OSDN Git Service

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