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