OSDN Git Service

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