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