Advertisement
Guest User

digenv.c

a guest
Nov 28th, 2014
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 14.49 KB | None | 0 0
  1. /*
  2.  *
  3.  * NAME:
  4.  *   digenv  -  a program for easy handling of environmental variables
  5.  *
  6.  * SYNTAX:
  7.  *   ./digenv [options] PATTERN [FILE...]
  8.  *   ./digenv [options] [-e PATTERN | -f FILE] [FILE...]
  9.  *
  10.  * DESCRIPTION:
  11.  *   The program digenv is supposed to help the user display the
  12.  *   environment variables of the system in an easy way using
  13.  *   pipes and built in system calls.
  14.  *
  15.  * OPTIONS:
  16.  *   see grep(1)
  17.  *
  18.  * EXAMPLES:
  19.  *   ./digenv -i PATH
  20.  *
  21.  * SEE ALSO:
  22.  *   grep(1), sort(1), printenv(1), less(1), more(1)
  23.  *
  24.  * NOTES:
  25.  *   If any parameter is entered in the wrong way, the program will exit.
  26.  *
  27.  * AUTHOR:
  28.  *   Rickard Eriksson   -   rieri@kth.se
  29.  *   Rebecca Ahlstrand  -   reah@kth.se
  30.  */
  31.  
  32.  
  33. #include <stdlib.h>
  34. #include <stdio.h>
  35. #include <unistd.h>
  36. #include <string.h>
  37. #include <sys/wait.h>
  38.  
  39. #define READ_PIPE (0)   /* defines that the integer 0 is bound to READ_PIPE */
  40. #define WRITE_PIPE (1)  /* defines that the integer 1 is bound to WRITE_PIPE */
  41.  
  42. pid_t printenvpid;  /* holds the pid for the child process printenv */
  43. pid_t greppid;      /* holds the pid for the child process grep */
  44. pid_t sortpid;      /* holds the pid for the child process sort */
  45. pid_t pagerpid;     /* holds the pid for the child process pager */
  46.  
  47. int pipe_print[2];  /* variable to hold the file descriptors for the function printenv */
  48. int pipe_grep[2];   /* variable to hold the file descriptors for the function grep */
  49. int pipe_sort[2];   /* variable to hold the file descriptors for the function sort */
  50. int ret;            /* variable to hold returns from system calls for error handling */
  51.  
  52. /* Function pipe_close(int pipe[])
  53.  *
  54.  * The function takes an int array that contains the file descriptors of a pipe and
  55.  * closes them. There's also error handling if any of the system calls gets an error.
  56.  */
  57.  
  58. void pipe_close(int p[]) {
  59.     ret = close(p[READ_PIPE]);      /* system call to close to end
  60.                                      * the READ end of a pipe */
  61.     if (ret < 0) {                  /* if ret < 0 then there has been
  62.                                      * an error and the program exits */
  63.         perror("Read pipe closure failed");
  64.         exit(EXIT_FAILURE);
  65.     }
  66.    
  67.     ret = close(p[WRITE_PIPE]);     /* system call to close to end
  68.                                      * the WRITE end of a pipe */
  69.     if (ret < 0) {                  /* if ret < 0 then there has been
  70.                                      * an error and the program exits */
  71.         perror("Write pipe closure failed");
  72.         exit(EXIT_FAILURE);
  73.     }
  74. }
  75.  
  76. /* Function printenv()
  77.  *
  78.  * Writes all the environment variables on the system to the pipe pipe_print.
  79.  * If errors occur there is error handling.
  80.  */
  81.  
  82. void printenv() {
  83.    
  84.     char *args[] = { "printenv", NULL };    /* array that defines which system call to use */
  85.    
  86.     ret = dup2(pipe_print[WRITE_PIPE], STDOUT_FILENO);      /* dup2 copys the file descriptor
  87.                                                              * from stdout to the pipe */
  88.     if (ret < 0) {                      /* if ret < 0 then there has been
  89.                                          * an error and the program exits */
  90.         perror("Dup failed");
  91.         exit(EXIT_FAILURE);
  92.     }
  93.    
  94.     pipe_close(pipe_print);     /* closing of pipe after use */
  95.    
  96.     execvp(args[0], args);      /* executes the program defined in args[0] */
  97.    
  98.     perror("exec failed");
  99.     exit(EXIT_FAILURE);
  100. }
  101.  
  102. /* Function grep(char **arguments)
  103.  *
  104.  * Takes a list of parameters to pass on to the system function grep(1) and
  105.  * uses these on the list passed on from printenv via the pipe pipe_print.
  106.  */
  107.  
  108. void grep(char **arguments) {
  109.    
  110.     ret = dup2(pipe_print[READ_PIPE], STDIN_FILENO);        /* dup2 copys the file descriptor
  111.                                                              * from stdin to the pipe */
  112.     if (ret < 0) {                      /* if ret < 0 then there has been
  113.                                          * an error and the program exits */
  114.         perror("Dup failed");
  115.         exit(EXIT_FAILURE);
  116.     }
  117.    
  118.     /* set write end of pipe as stdout for this child process */
  119.     ret = dup2(pipe_grep[WRITE_PIPE], STDOUT_FILENO);       /* dup2 copys the file descriptor
  120.                                                              * from stdout to the pipe */
  121.     if (ret < 0) {                      /* if ret < 0 then there has been
  122.                                          * an error and the program exits */
  123.         perror("Dup failed");
  124.         exit(EXIT_FAILURE);
  125.     }
  126.    
  127.     pipe_close(pipe_print);     /* closing of pipe after use */
  128.     pipe_close(pipe_grep);      /* closing of pipe after use */
  129.    
  130.     execvp("grep", arguments);  /* executes the program defined in args[0] */
  131.    
  132.     perror("exec failed");
  133.     exit(EXIT_FAILURE);
  134. }
  135.  
  136. /* Function sort(int p[])
  137.  *
  138.  * Sorts a list of environment variables in alphabetical order. The list of variables are
  139.  * either all the variables passed from printenv or the function grep depending on the users
  140.  * choice. int p[] is the pipe that contains the list that is to be sorted.
  141.  */
  142.  
  143. void sort(int p[]) {
  144.     char *args[] = { "sort", NULL };            /* array that defines which system call to use */
  145.    
  146.     ret = dup2(p[READ_PIPE], STDIN_FILENO);     /* dup2 copys the file descriptor
  147.                                                  * from stdin to the pipe */
  148.     if (ret < 0) {                              /* if ret < 0 then there has been
  149.                                                  * an error and the program exits */
  150.         perror("Dup failed");
  151.         exit(EXIT_FAILURE);
  152.     }
  153.    
  154.     ret = dup2(pipe_sort[WRITE_PIPE], STDOUT_FILENO);       /* dup2 copys the file descriptor
  155.                                                              * from stdout to the pipe */
  156.     if (ret < 0) {                      /* if ret < 0 then there has been
  157.                                          * an error and the program exits */
  158.         perror("Dup failed");
  159.         exit(EXIT_FAILURE);
  160.     }
  161.    
  162.     pipe_close(p);              /* closing of pipe after use */
  163.     pipe_close(pipe_sort);      /* closing of pipe after use */
  164.    
  165.     execvp(args[0], args);      /* executes the program defined in args[0] */
  166.    
  167.     perror("exec failed");
  168.     exit(EXIT_FAILURE);
  169. }
  170.  
  171. /* Function pager()
  172.  *
  173.  * The function that decides the pager that is to be used when displaying the sorted list.
  174.  * If the environment variable "PAGER" contains a default the program will use it,
  175.  * otherwise the default is to use less().
  176.  */
  177.  
  178. void pager() {
  179.    
  180.     char *args[] = { getenv("PAGER"), NULL };
  181.    
  182.     if (args[0] == NULL) {
  183.         args[0] = "less";
  184.     }
  185.    
  186.     ret = dup2(pipe_sort[READ_PIPE], STDIN_FILENO);         /* dup2 copys the file descriptor
  187.                                                              * from stdin to the pipe */
  188.     if (ret < 0) {                      /* if ret < 0 then there has been
  189.                                          * an error and the program exits */
  190.         perror("Dup failed");
  191.         exit(EXIT_FAILURE);
  192.     }
  193.    
  194.     pipe_close(pipe_sort);      /* closing of pipe after use */
  195.    
  196.     ret = execvp(args[0], args);    /* executes the program defined in args[0] */
  197.     if (ret < 0) {                  /* if ret < 0 then there has been an error */
  198.         args[0] = "more";           /* if the system can't find less(), then more() is used */
  199.         execvp(args[0], args);      /* executes the program defined in args[0] */
  200.     }
  201.    
  202.     perror("exec failed");
  203.     exit(EXIT_FAILURE);
  204. }
  205.  
  206. /* The main program
  207.  *
  208.  * The program takes two parameters, first the input counter and then the array och inputs.
  209.  * Main.c is the program that creates all the child processes, pipes and handles parts of
  210.  * the error handling. At the end of the program it waits for all the child-processes to
  211.  * finish.
  212.  */
  213.  
  214. int main(int argc, char **argv) {
  215.    
  216.     int status;        /* Variable to indicate the status of a child process */
  217.    
  218.     if (pipe(pipe_print) < 0) {         /* opening pipe to printenv, if the returned
  219.                                          * value < 0 an error has occured */
  220.         perror("pipe failed");
  221.         return EXIT_FAILURE;
  222.     }
  223.    
  224.     printenvpid = fork();               /* creates a child process for the printenv function */
  225.     if (printenvpid < 0) {              /* if this is TRUE, an error has
  226.                                          * occured and the program is shut down */
  227.         perror("fork failed");
  228.         return EXIT_FAILURE;
  229.     }
  230.    
  231.     if (printenvpid == 0) {             /* if this is TRUE then the program
  232.                                          * is in the child process */
  233.         printenv();                     /* a call to the function printenv() */
  234.        
  235.     }
  236.    
  237.     if (argc > 1) {                     /* if this is TRUE, input to the function
  238.                                          * grep exists. If FALSE then the program
  239.                                          * skips the grep() function and goes directly to sort()*/
  240.         if (pipe(pipe_grep) < 0) {      /* opening pipe to grep, if the returned
  241.                                          * value < 0 an error has occured */
  242.             perror("pipe failed");
  243.             return EXIT_FAILURE;
  244.         }
  245.        
  246.         greppid = fork();               /* creates a child process for the grep function */
  247.         if (greppid < 0) {              /* if this is TRUE, an error has
  248.                                          * occured and the program is shut down */
  249.             perror("fork failed");
  250.             return EXIT_FAILURE;
  251.         }
  252.        
  253.         if (greppid == 0) {             /* if this is TRUE then the program
  254.                                          * is in the child process */
  255.            
  256.             grep(argv);                 /* a call to the function grep() */
  257.            
  258.         }
  259.        
  260.         pipe_close(pipe_print);         /* closing of pipe after use */
  261.        
  262.         if (pipe(pipe_sort) < 0) {      /* opening pipe to sort, if the returned
  263.                                          * value < 0 an error has occured */
  264.             perror("pipe failed");
  265.             return EXIT_FAILURE;
  266.         }
  267.        
  268.         sortpid = fork();               /* creates a child process for the sort function */
  269.         if (sortpid < 0) {              /* if this is TRUE, an error has occured
  270.                                          * and the program is shut down */
  271.             perror("fork failed");
  272.             return EXIT_FAILURE;
  273.         }
  274.        
  275.         if (sortpid == 0) {             /* if this is TRUE then the program
  276.                                          * is in the child process */
  277.             sort(pipe_grep);            /* a call to the function sort() */
  278.            
  279.         }
  280.        
  281.         pipe_close(pipe_grep);          /* closing of pipe after use */
  282.        
  283.         ret = waitpid(greppid, &status, 0);         /* this makes the program wait for grep
  284.                                                      * to finish to avoid bypassing grep */
  285.         if( ret < 0 || status != 0) {               /* if waitpid() fails or the child process
  286.                                                      * returns a status != 0 an error has occured */
  287.             perror( "waitpid() for grep failed" );
  288.             exit( 1 );
  289.         }
  290.        
  291.     } else {                            /* this part executes if no parameters to grep is entered */
  292.        
  293.         if (pipe(pipe_sort) < 0) {      /* opening pipe to sort, if the returned
  294.                                          * value < 0 an error has occured */
  295.             perror("pipe failed");
  296.             return EXIT_FAILURE;
  297.         }
  298.        
  299.         sortpid = fork();               /* creates a child process for the sort function */
  300.         if (sortpid < 0) {              /* if this is TRUE, an error has
  301.                                          * occured and the program is shut down */
  302.             perror("fork failed");
  303.             return EXIT_FAILURE;
  304.         }
  305.        
  306.         if (sortpid == 0) {             /* if this is TRUE then the program
  307.                                          * is in the child process */
  308.            
  309.             sort(pipe_print);           /* a call to the function sort() */
  310.            
  311.         }
  312.        
  313.         pipe_close(pipe_print);         /* closing of pipe after use */
  314.     }
  315.    
  316.     pagerpid = fork();                  /* creates a child process for the pager function */
  317.     if (pagerpid < 0) {                 /* if this is TRUE, an error has
  318.                                          * occured and the program is shut down */
  319.         perror("fork failed");
  320.         return EXIT_FAILURE;
  321.     }
  322.    
  323.     if (pagerpid == 0) {                /* if this is TRUE then the program
  324.                                          * is in the child process */
  325.         pager();                        /* a call to the function pager() */
  326.        
  327.     }
  328.    
  329.     pipe_close(pipe_sort);              /* closing of pipe after use */
  330.    
  331.     ret = waitpid(printenvpid, &status, 0);         /* this makes the program wait for printenv
  332.                                                      * to finish to avoid bypassing printenv */
  333.     if( ret < 0 || status != 0) {                   /* if waitpid() fails or the child process
  334.                                                      * returns a status != 0 an error has occured */
  335.         perror( "waitpid() for printenv failed" );
  336.         exit( 1 );
  337.     }
  338.     ret = waitpid(sortpid, &status, 0);             /* this makes the program wait for sort
  339.                                                      * to finish to avoid bypassing sort */
  340.     if( ret < 0 || status != 0) {                   /* if waitpid() fails or the child process
  341.                                                      * returns a status != 0 an error has occured */
  342.         perror( "waitpid() for sort failed" );
  343.         exit( 1 );
  344.     }
  345.     ret = waitpid(pagerpid, &status, 0);            /* this makes the program wait for pager to
  346.                                                      * finish to avoid bypassing pager */
  347.     if( ret < 0 || status != 0) {                   /* if waitpid() fails or the child process
  348.                                                      * returns a status != 0 an error has occured */
  349.         perror( "waitpid() for pager failed" );
  350.         exit( 1 );
  351.     }
  352.    
  353.     exit(0);
  354. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement