1 /* $NetBSD: sem.c,v 1.27 2007/07/16 14:07:01 christos Exp $ */
4 * Copyright (c) 1980, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)sem.c 8.1 (Berkeley) 5/31/93";
37 __RCSID("$NetBSD: sem.c,v 1.27 2007/07/16 14:07:01 christos Exp $");
41 #include <sys/ioctl.h>
42 #include <sys/param.h>
56 static void vffree(int);
57 static Char
*splicepipe(struct command
*t
, Char
*);
58 static void doio(struct command
*t
, int *, int *);
59 static void chkclob(char *);
62 execute(struct command
*t
, int wtty
, int *pipein
, int *pipeout
)
64 static sigset_t csigset
, ocsigset
;
65 static int nosigchld
= 0, onosigchld
= 0;
66 volatile int wanttty
= wtty
;
67 struct biltins
* volatile bifunc
;
82 if (t
->t_dflg
& F_AMPERSAND
)
86 if ((t
->t_dcom
[0][0] & (QUOTE
| TRIM
)) == QUOTE
)
87 (void)Strcpy(t
->t_dcom
[0], t
->t_dcom
[0] + 1);
88 if ((t
->t_dflg
& F_REPEAT
) == 0)
89 Dfix(t
); /* $ " ' \ */
90 if (t
->t_dcom
[0] == 0)
94 if (t
->t_dflg
& F_PIPEOUT
)
97 * Must do << early so parent will know where input pointer should be.
98 * If noexec then this is all we do.
100 if (t
->t_dflg
& F_READ
) {
107 set(STRstatus
, Strsave(STR0
));
110 * This mess is the necessary kludge to handle the prefix builtins:
111 * nice, nohup, time. These commands can also be used by themselves,
112 * and this is not handled here. This will also work when loops are
115 while (t
->t_dtyp
== NODE_COMMAND
)
116 if (eq(t
->t_dcom
[0], STRnice
)) {
118 if (strchr("+-", t
->t_dcom
[1][0])) {
123 lshift(t
->t_dcom
, 2);
130 lshift(t
->t_dcom
, 1);
135 } else if (eq(t
->t_dcom
[0], STRnohup
)) {
137 t
->t_dflg
|= F_NOHUP
;
138 lshift(t
->t_dcom
, 1);
142 } else if (eq(t
->t_dcom
[0], STRtime
)) {
145 lshift(t
->t_dcom
, 1);
152 /* is it a command */
153 if (t
->t_dtyp
== NODE_COMMAND
) {
155 * Check if we have a builtin function and remember which one.
158 if (noexec
&& bifunc
!= NULL
) {
160 * Continue for builtins that are part of the scripting language
162 if (bifunc
->bfunct
!= dobreak
&& bifunc
->bfunct
!= docontin
&&
163 bifunc
->bfunct
!= doelse
&& bifunc
->bfunct
!= doend
&&
164 bifunc
->bfunct
!= doforeach
&& bifunc
->bfunct
!= dogoto
&&
165 bifunc
->bfunct
!= doif
&& bifunc
->bfunct
!= dorepeat
&&
166 bifunc
->bfunct
!= doswbrk
&& bifunc
->bfunct
!= doswitch
&&
167 bifunc
->bfunct
!= dowhile
&& bifunc
->bfunct
!= dozip
)
171 else { /* not a command */
178 * We fork only if we are timed, or are not the end of a parenthesized
179 * list and not a simple builtin function. Simple meaning one that is
180 * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not
181 * fork in some of these cases.
184 * Prevent forking cd, pushd, popd, chdir cause this will cause the
185 * shell not to change dir!
187 if (bifunc
&& (bifunc
->bfunct
== dochngd
||
188 bifunc
->bfunct
== dopushd
||
189 bifunc
->bfunct
== dopopd
))
190 t
->t_dflg
&= ~(F_NICE
);
191 if (((t
->t_dflg
& F_TIME
) || ((t
->t_dflg
& F_NOFORK
) == 0 &&
192 (!bifunc
|| t
->t_dflg
&
193 (F_PIPEOUT
| F_AMPERSAND
| F_NICE
| F_NOHUP
)))) ||
195 * We have to fork for eval too.
197 (bifunc
&& (t
->t_dflg
& (F_PIPEIN
| F_PIPEOUT
)) != 0 &&
198 bifunc
->bfunct
== doeval
)) {
199 if (t
->t_dtyp
== NODE_PAREN
||
200 t
->t_dflg
& (F_REPEAT
| F_AMPERSAND
) || bifunc
) {
203 * We need to block SIGCHLD here, so that if the process does
204 * not die before we can set the process group
206 if (wanttty
>= 0 && !nosigchld
) {
207 sigemptyset(&nsigset
);
208 (void)sigaddset(&nsigset
, SIGCHLD
);
209 (void)sigprocmask(SIG_BLOCK
, &nsigset
, &csigset
);
213 pid
= pfork(t
, wanttty
);
214 if (pid
== 0 && nosigchld
) {
215 (void)sigprocmask(SIG_SETMASK
, &csigset
, NULL
);
218 else if (pid
!= 0 && (t
->t_dflg
& F_AMPERSAND
))
223 int ochild
, osetintr
, ohaderr
, odidfds
;
224 int oSHIN
, oSHOUT
, oSHERR
, oOLDSTD
, otpgrp
;
228 * Prepare for the vfork by saving everything that the child
229 * corrupts before it exec's. Note that in some signal
230 * implementations which keep the signal info in user space
231 * (e.g. Sun's) it will also be necessary to save and restore
232 * the current sigaction's for the signals the child touches
235 if (wanttty
>= 0 && !nosigchld
&& !noexec
) {
236 sigemptyset(&nsigset
);
237 (void)sigaddset(&nsigset
, SIGCHLD
);
238 (void)sigprocmask(SIG_BLOCK
, &nsigset
, &csigset
);
241 sigemptyset(&nsigset
);
242 (void)sigaddset(&nsigset
, SIGCHLD
);
243 (void)sigaddset(&nsigset
, SIGINT
);
244 (void)sigprocmask(SIG_BLOCK
, &nsigset
, &osigset
);
255 onosigchld
= nosigchld
;
262 (void)sigprocmask(SIG_SETMASK
, &osigset
, NULL
);
263 stderror(ERR_NOPROC
);
266 if (pid
) { /* parent */
277 nosigchld
= onosigchld
;
283 xfree((ptr_t
) Vexpath
);
285 blkfree((Char
**) Vt
);
287 /* this is from pfork() */
289 (void)sigprocmask(SIG_SETMASK
, &osigset
, NULL
);
292 /* this is from pfork() */
297 (void)sigprocmask(SIG_SETMASK
, &csigset
, NULL
);
304 (t
->t_dflg
& F_NOINTERRUPT
))
305 || (gointr
&& eq(gointr
, STRminus
));
306 pgrp
= pcurrjob
? pcurrjob
->p_jobid
: getpid();
311 (void)signal(SIGINT
, SIG_IGN
);
312 (void)signal(SIGQUIT
, SIG_IGN
);
315 (void)signal(SIGINT
, vffree
);
316 (void)signal(SIGQUIT
, SIG_DFL
);
320 (void)signal(SIGTSTP
, SIG_DFL
);
321 (void)signal(SIGTTIN
, SIG_DFL
);
322 (void)signal(SIGTTOU
, SIG_DFL
);
325 (void)signal(SIGTERM
, parterm
);
327 else if (tpgrp
== -1 &&
328 (t
->t_dflg
& F_NOINTERRUPT
)) {
329 (void)signal(SIGINT
, SIG_IGN
);
330 (void)signal(SIGQUIT
, SIG_IGN
);
333 pgetty(wanttty
, pgrp
);
334 if (t
->t_dflg
& F_NOHUP
)
335 (void)signal(SIGHUP
, SIG_IGN
);
336 if (t
->t_dflg
& F_NICE
)
337 (void)setpriority(PRIO_PROCESS
, 0, t
->t_nice
);
344 * It would be better if we could wait for the whole job when we
345 * knew the last process had been started. Pwait, in fact, does
346 * wait for the whole job anyway, but this test doesn't really
347 * express our intentions.
349 if (didfds
== 0 && t
->t_dflg
& F_PIPEIN
) {
350 (void)close(pipein
[0]);
351 (void)close(pipein
[1]);
353 if ((t
->t_dflg
& F_PIPEOUT
) == 0) {
355 (void)sigprocmask(SIG_SETMASK
, &csigset
, NULL
);
358 if ((t
->t_dflg
& F_AMPERSAND
) == 0)
363 doio(t
, pipein
, pipeout
);
364 if (t
->t_dflg
& F_PIPEOUT
) {
365 (void)close(pipeout
[0]);
366 (void)close(pipeout
[1]);
369 * Perform a builtin function. If we are not forked, arrange for
378 if (t
->t_dtyp
!= NODE_PAREN
)
381 * For () commands must put new 0,1,2 in FSH* and recurse
383 (void) ioctl(OLDSTD
= dcopy(0, FOLDSTD
), FIOCLEX
, NULL
);
384 (void) ioctl(SHOUT
= dcopy(1, FSHOUT
), FIOCLEX
, NULL
);
385 (void) ioctl(SHERR
= dcopy(2, FSHERR
), FIOCLEX
, NULL
);
391 t
->t_dspr
->t_dflg
|= t
->t_dflg
& F_NOINTERRUPT
;
392 execute(t
->t_dspr
, wanttty
, NULL
, NULL
);
396 t
->t_dcar
->t_dflg
|= F_PIPEOUT
|
397 (t
->t_dflg
& (F_PIPEIN
| F_AMPERSAND
| F_STDERR
| F_NOINTERRUPT
));
398 execute(t
->t_dcar
, wanttty
, pipein
, pv
);
399 t
->t_dcdr
->t_dflg
|= F_PIPEIN
| (t
->t_dflg
&
400 (F_PIPEOUT
| F_AMPERSAND
| F_NOFORK
| F_NOINTERRUPT
));
402 wanttty
= 0; /* got tty already */
403 execute(t
->t_dcdr
, wanttty
, pv
, pipeout
);
407 t
->t_dcar
->t_dflg
|= t
->t_dflg
& F_NOINTERRUPT
;
408 execute(t
->t_dcar
, wanttty
, NULL
, NULL
);
410 * In strange case of A&B make a new job after A
412 if (t
->t_dcar
->t_dflg
& F_AMPERSAND
&& t
->t_dcdr
&&
413 (t
->t_dcdr
->t_dflg
& F_AMPERSAND
) == 0)
417 t
->t_dcdr
->t_dflg
|= t
->t_dflg
&
418 (F_NOFORK
| F_NOINTERRUPT
);
419 execute(t
->t_dcdr
, wanttty
, NULL
, NULL
);
425 t
->t_dcar
->t_dflg
|= t
->t_dflg
& F_NOINTERRUPT
;
426 execute(t
->t_dcar
, wanttty
, NULL
, NULL
);
427 if ((getn(value(STRstatus
)) == 0) !=
428 (t
->t_dtyp
== NODE_AND
))
432 t
->t_dcdr
->t_dflg
|= t
->t_dflg
&
433 (F_NOFORK
| F_NOINTERRUPT
);
434 execute(t
->t_dcdr
, wanttty
, NULL
, NULL
);
439 * Fall through for all breaks from switch
441 * If there will be no more executions of this command, flush all file
442 * descriptors. Places that turn on the F_REPEAT bit are responsible for
443 * doing donefds after the last re-execution
445 if (didfds
&& !(t
->t_dflg
& F_REPEAT
))
454 if ((v
= gargv
) != NULL
) {
458 if ((v
= pargv
) != NULL
) {
467 * Expand and glob the words after an i/o redirection.
468 * If more than one word is generated, then update the command vector.
470 * This is done differently in all the shells:
471 * 1. in the bourne shell and ksh globbing is not performed
472 * 2. Bash/csh say ambiguous
473 * 3. zsh does i/o to/from all the files
474 * 4. itcsh concatenates the words.
476 * I don't know what is best to do. I think that Ambiguous is better
477 * than restructuring the command vector, because the user can get
478 * unexpected results. In any case, the command vector restructuring
479 * code is present and the user can choose it by setting noambiguous
482 splicepipe(struct command
*t
, Char
*cp
/* word after < or > */)
486 if (adrof(STRnoambiguous
)) {
489 blk
[0] = Dfix1(cp
); /* expand $ */
492 gflag
= 0, tglob(blk
);
496 setname(vis_str(blk
[0]));
497 xfree((ptr_t
) blk
[0]);
498 stderror(ERR_NAME
| ERR_NOMATCH
);
502 if (pv
[1] != NULL
) { /* we need to fix the command vector */
503 Char
**av
= blkspl(t
->t_dcom
, &pv
[1]);
504 xfree((ptr_t
) t
->t_dcom
);
507 xfree((ptr_t
) blk
[0]);
513 blk
[0] = globone(blk
[1] = Dfix1(cp
), G_ERROR
);
514 xfree((ptr_t
) blk
[1]);
520 * Perform io redirection.
521 * We may or maynot be forked here.
524 doio(struct command
*t
, int *pipein
, int *pipeout
)
530 if (didfds
|| (flags
& F_REPEAT
))
532 if ((flags
& F_READ
) == 0) {/* F_READ already done */
534 char tmp
[MAXPATHLEN
+1];
537 * so < /dev/std{in,out,err} work
539 (void)dcopy(SHIN
, 0);
540 (void)dcopy(SHOUT
, 1);
541 (void)dcopy(SHERR
, 2);
542 cp
= splicepipe(t
, t
->t_dlef
);
543 (void)strlcpy(tmp
, short2str(cp
), sizeof(tmp
));
545 if ((fd
= open(tmp
, O_RDONLY
)) < 0) {
546 stderror(ERR_SYSTEM
, tmp
, strerror(errno
));
551 else if (flags
& F_PIPEIN
) {
553 (void)dup(pipein
[0]);
554 (void)close(pipein
[0]);
555 (void)close(pipein
[1]);
557 else if ((flags
& F_NOINTERRUPT
) && tpgrp
== -1) {
559 (void)open(_PATH_DEVNULL
, O_RDONLY
);
564 (void)ioctl(0, FIONCLEX
, NULL
);
568 char tmp
[MAXPATHLEN
+1];
570 cp
= splicepipe(t
, t
->t_drit
);
571 (void)strlcpy(tmp
, short2str(cp
), sizeof(tmp
));
574 * so > /dev/std{out,err} work
576 (void)dcopy(SHOUT
, 1);
577 (void)dcopy(SHERR
, 2);
578 if ((flags
& F_APPEND
) &&
580 (fd
= open(tmp
, O_WRONLY
| O_APPEND
)) >= 0);
582 (fd
= open(tmp
, O_WRONLY
)) >= 0)
583 (void)lseek(1, (off_t
) 0, SEEK_END
);
586 if (!(flags
& F_OVERWRITE
) && adrof(STRnoclobber
)) {
587 if (flags
& F_APPEND
) {
588 stderror(ERR_SYSTEM
, tmp
, strerror(errno
));
593 if ((fd
= open(tmp
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0666)) < 0) {
594 stderror(ERR_SYSTEM
, tmp
, strerror(errno
));
600 else if (flags
& F_PIPEOUT
) {
602 (void)dup(pipeout
[1]);
607 (void)ioctl(1, FIONCLEX
, NULL
);
611 if (flags
& F_STDERR
) {
616 (void)ioctl(2, FIONCLEX
, NULL
);
626 pv
[0] = dmove(pv
[0], -1);
627 pv
[1] = dmove(pv
[1], -1);
628 if (pv
[0] >= 0 && pv
[1] >= 0)
640 if (stat(cp
, &stb
) < 0)
642 if (S_ISCHR(stb
.st_mode
))
644 stderror(ERR_EXISTS
, cp
);