xref: /plan9-contrib/sys/src/cmd/rc/havefork.c (revision a84536681645e23c630ce4ef2e5c3b284d4c590b)
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 		pushredir(ROPEN, null, 0);
26 		start(runq->code, runq->pc+1, runq->local);
27 		runq->ret = 0;
28 		break;
29 	default:
30 		close(null);
31 		runq->pc = runq->code[runq->pc].i;
32 		inttoascii(npid, pid);
33 		setvar("apid", newword(npid, (word *)0));
34 		break;
35 	}
36 }
37 
38 void
39 Xpipe(void)
40 {
41 	struct thread *p = runq;
42 	int pc = p->pc, forkid;
43 	int lfd = p->code[pc++].i;
44 	int rfd = p->code[pc++].i;
45 	int pfd[2];
46 	if(pipe(pfd)<0){
47 		Xerror("can't get pipe");
48 		return;
49 	}
50 	switch(forkid = fork()){
51 	case -1:
52 		Xerror("try again");
53 		break;
54 	case 0:
55 		start(p->code, pc+2, runq->local);
56 		runq->ret = 0;
57 		close(pfd[PRD]);
58 		pushredir(ROPEN, pfd[PWR], lfd);
59 		break;
60 	default:
61 		start(p->code, p->code[pc].i, runq->local);
62 		close(pfd[PWR]);
63 		pushredir(ROPEN, pfd[PRD], rfd);
64 		p->pc = p->code[pc+1].i;
65 		p->pid = forkid;
66 		break;
67 	}
68 }
69 
70 /*
71  * Who should wait for the exit from the fork?
72  */
73 void
74 Xbackq(void)
75 {
76 	char wd[8193];
77 	int c;
78 	char *s, *ewd=&wd[8192], *stop;
79 	struct io *f;
80 	var *ifs = vlook("ifs");
81 	word *v, *nextv;
82 	int pfd[2];
83 	int pid;
84 	stop = ifs->val?ifs->val->word:"";
85 	if(pipe(pfd)<0){
86 		Xerror("can't make pipe");
87 		return;
88 	}
89 	switch(pid = fork()){
90 	case -1:
91 		Xerror("try again");
92 		close(pfd[PRD]);
93 		close(pfd[PWR]);
94 		return;
95 	case 0:
96 		close(pfd[PRD]);
97 		start(runq->code, runq->pc+1, runq->local);
98 		pushredir(ROPEN, pfd[PWR], 1);
99 		return;
100 	default:
101 		close(pfd[PWR]);
102 		f = openfd(pfd[PRD]);
103 		s = wd;
104 		v = 0;
105 		while((c = rchr(f))!=EOF){
106 			if(strchr(stop, c) || s==ewd){
107 				if(s!=wd){
108 					*s='\0';
109 					v = newword(wd, v);
110 					s = wd;
111 				}
112 			}
113 			else *s++=c;
114 		}
115 		if(s!=wd){
116 			*s='\0';
117 			v = newword(wd, v);
118 		}
119 		closeio(f);
120 		Waitfor(pid, 0);
121 		/* v points to reversed arglist -- reverse it onto argv */
122 		while(v){
123 			nextv = v->next;
124 			v->next = runq->argv->words;
125 			runq->argv->words = v;
126 			v = nextv;
127 		}
128 		runq->pc = runq->code[runq->pc].i;
129 		return;
130 	}
131 }
132 
133 void
134 Xpipefd(void)
135 {
136 	struct thread *p = runq;
137 	int pc = p->pc;
138 	char name[40];
139 	int pfd[2];
140 	int sidefd, mainfd;
141 	if(pipe(pfd)<0){
142 		Xerror("can't get pipe");
143 		return;
144 	}
145 	if(p->code[pc].i==READ){
146 		sidefd = pfd[PWR];
147 		mainfd = pfd[PRD];
148 	}
149 	else{
150 		sidefd = pfd[PRD];
151 		mainfd = pfd[PWR];
152 	}
153 	switch(fork()){
154 	case -1:
155 		Xerror("try again");
156 		break;
157 	case 0:
158 		start(p->code, pc+2, runq->local);
159 		close(mainfd);
160 		pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
161 		runq->ret = 0;
162 		break;
163 	default:
164 		close(sidefd);
165 		pushredir(ROPEN, mainfd, mainfd);	/* isn't this a noop? */
166 		strcpy(name, Fdprefix);
167 		inttoascii(name+strlen(name), mainfd);
168 		pushword(name);
169 		p->pc = p->code[pc+1].i;
170 		break;
171 	}
172 }
173 
174 void
175 Xsubshell(void)
176 {
177 	int pid;
178 	switch(pid = fork()){
179 	case -1:
180 		Xerror("try again");
181 		break;
182 	case 0:
183 		start(runq->code, runq->pc+1, runq->local);
184 		runq->ret = 0;
185 		break;
186 	default:
187 		Waitfor(pid, 1);
188 		runq->pc = runq->code[runq->pc].i;
189 		break;
190 	}
191 }
192 
193 int
194 execforkexec(void)
195 {
196 	int pid;
197 	int n;
198 	char buf[ERRMAX];
199 
200 	switch(pid = fork()){
201 	case -1:
202 		return -1;
203 	case 0:
204 		pushword("exec");
205 		execexec();
206 		strcpy(buf, "can't exec: ");
207 		n = strlen(buf);
208 		errstr(buf+n, ERRMAX-n);
209 		Exit(buf);
210 	}
211 	return pid;
212 }
213