1 #define USE_OLD_TTY 2 /* 3 4 * Copyright (c) 1984, 1985, 1986 AT&T 5 * All Rights Reserved 6 7 * THIS IS UNPUBLISHED PROPRIETARY SOURCE 8 * CODE OF AT&T. 9 * The copyright notice above does not 10 * evidence any actual or intended 11 * publication of such source code. 12 13 */ 14 /* @(#)jobs.c 1.1 */ 15 16 /* 17 * Job control for UNIX Shell 18 * 19 * David Korn 20 * AT&T Bell Laboratories 21 * Room 5D-112 22 * Murray Hill, N. J. 07974 23 * Tel. x7975 24 * 25 * Written October, 1982 26 */ 27 28 29 #include <errno.h> 30 31 #ifdef BSD 32 # ifdef BSD_4_2 33 #include <sys/wait.h> 34 # else 35 #include <wait.h> 36 # endif /* BSD_4_2 */ 37 #endif /* BSD */ 38 39 #ifdef SXT 40 #define SIGSTOP 20 41 #define SIGSTIN 21 42 #include <sys/types.h> 43 #include <sys/tty.h> 44 #include <sys/sxt.h> 45 #include <sys/stat.h> 46 #endif /* SXT */ 47 48 #include "defs.h" 49 #include "flags.h" 50 #include "shtype.h" 51 #include "jobs.h" 52 #include "brkincr.h" 53 #include "io.h" 54 #include "history.h" 55 56 #ifdef SXT 57 #undef input 58 static status_update(); 59 static int open_chan(); 60 static int fd_chan = -1; 61 static char tinybuf; 62 #endif /* SXT */ 63 64 #define LOBYTE 0377 65 #define MAXMSG 25 66 67 void await(); 68 void postclr(); 69 70 extern void fault(); 71 extern long hist_list(); 72 extern long hist_position(); 73 extern char *itos(); 74 extern char *malloc(); 75 extern void failed(); 76 extern void free(); 77 extern void p_str(); 78 extern void p_prp(); 79 extern void p_num(); 80 extern void p_sub(); 81 extern void p_nchr(); 82 extern void p_flush(); 83 extern void p_setout(); 84 85 static int set_ttygrp(); 86 static int set_job(); 87 static int reset_ttygrp(); 88 static struct process *next_proc(); 89 static struct process *jobbyname(); 90 static struct process *job_bynum(); 91 static struct process *job_bypid(); 92 static struct process *job_post(); 93 static struct process *unpost(); 94 static struct process *pgrp_jobs(); 95 static int get_job(); 96 static int match_jobname(); 97 static int unstop(); 98 static void free_job(); 99 static void pw_unlink(); 100 static struct process *freelist; 101 #define numrun jobstat.p_numrun /* number of running jobs */ 102 #define numpost jobstat.p_numpost /* number of posted jobs */ 103 #define pwlist jobstat.p_pwlist 104 #define freejobs jobstat.p_freejobs /* free job numbers */ 105 static long pr_jobname(); 106 107 #ifdef FIOLOOKLD 108 #define version8 1 109 extern int tty_ld, ntty_ld; 110 #define OTTYDISC tty_ld 111 #define NTTYDISC ntty_ld 112 #endif /* FIOLOOKLD */ 113 114 115 static int savepgrp; 116 static int savetgrp; 117 static BOOL old_driver; 118 static BOOL beenhere; 119 static int saveldisc; 120 121 #ifdef POSIX 122 static struct termios my_stty; /* terminal state for shell */ 123 #else 124 # ifdef BSD 125 static struct sgttyb my_stty; /* terminal state for shell */ 126 # else 127 static struct termio my_stty; /* terminal state for shell */ 128 # endif /* BSD */ 129 #endif /* !POSIX */ 130 131 #ifdef BSD 132 /* 133 * initialize job control 134 * if lflag is set the switching driver message will not print 135 */ 136 137 int init_jobs(lflag) 138 { 139 int ldisc; 140 register int ntry = 0; 141 register int pid; 142 jobstat.mypid = pid = getpid(); 143 savepgrp = getpgrp(pid); 144 # ifdef version8 145 if((ldisc = ioctl (2, FIOLOOKLD, 0)) <0) 146 # else 147 if(ioctl(2,TIOCGETD,&ldisc) !=0) 148 # endif /* version8 */ 149 return(-1); 150 if(ldisc!=NTTYDISC 151 #ifdef notdef /*POSIX*/ 152 && ldisc!=POSXDISC 153 #endif 154 && ldisc!=OTTYDISC) 155 { 156 /* no job control when running with MPX */ 157 # ifdef VSH 158 on_option(VIRAW); 159 # endif /* VSH */ 160 return(-1); 161 } 162 retry: 163 signal(SIGTTOU,SIG_IGN); 164 if(ioctl(2,TIOCGPGRP,&savetgrp) !=0) 165 { 166 fputs(j_not_tty,output); 167 return(-1); 168 } 169 /* This shell must be in foreground to change state */ 170 if(savetgrp != savepgrp) 171 { 172 signal(SIGTTOU,SIG_DFL); 173 kill(pid,SIGTTOU); 174 /* wait for continue and try again */ 175 if(ntry++ > 100) 176 { 177 fputs(j_no_start,output); 178 return(-1); 179 } 180 goto retry; 181 } 182 #ifdef notdef /*POSIX*/ 183 if(ldisc != POSXDISC) 184 { 185 saveldisc = ldisc; 186 ldisc = POSXDISC; 187 #else 188 if(ldisc == OTTYDISC) 189 { 190 ldisc = NTTYDISC; 191 #endif 192 # ifdef version8 193 ioctl(2,TIOCGETP,&my_stty); 194 if (ioctl(2, FIOPOPLD, 0) < 0) 195 return(-1); 196 if (ioctl(2, FIOPUSHLD, &ldisc, 0) < 0) 197 { 198 ldisc = OTTYDISC; 199 ioctl(2, FIOPUSHLD, &ldisc, 0); 200 return(-1); 201 } 202 ioctl(2,TIOCSETN,&my_stty); 203 # else 204 if(ioctl(2,TIOCSETD,&ldisc) !=0) 205 return(-1); 206 # endif /* version8 */ 207 if(lflag==0) 208 { 209 fputs(j_newtty,output); 210 old_driver++; 211 } 212 } 213 on_option(MONITOR); 214 signal(SIGCHLD,fault); 215 signal(SIGTSTP,SIG_IGN); 216 signal(SIGTTIN,SIG_IGN); 217 setpgrp(pid,pid); 218 set_ttygrp(pid); 219 return(0); 220 } 221 222 223 /* 224 * see if there are any stopped jobs 225 * restore tty driver and pgrp 226 */ 227 228 int close_jobs() 229 { 230 register struct process *pw = pwlist; 231 register int count = 0; 232 int ldisc; 233 if((states&MONITOR)==0) 234 return(0); 235 for(;pw;pw=pw->p_next) 236 { 237 if((pw->p_flag&P_STOPPED)==0) 238 continue; 239 if(beenhere) 240 killpg(pw->p_pgrp,SIGTERM); 241 count++; 242 } 243 if(beenhere++ == 0 && pwlist) 244 { 245 if(count) 246 { 247 fputs(j_terminate,output); 248 return(-1); 249 } 250 else if(login_sh) 251 { 252 fputs(j_running,output); 253 return(-1); 254 } 255 } 256 set_ttygrp(savepgrp); 257 if(old_driver) 258 { 259 /* restore old line discipline */ 260 #ifdef POSIX 261 ldisc = saveldisc; 262 #else 263 ldisc = OTTYDISC; 264 #endif 265 # ifdef version8 266 ioctl(2,TIOCGETP,&my_stty); 267 if (ioctl(2, FIOPOPLD, 0) < 0) 268 return(0); 269 if (ioctl(2, FIOPUSHLD, &ldisc, 0) < 0) 270 { 271 ldisc = NTTYDISC; 272 ioctl(2, FIOPUSHLD, &ldisc, 0); 273 return(0); 274 } 275 ioctl(2,TIOCSETN,&my_stty); 276 # else 277 if(ioctl(2,TIOCSETD,&ldisc) !=0) 278 return(0); 279 # endif /* version8 */ 280 fputs(j_oldtty,output); 281 } 282 return(0); 283 } 284 285 /* 286 * Set the ttygroup id to pid 287 */ 288 289 static int set_ttygrp(pid) 290 { 291 if(ioctl(2,TIOCSPGRP,&pid) !=0) 292 return(-1); 293 return(0); 294 } 295 296 /* 297 * Set the ttygroup id to a previously running job 298 */ 299 #else /* !BSD */ 300 # ifdef SXT 301 static char sxt[] = "/dev/sxt/000"; 302 static struct sxtblock status1,status2; 303 304 int init_jobs(lflag) 305 { 306 register int pid; 307 register int dev; 308 struct stat statbuf; 309 jobstat.mypid = pid = getpid(); 310 savepgrp = getpgrp(pid); 311 if(ioctl(2,SXTIOCSTAT,&status2) < 0) 312 return(-1); 313 if(ioctl(2,TCGETA,&my_stty) < 0) 314 return(-1); 315 if(fstat(2,&statbuf) < 0) 316 return(-1); 317 dev = statbuf.st_rdev&0xff; 318 /* must be channel 0 */ 319 if(dev&07) 320 return(-1); 321 dev >>= 3; 322 sxt[10] = '0' + (dev%10); 323 sxt[9] = '0' + dev/10; 324 my_stty.c_cc[VSWTCH] = CSWTCH; 325 if(ioctl(2,TCSETAF,&my_stty) < 0) 326 return(-1); 327 setpgrp(pid,pid); 328 jobstat.maxjob = MAXPCHAN; 329 on_option(MONITOR); 330 return(0); 331 } 332 #endif /* SXT */ 333 334 int close_jobs() 335 { 336 register struct process *pw = pwlist; 337 register int count = 0; 338 if((states&MONITOR)==0) 339 return(0); 340 # ifdef SXT 341 for(;pw;pw=pw->p_next) 342 { 343 if((pw->p_flag&P_STOPPED)==0) 344 continue; 345 if(beenhere) 346 kill(-pw->p_pgrp,SIGTERM); 347 count++; 348 } 349 # endif /* SXT */ 350 if(beenhere++ == 0 && pwlist && login_sh) 351 # ifdef SXT 352 { 353 if(count) 354 { 355 fputs(j_terminate,output); 356 return(-1); 357 } 358 if(login_sh || jobstat.maxjob) 359 # endif /* SXT */ 360 { 361 fputs(j_running,output); 362 return(-1); 363 } 364 # ifdef SXT 365 } 366 if(jobstat.maxjob) 367 kill_all(); 368 # endif /* SXT */ 369 return(0); 370 } 371 372 #endif /* !BSD */ 373 374 static int set_job(pw) 375 register struct process *pw; 376 { 377 /* save current terminal state */ 378 #if defined(BSD) && !defined(POSIX) 379 ioctl(2,TIOCGETP,&my_stty); 380 #else 381 ioctl(2,TCGETA,&my_stty); 382 #endif /* BSD */ 383 #ifdef SXT 384 /* make sure child has opened channel */ 385 if(jobstat.pipe[0] > 0) 386 { 387 read(jobstat.pipe[0],&tinybuf,1); 388 close(jobstat.pipe[0]); 389 jobstat.pipe[0] = 0; 390 } 391 if(pw->p_job < jobstat.maxjob) 392 if(ioctl(2,SXTIOCSWTCH,pw->p_job)!=0) 393 { 394 return(-1); 395 } 396 #endif /* SXT */ 397 if(pw->p_flag&P_STTY) 398 { 399 /* restore terminal state for job */ 400 #if defined(BSD) && !defined(POSIX) 401 ioctl(2,TIOCSETN,&pw->p_stty); 402 #else 403 ioctl(2,TCSETAF,&pw->p_stty); 404 #endif /* BSD */ 405 } 406 #ifdef BSD 407 if(ioctl(2,TIOCSPGRP,&pw->p_pgrp) !=0) 408 return(-1); 409 #endif /* BSD */ 410 return(0); 411 } 412 413 static int reset_ttygrp(pw,flag) 414 register struct process *pw; 415 { 416 /* save the terminal state for current job */ 417 #ifdef BSD 418 if(ioctl(2,TIOCSPGRP,&jobstat.mypid) !=0) 419 { 420 return(-1); 421 } 422 #endif /* BSD */ 423 #ifdef SXT 424 if(pw && pw->p_job < jobstat.maxjob) 425 { 426 /* save the state of terminated process */ 427 if(flag==0 && fd_chan>=0) 428 { 429 if(ioctl(fd_chan,TCGETA,&pw->p_stty)==0) 430 { 431 my_stty = pw->p_stty; 432 /* for timing problem */ 433 ioctl(fd_chan,TCSETAW,&my_stty); 434 } 435 } 436 close(fd_chan); 437 fd_chan = -1; 438 /* grab control in channel 0 */ 439 ioctl(2,TCSETAW,&my_stty); 440 if(ioctl(2,SXTIOCSWTCH,0)!=0) 441 { 442 return(-1); 443 } 444 if(flag==0) 445 ioctl(2,TCSETAW,&my_stty); 446 beenhere = 0; 447 return(0); 448 } 449 #endif /* SXT */ 450 if(pw && flag) 451 { 452 #if defined(BSD) && !defined(POSIX) 453 if(ioctl(2,TIOCGETP,&pw->p_stty) == 0) 454 #else 455 if(ioctl(2,TCGETA,&pw->p_stty) == 0) 456 #endif /* BSD */ 457 pw->p_flag |= P_STTY; 458 /* restore terminal state for job */ 459 #if defined(BSD) && !defined(POSIX) 460 ioctl(2,TIOCSETN,&my_stty); 461 #else 462 ioctl(2,TCSETAF,&my_stty); 463 #endif /* BSD */ 464 } 465 beenhere = 0; 466 return(0); 467 } 468 469 #if BSD || SXT 470 471 /* 472 * move job to foreground if bgflag == 0 473 * move job to background if bgflag != 0 474 */ 475 476 switch_jobs(ajob,bgflag) 477 register char *ajob; 478 { 479 register struct process *pw=NULL; 480 register int pgrp; 481 # ifdef SXT 482 if(jobstat.maxjob==0) 483 return(NULL); 484 # endif /* SXT */ 485 if(*ajob) 486 pw = pgrp_jobs(ajob); 487 else if(pwlist) 488 pw = job_bynum((int)pwlist->p_job); 489 if(pw) 490 { 491 if(bgflag) 492 { 493 pgrp = pw->p_pgrp; 494 if(pw->p_flag&P_STOPPED) 495 { 496 p_sub((int)pw->p_job,'\t'); 497 pr_jobname(pw,'&',0L); 498 fputs(j_amp,output); 499 unstop(pgrp); 500 } 501 } 502 else 503 { 504 pw_unlink(pw); 505 pw->p_next = pwlist; 506 pwlist = pw; 507 pr_jobname(pw,'&',0L); 508 newline(); 509 await(pw->p_pid,3); 510 } 511 } 512 return(pw!=NULL); 513 } 514 515 /* 516 * list the current jobs 517 * flag L_FLAG for long listing 518 * flag N_FLAG for list only jobs marked for notification 519 */ 520 #endif /* BSD */ 521 522 list_jobs(flag) 523 int flag; 524 { 525 register struct process *pw; 526 register struct process *px; 527 register int m; 528 register struct process *py; 529 int n; 530 long offset; 531 int jobm = 0; 532 register char *msg; 533 int msize; 534 if(pwlist==NULL) 535 return; 536 await(0,2); 537 p_setout(standout); 538 /* get job number corresponding to '-' */ 539 if(pw=pgrp_jobs("%-")) 540 jobm = pw->p_job; 541 for(pw=pwlist;pw;pw=py) 542 { 543 py = pw->p_next; 544 if(pw->p_flag&P_PIPEJOB) 545 continue; 546 if((flag&N_FLAG) && (pw->p_flag&P_NOTIFY)==0) 547 continue; 548 n = pw->p_job; 549 p_sub(n,' '); 550 m = ' '; 551 if(pw->p_job==pwlist->p_job) 552 m = '+'; 553 else if(pw->p_job==jobm) 554 { 555 m = '-'; 556 jobm = 0; 557 } 558 putc(m,output); 559 putc(' ',output); 560 offset = 0; 561 if(flag&L_FLAG) 562 px = next_proc(pwlist,(int)pw->p_job); 563 else 564 px = pw; 565 do 566 { 567 unsigned xitval = 0; 568 if(flag&L_FLAG) 569 p_num(px->p_pid,'\t'); 570 if(px->p_sig&0177) 571 msg = sysmsg[px->p_sig&0177]; 572 else if(px->p_flag&P_NOTIFY) 573 { 574 msg = j_Done; 575 xitval = px->p_sig>>8; 576 } 577 else 578 msg = j_Running; 579 fputs(msg,output); 580 msize = strlen(msg); 581 if(xitval) 582 { 583 putc('(',output); 584 p_num((int)xitval,')'); 585 msize += (3+(xitval>10)+(xitval>100)); 586 } 587 if(px->p_flag&P_COREDUMP) 588 { 589 fputs(j_coredump,output); 590 msize += strlen(j_coredump); 591 } 592 p_nchr(SP,MAXMSG-msize); 593 if(flag&L_FLAG) 594 px = next_proc(px->p_next,(int)pw->p_job); 595 else 596 px = NULL; 597 offset = pr_jobname(pw,(px?'|':0),offset); 598 if(flag&L_FLAG) 599 { 600 if(px) 601 fputs(j_space,output); 602 else if(pw->p_pid == cpid) 603 fputs(j_cpid,output); 604 } 605 } 606 while(px); 607 if(pw->p_flag&P_STOPPED) 608 pw->p_flag &= ~P_NOTIFY; 609 else if(pw->p_flag&P_NOTIFY) 610 { 611 unpost(pw); 612 if(jobm && (px=pgrp_jobs("%-"))) 613 jobm = px->p_job; 614 } 615 } 616 } 617 618 /* 619 * return the pointer of next process with given job number after slot px 620 */ 621 622 static struct process * next_proc(pw,job) 623 register struct process *pw; 624 register int job; 625 { 626 for(;pw;pw=pw->p_next) 627 { 628 if(pw->p_job == job) 629 return(pw); 630 } 631 return(NULL); 632 } 633 634 /* 635 * print the command 636 * Stop the output if character <ch> encountered 637 */ 638 639 static long pr_jobname(pw,ch,offset) 640 register struct process *pw; 641 register long offset; 642 int ch; 643 { 644 if(fc_fix) 645 { 646 offset = hist_list(pw->p_name+offset,ch,";"); 647 offset -= pw->p_name; 648 } 649 return(++offset); 650 } 651 652 /* 653 * get the process group given the job number 654 * This routine returns the process group number or -1 655 */ 656 657 static struct process *pgrp_jobs(ajob) 658 register char *ajob; 659 { 660 register struct process *pw; 661 register int c; 662 if(*ajob++ != '%' || pwlist==NULL) 663 return(NULL); 664 c = *ajob; 665 if(isdigit(c)) 666 pw = job_bynum(atoi(ajob)); 667 else if(c=='+' || c=='%') 668 pw = job_bynum((int)pwlist->p_job); 669 else if(c=='-') 670 { 671 /* find the second jobnumber on the list */ 672 for(pw=pwlist->p_next;pw && pw->p_job==pwlist->p_job;pw=pw->p_next); 673 if(pw==NULL) 674 return(pw); 675 pw = job_bynum((int)pw->p_job); 676 } 677 else 678 pw = jobbyname(ajob); 679 if(pw && pw->p_flag) 680 return(pw); 681 return(NULL); 682 } 683 684 /* 685 * send a hang-up signal to each of the jobs 686 */ 687 int kill_all() 688 { 689 register struct process *pw = pwlist; 690 for(;pw;pw=pw->p_next) 691 { 692 if(pw->p_pgrp == pw->p_pid) 693 { 694 #ifdef BSD 695 unstop(pw->p_pgrp); 696 killpg(pw->p_pgrp,SIGHUP); 697 #else 698 kill(-pw->p_pgrp,SIGHUP); 699 #endif /* BSD */ 700 } 701 } 702 } 703 704 /* 705 * Kill a job or process 706 */ 707 708 int job_kill(job,sig) 709 register char *job; 710 int sig; 711 { 712 register char *rjob = job; 713 register struct process *pw; 714 register int pid; 715 register int r; 716 char *msg; 717 if(*rjob == '%') 718 { 719 if(pw=pgrp_jobs(rjob)) 720 { 721 #ifdef BSD 722 r = unstop(pw->p_pgrp); 723 if(sig!=SIGCONT || r < 0) 724 r = killpg(pw->p_pgrp,sig); 725 #else 726 pid = pw->p_pgrp; 727 if(states&MONITOR) 728 pid = -pid; 729 r = kill(pid,sig); 730 #endif /* BSD */ 731 } 732 else 733 { 734 r = -1; 735 errno = ESRCH; 736 } 737 } 738 else 739 { 740 pid = atoi(rjob); 741 if(pid==0 && *rjob != '0') 742 failed(bkill,kill_usage); 743 #ifdef BSD 744 if(sig==SIGSTOP && pid==jobstat.mypid && (login_sh || ppid==1)) 745 { 746 /* can't stop login shell */ 747 errno = EPERM; 748 r = -1; 749 } 750 else 751 { 752 if((pw=job_bypid(pid)) && (pw->p_flag&P_STOPPED)) 753 { 754 pw->p_flag &= ~P_STOPPED; 755 numrun++; 756 kill(pid,SIGCONT); 757 } 758 r = kill(pid,sig); 759 } 760 #else 761 r = kill(pid,sig); 762 #endif /* BSD */ 763 } 764 if(r<0) 765 { 766 p_setout(stderr); 767 fputs(j_kill,output); 768 if(*rjob == '%') 769 msg = j_no_job; 770 else 771 msg = j_no_proc; 772 p_str(rjob,':'); 773 if(errno == EPERM) 774 msg = j_perm; 775 p_str(msg,NL); 776 r = 1; 777 } 778 return(r); 779 } 780 781 /* 782 * Get process structure from job number 783 */ 784 785 static struct process *job_bynum(num) 786 register int num; 787 { 788 register struct process *pw = pwlist; 789 for(;pw;pw=pw->p_next) 790 { 791 if((pw->p_flag&(P_PIPEJOB|P_WAITED)) == P_PIPEJOB) 792 continue; 793 if(pw->p_job == num) 794 return(pw); 795 } 796 return(NULL); 797 } 798 799 /* 800 * Get process structure from first letters of jobname 801 * 802 */ 803 804 static struct process *jobbyname(name) 805 char *name; 806 { 807 register struct process *pw = pwlist; 808 register struct fixcmd *fp = fc_fix; 809 if(fp==NULL) 810 return(NULL); 811 for(;pw;pw=pw->p_next) 812 { 813 if((pw->p_flag&(P_PIPEJOB|P_WAITED)) == P_PIPEJOB) 814 continue; 815 if(match_jobname(fp->fixfd,pw,name)) 816 goto retrn; 817 } 818 pw = NULL; 819 retrn: 820 return(pw); 821 } 822 823 824 /* 825 * match the name to the command starting with given name 826 */ 827 828 static int match_jobname(fdi,pw,name) 829 FILE *fdi; 830 register struct process *pw; 831 char *name; 832 { 833 register int c; 834 register char *sp; 835 if(fdi && pw->p_name>0) 836 { 837 fseek(fdi,pw->p_name,0); 838 for(sp=name;*sp;sp++) 839 { 840 c = getc(fdi); 841 if(c != *sp) 842 return(0); 843 } 844 return(1); 845 } 846 return(0); 847 } 848 849 850 851 /* 852 * Initialize the process posting array 853 */ 854 855 void postclr() 856 { 857 register struct process *pw = pwlist; 858 register struct process *px; 859 register int j = JBYTES; 860 for(;pw;pw=px) 861 { 862 px = pw->p_next; 863 free((char*)pw); 864 } 865 pwlist = NULL; 866 numpost=0; 867 numrun = 0; 868 while(--j >=0) 869 freejobs[j] = 0; 870 } 871 872 /* 873 * put the process <pcsid> on the process list and return the job number 874 * turn on the specified flag bits. 875 */ 876 877 int post(pid,flag) 878 int pid; 879 { 880 register struct process *pw; 881 if(pw=job_post(pid)) 882 { 883 pw->p_flag |= flag; 884 return(pw->p_job); 885 } 886 return(-1); 887 } 888 889 /* 890 * internal version of post, this routine returns a process structure 891 */ 892 893 static struct process *job_post(pcsid) 894 int pcsid; 895 { 896 register struct process *pw = pwlist; 897 register struct process *px=NULL; 898 register struct fixcmd *fp = fc_fix; 899 if(pcsid) 900 { 901 for(;pw;pw=pw->p_next) 902 { 903 if(pw->p_pid==pcsid) 904 return(pw); 905 if(pw->p_pgrp == jobstat.cur_pgrp) 906 px = pw; 907 } 908 if(pw=freelist) 909 freelist = pw->p_next; 910 else if((pw=(struct process*)malloc(sizeof(struct process)))==NULL) 911 error(nospace); 912 numrun++; 913 numpost++; 914 if(px) 915 { 916 pw->p_next = px->p_next; 917 px->p_next = pw; 918 pw->p_job = px->p_job; 919 } 920 else 921 { 922 /* put at front of list */ 923 pw->p_next = pwlist; 924 pw->p_job = get_job(); 925 pwlist = pw; 926 } 927 pw->p_pid = pcsid; 928 pw->p_flag = P_RUNNING; 929 pw->p_pgrp = jobstat.cur_pgrp; 930 if(fp!=NULL) 931 pw->p_name=hist_position(fp->fixind-1); 932 else 933 pw->p_name = -1; 934 pw->p_sig = 0; 935 if(numpost >= MAXJ-1) 936 await(0,0); 937 return(pw); 938 } 939 return(NULL); 940 } 941 942 /* 943 * get job number given the process id 944 */ 945 946 static struct process *job_bypid(pid) 947 register int pid; 948 { 949 register struct process *pw; 950 if(pid==0) 951 return(NULL); 952 for(pw=pwlist;pw;pw=pw->p_next) 953 if(pw->p_pid == pid) 954 break; 955 return(pw); 956 } 957 958 /* 959 * Wait for process i to complete 960 * flag=1 when wait builtin invoked so that it can be interrupted 961 * flag=2 to check for waiting processes and return 962 * flag=3 to resume job in foreground 963 * i=0 to wait for any process 964 * i=-1 to wait for all runing processes 965 */ 966 967 void await(i, flag) 968 register int i; 969 int flag; 970 { 971 int rc=0; 972 int w; 973 int my_job = -1; 974 #ifdef BSD 975 union wait wstat; 976 #endif /* BSD */ 977 register struct process *pw = NULL; 978 struct process *px; 979 if(i!= -1 && i) 980 { 981 if(flag) 982 { 983 pw = job_bypid(i); 984 if(flag==3 && pw) 985 flag = 0; 986 } 987 else 988 pw = job_post(i); 989 if(flag) 990 { 991 if(pw==0 || (pw->p_flag&P_STOPPED)) 992 return; 993 } 994 my_job = pw->p_job; 995 } 996 if(flag==0 && (states&MONITOR) && pw) 997 { 998 set_job(pw); 999 /* if job is stopped, resume it in the background */ 1000 #if BSD || SXT 1001 if(pw->p_flag&P_STOPPED) 1002 unstop(pw->p_pgrp); 1003 # ifdef SXT 1004 if(pw->p_job < jobstat.maxjob) 1005 open_chan(pw->p_job); 1006 # endif /* SXT */ 1007 #endif /* BSD */ 1008 } 1009 p_flush(); 1010 while(numrun>0) 1011 { 1012 register int p; 1013 register int sig; 1014 register int w_hi; 1015 #ifdef BSD 1016 if(is_option(MONITOR) || flag==2) 1017 { 1018 retry: 1019 errno = 0; 1020 sig = sighold(SIGCHLD); 1021 trapnote &= ~SIGJOBS; 1022 p=wait3(&wstat,WNOHANG|WUNTRACED,0); 1023 errno = 0; 1024 if(p==0 && flag!=2) 1025 { 1026 # ifdef BSD_4_2 1027 sigpause(sig&~(1<<(SIGCHLD-1))); 1028 # else 1029 sigpause(SIGCHLD); 1030 # endif /* BSD_4_2 */ 1031 if(errno==EINTR && flag==1 && (trapnote&SIGJOBS)==0) 1032 break; 1033 goto retry; 1034 } 1035 trapnote &= ~SIGJOBS; 1036 sigrelse(SIGCHLD); 1037 if(p==0 || p== -1) 1038 return; 1039 w = wstat.w_status; 1040 pw = job_bypid(p); 1041 if(pw->p_job == my_job && (states&MONITOR)) 1042 { 1043 register int ssig = wstat.w_S.w_Stopsig; 1044 if(WIFSTOPPED(wstat) && (ssig==SIGTTIN||ssig==SIGTTOU)) 1045 { 1046 /* job stopped before it got terminal */ 1047 killpg(pw->p_pgrp,SIGCONT); 1048 continue; 1049 } 1050 if(p==i) 1051 reset_ttygrp(pw,w&LOBYTE); 1052 } 1053 } 1054 else 1055 #endif /* BSD */ 1056 { 1057 #ifndef BSD 1058 # ifdef SXT 1059 if(jobstat.maxjob >0) 1060 { 1061 /* check for job status change */ 1062 status1 = status2; 1063 status2.input = status2.output = 0; 1064 if(ioctl(2,SXTIOCSTAT,&status2)!=0) 1065 { 1066 jobstat.maxjob = 0; 1067 } 1068 else if(status1.input != status2.input) 1069 { 1070 status_update(status2.input,status1.input,SIGSTIN); 1071 } 1072 else if(status1.output != status2.output) 1073 { 1074 status_update(status2.output,status1.output,SIGSTOP); 1075 } 1076 } 1077 # endif /* SXT */ 1078 /* enable fault handler to see if there are any pending jobs */ 1079 if((trapnote&SIGJOBS)==0) 1080 signal(SIGCLD,fault); 1081 if(flag==2 && (trapnote&SIGJOBS)==0) 1082 return; 1083 # ifdef SXT 1084 if(my_job>=0 && (trapnote&SIGJOBS)==0 && jobstat.maxjob) 1085 { 1086 errno = 0; 1087 p = ioctl(2, SXTIOCWF, 0); 1088 if(p==0) 1089 /* job stopped */ 1090 { 1091 ioctl(2, SXTIOCBLK, my_job); 1092 if(fd_chan>=0) 1093 { 1094 if(ioctl(fd_chan,TCFLSH,2)!=0) 1095 { 1096 ; 1097 } 1098 } 1099 pw->p_flag |= (P_NOTIFY|P_STOPPED); 1100 pw->p_sig = SIGSTOP; 1101 reset_ttygrp(pw,1); 1102 break; 1103 } 1104 } 1105 # endif /* SXT */ 1106 #endif /* BSD */ 1107 trapnote &= ~ SIGJOBS; 1108 p=wait(&w); 1109 if(p== -1) 1110 { 1111 if(errno==ECHILD) 1112 { 1113 postclr(); 1114 return; 1115 } 1116 else if(errno==EINTR) 1117 { 1118 if(trapnote&SIGJOBS) 1119 continue; 1120 if(flag) 1121 break; 1122 } 1123 continue; 1124 } 1125 trapnote &= ~ SIGJOBS; 1126 pw = job_bypid(p); 1127 #ifdef SXT 1128 pw->p_flag &= ~P_STOPPED; 1129 #endif /* SXT */ 1130 /* restore original tty state if jobs aborted */ 1131 if(p == i && (states&MONITOR)) 1132 reset_ttygrp(pw,w&LOBYTE); 1133 } 1134 if(pw) 1135 { 1136 numrun--; 1137 pw->p_flag |= P_NOTIFY; 1138 #ifdef BSD 1139 if((states&MONITOR) && WIFSTOPPED(wstat)) 1140 pw->p_flag |= P_STOPPED; 1141 else 1142 #endif /* BSD */ 1143 { 1144 if(p==cpid) 1145 { 1146 cpid = 0; 1147 cpipe[1] = NULL; 1148 } 1149 if(p==i || (states&MONITOR)==0) 1150 { 1151 if(px=unpost(pw)) 1152 { 1153 if(i) 1154 { 1155 if(p==i && (states&MONITOR)) 1156 set_job(px); 1157 i = px->p_pid; 1158 } 1159 continue; 1160 } 1161 } 1162 } 1163 } 1164 sig = w&0177; 1165 if(states&MONITOR) 1166 { 1167 #ifdef BSD 1168 if(WIFSTOPPED(wstat)) 1169 { 1170 if(pw) 1171 pw->p_sig = wstat.w_S.w_Stopsig; 1172 if(p == i) 1173 break; 1174 continue; 1175 } 1176 else if(p!=i) 1177 #else 1178 if(p!=i) 1179 #endif /* BSD */ 1180 { 1181 if(pw) 1182 pw->p_sig = w; 1183 if(w&HIGHBIT) 1184 pw->p_flag |= P_COREDUMP; 1185 continue; 1186 } 1187 /* this is needed since child not in same process group */ 1188 else if(sig==SIGINT || sig==SIGQUIT || sig==SIGHUP) 1189 fault(sig); 1190 } 1191 w_hi = (w>>8)&LOBYTE; 1192 if(sig) 1193 { 1194 if(sig == 0177 /* ptrace! return */) 1195 { 1196 fputs(ptrace,output); 1197 sig = w_hi; 1198 } 1199 if(sig!=SIGINT && sig!=SIGPIPE) 1200 { 1201 if(i!=p || (states&PROMPT)==0) 1202 p_prp(itos(p),SP); 1203 fputs(sysmsg[sig],output); 1204 if(w&HIGHBIT) 1205 fputs(coredump,output); 1206 } 1207 newline(); 1208 } 1209 if(p == i) 1210 { 1211 rc = (sig ? sig|SIGFAIL : w_hi); 1212 break; 1213 } 1214 if(i == 0) 1215 break; 1216 } 1217 if(flag>=2) 1218 return; 1219 exitval=rc; 1220 exitset(); 1221 } 1222 1223 #if BSD || SXT 1224 /* 1225 * turn off STOP state of a process group 1226 */ 1227 1228 static int unstop(grp) 1229 register int grp; 1230 { 1231 register struct process *pw; 1232 register int num = numrun; 1233 for(pw=pwlist;pw;pw=pw->p_next) 1234 { 1235 if(pw->p_pgrp != grp) 1236 continue; 1237 if(pw->p_flag&P_STOPPED) 1238 { 1239 num++; 1240 pw->p_flag &= ~P_STOPPED; 1241 pw->p_sig = 0; 1242 # ifdef SXT 1243 break; 1244 # endif /* SXT */ 1245 } 1246 } 1247 if(num!=numrun) 1248 { 1249 p_flush(); 1250 #ifdef BSD 1251 numrun = num; 1252 return(killpg(grp,SIGCONT)); 1253 #endif 1254 } 1255 return(-1); 1256 } 1257 #endif /* BSD */ 1258 1259 /* 1260 * remove a process group from table 1261 * If all the processes have not completed then unpost returns 1262 * the structure pointer of an unfinished process. 1263 * Otherwise NULL is returned. 1264 */ 1265 1266 static struct process *unpost(pwtop) 1267 struct process *pwtop; 1268 { 1269 register struct process *pw; 1270 register struct process *px=NULL; 1271 register int job = pwtop->p_job; 1272 register struct process *py; 1273 /* look for unfinished processes */ 1274 for(pw=pwlist;pw;pw=pw->p_next) 1275 { 1276 if(pw->p_job != job) 1277 continue; 1278 if((pw->p_flag&P_NOTIFY)==0) 1279 px = pw; 1280 } 1281 if(px) 1282 { 1283 px->p_flag &= ~P_PIPEJOB; 1284 px->p_flag |= P_WAITED; 1285 return(px); 1286 } 1287 /* all processes complete, unpost job */ 1288 for(pw=pwlist;pw;pw=py) 1289 { 1290 py = pw->p_next; 1291 if(pw->p_job != job) 1292 { 1293 px = pw; 1294 continue; 1295 } 1296 numpost--; 1297 if(px==NULL) 1298 pwlist = py; 1299 else 1300 px->p_next = py; 1301 pw->p_next = freelist; 1302 freelist = pw; 1303 } 1304 free_job((int)pwtop->p_job); 1305 return(NULL); 1306 } 1307 1308 /* 1309 * unlink a process form the process list 1310 */ 1311 1312 static void pw_unlink(pw) 1313 register struct process *pw; 1314 { 1315 register struct process *px; 1316 if(pw==pwlist) 1317 { 1318 pwlist = pw->p_next; 1319 return; 1320 } 1321 for(px=pwlist;px;px=px->p_next) 1322 if(px->p_next == pw) 1323 { 1324 px->p_next = pw->p_next; 1325 return; 1326 } 1327 } 1328 1329 /* 1330 * get an unused job number 1331 * freejobs is a bit vector, 0 is unused 1332 */ 1333 1334 static int get_job() 1335 { 1336 register int j=0; 1337 register unsigned mask = 1; 1338 register unsigned char *freeword; 1339 /* skip to first word with a free slot */ 1340 while(freejobs[j] == 0xff) 1341 j++; 1342 freeword = &freejobs[j]; 1343 j *= 8; 1344 for(j++;mask&(*freeword);j++,mask <<=1); 1345 *freeword |=mask; 1346 return(j); 1347 } 1348 1349 /* 1350 * return a job number 1351 */ 1352 1353 static void free_job(n) 1354 register int n; 1355 { 1356 register int j = (--n)/8; 1357 register unsigned mask; 1358 n -= j*8; 1359 mask = 1 << n; 1360 freejobs[j] &= ~mask; 1361 } 1362 1363 #ifdef SXT 1364 /* 1365 * open up the input streams for a new channel 1366 */ 1367 1368 static char *open_mode[3] = {"r","w","w+"}; 1369 j_new_chan() 1370 { 1371 register FILE* fd; 1372 register int i; 1373 sxt[11] = '0' + jobstat.cur_job; 1374 close(jobstat.pipe[0]); 1375 fd = fopen(sxt,"r+"); 1376 if(ioctl(fileno(fd),TCSETA,&my_stty)<0 || fd==NULL) 1377 { 1378 close(jobstat.pipe[1]); 1379 return(0); 1380 } 1381 for(i=0;i<3;i++) 1382 { 1383 if(isatty(i)) 1384 { 1385 fclose(file_fd(i)); 1386 fdopen(dup(fileno(fd)),open_mode[i]); 1387 } 1388 } 1389 fclose(fd); 1390 write(jobstat.pipe[1],nullstr,1); 1391 close(jobstat.pipe[1]); 1392 return(1); 1393 } 1394 1395 int next_job() 1396 { 1397 register int i = get_job(); 1398 free_job(i); 1399 return(i); 1400 } 1401 1402 static status_update(mask2,mask1,sigval) 1403 { 1404 register int i,j; 1405 register struct process *pw; 1406 for(i = 1; i < MAXPCHAN; i++) 1407 { 1408 j = 1<<i; 1409 if((mask1&j)==0 && (mask2&j)) 1410 { 1411 if(pw = job_bynum(i)) 1412 pw->p_sig = sigval; 1413 } 1414 else if((mask2&j)==0 && (mask1&j)) 1415 { 1416 if(pw = job_bynum(i)) 1417 pw->p_sig = 0; 1418 } 1419 } 1420 } 1421 1422 static int open_chan(j) 1423 { 1424 sxt[11] = '0' + j; 1425 if(fd_chan>=0) 1426 { 1427 return; 1428 } 1429 fd_chan = open(sxt,2); 1430 } 1431 #endif /* SXT */ 1432 1433 /* XXX */ 1434 #ifdef POSIX 1435 cfgetospeed(t) 1436 struct termios *t; 1437 { 1438 return(t->c_ospeed); 1439 } 1440 #endif 1441