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