4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * Job control for UNIX Shell
34 #include <sys/termio.h>
35 #include <sys/types.h>
37 #include <sys/param.h>
44 * one of these for each active job
49 struct job
*j_nxtp
; /* next job in job ID order */
50 struct job
*j_curp
; /* next job in job currency order */
51 struct termios j_stty
; /* termio save area when job stops */
52 pid_t j_pid
; /* job leader's process ID */
53 pid_t j_pgid
; /* job's process group ID */
54 pid_t j_tgid
; /* job's foreground process group ID */
55 uint_t j_jid
; /* job ID */
56 ushort_t j_xval
; /* exit code, or exit or stop signal */
57 ushort_t j_flag
; /* various status flags defined below */
58 char *j_pwd
; /* job's working directory */
59 char *j_cmd
; /* cmd used to invoke this job */
62 /* defines for j_flag */
64 #define J_DUMPED 0001 /* job has core dumped */
65 #define J_NOTIFY 0002 /* job has changed status */
66 #define J_SAVETTY 0004 /* job was stopped in foreground, and its */
67 /* termio settings were saved */
68 #define J_STOPPED 0010 /* job has been stopped */
69 #define J_SIGNALED 0020 /* job has received signal; j_xval has it */
70 #define J_DONE 0040 /* job has finished */
71 #define J_RUNNING 0100 /* job is currently running */
72 #define J_FOREGND 0200 /* job was put in foreground by shell */
74 /* options to the printjob() function defined below */
76 #define PR_CUR 00001 /* print job currency ('+', '-', or ' ') */
77 #define PR_JID 00002 /* print job ID */
78 #define PR_PGID 00004 /* print job's process group ID */
79 #define PR_STAT 00010 /* print status obtained from wait */
80 #define PR_CMD 00020 /* print cmd that invoked job */
81 #define PR_AMP 00040 /* print a '&' if in the background */
82 #define PR_PWD 00100 /* print jobs present working directory */
84 #define PR_DFL (PR_CUR|PR_JID|PR_STAT|PR_CMD) /* default options */
85 #define PR_LONG (PR_DFL|PR_PGID|PR_PWD) /* long options */
87 static struct termios mystty
; /* default termio settings */
89 jobcnt
, /* number of active jobs */
90 jobdone
, /* number of active but finished jobs */
91 jobnote
; /* jobs requiring notification */
92 static pid_t svpgid
, /* saved process group ID */
93 svtgid
; /* saved foreground process group ID */
94 static struct job
*jobcur
, /* active jobs listed in currency order */
97 *joblst
; /* active jobs listed in job ID order */
99 static void printjob(struct job
*, int);
106 for (jp
= joblst
; jp
!= 0 && jp
->j_pid
!= pgid
; jp
= jp
->j_nxtp
)
113 str2job(char *cmd
, char *job
, int mustbejob
)
115 struct job
*jp
, *njp
;
119 jp
= pgid2job(stoi(job
));
120 else if (*++job
== 0 || *job
== '+' || *job
== '%' || *job
== '-') {
122 if (*job
== '-' && jp
)
124 } else if (*job
>= '0' && *job
<= '9') {
126 for (jp
= joblst
; jp
&& jp
->j_jid
!= i
; jp
= jp
->j_nxtp
)
128 } else if (*job
== '?') {
133 for (njp
= jobcur
; njp
; njp
= njp
->j_curp
) {
136 for (p
= njp
->j_cmd
, j
= strlen(p
); j
>= i
; p
++, j
--) {
137 if (strncmp(job
, p
, i
) == 0) {
139 failed((unsigned char *)cmd
,
149 for (njp
= jobcur
; njp
; njp
= njp
->j_curp
) {
152 if (strncmp(job
, njp
->j_cmd
, i
) == 0) {
154 failed((unsigned char *)cmd
, ambiguous
);
160 if (mustbejob
&& (jp
== 0 || jp
->j_jid
== 0))
161 failed((unsigned char *)cmd
, nosuchjob
);
167 freejob(struct job
*jp
)
172 for (njp
= &joblst
; *njp
!= jp
; njp
= &(*njp
)->j_nxtp
)
175 for (cjp
= &jobcur
; *cjp
!= jp
; cjp
= &(*cjp
)->j_curp
)
186 * Collect the foreground job.
187 * Used in the case where the subshell wants
188 * to exit, but needs to wait until the fg job
198 for (jp
= joblst
; jp
; jp
= jp
->j_nxtp
)
199 if (jp
->j_flag
& J_FOREGND
)
203 /* no foreground job */
207 * Wait on fg job until wait succeeds
208 * or it fails due to no waitable children.
213 pid
= waitpid(jp
->j_pid
, &stat
, 0);
214 if (pid
== jp
->j_pid
|| (pid
== -1 && errno
== ECHILD
))
220 * analyze the status of a job
224 statjob(struct job
*jp
, int stat
, int fg
, int rc
)
229 if (WIFCONTINUED(stat
)) {
230 if (jp
->j_flag
& J_STOPPED
) {
231 jp
->j_flag
&= ~(J_STOPPED
|J_SIGNALED
|J_SAVETTY
);
232 jp
->j_flag
|= J_RUNNING
;
233 if (!fg
&& jp
->j_jid
) {
234 jp
->j_flag
|= J_NOTIFY
;
238 } else if (WIFSTOPPED(stat
)) {
239 jp
->j_xval
= WSTOPSIG(stat
);
240 jp
->j_flag
&= ~J_RUNNING
;
241 jp
->j_flag
|= (J_SIGNALED
|J_STOPPED
);
242 jp
->j_pgid
= getpgid(jp
->j_pid
);
243 jp
->j_tgid
= jp
->j_pgid
;
245 if (tgid
= settgid(mypgid
, jp
->j_pgid
))
248 jp
->j_flag
|= J_SAVETTY
;
249 tcgetattr(0, &jp
->j_stty
);
250 (void) tcsetattr(0, TCSANOW
, &mystty
);
254 jp
->j_flag
|= J_NOTIFY
;
258 jp
->j_flag
&= ~J_RUNNING
;
259 jp
->j_flag
|= J_DONE
;
262 if (WIFSIGNALED(stat
)) {
263 jp
->j_xval
= WTERMSIG(stat
);
264 jp
->j_flag
|= J_SIGNALED
;
266 jp
->j_flag
|= J_DUMPED
;
267 if (!fg
|| jp
->j_xval
!= SIGINT
) {
268 jp
->j_flag
|= J_NOTIFY
;
271 } else { /* WIFEXITED */
272 jp
->j_xval
= WEXITSTATUS(stat
);
273 jp
->j_flag
&= ~J_SIGNALED
;
274 if (!fg
&& jp
->j_jid
) {
275 jp
->j_flag
|= J_NOTIFY
;
280 if (!settgid(mypgid
, jp
->j_pgid
) ||
281 !settgid(mypgid
, getpgid(jp
->j_pid
)))
282 tcgetattr(0, &mystty
);
286 exitval
= jp
->j_xval
;
287 if (jp
->j_flag
& J_SIGNALED
)
291 if (done
&& !(jp
->j_flag
& J_NOTIFY
))
297 * collect the status of jobs that have recently exited or stopped -
298 * if wnohang == WNOHANG, wait until error, or all jobs are accounted for;
300 * called after each command is executed, with wnohang == 0, and as part
301 * of "wait" builtin with wnohang == WNOHANG
303 * We do not need to call chktrap here if waitpid(2) is called with
304 * wnohang == 0, because that only happens from syswait() which is called
305 * from builtin() where chktrap() is already called.
316 if ((flags
& (monitorflg
|jcflg
|jcoff
)) == (monitorflg
|jcflg
))
317 wflags
= WUNTRACED
|WCONTINUED
;
321 for (n
= jobcnt
- jobdone
; n
> 0; n
--) {
322 if ((pid
= waitpid(-1, &stat
, wnohang
|wflags
)) <= 0)
324 if (jp
= pgid2job(pid
))
325 (void) statjob(jp
, stat
, 0, 0);
335 collectjobs(WNOHANG
);
338 int savefd
= setb(2);
339 for (jp
= joblst
; jp
; jp
= jp
->j_nxtp
) {
340 if (jp
->j_flag
& J_NOTIFY
) {
342 printjob(jp
, PR_DFL
);
343 else if (jp
->j_flag
& J_FOREGND
)
344 printjob(jp
, PR_STAT
);
346 printjob(jp
, PR_STAT
|PR_PGID
);
353 for (jp
= joblst
; jp
; jp
= jp
->j_nxtp
) {
354 if (jp
->j_flag
& J_DONE
)
361 waitjob(struct job
*jp
)
365 pid_t pid
= jp
->j_pid
;
370 if ((flags
& (monitorflg
|jcflg
|jcoff
)) == (monitorflg
|jcflg
))
376 ret
= waitpid(pid
, &stat
, wflags
|WNOWAIT
);
378 if (ret
== -1 && err
== ECHILD
) {
382 } while (ret
!= pid
);
384 done
= statjob(jp
, stat
, 1, 1);
385 waitpid(pid
, 0, wflags
);
386 if (done
&& exitval
&& (flags
& errflg
))
392 * modify the foreground process group to *new* only if the
393 * current foreground process group is equal to *expected*
397 settgid(new, expected
)
400 pid_t current
= tcgetpgrp(0);
402 if (current
!= expected
)
412 restartjob(struct job
*jp
, int fg
)
417 for (t
= jobcur
; t
->j_curp
!= jp
; t
= t
->j_curp
)
419 t
->j_curp
= jp
->j_curp
;
424 if (jp
->j_flag
& J_SAVETTY
) {
425 jp
->j_stty
.c_lflag
&= ~TOSTOP
;
426 jp
->j_stty
.c_lflag
|= (mystty
.c_lflag
&TOSTOP
);
427 jp
->j_stty
.c_cc
[VSUSP
] = mystty
.c_cc
[VSUSP
];
428 jp
->j_stty
.c_cc
[VDSUSP
] = mystty
.c_cc
[VDSUSP
];
429 (void) tcsetattr(0, TCSADRAIN
, &jp
->j_stty
);
431 (void) settgid(jp
->j_tgid
, mypgid
);
433 (void) kill(-(jp
->j_pgid
), SIGCONT
);
434 if (jp
->j_tgid
!= jp
->j_pgid
)
435 (void) kill(-(jp
->j_tgid
), SIGCONT
);
436 jp
->j_flag
&= ~(J_STOPPED
|J_SIGNALED
|J_SAVETTY
);
437 jp
->j_flag
|= J_RUNNING
;
439 jp
->j_flag
|= J_FOREGND
;
440 printjob(jp
, PR_JID
|PR_CMD
);
443 jp
->j_flag
&= ~J_FOREGND
;
444 printjob(jp
, PR_JID
|PR_CMD
|PR_AMP
);
449 printjob(struct job
*jp
, int propts
)
453 if (jp
->j_flag
& J_NOTIFY
) {
455 jp
->j_flag
&= ~J_NOTIFY
;
458 if (propts
& PR_JID
) {
465 if (propts
& PR_CUR
) {
471 else if (jobcur
!= 0 && jobcur
->j_curp
== jp
)
477 if (propts
& PR_PGID
) {
484 if (propts
& PR_STAT
) {
489 if (jp
->j_flag
& J_SIGNALED
) {
490 char *sigstr
, *strsignal();
491 if ((sigstr
= strsignal(jp
->j_xval
)) != NULL
) {
492 sp
-= strlen(sigstr
);
496 gmsg
= gettext(signalnum
);
497 sp
-= strlen(numbuf
) + strlen(gmsg
);
498 prs_buff((unsigned char *)gmsg
);
501 if (jp
->j_flag
& J_DUMPED
) {
502 gmsg
= gettext(coredump
);
504 prs_buff((unsigned char *)gmsg
);
506 } else if (jp
->j_flag
& J_DONE
) {
508 gmsg
= gettext(exited
);
509 sp
-= strlen(gmsg
) + strlen(numbuf
) + 2;
510 prs_buff((unsigned char *)gmsg
);
516 gmsg
= gettext(running
);
518 prs_buff((unsigned char *)gmsg
);
524 if (propts
& PR_CMD
) {
531 if (propts
& PR_AMP
) {
538 if (propts
& PR_PWD
) {
553 * called to initialize job control for each new input file to the shell,
554 * and after the "exec" builtin
562 if (tcgetattr(0, &mystty
) == -1 || (svtgid
= tcgetpgrp(0)) == -1) {
569 handle(SIGTTOU
, SIG_IGN
);
570 handle(SIGTSTP
, SIG_DFL
);
572 if (mysid
!= mypgid
) {
575 (void) settgid(mypgid
, svpgid
);
584 if ((flags
& (jcoff
|jcflg
)) != jcflg
)
587 if (check_if
&& jobcnt
&& eofflg
++ == 0) {
589 if (check_if
& JOB_STOPPED
) {
590 for (jp
= joblst
; jp
; jp
= jp
->j_nxtp
) {
591 if (jp
->j_jid
&& (jp
->j_flag
& J_STOPPED
)) {
592 prs(_gettext(jobsstopped
));
598 if (check_if
& JOB_RUNNING
) {
599 for (jp
= joblst
; jp
; jp
= jp
->j_nxtp
) {
600 if (jp
->j_jid
&& (jp
->j_flag
& J_RUNNING
)) {
601 prs(_gettext(jobsrunning
));
609 if (svpgid
!= mypgid
) {
610 (void) settgid(svtgid
, mypgid
);
619 * called by the shell to reserve a job slot for a job about to be spawned
630 allocjob(char *cmd
, uchar_t
*cwd
, int monitor
)
632 struct job
*jp
, **jpp
;
633 int jid
, cmdlen
, cwdlen
;
635 cmdlen
= strlen(cmd
) + 1;
636 if (cmd
[cmdlen
-2] == '&') {
640 cwdlen
= strlen(cwd
) + 1;
641 jp
= (struct job
*) alloc(sizeof (struct job
) + cmdlen
+ cwdlen
);
645 jp
->j_cmd
= ((char *)jp
) + sizeof (struct job
);
646 strcpy(jp
->j_cmd
, cmd
);
647 jp
->j_pwd
= jp
->j_cmd
+ cmdlen
;
648 strcpy(jp
->j_pwd
, cwd
);
653 for (; *jpp
; jpp
= &(*jpp
)->j_nxtp
)
654 if ((*jpp
)->j_jid
!= 0)
656 for (jid
= 1; *jpp
; jpp
= &(*jpp
)->j_nxtp
, jid
++)
657 if ((*jpp
)->j_jid
!= jid
)
670 struct job
*jp
, *sjp
;
672 for (jp
= joblst
; jp
; jp
= sjp
) {
684 makejob(int monitor
, int fg
)
691 handle(SIGTTOU
, SIG_DFL
);
692 handle(SIGTSTP
, SIG_DFL
);
697 handle(SIGTTIN
, SIG_IGN
);
698 handle(SIGINT
, SIG_IGN
);
699 handle(SIGQUIT
, SIG_IGN
);
701 renamef(chkopen(devnull
, 0), 0);
706 * called by the shell after job has been spawned, to fill in the
707 * job slot, and wait for the job if in the foreground
718 thisjob
->j_nxtp
= *nextjob
;
720 thisjob
->j_curp
= jobcur
;
723 if (thisjob
->j_jid
) {
724 thisjob
->j_pgid
= pid
;
725 propts
= PR_JID
|PR_PGID
;
727 thisjob
->j_pgid
= mypgid
;
731 thisjob
->j_flag
= J_RUNNING
;
732 thisjob
->j_tgid
= thisjob
->j_pgid
;
733 thisjob
->j_pid
= pid
;
737 thisjob
->j_flag
|= J_FOREGND
;
741 printjob(thisjob
, propts
);
742 assnum(&pcsadr
, (long)pid
);
747 * the builtin "jobs" command
758 extern int opterr
, i
;
759 int savoptind
= optind
;
761 int savopterr
= opterr
;
763 char *savoptarg
= optarg
;
769 if ((flags
& jcflg
) == 0)
770 failed((unsigned char *)cmd
, nojc
);
772 while ((c
= getopt(argc
, argv
, "lpx")) != -1) {
774 gfailure(usage
, jobsuse
);
788 gfailure(usage
, jobsuse
);
805 unsigned char *savebp
;
806 for (savebp
= bp
= locstak(); loptind
< argc
; loptind
++) {
809 jp
= str2job(cmd
, cp
, 1);
827 collectjobs(WNOHANG
);
832 if (loptind
== argc
) {
833 for (jp
= joblst
; jp
; jp
= jp
->j_nxtp
) {
835 printjob(jp
, propts
);
838 printjob(str2job(cmd
, argv
[loptind
++], 1), propts
);
839 while (loptind
< argc
);
844 * the builtin "fg" and "bg" commands
847 sysfgbg(int argc
, char *argv
[])
852 if ((flags
& jcflg
) == 0)
853 failed((unsigned char *)cmd
, nojc
);
859 for (jp
= jobcur
; ; jp
= jp
->j_curp
) {
861 failed((unsigned char *)cmd
, nocurjob
);
868 restartjob(str2job(cmd
, *argv
, 1), fg
);
874 * the builtin "wait" commands
887 if ((flags
& (monitorflg
|jcflg
|jcoff
)) == (monitorflg
|jcflg
))
894 else while (--argc
) {
895 if ((jp
= str2job(cmd
, *++argv
, 0)) == 0)
897 if (!(jp
->j_flag
& J_RUNNING
))
899 if (waitpid(jp
->j_pid
, &stat
, wflags
) <= 0)
901 (void) statjob(jp
, stat
, 0, 1);
906 sigv(char *cmd
, int sig
, char *args
)
914 jp
= str2job(cmd
, args
, 1);
924 if (*args
< '0' || *args
> '9') {
928 id
= (id
* 10) + (*args
- '0');
936 if (sig
== SIGSTOP
) {
937 if (id
== mysid
|| id
== mypid
&& mypgid
== mysid
) {
938 failure(cmd
, loginsh
);
941 if (id
== mypgid
&& mypgid
!= svpgid
) {
942 (void) settgid(svtgid
, mypgid
);
951 if (kill(id
, sig
) < 0) {
955 failure(cmd
, eacces
);
959 failure(cmd
, badsig
);
964 failure(cmd
, nosuchpgid
);
966 failure(cmd
, nosuchpid
);
970 } else if (sig
== SIGTERM
&& pgrp
)
971 (void) kill(id
, SIGCONT
);
975 (void) settgid(mypgid
, svpgid
);
981 sysstop(int argc
, char *argv
[])
985 gfailure(usage
, stopuse
);
989 sigv(cmd
, SIGSTOP
, *argv
);
993 syskill(int argc
, char *argv
[])
999 gfailure(usage
, killuse
);
1003 if (argv
[1][0] == '-') {
1012 if (!eq(argv
[1], "-l")) {
1013 gfailure(usage
, killuse
);
1017 for (i
= 1; i
< MAXTRAP
; i
++) {
1018 if (sig2str(i
, buf
) < 0)
1023 if ((flags
& ttyflg
) && (++cnt
% 10))
1032 if (str2sig(&argv
[1][1], &sig
)) {
1033 failure(cmd
, badsig
);
1040 sigv(cmd
, sig
, *argv
);
1045 syssusp(int argc
, char *argv
[])
1048 failed((unsigned char *)argv
[0], badopt
);
1049 sigv(argv
[0], SIGSTOP
, "0");
1057 (void) sighold(SIGCHLD
);
1058 for (jp
= joblst
; jp
!= NULL
; jp
= jp
->j_nxtp
) {
1059 if (jp
->j_flag
& J_FOREGND
) {
1060 (void) kill(jp
->j_pid
, SIGHUP
);
1064 (void) sigrelse(SIGCHLD
);