jobs.c revision 97659
1/*- 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Kenneth Almquist. 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 39static char sccsid[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95"; 40#endif 41static const char rcsid[] = 42 "$FreeBSD: head/bin/sh/jobs.c 97659 2002-05-31 12:31:23Z tjr $"; 43#endif /* not lint */ 44 45#include <fcntl.h> 46#include <signal.h> 47#include <errno.h> 48#include <unistd.h> 49#include <stdlib.h> 50#include <sys/param.h> 51#ifdef BSD 52#include <sys/wait.h> 53#include <sys/time.h> 54#include <sys/resource.h> 55#include <paths.h> 56#endif 57#include <sys/ioctl.h> 58 59#include "shell.h" 60#if JOBS 61#if OLD_TTY_DRIVER 62#include "sgtty.h" 63#else 64#include <termios.h> 65#endif 66#undef CEOF /* syntax.h redefines this */ 67#endif 68#include "redir.h" 69#include "show.h" 70#include "main.h" 71#include "parser.h" 72#include "nodes.h" 73#include "jobs.h" 74#include "options.h" 75#include "trap.h" 76#include "syntax.h" 77#include "input.h" 78#include "output.h" 79#include "memalloc.h" 80#include "error.h" 81#include "mystring.h" 82 83 84struct job *jobtab; /* array of jobs */ 85int njobs; /* size of array */ 86MKINIT pid_t backgndpid = -1; /* pid of last background process */ 87#if JOBS 88struct job *jobmru; /* most recently used job list */ 89int initialpgrp; /* pgrp of shell on invocation */ 90#endif 91int in_waitcmd = 0; /* are we in waitcmd()? */ 92int in_dowait = 0; /* are we in dowait()? */ 93volatile sig_atomic_t breakwaitcmd = 0; /* should wait be terminated? */ 94 95#if JOBS 96STATIC void restartjob(struct job *); 97#endif 98STATIC void freejob(struct job *); 99STATIC struct job *getjob(char *); 100STATIC int dowait(int, struct job *); 101#if SYSV 102STATIC int onsigchild(void); 103#endif 104STATIC int waitproc(int, int *); 105STATIC void cmdtxt(union node *); 106STATIC void cmdputs(char *); 107#if JOBS 108STATIC void setcurjob(struct job *); 109STATIC void deljob(struct job *); 110STATIC struct job *getcurjob(struct job *); 111#endif 112 113 114/* 115 * Turn job control on and off. 116 * 117 * Note: This code assumes that the third arg to ioctl is a character 118 * pointer, which is true on Berkeley systems but not System V. Since 119 * System V doesn't have job control yet, this isn't a problem now. 120 */ 121 122MKINIT int jobctl; 123 124#if JOBS 125void 126setjobctl(int on) 127{ 128#ifdef OLD_TTY_DRIVER 129 int ldisc; 130#endif 131 132 if (on == jobctl || rootshell == 0) 133 return; 134 if (on) { 135 do { /* while we are in the background */ 136#ifdef OLD_TTY_DRIVER 137 if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) { 138#else 139 initialpgrp = tcgetpgrp(2); 140 if (initialpgrp < 0) { 141#endif 142 out2str("sh: can't access tty; job control turned off\n"); 143 mflag = 0; 144 return; 145 } 146 if (initialpgrp == -1) 147 initialpgrp = getpgrp(); 148 else if (initialpgrp != getpgrp()) { 149 killpg(initialpgrp, SIGTTIN); 150 continue; 151 } 152 } while (0); 153#ifdef OLD_TTY_DRIVER 154 if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) { 155 out2str("sh: need new tty driver to run job control; job control turned off\n"); 156 mflag = 0; 157 return; 158 } 159#endif 160 setsignal(SIGTSTP); 161 setsignal(SIGTTOU); 162 setsignal(SIGTTIN); 163 setpgid(0, rootpid); 164#ifdef OLD_TTY_DRIVER 165 ioctl(2, TIOCSPGRP, (char *)&rootpid); 166#else 167 tcsetpgrp(2, rootpid); 168#endif 169 } else { /* turning job control off */ 170 setpgid(0, initialpgrp); 171#ifdef OLD_TTY_DRIVER 172 ioctl(2, TIOCSPGRP, (char *)&initialpgrp); 173#else 174 tcsetpgrp(2, initialpgrp); 175#endif 176 setsignal(SIGTSTP); 177 setsignal(SIGTTOU); 178 setsignal(SIGTTIN); 179 } 180 jobctl = on; 181} 182#endif 183 184 185#ifdef mkinit 186INCLUDE <sys/types.h> 187INCLUDE <stdlib.h> 188 189SHELLPROC { 190 backgndpid = -1; 191#if JOBS 192 jobctl = 0; 193#endif 194} 195 196#endif 197 198 199 200#if JOBS 201int 202fgcmd(int argc __unused, char **argv) 203{ 204 struct job *jp; 205 int pgrp; 206 int status; 207 208 jp = getjob(argv[1]); 209 if (jp->jobctl == 0) 210 error("job not created under job control"); 211 out1str(jp->ps[0].cmd); 212 out1c('\n'); 213 flushout(&output); 214 pgrp = jp->ps[0].pid; 215#ifdef OLD_TTY_DRIVER 216 ioctl(2, TIOCSPGRP, (char *)&pgrp); 217#else 218 tcsetpgrp(2, pgrp); 219#endif 220 restartjob(jp); 221 INTOFF; 222 status = waitforjob(jp, (int *)NULL); 223 INTON; 224 return status; 225} 226 227 228int 229bgcmd(int argc, char **argv) 230{ 231 char s[64]; 232 struct job *jp; 233 234 do { 235 jp = getjob(*++argv); 236 if (jp->jobctl == 0) 237 error("job not created under job control"); 238 if (jp->state == JOBDONE) 239 continue; 240 restartjob(jp); 241 fmtstr(s, 64, "[%d] ", jp - jobtab + 1); 242 out1str(s); 243 out1str(jp->ps[0].cmd); 244 out1c('\n'); 245 } while (--argc > 1); 246 return 0; 247} 248 249 250STATIC void 251restartjob(struct job *jp) 252{ 253 struct procstat *ps; 254 int i; 255 256 if (jp->state == JOBDONE) 257 return; 258 INTOFF; 259 killpg(jp->ps[0].pid, SIGCONT); 260 for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) { 261 if (WIFSTOPPED(ps->status)) { 262 ps->status = -1; 263 jp->state = 0; 264 } 265 } 266 INTON; 267} 268#endif 269 270 271int 272jobscmd(int argc __unused, char **argv __unused) 273{ 274 showjobs(0); 275 return 0; 276} 277 278 279/* 280 * Print a list of jobs. If "change" is nonzero, only print jobs whose 281 * statuses have changed since the last call to showjobs. 282 * 283 * If the shell is interrupted in the process of creating a job, the 284 * result may be a job structure containing zero processes. Such structures 285 * will be freed here. 286 */ 287 288void 289showjobs(int change) 290{ 291 int jobno; 292 int procno; 293 int i; 294 struct job *jp; 295 struct procstat *ps; 296 int col; 297 char s[64]; 298 299 TRACE(("showjobs(%d) called\n", change)); 300 while (dowait(0, (struct job *)NULL) > 0); 301 for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) { 302 if (! jp->used) 303 continue; 304 if (jp->nprocs == 0) { 305 freejob(jp); 306 continue; 307 } 308 if (change && ! jp->changed) 309 continue; 310 procno = jp->nprocs; 311 for (ps = jp->ps ; ; ps++) { /* for each process */ 312 if (ps == jp->ps) 313 fmtstr(s, 64, "[%d] %d ", jobno, ps->pid); 314 else 315 fmtstr(s, 64, " %d ", ps->pid); 316 out1str(s); 317 col = strlen(s); 318 s[0] = '\0'; 319 if (ps->status == -1) { 320 /* don't print anything */ 321 } else if (WIFEXITED(ps->status)) { 322 fmtstr(s, 64, "Exit %d", WEXITSTATUS(ps->status)); 323 } else { 324#if JOBS 325 if (WIFSTOPPED(ps->status)) 326 i = WSTOPSIG(ps->status); 327 else 328#endif 329 i = WTERMSIG(ps->status); 330 if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F]) 331 scopy(sys_siglist[i & 0x7F], s); 332 else 333 fmtstr(s, 64, "Signal %d", i & 0x7F); 334 if (WCOREDUMP(ps->status)) 335 strcat(s, " (core dumped)"); 336 } 337 out1str(s); 338 col += strlen(s); 339 do { 340 out1c(' '); 341 col++; 342 } while (col < 30); 343 out1str(ps->cmd); 344 out1c('\n'); 345 if (--procno <= 0) 346 break; 347 } 348 jp->changed = 0; 349 if (jp->state == JOBDONE) { 350 freejob(jp); 351 } 352 } 353} 354 355 356/* 357 * Mark a job structure as unused. 358 */ 359 360STATIC void 361freejob(struct job *jp) 362{ 363 struct procstat *ps; 364 int i; 365 366 INTOFF; 367 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) { 368 if (ps->cmd != nullstr) 369 ckfree(ps->cmd); 370 } 371 if (jp->ps != &jp->ps0) 372 ckfree(jp->ps); 373 jp->used = 0; 374#if JOBS 375 deljob(jp); 376#endif 377 INTON; 378} 379 380 381 382int 383waitcmd(int argc, char **argv) 384{ 385 struct job *job; 386 int status, retval; 387 struct job *jp; 388 389 if (argc > 1) { 390 job = getjob(argv[1]); 391 } else { 392 job = NULL; 393 } 394 395 /* 396 * Loop until a process is terminated or stopped, or a SIGINT is 397 * received. 398 */ 399 400 in_waitcmd++; 401 do { 402 if (job != NULL) { 403 if (job->state) { 404 status = job->ps[job->nprocs - 1].status; 405 if (WIFEXITED(status)) 406 retval = WEXITSTATUS(status); 407#if JOBS 408 else if (WIFSTOPPED(status)) 409 retval = WSTOPSIG(status) + 128; 410#endif 411 else 412 retval = WTERMSIG(status) + 128; 413 if (! iflag) 414 freejob(job); 415 in_waitcmd--; 416 return retval; 417 } 418 } else { 419 for (jp = jobtab ; ; jp++) { 420 if (jp >= jobtab + njobs) { /* no running procs */ 421 in_waitcmd--; 422 return 0; 423 } 424 if (jp->used && jp->state == 0) 425 break; 426 } 427 } 428 } while (dowait(1, (struct job *)NULL) != -1); 429 in_waitcmd--; 430 431 return 0; 432} 433 434 435 436int 437jobidcmd(int argc __unused, char **argv) 438{ 439 struct job *jp; 440 int i; 441 442 jp = getjob(argv[1]); 443 for (i = 0 ; i < jp->nprocs ; ) { 444 out1fmt("%d", jp->ps[i].pid); 445 out1c(++i < jp->nprocs? ' ' : '\n'); 446 } 447 return 0; 448} 449 450 451 452/* 453 * Convert a job name to a job structure. 454 */ 455 456STATIC struct job * 457getjob(char *name) 458{ 459 int jobno; 460 struct job *jp; 461 int pid; 462 int i; 463 464 if (name == NULL) { 465#if JOBS 466currentjob: if ((jp = getcurjob(NULL)) == NULL) 467 error("No current job"); 468 return (jp); 469#else 470 error("No current job"); 471#endif 472 } else if (name[0] == '%') { 473 if (is_digit(name[1])) { 474 jobno = number(name + 1); 475 if (jobno > 0 && jobno <= njobs 476 && jobtab[jobno - 1].used != 0) 477 return &jobtab[jobno - 1]; 478#if JOBS 479 } else if (name[1] == '%' && name[2] == '\0') { 480 goto currentjob; 481#endif 482 } else { 483 struct job *found = NULL; 484 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { 485 if (jp->used && jp->nprocs > 0 486 && prefix(name + 1, jp->ps[0].cmd)) { 487 if (found) 488 error("%s: ambiguous", name); 489 found = jp; 490 } 491 } 492 if (found) 493 return found; 494 } 495 } else if (is_number(name)) { 496 pid = number(name); 497 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { 498 if (jp->used && jp->nprocs > 0 499 && jp->ps[jp->nprocs - 1].pid == pid) 500 return jp; 501 } 502 } 503 error("No such job: %s", name); 504 /*NOTREACHED*/ 505 return NULL; 506} 507 508 509 510/* 511 * Return a new job structure, 512 */ 513 514struct job * 515makejob(union node *node __unused, int nprocs) 516{ 517 int i; 518 struct job *jp; 519 520 for (i = njobs, jp = jobtab ; ; jp++) { 521 if (--i < 0) { 522 INTOFF; 523 if (njobs == 0) { 524 jobtab = ckmalloc(4 * sizeof jobtab[0]); 525 jobmru = NULL; 526 } else { 527 jp = ckmalloc((njobs + 4) * sizeof jobtab[0]); 528 memcpy(jp, jobtab, njobs * sizeof jp[0]); 529#if JOBS 530 /* Relocate `next' pointers and list head */ 531 jobmru = &jp[jobmru - jobtab]; 532 for (i = 0; i < njobs; i++) 533 if (jp[i].next != NULL) 534 jp[i].next = &jp[jp[i].next - 535 jobtab]; 536#endif 537 /* Relocate `ps' pointers */ 538 for (i = 0; i < njobs; i++) 539 if (jp[i].ps == &jobtab[i].ps0) 540 jp[i].ps = &jp[i].ps0; 541 ckfree(jobtab); 542 jobtab = jp; 543 } 544 jp = jobtab + njobs; 545 for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0); 546 INTON; 547 break; 548 } 549 if (jp->used == 0) 550 break; 551 } 552 INTOFF; 553 jp->state = 0; 554 jp->used = 1; 555 jp->changed = 0; 556 jp->nprocs = 0; 557#if JOBS 558 jp->jobctl = jobctl; 559 jp->next = NULL; 560#endif 561 if (nprocs > 1) { 562 jp->ps = ckmalloc(nprocs * sizeof (struct procstat)); 563 } else { 564 jp->ps = &jp->ps0; 565 } 566 INTON; 567 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs, 568 jp - jobtab + 1)); 569 return jp; 570} 571 572#if JOBS 573STATIC void 574setcurjob(struct job *cj) 575{ 576 struct job *jp, *prev; 577 578 for (prev = NULL, jp = jobmru; jp != NULL; prev = jp, jp = jp->next) { 579 if (jp == cj) { 580 if (prev != NULL) 581 prev->next = jp->next; 582 else 583 jobmru = jp->next; 584 jp->next = jobmru; 585 jobmru = cj; 586 return; 587 } 588 } 589 cj->next = jobmru; 590 jobmru = cj; 591} 592 593STATIC void 594deljob(struct job *j) 595{ 596 struct job *jp, *prev; 597 598 for (prev = NULL, jp = jobmru; jp != NULL; prev = jp, jp = jp->next) { 599 if (jp == j) { 600 if (prev != NULL) 601 prev->next = jp->next; 602 else 603 jobmru = jp->next; 604 return; 605 } 606 } 607} 608 609/* 610 * Return the most recently used job that isn't `nj', and preferably one 611 * that is stopped. 612 */ 613STATIC struct job * 614getcurjob(struct job *nj) 615{ 616 struct job *jp; 617 618 /* Try to find a stopped one.. */ 619 for (jp = jobmru; jp != NULL; jp = jp->next) 620 if (jp->used && jp != nj && jp->state == JOBSTOPPED) 621 return (jp); 622 /* Otherwise the most recently used job that isn't `nj' */ 623 for (jp = jobmru; jp != NULL; jp = jp->next) 624 if (jp->used && jp != nj) 625 return (jp); 626 627 return (NULL); 628} 629 630#endif 631 632/* 633 * Fork of a subshell. If we are doing job control, give the subshell its 634 * own process group. Jp is a job structure that the job is to be added to. 635 * N is the command that will be evaluated by the child. Both jp and n may 636 * be NULL. The mode parameter can be one of the following: 637 * FORK_FG - Fork off a foreground process. 638 * FORK_BG - Fork off a background process. 639 * FORK_NOJOB - Like FORK_FG, but don't give the process its own 640 * process group even if job control is on. 641 * 642 * When job control is turned off, background processes have their standard 643 * input redirected to /dev/null (except for the second and later processes 644 * in a pipeline). 645 */ 646 647int 648forkshell(struct job *jp, union node *n, int mode) 649{ 650 int pid; 651 int pgrp; 652 653 TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long)n, 654 mode)); 655 INTOFF; 656 pid = fork(); 657 if (pid == -1) { 658 TRACE(("Fork failed, errno=%d\n", errno)); 659 INTON; 660 error("Cannot fork: %s", strerror(errno)); 661 } 662 if (pid == 0) { 663 struct job *p; 664 int wasroot; 665 int i; 666 667 TRACE(("Child shell %d\n", getpid())); 668 wasroot = rootshell; 669 rootshell = 0; 670 for (i = njobs, p = jobtab ; --i >= 0 ; p++) 671 if (p->used) 672 freejob(p); 673 closescript(); 674 INTON; 675 clear_traps(); 676#if JOBS 677 jobctl = 0; /* do job control only in root shell */ 678 if (wasroot && mode != FORK_NOJOB && mflag) { 679 if (jp == NULL || jp->nprocs == 0) 680 pgrp = getpid(); 681 else 682 pgrp = jp->ps[0].pid; 683 if (setpgid(0, pgrp) == 0 && mode == FORK_FG) { 684 /*** this causes superfluous TIOCSPGRPS ***/ 685#ifdef OLD_TTY_DRIVER 686 if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0) 687 error("TIOCSPGRP failed, errno=%d", errno); 688#else 689 if (tcsetpgrp(2, pgrp) < 0) 690 error("tcsetpgrp failed, errno=%d", errno); 691#endif 692 } 693 setsignal(SIGTSTP); 694 setsignal(SIGTTOU); 695 } else if (mode == FORK_BG) { 696 ignoresig(SIGINT); 697 ignoresig(SIGQUIT); 698 if ((jp == NULL || jp->nprocs == 0) && 699 ! fd0_redirected_p ()) { 700 close(0); 701 if (open(_PATH_DEVNULL, O_RDONLY) != 0) 702 error("Can't open %s: %s", 703 _PATH_DEVNULL, strerror(errno)); 704 } 705 } 706#else 707 if (mode == FORK_BG) { 708 ignoresig(SIGINT); 709 ignoresig(SIGQUIT); 710 if ((jp == NULL || jp->nprocs == 0) && 711 ! fd0_redirected_p ()) { 712 close(0); 713 if (open(_PATH_DEVNULL, O_RDONLY) != 0) 714 error("Can't open %s: %s", 715 _PATH_DEVNULL, strerror(errno)); 716 } 717 } 718#endif 719 if (wasroot && iflag) { 720 setsignal(SIGINT); 721 setsignal(SIGQUIT); 722 setsignal(SIGTERM); 723 } 724 return pid; 725 } 726 if (rootshell && mode != FORK_NOJOB && mflag) { 727 if (jp == NULL || jp->nprocs == 0) 728 pgrp = pid; 729 else 730 pgrp = jp->ps[0].pid; 731 setpgid(pid, pgrp); 732 } 733 if (mode == FORK_BG) 734 backgndpid = pid; /* set $! */ 735 if (jp) { 736 struct procstat *ps = &jp->ps[jp->nprocs++]; 737 ps->pid = pid; 738 ps->status = -1; 739 ps->cmd = nullstr; 740 if (iflag && rootshell && n) 741 ps->cmd = commandtext(n); 742#if JOBS 743 setcurjob(jp); 744#endif 745 } 746 INTON; 747 TRACE(("In parent shell: child = %d\n", pid)); 748 return pid; 749} 750 751 752 753/* 754 * Wait for job to finish. 755 * 756 * Under job control we have the problem that while a child process is 757 * running interrupts generated by the user are sent to the child but not 758 * to the shell. This means that an infinite loop started by an inter- 759 * active user may be hard to kill. With job control turned off, an 760 * interactive user may place an interactive program inside a loop. If 761 * the interactive program catches interrupts, the user doesn't want 762 * these interrupts to also abort the loop. The approach we take here 763 * is to have the shell ignore interrupt signals while waiting for a 764 * foreground process to terminate, and then send itself an interrupt 765 * signal if the child process was terminated by an interrupt signal. 766 * Unfortunately, some programs want to do a bit of cleanup and then 767 * exit on interrupt; unless these processes terminate themselves by 768 * sending a signal to themselves (instead of calling exit) they will 769 * confuse this approach. 770 */ 771 772int 773waitforjob(struct job *jp, int *origstatus) 774{ 775#if JOBS 776 int mypgrp = getpgrp(); 777#endif 778 int status; 779 int st; 780 781 INTOFF; 782 TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1)); 783 while (jp->state == 0) 784 if (dowait(1, jp) == -1) 785 dotrap(); 786#if JOBS 787 if (jp->jobctl) { 788#ifdef OLD_TTY_DRIVER 789 if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0) 790 error("TIOCSPGRP failed, errno=%d\n", errno); 791#else 792 if (tcsetpgrp(2, mypgrp) < 0) 793 error("tcsetpgrp failed, errno=%d\n", errno); 794#endif 795 } 796 if (jp->state == JOBSTOPPED) 797 setcurjob(jp); 798#endif 799 status = jp->ps[jp->nprocs - 1].status; 800 if (origstatus != NULL) 801 *origstatus = status; 802 /* convert to 8 bits */ 803 if (WIFEXITED(status)) 804 st = WEXITSTATUS(status); 805#if JOBS 806 else if (WIFSTOPPED(status)) 807 st = WSTOPSIG(status) + 128; 808#endif 809 else 810 st = WTERMSIG(status) + 128; 811 if (! JOBS || jp->state == JOBDONE) 812 freejob(jp); 813 if (int_pending()) { 814 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT) 815 kill(getpid(), SIGINT); 816 else 817 CLEAR_PENDING_INT; 818 } 819 INTON; 820 return st; 821} 822 823 824 825/* 826 * Wait for a process to terminate. 827 */ 828 829STATIC int 830dowait(int block, struct job *job) 831{ 832 int pid; 833 int status; 834 struct procstat *sp; 835 struct job *jp; 836 struct job *thisjob; 837 int done; 838 int stopped; 839 int core; 840 int sig; 841 842 in_dowait++; 843 TRACE(("dowait(%d) called\n", block)); 844 do { 845 pid = waitproc(block, &status); 846 TRACE(("wait returns %d, status=%d\n", pid, status)); 847 } while ((pid == -1 && errno == EINTR && breakwaitcmd == 0) || 848 (WIFSTOPPED(status) && !iflag)); 849 in_dowait--; 850 if (breakwaitcmd != 0) { 851 breakwaitcmd = 0; 852 return -1; 853 } 854 if (pid <= 0) 855 return pid; 856 INTOFF; 857 thisjob = NULL; 858 for (jp = jobtab ; jp < jobtab + njobs ; jp++) { 859 if (jp->used) { 860 done = 1; 861 stopped = 1; 862 for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) { 863 if (sp->pid == -1) 864 continue; 865 if (sp->pid == pid) { 866 TRACE(("Changing status of proc %d from 0x%x to 0x%x\n", 867 pid, sp->status, status)); 868 sp->status = status; 869 thisjob = jp; 870 } 871 if (sp->status == -1) 872 stopped = 0; 873 else if (WIFSTOPPED(sp->status)) 874 done = 0; 875 } 876 if (stopped) { /* stopped or done */ 877 int state = done? JOBDONE : JOBSTOPPED; 878 if (jp->state != state) { 879 TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state)); 880 jp->state = state; 881#if JOBS 882 if (done) 883 deljob(jp); 884#endif 885 } 886 } 887 } 888 } 889 INTON; 890 if (! rootshell || ! iflag || (job && thisjob == job)) { 891 core = WCOREDUMP(status); 892#if JOBS 893 if (WIFSTOPPED(status)) 894 sig = WSTOPSIG(status); 895 else 896#endif 897 if (WIFEXITED(status)) 898 sig = 0; 899 else 900 sig = WTERMSIG(status); 901 902 if (sig != 0 && sig != SIGINT && sig != SIGPIPE) { 903 if (thisjob != job) 904 outfmt(out2, "%d: ", pid); 905#if JOBS 906 if (sig == SIGTSTP && rootshell && iflag) 907 outfmt(out2, "%%%d ", job - jobtab + 1); 908#endif 909 if (sig < NSIG && sys_siglist[sig]) 910 out2str(sys_siglist[sig]); 911 else 912 outfmt(out2, "Signal %d", sig); 913 if (core) 914 out2str(" - core dumped"); 915 out2c('\n'); 916 flushout(&errout); 917 } else { 918 TRACE(("Not printing status: status=%d, sig=%d\n", 919 status, sig)); 920 } 921 } else { 922 TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell, job)); 923 if (thisjob) 924 thisjob->changed = 1; 925 } 926 return pid; 927} 928 929 930 931/* 932 * Do a wait system call. If job control is compiled in, we accept 933 * stopped processes. If block is zero, we return a value of zero 934 * rather than blocking. 935 * 936 * System V doesn't have a non-blocking wait system call. It does 937 * have a SIGCLD signal that is sent to a process when one of it's 938 * children dies. The obvious way to use SIGCLD would be to install 939 * a handler for SIGCLD which simply bumped a counter when a SIGCLD 940 * was received, and have waitproc bump another counter when it got 941 * the status of a process. Waitproc would then know that a wait 942 * system call would not block if the two counters were different. 943 * This approach doesn't work because if a process has children that 944 * have not been waited for, System V will send it a SIGCLD when it 945 * installs a signal handler for SIGCLD. What this means is that when 946 * a child exits, the shell will be sent SIGCLD signals continuously 947 * until is runs out of stack space, unless it does a wait call before 948 * restoring the signal handler. The code below takes advantage of 949 * this (mis)feature by installing a signal handler for SIGCLD and 950 * then checking to see whether it was called. If there are any 951 * children to be waited for, it will be. 952 * 953 * If neither SYSV nor BSD is defined, we don't implement nonblocking 954 * waits at all. In this case, the user will not be informed when 955 * a background process until the next time she runs a real program 956 * (as opposed to running a builtin command or just typing return), 957 * and the jobs command may give out of date information. 958 */ 959 960#ifdef SYSV 961STATIC sig_atomic_t gotsigchild; 962 963STATIC int onsigchild() { 964 gotsigchild = 1; 965} 966#endif 967 968 969STATIC int 970waitproc(int block, int *status) 971{ 972#ifdef BSD 973 int flags; 974 975#if JOBS 976 flags = WUNTRACED; 977#else 978 flags = 0; 979#endif 980 if (block == 0) 981 flags |= WNOHANG; 982 return wait3(status, flags, (struct rusage *)NULL); 983#else 984#ifdef SYSV 985 int (*save)(); 986 987 if (block == 0) { 988 gotsigchild = 0; 989 save = signal(SIGCLD, onsigchild); 990 signal(SIGCLD, save); 991 if (gotsigchild == 0) 992 return 0; 993 } 994 return wait(status); 995#else 996 if (block == 0) 997 return 0; 998 return wait(status); 999#endif 1000#endif 1001} 1002 1003/* 1004 * return 1 if there are stopped jobs, otherwise 0 1005 */ 1006int job_warning = 0; 1007int 1008stoppedjobs(void) 1009{ 1010 int jobno; 1011 struct job *jp; 1012 1013 if (job_warning) 1014 return (0); 1015 for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) { 1016 if (jp->used == 0) 1017 continue; 1018 if (jp->state == JOBSTOPPED) { 1019 out2str("You have stopped jobs.\n"); 1020 job_warning = 2; 1021 return (1); 1022 } 1023 } 1024 1025 return (0); 1026} 1027 1028/* 1029 * Return a string identifying a command (to be printed by the 1030 * jobs command. 1031 */ 1032 1033STATIC char *cmdnextc; 1034STATIC int cmdnleft; 1035#define MAXCMDTEXT 200 1036 1037char * 1038commandtext(union node *n) 1039{ 1040 char *name; 1041 1042 cmdnextc = name = ckmalloc(MAXCMDTEXT); 1043 cmdnleft = MAXCMDTEXT - 4; 1044 cmdtxt(n); 1045 *cmdnextc = '\0'; 1046 return name; 1047} 1048 1049 1050STATIC void 1051cmdtxt(union node *n) 1052{ 1053 union node *np; 1054 struct nodelist *lp; 1055 char *p; 1056 int i; 1057 char s[2]; 1058 1059 if (n == NULL) 1060 return; 1061 switch (n->type) { 1062 case NSEMI: 1063 cmdtxt(n->nbinary.ch1); 1064 cmdputs("; "); 1065 cmdtxt(n->nbinary.ch2); 1066 break; 1067 case NAND: 1068 cmdtxt(n->nbinary.ch1); 1069 cmdputs(" && "); 1070 cmdtxt(n->nbinary.ch2); 1071 break; 1072 case NOR: 1073 cmdtxt(n->nbinary.ch1); 1074 cmdputs(" || "); 1075 cmdtxt(n->nbinary.ch2); 1076 break; 1077 case NPIPE: 1078 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 1079 cmdtxt(lp->n); 1080 if (lp->next) 1081 cmdputs(" | "); 1082 } 1083 break; 1084 case NSUBSHELL: 1085 cmdputs("("); 1086 cmdtxt(n->nredir.n); 1087 cmdputs(")"); 1088 break; 1089 case NREDIR: 1090 case NBACKGND: 1091 cmdtxt(n->nredir.n); 1092 break; 1093 case NIF: 1094 cmdputs("if "); 1095 cmdtxt(n->nif.test); 1096 cmdputs("; then "); 1097 cmdtxt(n->nif.ifpart); 1098 cmdputs("..."); 1099 break; 1100 case NWHILE: 1101 cmdputs("while "); 1102 goto until; 1103 case NUNTIL: 1104 cmdputs("until "); 1105until: 1106 cmdtxt(n->nbinary.ch1); 1107 cmdputs("; do "); 1108 cmdtxt(n->nbinary.ch2); 1109 cmdputs("; done"); 1110 break; 1111 case NFOR: 1112 cmdputs("for "); 1113 cmdputs(n->nfor.var); 1114 cmdputs(" in ..."); 1115 break; 1116 case NCASE: 1117 cmdputs("case "); 1118 cmdputs(n->ncase.expr->narg.text); 1119 cmdputs(" in ..."); 1120 break; 1121 case NDEFUN: 1122 cmdputs(n->narg.text); 1123 cmdputs("() ..."); 1124 break; 1125 case NCMD: 1126 for (np = n->ncmd.args ; np ; np = np->narg.next) { 1127 cmdtxt(np); 1128 if (np->narg.next) 1129 cmdputs(" "); 1130 } 1131 for (np = n->ncmd.redirect ; np ; np = np->nfile.next) { 1132 cmdputs(" "); 1133 cmdtxt(np); 1134 } 1135 break; 1136 case NARG: 1137 cmdputs(n->narg.text); 1138 break; 1139 case NTO: 1140 p = ">"; i = 1; goto redir; 1141 case NAPPEND: 1142 p = ">>"; i = 1; goto redir; 1143 case NTOFD: 1144 p = ">&"; i = 1; goto redir; 1145 case NCLOBBER: 1146 p = ">|"; i = 1; goto redir; 1147 case NFROM: 1148 p = "<"; i = 0; goto redir; 1149 case NFROMTO: 1150 p = "<>"; i = 0; goto redir; 1151 case NFROMFD: 1152 p = "<&"; i = 0; goto redir; 1153redir: 1154 if (n->nfile.fd != i) { 1155 s[0] = n->nfile.fd + '0'; 1156 s[1] = '\0'; 1157 cmdputs(s); 1158 } 1159 cmdputs(p); 1160 if (n->type == NTOFD || n->type == NFROMFD) { 1161 s[0] = n->ndup.dupfd + '0'; 1162 s[1] = '\0'; 1163 cmdputs(s); 1164 } else { 1165 cmdtxt(n->nfile.fname); 1166 } 1167 break; 1168 case NHERE: 1169 case NXHERE: 1170 cmdputs("<<..."); 1171 break; 1172 default: 1173 cmdputs("???"); 1174 break; 1175 } 1176} 1177 1178 1179 1180STATIC void 1181cmdputs(char *s) 1182{ 1183 char *p, *q; 1184 char c; 1185 int subtype = 0; 1186 1187 if (cmdnleft <= 0) 1188 return; 1189 p = s; 1190 q = cmdnextc; 1191 while ((c = *p++) != '\0') { 1192 if (c == CTLESC) 1193 *q++ = *p++; 1194 else if (c == CTLVAR) { 1195 *q++ = '$'; 1196 if (--cmdnleft > 0) 1197 *q++ = '{'; 1198 subtype = *p++; 1199 } else if (c == '=' && subtype != 0) { 1200 *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL]; 1201 subtype = 0; 1202 } else if (c == CTLENDVAR) { 1203 *q++ = '}'; 1204 } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE) 1205 cmdnleft++; /* ignore it */ 1206 else 1207 *q++ = c; 1208 if (--cmdnleft <= 0) { 1209 *q++ = '.'; 1210 *q++ = '.'; 1211 *q++ = '.'; 1212 break; 1213 } 1214 } 1215 cmdnextc = q; 1216} 1217