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