1 /* 2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7 /* All Rights Reserved */ 8 9 /* 10 * Copyright (c) 1980 Regents of the University of California. 11 * All rights reserved. The Berkeley Software License Agreement 12 * specifies the terms and conditions for redistribution. 13 */ 14 15 #include "sh.h" 16 #include "sh.dir.h" 17 #include "sh.proc.h" 18 #include "wait.h" 19 #include "sh.tconst.h" 20 21 /* 22 * C Shell - functions that manage processes, handling hanging, termination 23 */ 24 25 bool neednote; 26 bool pjobs; 27 static struct process *pprevious; 28 static short pmaxindex; 29 static struct process proclist; 30 static struct process *pcurrent; 31 struct process *pcurrjob; 32 static struct process *pholdjob; 33 34 #define BIGINDEX 9 /* largest desirable job index */ 35 36 void pjwait(struct process *); 37 void pflush(struct process *); 38 void pclrcurr(struct process *); 39 void padd(struct command *); 40 void pads(tchar *); 41 void ptprint(struct process *); 42 void pkill(tchar **, int); 43 void pstart(struct process *, int); 44 void okpcntl(void); 45 struct process *pgetcurr(struct process *); 46 struct process *pfind(tchar *); 47 48 /* 49 * pchild - called at interrupt level by the SIGCHLD signal 50 * indicating that at least one child has terminated or stopped 51 * thus at least one wait system call will definitely return a 52 * childs status. Top level routines (like pwait) must be sure 53 * to mask interrupts when playing with the proclist data structures! 54 */ 55 void 56 pchild(int signal __unused) 57 { 58 struct process *pp; 59 struct process *fp; 60 int pid; 61 union wait w; 62 int jobflags; 63 struct rusage ru; 64 65 #ifdef TRACE 66 tprintf("TRACE- pchile()\n"); 67 #endif 68 loop: 69 pid = csh_wait3(&w, (setintr ? WNOHANG|WUNTRACED:WNOHANG), &ru); 70 /* 71 * SysV sends a SIGCHLD when the child process 72 * receives a SIGCONT, and result of that action is ignored here 73 */ 74 if (w.w_status == WCONTFLG) 75 return; 76 if (pid <= 0) { 77 if (errno == EINTR) { 78 errno = 0; 79 goto loop; 80 } 81 return; 82 } 83 for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next) 84 if (pid == pp->p_pid) 85 goto found; 86 goto loop; 87 found: 88 if (pid == atoi_(value(S_child /* "child" */))) 89 unsetv(S_child /* "child" */); 90 pp->p_flags &= ~(PRUNNING|PSTOPPED|PREPORTED); 91 if (WIFSTOPPED(w)) { 92 pp->p_flags |= PSTOPPED; 93 pp->p_reason = w.w_stopsig; 94 } else { 95 if (pp->p_flags & (PTIME|PPTIME) || adrof(S_time /* "time" */)) 96 (void) gettimeofday(&pp->p_etime, (struct timezone *)0); 97 pp->p_rusage = ru; 98 if (WIFSIGNALED(w)) { 99 if (w.w_termsig == SIGINT) 100 pp->p_flags |= PINTERRUPTED; 101 else 102 pp->p_flags |= PSIGNALED; 103 if (w.w_coredump) 104 pp->p_flags |= PDUMPED; 105 pp->p_reason = w.w_termsig; 106 } else { 107 pp->p_reason = w.w_retcode; 108 if (pp->p_reason != 0) 109 pp->p_flags |= PAEXITED; 110 else 111 pp->p_flags |= PNEXITED; 112 } 113 } 114 jobflags = 0; 115 fp = pp; 116 do { 117 if ((fp->p_flags & (PPTIME|PRUNNING|PSTOPPED)) == 0 && 118 !child && adrof(S_time /* "time" */) && 119 fp->p_rusage.ru_utime.tv_sec+fp->p_rusage.ru_stime.tv_sec >= 120 atoi_(value(S_time /* "time" */))) 121 fp->p_flags |= PTIME; 122 jobflags |= fp->p_flags; 123 } while ((fp = fp->p_friends) != pp); 124 pp->p_flags &= ~PFOREGND; 125 if (pp == pp->p_friends && (pp->p_flags & PPTIME)) { 126 pp->p_flags &= ~PPTIME; 127 pp->p_flags |= PTIME; 128 } 129 if ((jobflags & (PRUNNING|PREPORTED)) == 0) { 130 fp = pp; 131 do { 132 if (fp->p_flags&PSTOPPED) 133 fp->p_flags |= PREPORTED; 134 } while ((fp = fp->p_friends) != pp); 135 while (fp->p_pid != fp->p_jobid) 136 fp = fp->p_friends; 137 if (jobflags&PSTOPPED) { 138 if (pcurrent && pcurrent != fp) 139 pprevious = pcurrent; 140 pcurrent = fp; 141 } else 142 pclrcurr(fp); 143 if (jobflags&PFOREGND) { 144 if (jobflags & (PSIGNALED|PSTOPPED|PPTIME) || 145 #ifdef IIASA 146 jobflags & PAEXITED || 147 #endif 148 !eq(dcwd->di_name, fp->p_cwd->di_name)) { 149 ; /* print in pjwait */ 150 } 151 } else { 152 if (jobflags&PNOTIFY || adrof(S_notify /* "notify" */)) { 153 write_string("\015\n"); 154 flush(); 155 (void) pprint(pp, NUMBER|NAME|REASON); 156 if ((jobflags&PSTOPPED) == 0) 157 pflush(pp); 158 } else { 159 fp->p_flags |= PNEEDNOTE; 160 neednote++; 161 } 162 } 163 } 164 goto loop; 165 } 166 167 void 168 pnote(void) 169 { 170 struct process *pp; 171 int flags, omask; 172 173 #ifdef TRACE 174 tprintf("TRACE- pnote()\n"); 175 #endif 176 neednote = 0; 177 for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next) { 178 if (pp->p_flags & PNEEDNOTE) { 179 omask = sigblock(sigmask(SIGCHLD)); 180 pp->p_flags &= ~PNEEDNOTE; 181 flags = pprint(pp, NUMBER|NAME|REASON); 182 if ((flags&(PRUNNING|PSTOPPED)) == 0) 183 pflush(pp); 184 (void) sigsetmask(omask); 185 } 186 } 187 } 188 189 /* 190 * pwait - wait for current job to terminate, maintaining integrity 191 * of current and previous job indicators. 192 */ 193 void 194 pwait(void) 195 { 196 struct process *fp, *pp; 197 int omask; 198 199 #ifdef TRACE 200 tprintf("TRACE- pwait()\n"); 201 #endif 202 /* 203 * Here's where dead procs get flushed. 204 */ 205 omask = sigblock(sigmask(SIGCHLD)); 206 for (pp = (fp = &proclist)->p_next; pp != PNULL; pp = (fp = pp)->p_next) 207 if (pp->p_pid == 0) { 208 fp->p_next = pp->p_next; 209 xfree(pp->p_command); 210 if (pp->p_cwd && --pp->p_cwd->di_count == 0) 211 if (pp->p_cwd->di_next == 0) 212 dfree(pp->p_cwd); 213 xfree((tchar *)pp); 214 pp = fp; 215 } 216 (void) sigsetmask(omask); 217 pjwait(pcurrjob); 218 } 219 220 /* 221 * pjwait - wait for a job to finish or become stopped 222 * It is assumed to be in the foreground state (PFOREGND) 223 */ 224 void 225 pjwait(struct process *pp) 226 { 227 struct process *fp; 228 int jobflags, reason, omask; 229 230 #ifdef TRACE 231 tprintf("TRACE- pjwait()\n"); 232 #endif 233 while (pp->p_pid != pp->p_jobid) 234 pp = pp->p_friends; 235 fp = pp; 236 do { 237 if ((fp->p_flags&(PFOREGND|PRUNNING)) == PRUNNING) 238 printf("BUG: waiting for background job!\n"); 239 } while ((fp = fp->p_friends) != pp); 240 /* 241 * Now keep pausing as long as we are not interrupted (SIGINT), 242 * and the target process, or any of its friends, are running 243 */ 244 fp = pp; 245 omask = sigblock(sigmask(SIGCHLD)); 246 for (;;) { 247 jobflags = 0; 248 do 249 jobflags |= fp->p_flags; 250 while ((fp = (fp->p_friends)) != pp); 251 if ((jobflags & PRUNNING) == 0) 252 break; 253 /* 254 * At this point, csh used to call: 255 * sigpause(sigblock(0) &~ sigmask(SIGCHLD)); 256 * expecting to receive a SIGCHLD signal from the 257 * termination of the child and to invoke the 258 * signal handler, pchild(), as a result. 259 * 260 * However, vfork() now causes a vfork()'d child to 261 * have all of its active signal handlers reset to 262 * SIG_DFL, to forstall parent memory corruption due 263 * to race conditions with signal handling. 264 * 265 * If this instance of csh is itself a child of vfork(), 266 * which can happen when the top-level csh performs a 267 * command substitution inside an i/o redirection, like: 268 * /bin/echo foo >`/bin/echo trash` 269 * then we will never receive SIGCHLD. To accommodate 270 * this, we wait until one of our children terminates 271 * (without actually reaping the child) and call the 272 * SIGCHLD signal handler (pchild()) directly. 273 */ 274 if (csh_wait_noreap() > 0) 275 pchild(SIGCHLD); /* simulate receipt of SIGCHLD */ 276 } 277 (void) sigsetmask(omask); 278 if (tpgrp > 0) /* get tty back */ 279 (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&tpgrp); 280 if ((jobflags&(PSIGNALED|PSTOPPED|PTIME)) || 281 !eq(dcwd->di_name, fp->p_cwd->di_name)) { 282 if (jobflags&PSTOPPED) 283 printf("\n"); 284 (void) pprint(pp, AREASON|SHELLDIR); 285 } 286 if ((jobflags&(PINTERRUPTED|PSTOPPED)) && setintr && 287 (!gointr || !eq(gointr, S_MINUS /* "-" */))) { 288 if ((jobflags & PSTOPPED) == 0) 289 pflush(pp); 290 pintr1(0); 291 /*NOTREACHED*/ 292 } 293 reason = 0; 294 fp = pp; 295 do { 296 if (fp->p_reason) 297 reason = fp->p_flags & (PSIGNALED|PINTERRUPTED) ? 298 fp->p_reason | ABN_TERM : fp->p_reason; 299 } while ((fp = fp->p_friends) != pp); 300 set(S_status /* "status" */, putn(reason)); 301 if (reason && exiterr) 302 exitstat(); 303 pflush(pp); 304 } 305 306 /* 307 * dowait - wait for all processes to finish 308 */ 309 void 310 dowait(void) 311 { 312 struct process *pp; 313 int omask; 314 315 #ifdef TRACE 316 tprintf("TRACE- dowait()\n"); 317 #endif 318 pjobs++; 319 omask = sigblock(sigmask(SIGCHLD)); 320 loop: 321 for (pp = proclist.p_next; pp; pp = pp->p_next) 322 if (pp->p_pid && /* pp->p_pid == pp->p_jobid && */ 323 pp->p_flags&PRUNNING) { 324 sigpause(0); 325 goto loop; 326 } 327 (void) sigsetmask(omask); 328 pjobs = 0; 329 } 330 331 /* 332 * pflushall - flush all jobs from list (e.g. at fork()) 333 */ 334 void 335 pflushall(void) 336 { 337 struct process *pp; 338 339 #ifdef TRACE 340 tprintf("TRACE- pflush()\n"); 341 #endif 342 for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next) 343 if (pp->p_pid) 344 pflush(pp); 345 } 346 347 /* 348 * pflush - flag all process structures in the same job as the 349 * the argument process for deletion. The actual free of the 350 * space is not done here since pflush is called at interrupt level. 351 */ 352 void 353 pflush(struct process *pp) 354 { 355 struct process *np; 356 int index; 357 358 #ifdef TRACE 359 tprintf("TRACE- pflush()\n"); 360 #endif 361 if (pp->p_pid == 0) { 362 printf("BUG: process flushed twice"); 363 return; 364 } 365 while (pp->p_pid != pp->p_jobid) 366 pp = pp->p_friends; 367 pclrcurr(pp); 368 if (pp == pcurrjob) 369 pcurrjob = 0; 370 index = pp->p_index; 371 np = pp; 372 do { 373 np->p_index = np->p_pid = 0; 374 np->p_flags &= ~PNEEDNOTE; 375 } while ((np = np->p_friends) != pp); 376 if (index == pmaxindex) { 377 for (np = proclist.p_next, index = 0; np; np = np->p_next) 378 if (np->p_index > (tchar)index) 379 index = np->p_index; 380 pmaxindex = index; 381 } 382 } 383 384 /* 385 * pclrcurr - make sure the given job is not the current or previous job; 386 * pp MUST be the job leader 387 */ 388 void 389 pclrcurr(struct process *pp) 390 { 391 392 #ifdef TRACE 393 tprintf("TRACE- pclrcurr()\n"); 394 #endif 395 if (pp == pcurrent) 396 if (pprevious != PNULL) { 397 pcurrent = pprevious; 398 pprevious = pgetcurr(pp); 399 } else { 400 pcurrent = pgetcurr(pp); 401 pprevious = pgetcurr(pp); 402 } 403 else if (pp == pprevious) 404 pprevious = pgetcurr(pp); 405 } 406 407 /* +4 here is 1 for '\0', 1 ea for << >& >> */ 408 tchar command[PMAXLEN+4]; 409 int cmdlen; 410 tchar *cmdp; 411 /* 412 * palloc - allocate a process structure and fill it up. 413 * an important assumption is made that the process is running. 414 */ 415 void 416 palloc(int pid, struct command *t) 417 { 418 struct process *pp; 419 int i; 420 421 #ifdef TRACE 422 tprintf("TRACE- palloc()\n"); 423 #endif 424 pp = (struct process *)xcalloc(1, sizeof (struct process)); 425 pp->p_pid = pid; 426 pp->p_flags = t->t_dflg & FAND ? PRUNNING : PRUNNING|PFOREGND; 427 if (t->t_dflg & FTIME) 428 pp->p_flags |= PPTIME; 429 cmdp = command; 430 cmdlen = 0; 431 padd(t); 432 *cmdp++ = 0; 433 if (t->t_dflg & FPOU) { 434 pp->p_flags |= PPOU; 435 if (t->t_dflg & FDIAG) 436 pp->p_flags |= PDIAG; 437 } 438 pp->p_command = savestr(command); 439 if (pcurrjob) { 440 struct process *fp; 441 /* careful here with interrupt level */ 442 pp->p_cwd = 0; 443 pp->p_index = pcurrjob->p_index; 444 pp->p_friends = pcurrjob; 445 pp->p_jobid = pcurrjob->p_pid; 446 for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends) 447 ; 448 fp->p_friends = pp; 449 } else { 450 pcurrjob = pp; 451 pp->p_jobid = pid; 452 pp->p_friends = pp; 453 pp->p_cwd = dcwd; 454 dcwd->di_count++; 455 if (pmaxindex < BIGINDEX) 456 pp->p_index = ++pmaxindex; 457 else { 458 struct process *np; 459 460 for (i = 1; ; i++) { 461 for (np = proclist.p_next; np; np = np->p_next) 462 if (np->p_index == i) 463 goto tryagain; 464 pp->p_index = i; 465 if (i > pmaxindex) 466 pmaxindex = i; 467 break; 468 tryagain:; 469 } 470 } 471 pprevious = pcurrent; 472 pcurrent = pp; 473 } 474 pp->p_next = proclist.p_next; 475 proclist.p_next = pp; 476 (void) gettimeofday(&pp->p_btime, (struct timezone *)0); 477 } 478 479 void 480 padd(struct command *t) 481 { 482 tchar **argp; 483 484 #ifdef TRACE 485 tprintf("TRACE- padd()\n"); 486 #endif 487 if (t == 0) 488 return; 489 switch (t->t_dtyp) { 490 491 case TPAR: 492 pads(S_LBRASP /* "( " */); 493 padd(t->t_dspr); 494 pads(S_SPRBRA /* " )" */); 495 break; 496 497 case TCOM: 498 for (argp = t->t_dcom; *argp; argp++) { 499 pads(*argp); 500 if (argp[1]) 501 pads(S_SP /* " " */); 502 } 503 break; 504 505 case TOR: 506 case TAND: 507 case TFIL: 508 case TLST: 509 padd(t->t_dcar); 510 switch (t->t_dtyp) { 511 case TOR: 512 pads(S_SPBARBARSP /* " || " */); 513 break; 514 case TAND: 515 pads(S_SPANDANDSP /* " && " */); 516 break; 517 case TFIL: 518 pads(S_SPBARSP /* " | " */); 519 break; 520 case TLST: 521 pads(S_SEMICOLONSP /* "; " */); 522 break; 523 } 524 padd(t->t_dcdr); 525 return; 526 } 527 if ((t->t_dflg & FPIN) == 0 && t->t_dlef) { 528 pads((t->t_dflg & FHERE) ? S_SPLESLESSP /* " << " */ : S_SPLESSP /* " < " */); 529 pads(t->t_dlef); 530 } 531 if ((t->t_dflg & FPOU) == 0 && t->t_drit) { 532 pads((t->t_dflg & FCAT) ? S_SPGTRGTRSP /* " >>" */ : S_SPGTR /* " >" */); 533 if (t->t_dflg & FDIAG) 534 pads(S_AND /* "&" */); 535 pads(S_SP /* " " */); 536 pads(t->t_drit); 537 } 538 } 539 540 void 541 pads(tchar *cp) 542 { 543 int i = strlen_(cp); 544 545 #ifdef TRACE 546 tprintf("TRACE- pads()\n"); 547 #endif 548 if (cmdlen >= PMAXLEN) 549 return; 550 if (cmdlen + i >= PMAXLEN) { 551 (void) strcpy_(cmdp, S_SPPPP /* " ..." */); 552 cmdlen = PMAXLEN; 553 cmdp += 4; 554 return; 555 } 556 (void) strcpy_(cmdp, cp); 557 cmdp += i; 558 cmdlen += i; 559 } 560 561 /* 562 * psavejob - temporarily save the current job on a one level stack 563 * so another job can be created. Used for { } in exp6 564 * and `` in globbing. 565 */ 566 void 567 psavejob(void) 568 { 569 570 #ifdef TRACE 571 tprintf("TRACE- psavejob()\n"); 572 #endif 573 pholdjob = pcurrjob; 574 pcurrjob = PNULL; 575 } 576 577 /* 578 * prestjob - opposite of psavejob. This may be missed if we are interrupted 579 * somewhere, but pendjob cleans up anyway. 580 */ 581 void 582 prestjob(void) 583 { 584 585 #ifdef TRACE 586 tprintf("TRACE- prestjob()\n"); 587 #endif 588 pcurrjob = pholdjob; 589 pholdjob = PNULL; 590 } 591 592 /* 593 * pendjob - indicate that a job (set of commands) has been completed 594 * or is about to begin. 595 */ 596 void 597 pendjob(void) 598 { 599 struct process *pp, *tp; 600 601 #ifdef TRACE 602 tprintf("TRACE- pendjob()\n"); 603 #endif 604 if (pcurrjob && (pcurrjob->p_flags&(PFOREGND|PSTOPPED)) == 0) { 605 pp = pcurrjob; 606 while (pp->p_pid != pp->p_jobid) 607 pp = pp->p_friends; 608 printf("[%d]", pp->p_index); 609 tp = pp; 610 do { 611 printf(" %d", pp->p_pid); 612 pp = pp->p_friends; 613 } while (pp != tp); 614 printf("\n"); 615 } 616 pholdjob = pcurrjob = 0; 617 } 618 619 /* 620 * pprint - print a job 621 */ 622 int 623 pprint(struct process *pp, int flag) 624 { 625 int status, reason; 626 struct process *tp; 627 extern char *linp, linbuf[]; 628 int jobflags, pstatus; 629 char *format; 630 631 #ifdef TRACE 632 tprintf("TRACE- pprint()\n"); 633 #endif 634 while (pp->p_pid != pp->p_jobid) 635 pp = pp->p_friends; 636 if (pp == pp->p_friends && (pp->p_flags & PPTIME)) { 637 pp->p_flags &= ~PPTIME; 638 pp->p_flags |= PTIME; 639 } 640 tp = pp; 641 status = reason = -1; 642 jobflags = 0; 643 do { 644 jobflags |= pp->p_flags; 645 pstatus = pp->p_flags & PALLSTATES; 646 if (tp != pp && linp != linbuf && !(flag&FANCY) && 647 (pstatus == status && pp->p_reason == reason || 648 !(flag&REASON))) 649 printf(" "); 650 else { 651 if (tp != pp && linp != linbuf) 652 printf("\n"); 653 if (flag&NUMBER) 654 if (pp == tp) 655 printf("[%d]%s %c ", pp->p_index, 656 pp->p_index < 10 ? " " : "", 657 pp == pcurrent ? '+' : 658 (pp == pprevious ? (tchar) '-' 659 : (tchar) ' ')); 660 else 661 printf(" "); 662 if (flag&FANCY) 663 printf("%5d ", pp->p_pid); 664 if (flag&(REASON|AREASON)) { 665 if (flag&NAME) 666 format = "%-21s"; 667 else 668 format = "%s"; 669 if (pstatus == status) 670 if (pp->p_reason == reason) { 671 printf(format, ""); 672 goto prcomd; 673 } else 674 reason = pp->p_reason; 675 else { 676 status = pstatus; 677 reason = pp->p_reason; 678 } 679 switch (status) { 680 681 case PRUNNING: 682 printf(format, "Running "); 683 break; 684 685 case PINTERRUPTED: 686 case PSTOPPED: 687 case PSIGNALED: 688 if ((flag&(REASON|AREASON)) 689 && reason != SIGINT 690 && reason != SIGPIPE) 691 printf(format, 692 strsignal(pp->p_reason)); 693 break; 694 695 case PNEXITED: 696 case PAEXITED: 697 if (flag & REASON) 698 if (pp->p_reason) 699 printf("Exit %-16d", pp->p_reason); 700 else 701 printf(format, "Done"); 702 break; 703 704 default: 705 printf("BUG: status=%-9o", status); 706 } 707 } 708 } 709 prcomd: 710 if (flag&NAME) { 711 printf("%t", pp->p_command); 712 if (pp->p_flags & PPOU) 713 printf(" |"); 714 if (pp->p_flags & PDIAG) 715 printf("&"); 716 } 717 if (flag&(REASON|AREASON) && pp->p_flags&PDUMPED) 718 printf(" (core dumped)"); 719 if (tp == pp->p_friends) { 720 if (flag&ERSAND) 721 printf(" &"); 722 if (flag&JOBDIR && 723 !eq(tp->p_cwd->di_name, dcwd->di_name)) { 724 printf(" (wd: "); 725 dtildepr(value(S_home /* "home" */), tp->p_cwd->di_name); 726 printf(")"); 727 } 728 } 729 if (pp->p_flags&PPTIME && !(status&(PSTOPPED|PRUNNING))) { 730 if (linp != linbuf) 731 printf("\n\t"); 732 { static struct rusage zru; 733 prusage(&zru, &pp->p_rusage, &pp->p_etime, 734 &pp->p_btime); 735 } 736 } 737 if (tp == pp->p_friends) { 738 if (linp != linbuf) 739 printf("\n"); 740 if (flag&SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) { 741 printf("(wd now: "); 742 dtildepr(value(S_home /* "home" */), dcwd->di_name); 743 printf(")\n"); 744 } 745 } 746 } while ((pp = pp->p_friends) != tp); 747 if (jobflags&PTIME && (jobflags&(PSTOPPED|PRUNNING)) == 0) { 748 if (jobflags & NUMBER) 749 printf(" "); 750 ptprint(tp); 751 } 752 return (jobflags); 753 } 754 755 void 756 ptprint(struct process *tp) 757 { 758 struct timeval tetime, diff; 759 static struct timeval ztime; 760 struct rusage ru; 761 static struct rusage zru; 762 struct process *pp = tp; 763 764 #ifdef TRACE 765 tprintf("TRACE- ptprint()\n"); 766 #endif 767 ru = zru; 768 tetime = ztime; 769 do { 770 ruadd(&ru, &pp->p_rusage); 771 tvsub(&diff, &pp->p_etime, &pp->p_btime); 772 if (timercmp(&diff, &tetime, >)) 773 tetime = diff; 774 } while ((pp = pp->p_friends) != tp); 775 prusage(&zru, &ru, &tetime, &ztime); 776 } 777 778 /* 779 * dojobs - print all jobs 780 */ 781 void 782 dojobs(tchar **v) 783 { 784 struct process *pp; 785 int flag = NUMBER|NAME|REASON; 786 int i; 787 788 #ifdef TRACE 789 tprintf("TRACE- dojobs()\n"); 790 #endif 791 if (chkstop) 792 chkstop = 2; 793 if (*++v) { 794 if (v[1] || !eq(*v, S_DASHl /* "-l" */)) 795 error("Usage: jobs [ -l ]"); 796 flag |= FANCY|JOBDIR; 797 } 798 for (i = 1; i <= pmaxindex; i++) 799 for (pp = proclist.p_next; pp; pp = pp->p_next) 800 if (pp->p_index == i && pp->p_pid == pp->p_jobid) { 801 pp->p_flags &= ~PNEEDNOTE; 802 if (!(pprint(pp, flag) & (PRUNNING|PSTOPPED))) 803 pflush(pp); 804 break; 805 } 806 } 807 808 /* 809 * dofg - builtin - put the job into the foreground 810 */ 811 void 812 dofg(tchar **v) 813 { 814 struct process *pp; 815 816 #ifdef TRACE 817 tprintf("TRACE- dofg()\n"); 818 #endif 819 okpcntl(); 820 ++v; 821 do { 822 pp = pfind(*v); 823 pstart(pp, 1); 824 pjwait(pp); 825 } while (*v && *++v); 826 } 827 828 /* 829 * %... - builtin - put the job into the foreground 830 */ 831 void 832 dofg1(tchar **v) 833 { 834 struct process *pp; 835 836 #ifdef TRACE 837 tprintf("TRACE- untty()\n"); 838 #endif 839 okpcntl(); 840 pp = pfind(v[0]); 841 pstart(pp, 1); 842 pjwait(pp); 843 } 844 845 /* 846 * dobg - builtin - put the job into the background 847 */ 848 void 849 dobg(tchar **v) 850 { 851 struct process *pp; 852 853 #ifdef TRACE 854 tprintf("TRACE- dobg()\n"); 855 #endif 856 okpcntl(); 857 ++v; 858 do { 859 pp = pfind(*v); 860 pstart(pp, 0); 861 } while (*v && *++v); 862 } 863 864 /* 865 * %... & - builtin - put the job into the background 866 */ 867 void 868 dobg1(tchar **v) 869 { 870 struct process *pp; 871 872 #ifdef TRACE 873 tprintf("TRACE- dobg1()\n"); 874 #endif 875 pp = pfind(v[0]); 876 pstart(pp, 0); 877 } 878 879 /* 880 * dostop - builtin - stop the job 881 */ 882 void 883 dostop(tchar **v) 884 { 885 886 #ifdef TRACE 887 tprintf("TRACE- dostop()\n"); 888 #endif 889 pkill(++v, SIGSTOP); 890 } 891 892 /* 893 * dokill - builtin - superset of kill (1) 894 */ 895 void 896 dokill(tchar **v) 897 { 898 int signum; 899 tchar *name; 900 901 #ifdef TRACE 902 tprintf("TRACE- dokill()\n"); 903 #endif 904 v++; 905 if (v[0] && v[0][0] == '-') { 906 if (v[0][1] == 'l') { 907 for (signum = 1; signum <= NSIG-1; signum++) { 908 char sbuf[BUFSIZ]; 909 if (sig2str(signum, sbuf) == 0) 910 printf("%s ", sbuf); 911 if (signum % 8 == 0) 912 Putchar('\n'); 913 } 914 Putchar('\n'); 915 return; 916 } 917 if (digit(v[0][1])) { 918 if (chkalldigit_(v[0]+1) != 0) { 919 setname(v[0]+1); 920 bferr("Unknown signal; kill -l lists signals"); 921 } 922 signum = atoi_(v[0]+1); 923 if (signum < 0 || signum > NSIG) 924 bferr("Bad signal number"); 925 } else { 926 int signo; 927 char sbuf[BUFSIZ]; 928 name = &v[0][1]; 929 tstostr(sbuf, name); 930 if (str2sig(sbuf, &signo) == 0) { 931 signum = signo; 932 goto gotsig; 933 } 934 if (eq(name, S_IOT /* "IOT" */)) { 935 signum = SIGABRT; 936 goto gotsig; 937 } 938 setname(name); 939 bferr("Unknown signal; kill -l lists signals"); 940 } 941 gotsig: 942 v++; 943 } else 944 signum = SIGTERM; 945 pkill(v, signum); 946 } 947 948 void 949 pkill(tchar **v, int signum) 950 { 951 struct process *pp, *np; 952 int jobflags = 0; 953 int omask, pid, err = 0; 954 tchar *cp; 955 956 #ifdef TRACE 957 tprintf("TRACE- pkill()\n"); 958 #endif 959 omask = sigmask(SIGCHLD); 960 if (setintr) 961 omask |= sigmask(SIGINT); 962 omask = sigblock(omask) & ~omask; 963 while (*v) { 964 cp = globone(*v); 965 if (*cp == '%') { 966 np = pp = pfind(cp); 967 do 968 jobflags |= np->p_flags; 969 while ((np = np->p_friends) != pp); 970 switch (signum) { 971 972 case SIGSTOP: 973 case SIGTSTP: 974 case SIGTTIN: 975 case SIGTTOU: 976 if ((jobflags & PRUNNING) == 0) { 977 /* %s -> %t */ 978 printf("%t: Already stopped\n", cp); 979 err++; 980 goto cont; 981 } 982 } 983 if (killpg(pp->p_jobid, signum) < 0) { 984 /* %s -> %t */ 985 printf("%t: ", cp); 986 printf("%s\n", strerror(errno)); 987 err++; 988 } 989 if (signum == SIGTERM || signum == SIGHUP) 990 (void) killpg(pp->p_jobid, SIGCONT); 991 } else if (!(digit(*cp) || *cp == '-')) 992 bferr("Arguments should be jobs or process id's"); 993 else { 994 pid = atoi_(cp); 995 if (kill(pid, signum) < 0) { 996 printf("%d: ", pid); 997 printf("%s\n", strerror(errno)); 998 err++; 999 goto cont; 1000 } 1001 if (signum == SIGTERM || signum == SIGHUP) 1002 (void) kill(pid, SIGCONT); 1003 } 1004 cont: 1005 xfree(cp); 1006 v++; 1007 } 1008 (void) sigsetmask(omask); 1009 if (err) 1010 error(NULL); 1011 } 1012 1013 /* 1014 * pstart - start the job in foreground/background 1015 */ 1016 void 1017 pstart(struct process *pp, int foregnd) 1018 { 1019 struct process *np; 1020 int omask, jobflags = 0; 1021 1022 #ifdef TRACE 1023 tprintf("TRACE- pstart()\n"); 1024 #endif 1025 omask = sigblock(sigmask(SIGCHLD)); 1026 np = pp; 1027 do { 1028 jobflags |= np->p_flags; 1029 if (np->p_flags&(PRUNNING|PSTOPPED)) { 1030 np->p_flags |= PRUNNING; 1031 np->p_flags &= ~PSTOPPED; 1032 if (foregnd) 1033 np->p_flags |= PFOREGND; 1034 else 1035 np->p_flags &= ~PFOREGND; 1036 } 1037 } while ((np = np->p_friends) != pp); 1038 1039 if (foregnd) 1040 pclrcurr(pp); 1041 else 1042 { 1043 if (pprevious && (pprevious->p_flags & PSTOPPED)) 1044 { 1045 pcurrent = pprevious; 1046 pprevious = pgetcurr(PNULL); 1047 } 1048 else 1049 { 1050 pcurrent = pgetcurr(pp); 1051 if (!pcurrent || (pcurrent->p_flags & PRUNNING)) 1052 pcurrent = pp; 1053 else 1054 pprevious = pp; 1055 } 1056 } 1057 (void) pprint(pp, foregnd ? NAME|JOBDIR : NUMBER|NAME|AMPERSAND); 1058 if (foregnd) 1059 (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&pp->p_jobid); 1060 if (jobflags&PSTOPPED) 1061 (void) killpg(pp->p_jobid, SIGCONT); 1062 (void) sigsetmask(omask); 1063 } 1064 1065 void 1066 panystop(int neednl) 1067 { 1068 struct process *pp; 1069 1070 #ifdef TRACE 1071 tprintf("TRACE- panystop()\n"); 1072 #endif 1073 chkstop = 2; 1074 for (pp = proclist.p_next; pp; pp = pp->p_next) 1075 if (pp->p_flags & PSTOPPED) 1076 error("\nThere are stopped jobs" + 1 - neednl); 1077 } 1078 1079 struct process * 1080 pfind(tchar *cp) 1081 { 1082 struct process *pp, *np; 1083 1084 #ifdef TRACE 1085 tprintf("TRACE- pfind()\n"); 1086 #endif 1087 if (cp == 0 || cp[1] == 0 || eq(cp, S_PARCENTPARCENT /* "%%" */) || 1088 eq(cp, S_PARCENTPLUS /* "%+" */)) { 1089 if (pcurrent == PNULL) 1090 if ((pcurrent = pgetcurr(PNULL)) == PNULL) 1091 bferr("No current job"); 1092 return (pcurrent); 1093 } 1094 if (eq(cp, S_PARCENTMINUS /* "%-" */) || 1095 eq(cp, S_PARCENTSHARP /* "%#" */)) { 1096 if (pprevious == PNULL) 1097 bferr("No previous job"); 1098 return (pprevious); 1099 } 1100 if (digit(cp[1])) { 1101 int index = atoi_(cp+1); 1102 for (pp = proclist.p_next; pp; pp = pp->p_next) 1103 if (pp->p_index == index && pp->p_pid == pp->p_jobid) 1104 return (pp); 1105 bferr("No such job"); 1106 } 1107 np = PNULL; 1108 for (pp = proclist.p_next; pp; pp = pp->p_next) 1109 if (pp->p_pid == pp->p_jobid) { 1110 if (cp[1] == '?') { 1111 tchar *dp; 1112 for (dp = pp->p_command; *dp; dp++) { 1113 if (*dp != cp[2]) 1114 continue; 1115 if (prefix(cp+2, dp)) 1116 goto match; 1117 } 1118 } else if (prefix(cp+1, pp->p_command)) { 1119 match: 1120 if (np) 1121 bferr("Ambiguous"); 1122 np = pp; 1123 } 1124 } 1125 if (np) 1126 return (np); 1127 if (cp[1] == '?') 1128 bferr("No job matches pattern"); 1129 else 1130 bferr("No such job"); 1131 /*NOTREACHED*/ 1132 } 1133 1134 /* 1135 * pgetcurr - find most recent job that is not pp, preferably stopped 1136 */ 1137 struct process * 1138 pgetcurr(struct process *pp) 1139 { 1140 struct process *np; 1141 struct process *xp = PNULL; 1142 1143 #ifdef TRACE 1144 tprintf("TRACE- pgetcurr()\n"); 1145 #endif 1146 for (np = proclist.p_next; np; np = np->p_next) 1147 if (np != pcurrent && np != pp && np->p_pid && 1148 np->p_pid == np->p_jobid) { 1149 if (np->p_flags & PSTOPPED) 1150 return (np); 1151 if (xp == PNULL) 1152 xp = np; 1153 } 1154 return (xp); 1155 } 1156 1157 /* 1158 * donotify - flag the job so as to report termination asynchronously 1159 */ 1160 void 1161 donotify(tchar **v) 1162 { 1163 struct process *pp; 1164 1165 #ifdef TRACE 1166 tprintf("TRACE- donotify()\n"); 1167 #endif 1168 pp = pfind(*++v); 1169 pp->p_flags |= PNOTIFY; 1170 } 1171 1172 /* 1173 * Do the fork and whatever should be done in the child side that 1174 * should not be done if we are not forking at all (like for simple builtin's) 1175 * Also do everything that needs any signals fiddled with in the parent side 1176 * 1177 * Wanttty tells whether process and/or tty pgrps are to be manipulated: 1178 * -1: leave tty alone; inherit pgrp from parent 1179 * 0: already have tty; manipulate process pgrps only 1180 * 1: want to claim tty; manipulate process and tty pgrps 1181 * It is usually just the value of tpgrp. 1182 * 1183 * argument: 1184 * t: command we are forking for 1185 */ 1186 int 1187 pfork(struct command *t, int wanttty) 1188 { 1189 int pid; 1190 bool ignint = 0; 1191 int pgrp, omask; 1192 int child_pid; 1193 1194 #ifdef TRACE 1195 tprintf("TRACE- pfork()\n"); 1196 #endif 1197 /* 1198 * A child will be uninterruptible only under very special 1199 * conditions. Remember that the semantics of '&' is 1200 * implemented by disconnecting the process from the tty so 1201 * signals do not need to ignored just for '&'. 1202 * Thus signals are set to default action for children unless: 1203 * we have had an "onintr -" (then specifically ignored) 1204 * we are not playing with signals (inherit action) 1205 */ 1206 if (setintr) 1207 ignint = (tpgrp == -1 && (t->t_dflg&FINT)) 1208 || (gointr && eq(gointr, S_MINUS /* "-" */)); 1209 /* 1210 * Hold SIGCHLD until we have the process installed in our table. 1211 */ 1212 omask = sigblock(sigmask(SIGCHLD)); 1213 while ((pid = fork()) < 0) 1214 if (setintr == 0) 1215 sleep(FORKSLEEP); 1216 else { 1217 (void) sigsetmask(omask); 1218 error("Fork failed"); 1219 } 1220 1221 /* 1222 * setup the process group 1223 */ 1224 if (pid == 0) 1225 child_pid = getpid(); 1226 else 1227 child_pid = pid; 1228 pgrp = pcurrjob ? pcurrjob->p_jobid : child_pid; 1229 1230 if (pid == 0) { 1231 int sigttou; 1232 settimes(); 1233 pflushall(); 1234 pcurrjob = PNULL; 1235 child++; 1236 if (setintr) { 1237 setintr = 0; /* until I think otherwise */ 1238 /* 1239 * Children just get blown away on SIGINT, SIGQUIT 1240 * unless "onintr -" seen. 1241 */ 1242 (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL); 1243 (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL); 1244 if (wanttty >= 0) { 1245 /* make stoppable */ 1246 (void) signal(SIGTSTP, SIG_DFL); 1247 (void) signal(SIGTTIN, SIG_DFL); 1248 (void) signal(SIGTTOU, SIG_DFL); 1249 } 1250 (void) signal(SIGTERM, parterm); 1251 } else if (tpgrp == -1 && (t->t_dflg&FINT)) { 1252 (void) signal(SIGINT, SIG_IGN); 1253 (void) signal(SIGQUIT, SIG_IGN); 1254 } 1255 if (wanttty >= 0 && tpgrp >= 0) 1256 (void) setpgid(0, pgrp); 1257 if (wanttty > 0) { 1258 sigttou = sigblock(sigmask(SIGTTOU) | 1259 sigmask(SIGTTIN) | 1260 sigmask(SIGTSTP)); 1261 (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&pgrp); 1262 sigsetmask(sigttou); 1263 } 1264 if (tpgrp > 0) 1265 tpgrp = 0; /* gave tty away */ 1266 /* 1267 * Nohup and nice apply only to TCOM's but it would be 1268 * nice (?!?) if you could say "nohup (foo;bar)" 1269 * Then the parser would have to know about nice/nohup/time 1270 */ 1271 if (t->t_dflg & FNOHUP) 1272 (void) signal(SIGHUP, SIG_IGN); 1273 if (t->t_dflg & FNICE) 1274 (void) setpriority(PRIO_PROCESS, 0, t->t_nice); 1275 } else { 1276 if (wanttty >= 0 && tpgrp >= 0) 1277 setpgid(pid, pgrp); 1278 palloc(pid, t); 1279 (void) sigsetmask(omask); 1280 } 1281 1282 return (pid); 1283 } 1284 1285 void 1286 okpcntl(void) 1287 { 1288 #ifdef TRACE 1289 tprintf("TRACE- okpcntl()\n"); 1290 #endif 1291 1292 if (tpgrp == -1) 1293 error("No job control in this shell"); 1294 if (tpgrp == 0) 1295 error("No job control in subshells"); 1296 } 1297 1298 void 1299 hupforegnd(void) 1300 { 1301 struct process *pp; 1302 int omask; 1303 1304 omask = sigblock(sigmask(SIGCHLD)); 1305 for (pp = (&proclist)->p_next; pp != PNULL; pp = pp->p_next) 1306 if (pp->p_pid > 0) { 1307 if (pp->p_flags & PFOREGND) 1308 (void) kill(pp->p_pid, SIGHUP); 1309 } 1310 (void) sigsetmask(omask); 1311 } 1312