jobs.c revision 38521
160786Sps/*- 260786Sps * Copyright (c) 1991, 1993 360786Sps * The Regents of the University of California. All rights reserved. 460786Sps * 560786Sps * This code is derived from software contributed to Berkeley by 660786Sps * Kenneth Almquist. 760786Sps * 860786Sps * Redistribution and use in source and binary forms, with or without 960786Sps * modification, are permitted provided that the following conditions 1060786Sps * are met: 1160786Sps * 1. Redistributions of source code must retain the above copyright 1260786Sps * notice, this list of conditions and the following disclaimer. 1360786Sps * 2. Redistributions in binary form must reproduce the above copyright 1460786Sps * notice, this list of conditions and the following disclaimer in the 1560786Sps * documentation and/or other materials provided with the distribution. 1660786Sps * 3. All advertising materials mentioning features or use of this software 1760786Sps * must display the following acknowledgement: 1860786Sps * This product includes software developed by the University of 1960786Sps * California, Berkeley and its contributors. 2060786Sps * 4. Neither the name of the University nor the names of its contributors 2160786Sps * may be used to endorse or promote products derived from this software 2260786Sps * without specific prior written permission. 2360786Sps * 2460786Sps * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2560786Sps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2660786Sps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2760786Sps * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2860786Sps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2960786Sps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3060786Sps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3160786Sps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3260786Sps * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3360786Sps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3460786Sps * SUCH DAMAGE. 3589019Sps */ 3660786Sps 3789019Sps#ifndef lint 3860786Sps#if 0 3960786Spsstatic char sccsid[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95"; 4060786Sps#endif 4160786Spsstatic const char rcsid[] = 4260786Sps "$Id: jobs.c,v 1.20 1998/05/18 06:43:47 charnier Exp $"; 4360786Sps#endif /* not lint */ 4460786Sps 4589019Sps#include <fcntl.h> 4689019Sps#include <signal.h> 4789019Sps#include <errno.h> 4889019Sps#include <unistd.h> 4989019Sps#include <stdlib.h> 5089019Sps#include <sys/param.h> 5189019Sps#ifdef BSD 5289019Sps#include <sys/wait.h> 5389019Sps#include <sys/time.h> 5460786Sps#include <sys/resource.h> 5560786Sps#endif 5660786Sps#include <sys/ioctl.h> 5760786Sps 5860786Sps#include "shell.h" 5960786Sps#if JOBS 6060786Sps#if OLD_TTY_DRIVER 6160786Sps#include "sgtty.h" 6260786Sps#else 6360786Sps#include <termios.h> 6460786Sps#endif 6560786Sps#undef CEOF /* syntax.h redefines this */ 6660786Sps#endif 6760786Sps#include "redir.h" 6860786Sps#include "show.h" 6960786Sps#include "main.h" 7060786Sps#include "parser.h" 7160786Sps#include "nodes.h" 7260786Sps#include "jobs.h" 7360786Sps#include "options.h" 7460786Sps#include "trap.h" 7560786Sps#include "syntax.h" 7660786Sps#include "input.h" 7760786Sps#include "output.h" 7860786Sps#include "memalloc.h" 7960786Sps#include "error.h" 8060786Sps#include "mystring.h" 8160786Sps 8260786Sps 8360786Spsstruct job *jobtab; /* array of jobs */ 8460786Spsint njobs; /* size of array */ 8560786SpsMKINIT pid_t backgndpid = -1; /* pid of last background process */ 8660786Sps#if JOBS 8760786Spsint initialpgrp; /* pgrp of shell on invocation */ 8860786Spsint curjob; /* current job */ 8960786Sps#endif 9060786Spsint in_waitcmd = 0; /* Are we in waitcmd? */ 9160786Spsvolatile sig_atomic_t breakwaitcmd = 0; /* Should wait be terminated? */ 9260786Sps 9360786Sps#if JOBS 9460786SpsSTATIC void restartjob __P((struct job *)); 9560786Sps#endif 9660786SpsSTATIC void freejob __P((struct job *)); 9760786SpsSTATIC struct job *getjob __P((char *)); 9860786SpsSTATIC int dowait __P((int, struct job *)); 9960786Sps#if SYSV 10060786SpsSTATIC volatile int onsigchild __P((void)); 10160786Sps#endif 10260786SpsSTATIC int waitproc __P((int, int *)); 10360786SpsSTATIC void cmdtxt __P((union node *)); 10460786SpsSTATIC void cmdputs __P((char *)); 10560786Sps 10660786Sps 10760786Sps/* 10860786Sps * Turn job control on and off. 10960786Sps * 11060786Sps * Note: This code assumes that the third arg to ioctl is a character 11160786Sps * pointer, which is true on Berkeley systems but not System V. Since 11260786Sps * System V doesn't have job control yet, this isn't a problem now. 11360786Sps */ 11460786Sps 11560786SpsMKINIT int jobctl; 11660786Sps 11760786Sps#if JOBS 11860786Spsvoid 11960786Spssetjobctl(on) 12060786Sps int on; 12160786Sps{ 12260786Sps#ifdef OLD_TTY_DRIVER 12360786Sps int ldisc; 12460786Sps#endif 12560786Sps 12660786Sps if (on == jobctl || rootshell == 0) 12760786Sps return; 12860786Sps if (on) { 12960786Sps do { /* while we are in the background */ 13060786Sps#ifdef OLD_TTY_DRIVER 13160786Sps if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) { 13260786Sps#else 13360786Sps initialpgrp = tcgetpgrp(2); 13460786Sps if (initialpgrp < 0) { 13560786Sps#endif 13660786Sps out2str("sh: can't access tty; job control turned off\n"); 13760786Sps mflag = 0; 13889019Sps return; 13960786Sps } 14060786Sps if (initialpgrp == -1) 14160786Sps initialpgrp = getpgrp(); 14260786Sps else if (initialpgrp != getpgrp()) { 14389019Sps killpg(initialpgrp, SIGTTIN); 14489019Sps continue; 14589019Sps } 14689019Sps } while (0); 14789019Sps#ifdef OLD_TTY_DRIVER 14889019Sps if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) { 14989019Sps out2str("sh: need new tty driver to run job control; job control turned off\n"); 15089019Sps mflag = 0; 15189019Sps return; 15289019Sps } 15360786Sps#endif 15460786Sps setsignal(SIGTSTP); 15560786Sps setsignal(SIGTTOU); 15660786Sps setsignal(SIGTTIN); 15760786Sps setpgid(0, rootpid); 15860786Sps#ifdef OLD_TTY_DRIVER 15960786Sps ioctl(2, TIOCSPGRP, (char *)&rootpid); 16060786Sps#else 16160786Sps tcsetpgrp(2, rootpid); 16260786Sps#endif 16360786Sps } else { /* turning job control off */ 16460786Sps setpgid(0, initialpgrp); 16560786Sps#ifdef OLD_TTY_DRIVER 16660786Sps ioctl(2, TIOCSPGRP, (char *)&initialpgrp); 16760786Sps#else 16860786Sps tcsetpgrp(2, initialpgrp); 16960786Sps#endif 17060786Sps setsignal(SIGTSTP); 17160786Sps setsignal(SIGTTOU); 17260786Sps setsignal(SIGTTIN); 17360786Sps } 17460786Sps jobctl = on; 17560786Sps} 17660786Sps#endif 17760786Sps 17860786Sps 17960786Sps#ifdef mkinit 18060786SpsINCLUDE <sys/types.h> 18160786SpsINCLUDE <stdlib.h> 18260786Sps 18360786SpsSHELLPROC { 18460786Sps backgndpid = -1; 18560786Sps#if JOBS 18660786Sps jobctl = 0; 18760786Sps#endif 18860786Sps} 18960786Sps 19060786Sps#endif 19160786Sps 19260786Sps 19360786Sps 19460786Sps#if JOBS 19560786Spsint 19660786Spsfgcmd(argc, argv) 19760786Sps int argc __unused; 19860786Sps char **argv; 19960786Sps{ 20060786Sps struct job *jp; 20160786Sps int pgrp; 20260786Sps int status; 20360786Sps 20460786Sps jp = getjob(argv[1]); 20560786Sps if (jp->jobctl == 0) 20660786Sps error("job not created under job control"); 20760786Sps pgrp = jp->ps[0].pid; 20860786Sps#ifdef OLD_TTY_DRIVER 20960786Sps ioctl(2, TIOCSPGRP, (char *)&pgrp); 21060786Sps#else 21160786Sps tcsetpgrp(2, pgrp); 21260786Sps#endif 21360786Sps restartjob(jp); 21460786Sps INTOFF; 21560786Sps status = waitforjob(jp); 21660786Sps INTON; 21760786Sps return status; 21860786Sps} 21960786Sps 22060786Sps 22160786Spsint 22260786Spsbgcmd(argc, argv) 22360786Sps int argc; 22460786Sps char **argv; 22560786Sps{ 22660786Sps struct job *jp; 22760786Sps 22860786Sps do { 22960786Sps jp = getjob(*++argv); 23060786Sps if (jp->jobctl == 0) 23160786Sps error("job not created under job control"); 23260786Sps restartjob(jp); 23360786Sps } while (--argc > 1); 23460786Sps return 0; 23560786Sps} 23660786Sps 23760786Sps 23860786SpsSTATIC void 23960786Spsrestartjob(jp) 24060786Sps struct job *jp; 24160786Sps{ 24260786Sps struct procstat *ps; 24360786Sps int i; 24460786Sps 24560786Sps if (jp->state == JOBDONE) 24660786Sps return; 24760786Sps INTOFF; 24860786Sps killpg(jp->ps[0].pid, SIGCONT); 24960786Sps for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) { 25060786Sps if (WIFSTOPPED(ps->status)) { 25160786Sps ps->status = -1; 25260786Sps jp->state = 0; 25360786Sps } 25460786Sps } 25560786Sps INTON; 25660786Sps} 25760786Sps#endif 25860786Sps 25960786Sps 26060786Spsint 26160786Spsjobscmd(argc, argv) 26260786Sps int argc __unused; 26360786Sps char **argv __unused; 26460786Sps{ 26589019Sps showjobs(0); 26660786Sps return 0; 26789019Sps} 26889019Sps 26989019Sps 27089019Sps/* 27189019Sps * Print a list of jobs. If "change" is nonzero, only print jobs whose 27260786Sps * statuses have changed since the last call to showjobs. 27360786Sps * 27460786Sps * If the shell is interrupted in the process of creating a job, the 27560786Sps * result may be a job structure containing zero processes. Such structures 27689019Sps * will be freed here. 27760786Sps */ 27860786Sps 27960786Spsvoid 28060786Spsshowjobs(change) 28160786Sps int change; 28260786Sps{ 28360786Sps int jobno; 28460786Sps int procno; 28560786Sps int i; 28660786Sps struct job *jp; 28760786Sps struct procstat *ps; 28860786Sps int col; 28960786Sps char s[64]; 29060786Sps 29160786Sps TRACE(("showjobs(%d) called\n", change)); 29260786Sps while (dowait(0, (struct job *)NULL) > 0); 29360786Sps for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) { 29460786Sps if (! jp->used) 29560786Sps continue; 29660786Sps if (jp->nprocs == 0) { 29760786Sps freejob(jp); 29860786Sps continue; 29960786Sps } 30060786Sps if (change && ! jp->changed) 30160786Sps continue; 30260786Sps procno = jp->nprocs; 30360786Sps for (ps = jp->ps ; ; ps++) { /* for each process */ 30460786Sps if (ps == jp->ps) 30560786Sps fmtstr(s, 64, "[%d] %d ", jobno, ps->pid); 30660786Sps else 30760786Sps fmtstr(s, 64, " %d ", ps->pid); 30860786Sps out1str(s); 30960786Sps col = strlen(s); 31060786Sps s[0] = '\0'; 31160786Sps if (ps->status == -1) { 31260786Sps /* don't print anything */ 31360786Sps } else if (WIFEXITED(ps->status)) { 31460786Sps fmtstr(s, 64, "Exit %d", WEXITSTATUS(ps->status)); 31560786Sps } else { 31689019Sps#if JOBS 31789019Sps if (WIFSTOPPED(ps->status)) 31889019Sps i = WSTOPSIG(ps->status); 31989019Sps else 32089019Sps#endif 32189019Sps i = WTERMSIG(ps->status); 32289019Sps if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F]) 32389019Sps scopy(sys_siglist[i & 0x7F], s); 32489019Sps else 32589019Sps fmtstr(s, 64, "Signal %d", i & 0x7F); 32689019Sps if (WCOREDUMP(ps->status)) 32789019Sps strcat(s, " (core dumped)"); 32889019Sps } 32989019Sps out1str(s); 33089019Sps col += strlen(s); 33189019Sps do { 33260786Sps out1c(' '); 33360786Sps col++; 33460786Sps } while (col < 30); 33560786Sps out1str(ps->cmd); 336 out1c('\n'); 337 if (--procno <= 0) 338 break; 339 } 340 jp->changed = 0; 341 if (jp->state == JOBDONE) { 342 freejob(jp); 343 } 344 } 345} 346 347 348/* 349 * Mark a job structure as unused. 350 */ 351 352STATIC void 353freejob(jp) 354 struct job *jp; 355 { 356 struct procstat *ps; 357 int i; 358 359 INTOFF; 360 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) { 361 if (ps->cmd != nullstr) 362 ckfree(ps->cmd); 363 } 364 if (jp->ps != &jp->ps0) 365 ckfree(jp->ps); 366 jp->used = 0; 367#if JOBS 368 if (curjob == jp - jobtab + 1) 369 curjob = 0; 370#endif 371 INTON; 372} 373 374 375 376int 377waitcmd(argc, argv) 378 int argc; 379 char **argv; 380{ 381 struct job *job; 382 int status, retval; 383 struct job *jp; 384 385 if (argc > 1) { 386 job = getjob(argv[1]); 387 } else { 388 job = NULL; 389 } 390 in_waitcmd++; 391 do { /* loop until process terminated or stopped or SIGINT is 392 * received 393 */ 394 if (job != NULL) { 395 if (job->state) { 396 status = job->ps[job->nprocs - 1].status; 397 if (WIFEXITED(status)) 398 retval = WEXITSTATUS(status); 399#if JOBS 400 else if (WIFSTOPPED(status)) 401 retval = WSTOPSIG(status) + 128; 402#endif 403 else 404 retval = WTERMSIG(status) + 128; 405 if (! iflag) 406 freejob(job); 407 return retval; 408 } 409 } else { 410 for (jp = jobtab ; ; jp++) { 411 if (jp >= jobtab + njobs) { /* no running procs */ 412 return 0; 413 } 414 if (jp->used && jp->state == 0) 415 break; 416 } 417 } 418 } while (dowait(1, (struct job *)NULL) != -1); 419 in_waitcmd--; 420 421 /* Not reachable */ 422 return 0; 423} 424 425 426 427int 428jobidcmd(argc, argv) 429 int argc __unused; 430 char **argv; 431{ 432 struct job *jp; 433 int i; 434 435 jp = getjob(argv[1]); 436 for (i = 0 ; i < jp->nprocs ; ) { 437 out1fmt("%d", jp->ps[i].pid); 438 out1c(++i < jp->nprocs? ' ' : '\n'); 439 } 440 return 0; 441} 442 443 444 445/* 446 * Convert a job name to a job structure. 447 */ 448 449STATIC struct job * 450getjob(name) 451 char *name; 452 { 453 int jobno; 454 struct job *jp; 455 int pid; 456 int i; 457 458 if (name == NULL) { 459#if JOBS 460currentjob: 461 if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0) 462 error("No current job"); 463 return &jobtab[jobno - 1]; 464#else 465 error("No current job"); 466#endif 467 } else if (name[0] == '%') { 468 if (is_digit(name[1])) { 469 jobno = number(name + 1); 470 if (jobno > 0 && jobno <= njobs 471 && jobtab[jobno - 1].used != 0) 472 return &jobtab[jobno - 1]; 473#if JOBS 474 } else if (name[1] == '%' && name[2] == '\0') { 475 goto currentjob; 476#endif 477 } else { 478 struct job *found = NULL; 479 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { 480 if (jp->used && jp->nprocs > 0 481 && prefix(name + 1, jp->ps[0].cmd)) { 482 if (found) 483 error("%s: ambiguous", name); 484 found = jp; 485 } 486 } 487 if (found) 488 return found; 489 } 490 } else if (is_number(name)) { 491 pid = number(name); 492 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { 493 if (jp->used && jp->nprocs > 0 494 && jp->ps[jp->nprocs - 1].pid == pid) 495 return jp; 496 } 497 } 498 error("No such job: %s", name); 499 /*NOTREACHED*/ 500 return NULL; 501} 502 503 504 505/* 506 * Return a new job structure, 507 */ 508 509struct job * 510makejob(node, nprocs) 511 union node *node __unused; 512 int nprocs; 513{ 514 int i; 515 struct job *jp; 516 517 for (i = njobs, jp = jobtab ; ; jp++) { 518 if (--i < 0) { 519 INTOFF; 520 if (njobs == 0) { 521 jobtab = ckmalloc(4 * sizeof jobtab[0]); 522 } else { 523 jp = ckmalloc((njobs + 4) * sizeof jobtab[0]); 524 memcpy(jp, jobtab, njobs * sizeof jp[0]); 525 /* Relocate `ps' pointers */ 526 for (i = 0; i < njobs; i++) 527 if (jp[i].ps == &jobtab[i].ps0) 528 jp[i].ps = &jp[i].ps0; 529 ckfree(jobtab); 530 jobtab = jp; 531 } 532 jp = jobtab + njobs; 533 for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0); 534 INTON; 535 break; 536 } 537 if (jp->used == 0) 538 break; 539 } 540 INTOFF; 541 jp->state = 0; 542 jp->used = 1; 543 jp->changed = 0; 544 jp->nprocs = 0; 545#if JOBS 546 jp->jobctl = jobctl; 547#endif 548 if (nprocs > 1) { 549 jp->ps = ckmalloc(nprocs * sizeof (struct procstat)); 550 } else { 551 jp->ps = &jp->ps0; 552 } 553 INTON; 554 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs, 555 jp - jobtab + 1)); 556 return jp; 557} 558 559 560/* 561 * Fork of a subshell. If we are doing job control, give the subshell its 562 * own process group. Jp is a job structure that the job is to be added to. 563 * N is the command that will be evaluated by the child. Both jp and n may 564 * be NULL. The mode parameter can be one of the following: 565 * FORK_FG - Fork off a foreground process. 566 * FORK_BG - Fork off a background process. 567 * FORK_NOJOB - Like FORK_FG, but don't give the process its own 568 * process group even if job control is on. 569 * 570 * When job control is turned off, background processes have their standard 571 * input redirected to /dev/null (except for the second and later processes 572 * in a pipeline). 573 */ 574 575int 576forkshell(jp, n, mode) 577 union node *n; 578 struct job *jp; 579 int mode; 580{ 581 int pid; 582 int pgrp; 583 584 TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long)n, 585 mode)); 586 INTOFF; 587 pid = fork(); 588 if (pid == -1) { 589 TRACE(("Fork failed, errno=%d\n", errno)); 590 INTON; 591 error("Cannot fork"); 592 } 593 if (pid == 0) { 594 struct job *p; 595 int wasroot; 596 int i; 597 598 TRACE(("Child shell %d\n", getpid())); 599 wasroot = rootshell; 600 rootshell = 0; 601 for (i = njobs, p = jobtab ; --i >= 0 ; p++) 602 if (p->used) 603 freejob(p); 604 closescript(); 605 INTON; 606 clear_traps(); 607#if JOBS 608 jobctl = 0; /* do job control only in root shell */ 609 if (wasroot && mode != FORK_NOJOB && mflag) { 610 if (jp == NULL || jp->nprocs == 0) 611 pgrp = getpid(); 612 else 613 pgrp = jp->ps[0].pid; 614 if (setpgid(0, pgrp) == 0 && mode == FORK_FG) { 615 /*** this causes superfluous TIOCSPGRPS ***/ 616#ifdef OLD_TTY_DRIVER 617 if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0) 618 error("TIOCSPGRP failed, errno=%d", errno); 619#else 620 if (tcsetpgrp(2, pgrp) < 0) 621 error("tcsetpgrp failed, errno=%d", errno); 622#endif 623 } 624 setsignal(SIGTSTP); 625 setsignal(SIGTTOU); 626 } else if (mode == FORK_BG) { 627 ignoresig(SIGINT); 628 ignoresig(SIGQUIT); 629 if ((jp == NULL || jp->nprocs == 0) && 630 ! fd0_redirected_p ()) { 631 close(0); 632 if (open("/dev/null", O_RDONLY) != 0) 633 error("Can't open /dev/null"); 634 } 635 } 636#else 637 if (mode == FORK_BG) { 638 ignoresig(SIGINT); 639 ignoresig(SIGQUIT); 640 if ((jp == NULL || jp->nprocs == 0) && 641 ! fd0_redirected_p ()) { 642 close(0); 643 if (open("/dev/null", O_RDONLY) != 0) 644 error("Can't open /dev/null"); 645 } 646 } 647#endif 648 if (wasroot && iflag) { 649 setsignal(SIGINT); 650 setsignal(SIGQUIT); 651 setsignal(SIGTERM); 652 } 653 return pid; 654 } 655 if (rootshell && mode != FORK_NOJOB && mflag) { 656 if (jp == NULL || jp->nprocs == 0) 657 pgrp = pid; 658 else 659 pgrp = jp->ps[0].pid; 660 setpgid(pid, pgrp); 661 } 662 if (mode == FORK_BG) 663 backgndpid = pid; /* set $! */ 664 if (jp) { 665 struct procstat *ps = &jp->ps[jp->nprocs++]; 666 ps->pid = pid; 667 ps->status = -1; 668 ps->cmd = nullstr; 669 if (iflag && rootshell && n) 670 ps->cmd = commandtext(n); 671 } 672 INTON; 673 TRACE(("In parent shell: child = %d\n", pid)); 674 return pid; 675} 676 677 678 679/* 680 * Wait for job to finish. 681 * 682 * Under job control we have the problem that while a child process is 683 * running interrupts generated by the user are sent to the child but not 684 * to the shell. This means that an infinite loop started by an inter- 685 * active user may be hard to kill. With job control turned off, an 686 * interactive user may place an interactive program inside a loop. If 687 * the interactive program catches interrupts, the user doesn't want 688 * these interrupts to also abort the loop. The approach we take here 689 * is to have the shell ignore interrupt signals while waiting for a 690 * forground process to terminate, and then send itself an interrupt 691 * signal if the child process was terminated by an interrupt signal. 692 * Unfortunately, some programs want to do a bit of cleanup and then 693 * exit on interrupt; unless these processes terminate themselves by 694 * sending a signal to themselves (instead of calling exit) they will 695 * confuse this approach. 696 */ 697 698int 699waitforjob(jp) 700 struct job *jp; 701 { 702#if JOBS 703 int mypgrp = getpgrp(); 704#endif 705 int status; 706 int st; 707 708 INTOFF; 709 TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1)); 710 while (jp->state == 0) { 711 dowait(1, jp); 712 } 713#if JOBS 714 if (jp->jobctl) { 715#ifdef OLD_TTY_DRIVER 716 if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0) 717 error("TIOCSPGRP failed, errno=%d\n", errno); 718#else 719 if (tcsetpgrp(2, mypgrp) < 0) 720 error("tcsetpgrp failed, errno=%d\n", errno); 721#endif 722 } 723 if (jp->state == JOBSTOPPED) 724 curjob = jp - jobtab + 1; 725#endif 726 status = jp->ps[jp->nprocs - 1].status; 727 /* convert to 8 bits */ 728 if (WIFEXITED(status)) 729 st = WEXITSTATUS(status); 730#if JOBS 731 else if (WIFSTOPPED(status)) 732 st = WSTOPSIG(status) + 128; 733#endif 734 else 735 st = WTERMSIG(status) + 128; 736 if (! JOBS || jp->state == JOBDONE) 737 freejob(jp); 738 if (int_pending()) { 739 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT) 740 kill(getpid(), SIGINT); 741 else 742 CLEAR_PENDING_INT; 743 } 744 INTON; 745 return st; 746} 747 748 749 750/* 751 * Wait for a process to terminate. 752 */ 753 754STATIC int 755dowait(block, job) 756 int block; 757 struct job *job; 758{ 759 int pid; 760 int status; 761 struct procstat *sp; 762 struct job *jp; 763 struct job *thisjob; 764 int done; 765 int stopped; 766 int core; 767 int sig; 768 769 TRACE(("dowait(%d) called\n", block)); 770 do { 771 pid = waitproc(block, &status); 772 TRACE(("wait returns %d, status=%d\n", pid, status)); 773 } while (pid == -1 && errno == EINTR && breakwaitcmd == 0); 774 if (breakwaitcmd != 0) { 775 breakwaitcmd = 0; 776 return -1; 777 } 778 if (pid <= 0) 779 return pid; 780 INTOFF; 781 thisjob = NULL; 782 for (jp = jobtab ; jp < jobtab + njobs ; jp++) { 783 if (jp->used) { 784 done = 1; 785 stopped = 1; 786 for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) { 787 if (sp->pid == -1) 788 continue; 789 if (sp->pid == pid) { 790 TRACE(("Changing status of proc %d from 0x%x to 0x%x\n", 791 pid, sp->status, status)); 792 sp->status = status; 793 thisjob = jp; 794 } 795 if (sp->status == -1) 796 stopped = 0; 797 else if (WIFSTOPPED(sp->status)) 798 done = 0; 799 } 800 if (stopped) { /* stopped or done */ 801 int state = done? JOBDONE : JOBSTOPPED; 802 if (jp->state != state) { 803 TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state)); 804 jp->state = state; 805#if JOBS 806 if (done && curjob == jp - jobtab + 1) 807 curjob = 0; /* no current job */ 808#endif 809 } 810 } 811 } 812 } 813 INTON; 814 if (! rootshell || ! iflag || (job && thisjob == job)) { 815 core = WCOREDUMP(status); 816#if JOBS 817 if (WIFSTOPPED(status)) 818 sig = WSTOPSIG(status); 819 else 820#endif 821 if (WIFEXITED(status)) 822 sig = 0; 823 else 824 sig = WTERMSIG(status); 825 826 if (sig != 0 && sig != SIGINT && sig != SIGPIPE) { 827 if (thisjob != job) 828 outfmt(out2, "%d: ", pid); 829#if JOBS 830 if (sig == SIGTSTP && rootshell && iflag) 831 outfmt(out2, "%%%d ", job - jobtab + 1); 832#endif 833 if (sig < NSIG && sys_siglist[sig]) 834 out2str(sys_siglist[sig]); 835 else 836 outfmt(out2, "Signal %d", sig); 837 if (core) 838 out2str(" - core dumped"); 839 out2c('\n'); 840 flushout(&errout); 841 } else { 842 TRACE(("Not printing status: status=%d, sig=%d\n", 843 status, sig)); 844 } 845 } else { 846 TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell, job)); 847 if (thisjob) 848 thisjob->changed = 1; 849 } 850 return pid; 851} 852 853 854 855/* 856 * Do a wait system call. If job control is compiled in, we accept 857 * stopped processes. If block is zero, we return a value of zero 858 * rather than blocking. 859 * 860 * System V doesn't have a non-blocking wait system call. It does 861 * have a SIGCLD signal that is sent to a process when one of it's 862 * children dies. The obvious way to use SIGCLD would be to install 863 * a handler for SIGCLD which simply bumped a counter when a SIGCLD 864 * was received, and have waitproc bump another counter when it got 865 * the status of a process. Waitproc would then know that a wait 866 * system call would not block if the two counters were different. 867 * This approach doesn't work because if a process has children that 868 * have not been waited for, System V will send it a SIGCLD when it 869 * installs a signal handler for SIGCLD. What this means is that when 870 * a child exits, the shell will be sent SIGCLD signals continuously 871 * until is runs out of stack space, unless it does a wait call before 872 * restoring the signal handler. The code below takes advantage of 873 * this (mis)feature by installing a signal handler for SIGCLD and 874 * then checking to see whether it was called. If there are any 875 * children to be waited for, it will be. 876 * 877 * If neither SYSV nor BSD is defined, we don't implement nonblocking 878 * waits at all. In this case, the user will not be informed when 879 * a background process until the next time she runs a real program 880 * (as opposed to running a builtin command or just typing return), 881 * and the jobs command may give out of date information. 882 */ 883 884#ifdef SYSV 885STATIC sig_atomic_t gotsigchild; 886 887STATIC int onsigchild() { 888 gotsigchild = 1; 889} 890#endif 891 892 893STATIC int 894waitproc(block, status) 895 int block; 896 int *status; 897{ 898#ifdef BSD 899 int flags; 900 901#if JOBS 902 flags = WUNTRACED; 903#else 904 flags = 0; 905#endif 906 if (block == 0) 907 flags |= WNOHANG; 908 return wait3(status, flags, (struct rusage *)NULL); 909#else 910#ifdef SYSV 911 int (*save)(); 912 913 if (block == 0) { 914 gotsigchild = 0; 915 save = signal(SIGCLD, onsigchild); 916 signal(SIGCLD, save); 917 if (gotsigchild == 0) 918 return 0; 919 } 920 return wait(status); 921#else 922 if (block == 0) 923 return 0; 924 return wait(status); 925#endif 926#endif 927} 928 929/* 930 * return 1 if there are stopped jobs, otherwise 0 931 */ 932int job_warning = 0; 933int 934stoppedjobs() 935{ 936 int jobno; 937 struct job *jp; 938 939 if (job_warning) 940 return (0); 941 for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) { 942 if (jp->used == 0) 943 continue; 944 if (jp->state == JOBSTOPPED) { 945 out2str("You have stopped jobs.\n"); 946 job_warning = 2; 947 return (1); 948 } 949 } 950 951 return (0); 952} 953 954/* 955 * Return a string identifying a command (to be printed by the 956 * jobs command. 957 */ 958 959STATIC char *cmdnextc; 960STATIC int cmdnleft; 961STATIC void cmdtxt(), cmdputs(); 962#define MAXCMDTEXT 200 963 964char * 965commandtext(n) 966 union node *n; 967 { 968 char *name; 969 970 cmdnextc = name = ckmalloc(MAXCMDTEXT); 971 cmdnleft = MAXCMDTEXT - 4; 972 cmdtxt(n); 973 *cmdnextc = '\0'; 974 return name; 975} 976 977 978STATIC void 979cmdtxt(n) 980 union node *n; 981 { 982 union node *np; 983 struct nodelist *lp; 984 char *p; 985 int i; 986 char s[2]; 987 988 if (n == NULL) 989 return; 990 switch (n->type) { 991 case NSEMI: 992 cmdtxt(n->nbinary.ch1); 993 cmdputs("; "); 994 cmdtxt(n->nbinary.ch2); 995 break; 996 case NAND: 997 cmdtxt(n->nbinary.ch1); 998 cmdputs(" && "); 999 cmdtxt(n->nbinary.ch2); 1000 break; 1001 case NOR: 1002 cmdtxt(n->nbinary.ch1); 1003 cmdputs(" || "); 1004 cmdtxt(n->nbinary.ch2); 1005 break; 1006 case NPIPE: 1007 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { 1008 cmdtxt(lp->n); 1009 if (lp->next) 1010 cmdputs(" | "); 1011 } 1012 break; 1013 case NSUBSHELL: 1014 cmdputs("("); 1015 cmdtxt(n->nredir.n); 1016 cmdputs(")"); 1017 break; 1018 case NREDIR: 1019 case NBACKGND: 1020 cmdtxt(n->nredir.n); 1021 break; 1022 case NIF: 1023 cmdputs("if "); 1024 cmdtxt(n->nif.test); 1025 cmdputs("; then "); 1026 cmdtxt(n->nif.ifpart); 1027 cmdputs("..."); 1028 break; 1029 case NWHILE: 1030 cmdputs("while "); 1031 goto until; 1032 case NUNTIL: 1033 cmdputs("until "); 1034until: 1035 cmdtxt(n->nbinary.ch1); 1036 cmdputs("; do "); 1037 cmdtxt(n->nbinary.ch2); 1038 cmdputs("; done"); 1039 break; 1040 case NFOR: 1041 cmdputs("for "); 1042 cmdputs(n->nfor.var); 1043 cmdputs(" in ..."); 1044 break; 1045 case NCASE: 1046 cmdputs("case "); 1047 cmdputs(n->ncase.expr->narg.text); 1048 cmdputs(" in ..."); 1049 break; 1050 case NDEFUN: 1051 cmdputs(n->narg.text); 1052 cmdputs("() ..."); 1053 break; 1054 case NCMD: 1055 for (np = n->ncmd.args ; np ; np = np->narg.next) { 1056 cmdtxt(np); 1057 if (np->narg.next) 1058 cmdputs(" "); 1059 } 1060 for (np = n->ncmd.redirect ; np ; np = np->nfile.next) { 1061 cmdputs(" "); 1062 cmdtxt(np); 1063 } 1064 break; 1065 case NARG: 1066 cmdputs(n->narg.text); 1067 break; 1068 case NTO: 1069 p = ">"; i = 1; goto redir; 1070 case NAPPEND: 1071 p = ">>"; i = 1; goto redir; 1072 case NTOFD: 1073 p = ">&"; i = 1; goto redir; 1074 case NFROM: 1075 p = "<"; i = 0; goto redir; 1076 case NFROMFD: 1077 p = "<&"; i = 0; goto redir; 1078redir: 1079 if (n->nfile.fd != i) { 1080 s[0] = n->nfile.fd + '0'; 1081 s[1] = '\0'; 1082 cmdputs(s); 1083 } 1084 cmdputs(p); 1085 if (n->type == NTOFD || n->type == NFROMFD) { 1086 s[0] = n->ndup.dupfd + '0'; 1087 s[1] = '\0'; 1088 cmdputs(s); 1089 } else { 1090 cmdtxt(n->nfile.fname); 1091 } 1092 break; 1093 case NHERE: 1094 case NXHERE: 1095 cmdputs("<<..."); 1096 break; 1097 default: 1098 cmdputs("???"); 1099 break; 1100 } 1101} 1102 1103 1104 1105STATIC void 1106cmdputs(s) 1107 char *s; 1108 { 1109 char *p, *q; 1110 char c; 1111 int subtype = 0; 1112 1113 if (cmdnleft <= 0) 1114 return; 1115 p = s; 1116 q = cmdnextc; 1117 while ((c = *p++) != '\0') { 1118 if (c == CTLESC) 1119 *q++ = *p++; 1120 else if (c == CTLVAR) { 1121 *q++ = '$'; 1122 if (--cmdnleft > 0) 1123 *q++ = '{'; 1124 subtype = *p++; 1125 } else if (c == '=' && subtype != 0) { 1126 *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL]; 1127 subtype = 0; 1128 } else if (c == CTLENDVAR) { 1129 *q++ = '}'; 1130 } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE) 1131 cmdnleft++; /* ignore it */ 1132 else 1133 *q++ = c; 1134 if (--cmdnleft <= 0) { 1135 *q++ = '.'; 1136 *q++ = '.'; 1137 *q++ = '.'; 1138 break; 1139 } 1140 } 1141 cmdnextc = q; 1142} 1143