xref: /netbsd-src/bin/sh/jobs.c (revision 27578b9aac214cc7796ead81dcc5427e79d5f2a0)
1 /*	$NetBSD: jobs.c,v 1.40 2001/09/16 16:34:23 wiz Exp $	*/
2 
3 /*-
4  * Copyright (c) 1991, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Kenneth Almquist.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  */
38 
39 #include <sys/cdefs.h>
40 #ifndef lint
41 #if 0
42 static char sccsid[] = "@(#)jobs.c	8.5 (Berkeley) 5/4/95";
43 #else
44 __RCSID("$NetBSD: jobs.c,v 1.40 2001/09/16 16:34:23 wiz Exp $");
45 #endif
46 #endif /* not lint */
47 
48 #include <fcntl.h>
49 #include <signal.h>
50 #include <errno.h>
51 #include <unistd.h>
52 #include <stdlib.h>
53 #include <paths.h>
54 #include <sys/types.h>
55 #include <sys/param.h>
56 #ifdef BSD
57 #include <sys/wait.h>
58 #include <sys/time.h>
59 #include <sys/resource.h>
60 #endif
61 #include <sys/ioctl.h>
62 
63 #include "shell.h"
64 #if JOBS
65 #if OLD_TTY_DRIVER
66 #include "sgtty.h"
67 #else
68 #include <termios.h>
69 #endif
70 #undef CEOF			/* syntax.h redefines this */
71 #endif
72 #include "redir.h"
73 #include "show.h"
74 #include "main.h"
75 #include "parser.h"
76 #include "nodes.h"
77 #include "jobs.h"
78 #include "options.h"
79 #include "trap.h"
80 #include "syntax.h"
81 #include "input.h"
82 #include "output.h"
83 #include "memalloc.h"
84 #include "error.h"
85 #include "mystring.h"
86 
87 
88 struct job *jobtab;		/* array of jobs */
89 int njobs;			/* size of array */
90 MKINIT short backgndpid = -1;	/* pid of last background process */
91 #if JOBS
92 int initialpgrp;		/* pgrp of shell on invocation */
93 short curjob;			/* current job */
94 #endif
95 
96 STATIC void restartjob __P((struct job *));
97 STATIC void freejob __P((struct job *));
98 STATIC struct job *getjob __P((char *));
99 STATIC int dowait __P((int, struct job *));
100 STATIC int onsigchild __P((void));
101 STATIC int waitproc __P((int, struct job *, int *));
102 STATIC void cmdtxt __P((union node *));
103 STATIC void cmdputs __P((const char *));
104 
105 
106 /*
107  * Turn job control on and off.
108  *
109  * Note:  This code assumes that the third arg to ioctl is a character
110  * pointer, which is true on Berkeley systems but not System V.  Since
111  * System V doesn't have job control yet, this isn't a problem now.
112  */
113 
114 MKINIT int jobctl;
115 
116 void
117 setjobctl(on)
118 	int on;
119 {
120 #ifdef OLD_TTY_DRIVER
121 	int ldisc;
122 #endif
123 
124 	if (on == jobctl || rootshell == 0)
125 		return;
126 	if (on) {
127 		do { /* while we are in the background */
128 #ifdef OLD_TTY_DRIVER
129 			if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
130 #else
131 			initialpgrp = tcgetpgrp(2);
132 			if (initialpgrp < 0) {
133 #endif
134 				out2str("sh: can't access tty; job control turned off\n");
135 				mflag = 0;
136 				return;
137 			}
138 			if (initialpgrp == -1)
139 				initialpgrp = getpgrp();
140 			else if (initialpgrp != getpgrp()) {
141 				killpg(initialpgrp, SIGTTIN);
142 				continue;
143 			}
144 		} while (0);
145 #ifdef OLD_TTY_DRIVER
146 		if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {
147 			out2str("sh: need new tty driver to run job control; job control turned off\n");
148 			mflag = 0;
149 			return;
150 		}
151 #endif
152 		setsignal(SIGTSTP);
153 		setsignal(SIGTTOU);
154 		setsignal(SIGTTIN);
155 		setpgid(0, rootpid);
156 #ifdef OLD_TTY_DRIVER
157 		ioctl(2, TIOCSPGRP, (char *)&rootpid);
158 #else
159 		tcsetpgrp(2, rootpid);
160 #endif
161 	} else { /* turning job control off */
162 		setpgid(0, initialpgrp);
163 #ifdef OLD_TTY_DRIVER
164 		ioctl(2, TIOCSPGRP, (char *)&initialpgrp);
165 #else
166 		tcsetpgrp(2, initialpgrp);
167 #endif
168 		setsignal(SIGTSTP);
169 		setsignal(SIGTTOU);
170 		setsignal(SIGTTIN);
171 	}
172 	jobctl = on;
173 }
174 
175 
176 #ifdef mkinit
177 INCLUDE <stdlib.h>
178 
179 SHELLPROC {
180 	backgndpid = -1;
181 #if JOBS
182 	jobctl = 0;
183 #endif
184 }
185 
186 #endif
187 
188 
189 
190 #if JOBS
191 int
192 fgcmd(argc, argv)
193 	int argc;
194 	char **argv;
195 {
196 	struct job *jp;
197 	int pgrp;
198 	int status;
199 
200 	jp = getjob(argv[1]);
201 	if (jp->jobctl == 0)
202 		error("job not created under job control");
203 	pgrp = jp->ps[0].pid;
204 #ifdef OLD_TTY_DRIVER
205 	ioctl(2, TIOCSPGRP, (char *)&pgrp);
206 #else
207 	tcsetpgrp(2, pgrp);
208 #endif
209 	restartjob(jp);
210 	INTOFF;
211 	status = waitforjob(jp);
212 	INTON;
213 	return status;
214 }
215 
216 
217 int
218 bgcmd(argc, argv)
219 	int argc;
220 	char **argv;
221 {
222 	struct job *jp;
223 
224 	do {
225 		jp = getjob(*++argv);
226 		if (jp->jobctl == 0)
227 			error("job not created under job control");
228 		restartjob(jp);
229 	} while (--argc > 1);
230 	return 0;
231 }
232 
233 
234 STATIC void
235 restartjob(jp)
236 	struct job *jp;
237 {
238 	struct procstat *ps;
239 	int i;
240 
241 	if (jp->state == JOBDONE)
242 		return;
243 	INTOFF;
244 	killpg(jp->ps[0].pid, SIGCONT);
245 	for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
246 		if (WIFSTOPPED(ps->status)) {
247 			ps->status = -1;
248 			jp->state = 0;
249 		}
250 	}
251 	INTON;
252 }
253 #endif
254 
255 
256 int
257 jobscmd(argc, argv)
258 	int argc;
259 	char **argv;
260 {
261 	showjobs(0);
262 	return 0;
263 }
264 
265 
266 /*
267  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
268  * statuses have changed since the last call to showjobs.
269  *
270  * If the shell is interrupted in the process of creating a job, the
271  * result may be a job structure containing zero processes.  Such structures
272  * will be freed here.
273  */
274 
275 void
276 showjobs(change)
277 	int change;
278 {
279 	int jobno;
280 	int procno;
281 	int i;
282 	struct job *jp;
283 	struct procstat *ps;
284 	int col;
285 	char s[64];
286 
287 	TRACE(("showjobs(%d) called\n", change));
288 	while (dowait(0, (struct job *)NULL) > 0);
289 	for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
290 		if (! jp->used)
291 			continue;
292 		if (jp->nprocs == 0) {
293 			freejob(jp);
294 			continue;
295 		}
296 		if (change && ! jp->changed)
297 			continue;
298 		procno = jp->nprocs;
299 		for (ps = jp->ps ; ; ps++) {	/* for each process */
300 			if (ps == jp->ps)
301 				fmtstr(s, 64, "[%d] %ld ", jobno,
302 				    (long)ps->pid);
303 			else
304 				fmtstr(s, 64, "    %ld ",
305 				    (long)ps->pid);
306 			out1str(s);
307 			col = strlen(s);
308 			s[0] = '\0';
309 			if (ps->status == -1) {
310 				/* don't print anything */
311 			} else if (WIFEXITED(ps->status)) {
312 				fmtstr(s, 64, "Exit %d",
313 				       WEXITSTATUS(ps->status));
314 			} else {
315 #if JOBS
316 				if (WIFSTOPPED(ps->status))
317 					i = WSTOPSIG(ps->status);
318 				else /* WIFSIGNALED(ps->status) */
319 #endif
320 					i = WTERMSIG(ps->status);
321 				if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
322 					scopy(sys_siglist[i & 0x7F], s);
323 				else
324 					fmtstr(s, 64, "Signal %d", i & 0x7F);
325 				if (WCOREDUMP(ps->status))
326 					strcat(s, " (core dumped)");
327 			}
328 			out1str(s);
329 			col += strlen(s);
330 			do {
331 				out1c(' ');
332 				col++;
333 			} while (col < 30);
334 			out1str(ps->cmd);
335 			out1c('\n');
336 			if (--procno <= 0)
337 				break;
338 		}
339 		jp->changed = 0;
340 		if (jp->state == JOBDONE) {
341 			freejob(jp);
342 		}
343 	}
344 }
345 
346 
347 /*
348  * Mark a job structure as unused.
349  */
350 
351 STATIC void
352 freejob(jp)
353 	struct job *jp;
354 	{
355 	struct procstat *ps;
356 	int i;
357 
358 	INTOFF;
359 	for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
360 		if (ps->cmd != nullstr)
361 			ckfree(ps->cmd);
362 	}
363 	if (jp->ps != &jp->ps0)
364 		ckfree(jp->ps);
365 	jp->used = 0;
366 #if JOBS
367 	if (curjob == jp - jobtab + 1)
368 		curjob = 0;
369 #endif
370 	INTON;
371 }
372 
373 
374 
375 int
376 waitcmd(argc, argv)
377 	int argc;
378 	char **argv;
379 {
380 	struct job *job;
381 	int status, retval;
382 	struct job *jp;
383 
384 	if (argc > 1) {
385 		job = getjob(argv[1]);
386 	} else {
387 		job = NULL;
388 	}
389 	for (;;) {	/* loop until process terminated or stopped */
390 		if (job != NULL) {
391 			if (job->state) {
392 				status = job->ps[job->nprocs - 1].status;
393 				if (WIFEXITED(status))
394 					retval = WEXITSTATUS(status);
395 #if JOBS
396 				else if (WIFSTOPPED(status))
397 					retval = WSTOPSIG(status) + 128;
398 #endif
399 				else {
400 					/* XXX: limits number of signals */
401 					retval = WTERMSIG(status) + 128;
402 				}
403 				if (! iflag)
404 					freejob(job);
405 				return retval;
406 			}
407 		} else {
408 			for (jp = jobtab ; ; jp++) {
409 				if (jp >= jobtab + njobs) {	/* no running procs */
410 					return 0;
411 				}
412 				if (jp->used && jp->state == 0)
413 					break;
414 			}
415 		}
416 		dowait(1, (struct job *)NULL);
417 	}
418 }
419 
420 
421 
422 int
423 jobidcmd(argc, argv)
424 	int argc;
425 	char **argv;
426 {
427 	struct job *jp;
428 	int i;
429 
430 	jp = getjob(argv[1]);
431 	for (i = 0 ; i < jp->nprocs ; ) {
432 		out1fmt("%ld", (long)jp->ps[i].pid);
433 		out1c(++i < jp->nprocs? ' ' : '\n');
434 	}
435 	return 0;
436 }
437 
438 
439 
440 /*
441  * Convert a job name to a job structure.
442  */
443 
444 STATIC struct job *
445 getjob(name)
446 	char *name;
447 	{
448 	int jobno;
449 	struct job *jp;
450 	int pid;
451 	int i;
452 
453 	if (name == NULL) {
454 #if JOBS
455 currentjob:
456 		if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
457 			error("No current job");
458 		return &jobtab[jobno - 1];
459 #else
460 		error("No current job");
461 #endif
462 	} else if (name[0] == '%') {
463 		if (is_digit(name[1])) {
464 			jobno = number(name + 1);
465 			if (jobno > 0 && jobno <= njobs
466 			 && jobtab[jobno - 1].used != 0)
467 				return &jobtab[jobno - 1];
468 #if JOBS
469 		} else if (name[1] == '%' && name[2] == '\0') {
470 			goto currentjob;
471 #endif
472 		} else {
473 			struct job *found = NULL;
474 			for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
475 				if (jp->used && jp->nprocs > 0
476 				 && prefix(name + 1, jp->ps[0].cmd)) {
477 					if (found)
478 						error("%s: ambiguous", name);
479 					found = jp;
480 				}
481 			}
482 			if (found)
483 				return found;
484 		}
485 	} else if (is_number(name)) {
486 		pid = number(name);
487 		for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
488 			if (jp->used && jp->nprocs > 0
489 			 && jp->ps[jp->nprocs - 1].pid == pid)
490 				return jp;
491 		}
492 	}
493 	error("No such job: %s", name);
494 	/* NOTREACHED */
495 }
496 
497 
498 
499 /*
500  * Return a new job structure,
501  */
502 
503 struct job *
504 makejob(node, nprocs)
505 	union node *node;
506 	int nprocs;
507 {
508 	int i;
509 	struct job *jp;
510 
511 	for (i = njobs, jp = jobtab ; ; jp++) {
512 		if (--i < 0) {
513 			INTOFF;
514 			if (njobs == 0) {
515 				jobtab = ckmalloc(4 * sizeof jobtab[0]);
516 			} else {
517 				jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
518 				memcpy(jp, jobtab, njobs * sizeof jp[0]);
519 				/* Relocate `ps' pointers */
520 				for (i = 0; i < njobs; i++)
521 					if (jp[i].ps == &jobtab[i].ps0)
522 						jp[i].ps = &jp[i].ps0;
523 				ckfree(jobtab);
524 				jobtab = jp;
525 			}
526 			jp = jobtab + njobs;
527 			for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
528 			INTON;
529 			break;
530 		}
531 		if (jp->used == 0)
532 			break;
533 	}
534 	INTOFF;
535 	jp->state = 0;
536 	jp->used = 1;
537 	jp->changed = 0;
538 	jp->nprocs = 0;
539 #if JOBS
540 	jp->jobctl = jobctl;
541 #endif
542 	if (nprocs > 1) {
543 		jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
544 	} else {
545 		jp->ps = &jp->ps0;
546 	}
547 	INTON;
548 	TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
549 	    jp - jobtab + 1));
550 	return jp;
551 }
552 
553 
554 /*
555  * Fork off a subshell.  If we are doing job control, give the subshell its
556  * own process group.  Jp is a job structure that the job is to be added to.
557  * N is the command that will be evaluated by the child.  Both jp and n may
558  * be NULL.  The mode parameter can be one of the following:
559  *	FORK_FG - Fork off a foreground process.
560  *	FORK_BG - Fork off a background process.
561  *	FORK_NOJOB - Like FORK_FG, but don't give the process its own
562  *		     process group even if job control is on.
563  *
564  * When job control is turned off, background processes have their standard
565  * input redirected to /dev/null (except for the second and later processes
566  * in a pipeline).
567  */
568 
569 int
570 forkshell(jp, n, mode)
571 	union node *n;
572 	struct job *jp;
573 	int mode;
574 {
575 	int pid;
576 	int pgrp;
577 	const char *devnull = _PATH_DEVNULL;
578 	const char *nullerr = "Can't open %s";
579 
580 	TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long)n,
581 	    mode));
582 	INTOFF;
583 	pid = fork();
584 	if (pid == -1) {
585 		TRACE(("Fork failed, errno=%d\n", errno));
586 		INTON;
587 		error("Cannot fork");
588 	}
589 	if (pid == 0) {
590 		struct job *p;
591 		int wasroot;
592 		int i;
593 
594 		TRACE(("Child shell %d\n", getpid()));
595 		wasroot = rootshell;
596 		rootshell = 0;
597 		for (i = njobs, p = jobtab ; --i >= 0 ; p++)
598 			if (p->used)
599 				freejob(p);
600 		closescript();
601 		INTON;
602 		clear_traps();
603 #if JOBS
604 		jobctl = 0;		/* do job control only in root shell */
605 		if (wasroot && mode != FORK_NOJOB && mflag) {
606 			if (jp == NULL || jp->nprocs == 0)
607 				pgrp = getpid();
608 			else
609 				pgrp = jp->ps[0].pid;
610 			setpgid(0, pgrp);
611 			if (mode == FORK_FG) {
612 				/*** this causes superfluous TIOCSPGRPS ***/
613 #ifdef OLD_TTY_DRIVER
614 				if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0)
615 					error("TIOCSPGRP failed, errno=%d", errno);
616 #else
617 				if (tcsetpgrp(2, pgrp) < 0)
618 					error("tcsetpgrp failed, errno=%d", errno);
619 #endif
620 			}
621 			setsignal(SIGTSTP);
622 			setsignal(SIGTTOU);
623 		} else if (mode == FORK_BG) {
624 			ignoresig(SIGINT);
625 			ignoresig(SIGQUIT);
626 			if ((jp == NULL || jp->nprocs == 0) &&
627 			    ! fd0_redirected_p ()) {
628 				close(0);
629 				if (open(devnull, O_RDONLY) != 0)
630 					error(nullerr, devnull);
631 			}
632 		}
633 #else
634 		if (mode == FORK_BG) {
635 			ignoresig(SIGINT);
636 			ignoresig(SIGQUIT);
637 			if ((jp == NULL || jp->nprocs == 0) &&
638 			    ! fd0_redirected_p ()) {
639 				close(0);
640 				if (open(devnull, O_RDONLY) != 0)
641 					error(nullerr, devnull);
642 			}
643 		}
644 #endif
645 		if (wasroot && iflag) {
646 			setsignal(SIGINT);
647 			setsignal(SIGQUIT);
648 			setsignal(SIGTERM);
649 		}
650 		return pid;
651 	}
652 	if (rootshell && mode != FORK_NOJOB && mflag) {
653 		if (jp == NULL || jp->nprocs == 0)
654 			pgrp = pid;
655 		else
656 			pgrp = jp->ps[0].pid;
657 		setpgid(pid, pgrp);
658 	}
659 	if (mode == FORK_BG)
660 		backgndpid = pid;		/* set $! */
661 	if (jp) {
662 		struct procstat *ps = &jp->ps[jp->nprocs++];
663 		ps->pid = pid;
664 		ps->status = -1;
665 		ps->cmd = nullstr;
666 		if (iflag && rootshell && n)
667 			ps->cmd = commandtext(n);
668 	}
669 	INTON;
670 	TRACE(("In parent shell:  child = %d\n", pid));
671 	return pid;
672 }
673 
674 
675 
676 /*
677  * Wait for job to finish.
678  *
679  * Under job control we have the problem that while a child process is
680  * running interrupts generated by the user are sent to the child but not
681  * to the shell.  This means that an infinite loop started by an inter-
682  * active user may be hard to kill.  With job control turned off, an
683  * interactive user may place an interactive program inside a loop.  If
684  * the interactive program catches interrupts, the user doesn't want
685  * these interrupts to also abort the loop.  The approach we take here
686  * is to have the shell ignore interrupt signals while waiting for a
687  * forground process to terminate, and then send itself an interrupt
688  * signal if the child process was terminated by an interrupt signal.
689  * Unfortunately, some programs want to do a bit of cleanup and then
690  * exit on interrupt; unless these processes terminate themselves by
691  * sending a signal to themselves (instead of calling exit) they will
692  * confuse this approach.
693  */
694 
695 int
696 waitforjob(jp)
697 	struct job *jp;
698 	{
699 #if JOBS
700 	int mypgrp = getpgrp();
701 #endif
702 	int status;
703 	int st;
704 
705 	INTOFF;
706 	TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
707 	while (jp->state == 0) {
708 		dowait(1, jp);
709 	}
710 #if JOBS
711 	if (jp->jobctl) {
712 #ifdef OLD_TTY_DRIVER
713 		if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0)
714 			error("TIOCSPGRP failed, errno=%d\n", errno);
715 #else
716 		if (tcsetpgrp(2, mypgrp) < 0)
717 			error("tcsetpgrp failed, errno=%d\n", errno);
718 #endif
719 	}
720 	if (jp->state == JOBSTOPPED)
721 		curjob = jp - jobtab + 1;
722 #endif
723 	status = jp->ps[jp->nprocs - 1].status;
724 	/* convert to 8 bits */
725 	if (WIFEXITED(status))
726 		st = WEXITSTATUS(status);
727 #if JOBS
728 	else if (WIFSTOPPED(status))
729 		st = WSTOPSIG(status) + 128;
730 #endif
731 	else
732 		st = WTERMSIG(status) + 128;
733 #if JOBS
734 	if (jp->jobctl) {
735 		/*
736 		 * This is truly gross.
737 		 * If we're doing job control, then we did a TIOCSPGRP which
738 		 * caused us (the shell) to no longer be in the controlling
739 		 * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
740 		 * intuit from the subprocess exit status whether a SIGINT
741 		 * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
742 		 */
743 		if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
744 			raise(SIGINT);
745 	}
746 #endif
747 	if (! JOBS || jp->state == JOBDONE)
748 		freejob(jp);
749 	INTON;
750 	return st;
751 }
752 
753 
754 
755 /*
756  * Wait for a process to terminate.
757  */
758 
759 STATIC int
760 dowait(block, job)
761 	int block;
762 	struct job *job;
763 {
764 	int pid;
765 	int status;
766 	struct procstat *sp;
767 	struct job *jp;
768 	struct job *thisjob;
769 	int done;
770 	int stopped;
771 	int core;
772 	int sig;
773 
774 	TRACE(("dowait(%d) called\n", block));
775 	do {
776 		pid = waitproc(block, job, &status);
777 		TRACE(("wait returns %d, status=%d\n", pid, status));
778 	} while (pid == -1 && errno == EINTR);
779 	if (pid <= 0)
780 		return pid;
781 	INTOFF;
782 	thisjob = NULL;
783 	for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
784 		if (jp->used) {
785 			done = 1;
786 			stopped = 1;
787 			for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
788 				if (sp->pid == -1)
789 					continue;
790 				if (sp->pid == pid) {
791 					TRACE(("Changing status of proc %d from 0x%x to 0x%x\n", pid, sp->status, status));
792 					sp->status = status;
793 					thisjob = jp;
794 				}
795 				if (sp->status == -1)
796 					stopped = 0;
797 				else if (WIFSTOPPED(sp->status))
798 					done = 0;
799 			}
800 			if (stopped) {		/* stopped or done */
801 				int state = done? JOBDONE : JOBSTOPPED;
802 				if (jp->state != state) {
803 					TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
804 					jp->state = state;
805 #if JOBS
806 					if (done && curjob == jp - jobtab + 1)
807 						curjob = 0;		/* no current job */
808 #endif
809 				}
810 			}
811 		}
812 	}
813 	INTON;
814 	if (! rootshell || ! iflag || (job && thisjob == job)) {
815 		core = WCOREDUMP(status);
816 #if JOBS
817 		if (WIFSTOPPED(status)) sig = WSTOPSIG(status);
818 		else
819 #endif
820 		if (WIFEXITED(status)) sig = 0;
821 		else sig = WTERMSIG(status);
822 
823 		if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
824 			if (thisjob != job)
825 				outfmt(out2, "%d: ", pid);
826 #if JOBS
827 			if (sig == SIGTSTP && rootshell && iflag)
828 				outfmt(out2, "%%%ld ",
829 				    (long)(job - jobtab + 1));
830 #endif
831 			if (sig < NSIG && sys_siglist[sig])
832 				out2str(sys_siglist[sig]);
833 			else
834 				outfmt(out2, "Signal %d", sig);
835 			if (core)
836 				out2str(" - core dumped");
837 			out2c('\n');
838 			flushout(&errout);
839 		} else {
840 			TRACE(("Not printing status: status=%d, sig=%d\n",
841 			       status, sig));
842 		}
843 	} else {
844 		TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell, job));
845 		if (thisjob)
846 			thisjob->changed = 1;
847 	}
848 	return pid;
849 }
850 
851 
852 
853 /*
854  * Do a wait system call.  If job control is compiled in, we accept
855  * stopped processes.  If block is zero, we return a value of zero
856  * rather than blocking.
857  *
858  * System V doesn't have a non-blocking wait system call.  It does
859  * have a SIGCLD signal that is sent to a process when one of it's
860  * children dies.  The obvious way to use SIGCLD would be to install
861  * a handler for SIGCLD which simply bumped a counter when a SIGCLD
862  * was received, and have waitproc bump another counter when it got
863  * the status of a process.  Waitproc would then know that a wait
864  * system call would not block if the two counters were different.
865  * This approach doesn't work because if a process has children that
866  * have not been waited for, System V will send it a SIGCLD when it
867  * installs a signal handler for SIGCLD.  What this means is that when
868  * a child exits, the shell will be sent SIGCLD signals continuously
869  * until is runs out of stack space, unless it does a wait call before
870  * restoring the signal handler.  The code below takes advantage of
871  * this (mis)feature by installing a signal handler for SIGCLD and
872  * then checking to see whether it was called.  If there are any
873  * children to be waited for, it will be.
874  *
875  * If neither SYSV nor BSD is defined, we don't implement nonblocking
876  * waits at all.  In this case, the user will not be informed when
877  * a background process until the next time she runs a real program
878  * (as opposed to running a builtin command or just typing return),
879  * and the jobs command may give out of date information.
880  */
881 
882 #ifdef SYSV
883 STATIC int gotsigchild;
884 
885 STATIC int onsigchild() {
886 	gotsigchild = 1;
887 }
888 #endif
889 
890 
891 STATIC int
892 waitproc(block, jp, status)
893 	int block;
894 	struct job *jp;
895 	int *status;
896 {
897 #ifdef BSD
898 	int flags = 0;
899 
900 #if JOBS
901 	if (jp != NULL && jp->jobctl)
902 		flags |= WUNTRACED;
903 #endif
904 	if (block == 0)
905 		flags |= WNOHANG;
906 	return wait3(status, flags, (struct rusage *)NULL);
907 #else
908 #ifdef SYSV
909 	int (*save)();
910 
911 	if (block == 0) {
912 		gotsigchild = 0;
913 		save = signal(SIGCLD, onsigchild);
914 		signal(SIGCLD, save);
915 		if (gotsigchild == 0)
916 			return 0;
917 	}
918 	return wait(status);
919 #else
920 	if (block == 0)
921 		return 0;
922 	return wait(status);
923 #endif
924 #endif
925 }
926 
927 /*
928  * return 1 if there are stopped jobs, otherwise 0
929  */
930 int job_warning = 0;
931 int
932 stoppedjobs()
933 {
934 	int jobno;
935 	struct job *jp;
936 
937 	if (job_warning)
938 		return (0);
939 	for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
940 		if (jp->used == 0)
941 			continue;
942 		if (jp->state == JOBSTOPPED) {
943 			out2str("You have stopped jobs.\n");
944 			job_warning = 2;
945 			return (1);
946 		}
947 	}
948 
949 	return (0);
950 }
951 
952 /*
953  * Return a string identifying a command (to be printed by the
954  * jobs command.
955  */
956 
957 STATIC char *cmdnextc;
958 STATIC int cmdnleft;
959 #define MAXCMDTEXT	200
960 
961 char *
962 commandtext(n)
963 	union node *n;
964 	{
965 	char *name;
966 
967 	cmdnextc = name = ckmalloc(MAXCMDTEXT);
968 	cmdnleft = MAXCMDTEXT - 4;
969 	cmdtxt(n);
970 	*cmdnextc = '\0';
971 	return name;
972 }
973 
974 
975 STATIC void
976 cmdtxt(n)
977 	union node *n;
978 	{
979 	union node *np;
980 	struct nodelist *lp;
981 	const char *p;
982 	int i;
983 	char s[2];
984 
985 	if (n == NULL)
986 		return;
987 	switch (n->type) {
988 	case NSEMI:
989 		cmdtxt(n->nbinary.ch1);
990 		cmdputs("; ");
991 		cmdtxt(n->nbinary.ch2);
992 		break;
993 	case NAND:
994 		cmdtxt(n->nbinary.ch1);
995 		cmdputs(" && ");
996 		cmdtxt(n->nbinary.ch2);
997 		break;
998 	case NOR:
999 		cmdtxt(n->nbinary.ch1);
1000 		cmdputs(" || ");
1001 		cmdtxt(n->nbinary.ch2);
1002 		break;
1003 	case NPIPE:
1004 		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
1005 			cmdtxt(lp->n);
1006 			if (lp->next)
1007 				cmdputs(" | ");
1008 		}
1009 		break;
1010 	case NSUBSHELL:
1011 		cmdputs("(");
1012 		cmdtxt(n->nredir.n);
1013 		cmdputs(")");
1014 		break;
1015 	case NREDIR:
1016 	case NBACKGND:
1017 		cmdtxt(n->nredir.n);
1018 		break;
1019 	case NIF:
1020 		cmdputs("if ");
1021 		cmdtxt(n->nif.test);
1022 		cmdputs("; then ");
1023 		cmdtxt(n->nif.ifpart);
1024 		cmdputs("...");
1025 		break;
1026 	case NWHILE:
1027 		cmdputs("while ");
1028 		goto until;
1029 	case NUNTIL:
1030 		cmdputs("until ");
1031 until:
1032 		cmdtxt(n->nbinary.ch1);
1033 		cmdputs("; do ");
1034 		cmdtxt(n->nbinary.ch2);
1035 		cmdputs("; done");
1036 		break;
1037 	case NFOR:
1038 		cmdputs("for ");
1039 		cmdputs(n->nfor.var);
1040 		cmdputs(" in ...");
1041 		break;
1042 	case NCASE:
1043 		cmdputs("case ");
1044 		cmdputs(n->ncase.expr->narg.text);
1045 		cmdputs(" in ...");
1046 		break;
1047 	case NDEFUN:
1048 		cmdputs(n->narg.text);
1049 		cmdputs("() ...");
1050 		break;
1051 	case NCMD:
1052 		for (np = n->ncmd.args ; np ; np = np->narg.next) {
1053 			cmdtxt(np);
1054 			if (np->narg.next)
1055 				cmdputs(" ");
1056 		}
1057 		for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
1058 			cmdputs(" ");
1059 			cmdtxt(np);
1060 		}
1061 		break;
1062 	case NARG:
1063 		cmdputs(n->narg.text);
1064 		break;
1065 	case NTO:
1066 		p = ">";  i = 1;  goto redir;
1067 	case NAPPEND:
1068 		p = ">>";  i = 1;  goto redir;
1069 	case NTOFD:
1070 		p = ">&";  i = 1;  goto redir;
1071 	case NFROM:
1072 		p = "<";  i = 0;  goto redir;
1073 	case NFROMFD:
1074 		p = "<&";  i = 0;  goto redir;
1075 	case NFROMTO:
1076 		p = "<>";  i = 0;  goto redir;
1077 redir:
1078 		if (n->nfile.fd != i) {
1079 			s[0] = n->nfile.fd + '0';
1080 			s[1] = '\0';
1081 			cmdputs(s);
1082 		}
1083 		cmdputs(p);
1084 		if (n->type == NTOFD || n->type == NFROMFD) {
1085 			s[0] = n->ndup.dupfd + '0';
1086 			s[1] = '\0';
1087 			cmdputs(s);
1088 		} else {
1089 			cmdtxt(n->nfile.fname);
1090 		}
1091 		break;
1092 	case NHERE:
1093 	case NXHERE:
1094 		cmdputs("<<...");
1095 		break;
1096 	default:
1097 		cmdputs("???");
1098 		break;
1099 	}
1100 }
1101 
1102 
1103 
1104 STATIC void
1105 cmdputs(s)
1106 	const char *s;
1107 	{
1108 	const char *p;
1109 	char *q;
1110 	char c;
1111 	int subtype = 0;
1112 
1113 	if (cmdnleft <= 0)
1114 		return;
1115 	p = s;
1116 	q = cmdnextc;
1117 	while ((c = *p++) != '\0') {
1118 		if (c == CTLESC)
1119 			*q++ = *p++;
1120 		else if (c == CTLVAR) {
1121 			*q++ = '$';
1122 			if (--cmdnleft > 0)
1123 				*q++ = '{';
1124 			subtype = *p++;
1125 		} else if (c == '=' && subtype != 0) {
1126 			*q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
1127 			subtype = 0;
1128 		} else if (c == CTLENDVAR) {
1129 			*q++ = '}';
1130 		} else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
1131 			cmdnleft++;		/* ignore it */
1132 		else
1133 			*q++ = c;
1134 		if (--cmdnleft <= 0) {
1135 			*q++ = '.';
1136 			*q++ = '.';
1137 			*q++ = '.';
1138 			break;
1139 		}
1140 	}
1141 	cmdnextc = q;
1142 }
1143