Skip to content

Instantly share code, notes, and snippets.

@miikka
Created October 2, 2012 15:00
Show Gist options
  • Save miikka/3819839 to your computer and use it in GitHub Desktop.
Save miikka/3819839 to your computer and use it in GitHub Desktop.
Capturing the output of an external program in C
#include <stdio.h>
#include <unistd.h>
int my_popen(char *cmd, FILE *handles[2]) {
/* Naming convention: the child's input and output */
int input[2];
int output[2];
pipe(input);
pipe(output);
pid_t child_pid = fork();
if (child_pid == -1) {
for (int i = 0; i < 2; i++) {
close(input[i]); close(output[i]);
}
return -1;
} else if (!child_pid) {
/* Redirect stdin and stdout to our pipes. */
dup2(input[0], STDIN_FILENO);
dup2(output[1], STDOUT_FILENO);
/* The pipes have to be closed by both the parent and the child. Closing a
* file descriptor in the child does not close it in the parent and vice
* versa, even though the child inherits the parent's file descriptors.
* Hence we close the parents ends of pipes here in the child. */
close(input[1]);
close(output[0]);
/* The second parameter of execlp is argv[0] for the executed program,
* hence there's "sh" twice. */
execlp("sh", "sh", "-c", cmd, (char*)NULL);
_exit(127);
} else {
/* Close the child's ends of pipes. */
close(input[0]);
close(output[1]);
}
/* For the handles, we use the same convention as pipe(2): handles[1] is the
* write end and handles[0] the read end. */
handles[0] = fdopen(output[0], "r");
handles[1] = fdopen(input[1], "w");
return 0;
}
int main(void) {
FILE *handles[3];
char buffer[1024];
if (my_popen("pandoc", handles) == -1) { perror("my_popen"); return -1; }
fputs("I don't to *emphasize* my role.", handles[1]);
fclose(handles[1]);
fread(buffer, 1, 1024, handles[0]);
fclose(handles[0]);
puts("pandoc says:");
puts(buffer);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment