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