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