1 /* $NetBSD: proc.c,v 1.36 2013/07/16 17:47:43 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
[] = "@(#)proc.c 8.1 (Berkeley) 5/31/93";
37 __RCSID("$NetBSD: proc.c,v 1.36 2013/07/16 17:47:43 christos Exp $");
41 #include <sys/types.h>
55 #define BIGINDEX 9 /* largest desirable job index */
59 static void pflushall(void);
60 static void pflush(struct process
*);
61 static void pclrcurr(struct process
*);
62 static void padd(struct command
*);
63 static int pprint(struct process
*, int);
64 static void ptprint(struct process
*);
65 static void pads(Char
*);
66 static void pkill(Char
**v
, int);
67 static struct process
*pgetcurr(struct process
*);
68 static void okpcntl(void);
71 * pchild - called at interrupt level by the SIGCHLD signal
72 * indicating that at least one child has terminated or stopped
73 * thus at least one wait system call will definitely return a
74 * childs status. Top level routines (like pwait) must be sure
75 * to mask interrupts when playing with the proclist data structures!
82 struct process
*fp
, *pp
;
86 errno
= 0; /* reset, just in case */
88 (setintr
&& (intty
|| insource
) ? WNOHANG
| WUNTRACED
: WNOHANG
), &ru
);
95 pnoprocesses
= pid
== -1;
98 for (pp
= proclist
.p_next
; pp
!= NULL
; pp
= pp
->p_next
)
103 if (pid
== atoi(short2str(value(STRchild
))))
105 pp
->p_flags
&= ~(PRUNNING
| PSTOPPED
| PREPORTED
);
107 pp
->p_flags
|= PSTOPPED
;
108 pp
->p_reason
= WSTOPSIG(w
);
111 if (pp
->p_flags
& (PTIME
| PPTIME
) || adrof(STRtime
))
112 (void)clock_gettime(CLOCK_MONOTONIC
, &pp
->p_etime
);
115 if (WIFSIGNALED(w
)) {
116 if (WTERMSIG(w
) == SIGINT
)
117 pp
->p_flags
|= PINTERRUPTED
;
119 pp
->p_flags
|= PSIGNALED
;
121 pp
->p_flags
|= PDUMPED
;
122 pp
->p_reason
= WTERMSIG(w
);
125 pp
->p_reason
= WEXITSTATUS(w
);
126 if (pp
->p_reason
!= 0)
127 pp
->p_flags
|= PAEXITED
;
129 pp
->p_flags
|= PNEXITED
;
135 if ((fp
->p_flags
& (PPTIME
| PRUNNING
| PSTOPPED
)) == 0 &&
136 !child
&& adrof(STRtime
) &&
137 fp
->p_rusage
.ru_utime
.tv_sec
+ fp
->p_rusage
.ru_stime
.tv_sec
138 >= atoi(short2str(value(STRtime
))))
139 fp
->p_flags
|= PTIME
;
140 jobflags
|= fp
->p_flags
;
141 } while ((fp
= fp
->p_friends
) != pp
);
142 pp
->p_flags
&= ~PFOREGND
;
143 if (pp
== pp
->p_friends
&& (pp
->p_flags
& PPTIME
)) {
144 pp
->p_flags
&= ~PPTIME
;
145 pp
->p_flags
|= PTIME
;
147 if ((jobflags
& (PRUNNING
| PREPORTED
)) == 0) {
150 if (fp
->p_flags
& PSTOPPED
)
151 fp
->p_flags
|= PREPORTED
;
152 } while ((fp
= fp
->p_friends
) != pp
);
153 while (fp
->p_pid
!= fp
->p_jobid
)
155 if (jobflags
& PSTOPPED
) {
156 if (pcurrent
&& pcurrent
!= fp
)
157 pprevious
= pcurrent
;
162 if (jobflags
& PFOREGND
) {
163 if (jobflags
& (PSIGNALED
| PSTOPPED
| PPTIME
) ||
165 jobflags
& PAEXITED
||
167 !eq(dcwd
->di_name
, fp
->p_cwd
->di_name
)) {
168 ; /* print in pjwait */
170 /* PWP: print a newline after ^C */
171 else if (jobflags
& PINTERRUPTED
) {
172 (void)vis_fputc('\r' | QUOTE
, cshout
);
173 (void)fputc('\n', cshout
);
177 if (jobflags
& PNOTIFY
|| adrof(STRnotify
)) {
178 (void)vis_fputc('\r' | QUOTE
, cshout
);
179 (void)fputc('\n', cshout
);
180 (void)pprint(pp
, NUMBER
| NAME
| REASON
);
181 if ((jobflags
& PSTOPPED
) == 0)
185 fp
->p_flags
|= PNEEDNOTE
;
197 sigset_t osigset
, nsigset
;
201 sigemptyset(&nsigset
);
202 (void)sigaddset(&nsigset
, SIGCHLD
);
203 for (pp
= proclist
.p_next
; pp
!= NULL
; pp
= pp
->p_next
) {
204 if (pp
->p_flags
& PNEEDNOTE
) {
205 (void)sigprocmask(SIG_BLOCK
, &nsigset
, &osigset
);
206 pp
->p_flags
&= ~PNEEDNOTE
;
207 flags
= pprint(pp
, NUMBER
| NAME
| REASON
);
208 if ((flags
& (PRUNNING
| PSTOPPED
)) == 0)
210 (void)sigprocmask(SIG_SETMASK
, &osigset
, NULL
);
216 * pwait - wait for current job to terminate, maintaining integrity
217 * of current and previous job indicators.
222 struct process
*fp
, *pp
;
223 sigset_t osigset
, nsigset
;
226 * Here's where dead procs get flushed.
228 sigemptyset(&nsigset
);
229 (void)sigaddset(&nsigset
, SIGCHLD
);
230 (void)sigprocmask(SIG_BLOCK
, &nsigset
, &osigset
);
231 for (pp
= (fp
= &proclist
)->p_next
; pp
!= NULL
; pp
= (fp
= pp
)->p_next
)
232 if (pp
->p_pid
== 0) {
233 fp
->p_next
= pp
->p_next
;
234 xfree((ptr_t
) pp
->p_command
);
235 if (pp
->p_cwd
&& --pp
->p_cwd
->di_count
== 0)
236 if (pp
->p_cwd
->di_next
== 0)
241 (void)sigprocmask(SIG_SETMASK
, &osigset
, NULL
);
247 * pjwait - wait for a job to finish or become stopped
248 * It is assumed to be in the foreground state (PFOREGND)
251 pjwait(struct process
*pp
)
254 sigset_t osigset
, nsigset
;
255 int jobflags
, reason
;
257 while (pp
->p_pid
!= pp
->p_jobid
)
262 if ((fp
->p_flags
& (PFOREGND
| PRUNNING
)) == PRUNNING
)
263 (void)fprintf(csherr
, "BUG: waiting for background job!\n");
264 } while ((fp
= fp
->p_friends
) != pp
);
266 * Now keep pausing as long as we are not interrupted (SIGINT), and the
267 * target process, or any of its friends, are running
270 sigemptyset(&nsigset
);
271 (void)sigaddset(&nsigset
, SIGCHLD
);
272 (void)sigprocmask(SIG_BLOCK
, &nsigset
, &osigset
);
274 sigemptyset(&nsigset
);
275 (void)sigaddset(&nsigset
, SIGCHLD
);
276 (void)sigprocmask(SIG_BLOCK
, &nsigset
, NULL
);
279 jobflags
|= fp
->p_flags
;
280 while ((fp
= (fp
->p_friends
)) != pp
);
281 if ((jobflags
& PRUNNING
) == 0)
284 (void)fprintf(csherr
, "starting to sigsuspend for SIGCHLD on %d\n",
286 #endif /* JOBDEBUG */
288 (void)sigdelset(&nsigset
, SIGCHLD
);
289 (void)sigsuspend(&nsigset
);
291 (void)sigprocmask(SIG_SETMASK
, &osigset
, NULL
);
292 if (tpgrp
> 0) /* get tty back */
293 (void)tcsetpgrp(FSHTTY
, tpgrp
);
294 if ((jobflags
& (PSIGNALED
| PSTOPPED
| PTIME
)) ||
295 !eq(dcwd
->di_name
, fp
->p_cwd
->di_name
)) {
296 if (jobflags
& PSTOPPED
) {
297 (void) fputc('\n', cshout
);
298 if (adrof(STRlistjobs
)) {
301 jobcommand
[0] = STRjobs
;
302 if (eq(value(STRlistjobs
), STRlong
))
303 jobcommand
[1] = STRml
;
305 jobcommand
[1] = NULL
;
306 jobcommand
[2] = NULL
;
308 dojobs(jobcommand
, NULL
);
309 (void)pprint(pp
, SHELLDIR
);
312 (void)pprint(pp
, AREASON
| SHELLDIR
);
315 (void)pprint(pp
, AREASON
| SHELLDIR
);
317 if ((jobflags
& (PINTERRUPTED
| PSTOPPED
)) && setintr
&&
318 (!gointr
|| !eq(gointr
, STRminus
))) {
319 if ((jobflags
& PSTOPPED
) == 0)
327 reason
= fp
->p_flags
& (PSIGNALED
| PINTERRUPTED
) ?
328 fp
->p_reason
| META
: fp
->p_reason
;
329 } while ((fp
= fp
->p_friends
) != pp
);
330 if ((reason
!= 0) && (adrof(STRprintexitvalue
))) {
331 (void)fprintf(cshout
, "Exit %d\n", reason
);
333 set(STRstatus
, putn(reason
));
334 if (reason
&& exiterr
)
340 * dowait - wait for all processes to finish
344 dowait(Char
**v
, struct command
*t
)
347 sigset_t osigset
, nsigset
;
350 sigemptyset(&nsigset
);
351 (void)sigaddset(&nsigset
, SIGCHLD
);
352 (void)sigprocmask(SIG_BLOCK
, &nsigset
, &osigset
);
354 for (pp
= proclist
.p_next
; pp
; pp
= pp
->p_next
)
355 if (pp
->p_pid
&& /* pp->p_pid == pp->p_jobid && */
356 pp
->p_flags
& PRUNNING
) {
357 sigemptyset(&nsigset
);
358 (void)sigsuspend(&nsigset
);
361 (void)sigprocmask(SIG_SETMASK
, &osigset
, NULL
);
366 * pflushall - flush all jobs from list (e.g. at fork())
373 for (pp
= proclist
.p_next
; pp
!= NULL
; pp
= pp
->p_next
)
379 * pflush - flag all process structures in the same job as the
380 * the argument process for deletion. The actual free of the
381 * space is not done here since pflush is called at interrupt level.
384 pflush(struct process
*pp
)
389 if (pp
->p_pid
== 0) {
390 (void)fprintf(csherr
, "BUG: process flushed twice");
393 while (pp
->p_pid
!= pp
->p_jobid
)
401 np
->p_index
= np
->p_pid
= 0;
402 np
->p_flags
&= ~PNEEDNOTE
;
403 } while ((np
= np
->p_friends
) != pp
);
404 if (idx
== pmaxindex
) {
405 for (np
= proclist
.p_next
, idx
= 0; np
; np
= np
->p_next
)
406 if (np
->p_index
> idx
)
413 * pclrcurr - make sure the given job is not the current or previous job;
414 * pp MUST be the job leader
417 pclrcurr(struct process
*pp
)
419 if (pp
== pcurrent
) {
420 if (pprevious
!= NULL
) {
421 pcurrent
= pprevious
;
422 pprevious
= pgetcurr(pp
);
425 pcurrent
= pgetcurr(pp
);
426 pprevious
= pgetcurr(pp
);
428 } else if (pp
== pprevious
)
429 pprevious
= pgetcurr(pp
);
432 /* +4 here is 1 for '\0', 1 ea for << >& >> */
433 static Char command
[PMAXLEN
+ 4];
434 static size_t cmdlen
;
438 * palloc - allocate a process structure and fill it up.
439 * an important assumption is made that the process is running.
442 palloc(int pid
, struct command
*t
)
447 pp
= (struct process
*)xcalloc(1, (size_t)sizeof(struct process
));
449 pp
->p_flags
= t
->t_dflg
& F_AMPERSAND
? PRUNNING
: PRUNNING
| PFOREGND
;
450 if (t
->t_dflg
& F_TIME
)
451 pp
->p_flags
|= PPTIME
;
456 if (t
->t_dflg
& F_PIPEOUT
) {
458 if (t
->t_dflg
& F_STDERR
)
461 pp
->p_command
= Strsave(command
);
465 /* careful here with interrupt level */
467 pp
->p_index
= pcurrjob
->p_index
;
468 pp
->p_friends
= pcurrjob
;
469 pp
->p_jobid
= pcurrjob
->p_pid
;
470 for (fp
= pcurrjob
; fp
->p_friends
!= pcurrjob
; fp
= fp
->p_friends
)
480 if (pmaxindex
< BIGINDEX
)
481 pp
->p_index
= ++pmaxindex
;
486 for (np
= proclist
.p_next
; np
; np
= np
->p_next
)
487 if (np
->p_index
== i
)
496 if (pcurrent
== NULL
)
498 else if (pprevious
== NULL
)
501 pp
->p_next
= proclist
.p_next
;
502 proclist
.p_next
= pp
;
503 (void)clock_gettime(CLOCK_MONOTONIC
, &pp
->p_btime
);
507 padd(struct command
*t
)
520 for (argp
= t
->t_dcom
; *argp
; argp
++) {
548 if ((t
->t_dflg
& F_PIPEIN
) == 0 && t
->t_dlef
) {
549 pads((t
->t_dflg
& F_READ
) ? STRspLarrow2sp
: STRspLarrowsp
);
552 if ((t
->t_dflg
& F_PIPEOUT
) == 0 && t
->t_drit
) {
553 pads((t
->t_dflg
& F_APPEND
) ? STRspRarrow2
: STRspRarrow
);
554 if (t
->t_dflg
& F_STDERR
)
567 * Avoid the Quoted Space alias hack! Reported by:
568 * sam@john-bigboote.ICS.UCI.EDU (Sam Horrocks)
570 if (cp
[0] == STRQNULL
[0])
575 if (cmdlen
>= PMAXLEN
)
577 if (cmdlen
+ i
>= PMAXLEN
) {
578 (void)Strcpy(cmdp
, STRsp3dots
);
583 (void)Strcpy(cmdp
, cp
);
589 * psavejob - temporarily save the current job on a one level stack
590 * so another job can be created. Used for { } in exp6
591 * and `` in globbing.
601 * prestjob - opposite of psavejob. This may be missed if we are interrupted
602 * somewhere, but pendjob cleans up anyway.
612 * pendjob - indicate that a job (set of commands) has been completed
613 * or is about to begin.
618 struct process
*pp
, *tp
;
620 if (pcurrjob
&& (pcurrjob
->p_flags
& (PFOREGND
| PSTOPPED
)) == 0) {
622 while (pp
->p_pid
!= pp
->p_jobid
)
624 (void)fprintf(cshout
, "[%d]", pp
->p_index
);
627 (void)fprintf(cshout
, " %ld", (long)pp
->p_pid
);
630 (void)fputc('\n', cshout
);
632 pholdjob
= pcurrjob
= 0;
636 * pprint - print a job
639 pprint(struct process
*pp
, int flag
)
641 static struct rusage zru
;
644 int jobflags
, pstatus
, reason
, status
;
647 hadnl
= 1; /* did we just have a newline */
648 (void)fpurge(cshout
);
650 while (pp
->p_pid
!= pp
->p_jobid
)
652 if (pp
== pp
->p_friends
&& (pp
->p_flags
& PPTIME
)) {
653 pp
->p_flags
&= ~PPTIME
;
654 pp
->p_flags
|= PTIME
;
657 status
= reason
= -1;
660 jobflags
|= pp
->p_flags
;
661 pstatus
= pp
->p_flags
& PALLSTATES
;
662 if (tp
!= pp
&& !hadnl
&& !(flag
& FANCY
) &&
663 ((pstatus
== status
&& pp
->p_reason
== reason
) ||
665 (void)fputc(' ', cshout
);
669 if (tp
!= pp
&& !hadnl
) {
670 (void)fputc('\n', cshout
);
675 (void)fprintf(cshout
, "[%d]%s %c ", pp
->p_index
,
676 pp
->p_index
< 10 ? " " : "",
677 pp
== pcurrent
? '+' :
678 (pp
== pprevious
? '-' : ' '));
680 (void)fprintf(cshout
, " ");
684 (void)fprintf(cshout
, "%5ld ", (long)pp
->p_pid
);
687 if (flag
& (REASON
| AREASON
)) {
692 if (pstatus
== status
) {
693 if (pp
->p_reason
== reason
) {
694 (void)fprintf(cshout
, format
, "");
699 reason
= pp
->p_reason
;
702 reason
= pp
->p_reason
;
706 (void)fprintf(cshout
, format
, "Running ");
713 * tell what happened to the background job
714 * From: Michael Schroeder
715 * <mlschroe@immd4.informatik.uni-erlangen.de>
720 && (reason
!= SIGPIPE
721 || (pp
->p_flags
& PPOU
) == 0))) {
722 (void)fprintf(cshout
, format
,
723 sys_siglist
[(unsigned char)
732 (void)fprintf(cshout
, "Exit %-18d", pp
->p_reason
);
734 (void)fprintf(cshout
, format
, "Done");
739 (void)fprintf(csherr
, "BUG: status=%-9o", status
);
745 (void)fprintf(cshout
, "%s", vis_str(pp
->p_command
));
746 if (pp
->p_flags
& PPOU
)
747 (void)fprintf(cshout
, " |");
748 if (pp
->p_flags
& PERR
)
749 (void)fputc('&', cshout
);
752 if (flag
& (REASON
| AREASON
) && pp
->p_flags
& PDUMPED
) {
753 (void)fprintf(cshout
, " (core dumped)");
756 if (tp
== pp
->p_friends
) {
757 if (flag
& AMPERSAND
) {
758 (void)fprintf(cshout
, " &");
762 !eq(tp
->p_cwd
->di_name
, dcwd
->di_name
)) {
763 (void)fprintf(cshout
, " (wd: ");
764 dtildepr(value(STRhome
), tp
->p_cwd
->di_name
);
765 (void)fputc(')', cshout
);
769 if (pp
->p_flags
& PPTIME
&& !(status
& (PSTOPPED
| PRUNNING
))) {
771 (void)fprintf(cshout
, "\n\t");
772 prusage(cshout
, &zru
, &pp
->p_rusage
, &pp
->p_etime
,
776 if (tp
== pp
->p_friends
) {
778 (void)fputc('\n', cshout
);
781 if (flag
& SHELLDIR
&& !eq(tp
->p_cwd
->di_name
, dcwd
->di_name
)) {
782 (void)fprintf(cshout
, "(wd now: ");
783 dtildepr(value(STRhome
), dcwd
->di_name
);
784 (void)fprintf(cshout
, ")\n");
788 } while ((pp
= pp
->p_friends
) != tp
);
789 if (jobflags
& PTIME
&& (jobflags
& (PSTOPPED
| PRUNNING
)) == 0) {
790 if (jobflags
& NUMBER
)
791 (void)fprintf(cshout
, " ");
795 (void)fflush(cshout
);
800 ptprint(struct process
*tp
)
802 static struct rusage zru
;
803 static struct timespec ztime
;
805 struct timespec tetime
, diff
;
812 ruadd(&ru
, &pp
->p_rusage
);
813 timespecsub(&pp
->p_etime
, &pp
->p_btime
, &diff
);
814 if (timespeccmp(&diff
, &tetime
, >))
816 } while ((pp
= pp
->p_friends
) != tp
);
817 prusage(cshout
, &zru
, &ru
, &tetime
, &ztime
);
821 * dojobs - print all jobs
825 dojobs(Char
**v
, struct command
*t
)
830 flag
= NUMBER
| NAME
| REASON
;
834 if (v
[1] || !eq(*v
, STRml
))
836 flag
|= FANCY
| JOBDIR
;
838 for (i
= 1; i
<= pmaxindex
; i
++)
839 for (pp
= proclist
.p_next
; pp
; pp
= pp
->p_next
)
840 if (pp
->p_index
== i
&& pp
->p_pid
== pp
->p_jobid
) {
841 pp
->p_flags
&= ~PNEEDNOTE
;
842 if (!(pprint(pp
, flag
) & (PRUNNING
| PSTOPPED
)))
849 * dofg - builtin - put the job into the foreground
853 dofg(Char
**v
, struct command
*t
)
863 } while (*v
&& *++v
);
867 * %... - builtin - put the job into the foreground
871 dofg1(Char
**v
, struct command
*t
)
882 * dobg - builtin - put the job into the background
886 dobg(Char
**v
, struct command
*t
)
895 } while (*v
&& *++v
);
899 * %... & - builtin - put the job into the background
903 dobg1(Char
**v
, struct command
*t
)
912 * dostop - builtin - stop the job
916 dostop(Char
**v
, struct command
*t
)
922 * dokill - builtin - superset of kill (1)
926 dokill(Char
**v
, struct command
*t
)
935 if (v
[0] && v
[0][0] == '-') {
936 if (v
[0][1] == 'l') {
938 if (!Isdigit(v
[1][0]))
939 stderror(ERR_NAME
| ERR_BADSIG
);
941 signum
= strtol(short2str(v
[1]), &ep
, 10);
942 if (signum
< 0 || signum
>= NSIG
)
943 stderror(ERR_NAME
| ERR_BADSIG
);
944 else if (signum
== 0)
945 (void)fputc('0', cshout
); /* 0's symbolic name is '0' */
947 (void)fprintf(cshout
, "%s ", sys_signame
[signum
]);
949 for (signum
= 1; signum
< NSIG
; signum
++) {
950 (void)fprintf(cshout
, "%s ", sys_signame
[signum
]);
951 if (signum
== NSIG
/ 2)
952 (void)fputc('\n', cshout
);
955 (void)fputc('\n', cshout
);
958 if (Isdigit(v
[0][1])) {
959 signum
= strtol(short2str(v
[0] + 1), &ep
, 10);
960 if (signum
< 0 || signum
>= NSIG
|| *ep
)
961 stderror(ERR_NAME
| ERR_BADSIG
);
964 if (v
[0][1] == 's' && v
[0][2] == '\0')
969 if (signame
== NULL
|| v
[1] == NULL
)
970 stderror(ERR_NAME
| ERR_TOOFEW
);
972 name
= short2str(signame
);
973 for (signum
= 1; signum
< NSIG
; signum
++)
974 if (!strcasecmp(sys_signame
[signum
], name
) ||
975 (!strncasecmp("SIG", name
, 3) && /* skip "SIG" prefix */
976 !strcasecmp(sys_signame
[signum
], name
+ 3)))
979 if (signum
== NSIG
) {
980 if (signame
[0] == '0')
983 setname(vis_str(signame
));
984 stderror(ERR_NAME
| ERR_UNKSIG
);
990 pkill(v
, (int)signum
);
994 pkill(Char
**v
, int signum
)
996 struct process
*pp
, *np
;
999 int err1
, jobflags
, pid
;
1004 sigemptyset(&nsigset
);
1005 (void)sigaddset(&nsigset
, SIGCHLD
);
1007 (void)sigaddset(&nsigset
, SIGINT
);
1008 (void)sigprocmask(SIG_BLOCK
, &nsigset
, NULL
);
1009 gflag
= 0, tglob(v
);
1013 stderror(ERR_NAME
| ERR_NOMATCH
);
1016 v
= gargv
= saveblk(v
);
1020 while (v
&& (cp
= *v
)) {
1022 np
= pp
= pfind(cp
);
1024 jobflags
|= np
->p_flags
;
1025 while ((np
= np
->p_friends
) != pp
);
1031 if ((jobflags
& PRUNNING
) == 0) {
1032 (void)fprintf(csherr
, "%s: Already suspended\n",
1039 * suspend a process, kill -CONT %, then type jobs; the shell
1040 * says it is suspended, but it is running; thanks jaap..
1046 if (kill(-pp
->p_jobid
, signum
) < 0) {
1047 (void)fprintf(csherr
, "%s: %s\n", vis_str(cp
),
1051 if (signum
== SIGTERM
|| signum
== SIGHUP
)
1052 (void)kill(-pp
->p_jobid
, SIGCONT
);
1054 else if (!(Isdigit(*cp
) || *cp
== '-'))
1055 stderror(ERR_NAME
| ERR_JOBARGS
);
1057 pid
= (pid_t
)strtoul(short2str(cp
), &ep
, 0);
1059 (void)fprintf(csherr
, "%s: Badly formed number\n",
1063 } else if (kill(pid
, signum
) < 0) {
1064 (void)fprintf(csherr
, "%d: %s\n", pid
, strerror(errno
));
1068 if (signum
== SIGTERM
|| signum
== SIGHUP
)
1069 (void)kill((pid_t
) pid
, SIGCONT
);
1075 blkfree(gargv
), gargv
= 0;
1076 (void)sigprocmask(SIG_UNBLOCK
, &nsigset
, NULL
);
1078 stderror(ERR_SILENT
);
1082 * pstart - start the job in foreground/background
1085 pstart(struct process
*pp
, int foregnd
)
1088 sigset_t osigset
, nsigset
;
1092 sigemptyset(&nsigset
);
1093 (void)sigaddset(&nsigset
, SIGCHLD
);
1094 (void)sigprocmask(SIG_BLOCK
, &nsigset
, &osigset
);
1097 jobflags
|= np
->p_flags
;
1098 if (np
->p_flags
& (PRUNNING
| PSTOPPED
)) {
1099 np
->p_flags
|= PRUNNING
;
1100 np
->p_flags
&= ~PSTOPPED
;
1102 np
->p_flags
|= PFOREGND
;
1104 np
->p_flags
&= ~PFOREGND
;
1106 } while ((np
= np
->p_friends
) != pp
);
1109 (void)pprint(pp
, foregnd
? NAME
| JOBDIR
: NUMBER
| NAME
| AMPERSAND
);
1111 (void)tcsetpgrp(FSHTTY
, pp
->p_jobid
);
1112 if (jobflags
& PSTOPPED
)
1113 (void)kill(-pp
->p_jobid
, SIGCONT
);
1114 (void)sigprocmask(SIG_SETMASK
, &osigset
, NULL
);
1118 panystop(int neednl
)
1123 for (pp
= proclist
.p_next
; pp
; pp
= pp
->p_next
)
1124 if (pp
->p_flags
& PSTOPPED
)
1125 stderror(ERR_STOPPED
, neednl
? "\n" : "");
1131 struct process
*pp
, *np
;
1133 if (cp
== 0 || cp
[1] == 0 || eq(cp
, STRcent2
) || eq(cp
, STRcentplus
)) {
1134 if (pcurrent
== NULL
)
1135 stderror(ERR_NAME
| ERR_JOBCUR
);
1138 if (eq(cp
, STRcentminus
) || eq(cp
, STRcenthash
)) {
1139 if (pprevious
== NULL
)
1140 stderror(ERR_NAME
| ERR_JOBPREV
);
1143 if (Isdigit(cp
[1])) {
1144 int idx
= atoi(short2str(cp
+ 1));
1146 for (pp
= proclist
.p_next
; pp
; pp
= pp
->p_next
)
1147 if (pp
->p_index
== idx
&& pp
->p_pid
== pp
->p_jobid
)
1149 stderror(ERR_NAME
| ERR_NOSUCHJOB
);
1152 for (pp
= proclist
.p_next
; pp
; pp
= pp
->p_next
)
1153 if (pp
->p_pid
== pp
->p_jobid
) {
1157 for (dp
= pp
->p_command
; *dp
; dp
++) {
1160 if (prefix(cp
+ 2, dp
))
1164 else if (prefix(cp
+ 1, pp
->p_command
)) {
1167 stderror(ERR_NAME
| ERR_AMBIG
);
1173 stderror(ERR_NAME
| (cp
[1] == '?' ? ERR_JOBPAT
: ERR_NOSUCHJOB
));
1178 * pgetcurr - find most recent job that is not pp, preferably stopped
1180 static struct process
*
1181 pgetcurr(struct process
*pp
)
1183 struct process
*np
, *xp
;
1186 for (np
= proclist
.p_next
; np
; np
= np
->p_next
)
1187 if (np
!= pcurrent
&& np
!= pp
&& np
->p_pid
&&
1188 np
->p_pid
== np
->p_jobid
) {
1189 if (np
->p_flags
& PSTOPPED
)
1198 * donotify - flag the job so as to report termination asynchronously
1202 donotify(Char
**v
, struct command
*t
)
1207 pp
->p_flags
|= PNOTIFY
;
1211 * Do the fork and whatever should be done in the child side that
1212 * should not be done if we are not forking at all (like for simple builtin's)
1213 * Also do everything that needs any signals fiddled with in the parent side
1215 * Wanttty tells whether process and/or tty pgrps are to be manipulated:
1216 * -1: leave tty alone; inherit pgrp from parent
1217 * 0: already have tty; manipulate process pgrps only
1218 * 1: want to claim tty; manipulate process and tty pgrps
1219 * It is usually just the value of tpgrp.
1223 pfork(struct command
*t
/* command we are forking for */, int wanttty
)
1226 sigset_t osigset
, nsigset
;
1231 * A child will be uninterruptible only under very special conditions.
1232 * Remember that the semantics of '&' is implemented by disconnecting the
1233 * process from the tty so signals do not need to ignored just for '&'.
1234 * Thus signals are set to default action for children unless: we have had
1235 * an "onintr -" (then specifically ignored) we are not playing with
1236 * signals (inherit action)
1239 ignint
= (tpgrp
== -1 && (t
->t_dflg
& F_NOINTERRUPT
))
1240 || (gointr
&& eq(gointr
, STRminus
));
1242 * Check for maximum nesting of 16 processes to avoid Forking loops
1245 stderror(ERR_NESTING
, 16);
1247 * Hold SIGCHLD until we have the process installed in our table.
1249 sigemptyset(&nsigset
);
1250 (void)sigaddset(&nsigset
, SIGCHLD
);
1251 (void)sigprocmask(SIG_BLOCK
, &nsigset
, &osigset
);
1252 while ((pid
= fork()) < 0)
1254 (void)sleep(FORKSLEEP
);
1256 (void)sigprocmask(SIG_SETMASK
, &osigset
, NULL
);
1257 stderror(ERR_NOPROC
);
1261 pgrp
= pcurrjob
? pcurrjob
->p_jobid
: getpid();
1266 setintr
= 0; /* until I think otherwise */
1268 * Children just get blown away on SIGINT, SIGQUIT unless "onintr
1271 (void)signal(SIGINT
, ignint
? SIG_IGN
: SIG_DFL
);
1272 (void)signal(SIGQUIT
, ignint
? SIG_IGN
: SIG_DFL
);
1274 /* make stoppable */
1275 (void)signal(SIGTSTP
, SIG_DFL
);
1276 (void)signal(SIGTTIN
, SIG_DFL
);
1277 (void)signal(SIGTTOU
, SIG_DFL
);
1279 (void)signal(SIGTERM
, parterm
);
1281 else if (tpgrp
== -1 && (t
->t_dflg
& F_NOINTERRUPT
)) {
1282 (void)signal(SIGINT
, SIG_IGN
);
1283 (void)signal(SIGQUIT
, SIG_IGN
);
1285 pgetty(wanttty
, pgrp
);
1287 * Nohup and nice apply only to NODE_COMMAND's but it would be nice
1288 * (?!?) if you could say "nohup (foo;bar)" Then the parser would have
1289 * to know about nice/nohup/time
1291 if (t
->t_dflg
& F_NOHUP
)
1292 (void)signal(SIGHUP
, SIG_IGN
);
1293 if (t
->t_dflg
& F_NICE
)
1294 (void)setpriority(PRIO_PROCESS
, 0, t
->t_nice
);
1298 (void)setpgid(pid
, pcurrjob
? pcurrjob
->p_jobid
: pid
);
1300 (void)sigprocmask(SIG_SETMASK
, &osigset
, NULL
);
1310 stderror(ERR_JOBCONTROL
);
1312 stderror(ERR_JOBCTRLSUB
);
1317 * if we don't have vfork(), things can still go in the wrong order
1318 * resulting in the famous 'Stopped (tty output)'. But some systems
1319 * don't permit the setpgid() call, (these are more recent secure
1320 * systems such as ibm's aix). Then we'd rather print an error message
1321 * than hang the shell!
1322 * I am open to suggestions how to fix that.
1325 pgetty(int wanttty
, int pgrp
)
1327 sigset_t osigset
, nsigset
;
1330 * christos: I am blocking the tty signals till I've set things
1334 sigemptyset(&nsigset
);
1335 (void)sigaddset(&nsigset
, SIGTSTP
);
1336 (void)sigaddset(&nsigset
, SIGTTIN
);
1337 (void)sigaddset(&nsigset
, SIGTTOU
);
1338 (void)sigprocmask(SIG_BLOCK
, &nsigset
, &osigset
);
1341 * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
1342 * Don't check for tpgrp >= 0 so even non-interactive shells give
1343 * background jobs process groups Same for the comparison in the other part
1347 if (setpgid(0, pgrp
) == -1) {
1348 (void)fprintf(csherr
, "csh: setpgid error.\n");
1353 (void)tcsetpgrp(FSHTTY
, pgrp
);
1354 (void)sigprocmask(SIG_SETMASK
, &osigset
, NULL
);
1358 tpgrp
= 0; /* gave tty away */