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