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