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