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