\ C pipes - /g/pasta 2.4
From rhaps0dy, 4 Years ago, written in C.
Embed
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <assert.h>
  4. #include <sys/types.h>
  5. #include <sys/wait.h>
  6.  
  7. /* remember that argv's last element has to be NULL, and the first argument
  8.  * should be the program's name (file).
  9.  * Passes the buffer in as standard input to the program, and reads standard
  10.  * output to out and standard error to err.
  11.  * You can specify a NULL in, out or err parameters, that will cause that particular stream to be ignored.
  12.  * Returns return value of the program.
  13.  */
  14. enum {
  15.         PIPE_ERR = -1,
  16.         WRITE_ERR = -2,
  17.         READ_ERR = -3
  18. };
  19.  
  20. int
  21. call_program(char *in, char *out, size_t outsize, char *err, size_t errsize, char *file, char **argv)
  22. {
  23.         int inpipe[2], outpipe[2], errpipe[2], status, ret;
  24.         size_t i;
  25.  
  26.         assert(!(out && outsize == 0));
  27.         assert(!(err && errsize == 0));
  28.  
  29.         if(in && pipe(inpipe) == -1) return PIPE_ERR;
  30.         if(out && pipe(outpipe) == -1) return PIPE_ERR;
  31.         if(err && pipe(errpipe) == -1) return PIPE_ERR;
  32.  
  33.         if(!fork()) {
  34.                 if(in) {
  35.                         dup2(inpipe[0], 0);
  36.                         close(inpipe[1]);
  37.                 }
  38.                 if(out) {
  39.                         dup2(outpipe[1], 1);
  40.                         close(outpipe[0]);
  41.                 }
  42.                 if(err) {
  43.                         dup2(errpipe[1], 2);
  44.                         close(errpipe[0]);
  45.                 }
  46.                 execvp(file, argv);
  47.         }
  48.         if(in) {
  49.                 close(inpipe[0]);
  50.                 for(; *in; in++)
  51.                         if(write(inpipe[1], in, 1) == -1)
  52.                                 return WRITE_ERR;
  53.                 close(inpipe[1]);
  54.         }
  55.         if(out) {
  56.                 close(outpipe[1]);
  57.                 for(i=0; i<outsize-1; i++) {
  58.                         ret = read(outpipe[0], out+i, 1);
  59.                         if(ret == 0)
  60.                                 break;
  61.                         if(ret == -1)
  62.                                 return READ_ERR;
  63.                 }
  64.                 out[i] = '\0';
  65.                 close(outpipe[0]);
  66.         }
  67.         if(err) {
  68.                 close(errpipe[1]);
  69.                 for(i=0; i<errsize-1; i++) {
  70.                         ret = read(errpipe[0], err+i, 1);
  71.                         if(ret == 0)
  72.                                 break;
  73.                         if(ret == -1)
  74.                                 return READ_ERR;
  75.                 }
  76.                 err[i] = '\0';
  77.                 close(errpipe[0]);
  78.         }
  79.         wait(&status);
  80.         return status;
  81. }
  82.  
  83. int
  84. main(int argc, char **argv)
  85. {
  86.         char *in = "This is\nA multiline\nbuffer\n";
  87.         char out[200];
  88.         char *args[3] = {"grep", "multi", NULL};
  89.         int ret;
  90.  
  91.         ret = call_program(in, out, 200, NULL, 0, "grep", args);
  92.  
  93.         printf("The input was: \"%s\"\n", in);
  94.         printf("The output was: \"%s\"\n", out);
  95.         printf("The return value was: %d\n", ret);
  96.         return 0;
  97. }
  98.