1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2001 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 /* 31 * Job control for UNIX Shell 32 */ 33 34 #include <sys/termio.h> 35 #include <sys/types.h> 36 #include <sys/wait.h> 37 #include <sys/param.h> 38 #include <fcntl.h> 39 #include <errno.h> 40 #include "defs.h" 41 42 /* 43 * one of these for each active job 44 */ 45 46 struct job 47 { 48 struct job *j_nxtp; /* next job in job ID order */ 49 struct job *j_curp; /* next job in job currency order */ 50 struct termios j_stty; /* termio save area when job stops */ 51 pid_t j_pid; /* job leader's process ID */ 52 pid_t j_pgid; /* job's process group ID */ 53 pid_t j_tgid; /* job's foreground process group ID */ 54 uint j_jid; /* job ID */ 55 ushort j_xval; /* exit code, or exit or stop signal */ 56 ushort j_flag; /* various status flags defined below */ 57 char *j_pwd; /* job's working directory */ 58 char *j_cmd; /* cmd used to invoke this job */ 59 }; 60 61 /* defines for j_flag */ 62 63 #define J_DUMPED 0001 /* job has core dumped */ 64 #define J_NOTIFY 0002 /* job has changed status */ 65 #define J_SAVETTY 0004 /* job was stopped in foreground, and its */ 66 /* termio settings were saved */ 67 #define J_STOPPED 0010 /* job has been stopped */ 68 #define J_SIGNALED 0020 /* job has received signal; j_xval has it */ 69 #define J_DONE 0040 /* job has finished */ 70 #define J_RUNNING 0100 /* job is currently running */ 71 #define J_FOREGND 0200 /* job was put in foreground by shell */ 72 73 /* options to the printjob() function defined below */ 74 75 #define PR_CUR 00001 /* print job currency ('+', '-', or ' ') */ 76 #define PR_JID 00002 /* print job ID */ 77 #define PR_PGID 00004 /* print job's process group ID */ 78 #define PR_STAT 00010 /* print status obtained from wait */ 79 #define PR_CMD 00020 /* print cmd that invoked job */ 80 #define PR_AMP 00040 /* print a '&' if in the background */ 81 #define PR_PWD 00100 /* print jobs present working directory */ 82 83 #define PR_DFL (PR_CUR|PR_JID|PR_STAT|PR_CMD) /* default options */ 84 #define PR_LONG (PR_DFL|PR_PGID|PR_PWD) /* long options */ 85 86 static struct termios mystty; /* default termio settings */ 87 static int eofflg, 88 jobcnt, /* number of active jobs */ 89 jobdone, /* number of active but finished jobs */ 90 jobnote; /* jobs requiring notification */ 91 static pid_t svpgid, /* saved process group ID */ 92 svtgid; /* saved foreground process group ID */ 93 static struct job *jobcur, /* active jobs listed in currency order */ 94 **nextjob, 95 *thisjob, 96 *joblst; /* active jobs listed in job ID order */ 97 98 static void printjob(struct job *, int); 99 100 pid_t 101 tcgetpgrp(fd) 102 { 103 pid_t pgid; 104 if (ioctl(fd, TIOCGPGRP, &pgid) == 0) 105 return (pgid); 106 return ((pid_t)-1); 107 } 108 109 int 110 tcsetpgrp(fd, pgid) 111 int fd; 112 pid_t pgid; 113 { 114 return (ioctl(fd, TIOCSPGRP, &pgid)); 115 } 116 117 static struct job * 118 pgid2job(pid_t pgid) 119 { 120 struct job *jp; 121 122 for (jp = joblst; jp != 0 && jp->j_pid != pgid; jp = jp->j_nxtp) 123 continue; 124 125 return (jp); 126 } 127 128 static struct job * 129 str2job(char *cmd, char *job, int mustbejob) 130 { 131 struct job *jp, *njp; 132 int i; 133 134 if (*job != '%') 135 jp = pgid2job(stoi(job)); 136 else if (*++job == 0 || *job == '+' || *job == '%' || *job == '-') { 137 jp = jobcur; 138 if (*job == '-' && jp) 139 jp = jp->j_curp; 140 } else if (*job >= '0' && *job <= '9') { 141 i = stoi(job); 142 for (jp = joblst; jp && jp->j_jid != i; jp = jp->j_nxtp) 143 continue; 144 } else if (*job == '?') { 145 int j; 146 char *p; 147 i = strlen(++job); 148 jp = 0; 149 for (njp = jobcur; njp; njp = njp->j_curp) { 150 if (njp->j_jid == 0) 151 continue; 152 for (p = njp->j_cmd, j = strlen(p); j >= i; p++, j--) { 153 if (strncmp(job, p, i) == 0) { 154 if (jp != 0) 155 failed((unsigned char *)cmd, 156 ambiguous); 157 jp = njp; 158 break; 159 } 160 } 161 } 162 } else { 163 i = strlen(job); 164 jp = 0; 165 for (njp = jobcur; njp; njp = njp->j_curp) { 166 if (njp->j_jid == 0) 167 continue; 168 if (strncmp(job, njp->j_cmd, i) == 0) { 169 if (jp != 0) 170 failed((unsigned char *)cmd, ambiguous); 171 jp = njp; 172 } 173 } 174 } 175 176 if (mustbejob && (jp == 0 || jp->j_jid == 0)) 177 failed((unsigned char *)cmd, nosuchjob); 178 179 return (jp); 180 } 181 182 static void 183 freejob(struct job *jp) 184 { 185 struct job **njp; 186 struct job **cjp; 187 188 for (njp = &joblst; *njp != jp; njp = &(*njp)->j_nxtp) 189 continue; 190 191 for (cjp = &jobcur; *cjp != jp; cjp = &(*cjp)->j_curp) 192 continue; 193 194 *njp = jp->j_nxtp; 195 *cjp = jp->j_curp; 196 free(jp); 197 jobcnt--; 198 jobdone--; 199 } 200 201 /* 202 * Collect the foreground job. 203 * Used in the case where the subshell wants 204 * to exit, but needs to wait until the fg job 205 * is done. 206 */ 207 void 208 collect_fg_job(void) 209 { 210 struct job *jp; 211 pid_t pid; 212 int stat; 213 214 for (jp = joblst; jp; jp = jp->j_nxtp) 215 if (jp->j_flag & J_FOREGND) 216 break; 217 218 if (!jp) 219 /* no foreground job */ 220 return; 221 222 /* 223 * Wait on fg job until wait succeeds 224 * or it fails due to no waitable children. 225 */ 226 227 while (1) { 228 errno = 0; 229 pid = waitpid(jp->j_pid, &stat, 0); 230 if (pid == jp->j_pid || (pid == -1 && errno == ECHILD)) 231 break; 232 } 233 } 234 235 /* 236 * analyze the status of a job 237 */ 238 239 static int 240 statjob(struct job *jp, int stat, int fg, int rc) 241 { 242 pid_t tgid; 243 int done = 0; 244 245 if (WIFCONTINUED(stat)) { 246 if (jp->j_flag & J_STOPPED) { 247 jp->j_flag &= ~(J_STOPPED|J_SIGNALED|J_SAVETTY); 248 jp->j_flag |= J_RUNNING; 249 if (!fg && jp->j_jid) { 250 jp->j_flag |= J_NOTIFY; 251 jobnote++; 252 } 253 } 254 } else if (WIFSTOPPED(stat)) { 255 jp->j_xval = WSTOPSIG(stat); 256 jp->j_flag &= ~J_RUNNING; 257 jp->j_flag |= (J_SIGNALED|J_STOPPED); 258 jp->j_pgid = getpgid(jp->j_pid); 259 jp->j_tgid = jp->j_pgid; 260 if (fg) { 261 if (tgid = settgid(mypgid, jp->j_pgid)) 262 jp->j_tgid = tgid; 263 else { 264 jp->j_flag |= J_SAVETTY; 265 tcgetattr(0, &jp->j_stty); 266 (void) tcsetattr(0, TCSANOW, &mystty); 267 } 268 } 269 if (jp->j_jid) { 270 jp->j_flag |= J_NOTIFY; 271 jobnote++; 272 } 273 } else { 274 jp->j_flag &= ~J_RUNNING; 275 jp->j_flag |= J_DONE; 276 done++; 277 jobdone++; 278 if (WIFSIGNALED(stat)) { 279 jp->j_xval = WTERMSIG(stat); 280 jp->j_flag |= J_SIGNALED; 281 if (WCOREDUMP(stat)) 282 jp->j_flag |= J_DUMPED; 283 if (!fg || jp->j_xval != SIGINT) { 284 jp->j_flag |= J_NOTIFY; 285 jobnote++; 286 } 287 } else { /* WIFEXITED */ 288 jp->j_xval = WEXITSTATUS(stat); 289 jp->j_flag &= ~J_SIGNALED; 290 if (!fg && jp->j_jid) { 291 jp->j_flag |= J_NOTIFY; 292 jobnote++; 293 } 294 } 295 if (fg) { 296 if (!settgid(mypgid, jp->j_pgid) || 297 !settgid(mypgid, getpgid(jp->j_pid))) 298 tcgetattr(0, &mystty); 299 } 300 } 301 if (rc) { 302 exitval = jp->j_xval; 303 if (jp->j_flag & J_SIGNALED) 304 exitval |= SIGFLG; 305 exitset(); 306 } 307 if (done && !(jp->j_flag & J_NOTIFY)) 308 freejob(jp); 309 return (done); 310 } 311 312 /* 313 * collect the status of jobs that have recently exited or stopped - 314 * if wnohang == WNOHANG, wait until error, or all jobs are accounted for; 315 * 316 * called after each command is executed, with wnohang == 0, and as part 317 * of "wait" builtin with wnohang == WNOHANG 318 * 319 * We do not need to call chktrap here if waitpid(2) is called with 320 * wnohang == 0, because that only happens from syswait() which is called 321 * from builtin() where chktrap() is already called. 322 */ 323 324 static void 325 collectjobs(wnohang) 326 { 327 pid_t pid; 328 struct job *jp; 329 int stat, n; 330 int wflags; 331 332 if ((flags & (monitorflg|jcflg|jcoff)) == (monitorflg|jcflg)) 333 wflags = WUNTRACED|WCONTINUED; 334 else 335 wflags = 0; 336 337 for (n = jobcnt - jobdone; n > 0; n--) { 338 if ((pid = waitpid(-1, &stat, wnohang|wflags)) <= 0) 339 break; 340 if (jp = pgid2job(pid)) 341 (void) statjob(jp, stat, 0, 0); 342 } 343 344 } 345 346 void 347 freejobs() 348 { 349 struct job *jp; 350 351 collectjobs(WNOHANG); 352 353 if (jobnote) { 354 int savefd = setb(2); 355 for (jp = joblst; jp; jp = jp->j_nxtp) { 356 if (jp->j_flag & J_NOTIFY) { 357 if (jp->j_jid) 358 printjob(jp, PR_DFL); 359 else if (jp->j_flag & J_FOREGND) 360 printjob(jp, PR_STAT); 361 else 362 printjob(jp, PR_STAT|PR_PGID); 363 } 364 } 365 (void) setb(savefd); 366 } 367 368 if (jobdone) { 369 for (jp = joblst; jp; jp = jp->j_nxtp) { 370 if (jp->j_flag & J_DONE) 371 freejob(jp); 372 } 373 } 374 } 375 376 static void 377 waitjob(struct job *jp) 378 { 379 int stat; 380 int done; 381 pid_t pid = jp->j_pid; 382 int wflags; 383 int ret = 0; 384 int err = 0; 385 386 if ((flags & (monitorflg|jcflg|jcoff)) == (monitorflg|jcflg)) 387 wflags = WUNTRACED; 388 else 389 wflags = 0; 390 do { 391 errno = 0; 392 ret = waitpid(pid, &stat, wflags|WNOWAIT); 393 err = errno; 394 if (ret == -1 && err == ECHILD) { 395 stat = 0; 396 break; 397 } 398 } while (ret != pid); 399 400 done = statjob(jp, stat, 1, 1); 401 waitpid(pid, 0, wflags); 402 if (done && exitval && (flags & errflg)) 403 exitsh(exitval); 404 flags |= eflag; 405 } 406 407 /* 408 * modify the foreground process group to *new* only if the 409 * current foreground process group is equal to *expected* 410 */ 411 412 int 413 settgid(new, expected) 414 pid_t new, expected; 415 { 416 pid_t current = tcgetpgrp(0); 417 418 if (current != expected) 419 return (current); 420 421 if (new != current) 422 tcsetpgrp(0, new); 423 424 return (0); 425 } 426 427 static void 428 restartjob(struct job *jp, int fg) 429 { 430 if (jp != jobcur) { 431 struct job *t; 432 for (t = jobcur; t->j_curp != jp; t = t->j_curp); 433 t->j_curp = jp->j_curp; 434 jp->j_curp = jobcur; 435 jobcur = jp; 436 } 437 if (fg) { 438 if (jp->j_flag & J_SAVETTY) { 439 jp->j_stty.c_lflag &= ~TOSTOP; 440 jp->j_stty.c_lflag |= (mystty.c_lflag&TOSTOP); 441 jp->j_stty.c_cc[VSUSP] = mystty.c_cc[VSUSP]; 442 jp->j_stty.c_cc[VDSUSP] = mystty.c_cc[VDSUSP]; 443 (void) tcsetattr(0, TCSADRAIN, &jp->j_stty); 444 } 445 (void) settgid(jp->j_tgid, mypgid); 446 } 447 (void) kill(-(jp->j_pgid), SIGCONT); 448 if (jp->j_tgid != jp->j_pgid) 449 (void) kill(-(jp->j_tgid), SIGCONT); 450 jp->j_flag &= ~(J_STOPPED|J_SIGNALED|J_SAVETTY); 451 jp->j_flag |= J_RUNNING; 452 if (fg) { 453 jp->j_flag |= J_FOREGND; 454 printjob(jp, PR_JID|PR_CMD); 455 waitjob(jp); 456 } else { 457 jp->j_flag &= ~J_FOREGND; 458 printjob(jp, PR_JID|PR_CMD|PR_AMP); 459 } 460 } 461 462 static void 463 printjob(struct job *jp, int propts) 464 { 465 int sp = 0; 466 467 if (jp->j_flag & J_NOTIFY) { 468 jobnote--; 469 jp->j_flag &= ~J_NOTIFY; 470 } 471 472 if (propts & PR_JID) { 473 prc_buff('['); 474 prn_buff(jp->j_jid); 475 prc_buff(']'); 476 sp = 1; 477 } 478 479 if (propts & PR_CUR) { 480 while (sp-- > 0) 481 prc_buff(SPACE); 482 sp = 1; 483 if (jobcur == jp) 484 prc_buff('+'); 485 else if (jobcur != 0 && jobcur->j_curp == jp) 486 prc_buff('-'); 487 else 488 sp++; 489 } 490 491 if (propts & PR_PGID) { 492 while (sp-- > 0) 493 prc_buff(SPACE); 494 prn_buff(jp->j_pid); 495 sp = 1; 496 } 497 498 if (propts & PR_STAT) { 499 while (sp-- > 0) 500 prc_buff(SPACE); 501 sp = 28; 502 if (jp->j_flag & J_SIGNALED) { 503 char *sigstr, *strsignal(); 504 if ((sigstr = strsignal(jp->j_xval)) != NULL) { 505 sp -= strlen(sigstr); 506 prs_buff(sigstr); 507 } else { 508 itos(jp->j_xval); 509 sp -= strlen(numbuf) + 7; 510 prs_buff("Signal "); 511 prs_buff(numbuf); 512 } 513 if (jp->j_flag & J_DUMPED) { 514 sp -= strlen(coredump); 515 prs_buff(coredump); 516 } 517 } else if (jp->j_flag & J_DONE) { 518 itos(jp->j_xval); 519 sp -= strlen(exited) + strlen(numbuf) + 2; 520 prs_buff(exited); 521 prc_buff('('); 522 itos(jp->j_xval); 523 prs_buff(numbuf); 524 prc_buff(')'); 525 } else { 526 sp -= strlen(running); 527 prs_buff(running); 528 } 529 if (sp < 1) 530 sp = 1; 531 } 532 533 if (propts & PR_CMD) { 534 while (sp-- > 0) 535 prc_buff(SPACE); 536 prs_buff(jp->j_cmd); 537 sp = 1; 538 } 539 540 if (propts & PR_AMP) { 541 while (sp-- > 0) 542 prc_buff(SPACE); 543 prc_buff('&'); 544 sp = 1; 545 } 546 547 if (propts & PR_PWD) { 548 while (sp-- > 0) 549 prc_buff(SPACE); 550 prs_buff("(wd: "); 551 prs_buff(jp->j_pwd); 552 prc_buff(')'); 553 } 554 555 prc_buff(NL); 556 flushb(); 557 558 } 559 560 561 /* 562 * called to initialize job control for each new input file to the shell, 563 * and after the "exec" builtin 564 */ 565 566 void 567 startjobs() 568 { 569 svpgid = mypgid; 570 571 if (tcgetattr(0, &mystty) == -1 || (svtgid = tcgetpgrp(0)) == -1) { 572 flags &= ~jcflg; 573 return; 574 } 575 576 flags |= jcflg; 577 578 handle(SIGTTOU, SIG_IGN); 579 handle(SIGTSTP, SIG_DFL); 580 581 if (mysid != mypgid) { 582 setpgid(0, 0); 583 mypgid = mypid; 584 (void) settgid(mypgid, svpgid); 585 } 586 587 } 588 589 int 590 endjobs(check_if) 591 int check_if; 592 { 593 if ((flags & (jcoff|jcflg)) != jcflg) 594 return (1); 595 596 if (check_if && jobcnt && eofflg++ == 0) { 597 struct job *jp; 598 if (check_if & JOB_STOPPED) { 599 for (jp = joblst; jp; jp = jp->j_nxtp) { 600 if (jp->j_jid && (jp->j_flag & J_STOPPED)) { 601 prs(jobsstopped); 602 prc(NL); 603 return (0); 604 } 605 } 606 } 607 if (check_if & JOB_RUNNING) { 608 for (jp = joblst; jp; jp = jp->j_nxtp) { 609 if (jp->j_jid && (jp->j_flag & J_RUNNING)) { 610 prs(jobsrunning); 611 prc(NL); 612 return (0); 613 } 614 } 615 } 616 } 617 618 if (svpgid != mypgid) { 619 (void) settgid(svtgid, mypgid); 620 setpgid(0, svpgid); 621 } 622 623 return (1); 624 } 625 626 627 /* 628 * called by the shell to reserve a job slot for a job about to be spawned 629 */ 630 631 void 632 deallocjob() 633 { 634 free(thisjob); 635 jobcnt--; 636 } 637 638 void 639 allocjob(char *cmd, unchar *cwd, int monitor) 640 { 641 struct job *jp, **jpp; 642 int jid, cmdlen, cwdlen; 643 644 cmdlen = strlen(cmd) + 1; 645 if (cmd[cmdlen-2] == '&') { 646 cmd[cmdlen-3] = 0; 647 cmdlen -= 2; 648 } 649 cwdlen = strlen(cwd) + 1; 650 jp = (struct job *) alloc(sizeof (struct job) + cmdlen + cwdlen); 651 if (jp == 0) 652 error(nostack); 653 jobcnt++; 654 jp->j_cmd = ((char *)jp) + sizeof (struct job); 655 strcpy(jp->j_cmd, cmd); 656 jp->j_pwd = jp->j_cmd + cmdlen; 657 strcpy(jp->j_pwd, cwd); 658 659 jpp = &joblst; 660 661 if (monitor) { 662 for (; *jpp; jpp = &(*jpp)->j_nxtp) 663 if ((*jpp)->j_jid != 0) 664 break; 665 for (jid = 1; *jpp; jpp = &(*jpp)->j_nxtp, jid++) 666 if ((*jpp)->j_jid != jid) 667 break; 668 } else 669 jid = 0; 670 671 jp->j_jid = jid; 672 nextjob = jpp; 673 thisjob = jp; 674 } 675 676 void 677 clearjobs(void) 678 { 679 struct job *jp, *sjp; 680 681 for (jp = joblst; jp; jp = sjp) { 682 sjp = jp->j_nxtp; 683 free(jp); 684 } 685 joblst = NULL; 686 jobcnt = 0; 687 jobnote = 0; 688 jobdone = 0; 689 690 } 691 692 void 693 makejob(int monitor, int fg) 694 { 695 if (monitor) { 696 mypgid = mypid; 697 setpgid(0, 0); 698 if (fg) 699 tcsetpgrp(0, mypid); 700 handle(SIGTTOU, SIG_DFL); 701 handle(SIGTSTP, SIG_DFL); 702 } else if (!fg) { 703 #ifdef NICE 704 nice(NICE); 705 #endif 706 handle(SIGTTIN, SIG_IGN); 707 handle(SIGINT, SIG_IGN); 708 handle(SIGQUIT, SIG_IGN); 709 if (!ioset) 710 renamef(chkopen(devnull, 0), 0); 711 } 712 } 713 714 /* 715 * called by the shell after job has been spawned, to fill in the 716 * job slot, and wait for the job if in the foreground 717 */ 718 719 void 720 postjob(pid, fg) 721 pid_t pid; 722 int fg; 723 { 724 725 int propts; 726 727 thisjob->j_nxtp = *nextjob; 728 *nextjob = thisjob; 729 thisjob->j_curp = jobcur; 730 jobcur = thisjob; 731 732 if (thisjob->j_jid) { 733 thisjob->j_pgid = pid; 734 propts = PR_JID|PR_PGID; 735 } else { 736 thisjob->j_pgid = mypgid; 737 propts = PR_PGID; 738 } 739 740 thisjob->j_flag = J_RUNNING; 741 thisjob->j_tgid = thisjob->j_pgid; 742 thisjob->j_pid = pid; 743 eofflg = 0; 744 745 if (fg) { 746 thisjob->j_flag |= J_FOREGND; 747 waitjob(thisjob); 748 } else { 749 if (flags & ttyflg) 750 printjob(thisjob, propts); 751 assnum(&pcsadr, (long)pid); 752 } 753 } 754 755 /* 756 * the builtin "jobs" command 757 */ 758 759 void 760 sysjobs(argc, argv) 761 int argc; 762 char *argv[]; 763 { 764 char *cmd = *argv; 765 struct job *jp; 766 int propts, c; 767 extern int opterr, i; 768 int savoptind = optind; 769 int loptind = -1; 770 int savopterr = opterr; 771 int savsp = _sp; 772 char *savoptarg = optarg; 773 optind = 1; 774 opterr = 0; 775 _sp = 1; 776 propts = 0; 777 778 if ((flags & jcflg) == 0) 779 failed((unsigned char *)cmd, nojc); 780 781 while ((c = getopt(argc, argv, "lpx")) != -1) { 782 if (propts) { 783 failure(usage, jobsuse); 784 goto err; 785 } 786 switch (c) { 787 case 'x': 788 propts = -1; 789 break; 790 case 'p': 791 propts = PR_PGID; 792 break; 793 case 'l': 794 propts = PR_LONG; 795 break; 796 case '?': 797 failure(usage, jobsuse); 798 goto err; 799 } 800 } 801 802 loptind = optind; 803 err: 804 optind = savoptind; 805 optarg = savoptarg; 806 opterr = savopterr; 807 _sp = savsp; 808 if (loptind == -1) 809 return; 810 811 if (propts == -1) { 812 unsigned char *bp; 813 char *cp; 814 unsigned char *savebp; 815 for (savebp = bp = locstak(); loptind < argc; loptind++) { 816 cp = argv[loptind]; 817 if (*cp == '%') { 818 jp = str2job(cmd, cp, 1); 819 itos(jp->j_pid); 820 cp = (char *)numbuf; 821 } 822 while (*cp) { 823 if (bp >= brkend) 824 growstak(bp); 825 *bp++ = *cp++; 826 } 827 if (bp >= brkend) 828 growstak(bp); 829 *bp++ = SPACE; 830 } 831 endstak(bp); 832 execexp(savebp, 0); 833 return; 834 } 835 836 collectjobs(WNOHANG); 837 838 if (propts == 0) 839 propts = PR_DFL; 840 841 if (loptind == argc) { 842 for (jp = joblst; jp; jp = jp->j_nxtp) { 843 if (jp->j_jid) 844 printjob(jp, propts); 845 } 846 } else do 847 printjob(str2job(cmd, argv[loptind++], 1), propts); 848 while (loptind < argc); 849 850 } 851 852 /* 853 * the builtin "fg" and "bg" commands 854 */ 855 void 856 sysfgbg(int argc, char *argv[]) 857 { 858 char *cmd = *argv; 859 int fg; 860 861 if ((flags & jcflg) == 0) 862 failed((unsigned char *)cmd, nojc); 863 864 fg = eq("fg", cmd); 865 866 if (*++argv == 0) { 867 struct job *jp; 868 for (jp = jobcur; ; jp = jp->j_curp) { 869 if (jp == 0) 870 failed((unsigned char *)cmd, nocurjob); 871 if (jp->j_jid) 872 break; 873 } 874 restartjob(jp, fg); 875 } 876 877 else do 878 restartjob(str2job(cmd, *argv, 1), fg); 879 while (*++argv); 880 881 } 882 883 /* 884 * the builtin "wait" commands 885 */ 886 887 void 888 syswait(argc, argv) 889 int argc; 890 char *argv[]; 891 { 892 char *cmd = *argv; 893 struct job *jp; 894 int stat; 895 int wflags; 896 897 if ((flags & (monitorflg|jcflg|jcoff)) == (monitorflg|jcflg)) 898 wflags = WUNTRACED; 899 else 900 wflags = 0; 901 902 if (argc == 1) 903 collectjobs(0); 904 else while (--argc) { 905 if ((jp = str2job(cmd, *++argv, 0)) == 0) 906 continue; 907 if (!(jp->j_flag & J_RUNNING)) 908 continue; 909 if (waitpid(jp->j_pid, &stat, wflags) <= 0) 910 break; 911 (void) statjob(jp, stat, 0, 1); 912 } 913 } 914 915 static void 916 sigv(char *cmd, int sig, char *args) 917 { 918 int pgrp = 0; 919 int stopme = 0; 920 pid_t id; 921 922 if (*args == '%') { 923 struct job *jp; 924 jp = str2job(cmd, args, 1); 925 id = jp->j_pgid; 926 pgrp++; 927 } else { 928 if (*args == '-') { 929 pgrp++; 930 args++; 931 } 932 id = 0; 933 do { 934 if (*args < '0' || *args > '9') { 935 failure(cmd, badid); 936 return; 937 } 938 id = (id * 10) + (*args - '0'); 939 } while (*++args); 940 if (id == 0) { 941 id = mypgid; 942 pgrp++; 943 } 944 } 945 946 if (sig == SIGSTOP) { 947 if (id == mysid || id == mypid && mypgid == mysid) { 948 failure(cmd, loginsh); 949 return; 950 } 951 if (id == mypgid && mypgid != svpgid) { 952 (void) settgid(svtgid, mypgid); 953 setpgid(0, svpgid); 954 stopme++; 955 } 956 } 957 958 if (pgrp) 959 id = -id; 960 961 if (kill(id, sig) < 0) { 962 963 switch (errno) { 964 case EPERM: 965 failure(cmd, eacces); 966 break; 967 968 case EINVAL: 969 failure(cmd, badsig); 970 break; 971 972 default: 973 if (pgrp) 974 failure(cmd, nosuchpgid); 975 else 976 failure(cmd, nosuchpid); 977 break; 978 } 979 980 } else if (sig == SIGTERM && pgrp) 981 (void) kill(id, SIGCONT); 982 983 if (stopme) { 984 setpgid(0, mypgid); 985 (void) settgid(mypgid, svpgid); 986 } 987 988 } 989 990 void 991 sysstop(int argc, char *argv[]) 992 { 993 char *cmd = *argv; 994 if (argc <= 1) 995 failed((unsigned char *)usage, stopuse); 996 while (*++argv) 997 sigv(cmd, SIGSTOP, *argv); 998 } 999 1000 void 1001 syskill(int argc, char *argv[]) 1002 { 1003 char *cmd = *argv; 1004 int sig = SIGTERM; 1005 1006 if (argc == 1) { 1007 failure(usage, killuse); 1008 return; 1009 } 1010 1011 if (argv[1][0] == '-') { 1012 1013 if (argc == 2) { 1014 1015 int i; 1016 int cnt = 0; 1017 char sep = 0; 1018 char buf[12]; 1019 1020 if (!eq(argv[1], "-l")) { 1021 failure(usage, killuse); 1022 return; 1023 } 1024 1025 for (i = 1; i < MAXTRAP; i++) { 1026 if (sig2str(i, buf) < 0) 1027 continue; 1028 if (sep) 1029 prc_buff(sep); 1030 prs_buff(buf); 1031 if ((flags & ttyflg) && (++cnt % 10)) 1032 sep = TAB; 1033 else 1034 sep = NL; 1035 } 1036 prc_buff(NL); 1037 return; 1038 } 1039 1040 if (str2sig(&argv[1][1], &sig)) { 1041 failure(cmd, badsig); 1042 return; 1043 } 1044 argv++; 1045 } 1046 1047 while (*++argv) 1048 sigv(cmd, sig, *argv); 1049 1050 } 1051 1052 void 1053 syssusp(int argc, char *argv[]) 1054 { 1055 if (argc != 1) 1056 failed((unsigned char *)argv[0], badopt); 1057 sigv(argv[0], SIGSTOP, "0"); 1058 } 1059