1 /*
2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
8
9 /*
10 * Copyright (c) 1980 Regents of the University of California.
11 * All rights reserved. The Berkeley Software License Agreement
12 * specifies the terms and conditions for redistribution.
13 */
14
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include "sh.h"
18 #include "sh.proc.h"
19 #include "sh.tconst.h"
20
21 /*
22 * C shell
23 */
24
25 void doio(struct command *, int *, int *);
26 void mypipe(int *);
27 void chkclob(tchar *);
28
29 /*
30 * Return true if there is a back-quote (`) anywhere in the argument list.
31 * Its presence would cause glob() to be invoked in the child process
32 * and this would cause chaos if the child is created with vfork().
33 */
34 static bool
AnyBquote(struct command * t)35 AnyBquote(struct command *t)
36 {
37 tchar **pp;
38 tchar *p;
39
40 if (noexec)
41 return (0);
42 for (pp = t->t_dcom; p = *pp++;) {
43 if (any('`', p))
44 return (1);
45 }
46 return (0);
47 }
48
49 /*VARARGS 1*/
50 void
execute(t,wanttty,pipein,pipeout)51 execute(t, wanttty, pipein, pipeout)
52 struct command *t;
53 int wanttty, *pipein, *pipeout;
54 {
55 bool forked = 0;
56 struct biltins *bifunc;
57 int pid = 0;
58 int pv[2];
59 extern int globcnt;
60 #ifdef TRACE
61 tprintf("TRACE- execute()\n");
62 #endif
63
64 if (t == 0)
65 return;
66 if ((t->t_dflg & FAND) && wanttty > 0)
67 wanttty = 0;
68 switch (t->t_dtyp) {
69
70 case TCOM:
71 if (t->t_dcom[0][0] == (tchar)S_TOPBIT[0])
72 (void) strcpy_(t->t_dcom[0], t->t_dcom[0] + 1);
73 if ((t->t_dflg & FREDO) == 0)
74 Dfix(t); /* $ " ' \ */
75 if (t->t_dcom[0] == 0)
76 return;
77 /* fall into... */
78
79 case TPAR:
80 if (t->t_dflg & FPOU)
81 mypipe(pipeout);
82 /*
83 * Must do << early so parent will know
84 * where input pointer should be.
85 * If noexec then this is all we do.
86 */
87 if (t->t_dflg & FHERE) {
88 (void) close(0);
89 unsetfd(0);
90 heredoc(t->t_dlef);
91 if (noexec) {
92 (void) close(0);
93 unsetfd(0);
94 }
95 }
96 if (noexec)
97 break;
98
99 set(S_status, S_0);
100
101 /*
102 * This mess is the necessary kludge to handle the prefix
103 * builtins: nice, nohup, time. These commands can also
104 * be used by themselves, and this is not handled here.
105 * This will also work when loops are parsed.
106 */
107 while (t->t_dtyp == TCOM)
108 if (eq(t->t_dcom[0], S_nice /*"nice"*/))
109 if (t->t_dcom[1])
110 /*if (any(t->t_dcom[1][0], "+-"))*/
111 if (t->t_dcom[1][0] == '+' ||
112 t->t_dcom[1][0] == '-')
113 if (t->t_dcom[2]) {
114 setname(S_nice /*"nice"*/);
115 t->t_nice = getn(t->t_dcom[1]);
116 lshift(t->t_dcom, 2);
117 t->t_dflg |= FNICE;
118 } else
119 break;
120 else {
121 t->t_nice = 4;
122 lshift(t->t_dcom, 1);
123 t->t_dflg |= FNICE;
124 }
125 else
126 break;
127 else if (eq(t->t_dcom[0], S_nohup /*"nohup"*/))
128 if (t->t_dcom[1]) {
129 t->t_dflg |= FNOHUP;
130 lshift(t->t_dcom, 1);
131 } else
132 break;
133 else if (eq(t->t_dcom[0], S_time /*"time"*/))
134 if (t->t_dcom[1]) {
135 t->t_dflg |= FTIME;
136 lshift(t->t_dcom, 1);
137 } else
138 break;
139 else
140 break;
141 /*
142 * Check if we have a builtin function and remember which one.
143 */
144 bifunc = t->t_dtyp == TCOM ? isbfunc(t) : (struct biltins *) 0;
145
146 /*
147 * We fork only if we are timed, or are not the end of
148 * a parenthesized list and not a simple builtin function.
149 * Simple meaning one that is not pipedout, niced, nohupped,
150 * or &'d.
151 * It would be nice(?) to not fork in some of these cases.
152 */
153 if (((t->t_dflg & FTIME) || (t->t_dflg & FPAR) == 0 &&
154 (!bifunc || t->t_dflg & (FPOU|FAND|FNICE|FNOHUP))))
155 #ifdef VFORK
156 if (t->t_dtyp == TPAR || t->t_dflg&(FREDO|FAND) ||
157 bifunc || AnyBquote(t))
158 #endif
159 { forked++; pid = pfork(t, wanttty); }
160 #ifdef VFORK
161 else {
162 void vffree();
163 struct sv {
164 int mask, child, setintr, haderr, didfds;
165 int SHIN, SHOUT, SHDIAG, OLDSTD, tpgrp;
166 struct sigvec sigv;
167 } sv;
168
169 /*
170 * Prepare for the vfork by saving everything
171 * that the child corrupts before it exec's.
172 * Note that in some signal implementations
173 * which keep the signal info in user space
174 * (e.g. Sun's) it will also be necessary to
175 * save and restore the current sigvec's for
176 * the signals the child touches before it
177 * exec's.
178 */
179 sv.mask = sigblock(sigmask(SIGCHLD));
180 sv.child = child; sv.setintr = setintr;
181 sv.haderr = haderr; sv.didfds = didfds;
182 sv.SHIN = SHIN; sv.SHOUT = SHOUT;
183 sv.SHDIAG = SHDIAG; sv.OLDSTD = OLDSTD;
184 sv.tpgrp = tpgrp;
185 Vsav = Vdp = 0; Vav = 0;
186 (void) sigvec(SIGINT, (struct sigvec *)0, &sv.sigv);
187 pid = vfork();
188 if (pid < 0) {
189 (void) sigsetmask(sv.mask);
190 error("Vfork failed");
191 }
192 forked++;
193 if (pid) { /* parent */
194 int ppid;
195 closelog();
196 child = sv.child; setintr = sv.setintr;
197 haderr = sv.haderr; didfds = sv.didfds;
198 SHIN = sv.SHIN;
199 SHOUT = sv.SHOUT; SHDIAG = sv.SHDIAG;
200 OLDSTD = sv.OLDSTD; tpgrp = sv.tpgrp;
201 xfree(Vsav); Vsav = 0;
202 xfree(Vdp); Vdp = 0;
203 xfree( (tchar *)Vav); Vav = 0;
204 /* this is from pfork() */
205 ppid = pcurrjob ? pcurrjob->p_jobid : pid;
206 if (wanttty >= 0 && tpgrp >= 0)
207 setpgid (ppid, ppid);
208 palloc(pid, t);
209 /*
210 * Restore SIGINT handler.
211 */
212 (void) sigvec(SIGINT, &sv.sigv, (struct sigvec *)0);
213 (void) sigsetmask(sv.mask);
214 } else { /* child */
215 /* this is from pfork() */
216 int pgrp;
217 bool ignint = 0;
218 int sigttou;
219 if (setintr)
220 ignint =
221 (tpgrp == -1 && (t->t_dflg&FINT))
222 || gointr
223 && eq(gointr, S_MINUS/*"-"*/);
224 pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
225 child++;
226 if (setintr) {
227 setintr = 0;
228 #ifdef notdef
229 (void) signal(SIGCHLD, SIG_DFL);
230 #endif
231 (void) signal(SIGINT, ignint ?
232 SIG_IGN : vffree);
233 (void) signal(SIGQUIT, ignint ?
234 SIG_IGN : SIG_DFL);
235 if (wanttty >= 0) {
236 (void) signal(SIGTSTP, SIG_DFL);
237 (void) signal(SIGTTIN, SIG_DFL);
238 (void) signal(SIGTTOU, SIG_DFL);
239 }
240 (void) signal(SIGTERM, parterm);
241 } else if (tpgrp == -1 && (t->t_dflg&FINT)) {
242 (void) signal(SIGINT, SIG_IGN);
243 (void) signal(SIGQUIT, SIG_IGN);
244 }
245 if (wanttty >= 0 && tpgrp >= 0)
246 (void) setpgid(0, pgrp);
247 if (wanttty > 0) {
248 sigttou = sigblock (
249 sigmask(SIGTTOU) |
250 sigmask(SIGTTIN) |
251 sigmask(SIGTSTP));
252 (void) ioctl(FSHTTY, TIOCSPGRP,
253 (tchar *)&pgrp);
254 sigsetmask (sigttou);
255 }
256 if (tpgrp > 0)
257 tpgrp = 0;
258 if (t->t_dflg & FNOHUP)
259 (void) signal(SIGHUP, SIG_IGN);
260 if (t->t_dflg & FNICE)
261 (void) setpriority(PRIO_PROCESS,
262 0, t->t_nice);
263 }
264
265 }
266 #endif
267 if (pid != 0) {
268 /*
269 * It would be better if we could wait for the
270 * whole job when we knew the last process
271 * had been started. Pwait, in fact, does
272 * wait for the whole job anyway, but this test
273 * doesn't really express our intentions.
274 */
275 if (didfds==0 && t->t_dflg&FPIN) {
276 (void) close(pipein[0]);
277 unsetfd(pipein[0]);
278 (void) close(pipein[1]);
279 unsetfd(pipein[1]);
280 }
281 if ((t->t_dflg & (FPOU|FAND)) == 0)
282 pwait();
283 break;
284 }
285 doio(t, pipein, pipeout);
286 if (t->t_dflg & FPOU) {
287 (void) close(pipeout[0]);
288 (void) unsetfd(pipeout[0]);
289 (void) close(pipeout[1]);
290 (void) unsetfd(pipeout[1]);
291 }
292
293 /*
294 * Perform a builtin function.
295 * If we are not forked, arrange for possible stopping
296 */
297 if (bifunc) {
298 func(t, bifunc);
299 if (forked)
300 exitstat();
301 break;
302 }
303 if (t->t_dtyp != TPAR) {
304 doexec(t);
305 /*NOTREACHED*/
306 }
307 /*
308 * For () commands must put new 0,1,2 in FSH* and recurse
309 */
310 OLDSTD = dcopy(0, FOLDSTD);
311 SHOUT = dcopy(1, FSHOUT);
312 SHDIAG = dcopy(2, FSHDIAG);
313 (void) close(SHIN);
314 (void) unsetfd(SHIN);
315 SHIN = -1;
316 didfds = 0;
317 wanttty = -1;
318 t->t_dspr->t_dflg |= t->t_dflg & FINT;
319 execute(t->t_dspr, wanttty);
320 exitstat();
321
322 case TFIL:
323 t->t_dcar->t_dflg |= FPOU |
324 (t->t_dflg & (FPIN|FAND|FDIAG|FINT));
325 execute(t->t_dcar, wanttty, pipein, pv);
326 t->t_dcdr->t_dflg |= FPIN |
327 (t->t_dflg & (FPOU|FAND|FPAR|FINT));
328 if (wanttty > 0)
329 wanttty = 0; /* got tty already */
330 execute(t->t_dcdr, wanttty, pv, pipeout);
331 break;
332
333 case TLST:
334 if (t->t_dcar) {
335 t->t_dcar->t_dflg |= t->t_dflg & FINT;
336 execute(t->t_dcar, wanttty);
337 /*
338 * In strange case of A&B make a new job after A
339 */
340 if (t->t_dcar->t_dflg&FAND && t->t_dcdr &&
341 (t->t_dcdr->t_dflg&FAND) == 0)
342 pendjob();
343 }
344 if (t->t_dcdr) {
345 t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
346 execute(t->t_dcdr, wanttty);
347 }
348 break;
349
350 case TOR:
351 case TAND:
352 if (t->t_dcar) {
353 t->t_dcar->t_dflg |= t->t_dflg & FINT;
354 execute(t->t_dcar, wanttty);
355 if ((getn(value(S_status/*"status"*/)) == 0) != (t->t_dtyp == TAND))
356 return;
357 }
358 if (t->t_dcdr) {
359 t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT);
360 execute(t->t_dcdr, wanttty);
361 }
362 break;
363 }
364 /*
365 * Fall through for all breaks from switch
366 *
367 * If there will be no more executions of this
368 * command, flush all file descriptors.
369 * Places that turn on the FREDO bit are responsible
370 * for doing donefds after the last re-execution
371 */
372 if (didfds && !(t->t_dflg & FREDO))
373 donefds();
374
375 /*
376 * If glob() was called and arguments list is not yet
377 * free'ed, free them here.
378 */
379 if (gargv) {
380 blkfree(gargv);
381 gargv = 0;
382 globcnt = 0;
383 }
384 }
385
386 #ifdef VFORK
387 void
vffree(void)388 vffree(void)
389 {
390 tchar **v;
391
392 #ifdef TRACE
393 tprintf("TRACE- vffree()\n");
394 #endif
395 if (v = gargv)
396 gargv = 0, xfree( (tchar *)v);
397 if (v = pargv)
398 pargv = 0, xfree( (tchar *)v);
399 _exit(1);
400 }
401 #endif
402
403 /*
404 * Perform io redirection.
405 * We may or maynot be forked here.
406 */
407 void
doio(struct command * t,int * pipein,int * pipeout)408 doio(struct command *t, int *pipein, int *pipeout)
409 {
410 tchar *cp, *dp;
411 int flags = t->t_dflg;
412 int fd;
413
414 #ifdef TRACE
415 tprintf("TRACE- doio()\n");
416 #endif
417 if (didfds || (flags & FREDO))
418 return;
419 if ((flags & FHERE) == 0) { /* FHERE already done */
420 (void) close(0);
421 (void) unsetfd(0);
422 if (cp = t->t_dlef) {
423 dp = Dfix1(cp);
424 cp = globone(dp);
425 xfree(dp);
426 xfree(cp);
427 if (open_(cp, 0) < 0)
428 Perror(cp);
429 } else if (flags & FPIN) {
430 fd = dup(pipein[0]);
431 if (fd != -1)
432 setfd(fd);
433 (void) close(pipein[0]);
434 (void) unsetfd(pipein[0]);
435 (void) close(pipein[1]);
436 (void) unsetfd(pipein[1]);
437 } else if ((flags & FINT) && tpgrp == -1) {
438 (void) close(0); /* no need for unsetfd */
439 (void) open("/dev/null", 0); /* no need for setfd */
440 } else {
441 fd = dup(OLDSTD);
442 if (fd != -1)
443 setfd(fd);
444 }
445 }
446 (void) close(1);
447 (void) unsetfd(1);
448 if (cp = t->t_drit) {
449 dp = Dfix1(cp);
450 cp = globone(dp);
451 xfree(dp);
452 if ((flags & FCAT) && open_(cp, 1) >= 0)
453 (void) lseek(1, (off_t)0, 2);
454 else {
455 if (!(flags & FANY) && adrof(S_noclobber/*"noclobber"*/)) {
456 if (flags & FCAT)
457 Perror(cp);
458 chkclob(cp);
459 }
460 if (creat_(cp, 0666) < 0)
461 Perror(cp);
462 }
463 xfree(cp);
464 } else if (flags & FPOU) {
465 fd = dup(pipeout[1]);
466 if (fd != -1)
467 setfd (fd);
468 }
469 else {
470 fd = dup(SHOUT);
471 if (fd != -1)
472 setfd(fd);
473 }
474
475 (void) close(2);
476 (void) unsetfd(2);
477 if (flags & FDIAG) {
478 fd = dup(1);
479 if (fd != -1)
480 setfd(fd);
481 }
482 else {
483 fd = dup(SHDIAG);
484 if (fd != -1)
485 setfd(fd);
486 }
487 didfds = 1;
488 }
489
490 void
mypipe(int * pv)491 mypipe(int *pv)
492 {
493
494 #ifdef TRACE
495 tprintf("TRACE- mypipe()\n");
496 #endif
497 if (pipe(pv) < 0)
498 goto oops;
499 setfd(pv[0]);
500 setfd(pv[1]);
501
502 pv[0] = dmove(pv[0], -1);
503 pv[1] = dmove(pv[1], -1);
504 if (pv[0] >= 0 && pv[1] >= 0)
505 return;
506 oops:
507 error("Can't make pipe");
508 }
509
510 void
chkclob(tchar * cp)511 chkclob(tchar *cp)
512 {
513 struct stat stb;
514 unsigned short type;
515
516 #ifdef TRACE
517 tprintf("TRACE- chkclob()\n");
518 #endif
519 if (stat_(cp, &stb) < 0)
520 return;
521 type = stb.st_mode & S_IFMT;
522 if (type == S_IFCHR || type == S_IFIFO)
523 return;
524 error("%t: File exists", cp);
525 }
526