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