tprocess.c - plan9port - [fork] Plan 9 from user space
HTML git clone git://src.adamsgaard.dk/plan9port
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
tprocess.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 }