Skip to content

Instantly share code, notes, and snippets.

@getify
Created October 11, 2010 20:57
Show Gist options
  • Save getify/621210 to your computer and use it in GitHub Desktop.
Save getify/621210 to your computer and use it in GitHub Desktop.
char* executeProcess(char** args) {
int p[2], p2[2], pid, output_length = 100, current_size = 0, num_args = 3, i, child_stat;
bool error = false;
char cread;
char* output = NULL;
char** cmd_args;
std::string cmd(args[1]);
// take off args[0], since will be sent into stdin of process
std::string input_data(args[0]);
num_args--;
// copy the args array (starting at index 1) into cmd_args
cmd_args = (char**)malloc((num_args+1)*sizeof(char*));
for (i=0; i<num_args; i++) {
cmd_args[i] = (char*)malloc(strlen(args[i+1]))*sizeof(char));
strcpy(cmd_args[i],args[i+1]);
}
cmd_args[num_args] = (char *)0; // mark the end of the args array for execvp()
if (pipe(p) == -1) {
error = true;
}
if (pipe(p2) == -1) {
error = true;
}
if (!error) {
pid = fork();
switch (pid) {
case -1: // error
error = true;
case 0: // child process
close(p2[0]);
close(p[1]);
close(1); // close regular stdout
dup(p2[1]); // redirect pipe2 write end to be stdin of this child process
close(p2[1]); // pipe not needed anymore
close(0); // close regular stdin
dup(p[0]); // redirect pipe1 read end to be stdin of this child process
close(p[0]); // pipe not needed anymore
execvp(cmd.c_str(),cmd_args);
exit(1); // if we get here, the execute didn't work, so bail on child process
default: // parent process
close(p[0]);
close(p2[1]);
if (input_data != "") {
write(p[1],input_data.c_str(),strlen(input_data.c_str()));
}
close(p[1]);
waitpid(pid,&child_stat,0);
if (child_stat != 0) {
error = true;
}
else {
while ((read(p2[0],&cread,1)) && (cread != EOF)) {
if (output==NULL) output = (char*)malloc(output_length*sizeof(char));
else if (current_size == output_length-2) {
output_length *= 2;
output = (char*)realloc(output,output_length);
}
if (output!=NULL) {
output[current_size++] = cread;
}
else {
error = true;
}
}
}
if (!error && output!=NULL) {
output[current_size] = '\0';
}
}
}
close(p2[0]); // close rest of pipe
for (i=0; i<num_args; i++) free(cmd_args[i]);
free(cmd_args);
if (!error) {
return output;
}
return NULL;
}
@getify
Copy link
Author

getify commented Oct 11, 2010

the cmd that is sent to this program is another executable (in my testing, a simple CLI php script), which loops reading from stdin until it receives EOF, and then does its business. The above code (L44) where it write()'s the input from parent to child, even though it's followed on L46 with a close() on the pipe, the EOF is not getting sent, so the child process sits and waits for more input (it IS getting the initial written input).

How do i force EOF to be sent to the child after the write, other than closing the pipe?

@getify
Copy link
Author

getify commented Oct 12, 2010

updated the code with two pipes and it seems to be working correctly now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment