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