Revisions
-
mike-bourgeous revised this gist
Oct 23, 2016 . No changes.There are no files selected for viewing
-
mike-bourgeous revised this gist
Oct 23, 2016 . 2 changed files with 5 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -7,7 +7,8 @@ * but if used in an open source application, attribution would be appreciated. * * Mike Bourgeous * https://github.com/mike-bourgeous * http://www.mikebourgeous.com/ */ #include <stdio.h> #include <stdlib.h> This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -8,11 +8,12 @@ * non-blocking option present in the 2007 version. * * No warranty of correctness, safety, performance, security, or usability is * given. This implementation is released into the public domain/CC0, but if used * in an open source application, attribution would be appreciated. * * Mike Bourgeous * https://github.com/mike-bourgeous * http://www.mikebourgeous.com/ */ #include <stdio.h> #include <stdlib.h> -
Mike Bourgeous revised this gist
Oct 23, 2016 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -42,7 +42,7 @@ pid_t popen3(const char *command, int *fp_in, int *fp_out, int *fp_err, int nonb return -1; } /* Set the pipes to nonblocking IO if requested (a good idea for single-threaded apps) */ if(nonblock_in) { fcntl(p_stdin[POPEN3_WRITE], F_SETFL, fcntl(p_stdin[POPEN3_WRITE], F_GETFL) | O_NONBLOCK); } -
Mike revised this gist
Jun 13, 2011 . 2 changed files with 3 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -31,6 +31,7 @@ pid_t popen3(const char *command, int *fp_in, int *fp_out, int *fp_err, int nonb // Based on popen2() from http://snippets.dzone.com/posts/show/1134, // where it was listed as freeware. Modifications by Mike Bourgeous. // https://gist.github.com/1022231 int p_stdin[2], p_stdout[2], p_stderr[2]; pid_t pid; @@ -41,7 +42,7 @@ pid_t popen3(const char *command, int *fp_in, int *fp_out, int *fp_err, int nonb return -1; } /* Set the pipes to nonblocking IO if rhttps://gist.github.com/1022231equested (a good idea for single-threaded apps) */ if(nonblock_in) { fcntl(p_stdin[POPEN3_WRITE], F_SETFL, fcntl(p_stdin[POPEN3_WRITE], F_GETFL) | O_NONBLOCK); } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -49,6 +49,7 @@ pid_t popen3(char *command, int *writefd, int *readfd, int *errfd) pid_t pid; // 2011 implementation of popen3() by Mike Bourgeous // https://gist.github.com/1022231 if(command == NULL) { fprintf(stderr, "Cannot popen3() a NULL command.\n"); -
Mike created this gist
Jun 13, 2011 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,105 @@ /* * This implementation of popen3() was created in 2007 for an experimental * mpg123 frontend and is based on a popen2() snippet found online. This * implementation may behave in unexpected ways if stdin/stdout/stderr have * been closed or modified. No warranty of its correctness, security, or * usability is given. My modifications are released into the public domain, * but if used in an open source application, attribution would be appreciated. * * Mike Bourgeous * https://github.com/nitrogenlogic */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> /* * popen3() * * Runs the specified command line using a shell (SECURITY WARNING: don't put * user-provided input here, to avoid shell expansion), opening pipes for * stdin, stdout, and stderr. If NULL is specified for a given fd, that stream * will be discarded. * * It is recommended to set nonblock_in to zero, nonblock_outerr to nonzero. */ pid_t popen3(const char *command, int *fp_in, int *fp_out, int *fp_err, int nonblock_in, int nonblock_outerr) /* {{{ */ { #define POPEN3_READ 0 #define POPEN3_WRITE 1 // Based on popen2() from http://snippets.dzone.com/posts/show/1134, // where it was listed as freeware. Modifications by Mike Bourgeous. int p_stdin[2], p_stdout[2], p_stderr[2]; pid_t pid; /* Open the three pipes */ if(pipe(p_stdin) != 0 || pipe(p_stdout) != 0 || pipe(p_stderr) != 0) { perror("popen3: unable to open pipes for I/O"); return -1; } /* Set the pipes to nonblocking IO if requested (a good idea for single-threaded apps) */ if(nonblock_in) { fcntl(p_stdin[POPEN3_WRITE], F_SETFL, fcntl(p_stdin[POPEN3_WRITE], F_GETFL) | O_NONBLOCK); } if(nonblock_outerr) { fcntl(p_stdout[POPEN3_READ], F_SETFL, fcntl(p_stdout[POPEN3_READ], F_GETFL) | O_NONBLOCK); fcntl(p_stderr[POPEN3_READ], F_SETFL, fcntl(p_stderr[POPEN3_READ], F_GETFL) | O_NONBLOCK); } pid = fork(); if (pid < 0) { /* An error occurred */ return pid; } else if (pid == 0) { /* This is the child process */ // Close the parent-side half of the pipes close(p_stdin[POPEN3_WRITE]); close(p_stderr[POPEN3_READ]); close(p_stdout[POPEN3_READ]); // Replace the real stdin/stdout/stderr with the pipes created above dup2(p_stdin[POPEN3_READ], fileno(stdin)); dup2(p_stderr[POPEN3_WRITE], fileno(stderr)); // stderr is first in case err is redirected to out (i.e. with 2>&1) dup2(p_stdout[POPEN3_WRITE], fileno(stdout)); execl("/bin/sh", "sh", "-c", command, (char *)NULL); perror("popen3: execl failed"); exit(1); } /* This is the parent process */ if(fp_in == NULL) { /* fp_in was null - the caller doesn't want to write to stdin */ close(p_stdin[POPEN3_WRITE]); } else { /* Give the caller the file number for stdin */ *fp_in = p_stdin[POPEN3_WRITE]; } if(fp_out == NULL) { /* fp_out was null - the caller doesn't want to read from stdout */ close(p_stdout[POPEN3_READ]); } else { /* Give the caller the file number for stdout */ *fp_out = p_stdout[POPEN3_READ]; } if(fp_err == NULL) { /* fp_err was null - the caller doesn't want to read from stderr */ close(p_stderr[POPEN3_READ]); } else { /* Give the caller the file number for stderr */ *fp_err = p_stderr[POPEN3_READ]; } return pid; #undef POPEN3_READ #undef POPEN3_WRITE } /* }}} */ This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,152 @@ /* * This implementation of popen3() was created from scratch in June of 2011. It * is less likely to leak file descriptors if an error occurs than the 2007 * version and has been tested under valgrind. It also differs from the 2007 * version in its behavior if one of the file descriptor parameters is NULL. * Instead of closing the corresponding stream, it is left unmodified (typically * sharing the same terminal as the parent process). It also lacks the * non-blocking option present in the 2007 version. * * No warranty of correctness, safety, performance, security, or usability is * given. This implementation is released into the public domain, but if used * in an open source application, attribution would be appreciated. * * Mike Bourgeous * https://github.com/nitrogenlogic */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> /* * Sets the FD_CLOEXEC flag. Returns 0 on success, -1 on error. */ static int set_cloexec(int fd) { if(fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC) == -1) { perror("Error setting FD_CLOEXEC flag"); return -1; } return 0; } /* * Runs command in another process, with full remote interaction capabilities. * Be aware that command is passed to sh -c, so shell expansion will occur. * Writing to *writefd will write to the command's stdin. Reading from *readfd * will read from the command's stdout. Reading from *errfd will read from the * command's stderr. If NULL is passed for writefd, readfd, or errfd, then the * command's stdin, stdout, or stderr will not be changed. Returns the child * PID on success, -1 on error. */ pid_t popen3(char *command, int *writefd, int *readfd, int *errfd) { int in_pipe[2] = {-1, -1}; int out_pipe[2] = {-1, -1}; int err_pipe[2] = {-1, -1}; pid_t pid; // 2011 implementation of popen3() by Mike Bourgeous if(command == NULL) { fprintf(stderr, "Cannot popen3() a NULL command.\n"); goto error; } if(writefd && pipe(in_pipe)) { perror("Error creating pipe for stdin"); goto error; } if(readfd && pipe(out_pipe)) { perror("Error creating pipe for stdout"); goto error; } if(errfd && pipe(err_pipe)) { perror("Error creating pipe for stderr"); goto error; } pid = fork(); switch(pid) { case -1: // Error perror("Error creating child process"); goto error; case 0: // Child if(writefd) { close(in_pipe[1]); if(dup2(in_pipe[0], 0) == -1) { perror("Error assigning stdin in child process"); exit(-1); } close(in_pipe[0]); } if(readfd) { close(out_pipe[0]); if(dup2(out_pipe[1], 1) == -1) { perror("Error assigning stdout in child process"); exit(-1); } close(out_pipe[1]); } if(errfd) { close(err_pipe[0]); if(dup2(err_pipe[1], 2) == -1) { perror("Error assigning stderr in child process"); exit(-1); } close(err_pipe[1]); } execl("/bin/sh", "/bin/sh", "-c", command, (char *)NULL); perror("Error executing command in child process"); exit(-1); default: // Parent break; } if(writefd) { close(in_pipe[0]); set_cloexec(in_pipe[1]); *writefd = in_pipe[1]; } if(readfd) { close(out_pipe[1]); set_cloexec(out_pipe[0]); *readfd = out_pipe[0]; } if(errfd) { close(err_pipe[1]); set_cloexec(out_pipe[0]); *errfd = err_pipe[0]; } return pid; error: if(in_pipe[0] >= 0) { close(in_pipe[0]); } if(in_pipe[1] >= 0) { close(in_pipe[1]); } if(out_pipe[0] >= 0) { close(out_pipe[0]); } if(out_pipe[1] >= 0) { close(out_pipe[1]); } if(err_pipe[0] >= 0) { close(err_pipe[0]); } if(err_pipe[1] >= 0) { close(err_pipe[1]); } return -1; }