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$");
41 #include <sys/ioctl.h>
42 #include <sys/param.h>
43 #include <sys/resource.h>
57 #undef CEOF /* syntax.h redefines this */
78 static struct job
*jobtab
; /* array of jobs */
79 static int njobs
; /* size of array */
80 static pid_t backgndpid
= -1; /* pid of last background process */
81 static struct job
*bgjob
= NULL
; /* last background process */
83 static struct job
*jobmru
; /* most recently used job list */
84 static pid_t initialpgrp
; /* pgrp of shell on invocation */
86 static int ttyfd
= -1;
88 /* mode flags for dowait */
89 #define DOWAIT_BLOCK 0x1 /* wait until a child exits */
90 #define DOWAIT_SIG 0x2 /* if DOWAIT_BLOCK, abort on signal */
91 #define DOWAIT_SIG_TRAP 0x4 /* if DOWAIT_SIG, abort on trapped signal only */
94 static void restartjob(struct job
*);
96 static void freejob(struct job
*);
97 static int waitcmdloop(struct job
*);
98 static struct job
*getjob_nonotfound(const char *);
99 static struct job
*getjob(const char *);
100 pid_t
killjob(const char *, int);
101 static pid_t
dowait(int, struct job
*);
102 static void checkzombies(void);
103 static void cmdtxt(union node
*);
104 static void cmdputs(const char *);
106 static void setcurjob(struct job
*);
107 static void deljob(struct job
*);
108 static struct job
*getcurjob(struct job
*);
110 static void printjobcmd(struct job
*);
111 static void showjob(struct job
*, int);
115 * Turn job control on and off.
135 out2fmt_flush("sh: can't access tty; job control turned off\n");
144 if (on
== jobctl
|| rootshell
== 0)
149 if ((ttyfd
= open(_PATH_TTY
, O_RDWR
| O_CLOEXEC_MAYBE
)) < 0) {
151 while (i
<= 2 && !isatty(i
))
154 (ttyfd
= fcntl(i
, F_DUPFD_CLOEXEC_MAYBE
, 10)) < 0) {
161 * Keep our TTY file descriptor out of the way of
162 * the user's redirections.
164 if ((i
= fcntl(ttyfd
, F_DUPFD_CLOEXEC_MAYBE
, 10)) < 0) {
171 #if !defined(O_CLOEXEC) || !defined(F_DUPFD_CLOEXEC)
172 if (fcntl(ttyfd
, F_SETFD
, FD_CLOEXEC
) < 0) {
178 do { /* while we are in the background */
179 initialpgrp
= tcgetpgrp(ttyfd
);
180 if (initialpgrp
< 0) {
181 #if !defined(O_CLOEXEC) || !defined(F_DUPFD_CLOEXEC)
187 if (initialpgrp
!= getpgrp()) {
201 tcsetpgrp(ttyfd
, rootpid
);
202 } else { /* turning job control off */
203 setpgid(0, initialpgrp
);
205 tcsetpgrp(ttyfd
, initialpgrp
);
220 fgcmd(int argc __unused
, char **argv __unused
)
227 jp
= getjob(*argptr
);
229 error("job not created under job control");
232 pgrp
= jp
->ps
[0].pid
;
234 tcsetpgrp(ttyfd
, pgrp
);
238 status
= waitforjob(jp
, (int *)NULL
);
245 bgcmd(int argc __unused
, char **argv __unused
)
251 jp
= getjob(*argptr
);
253 error("job not created under job control");
254 if (jp
->state
== JOBDONE
)
258 out1fmt("[%td] ", jp
- jobtab
+ 1);
260 } while (*argptr
!= NULL
&& *++argptr
!= NULL
);
266 restartjob(struct job
*jp
)
271 if (jp
->state
== JOBDONE
)
275 kill(-jp
->ps
[0].pid
, SIGCONT
);
276 for (ps
= jp
->ps
, i
= jp
->nprocs
; --i
>= 0 ; ps
++) {
277 if (WIFSTOPPED(ps
->status
)) {
288 jobscmd(int argc __unused
, char *argv
[] __unused
)
293 mode
= SHOWJOBS_DEFAULT
;
294 while ((ch
= nextopt("lps")) != '\0') {
297 mode
= SHOWJOBS_VERBOSE
;
300 mode
= SHOWJOBS_PGIDS
;
303 mode
= SHOWJOBS_PIDS
;
311 while ((id
= *argptr
++) != NULL
)
312 showjob(getjob(id
), mode
);
318 printjobcmd(struct job
*jp
)
323 for (ps
= jp
->ps
, i
= jp
->nprocs
; --i
>= 0 ; ps
++) {
332 showjob(struct job
*jp
, int mode
)
339 int col
, curr
, i
, jobno
, prev
, procno
;
342 procno
= (mode
== SHOWJOBS_PGIDS
) ? 1 : jp
->nprocs
;
343 jobno
= jp
- jobtab
+ 1;
346 if ((j
= getcurjob(NULL
)) != NULL
) {
347 curr
= j
- jobtab
+ 1;
348 if ((j
= getcurjob(j
)) != NULL
)
349 prev
= j
- jobtab
+ 1;
352 ps
= jp
->ps
+ jp
->nprocs
- 1;
353 if (jp
->state
== 0) {
354 strcpy(statestr
, "Running");
356 } else if (jp
->state
== JOBSTOPPED
) {
357 while (!WIFSTOPPED(ps
->status
) && ps
> jp
->ps
)
359 if (WIFSTOPPED(ps
->status
))
360 i
= WSTOPSIG(ps
->status
);
363 sigstr
= strsignal(i
);
365 strcpy(statestr
, sigstr
);
367 strcpy(statestr
, "Suspended");
369 } else if (WIFEXITED(ps
->status
)) {
370 if (WEXITSTATUS(ps
->status
) == 0)
371 strcpy(statestr
, "Done");
373 fmtstr(statestr
, 64, "Done(%d)",
374 WEXITSTATUS(ps
->status
));
376 i
= WTERMSIG(ps
->status
);
377 sigstr
= strsignal(i
);
379 strcpy(statestr
, sigstr
);
381 strcpy(statestr
, "Unknown signal");
382 if (WCOREDUMP(ps
->status
))
383 strcat(statestr
, " (core dumped)");
386 for (ps
= jp
->ps
; procno
> 0 ; ps
++, procno
--) { /* for each process */
387 if (mode
== SHOWJOBS_PIDS
|| mode
== SHOWJOBS_PGIDS
) {
388 out1fmt("%d\n", (int)ps
->pid
);
391 if (mode
!= SHOWJOBS_VERBOSE
&& ps
!= jp
->ps
)
393 if (jobno
== curr
&& ps
== jp
->ps
)
395 else if (jobno
== prev
&& ps
== jp
->ps
)
400 fmtstr(s
, 64, "[%d] %c ", jobno
, c
);
402 fmtstr(s
, 64, " %c ", c
);
405 if (mode
== SHOWJOBS_VERBOSE
) {
406 fmtstr(s
, 64, "%d ", (int)ps
->pid
);
412 col
+= strlen(statestr
);
418 if (mode
== SHOWJOBS_VERBOSE
) {
427 * Print a list of jobs. If "change" is nonzero, only print jobs whose
428 * statuses have changed since the last call to showjobs.
430 * If the shell is interrupted in the process of creating a job, the
431 * result may be a job structure containing zero processes. Such structures
432 * will be freed here.
436 showjobs(int change
, int mode
)
441 TRACE(("showjobs(%d) called\n", change
));
443 for (jobno
= 1, jp
= jobtab
; jobno
<= njobs
; jobno
++, jp
++) {
446 if (jp
->nprocs
== 0) {
450 if (change
&& ! jp
->changed
)
453 if (mode
== SHOWJOBS_DEFAULT
|| mode
== SHOWJOBS_VERBOSE
) {
455 /* Hack: discard jobs for which $! has not been
456 * referenced in interactive mode when they terminate.
458 if (jp
->state
== JOBDONE
&& !jp
->remembered
&&
459 (iflag
|| jp
!= bgjob
)) {
468 * Mark a job structure as unused.
472 freejob(struct job
*jp
)
480 for (i
= jp
->nprocs
, ps
= jp
->ps
; --i
>= 0 ; ps
++) {
481 if (ps
->cmd
!= nullstr
)
484 if (jp
->ps
!= &jp
->ps0
)
496 waitcmd(int argc __unused
, char **argv __unused
)
503 return (waitcmdloop(NULL
));
506 job
= getjob_nonotfound(*argptr
);
510 retval
= waitcmdloop(job
);
512 } while (*argptr
!= NULL
);
518 waitcmdloop(struct job
*job
)
520 int status
, retval
, sig
;
524 * Loop until a process is terminated or stopped, or a SIGINT is
530 if (job
->state
== JOBDONE
) {
531 status
= job
->ps
[job
->nprocs
- 1].status
;
532 if (WIFEXITED(status
))
533 retval
= WEXITSTATUS(status
);
535 retval
= WTERMSIG(status
) + 128;
536 if (! iflag
|| ! job
->changed
)
546 for (jp
= jobtab
; jp
< jobtab
+ njobs
; jp
++)
547 if (jp
->used
&& jp
->state
== JOBDONE
) {
548 if (! iflag
|| ! jp
->changed
)
556 for (jp
= jobtab
; ; jp
++) {
557 if (jp
>= jobtab
+ njobs
) { /* no running procs */
560 if (jp
->used
&& jp
->state
== 0)
564 } while (dowait(DOWAIT_BLOCK
| DOWAIT_SIG
, (struct job
*)NULL
) != -1);
566 sig
= pendingsig_waitcmd
;
567 pendingsig_waitcmd
= 0;
574 jobidcmd(int argc __unused
, char **argv __unused
)
580 jp
= getjob(*argptr
);
581 for (i
= 0 ; i
< jp
->nprocs
; ) {
582 out1fmt("%d", (int)jp
->ps
[i
].pid
);
583 out1c(++i
< jp
->nprocs
? ' ' : '\n');
591 * Convert a job name to a job structure.
595 getjob_nonotfound(const char *name
)
598 struct job
*found
, *jp
;
607 error("No current job");
610 if (name
[0] == '%') {
611 if (is_digit(name
[1])) {
612 jobno
= number(name
+ 1);
613 if (jobno
> 0 && jobno
<= njobs
614 && jobtab
[jobno
- 1].used
!= 0)
615 return &jobtab
[jobno
- 1];
617 } else if ((name
[1] == '%' || name
[1] == '+') &&
619 if ((jp
= getcurjob(NULL
)) == NULL
)
620 error("No current job");
622 } else if (name
[1] == '-' && name
[2] == '\0') {
623 if ((jp
= getcurjob(NULL
)) == NULL
||
624 (jp
= getcurjob(jp
)) == NULL
)
625 error("No previous job");
628 } else if (name
[1] == '?') {
630 for (jp
= jobtab
, i
= njobs
; --i
>= 0 ; jp
++) {
631 if (jp
->used
&& jp
->nprocs
> 0
632 && strstr(jp
->ps
[0].cmd
, name
+ 2) != NULL
) {
634 error("%s: ambiguous", name
);
641 namelen
= strlen(name
);
643 for (jp
= jobtab
, i
= njobs
; --i
>= 0 ; jp
++) {
644 if (jp
->used
&& jp
->nprocs
> 0
645 && strncmp(jp
->ps
[0].cmd
, name
+ 1,
648 error("%s: ambiguous", name
);
655 } else if (is_number(name
)) {
656 pid
= (pid_t
)number(name
);
657 for (jp
= jobtab
, i
= njobs
; --i
>= 0 ; jp
++) {
658 if (jp
->used
&& jp
->nprocs
> 0
659 && jp
->ps
[jp
->nprocs
- 1].pid
== pid
)
668 getjob(const char *name
)
672 jp
= getjob_nonotfound(name
);
674 error("No such job: %s", name
);
680 killjob(const char *name
, int sig
)
686 if (jp
->state
== JOBDONE
)
689 return kill(-jp
->ps
[0].pid
, sig
);
692 for (i
= 0; i
< jp
->nprocs
; i
++)
693 if (jp
->ps
[i
].status
== -1 || WIFSTOPPED(jp
->ps
[i
].status
)) {
694 if (kill(jp
->ps
[i
].pid
, sig
) == 0)
702 * Return a new job structure,
706 makejob(union node
*node __unused
, int nprocs
)
711 for (i
= njobs
, jp
= jobtab
; ; jp
++) {
715 jobtab
= ckmalloc(4 * sizeof jobtab
[0]);
720 jp
= ckmalloc((njobs
+ 4) * sizeof jobtab
[0]);
721 memcpy(jp
, jobtab
, njobs
* sizeof jp
[0]);
723 /* Relocate `next' pointers and list head */
725 jobmru
= &jp
[jobmru
- jobtab
];
726 for (i
= 0; i
< njobs
; i
++)
727 if (jp
[i
].next
!= NULL
)
728 jp
[i
].next
= &jp
[jp
[i
].next
-
732 bgjob
= &jp
[bgjob
- jobtab
];
733 /* Relocate `ps' pointers */
734 for (i
= 0; i
< njobs
; i
++)
735 if (jp
[i
].ps
== &jobtab
[i
].ps0
)
736 jp
[i
].ps
= &jp
[i
].ps0
;
741 for (i
= 4 ; --i
>= 0 ; jobtab
[njobs
++].used
= 0)
761 jp
->ps
= ckmalloc(nprocs
* sizeof (struct procstat
));
766 TRACE(("makejob(%p, %d) returns %%%td\n", (void *)node
, nprocs
,
773 setcurjob(struct job
*cj
)
775 struct job
*jp
, *prev
;
777 for (prev
= NULL
, jp
= jobmru
; jp
!= NULL
; prev
= jp
, jp
= jp
->next
) {
780 prev
->next
= jp
->next
;
793 deljob(struct job
*j
)
795 struct job
*jp
, *prev
;
797 for (prev
= NULL
, jp
= jobmru
; jp
!= NULL
; prev
= jp
, jp
= jp
->next
) {
800 prev
->next
= jp
->next
;
809 * Return the most recently used job that isn't `nj', and preferably one
813 getcurjob(struct job
*nj
)
817 /* Try to find a stopped one.. */
818 for (jp
= jobmru
; jp
!= NULL
; jp
= jp
->next
)
819 if (jp
->used
&& jp
!= nj
&& jp
->state
== JOBSTOPPED
)
821 /* Otherwise the most recently used job that isn't `nj' */
822 for (jp
= jobmru
; jp
!= NULL
; jp
= jp
->next
)
823 if (jp
->used
&& jp
!= nj
)
832 * Fork of a subshell. If we are doing job control, give the subshell its
833 * own process group. Jp is a job structure that the job is to be added to.
834 * N is the command that will be evaluated by the child. Both jp and n may
835 * be NULL. The mode parameter can be one of the following:
836 * FORK_FG - Fork off a foreground process.
837 * FORK_BG - Fork off a background process.
838 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
839 * process group even if job control is on.
841 * When job control is turned off, background processes have their standard
842 * input redirected to /dev/null (except for the second and later processes
847 forkshell(struct job
*jp
, union node
*n
, int mode
)
852 TRACE(("forkshell(%%%td, %p, %d) called\n", jp
- jobtab
, (void *)n
,
855 if (mode
== FORK_BG
&& (jp
== NULL
|| jp
->nprocs
== 0))
860 TRACE(("Fork failed, errno=%d\n", errno
));
862 error("Cannot fork: %s", strerror(errno
));
869 TRACE(("Child shell %d\n", (int)getpid()));
872 handler
= &main_handler
;
878 jobctl
= 0; /* do job control only in root shell */
879 if (wasroot
&& mode
!= FORK_NOJOB
&& mflag
) {
880 if (jp
== NULL
|| jp
->nprocs
== 0)
883 pgrp
= jp
->ps
[0].pid
;
884 if (setpgid(0, pgrp
) == 0 && mode
== FORK_FG
&&
886 /*** this causes superfluous TIOCSPGRPS ***/
887 if (tcsetpgrp(ttyfd
, pgrp
) < 0)
888 error("tcsetpgrp failed, errno=%d", errno
);
892 } else if (mode
== FORK_BG
) {
895 if ((jp
== NULL
|| jp
->nprocs
== 0) &&
896 ! fd0_redirected_p ()) {
898 if (open(_PATH_DEVNULL
, O_RDONLY
) != 0)
899 error("cannot open %s: %s",
900 _PATH_DEVNULL
, strerror(errno
));
904 if (mode
== FORK_BG
) {
907 if ((jp
== NULL
|| jp
->nprocs
== 0) &&
908 ! fd0_redirected_p ()) {
910 if (open(_PATH_DEVNULL
, O_RDONLY
) != 0)
911 error("cannot open %s: %s",
912 _PATH_DEVNULL
, strerror(errno
));
917 for (i
= njobs
, p
= jobtab
; --i
>= 0 ; p
++)
921 if (wasroot
&& iflag
) {
928 if (rootshell
&& mode
!= FORK_NOJOB
&& mflag
) {
929 if (jp
== NULL
|| jp
->nprocs
== 0)
932 pgrp
= jp
->ps
[0].pid
;
935 if (mode
== FORK_BG
) {
936 if (bgjob
!= NULL
&& bgjob
->state
== JOBDONE
&&
937 !bgjob
->remembered
&& !iflag
)
939 backgndpid
= pid
; /* set $! */
943 struct procstat
*ps
= &jp
->ps
[jp
->nprocs
++];
947 if (iflag
&& rootshell
&& n
)
948 ps
->cmd
= commandtext(n
);
949 jp
->foreground
= mode
== FORK_FG
;
955 TRACE(("In parent shell: child = %d\n", (int)pid
));
961 vforkexecshell(struct job
*jp
, char **argv
, char **envp
, const char *path
, int idx
, int pip
[2])
964 struct jmploc jmploc
;
965 struct jmploc
*savehandler
;
967 TRACE(("vforkexecshell(%%%td, %s, %p) called\n", jp
- jobtab
, argv
[0],
971 savehandler
= handler
;
974 TRACE(("Vfork failed, errno=%d\n", errno
));
976 error("Cannot fork: %s", strerror(errno
));
979 TRACE(("Child shell %d\n", (int)getpid()));
980 if (setjmp(jmploc
.loc
))
981 _exit(exception
== EXEXEC
? exerrno
: 2);
990 shellexec(argv
, envp
, path
, idx
);
992 handler
= savehandler
;
994 struct procstat
*ps
= &jp
->ps
[jp
->nprocs
++];
1004 TRACE(("In parent shell: child = %d\n", (int)pid
));
1010 * Wait for job to finish.
1012 * Under job control we have the problem that while a child process is
1013 * running interrupts generated by the user are sent to the child but not
1014 * to the shell. This means that an infinite loop started by an inter-
1015 * active user may be hard to kill. With job control turned off, an
1016 * interactive user may place an interactive program inside a loop. If
1017 * the interactive program catches interrupts, the user doesn't want
1018 * these interrupts to also abort the loop. The approach we take here
1019 * is to have the shell ignore interrupt signals while waiting for a
1020 * foreground process to terminate, and then send itself an interrupt
1021 * signal if the child process was terminated by an interrupt signal.
1022 * Unfortunately, some programs want to do a bit of cleanup and then
1023 * exit on interrupt; unless these processes terminate themselves by
1024 * sending a signal to themselves (instead of calling exit) they will
1025 * confuse this approach.
1029 waitforjob(struct job
*jp
, int *origstatus
)
1032 int propagate_int
= jp
->jobctl
&& jp
->foreground
;
1038 TRACE(("waitforjob(%%%td) called\n", jp
- jobtab
+ 1));
1039 while (jp
->state
== 0)
1040 if (dowait(DOWAIT_BLOCK
| (Tflag
? DOWAIT_SIG
|
1041 DOWAIT_SIG_TRAP
: 0), jp
) == -1)
1045 if (ttyfd
>= 0 && tcsetpgrp(ttyfd
, rootpid
) < 0)
1046 error("tcsetpgrp failed, errno=%d\n", errno
);
1048 if (jp
->state
== JOBSTOPPED
)
1051 status
= jp
->ps
[jp
->nprocs
- 1].status
;
1052 if (origstatus
!= NULL
)
1053 *origstatus
= status
;
1054 /* convert to 8 bits */
1055 if (WIFEXITED(status
))
1056 st
= WEXITSTATUS(status
);
1058 else if (WIFSTOPPED(status
))
1059 st
= WSTOPSIG(status
) + 128;
1062 st
= WTERMSIG(status
) + 128;
1063 if (! JOBS
|| jp
->state
== JOBDONE
)
1065 if (int_pending()) {
1066 if (!WIFSIGNALED(status
) || WTERMSIG(status
) != SIGINT
)
1070 else if (rootshell
&& propagate_int
&&
1071 WIFSIGNALED(status
) && WTERMSIG(status
) == SIGINT
)
1072 kill(getpid(), SIGINT
);
1080 dummy_handler(int sig __unused
)
1085 * Wait for a process to terminate.
1089 dowait(int mode
, struct job
*job
)
1091 struct sigaction sa
, osa
;
1092 sigset_t mask
, omask
;
1095 struct procstat
*sp
;
1097 struct job
*thisjob
;
1104 int restore_sigchld
;
1106 TRACE(("dowait(%d, %p) called\n", mode
, job
));
1107 restore_sigchld
= 0;
1108 if ((mode
& DOWAIT_SIG
) != 0) {
1110 sigprocmask(SIG_BLOCK
, &mask
, &omask
);
1112 if (!issigchldtrapped()) {
1113 restore_sigchld
= 1;
1114 sa
.sa_handler
= dummy_handler
;
1116 sigemptyset(&sa
.sa_mask
);
1117 sigaction(SIGCHLD
, &sa
, &osa
);
1123 wflags
= WUNTRACED
| WCONTINUED
;
1127 if ((mode
& (DOWAIT_BLOCK
| DOWAIT_SIG
)) != DOWAIT_BLOCK
)
1129 pid
= wait3(&status
, wflags
, (struct rusage
*)NULL
);
1130 TRACE(("wait returns %d, status=%d\n", (int)pid
, status
));
1131 if (pid
== 0 && (mode
& DOWAIT_SIG
) != 0) {
1133 if (((mode
& DOWAIT_SIG_TRAP
) != 0 ?
1134 pendingsig
: pendingsig_waitcmd
) != 0) {
1142 } while (pid
== -1 && errno
== EINTR
);
1143 if (pid
== -1 && errno
== ECHILD
&& job
!= NULL
)
1144 job
->state
= JOBDONE
;
1145 if ((mode
& DOWAIT_SIG
) != 0) {
1146 if (restore_sigchld
)
1147 sigaction(SIGCHLD
, &osa
, NULL
);
1148 sigprocmask(SIG_SETMASK
, &omask
, NULL
);
1155 for (jp
= jobtab
; jp
< jobtab
+ njobs
; jp
++) {
1156 if (jp
->used
&& jp
->nprocs
> 0) {
1159 for (sp
= jp
->ps
; sp
< jp
->ps
+ jp
->nprocs
; sp
++) {
1162 if (sp
->pid
== pid
&& (sp
->status
== -1 ||
1163 WIFSTOPPED(sp
->status
))) {
1164 TRACE(("Changing status of proc %d from 0x%x to 0x%x\n",
1165 (int)pid
, sp
->status
,
1167 if (WIFCONTINUED(status
)) {
1171 sp
->status
= status
;
1174 if (sp
->status
== -1)
1176 else if (WIFSTOPPED(sp
->status
))
1179 if (stopped
) { /* stopped or done */
1180 int state
= done
? JOBDONE
: JOBSTOPPED
;
1181 if (jp
->state
!= state
) {
1182 TRACE(("Job %td: changing state from %d to %d\n", jp
- jobtab
+ 1, jp
->state
, state
));
1185 if (done
&& !jp
->remembered
&&
1186 !iflag
&& jp
!= bgjob
)
1198 if (!thisjob
|| thisjob
->state
== 0)
1200 else if ((!rootshell
|| !iflag
|| thisjob
== job
) &&
1201 thisjob
->foreground
&& thisjob
->state
!= JOBSTOPPED
) {
1204 for (sp
= thisjob
->ps
; sp
< thisjob
->ps
+ thisjob
->nprocs
; sp
++)
1205 if (WIFSIGNALED(sp
->status
)) {
1206 sig
= WTERMSIG(sp
->status
);
1207 coredump
= WCOREDUMP(sp
->status
);
1209 if (sig
> 0 && sig
!= SIGINT
&& sig
!= SIGPIPE
) {
1210 sigstr
= strsignal(sig
);
1214 out2str("Unknown signal");
1216 out2str(" (core dumped)");
1221 TRACE(("Not printing status, rootshell=%d, job=%p\n", rootshell
, job
));
1222 thisjob
->changed
= 1;
1230 * return 1 if there are stopped jobs, otherwise 0
1232 int job_warning
= 0;
1241 for (jobno
= 1, jp
= jobtab
; jobno
<= njobs
; jobno
++, jp
++) {
1244 if (jp
->state
== JOBSTOPPED
) {
1245 out2fmt_flush("You have stopped jobs.\n");
1258 while (njobs
> 0 && dowait(0, NULL
) > 0)
1266 return backgndpid
!= -1;
1273 if (bgjob
!= NULL
&& !forcelocal
)
1274 bgjob
->remembered
= 1;
1279 * Return a string identifying a command (to be printed by the
1283 static char *cmdnextc
;
1284 static int cmdnleft
;
1285 #define MAXCMDTEXT 200
1288 commandtext(union node
*n
)
1292 cmdnextc
= name
= ckmalloc(MAXCMDTEXT
);
1293 cmdnleft
= MAXCMDTEXT
- 4;
1301 cmdtxtdogroup(union node
*n
)
1310 cmdtxtredir(union node
*n
, const char *op
, int deffd
)
1314 if (n
->nfile
.fd
!= deffd
) {
1315 s
[0] = n
->nfile
.fd
+ '0';
1320 if (n
->type
== NTOFD
|| n
->type
== NFROMFD
) {
1321 if (n
->ndup
.dupfd
>= 0)
1322 s
[0] = n
->ndup
.dupfd
+ '0';
1328 cmdtxt(n
->nfile
.fname
);
1334 cmdtxt(union node
*n
)
1337 struct nodelist
*lp
;
1343 cmdtxt(n
->nbinary
.ch1
);
1345 cmdtxt(n
->nbinary
.ch2
);
1348 cmdtxt(n
->nbinary
.ch1
);
1350 cmdtxt(n
->nbinary
.ch2
);
1353 cmdtxt(n
->nbinary
.ch1
);
1355 cmdtxt(n
->nbinary
.ch2
);
1358 for (lp
= n
->npipe
.cmdlist
; lp
; lp
= lp
->next
) {
1366 cmdtxt(n
->nredir
.n
);
1371 cmdtxt(n
->nredir
.n
);
1375 cmdtxt(n
->nif
.test
);
1377 cmdtxt(n
->nif
.ifpart
);
1382 cmdtxt(n
->nbinary
.ch1
);
1383 cmdtxtdogroup(n
->nbinary
.ch2
);
1387 cmdtxt(n
->nbinary
.ch1
);
1388 cmdtxtdogroup(n
->nbinary
.ch2
);
1392 cmdputs(n
->nfor
.var
);
1397 cmdputs(n
->ncase
.expr
->narg
.text
);
1401 cmdputs(n
->narg
.text
);
1406 cmdtxt(n
->nnot
.com
);
1409 for (np
= n
->ncmd
.args
; np
; np
= np
->narg
.next
) {
1414 for (np
= n
->ncmd
.redirect
; np
; np
= np
->nfile
.next
) {
1420 cmdputs(n
->narg
.text
);
1423 cmdtxtredir(n
, ">", 1);
1426 cmdtxtredir(n
, ">>", 1);
1429 cmdtxtredir(n
, ">&", 1);
1432 cmdtxtredir(n
, ">|", 1);
1435 cmdtxtredir(n
, "<", 0);
1438 cmdtxtredir(n
, "<>", 0);
1441 cmdtxtredir(n
, "<&", 0);
1456 cmdputs(const char *s
)
1467 while ((c
= *p
++) != '\0') {
1470 else if (c
== CTLVAR
) {
1475 if ((subtype
& VSTYPE
) == VSLENGTH
&& --cmdnleft
> 0)
1477 } else if (c
== '=' && subtype
!= 0) {
1478 *q
= "}-+?=##%%\0X"[(subtype
& VSTYPE
) - VSNORMAL
];
1483 if (((subtype
& VSTYPE
) == VSTRIMLEFTMAX
||
1484 (subtype
& VSTYPE
) == VSTRIMRIGHTMAX
) &&
1488 } else if (c
== CTLENDVAR
) {
1490 } else if (c
== CTLBACKQ
|| c
== CTLBACKQ
+CTLQUOTE
) {
1500 } else if (c
== CTLARI
) {
1508 } else if (c
== CTLENDARI
) {
1509 if (--cmdnleft
> 0) {
1513 } else if (c
== CTLQUOTEMARK
|| c
== CTLQUOTEEND
)
1514 cmdnleft
++; /* ignore */
1517 if (--cmdnleft
<= 0) {