1/*	$OpenBSD: jobs.c,v 1.38 2009/12/12 04:28:44 deraadt Exp $	*/
2
3/*-
4 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011
5 *	Thorsten Glaser <tg@mirbsd.org>
6 *
7 * Provided that these terms and disclaimer and all copyright notices
8 * are retained or reproduced in an accompanying document, permission
9 * is granted to deal in this work without restriction, including un-
10 * limited rights to use, publicly perform, distribute, sell, modify,
11 * merge, give away, or sublicence.
12 *
13 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
14 * the utmost extent permitted by applicable law, neither express nor
15 * implied; without malicious intent or gross negligence. In no event
16 * may a licensor, author or contributor be held liable for indirect,
17 * direct, other damage, loss, or other issues arising in any way out
18 * of dealing in the work, even if advised of the possibility of such
19 * damage or existence of a defect, except proven that it results out
20 * of said person's immediate fault when using the work as intended.
21 */
22
23#include "sh.h"
24
25__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.81 2011/08/27 18:06:46 tg Exp $");
26
27#if HAVE_KILLPG
28#define mksh_killpg		killpg
29#else
30/* cross fingers and hope kill is killpg-endowed */
31#define mksh_killpg(p,s)	kill(-(p), (s))
32#endif
33
34/* Order important! */
35#define PRUNNING	0
36#define PEXITED		1
37#define PSIGNALLED	2
38#define PSTOPPED	3
39
40typedef struct proc	Proc;
41struct proc {
42	Proc *next;		/* next process in pipeline (if any) */
43	pid_t pid;		/* process id */
44	int state;
45	int status;		/* wait status */
46	char command[48];	/* process command string */
47};
48
49/* Notify/print flag - j_print() argument */
50#define JP_NONE		0	/* don't print anything */
51#define JP_SHORT	1	/* print signals processes were killed by */
52#define JP_MEDIUM	2	/* print [job-num] -/+ command */
53#define JP_LONG		3	/* print [job-num] -/+ pid command */
54#define JP_PGRP		4	/* print pgrp */
55
56/* put_job() flags */
57#define PJ_ON_FRONT	0	/* at very front */
58#define PJ_PAST_STOPPED	1	/* just past any stopped jobs */
59
60/* Job.flags values */
61#define JF_STARTED	0x001	/* set when all processes in job are started */
62#define JF_WAITING	0x002	/* set if j_waitj() is waiting on job */
63#define JF_W_ASYNCNOTIFY 0x004	/* set if waiting and async notification ok */
64#define JF_XXCOM	0x008	/* set for $(command) jobs */
65#define JF_FG		0x010	/* running in foreground (also has tty pgrp) */
66#define JF_SAVEDTTY	0x020	/* j->ttystat is valid */
67#define JF_CHANGED	0x040	/* process has changed state */
68#define JF_KNOWN	0x080	/* $! referenced */
69#define JF_ZOMBIE	0x100	/* known, unwaited process */
70#define JF_REMOVE	0x200	/* flagged for removal (j_jobs()/j_noityf()) */
71#define JF_USETTYMODE	0x400	/* tty mode saved if process exits normally */
72#define JF_SAVEDTTYPGRP	0x800	/* j->saved_ttypgrp is valid */
73
74typedef struct job Job;
75struct job {
76	Job *next;		/* next job in list */
77	Proc *proc_list;	/* process list */
78	Proc *last_proc;	/* last process in list */
79	struct timeval systime;	/* system time used by job */
80	struct timeval usrtime;	/* user time used by job */
81	pid_t pgrp;		/* process group of job */
82	pid_t ppid;		/* pid of process that forked job */
83	int job;		/* job number: %n */
84	int flags;		/* see JF_* */
85	volatile int state;	/* job state */
86	int status;		/* exit status of last process */
87	int32_t	age;		/* number of jobs started */
88	Coproc_id coproc_id;	/* 0 or id of coprocess output pipe */
89#ifndef MKSH_UNEMPLOYED
90	struct termios ttystat;	/* saved tty state for stopped jobs */
91	pid_t saved_ttypgrp;	/* saved tty process group for stopped jobs */
92#endif
93};
94
95/* Flags for j_waitj() */
96#define JW_NONE		0x00
97#define JW_INTERRUPT	0x01	/* ^C will stop the wait */
98#define JW_ASYNCNOTIFY	0x02	/* asynchronous notification during wait ok */
99#define JW_STOPPEDWAIT	0x04	/* wait even if job stopped */
100#define JW_PIPEST	0x08	/* want PIPESTATUS */
101
102/* Error codes for j_lookup() */
103#define JL_OK		0
104#define JL_NOSUCH	1	/* no such job */
105#define JL_AMBIG	2	/* %foo or %?foo is ambiguous */
106#define JL_INVALID	3	/* non-pid, non-% job id */
107
108static const char *const lookup_msgs[] = {
109	null,
110	"no such job",
111	"ambiguous",
112	"argument must be %job or process id",
113	NULL
114};
115
116static Job *job_list;		/* job list */
117static Job *last_job;
118static Job *async_job;
119static pid_t async_pid;
120
121static int nzombie;		/* # of zombies owned by this process */
122static int32_t njobs;		/* # of jobs started */
123
124#ifndef CHILD_MAX
125#define CHILD_MAX	25
126#endif
127
128#ifndef MKSH_NOPROSPECTOFWORK
129/* held_sigchld is set if sigchld occurs before a job is completely started */
130static volatile sig_atomic_t held_sigchld;
131#endif
132
133#ifndef MKSH_UNEMPLOYED
134static struct shf	*shl_j;
135static bool		ttypgrp_ok;	/* set if can use tty pgrps */
136static pid_t		restore_ttypgrp = -1;
137static int const	tt_sigs[] = { SIGTSTP, SIGTTIN, SIGTTOU };
138#endif
139
140static void		j_set_async(Job *);
141static void		j_startjob(Job *);
142static int		j_waitj(Job *, int, const char *);
143static void		j_sigchld(int);
144static void		j_print(Job *, int, struct shf *);
145static Job		*j_lookup(const char *, int *);
146static Job		*new_job(void);
147static Proc		*new_proc(void);
148static void		check_job(Job *);
149static void		put_job(Job *, int);
150static void		remove_job(Job *, const char *);
151static int		kill_job(Job *, int);
152
153/* initialise job control */
154void
155j_init(void)
156{
157#ifndef MKSH_UNEMPLOYED
158	bool mflagset = Flag(FMONITOR) != 127;
159
160	Flag(FMONITOR) = 0;
161#endif
162
163#ifndef MKSH_NOPROSPECTOFWORK
164	(void)sigemptyset(&sm_default);
165	sigprocmask(SIG_SETMASK, &sm_default, NULL);
166
167	(void)sigemptyset(&sm_sigchld);
168	(void)sigaddset(&sm_sigchld, SIGCHLD);
169
170	setsig(&sigtraps[SIGCHLD], j_sigchld,
171	    SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP);
172#else
173	/* Make sure SIGCHLD isn't ignored - can do odd things under SYSV */
174	setsig(&sigtraps[SIGCHLD], SIG_DFL, SS_RESTORE_ORIG|SS_FORCE);
175#endif
176
177#ifndef MKSH_UNEMPLOYED
178	if (!mflagset && Flag(FTALKING))
179		Flag(FMONITOR) = 1;
180
181	/*
182	 * shl_j is used to do asynchronous notification (used in
183	 * an interrupt handler, so need a distinct shf)
184	 */
185	shl_j = shf_fdopen(2, SHF_WR, NULL);
186
187	if (Flag(FMONITOR) || Flag(FTALKING)) {
188		int i;
189
190		/*
191		 * the TF_SHELL_USES test is a kludge that lets us know if
192		 * if the signals have been changed by the shell.
193		 */
194		for (i = NELEM(tt_sigs); --i >= 0; ) {
195			sigtraps[tt_sigs[i]].flags |= TF_SHELL_USES;
196			/* j_change() sets this to SS_RESTORE_DFL if FMONITOR */
197			setsig(&sigtraps[tt_sigs[i]], SIG_IGN,
198			    SS_RESTORE_IGN|SS_FORCE);
199		}
200	}
201
202	/* j_change() calls tty_init() */
203	if (Flag(FMONITOR))
204		j_change();
205	else
206#endif
207	  if (Flag(FTALKING))
208		tty_init(true, true);
209}
210
211static int
212proc_errorlevel(Proc *p)
213{
214	switch (p->state) {
215	case PEXITED:
216		return (WEXITSTATUS(p->status));
217	case PSIGNALLED:
218		return (128 + WTERMSIG(p->status));
219	default:
220		return (0);
221	}
222}
223
224/* job cleanup before shell exit */
225void
226j_exit(void)
227{
228	/* kill stopped, and possibly running, jobs */
229	Job *j;
230	bool killed = false;
231
232	for (j = job_list; j != NULL; j = j->next) {
233		if (j->ppid == procpid &&
234		    (j->state == PSTOPPED ||
235		    (j->state == PRUNNING &&
236		    ((j->flags & JF_FG) ||
237		    (Flag(FLOGIN) && !Flag(FNOHUP) && procpid == kshpid))))) {
238			killed = true;
239			if (j->pgrp == 0)
240				kill_job(j, SIGHUP);
241			else
242				mksh_killpg(j->pgrp, SIGHUP);
243#ifndef MKSH_UNEMPLOYED
244			if (j->state == PSTOPPED) {
245				if (j->pgrp == 0)
246					kill_job(j, SIGCONT);
247				else
248					mksh_killpg(j->pgrp, SIGCONT);
249			}
250#endif
251		}
252	}
253	if (killed)
254		sleep(1);
255	j_notify();
256
257#ifndef MKSH_UNEMPLOYED
258	if (kshpid == procpid && restore_ttypgrp >= 0) {
259		/*
260		 * Need to restore the tty pgrp to what it was when the
261		 * shell started up, so that the process that started us
262		 * will be able to access the tty when we are done.
263		 * Also need to restore our process group in case we are
264		 * about to do an exec so that both our parent and the
265		 * process we are to become will be able to access the tty.
266		 */
267		tcsetpgrp(tty_fd, restore_ttypgrp);
268		setpgid(0, restore_ttypgrp);
269	}
270	if (Flag(FMONITOR)) {
271		Flag(FMONITOR) = 0;
272		j_change();
273	}
274#endif
275}
276
277#ifndef MKSH_UNEMPLOYED
278/* turn job control on or off according to Flag(FMONITOR) */
279void
280j_change(void)
281{
282	int i;
283
284	if (Flag(FMONITOR)) {
285		bool use_tty = Flag(FTALKING);
286
287		/* Don't call tcgetattr() 'til we own the tty process group */
288		if (use_tty)
289			tty_init(false, true);
290
291		/* no controlling tty, no SIGT* */
292		if ((ttypgrp_ok = use_tty && tty_fd >= 0 && tty_devtty)) {
293			setsig(&sigtraps[SIGTTIN], SIG_DFL,
294			    SS_RESTORE_ORIG|SS_FORCE);
295			/* wait to be given tty (POSIX.1, B.2, job control) */
296			while (/* CONSTCOND */ 1) {
297				pid_t ttypgrp;
298
299				if ((ttypgrp = tcgetpgrp(tty_fd)) < 0) {
300					warningf(false, "%s: %s %s: %s",
301					    "j_init", "tcgetpgrp", "failed",
302					    strerror(errno));
303					ttypgrp_ok = false;
304					break;
305				}
306				if (ttypgrp == kshpgrp)
307					break;
308				kill(0, SIGTTIN);
309			}
310		}
311		for (i = NELEM(tt_sigs); --i >= 0; )
312			setsig(&sigtraps[tt_sigs[i]], SIG_IGN,
313			    SS_RESTORE_DFL|SS_FORCE);
314		if (ttypgrp_ok && kshpgrp != kshpid) {
315			if (setpgid(0, kshpid) < 0) {
316				warningf(false, "%s: %s %s: %s", "j_init",
317				    "setpgid", "failed", strerror(errno));
318				ttypgrp_ok = false;
319			} else {
320				if (tcsetpgrp(tty_fd, kshpid) < 0) {
321					warningf(false, "%s: %s %s: %s",
322					    "j_init", "tcsetpgrp", "failed",
323					    strerror(errno));
324					ttypgrp_ok = false;
325				} else
326					restore_ttypgrp = kshpgrp;
327				kshpgrp = kshpid;
328			}
329		}
330		if (use_tty && !ttypgrp_ok)
331			warningf(false, "%s: %s", "warning",
332			    "won't have full job control");
333		if (tty_fd >= 0)
334			tcgetattr(tty_fd, &tty_state);
335	} else {
336		ttypgrp_ok = false;
337		if (Flag(FTALKING))
338			for (i = NELEM(tt_sigs); --i >= 0; )
339				setsig(&sigtraps[tt_sigs[i]], SIG_IGN,
340				    SS_RESTORE_IGN|SS_FORCE);
341		else
342			for (i = NELEM(tt_sigs); --i >= 0; ) {
343				if (sigtraps[tt_sigs[i]].flags &
344				    (TF_ORIG_IGN | TF_ORIG_DFL))
345					setsig(&sigtraps[tt_sigs[i]],
346					    (sigtraps[tt_sigs[i]].flags & TF_ORIG_IGN) ?
347					    SIG_IGN : SIG_DFL,
348					    SS_RESTORE_ORIG|SS_FORCE);
349			}
350		if (!Flag(FTALKING))
351			tty_close();
352	}
353}
354#endif
355
356#if HAVE_NICE
357/* run nice(3) and ignore the result */
358static void
359ksh_nice(int ness)
360{
361#if defined(__USE_FORTIFY_LEVEL) && (__USE_FORTIFY_LEVEL > 0)
362	int e;
363
364	errno = 0;
365	/* this is gonna annoy users; complain to your distro, people! */
366	if (nice(ness) == -1 && (e = errno) != 0)
367		warningf(false, "%s: %s", "bgnice", strerror(e));
368#else
369	(void)nice(ness);
370#endif
371}
372#endif
373
374/* execute tree in child subprocess */
375int
376exchild(struct op *t, int flags,
377    volatile int *xerrok,
378    /* used if XPCLOSE or XCCLOSE */
379    int close_fd)
380{
381	/* for pipelines */
382	static Proc *last_proc;
383
384	int rv = 0, forksleep, jwflags = JW_NONE;
385#ifndef MKSH_NOPROSPECTOFWORK
386	sigset_t omask;
387#endif
388	Proc *p;
389	Job *j;
390	pid_t cldpid;
391
392	if (flags & XPIPEST) {
393		flags &= ~XPIPEST;
394		jwflags |= JW_PIPEST;
395	}
396
397	if (flags & XEXEC)
398		/*
399		 * Clear XFORK|XPCLOSE|XCCLOSE|XCOPROC|XPIPEO|XPIPEI|XXCOM|XBGND
400		 * (also done in another execute() below)
401		 */
402		return (execute(t, flags & (XEXEC | XERROK), xerrok));
403
404#ifndef MKSH_NOPROSPECTOFWORK
405	/* no SIGCHLDs while messing with job and process lists */
406	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
407#endif
408
409	p = new_proc();
410	p->next = NULL;
411	p->state = PRUNNING;
412	p->status = 0;
413	p->pid = 0;
414
415	/* link process into jobs list */
416	if (flags & XPIPEI) {
417		/* continuing with a pipe */
418		if (!last_job)
419			internal_errorf("%s %d",
420			    "exchild: XPIPEI and no last_job - pid",
421			    (int)procpid);
422		j = last_job;
423		if (last_proc)
424			last_proc->next = p;
425		last_proc = p;
426	} else {
427		/* fills in j->job */
428		j = new_job();
429		/*
430		 * we don't consider XXCOMs foreground since they don't get
431		 * tty process group and we don't save or restore tty modes.
432		 */
433		j->flags = (flags & XXCOM) ? JF_XXCOM :
434		    ((flags & XBGND) ? 0 : (JF_FG|JF_USETTYMODE));
435		timerclear(&j->usrtime);
436		timerclear(&j->systime);
437		j->state = PRUNNING;
438		j->pgrp = 0;
439		j->ppid = procpid;
440		j->age = ++njobs;
441		j->proc_list = p;
442		j->coproc_id = 0;
443		last_job = j;
444		last_proc = p;
445		put_job(j, PJ_PAST_STOPPED);
446	}
447
448	vistree(p->command, sizeof(p->command), t);
449
450	/* create child process */
451	forksleep = 1;
452	while ((cldpid = fork()) < 0 && errno == EAGAIN && forksleep < 32) {
453		if (intrsig)
454			/* allow user to ^C out... */
455			break;
456		sleep(forksleep);
457		forksleep <<= 1;
458	}
459	/* ensure $RANDOM changes between parent and child */
460	rndset((long)cldpid);
461	/* fork failed? */
462	if (cldpid < 0) {
463		kill_job(j, SIGKILL);
464		remove_job(j, "fork failed");
465#ifndef MKSH_NOPROSPECTOFWORK
466		sigprocmask(SIG_SETMASK, &omask, NULL);
467#endif
468		errorf("can't fork - try again");
469	}
470	p->pid = cldpid ? cldpid : (procpid = getpid());
471
472#ifndef MKSH_UNEMPLOYED
473	/* job control set up */
474	if (Flag(FMONITOR) && !(flags&XXCOM)) {
475		bool dotty = false;
476		if (j->pgrp == 0) {
477			/* First process */
478			j->pgrp = p->pid;
479			dotty = true;
480		}
481
482		/*
483		 * set pgrp in both parent and child to deal with race
484		 * condition
485		 */
486		setpgid(p->pid, j->pgrp);
487		if (ttypgrp_ok && dotty && !(flags & XBGND))
488			tcsetpgrp(tty_fd, j->pgrp);
489	}
490#endif
491
492	/* used to close pipe input fd */
493	if (close_fd >= 0 && (((flags & XPCLOSE) && cldpid) ||
494	    ((flags & XCCLOSE) && !cldpid)))
495		close(close_fd);
496	if (!cldpid) {
497		/* child */
498
499		/* Do this before restoring signal */
500		if (flags & XCOPROC)
501			coproc_cleanup(false);
502#ifndef MKSH_NOPROSPECTOFWORK
503		sigprocmask(SIG_SETMASK, &omask, NULL);
504#endif
505		cleanup_parents_env();
506#ifndef MKSH_UNEMPLOYED
507		/*
508		 * If FMONITOR or FTALKING is set, these signals are ignored,
509		 * if neither FMONITOR nor FTALKING are set, the signals have
510		 * their inherited values.
511		 */
512		if (Flag(FMONITOR) && !(flags & XXCOM)) {
513			for (forksleep = NELEM(tt_sigs); --forksleep >= 0; )
514				setsig(&sigtraps[tt_sigs[forksleep]], SIG_DFL,
515				    SS_RESTORE_DFL|SS_FORCE);
516		}
517#endif
518#if HAVE_NICE
519		if (Flag(FBGNICE) && (flags & XBGND))
520			ksh_nice(4);
521#endif
522		if ((flags & XBGND)
523#ifndef MKSH_UNEMPLOYED
524		    && !Flag(FMONITOR)
525#endif
526		    ) {
527			setsig(&sigtraps[SIGINT], SIG_IGN,
528			    SS_RESTORE_IGN|SS_FORCE);
529			setsig(&sigtraps[SIGQUIT], SIG_IGN,
530			    SS_RESTORE_IGN|SS_FORCE);
531			if ((!(flags & (XPIPEI | XCOPROC))) &&
532			    ((forksleep = open("/dev/null", 0)) > 0)) {
533				(void)ksh_dup2(forksleep, 0, true);
534				close(forksleep);
535			}
536		}
537		/* in case of $(jobs) command */
538		remove_job(j, "child");
539		nzombie = 0;
540#ifndef MKSH_UNEMPLOYED
541		ttypgrp_ok = false;
542		Flag(FMONITOR) = 0;
543#endif
544		Flag(FTALKING) = 0;
545		tty_close();
546		cleartraps();
547		/* no return */
548		execute(t, (flags & XERROK) | XEXEC, NULL);
549#ifndef MKSH_SMALL
550		if (t->type == TPIPE)
551			unwind(LLEAVE);
552		internal_warningf("%s: %s", "exchild", "execute() returned");
553		fptreef(shl_out, 8, "%s: tried to execute {\n\t%T\n}\n",
554		    "exchild", t);
555		shf_flush(shl_out);
556#endif
557		unwind(LLEAVE);
558		/* NOTREACHED */
559	}
560
561	/* shell (parent) stuff */
562	if (!(flags & XPIPEO)) {
563		/* last process in a job */
564		j_startjob(j);
565		if (flags & XCOPROC) {
566			j->coproc_id = coproc.id;
567			/* n jobs using co-process output */
568			coproc.njobs++;
569			/* j using co-process input */
570			coproc.job = (void *)j;
571		}
572		if (flags & XBGND) {
573			j_set_async(j);
574			if (Flag(FTALKING)) {
575				shf_fprintf(shl_out, "[%d]", j->job);
576				for (p = j->proc_list; p; p = p->next)
577					shf_fprintf(shl_out, " %d",
578					    (int)p->pid);
579				shf_putchar('\n', shl_out);
580				shf_flush(shl_out);
581			}
582		} else
583			rv = j_waitj(j, jwflags, "jw:last proc");
584	}
585
586#ifndef MKSH_NOPROSPECTOFWORK
587	sigprocmask(SIG_SETMASK, &omask, NULL);
588#endif
589
590	return (rv);
591}
592
593/* start the last job: only used for $(command) jobs */
594void
595startlast(void)
596{
597#ifndef MKSH_NOPROSPECTOFWORK
598	sigset_t omask;
599
600	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
601#endif
602
603	/* no need to report error - waitlast() will do it */
604	if (last_job) {
605		/* ensure it isn't removed by check_job() */
606		last_job->flags |= JF_WAITING;
607		j_startjob(last_job);
608	}
609#ifndef MKSH_NOPROSPECTOFWORK
610	sigprocmask(SIG_SETMASK, &omask, NULL);
611#endif
612}
613
614/* wait for last job: only used for $(command) jobs */
615int
616waitlast(void)
617{
618	int rv;
619	Job *j;
620#ifndef MKSH_NOPROSPECTOFWORK
621	sigset_t omask;
622
623	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
624#endif
625
626	j = last_job;
627	if (!j || !(j->flags & JF_STARTED)) {
628		if (!j)
629			warningf(true, "%s: %s", "waitlast", "no last job");
630		else
631			internal_warningf("%s: %s", "waitlast", "not started");
632#ifndef MKSH_NOPROSPECTOFWORK
633		sigprocmask(SIG_SETMASK, &omask, NULL);
634#endif
635		/* not so arbitrary, non-zero value */
636		return (125);
637	}
638
639	rv = j_waitj(j, JW_NONE, "waitlast");
640
641#ifndef MKSH_NOPROSPECTOFWORK
642	sigprocmask(SIG_SETMASK, &omask, NULL);
643#endif
644
645	return (rv);
646}
647
648/* wait for child, interruptable. */
649int
650waitfor(const char *cp, int *sigp)
651{
652	int rv, ecode, flags = JW_INTERRUPT|JW_ASYNCNOTIFY;
653	Job *j;
654#ifndef MKSH_NOPROSPECTOFWORK
655	sigset_t omask;
656
657	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
658#endif
659
660	*sigp = 0;
661
662	if (cp == NULL) {
663		/*
664		 * wait for an unspecified job - always returns 0, so
665		 * don't have to worry about exited/signaled jobs
666		 */
667		for (j = job_list; j; j = j->next)
668			/* AT&T ksh will wait for stopped jobs - we don't */
669			if (j->ppid == procpid && j->state == PRUNNING)
670				break;
671		if (!j) {
672#ifndef MKSH_NOPROSPECTOFWORK
673			sigprocmask(SIG_SETMASK, &omask, NULL);
674#endif
675			return (-1);
676		}
677	} else if ((j = j_lookup(cp, &ecode))) {
678		/* don't report normal job completion */
679		flags &= ~JW_ASYNCNOTIFY;
680		if (j->ppid != procpid) {
681#ifndef MKSH_NOPROSPECTOFWORK
682			sigprocmask(SIG_SETMASK, &omask, NULL);
683#endif
684			return (-1);
685		}
686	} else {
687#ifndef MKSH_NOPROSPECTOFWORK
688		sigprocmask(SIG_SETMASK, &omask, NULL);
689#endif
690		if (ecode != JL_NOSUCH)
691			bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
692		return (-1);
693	}
694
695	/* AT&T ksh will wait for stopped jobs - we don't */
696	rv = j_waitj(j, flags, "jw:waitfor");
697
698#ifndef MKSH_NOPROSPECTOFWORK
699	sigprocmask(SIG_SETMASK, &omask, NULL);
700#endif
701
702	if (rv < 0)
703		/* we were interrupted */
704		*sigp = 128 + -rv;
705
706	return (rv);
707}
708
709/* kill (built-in) a job */
710int
711j_kill(const char *cp, int sig)
712{
713	Job *j;
714	int rv = 0, ecode;
715#ifndef MKSH_NOPROSPECTOFWORK
716	sigset_t omask;
717
718	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
719#endif
720
721	if ((j = j_lookup(cp, &ecode)) == NULL) {
722#ifndef MKSH_NOPROSPECTOFWORK
723		sigprocmask(SIG_SETMASK, &omask, NULL);
724#endif
725		bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
726		return (1);
727	}
728
729	if (j->pgrp == 0) {
730		/* started when !Flag(FMONITOR) */
731		if (kill_job(j, sig) < 0) {
732			bi_errorf("%s: %s", cp, strerror(errno));
733			rv = 1;
734		}
735	} else {
736#ifndef MKSH_UNEMPLOYED
737		if (j->state == PSTOPPED && (sig == SIGTERM || sig == SIGHUP))
738			mksh_killpg(j->pgrp, SIGCONT);
739#endif
740		if (mksh_killpg(j->pgrp, sig) < 0) {
741			bi_errorf("%s: %s", cp, strerror(errno));
742			rv = 1;
743		}
744	}
745
746#ifndef MKSH_NOPROSPECTOFWORK
747	sigprocmask(SIG_SETMASK, &omask, NULL);
748#endif
749
750	return (rv);
751}
752
753#ifndef MKSH_UNEMPLOYED
754/* fg and bg built-ins: called only if Flag(FMONITOR) set */
755int
756j_resume(const char *cp, int bg)
757{
758	Job *j;
759	Proc *p;
760	int ecode, rv = 0;
761	bool running;
762	sigset_t omask;
763
764	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
765
766	if ((j = j_lookup(cp, &ecode)) == NULL) {
767		sigprocmask(SIG_SETMASK, &omask, NULL);
768		bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
769		return (1);
770	}
771
772	if (j->pgrp == 0) {
773		sigprocmask(SIG_SETMASK, &omask, NULL);
774		bi_errorf("job not job-controlled");
775		return (1);
776	}
777
778	if (bg)
779		shprintf("[%d] ", j->job);
780
781	running = false;
782	for (p = j->proc_list; p != NULL; p = p->next) {
783		if (p->state == PSTOPPED) {
784			p->state = PRUNNING;
785			p->status = 0;
786			running = true;
787		}
788		shf_puts(p->command, shl_stdout);
789		if (p->next)
790			shf_puts("| ", shl_stdout);
791	}
792	shf_putc('\n', shl_stdout);
793	shf_flush(shl_stdout);
794	if (running)
795		j->state = PRUNNING;
796
797	put_job(j, PJ_PAST_STOPPED);
798	if (bg)
799		j_set_async(j);
800	else {
801		/* attach tty to job */
802		if (j->state == PRUNNING) {
803			if (ttypgrp_ok && (j->flags & JF_SAVEDTTY))
804				tcsetattr(tty_fd, TCSADRAIN, &j->ttystat);
805			/* See comment in j_waitj regarding saved_ttypgrp. */
806			if (ttypgrp_ok &&
807			    tcsetpgrp(tty_fd, (j->flags & JF_SAVEDTTYPGRP) ?
808			    j->saved_ttypgrp : j->pgrp) < 0) {
809				rv = errno;
810				if (j->flags & JF_SAVEDTTY)
811					tcsetattr(tty_fd, TCSADRAIN, &tty_state);
812				sigprocmask(SIG_SETMASK, &omask, NULL);
813				bi_errorf("%s %s(%d, %ld) %s: %s",
814				    "1st", "tcsetpgrp", tty_fd,
815				    (long)((j->flags & JF_SAVEDTTYPGRP) ?
816				    j->saved_ttypgrp : j->pgrp), "failed",
817				    strerror(rv));
818				return (1);
819			}
820		}
821		j->flags |= JF_FG;
822		j->flags &= ~JF_KNOWN;
823		if (j == async_job)
824			async_job = NULL;
825	}
826
827	if (j->state == PRUNNING && mksh_killpg(j->pgrp, SIGCONT) < 0) {
828		int err = errno;
829
830		if (!bg) {
831			j->flags &= ~JF_FG;
832			if (ttypgrp_ok && (j->flags & JF_SAVEDTTY))
833				tcsetattr(tty_fd, TCSADRAIN, &tty_state);
834			if (ttypgrp_ok && tcsetpgrp(tty_fd, kshpgrp) < 0)
835				warningf(true, "%s %s(%d, %ld) %s: %s",
836				    "fg: 2nd", "tcsetpgrp", tty_fd,
837				    (long)kshpgrp, "failed", strerror(errno));
838		}
839		sigprocmask(SIG_SETMASK, &omask, NULL);
840		bi_errorf("%s %s %s", "can't continue job",
841		    cp, strerror(err));
842		return (1);
843	}
844	if (!bg) {
845		if (ttypgrp_ok) {
846			j->flags &= ~(JF_SAVEDTTY | JF_SAVEDTTYPGRP);
847		}
848		rv = j_waitj(j, JW_NONE, "jw:resume");
849	}
850	sigprocmask(SIG_SETMASK, &omask, NULL);
851	return (rv);
852}
853#endif
854
855/* are there any running or stopped jobs ? */
856int
857j_stopped_running(void)
858{
859	Job *j;
860	int which = 0;
861
862	for (j = job_list; j != NULL; j = j->next) {
863#ifndef MKSH_UNEMPLOYED
864		if (j->ppid == procpid && j->state == PSTOPPED)
865			which |= 1;
866#endif
867		if (Flag(FLOGIN) && !Flag(FNOHUP) && procpid == kshpid &&
868		    j->ppid == procpid && j->state == PRUNNING)
869			which |= 2;
870	}
871	if (which) {
872		shellf("You have %s%s%s jobs\n",
873		    which & 1 ? "stopped" : "",
874		    which == 3 ? " and " : "",
875		    which & 2 ? "running" : "");
876		return (1);
877	}
878
879	return (0);
880}
881
882
883/* list jobs for jobs built-in */
884int
885j_jobs(const char *cp, int slp,
886    /* 0: short, 1: long, 2: pgrp */
887    int nflag)
888{
889	Job *j, *tmp;
890	int how, zflag = 0;
891#ifndef MKSH_NOPROSPECTOFWORK
892	sigset_t omask;
893
894	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
895#endif
896
897	if (nflag < 0) {
898		/* kludge: print zombies */
899		nflag = 0;
900		zflag = 1;
901	}
902	if (cp) {
903		int	ecode;
904
905		if ((j = j_lookup(cp, &ecode)) == NULL) {
906#ifndef MKSH_NOPROSPECTOFWORK
907			sigprocmask(SIG_SETMASK, &omask, NULL);
908#endif
909			bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
910			return (1);
911		}
912	} else
913		j = job_list;
914	how = slp == 0 ? JP_MEDIUM : (slp == 1 ? JP_LONG : JP_PGRP);
915	for (; j; j = j->next) {
916		if ((!(j->flags & JF_ZOMBIE) || zflag) &&
917		    (!nflag || (j->flags & JF_CHANGED))) {
918			j_print(j, how, shl_stdout);
919			if (j->state == PEXITED || j->state == PSIGNALLED)
920				j->flags |= JF_REMOVE;
921		}
922		if (cp)
923			break;
924	}
925	/* Remove jobs after printing so there won't be multiple + or - jobs */
926	for (j = job_list; j; j = tmp) {
927		tmp = j->next;
928		if (j->flags & JF_REMOVE)
929			remove_job(j, "jobs");
930	}
931#ifndef MKSH_NOPROSPECTOFWORK
932	sigprocmask(SIG_SETMASK, &omask, NULL);
933#endif
934	return (0);
935}
936
937/* list jobs for top-level notification */
938void
939j_notify(void)
940{
941	Job *j, *tmp;
942#ifndef MKSH_NOPROSPECTOFWORK
943	sigset_t omask;
944
945	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
946#endif
947	for (j = job_list; j; j = j->next) {
948#ifndef MKSH_UNEMPLOYED
949		if (Flag(FMONITOR) && (j->flags & JF_CHANGED))
950			j_print(j, JP_MEDIUM, shl_out);
951#endif
952		/*
953		 * Remove job after doing reports so there aren't
954		 * multiple +/- jobs.
955		 */
956		if (j->state == PEXITED || j->state == PSIGNALLED)
957			j->flags |= JF_REMOVE;
958	}
959	for (j = job_list; j; j = tmp) {
960		tmp = j->next;
961		if (j->flags & JF_REMOVE)
962			remove_job(j, "notify");
963	}
964	shf_flush(shl_out);
965#ifndef MKSH_NOPROSPECTOFWORK
966	sigprocmask(SIG_SETMASK, &omask, NULL);
967#endif
968}
969
970/* Return pid of last process in last asynchronous job */
971pid_t
972j_async(void)
973{
974#ifndef MKSH_NOPROSPECTOFWORK
975	sigset_t omask;
976
977	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
978#endif
979
980	if (async_job)
981		async_job->flags |= JF_KNOWN;
982
983#ifndef MKSH_NOPROSPECTOFWORK
984	sigprocmask(SIG_SETMASK, &omask, NULL);
985#endif
986
987	return (async_pid);
988}
989
990/*
991 * Make j the last async process
992 *
993 * If jobs are compiled in then this routine expects sigchld to be blocked.
994 */
995static void
996j_set_async(Job *j)
997{
998	Job	*jl, *oldest;
999
1000	if (async_job && (async_job->flags & (JF_KNOWN|JF_ZOMBIE)) == JF_ZOMBIE)
1001		remove_job(async_job, "async");
1002	if (!(j->flags & JF_STARTED)) {
1003		internal_warningf("%s: %s", "j_async", "job not started");
1004		return;
1005	}
1006	async_job = j;
1007	async_pid = j->last_proc->pid;
1008	while (nzombie > CHILD_MAX) {
1009		oldest = NULL;
1010		for (jl = job_list; jl; jl = jl->next)
1011			if (jl != async_job && (jl->flags & JF_ZOMBIE) &&
1012			    (!oldest || jl->age < oldest->age))
1013				oldest = jl;
1014		if (!oldest) {
1015			/* XXX debugging */
1016			if (!(async_job->flags & JF_ZOMBIE) || nzombie != 1) {
1017				internal_warningf("%s: bad nzombie (%d)",
1018				    "j_async", nzombie);
1019				nzombie = 0;
1020			}
1021			break;
1022		}
1023		remove_job(oldest, "zombie");
1024	}
1025}
1026
1027/*
1028 * Start a job: set STARTED, check for held signals and set j->last_proc
1029 *
1030 * If jobs are compiled in then this routine expects sigchld to be blocked.
1031 */
1032static void
1033j_startjob(Job *j)
1034{
1035	Proc	*p;
1036
1037	j->flags |= JF_STARTED;
1038	for (p = j->proc_list; p->next; p = p->next)
1039		;
1040	j->last_proc = p;
1041
1042#ifndef MKSH_NOPROSPECTOFWORK
1043	if (held_sigchld) {
1044		held_sigchld = 0;
1045		/* Don't call j_sigchld() as it may remove job... */
1046		kill(procpid, SIGCHLD);
1047	}
1048#endif
1049}
1050
1051/*
1052 * wait for job to complete or change state
1053 *
1054 * If jobs are compiled in then this routine expects sigchld to be blocked.
1055 */
1056static int
1057j_waitj(Job *j,
1058    /* see JW_* */
1059    int flags,
1060    const char *where)
1061{
1062	int rv;
1063
1064	/*
1065	 * No auto-notify on the job we are waiting on.
1066	 */
1067	j->flags |= JF_WAITING;
1068	if (flags & JW_ASYNCNOTIFY)
1069		j->flags |= JF_W_ASYNCNOTIFY;
1070
1071#ifndef MKSH_UNEMPLOYED
1072	if (!Flag(FMONITOR))
1073#endif
1074		flags |= JW_STOPPEDWAIT;
1075
1076	while (j->state == PRUNNING ||
1077	    ((flags & JW_STOPPEDWAIT) && j->state == PSTOPPED)) {
1078#ifndef MKSH_NOPROSPECTOFWORK
1079		sigsuspend(&sm_default);
1080#else
1081		j_sigchld(SIGCHLD);
1082#endif
1083		if (fatal_trap) {
1084			int oldf = j->flags & (JF_WAITING|JF_W_ASYNCNOTIFY);
1085			j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY);
1086			runtraps(TF_FATAL);
1087			/* not reached... */
1088			j->flags |= oldf;
1089		}
1090		if ((flags & JW_INTERRUPT) && (rv = trap_pending())) {
1091			j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY);
1092			return (-rv);
1093		}
1094	}
1095	j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY);
1096
1097	if (j->flags & JF_FG) {
1098		j->flags &= ~JF_FG;
1099#ifndef MKSH_UNEMPLOYED
1100		if (Flag(FMONITOR) && ttypgrp_ok && j->pgrp) {
1101			/*
1102			 * Save the tty's current pgrp so it can be restored
1103			 * when the job is foregrounded. This is to
1104			 * deal with things like the GNU su which does
1105			 * a fork/exec instead of an exec (the fork means
1106			 * the execed shell gets a different pid from its
1107			 * pgrp, so naturally it sets its pgrp and gets hosed
1108			 * when it gets foregrounded by the parent shell which
1109			 * has restored the tty's pgrp to that of the su
1110			 * process).
1111			 */
1112			if (j->state == PSTOPPED &&
1113			    (j->saved_ttypgrp = tcgetpgrp(tty_fd)) >= 0)
1114				j->flags |= JF_SAVEDTTYPGRP;
1115			if (tcsetpgrp(tty_fd, kshpgrp) < 0)
1116				warningf(true, "%s %s(%d, %ld) %s: %s",
1117				    "j_waitj:", "tcsetpgrp", tty_fd,
1118				    (long)kshpgrp, "failed", strerror(errno));
1119			if (j->state == PSTOPPED) {
1120				j->flags |= JF_SAVEDTTY;
1121				tcgetattr(tty_fd, &j->ttystat);
1122			}
1123		}
1124#endif
1125		if (tty_fd >= 0) {
1126			/*
1127			 * Only restore tty settings if job was originally
1128			 * started in the foreground. Problems can be
1129			 * caused by things like 'more foobar &' which will
1130			 * typically get and save the shell's vi/emacs tty
1131			 * settings before setting up the tty for itself;
1132			 * when more exits, it restores the 'original'
1133			 * settings, and things go down hill from there...
1134			 */
1135			if (j->state == PEXITED && j->status == 0 &&
1136			    (j->flags & JF_USETTYMODE)) {
1137				tcgetattr(tty_fd, &tty_state);
1138			} else {
1139				tcsetattr(tty_fd, TCSADRAIN, &tty_state);
1140				/*-
1141				 * Don't use tty mode if job is stopped and
1142				 * later restarted and exits. Consider
1143				 * the sequence:
1144				 *	vi foo (stopped)
1145				 *	...
1146				 *	stty something
1147				 *	...
1148				 *	fg (vi; ZZ)
1149				 * mode should be that of the stty, not what
1150				 * was before the vi started.
1151				 */
1152				if (j->state == PSTOPPED)
1153					j->flags &= ~JF_USETTYMODE;
1154			}
1155		}
1156#ifndef MKSH_UNEMPLOYED
1157		/*
1158		 * If it looks like user hit ^C to kill a job, pretend we got
1159		 * one too to break out of for loops, etc. (AT&T ksh does this
1160		 * even when not monitoring, but this doesn't make sense since
1161		 * a tty generated ^C goes to the whole process group)
1162		 */
1163		{
1164			int status;
1165
1166			status = j->last_proc->status;
1167			if (Flag(FMONITOR) && j->state == PSIGNALLED &&
1168			    WIFSIGNALED(status) &&
1169			    (sigtraps[WTERMSIG(status)].flags & TF_TTY_INTR))
1170				trapsig(WTERMSIG(status));
1171		}
1172#endif
1173	}
1174
1175	j_usrtime = j->usrtime;
1176	j_systime = j->systime;
1177	rv = j->status;
1178
1179	if ((flags & JW_PIPEST) && (j->proc_list != NULL)) {
1180		uint32_t num = 0;
1181		Proc *p = j->proc_list;
1182		struct tbl *vp;
1183
1184		unset(vp_pipest, 1);
1185		vp = vp_pipest;
1186		vp->flag = DEFINED | ISSET | INTEGER | RDONLY | ARRAY | INT_U;
1187		goto got_array;
1188
1189		while (p != NULL) {
1190			{
1191				struct tbl *vq;
1192
1193				/* strlen(vp_pipest->name) == 10 */
1194				vq = alloc(offsetof(struct tbl, name[0]) + 11,
1195				    vp_pipest->areap);
1196				memset(vq, 0, offsetof(struct tbl, name[0]));
1197				memcpy(vq->name, vp_pipest->name, 11);
1198				vp->u.array = vq;
1199				vp = vq;
1200			}
1201			vp->areap = vp_pipest->areap;
1202			vp->ua.index = ++num;
1203			vp->flag = DEFINED | ISSET | INTEGER | RDONLY |
1204			    ARRAY | INT_U | AINDEX;
1205 got_array:
1206			vp->val.i = proc_errorlevel(p);
1207			p = p->next;
1208		}
1209	}
1210
1211	if (!(flags & JW_ASYNCNOTIFY)
1212#ifndef MKSH_UNEMPLOYED
1213	    && (!Flag(FMONITOR) || j->state != PSTOPPED)
1214#endif
1215	    ) {
1216		j_print(j, JP_SHORT, shl_out);
1217		shf_flush(shl_out);
1218	}
1219	if (j->state != PSTOPPED
1220#ifndef MKSH_UNEMPLOYED
1221	    && (!Flag(FMONITOR) || !(flags & JW_ASYNCNOTIFY))
1222#endif
1223	    )
1224		remove_job(j, where);
1225
1226	return (rv);
1227}
1228
1229/*
1230 * SIGCHLD handler to reap children and update job states
1231 *
1232 * If jobs are compiled in then this routine expects sigchld to be blocked.
1233 */
1234/* ARGSUSED */
1235static void
1236j_sigchld(int sig MKSH_A_UNUSED)
1237{
1238	/* this runs inside interrupt context, with errno saved */
1239
1240	Job *j;
1241	Proc *p = NULL;
1242	pid_t pid;
1243	int status;
1244	struct rusage ru0, ru1;
1245
1246#ifndef MKSH_NOPROSPECTOFWORK
1247	/*
1248	 * Don't wait for any processes if a job is partially started.
1249	 * This is so we don't do away with the process group leader
1250	 * before all the processes in a pipe line are started (so the
1251	 * setpgid() won't fail)
1252	 */
1253	for (j = job_list; j; j = j->next)
1254		if (j->ppid == procpid && !(j->flags & JF_STARTED)) {
1255			held_sigchld = 1;
1256			return;
1257		}
1258#endif
1259
1260	getrusage(RUSAGE_CHILDREN, &ru0);
1261	do {
1262#ifndef MKSH_NOPROSPECTOFWORK
1263		pid = waitpid(-1, &status, (WNOHANG|WUNTRACED));
1264#else
1265		pid = wait(&status);
1266#endif
1267
1268		/*
1269		 * return if this would block (0) or no children
1270		 * or interrupted (-1)
1271		 */
1272		if (pid <= 0)
1273			return;
1274
1275		getrusage(RUSAGE_CHILDREN, &ru1);
1276
1277		/* find job and process structures for this pid */
1278		for (j = job_list; j != NULL; j = j->next)
1279			for (p = j->proc_list; p != NULL; p = p->next)
1280				if (p->pid == pid)
1281					goto found;
1282 found:
1283		if (j == NULL) {
1284			/* Can occur if process has kids, then execs shell
1285			warningf(true, "bad process waited for (pid = %d)",
1286				pid);
1287			 */
1288			ru0 = ru1;
1289			continue;
1290		}
1291
1292		timeradd(&j->usrtime, &ru1.ru_utime, &j->usrtime);
1293		timersub(&j->usrtime, &ru0.ru_utime, &j->usrtime);
1294		timeradd(&j->systime, &ru1.ru_stime, &j->systime);
1295		timersub(&j->systime, &ru0.ru_stime, &j->systime);
1296		ru0 = ru1;
1297		p->status = status;
1298#ifndef MKSH_UNEMPLOYED
1299		if (WIFSTOPPED(status))
1300			p->state = PSTOPPED;
1301		else
1302#endif
1303		  if (WIFSIGNALED(status))
1304			p->state = PSIGNALLED;
1305		else
1306			p->state = PEXITED;
1307
1308		/* check to see if entire job is done */
1309		check_job(j);
1310	}
1311#ifndef MKSH_NOPROSPECTOFWORK
1312	    while (/* CONSTCOND */ 1);
1313#else
1314	    while (/* CONSTCOND */ 0);
1315#endif
1316}
1317
1318/*
1319 * Called only when a process in j has exited/stopped (ie, called only
1320 * from j_sigchld()). If no processes are running, the job status
1321 * and state are updated, asynchronous job notification is done and,
1322 * if unneeded, the job is removed.
1323 *
1324 * If jobs are compiled in then this routine expects sigchld to be blocked.
1325 */
1326static void
1327check_job(Job *j)
1328{
1329	int	jstate;
1330	Proc	*p;
1331
1332	/* XXX debugging (nasty - interrupt routine using shl_out) */
1333	if (!(j->flags & JF_STARTED)) {
1334		internal_warningf("check_job: job started (flags 0x%x)",
1335		    j->flags);
1336		return;
1337	}
1338
1339	jstate = PRUNNING;
1340	for (p=j->proc_list; p != NULL; p = p->next) {
1341		if (p->state == PRUNNING)
1342			/* some processes still running */
1343			return;
1344		if (p->state > jstate)
1345			jstate = p->state;
1346	}
1347	j->state = jstate;
1348	j->status = proc_errorlevel(j->last_proc);
1349
1350	/*
1351	 * Note when co-process dies: can't be done in j_wait() nor
1352	 * remove_job() since neither may be called for non-interactive
1353	 * shells.
1354	 */
1355	if (j->state == PEXITED || j->state == PSIGNALLED) {
1356		/*
1357		 * No need to keep co-process input any more
1358		 * (at least, this is what ksh93d thinks)
1359		 */
1360		if (coproc.job == j) {
1361			coproc.job = NULL;
1362			/*
1363			 * XXX would be nice to get the closes out of here
1364			 * so they aren't done in the signal handler.
1365			 * Would mean a check in coproc_getfd() to
1366			 * do "if job == 0 && write >= 0, close write".
1367			 */
1368			coproc_write_close(coproc.write);
1369		}
1370		/* Do we need to keep the output? */
1371		if (j->coproc_id && j->coproc_id == coproc.id &&
1372		    --coproc.njobs == 0)
1373			coproc_readw_close(coproc.read);
1374	}
1375
1376	j->flags |= JF_CHANGED;
1377#ifndef MKSH_UNEMPLOYED
1378	if (Flag(FMONITOR) && !(j->flags & JF_XXCOM)) {
1379		/*
1380		 * Only put stopped jobs at the front to avoid confusing
1381		 * the user (don't want finished jobs effecting %+ or %-)
1382		 */
1383		if (j->state == PSTOPPED)
1384			put_job(j, PJ_ON_FRONT);
1385		if (Flag(FNOTIFY) &&
1386		    (j->flags & (JF_WAITING|JF_W_ASYNCNOTIFY)) != JF_WAITING) {
1387			/* Look for the real file descriptor 2 */
1388			{
1389				struct env *ep;
1390				int fd = 2;
1391
1392				for (ep = e; ep; ep = ep->oenv)
1393					if (ep->savefd && ep->savefd[2])
1394						fd = ep->savefd[2];
1395				shf_reopen(fd, SHF_WR, shl_j);
1396			}
1397			/*
1398			 * Can't call j_notify() as it removes jobs. The job
1399			 * must stay in the job list as j_waitj() may be
1400			 * running with this job.
1401			 */
1402			j_print(j, JP_MEDIUM, shl_j);
1403			shf_flush(shl_j);
1404			if (!(j->flags & JF_WAITING) && j->state != PSTOPPED)
1405				remove_job(j, "notify");
1406		}
1407	}
1408#endif
1409	if (
1410#ifndef MKSH_UNEMPLOYED
1411	    !Flag(FMONITOR) &&
1412#endif
1413	    !(j->flags & (JF_WAITING|JF_FG)) &&
1414	    j->state != PSTOPPED) {
1415		if (j == async_job || (j->flags & JF_KNOWN)) {
1416			j->flags |= JF_ZOMBIE;
1417			j->job = -1;
1418			nzombie++;
1419		} else
1420			remove_job(j, "checkjob");
1421	}
1422}
1423
1424/*
1425 * Print job status in either short, medium or long format.
1426 *
1427 * If jobs are compiled in then this routine expects sigchld to be blocked.
1428 */
1429static void
1430j_print(Job *j, int how, struct shf *shf)
1431{
1432	Proc	*p;
1433	int	state;
1434	int	status;
1435	int	coredumped;
1436	char	jobchar = ' ';
1437	char	buf[64];
1438	const char *filler;
1439	int	output = 0;
1440
1441	if (how == JP_PGRP) {
1442		/*
1443		 * POSIX doesn't say what to do it there is no process
1444		 * group leader (ie, !FMONITOR). We arbitrarily return
1445		 * last pid (which is what $! returns).
1446		 */
1447		shf_fprintf(shf, "%d\n", (int)(j->pgrp ? j->pgrp :
1448		    (j->last_proc ? j->last_proc->pid : 0)));
1449		return;
1450	}
1451	j->flags &= ~JF_CHANGED;
1452	filler = j->job > 10 ? "\n       " : "\n      ";
1453	if (j == job_list)
1454		jobchar = '+';
1455	else if (j == job_list->next)
1456		jobchar = '-';
1457
1458	for (p = j->proc_list; p != NULL;) {
1459		coredumped = 0;
1460		switch (p->state) {
1461		case PRUNNING:
1462			memcpy(buf, "Running", 8);
1463			break;
1464		case PSTOPPED:
1465			strlcpy(buf, sigtraps[WSTOPSIG(p->status)].mess,
1466			    sizeof(buf));
1467			break;
1468		case PEXITED:
1469			if (how == JP_SHORT)
1470				buf[0] = '\0';
1471			else if (WEXITSTATUS(p->status) == 0)
1472				memcpy(buf, "Done", 5);
1473			else
1474				shf_snprintf(buf, sizeof(buf), "Done (%d)",
1475				    WEXITSTATUS(p->status));
1476			break;
1477		case PSIGNALLED:
1478#ifdef WCOREDUMP
1479			if (WCOREDUMP(p->status))
1480				coredumped = 1;
1481#endif
1482			/*
1483			 * kludge for not reporting 'normal termination
1484			 * signals' (i.e. SIGINT, SIGPIPE)
1485			 */
1486			if (how == JP_SHORT && !coredumped &&
1487			    (WTERMSIG(p->status) == SIGINT ||
1488			    WTERMSIG(p->status) == SIGPIPE)) {
1489				buf[0] = '\0';
1490			} else
1491				strlcpy(buf, sigtraps[WTERMSIG(p->status)].mess,
1492				    sizeof(buf));
1493			break;
1494		}
1495
1496		if (how != JP_SHORT) {
1497			if (p == j->proc_list)
1498				shf_fprintf(shf, "[%d] %c ", j->job, jobchar);
1499			else
1500				shf_puts(filler, shf);
1501		}
1502
1503		if (how == JP_LONG)
1504			shf_fprintf(shf, "%5d ", (int)p->pid);
1505
1506		if (how == JP_SHORT) {
1507			if (buf[0]) {
1508				output = 1;
1509				shf_fprintf(shf, "%s%s ",
1510				    buf, coredumped ? " (core dumped)" : null);
1511			}
1512		} else {
1513			output = 1;
1514			shf_fprintf(shf, "%-20s %s%s%s", buf, p->command,
1515			    p->next ? "|" : null,
1516			    coredumped ? " (core dumped)" : null);
1517		}
1518
1519		state = p->state;
1520		status = p->status;
1521		p = p->next;
1522		while (p && p->state == state && p->status == status) {
1523			if (how == JP_LONG)
1524				shf_fprintf(shf, "%s%5d %-20s %s%s", filler,
1525				    (int)p->pid, " ", p->command,
1526				    p->next ? "|" : null);
1527			else if (how == JP_MEDIUM)
1528				shf_fprintf(shf, " %s%s", p->command,
1529				    p->next ? "|" : null);
1530			p = p->next;
1531		}
1532	}
1533	if (output)
1534		shf_putc('\n', shf);
1535}
1536
1537/*
1538 * Convert % sequence to job
1539 *
1540 * If jobs are compiled in then this routine expects sigchld to be blocked.
1541 */
1542static Job *
1543j_lookup(const char *cp, int *ecodep)
1544{
1545	Job *j, *last_match;
1546	Proc *p;
1547	size_t len;
1548	int job = 0;
1549
1550	if (ksh_isdigit(*cp)) {
1551		getn(cp, &job);
1552		/* Look for last_proc->pid (what $! returns) first... */
1553		for (j = job_list; j != NULL; j = j->next)
1554			if (j->last_proc && j->last_proc->pid == job)
1555				return (j);
1556		/*
1557		 * ...then look for process group (this is non-POSIX,
1558		 * but should not break anything
1559		 */
1560		for (j = job_list; j != NULL; j = j->next)
1561			if (j->pgrp && j->pgrp == job)
1562				return (j);
1563		if (ecodep)
1564			*ecodep = JL_NOSUCH;
1565		return (NULL);
1566	}
1567	if (*cp != '%') {
1568		if (ecodep)
1569			*ecodep = JL_INVALID;
1570		return (NULL);
1571	}
1572	switch (*++cp) {
1573	case '\0': /* non-standard */
1574	case '+':
1575	case '%':
1576		if (job_list != NULL)
1577			return (job_list);
1578		break;
1579
1580	case '-':
1581		if (job_list != NULL && job_list->next)
1582			return (job_list->next);
1583		break;
1584
1585	case '0': case '1': case '2': case '3': case '4':
1586	case '5': case '6': case '7': case '8': case '9':
1587		getn(cp, &job);
1588		for (j = job_list; j != NULL; j = j->next)
1589			if (j->job == job)
1590				return (j);
1591		break;
1592
1593	/* %?string */
1594	case '?':
1595		last_match = NULL;
1596		for (j = job_list; j != NULL; j = j->next)
1597			for (p = j->proc_list; p != NULL; p = p->next)
1598				if (strstr(p->command, cp+1) != NULL) {
1599					if (last_match) {
1600						if (ecodep)
1601							*ecodep = JL_AMBIG;
1602						return (NULL);
1603					}
1604					last_match = j;
1605				}
1606		if (last_match)
1607			return (last_match);
1608		break;
1609
1610	/* %string */
1611	default:
1612		len = strlen(cp);
1613		last_match = NULL;
1614		for (j = job_list; j != NULL; j = j->next)
1615			if (strncmp(cp, j->proc_list->command, len) == 0) {
1616				if (last_match) {
1617					if (ecodep)
1618						*ecodep = JL_AMBIG;
1619					return (NULL);
1620				}
1621				last_match = j;
1622			}
1623		if (last_match)
1624			return (last_match);
1625		break;
1626	}
1627	if (ecodep)
1628		*ecodep = JL_NOSUCH;
1629	return (NULL);
1630}
1631
1632static Job	*free_jobs;
1633static Proc	*free_procs;
1634
1635/*
1636 * allocate a new job and fill in the job number.
1637 *
1638 * If jobs are compiled in then this routine expects sigchld to be blocked.
1639 */
1640static Job *
1641new_job(void)
1642{
1643	int	i;
1644	Job	*newj, *j;
1645
1646	if (free_jobs != NULL) {
1647		newj = free_jobs;
1648		free_jobs = free_jobs->next;
1649	} else
1650		newj = alloc(sizeof(Job), APERM);
1651
1652	/* brute force method */
1653	for (i = 1; ; i++) {
1654		for (j = job_list; j && j->job != i; j = j->next)
1655			;
1656		if (j == NULL)
1657			break;
1658	}
1659	newj->job = i;
1660
1661	return (newj);
1662}
1663
1664/*
1665 * Allocate new process struct
1666 *
1667 * If jobs are compiled in then this routine expects sigchld to be blocked.
1668 */
1669static Proc *
1670new_proc(void)
1671{
1672	Proc	*p;
1673
1674	if (free_procs != NULL) {
1675		p = free_procs;
1676		free_procs = free_procs->next;
1677	} else
1678		p = alloc(sizeof(Proc), APERM);
1679
1680	return (p);
1681}
1682
1683/*
1684 * Take job out of job_list and put old structures into free list.
1685 * Keeps nzombies, last_job and async_job up to date.
1686 *
1687 * If jobs are compiled in then this routine expects sigchld to be blocked.
1688 */
1689static void
1690remove_job(Job *j, const char *where)
1691{
1692	Proc	*p, *tmp;
1693	Job	**prev, *curr;
1694
1695	prev = &job_list;
1696	curr = *prev;
1697	for (; curr != NULL && curr != j; prev = &curr->next, curr = *prev)
1698		;
1699	if (curr != j) {
1700		internal_warningf("remove_job: job %s (%s)", "not found", where);
1701		return;
1702	}
1703	*prev = curr->next;
1704
1705	/* free up proc structures */
1706	for (p = j->proc_list; p != NULL; ) {
1707		tmp = p;
1708		p = p->next;
1709		tmp->next = free_procs;
1710		free_procs = tmp;
1711	}
1712
1713	if ((j->flags & JF_ZOMBIE) && j->ppid == procpid)
1714		--nzombie;
1715	j->next = free_jobs;
1716	free_jobs = j;
1717
1718	if (j == last_job)
1719		last_job = NULL;
1720	if (j == async_job)
1721		async_job = NULL;
1722}
1723
1724/*
1725 * put j in a particular location (taking it out job_list if it is there
1726 * already)
1727 *
1728 * If jobs are compiled in then this routine expects sigchld to be blocked.
1729 */
1730static void
1731put_job(Job *j, int where)
1732{
1733	Job	**prev, *curr;
1734
1735	/* Remove job from list (if there) */
1736	prev = &job_list;
1737	curr = job_list;
1738	for (; curr && curr != j; prev = &curr->next, curr = *prev)
1739		;
1740	if (curr == j)
1741		*prev = curr->next;
1742
1743	switch (where) {
1744	case PJ_ON_FRONT:
1745		j->next = job_list;
1746		job_list = j;
1747		break;
1748
1749	case PJ_PAST_STOPPED:
1750		prev = &job_list;
1751		curr = job_list;
1752		for (; curr && curr->state == PSTOPPED; prev = &curr->next,
1753		    curr = *prev)
1754			;
1755		j->next = curr;
1756		*prev = j;
1757		break;
1758	}
1759}
1760
1761/*
1762 * nuke a job (called when unable to start full job).
1763 *
1764 * If jobs are compiled in then this routine expects sigchld to be blocked.
1765 */
1766static int
1767kill_job(Job *j, int sig)
1768{
1769	Proc	*p;
1770	int	rval = 0;
1771
1772	for (p = j->proc_list; p != NULL; p = p->next)
1773		if (p->pid != 0)
1774			if (kill(p->pid, sig) < 0)
1775				rval = -1;
1776	return (rval);
1777}
1778