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