BSD 4 release
[unix-history] / usr / src / cmd / csh / sh.sem.c
CommitLineData
31cef89c 1static char *sccsid = "@(#)sh.sem.c 4.1 10/9/80";
e0cb907a
BJ
2
3#include "sh.h"
4#include "sh.proc.h"
5#include <sys/ioctl.h>
6
7/*
8 * C shell
9 */
10
11/*VARARGS 1*/
12execute(t, wanttty, pipein, pipeout)
13 register struct command *t;
14 int wanttty, *pipein, *pipeout;
15{
16 bool forked = 0;
17 struct biltins *bifunc;
18 int pid = 0;
19 int pv[2];
20
21 if (t == 0)
22 return;
23 if ((t->t_dflg & FAND) && wanttty > 0)
24 wanttty = 0;
25 switch (t->t_dtyp) {
26
27 case TCOM:
28 if ((t->t_dcom[0][0] & (QUOTE|TRIM)) == QUOTE)
29 strcpy(t->t_dcom[0], t->t_dcom[0] + 1);
30 if ((t->t_dflg & FREDO) == 0)
31 Dfix(t); /* $ " ' \ */
32 if (t->t_dcom[0] == 0)
33 return;
34 /* fall into... */
35
36 case TPAR:
37 if (t->t_dflg & FPOU)
38 mypipe(pipeout);
39 /*
40 * Must do << early so parent will know
41 * where input pointer should be.
42 * If noexec then this is all we do.
43 */
44 if (t->t_dflg & FHERE) {
45 close(0);
46 heredoc(t->t_dlef);
47 if (noexec)
48 close(0);
49 }
50 if (noexec)
51 break;
52
53 set("status", "0");
54
55 /*
56 * This mess is the necessary kludge to handle the prefix
57 * builtins: nice, nohup, time. These commands can also
58 * be used by themselves, and this is not handled here.
59 * This will also work when loops are parsed.
60 */
61 while (t->t_dtyp == TCOM)
62 if (eq(t->t_dcom[0], "nice"))
63 if (t->t_dcom[1])
64 if (any(t->t_dcom[1][0], "+-"))
65 if (t->t_dcom[2]) {
66 setname("nice");
67 t->t_nice = getn(t->t_dcom[1]);
68 lshift(t->t_dcom, 2);
69 t->t_dflg |= FNICE;
70 } else
71 break;
72 else {
73 t->t_nice = 4;
74 lshift(t->t_dcom, 1);
75 t->t_dflg |= FNICE;
76 }
77 else
78 break;
79 else if (eq(t->t_dcom[0], "nohup"))
80 if (t->t_dcom[1]) {
81 t->t_dflg |= FNOHUP;
82 lshift(t->t_dcom, 1);
83 } else
84 break;
85 else if (eq(t->t_dcom[0], "time"))
86 if (t->t_dcom[1]) {
87 t->t_dflg |= FTIME;
88 lshift(t->t_dcom, 1);
89 } else
90 break;
91 else
92 break;
93 /*
94 * Check if we have a builtin function and remember which one.
95 */
96 bifunc = t->t_dtyp == TCOM ? isbfunc(t) : (struct biltins *) 0;
97
98 /*
99 * We fork only if we are timed, or are not the end of
100 * a parenthesized list and not a simple builtin function.
101 * Simple meaning one that is not pipedout, niced, nohupped,
102 * or &'d.
103 * It would be nice(?) to not fork in some of these cases.
104 */
105 if (((t->t_dflg & FTIME) || (t->t_dflg & FPAR) == 0 &&
106 (!bifunc || t->t_dflg & (FPOU|FAND|FNICE|FNOHUP))))
107#ifdef VFORK
108 if (t->t_dtyp == TPAR || t->t_dflg&(FREDO|FAND) || bifunc)
109#endif
110 { forked++; pid = pfork(t, wanttty); }
111#ifdef VFORK
112 else {
113 int vffree();
114 int ochild, osetintr, ohaderr, odidfds, odidcch;
115 int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp;
116
117 sighold(SIGCHLD);
118 ochild = child; osetintr = setintr;
119 ohaderr = haderr; odidfds = didfds; odidcch = didcch;
120 oSHIN = SHIN; oSHOUT = SHOUT;
121 oSHDIAG = SHDIAG; oOLDSTD = OLDSTD; otpgrp = tpgrp;
122 Vsav = Vdp = 0; Vav = 0;
123 pid = vfork();
124 if (pid < 0) {
125 sigrelse(SIGCHLD);
126 error("No more processes");
127 }
128 forked++;
129 if (pid) {
130 child = ochild; setintr = osetintr;
131 haderr = ohaderr; didfds = odidfds;
132 didcch = odidcch; SHIN = oSHIN;
133 SHOUT = oSHOUT; SHDIAG = oSHDIAG;
134 OLDSTD = oOLDSTD; tpgrp = otpgrp;
135 xfree(Vsav); Vsav = 0;
136 xfree(Vdp); Vdp = 0;
137 xfree(Vav); Vav = 0;
138 /* this is from pfork() */
139 palloc(pid, t);
140 sigrelse(SIGCHLD);
141 } else {
142 /* this is from pfork() */
143 int pgrp;
144 bool ignint = 0;
145
146 if (setintr)
147 ignint =
148 (tpgrp == -1 && (t->t_dflg&FINT))
149 || gointr && eq(gointr, "-");
150 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
151 child++;
152 if (setintr) {
153 setintr = 0;
154 sigsys(SIGCHLD, SIG_DFL);
155 sigsys(SIGINT, ignint ? SIG_IGN : vffree);
156 sigsys(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
157 if (wanttty >= 0) {
158 sigsys(SIGTSTP, SIG_DFL);
159 sigsys(SIGTTIN, SIG_DFL);
160 sigsys(SIGTTOU, SIG_DFL);
161 }
162 sigsys(SIGTERM, parterm);
163 } else if (tpgrp == -1 && (t->t_dflg&FINT)) {
164 sigsys(SIGINT, SIG_IGN);
165 sigsys(SIGQUIT, SIG_IGN);
166 }
167 if (wanttty > 0)
168 ioctl(FSHTTY, TIOCSPGRP, &pgrp);
169 if (wanttty >= 0 && tpgrp >= 0)
170 setpgrp(0, pgrp);
171 if (tpgrp > 0)
172 tpgrp = 0;
173 if (t->t_dflg & FNOHUP)
174 sigsys(SIGHUP, SIG_IGN);
175 if (t->t_dflg & FNICE)
176 nice(t->t_nice);
177 }
178
179 }
180#endif
181 if (pid != 0) {
182 /*
183 * It would be better if we could wait for the
184 * whole job when we knew the last process
185 * had been started. Pwait, in fact, does
186 * wait for the whole job anyway, but this test
187 * doesn't really express our intentions.
188 */
189 if (didfds==0 && t->t_dflg&FPIN)
190 close(pipein[0]), close(pipein[1]);
191 if ((t->t_dflg & (FPOU|FAND)) == 0)
192 pwait();
193 break;
194 }
195 doio(t, pipein, pipeout);
196 if (t->t_dflg & FPOU)
197 close(pipeout[0]), close(pipeout[1]);
198
199 /*
200 * Perform a builtin function.
201 * If we are not forked, arrange for possible stopping
202 */
203 if (bifunc) {
204 func(t, bifunc);
205 if (forked)
206 exitstat();
207 break;
208 }
209 if (t->t_dtyp != TPAR) {
210 doexec(t);
211 /*NOTREACHED*/
212 }
213 /*
214 * For () commands must put new 0,1,2 in FSH* and recurse
215 */
216 OLDSTD = dcopy(0, FOLDSTD);
217 SHOUT = dcopy(1, FSHOUT);
218 SHDIAG = dcopy(2, FSHDIAG);
219 close(SHIN), SHIN = -1;
220 didcch = 0, didfds = 0;
221 wanttty = -1;
222 t->t_dspr->t_dflg |= t->t_dflg & FINT;
223 execute(t->t_dspr, wanttty);
224 exitstat();
225
226 case TFIL:
227 t->t_dcar->t_dflg |= FPOU |
228 (t->t_dflg & (FPIN|FAND|FDIAG|FINT));
229 execute(t->t_dcar, wanttty, pipein, pv);
230 t->t_dcdr->t_dflg |= FPIN |
231 (t->t_dflg & (FPOU|FAND|FPAR|FINT));
232 if (wanttty > 0)
233 wanttty = 0; /* got tty already */
234 execute(t->t_dcdr, wanttty, pv, pipeout);
235 break;
236
237 case TLST:
238 if (t->t_dcar) {
239 t->t_dcar->t_dflg |= t->t_dflg & FINT;
240 execute(t->t_dcar, wanttty);
241 /*
242 * In strange case of A&B make a new job after A
243 */
244 if (t->t_dcar->t_dflg&FAND && t->t_dcdr &&
245 (t->t_dcdr->t_dflg&FAND) == 0)
246 pendjob();
247 }
248 if (t->t_dcdr) {
249 t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
250 execute(t->t_dcdr, wanttty);
251 }
252 break;
253
254 case TOR:
255 case TAND:
256 if (t->t_dcar) {
257 t->t_dcar->t_dflg |= t->t_dflg & FINT;
258 execute(t->t_dcar, wanttty);
259 if ((getn(value("status")) == 0) != (t->t_dtyp == TAND))
260 return;
261 }
262 if (t->t_dcdr) {
263 t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
264 execute(t->t_dcdr, wanttty);
265 }
266 break;
267 }
268 /*
269 * Fall through for all breaks from switch
270 *
271 * If there will be no more executions of this
272 * command, flush all file descriptors.
273 * Places that turn on the FREDO bit are responsible
274 * for doing donefds after the last re-execution
275 */
276 if (didfds && !(t->t_dflg & FREDO))
277 donefds();
278}
279
280#ifdef VFORK
281vffree()
282{
283 register char **v;
284
285 if (v = gargv)
286 gargv = 0, xfree(gargv);
287 if (v = pargv)
288 pargv = 0, xfree(pargv);
289 _exit(1);
290}
291#endif
292
293/*
294 * Perform io redirection.
295 * We may or maynot be forked here.
296 */
297doio(t, pipein, pipeout)
298 register struct command *t;
299 int *pipein, *pipeout;
300{
301 register char *cp;
302 register int flags = t->t_dflg;
303
304 if (didfds || (flags & FREDO))
305 return;
306 if ((flags & FHERE) == 0) { /* FHERE already done */
307 close(0);
308 if (cp = t->t_dlef) {
309 cp = globone(Dfix1(cp));
310 xfree(cp);
311 if (open(cp, 0) < 0)
312 Perror(cp);
313 } else if (flags & FPIN)
314 dup(pipein[0]), close(pipein[0]), close(pipein[1]);
315 else if ((flags & FINT) && tpgrp == -1)
316 close(0), open("/dev/null", 0);
317 else
318 dup(OLDSTD);
319 }
320 close(1);
321 if (cp = t->t_drit) {
322 cp = globone(Dfix1(cp));
323 xfree(cp);
324 if ((flags & FCAT) && open(cp, 1) >= 0)
325 lseek(1, 0l, 2);
326 else {
327 if (!(flags & FANY) && adrof("noclobber")) {
328 if (flags & FCAT)
329 Perror(cp);
330 chkclob(cp);
331 }
332 if (creat(cp, 0666) < 0)
333 Perror(cp);
334 }
335 } else if (flags & FPOU)
336 dup(pipeout[1]);
337 else
338 dup(SHOUT);
339
340 close(2);
341 dup((flags & FDIAG) ? 1 : SHDIAG);
342 didfds = 1;
343}
344
345mypipe(pv)
346 register int *pv;
347{
348
349 if (pipe(pv) < 0)
350 goto oops;
351 pv[0] = dmove(pv[0], -1);
352 pv[1] = dmove(pv[1], -1);
353 if (pv[0] >= 0 && pv[1] >= 0)
354 return;
355oops:
356 error("Can't make pipe");
357}
358
359chkclob(cp)
360 register char *cp;
361{
362 struct stat stb;
363
364 if (stat(cp, &stb) < 0)
365 return;
366 if ((stb.st_mode & S_IFMT) == S_IFCHR)
367 return;
368 error("%s: File exists", cp);
369}