UNIXworkcode

/* * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE * Version 2, December 2004 * * Copyright (C) 2019 Olaf Wintermann <olaf.wintermann@gmail.com> * * Everyone is permitted to copy and distribute verbatim or modified * copies of this license document, and changing it is allowed as long * as the name is changed. * * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE * TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION * * 0. You just DO WHAT THE FUCK YOU WANT TO. */ #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <unistd.h> #include <sys/fcntl.h> #include <spawn.h> #include <sys/wait.h> int main(int argc, char **argv) { int ret; // create pipe for child process // write to pout[1], read from pout[0] int pout[2]; if(pipe(pout)) { perror("pipe"); return 1; } // posix_spawn_file_actions_t defines actions on files of the child process posix_spawn_file_actions_t actions; // actions must be initialized with posix_spawn_file_actions_init // and should be destroyed with posix_spawn_file_actions_destroy posix_spawn_file_actions_init(&actions); // possible actions: // posix_spawn_file_actions_addclose // closes a file descriptor in the child process // posix_spawn_file_actions_addopen // opens a file path // posix_spawn_file_actions_adddup2 // performs dup2() on a file descriptor in the child process // examples: // close stdout in the child process //posix_spawn_file_actions_addclose(&actions, 2); // redirect stdout to a file //posix_spawn_file_actions_addopen(&actions, 1, "out.txt", O_CREAT|O_WRONLY, 0644); // redirect stdout to a pipe posix_spawn_file_actions_adddup2(&actions, pout[1], 1); // Attributes: unused in this example //posix_spawnattr_t attr; // init with posix_spawnattr_init // free with posix_spawnattr_destroy // can be used to speficy process attributes // child command arguments char *args[10]; args[0] = "/bin/printf"; args[1] = "%s\n%f\n%s\n"; args[2] = "Hello World"; args[3] = "3.14"; args[4] = "posix_spawn test"; args[5] = NULL; // array must be null-terminated // child environment variables char *env[10]; env[0] = "LC_ALL=C"; env[1] = NULL; // array must be null-terminated // execute posix_spawn to create a child process pid_t child; ret = posix_spawn( &child, "/bin/printf", &actions, NULL, // attributes args, env); posix_spawn_file_actions_destroy(&actions); if(ret) { // posix spawn failed perror("posix_spawn"); return 1; } // close pout[1] (the write-part of the pipe) in the parent-process // pout[1] is still open after that in the child-process // if we don't close it here, read from pout[0] would never end close(pout[1]); // read the output of our child-process char buf[1024]; ssize_t r; int linestart = 1; while((r=read(pout[0], buf, 1024)) > 0) { // write every child-output line to stdout and customize the output for(int i=0;i<r;i++) { if(linestart) { // add prefix to every output line printf("stdout: ["); linestart = 0; } if(buf[i] == '\n') { printf("]\n"); linestart = 1; } else { putchar(buf[i]); } } } // wait for the child to exit int status; waitpid(child, &status, 0); return 0; }