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