1 /* $NetBSD: jobs.c,v 1.68 2008/12/21 17:16:11 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Kenneth Almquist. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 #ifndef lint 37 #if 0 38 static char sccsid[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95"; 39 #else 40 __RCSID("$NetBSD: jobs.c,v 1.68 2008/12/21 17:16:11 christos Exp $"); 41 #endif 42 #endif /* not lint */ 43 44 #include <fcntl.h> 45 #include <signal.h> 46 #include <errno.h> 47 #include <unistd.h> 48 #include <stdlib.h> 49 #include <paths.h> 50 #include <sys/types.h> 51 #include <sys/param.h> 52 #ifdef BSD 53 #include <sys/wait.h> 54 #include <sys/time.h> 55 #include <sys/resource.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 84 static struct job *jobtab; /* array of jobs */ 85 static int njobs; /* size of array */ 86 static int jobs_invalid; /* set in child */ 87 MKINIT pid_t backgndpid = -1; /* pid of last background process */ 88 #if JOBS 89 int initialpgrp; /* pgrp of shell on invocation */ 90 static int curjob = -1; /* current job */ 91 #endif 92 static int ttyfd = -1; 93 94 STATIC void restartjob(struct job *); 95 STATIC void freejob(struct job *); 96 STATIC struct job *getjob(const char *, int); 97 STATIC int dowait(int, struct job *); 98 #define WBLOCK 1 99 #define WNOFREE 2 100 STATIC int waitproc(int, struct job *, int *); 101 STATIC void cmdtxt(union node *); 102 STATIC void cmdlist(union node *, int); 103 STATIC void cmdputs(const char *); 104 105 #ifdef SYSV 106 STATIC int onsigchild(void); 107 #endif 108 109 #ifdef OLD_TTY_DRIVER 110 static pid_t tcgetpgrp(int fd); 111 static int tcsetpgrp(int fd, pid_t pgrp); 112 113 static pid_t 114 tcgetpgrp(int fd) 115 { 116 pid_t pgrp; 117 if (ioctl(fd, TIOCGPGRP, (char *)&pgrp) == -1) 118 return -1; 119 else 120 return pgrp; 121 } 122 123 static int 124 tcsetpgrp(int fd, pid_tpgrp) 125 { 126 return ioctl(fd, TIOCSPGRP, (char *)&pgrp); 127 } 128 #endif 129 130 /* 131 * Turn job control on and off. 132 * 133 * Note: This code assumes that the third arg to ioctl is a character 134 * pointer, which is true on Berkeley systems but not System V. Since 135 * System V doesn't have job control yet, this isn't a problem now. 136 */ 137 138 MKINIT int jobctl; 139 140 void 141 setjobctl(int on) 142 { 143 #ifdef OLD_TTY_DRIVER 144 int ldisc; 145 #endif 146 147 if (on == jobctl || rootshell == 0) 148 return; 149 if (on) { 150 #if defined(FIOCLEX) || defined(FD_CLOEXEC) 151 int err; 152 int i; 153 if (ttyfd != -1) 154 close(ttyfd); 155 if ((ttyfd = open("/dev/tty", O_RDWR)) == -1) { 156 for (i = 0; i < 3; i++) { 157 if (isatty(i) && (ttyfd = dup(i)) != -1) 158 break; 159 } 160 if (i == 3) 161 goto out; 162 } 163 /* Move to a high fd */ 164 for (i = 10; i > 2; i--) { 165 if ((err = fcntl(ttyfd, F_DUPFD, (1 << i) - 1)) != -1) 166 break; 167 } 168 if (err != -1) { 169 close(ttyfd); 170 ttyfd = err; 171 } 172 #ifdef FIOCLEX 173 err = ioctl(ttyfd, FIOCLEX, 0); 174 #elif FD_CLOEXEC 175 err = fcntl(ttyfd, F_SETFD, 176 fcntl(ttyfd, F_GETFD, 0) | FD_CLOEXEC); 177 #endif 178 if (err == -1) { 179 close(ttyfd); 180 ttyfd = -1; 181 goto out; 182 } 183 #else 184 out2str("sh: Need FIOCLEX or FD_CLOEXEC to support job control"); 185 goto out; 186 #endif 187 do { /* while we are in the background */ 188 if ((initialpgrp = tcgetpgrp(ttyfd)) < 0) { 189 out: 190 out2str("sh: can't access tty; job control turned off\n"); 191 mflag = 0; 192 return; 193 } 194 if (initialpgrp == -1) 195 initialpgrp = getpgrp(); 196 else if (initialpgrp != getpgrp()) { 197 killpg(0, SIGTTIN); 198 continue; 199 } 200 } while (0); 201 202 #ifdef OLD_TTY_DRIVER 203 if (ioctl(ttyfd, TIOCGETD, (char *)&ldisc) < 0 204 || ldisc != NTTYDISC) { 205 out2str("sh: need new tty driver to run job control; job control turned off\n"); 206 mflag = 0; 207 return; 208 } 209 #endif 210 setsignal(SIGTSTP, 0); 211 setsignal(SIGTTOU, 0); 212 setsignal(SIGTTIN, 0); 213 if (getpgrp() != rootpid && setpgid(0, rootpid) == -1) 214 error("Cannot set process group (%s) at %d", 215 strerror(errno), __LINE__); 216 if (tcsetpgrp(ttyfd, rootpid) == -1) 217 error("Cannot set tty process group (%s) at %d", 218 strerror(errno), __LINE__); 219 } else { /* turning job control off */ 220 if (getpgrp() != initialpgrp && setpgid(0, initialpgrp) == -1) 221 error("Cannot set process group (%s) at %d", 222 strerror(errno), __LINE__); 223 if (tcsetpgrp(ttyfd, initialpgrp) == -1) 224 error("Cannot set tty process group (%s) at %d", 225 strerror(errno), __LINE__); 226 close(ttyfd); 227 ttyfd = -1; 228 setsignal(SIGTSTP, 0); 229 setsignal(SIGTTOU, 0); 230 setsignal(SIGTTIN, 0); 231 } 232 jobctl = on; 233 } 234 235 236 #ifdef mkinit 237 INCLUDE <stdlib.h> 238 239 SHELLPROC { 240 backgndpid = -1; 241 #if JOBS 242 jobctl = 0; 243 #endif 244 } 245 246 #endif 247 248 249 250 #if JOBS 251 int 252 fgcmd(int argc, char **argv) 253 { 254 struct job *jp; 255 int i; 256 int status; 257 258 nextopt(""); 259 jp = getjob(*argptr, 0); 260 if (jp->jobctl == 0) 261 error("job not created under job control"); 262 out1fmt("%s", jp->ps[0].cmd); 263 for (i = 1; i < jp->nprocs; i++) 264 out1fmt(" | %s", jp->ps[i].cmd ); 265 out1c('\n'); 266 flushall(); 267 268 for (i = 0; i < jp->nprocs; i++) 269 if (tcsetpgrp(ttyfd, jp->ps[i].pid) != -1) 270 break; 271 272 if (i >= jp->nprocs) { 273 error("Cannot set tty process group (%s) at %d", 274 strerror(errno), __LINE__); 275 } 276 restartjob(jp); 277 INTOFF; 278 status = waitforjob(jp); 279 INTON; 280 return status; 281 } 282 283 static void 284 set_curjob(struct job *jp, int mode) 285 { 286 struct job *jp1, *jp2; 287 int i, ji; 288 289 ji = jp - jobtab; 290 291 /* first remove from list */ 292 if (ji == curjob) 293 curjob = jp->prev_job; 294 else { 295 for (i = 0; i < njobs; i++) { 296 if (jobtab[i].prev_job != ji) 297 continue; 298 jobtab[i].prev_job = jp->prev_job; 299 break; 300 } 301 } 302 303 /* Then re-insert in correct position */ 304 switch (mode) { 305 case 0: /* job being deleted */ 306 jp->prev_job = -1; 307 break; 308 case 1: /* newly created job or backgrounded job, 309 put after all stopped jobs. */ 310 if (curjob != -1 && jobtab[curjob].state == JOBSTOPPED) { 311 for (jp1 = jobtab + curjob; ; jp1 = jp2) { 312 if (jp1->prev_job == -1) 313 break; 314 jp2 = jobtab + jp1->prev_job; 315 if (jp2->state != JOBSTOPPED) 316 break; 317 } 318 jp->prev_job = jp1->prev_job; 319 jp1->prev_job = ji; 320 break; 321 } 322 /* FALLTHROUGH */ 323 case 2: /* newly stopped job - becomes curjob */ 324 jp->prev_job = curjob; 325 curjob = ji; 326 break; 327 } 328 } 329 330 int 331 bgcmd(int argc, char **argv) 332 { 333 struct job *jp; 334 int i; 335 336 nextopt(""); 337 do { 338 jp = getjob(*argptr, 0); 339 if (jp->jobctl == 0) 340 error("job not created under job control"); 341 set_curjob(jp, 1); 342 out1fmt("[%ld] %s", (long)(jp - jobtab + 1), jp->ps[0].cmd); 343 for (i = 1; i < jp->nprocs; i++) 344 out1fmt(" | %s", jp->ps[i].cmd ); 345 out1c('\n'); 346 flushall(); 347 restartjob(jp); 348 } while (*argptr && *++argptr); 349 return 0; 350 } 351 352 353 STATIC void 354 restartjob(struct job *jp) 355 { 356 struct procstat *ps; 357 int i; 358 359 if (jp->state == JOBDONE) 360 return; 361 INTOFF; 362 for (i = 0; i < jp->nprocs; i++) 363 if (killpg(jp->ps[i].pid, SIGCONT) != -1) 364 break; 365 if (i >= jp->nprocs) 366 error("Cannot continue job (%s)", strerror(errno)); 367 for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) { 368 if (WIFSTOPPED(ps->status)) { 369 ps->status = -1; 370 jp->state = JOBRUNNING; 371 } 372 } 373 INTON; 374 } 375 #endif 376 377 static void 378 showjob(struct output *out, struct job *jp, int mode) 379 { 380 int procno; 381 int st; 382 struct procstat *ps; 383 int col; 384 char s[64]; 385 386 #if JOBS 387 if (mode & SHOW_PGID) { 388 /* just output process (group) id of pipeline */ 389 outfmt(out, "%ld\n", (long)jp->ps->pid); 390 return; 391 } 392 #endif 393 394 procno = jp->nprocs; 395 if (!procno) 396 return; 397 398 if (mode & SHOW_PID) 399 mode |= SHOW_MULTILINE; 400 401 if ((procno > 1 && !(mode & SHOW_MULTILINE)) 402 || (mode & SHOW_SIGNALLED)) { 403 /* See if we have more than one status to report */ 404 ps = jp->ps; 405 st = ps->status; 406 do { 407 int st1 = ps->status; 408 if (st1 != st) 409 /* yes - need multi-line output */ 410 mode |= SHOW_MULTILINE; 411 if (st1 == -1 || !(mode & SHOW_SIGNALLED) || WIFEXITED(st1)) 412 continue; 413 if (WIFSTOPPED(st1) || ((st1 = WTERMSIG(st1) & 0x7f) 414 && st1 != SIGINT && st1 != SIGPIPE)) 415 mode |= SHOW_ISSIG; 416 417 } while (ps++, --procno); 418 procno = jp->nprocs; 419 } 420 421 if (mode & SHOW_SIGNALLED && !(mode & SHOW_ISSIG)) { 422 if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE)) { 423 TRACE(("showjob: freeing job %d\n", jp - jobtab + 1)); 424 freejob(jp); 425 } 426 return; 427 } 428 429 for (ps = jp->ps; --procno >= 0; ps++) { /* for each process */ 430 if (ps == jp->ps) 431 fmtstr(s, 16, "[%ld] %c ", 432 (long)(jp - jobtab + 1), 433 #if JOBS 434 jp == jobtab + curjob ? '+' : 435 curjob != -1 && jp == jobtab + 436 jobtab[curjob].prev_job ? '-' : 437 #endif 438 ' '); 439 else 440 fmtstr(s, 16, " " ); 441 col = strlen(s); 442 if (mode & SHOW_PID) { 443 fmtstr(s + col, 16, "%ld ", (long)ps->pid); 444 col += strlen(s + col); 445 } 446 if (ps->status == -1) { 447 scopy("Running", s + col); 448 } else if (WIFEXITED(ps->status)) { 449 st = WEXITSTATUS(ps->status); 450 if (st) 451 fmtstr(s + col, 16, "Done(%d)", st); 452 else 453 fmtstr(s + col, 16, "Done"); 454 } else { 455 #if JOBS 456 if (WIFSTOPPED(ps->status)) 457 st = WSTOPSIG(ps->status); 458 else /* WIFSIGNALED(ps->status) */ 459 #endif 460 st = WTERMSIG(ps->status); 461 st &= 0x7f; 462 if (st < NSIG && sys_siglist[st]) 463 scopyn(sys_siglist[st], s + col, 32); 464 else 465 fmtstr(s + col, 16, "Signal %d", st); 466 if (WCOREDUMP(ps->status)) { 467 col += strlen(s + col); 468 scopyn(" (core dumped)", s + col, 64 - col); 469 } 470 } 471 col += strlen(s + col); 472 outstr(s, out); 473 do { 474 outc(' ', out); 475 col++; 476 } while (col < 30); 477 outstr(ps->cmd, out); 478 if (mode & SHOW_MULTILINE) { 479 if (procno > 0) { 480 outc(' ', out); 481 outc('|', out); 482 } 483 } else { 484 while (--procno >= 0) 485 outfmt(out, " | %s", (++ps)->cmd ); 486 } 487 outc('\n', out); 488 } 489 flushout(out); 490 jp->changed = 0; 491 if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE)) 492 freejob(jp); 493 } 494 495 496 int 497 jobscmd(int argc, char **argv) 498 { 499 int mode, m; 500 int sv = jobs_invalid; 501 502 jobs_invalid = 0; 503 mode = 0; 504 while ((m = nextopt("lp"))) 505 if (m == 'l') 506 mode = SHOW_PID; 507 else 508 mode = SHOW_PGID; 509 if (*argptr) 510 do 511 showjob(out1, getjob(*argptr,0), mode); 512 while (*++argptr); 513 else 514 showjobs(out1, mode); 515 jobs_invalid = sv; 516 return 0; 517 } 518 519 520 /* 521 * Print a list of jobs. If "change" is nonzero, only print jobs whose 522 * statuses have changed since the last call to showjobs. 523 * 524 * If the shell is interrupted in the process of creating a job, the 525 * result may be a job structure containing zero processes. Such structures 526 * will be freed here. 527 */ 528 529 void 530 showjobs(struct output *out, int mode) 531 { 532 int jobno; 533 struct job *jp; 534 int silent = 0, gotpid; 535 536 TRACE(("showjobs(%x) called\n", mode)); 537 538 /* If not even one one job changed, there is nothing to do */ 539 gotpid = dowait(0, NULL); 540 while (dowait(0, NULL) > 0) 541 continue; 542 #ifdef JOBS 543 /* 544 * Check if we are not in our foreground group, and if not 545 * put us in it. 546 */ 547 if (mflag && gotpid != -1 && tcgetpgrp(ttyfd) != getpid()) { 548 if (tcsetpgrp(ttyfd, getpid()) == -1) 549 error("Cannot set tty process group (%s) at %d", 550 strerror(errno), __LINE__); 551 TRACE(("repaired tty process group\n")); 552 silent = 1; 553 } 554 #endif 555 if (jobs_invalid) 556 return; 557 558 for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) { 559 if (!jp->used) 560 continue; 561 if (jp->nprocs == 0) { 562 freejob(jp); 563 continue; 564 } 565 if ((mode & SHOW_CHANGED) && !jp->changed) 566 continue; 567 if (silent && jp->changed) { 568 jp->changed = 0; 569 continue; 570 } 571 showjob(out, jp, mode); 572 } 573 } 574 575 /* 576 * Mark a job structure as unused. 577 */ 578 579 STATIC void 580 freejob(struct job *jp) 581 { 582 INTOFF; 583 if (jp->ps != &jp->ps0) { 584 ckfree(jp->ps); 585 jp->ps = &jp->ps0; 586 } 587 jp->nprocs = 0; 588 jp->used = 0; 589 #if JOBS 590 set_curjob(jp, 0); 591 #endif 592 INTON; 593 } 594 595 596 597 int 598 waitcmd(int argc, char **argv) 599 { 600 struct job *job; 601 int status, retval; 602 struct job *jp; 603 604 nextopt(""); 605 606 if (!*argptr) { 607 /* wait for all jobs */ 608 jp = jobtab; 609 if (jobs_invalid) 610 return 0; 611 for (;;) { 612 if (jp >= jobtab + njobs) { 613 /* no running procs */ 614 return 0; 615 } 616 if (!jp->used || jp->state != JOBRUNNING) { 617 jp++; 618 continue; 619 } 620 if (dowait(WBLOCK, NULL) == -1) 621 return 128 + SIGINT; 622 jp = jobtab; 623 } 624 } 625 626 retval = 127; /* XXXGCC: -Wuninitialized */ 627 for (; *argptr; argptr++) { 628 job = getjob(*argptr, 1); 629 if (!job) { 630 retval = 127; 631 continue; 632 } 633 /* loop until process terminated or stopped */ 634 while (job->state == JOBRUNNING) { 635 if (dowait(WBLOCK|WNOFREE, job) == -1) 636 return 128 + SIGINT; 637 } 638 status = job->ps[job->nprocs - 1].status; 639 if (WIFEXITED(status)) 640 retval = WEXITSTATUS(status); 641 #if JOBS 642 else if (WIFSTOPPED(status)) 643 retval = WSTOPSIG(status) + 128; 644 #endif 645 else { 646 /* XXX: limits number of signals */ 647 retval = WTERMSIG(status) + 128; 648 } 649 if (!iflag) 650 freejob(job); 651 } 652 return retval; 653 } 654 655 656 657 int 658 jobidcmd(int argc, char **argv) 659 { 660 struct job *jp; 661 int i; 662 663 nextopt(""); 664 jp = getjob(*argptr, 0); 665 for (i = 0 ; i < jp->nprocs ; ) { 666 out1fmt("%ld", (long)jp->ps[i].pid); 667 out1c(++i < jp->nprocs ? ' ' : '\n'); 668 } 669 return 0; 670 } 671 672 int 673 getjobpgrp(const char *name) 674 { 675 struct job *jp; 676 677 jp = getjob(name, 1); 678 if (jp == 0) 679 return 0; 680 return -jp->ps[0].pid; 681 } 682 683 /* 684 * Convert a job name to a job structure. 685 */ 686 687 STATIC struct job * 688 getjob(const char *name, int noerror) 689 { 690 int jobno = -1; 691 struct job *jp; 692 int pid; 693 int i; 694 const char *err_msg = "No such job: %s"; 695 696 if (name == NULL) { 697 #if JOBS 698 jobno = curjob; 699 #endif 700 err_msg = "No current job"; 701 } else if (name[0] == '%') { 702 if (is_number(name + 1)) { 703 jobno = number(name + 1) - 1; 704 } else if (!name[2]) { 705 switch (name[1]) { 706 #if JOBS 707 case 0: 708 case '+': 709 case '%': 710 jobno = curjob; 711 err_msg = "No current job"; 712 break; 713 case '-': 714 jobno = curjob; 715 if (jobno != -1) 716 jobno = jobtab[jobno].prev_job; 717 err_msg = "No previous job"; 718 break; 719 #endif 720 default: 721 goto check_pattern; 722 } 723 } else { 724 struct job *found; 725 check_pattern: 726 found = NULL; 727 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { 728 if (!jp->used || jp->nprocs <= 0) 729 continue; 730 if ((name[1] == '?' 731 && strstr(jp->ps[0].cmd, name + 2)) 732 || prefix(name + 1, jp->ps[0].cmd)) { 733 if (found) { 734 err_msg = "%s: ambiguous"; 735 found = 0; 736 break; 737 } 738 found = jp; 739 } 740 } 741 if (found) 742 return found; 743 } 744 745 } else if (is_number(name)) { 746 pid = number(name); 747 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { 748 if (jp->used && jp->nprocs > 0 749 && jp->ps[jp->nprocs - 1].pid == pid) 750 return jp; 751 } 752 } 753 754 if (!jobs_invalid && jobno >= 0 && jobno < njobs) { 755 jp = jobtab + jobno; 756 if (jp->used) 757 return jp; 758 } 759 if (!noerror) 760 error(err_msg, name); 761 return 0; 762 } 763 764 765 766 /* 767 * Return a new job structure, 768 */ 769 770 struct job * 771 makejob(union node *node, int nprocs) 772 { 773 int i; 774 struct job *jp; 775 776 if (jobs_invalid) { 777 for (i = njobs, jp = jobtab ; --i >= 0 ; jp++) { 778 if (jp->used) 779 freejob(jp); 780 } 781 jobs_invalid = 0; 782 } 783 784 for (i = njobs, jp = jobtab ; ; jp++) { 785 if (--i < 0) { 786 INTOFF; 787 if (njobs == 0) { 788 jobtab = ckmalloc(4 * sizeof jobtab[0]); 789 } else { 790 jp = ckmalloc((njobs + 4) * sizeof jobtab[0]); 791 memcpy(jp, jobtab, njobs * sizeof jp[0]); 792 /* Relocate `ps' pointers */ 793 for (i = 0; i < njobs; i++) 794 if (jp[i].ps == &jobtab[i].ps0) 795 jp[i].ps = &jp[i].ps0; 796 ckfree(jobtab); 797 jobtab = jp; 798 } 799 jp = jobtab + njobs; 800 for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0); 801 INTON; 802 break; 803 } 804 if (jp->used == 0) 805 break; 806 } 807 INTOFF; 808 jp->state = JOBRUNNING; 809 jp->used = 1; 810 jp->changed = 0; 811 jp->nprocs = 0; 812 #if JOBS 813 jp->jobctl = jobctl; 814 set_curjob(jp, 1); 815 #endif 816 if (nprocs > 1) { 817 jp->ps = ckmalloc(nprocs * sizeof (struct procstat)); 818 } else { 819 jp->ps = &jp->ps0; 820 } 821 INTON; 822 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs, 823 jp - jobtab + 1)); 824 return jp; 825 } 826 827 828 /* 829 * Fork off a subshell. If we are doing job control, give the subshell its 830 * own process group. Jp is a job structure that the job is to be added to. 831 * N is the command that will be evaluated by the child. Both jp and n may 832 * be NULL. The mode parameter can be one of the following: 833 * FORK_FG - Fork off a foreground process. 834 * FORK_BG - Fork off a background process. 835 * FORK_NOJOB - Like FORK_FG, but don't give the process its own 836 * process group even if job control is on. 837 * 838 * When job control is turned off, background processes have their standard 839 * input redirected to /dev/null (except for the second and later processes 840 * in a pipeline). 841 */ 842 843 int 844 forkshell(struct job *jp, union node *n, int mode) 845 { 846 int pid; 847 848 TRACE(("forkshell(%%%d, %p, %d) called\n", jp - jobtab, n, mode)); 849 switch ((pid = fork())) { 850 case -1: 851 TRACE(("Fork failed, errno=%d\n", errno)); 852 INTON; 853 error("Cannot fork"); 854 break; 855 case 0: 856 forkchild(jp, n, mode, 0); 857 return 0; 858 default: 859 return forkparent(jp, n, mode, pid); 860 } 861 } 862 863 int 864 forkparent(struct job *jp, union node *n, int mode, pid_t pid) 865 { 866 int pgrp; 867 868 if (rootshell && mode != FORK_NOJOB && mflag) { 869 if (jp == NULL || jp->nprocs == 0) 870 pgrp = pid; 871 else 872 pgrp = jp->ps[0].pid; 873 /* This can fail because we are doing it in the child also */ 874 (void)setpgid(pid, pgrp); 875 } 876 if (mode == FORK_BG) 877 backgndpid = pid; /* set $! */ 878 if (jp) { 879 struct procstat *ps = &jp->ps[jp->nprocs++]; 880 ps->pid = pid; 881 ps->status = -1; 882 ps->cmd[0] = 0; 883 if (/* iflag && rootshell && */ n) 884 commandtext(ps, n); 885 } 886 TRACE(("In parent shell: child = %d\n", pid)); 887 return pid; 888 } 889 890 void 891 forkchild(struct job *jp, union node *n, int mode, int vforked) 892 { 893 int wasroot; 894 int pgrp; 895 const char *devnull = _PATH_DEVNULL; 896 const char *nullerr = "Can't open %s"; 897 898 wasroot = rootshell; 899 TRACE(("Child shell %d\n", getpid())); 900 if (!vforked) 901 rootshell = 0; 902 903 closescript(vforked); 904 clear_traps(vforked); 905 #if JOBS 906 if (!vforked) 907 jobctl = 0; /* do job control only in root shell */ 908 if (wasroot && mode != FORK_NOJOB && mflag) { 909 if (jp == NULL || jp->nprocs == 0) 910 pgrp = getpid(); 911 else 912 pgrp = jp->ps[0].pid; 913 /* This can fail because we are doing it in the parent also */ 914 (void)setpgid(0, pgrp); 915 if (mode == FORK_FG) { 916 if (tcsetpgrp(ttyfd, pgrp) == -1) 917 error("Cannot set tty process group (%s) at %d", 918 strerror(errno), __LINE__); 919 } 920 setsignal(SIGTSTP, vforked); 921 setsignal(SIGTTOU, vforked); 922 } else if (mode == FORK_BG) { 923 ignoresig(SIGINT, vforked); 924 ignoresig(SIGQUIT, vforked); 925 if ((jp == NULL || jp->nprocs == 0) && 926 ! fd0_redirected_p ()) { 927 close(0); 928 if (open(devnull, O_RDONLY) != 0) 929 error(nullerr, devnull); 930 } 931 } 932 #else 933 if (mode == FORK_BG) { 934 ignoresig(SIGINT, vforked); 935 ignoresig(SIGQUIT, vforked); 936 if ((jp == NULL || jp->nprocs == 0) && 937 ! fd0_redirected_p ()) { 938 close(0); 939 if (open(devnull, O_RDONLY) != 0) 940 error(nullerr, devnull); 941 } 942 } 943 #endif 944 if (wasroot && iflag) { 945 setsignal(SIGINT, vforked); 946 setsignal(SIGQUIT, vforked); 947 setsignal(SIGTERM, vforked); 948 } 949 950 if (!vforked) 951 jobs_invalid = 1; 952 } 953 954 /* 955 * Wait for job to finish. 956 * 957 * Under job control we have the problem that while a child process is 958 * running interrupts generated by the user are sent to the child but not 959 * to the shell. This means that an infinite loop started by an inter- 960 * active user may be hard to kill. With job control turned off, an 961 * interactive user may place an interactive program inside a loop. If 962 * the interactive program catches interrupts, the user doesn't want 963 * these interrupts to also abort the loop. The approach we take here 964 * is to have the shell ignore interrupt signals while waiting for a 965 * forground process to terminate, and then send itself an interrupt 966 * signal if the child process was terminated by an interrupt signal. 967 * Unfortunately, some programs want to do a bit of cleanup and then 968 * exit on interrupt; unless these processes terminate themselves by 969 * sending a signal to themselves (instead of calling exit) they will 970 * confuse this approach. 971 */ 972 973 int 974 waitforjob(struct job *jp) 975 { 976 #if JOBS 977 int mypgrp = getpgrp(); 978 #endif 979 int status; 980 int st; 981 982 INTOFF; 983 TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1)); 984 while (jp->state == JOBRUNNING) { 985 dowait(WBLOCK, jp); 986 } 987 #if JOBS 988 if (jp->jobctl) { 989 if (tcsetpgrp(ttyfd, mypgrp) == -1) 990 error("Cannot set tty process group (%s) at %d", 991 strerror(errno), __LINE__); 992 } 993 if (jp->state == JOBSTOPPED && curjob != jp - jobtab) 994 set_curjob(jp, 2); 995 #endif 996 status = jp->ps[jp->nprocs - 1].status; 997 /* convert to 8 bits */ 998 if (WIFEXITED(status)) 999 st = WEXITSTATUS(status); 1000 #if JOBS 1001 else if (WIFSTOPPED(status)) 1002 st = WSTOPSIG(status) + 128; 1003 #endif 1004 else 1005 st = WTERMSIG(status) + 128; 1006 TRACE(("waitforjob: job %d, nproc %d, status %x, st %x\n", 1007 jp - jobtab + 1, jp->nprocs, status, st )); 1008 #if JOBS 1009 if (jp->jobctl) { 1010 /* 1011 * This is truly gross. 1012 * If we're doing job control, then we did a TIOCSPGRP which 1013 * caused us (the shell) to no longer be in the controlling 1014 * session -- so we wouldn't have seen any ^C/SIGINT. So, we 1015 * intuit from the subprocess exit status whether a SIGINT 1016 * occurred, and if so interrupt ourselves. Yuck. - mycroft 1017 */ 1018 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT) 1019 raise(SIGINT); 1020 } 1021 #endif 1022 if (! JOBS || jp->state == JOBDONE) 1023 freejob(jp); 1024 INTON; 1025 return st; 1026 } 1027 1028 1029 1030 /* 1031 * Wait for a process to terminate. 1032 */ 1033 1034 STATIC int 1035 dowait(int flags, struct job *job) 1036 { 1037 int pid; 1038 int status; 1039 struct procstat *sp; 1040 struct job *jp; 1041 struct job *thisjob; 1042 int done; 1043 int stopped; 1044 extern volatile char gotsig[]; 1045 1046 TRACE(("dowait(%x) called\n", flags)); 1047 do { 1048 pid = waitproc(flags & WBLOCK, job, &status); 1049 TRACE(("wait returns pid %d, status %d\n", pid, status)); 1050 } while (pid == -1 && errno == EINTR && gotsig[SIGINT - 1] == 0); 1051 if (pid <= 0) 1052 return pid; 1053 INTOFF; 1054 thisjob = NULL; 1055 for (jp = jobtab ; jp < jobtab + njobs ; jp++) { 1056 if (jp->used) { 1057 done = 1; 1058 stopped = 1; 1059 for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) { 1060 if (sp->pid == -1) 1061 continue; 1062 if (sp->pid == pid) { 1063 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jp - jobtab + 1, pid, sp->status, status)); 1064 sp->status = status; 1065 thisjob = jp; 1066 } 1067 if (sp->status == -1) 1068 stopped = 0; 1069 else if (WIFSTOPPED(sp->status)) 1070 done = 0; 1071 } 1072 if (stopped) { /* stopped or done */ 1073 int state = done ? JOBDONE : JOBSTOPPED; 1074 if (jp->state != state) { 1075 TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state)); 1076 jp->state = state; 1077 #if JOBS 1078 if (done) 1079 set_curjob(jp, 0); 1080 #endif 1081 } 1082 } 1083 } 1084 } 1085 1086 if (thisjob && thisjob->state != JOBRUNNING) { 1087 int mode = 0; 1088 if (!rootshell || !iflag) 1089 mode = SHOW_SIGNALLED; 1090 if ((job == thisjob && (flags & WNOFREE) == 0) || 1091 (job != thisjob && (flags & WNOFREE) != 0)) 1092 mode = SHOW_SIGNALLED | SHOW_NO_FREE; 1093 if (mode) 1094 showjob(out2, thisjob, mode); 1095 else { 1096 TRACE(("Not printing status, rootshell=%d, job=%p\n", 1097 rootshell, job)); 1098 thisjob->changed = 1; 1099 } 1100 } 1101 1102 INTON; 1103 return pid; 1104 } 1105 1106 1107 1108 /* 1109 * Do a wait system call. If job control is compiled in, we accept 1110 * stopped processes. If block is zero, we return a value of zero 1111 * rather than blocking. 1112 * 1113 * System V doesn't have a non-blocking wait system call. It does 1114 * have a SIGCLD signal that is sent to a process when one of its 1115 * children dies. The obvious way to use SIGCLD would be to install 1116 * a handler for SIGCLD which simply bumped a counter when a SIGCLD 1117 * was received, and have waitproc bump another counter when it got 1118 * the status of a process. Waitproc would then know that a wait 1119 * system call would not block if the two counters were different. 1120 * This approach doesn't work because if a process has children that 1121 * have not been waited for, System V will send it a SIGCLD when it 1122 * installs a signal handler for SIGCLD. What this means is that when 1123 * a child exits, the shell will be sent SIGCLD signals continuously 1124 * until is runs out of stack space, unless it does a wait call before 1125 * restoring the signal handler. The code below takes advantage of 1126 * this (mis)feature by installing a signal handler for SIGCLD and 1127 * then checking to see whether it was called. If there are any 1128 * children to be waited for, it will be. 1129 * 1130 * If neither SYSV nor BSD is defined, we don't implement nonblocking 1131 * waits at all. In this case, the user will not be informed when 1132 * a background process until the next time she runs a real program 1133 * (as opposed to running a builtin command or just typing return), 1134 * and the jobs command may give out of date information. 1135 */ 1136 1137 #ifdef SYSV 1138 STATIC int gotsigchild; 1139 1140 STATIC int onsigchild() { 1141 gotsigchild = 1; 1142 } 1143 #endif 1144 1145 1146 STATIC int 1147 waitproc(int block, struct job *jp, int *status) 1148 { 1149 #ifdef BSD 1150 int flags = 0; 1151 1152 #if JOBS 1153 if (jp != NULL && jp->jobctl) 1154 flags |= WUNTRACED; 1155 #endif 1156 if (block == 0) 1157 flags |= WNOHANG; 1158 return waitpid(-1, status, flags); 1159 #else 1160 #ifdef SYSV 1161 int (*save)(); 1162 1163 if (block == 0) { 1164 gotsigchild = 0; 1165 save = signal(SIGCLD, onsigchild); 1166 signal(SIGCLD, save); 1167 if (gotsigchild == 0) 1168 return 0; 1169 } 1170 return wait(status); 1171 #else 1172 if (block == 0) 1173 return 0; 1174 return wait(status); 1175 #endif 1176 #endif 1177 } 1178 1179 /* 1180 * return 1 if there are stopped jobs, otherwise 0 1181 */ 1182 int job_warning = 0; 1183 int 1184 stoppedjobs(void) 1185 { 1186 int jobno; 1187 struct job *jp; 1188 1189 if (job_warning || jobs_invalid) 1190 return (0); 1191 for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) { 1192 if (jp->used == 0) 1193 continue; 1194 if (jp->state == JOBSTOPPED) { 1195 out2str("You have stopped jobs.\n"); 1196 job_warning = 2; 1197 return (1); 1198 } 1199 } 1200 1201 return (0); 1202 } 1203 1204 /* 1205 * Return a string identifying a command (to be printed by the 1206 * jobs command). 1207 */ 1208 1209 STATIC char *cmdnextc; 1210 STATIC int cmdnleft; 1211 1212 void 1213 commandtext(struct procstat *ps, union node *n) 1214 { 1215 int len; 1216 1217 cmdnextc = ps->cmd; 1218 if (iflag || mflag || sizeof ps->cmd < 100) 1219 len = sizeof(ps->cmd); 1220 else 1221 len = sizeof(ps->cmd) / 10; 1222 cmdnleft = len; 1223 cmdtxt(n); 1224 if (cmdnleft <= 0) { 1225 char *p = ps->cmd + len - 4; 1226 p[0] = '.'; 1227 p[1] = '.'; 1228 p[2] = '.'; 1229 p[3] = 0; 1230 } else 1231 *cmdnextc = '\0'; 1232 TRACE(("commandtext: ps->cmd %x, end %x, left %d\n\t\"%s\"\n", 1233 ps->cmd, cmdnextc, cmdnleft, ps->cmd)); 1234 } 1235 1236 1237 STATIC void 1238 cmdtxt(union node *n) 1239 { 1240 union node *np; 1241 struct nodelist *lp; 1242 const char *p; 1243 int i; 1244 char s[2]; 1245 1246 if (n == NULL || cmdnleft <= 0) 1247 return; 1248 switch (n->type) { 1249 case NSEMI: 1250 cmdtxt(n->nbinary.ch1); 1251 cmdputs("; "); 1252 cmdtxt(n->nbinary.ch2); 1253 break; 1254 case NAND: 1255 cmdtxt(n->nbinary.ch1); 1256 cmdputs(" && "); 1257 cmdtxt(n->nbinary.ch2); 1258 break; 1259 case NOR: 1260 cmdtxt(n->nbinary.ch1); 1261 cmdputs(" || "); 1262 cmdtxt(n->nbinary.ch2); 1263 break; 1264 case NPIPE: 1265 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 1266 cmdtxt(lp->n); 1267 if (lp->next) 1268 cmdputs(" | "); 1269 } 1270 break; 1271 case NSUBSHELL: 1272 cmdputs("("); 1273 cmdtxt(n->nredir.n); 1274 cmdputs(")"); 1275 break; 1276 case NREDIR: 1277 case NBACKGND: 1278 cmdtxt(n->nredir.n); 1279 break; 1280 case NIF: 1281 cmdputs("if "); 1282 cmdtxt(n->nif.test); 1283 cmdputs("; then "); 1284 cmdtxt(n->nif.ifpart); 1285 if (n->nif.elsepart) { 1286 cmdputs("; else "); 1287 cmdtxt(n->nif.elsepart); 1288 } 1289 cmdputs("; fi"); 1290 break; 1291 case NWHILE: 1292 cmdputs("while "); 1293 goto until; 1294 case NUNTIL: 1295 cmdputs("until "); 1296 until: 1297 cmdtxt(n->nbinary.ch1); 1298 cmdputs("; do "); 1299 cmdtxt(n->nbinary.ch2); 1300 cmdputs("; done"); 1301 break; 1302 case NFOR: 1303 cmdputs("for "); 1304 cmdputs(n->nfor.var); 1305 cmdputs(" in "); 1306 cmdlist(n->nfor.args, 1); 1307 cmdputs("; do "); 1308 cmdtxt(n->nfor.body); 1309 cmdputs("; done"); 1310 break; 1311 case NCASE: 1312 cmdputs("case "); 1313 cmdputs(n->ncase.expr->narg.text); 1314 cmdputs(" in "); 1315 for (np = n->ncase.cases; np; np = np->nclist.next) { 1316 cmdtxt(np->nclist.pattern); 1317 cmdputs(") "); 1318 cmdtxt(np->nclist.body); 1319 cmdputs(";; "); 1320 } 1321 cmdputs("esac"); 1322 break; 1323 case NDEFUN: 1324 cmdputs(n->narg.text); 1325 cmdputs("() { ... }"); 1326 break; 1327 case NCMD: 1328 cmdlist(n->ncmd.args, 1); 1329 cmdlist(n->ncmd.redirect, 0); 1330 break; 1331 case NARG: 1332 cmdputs(n->narg.text); 1333 break; 1334 case NTO: 1335 p = ">"; i = 1; goto redir; 1336 case NCLOBBER: 1337 p = ">|"; i = 1; goto redir; 1338 case NAPPEND: 1339 p = ">>"; i = 1; goto redir; 1340 case NTOFD: 1341 p = ">&"; i = 1; goto redir; 1342 case NFROM: 1343 p = "<"; i = 0; goto redir; 1344 case NFROMFD: 1345 p = "<&"; i = 0; goto redir; 1346 case NFROMTO: 1347 p = "<>"; i = 0; goto redir; 1348 redir: 1349 if (n->nfile.fd != i) { 1350 s[0] = n->nfile.fd + '0'; 1351 s[1] = '\0'; 1352 cmdputs(s); 1353 } 1354 cmdputs(p); 1355 if (n->type == NTOFD || n->type == NFROMFD) { 1356 s[0] = n->ndup.dupfd + '0'; 1357 s[1] = '\0'; 1358 cmdputs(s); 1359 } else { 1360 cmdtxt(n->nfile.fname); 1361 } 1362 break; 1363 case NHERE: 1364 case NXHERE: 1365 cmdputs("<<..."); 1366 break; 1367 default: 1368 cmdputs("???"); 1369 break; 1370 } 1371 } 1372 1373 STATIC void 1374 cmdlist(union node *np, int sep) 1375 { 1376 for (; np; np = np->narg.next) { 1377 if (!sep) 1378 cmdputs(" "); 1379 cmdtxt(np); 1380 if (sep && np->narg.next) 1381 cmdputs(" "); 1382 } 1383 } 1384 1385 1386 STATIC void 1387 cmdputs(const char *s) 1388 { 1389 const char *p, *str = 0; 1390 char c, cc[2] = " "; 1391 char *nextc; 1392 int nleft; 1393 int subtype = 0; 1394 int quoted = 0; 1395 static char vstype[16][4] = { "", "}", "-", "+", "?", "=", 1396 "#", "##", "%", "%%" }; 1397 1398 p = s; 1399 nextc = cmdnextc; 1400 nleft = cmdnleft; 1401 while (nleft > 0 && (c = *p++) != 0) { 1402 switch (c) { 1403 case CTLESC: 1404 c = *p++; 1405 break; 1406 case CTLVAR: 1407 subtype = *p++; 1408 if ((subtype & VSTYPE) == VSLENGTH) 1409 str = "${#"; 1410 else 1411 str = "${"; 1412 if (!(subtype & VSQUOTE) != !(quoted & 1)) { 1413 quoted ^= 1; 1414 c = '"'; 1415 } else 1416 c = *str++; 1417 break; 1418 case CTLENDVAR: 1419 if (quoted & 1) { 1420 c = '"'; 1421 str = "}"; 1422 } else 1423 c = '}'; 1424 quoted >>= 1; 1425 subtype = 0; 1426 break; 1427 case CTLBACKQ: 1428 c = '$'; 1429 str = "(...)"; 1430 break; 1431 case CTLBACKQ+CTLQUOTE: 1432 c = '"'; 1433 str = "$(...)\""; 1434 break; 1435 case CTLARI: 1436 c = '$'; 1437 str = "(("; 1438 break; 1439 case CTLENDARI: 1440 c = ')'; 1441 str = ")"; 1442 break; 1443 case CTLQUOTEMARK: 1444 quoted ^= 1; 1445 c = '"'; 1446 break; 1447 case '=': 1448 if (subtype == 0) 1449 break; 1450 str = vstype[subtype & VSTYPE]; 1451 if (subtype & VSNUL) 1452 c = ':'; 1453 else 1454 c = *str++; 1455 if (c != '}') 1456 quoted <<= 1; 1457 break; 1458 case '\'': 1459 case '\\': 1460 case '"': 1461 case '$': 1462 /* These can only happen inside quotes */ 1463 cc[0] = c; 1464 str = cc; 1465 c = '\\'; 1466 break; 1467 default: 1468 break; 1469 } 1470 do { 1471 *nextc++ = c; 1472 } while (--nleft > 0 && str && (c = *str++)); 1473 str = 0; 1474 } 1475 if ((quoted & 1) && nleft) { 1476 *nextc++ = '"'; 1477 nleft--; 1478 } 1479 cmdnleft = nleft; 1480 cmdnextc = nextc; 1481 } 1482