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 134