xref: /openbsd-src/bin/csh/proc.c (revision d29fd0a028ca5fa859a07b81d8a4bda5ea2b83fc)
1 /*	$OpenBSD: proc.c,v 1.26 2015/02/08 06:09:50 tedu Exp $	*/
2 /*	$NetBSD: proc.c,v 1.9 1995/04/29 23:21:33 mycroft Exp $	*/
3 
4 /*-
5  * Copyright (c) 1980, 1991, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
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.
19  *
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
30  * SUCH DAMAGE.
31  */
32 
33 #include <sys/types.h>
34 #include <sys/wait.h>
35 #include <errno.h>
36 #include <unistd.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <stdarg.h>
40 
41 #include "csh.h"
42 #include "dir.h"
43 #include "proc.h"
44 #include "extern.h"
45 
46 #define BIGINDEX	9	/* largest desirable job index */
47 
48 static struct rusage zru;
49 
50 static void	 pflushall(void);
51 static void	 pflush(struct process *);
52 static void	 pclrcurr(struct process *);
53 static void	 padd(struct command *);
54 static int	 pprint(struct process *, int);
55 static void	 ptprint(struct process *);
56 static void	 pads(Char *);
57 static void	 pkill(Char **v, int);
58 static struct	process
59 		*pgetcurr(struct process *);
60 static void	 okpcntl(void);
61 
62 /*
63  * pchild - called at interrupt level by the SIGCHLD signal
64  *	indicating that at least one child has terminated or stopped
65  *	thus at least one wait system call will definitely return a
66  *	childs status.  Top level routines (like pwait) must be sure
67  *	to mask interrupts when playing with the proclist data structures!
68  */
69 /* ARGUSED */
70 void
71 pchild(int notused)
72 {
73     struct process *pp;
74     struct process *fp;
75     int pid;
76     extern int insource;
77     int save_errno = errno;
78     int w;
79     int     jobflags;
80     struct rusage ru;
81 
82 loop:
83     errno = 0;			/* reset, just in case */
84     pid = wait3(&w,
85        (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
86 
87     if (pid <= 0) {
88 	if (errno == EINTR) {
89 	    errno = 0;
90 	    goto loop;
91 	}
92 	pnoprocesses = pid == -1;
93 	errno = save_errno;
94 	return;
95     }
96     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
97 	if (pid == pp->p_pid)
98 	    goto found;
99     goto loop;
100 found:
101     if (pid == atoi(short2str(value(STRchild))))
102 	unsetv(STRchild);
103     pp->p_flags &= ~(PRUNNING | PSTOPPED | PREPORTED);
104     if (WIFSTOPPED(w)) {
105 	pp->p_flags |= PSTOPPED;
106 	pp->p_reason = WSTOPSIG(w);
107     }
108     else {
109 	if (pp->p_flags & (PTIME | PPTIME) || adrof(STRtime))
110 	    (void) gettimeofday(&pp->p_etime, NULL);
111 
112 	pp->p_rusage = ru;
113 	if (WIFSIGNALED(w)) {
114 	    if (WTERMSIG(w) == SIGINT)
115 		pp->p_flags |= PINTERRUPTED;
116 	    else
117 		pp->p_flags |= PSIGNALED;
118 	    if (WCOREDUMP(w))
119 		pp->p_flags |= PDUMPED;
120 	    pp->p_reason = WTERMSIG(w);
121 	}
122 	else {
123 	    pp->p_reason = WEXITSTATUS(w);
124 	    if (pp->p_reason != 0)
125 		pp->p_flags |= PAEXITED;
126 	    else
127 		pp->p_flags |= PNEXITED;
128 	}
129     }
130     jobflags = 0;
131     fp = pp;
132     do {
133 	if ((fp->p_flags & (PPTIME | PRUNNING | PSTOPPED)) == 0 &&
134 	    !child && adrof(STRtime) &&
135 	    fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec
136 	    >= atoi(short2str(value(STRtime))))
137 	    fp->p_flags |= PTIME;
138 	jobflags |= fp->p_flags;
139     } while ((fp = fp->p_friends) != pp);
140     pp->p_flags &= ~PFOREGND;
141     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
142 	pp->p_flags &= ~PPTIME;
143 	pp->p_flags |= PTIME;
144     }
145     if ((jobflags & (PRUNNING | PREPORTED)) == 0) {
146 	fp = pp;
147 	do {
148 	    if (fp->p_flags & PSTOPPED)
149 		fp->p_flags |= PREPORTED;
150 	} while ((fp = fp->p_friends) != pp);
151 	while (fp->p_pid != fp->p_jobid)
152 	    fp = fp->p_friends;
153 	if (jobflags & PSTOPPED) {
154 	    if (pcurrent && pcurrent != fp)
155 		pprevious = pcurrent;
156 	    pcurrent = fp;
157 	}
158 	else
159 	    pclrcurr(fp);
160 	if (jobflags & PFOREGND) {
161 	    if (jobflags & (PSIGNALED | PSTOPPED | PPTIME) ||
162 #ifdef IIASA
163 		jobflags & PAEXITED ||
164 #endif
165 		!eq(dcwd->di_name, fp->p_cwd->di_name)) {
166 		;		/* print in pjwait */
167 	    }
168 	    /* PWP: print a newline after ^C */
169 	    else if (jobflags & PINTERRUPTED) {
170 		(void) vis_fputc('\r' | QUOTE, cshout);
171 		(void) fputc('\n', cshout);
172 	    }
173 	}
174 	else {
175 	    if (jobflags & PNOTIFY || adrof(STRnotify)) {
176 		(void) vis_fputc('\r' | QUOTE, cshout);
177 		(void) fputc('\n', cshout);
178 		(void) pprint(pp, NUMBER | NAME | REASON);
179 		if ((jobflags & PSTOPPED) == 0)
180 		    pflush(pp);
181 	    }
182 	    else {
183 		fp->p_flags |= PNEEDNOTE;
184 		neednote++;
185 	    }
186 	}
187     }
188     goto loop;
189 }
190 
191 void
192 pnote(void)
193 {
194     struct process *pp;
195     int     flags;
196     sigset_t sigset, osigset;
197 
198     neednote = 0;
199     sigemptyset(&sigset);
200     sigaddset(&sigset, SIGCHLD);
201     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) {
202 	if (pp->p_flags & PNEEDNOTE) {
203 	    sigprocmask(SIG_BLOCK, &sigset, &osigset);
204 	    pp->p_flags &= ~PNEEDNOTE;
205 	    flags = pprint(pp, NUMBER | NAME | REASON);
206 	    if ((flags & (PRUNNING | PSTOPPED)) == 0)
207 		pflush(pp);
208 	    sigprocmask(SIG_SETMASK, &osigset, NULL);
209 	}
210     }
211 }
212 
213 /*
214  * pwait - wait for current job to terminate, maintaining integrity
215  *	of current and previous job indicators.
216  */
217 void
218 pwait(void)
219 {
220     struct process *fp, *pp;
221     sigset_t sigset, osigset;
222 
223     /*
224      * Here's where dead procs get flushed.
225      */
226     sigemptyset(&sigset);
227     sigaddset(&sigset, SIGCHLD);
228     sigprocmask(SIG_BLOCK, &sigset, &osigset);
229     for (pp = (fp = &proclist)->p_next; pp != NULL; pp = (fp = pp)->p_next)
230 	if (pp->p_pid == 0) {
231 	    fp->p_next = pp->p_next;
232 	    xfree(pp->p_command);
233 	    if (pp->p_cwd && --pp->p_cwd->di_count == 0)
234 		if (pp->p_cwd->di_next == 0)
235 		    dfree(pp->p_cwd);
236 	    xfree(pp);
237 	    pp = fp;
238 	}
239     sigprocmask(SIG_SETMASK, &osigset, NULL);
240     pjwait(pcurrjob);
241 }
242 
243 
244 /*
245  * pjwait - wait for a job to finish or become stopped
246  *	It is assumed to be in the foreground state (PFOREGND)
247  */
248 void
249 pjwait(struct process *pp)
250 {
251     struct process *fp;
252     int     jobflags, reason;
253     sigset_t sigset, osigset;
254 
255     while (pp->p_pid != pp->p_jobid)
256 	pp = pp->p_friends;
257     fp = pp;
258 
259     do {
260 	if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING)
261 	    (void) fprintf(csherr, "BUG: waiting for background job!\n");
262     } while ((fp = fp->p_friends) != pp);
263     /*
264      * Now keep pausing as long as we are not interrupted (SIGINT), and the
265      * target process, or any of its friends, are running
266      */
267     fp = pp;
268     sigemptyset(&sigset);
269     sigaddset(&sigset, SIGCHLD);
270     sigprocmask(SIG_BLOCK, &sigset, &osigset);
271     for (;;) {
272 	sigemptyset(&sigset);
273 	sigaddset(&sigset, SIGCHLD);
274 	sigprocmask(SIG_BLOCK, &sigset, NULL);
275 	jobflags = 0;
276 	do
277 	    jobflags |= fp->p_flags;
278 	while ((fp = (fp->p_friends)) != pp);
279 	if ((jobflags & PRUNNING) == 0)
280 	    break;
281 #ifdef JOBDEBUG
282 	(void) fprintf(csherr, "starting to sigsuspend for  SIGCHLD on %d\n",
283 		       fp->p_pid);
284 #endif				/* JOBDEBUG */
285 	sigset = osigset;
286 	sigdelset(&sigset, SIGCHLD);
287 	sigsuspend(&sigset);
288     }
289     sigprocmask(SIG_SETMASK, &osigset, NULL);
290     if (tpgrp > 0)		/* get tty back */
291 	(void) tcsetpgrp(FSHTTY, tpgrp);
292     if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) ||
293 	!eq(dcwd->di_name, fp->p_cwd->di_name)) {
294 	if (jobflags & PSTOPPED) {
295 	    (void) fputc('\n', cshout);
296 	    if (adrof(STRlistjobs)) {
297 		Char   *jobcommand[3];
298 
299 		jobcommand[0] = STRjobs;
300 		if (eq(value(STRlistjobs), STRlong))
301 		    jobcommand[1] = STRml;
302 		else
303 		    jobcommand[1] = NULL;
304 		jobcommand[2] = NULL;
305 
306 		dojobs(jobcommand, NULL);
307 		(void) pprint(pp, SHELLDIR);
308 	    }
309 	    else
310 		(void) pprint(pp, AREASON | SHELLDIR);
311 	}
312 	else
313 	    (void) pprint(pp, AREASON | SHELLDIR);
314     }
315     if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr &&
316 	(!gointr || !eq(gointr, STRminus))) {
317 	if ((jobflags & PSTOPPED) == 0)
318 	    pflush(pp);
319 	pintr1(0);
320 	/* NOTREACHED */
321     }
322     reason = 0;
323     fp = pp;
324     do {
325 	if (fp->p_reason)
326 	    reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ?
327 		fp->p_reason | META : fp->p_reason;
328     } while ((fp = fp->p_friends) != pp);
329     if ((reason != 0) && (adrof(STRprintexitvalue))) {
330 	(void) fprintf(cshout, "Exit %d\n", reason);
331     }
332     set(STRstatus, putn(reason));
333     if (reason && exiterr)
334 	exitstat();
335     pflush(pp);
336 }
337 
338 /*
339  * dowait - wait for all processes to finish
340  */
341 void
342 /*ARGSUSED*/
343 dowait(Char **v, struct command *t)
344 {
345     struct process *pp;
346     sigset_t sigset, osigset;
347 
348     pjobs++;
349     sigemptyset(&sigset);
350     sigaddset(&sigset, SIGCHLD);
351     sigprocmask(SIG_BLOCK, &sigset, &osigset);
352 loop:
353     for (pp = proclist.p_next; pp; pp = pp->p_next)
354 	if (pp->p_pid &&	/* pp->p_pid == pp->p_jobid && */
355 	    pp->p_flags & PRUNNING) {
356 	    sigemptyset(&sigset);
357 	    sigsuspend(&sigset);
358 	    goto loop;
359 	}
360     sigprocmask(SIG_SETMASK, &osigset, NULL);
361     pjobs = 0;
362 }
363 
364 /*
365  * pflushall - flush all jobs from list (e.g. at fork())
366  */
367 static void
368 pflushall(void)
369 {
370     struct process *pp;
371 
372     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
373 	if (pp->p_pid)
374 	    pflush(pp);
375 }
376 
377 /*
378  * pflush - flag all process structures in the same job as the
379  *	the argument process for deletion.  The actual free of the
380  *	space is not done here since pflush is called at interrupt level.
381  */
382 static void
383 pflush(struct process *pp)
384 {
385     struct process *np;
386     int idx;
387 
388     if (pp->p_pid == 0) {
389 	(void) fprintf(csherr, "BUG: process flushed twice");
390 	return;
391     }
392     while (pp->p_pid != pp->p_jobid)
393 	pp = pp->p_friends;
394     pclrcurr(pp);
395     if (pp == pcurrjob)
396 	pcurrjob = 0;
397     idx = pp->p_index;
398     np = pp;
399     do {
400 	np->p_index = np->p_pid = 0;
401 	np->p_flags &= ~PNEEDNOTE;
402     } while ((np = np->p_friends) != pp);
403     if (idx == pmaxindex) {
404 	for (np = proclist.p_next, idx = 0; np; np = np->p_next)
405 	    if (np->p_index > idx)
406 		idx = np->p_index;
407 	pmaxindex = idx;
408     }
409 }
410 
411 /*
412  * pclrcurr - make sure the given job is not the current or previous job;
413  *	pp MUST be the job leader
414  */
415 static void
416 pclrcurr(struct process *pp)
417 {
418 
419     if (pp == pcurrent)
420 	if (pprevious != NULL) {
421 	    pcurrent = pprevious;
422 	    pprevious = pgetcurr(pp);
423 	}
424 	else {
425 	    pcurrent = pgetcurr(pp);
426 	    pprevious = pgetcurr(pp);
427 	}
428     else if (pp == pprevious)
429 	pprevious = pgetcurr(pp);
430 }
431 
432 /* +4 here is 1 for '\0', 1 ea for << >& >> */
433 static Char command[PMAXLEN + 4];
434 static int cmdlen;
435 static Char *cmdp;
436 
437 /*
438  * palloc - allocate a process structure and fill it up.
439  *	an important assumption is made that the process is running.
440  */
441 void
442 palloc(int pid, struct command *t)
443 {
444     struct process *pp;
445     int     i;
446 
447     pp = xcalloc(1, (size_t) sizeof(struct process));
448     pp->p_pid = pid;
449     pp->p_flags = t->t_dflg & F_AMPERSAND ? PRUNNING : PRUNNING | PFOREGND;
450     if (t->t_dflg & F_TIME)
451 	pp->p_flags |= PPTIME;
452     cmdp = command;
453     cmdlen = 0;
454     padd(t);
455     *cmdp++ = 0;
456     if (t->t_dflg & F_PIPEOUT) {
457 	pp->p_flags |= PPOU;
458 	if (t->t_dflg & F_STDERR)
459 	    pp->p_flags |= PERR;
460     }
461     pp->p_command = Strsave(command);
462     if (pcurrjob) {
463 	struct process *fp;
464 
465 	/* careful here with interrupt level */
466 	pp->p_cwd = 0;
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)
471 	    continue;
472 	fp->p_friends = pp;
473     }
474     else {
475 	pcurrjob = pp;
476 	pp->p_jobid = pid;
477 	pp->p_friends = pp;
478 	pp->p_cwd = dcwd;
479 	dcwd->di_count++;
480 	if (pmaxindex < BIGINDEX)
481 	    pp->p_index = ++pmaxindex;
482 	else {
483 	    struct process *np;
484 
485 	    for (i = 1;; i++) {
486 		for (np = proclist.p_next; np; np = np->p_next)
487 		    if (np->p_index == i)
488 			goto tryagain;
489 		pp->p_index = i;
490 		if (i > pmaxindex)
491 		    pmaxindex = i;
492 		break;
493 	tryagain:;
494 	    }
495 	}
496 	if (pcurrent == NULL)
497 	    pcurrent = pp;
498 	else if (pprevious == NULL)
499 	    pprevious = pp;
500     }
501     pp->p_next = proclist.p_next;
502     proclist.p_next = pp;
503     (void) gettimeofday(&pp->p_btime, NULL);
504 }
505 
506 static void
507 padd(struct command *t)
508 {
509     Char  **argp;
510 
511     if (t == 0)
512 	return;
513     switch (t->t_dtyp) {
514 
515     case NODE_PAREN:
516 	pads(STRLparensp);
517 	padd(t->t_dspr);
518 	pads(STRspRparen);
519 	break;
520 
521     case NODE_COMMAND:
522 	for (argp = t->t_dcom; *argp; argp++) {
523 	    pads(*argp);
524 	    if (argp[1])
525 		pads(STRspace);
526 	}
527 	break;
528 
529     case NODE_OR:
530     case NODE_AND:
531     case NODE_PIPE:
532     case NODE_LIST:
533 	padd(t->t_dcar);
534 	switch (t->t_dtyp) {
535 	case NODE_OR:
536 	    pads(STRspor2sp);
537 	    break;
538 	case NODE_AND:
539 	    pads(STRspand2sp);
540 	    break;
541 	case NODE_PIPE:
542 	    pads(STRsporsp);
543 	    break;
544 	case NODE_LIST:
545 	    pads(STRsemisp);
546 	    break;
547 	}
548 	padd(t->t_dcdr);
549 	return;
550     }
551     if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) {
552 	pads((t->t_dflg & F_READ) ? STRspLarrow2sp : STRspLarrowsp);
553 	pads(t->t_dlef);
554     }
555     if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) {
556 	pads((t->t_dflg & F_APPEND) ? STRspRarrow2 : STRspRarrow);
557 	if (t->t_dflg & F_STDERR)
558 	    pads(STRand);
559 	pads(STRspace);
560 	pads(t->t_drit);
561     }
562 }
563 
564 static void
565 pads(Char *cp)
566 {
567     int i;
568 
569     /*
570      * Avoid the Quoted Space alias hack! Reported by:
571      * sam@john-bigboote.ICS.UCI.EDU (Sam Horrocks)
572      */
573     if (cp[0] == STRQNULL[0])
574 	cp++;
575 
576     i = Strlen(cp);
577 
578     if (cmdlen >= PMAXLEN)
579 	return;
580     if (cmdlen + i >= PMAXLEN) {
581 	(void) Strlcpy(cmdp, STRsp3dots, PMAXLEN - cmdlen);
582 	cmdlen = PMAXLEN;
583 	cmdp += 4;
584 	return;
585     }
586     (void) Strlcpy(cmdp, cp, PMAXLEN - cmdlen);
587     cmdp += i;
588     cmdlen += i;
589 }
590 
591 /*
592  * psavejob - temporarily save the current job on a one level stack
593  *	so another job can be created.  Used for { } in exp6
594  *	and `` in globbing.
595  */
596 void
597 psavejob(void)
598 {
599 
600     pholdjob = pcurrjob;
601     pcurrjob = NULL;
602 }
603 
604 /*
605  * prestjob - opposite of psavejob.  This may be missed if we are interrupted
606  *	somewhere, but pendjob cleans up anyway.
607  */
608 void
609 prestjob(void)
610 {
611 
612     pcurrjob = pholdjob;
613     pholdjob = NULL;
614 }
615 
616 /*
617  * pendjob - indicate that a job (set of commands) has been completed
618  *	or is about to begin.
619  */
620 void
621 pendjob(void)
622 {
623     struct process *pp, *tp;
624 
625     if (pcurrjob && (pcurrjob->p_flags & (PFOREGND | PSTOPPED)) == 0) {
626 	pp = pcurrjob;
627 	while (pp->p_pid != pp->p_jobid)
628 	    pp = pp->p_friends;
629 	(void) fprintf(cshout, "[%d]", pp->p_index);
630 	tp = pp;
631 	do {
632 	    (void) fprintf(cshout, " %d", pp->p_pid);
633 	    pp = pp->p_friends;
634 	} while (pp != tp);
635 	(void) fputc('\n', cshout);
636     }
637     pholdjob = pcurrjob = 0;
638 }
639 
640 /*
641  * pprint - print a job
642  */
643 static int
644 pprint(struct process *pp, bool flag)
645 {
646     int status, reason;
647     struct process *tp;
648     int     jobflags, pstatus;
649     bool hadnl = 1;	/* did we just have a newline */
650 
651     (void) fpurge(cshout);
652 
653     while (pp->p_pid != pp->p_jobid)
654 	pp = pp->p_friends;
655     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
656 	pp->p_flags &= ~PPTIME;
657 	pp->p_flags |= PTIME;
658     }
659     tp = pp;
660     status = reason = -1;
661     jobflags = 0;
662     do {
663 	jobflags |= pp->p_flags;
664 	pstatus = pp->p_flags & PALLSTATES;
665 	if (tp != pp && !hadnl && !(flag & FANCY) &&
666 	    ((pstatus == status && pp->p_reason == reason) ||
667 	     !(flag & REASON))) {
668 	    (void) fputc(' ', cshout);
669 	    hadnl = 0;
670 	}
671 	else {
672 	    if (tp != pp && !hadnl) {
673 		(void) fputc('\n', cshout);
674 		hadnl = 1;
675 	    }
676 	    if (flag & NUMBER) {
677 		if (pp == tp)
678 		    (void) fprintf(cshout, "[%d]%s %c ", pp->p_index,
679 			    pp->p_index < 10 ? " " : "",
680 			    pp == pcurrent ? '+' :
681 			    (pp == pprevious ? '-' : ' '));
682 		else
683 		    (void) fprintf(cshout, "       ");
684 		hadnl = 0;
685 	    }
686 	    if (flag & FANCY) {
687 		(void) fprintf(cshout, "%5d ", pp->p_pid);
688 		hadnl = 0;
689 	    }
690 	    if (flag & (REASON | AREASON)) {
691 		int width = 0;
692 		if (flag & NAME)
693 		    width = -23;
694 		if (pstatus == status)
695 		    if (pp->p_reason == reason) {
696 			(void) fprintf(cshout, "%*s", width, "");
697 			hadnl = 0;
698 			goto prcomd;
699 		    }
700 		    else
701 			reason = pp->p_reason;
702 		else {
703 		    status = pstatus;
704 		    reason = pp->p_reason;
705 		}
706 		switch (status) {
707 
708 		case PRUNNING:
709 		    (void) fprintf(cshout, "%*s", width, "Running ");
710 		    hadnl = 0;
711 		    break;
712 
713 		case PINTERRUPTED:
714 		case PSTOPPED:
715 		case PSIGNALED:
716 		    /*
717 		     * tell what happened to the background job
718 		     * From: Michael Schroeder
719 		     * <mlschroe@immd4.informatik.uni-erlangen.de>
720 		     */
721 		    if ((flag & REASON)
722 			|| ((flag & AREASON)
723 			    && reason != SIGINT
724 			    && (reason != SIGPIPE
725 				|| (pp->p_flags & PPOU) == 0))) {
726 			(void) fprintf(cshout, "%*s", width,
727 				       sys_siglist[(unsigned char)
728 						   pp->p_reason]);
729 			hadnl = 0;
730 		    }
731 		    break;
732 
733 		case PNEXITED:
734 		case PAEXITED:
735 		    if (flag & REASON) {
736 			if (pp->p_reason)
737 			    (void) fprintf(cshout, "Exit %-18d", pp->p_reason);
738 			else
739 			    (void) fprintf(cshout, "%*s", width, "Done");
740 			hadnl = 0;
741 		    }
742 		    break;
743 
744 		default:
745 		    (void) fprintf(csherr, "BUG: status=%-9o", status);
746 		}
747 	    }
748 	}
749 prcomd:
750 	if (flag & NAME) {
751 	    (void) fprintf(cshout, "%s", vis_str(pp->p_command));
752 	    if (pp->p_flags & PPOU)
753 		(void) fprintf(cshout, " |");
754 	    if (pp->p_flags & PERR)
755 		(void) fputc('&', cshout);
756 	    hadnl = 0;
757 	}
758 	if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED) {
759 	    (void) fprintf(cshout, " (core dumped)");
760 	    hadnl = 0;
761 	}
762 	if (tp == pp->p_friends) {
763 	    if (flag & AMPERSAND) {
764 		(void) fprintf(cshout, " &");
765 		hadnl = 0;
766 	    }
767 	    if (flag & JOBDIR &&
768 		!eq(tp->p_cwd->di_name, dcwd->di_name)) {
769 		(void) fprintf(cshout, " (wd: ");
770 		dtildepr(value(STRhome), tp->p_cwd->di_name);
771 		(void) fputc(')', cshout);
772 		hadnl = 0;
773 	    }
774 	}
775 	if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) {
776 	    if (!hadnl)
777 		(void) fprintf(cshout, "\n\t");
778 	    prusage(&zru, &pp->p_rusage, &pp->p_etime,
779 		    &pp->p_btime);
780 	    hadnl = 1;
781 	}
782 	if (tp == pp->p_friends) {
783 	    if (!hadnl) {
784 		(void) fputc('\n', cshout);
785 		hadnl = 1;
786 	    }
787 	    if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
788 		(void) fprintf(cshout, "(wd now: ");
789 		dtildepr(value(STRhome), dcwd->di_name);
790 		(void) fprintf(cshout, ")\n");
791 		hadnl = 1;
792 	    }
793 	}
794     } while ((pp = pp->p_friends) != tp);
795     if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) {
796 	if (jobflags & NUMBER)
797 	    (void) fprintf(cshout, "       ");
798 	ptprint(tp);
799 	hadnl = 1;
800     }
801     (void) fflush(cshout);
802     return (jobflags);
803 }
804 
805 static void
806 ptprint(struct process *tp)
807 {
808     struct timeval tetime, diff;
809     static struct timeval ztime;
810     struct rusage ru;
811     static struct rusage zru;
812     struct process *pp = tp;
813 
814     ru = zru;
815     tetime = ztime;
816     do {
817 	ruadd(&ru, &pp->p_rusage);
818 	timersub(&pp->p_etime, &pp->p_btime, &diff);
819 	if (timercmp(&diff, &tetime, >))
820 	    tetime = diff;
821     } while ((pp = pp->p_friends) != tp);
822     prusage(&zru, &ru, &tetime, &ztime);
823 }
824 
825 /*
826  * dojobs - print all jobs
827  */
828 void
829 /*ARGSUSED*/
830 dojobs(Char **v, struct command *t)
831 {
832     struct process *pp;
833     int flag = NUMBER | NAME | REASON;
834     int     i;
835 
836     if (chkstop)
837 	chkstop = 2;
838     if (*++v) {
839 	if (v[1] || !eq(*v, STRml))
840 	    stderror(ERR_JOBS);
841 	flag |= FANCY | JOBDIR;
842     }
843     for (i = 1; i <= pmaxindex; i++)
844 	for (pp = proclist.p_next; pp; pp = pp->p_next)
845 	    if (pp->p_index == i && pp->p_pid == pp->p_jobid) {
846 		pp->p_flags &= ~PNEEDNOTE;
847 		if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED)))
848 		    pflush(pp);
849 		break;
850 	    }
851 }
852 
853 /*
854  * dofg - builtin - put the job into the foreground
855  */
856 void
857 /*ARGSUSED*/
858 dofg(Char **v, struct command *t)
859 {
860     struct process *pp;
861 
862     okpcntl();
863     ++v;
864     do {
865 	pp = pfind(*v);
866 	pstart(pp, 1);
867 	pjwait(pp);
868     } while (*v && *++v);
869 }
870 
871 /*
872  * %... - builtin - put the job into the foreground
873  */
874 void
875 /*ARGSUSED*/
876 dofg1(Char **v, struct command *t)
877 {
878     struct process *pp;
879 
880     okpcntl();
881     pp = pfind(v[0]);
882     pstart(pp, 1);
883     pjwait(pp);
884 }
885 
886 /*
887  * dobg - builtin - put the job into the background
888  */
889 void
890 /*ARGSUSED*/
891 dobg(Char **v, struct command *t)
892 {
893     struct process *pp;
894 
895     okpcntl();
896     ++v;
897     do {
898 	pp = pfind(*v);
899 	pstart(pp, 0);
900     } while (*v && *++v);
901 }
902 
903 /*
904  * %... & - builtin - put the job into the background
905  */
906 void
907 /*ARGSUSED*/
908 dobg1(Char **v, struct command *t)
909 {
910     struct process *pp;
911 
912     pp = pfind(v[0]);
913     pstart(pp, 0);
914 }
915 
916 /*
917  * dostop - builtin - stop the job
918  */
919 void
920 /*ARGSUSED*/
921 dostop(Char **v, struct command *t)
922 {
923     pkill(++v, SIGSTOP);
924 }
925 
926 /*
927  * dokill - builtin - superset of kill (1)
928  */
929 void
930 /*ARGSUSED*/
931 dokill(Char **v, struct command *t)
932 {
933     int signum = SIGTERM;
934     char *name;
935 
936     v++;
937     if (v[0] && v[0][0] == '-') {
938 	if (v[0][1] == 'l') {
939 	    if (v[1]) {
940 		if (!Isdigit(v[1][0]))
941 		    stderror(ERR_NAME | ERR_BADSIG);
942 
943 		signum = atoi(short2str(v[1]));
944 		if (signum < 0 || signum >= NSIG)
945 		    stderror(ERR_NAME | ERR_BADSIG);
946 		else if (signum == 0)
947 		    (void) fputc('0', cshout); /* 0's symbolic name is '0' */
948 		else
949 		    (void) fprintf(cshout, "%s ", sys_signame[signum]);
950 	    } else {
951 		for (signum = 1; signum < NSIG; signum++) {
952 		    (void) fprintf(cshout, "%s ", sys_signame[signum]);
953 		    if (signum == NSIG / 2)
954 			(void) fputc('\n', cshout);
955 	    	}
956 	    }
957 	    (void) fputc('\n', cshout);
958 	    return;
959 	}
960 	if (Isdigit(v[0][1])) {
961 	    signum = atoi(short2str(v[0] + 1));
962 	    if (signum < 0 || signum >= NSIG)
963 		stderror(ERR_NAME | ERR_BADSIG);
964 	}
965 	else {
966 	    if (v[0][1] == 's' && (Isspace(v[0][2]) || v[0][2] == '\0')) {
967 		v++;
968 		name = short2str(&v[0][0]);
969 	    } else {
970 		name = short2str(&v[0][1]);
971 	    }
972 
973 	    if (v[0] == NULL || v[1] == NULL) {
974 		stderror(ERR_NAME | ERR_TOOFEW);
975 		return;
976 	    }
977 
978 	    for (signum = 1; signum < NSIG; signum++)
979 		if (!strcasecmp(sys_signame[signum], name) ||
980 		    (strlen(name) > 3 && !strncasecmp("SIG", name, 3) &&
981 		     !strcasecmp(sys_signame[signum], name + 3)))
982 			break;
983 
984 	    if (signum == NSIG) {
985 		if (name[0] == '0')
986 		    signum = 0;
987 		else {
988 		    setname(vis_str(&v[0][0]));
989 		    stderror(ERR_NAME | ERR_UNKSIG);
990 		}
991 	    }
992 	}
993 	v++;
994     }
995     pkill(v, signum);
996 }
997 
998 static void
999 pkill(Char **v, int signum)
1000 {
1001     struct process *pp, *np;
1002     int jobflags = 0;
1003     int     pid, err1 = 0;
1004     sigset_t sigset;
1005     Char   *cp;
1006 
1007     sigemptyset(&sigset);
1008     sigaddset(&sigset, SIGCHLD);
1009     if (setintr)
1010 	sigaddset(&sigset, SIGINT);
1011     sigprocmask(SIG_BLOCK, &sigset, NULL);
1012     gflag = 0, tglob(v);
1013     if (gflag) {
1014 	v = globall(v);
1015 	if (v == 0)
1016 	    stderror(ERR_NAME | ERR_NOMATCH);
1017     }
1018     else {
1019 	v = gargv = saveblk(v);
1020 	trim(v);
1021     }
1022 
1023     while (v && (cp = *v)) {
1024 	if (*cp == '%') {
1025 	    np = pp = pfind(cp);
1026 	    do
1027 		jobflags |= np->p_flags;
1028 	    while ((np = np->p_friends) != pp);
1029 	    switch (signum) {
1030 
1031 	    case SIGSTOP:
1032 	    case SIGTSTP:
1033 	    case SIGTTIN:
1034 	    case SIGTTOU:
1035 		if ((jobflags & PRUNNING) == 0) {
1036 		    (void) fprintf(csherr, "%s: Already suspended\n",
1037 				   vis_str(cp));
1038 		    err1++;
1039 		    goto cont;
1040 		}
1041 		break;
1042 		/*
1043 		 * suspend a process, kill -CONT %, then type jobs; the shell
1044 		 * says it is suspended, but it is running; thanks jaap..
1045 		 */
1046 	    case SIGCONT:
1047 		pstart(pp, 0);
1048 		goto cont;
1049 	    }
1050 	    if (kill(-pp->p_jobid, signum) < 0) {
1051 		(void) fprintf(csherr, "%s: %s\n", vis_str(cp),
1052 			       strerror(errno));
1053 		err1++;
1054 	    }
1055 	    if (signum == SIGTERM || signum == SIGHUP)
1056 		(void) kill(-pp->p_jobid, SIGCONT);
1057 	}
1058 	else if (!(Isdigit(*cp) || *cp == '-'))
1059 	    stderror(ERR_NAME | ERR_JOBARGS);
1060 	else {
1061 	    char *ep;
1062 	    char *pidnam = short2str(cp);
1063 
1064 	    pid = strtol(pidnam, &ep, 10);
1065 	    if (!*pidnam || *ep) {
1066 		(void) fprintf(csherr, "%s: illegal process id\n", pidnam);
1067 		err1++;
1068 		goto cont;
1069 	    }
1070 	    if (kill((pid_t) pid, signum) < 0) {
1071 		(void) fprintf(csherr, "%d: %s\n", pid, strerror(errno));
1072 		err1++;
1073 		goto cont;
1074 	    }
1075 	    if (signum == SIGTERM || signum == SIGHUP)
1076 		(void) kill((pid_t) pid, SIGCONT);
1077 	}
1078 cont:
1079 	v++;
1080     }
1081     if (gargv)
1082 	blkfree(gargv), gargv = 0;
1083     sigprocmask(SIG_UNBLOCK, &sigset, NULL);
1084     if (err1)
1085 	stderror(ERR_SILENT);
1086 }
1087 
1088 /*
1089  * pstart - start the job in foreground/background
1090  */
1091 void
1092 pstart(struct process *pp, int foregnd)
1093 {
1094     struct process *np;
1095     sigset_t sigset, osigset;
1096     long    jobflags = 0;
1097 
1098     sigemptyset(&sigset);
1099     sigaddset(&sigset, SIGCHLD);
1100     sigprocmask(SIG_BLOCK, &sigset, &osigset);
1101     np = pp;
1102     do {
1103 	jobflags |= np->p_flags;
1104 	if (np->p_flags & (PRUNNING | PSTOPPED)) {
1105 	    np->p_flags |= PRUNNING;
1106 	    np->p_flags &= ~PSTOPPED;
1107 	    if (foregnd)
1108 		np->p_flags |= PFOREGND;
1109 	    else
1110 		np->p_flags &= ~PFOREGND;
1111 	}
1112     } while ((np = np->p_friends) != pp);
1113     if (!foregnd)
1114 	pclrcurr(pp);
1115     (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND);
1116     if (foregnd)
1117 	(void) tcsetpgrp(FSHTTY, pp->p_jobid);
1118     if (jobflags & PSTOPPED)
1119 	(void) kill(-pp->p_jobid, SIGCONT);
1120     sigprocmask(SIG_SETMASK, &osigset, NULL);
1121 }
1122 
1123 void
1124 panystop(bool neednl)
1125 {
1126     struct process *pp;
1127 
1128     chkstop = 2;
1129     for (pp = proclist.p_next; pp; pp = pp->p_next)
1130 	if (pp->p_flags & PSTOPPED)
1131 	    stderror(ERR_STOPPED, neednl ? "\n" : "");
1132 }
1133 
1134 struct process *
1135 pfind(Char *cp)
1136 {
1137     struct process *pp, *np;
1138 
1139     if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) {
1140 	if (pcurrent == NULL)
1141 	    stderror(ERR_NAME | ERR_JOBCUR);
1142 	return (pcurrent);
1143     }
1144     if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) {
1145 	if (pprevious == NULL)
1146 	    stderror(ERR_NAME | ERR_JOBPREV);
1147 	return (pprevious);
1148     }
1149     if (Isdigit(cp[1])) {
1150 	int     idx = atoi(short2str(cp + 1));
1151 
1152 	for (pp = proclist.p_next; pp; pp = pp->p_next)
1153 	    if (pp->p_index == idx && pp->p_pid == pp->p_jobid)
1154 		return (pp);
1155 	stderror(ERR_NAME | ERR_NOSUCHJOB);
1156     }
1157     np = NULL;
1158     for (pp = proclist.p_next; pp; pp = pp->p_next)
1159 	if (pp->p_pid == pp->p_jobid) {
1160 	    if (cp[1] == '?') {
1161 		Char *dp;
1162 
1163 		for (dp = pp->p_command; *dp; dp++) {
1164 		    if (*dp != cp[2])
1165 			continue;
1166 		    if (prefix(cp + 2, dp))
1167 			goto match;
1168 		}
1169 	    }
1170 	    else if (prefix(cp + 1, pp->p_command)) {
1171 	match:
1172 		if (np)
1173 		    stderror(ERR_NAME | ERR_AMBIG);
1174 		np = pp;
1175 	    }
1176 	}
1177     if (np)
1178 	return (np);
1179     stderror(ERR_NAME | (cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB));
1180     /* NOTREACHED */
1181     return (0);
1182 }
1183 
1184 
1185 /*
1186  * pgetcurr - find most recent job that is not pp, preferably stopped
1187  */
1188 static struct process *
1189 pgetcurr(struct process *pp)
1190 {
1191     struct process *np;
1192     struct process *xp = NULL;
1193 
1194     for (np = proclist.p_next; np; np = np->p_next)
1195 	if (np != pcurrent && np != pp && np->p_pid &&
1196 	    np->p_pid == np->p_jobid) {
1197 	    if (np->p_flags & PSTOPPED)
1198 		return (np);
1199 	    if (xp == NULL)
1200 		xp = np;
1201 	}
1202     return (xp);
1203 }
1204 
1205 /*
1206  * donotify - flag the job so as to report termination asynchronously
1207  */
1208 void
1209 /*ARGSUSED*/
1210 donotify(Char **v, struct command *t)
1211 {
1212     struct process *pp;
1213 
1214     pp = pfind(*++v);
1215     pp->p_flags |= PNOTIFY;
1216 }
1217 
1218 /*
1219  * Do the fork and whatever should be done in the child side that
1220  * should not be done if we are not forking at all (like for simple builtin's)
1221  * Also do everything that needs any signals fiddled with in the parent side
1222  *
1223  * Wanttty tells whether process and/or tty pgrps are to be manipulated:
1224  *	-1:	leave tty alone; inherit pgrp from parent
1225  *	 0:	already have tty; manipulate process pgrps only
1226  *	 1:	want to claim tty; manipulate process and tty pgrps
1227  * It is usually just the value of tpgrp.
1228  */
1229 
1230 int
1231 pfork(struct command *t, int wanttty)
1232 {
1233     int pid;
1234     bool    ignint = 0;
1235     int     pgrp;
1236     sigset_t sigset, osigset;
1237 
1238     /*
1239      * A child will be uninterruptible only under very special conditions.
1240      * Remember that the semantics of '&' is implemented by disconnecting the
1241      * process from the tty so signals do not need to ignored just for '&'.
1242      * Thus signals are set to default action for children unless: we have had
1243      * an "onintr -" (then specifically ignored) we are not playing with
1244      * signals (inherit action)
1245      */
1246     if (setintr)
1247 	ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
1248 	    || (gointr && eq(gointr, STRminus));
1249     /*
1250      * Check for maximum nesting of 16 processes to avoid Forking loops
1251      */
1252     if (child == 16)
1253 	stderror(ERR_NESTING, 16);
1254     /*
1255      * Hold SIGCHLD until we have the process installed in our table.
1256      */
1257     sigemptyset(&sigset);
1258     sigaddset(&sigset, SIGCHLD);
1259     sigprocmask(SIG_BLOCK, &sigset, &osigset);
1260     while ((pid = fork()) < 0)
1261 	if (setintr == 0)
1262 	    (void) sleep(FORKSLEEP);
1263 	else {
1264 	    sigprocmask(SIG_SETMASK, &osigset, NULL);
1265 	    stderror(ERR_NOPROC);
1266 	}
1267     if (pid == 0) {
1268 	settimes();
1269 	pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
1270 	pflushall();
1271 	pcurrjob = NULL;
1272 	child++;
1273 	if (setintr) {
1274 	    setintr = 0;	/* until I think otherwise */
1275 	    /*
1276 	     * Children just get blown away on SIGINT, SIGQUIT unless "onintr
1277 	     * -" seen.
1278 	     */
1279 	    (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
1280 	    (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
1281 	    if (wanttty >= 0) {
1282 		/* make stoppable */
1283 		(void) signal(SIGTSTP, SIG_DFL);
1284 		(void) signal(SIGTTIN, SIG_DFL);
1285 		(void) signal(SIGTTOU, SIG_DFL);
1286 	    }
1287 	    (void) signal(SIGTERM, parterm);
1288 	}
1289 	else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) {
1290 	    (void) signal(SIGINT, SIG_IGN);
1291 	    (void) signal(SIGQUIT, SIG_IGN);
1292 	}
1293 	pgetty(wanttty, pgrp);
1294 	/*
1295 	 * Nohup and nice apply only to NODE_COMMAND's but it would be nice
1296 	 * (?!?) if you could say "nohup (foo;bar)" Then the parser would have
1297 	 * to know about nice/nohup/time
1298 	 */
1299 	if (t->t_dflg & F_NOHUP)
1300 	    (void) signal(SIGHUP, SIG_IGN);
1301 	if (t->t_dflg & F_NICE)
1302 	    (void) setpriority(PRIO_PROCESS, 0, t->t_nice);
1303     }
1304     else {
1305 	if (wanttty >= 0)
1306 	    (void) setpgid(pid, pcurrjob ? pcurrjob->p_jobid : pid);
1307 	palloc(pid, t);
1308 	sigprocmask(SIG_SETMASK, &osigset, NULL);
1309     }
1310 
1311     return (pid);
1312 }
1313 
1314 static void
1315 okpcntl(void)
1316 {
1317     if (tpgrp == -1)
1318 	stderror(ERR_JOBCONTROL);
1319     if (tpgrp == 0)
1320 	stderror(ERR_JOBCTRLSUB);
1321 }
1322 
1323 /*
1324  * if we don't have vfork(), things can still go in the wrong order
1325  * resulting in the famous 'Stopped (tty output)'. But some systems
1326  * don't permit the setpgid() call, (these are more recent secure
1327  * systems such as ibm's aix). Then we'd rather print an error message
1328  * than hang the shell!
1329  * I am open to suggestions how to fix that.
1330  */
1331 void
1332 pgetty(int wanttty, int pgrp)
1333 {
1334     sigset_t sigset, osigset;
1335 
1336     /*
1337      * christos: I am blocking the tty signals till I've set things
1338      * correctly....
1339      */
1340     if (wanttty > 0) {
1341 	sigemptyset(&sigset);
1342 	sigaddset(&sigset, SIGTSTP);
1343 	sigaddset(&sigset, SIGTTIN);
1344 	sigaddset(&sigset, SIGTTOU);
1345 	sigprocmask(SIG_BLOCK, &sigset, &osigset);
1346     }
1347     /*
1348      * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
1349      * Don't check for tpgrp >= 0 so even non-interactive shells give
1350      * background jobs process groups Same for the comparison in the other part
1351      * of the #ifdef
1352      */
1353     if (wanttty >= 0)
1354 	if (setpgid(0, pgrp) == -1) {
1355 	    (void) fprintf(csherr, "csh: setpgid error.\n");
1356 	    xexit(0);
1357 	}
1358 
1359     if (wanttty > 0) {
1360 	(void) tcsetpgrp(FSHTTY, pgrp);
1361 	sigprocmask(SIG_SETMASK, &osigset, NULL);
1362     }
1363 
1364     if (tpgrp > 0)
1365 	tpgrp = 0;		/* gave tty away */
1366 }
1367