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