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