2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
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.
15 #pragma ident "%Z%%M% %I% %E% SMI"
21 #include "sh.tconst.h"
27 void doio(struct command
*, int *, int *);
29 void chkclob(tchar
*);
32 * Return true if there is a back-quote (`) anywhere in the argument list.
33 * Its presence would cause glob() to be invoked in the child process
34 * and this would cause chaos if the child is created with vfork().
37 AnyBquote(struct command
*t
)
44 for (pp
= t
->t_dcom
; p
= *pp
++;) {
53 execute(t
, wanttty
, pipein
, pipeout
)
55 int wanttty
, *pipein
, *pipeout
;
58 struct biltins
*bifunc
;
63 tprintf("TRACE- execute()\n");
68 if ((t
->t_dflg
& FAND
) && wanttty
> 0)
73 if (t
->t_dcom
[0][0] == (tchar
)S_TOPBIT
[0])
74 (void) strcpy_(t
->t_dcom
[0], t
->t_dcom
[0] + 1);
75 if ((t
->t_dflg
& FREDO
) == 0)
76 Dfix(t
); /* $ " ' \ */
77 if (t
->t_dcom
[0] == 0)
85 * Must do << early so parent will know
86 * where input pointer should be.
87 * If noexec then this is all we do.
89 if (t
->t_dflg
& FHERE
) {
104 * This mess is the necessary kludge to handle the prefix
105 * builtins: nice, nohup, time. These commands can also
106 * be used by themselves, and this is not handled here.
107 * This will also work when loops are parsed.
109 while (t
->t_dtyp
== TCOM
)
110 if (eq(t
->t_dcom
[0], S_nice
/*"nice"*/))
112 /*if (any(t->t_dcom[1][0], "+-"))*/
113 if (t
->t_dcom
[1][0] == '+' ||
114 t
->t_dcom
[1][0] == '-')
116 setname(S_nice
/*"nice"*/);
117 t
->t_nice
= getn(t
->t_dcom
[1]);
118 lshift(t
->t_dcom
, 2);
124 lshift(t
->t_dcom
, 1);
129 else if (eq(t
->t_dcom
[0], S_nohup
/*"nohup"*/))
132 lshift(t
->t_dcom
, 1);
135 else if (eq(t
->t_dcom
[0], S_time
/*"time"*/))
138 lshift(t
->t_dcom
, 1);
144 * Check if we have a builtin function and remember which one.
146 bifunc
= t
->t_dtyp
== TCOM
? isbfunc(t
) : NULL
;
149 * We fork only if we are timed, or are not the end of
150 * a parenthesized list and not a simple builtin function.
151 * Simple meaning one that is not pipedout, niced, nohupped,
153 * It would be nice(?) to not fork in some of these cases.
155 if (((t
->t_dflg
& FTIME
) || (t
->t_dflg
& FPAR
) == 0 &&
156 (!bifunc
|| t
->t_dflg
& (FPOU
|FAND
|FNICE
|FNOHUP
))))
158 if (t
->t_dtyp
== TPAR
|| t
->t_dflg
&(FREDO
|FAND
) ||
159 bifunc
|| AnyBquote(t
))
161 { forked
++; pid
= pfork(t
, wanttty
); }
166 int mask
, child
, setintr
, haderr
, didfds
;
167 int SHIN
, SHOUT
, SHDIAG
, OLDSTD
, tpgrp
;
172 * Prepare for the vfork by saving everything
173 * that the child corrupts before it exec's.
174 * Note that in some signal implementations
175 * which keep the signal info in user space
176 * (e.g. Sun's) it will also be necessary to
177 * save and restore the current sigvec's for
178 * the signals the child touches before it
181 sv
.mask
= sigblock(sigmask(SIGCHLD
));
182 sv
.child
= child
; sv
.setintr
= setintr
;
183 sv
.haderr
= haderr
; sv
.didfds
= didfds
;
184 sv
.SHIN
= SHIN
; sv
.SHOUT
= SHOUT
;
185 sv
.SHDIAG
= SHDIAG
; sv
.OLDSTD
= OLDSTD
;
187 Vsav
= Vdp
= 0; Vav
= 0;
188 (void) sigvec(SIGINT
, NULL
, &sv
.sigv
);
191 (void) sigsetmask(sv
.mask
);
192 error("Vfork failed");
195 if (pid
) { /* parent */
198 child
= sv
.child
; setintr
= sv
.setintr
;
199 haderr
= sv
.haderr
; didfds
= sv
.didfds
;
201 SHOUT
= sv
.SHOUT
; SHDIAG
= sv
.SHDIAG
;
202 OLDSTD
= sv
.OLDSTD
; tpgrp
= sv
.tpgrp
;
203 xfree(Vsav
); Vsav
= 0;
205 xfree( (tchar
*)Vav
); Vav
= 0;
206 /* this is from pfork() */
207 ppid
= pcurrjob
? pcurrjob
->p_jobid
: pid
;
208 if (wanttty
>= 0 && tpgrp
>= 0)
209 setpgid (ppid
, ppid
);
212 * Restore SIGINT handler.
214 (void) sigvec(SIGINT
, &sv
.sigv
, NULL
);
215 (void) sigsetmask(sv
.mask
);
217 /* this is from pfork() */
223 (tpgrp
== -1 && (t
->t_dflg
&FINT
))
225 && eq(gointr
, S_MINUS
/*"-"*/);
226 pgrp
= pcurrjob
? pcurrjob
->p_jobid
: getpid();
231 (void) signal(SIGCHLD
, SIG_DFL
);
233 (void) signal(SIGINT
, ignint
?
235 (void) signal(SIGQUIT
, ignint
?
238 (void) signal(SIGTSTP
, SIG_DFL
);
239 (void) signal(SIGTTIN
, SIG_DFL
);
240 (void) signal(SIGTTOU
, SIG_DFL
);
242 (void) signal(SIGTERM
, parterm
);
243 } else if (tpgrp
== -1 && (t
->t_dflg
&FINT
)) {
244 (void) signal(SIGINT
, SIG_IGN
);
245 (void) signal(SIGQUIT
, SIG_IGN
);
247 if (wanttty
>= 0 && tpgrp
>= 0)
248 (void) setpgid(0, pgrp
);
254 (void) ioctl(FSHTTY
, TIOCSPGRP
,
256 sigsetmask (sigttou
);
260 if (t
->t_dflg
& FNOHUP
)
261 (void) signal(SIGHUP
, SIG_IGN
);
262 if (t
->t_dflg
& FNICE
)
263 (void) setpriority(PRIO_PROCESS
,
271 * It would be better if we could wait for the
272 * whole job when we knew the last process
273 * had been started. Pwait, in fact, does
274 * wait for the whole job anyway, but this test
275 * doesn't really express our intentions.
277 if (didfds
==0 && t
->t_dflg
&FPIN
) {
278 (void) close(pipein
[0]);
280 (void) close(pipein
[1]);
283 if ((t
->t_dflg
& (FPOU
|FAND
)) == 0)
287 doio(t
, pipein
, pipeout
);
288 if (t
->t_dflg
& FPOU
) {
289 (void) close(pipeout
[0]);
290 (void) unsetfd(pipeout
[0]);
291 (void) close(pipeout
[1]);
292 (void) unsetfd(pipeout
[1]);
296 * Perform a builtin function.
297 * If we are not forked, arrange for possible stopping
305 if (t
->t_dtyp
!= TPAR
) {
310 * For () commands must put new 0,1,2 in FSH* and recurse
312 OLDSTD
= dcopy(0, FOLDSTD
);
313 SHOUT
= dcopy(1, FSHOUT
);
314 SHDIAG
= dcopy(2, FSHDIAG
);
316 (void) unsetfd(SHIN
);
320 t
->t_dspr
->t_dflg
|= t
->t_dflg
& FINT
;
321 execute(t
->t_dspr
, wanttty
);
325 t
->t_dcar
->t_dflg
|= FPOU
|
326 (t
->t_dflg
& (FPIN
|FAND
|FDIAG
|FINT
));
327 execute(t
->t_dcar
, wanttty
, pipein
, pv
);
328 t
->t_dcdr
->t_dflg
|= FPIN
|
329 (t
->t_dflg
& (FPOU
|FAND
|FPAR
|FINT
));
331 wanttty
= 0; /* got tty already */
332 execute(t
->t_dcdr
, wanttty
, pv
, pipeout
);
337 t
->t_dcar
->t_dflg
|= t
->t_dflg
& FINT
;
338 execute(t
->t_dcar
, wanttty
);
340 * In strange case of A&B make a new job after A
342 if (t
->t_dcar
->t_dflg
&FAND
&& t
->t_dcdr
&&
343 (t
->t_dcdr
->t_dflg
&FAND
) == 0)
347 t
->t_dcdr
->t_dflg
|= t
->t_dflg
& (FPAR
|FINT
);
348 execute(t
->t_dcdr
, wanttty
);
355 t
->t_dcar
->t_dflg
|= t
->t_dflg
& FINT
;
356 execute(t
->t_dcar
, wanttty
);
357 if ((getn(value(S_status
/*"status"*/)) == 0) != (t
->t_dtyp
== TAND
))
361 t
->t_dcdr
->t_dflg
|= t
->t_dflg
& (FPAR
|FINT
);
362 execute(t
->t_dcdr
, wanttty
);
367 * Fall through for all breaks from switch
369 * If there will be no more executions of this
370 * command, flush all file descriptors.
371 * Places that turn on the FREDO bit are responsible
372 * for doing donefds after the last re-execution
374 if (didfds
&& !(t
->t_dflg
& FREDO
))
378 * If glob() was called and arguments list is not yet
379 * free'ed, free them here.
395 tprintf("TRACE- vffree()\n");
398 gargv
= 0, xfree( (tchar
*)v
);
400 pargv
= 0, xfree( (tchar
*)v
);
406 * Perform io redirection.
407 * We may or maynot be forked here.
410 doio(struct command
*t
, int *pipein
, int *pipeout
)
413 int flags
= t
->t_dflg
;
417 tprintf("TRACE- doio()\n");
419 if (didfds
|| (flags
& FREDO
))
421 if ((flags
& FHERE
) == 0) { /* FHERE already done */
424 if (cp
= t
->t_dlef
) {
429 if (open_(cp
, 0) < 0)
431 } else if (flags
& FPIN
) {
435 (void) close(pipein
[0]);
436 (void) unsetfd(pipein
[0]);
437 (void) close(pipein
[1]);
438 (void) unsetfd(pipein
[1]);
439 } else if ((flags
& FINT
) && tpgrp
== -1) {
440 (void) close(0); /* no need for unsetfd */
441 (void) open("/dev/null", O_RDONLY
); /* no need for setfd */
450 if (cp
= t
->t_drit
) {
454 if ((flags
& FCAT
) && open_(cp
, 1) >= 0)
455 (void) lseek(1, (off_t
)0, 2);
457 if (!(flags
& FANY
) && adrof(S_noclobber
/*"noclobber"*/)) {
462 if (creat_(cp
, 0666) < 0)
466 } else if (flags
& FPOU
) {
467 fd
= dup(pipeout
[1]);
497 tprintf("TRACE- mypipe()\n");
504 pv
[0] = dmove(pv
[0], -1);
505 pv
[1] = dmove(pv
[1], -1);
506 if (pv
[0] >= 0 && pv
[1] >= 0)
509 error("Can't make pipe");
519 tprintf("TRACE- chkclob()\n");
521 if (stat_(cp
, &stb
) < 0)
523 type
= stb
.st_mode
& S_IFMT
;
524 if (type
== S_IFCHR
|| type
== S_IFIFO
)
526 error("%t: File exists", cp
);