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