1 #include "rc.h"
2 #include "exec.h"
3 #include "io.h"
4 #include "fns.h"
5
6 int havefork = 1;
7
8 void
Xasync(void)9 Xasync(void)
10 {
11 int null = open("/dev/null", 0);
12 int pid;
13 char npid[10];
14 if(null<0){
15 Xerror("Can't open /dev/null\n");
16 return;
17 }
18 switch(pid = rfork(RFFDG|RFPROC|RFNOTEG)){
19 case -1:
20 close(null);
21 Xerror("try again");
22 break;
23 case 0:
24 clearwaitpids();
25 pushredir(ROPEN, null, 0);
26 start(runq->code, runq->pc+1, runq->local);
27 runq->ret = 0;
28 break;
29 default:
30 addwaitpid(pid);
31 close(null);
32 runq->pc = runq->code[runq->pc].i;
33 inttoascii(npid, pid);
34 setvar("apid", newword(npid, (word *)0));
35 break;
36 }
37 }
38
39 void
Xpipe(void)40 Xpipe(void)
41 {
42 struct thread *p = runq;
43 int pc = p->pc, forkid;
44 int lfd = p->code[pc++].i;
45 int rfd = p->code[pc++].i;
46 int pfd[2];
47 if(pipe(pfd)<0){
48 Xerror("can't get pipe");
49 return;
50 }
51 switch(forkid = fork()){
52 case -1:
53 Xerror("try again");
54 break;
55 case 0:
56 clearwaitpids();
57 start(p->code, pc+2, runq->local);
58 runq->ret = 0;
59 close(pfd[PRD]);
60 pushredir(ROPEN, pfd[PWR], lfd);
61 break;
62 default:
63 addwaitpid(forkid);
64 start(p->code, p->code[pc].i, runq->local);
65 close(pfd[PWR]);
66 pushredir(ROPEN, pfd[PRD], rfd);
67 p->pc = p->code[pc+1].i;
68 p->pid = forkid;
69 break;
70 }
71 }
72
73 /*
74 * Who should wait for the exit from the fork?
75 */
76
77 void
Xbackq(void)78 Xbackq(void)
79 {
80 int n, pid;
81 int pfd[2];
82 char *stop;
83 char utf[UTFmax+1];
84 io *f, *wd;
85 word *v, *nextv;
86 Rune r;
87
88 stop = "";
89 if(runq->argv && runq->argv->words)
90 stop = runq->argv->words->word;
91 if(pipe(pfd)<0){
92 Xerror("can't make pipe");
93 return;
94 }
95 switch(pid = fork()){
96 case -1:
97 Xerror("try again");
98 close(pfd[PRD]);
99 close(pfd[PWR]);
100 return;
101 case 0:
102 clearwaitpids();
103 close(pfd[PRD]);
104 start(runq->code, runq->pc+1, runq->local);
105 pushredir(ROPEN, pfd[PWR], 1);
106 return;
107 default:
108 addwaitpid(pid);
109 close(pfd[PWR]);
110 f = openfd(pfd[PRD]);
111 wd = openstr();
112 v = nil;
113 /* rutf requires at least UTFmax+1 bytes in utf */
114 while((n = rutf(f, utf, &r)) != EOF){
115 utf[n] = '\0';
116 if(utfutf(stop, utf) == nil)
117 pstr(wd, utf); /* append utf to word */
118 else
119 /*
120 * utf/r is an ifs rune (e.g., \t, \n), thus
121 * ends the current word, if any.
122 */
123 if(*(char *)wd->strp != '\0'){
124 v = newword((char *)wd->strp, v);
125 rewind(wd);
126 }
127 }
128 if(*(char *)wd->strp != '\0')
129 v = newword((char *)wd->strp, v);
130 closeio(wd);
131 closeio(f);
132 Waitfor(pid, 0);
133 poplist(); /* ditch split in "stop" */
134 /* v points to reversed arglist -- reverse it onto argv */
135 while(v){
136 nextv = v->next;
137 v->next = runq->argv->words;
138 runq->argv->words = v;
139 v = nextv;
140 }
141 runq->pc = runq->code[runq->pc].i;
142 return;
143 }
144 }
145
146 void
Xpipefd(void)147 Xpipefd(void)
148 {
149 struct thread *p = runq;
150 int pc = p->pc, pid;
151 char name[40];
152 int pfd[2];
153 int sidefd, mainfd;
154 if(pipe(pfd)<0){
155 Xerror("can't get pipe");
156 return;
157 }
158 if(p->code[pc].i==READ){
159 sidefd = pfd[PWR];
160 mainfd = pfd[PRD];
161 }
162 else{
163 sidefd = pfd[PRD];
164 mainfd = pfd[PWR];
165 }
166 switch(pid = fork()){
167 case -1:
168 Xerror("try again");
169 break;
170 case 0:
171 clearwaitpids();
172 start(p->code, pc+2, runq->local);
173 close(mainfd);
174 pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
175 runq->ret = 0;
176 break;
177 default:
178 addwaitpid(pid);
179 close(sidefd);
180 pushredir(ROPEN, mainfd, mainfd);
181 shuffleredir(); /* shuffle redir to bottom of stack for turfredir() */
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