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