OSDN Git Service

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