process.c (3066B)
1 #include "common.h" 2 3 /* make a stream to a child process */ 4 extern stream * 5 instream(void) 6 { 7 stream *rv; 8 int pfd[2]; 9 10 if ((rv = (stream *)malloc(sizeof(stream))) == 0) 11 return 0; 12 memset(rv, 0, sizeof(stream)); 13 if (pipe(pfd) < 0) 14 return 0; 15 if(Binit(&rv->bb, pfd[1], OWRITE) < 0){ 16 close(pfd[0]); 17 close(pfd[1]); 18 return 0; 19 } 20 rv->fp = &rv->bb; 21 rv->fd = pfd[0]; 22 return rv; 23 } 24 25 /* make a stream from a child process */ 26 extern stream * 27 outstream(void) 28 { 29 stream *rv; 30 int pfd[2]; 31 32 if ((rv = (stream *)malloc(sizeof(stream))) == 0) 33 return 0; 34 memset(rv, 0, sizeof(stream)); 35 if (pipe(pfd) < 0) 36 return 0; 37 if (Binit(&rv->bb, pfd[0], OREAD) < 0){ 38 close(pfd[0]); 39 close(pfd[1]); 40 return 0; 41 } 42 rv->fp = &rv->bb; 43 rv->fd = pfd[1]; 44 return rv; 45 } 46 47 extern void 48 stream_free(stream *sp) 49 { 50 int fd; 51 52 close(sp->fd); 53 fd = Bfildes(sp->fp); 54 Bterm(sp->fp); 55 close(fd); 56 free((char *)sp); 57 } 58 59 /* start a new process */ 60 extern process * 61 noshell_proc_start(char **av, stream *inp, stream *outp, stream *errp, int newpg, char *who) 62 { 63 process *pp; 64 int i, n; 65 66 if ((pp = (process *)malloc(sizeof(process))) == 0) { 67 if (inp != 0) 68 stream_free(inp); 69 if (outp != 0) 70 stream_free(outp); 71 if (errp != 0) 72 stream_free(errp); 73 return 0; 74 } 75 pp->std[0] = inp; 76 pp->std[1] = outp; 77 pp->std[2] = errp; 78 switch (pp->pid = fork()) { 79 case -1: 80 proc_free(pp); 81 return 0; 82 case 0: 83 if(newpg) 84 sysdetach(); 85 for (i=0; i<3; i++) 86 if (pp->std[i] != 0){ 87 close(Bfildes(pp->std[i]->fp)); 88 while(pp->std[i]->fd < 3) 89 pp->std[i]->fd = dup(pp->std[i]->fd, -1); 90 } 91 for (i=0; i<3; i++) 92 if (pp->std[i] != 0) 93 dup(pp->std[i]->fd, i); 94 for (n = sysfiles(); i < n; i++) 95 close(i); 96 if(who) 97 fprint(2, "warning: cannot run %s as %s\n", av[0], who); 98 exec(av[0], av); 99 perror("proc_start"); 100 exits("proc_start"); 101 default: 102 for (i=0; i<3; i++) 103 if (pp->std[i] != 0) { 104 close(pp->std[i]->fd); 105 pp->std[i]->fd = -1; 106 } 107 return pp; 108 } 109 } 110 111 /* start a new process under a shell */ 112 extern process * 113 proc_start(char *cmd, stream *inp, stream *outp, stream *errp, int newpg, char *who) 114 { 115 char *av[4]; 116 117 upasconfig(); 118 av[0] = SHELL; 119 av[1] = "-c"; 120 av[2] = cmd; 121 av[3] = 0; 122 return noshell_proc_start(av, inp, outp, errp, newpg, who); 123 } 124 125 /* wait for a process to stop */ 126 extern int 127 proc_wait(process *pp) 128 { 129 Waitmsg *status; 130 char err[Errlen]; 131 132 for(;;){ 133 status = wait(); 134 if(status == nil){ 135 errstr(err, sizeof(err)); 136 if(strstr(err, "interrupt") == 0) 137 break; 138 } 139 if (status->pid==pp->pid) 140 break; 141 } 142 pp->pid = -1; 143 if(status == nil) 144 pp->status = -1; 145 else 146 pp->status = status->msg[0]; 147 pp->waitmsg = status; 148 return pp->status; 149 } 150 151 /* free a process */ 152 extern int 153 proc_free(process *pp) 154 { 155 int i; 156 157 if(pp->std[1] == pp->std[2]) 158 pp->std[2] = 0; /* avoid freeing it twice */ 159 for (i = 0; i < 3; i++) 160 if (pp->std[i]) 161 stream_free(pp->std[i]); 162 if (pp->pid >= 0) 163 proc_wait(pp); 164 free(pp->waitmsg); 165 free((char *)pp); 166 return 0; 167 } 168 169 /* kill a process */ 170 extern int 171 proc_kill(process *pp) 172 { 173 return syskill(pp->pid); 174 }