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