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