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