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