jobs.c revision 72086
182518Sgallatin/*-
282518Sgallatin * Copyright (c) 1991, 1993
382518Sgallatin *	The Regents of the University of California.  All rights reserved.
482518Sgallatin *
582518Sgallatin * This code is derived from software contributed to Berkeley by
682518Sgallatin * Kenneth Almquist.
782518Sgallatin *
882518Sgallatin * Redistribution and use in source and binary forms, with or without
982518Sgallatin * modification, are permitted provided that the following conditions
1082518Sgallatin * are met:
1182518Sgallatin * 1. Redistributions of source code must retain the above copyright
1282518Sgallatin *    notice, this list of conditions and the following disclaimer.
1382518Sgallatin * 2. Redistributions in binary form must reproduce the above copyright
1482518Sgallatin *    notice, this list of conditions and the following disclaimer in the
1582518Sgallatin *    documentation and/or other materials provided with the distribution.
1682518Sgallatin * 3. All advertising materials mentioning features or use of this software
1782518Sgallatin *    must display the following acknowledgement:
1882518Sgallatin *	This product includes software developed by the University of
1982518Sgallatin *	California, Berkeley and its contributors.
2082518Sgallatin * 4. Neither the name of the University nor the names of its contributors
2182518Sgallatin *    may be used to endorse or promote products derived from this software
2282518Sgallatin *    without specific prior written permission.
2382518Sgallatin *
2482518Sgallatin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2582518Sgallatin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2682518Sgallatin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2782518Sgallatin * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2882518Sgallatin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2982518Sgallatin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3082518Sgallatin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3182518Sgallatin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3282518Sgallatin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3382518Sgallatin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3482518Sgallatin * SUCH DAMAGE.
3582518Sgallatin */
3682518Sgallatin
3782518Sgallatin#ifndef lint
38116173Sobrien#if 0
39116173Sobrienstatic char sccsid[] = "@(#)jobs.c	8.5 (Berkeley) 5/4/95";
40116173Sobrien#endif
41116173Sobrienstatic const char rcsid[] =
42112430Sphk  "$FreeBSD: head/bin/sh/jobs.c 72086 2001-02-06 10:29:34Z cracauer $";
43112430Sphk#endif /* not lint */
4482518Sgallatin
4582518Sgallatin#include <fcntl.h>
4682518Sgallatin#include <signal.h>
47112430Sphk#include <errno.h>
48112430Sphk#include <unistd.h>
49112430Sphk#include <stdlib.h>
50112430Sphk#include <sys/param.h>
51112430Sphk#ifdef BSD
52102872Siedowse#include <sys/wait.h>
53112430Sphk#include <sys/time.h>
54112430Sphk#include <sys/resource.h>
5582518Sgallatin#include <paths.h>
56112430Sphk#endif
57112430Sphk#include <sys/ioctl.h>
58112430Sphk
59112430Sphk#include "shell.h"
60112430Sphk#if JOBS
6182518Sgallatin#if OLD_TTY_DRIVER
62133816Stjr#include "sgtty.h"
63133816Stjr#else
64140214Sobrien#include <termios.h>
65140214Sobrien#endif
66140214Sobrien#undef CEOF			/* syntax.h redefines this */
67140214Sobrien#endif
6882518Sgallatin#include "redir.h"
6982518Sgallatin#include "show.h"
70133816Stjr#include "main.h"
71112430Sphk#include "parser.h"
7282518Sgallatin#include "nodes.h"
73112430Sphk#include "jobs.h"
74112430Sphk#include "options.h"
75112430Sphk#include "trap.h"
76112430Sphk#include "syntax.h"
77112430Sphk#include "input.h"
78112430Sphk#include "output.h"
79112430Sphk#include "memalloc.h"
80112430Sphk#include "error.h"
81112430Sphk#include "mystring.h"
8282518Sgallatin
83112430Sphk
84112430Sphkstruct job *jobtab;		/* array of jobs */
85112430Sphkint njobs;			/* size of array */
86112430SphkMKINIT pid_t backgndpid = -1;	/* pid of last background process */
87112430Sphk#if JOBS
88112430Sphkint initialpgrp;		/* pgrp of shell on invocation */
89112430Sphkint curjob;			/* current job */
90112430Sphk#endif
91112430Sphkint in_waitcmd = 0;		/* are we in waitcmd()? */
92112430Sphkint in_dowait = 0;		/* are we in dowait()? */
93112430Sphkvolatile sig_atomic_t breakwaitcmd = 0;	/* should wait be terminated? */
94112430Sphk
95112430Sphk#if JOBS
96112430SphkSTATIC void restartjob __P((struct job *));
97112430Sphk#endif
98112430SphkSTATIC void freejob __P((struct job *));
99112430SphkSTATIC struct job *getjob __P((char *));
100112430SphkSTATIC int dowait __P((int, struct job *));
101112430Sphk#if SYSV
102112430SphkSTATIC int onsigchild __P((void));
103112430Sphk#endif
104112430SphkSTATIC int waitproc __P((int, int *));
105112430SphkSTATIC void cmdtxt __P((union node *));
106112430SphkSTATIC void cmdputs __P((char *));
107112430Sphk
108112430Sphk
109112430Sphk/*
110112430Sphk * Turn job control on and off.
111112430Sphk *
112112430Sphk * Note:  This code assumes that the third arg to ioctl is a character
113112430Sphk * pointer, which is true on Berkeley systems but not System V.  Since
114112430Sphk * System V doesn't have job control yet, this isn't a problem now.
115112430Sphk */
116112430Sphk
117112430SphkMKINIT int jobctl;
118112430Sphk
119112430Sphk#if JOBS
120112430Sphkvoid
121112430Sphksetjobctl(on)
122112430Sphk	int on;
123112430Sphk{
124112430Sphk#ifdef OLD_TTY_DRIVER
125112430Sphk	int ldisc;
126112430Sphk#endif
127112430Sphk
128112430Sphk	if (on == jobctl || rootshell == 0)
129112430Sphk		return;
130112430Sphk	if (on) {
131112430Sphk		do { /* while we are in the background */
132112430Sphk#ifdef OLD_TTY_DRIVER
133112430Sphk			if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
134112430Sphk#else
135112430Sphk			initialpgrp = tcgetpgrp(2);
136112430Sphk			if (initialpgrp < 0) {
137112430Sphk#endif
138112430Sphk				out2str("sh: can't access tty; job control turned off\n");
139112430Sphk				mflag = 0;
140112430Sphk				return;
141112430Sphk			}
142112430Sphk			if (initialpgrp == -1)
143112430Sphk				initialpgrp = getpgrp();
144112430Sphk			else if (initialpgrp != getpgrp()) {
145112430Sphk				killpg(initialpgrp, SIGTTIN);
146112430Sphk				continue;
147112430Sphk			}
148112430Sphk		} while (0);
149112430Sphk#ifdef OLD_TTY_DRIVER
150112430Sphk		if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {
151112430Sphk			out2str("sh: need new tty driver to run job control; job control turned off\n");
152112430Sphk			mflag = 0;
153112430Sphk			return;
154112430Sphk		}
155112430Sphk#endif
156112430Sphk		setsignal(SIGTSTP);
157112430Sphk		setsignal(SIGTTOU);
158112430Sphk		setsignal(SIGTTIN);
159112430Sphk		setpgid(0, rootpid);
160112430Sphk#ifdef OLD_TTY_DRIVER
161112430Sphk		ioctl(2, TIOCSPGRP, (char *)&rootpid);
162112430Sphk#else
163112430Sphk		tcsetpgrp(2, rootpid);
164112430Sphk#endif
165112430Sphk	} else { /* turning job control off */
166112430Sphk		setpgid(0, initialpgrp);
167144290Sjeff#ifdef OLD_TTY_DRIVER
168112430Sphk		ioctl(2, TIOCSPGRP, (char *)&initialpgrp);
169112430Sphk#else
170112430Sphk		tcsetpgrp(2, initialpgrp);
171112430Sphk#endif
172112430Sphk		setsignal(SIGTSTP);
173122861Srwatson		setsignal(SIGTTOU);
174122861Srwatson		setsignal(SIGTTIN);
175122861Srwatson	}
176122861Srwatson	jobctl = on;
177122861Srwatson}
178112430Sphk#endif
179112430Sphk
180112430Sphk
181112430Sphk#ifdef mkinit
182112430SphkINCLUDE <sys/types.h>
183112430SphkINCLUDE <stdlib.h>
184112430Sphk
185112430SphkSHELLPROC {
186112430Sphk	backgndpid = -1;
187112430Sphk#if JOBS
188145006Sjeff	jobctl = 0;
189112430Sphk#endif
190112430Sphk}
191112430Sphk
192112430Sphk#endif
193112430Sphk
194112430Sphk
195112430Sphk
196112430Sphk#if JOBS
197112430Sphkint
198112430Sphkfgcmd(argc, argv)
199112430Sphk	int argc __unused;
200112430Sphk	char **argv;
201112430Sphk{
202112430Sphk	struct job *jp;
203112430Sphk	int pgrp;
204112430Sphk	int status;
205112430Sphk
206112430Sphk	jp = getjob(argv[1]);
207112430Sphk	if (jp->jobctl == 0)
208112430Sphk		error("job not created under job control");
209112430Sphk	pgrp = jp->ps[0].pid;
210112430Sphk#ifdef OLD_TTY_DRIVER
211112430Sphk	ioctl(2, TIOCSPGRP, (char *)&pgrp);
212112430Sphk#else
213112430Sphk	tcsetpgrp(2, pgrp);
214112430Sphk#endif
215112430Sphk	restartjob(jp);
216112430Sphk	INTOFF;
217112430Sphk	status = waitforjob(jp, (int *)NULL);
218112430Sphk	INTON;
219112430Sphk	return status;
220112430Sphk}
221112430Sphk
222112430Sphk
223112430Sphkint
224112430Sphkbgcmd(argc, argv)
225112430Sphk	int argc;
226112430Sphk	char **argv;
227112430Sphk{
228112430Sphk	struct job *jp;
229112430Sphk
230112430Sphk	do {
231112430Sphk		jp = getjob(*++argv);
232112430Sphk		if (jp->jobctl == 0)
233112430Sphk			error("job not created under job control");
234112430Sphk		restartjob(jp);
235112430Sphk	} while (--argc > 1);
236112430Sphk	return 0;
237112430Sphk}
238112430Sphk
239112430Sphk
240112430SphkSTATIC void
241112430Sphkrestartjob(jp)
242112430Sphk	struct job *jp;
243112430Sphk{
244112430Sphk	struct procstat *ps;
245112430Sphk	int i;
246112430Sphk
247112430Sphk	if (jp->state == JOBDONE)
248112430Sphk		return;
249112430Sphk	INTOFF;
250112430Sphk	killpg(jp->ps[0].pid, SIGCONT);
251112430Sphk	for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
252112430Sphk		if (WIFSTOPPED(ps->status)) {
253112430Sphk			ps->status = -1;
254112430Sphk			jp->state = 0;
255112430Sphk		}
256112430Sphk	}
257112430Sphk	INTON;
258112430Sphk}
259112430Sphk#endif
260112430Sphk
261112430Sphk
262112430Sphkint
263112430Sphkjobscmd(argc, argv)
264112430Sphk	int argc __unused;
265112430Sphk	char **argv __unused;
266112430Sphk{
267112430Sphk	showjobs(0);
268112430Sphk	return 0;
269112430Sphk}
270112430Sphk
271112430Sphk
272112430Sphk/*
273112430Sphk * Print a list of jobs.  If "change" is nonzero, only print jobs whose
274112430Sphk * statuses have changed since the last call to showjobs.
275112430Sphk *
276112430Sphk * If the shell is interrupted in the process of creating a job, the
277112430Sphk * result may be a job structure containing zero processes.  Such structures
278112430Sphk * will be freed here.
279112430Sphk */
280112430Sphk
281112430Sphkvoid
282112430Sphkshowjobs(change)
283112430Sphk	int change;
284145006Sjeff{
285112430Sphk	int jobno;
286112430Sphk	int procno;
287112430Sphk	int i;
288112430Sphk	struct job *jp;
289112430Sphk	struct procstat *ps;
290112430Sphk	int col;
291112430Sphk	char s[64];
292112430Sphk
293112430Sphk	TRACE(("showjobs(%d) called\n", change));
294112430Sphk	while (dowait(0, (struct job *)NULL) > 0);
295112430Sphk	for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
296112430Sphk		if (! jp->used)
297112430Sphk			continue;
298112430Sphk		if (jp->nprocs == 0) {
299112430Sphk			freejob(jp);
300112430Sphk			continue;
301112430Sphk		}
302112430Sphk		if (change && ! jp->changed)
303112430Sphk			continue;
304112430Sphk		procno = jp->nprocs;
305112430Sphk		for (ps = jp->ps ; ; ps++) {	/* for each process */
306112430Sphk			if (ps == jp->ps)
307112430Sphk				fmtstr(s, 64, "[%d] %d ", jobno, ps->pid);
308112430Sphk			else
309112430Sphk				fmtstr(s, 64, "    %d ", ps->pid);
310112430Sphk			out1str(s);
311112430Sphk			col = strlen(s);
312112430Sphk			s[0] = '\0';
313112430Sphk			if (ps->status == -1) {
314112430Sphk				/* don't print anything */
315112430Sphk			} else if (WIFEXITED(ps->status)) {
316112430Sphk				fmtstr(s, 64, "Exit %d", WEXITSTATUS(ps->status));
317112430Sphk			} else {
318112430Sphk#if JOBS
319112430Sphk				if (WIFSTOPPED(ps->status))
320112430Sphk					i = WSTOPSIG(ps->status);
321112430Sphk				else
322112430Sphk#endif
323112430Sphk					i = WTERMSIG(ps->status);
324112430Sphk				if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
325112430Sphk					scopy(sys_siglist[i & 0x7F], s);
326112430Sphk				else
327112430Sphk					fmtstr(s, 64, "Signal %d", i & 0x7F);
328112430Sphk				if (WCOREDUMP(ps->status))
329112430Sphk					strcat(s, " (core dumped)");
330112430Sphk			}
331112430Sphk			out1str(s);
332112430Sphk			col += strlen(s);
333112430Sphk			do {
334112430Sphk				out1c(' ');
335112430Sphk				col++;
336112430Sphk			} while (col < 30);
337112430Sphk			out1str(ps->cmd);
338112430Sphk			out1c('\n');
339112430Sphk			if (--procno <= 0)
340112430Sphk				break;
341112430Sphk		}
342112430Sphk		jp->changed = 0;
343112430Sphk		if (jp->state == JOBDONE) {
344112430Sphk			freejob(jp);
345112430Sphk		}
346112430Sphk	}
347112430Sphk}
348112430Sphk
349112430Sphk
350112430Sphk/*
351112430Sphk * Mark a job structure as unused.
352112430Sphk */
353112430Sphk
354112430SphkSTATIC void
355112430Sphkfreejob(jp)
356112430Sphk	struct job *jp;
357112430Sphk	{
358112430Sphk	struct procstat *ps;
359112430Sphk	int i;
360112430Sphk
361112430Sphk	INTOFF;
362112430Sphk	for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
363112430Sphk		if (ps->cmd != nullstr)
364112430Sphk			ckfree(ps->cmd);
365112430Sphk	}
366112430Sphk	if (jp->ps != &jp->ps0)
367112430Sphk		ckfree(jp->ps);
368112430Sphk	jp->used = 0;
369112430Sphk#if JOBS
370112430Sphk	if (curjob == jp - jobtab + 1)
371112430Sphk		curjob = 0;
372112430Sphk#endif
373112430Sphk	INTON;
374112430Sphk}
375112430Sphk
376112430Sphk
377112430Sphk
378112430Sphkint
379112430Sphkwaitcmd(argc, argv)
380112430Sphk	int argc;
381112430Sphk	char **argv;
382112430Sphk{
383112430Sphk	struct job *job;
384112430Sphk	int status, retval;
385112430Sphk	struct job *jp;
386112430Sphk
387112430Sphk	if (argc > 1) {
388112430Sphk		job = getjob(argv[1]);
389112430Sphk	} else {
390112430Sphk		job = NULL;
391112430Sphk	}
392112430Sphk
393112430Sphk	/*
394112430Sphk	 * Loop until a process is terminated or stopped, or a SIGINT is
395112430Sphk	 * received.
396112430Sphk	 */
397112430Sphk
398112430Sphk	in_waitcmd++;
399112430Sphk	do {
400112430Sphk		if (job != NULL) {
401112430Sphk			if (job->state) {
402112430Sphk				status = job->ps[job->nprocs - 1].status;
403112430Sphk				if (WIFEXITED(status))
404112430Sphk					retval = WEXITSTATUS(status);
405112430Sphk#if JOBS
406112430Sphk				else if (WIFSTOPPED(status))
407112430Sphk					retval = WSTOPSIG(status) + 128;
408112430Sphk#endif
409112430Sphk				else
410112430Sphk					retval = WTERMSIG(status) + 128;
411112430Sphk				if (! iflag)
412112430Sphk					freejob(job);
413112430Sphk				in_waitcmd--;
414112430Sphk				return retval;
415112430Sphk			}
416112430Sphk		} else {
417112430Sphk			for (jp = jobtab ; ; jp++) {
418112430Sphk				if (jp >= jobtab + njobs) {	/* no running procs */
419112430Sphk					in_waitcmd--;
420112430Sphk					return 0;
421112430Sphk				}
42282518Sgallatin				if (jp->used && jp->state == 0)
42382518Sgallatin					break;
42482518Sgallatin			}
425112430Sphk		}
42682518Sgallatin	} while (dowait(1, (struct job *)NULL) != -1);
42782518Sgallatin	in_waitcmd--;
42882518Sgallatin
42983366Sjulian	return 0;
43082518Sgallatin}
431112430Sphk
432112430Sphk
433112430Sphk
434112430Sphkint
435112430Sphkjobidcmd(argc, argv)
436112430Sphk	int argc __unused;
437112430Sphk	char **argv;
438112430Sphk{
439112430Sphk	struct job *jp;
440112430Sphk	int i;
441112430Sphk
442112430Sphk	jp = getjob(argv[1]);
443112430Sphk	for (i = 0 ; i < jp->nprocs ; ) {
444112430Sphk		out1fmt("%d", jp->ps[i].pid);
445112430Sphk		out1c(++i < jp->nprocs? ' ' : '\n');
446112430Sphk	}
447112430Sphk	return 0;
448112430Sphk}
449112430Sphk
450112430Sphk
451112430Sphk
452112430Sphk/*
453112430Sphk * Convert a job name to a job structure.
454112430Sphk */
455112430Sphk
456112430SphkSTATIC struct job *
457112430Sphkgetjob(name)
458112430Sphk	char *name;
459112430Sphk	{
460112430Sphk	int jobno;
461112430Sphk	struct job *jp;
462112430Sphk	int pid;
463112430Sphk	int i;
464112430Sphk
465112430Sphk	if (name == NULL) {
466112430Sphk#if JOBS
467112430Sphkcurrentjob:
468147854Sjhb		if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
469112430Sphk			error("No current job");
470112430Sphk		return &jobtab[jobno - 1];
471147854Sjhb#else
472112430Sphk		error("No current job");
473112430Sphk#endif
474112430Sphk	} else if (name[0] == '%') {
475112430Sphk		if (is_digit(name[1])) {
476112430Sphk			jobno = number(name + 1);
477112430Sphk			if (jobno > 0 && jobno <= njobs
478112430Sphk			 && jobtab[jobno - 1].used != 0)
479112430Sphk				return &jobtab[jobno - 1];
480112430Sphk#if JOBS
481112430Sphk		} else if (name[1] == '%' && name[2] == '\0') {
482112430Sphk			goto currentjob;
48382518Sgallatin#endif
48482518Sgallatin		} else {
485			struct job *found = NULL;
486			for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
487				if (jp->used && jp->nprocs > 0
488				 && prefix(name + 1, jp->ps[0].cmd)) {
489					if (found)
490						error("%s: ambiguous", name);
491					found = jp;
492				}
493			}
494			if (found)
495				return found;
496		}
497	} else if (is_number(name)) {
498		pid = number(name);
499		for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
500			if (jp->used && jp->nprocs > 0
501			 && jp->ps[jp->nprocs - 1].pid == pid)
502				return jp;
503		}
504	}
505	error("No such job: %s", name);
506	/*NOTREACHED*/
507	return NULL;
508}
509
510
511
512/*
513 * Return a new job structure,
514 */
515
516struct job *
517makejob(node, nprocs)
518	union node *node __unused;
519	int nprocs;
520{
521	int i;
522	struct job *jp;
523
524	for (i = njobs, jp = jobtab ; ; jp++) {
525		if (--i < 0) {
526			INTOFF;
527			if (njobs == 0) {
528				jobtab = ckmalloc(4 * sizeof jobtab[0]);
529			} else {
530				jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
531				memcpy(jp, jobtab, njobs * sizeof jp[0]);
532				/* Relocate `ps' pointers */
533				for (i = 0; i < njobs; i++)
534					if (jp[i].ps == &jobtab[i].ps0)
535						jp[i].ps = &jp[i].ps0;
536				ckfree(jobtab);
537				jobtab = jp;
538			}
539			jp = jobtab + njobs;
540			for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
541			INTON;
542			break;
543		}
544		if (jp->used == 0)
545			break;
546	}
547	INTOFF;
548	jp->state = 0;
549	jp->used = 1;
550	jp->changed = 0;
551	jp->nprocs = 0;
552#if JOBS
553	jp->jobctl = jobctl;
554#endif
555	if (nprocs > 1) {
556		jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
557	} else {
558		jp->ps = &jp->ps0;
559	}
560	INTON;
561	TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
562	    jp - jobtab + 1));
563	return jp;
564}
565
566
567/*
568 * Fork of a subshell.  If we are doing job control, give the subshell its
569 * own process group.  Jp is a job structure that the job is to be added to.
570 * N is the command that will be evaluated by the child.  Both jp and n may
571 * be NULL.  The mode parameter can be one of the following:
572 *	FORK_FG - Fork off a foreground process.
573 *	FORK_BG - Fork off a background process.
574 *	FORK_NOJOB - Like FORK_FG, but don't give the process its own
575 *		     process group even if job control is on.
576 *
577 * When job control is turned off, background processes have their standard
578 * input redirected to /dev/null (except for the second and later processes
579 * in a pipeline).
580 */
581
582int
583forkshell(jp, n, mode)
584	union node *n;
585	struct job *jp;
586	int mode;
587{
588	int pid;
589	int pgrp;
590
591	TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long)n,
592	    mode));
593	INTOFF;
594	pid = fork();
595	if (pid == -1) {
596		TRACE(("Fork failed, errno=%d\n", errno));
597		INTON;
598		error("Cannot fork: %s", strerror(errno));
599	}
600	if (pid == 0) {
601		struct job *p;
602		int wasroot;
603		int i;
604
605		TRACE(("Child shell %d\n", getpid()));
606		wasroot = rootshell;
607		rootshell = 0;
608		for (i = njobs, p = jobtab ; --i >= 0 ; p++)
609			if (p->used)
610				freejob(p);
611		closescript();
612		INTON;
613		clear_traps();
614#if JOBS
615		jobctl = 0;		/* do job control only in root shell */
616		if (wasroot && mode != FORK_NOJOB && mflag) {
617			if (jp == NULL || jp->nprocs == 0)
618				pgrp = getpid();
619			else
620				pgrp = jp->ps[0].pid;
621			if (setpgid(0, pgrp) == 0 && mode == FORK_FG) {
622				/*** this causes superfluous TIOCSPGRPS ***/
623#ifdef OLD_TTY_DRIVER
624				if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0)
625					error("TIOCSPGRP failed, errno=%d", errno);
626#else
627				if (tcsetpgrp(2, pgrp) < 0)
628					error("tcsetpgrp failed, errno=%d", errno);
629#endif
630			}
631			setsignal(SIGTSTP);
632			setsignal(SIGTTOU);
633		} else if (mode == FORK_BG) {
634			ignoresig(SIGINT);
635			ignoresig(SIGQUIT);
636			if ((jp == NULL || jp->nprocs == 0) &&
637			    ! fd0_redirected_p ()) {
638				close(0);
639				if (open(_PATH_DEVNULL, O_RDONLY) != 0)
640					error("Can't open %s: %s",
641					    _PATH_DEVNULL, strerror(errno));
642			}
643		}
644#else
645		if (mode == FORK_BG) {
646			ignoresig(SIGINT);
647			ignoresig(SIGQUIT);
648			if ((jp == NULL || jp->nprocs == 0) &&
649			    ! fd0_redirected_p ()) {
650				close(0);
651				if (open(_PATH_DEVNULL, O_RDONLY) != 0)
652					error("Can't open %s: %s",
653					    _PATH_DEVNULL, strerror(errno));
654			}
655		}
656#endif
657		if (wasroot && iflag) {
658			setsignal(SIGINT);
659			setsignal(SIGQUIT);
660			setsignal(SIGTERM);
661		}
662		return pid;
663	}
664	if (rootshell && mode != FORK_NOJOB && mflag) {
665		if (jp == NULL || jp->nprocs == 0)
666			pgrp = pid;
667		else
668			pgrp = jp->ps[0].pid;
669		setpgid(pid, pgrp);
670	}
671	if (mode == FORK_BG)
672		backgndpid = pid;		/* set $! */
673	if (jp) {
674		struct procstat *ps = &jp->ps[jp->nprocs++];
675		ps->pid = pid;
676		ps->status = -1;
677		ps->cmd = nullstr;
678		if (iflag && rootshell && n)
679			ps->cmd = commandtext(n);
680	}
681	INTON;
682	TRACE(("In parent shell:  child = %d\n", pid));
683	return pid;
684}
685
686
687
688/*
689 * Wait for job to finish.
690 *
691 * Under job control we have the problem that while a child process is
692 * running interrupts generated by the user are sent to the child but not
693 * to the shell.  This means that an infinite loop started by an inter-
694 * active user may be hard to kill.  With job control turned off, an
695 * interactive user may place an interactive program inside a loop.  If
696 * the interactive program catches interrupts, the user doesn't want
697 * these interrupts to also abort the loop.  The approach we take here
698 * is to have the shell ignore interrupt signals while waiting for a
699 * foreground process to terminate, and then send itself an interrupt
700 * signal if the child process was terminated by an interrupt signal.
701 * Unfortunately, some programs want to do a bit of cleanup and then
702 * exit on interrupt; unless these processes terminate themselves by
703 * sending a signal to themselves (instead of calling exit) they will
704 * confuse this approach.
705 */
706
707int
708waitforjob(jp, origstatus)
709	struct job *jp;
710	int *origstatus;
711{
712#if JOBS
713	int mypgrp = getpgrp();
714#endif
715	int status;
716	int st;
717
718	INTOFF;
719	TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
720	while (jp->state == 0)
721		if (dowait(1, jp) == -1)
722			dotrap();
723#if JOBS
724	if (jp->jobctl) {
725#ifdef OLD_TTY_DRIVER
726		if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0)
727			error("TIOCSPGRP failed, errno=%d\n", errno);
728#else
729		if (tcsetpgrp(2, mypgrp) < 0)
730			error("tcsetpgrp failed, errno=%d\n", errno);
731#endif
732	}
733	if (jp->state == JOBSTOPPED)
734		curjob = jp - jobtab + 1;
735#endif
736	status = jp->ps[jp->nprocs - 1].status;
737	if (origstatus != NULL)
738		*origstatus = status;
739	/* convert to 8 bits */
740	if (WIFEXITED(status))
741		st = WEXITSTATUS(status);
742#if JOBS
743	else if (WIFSTOPPED(status))
744		st = WSTOPSIG(status) + 128;
745#endif
746	else
747		st = WTERMSIG(status) + 128;
748	if (! JOBS || jp->state == JOBDONE)
749		freejob(jp);
750	if (int_pending()) {
751		if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
752			kill(getpid(), SIGINT);
753		else
754			CLEAR_PENDING_INT;
755	}
756	INTON;
757	return st;
758}
759
760
761
762/*
763 * Wait for a process to terminate.
764 */
765
766STATIC int
767dowait(block, job)
768	int block;
769	struct job *job;
770{
771	int pid;
772	int status;
773	struct procstat *sp;
774	struct job *jp;
775	struct job *thisjob;
776	int done;
777	int stopped;
778	int core;
779	int sig;
780
781	in_dowait++;
782	TRACE(("dowait(%d) called\n", block));
783	do {
784		pid = waitproc(block, &status);
785		TRACE(("wait returns %d, status=%d\n", pid, status));
786	} while ((pid == -1 && errno == EINTR && breakwaitcmd == 0) ||
787	    (WIFSTOPPED(status) && !iflag));
788	in_dowait--;
789	if (breakwaitcmd != 0) {
790		breakwaitcmd = 0;
791		return -1;
792	}
793	if (pid <= 0)
794		return pid;
795	INTOFF;
796	thisjob = NULL;
797	for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
798		if (jp->used) {
799			done = 1;
800			stopped = 1;
801			for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
802				if (sp->pid == -1)
803					continue;
804				if (sp->pid == pid) {
805					TRACE(("Changing status of proc %d from 0x%x to 0x%x\n",
806						   pid, sp->status, status));
807					sp->status = status;
808					thisjob = jp;
809				}
810				if (sp->status == -1)
811					stopped = 0;
812				else if (WIFSTOPPED(sp->status))
813					done = 0;
814			}
815			if (stopped) {		/* stopped or done */
816				int state = done? JOBDONE : JOBSTOPPED;
817				if (jp->state != state) {
818					TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
819					jp->state = state;
820#if JOBS
821					if (done && curjob == jp - jobtab + 1)
822						curjob = 0;		/* no current job */
823#endif
824				}
825			}
826		}
827	}
828	INTON;
829	if (! rootshell || ! iflag || (job && thisjob == job)) {
830		core = WCOREDUMP(status);
831#if JOBS
832		if (WIFSTOPPED(status))
833			sig = WSTOPSIG(status);
834		else
835#endif
836			if (WIFEXITED(status))
837				sig = 0;
838			else
839				sig = WTERMSIG(status);
840
841		if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
842			if (thisjob != job)
843				outfmt(out2, "%d: ", pid);
844#if JOBS
845			if (sig == SIGTSTP && rootshell && iflag)
846				outfmt(out2, "%%%d ", job - jobtab + 1);
847#endif
848			if (sig < NSIG && sys_siglist[sig])
849				out2str(sys_siglist[sig]);
850			else
851				outfmt(out2, "Signal %d", sig);
852			if (core)
853				out2str(" - core dumped");
854			out2c('\n');
855			flushout(&errout);
856		} else {
857			TRACE(("Not printing status: status=%d, sig=%d\n",
858				   status, sig));
859		}
860	} else {
861		TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell, job));
862		if (thisjob)
863			thisjob->changed = 1;
864	}
865	return pid;
866}
867
868
869
870/*
871 * Do a wait system call.  If job control is compiled in, we accept
872 * stopped processes.  If block is zero, we return a value of zero
873 * rather than blocking.
874 *
875 * System V doesn't have a non-blocking wait system call.  It does
876 * have a SIGCLD signal that is sent to a process when one of it's
877 * children dies.  The obvious way to use SIGCLD would be to install
878 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
879 * was received, and have waitproc bump another counter when it got
880 * the status of a process.  Waitproc would then know that a wait
881 * system call would not block if the two counters were different.
882 * This approach doesn't work because if a process has children that
883 * have not been waited for, System V will send it a SIGCLD when it
884 * installs a signal handler for SIGCLD.  What this means is that when
885 * a child exits, the shell will be sent SIGCLD signals continuously
886 * until is runs out of stack space, unless it does a wait call before
887 * restoring the signal handler.  The code below takes advantage of
888 * this (mis)feature by installing a signal handler for SIGCLD and
889 * then checking to see whether it was called.  If there are any
890 * children to be waited for, it will be.
891 *
892 * If neither SYSV nor BSD is defined, we don't implement nonblocking
893 * waits at all.  In this case, the user will not be informed when
894 * a background process until the next time she runs a real program
895 * (as opposed to running a builtin command or just typing return),
896 * and the jobs command may give out of date information.
897 */
898
899#ifdef SYSV
900STATIC sig_atomic_t gotsigchild;
901
902STATIC int onsigchild() {
903	gotsigchild = 1;
904}
905#endif
906
907
908STATIC int
909waitproc(block, status)
910	int block;
911	int *status;
912{
913#ifdef BSD
914	int flags;
915
916#if JOBS
917	flags = WUNTRACED;
918#else
919	flags = 0;
920#endif
921	if (block == 0)
922		flags |= WNOHANG;
923	return wait3(status, flags, (struct rusage *)NULL);
924#else
925#ifdef SYSV
926	int (*save)();
927
928	if (block == 0) {
929		gotsigchild = 0;
930		save = signal(SIGCLD, onsigchild);
931		signal(SIGCLD, save);
932		if (gotsigchild == 0)
933			return 0;
934	}
935	return wait(status);
936#else
937	if (block == 0)
938		return 0;
939	return wait(status);
940#endif
941#endif
942}
943
944/*
945 * return 1 if there are stopped jobs, otherwise 0
946 */
947int job_warning = 0;
948int
949stoppedjobs()
950{
951	int jobno;
952	struct job *jp;
953
954	if (job_warning)
955		return (0);
956	for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
957		if (jp->used == 0)
958			continue;
959		if (jp->state == JOBSTOPPED) {
960			out2str("You have stopped jobs.\n");
961			job_warning = 2;
962			return (1);
963		}
964	}
965
966	return (0);
967}
968
969/*
970 * Return a string identifying a command (to be printed by the
971 * jobs command.
972 */
973
974STATIC char *cmdnextc;
975STATIC int cmdnleft;
976#define MAXCMDTEXT	200
977
978char *
979commandtext(n)
980	union node *n;
981	{
982	char *name;
983
984	cmdnextc = name = ckmalloc(MAXCMDTEXT);
985	cmdnleft = MAXCMDTEXT - 4;
986	cmdtxt(n);
987	*cmdnextc = '\0';
988	return name;
989}
990
991
992STATIC void
993cmdtxt(n)
994	union node *n;
995	{
996	union node *np;
997	struct nodelist *lp;
998	char *p;
999	int i;
1000	char s[2];
1001
1002	if (n == NULL)
1003		return;
1004	switch (n->type) {
1005	case NSEMI:
1006		cmdtxt(n->nbinary.ch1);
1007		cmdputs("; ");
1008		cmdtxt(n->nbinary.ch2);
1009		break;
1010	case NAND:
1011		cmdtxt(n->nbinary.ch1);
1012		cmdputs(" && ");
1013		cmdtxt(n->nbinary.ch2);
1014		break;
1015	case NOR:
1016		cmdtxt(n->nbinary.ch1);
1017		cmdputs(" || ");
1018		cmdtxt(n->nbinary.ch2);
1019		break;
1020	case NPIPE:
1021		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
1022			cmdtxt(lp->n);
1023			if (lp->next)
1024				cmdputs(" | ");
1025		}
1026		break;
1027	case NSUBSHELL:
1028		cmdputs("(");
1029		cmdtxt(n->nredir.n);
1030		cmdputs(")");
1031		break;
1032	case NREDIR:
1033	case NBACKGND:
1034		cmdtxt(n->nredir.n);
1035		break;
1036	case NIF:
1037		cmdputs("if ");
1038		cmdtxt(n->nif.test);
1039		cmdputs("; then ");
1040		cmdtxt(n->nif.ifpart);
1041		cmdputs("...");
1042		break;
1043	case NWHILE:
1044		cmdputs("while ");
1045		goto until;
1046	case NUNTIL:
1047		cmdputs("until ");
1048until:
1049		cmdtxt(n->nbinary.ch1);
1050		cmdputs("; do ");
1051		cmdtxt(n->nbinary.ch2);
1052		cmdputs("; done");
1053		break;
1054	case NFOR:
1055		cmdputs("for ");
1056		cmdputs(n->nfor.var);
1057		cmdputs(" in ...");
1058		break;
1059	case NCASE:
1060		cmdputs("case ");
1061		cmdputs(n->ncase.expr->narg.text);
1062		cmdputs(" in ...");
1063		break;
1064	case NDEFUN:
1065		cmdputs(n->narg.text);
1066		cmdputs("() ...");
1067		break;
1068	case NCMD:
1069		for (np = n->ncmd.args ; np ; np = np->narg.next) {
1070			cmdtxt(np);
1071			if (np->narg.next)
1072				cmdputs(" ");
1073		}
1074		for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
1075			cmdputs(" ");
1076			cmdtxt(np);
1077		}
1078		break;
1079	case NARG:
1080		cmdputs(n->narg.text);
1081		break;
1082	case NTO:
1083		p = ">";  i = 1;  goto redir;
1084	case NAPPEND:
1085		p = ">>";  i = 1;  goto redir;
1086	case NTOFD:
1087		p = ">&";  i = 1;  goto redir;
1088	case NFROM:
1089		p = "<";  i = 0;  goto redir;
1090	case NFROMTO:
1091		p = "<>";  i = 0;  goto redir;
1092	case NFROMFD:
1093		p = "<&";  i = 0;  goto redir;
1094redir:
1095		if (n->nfile.fd != i) {
1096			s[0] = n->nfile.fd + '0';
1097			s[1] = '\0';
1098			cmdputs(s);
1099		}
1100		cmdputs(p);
1101		if (n->type == NTOFD || n->type == NFROMFD) {
1102			s[0] = n->ndup.dupfd + '0';
1103			s[1] = '\0';
1104			cmdputs(s);
1105		} else {
1106			cmdtxt(n->nfile.fname);
1107		}
1108		break;
1109	case NHERE:
1110	case NXHERE:
1111		cmdputs("<<...");
1112		break;
1113	default:
1114		cmdputs("???");
1115		break;
1116	}
1117}
1118
1119
1120
1121STATIC void
1122cmdputs(s)
1123	char *s;
1124	{
1125	char *p, *q;
1126	char c;
1127	int subtype = 0;
1128
1129	if (cmdnleft <= 0)
1130		return;
1131	p = s;
1132	q = cmdnextc;
1133	while ((c = *p++) != '\0') {
1134		if (c == CTLESC)
1135			*q++ = *p++;
1136		else if (c == CTLVAR) {
1137			*q++ = '$';
1138			if (--cmdnleft > 0)
1139				*q++ = '{';
1140			subtype = *p++;
1141		} else if (c == '=' && subtype != 0) {
1142			*q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
1143			subtype = 0;
1144		} else if (c == CTLENDVAR) {
1145			*q++ = '}';
1146		} else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
1147			cmdnleft++;		/* ignore it */
1148		else
1149			*q++ = c;
1150		if (--cmdnleft <= 0) {
1151			*q++ = '.';
1152			*q++ = '.';
1153			*q++ = '.';
1154			break;
1155		}
1156	}
1157	cmdnextc = q;
1158}
1159