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