UNIXworkcode

  1  /*
  2   *             DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
  3   *                     Version 2, December 2004
  4   * 
  5   *  Copyright (C) 2019 Olaf Wintermann <olaf.wintermann@gmail.com>
  6   * 
  7   *  Everyone is permitted to copy and distribute verbatim or modified
  8   *  copies of this license document, and changing it is allowed as long
  9   *  as the name is changed.
 10   * 
 11   *             DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
 12   *    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 13   * 
 14   *   0. You just DO WHAT THE FUCK YOU WANT TO.
 15   */
 16  
 17  #include <stdio.h>
 18  #include <stdlib.h>
 19  #include <sys/stat.h>
 20  #include <unistd.h>
 21  #include <sys/fcntl.h>
 22  
 23  #include <spawn.h>
 24  #include <sys/wait.h>
 25  
 26  int main(int argc, char **argv) {
 27      int ret;
 28      
 29      // create pipe for child process
 30      // write to pout[1], read from pout[0]
 31      int pout[2];
 32      if(pipe(pout)) {
 33          perror("pipe");
 34          return 1;
 35      }
 36      
 37      // posix_spawn_file_actions_t defines actions on files of the child process
 38      posix_spawn_file_actions_t actions;
 39      
 40      // actions must be initialized with posix_spawn_file_actions_init
 41      // and should be destroyed with posix_spawn_file_actions_destroy
 42      posix_spawn_file_actions_init(&actions);
 43      
 44      // possible actions:
 45      // posix_spawn_file_actions_addclose
 46      //   closes a file descriptor in the child process
 47      // posix_spawn_file_actions_addopen
 48      //   opens a file path
 49      // posix_spawn_file_actions_adddup2
 50      //   performs dup2() on a file descriptor in the child process
 51      
 52      // examples:
 53      
 54      // close stdout in the child process
 55      //posix_spawn_file_actions_addclose(&actions, 2);
 56      
 57      // redirect stdout to a file
 58      //posix_spawn_file_actions_addopen(&actions, 1, "out.txt", O_CREAT|O_WRONLY, 0644);
 59      
 60      // redirect stdout to a pipe
 61      posix_spawn_file_actions_adddup2(&actions, pout[1], 1);
 62      
 63      
 64      // Attributes: unused in this example
 65      //posix_spawnattr_t attr;
 66      // init with posix_spawnattr_init
 67      // free with posix_spawnattr_destroy
 68      // can be used to speficy process attributes
 69      
 70      
 71      // child command arguments
 72      char *args[10];
 73      args[0] = "/bin/printf";
 74      args[1] = "%s\n%f\n%s\n";
 75      args[2] = "Hello World";
 76      args[3] = "3.14";
 77      args[4] = "posix_spawn test";
 78      args[5] = NULL; // array must be null-terminated
 79      
 80      // child environment variables
 81      char *env[10];
 82      env[0] = "LC_ALL=C";
 83      env[1] = NULL; // array must be null-terminated
 84      
 85      // execute posix_spawn to create a child process
 86      pid_t child;
 87      ret = posix_spawn(
 88              &child,
 89              "/bin/printf",
 90              &actions,
 91              NULL,            // attributes
 92              args,
 93              env);
 94      posix_spawn_file_actions_destroy(&actions);
 95      if(ret) {
 96          // posix spawn failed
 97          perror("posix_spawn");
 98          return 1;
 99      }
100      
101      // close pout[1] (the write-part of the pipe) in the parent-process
102      // pout[1] is still open after that in the child-process
103      // if we don't close it here, read from pout[0] would never end
104      close(pout[1]);
105      
106      // read the output of our child-process
107      char buf[1024];
108      ssize_t r;
109      int linestart = 1;
110      while((r=read(pout[0], buf, 1024)) > 0) {
111          // write every child-output line to stdout and customize the output
112          for(int i=0;i<r;i++) {
113              if(linestart) {
114                  // add prefix to every output line
115                  printf("stdout: [");
116                  linestart = 0;
117              }
118              if(buf[i] == '\n') {
119                  printf("]\n");
120                  linestart = 1;
121              } else {
122                  putchar(buf[i]);
123              }
124          }
125      }
126      
127      // wait for the child to exit
128      int status;
129      waitpid(child, &status, 0);
130      
131      return 0;
132  }
133