OSDN Git Service

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