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