jobs.c revision 213925
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 213925 2010-10-16 12:40:00Z 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	pid_t ppid;
312	char c;
313
314	procno = (mode == SHOWJOBS_PGIDS) ? 1 : jp->nprocs;
315	jobno = jp - jobtab + 1;
316	curr = prev = 0;
317#if JOBS
318	if ((j = getcurjob(NULL)) != NULL) {
319		curr = j - jobtab + 1;
320		if ((j = getcurjob(j)) != NULL)
321			prev = j - jobtab + 1;
322	}
323#endif
324	for (ps = jp->ps ; ; ps++) {	/* for each process */
325		if (mode == SHOWJOBS_PIDS || mode == SHOWJOBS_PGIDS) {
326			ppid = (mode == SHOWJOBS_PIDS) ? ps->pid :
327			    getpgid(ps->pid);
328			out1fmt("%d\n", (int)ppid);
329			goto skip;
330		}
331		if (mode != SHOWJOBS_VERBOSE && ps != jp->ps && pid == 0)
332			goto skip;
333		if (pid != 0 && pid != ps->pid)
334			goto skip;
335		if (jobno == curr && ps == jp->ps)
336			c = '+';
337		else if (jobno == prev && ps == jp->ps)
338			c = '-';
339		else
340			c = ' ';
341		if (ps == jp->ps)
342			fmtstr(s, 64, "[%d] %c ", jobno, c);
343		else
344			fmtstr(s, 64, "    %c ", c);
345		out1str(s);
346		col = strlen(s);
347		if (mode == SHOWJOBS_VERBOSE) {
348			fmtstr(s, 64, "%d ", (int)ps->pid);
349			out1str(s);
350			col += strlen(s);
351		}
352		s[0] = '\0';
353		if (ps != jp->ps) {
354			*s = '\0';
355		} else if (ps->status == -1) {
356			strcpy(s, "Running");
357		} else if (WIFEXITED(ps->status)) {
358			if (WEXITSTATUS(ps->status) == 0)
359				strcpy(s, "Done");
360			else
361				fmtstr(s, 64, "Done (%d)",
362				    WEXITSTATUS(ps->status));
363		} else {
364#if JOBS
365			if (WIFSTOPPED(ps->status))
366				i = WSTOPSIG(ps->status);
367			else
368#endif
369				i = WTERMSIG(ps->status);
370			if ((i & 0x7F) < sys_nsig && sys_siglist[i & 0x7F])
371				scopy(sys_siglist[i & 0x7F], s);
372			else
373				fmtstr(s, 64, "Signal %d", i & 0x7F);
374			if (WCOREDUMP(ps->status))
375				strcat(s, " (core dumped)");
376		}
377		out1str(s);
378		col += strlen(s);
379		do {
380			out1c(' ');
381			col++;
382		} while (col < 30);
383		out1str(ps->cmd);
384		out1c('\n');
385skip:		if (--procno <= 0)
386			break;
387	}
388}
389
390/*
391 * Print a list of jobs.  If "change" is nonzero, only print jobs whose
392 * statuses have changed since the last call to showjobs.
393 *
394 * If the shell is interrupted in the process of creating a job, the
395 * result may be a job structure containing zero processes.  Such structures
396 * will be freed here.
397 */
398
399void
400showjobs(int change, int mode)
401{
402	int jobno;
403	struct job *jp;
404
405	TRACE(("showjobs(%d) called\n", change));
406	checkzombies();
407	for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
408		if (! jp->used)
409			continue;
410		if (jp->nprocs == 0) {
411			freejob(jp);
412			continue;
413		}
414		if (change && ! jp->changed)
415			continue;
416		showjob(jp, 0, mode);
417		jp->changed = 0;
418		/* Hack: discard jobs for which $! has not been referenced
419		 * in interactive mode when they terminate.
420		 */
421		if (jp->state == JOBDONE && !jp->remembered &&
422				(iflag || jp != bgjob)) {
423			freejob(jp);
424		}
425	}
426}
427
428
429/*
430 * Mark a job structure as unused.
431 */
432
433static void
434freejob(struct job *jp)
435{
436	struct procstat *ps;
437	int i;
438
439	INTOFF;
440	if (bgjob == jp)
441		bgjob = NULL;
442	for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
443		if (ps->cmd != nullstr)
444			ckfree(ps->cmd);
445	}
446	if (jp->ps != &jp->ps0)
447		ckfree(jp->ps);
448	jp->used = 0;
449#if JOBS
450	deljob(jp);
451#endif
452	INTON;
453}
454
455
456
457int
458waitcmd(int argc, char **argv)
459{
460	struct job *job;
461	int status, retval;
462	struct job *jp;
463
464	if (argc > 1) {
465		job = getjob(argv[1]);
466	} else {
467		job = NULL;
468	}
469
470	/*
471	 * Loop until a process is terminated or stopped, or a SIGINT is
472	 * received.
473	 */
474
475	in_waitcmd++;
476	do {
477		if (job != NULL) {
478			if (job->state) {
479				status = job->ps[job->nprocs - 1].status;
480				if (WIFEXITED(status))
481					retval = WEXITSTATUS(status);
482#if JOBS
483				else if (WIFSTOPPED(status))
484					retval = WSTOPSIG(status) + 128;
485#endif
486				else
487					retval = WTERMSIG(status) + 128;
488				if (! iflag || ! job->changed)
489					freejob(job);
490				else {
491					job->remembered = 0;
492					if (job == bgjob)
493						bgjob = NULL;
494				}
495				in_waitcmd--;
496				return retval;
497			}
498		} else {
499			for (jp = jobtab ; jp < jobtab + njobs; jp++)
500				if (jp->used && jp->state == JOBDONE) {
501					if (! iflag || ! jp->changed)
502						freejob(jp);
503					else {
504						jp->remembered = 0;
505						if (jp == bgjob)
506							bgjob = NULL;
507					}
508				}
509			for (jp = jobtab ; ; jp++) {
510				if (jp >= jobtab + njobs) {	/* no running procs */
511					in_waitcmd--;
512					return 0;
513				}
514				if (jp->used && jp->state == 0)
515					break;
516			}
517		}
518	} while (dowait(1, (struct job *)NULL) != -1);
519	in_waitcmd--;
520
521	return 0;
522}
523
524
525
526int
527jobidcmd(int argc __unused, char **argv)
528{
529	struct job *jp;
530	int i;
531
532	jp = getjob(argv[1]);
533	for (i = 0 ; i < jp->nprocs ; ) {
534		out1fmt("%d", (int)jp->ps[i].pid);
535		out1c(++i < jp->nprocs? ' ' : '\n');
536	}
537	return 0;
538}
539
540
541
542/*
543 * Convert a job name to a job structure.
544 */
545
546static struct job *
547getjob(char *name)
548{
549	int jobno;
550	struct job *found, *jp;
551	pid_t pid;
552	int i;
553
554	if (name == NULL) {
555#if JOBS
556currentjob:	if ((jp = getcurjob(NULL)) == NULL)
557			error("No current job");
558		return (jp);
559#else
560		error("No current job");
561#endif
562	} else if (name[0] == '%') {
563		if (is_digit(name[1])) {
564			jobno = number(name + 1);
565			if (jobno > 0 && jobno <= njobs
566			 && jobtab[jobno - 1].used != 0)
567				return &jobtab[jobno - 1];
568#if JOBS
569		} else if (name[1] == '%' && name[2] == '\0') {
570			goto currentjob;
571		} else if (name[1] == '+' && name[2] == '\0') {
572			goto currentjob;
573		} else if (name[1] == '-' && name[2] == '\0') {
574			if ((jp = getcurjob(NULL)) == NULL ||
575			    (jp = getcurjob(jp)) == NULL)
576				error("No previous job");
577			return (jp);
578#endif
579		} else if (name[1] == '?') {
580			found = NULL;
581			for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
582				if (jp->used && jp->nprocs > 0
583				 && strstr(jp->ps[0].cmd, name + 2) != NULL) {
584					if (found)
585						error("%s: ambiguous", name);
586					found = jp;
587				}
588			}
589			if (found != NULL)
590				return (found);
591		} else {
592			found = NULL;
593			for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
594				if (jp->used && jp->nprocs > 0
595				 && prefix(name + 1, jp->ps[0].cmd)) {
596					if (found)
597						error("%s: ambiguous", name);
598					found = jp;
599				}
600			}
601			if (found)
602				return found;
603		}
604	} else if (is_number(name)) {
605		pid = (pid_t)number(name);
606		for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
607			if (jp->used && jp->nprocs > 0
608			 && jp->ps[jp->nprocs - 1].pid == pid)
609				return jp;
610		}
611	}
612	error("No such job: %s", name);
613	/*NOTREACHED*/
614	return NULL;
615}
616
617
618
619/*
620 * Return a new job structure,
621 */
622
623struct job *
624makejob(union node *node __unused, int nprocs)
625{
626	int i;
627	struct job *jp;
628
629	for (i = njobs, jp = jobtab ; ; jp++) {
630		if (--i < 0) {
631			INTOFF;
632			if (njobs == 0) {
633				jobtab = ckmalloc(4 * sizeof jobtab[0]);
634#if JOBS
635				jobmru = NULL;
636#endif
637			} else {
638				jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
639				memcpy(jp, jobtab, njobs * sizeof jp[0]);
640#if JOBS
641				/* Relocate `next' pointers and list head */
642				if (jobmru != NULL)
643					jobmru = &jp[jobmru - jobtab];
644				for (i = 0; i < njobs; i++)
645					if (jp[i].next != NULL)
646						jp[i].next = &jp[jp[i].next -
647						    jobtab];
648#endif
649				if (bgjob != NULL)
650					bgjob = &jp[bgjob - jobtab];
651				/* Relocate `ps' pointers */
652				for (i = 0; i < njobs; i++)
653					if (jp[i].ps == &jobtab[i].ps0)
654						jp[i].ps = &jp[i].ps0;
655				ckfree(jobtab);
656				jobtab = jp;
657			}
658			jp = jobtab + njobs;
659			for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
660			INTON;
661			break;
662		}
663		if (jp->used == 0)
664			break;
665	}
666	INTOFF;
667	jp->state = 0;
668	jp->used = 1;
669	jp->changed = 0;
670	jp->nprocs = 0;
671	jp->foreground = 0;
672	jp->remembered = 0;
673#if JOBS
674	jp->jobctl = jobctl;
675	jp->next = NULL;
676#endif
677	if (nprocs > 1) {
678		jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
679	} else {
680		jp->ps = &jp->ps0;
681	}
682	INTON;
683	TRACE(("makejob(%p, %d) returns %%%td\n", (void *)node, nprocs,
684	    jp - jobtab + 1));
685	return jp;
686}
687
688#if JOBS
689static void
690setcurjob(struct job *cj)
691{
692	struct job *jp, *prev;
693
694	for (prev = NULL, jp = jobmru; jp != NULL; prev = jp, jp = jp->next) {
695		if (jp == cj) {
696			if (prev != NULL)
697				prev->next = jp->next;
698			else
699				jobmru = jp->next;
700			jp->next = jobmru;
701			jobmru = cj;
702			return;
703		}
704	}
705	cj->next = jobmru;
706	jobmru = cj;
707}
708
709static void
710deljob(struct job *j)
711{
712	struct job *jp, *prev;
713
714	for (prev = NULL, jp = jobmru; jp != NULL; prev = jp, jp = jp->next) {
715		if (jp == j) {
716			if (prev != NULL)
717				prev->next = jp->next;
718			else
719				jobmru = jp->next;
720			return;
721		}
722	}
723}
724
725/*
726 * Return the most recently used job that isn't `nj', and preferably one
727 * that is stopped.
728 */
729static struct job *
730getcurjob(struct job *nj)
731{
732	struct job *jp;
733
734	/* Try to find a stopped one.. */
735	for (jp = jobmru; jp != NULL; jp = jp->next)
736		if (jp->used && jp != nj && jp->state == JOBSTOPPED)
737			return (jp);
738	/* Otherwise the most recently used job that isn't `nj' */
739	for (jp = jobmru; jp != NULL; jp = jp->next)
740		if (jp->used && jp != nj)
741			return (jp);
742
743	return (NULL);
744}
745
746#endif
747
748/*
749 * Fork of a subshell.  If we are doing job control, give the subshell its
750 * own process group.  Jp is a job structure that the job is to be added to.
751 * N is the command that will be evaluated by the child.  Both jp and n may
752 * be NULL.  The mode parameter can be one of the following:
753 *	FORK_FG - Fork off a foreground process.
754 *	FORK_BG - Fork off a background process.
755 *	FORK_NOJOB - Like FORK_FG, but don't give the process its own
756 *		     process group even if job control is on.
757 *
758 * When job control is turned off, background processes have their standard
759 * input redirected to /dev/null (except for the second and later processes
760 * in a pipeline).
761 */
762
763pid_t
764forkshell(struct job *jp, union node *n, int mode)
765{
766	pid_t pid;
767	pid_t pgrp;
768
769	TRACE(("forkshell(%%%td, %p, %d) called\n", jp - jobtab, (void *)n,
770	    mode));
771	INTOFF;
772	if (mode == FORK_BG)
773		checkzombies();
774	flushall();
775	pid = fork();
776	if (pid == -1) {
777		TRACE(("Fork failed, errno=%d\n", errno));
778		INTON;
779		error("Cannot fork: %s", strerror(errno));
780	}
781	if (pid == 0) {
782		struct job *p;
783		int wasroot;
784		int i;
785
786		TRACE(("Child shell %d\n", (int)getpid()));
787		wasroot = rootshell;
788		rootshell = 0;
789		handler = &main_handler;
790		closescript();
791		INTON;
792		clear_traps();
793#if JOBS
794		jobctl = 0;		/* do job control only in root shell */
795		if (wasroot && mode != FORK_NOJOB && mflag) {
796			if (jp == NULL || jp->nprocs == 0)
797				pgrp = getpid();
798			else
799				pgrp = jp->ps[0].pid;
800			if (setpgid(0, pgrp) == 0 && mode == FORK_FG) {
801				/*** this causes superfluous TIOCSPGRPS ***/
802				if (tcsetpgrp(ttyfd, pgrp) < 0)
803					error("tcsetpgrp failed, errno=%d", errno);
804			}
805			setsignal(SIGTSTP);
806			setsignal(SIGTTOU);
807		} else if (mode == FORK_BG) {
808			ignoresig(SIGINT);
809			ignoresig(SIGQUIT);
810			if ((jp == NULL || jp->nprocs == 0) &&
811			    ! fd0_redirected_p ()) {
812				close(0);
813				if (open(_PATH_DEVNULL, O_RDONLY) != 0)
814					error("Can't open %s: %s",
815					    _PATH_DEVNULL, strerror(errno));
816			}
817		}
818#else
819		if (mode == FORK_BG) {
820			ignoresig(SIGINT);
821			ignoresig(SIGQUIT);
822			if ((jp == NULL || jp->nprocs == 0) &&
823			    ! fd0_redirected_p ()) {
824				close(0);
825				if (open(_PATH_DEVNULL, O_RDONLY) != 0)
826					error("Can't open %s: %s",
827					    _PATH_DEVNULL, strerror(errno));
828			}
829		}
830#endif
831		INTOFF;
832		for (i = njobs, p = jobtab ; --i >= 0 ; p++)
833			if (p->used)
834				freejob(p);
835		INTON;
836		if (wasroot && iflag) {
837			setsignal(SIGINT);
838			setsignal(SIGQUIT);
839			setsignal(SIGTERM);
840		}
841		return pid;
842	}
843	if (rootshell && mode != FORK_NOJOB && mflag) {
844		if (jp == NULL || jp->nprocs == 0)
845			pgrp = pid;
846		else
847			pgrp = jp->ps[0].pid;
848		setpgid(pid, pgrp);
849	}
850	if (mode == FORK_BG) {
851		if (bgjob != NULL && bgjob->state == JOBDONE &&
852		    !bgjob->remembered && !iflag)
853			freejob(bgjob);
854		backgndpid = pid;		/* set $! */
855		bgjob = jp;
856	}
857	if (jp) {
858		struct procstat *ps = &jp->ps[jp->nprocs++];
859		ps->pid = pid;
860		ps->status = -1;
861		ps->cmd = nullstr;
862		if (iflag && rootshell && n)
863			ps->cmd = commandtext(n);
864		jp->foreground = mode == FORK_FG;
865#if JOBS
866		setcurjob(jp);
867#endif
868	}
869	INTON;
870	TRACE(("In parent shell:  child = %d\n", (int)pid));
871	return pid;
872}
873
874
875
876/*
877 * Wait for job to finish.
878 *
879 * Under job control we have the problem that while a child process is
880 * running interrupts generated by the user are sent to the child but not
881 * to the shell.  This means that an infinite loop started by an inter-
882 * active user may be hard to kill.  With job control turned off, an
883 * interactive user may place an interactive program inside a loop.  If
884 * the interactive program catches interrupts, the user doesn't want
885 * these interrupts to also abort the loop.  The approach we take here
886 * is to have the shell ignore interrupt signals while waiting for a
887 * foreground process to terminate, and then send itself an interrupt
888 * signal if the child process was terminated by an interrupt signal.
889 * Unfortunately, some programs want to do a bit of cleanup and then
890 * exit on interrupt; unless these processes terminate themselves by
891 * sending a signal to themselves (instead of calling exit) they will
892 * confuse this approach.
893 */
894
895int
896waitforjob(struct job *jp, int *origstatus)
897{
898#if JOBS
899	pid_t mypgrp = getpgrp();
900	int propagate_int = jp->jobctl && jp->foreground;
901#endif
902	int status;
903	int st;
904
905	INTOFF;
906	TRACE(("waitforjob(%%%td) called\n", jp - jobtab + 1));
907	while (jp->state == 0)
908		if (dowait(1, jp) == -1)
909			dotrap();
910#if JOBS
911	if (jp->jobctl) {
912		if (tcsetpgrp(ttyfd, mypgrp) < 0)
913			error("tcsetpgrp failed, errno=%d\n", errno);
914	}
915	if (jp->state == JOBSTOPPED)
916		setcurjob(jp);
917#endif
918	status = jp->ps[jp->nprocs - 1].status;
919	if (origstatus != NULL)
920		*origstatus = status;
921	/* convert to 8 bits */
922	if (WIFEXITED(status))
923		st = WEXITSTATUS(status);
924#if JOBS
925	else if (WIFSTOPPED(status))
926		st = WSTOPSIG(status) + 128;
927#endif
928	else
929		st = WTERMSIG(status) + 128;
930	if (! JOBS || jp->state == JOBDONE)
931		freejob(jp);
932	if (int_pending()) {
933		if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
934			kill(getpid(), SIGINT);
935		else
936			CLEAR_PENDING_INT;
937	}
938#if JOBS
939	else if (rootshell && iflag && propagate_int &&
940			WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
941		kill(getpid(), SIGINT);
942#endif
943	INTON;
944	return st;
945}
946
947
948
949/*
950 * Wait for a process to terminate.
951 */
952
953static pid_t
954dowait(int block, struct job *job)
955{
956	pid_t pid;
957	int status;
958	struct procstat *sp;
959	struct job *jp;
960	struct job *thisjob;
961	int done;
962	int stopped;
963	int sig;
964	int i;
965
966	in_dowait++;
967	TRACE(("dowait(%d) called\n", block));
968	do {
969		pid = waitproc(block, &status);
970		TRACE(("wait returns %d, status=%d\n", (int)pid, status));
971	} while ((pid == -1 && errno == EINTR && breakwaitcmd == 0) ||
972		 (pid > 0 && WIFSTOPPED(status) && !iflag));
973	in_dowait--;
974	if (pid == -1 && errno == ECHILD && job != NULL)
975		job->state = JOBDONE;
976	if (breakwaitcmd != 0) {
977		breakwaitcmd = 0;
978		if (pid <= 0)
979			return -1;
980	}
981	if (pid <= 0)
982		return pid;
983	INTOFF;
984	thisjob = NULL;
985	for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
986		if (jp->used) {
987			done = 1;
988			stopped = 1;
989			for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
990				if (sp->pid == -1)
991					continue;
992				if (sp->pid == pid) {
993					TRACE(("Changing status of proc %d from 0x%x to 0x%x\n",
994						   (int)pid, sp->status,
995						   status));
996					sp->status = status;
997					thisjob = jp;
998				}
999				if (sp->status == -1)
1000					stopped = 0;
1001				else if (WIFSTOPPED(sp->status))
1002					done = 0;
1003			}
1004			if (stopped) {		/* stopped or done */
1005				int state = done? JOBDONE : JOBSTOPPED;
1006				if (jp->state != state) {
1007					TRACE(("Job %td: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
1008					jp->state = state;
1009					if (jp != job) {
1010						if (done && !jp->remembered &&
1011						    !iflag && jp != bgjob)
1012							freejob(jp);
1013#if JOBS
1014						else if (done)
1015							deljob(jp);
1016#endif
1017					}
1018				}
1019			}
1020		}
1021	}
1022	INTON;
1023	if (! rootshell || ! iflag || (job && thisjob == job)) {
1024#if JOBS
1025		if (WIFSTOPPED(status))
1026			sig = WSTOPSIG(status);
1027		else
1028#endif
1029		{
1030			if (WIFEXITED(status))
1031				sig = 0;
1032			else
1033				sig = WTERMSIG(status);
1034		}
1035		if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
1036			if (!mflag ||
1037			    (thisjob->foreground && !WIFSTOPPED(status))) {
1038				i = WTERMSIG(status);
1039				if ((i & 0x7F) < sys_nsig && sys_siglist[i & 0x7F])
1040					out1str(sys_siglist[i & 0x7F]);
1041				else
1042					out1fmt("Signal %d", i & 0x7F);
1043				if (WCOREDUMP(status))
1044					out1str(" (core dumped)");
1045				out1c('\n');
1046			} else
1047				showjob(thisjob, pid, SHOWJOBS_DEFAULT);
1048		}
1049	} else {
1050		TRACE(("Not printing status, rootshell=%d, job=%p\n", rootshell, job));
1051		if (thisjob)
1052			thisjob->changed = 1;
1053	}
1054	return pid;
1055}
1056
1057
1058
1059/*
1060 * Do a wait system call.  If job control is compiled in, we accept
1061 * stopped processes.  If block is zero, we return a value of zero
1062 * rather than blocking.
1063 */
1064static pid_t
1065waitproc(int block, int *status)
1066{
1067	int flags;
1068
1069#if JOBS
1070	flags = WUNTRACED;
1071#else
1072	flags = 0;
1073#endif
1074	if (block == 0)
1075		flags |= WNOHANG;
1076	return wait3(status, flags, (struct rusage *)NULL);
1077}
1078
1079/*
1080 * return 1 if there are stopped jobs, otherwise 0
1081 */
1082int job_warning = 0;
1083int
1084stoppedjobs(void)
1085{
1086	int jobno;
1087	struct job *jp;
1088
1089	if (job_warning)
1090		return (0);
1091	for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
1092		if (jp->used == 0)
1093			continue;
1094		if (jp->state == JOBSTOPPED) {
1095			out2fmt_flush("You have stopped jobs.\n");
1096			job_warning = 2;
1097			return (1);
1098		}
1099	}
1100
1101	return (0);
1102}
1103
1104
1105static void
1106checkzombies(void)
1107{
1108	while (njobs > 0 && dowait(0, NULL) > 0)
1109		;
1110}
1111
1112
1113int
1114backgndpidset(void)
1115{
1116	return backgndpid != -1;
1117}
1118
1119
1120pid_t
1121backgndpidval(void)
1122{
1123	if (bgjob != NULL)
1124		bgjob->remembered = 1;
1125	return backgndpid;
1126}
1127
1128/*
1129 * Return a string identifying a command (to be printed by the
1130 * jobs command.
1131 */
1132
1133static char *cmdnextc;
1134static int cmdnleft;
1135#define MAXCMDTEXT	200
1136
1137char *
1138commandtext(union node *n)
1139{
1140	char *name;
1141
1142	cmdnextc = name = ckmalloc(MAXCMDTEXT);
1143	cmdnleft = MAXCMDTEXT - 4;
1144	cmdtxt(n);
1145	*cmdnextc = '\0';
1146	return name;
1147}
1148
1149
1150static void
1151cmdtxt(union node *n)
1152{
1153	union node *np;
1154	struct nodelist *lp;
1155	const char *p;
1156	int i;
1157	char s[2];
1158
1159	if (n == NULL)
1160		return;
1161	switch (n->type) {
1162	case NSEMI:
1163		cmdtxt(n->nbinary.ch1);
1164		cmdputs("; ");
1165		cmdtxt(n->nbinary.ch2);
1166		break;
1167	case NAND:
1168		cmdtxt(n->nbinary.ch1);
1169		cmdputs(" && ");
1170		cmdtxt(n->nbinary.ch2);
1171		break;
1172	case NOR:
1173		cmdtxt(n->nbinary.ch1);
1174		cmdputs(" || ");
1175		cmdtxt(n->nbinary.ch2);
1176		break;
1177	case NPIPE:
1178		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
1179			cmdtxt(lp->n);
1180			if (lp->next)
1181				cmdputs(" | ");
1182		}
1183		break;
1184	case NSUBSHELL:
1185		cmdputs("(");
1186		cmdtxt(n->nredir.n);
1187		cmdputs(")");
1188		break;
1189	case NREDIR:
1190	case NBACKGND:
1191		cmdtxt(n->nredir.n);
1192		break;
1193	case NIF:
1194		cmdputs("if ");
1195		cmdtxt(n->nif.test);
1196		cmdputs("; then ");
1197		cmdtxt(n->nif.ifpart);
1198		cmdputs("...");
1199		break;
1200	case NWHILE:
1201		cmdputs("while ");
1202		goto until;
1203	case NUNTIL:
1204		cmdputs("until ");
1205until:
1206		cmdtxt(n->nbinary.ch1);
1207		cmdputs("; do ");
1208		cmdtxt(n->nbinary.ch2);
1209		cmdputs("; done");
1210		break;
1211	case NFOR:
1212		cmdputs("for ");
1213		cmdputs(n->nfor.var);
1214		cmdputs(" in ...");
1215		break;
1216	case NCASE:
1217		cmdputs("case ");
1218		cmdputs(n->ncase.expr->narg.text);
1219		cmdputs(" in ...");
1220		break;
1221	case NDEFUN:
1222		cmdputs(n->narg.text);
1223		cmdputs("() ...");
1224		break;
1225	case NCMD:
1226		for (np = n->ncmd.args ; np ; np = np->narg.next) {
1227			cmdtxt(np);
1228			if (np->narg.next)
1229				cmdputs(" ");
1230		}
1231		for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
1232			cmdputs(" ");
1233			cmdtxt(np);
1234		}
1235		break;
1236	case NARG:
1237		cmdputs(n->narg.text);
1238		break;
1239	case NTO:
1240		p = ">";  i = 1;  goto redir;
1241	case NAPPEND:
1242		p = ">>";  i = 1;  goto redir;
1243	case NTOFD:
1244		p = ">&";  i = 1;  goto redir;
1245	case NCLOBBER:
1246		p = ">|"; i = 1; goto redir;
1247	case NFROM:
1248		p = "<";  i = 0;  goto redir;
1249	case NFROMTO:
1250		p = "<>";  i = 0;  goto redir;
1251	case NFROMFD:
1252		p = "<&";  i = 0;  goto redir;
1253redir:
1254		if (n->nfile.fd != i) {
1255			s[0] = n->nfile.fd + '0';
1256			s[1] = '\0';
1257			cmdputs(s);
1258		}
1259		cmdputs(p);
1260		if (n->type == NTOFD || n->type == NFROMFD) {
1261			if (n->ndup.dupfd >= 0)
1262				s[0] = n->ndup.dupfd + '0';
1263			else
1264				s[0] = '-';
1265			s[1] = '\0';
1266			cmdputs(s);
1267		} else {
1268			cmdtxt(n->nfile.fname);
1269		}
1270		break;
1271	case NHERE:
1272	case NXHERE:
1273		cmdputs("<<...");
1274		break;
1275	default:
1276		cmdputs("???");
1277		break;
1278	}
1279}
1280
1281
1282
1283static void
1284cmdputs(const char *s)
1285{
1286	const char *p;
1287	char *q;
1288	char c;
1289	int subtype = 0;
1290
1291	if (cmdnleft <= 0)
1292		return;
1293	p = s;
1294	q = cmdnextc;
1295	while ((c = *p++) != '\0') {
1296		if (c == CTLESC)
1297			*q++ = *p++;
1298		else if (c == CTLVAR) {
1299			*q++ = '$';
1300			if (--cmdnleft > 0)
1301				*q++ = '{';
1302			subtype = *p++;
1303		} else if (c == '=' && subtype != 0) {
1304			*q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
1305			subtype = 0;
1306		} else if (c == CTLENDVAR) {
1307			*q++ = '}';
1308		} else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
1309			cmdnleft++;		/* ignore it */
1310		else
1311			*q++ = c;
1312		if (--cmdnleft <= 0) {
1313			*q++ = '.';
1314			*q++ = '.';
1315			*q++ = '.';
1316			break;
1317		}
1318	}
1319	cmdnextc = q;
1320}
1321