Advertisement
Guest User

digenv.c

a guest
Nov 28th, 2014
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.67 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 the READ end of a pipe */
  60.     if (ret < 0) {                  /* if ret < 0 then there has been an error and the program exits */
  61.         perror("Read pipe closure failed");
  62.         exit(EXIT_FAILURE);
  63.     }
  64.    
  65.     ret = close(p[WRITE_PIPE]);     /* system call to close to end the WRITE end of a pipe */
  66.     if (ret < 0) {                  /* if ret < 0 then there has been an error and the program exits */
  67.         perror("Write pipe closure failed");
  68.         exit(EXIT_FAILURE);
  69.     }
  70. }
  71.  
  72. /* Function printenv()
  73.  *
  74.  * Writes all the environment variables on the system to the pipe pipe_print. If errors occur
  75.  * there is error handling.
  76.  */
  77.  
  78. void printenv() {
  79.    
  80.     char *args[] = { "printenv", NULL };        /* array that defines which system call to use */
  81.    
  82.     ret = dup2(pipe_print[WRITE_PIPE], STDOUT_FILENO);      /* dup2 copys the file descriptor from stdout to the pipe */
  83.     if (ret < 0) {              /* if ret < 0 then there has been an error and the program exits */
  84.         perror("Dup failed");
  85.         exit(EXIT_FAILURE);
  86.     }
  87.    
  88.     pipe_close(pipe_print);     /* closing of pipe after use */
  89.    
  90.     execvp(args[0], args);      /* executes the program defined in args[0] */
  91.    
  92.     perror("exec failed");
  93.     exit(EXIT_FAILURE);
  94. }
  95.  
  96. /* Function grep(char **arguments)
  97.  *
  98.  * Takes a list of parameters to pass on to the system function grep(1) and uses these on the list passed on from printenv
  99.  * via the pipe pipe_print.
  100.  */
  101.  
  102. void grep(char **arguments) {
  103.    
  104.     ret = dup2(pipe_print[READ_PIPE], STDIN_FILENO);        /* dup2 copys the file descriptor from stdin to the pipe */
  105.     if (ret < 0) {              /* if ret < 0 then there has been an error and the program exits */
  106.         perror("Dup failed");
  107.         exit(EXIT_FAILURE);
  108.     }
  109.    
  110.     /* set write end of pipe as stdout for this child process */
  111.     ret = dup2(pipe_grep[WRITE_PIPE], STDOUT_FILENO);       /* dup2 copys the file descriptor from stdout to the pipe */
  112.     if (ret < 0) {              /* if ret < 0 then there has been an error and the program exits */
  113.         perror("Dup failed");
  114.         exit(EXIT_FAILURE);
  115.     }
  116.    
  117.     pipe_close(pipe_print);     /* closing of pipe after use */
  118.     pipe_close(pipe_grep);      /* closing of pipe after use */
  119.    
  120.     execvp("grep", arguments);  /* executes the program defined in args[0] */
  121.    
  122.     perror("exec failed");
  123.     exit(EXIT_FAILURE);
  124. }
  125.  
  126. /* Function sort(int p[])
  127.  *
  128.  * Sorts a list of environment variables in alphabetical order. The list of variables are
  129.  * either all the variables passed from printenv or the function grep depending on the users
  130.  * choice. int p[] is the pipe that contains the list that is to be sorted.
  131.  */
  132.  
  133. void sort(int p[]) {
  134.     char *args[] = { "sort", NULL };            /* array that defines which system call to use */
  135.    
  136.     ret = dup2(p[READ_PIPE], STDIN_FILENO);     /* dup2 copys the file descriptor from stdin to the pipe */
  137.     if (ret < 0) {              /* if ret < 0 then there has been an error and the program exits */
  138.         perror("Dup failed");
  139.         exit(EXIT_FAILURE);
  140.     }
  141.    
  142.     ret = dup2(pipe_sort[WRITE_PIPE], STDOUT_FILENO);       /* dup2 copys the file descriptor from stdout to the pipe */
  143.     if (ret < 0) {              /* if ret < 0 then there has been an error and the program exits */
  144.         perror("Dup failed");
  145.         exit(EXIT_FAILURE);
  146.     }
  147.    
  148.     pipe_close(p);              /* closing of pipe after use */
  149.     pipe_close(pipe_sort);      /* closing of pipe after use */
  150.    
  151.     execvp(args[0], args);      /* executes the program defined in args[0] */
  152.    
  153.     perror("exec failed");
  154.     exit(EXIT_FAILURE);
  155. }
  156.  
  157. /* Function pager()
  158.  *
  159.  * The function that decides the pager that is to be used when displaying the sorted list.
  160.  * If the environment variable "PAGER" contains a default the program will use it,
  161.  * otherwise the default is to use less().
  162.  */
  163.  
  164. void pager() {
  165.    
  166.     char *args[] = { getenv("PAGER"), NULL };
  167.    
  168.     if (args[0] == NULL) {
  169.         args[0] = "less";
  170.     }
  171.    
  172.     /* set write end of pipe as stdout for this child process */
  173.     ret = dup2(pipe_sort[READ_PIPE], STDIN_FILENO);         /* dup2 copys the file descriptor from stdin to the pipe */
  174.     if (ret < 0) {              /* if ret < 0 then there has been an error and the program exits */
  175.         perror("Dup failed");
  176.         exit(EXIT_FAILURE);
  177.     }
  178.    
  179.     pipe_close(pipe_sort);      /* closing of pipe after use */
  180.    
  181.     ret = execvp(args[0], args);    /* executes the program defined in args[0] */
  182.     if (ret < 0) {                  /* if ret < 0 then there has been an error */
  183.         args[0] = "more";           /* if the system can't find less(), then more() is used */
  184.         execvp(args[0], args);      /* executes the program defined in args[0] */
  185.     }
  186.    
  187.     perror("exec failed");
  188.     exit(EXIT_FAILURE);
  189. }
  190.  
  191. /* The main program
  192.  *
  193.  * The program takes two parameters, first the input counter and then the array och inputs.
  194.  * Main.c is the program that creates all the child processes, pipes and handles parts of
  195.  * the error handling. At the end of the program it waits for all the child-processes to
  196.  * finish.
  197.  */
  198.  
  199. int main(int argc, char **argv) {
  200.    
  201.     int status;        /* Variable to indicate the status of a child process */
  202.    
  203.     if (pipe(pipe_print) < 0) {         /* opening pipe to printenv, if the returned value < 0 an error has occured */
  204.         perror("pipe failed");
  205.         return EXIT_FAILURE;
  206.     }
  207.    
  208.     printenvpid = fork();               /* creates a child process for the printenv function */
  209.     if (printenvpid < 0) {              /* if this is TRUE, an error has occured and the program is shut down */
  210.         perror("fork failed");
  211.         return EXIT_FAILURE;
  212.     }
  213.    
  214.     if (printenvpid == 0) {             /* if this is TRUE then the program is in the child process */
  215.        
  216.         printenv();                     /* a call to the function printenv() */
  217.        
  218.     }
  219.    
  220.     if (argc > 1) {                     /* if this is TRUE, input to the function grep exists. If FALSE then the
  221.                                          * program skips the grep() function and goes directly to sort()
  222.                                          */
  223.         if (pipe(pipe_grep) < 0) {      /* opening pipe to grep, if the returned value < 0 an error has occured */
  224.             perror("pipe failed");
  225.             return EXIT_FAILURE;
  226.         }
  227.        
  228.         greppid = fork();               /* creates a child process for the grep function */
  229.         if (greppid < 0) {              /* if this is TRUE, an error has occured and the program is shut down */
  230.             perror("fork failed");
  231.             return EXIT_FAILURE;
  232.         }
  233.        
  234.         if (greppid == 0) {             /* if this is TRUE then the program is in the child process */
  235.            
  236.             grep(argv);                 /* a call to the function grep() */
  237.            
  238.         }
  239.        
  240.         pipe_close(pipe_print);         /* closing of pipe after use */
  241.        
  242.         if (pipe(pipe_sort) < 0) {      /* opening pipe to sort, if the returned value < 0 an error has occured */
  243.             perror("pipe failed");
  244.             return EXIT_FAILURE;
  245.         }
  246.        
  247.         sortpid = fork();               /* creates a child process for the sort function */
  248.         if (sortpid < 0) {              /* if this is TRUE, an error has occured and the program is shut down */
  249.             perror("fork failed");
  250.             return EXIT_FAILURE;
  251.         }
  252.        
  253.         if (sortpid == 0) {             /* if this is TRUE then the program is in the child process */
  254.            
  255.             sort(pipe_grep);            /* a call to the function sort() */
  256.            
  257.         }
  258.        
  259.         pipe_close(pipe_grep);          /* closing of pipe after use */
  260.        
  261.         ret = waitpid(greppid, &status, 0);         /* this makes the program wait for grep to finish to avoid bypassing grep */
  262.         if( ret < 0 || status != 0) {               /* if waitpid() fails or the child process returns a status != 0 an error has occured */
  263.             perror( "waitpid() for grep failed" );
  264.             exit( 1 );
  265.         }
  266.        
  267.     } else {                            /* this part executes if no parameters to grep is entered */
  268.        
  269.         if (pipe(pipe_sort) < 0) {      /* opening pipe to sort, if the returned value < 0 an error has occured */
  270.             perror("pipe failed");
  271.             return EXIT_FAILURE;
  272.         }
  273.        
  274.         sortpid = fork();               /* creates a child process for the sort function */
  275.         if (sortpid < 0) {              /* if this is TRUE, an error has occured and the program is shut down */
  276.             perror("fork failed");
  277.             return EXIT_FAILURE;
  278.         }
  279.        
  280.         if (sortpid == 0) {             /* if this is TRUE then the program is in the child process */
  281.            
  282.             sort(pipe_print);           /* a call to the function sort() */
  283.            
  284.         }
  285.        
  286.         pipe_close(pipe_print);         /* closing of pipe after use */
  287.     }
  288.    
  289.     pagerpid = fork();                  /* creates a child process for the pager function */
  290.     if (pagerpid < 0) {                 /* if this is TRUE, an error has occured and the program is shut down */
  291.         perror("fork failed");
  292.         return EXIT_FAILURE;
  293.     }
  294.    
  295.     if (pagerpid == 0) {                /* if this is TRUE then the program is in the child process */
  296.        
  297.         pager();                        /* a call to the function pager() */
  298.        
  299.     }
  300.    
  301.     pipe_close(pipe_sort);              /* closing of pipe after use */
  302.    
  303.     ret = waitpid(printenvpid, &status, 0);         /* this makes the program wait for printenv to finish to avoid bypassing printenv */
  304.     if( ret < 0 || status != 0) {                   /* if waitpid() fails or the child process returns a status != 0 an error has occured */
  305.         perror( "waitpid() for printenv failed" );
  306.         exit( 1 );
  307.     }
  308.     ret = waitpid(sortpid, &status, 0);             /* this makes the program wait for sort to finish to avoid bypassing sort */
  309.     if( ret < 0 || status != 0) {                   /* if waitpid() fails or the child process returns a status != 0 an error has occured */
  310.         perror( "waitpid() for sort failed" );
  311.         exit( 1 );
  312.     }
  313.     ret = waitpid(pagerpid, &status, 0);            /* this makes the program wait for pager to finish to avoid bypassing pager */
  314.     if( ret < 0 || status != 0) {                   /* if waitpid() fails or the child process returns a status != 0 an error has occured */
  315.         perror( "waitpid() for pager failed" );
  316.         exit( 1 );
  317.     }
  318.    
  319.     exit(0);
  320. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement