diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/lib/bsd/popen.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/lib/bsd/popen.c')
-rwxr-xr-x | sys/src/ape/lib/bsd/popen.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/sys/src/ape/lib/bsd/popen.c b/sys/src/ape/lib/bsd/popen.c new file mode 100755 index 000000000..32af1de3d --- /dev/null +++ b/sys/src/ape/lib/bsd/popen.c @@ -0,0 +1,84 @@ +#include <stdlib.h> +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> +#include <sys/wait.h> + +#define MAXFORKS 20 +#define NSYSFILE 3 +#define tst(a,b) (*mode == 'r'? (b) : (a)) +#define RDR 0 +#define WTR 1 + +struct a_fork { + short done; + short fd; + int pid; + int status; +}; +static struct a_fork the_fork[MAXFORKS]; + +FILE * +popen(char *cmd, char *mode) +{ + int p[2]; + int myside, hisside, pid; + int i, ind; + + for (ind = 0; ind < MAXFORKS; ind++) + if (the_fork[ind].pid == 0) + break; + if (ind == MAXFORKS) + return NULL; + if(pipe(p) < 0) + return NULL; + myside = tst(p[WTR], p[RDR]); + hisside = tst(p[RDR], p[WTR]); + switch (pid = fork()) { + case -1: + return NULL; + case 0: + /* myside and hisside reverse roles in child */ + close(myside); + dup2(hisside, tst(0, 1)); + for (i=NSYSFILE; i<FOPEN_MAX; i++) + close(i); + execl("/bin/ape/sh", "sh", "-c", cmd, NULL); + _exit(1); + default: + the_fork[ind].pid = pid; + the_fork[ind].fd = myside; + the_fork[ind].done = 0; + close(hisside); + return(fdopen(myside, mode)); + } +} + +int +pclose(FILE *ptr) +{ + int f, r, ind; + int status; + + f = fileno(ptr); + fclose(ptr); + for (ind = 0; ind < MAXFORKS; ind++) + if (the_fork[ind].fd == f && the_fork[ind].pid != 0) + break; + if (ind == MAXFORKS) + return 0; + if (!the_fork[ind].done) { + do { + r = wait(&status); + for (f = 0; f < MAXFORKS; f++) + if (the_fork[f].pid == r) { + the_fork[f].done = 1; + the_fork[f].status = status; + break; + } + } while(r != the_fork[ind].pid && r != -1); + the_fork[ind].status = r == -1 ? -1 : status; + } + the_fork[ind].pid = 0; + return (the_fork[ind].status); +} |