]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/rc/havefork.c
rc: change plan9 envname limit to 128, cleanup
[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 /*
75  * Who should wait for the exit from the fork?
76  */
77 enum { Stralloc = 100, };
78
79 void
80 Xbackq(void)
81 {
82         int c, l, pid;
83         int pfd[2];
84         char *s, *wd, *ewd, *stop;
85         struct io *f;
86         var *ifs = vlook("ifs");
87         word *v, *nextv;
88
89         stop = ifs->val? ifs->val->word: "";
90         if(pipe(pfd)<0){
91                 Xerror("can't make pipe");
92                 return;
93         }
94         switch(pid = fork()){
95         case -1:
96                 Xerror("try again");
97                 close(pfd[PRD]);
98                 close(pfd[PWR]);
99                 return;
100         case 0:
101                 clearwaitpids();
102                 close(pfd[PRD]);
103                 start(runq->code, runq->pc+1, runq->local);
104                 pushredir(ROPEN, pfd[PWR], 1);
105                 return;
106         default:
107                 addwaitpid(pid);
108                 close(pfd[PWR]);
109                 f = openfd(pfd[PRD]);
110                 s = wd = ewd = 0;
111                 v = 0;
112                 while((c = rchr(f))!=EOF){
113                         if(s==ewd){
114                                 l = s-wd;
115                                 wd = erealloc(wd, l+Stralloc);
116                                 ewd = wd+l+Stralloc-1;
117                                 s = wd+l;
118                         }
119                         if(strchr(stop, c)){
120                                 if(s!=wd){
121                                         *s='\0';
122                                         v = newword(wd, v);
123                                         s = wd;
124                                 }
125                         }
126                         else *s++=c;
127                 }
128                 if(s!=wd){
129                         *s='\0';
130                         v = newword(wd, v);
131                 }
132                 if(wd)
133                         efree(wd);
134                 closeio(f);
135                 Waitfor(pid, 0);
136                 /* v points to reversed arglist -- reverse it onto argv */
137                 while(v){
138                         nextv = v->next;
139                         v->next = runq->argv->words;
140                         runq->argv->words = v;
141                         v = nextv;
142                 }
143                 runq->pc = runq->code[runq->pc].i;
144                 return;
145         }
146 }
147
148 void
149 Xpipefd(void)
150 {
151         struct thread *p = runq;
152         int pc = p->pc, pid;
153         char name[40];
154         int pfd[2];
155         int sidefd, mainfd;
156         if(pipe(pfd)<0){
157                 Xerror("can't get pipe");
158                 return;
159         }
160         if(p->code[pc].i==READ){
161                 sidefd = pfd[PWR];
162                 mainfd = pfd[PRD];
163         }
164         else{
165                 sidefd = pfd[PRD];
166                 mainfd = pfd[PWR];
167         }
168         switch(pid = fork()){
169         case -1:
170                 Xerror("try again");
171                 break;
172         case 0:
173                 clearwaitpids();
174                 start(p->code, pc+2, runq->local);
175                 close(mainfd);
176                 pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
177                 runq->ret = 0;
178                 break;
179         default:
180                 addwaitpid(pid);
181                 close(sidefd);
182                 pushredir(ROPEN, mainfd, mainfd);       /* isn't this a noop? */
183                 strcpy(name, Fdprefix);
184                 inttoascii(name+strlen(name), mainfd);
185                 pushword(name);
186                 p->pc = p->code[pc+1].i;
187                 break;
188         }
189 }
190
191 void
192 Xsubshell(void)
193 {
194         int pid;
195         switch(pid = fork()){
196         case -1:
197                 Xerror("try again");
198                 break;
199         case 0:
200                 clearwaitpids();
201                 start(runq->code, runq->pc+1, runq->local);
202                 runq->ret = 0;
203                 break;
204         default:
205                 addwaitpid(pid);
206                 Waitfor(pid, 1);
207                 runq->pc = runq->code[runq->pc].i;
208                 break;
209         }
210 }
211
212 int
213 execforkexec(void)
214 {
215         int pid;
216         int n;
217         char buf[ERRMAX];
218
219         switch(pid = fork()){
220         case -1:
221                 return -1;
222         case 0:
223                 clearwaitpids();
224                 pushword("exec");
225                 execexec();
226                 strcpy(buf, "can't exec: ");
227                 n = strlen(buf);
228                 errstr(buf+n, ERRMAX-n);
229                 Exit(buf);
230         }
231         addwaitpid(pid);
232         return pid;
233 }