plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }