Re: Bi-directional popen()

From: Date: Sat, 24 Mar 2001 09:13:35 +0000
Subject: Re: Bi-directional popen()
References: 1  Groups: php.dev 
Request: Send a blank email to php-dev+get-49867@lists.php.net to get a copy of this message
On Wed, 21 Mar 2001, Anil Madhavapeddy wrote: > This has come up a few times, but is there any chance of having a > bi-directional popen() that doesn't depend on the underlying system > call supporting it? Hm.. it would be possible to make one that uses socketpair() instead of pipe() to do it's work. Something to the effect of: /* Real global */ int return_code = 0; pid_t last_pid = 0; /* This means it can only have one popen() going at once.. */ void php_sigchld_handler(int sig) { int status; pid_t pid; pid = wait4(-1, &status, WNOHANG, NULL); if (pid > 0) { if (WIFEXITED(status)) { return_code = WEXITSTATUS(status); } } return; } int php_pclose(FILE *pipe) { int fd = _fileno(pipe); int ret; int status; fclose(pipe); ret = wait4(last_pid, &status, WNOHANG, NULL); if (ret == 0) { kill(last_pid, SIGTERM); if (ret == 0) return return_code; else return WEXITSTATUS(status); } else { return WEXITSTATUS(status); } } FILE* php_popen(char *cmd, char *mode) { int fds[2]; FILE *ret; pid_t pid; int i; if ((mode[0] == 'r' || mode[0] == 'w') && mode[1] == '\0') { return popen(cmd, mode); } else { if (socketpair(AF_INET, SOCK_STREAM, 0, fds[2]) == 0) { pid = fork(); if (pid > 0) { /* Parent process */ /* Catch SIGCHLD to tell us when it's exited. */ (void) signal(SIGCHLD, php_sigchld_handler); /* Create a FILE* from the file descriptor */ ret = fdopen(fds[0], "w+"); if (ret == NULL) { /* Oh -- can't fdopen()? */ (void) kill(ret, SIGKILL); } /* And we're done */ return ret; } else if (pid == 0) { /* Child process */ for (i = 0; i < 1024; i++) { if (i != fds[1]) { (void) close(i); } } /* Create stdin/stdout/stderr */ dup2(fds[1], 0); dup2(fds[1], 1); dup2(fds[1], 2); execl("/bin/sh", "-c", cmd, (char *) 0); exit(127); } else { return NULL; } } } } PS: This is just a quick hack. I think it might work as is, but it's not something I would try using as-is without checking it out first. Chris

« previous php.dev (#49867) next »