2 * Copyright 2006 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"
24 * C Shell - functions that manage processes, handling hanging, termination
27 #define BIGINDEX 9 /* largest desirable job index */
29 void pjwait(struct process
*);
30 void pflush(struct process
*);
31 void pclrcurr(struct process
*);
32 void padd(struct command
*);
34 void ptprint(struct process
*);
35 void pkill(tchar
**, int);
36 void pstart(struct process
*, int);
38 struct process
*pgetcurr(struct process
*);
39 struct process
*pfind(tchar
*);
42 * pchild - called at interrupt level by the SIGCHLD signal
43 * indicating that at least one child has terminated or stopped
44 * thus at least one wait system call will definitely return a
45 * childs status. Top level routines (like pwait) must be sure
46 * to mask interrupts when playing with the proclist data structures!
59 tprintf("TRACE- pchile()\n");
62 pid
= csh_wait3(&w
, (setintr
? WNOHANG
|WUNTRACED
:WNOHANG
), &ru
);
64 * SysV sends a SIGCHLD when the child process
65 * receives a SIGCONT, and result of that action is ignored here
67 if (w
.w_status
== WCONTFLG
)
74 pnoprocesses
= pid
== -1;
77 for (pp
= proclist
.p_next
; pp
!= PNULL
; pp
= pp
->p_next
)
82 if (pid
== atoi_(value(S_child
/* "child" */)))
83 unsetv(S_child
/* "child" */);
84 pp
->p_flags
&= ~(PRUNNING
|PSTOPPED
|PREPORTED
);
86 pp
->p_flags
|= PSTOPPED
;
87 pp
->p_reason
= w
.w_stopsig
;
89 if (pp
->p_flags
& (PTIME
|PPTIME
) || adrof(S_time
/* "time" */))
90 (void) gettimeofday(&pp
->p_etime
, (struct timezone
*)0);
93 if (w
.w_termsig
== SIGINT
)
94 pp
->p_flags
|= PINTERRUPTED
;
96 pp
->p_flags
|= PSIGNALED
;
98 pp
->p_flags
|= PDUMPED
;
99 pp
->p_reason
= w
.w_termsig
;
101 pp
->p_reason
= w
.w_retcode
;
102 if (pp
->p_reason
!= 0)
103 pp
->p_flags
|= PAEXITED
;
105 pp
->p_flags
|= PNEXITED
;
111 if ((fp
->p_flags
& (PPTIME
|PRUNNING
|PSTOPPED
)) == 0 &&
112 !child
&& adrof(S_time
/* "time" */) &&
113 fp
->p_rusage
.ru_utime
.tv_sec
+fp
->p_rusage
.ru_stime
.tv_sec
>=
114 atoi_(value(S_time
/* "time" */)))
115 fp
->p_flags
|= PTIME
;
116 jobflags
|= fp
->p_flags
;
117 } while ((fp
= fp
->p_friends
) != pp
);
118 pp
->p_flags
&= ~PFOREGND
;
119 if (pp
== pp
->p_friends
&& (pp
->p_flags
& PPTIME
)) {
120 pp
->p_flags
&= ~PPTIME
;
121 pp
->p_flags
|= PTIME
;
123 if ((jobflags
& (PRUNNING
|PREPORTED
)) == 0) {
126 if (fp
->p_flags
&PSTOPPED
)
127 fp
->p_flags
|= PREPORTED
;
128 } while ((fp
= fp
->p_friends
) != pp
);
129 while (fp
->p_pid
!= fp
->p_jobid
)
131 if (jobflags
&PSTOPPED
) {
132 if (pcurrent
&& pcurrent
!= fp
)
133 pprevious
= pcurrent
;
137 if (jobflags
&PFOREGND
) {
138 if (jobflags
& (PSIGNALED
|PSTOPPED
|PPTIME
) ||
140 jobflags
& PAEXITED
||
142 !eq(dcwd
->di_name
, fp
->p_cwd
->di_name
)) {
143 ; /* print in pjwait */
146 if (jobflags
&PNOTIFY
|| adrof(S_notify
/* "notify" */)) {
147 write_string("\015\n");
149 (void) pprint(pp
, NUMBER
|NAME
|REASON
);
150 if ((jobflags
&PSTOPPED
) == 0)
153 fp
->p_flags
|= PNEEDNOTE
;
168 tprintf("TRACE- pnote()\n");
171 for (pp
= proclist
.p_next
; pp
!= PNULL
; pp
= pp
->p_next
) {
172 if (pp
->p_flags
& PNEEDNOTE
) {
173 omask
= sigblock(sigmask(SIGCHLD
));
174 pp
->p_flags
&= ~PNEEDNOTE
;
175 flags
= pprint(pp
, NUMBER
|NAME
|REASON
);
176 if ((flags
&(PRUNNING
|PSTOPPED
)) == 0)
178 (void) sigsetmask(omask
);
184 * pwait - wait for current job to terminate, maintaining integrity
185 * of current and previous job indicators.
190 struct process
*fp
, *pp
;
194 tprintf("TRACE- pwait()\n");
197 * Here's where dead procs get flushed.
199 omask
= sigblock(sigmask(SIGCHLD
));
200 for (pp
= (fp
= &proclist
)->p_next
; pp
!= PNULL
; pp
= (fp
= pp
)->p_next
)
201 if (pp
->p_pid
== 0) {
202 fp
->p_next
= pp
->p_next
;
203 xfree(pp
->p_command
);
204 if (pp
->p_cwd
&& --pp
->p_cwd
->di_count
== 0)
205 if (pp
->p_cwd
->di_next
== 0)
210 (void) sigsetmask(omask
);
215 * pjwait - wait for a job to finish or become stopped
216 * It is assumed to be in the foreground state (PFOREGND)
219 pjwait(struct process
*pp
)
222 int jobflags
, reason
, omask
;
225 tprintf("TRACE- pjwait()\n");
227 while (pp
->p_pid
!= pp
->p_jobid
)
231 if ((fp
->p_flags
&(PFOREGND
|PRUNNING
)) == PRUNNING
)
232 printf("BUG: waiting for background job!\n");
233 } while ((fp
= fp
->p_friends
) != pp
);
235 * Now keep pausing as long as we are not interrupted (SIGINT),
236 * and the target process, or any of its friends, are running
239 omask
= sigblock(sigmask(SIGCHLD
));
243 jobflags
|= fp
->p_flags
;
244 while ((fp
= (fp
->p_friends
)) != pp
);
245 if ((jobflags
& PRUNNING
) == 0)
248 * At this point, csh used to call:
249 * sigpause(sigblock(0) &~ sigmask(SIGCHLD));
250 * expecting to receive a SIGCHLD signal from the
251 * termination of the child and to invoke the
252 * signal handler, pchild(), as a result.
254 * However, vfork() now causes a vfork()'d child to
255 * have all of its active signal handlers reset to
256 * SIG_DFL, to forstall parent memory corruption due
257 * to race conditions with signal handling.
259 * If this instance of csh is itself a child of vfork(),
260 * which can happen when the top-level csh performs a
261 * command substitution inside an i/o redirection, like:
262 * /bin/echo foo >`/bin/echo trash`
263 * then we will never receive SIGCHLD. To accommodate
264 * this, we wait until one of our children terminates
265 * (without actually reaping the child) and call the
266 * SIGCHLD signal handler (pchild()) directly.
268 if (csh_wait_noreap() > 0)
269 pchild(); /* simulate receipt of SIGCHLD */
271 (void) sigsetmask(omask
);
272 if (tpgrp
> 0) /* get tty back */
273 (void) ioctl(FSHTTY
, TIOCSPGRP
, (char *)&tpgrp
);
274 if ((jobflags
&(PSIGNALED
|PSTOPPED
|PTIME
)) ||
275 !eq(dcwd
->di_name
, fp
->p_cwd
->di_name
)) {
276 if (jobflags
&PSTOPPED
)
278 (void) pprint(pp
, AREASON
|SHELLDIR
);
280 if ((jobflags
&(PINTERRUPTED
|PSTOPPED
)) && setintr
&&
281 (!gointr
|| !eq(gointr
, S_MINUS
/* "-" */))) {
282 if ((jobflags
& PSTOPPED
) == 0)
291 reason
= fp
->p_flags
& (PSIGNALED
|PINTERRUPTED
) ?
292 fp
->p_reason
| ABN_TERM
: fp
->p_reason
;
293 } while ((fp
= fp
->p_friends
) != pp
);
294 set(S_status
/* "status" */, putn(reason
));
295 if (reason
&& exiterr
)
301 * dowait - wait for all processes to finish
310 tprintf("TRACE- dowait()\n");
313 omask
= sigblock(sigmask(SIGCHLD
));
315 for (pp
= proclist
.p_next
; pp
; pp
= pp
->p_next
)
316 if (pp
->p_pid
&& /* pp->p_pid == pp->p_jobid && */
317 pp
->p_flags
&PRUNNING
) {
321 (void) sigsetmask(omask
);
326 * pflushall - flush all jobs from list (e.g. at fork())
334 tprintf("TRACE- pflush()\n");
336 for (pp
= proclist
.p_next
; pp
!= PNULL
; pp
= pp
->p_next
)
342 * pflush - flag all process structures in the same job as the
343 * the argument process for deletion. The actual free of the
344 * space is not done here since pflush is called at interrupt level.
347 pflush(struct process
*pp
)
353 tprintf("TRACE- pflush()\n");
355 if (pp
->p_pid
== 0) {
356 printf("BUG: process flushed twice");
359 while (pp
->p_pid
!= pp
->p_jobid
)
367 np
->p_index
= np
->p_pid
= 0;
368 np
->p_flags
&= ~PNEEDNOTE
;
369 } while ((np
= np
->p_friends
) != pp
);
370 if (index
== pmaxindex
) {
371 for (np
= proclist
.p_next
, index
= 0; np
; np
= np
->p_next
)
372 if (np
->p_index
> (tchar
)index
)
379 * pclrcurr - make sure the given job is not the current or previous job;
380 * pp MUST be the job leader
383 pclrcurr(struct process
*pp
)
387 tprintf("TRACE- pclrcurr()\n");
390 if (pprevious
!= PNULL
) {
391 pcurrent
= pprevious
;
392 pprevious
= pgetcurr(pp
);
394 pcurrent
= pgetcurr(pp
);
395 pprevious
= pgetcurr(pp
);
397 else if (pp
== pprevious
)
398 pprevious
= pgetcurr(pp
);
401 /* +4 here is 1 for '\0', 1 ea for << >& >> */
402 tchar command
[PMAXLEN
+4];
406 * palloc - allocate a process structure and fill it up.
407 * an important assumption is made that the process is running.
410 palloc(int pid
, struct command
*t
)
416 tprintf("TRACE- palloc()\n");
418 pp
= (struct process
*)xcalloc(1, sizeof (struct process
));
420 pp
->p_flags
= t
->t_dflg
& FAND
? PRUNNING
: PRUNNING
|PFOREGND
;
421 if (t
->t_dflg
& FTIME
)
422 pp
->p_flags
|= PPTIME
;
427 if (t
->t_dflg
& FPOU
) {
429 if (t
->t_dflg
& FDIAG
)
430 pp
->p_flags
|= PDIAG
;
432 pp
->p_command
= savestr(command
);
435 /* careful here with interrupt level */
437 pp
->p_index
= pcurrjob
->p_index
;
438 pp
->p_friends
= pcurrjob
;
439 pp
->p_jobid
= pcurrjob
->p_pid
;
440 for (fp
= pcurrjob
; fp
->p_friends
!= pcurrjob
; fp
= fp
->p_friends
)
449 if (pmaxindex
< BIGINDEX
)
450 pp
->p_index
= ++pmaxindex
;
455 for (np
= proclist
.p_next
; np
; np
= np
->p_next
)
456 if (np
->p_index
== i
)
465 pprevious
= pcurrent
;
468 pp
->p_next
= proclist
.p_next
;
469 proclist
.p_next
= pp
;
470 (void) gettimeofday(&pp
->p_btime
, (struct timezone
*)0);
474 padd(struct command
*t
)
479 tprintf("TRACE- padd()\n");
486 pads(S_LBRASP
/* "( " */);
488 pads(S_SPRBRA
/* " )" */);
492 for (argp
= t
->t_dcom
; *argp
; argp
++) {
495 pads(S_SP
/* " " */);
506 pads(S_SPBARBARSP
/* " || " */);
509 pads(S_SPANDANDSP
/* " && " */);
512 pads(S_SPBARSP
/* " | " */);
515 pads(S_SEMICOLONSP
/* "; " */);
521 if ((t
->t_dflg
& FPIN
) == 0 && t
->t_dlef
) {
522 pads((t
->t_dflg
& FHERE
) ? S_SPLESLESSP
/* " << " */ : S_SPLESSP
/* " < " */);
525 if ((t
->t_dflg
& FPOU
) == 0 && t
->t_drit
) {
526 pads((t
->t_dflg
& FCAT
) ? S_SPGTRGTRSP
/* " >>" */ : S_SPGTR
/* " >" */);
527 if (t
->t_dflg
& FDIAG
)
528 pads(S_AND
/* "&" */);
529 pads(S_SP
/* " " */);
540 tprintf("TRACE- pads()\n");
542 if (cmdlen
>= PMAXLEN
)
544 if (cmdlen
+ i
>= PMAXLEN
) {
545 (void) strcpy_(cmdp
, S_SPPPP
/* " ..." */);
550 (void) strcpy_(cmdp
, cp
);
556 * psavejob - temporarily save the current job on a one level stack
557 * so another job can be created. Used for { } in exp6
558 * and `` in globbing.
565 tprintf("TRACE- psavejob()\n");
572 * prestjob - opposite of psavejob. This may be missed if we are interrupted
573 * somewhere, but pendjob cleans up anyway.
580 tprintf("TRACE- prestjob()\n");
587 * pendjob - indicate that a job (set of commands) has been completed
588 * or is about to begin.
593 struct process
*pp
, *tp
;
596 tprintf("TRACE- pendjob()\n");
598 if (pcurrjob
&& (pcurrjob
->p_flags
&(PFOREGND
|PSTOPPED
)) == 0) {
600 while (pp
->p_pid
!= pp
->p_jobid
)
602 printf("[%d]", pp
->p_index
);
605 printf(" %d", pp
->p_pid
);
610 pholdjob
= pcurrjob
= 0;
614 * pprint - print a job
617 pprint(struct process
*pp
, int flag
)
621 extern char *linp
, linbuf
[];
622 int jobflags
, pstatus
;
626 tprintf("TRACE- pprint()\n");
628 while (pp
->p_pid
!= pp
->p_jobid
)
630 if (pp
== pp
->p_friends
&& (pp
->p_flags
& PPTIME
)) {
631 pp
->p_flags
&= ~PPTIME
;
632 pp
->p_flags
|= PTIME
;
635 status
= reason
= -1;
638 jobflags
|= pp
->p_flags
;
639 pstatus
= pp
->p_flags
& PALLSTATES
;
640 if (tp
!= pp
&& linp
!= linbuf
&& !(flag
&FANCY
) &&
641 (pstatus
== status
&& pp
->p_reason
== reason
||
645 if (tp
!= pp
&& linp
!= linbuf
)
649 printf("[%d]%s %c ", pp
->p_index
,
650 pp
->p_index
< 10 ? " " : "",
651 pp
== pcurrent
? '+' :
652 (pp
== pprevious
? (tchar
) '-'
657 printf("%5d ", pp
->p_pid
);
658 if (flag
&(REASON
|AREASON
)) {
663 if (pstatus
== status
)
664 if (pp
->p_reason
== reason
) {
668 reason
= pp
->p_reason
;
671 reason
= pp
->p_reason
;
676 printf(format
, "Running ");
682 if ((flag
&(REASON
|AREASON
))
684 && reason
!= SIGPIPE
)
686 strsignal(pp
->p_reason
));
693 printf("Exit %-16d", pp
->p_reason
);
695 printf(format
, "Done");
699 printf("BUG: status=%-9o", status
);
705 printf("%t", pp
->p_command
);
706 if (pp
->p_flags
& PPOU
)
708 if (pp
->p_flags
& PDIAG
)
711 if (flag
&(REASON
|AREASON
) && pp
->p_flags
&PDUMPED
)
712 printf(" (core dumped)");
713 if (tp
== pp
->p_friends
) {
717 !eq(tp
->p_cwd
->di_name
, dcwd
->di_name
)) {
719 dtildepr(value(S_home
/* "home" */), tp
->p_cwd
->di_name
);
723 if (pp
->p_flags
&PPTIME
&& !(status
&(PSTOPPED
|PRUNNING
))) {
726 { static struct rusage zru
;
727 prusage(&zru
, &pp
->p_rusage
, &pp
->p_etime
,
731 if (tp
== pp
->p_friends
) {
734 if (flag
&SHELLDIR
&& !eq(tp
->p_cwd
->di_name
, dcwd
->di_name
)) {
736 dtildepr(value(S_home
/* "home" */), dcwd
->di_name
);
740 } while ((pp
= pp
->p_friends
) != tp
);
741 if (jobflags
&PTIME
&& (jobflags
&(PSTOPPED
|PRUNNING
)) == 0) {
742 if (jobflags
& NUMBER
)
750 ptprint(struct process
*tp
)
752 struct timeval tetime
, diff
;
753 static struct timeval ztime
;
755 static struct rusage zru
;
756 struct process
*pp
= tp
;
759 tprintf("TRACE- ptprint()\n");
764 ruadd(&ru
, &pp
->p_rusage
);
765 tvsub(&diff
, &pp
->p_etime
, &pp
->p_btime
);
766 if (timercmp(&diff
, &tetime
, >))
768 } while ((pp
= pp
->p_friends
) != tp
);
769 prusage(&zru
, &ru
, &tetime
, &ztime
);
773 * dojobs - print all jobs
779 int flag
= NUMBER
|NAME
|REASON
;
783 tprintf("TRACE- dojobs()\n");
788 if (v
[1] || !eq(*v
, S_DASHl
/* "-l" */))
789 error("Usage: jobs [ -l ]");
790 flag
|= FANCY
|JOBDIR
;
792 for (i
= 1; i
<= pmaxindex
; i
++)
793 for (pp
= proclist
.p_next
; pp
; pp
= pp
->p_next
)
794 if (pp
->p_index
== i
&& pp
->p_pid
== pp
->p_jobid
) {
795 pp
->p_flags
&= ~PNEEDNOTE
;
796 if (!(pprint(pp
, flag
) & (PRUNNING
|PSTOPPED
)))
803 * dofg - builtin - put the job into the foreground
811 tprintf("TRACE- dofg()\n");
819 } while (*v
&& *++v
);
823 * %... - builtin - put the job into the foreground
831 tprintf("TRACE- untty()\n");
840 * dobg - builtin - put the job into the background
848 tprintf("TRACE- dobg()\n");
855 } while (*v
&& *++v
);
859 * %... & - builtin - put the job into the background
867 tprintf("TRACE- dobg1()\n");
874 * dostop - builtin - stop the job
881 tprintf("TRACE- dostop()\n");
887 * dokill - builtin - superset of kill (1)
896 tprintf("TRACE- dokill()\n");
899 if (v
[0] && v
[0][0] == '-') {
900 if (v
[0][1] == 'l') {
901 for (signum
= 1; signum
<= NSIG
-1; signum
++) {
903 if (sig2str(signum
, sbuf
) == 0)
911 if (digit(v
[0][1])) {
912 if (chkalldigit_(v
[0]+1) != 0) {
914 bferr("Unknown signal; kill -l lists signals");
916 signum
= atoi_(v
[0]+1);
917 if (signum
< 0 || signum
> NSIG
)
918 bferr("Bad signal number");
924 if (str2sig(sbuf
, &signo
) == 0) {
928 if (eq(name
, S_IOT
/* "IOT" */)) {
933 bferr("Unknown signal; kill -l lists signals");
943 pkill(tchar
**v
, int signum
)
945 struct process
*pp
, *np
;
947 int omask
, pid
, err
= 0;
951 tprintf("TRACE- pkill()\n");
953 omask
= sigmask(SIGCHLD
);
955 omask
|= sigmask(SIGINT
);
956 omask
= sigblock(omask
) & ~omask
;
962 jobflags
|= np
->p_flags
;
963 while ((np
= np
->p_friends
) != pp
);
970 if ((jobflags
& PRUNNING
) == 0) {
972 printf("%t: Already stopped\n", cp
);
977 if (killpg(pp
->p_jobid
, signum
) < 0) {
980 printf("%s\n", strerror(errno
));
983 if (signum
== SIGTERM
|| signum
== SIGHUP
)
984 (void) killpg(pp
->p_jobid
, SIGCONT
);
985 } else if (!(digit(*cp
) || *cp
== '-'))
986 bferr("Arguments should be jobs or process id's");
989 if (kill(pid
, signum
) < 0) {
991 printf("%s\n", strerror(errno
));
995 if (signum
== SIGTERM
|| signum
== SIGHUP
)
996 (void) kill(pid
, SIGCONT
);
1002 (void) sigsetmask(omask
);
1008 * pstart - start the job in foreground/background
1011 pstart(struct process
*pp
, int foregnd
)
1014 int omask
, jobflags
= 0;
1017 tprintf("TRACE- pstart()\n");
1019 omask
= sigblock(sigmask(SIGCHLD
));
1022 jobflags
|= np
->p_flags
;
1023 if (np
->p_flags
&(PRUNNING
|PSTOPPED
)) {
1024 np
->p_flags
|= PRUNNING
;
1025 np
->p_flags
&= ~PSTOPPED
;
1027 np
->p_flags
|= PFOREGND
;
1029 np
->p_flags
&= ~PFOREGND
;
1031 } while ((np
= np
->p_friends
) != pp
);
1037 if (pprevious
&& (pprevious
->p_flags
& PSTOPPED
))
1039 pcurrent
= pprevious
;
1040 pprevious
= pgetcurr(PNULL
);
1044 pcurrent
= pgetcurr(pp
);
1045 if (!pcurrent
|| (pcurrent
->p_flags
& PRUNNING
))
1051 (void) pprint(pp
, foregnd
? NAME
|JOBDIR
: NUMBER
|NAME
|AMPERSAND
);
1053 (void) ioctl(FSHTTY
, TIOCSPGRP
, (char *)&pp
->p_jobid
);
1054 if (jobflags
&PSTOPPED
)
1055 (void) killpg(pp
->p_jobid
, SIGCONT
);
1056 (void) sigsetmask(omask
);
1060 panystop(int neednl
)
1065 tprintf("TRACE- panystop()\n");
1068 for (pp
= proclist
.p_next
; pp
; pp
= pp
->p_next
)
1069 if (pp
->p_flags
& PSTOPPED
)
1070 error("\nThere are stopped jobs" + 1 - neednl
);
1076 struct process
*pp
, *np
;
1079 tprintf("TRACE- pfind()\n");
1081 if (cp
== 0 || cp
[1] == 0 || eq(cp
, S_PARCENTPARCENT
/* "%%" */) ||
1082 eq(cp
, S_PARCENTPLUS
/* "%+" */)) {
1083 if (pcurrent
== PNULL
)
1084 if ((pcurrent
= pgetcurr(PNULL
)) == PNULL
)
1085 bferr("No current job");
1088 if (eq(cp
, S_PARCENTMINUS
/* "%-" */) ||
1089 eq(cp
, S_PARCENTSHARP
/* "%#" */)) {
1090 if (pprevious
== PNULL
)
1091 bferr("No previous job");
1095 int index
= atoi_(cp
+1);
1096 for (pp
= proclist
.p_next
; pp
; pp
= pp
->p_next
)
1097 if (pp
->p_index
== index
&& pp
->p_pid
== pp
->p_jobid
)
1099 bferr("No such job");
1102 for (pp
= proclist
.p_next
; pp
; pp
= pp
->p_next
)
1103 if (pp
->p_pid
== pp
->p_jobid
) {
1106 for (dp
= pp
->p_command
; *dp
; dp
++) {
1109 if (prefix(cp
+2, dp
))
1112 } else if (prefix(cp
+1, pp
->p_command
)) {
1122 bferr("No job matches pattern");
1124 bferr("No such job");
1129 * pgetcurr - find most recent job that is not pp, preferably stopped
1132 pgetcurr(struct process
*pp
)
1135 struct process
*xp
= PNULL
;
1138 tprintf("TRACE- pgetcurr()\n");
1140 for (np
= proclist
.p_next
; np
; np
= np
->p_next
)
1141 if (np
!= pcurrent
&& np
!= pp
&& np
->p_pid
&&
1142 np
->p_pid
== np
->p_jobid
) {
1143 if (np
->p_flags
& PSTOPPED
)
1152 * donotify - flag the job so as to report termination asynchronously
1160 tprintf("TRACE- donotify()\n");
1163 pp
->p_flags
|= PNOTIFY
;
1167 * Do the fork and whatever should be done in the child side that
1168 * should not be done if we are not forking at all (like for simple builtin's)
1169 * Also do everything that needs any signals fiddled with in the parent side
1171 * Wanttty tells whether process and/or tty pgrps are to be manipulated:
1172 * -1: leave tty alone; inherit pgrp from parent
1173 * 0: already have tty; manipulate process pgrps only
1174 * 1: want to claim tty; manipulate process and tty pgrps
1175 * It is usually just the value of tpgrp.
1178 * t: command we are forking for
1181 pfork(struct command
*t
, int wanttty
)
1189 tprintf("TRACE- pfork()\n");
1192 * A child will be uninterruptible only under very special
1193 * conditions. Remember that the semantics of '&' is
1194 * implemented by disconnecting the process from the tty so
1195 * signals do not need to ignored just for '&'.
1196 * Thus signals are set to default action for children unless:
1197 * we have had an "onintr -" (then specifically ignored)
1198 * we are not playing with signals (inherit action)
1201 ignint
= (tpgrp
== -1 && (t
->t_dflg
&FINT
))
1202 || (gointr
&& eq(gointr
, S_MINUS
/* "-" */));
1204 * Hold SIGCHLD until we have the process installed in our table.
1206 omask
= sigblock(sigmask(SIGCHLD
));
1207 while ((pid
= fork()) < 0)
1211 (void) sigsetmask(omask
);
1212 error("Fork failed");
1216 * setup the process group
1219 child_pid
= getpid();
1222 pgrp
= pcurrjob
? pcurrjob
->p_jobid
: child_pid
;
1231 setintr
= 0; /* until I think otherwise */
1233 * Children just get blown away on SIGINT, SIGQUIT
1234 * unless "onintr -" seen.
1236 (void) signal(SIGINT
, ignint
? SIG_IGN
: SIG_DFL
);
1237 (void) signal(SIGQUIT
, ignint
? SIG_IGN
: SIG_DFL
);
1239 /* make stoppable */
1240 (void) signal(SIGTSTP
, SIG_DFL
);
1241 (void) signal(SIGTTIN
, SIG_DFL
);
1242 (void) signal(SIGTTOU
, SIG_DFL
);
1244 (void) signal(SIGTERM
, parterm
);
1245 } else if (tpgrp
== -1 && (t
->t_dflg
&FINT
)) {
1246 (void) signal(SIGINT
, SIG_IGN
);
1247 (void) signal(SIGQUIT
, SIG_IGN
);
1249 if (wanttty
>= 0 && tpgrp
>= 0)
1250 (void) setpgid(0, pgrp
);
1252 sigttou
= sigblock(sigmask(SIGTTOU
) |
1255 (void) ioctl(FSHTTY
, TIOCSPGRP
, (char *)&pgrp
);
1256 sigsetmask(sigttou
);
1259 tpgrp
= 0; /* gave tty away */
1261 * Nohup and nice apply only to TCOM's but it would be
1262 * nice (?!?) if you could say "nohup (foo;bar)"
1263 * Then the parser would have to know about nice/nohup/time
1265 if (t
->t_dflg
& FNOHUP
)
1266 (void) signal(SIGHUP
, SIG_IGN
);
1267 if (t
->t_dflg
& FNICE
)
1268 (void) setpriority(PRIO_PROCESS
, 0, t
->t_nice
);
1270 if (wanttty
>= 0 && tpgrp
>= 0)
1273 (void) sigsetmask(omask
);
1283 tprintf("TRACE- okpcntl()\n");
1287 error("No job control in this shell");
1289 error("No job control in subshells");
1298 omask
= sigblock(sigmask(SIGCHLD
));
1299 for (pp
= (&proclist
)->p_next
; pp
!= PNULL
; pp
= pp
->p_next
)
1300 if (pp
->p_pid
> 0) {
1301 if (pp
->p_flags
& PFOREGND
)
1302 (void) kill(pp
->p_pid
, SIGHUP
);
1304 (void) sigsetmask(omask
);