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