]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/rc/havefork.c
kernel: keep segment locked for data2txt
[plan9front.git] / sys / src / cmd / rc / havefork.c
1 #include "rc.h"
2 #include "getflags.h"
3 #include "exec.h"
4 #include "io.h"
5 #include "fns.h"
6
7 int havefork = 1;
8
9 void
10 Xasync(void)
11 {
12         int null = open("/dev/null", 0);
13         int pid;
14         char npid[10];
15         if(null<0){
16                 Xerror("Can't open /dev/null\n");
17                 return;
18         }
19         switch(pid = rfork(RFFDG|RFPROC|RFNOTEG)){
20         case -1:
21                 close(null);
22                 Xerror("try again");
23                 break;
24         case 0:
25                 clearwaitpids();
26                 pushredir(ROPEN, null, 0);
27                 start(runq->code, runq->pc+1, runq->local);
28                 runq->ret = 0;
29                 break;
30         default:
31                 addwaitpid(pid);
32                 close(null);
33                 runq->pc = runq->code[runq->pc].i;
34                 inttoascii(npid, pid);
35                 setvar("apid", newword(npid, (word *)0));
36                 break;
37         }
38 }
39
40 void
41 Xpipe(void)
42 {
43         struct thread *p = runq;
44         int pc = p->pc, forkid;
45         int lfd = p->code[pc++].i;
46         int rfd = p->code[pc++].i;
47         int pfd[2];
48         if(pipe(pfd)<0){
49                 Xerror("can't get pipe");
50                 return;
51         }
52         switch(forkid = fork()){
53         case -1:
54                 Xerror("try again");
55                 break;
56         case 0:
57                 clearwaitpids();
58                 start(p->code, pc+2, runq->local);
59                 runq->ret = 0;
60                 close(pfd[PRD]);
61                 pushredir(ROPEN, pfd[PWR], lfd);
62                 break;
63         default:
64                 addwaitpid(forkid);
65                 start(p->code, p->code[pc].i, runq->local);
66                 close(pfd[PWR]);
67                 pushredir(ROPEN, pfd[PRD], rfd);
68                 p->pc = p->code[pc+1].i;
69                 p->pid = forkid;
70                 break;
71         }
72 }
73
74 char*
75 erealloc(char *p, long n)
76 {
77         p = realloc(p, n);              /* botch, should be Realloc */
78         if(p==0)
79                 panic("Can't realloc %d bytes\n", n);
80         return p;
81 }
82
83 /*
84  * Who should wait for the exit from the fork?
85  */
86 enum { Stralloc = 100, };
87
88 void
89 Xbackq(void)
90 {
91         int c, l, pid;
92         int pfd[2];
93         char *s, *wd, *ewd, *stop;
94         struct io *f;
95         var *ifs = vlook("ifs");
96         word *v, *nextv;
97
98         stop = ifs->val? ifs->val->word: "";
99         if(pipe(pfd)<0){
100                 Xerror("can't make pipe");
101                 return;
102         }
103         switch(pid = fork()){
104         case -1:
105                 Xerror("try again");
106                 close(pfd[PRD]);
107                 close(pfd[PWR]);
108                 return;
109         case 0:
110                 clearwaitpids();
111                 close(pfd[PRD]);
112                 start(runq->code, runq->pc+1, runq->local);
113                 pushredir(ROPEN, pfd[PWR], 1);
114                 return;
115         default:
116                 addwaitpid(pid);
117                 close(pfd[PWR]);
118                 f = openfd(pfd[PRD]);
119                 s = wd = ewd = 0;
120                 v = 0;
121                 while((c = rchr(f))!=EOF){
122                         if(s==ewd){
123                                 l = s-wd;
124                                 wd = erealloc(wd, l+Stralloc);
125                                 ewd = wd+l+Stralloc-1;
126                                 s = wd+l;
127                         }
128                         if(strchr(stop, c)){
129                                 if(s!=wd){
130                                         *s='\0';
131                                         v = newword(wd, v);
132                                         s = wd;
133                                 }
134                         }
135                         else *s++=c;
136                 }
137                 if(s!=wd){
138                         *s='\0';
139                         v = newword(wd, v);
140                 }
141                 if(wd)
142                         efree(wd);
143                 closeio(f);
144                 Waitfor(pid, 0);
145                 /* v points to reversed arglist -- reverse it onto argv */
146                 while(v){
147                         nextv = v->next;
148                         v->next = runq->argv->words;
149                         runq->argv->words = v;
150                         v = nextv;
151                 }
152                 runq->pc = runq->code[runq->pc].i;
153                 return;
154         }
155 }
156
157 void
158 Xpipefd(void)
159 {
160         struct thread *p = runq;
161         int pc = p->pc, pid;
162         char name[40];
163         int pfd[2];
164         int sidefd, mainfd;
165         if(pipe(pfd)<0){
166                 Xerror("can't get pipe");
167                 return;
168         }
169         if(p->code[pc].i==READ){
170                 sidefd = pfd[PWR];
171                 mainfd = pfd[PRD];
172         }
173         else{
174                 sidefd = pfd[PRD];
175                 mainfd = pfd[PWR];
176         }
177         switch(pid = fork()){
178         case -1:
179                 Xerror("try again");
180                 break;
181         case 0:
182                 clearwaitpids();
183                 start(p->code, pc+2, runq->local);
184                 close(mainfd);
185                 pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
186                 runq->ret = 0;
187                 break;
188         default:
189                 addwaitpid(pid);
190                 close(sidefd);
191                 pushredir(ROPEN, mainfd, mainfd);       /* isn't this a noop? */
192                 strcpy(name, Fdprefix);
193                 inttoascii(name+strlen(name), mainfd);
194                 pushword(name);
195                 p->pc = p->code[pc+1].i;
196                 break;
197         }
198 }
199
200 void
201 Xsubshell(void)
202 {
203         int pid;
204         switch(pid = fork()){
205         case -1:
206                 Xerror("try again");
207                 break;
208         case 0:
209                 clearwaitpids();
210                 start(runq->code, runq->pc+1, runq->local);
211                 runq->ret = 0;
212                 break;
213         default:
214                 addwaitpid(pid);
215                 Waitfor(pid, 1);
216                 runq->pc = runq->code[runq->pc].i;
217                 break;
218         }
219 }
220
221 int
222 execforkexec(void)
223 {
224         int pid;
225         int n;
226         char buf[ERRMAX];
227
228         switch(pid = fork()){
229         case -1:
230                 return -1;
231         case 0:
232                 clearwaitpids();
233                 pushword("exec");
234                 execexec();
235                 strcpy(buf, "can't exec: ");
236                 n = strlen(buf);
237                 errstr(buf+n, ERRMAX-n);
238                 Exit(buf);
239         }
240         addwaitpid(pid);
241         return pid;
242 }