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