2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 static char sccsid
[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95";
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD: head/bin/sh/jobs.c 361112 2020-05-16 16:29:23Z jilles $");
41 #include <sys/ioctl.h>
42 #include <sys/param.h>
43 #include <sys/resource.h>
57 #undef CEOF /* syntax.h redefines this */
80 * A job structure contains information about a job. A job is either a
81 * single process or a set of processes contained in a pipeline. In the
82 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
87 pid_t pid
; /* process id */
88 int status
; /* status flags (defined above) */
89 char *cmd
; /* text of command being run */
94 #define JOBSTOPPED 1 /* all procs are stopped */
95 #define JOBDONE 2 /* all procs are completed */
99 struct procstat ps0
; /* status of process */
100 struct procstat
*ps
; /* status or processes when more than one */
101 short nprocs
; /* number of processes */
102 pid_t pgrp
; /* process group of this job */
103 char state
; /* true if job is finished */
104 char used
; /* true if this entry is in used */
105 char changed
; /* true if status has changed */
106 char foreground
; /* true if running in the foreground */
107 char remembered
; /* true if $! referenced */
108 char pipefail
; /* pass any non-zero status */
110 char jobctl
; /* job running under job control */
111 struct job
*next
; /* job used after this one */
116 static struct job
*jobtab
; /* array of jobs */
117 static int njobs
; /* size of array */
118 static pid_t backgndpid
= -1; /* pid of last background process */
119 static struct job
*bgjob
= NULL
; /* last background process */
121 static struct job
*jobmru
; /* most recently used job list */
122 static pid_t initialpgrp
; /* pgrp of shell on invocation */
124 static int ttyfd
= -1;
126 /* mode flags for dowait */
127 #define DOWAIT_BLOCK 0x1 /* wait until a child exits */
128 #define DOWAIT_SIG 0x2 /* if DOWAIT_BLOCK, abort on signal */
129 #define DOWAIT_SIG_TRAP 0x4 /* if DOWAIT_SIG, abort on trapped signal only */
132 static void restartjob(struct job
*);
134 static void freejob(struct job
*);
135 static int waitcmdloop(struct job
*);
136 static struct job
*getjob_nonotfound(const char *);
137 static struct job
*getjob(const char *);
138 pid_t
killjob(const char *, int);
139 static pid_t
dowait(int, struct job
*);
140 static void checkzombies(void);
141 static void cmdtxt(union node
*);
142 static void cmdputs(const char *);
144 static void setcurjob(struct job
*);
145 static void deljob(struct job
*);
146 static struct job
*getcurjob(struct job
*);
148 static int getjobstatus(const struct job
*);
149 static void printjobcmd(struct job
*);
150 static void showjob(struct job
*, int);
154 * Turn job control on and off.
174 out2fmt_flush("sh: can't access tty; job control turned off\n");
183 if (on
== jobctl
|| rootshell
== 0)
188 if ((ttyfd
= open(_PATH_TTY
, O_RDWR
| O_CLOEXEC_MAYBE
)) < 0) {
190 while (i
<= 2 && !isatty(i
))
193 (ttyfd
= fcntl(i
, F_DUPFD_CLOEXEC_MAYBE
, 10)) < 0) {
200 * Keep our TTY file descriptor out of the way of
201 * the user's redirections.
203 if ((i
= fcntl(ttyfd
, F_DUPFD_CLOEXEC_MAYBE
, 10)) < 0) {
210 #if !defined(O_CLOEXEC) || !defined(F_DUPFD_CLOEXEC)
211 if (fcntl(ttyfd
, F_SETFD
, FD_CLOEXEC
) < 0) {
217 do { /* while we are in the background */
218 initialpgrp
= tcgetpgrp(ttyfd
);
219 if (initialpgrp
< 0) {
220 #if !defined(O_CLOEXEC) || !defined(F_DUPFD_CLOEXEC)
226 if (initialpgrp
!= getpgrp()) {
240 tcsetpgrp(ttyfd
, rootpid
);
241 } else { /* turning job control off */
242 setpgid(0, initialpgrp
);
244 tcsetpgrp(ttyfd
, initialpgrp
);
259 fgcmd(int argc __unused
, char **argv __unused
)
266 jp
= getjob(*argptr
);
268 error("job not created under job control");
271 pgrp
= jp
->ps
[0].pid
;
273 tcsetpgrp(ttyfd
, pgrp
);
277 status
= waitforjob(jp
, (int *)NULL
);
284 bgcmd(int argc __unused
, char **argv __unused
)
290 jp
= getjob(*argptr
);
292 error("job not created under job control");
293 if (jp
->state
== JOBDONE
)
297 out1fmt("[%td] ", jp
- jobtab
+ 1);
299 } while (*argptr
!= NULL
&& *++argptr
!= NULL
);
305 restartjob(struct job
*jp
)
310 if (jp
->state
== JOBDONE
)
314 kill(-jp
->ps
[0].pid
, SIGCONT
);
315 for (ps
= jp
->ps
, i
= jp
->nprocs
; --i
>= 0 ; ps
++) {
316 if (WIFSTOPPED(ps
->status
)) {
327 jobscmd(int argc __unused
, char *argv
[] __unused
)
332 mode
= SHOWJOBS_DEFAULT
;
333 while ((ch
= nextopt("lps")) != '\0') {
336 mode
= SHOWJOBS_VERBOSE
;
339 mode
= SHOWJOBS_PGIDS
;
342 mode
= SHOWJOBS_PIDS
;
350 while ((id
= *argptr
++) != NULL
)
351 showjob(getjob(id
), mode
);
356 static int getjobstatus(const struct job
*jp
)
361 return (jp
->ps
[jp
->nprocs
- 1].status
);
362 for (i
= jp
->nprocs
- 1; i
>= 0; i
--) {
363 status
= jp
->ps
[i
].status
;
371 printjobcmd(struct job
*jp
)
376 for (ps
= jp
->ps
, i
= jp
->nprocs
; --i
>= 0 ; ps
++) {
385 showjob(struct job
*jp
, int mode
)
389 const char *statestr
, *coredump
;
392 int col
, curr
, i
, jobno
, prev
, procno
, status
;
395 procno
= (mode
== SHOWJOBS_PGIDS
) ? 1 : jp
->nprocs
;
396 jobno
= jp
- jobtab
+ 1;
399 if ((j
= getcurjob(NULL
)) != NULL
) {
400 curr
= j
- jobtab
+ 1;
401 if ((j
= getcurjob(j
)) != NULL
)
402 prev
= j
- jobtab
+ 1;
406 status
= getjobstatus(jp
);
407 if (jp
->state
== 0) {
408 statestr
= "Running";
410 } else if (jp
->state
== JOBSTOPPED
) {
411 ps
= jp
->ps
+ jp
->nprocs
- 1;
412 while (!WIFSTOPPED(ps
->status
) && ps
> jp
->ps
)
414 if (WIFSTOPPED(ps
->status
))
415 i
= WSTOPSIG(ps
->status
);
418 statestr
= strsignal(i
);
419 if (statestr
== NULL
)
420 statestr
= "Suspended";
422 } else if (WIFEXITED(status
)) {
423 if (WEXITSTATUS(status
) == 0)
426 fmtstr(statebuf
, sizeof(statebuf
), "Done(%d)",
427 WEXITSTATUS(status
));
431 i
= WTERMSIG(status
);
432 statestr
= strsignal(i
);
433 if (statestr
== NULL
)
434 statestr
= "Unknown signal";
435 if (WCOREDUMP(status
))
436 coredump
= " (core dumped)";
439 for (ps
= jp
->ps
; procno
> 0 ; ps
++, procno
--) { /* for each process */
440 if (mode
== SHOWJOBS_PIDS
|| mode
== SHOWJOBS_PGIDS
) {
441 out1fmt("%d\n", (int)ps
->pid
);
444 if (mode
!= SHOWJOBS_VERBOSE
&& ps
!= jp
->ps
)
446 if (jobno
== curr
&& ps
== jp
->ps
)
448 else if (jobno
== prev
&& ps
== jp
->ps
)
453 fmtstr(s
, 64, "[%d] %c ", jobno
, c
);
455 fmtstr(s
, 64, " %c ", c
);
458 if (mode
== SHOWJOBS_VERBOSE
) {
459 fmtstr(s
, 64, "%d ", (int)ps
->pid
);
466 col
+= strlen(statestr
) + strlen(coredump
);
472 if (mode
== SHOWJOBS_VERBOSE
) {
481 * Print a list of jobs. If "change" is nonzero, only print jobs whose
482 * statuses have changed since the last call to showjobs.
484 * If the shell is interrupted in the process of creating a job, the
485 * result may be a job structure containing zero processes. Such structures
486 * will be freed here.
490 showjobs(int change
, int mode
)
495 TRACE(("showjobs(%d) called\n", change
));
497 for (jobno
= 1, jp
= jobtab
; jobno
<= njobs
; jobno
++, jp
++) {
500 if (jp
->nprocs
== 0) {
504 if (change
&& ! jp
->changed
)
507 if (mode
== SHOWJOBS_DEFAULT
|| mode
== SHOWJOBS_VERBOSE
) {
509 /* Hack: discard jobs for which $! has not been
510 * referenced in interactive mode when they terminate.
512 if (jp
->state
== JOBDONE
&& !jp
->remembered
&&
513 (iflag
|| jp
!= bgjob
)) {
522 * Mark a job structure as unused.
526 freejob(struct job
*jp
)
534 for (i
= jp
->nprocs
, ps
= jp
->ps
; --i
>= 0 ; ps
++) {
535 if (ps
->cmd
!= nullstr
)
538 if (jp
->ps
!= &jp
->ps0
)
550 waitcmd(int argc __unused
, char **argv __unused
)
557 return (waitcmdloop(NULL
));
560 job
= getjob_nonotfound(*argptr
);
564 retval
= waitcmdloop(job
);
566 } while (*argptr
!= NULL
);
572 waitcmdloop(struct job
*job
)
574 int status
, retval
, sig
;
578 * Loop until a process is terminated or stopped, or a SIGINT is
584 if (job
->state
== JOBDONE
) {
585 status
= getjobstatus(job
);
586 if (WIFEXITED(status
))
587 retval
= WEXITSTATUS(status
);
589 retval
= WTERMSIG(status
) + 128;
590 if (! iflag
|| ! job
->changed
)
600 for (jp
= jobtab
; jp
< jobtab
+ njobs
; jp
++)
601 if (jp
->used
&& jp
->state
== JOBDONE
) {
602 if (! iflag
|| ! jp
->changed
)
610 for (jp
= jobtab
; ; jp
++) {
611 if (jp
>= jobtab
+ njobs
) { /* no running procs */
614 if (jp
->used
&& jp
->state
== 0)
618 } while (dowait(DOWAIT_BLOCK
| DOWAIT_SIG
, (struct job
*)NULL
) != -1);
620 sig
= pendingsig_waitcmd
;
621 pendingsig_waitcmd
= 0;
628 jobidcmd(int argc __unused
, char **argv __unused
)
634 jp
= getjob(*argptr
);
635 for (i
= 0 ; i
< jp
->nprocs
; ) {
636 out1fmt("%d", (int)jp
->ps
[i
].pid
);
637 out1c(++i
< jp
->nprocs
? ' ' : '\n');
645 * Convert a job name to a job structure.
649 getjob_nonotfound(const char *name
)
652 struct job
*found
, *jp
;
661 error("No current job");
664 if (name
[0] == '%') {
665 if (is_digit(name
[1])) {
666 jobno
= number(name
+ 1);
667 if (jobno
> 0 && jobno
<= njobs
668 && jobtab
[jobno
- 1].used
!= 0)
669 return &jobtab
[jobno
- 1];
671 } else if ((name
[1] == '%' || name
[1] == '+') &&
673 if ((jp
= getcurjob(NULL
)) == NULL
)
674 error("No current job");
676 } else if (name
[1] == '-' && name
[2] == '\0') {
677 if ((jp
= getcurjob(NULL
)) == NULL
||
678 (jp
= getcurjob(jp
)) == NULL
)
679 error("No previous job");
682 } else if (name
[1] == '?') {
684 for (jp
= jobtab
, i
= njobs
; --i
>= 0 ; jp
++) {
685 if (jp
->used
&& jp
->nprocs
> 0
686 && strstr(jp
->ps
[0].cmd
, name
+ 2) != NULL
) {
688 error("%s: ambiguous", name
);
695 namelen
= strlen(name
);
697 for (jp
= jobtab
, i
= njobs
; --i
>= 0 ; jp
++) {
698 if (jp
->used
&& jp
->nprocs
> 0
699 && strncmp(jp
->ps
[0].cmd
, name
+ 1,
702 error("%s: ambiguous", name
);
709 } else if (is_number(name
)) {
710 pid
= (pid_t
)number(name
);
711 for (jp
= jobtab
, i
= njobs
; --i
>= 0 ; jp
++) {
712 if (jp
->used
&& jp
->nprocs
> 0
713 && jp
->ps
[jp
->nprocs
- 1].pid
== pid
)
722 getjob(const char *name
)
726 jp
= getjob_nonotfound(name
);
728 error("No such job: %s", name
);
734 killjob(const char *name
, int sig
)
740 if (jp
->state
== JOBDONE
)
743 return kill(-jp
->ps
[0].pid
, sig
);
746 for (i
= 0; i
< jp
->nprocs
; i
++)
747 if (jp
->ps
[i
].status
== -1 || WIFSTOPPED(jp
->ps
[i
].status
)) {
748 if (kill(jp
->ps
[i
].pid
, sig
) == 0)
756 * Return a new job structure,
760 makejob(union node
*node __unused
, int nprocs
)
765 for (i
= njobs
, jp
= jobtab
; ; jp
++) {
769 jobtab
= ckmalloc(4 * sizeof jobtab
[0]);
774 jp
= ckmalloc((njobs
+ 4) * sizeof jobtab
[0]);
775 memcpy(jp
, jobtab
, njobs
* sizeof jp
[0]);
777 /* Relocate `next' pointers and list head */
779 jobmru
= &jp
[jobmru
- jobtab
];
780 for (i
= 0; i
< njobs
; i
++)
781 if (jp
[i
].next
!= NULL
)
782 jp
[i
].next
= &jp
[jp
[i
].next
-
786 bgjob
= &jp
[bgjob
- jobtab
];
787 /* Relocate `ps' pointers */
788 for (i
= 0; i
< njobs
; i
++)
789 if (jp
[i
].ps
== &jobtab
[i
].ps0
)
790 jp
[i
].ps
= &jp
[i
].ps0
;
795 for (i
= 4 ; --i
>= 0 ; jobtab
[njobs
++].used
= 0)
810 jp
->pipefail
= pipefailflag
;
816 jp
->ps
= ckmalloc(nprocs
* sizeof (struct procstat
));
821 TRACE(("makejob(%p, %d) returns %%%td\n", (void *)node
, nprocs
,
828 setcurjob(struct job
*cj
)
830 struct job
*jp
, *prev
;
832 for (prev
= NULL
, jp
= jobmru
; jp
!= NULL
; prev
= jp
, jp
= jp
->next
) {
835 prev
->next
= jp
->next
;
848 deljob(struct job
*j
)
850 struct job
*jp
, *prev
;
852 for (prev
= NULL
, jp
= jobmru
; jp
!= NULL
; prev
= jp
, jp
= jp
->next
) {
855 prev
->next
= jp
->next
;
864 * Return the most recently used job that isn't `nj', and preferably one
868 getcurjob(struct job
*nj
)
872 /* Try to find a stopped one.. */
873 for (jp
= jobmru
; jp
!= NULL
; jp
= jp
->next
)
874 if (jp
->used
&& jp
!= nj
&& jp
->state
== JOBSTOPPED
)
876 /* Otherwise the most recently used job that isn't `nj' */
877 for (jp
= jobmru
; jp
!= NULL
; jp
= jp
->next
)
878 if (jp
->used
&& jp
!= nj
)
887 * Fork of a subshell. If we are doing job control, give the subshell its
888 * own process group. Jp is a job structure that the job is to be added to.
889 * N is the command that will be evaluated by the child. Both jp and n may
890 * be NULL. The mode parameter can be one of the following:
891 * FORK_FG - Fork off a foreground process.
892 * FORK_BG - Fork off a background process.
893 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
894 * process group even if job control is on.
896 * When job control is turned off, background processes have their standard
897 * input redirected to /dev/null (except for the second and later processes
902 forkshell(struct job
*jp
, union node
*n
, int mode
)
907 TRACE(("forkshell(%%%td, %p, %d) called\n", jp
- jobtab
, (void *)n
,
910 if (mode
== FORK_BG
&& (jp
== NULL
|| jp
->nprocs
== 0))
915 TRACE(("Fork failed, errno=%d\n", errno
));
917 error("Cannot fork: %s", strerror(errno
));
924 TRACE(("Child shell %d\n", (int)getpid()));
927 handler
= &main_handler
;
933 jobctl
= 0; /* do job control only in root shell */
934 if (wasroot
&& mode
!= FORK_NOJOB
&& mflag
) {
935 if (jp
== NULL
|| jp
->nprocs
== 0)
938 pgrp
= jp
->ps
[0].pid
;
939 if (setpgid(0, pgrp
) == 0 && mode
== FORK_FG
&&
941 /*** this causes superfluous TIOCSPGRPS ***/
942 if (tcsetpgrp(ttyfd
, pgrp
) < 0)
943 error("tcsetpgrp failed, errno=%d", errno
);
947 } else if (mode
== FORK_BG
) {
950 if ((jp
== NULL
|| jp
->nprocs
== 0) &&
951 ! fd0_redirected_p ()) {
953 if (open(_PATH_DEVNULL
, O_RDONLY
) != 0)
954 error("cannot open %s: %s",
955 _PATH_DEVNULL
, strerror(errno
));
959 if (mode
== FORK_BG
) {
962 if ((jp
== NULL
|| jp
->nprocs
== 0) &&
963 ! fd0_redirected_p ()) {
965 if (open(_PATH_DEVNULL
, O_RDONLY
) != 0)
966 error("cannot open %s: %s",
967 _PATH_DEVNULL
, strerror(errno
));
972 for (i
= njobs
, p
= jobtab
; --i
>= 0 ; p
++)
976 if (wasroot
&& iflag
) {
983 if (rootshell
&& mode
!= FORK_NOJOB
&& mflag
) {
984 if (jp
== NULL
|| jp
->nprocs
== 0)
987 pgrp
= jp
->ps
[0].pid
;
990 if (mode
== FORK_BG
) {
991 if (bgjob
!= NULL
&& bgjob
->state
== JOBDONE
&&
992 !bgjob
->remembered
&& !iflag
)
994 backgndpid
= pid
; /* set $! */
998 struct procstat
*ps
= &jp
->ps
[jp
->nprocs
++];
1002 if (iflag
&& rootshell
&& n
)
1003 ps
->cmd
= commandtext(n
);
1004 jp
->foreground
= mode
== FORK_FG
;
1010 TRACE(("In parent shell: child = %d\n", (int)pid
));
1016 vforkexecshell(struct job
*jp
, char **argv
, char **envp
, const char *path
, int idx
, int pip
[2])
1019 struct jmploc jmploc
;
1020 struct jmploc
*savehandler
;
1023 TRACE(("vforkexecshell(%%%td, %s, %p) called\n", jp
- jobtab
, argv
[0],
1025 inton
= is_int_on();
1028 savehandler
= handler
;
1031 TRACE(("Vfork failed, errno=%d\n", errno
));
1033 error("Cannot fork: %s", strerror(errno
));
1036 TRACE(("Child shell %d\n", (int)getpid()));
1037 if (setjmp(jmploc
.loc
))
1047 shellexec(argv
, envp
, path
, idx
);
1049 handler
= savehandler
;
1051 struct procstat
*ps
= &jp
->ps
[jp
->nprocs
++];
1061 TRACE(("In parent shell: child = %d\n", (int)pid
));
1067 * Wait for job to finish.
1069 * Under job control we have the problem that while a child process is
1070 * running interrupts generated by the user are sent to the child but not
1071 * to the shell. This means that an infinite loop started by an inter-
1072 * active user may be hard to kill. With job control turned off, an
1073 * interactive user may place an interactive program inside a loop. If
1074 * the interactive program catches interrupts, the user doesn't want
1075 * these interrupts to also abort the loop. The approach we take here
1076 * is to have the shell ignore interrupt signals while waiting for a
1077 * foreground process to terminate, and then send itself an interrupt
1078 * signal if the child process was terminated by an interrupt signal.
1079 * Unfortunately, some programs want to do a bit of cleanup and then
1080 * exit on interrupt; unless these processes terminate themselves by
1081 * sending a signal to themselves (instead of calling exit) they will
1082 * confuse this approach.
1086 waitforjob(struct job
*jp
, int *signaled
)
1089 int propagate_int
= jp
->jobctl
&& jp
->foreground
;
1095 TRACE(("waitforjob(%%%td) called\n", jp
- jobtab
+ 1));
1096 while (jp
->state
== 0)
1097 if (dowait(DOWAIT_BLOCK
| (Tflag
? DOWAIT_SIG
|
1098 DOWAIT_SIG_TRAP
: 0), jp
) == -1)
1102 if (ttyfd
>= 0 && tcsetpgrp(ttyfd
, rootpid
) < 0)
1103 error("tcsetpgrp failed, errno=%d\n", errno
);
1105 if (jp
->state
== JOBSTOPPED
)
1108 status
= getjobstatus(jp
);
1109 if (signaled
!= NULL
)
1110 *signaled
= WIFSIGNALED(status
);
1111 /* convert to 8 bits */
1112 if (WIFEXITED(status
))
1113 st
= WEXITSTATUS(status
);
1115 else if (WIFSTOPPED(status
))
1116 st
= WSTOPSIG(status
) + 128;
1119 st
= WTERMSIG(status
) + 128;
1120 if (! JOBS
|| jp
->state
== JOBDONE
)
1122 if (int_pending()) {
1123 if (!WIFSIGNALED(status
) || WTERMSIG(status
) != SIGINT
)
1127 else if (rootshell
&& propagate_int
&&
1128 WIFSIGNALED(status
) && WTERMSIG(status
) == SIGINT
)
1129 kill(getpid(), SIGINT
);
1137 dummy_handler(int sig __unused
)
1142 * Wait for a process to terminate.
1146 dowait(int mode
, struct job
*job
)
1148 struct sigaction sa
, osa
;
1149 sigset_t mask
, omask
;
1152 struct procstat
*sp
;
1154 struct job
*thisjob
;
1161 int restore_sigchld
;
1163 TRACE(("dowait(%d, %p) called\n", mode
, job
));
1164 restore_sigchld
= 0;
1165 if ((mode
& DOWAIT_SIG
) != 0) {
1167 sigprocmask(SIG_BLOCK
, &mask
, &omask
);
1169 if (!issigchldtrapped()) {
1170 restore_sigchld
= 1;
1171 sa
.sa_handler
= dummy_handler
;
1173 sigemptyset(&sa
.sa_mask
);
1174 sigaction(SIGCHLD
, &sa
, &osa
);
1180 wflags
= WUNTRACED
| WCONTINUED
;
1184 if ((mode
& (DOWAIT_BLOCK
| DOWAIT_SIG
)) != DOWAIT_BLOCK
)
1186 pid
= wait3(&status
, wflags
, (struct rusage
*)NULL
);
1187 TRACE(("wait returns %d, status=%d\n", (int)pid
, status
));
1188 if (pid
== 0 && (mode
& DOWAIT_SIG
) != 0) {
1190 if (((mode
& DOWAIT_SIG_TRAP
) != 0 ?
1191 pendingsig
: pendingsig_waitcmd
) != 0) {
1199 } while (pid
== -1 && errno
== EINTR
);
1200 if (pid
== -1 && errno
== ECHILD
&& job
!= NULL
)
1201 job
->state
= JOBDONE
;
1202 if ((mode
& DOWAIT_SIG
) != 0) {
1203 if (restore_sigchld
)
1204 sigaction(SIGCHLD
, &osa
, NULL
);
1205 sigprocmask(SIG_SETMASK
, &omask
, NULL
);
1212 for (jp
= jobtab
; jp
< jobtab
+ njobs
; jp
++) {
1213 if (jp
->used
&& jp
->nprocs
> 0) {
1216 for (sp
= jp
->ps
; sp
< jp
->ps
+ jp
->nprocs
; sp
++) {
1219 if (sp
->pid
== pid
&& (sp
->status
== -1 ||
1220 WIFSTOPPED(sp
->status
))) {
1221 TRACE(("Changing status of proc %d from 0x%x to 0x%x\n",
1222 (int)pid
, sp
->status
,
1224 if (WIFCONTINUED(status
)) {
1228 sp
->status
= status
;
1231 if (sp
->status
== -1)
1233 else if (WIFSTOPPED(sp
->status
))
1236 if (stopped
) { /* stopped or done */
1237 int state
= done
? JOBDONE
: JOBSTOPPED
;
1238 if (jp
->state
!= state
) {
1239 TRACE(("Job %td: changing state from %d to %d\n", jp
- jobtab
+ 1, jp
->state
, state
));
1242 if (done
&& !jp
->remembered
&&
1243 !iflag
&& jp
!= bgjob
)
1255 if (!thisjob
|| thisjob
->state
== 0)
1257 else if ((!rootshell
|| !iflag
|| thisjob
== job
) &&
1258 thisjob
->foreground
&& thisjob
->state
!= JOBSTOPPED
) {
1261 for (sp
= thisjob
->ps
; sp
< thisjob
->ps
+ thisjob
->nprocs
; sp
++)
1262 if (WIFSIGNALED(sp
->status
)) {
1263 sig
= WTERMSIG(sp
->status
);
1264 coredump
= WCOREDUMP(sp
->status
);
1266 if (sig
> 0 && sig
!= SIGINT
&& sig
!= SIGPIPE
) {
1267 sigstr
= strsignal(sig
);
1271 out2str("Unknown signal");
1273 out2str(" (core dumped)");
1278 TRACE(("Not printing status, rootshell=%d, job=%p\n", rootshell
, job
));
1279 thisjob
->changed
= 1;
1287 * return 1 if there are stopped jobs, otherwise 0
1289 int job_warning
= 0;
1298 for (jobno
= 1, jp
= jobtab
; jobno
<= njobs
; jobno
++, jp
++) {
1301 if (jp
->state
== JOBSTOPPED
) {
1302 out2fmt_flush("You have stopped jobs.\n");
1315 while (njobs
> 0 && dowait(0, NULL
) > 0)
1323 return backgndpid
!= -1;
1330 if (bgjob
!= NULL
&& !forcelocal
)
1331 bgjob
->remembered
= 1;
1336 * Return a string identifying a command (to be printed by the
1340 static char *cmdnextc
;
1341 static int cmdnleft
;
1342 #define MAXCMDTEXT 200
1345 commandtext(union node
*n
)
1349 cmdnextc
= name
= ckmalloc(MAXCMDTEXT
);
1350 cmdnleft
= MAXCMDTEXT
- 4;
1358 cmdtxtdogroup(union node
*n
)
1367 cmdtxtredir(union node
*n
, const char *op
, int deffd
)
1371 if (n
->nfile
.fd
!= deffd
) {
1372 s
[0] = n
->nfile
.fd
+ '0';
1377 if (n
->type
== NTOFD
|| n
->type
== NFROMFD
) {
1378 if (n
->ndup
.dupfd
>= 0)
1379 s
[0] = n
->ndup
.dupfd
+ '0';
1385 cmdtxt(n
->nfile
.fname
);
1391 cmdtxt(union node
*n
)
1394 struct nodelist
*lp
;
1400 cmdtxt(n
->nbinary
.ch1
);
1402 cmdtxt(n
->nbinary
.ch2
);
1405 cmdtxt(n
->nbinary
.ch1
);
1407 cmdtxt(n
->nbinary
.ch2
);
1410 cmdtxt(n
->nbinary
.ch1
);
1412 cmdtxt(n
->nbinary
.ch2
);
1415 for (lp
= n
->npipe
.cmdlist
; lp
; lp
= lp
->next
) {
1423 cmdtxt(n
->nredir
.n
);
1428 cmdtxt(n
->nredir
.n
);
1432 cmdtxt(n
->nif
.test
);
1434 cmdtxt(n
->nif
.ifpart
);
1439 cmdtxt(n
->nbinary
.ch1
);
1440 cmdtxtdogroup(n
->nbinary
.ch2
);
1444 cmdtxt(n
->nbinary
.ch1
);
1445 cmdtxtdogroup(n
->nbinary
.ch2
);
1449 cmdputs(n
->nfor
.var
);
1454 cmdputs(n
->ncase
.expr
->narg
.text
);
1458 cmdputs(n
->narg
.text
);
1463 cmdtxt(n
->nnot
.com
);
1466 for (np
= n
->ncmd
.args
; np
; np
= np
->narg
.next
) {
1471 for (np
= n
->ncmd
.redirect
; np
; np
= np
->nfile
.next
) {
1477 cmdputs(n
->narg
.text
);
1480 cmdtxtredir(n
, ">", 1);
1483 cmdtxtredir(n
, ">>", 1);
1486 cmdtxtredir(n
, ">&", 1);
1489 cmdtxtredir(n
, ">|", 1);
1492 cmdtxtredir(n
, "<", 0);
1495 cmdtxtredir(n
, "<>", 0);
1498 cmdtxtredir(n
, "<&", 0);
1513 cmdputs(const char *s
)
1524 while ((c
= *p
++) != '\0') {
1527 else if (c
== CTLVAR
) {
1532 if ((subtype
& VSTYPE
) == VSLENGTH
&& --cmdnleft
> 0)
1534 } else if (c
== '=' && subtype
!= 0) {
1535 *q
= "}-+?=##%%\0X"[(subtype
& VSTYPE
) - VSNORMAL
];
1540 if (((subtype
& VSTYPE
) == VSTRIMLEFTMAX
||
1541 (subtype
& VSTYPE
) == VSTRIMRIGHTMAX
) &&
1545 } else if (c
== CTLENDVAR
) {
1547 } else if (c
== CTLBACKQ
|| c
== CTLBACKQ
+CTLQUOTE
) {
1557 } else if (c
== CTLARI
) {
1565 } else if (c
== CTLENDARI
) {
1566 if (--cmdnleft
> 0) {
1570 } else if (c
== CTLQUOTEMARK
|| c
== CTLQUOTEEND
)
1571 cmdnleft
++; /* ignore */
1574 if (--cmdnleft
<= 0) {