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