xref: /plan9/sys/src/cmd/upas/common/process.c (revision 3b86f2f88bade1f00206c7aa750b7add255f5724)
1 #include "common.h"
2 
3 /* make a stream to a child process */
4 extern stream *
instream(void)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 *
outstream(void)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
stream_free(stream * sp)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 *
noshell_proc_start(char ** av,stream * inp,stream * outp,stream * errp,int newpg,char * who)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 			become(av, 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 *
proc_start(char * cmd,stream * inp,stream * outp,stream * errp,int newpg,char * who)113 proc_start(char *cmd, stream *inp, stream *outp, stream *errp, int newpg, char *who)
114 {
115 	char *av[4];
116 
117 	av[0] = SHELL;
118 	av[1] = "-c";
119 	av[2] = cmd;
120 	av[3] = 0;
121 	return noshell_proc_start(av, inp, outp, errp, newpg, who);
122 }
123 
124 /* wait for a process to stop */
125 extern int
proc_wait(process * pp)126 proc_wait(process *pp)
127 {
128 	Waitmsg *status;
129 	char err[Errlen];
130 
131 	for(;;){
132 		status = wait();
133 		if(status == nil){
134 			rerrstr(err, sizeof(err));
135 			if(strstr(err, "interrupt") == 0)
136 				break;
137 		}
138 		if (status->pid==pp->pid)
139 			break;
140 	}
141 	pp->pid = -1;
142 	if(status == nil)
143 		pp->status = -1;
144 	else
145 		pp->status = status->msg[0];
146 	pp->waitmsg = status;
147 	return pp->status;
148 }
149 
150 /* free a process */
151 extern int
proc_free(process * pp)152 proc_free(process *pp)
153 {
154 	int i;
155 
156 	if(pp->std[1] == pp->std[2])
157 		pp->std[2] = 0;		/* avoid freeing it twice */
158 	for (i = 0; i < 3; i++)
159 		if (pp->std[i])
160 			stream_free(pp->std[i]);
161 	if (pp->pid >= 0)
162 		proc_wait(pp);
163 	free(pp->waitmsg);
164 	free((char *)pp);
165 	return 0;
166 }
167 
168 /* kill a process */
169 extern int
proc_kill(process * pp)170 proc_kill(process *pp)
171 {
172 	return syskill(pp->pid);
173 }
174