xref: /plan9-contrib/sys/src/cmd/rc/haventfork.c (revision c6df144405f586b73992827d584728dc975dff14)
1 #include "rc.h"
2 #include "exec.h"
3 #include "io.h"
4 #include "fns.h"
5 
6 int havefork = 0;
7 
8 static char **
rcargv(char * s)9 rcargv(char *s)
10 {
11 	int argc;
12 	char **argv;
13 	word *p;
14 
15 	p = vlook("*")->val;
16 	argv = emalloc((count(p)+6)*sizeof(char*));
17 	argc = 0;
18 	argv[argc++] = argv0;
19 	if(flag['e'])
20 		argv[argc++] = "-Se";
21 	else
22 		argv[argc++] = "-S";
23 	argv[argc++] = "-c";
24 	argv[argc++] = s;
25 	for(p = vlook("*")->val; p; p = p->next)
26 		argv[argc++] = p->word;
27 	argv[argc] = 0;
28 	return argv;
29 }
30 
31 void
Xasync(void)32 Xasync(void)
33 {
34 	uint pid;
35 	char buf[20], **argv;
36 
37 	Updenv();
38 
39 	argv = rcargv(runq->code[runq->pc].s);
40 	pid = ForkExecute(argv0, argv, -1, 1, 2);
41 	free(argv);
42 
43 	if(pid == 0) {
44 		Xerror("proc failed");
45 		return;
46 	}
47 
48 	runq->pc++;
49 	snprint(buf, sizeof buf, "%d", pid);
50 	setvar("apid", newword(buf, (word *)0));
51 }
52 
53 void
Xbackq(void)54 Xbackq(void)
55 {
56 	char wd[8193], **argv;
57 	int c;
58 	char *s, *ewd=&wd[8192], *stop;
59 	struct io *f;
60 	var *ifs = vlook("ifs");
61 	word *v, *nextv;
62 	int pfd[2];
63 	int pid;
64 
65 	stop = ifs->val?ifs->val->word:"";
66 	if(pipe(pfd)<0){
67 		Xerror("can't make pipe");
68 		return;
69 	}
70 
71 	Updenv();
72 
73 	argv = rcargv(runq->code[runq->pc].s);
74 	pid = ForkExecute(argv0, argv, -1, pfd[1], 2);
75 	free(argv);
76 
77 	close(pfd[1]);
78 
79 	if(pid == 0) {
80 		Xerror("proc failed");
81 		close(pfd[0]);
82 		return;
83 	}
84 
85 	f = openfd(pfd[0]);
86 	s = wd;
87 	v = 0;
88 	while((c=rchr(f))!=EOF){
89 		if(strchr(stop, c) || s==ewd){
90 			if(s!=wd){
91 				*s='\0';
92 				v=newword(wd, v);
93 				s=wd;
94 			}
95 		}
96 		else *s++=c;
97 	}
98 	if(s!=wd){
99 		*s='\0';
100 		v=newword(wd, v);
101 	}
102 	closeio(f);
103 	Waitfor(pid, 1);
104 	/* v points to reversed arglist -- reverse it onto argv */
105 	while(v){
106 		nextv=v->next;
107 		v->next=runq->argv->words;
108 		runq->argv->words=v;
109 		v=nextv;
110 	}
111 	runq->pc++;
112 }
113 
114 void
Xpipe(void)115 Xpipe(void)
116 {
117 	thread *p=runq;
118 	int pc=p->pc, pid;
119 	int rfd=p->code[pc+1].i;
120 	int pfd[2];
121 	char **argv;
122 
123 	if(pipe(pfd)<0){
124 		Xerror1("can't get pipe");
125 		return;
126 	}
127 
128 	Updenv();
129 
130 	argv = rcargv(runq->code[pc+2].s);
131 	pid = ForkExecute(argv0, argv, 0, pfd[1], 2);
132 	free(argv);
133 	close(pfd[1]);
134 
135 	if(pid == 0) {
136 		Xerror("proc failed");
137 		close(pfd[0]);
138 		return;
139 	}
140 
141 	start(p->code, pc+4, runq->local);
142 	pushredir(ROPEN, pfd[0], rfd);
143 	p->pc=p->code[pc+3].i;
144 	p->pid=pid;
145 }
146 
147 void
Xpipefd(void)148 Xpipefd(void)
149 {
150 	Abort();
151 }
152 
153 void
Xsubshell(void)154 Xsubshell(void)
155 {
156 	char **argv;
157 	int pid;
158 
159 	Updenv();
160 
161 	argv = rcargv(runq->code[runq->pc].s);
162 	pid = ForkExecute(argv0, argv, -1, 1, 2);
163 	free(argv);
164 
165 	if(pid < 0) {
166 		Xerror("proc failed");
167 		return;
168 	}
169 
170 	Waitfor(pid, 1);
171 	runq->pc++;
172 }
173 
174 /*
175  *  start a process running the cmd on the stack and return its pid.
176  */
177 int
execforkexec(void)178 execforkexec(void)
179 {
180 	char **argv;
181 	char file[1024];
182 	int nc;
183 	word *path;
184 	int pid;
185 
186 	if(runq->argv->words==0)
187 		return -1;
188 	argv = mkargv(runq->argv->words);
189 
190 	for(path = searchpath(runq->argv->words->word);path;path = path->next){
191 		nc = strlen(path->word);
192 		if(nc < sizeof file - 1){	/* 1 for / */
193 			strcpy(file, path->word);
194 			if(file[0]){
195 				strcat(file, "/");
196 				nc++;
197 			}
198 			if(nc+strlen(argv[1])<sizeof(file)){
199 				strcat(file, argv[1]);
200 				pid = ForkExecute(file, argv+1, mapfd(0), mapfd(1), mapfd(2));
201 				if(pid >= 0){
202 					free(argv);
203 					return pid;
204 				}
205 			}
206 		}
207 	}
208 	free(argv);
209 	return -1;
210 }
211