|
|
1.1 ! root 1: /* @(#)popen.c 4.1 (Berkeley) 12/21/80 */ ! 2: #include <stdio.h> ! 3: #include <signal.h> ! 4: #include <sys/param.h> ! 5: ! 6: #define MAXFORKS 20 ! 7: #define tst(a,b) (*mode == 'r'? (b) : (a)) ! 8: #define RDR 0 ! 9: #define WTR 1 ! 10: ! 11: struct a_fork { ! 12: short done; ! 13: short fd; ! 14: int pid; ! 15: int status; ! 16: }; ! 17: static struct a_fork the_fork[MAXFORKS]; ! 18: ! 19: static FILE * ! 20: _popen(cmd,mode,paranoid,args,env) ! 21: char *cmd; ! 22: char *mode; ! 23: int paranoid; ! 24: char **args, **env; ! 25: { ! 26: int p[2]; ! 27: register myside, hisside, pid; ! 28: register i, ind; ! 29: ! 30: for (ind = 0; ind < MAXFORKS; ind++) ! 31: if (the_fork[ind].pid == 0) ! 32: break; ! 33: if (ind == MAXFORKS) ! 34: return NULL; ! 35: if(pipe(p) < 0) ! 36: return NULL; ! 37: myside = tst(p[WTR], p[RDR]); ! 38: hisside = tst(p[RDR], p[WTR]); ! 39: switch (pid = vfork()) { ! 40: case -1: ! 41: return NULL; ! 42: case 0: ! 43: /* myside and hisside reverse roles in child */ ! 44: close(myside); ! 45: dup2(hisside, tst(0, 1)); ! 46: if (paranoid!=2) { ! 47: /* a hack for "safety" against incautious SUIDs */ ! 48: setuid(getuid()); ! 49: setgid(getgid()); ! 50: } ! 51: for (i=NSYSFILE; i<_NFILE; i++) ! 52: close(i); ! 53: if (paranoid==2) ! 54: execve(cmd, args, env); ! 55: else if (paranoid==1) ! 56: execl("/bin/sh", "sh", "-c", "-p", cmd, 0); ! 57: else ! 58: execl("/bin/sh", "sh", "-c", cmd, 0); ! 59: _exit(1); ! 60: default: ! 61: the_fork[ind].pid = pid; ! 62: the_fork[ind].fd = myside; ! 63: the_fork[ind].done = 0; ! 64: close(hisside); ! 65: return(fdopen(myside, mode)); ! 66: } ! 67: } ! 68: ! 69: FILE * ! 70: popen(cmd,mode) ! 71: char *cmd; ! 72: char *mode; ! 73: { ! 74: return _popen(cmd, mode, 0, (char **)NULL, (char **)NULL); ! 75: } ! 76: ! 77: FILE * ! 78: ppopen(cmd,mode) ! 79: char *cmd; ! 80: char *mode; ! 81: { ! 82: return _popen(cmd, mode, 1, (char **)NULL, (char **)NULL); ! 83: } ! 84: ! 85: FILE * ! 86: vepopen(cmd,mode,args,env) ! 87: char *cmd; ! 88: char *mode; ! 89: char **args; ! 90: char **env; ! 91: { ! 92: return(_popen(cmd, mode, 2, args, env)); ! 93: } ! 94: ! 95: pclose(ptr) ! 96: FILE *ptr; ! 97: { ! 98: register f, r, ind, (*hstat)(), (*istat)(), (*qstat)(); ! 99: int status; ! 100: ! 101: f = fileno(ptr); ! 102: fclose(ptr); ! 103: for (ind = 0; ind < MAXFORKS; ind++) ! 104: if (the_fork[ind].fd == f && the_fork[ind].pid != 0) ! 105: break; ! 106: if (ind == MAXFORKS) ! 107: return 0; ! 108: if (!the_fork[ind].done) { ! 109: istat = signal(SIGINT, SIG_IGN); ! 110: qstat = signal(SIGQUIT, SIG_IGN); ! 111: hstat = signal(SIGHUP, SIG_IGN); ! 112: do { ! 113: r = wait(&status); ! 114: for (f = 0; f < MAXFORKS; f++) ! 115: if (the_fork[f].pid == r) { ! 116: the_fork[f].done = 1; ! 117: the_fork[f].status = status; ! 118: break; ! 119: } ! 120: } while(r != the_fork[ind].pid && r != -1); ! 121: the_fork[ind].status = r == -1 ? -1 : status; ! 122: signal(SIGINT, istat); ! 123: signal(SIGQUIT, qstat); ! 124: signal(SIGHUP, hstat); ! 125: } ! 126: the_fork[ind].pid = 0; ! 127: return (the_fork[ind].status); ! 128: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.