GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/ksh/jobs.c Lines: 366 706 51.8 %
Date: 2016-12-06 Branches: 271 668 40.6 %

Line Branch Exec Source
1
/*	$OpenBSD: jobs.c,v 1.55 2016/03/17 23:33:23 mmcc Exp $	*/
2
3
/*
4
 * Process and job control
5
 */
6
7
/*
8
 * Reworked/Rewritten version of Eric Gisin's/Ron Natalie's code by
9
 * Larry Bouzane (larry@cs.mun.ca) and hacked again by
10
 * Michael Rendell (michael@cs.mun.ca)
11
 *
12
 * The interface to the rest of the shell should probably be changed
13
 * to allow use of vfork() when available but that would be way too much
14
 * work :)
15
 *
16
 */
17
18
#include <sys/resource.h>
19
#include <sys/stat.h>
20
#include <sys/time.h>
21
#include <sys/wait.h>
22
23
#include <ctype.h>
24
#include <errno.h>
25
#include <fcntl.h>
26
#include <limits.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <unistd.h>
30
31
#include "sh.h"
32
#include "tty.h"
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
	int	state;
44
	int	status;		/* wait status */
45
	pid_t	pid;		/* process id */
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
	int	job;		/* job number: %n */
78
	int	flags;		/* see JF_* */
79
	int	state;		/* job state */
80
	int	status;		/* exit status of last process */
81
	pid_t	pgrp;		/* process group of job */
82
	pid_t	ppid;		/* pid of process that forked job */
83
	int	age;		/* number of jobs started */
84
	struct timeval systime;	/* system time used by job */
85
	struct timeval usrtime;	/* user time used by job */
86
	Proc	*proc_list;	/* process list */
87
	Proc	*last_proc;	/* last process in list */
88
	Coproc_id coproc_id;	/* 0 or id of coprocess output pipe */
89
#ifdef JOBS
90
	struct termios ttystate;/* saved tty state for stopped jobs */
91
	pid_t	saved_ttypgrp;	/* saved tty process group for stopped jobs */
92
#endif /* JOBS */
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
struct timeval	j_systime, j_usrtime;	/* user and system time of last j_waitjed job */
116
117
static Job		*job_list;	/* job list */
118
static Job		*last_job;
119
static Job		*async_job;
120
static pid_t		async_pid;
121
122
static int		nzombie;	/* # of zombies owned by this process */
123
int			njobs;		/* # of jobs started */
124
static int		child_max;	/* CHILD_MAX */
125
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
#ifdef JOBS
131
static struct shf	*shl_j;
132
static int		ttypgrp_ok;	/* set if can use tty pgrps */
133
static pid_t		restore_ttypgrp = -1;
134
static pid_t		our_pgrp;
135
static int const	tt_sigs[] = { SIGTSTP, SIGTTIN, SIGTTOU };
136
#endif /* JOBS */
137
138
static void		j_set_async(Job *);
139
static void		j_startjob(Job *);
140
static int		j_waitj(Job *, int, const char *);
141
static void		j_sigchld(int);
142
static void		j_print(Job *, int, struct shf *);
143
static Job		*j_lookup(const char *, int *);
144
static Job		*new_job(void);
145
static Proc		*new_proc(void);
146
static void		check_job(Job *);
147
static void		put_job(Job *, int);
148
static void		remove_job(Job *, const char *);
149
static int		kill_job(Job *, int);
150
151
/* initialize job control */
152
void
153
j_init(int mflagset)
154
3525
{
155
3525
	child_max = CHILD_MAX; /* so syscon() isn't always being called */
156
157
3525
	sigemptyset(&sm_default);
158
3525
	sigprocmask(SIG_SETMASK, &sm_default, NULL);
159
160
3525
	sigemptyset(&sm_sigchld);
161
3525
	sigaddset(&sm_sigchld, SIGCHLD);
162
163
3525
	setsig(&sigtraps[SIGCHLD], j_sigchld,
164
	    SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP);
165
166
#ifdef JOBS
167

3525
	if (!mflagset && Flag(FTALKING))
168
63
		Flag(FMONITOR) = 1;
169
170
	/* shl_j is used to do asynchronous notification (used in
171
	 * an interrupt handler, so need a distinct shf)
172
	 */
173
3525
	shl_j = shf_fdopen(2, SHF_WR, NULL);
174
175

3525
	if (Flag(FMONITOR) || Flag(FTALKING)) {
176
		int i;
177
178
		/* the TF_SHELL_USES test is a kludge that lets us know if
179
		 * if the signals have been changed by the shell.
180
		 */
181
315
		for (i = NELEM(tt_sigs); --i >= 0; ) {
182
189
			sigtraps[tt_sigs[i]].flags |= TF_SHELL_USES;
183
			/* j_change() sets this to SS_RESTORE_DFL if FMONITOR */
184
189
			setsig(&sigtraps[tt_sigs[i]], SIG_IGN,
185
			    SS_RESTORE_IGN|SS_FORCE);
186
		}
187
	}
188
189
	/* j_change() calls tty_init() */
190
3525
	if (Flag(FMONITOR))
191
63
		j_change();
192
	else
193
#endif /* JOBS */
194
3462
		if (Flag(FTALKING))
195
			tty_init(true);
196
3525
}
197
198
/* suspend the shell */
199
void
200
j_suspend(void)
201
{
202
	struct sigaction sa, osa;
203
204
	/* Restore tty and pgrp. */
205
	if (ttypgrp_ok) {
206
		tcsetattr(tty_fd, TCSADRAIN, &tty_state);
207
		if (restore_ttypgrp >= 0) {
208
			if (tcsetpgrp(tty_fd, restore_ttypgrp) < 0) {
209
				warningf(false,
210
				    "j_suspend: tcsetpgrp() failed: %s",
211
				    strerror(errno));
212
			} else {
213
				if (setpgid(0, restore_ttypgrp) < 0) {
214
					warningf(false,
215
					    "j_suspend: setpgid() failed: %s",
216
					    strerror(errno));
217
				}
218
			}
219
		}
220
	}
221
222
	/* Suspend the shell. */
223
	memset(&sa, 0, sizeof(sa));
224
	sigemptyset(&sa.sa_mask);
225
	sa.sa_handler = SIG_DFL;
226
	sigaction(SIGTSTP, &sa, &osa);
227
	kill(0, SIGTSTP);
228
229
	/* Back from suspend, reset signals, pgrp and tty. */
230
	sigaction(SIGTSTP, &osa, NULL);
231
	if (ttypgrp_ok) {
232
		if (restore_ttypgrp >= 0) {
233
			if (setpgid(0, kshpid) < 0) {
234
				warningf(false,
235
				    "j_suspend: setpgid() failed: %s",
236
				    strerror(errno));
237
				ttypgrp_ok = 0;
238
			} else {
239
				if (tcsetpgrp(tty_fd, kshpid) < 0) {
240
					warningf(false,
241
					    "j_suspend: tcsetpgrp() failed: %s",
242
					    strerror(errno));
243
					ttypgrp_ok = 0;
244
				}
245
			}
246
		}
247
		tty_init(true);
248
	}
249
}
250
251
/* job cleanup before shell exit */
252
void
253
j_exit(void)
254
7171
{
255
	/* kill stopped, and possibly running, jobs */
256
	Job	*j;
257
7171
	int	killed = 0;
258
259
13405
	for (j = job_list; j != NULL; j = j->next) {
260



6234
		if (j->ppid == procpid &&
261
		    (j->state == PSTOPPED ||
262
		    (j->state == PRUNNING &&
263
		    ((j->flags & JF_FG) ||
264
		    (Flag(FLOGIN) && !Flag(FNOHUP) && procpid == kshpid))))) {
265
			killed = 1;
266
			if (j->pgrp == 0)
267
				kill_job(j, SIGHUP);
268
			else
269
				killpg(j->pgrp, SIGHUP);
270
#ifdef JOBS
271
			if (j->state == PSTOPPED) {
272
				if (j->pgrp == 0)
273
					kill_job(j, SIGCONT);
274
				else
275
					killpg(j->pgrp, SIGCONT);
276
			}
277
#endif /* JOBS */
278
		}
279
	}
280
7171
	if (killed)
281
		sleep(1);
282
7171
	j_notify();
283
284
#ifdef JOBS
285

7171
	if (kshpid == procpid && restore_ttypgrp >= 0) {
286
		/* Need to restore the tty pgrp to what it was when the
287
		 * shell started up, so that the process that started us
288
		 * will be able to access the tty when we are done.
289
		 * Also need to restore our process group in case we are
290
		 * about to do an exec so that both our parent and the
291
		 * process we are to become will be able to access the tty.
292
		 */
293
56
		tcsetpgrp(tty_fd, restore_ttypgrp);
294
56
		setpgid(0, restore_ttypgrp);
295
	}
296
7171
	if (Flag(FMONITOR)) {
297
62
		Flag(FMONITOR) = 0;
298
62
		j_change();
299
	}
300
#endif /* JOBS */
301
7171
}
302
303
#ifdef JOBS
304
/* turn job control on or off according to Flag(FMONITOR) */
305
void
306
j_change(void)
307
125
{
308
	int i;
309
310
125
	if (Flag(FMONITOR)) {
311
		int use_tty;
312
313
63
		if (Flag(FTALKING)) {
314
			/* Don't call tcgetattr() 'til we own the tty process group */
315
63
			use_tty = 1;
316
63
			tty_init(false);
317
		} else
318
			use_tty = 0;
319
320
		/* no controlling tty, no SIGT* */
321

63
		ttypgrp_ok = use_tty && tty_fd >= 0 && tty_devtty;
322
323

63
		if (ttypgrp_ok && (our_pgrp = getpgrp()) < 0) {
324
			warningf(false, "j_init: getpgrp() failed: %s",
325
			    strerror(errno));
326
			ttypgrp_ok = 0;
327
		}
328
63
		if (ttypgrp_ok) {
329
63
			setsig(&sigtraps[SIGTTIN], SIG_DFL,
330
			    SS_RESTORE_ORIG|SS_FORCE);
331
			/* wait to be given tty (POSIX.1, B.2, job control) */
332
			while (1) {
333
				pid_t ttypgrp;
334
335
63
				if ((ttypgrp = tcgetpgrp(tty_fd)) < 0) {
336
					warningf(false,
337
					    "j_init: tcgetpgrp() failed: %s",
338
					    strerror(errno));
339
					ttypgrp_ok = 0;
340
					break;
341
				}
342
63
				if (ttypgrp == our_pgrp)
343
63
					break;
344
				kill(0, SIGTTIN);
345
			}
346
		}
347
315
		for (i = NELEM(tt_sigs); --i >= 0; )
348
189
			setsig(&sigtraps[tt_sigs[i]], SIG_IGN,
349
			    SS_RESTORE_DFL|SS_FORCE);
350

63
		if (ttypgrp_ok && our_pgrp != kshpid) {
351
56
			if (setpgid(0, kshpid) < 0) {
352
				warningf(false,
353
				    "j_init: setpgid() failed: %s",
354
				    strerror(errno));
355
				ttypgrp_ok = 0;
356
			} else {
357
56
				if (tcsetpgrp(tty_fd, kshpid) < 0) {
358
					warningf(false,
359
					    "j_init: tcsetpgrp() failed: %s",
360
					    strerror(errno));
361
					ttypgrp_ok = 0;
362
				} else
363
56
					restore_ttypgrp = our_pgrp;
364
56
				our_pgrp = kshpid;
365
			}
366
		}
367
63
		if (use_tty) {
368
63
			if (!ttypgrp_ok)
369
				warningf(false, "warning: won't have full job control");
370
		}
371
63
		if (tty_fd >= 0)
372
63
			tcgetattr(tty_fd, &tty_state);
373
	} else {
374
62
		ttypgrp_ok = 0;
375
62
		if (Flag(FTALKING))
376
310
			for (i = NELEM(tt_sigs); --i >= 0; )
377
186
				setsig(&sigtraps[tt_sigs[i]], SIG_IGN,
378
				    SS_RESTORE_IGN|SS_FORCE);
379
		else
380
			for (i = NELEM(tt_sigs); --i >= 0; ) {
381
				if (sigtraps[tt_sigs[i]].flags &
382
				    (TF_ORIG_IGN | TF_ORIG_DFL))
383
					setsig(&sigtraps[tt_sigs[i]],
384
					    (sigtraps[tt_sigs[i]].flags & TF_ORIG_IGN) ?
385
					    SIG_IGN : SIG_DFL,
386
					    SS_RESTORE_ORIG|SS_FORCE);
387
			}
388
62
		if (!Flag(FTALKING))
389
			tty_close();
390
	}
391
125
}
392
#endif /* JOBS */
393
394
/* execute tree in child subprocess */
395
int
396
exchild(struct op *t, int flags, volatile int *xerrok,
397
    int close_fd)	/* used if XPCLOSE or XCCLOSE */
398
17829
{
399
	static Proc	*last_proc;	/* for pipelines */
400
401
	int		i;
402
	sigset_t	omask;
403
	Proc		*p;
404
	Job		*j;
405
17829
	int		rv = 0;
406
	int		forksleep;
407
	int		ischild;
408
409
17829
	if (flags & XEXEC)
410
		/* Clear XFORK|XPCLOSE|XCCLOSE|XCOPROC|XPIPEO|XPIPEI|XXCOM|XBGND
411
		 * (also done in another execute() below)
412
		 */
413
3656
		return execute(t, flags & (XEXEC | XERROK), xerrok);
414
415
	/* no SIGCHLD's while messing with job and process lists */
416
14173
	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
417
418
14173
	p = new_proc();
419
14173
	p->next = NULL;
420
14173
	p->state = PRUNNING;
421
14173
	p->status = 0;
422
14173
	p->pid = 0;
423
424
	/* link process into jobs list */
425
14173
	if (flags&XPIPEI) {	/* continuing with a pipe */
426
2343
		if (!last_job)
427
			internal_errorf(1,
428
			    "exchild: XPIPEI and no last_job - pid %d",
429
			    (int) procpid);
430
2343
		j = last_job;
431
2343
		last_proc->next = p;
432
2343
		last_proc = p;
433
	} else {
434
11830
		j = new_job(); /* fills in j->job */
435
		/* we don't consider XXCOM's foreground since they don't get
436
		 * tty process group and we don't save or restore tty modes.
437
		 */
438

11830
		j->flags = (flags & XXCOM) ? JF_XXCOM :
439
		    ((flags & XBGND) ? 0 : (JF_FG|JF_USETTYMODE));
440
11830
		timerclear(&j->usrtime);
441
11830
		timerclear(&j->systime);
442
11830
		j->state = PRUNNING;
443
11830
		j->pgrp = 0;
444
11830
		j->ppid = procpid;
445
11830
		j->age = ++njobs;
446
11830
		j->proc_list = p;
447
11830
		j->coproc_id = 0;
448
11830
		last_job = j;
449
11830
		last_proc = p;
450
11830
		put_job(j, PJ_PAST_STOPPED);
451
	}
452
453
14173
	snptreef(p->command, sizeof(p->command), "%T", t);
454
455
	/* create child process */
456
14173
	forksleep = 1;
457

28346
	while ((i = fork()) < 0 && errno == EAGAIN && forksleep < 32) {
458
		if (intrsig)	 /* allow user to ^C out... */
459
			break;
460
		sleep(forksleep);
461
		forksleep <<= 1;
462
	}
463
28336
	if (i < 0) {
464
		kill_job(j, SIGKILL);
465
		remove_job(j, "fork failed");
466
		sigprocmask(SIG_SETMASK, &omask, NULL);
467
		errorf("cannot fork - try again");
468
	}
469
28336
	ischild = i == 0;
470
28336
	if (ischild)
471
14164
		p->pid = procpid = getpid();
472
	else
473
14172
		p->pid = i;
474
475
#ifdef JOBS
476
	/* job control set up */
477

28336
	if (Flag(FMONITOR) && !(flags&XXCOM)) {
478
41
		int	dotty = 0;
479
41
		if (j->pgrp == 0) {	/* First process */
480
33
			j->pgrp = p->pid;
481
33
			dotty = 1;
482
		}
483
484
		/* set pgrp in both parent and child to deal with race
485
		 * condition
486
		 */
487
41
		setpgid(p->pid, j->pgrp);
488
		/* YYY: should this be
489
		   if (ttypgrp_ok && ischild && !(flags&XBGND))
490
			tcsetpgrp(tty_fd, j->pgrp);
491
		   instead? (see also YYY below)
492
		 */
493

41
		if (ttypgrp_ok && dotty && !(flags & XBGND))
494
33
			tcsetpgrp(tty_fd, j->pgrp);
495
	}
496
#endif /* JOBS */
497
498
	/* used to close pipe input fd */
499

28337
	if (close_fd >= 0 && (((flags & XPCLOSE) && !ischild) ||
500
	    ((flags & XCCLOSE) && ischild)))
501
4522
		close(close_fd);
502
28341
	if (ischild) {		/* child */
503
		/* Do this before restoring signal */
504
14167
		if (flags & XCOPROC)
505
			coproc_cleanup(false);
506
14167
		sigprocmask(SIG_SETMASK, &omask, NULL);
507
14167
		cleanup_parents_env();
508
#ifdef JOBS
509
		/* If FMONITOR or FTALKING is set, these signals are ignored,
510
		 * if neither FMONITOR nor FTALKING are set, the signals have
511
		 * their inherited values.
512
		 */
513

14167
		if (Flag(FMONITOR) && !(flags & XXCOM)) {
514
105
			for (i = NELEM(tt_sigs); --i >= 0; )
515
63
				setsig(&sigtraps[tt_sigs[i]], SIG_DFL,
516
				    SS_RESTORE_DFL|SS_FORCE);
517
		}
518
#endif /* JOBS */
519

14167
		if (Flag(FBGNICE) && (flags & XBGND))
520
			nice(4);
521

14167
		if ((flags & XBGND) && !Flag(FMONITOR)) {
522
122
			setsig(&sigtraps[SIGINT], SIG_IGN,
523
			    SS_RESTORE_IGN|SS_FORCE);
524
122
			setsig(&sigtraps[SIGQUIT], SIG_IGN,
525
			    SS_RESTORE_IGN|SS_FORCE);
526
122
			if (!(flags & (XPIPEI | XCOPROC))) {
527
120
				int fd = open("/dev/null", O_RDONLY);
528
120
				if (fd != 0) {
529
120
					(void) ksh_dup2(fd, 0, true);
530
120
					close(fd);
531
				}
532
			}
533
		}
534
14167
		remove_job(j, "child");	/* in case of `jobs` command */
535
14167
		nzombie = 0;
536
#ifdef JOBS
537
14167
		ttypgrp_ok = 0;
538
14167
		Flag(FMONITOR) = 0;
539
#endif /* JOBS */
540
14167
		Flag(FTALKING) = 0;
541
14167
		tty_close();
542
14167
		cleartraps();
543
14167
		execute(t, (flags & XERROK) | XEXEC, NULL); /* no return */
544
		internal_errorf(0, "exchild: execute() returned");
545
		unwind(LLEAVE);
546
		/* NOTREACHED */
547
	}
548
549
	/* shell (parent) stuff */
550
	/* Ensure next child gets a (slightly) different $RANDOM sequence */
551
14174
	change_random();
552
14174
	if (!(flags & XPIPEO)) {	/* last process in a job */
553
#ifdef JOBS
554
		/* YYY: Is this needed? (see also YYY above)
555
		   if (Flag(FMONITOR) && !(flags&(XXCOM|XBGND)))
556
			tcsetpgrp(tty_fd, j->pgrp);
557
		*/
558
#endif /* JOBS */
559
9388
		j_startjob(j);
560
9388
		if (flags & XCOPROC) {
561
			j->coproc_id = coproc.id;
562
			coproc.njobs++; /* n jobs using co-process output */
563
			coproc.job = (void *) j; /* j using co-process input */
564
		}
565
9388
		if (flags & XBGND) {
566
121
			j_set_async(j);
567
121
			if (Flag(FTALKING)) {
568
				shf_fprintf(shl_out, "[%d]", j->job);
569
				for (p = j->proc_list; p; p = p->next)
570
					shf_fprintf(shl_out, " %d", p->pid);
571
				shf_putchar('\n', shl_out);
572
				shf_flush(shl_out);
573
			}
574
		} else
575
9267
			rv = j_waitj(j, JW_NONE, "jw:last proc");
576
	}
577
578
14174
	sigprocmask(SIG_SETMASK, &omask, NULL);
579
580
14174
	return rv;
581
}
582
583
/* start the last job: only used for `command` jobs */
584
void
585
startlast(void)
586
2442
{
587
	sigset_t omask;
588
589
2442
	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
590
591
2442
	if (last_job) { /* no need to report error - waitlast() will do it */
592
		/* ensure it isn't removed by check_job() */
593
2442
		last_job->flags |= JF_WAITING;
594
2442
		j_startjob(last_job);
595
	}
596
2442
	sigprocmask(SIG_SETMASK, &omask, NULL);
597
2442
}
598
599
/* wait for last job: only used for `command` jobs */
600
int
601
waitlast(void)
602
2442
{
603
	int	rv;
604
	Job	*j;
605
	sigset_t omask;
606
607
2442
	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
608
609
2442
	j = last_job;
610

2442
	if (!j || !(j->flags & JF_STARTED)) {
611
		if (!j)
612
			warningf(true, "waitlast: no last job");
613
		else
614
			internal_errorf(0, "waitlast: not started");
615
		sigprocmask(SIG_SETMASK, &omask, NULL);
616
		return 125; /* not so arbitrary, non-zero value */
617
	}
618
619
2442
	rv = j_waitj(j, JW_NONE, "jw:waitlast");
620
621
2442
	sigprocmask(SIG_SETMASK, &omask, NULL);
622
623
2442
	return rv;
624
}
625
626
/* wait for child, interruptable. */
627
int
628
waitfor(const char *cp, int *sigp)
629
{
630
	int	rv;
631
	Job	*j;
632
	int	ecode;
633
	int	flags = JW_INTERRUPT|JW_ASYNCNOTIFY;
634
	sigset_t omask;
635
636
	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
637
638
	*sigp = 0;
639
640
	if (cp == NULL) {
641
		/* wait for an unspecified job - always returns 0, so
642
		 * don't have to worry about exited/signaled jobs
643
		 */
644
		for (j = job_list; j; j = j->next)
645
			/* at&t ksh will wait for stopped jobs - we don't */
646
			if (j->ppid == procpid && j->state == PRUNNING)
647
				break;
648
		if (!j) {
649
			sigprocmask(SIG_SETMASK, &omask, NULL);
650
			return -1;
651
		}
652
	} else if ((j = j_lookup(cp, &ecode))) {
653
		/* don't report normal job completion */
654
		flags &= ~JW_ASYNCNOTIFY;
655
		if (j->ppid != procpid) {
656
			sigprocmask(SIG_SETMASK, &omask, NULL);
657
			return -1;
658
		}
659
	} else {
660
		sigprocmask(SIG_SETMASK, &omask, NULL);
661
		if (ecode != JL_NOSUCH)
662
			bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
663
		return -1;
664
	}
665
666
	/* at&t ksh will wait for stopped jobs - we don't */
667
	rv = j_waitj(j, flags, "jw:waitfor");
668
669
	sigprocmask(SIG_SETMASK, &omask, NULL);
670
671
	if (rv < 0) /* we were interrupted */
672
		*sigp = 128 + -rv;
673
674
	return rv;
675
}
676
677
/* kill (built-in) a job */
678
int
679
j_kill(const char *cp, int sig)
680
{
681
	Job	*j;
682
	int	rv = 0;
683
	int	ecode;
684
	sigset_t omask;
685
686
	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
687
688
	if ((j = j_lookup(cp, &ecode)) == NULL) {
689
		sigprocmask(SIG_SETMASK, &omask, NULL);
690
		bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
691
		return 1;
692
	}
693
694
	if (j->pgrp == 0) {	/* started when !Flag(FMONITOR) */
695
		if (kill_job(j, sig) < 0) {
696
			bi_errorf("%s: %s", cp, strerror(errno));
697
			rv = 1;
698
		}
699
	} else {
700
#ifdef JOBS
701
		if (j->state == PSTOPPED && (sig == SIGTERM || sig == SIGHUP))
702
			(void) killpg(j->pgrp, SIGCONT);
703
#endif /* JOBS */
704
		if (killpg(j->pgrp, sig) < 0) {
705
			bi_errorf("%s: %s", cp, strerror(errno));
706
			rv = 1;
707
		}
708
	}
709
710
	sigprocmask(SIG_SETMASK, &omask, NULL);
711
712
	return rv;
713
}
714
715
#ifdef JOBS
716
/* fg and bg built-ins: called only if Flag(FMONITOR) set */
717
int
718
j_resume(const char *cp, int bg)
719
{
720
	Job	*j;
721
	Proc	*p;
722
	int	ecode;
723
	int	running;
724
	int	rv = 0;
725
	sigset_t omask;
726
727
	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
728
729
	if ((j = j_lookup(cp, &ecode)) == NULL) {
730
		sigprocmask(SIG_SETMASK, &omask, NULL);
731
		bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
732
		return 1;
733
	}
734
735
	if (j->pgrp == 0) {
736
		sigprocmask(SIG_SETMASK, &omask, NULL);
737
		bi_errorf("job not job-controlled");
738
		return 1;
739
	}
740
741
	if (bg)
742
		shprintf("[%d] ", j->job);
743
744
	running = 0;
745
	for (p = j->proc_list; p != NULL; p = p->next) {
746
		if (p->state == PSTOPPED) {
747
			p->state = PRUNNING;
748
			p->status = 0;
749
			running = 1;
750
		}
751
		shprintf("%s%s", p->command, p->next ? "| " : "");
752
	}
753
	shprintf("\n");
754
	shf_flush(shl_stdout);
755
	if (running)
756
		j->state = PRUNNING;
757
758
	put_job(j, PJ_PAST_STOPPED);
759
	if (bg)
760
		j_set_async(j);
761
	else {
762
# ifdef JOBS
763
		/* attach tty to job */
764
		if (j->state == PRUNNING) {
765
			if (ttypgrp_ok && (j->flags & JF_SAVEDTTY))
766
				tcsetattr(tty_fd, TCSADRAIN, &j->ttystate);
767
			/* See comment in j_waitj regarding saved_ttypgrp. */
768
			if (ttypgrp_ok &&
769
			    tcsetpgrp(tty_fd, (j->flags & JF_SAVEDTTYPGRP) ?
770
			    j->saved_ttypgrp : j->pgrp) < 0) {
771
				if (j->flags & JF_SAVEDTTY)
772
					tcsetattr(tty_fd, TCSADRAIN, &tty_state);
773
				sigprocmask(SIG_SETMASK, &omask, NULL);
774
				bi_errorf("1st tcsetpgrp(%d, %d) failed: %s",
775
				    tty_fd,
776
				    (int) ((j->flags & JF_SAVEDTTYPGRP) ?
777
				    j->saved_ttypgrp : j->pgrp),
778
				    strerror(errno));
779
				return 1;
780
			}
781
		}
782
# endif /* JOBS */
783
		j->flags |= JF_FG;
784
		j->flags &= ~JF_KNOWN;
785
		if (j == async_job)
786
			async_job = NULL;
787
	}
788
789
	if (j->state == PRUNNING && killpg(j->pgrp, SIGCONT) < 0) {
790
		int	err = errno;
791
792
		if (!bg) {
793
			j->flags &= ~JF_FG;
794
# ifdef JOBS
795
			if (ttypgrp_ok && (j->flags & JF_SAVEDTTY))
796
				tcsetattr(tty_fd, TCSADRAIN, &tty_state);
797
			if (ttypgrp_ok && tcsetpgrp(tty_fd, our_pgrp) < 0) {
798
				warningf(true,
799
				    "fg: 2nd tcsetpgrp(%d, %d) failed: %s",
800
				    tty_fd, (int) our_pgrp,
801
				    strerror(errno));
802
			}
803
# endif /* JOBS */
804
		}
805
		sigprocmask(SIG_SETMASK, &omask, NULL);
806
		bi_errorf("cannot continue job %s: %s",
807
		    cp, strerror(err));
808
		return 1;
809
	}
810
	if (!bg) {
811
# ifdef JOBS
812
		if (ttypgrp_ok) {
813
			j->flags &= ~(JF_SAVEDTTY | JF_SAVEDTTYPGRP);
814
		}
815
# endif /* JOBS */
816
		rv = j_waitj(j, JW_NONE, "jw:resume");
817
	}
818
	sigprocmask(SIG_SETMASK, &omask, NULL);
819
	return rv;
820
}
821
#endif /* JOBS */
822
823
/* are there any running or stopped jobs ? */
824
int
825
j_stopped_running(void)
826
208
{
827
	Job	*j;
828
208
	int	which = 0;
829
830
303
	for (j = job_list; j != NULL; j = j->next) {
831
#ifdef JOBS
832

95
		if (j->ppid == procpid && j->state == PSTOPPED)
833
			which |= 1;
834
#endif /* JOBS */
835


95
		if (Flag(FLOGIN) && !Flag(FNOHUP) && procpid == kshpid &&
836
		    j->ppid == procpid && j->state == PRUNNING)
837
			which |= 2;
838
	}
839
208
	if (which) {
840
		shellf("You have %s%s%s jobs\n",
841
		    which & 1 ? "stopped" : "",
842
		    which == 3 ? " and " : "",
843
		    which & 2 ? "running" : "");
844
		return 1;
845
	}
846
847
208
	return 0;
848
}
849
850
int
851
j_njobs(void)
852
{
853
	Job *j;
854
	int nj = 0;
855
	sigset_t omask;
856
857
	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
858
	for (j = job_list; j; j = j->next)
859
		nj++;
860
861
	sigprocmask(SIG_SETMASK, &omask, NULL);
862
	return nj;
863
}
864
865
866
/* list jobs for jobs built-in */
867
int
868
j_jobs(const char *cp, int slp,
869
    int nflag)		/* 0: short, 1: long, 2: pgrp */
870
{
871
	Job	*j, *tmp;
872
	int	how;
873
	int	zflag = 0;
874
	sigset_t omask;
875
876
	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
877
878
	if (nflag < 0) { /* kludge: print zombies */
879
		nflag = 0;
880
		zflag = 1;
881
	}
882
	if (cp) {
883
		int	ecode;
884
885
		if ((j = j_lookup(cp, &ecode)) == NULL) {
886
			sigprocmask(SIG_SETMASK, &omask, NULL);
887
			bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
888
			return 1;
889
		}
890
	} else
891
		j = job_list;
892
	how = slp == 0 ? JP_MEDIUM : (slp == 1 ? JP_LONG : JP_PGRP);
893
	for (; j; j = j->next) {
894
		if ((!(j->flags & JF_ZOMBIE) || zflag) &&
895
		    (!nflag || (j->flags & JF_CHANGED))) {
896
			j_print(j, how, shl_stdout);
897
			if (j->state == PEXITED || j->state == PSIGNALLED)
898
				j->flags |= JF_REMOVE;
899
		}
900
		if (cp)
901
			break;
902
	}
903
	/* Remove jobs after printing so there won't be multiple + or - jobs */
904
	for (j = job_list; j; j = tmp) {
905
		tmp = j->next;
906
		if (j->flags & JF_REMOVE)
907
			remove_job(j, "jobs");
908
	}
909
	sigprocmask(SIG_SETMASK, &omask, NULL);
910
	return 0;
911
}
912
913
/* list jobs for top-level notification */
914
void
915
j_notify(void)
916
7466
{
917
	Job	*j, *tmp;
918
	sigset_t omask;
919
920
7466
	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
921
13700
	for (j = job_list; j; j = j->next) {
922
#ifdef JOBS
923

6234
		if (Flag(FMONITOR) && (j->flags & JF_CHANGED))
924
			j_print(j, JP_MEDIUM, shl_out);
925
#endif /* JOBS */
926
		/* Remove job after doing reports so there aren't
927
		 * multiple +/- jobs.
928
		 */
929
6234
		if (j->state == PEXITED || j->state == PSIGNALLED)
930
5974
			j->flags |= JF_REMOVE;
931
	}
932
13700
	for (j = job_list; j; j = tmp) {
933
6234
		tmp = j->next;
934
6234
		if (j->flags & JF_REMOVE)
935
5974
			remove_job(j, "notify");
936
	}
937
7466
	shf_flush(shl_out);
938
7466
	sigprocmask(SIG_SETMASK, &omask, NULL);
939
7466
}
940
941
/* Return pid of last process in last asynchronous job */
942
pid_t
943
j_async(void)
944
94
{
945
	sigset_t omask;
946
947
94
	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
948
949
94
	if (async_job)
950
94
		async_job->flags |= JF_KNOWN;
951
952
94
	sigprocmask(SIG_SETMASK, &omask, NULL);
953
954
94
	return async_pid;
955
}
956
957
/* Make j the last async process
958
 *
959
 * If jobs are compiled in then this routine expects sigchld to be blocked.
960
 */
961
static void
962
j_set_async(Job *j)
963
120
{
964
	Job	*jl, *oldest;
965
966

120
	if (async_job && (async_job->flags & (JF_KNOWN|JF_ZOMBIE)) == JF_ZOMBIE)
967
		remove_job(async_job, "async");
968
120
	if (!(j->flags & JF_STARTED)) {
969
		internal_errorf(0, "j_async: job not started");
970
		return;
971
	}
972
120
	async_job = j;
973
120
	async_pid = j->last_proc->pid;
974
240
	while (nzombie > child_max) {
975
		oldest = NULL;
976
		for (jl = job_list; jl; jl = jl->next)
977
			if (jl != async_job && (jl->flags & JF_ZOMBIE) &&
978
			    (!oldest || jl->age < oldest->age))
979
				oldest = jl;
980
		if (!oldest) {
981
			/* XXX debugging */
982
			if (!(async_job->flags & JF_ZOMBIE) || nzombie != 1) {
983
				internal_errorf(0,
984
				    "j_async: bad nzombie (%d)", nzombie);
985
				nzombie = 0;
986
			}
987
			break;
988
		}
989
		remove_job(oldest, "zombie");
990
	}
991
}
992
993
/* Start a job: set STARTED, check for held signals and set j->last_proc
994
 *
995
 * If jobs are compiled in then this routine expects sigchld to be blocked.
996
 */
997
static void
998
j_startjob(Job *j)
999
11829
{
1000
	Proc	*p;
1001
1002
11829
	j->flags |= JF_STARTED;
1003
11829
	for (p = j->proc_list; p->next; p = p->next)
1004
		;
1005
11829
	j->last_proc = p;
1006
1007
11829
	if (held_sigchld) {
1008
158
		held_sigchld = 0;
1009
		/* Don't call j_sigchld() as it may remove job... */
1010
158
		kill(procpid, SIGCHLD);
1011
	}
1012
11829
}
1013
1014
/*
1015
 * wait for job to complete or change state
1016
 *
1017
 * If jobs are compiled in then this routine expects sigchld to be blocked.
1018
 */
1019
static int
1020
j_waitj(Job *j,
1021
    int flags,			/* see JW_* */
1022
    const char *where)
1023
11709
{
1024
	int	rv;
1025
1026
	/*
1027
	 * No auto-notify on the job we are waiting on.
1028
	 */
1029
11709
	j->flags |= JF_WAITING;
1030
11709
	if (flags & JW_ASYNCNOTIFY)
1031
		j->flags |= JF_W_ASYNCNOTIFY;
1032
1033
11709
	if (!Flag(FMONITOR))
1034
11686
		flags |= JW_STOPPEDWAIT;
1035
1036

22715
	while ((volatile int) j->state == PRUNNING ||
1037
	    ((flags & JW_STOPPEDWAIT) && (volatile int) j->state == PSTOPPED)) {
1038
11006
		sigsuspend(&sm_default);
1039
11006
		if (fatal_trap) {
1040
			int oldf = j->flags & (JF_WAITING|JF_W_ASYNCNOTIFY);
1041
			j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY);
1042
			runtraps(TF_FATAL);
1043
			j->flags |= oldf; /* not reached... */
1044
		}
1045

11006
		if ((flags & JW_INTERRUPT) && (rv = trap_pending())) {
1046
			j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY);
1047
			return -rv;
1048
		}
1049
	}
1050
11709
	j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY);
1051
1052
11709
	if (j->flags & JF_FG) {
1053
		int	status;
1054
1055
9267
		j->flags &= ~JF_FG;
1056
#ifdef JOBS
1057

9267
		if (Flag(FMONITOR) && ttypgrp_ok && j->pgrp) {
1058
			/*
1059
			 * Save the tty's current pgrp so it can be restored
1060
			 * when the job is foregrounded.  This is to
1061
			 * deal with things like the GNU su which does
1062
			 * a fork/exec instead of an exec (the fork means
1063
			 * the execed shell gets a different pid from its
1064
			 * pgrp, so naturally it sets its pgrp and gets hosed
1065
			 * when it gets foregrounded by the parent shell, which
1066
			 * has restored the tty's pgrp to that of the su
1067
			 * process).
1068
			 */
1069

16
			if (j->state == PSTOPPED &&
1070
			    (j->saved_ttypgrp = tcgetpgrp(tty_fd)) >= 0)
1071
				j->flags |= JF_SAVEDTTYPGRP;
1072
16
			if (tcsetpgrp(tty_fd, our_pgrp) < 0) {
1073
				warningf(true,
1074
				    "j_waitj: tcsetpgrp(%d, %d) failed: %s",
1075
				    tty_fd, (int) our_pgrp,
1076
					strerror(errno));
1077
			}
1078
16
			if (j->state == PSTOPPED) {
1079
				j->flags |= JF_SAVEDTTY;
1080
				tcgetattr(tty_fd, &j->ttystate);
1081
			}
1082
		}
1083
#endif /* JOBS */
1084
9267
		if (tty_fd >= 0) {
1085
			/* Only restore tty settings if job was originally
1086
			 * started in the foreground.  Problems can be
1087
			 * caused by things like `more foobar &' which will
1088
			 * typically get and save the shell's vi/emacs tty
1089
			 * settings before setting up the tty for itself;
1090
			 * when more exits, it restores the `original'
1091
			 * settings, and things go down hill from there...
1092
			 */
1093

28
			if (j->state == PEXITED && j->status == 0 &&
1094
			    (j->flags & JF_USETTYMODE)) {
1095
12
				tcgetattr(tty_fd, &tty_state);
1096
			} else {
1097
4
				tcsetattr(tty_fd, TCSADRAIN, &tty_state);
1098
				/* Don't use tty mode if job is stopped and
1099
				 * later restarted and exits.  Consider
1100
				 * the sequence:
1101
				 *	vi foo (stopped)
1102
				 *	...
1103
				 *	stty something
1104
				 *	...
1105
				 *	fg (vi; ZZ)
1106
				 * mode should be that of the stty, not what
1107
				 * was before the vi started.
1108
				 */
1109
4
				if (j->state == PSTOPPED)
1110
					j->flags &= ~JF_USETTYMODE;
1111
			}
1112
		}
1113
#ifdef JOBS
1114
		/* If it looks like user hit ^C to kill a job, pretend we got
1115
		 * one too to break out of for loops, etc.  (at&t ksh does this
1116
		 * even when not monitoring, but this doesn't make sense since
1117
		 * a tty generated ^C goes to the whole process group)
1118
		 */
1119
9267
		status = j->last_proc->status;
1120


9267
		if (Flag(FMONITOR) && j->state == PSIGNALLED &&
1121
		    WIFSIGNALED(status) &&
1122
		    (sigtraps[WTERMSIG(status)].flags & TF_TTY_INTR))
1123
			trapsig(WTERMSIG(status));
1124
#endif /* JOBS */
1125
	}
1126
1127
11709
	j_usrtime = j->usrtime;
1128
11709
	j_systime = j->systime;
1129
11709
	rv = j->status;
1130
1131

11709
	if (!(flags & JW_ASYNCNOTIFY) &&
1132
	    (!Flag(FMONITOR) || j->state != PSTOPPED)) {
1133
11709
		j_print(j, JP_SHORT, shl_out);
1134
11709
		shf_flush(shl_out);
1135
	}
1136

11709
	if (j->state != PSTOPPED &&
1137
	    (!Flag(FMONITOR) || !(flags & JW_ASYNCNOTIFY)))
1138
11709
		remove_job(j, where);
1139
1140
11709
	return rv;
1141
}
1142
1143
/* SIGCHLD handler to reap children and update job states
1144
 *
1145
 * If jobs are compiled in then this routine expects sigchld to be blocked.
1146
 */
1147
static void
1148
j_sigchld(int sig)
1149
14189
{
1150
14189
	int		errno_ = errno;
1151
	Job		*j;
1152
14189
	Proc		*p = NULL;
1153
	int		pid;
1154
	int		status;
1155
	struct rusage	ru0, ru1;
1156
1157
	/* Don't wait for any processes if a job is partially started.
1158
	 * This is so we don't do away with the process group leader
1159
	 * before all the processes in a pipe line are started (so the
1160
	 * setpgid() won't fail)
1161
	 */
1162
35926
	for (j = job_list; j; j = j->next)
1163

21896
		if (j->ppid == procpid && !(j->flags & JF_STARTED)) {
1164
159
			held_sigchld = 1;
1165
159
			goto finished;
1166
		}
1167
1168
14030
	getrusage(RUSAGE_CHILDREN, &ru0);
1169
	do {
1170
28190
		pid = waitpid(-1, &status, (WNOHANG|WUNTRACED));
1171
1172
28190
		if (pid <= 0)	/* return if would block (0) ... */
1173
14030
			break;	/* ... or no children or interrupted (-1) */
1174
1175
14160
		getrusage(RUSAGE_CHILDREN, &ru1);
1176
1177
		/* find job and process structures for this pid */
1178
14176
		for (j = job_list; j != NULL; j = j->next)
1179
16736
			for (p = j->proc_list; p != NULL; p = p->next)
1180
16720
				if (p->pid == pid)
1181
14160
					goto found;
1182
14160
found:
1183
14160
		if (j == NULL) {
1184
			/* Can occur if process has kids, then execs shell
1185
			warningf(true, "bad process waited for (pid = %d)",
1186
				pid);
1187
			 */
1188
			ru0 = ru1;
1189
			continue;
1190
		}
1191
1192
14160
		timeradd(&j->usrtime, &ru1.ru_utime, &j->usrtime);
1193
14160
		timersub(&j->usrtime, &ru0.ru_utime, &j->usrtime);
1194
14160
		timeradd(&j->systime, &ru1.ru_stime, &j->systime);
1195
14160
		timersub(&j->systime, &ru0.ru_stime, &j->systime);
1196
14160
		ru0 = ru1;
1197
14160
		p->status = status;
1198
#ifdef JOBS
1199
14160
		if (WIFSTOPPED(status))
1200
			p->state = PSTOPPED;
1201
		else
1202
#endif /* JOBS */
1203
14160
		if (WIFSIGNALED(status))
1204
631
			p->state = PSIGNALLED;
1205
		else
1206
13529
			p->state = PEXITED;
1207
1208
14160
		check_job(j);	/* check to see if entire job is done */
1209
	} while (1);
1210
1211
14189
finished:
1212
14189
	errno = errno_;
1213
14189
}
1214
1215
/*
1216
 * Called only when a process in j has exited/stopped (ie, called only
1217
 * from j_sigchld()).  If no processes are running, the job status
1218
 * and state are updated, asynchronous job notification is done and,
1219
 * if unneeded, the job is removed.
1220
 *
1221
 * If jobs are compiled in then this routine expects sigchld to be blocked.
1222
 */
1223
static void
1224
check_job(Job *j)
1225
14160
{
1226
	int	jstate;
1227
	Proc	*p;
1228
1229
	/* XXX debugging (nasty - interrupt routine using shl_out) */
1230
14160
	if (!(j->flags & JF_STARTED)) {
1231
		internal_errorf(0, "check_job: job started (flags 0x%x)",
1232
		    j->flags);
1233
		return;
1234
	}
1235
1236
14160
	jstate = PRUNNING;
1237
30684
	for (p=j->proc_list; p != NULL; p = p->next) {
1238
18866
		if (p->state == PRUNNING)
1239
2342
			return;	/* some processes still running */
1240
16524
		if (p->state > jstate)
1241
14016
			jstate = p->state;
1242
	}
1243
11818
	j->state = jstate;
1244
1245
11818
	switch (j->last_proc->state) {
1246
	case PEXITED:
1247
11187
		j->status = WEXITSTATUS(j->last_proc->status);
1248
11187
		break;
1249
	case PSIGNALLED:
1250
631
		j->status = 128 + WTERMSIG(j->last_proc->status);
1251
631
		break;
1252
	default:
1253
		j->status = 0;
1254
		break;
1255
	}
1256
1257
	/* Note when co-process dies: can't be done in j_wait() nor
1258
	 * remove_job() since neither may be called for non-interactive
1259
	 * shells.
1260
	 */
1261
11818
	if (j->state == PEXITED || j->state == PSIGNALLED) {
1262
		/* No need to keep co-process input any more
1263
		 * (at least, this is what ksh93d thinks)
1264
		 */
1265
11818
		if (coproc.job == j) {
1266
			coproc.job = NULL;
1267
			/* XXX would be nice to get the closes out of here
1268
			 * so they aren't done in the signal handler.
1269
			 * Would mean a check in coproc_getfd() to
1270
			 * do "if job == 0 && write >= 0, close write".
1271
			 */
1272
			coproc_write_close(coproc.write);
1273
		}
1274
		/* Do we need to keep the output? */
1275

11818
		if (j->coproc_id && j->coproc_id == coproc.id &&
1276
		    --coproc.njobs == 0)
1277
			coproc_readw_close(coproc.read);
1278
	}
1279
1280
11818
	j->flags |= JF_CHANGED;
1281
#ifdef JOBS
1282

11818
	if (Flag(FMONITOR) && !(j->flags & JF_XXCOM)) {
1283
		/* Only put stopped jobs at the front to avoid confusing
1284
		 * the user (don't want finished jobs effecting %+ or %-)
1285
		 */
1286
16
		if (j->state == PSTOPPED)
1287
			put_job(j, PJ_ON_FRONT);
1288

16
		if (Flag(FNOTIFY) &&
1289
		    (j->flags & (JF_WAITING|JF_W_ASYNCNOTIFY)) != JF_WAITING) {
1290
			/* Look for the real file descriptor 2 */
1291
			{
1292
				struct env *ep;
1293
				int fd = 2;
1294
1295
				for (ep = genv; ep; ep = ep->oenv)
1296
					if (ep->savefd && ep->savefd[2])
1297
						fd = ep->savefd[2];
1298
				shf_reopen(fd, SHF_WR, shl_j);
1299
			}
1300
			/* Can't call j_notify() as it removes jobs.  The job
1301
			 * must stay in the job list as j_waitj() may be
1302
			 * running with this job.
1303
			 */
1304
			j_print(j, JP_MEDIUM, shl_j);
1305
			shf_flush(shl_j);
1306
			if (!(j->flags & JF_WAITING) && j->state != PSTOPPED)
1307
				remove_job(j, "notify");
1308
		}
1309
	}
1310
#endif /* JOBS */
1311

11818
	if (!Flag(FMONITOR) && !(j->flags & (JF_WAITING|JF_FG)) &&
1312
	    j->state != PSTOPPED) {
1313

218
		if (j == async_job || (j->flags & JF_KNOWN)) {
1314
109
			j->flags |= JF_ZOMBIE;
1315
109
			j->job = -1;
1316
109
			nzombie++;
1317
		} else
1318
			remove_job(j, "checkjob");
1319
	}
1320
}
1321
1322
/*
1323
 * Print job status in either short, medium or long format.
1324
 *
1325
 * If jobs are compiled in then this routine expects sigchld to be blocked.
1326
 */
1327
static void
1328
j_print(Job *j, int how, struct shf *shf)
1329
11709
{
1330
	Proc	*p;
1331
	int	state;
1332
	int	status;
1333
	int	coredumped;
1334
11709
	char	jobchar = ' ';
1335
	char	buf[64];
1336
	const char *filler;
1337
11709
	int	output = 0;
1338
1339
11709
	if (how == JP_PGRP) {
1340
		/* POSIX doesn't say what to do it there is no process
1341
		 * group leader (ie, !FMONITOR).  We arbitrarily return
1342
		 * last pid (which is what $! returns).
1343
		 */
1344
		shf_fprintf(shf, "%d\n", j->pgrp ? j->pgrp :
1345
		    (j->last_proc ? j->last_proc->pid : 0));
1346
		return;
1347
	}
1348
11709
	j->flags &= ~JF_CHANGED;
1349
11709
	filler = j->job > 10 ?  "\n       " : "\n      ";
1350
11709
	if (j == job_list)
1351
11709
		jobchar = '+';
1352
	else if (j == job_list->next)
1353
		jobchar = '-';
1354
1355
35170
	for (p = j->proc_list; p != NULL;) {
1356
11752
		coredumped = 0;
1357

11752
		switch (p->state) {
1358
		case PRUNNING:
1359
			strlcpy(buf, "Running", sizeof buf);
1360
			break;
1361
		case PSTOPPED:
1362
			strlcpy(buf, sigtraps[WSTOPSIG(p->status)].mess,
1363
			    sizeof buf);
1364
			break;
1365
		case PEXITED:
1366
11214
			if (how == JP_SHORT)
1367
11214
				buf[0] = '\0';
1368
			else if (WEXITSTATUS(p->status) == 0)
1369
				strlcpy(buf, "Done", sizeof buf);
1370
			else
1371
				shf_snprintf(buf, sizeof(buf), "Done (%d)",
1372
				    WEXITSTATUS(p->status));
1373
			break;
1374
		case PSIGNALLED:
1375
538
			if (WCOREDUMP(p->status))
1376
536
				coredumped = 1;
1377
			/* kludge for not reporting `normal termination signals'
1378
			 * (ie, SIGINT, SIGPIPE)
1379
			 */
1380

540
			if (how == JP_SHORT && !coredumped &&
1381
			    (WTERMSIG(p->status) == SIGINT ||
1382
			    WTERMSIG(p->status) == SIGPIPE)) {
1383
2
				buf[0] = '\0';
1384
			} else
1385
536
				strlcpy(buf, sigtraps[WTERMSIG(p->status)].mess,
1386
				    sizeof buf);
1387
			break;
1388
		}
1389
1390
11752
		if (how != JP_SHORT) {
1391
			if (p == j->proc_list)
1392
				shf_fprintf(shf, "[%d] %c ", j->job, jobchar);
1393
			else
1394
				shf_fprintf(shf, "%s", filler);
1395
		}
1396
1397
11752
		if (how == JP_LONG)
1398
			shf_fprintf(shf, "%5d ", p->pid);
1399
1400
11752
		if (how == JP_SHORT) {
1401
11752
			if (buf[0]) {
1402
536
				output = 1;
1403
536
				shf_fprintf(shf, "%s%s ",
1404
				    buf, coredumped ? " (core dumped)" : "");
1405
			}
1406
		} else {
1407
			output = 1;
1408
			shf_fprintf(shf, "%-20s %s%s%s", buf, p->command,
1409
			    p->next ? "|" : "",
1410
			    coredumped ? " (core dumped)" : "");
1411
		}
1412
1413
11752
		state = p->state;
1414
11752
		status = p->status;
1415
11752
		p = p->next;
1416

25803
		while (p && p->state == state && p->status == status) {
1417
2299
			if (how == JP_LONG)
1418
				shf_fprintf(shf, "%s%5d %-20s %s%s", filler, p->pid,
1419
				    " ", p->command, p->next ? "|" : "");
1420
2299
			else if (how == JP_MEDIUM)
1421
				shf_fprintf(shf, " %s%s", p->command,
1422
				    p->next ? "|" : "");
1423
2299
			p = p->next;
1424
		}
1425
	}
1426
11709
	if (output)
1427
536
		shf_fprintf(shf, "\n");
1428
}
1429
1430
/* Convert % sequence to job
1431
 *
1432
 * If jobs are compiled in then this routine expects sigchld to be blocked.
1433
 */
1434
static Job *
1435
j_lookup(const char *cp, int *ecodep)
1436
{
1437
	Job		*j, *last_match;
1438
	const char	*errstr;
1439
	Proc		*p;
1440
	int		len, job = 0;
1441
1442
	if (digit(*cp)) {
1443
		job = strtonum(cp, 1, INT_MAX, &errstr);
1444
		if (errstr) {
1445
			if (ecodep)
1446
				*ecodep = JL_NOSUCH;
1447
			return NULL;
1448
		}
1449
		/* Look for last_proc->pid (what $! returns) first... */
1450
		for (j = job_list; j != NULL; j = j->next)
1451
			if (j->last_proc && j->last_proc->pid == job)
1452
				return j;
1453
		/* ...then look for process group (this is non-POSIX),
1454
		 * but should not break anything (so FPOSIX isn't used).
1455
		 */
1456
		for (j = job_list; j != NULL; j = j->next)
1457
			if (j->pgrp && j->pgrp == job)
1458
				return j;
1459
		if (ecodep)
1460
			*ecodep = JL_NOSUCH;
1461
		return NULL;
1462
	}
1463
	if (*cp != '%') {
1464
		if (ecodep)
1465
			*ecodep = JL_INVALID;
1466
		return NULL;
1467
	}
1468
	switch (*++cp) {
1469
	case '\0': /* non-standard */
1470
	case '+':
1471
	case '%':
1472
		if (job_list != NULL)
1473
			return job_list;
1474
		break;
1475
1476
	case '-':
1477
		if (job_list != NULL && job_list->next)
1478
			return job_list->next;
1479
		break;
1480
1481
	case '0': case '1': case '2': case '3': case '4':
1482
	case '5': case '6': case '7': case '8': case '9':
1483
		job = strtonum(cp, 1, INT_MAX, &errstr);
1484
		if (errstr)
1485
			break;
1486
		for (j = job_list; j != NULL; j = j->next)
1487
			if (j->job == job)
1488
				return j;
1489
		break;
1490
1491
	case '?':		/* %?string */
1492
		last_match = NULL;
1493
		for (j = job_list; j != NULL; j = j->next)
1494
			for (p = j->proc_list; p != NULL; p = p->next)
1495
				if (strstr(p->command, cp+1) != NULL) {
1496
					if (last_match) {
1497
						if (ecodep)
1498
							*ecodep = JL_AMBIG;
1499
						return NULL;
1500
					}
1501
					last_match = j;
1502
				}
1503
		if (last_match)
1504
			return last_match;
1505
		break;
1506
1507
	default:		/* %string */
1508
		len = strlen(cp);
1509
		last_match = NULL;
1510
		for (j = job_list; j != NULL; j = j->next)
1511
			if (strncmp(cp, j->proc_list->command, len) == 0) {
1512
				if (last_match) {
1513
					if (ecodep)
1514
						*ecodep = JL_AMBIG;
1515
					return NULL;
1516
				}
1517
				last_match = j;
1518
			}
1519
		if (last_match)
1520
			return last_match;
1521
		break;
1522
	}
1523
	if (ecodep)
1524
		*ecodep = JL_NOSUCH;
1525
	return NULL;
1526
}
1527
1528
static Job	*free_jobs;
1529
static Proc	*free_procs;
1530
1531
/* allocate a new job and fill in the job number.
1532
 *
1533
 * If jobs are compiled in then this routine expects sigchld to be blocked.
1534
 */
1535
static Job *
1536
new_job(void)
1537
11830
{
1538
	int	i;
1539
	Job	*newj, *j;
1540
1541
11830
	if (free_jobs != NULL) {
1542
8564
		newj = free_jobs;
1543
8564
		free_jobs = free_jobs->next;
1544
	} else
1545
3266
		newj = alloc(sizeof(Job), APERM);
1546
1547
	/* brute force method */
1548
12077
	for (i = 1; ; i++) {
1549

12077
		for (j = job_list; j && j->job != i; j = j->next)
1550
			;
1551
12077
		if (j == NULL)
1552
11830
			break;
1553
247
	}
1554
11830
	newj->job = i;
1555
1556
11830
	return newj;
1557
}
1558
1559
/* Allocate new process struct
1560
 *
1561
 * If jobs are compiled in then this routine expects sigchld to be blocked.
1562
 */
1563
static Proc *
1564
new_proc(void)
1565
14173
{
1566
	Proc	*p;
1567
1568
14173
	if (free_procs != NULL) {
1569
9620
		p = free_procs;
1570
9620
		free_procs = free_procs->next;
1571
	} else
1572
4553
		p = alloc(sizeof(Proc), APERM);
1573
1574
14173
	return p;
1575
}
1576
1577
/* Take job out of job_list and put old structures into free list.
1578
 * Keeps nzombies, last_job and async_job up to date.
1579
 *
1580
 * If jobs are compiled in then this routine expects sigchld to be blocked.
1581
 */
1582
static void
1583
remove_job(Job *j, const char *where)
1584
31848
{
1585
	Proc	*p, *tmp;
1586
	Job	**prev, *curr;
1587
1588
31848
	prev = &job_list;
1589
31848
	curr = *prev;
1590
31848
	for (; curr != NULL && curr != j; prev = &curr->next, curr = *prev)
1591
		;
1592
31848
	if (curr != j) {
1593
		internal_errorf(0, "remove_job: job not found (%s)", where);
1594
		return;
1595
	}
1596
31848
	*prev = curr->next;
1597
1598
	/* free up proc structures */
1599
100431
	for (p = j->proc_list; p != NULL; ) {
1600
36735
		tmp = p;
1601
36735
		p = p->next;
1602
36735
		tmp->next = free_procs;
1603
36735
		free_procs = tmp;
1604
	}
1605
1606

31848
	if ((j->flags & JF_ZOMBIE) && j->ppid == procpid)
1607
109
		--nzombie;
1608
31848
	j->next = free_jobs;
1609
31848
	free_jobs = j;
1610
1611
31848
	if (j == last_job)
1612
25874
		last_job = NULL;
1613
31848
	if (j == async_job)
1614
108
		async_job = NULL;
1615
}
1616
1617
/* put j in a particular location (taking it out job_list if it is there
1618
 * already)
1619
 *
1620
 * If jobs are compiled in then this routine expects sigchld to be blocked.
1621
 */
1622
static void
1623
put_job(Job *j, int where)
1624
11830
{
1625
	Job	**prev, *curr;
1626
1627
	/* Remove job from list (if there) */
1628
11830
	prev = &job_list;
1629
11830
	curr = job_list;
1630
11830
	for (; curr && curr != j; prev = &curr->next, curr = *prev)
1631
		;
1632
11830
	if (curr == j)
1633
		*prev = curr->next;
1634
1635
11830
	switch (where) {
1636
	case PJ_ON_FRONT:
1637
		j->next = job_list;
1638
		job_list = j;
1639
		break;
1640
1641
	case PJ_PAST_STOPPED:
1642
11830
		prev = &job_list;
1643
11830
		curr = job_list;
1644

23660
		for (; curr && curr->state == PSTOPPED; prev = &curr->next,
1645
		    curr = *prev)
1646
			;
1647
11830
		j->next = curr;
1648
11830
		*prev = j;
1649
		break;
1650
	}
1651
11830
}
1652
1653
/* nuke a job (called when unable to start full job).
1654
 *
1655
 * If jobs are compiled in then this routine expects sigchld to be blocked.
1656
 */
1657
static int
1658
kill_job(Job *j, int sig)
1659
{
1660
	Proc	*p;
1661
	int	rval = 0;
1662
1663
	for (p = j->proc_list; p != NULL; p = p->next)
1664
		if (p->pid != 0)
1665
			if (kill(p->pid, sig) < 0)
1666
				rval = -1;
1667
	return rval;
1668
}