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