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