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