1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1982-2012 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Eclipse Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.eclipse.org/org/documents/epl-v10.html * 11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * David Korn <dgk@research.att.com> * 18 * * 19 ***********************************************************************/ 20 #pragma prototyped 21 /* 22 * Job control for UNIX Shell 23 * 24 * David Korn 25 * AT&T Labs 26 * 27 * Written October, 1982 28 * Rewritten April, 1988 29 * Revised January, 1992 30 */ 31 32 #include "defs.h" 33 #include <wait.h> 34 #include "io.h" 35 #include "jobs.h" 36 #include "history.h" 37 38 #if !defined(WCONTINUED) || !defined(WIFCONTINUED) 39 # undef WCONTINUED 40 # define WCONTINUED 0 41 # undef WIFCONTINUED 42 # define WIFCONTINUED(wstat) (0) 43 #endif 44 45 #define NJOB_SAVELIST 4 46 47 /* 48 * temporary hack to get W* macros to work 49 */ 50 #undef wait 51 #define wait ______wait 52 /* 53 * This struct saves a link list of processes that have non-zero exit 54 * status, have had $! saved, but haven't been waited for 55 */ 56 struct jobsave 57 { 58 struct jobsave *next; 59 pid_t pid; 60 unsigned short exitval; 61 unsigned short env; 62 }; 63 64 static struct jobsave *job_savelist; 65 static int njob_savelist; 66 static struct process *pwfg; 67 static int jobfork; 68 69 pid_t pid_fromstring(char *str) 70 { 71 pid_t pid; 72 char *last; 73 errno = 0; 74 if(sizeof(pid)==sizeof(Sflong_t)) 75 pid = (pid_t)strtoll(str, &last, 10); 76 else 77 pid = (pid_t)strtol(str, &last, 10); 78 if(errno==ERANGE || *last) 79 errormsg(SH_DICT,ERROR_exit(1),"%s: invalid process id",str); 80 return(pid); 81 } 82 83 static void init_savelist(void) 84 { 85 register struct jobsave *jp; 86 while(njob_savelist < NJOB_SAVELIST) 87 { 88 jp = newof(0,struct jobsave,1,0); 89 jp->next = job_savelist; 90 job_savelist = jp; 91 njob_savelist++; 92 } 93 } 94 95 struct back_save 96 { 97 int count; 98 struct jobsave *list; 99 struct back_save *prev; 100 }; 101 102 #define BYTE(n) (((n)+CHAR_BIT-1)/CHAR_BIT) 103 #define MAXMSG 25 104 #define SH_STOPSIG (SH_EXITSIG<<1) 105 106 #ifdef VSUSP 107 # ifndef CNSUSP 108 # ifdef _POSIX_VDISABLE 109 # define CNSUSP _POSIX_VDISABLE 110 # else 111 # define CNSUSP 0 112 # endif /* _POSIX_VDISABLE */ 113 # endif /* CNSUSP */ 114 # ifndef CSWTCH 115 # ifdef CSUSP 116 # define CSWTCH CSUSP 117 # else 118 # define CSWTCH ('z'&037) 119 # endif /* CSUSP */ 120 # endif /* CSWTCH */ 121 #endif /* VSUSP */ 122 123 /* Process states */ 124 #define P_EXITSAVE 01 125 #define P_STOPPED 02 126 #define P_NOTIFY 04 127 #define P_SIGNALLED 010 128 #define P_STTY 020 129 #define P_DONE 040 130 #define P_COREDUMP 0100 131 #define P_DISOWN 0200 132 #define P_FG 0400 133 #ifdef SHOPT_BGX 134 #define P_BG 01000 135 #endif /* SHOPT_BGX */ 136 137 static int job_chksave(pid_t,long); 138 static struct process *job_bypid(pid_t); 139 static struct process *job_byjid(int); 140 static char *job_sigmsg(int); 141 static int job_alloc(void); 142 static void job_free(int); 143 static struct process *job_unpost(struct process*,int); 144 static void job_unlink(struct process*); 145 static void job_prmsg(struct process*); 146 static struct process *freelist; 147 static char beenhere; 148 static char possible; 149 static struct process dummy; 150 static char by_number; 151 static Sfio_t *outfile; 152 static pid_t lastpid; 153 static struct back_save bck; 154 155 #ifdef JOBS 156 static void job_set(struct process*); 157 static void job_reset(struct process*); 158 static void job_waitsafe(int); 159 static struct process *job_byname(char*); 160 static struct process *job_bystring(char*); 161 static struct termios my_stty; /* terminal state for shell */ 162 static char *job_string; 163 #else 164 extern const char e_coredump[]; 165 #endif /* JOBS */ 166 167 #ifdef SIGTSTP 168 static void job_unstop(struct process*); 169 static void job_fgrp(struct process*, int); 170 # ifndef _lib_tcgetpgrp 171 # ifdef TIOCGPGRP 172 static int _i_; 173 # define tcgetpgrp(a) (ioctl(a, TIOCGPGRP, &_i_)>=0?_i_:-1) 174 # endif /* TIOCGPGRP */ 175 int tcsetpgrp(int fd,pid_t pgrp) 176 { 177 int pgid = pgrp; 178 # ifdef TIOCGPGRP 179 return(ioctl(fd, TIOCSPGRP, &pgid)); 180 # else 181 return(-1); 182 # endif /* TIOCGPGRP */ 183 } 184 # endif /* _lib_tcgetpgrp */ 185 #else 186 # define job_unstop(pw) 187 # undef CNSUSP 188 #endif /* SIGTSTP */ 189 190 #ifndef OTTYDISC 191 # undef NTTYDISC 192 #endif /* OTTYDISC */ 193 194 #ifdef JOBS 195 196 typedef int (*Waitevent_f)(int,long,int); 197 198 #ifdef SHOPT_BGX 199 void job_chldtrap(Shell_t *shp, const char *trap, int unpost) 200 { 201 register struct process *pw,*pwnext; 202 pid_t bckpid; 203 int oldexit,trapnote; 204 job_lock(); 205 shp->sigflag[SIGCHLD] &= ~SH_SIGTRAP; 206 trapnote = shp->trapnote; 207 shp->trapnote = 0; 208 for(pw=job.pwlist;pw;pw=pwnext) 209 { 210 pwnext = pw->p_nxtjob; 211 if((pw->p_flag&(P_BG|P_DONE)) != (P_BG|P_DONE)) 212 continue; 213 pw->p_flag &= ~P_BG; 214 bckpid = shp->bckpid; 215 oldexit = shp->savexit; 216 shp->bckpid = pw->p_pid; 217 shp->savexit = pw->p_exit; 218 if(pw->p_flag&P_SIGNALLED) 219 shp->savexit |= SH_EXITSIG; 220 sh_trap(trap,0); 221 if(pw->p_pid==bckpid && unpost) 222 job_unpost(pw,0); 223 shp->savexit = oldexit; 224 shp->bckpid = bckpid; 225 } 226 shp->trapnote = trapnote; 227 job_unlock(); 228 } 229 #endif /* SHOPT_BGX */ 230 231 /* 232 * return next on link list of jobsave free list 233 */ 234 static struct jobsave *jobsave_create(pid_t pid) 235 { 236 register struct jobsave *jp = job_savelist; 237 job_chksave(pid,-1); 238 if(++bck.count > shgd->lim.child_max) 239 job_chksave(0,-1); 240 if(jp) 241 { 242 njob_savelist--; 243 job_savelist = jp->next; 244 } 245 else 246 jp = newof(0,struct jobsave,1,0); 247 if(jp) 248 { 249 jp->pid = pid; 250 jp->next = bck.list; 251 bck.list = jp; 252 jp->exitval = 0; 253 } 254 return(jp); 255 } 256 257 #if SHOPT_COSHELL 258 pid_t sh_copid(struct cosh *csp) 259 { 260 return(COPID_BIT|(csp->id<<16)|csp->cojob->id); 261 } 262 263 264 char *sh_pid2str(Shell_t *shp,pid_t pid) 265 { 266 struct cosh *csp=0; 267 if(pid&COPID_BIT) 268 { 269 int id = (pid>>16) &0x3f; 270 for(csp=job.colist; csp; csp = csp->next) 271 { 272 if(csp->id == id) 273 break; 274 } 275 } 276 if(csp) 277 sfprintf(shp->strbuf,"%s.%d%c",csp->name,pid&0xff,0); 278 else 279 sfprintf(shp->strbuf,"%d%c",pid,0); 280 return(sfstruse(shp->strbuf)); 281 } 282 283 int job_cowalk(int (*fun)(struct process*,int),int arg,char *name) 284 { 285 Shell_t *shp = sh_getinterp(); 286 struct cosh *csp; 287 struct process *pw,*pwnext; 288 pid_t val; 289 int n,r=0; 290 char *cp = strchr(name,'.'); 291 if(!cp) 292 n = strlen(name); 293 else 294 n = cp-name; 295 for(csp=(struct cosh*)job.colist;csp;csp=csp->next) 296 { 297 if(memcmp(name,csp->name,n)==0 && csp->name[n]==0) 298 break; 299 } 300 if(!csp) 301 errormsg(SH_DICT,ERROR_exit(1),e_jobusage,name); 302 if(cp) 303 { 304 n = pid_fromstring(cp+1); 305 val = (csp->id<<16)|n|COPID_BIT; 306 } 307 job_reap(SIGCHLD); 308 for(n=0,pw=job.pwlist; pw; pw=pwnext) 309 { 310 pwnext = pw->p_nxtjob; 311 if((cp && val==pw->p_pid) || (pw->p_cojob && pw->p_cojob->local==(void*)csp)) 312 { 313 if(fun) 314 { 315 if(pw->p_flag&P_DONE) 316 continue; 317 r |= (*fun)(pw,arg); 318 } 319 else 320 job_wait(-pw->p_pid); 321 n++; 322 } 323 } 324 if(!n) 325 shp->exitval = fun?1:ERROR_NOENT; 326 else if(fun) 327 shp->exitval = r; 328 return(r); 329 } 330 331 #endif /* SHOPT_COSHELL */ 332 333 /* 334 * Reap one job 335 * When called with sig==0, it does a blocking wait 336 */ 337 int job_reap(register int sig) 338 { 339 Shell_t *shp = sh_getinterp(); 340 register pid_t pid; 341 register struct process *pw; 342 struct process *px; 343 register int flags; 344 struct jobsave *jp; 345 int nochild=0, oerrno, wstat; 346 Waitevent_f waitevent = shp->gd->waitevent; 347 static int wcontinued = WCONTINUED; 348 #if SHOPT_COSHELL 349 Cojob_t *cjp; 350 int cojobs; 351 long cotimeout = sig?0:-1; 352 for(pw=job.pwlist;pw;pw=pw->p_nxtjob) 353 { 354 if(pw->p_cojob && !(pw->p_flag&P_DONE)) 355 break; 356 } 357 cojobs = (pw!=0); 358 pid = 0; 359 #endif /* SHOPT_COSHELL */ 360 if (vmbusy()) 361 { 362 errormsg(SH_DICT,ERROR_warn(0),"vmbusy() inside job_reap() -- should not happen"); 363 if (getenv("_AST_KSH_VMBUSY_ABORT")) 364 abort(); 365 } 366 #ifdef DEBUG 367 if(sfprintf(sfstderr,"ksh: job line %4d: reap pid=%d critical=%d signal=%d\n",__LINE__,getpid(),job.in_critical,sig) <=0) 368 write(2,"waitsafe\n",9); 369 sfsync(sfstderr); 370 #endif /* DEBUG */ 371 job.savesig = 0; 372 if(sig) 373 flags = WNOHANG|WUNTRACED|wcontinued; 374 else 375 flags = WUNTRACED|wcontinued; 376 shp->gd->waitevent = 0; 377 oerrno = errno; 378 while(1) 379 { 380 if(!(flags&WNOHANG) && !sh.intrap && job.pwlist) 381 { 382 sh_onstate(SH_TTYWAIT); 383 if(waitevent && (*waitevent)(-1,-1L,0)) 384 flags |= WNOHANG; 385 } 386 #if SHOPT_COSHELL 387 if(cojobs) 388 { 389 if(cjp = cowait(0,0,cotimeout)) 390 { 391 struct cosh *csp; 392 csp = (struct cosh*)(cjp->coshell->data); 393 csp->cojob = cjp; 394 pid = sh_copid(csp); 395 if(cjp->status < 256) 396 wstat = cjp->status <<8; 397 else 398 wstat = cjp->status-256; 399 cotimeout = 0; 400 goto cojob; 401 } 402 else if(copending(0)==0) 403 cojobs = 0; 404 cotimeout = 0; 405 } 406 #endif /* SHOPT_COSHELL */ 407 pid = waitpid((pid_t)-1,&wstat,flags); 408 sh_offstate(SH_TTYWAIT); 409 #if SHOPT_COSHELL 410 cojob: 411 #endif /* SHOPT_COSHELL */ 412 413 /* 414 * some systems (linux 2.6) may return EINVAL 415 * when there are no continued children 416 */ 417 418 if (pid<0 && errno==EINVAL && (flags&WCONTINUED)) 419 pid = waitpid((pid_t)-1,&wstat,flags&=~WCONTINUED); 420 sh_sigcheck(shp); 421 if(pid<0 && errno==EINTR && (sig||job.savesig)) 422 { 423 errno = 0; 424 continue; 425 } 426 if(pid<=0) 427 break; 428 if(wstat==0) 429 job_chksave(pid,-1); 430 flags |= WNOHANG; 431 job.waitsafe++; 432 jp = 0; 433 lastpid = pid; 434 if(!(pw=job_bypid(pid))) 435 { 436 #ifdef DEBUG 437 sfprintf(sfstderr,"ksh: job line %4d: reap pid=%d critical=%d unknown job pid=%d pw=%x\n",__LINE__,getpid(),job.in_critical,pid,pw); 438 #endif /* DEBUG */ 439 if (WIFCONTINUED(wstat) && wcontinued) 440 continue; 441 pw = &dummy; 442 pw->p_exit = 0; 443 pw->p_pgrp = 0; 444 pw->p_exitmin = 0; 445 if(job.toclear) 446 job_clear(); 447 jp = jobsave_create(pid); 448 pw->p_flag = 0; 449 lastpid = pw->p_pid = pid; 450 px = 0; 451 if(jp && WIFSTOPPED(wstat)) 452 { 453 jp->exitval = SH_STOPSIG; 454 continue; 455 } 456 } 457 #ifdef SIGTSTP 458 else 459 px=job_byjid(pw->p_job); 460 if (WIFCONTINUED(wstat) && wcontinued) 461 pw->p_flag &= ~(P_NOTIFY|P_SIGNALLED|P_STOPPED); 462 else if(WIFSTOPPED(wstat)) 463 { 464 pw->p_flag |= (P_NOTIFY|P_SIGNALLED|P_STOPPED); 465 pw->p_exit = WSTOPSIG(wstat); 466 if(pw->p_pgrp && pw->p_pgrp==job.curpgid && sh_isstate(SH_STOPOK)) 467 kill(getpid(),pw->p_exit); 468 if(px) 469 { 470 /* move to top of job list */ 471 job_unlink(px); 472 px->p_nxtjob = job.pwlist; 473 job.pwlist = px; 474 } 475 continue; 476 } 477 else 478 #endif /* SIGTSTP */ 479 { 480 /* check for coprocess completion */ 481 if(pid==shp->cpid) 482 { 483 sh_close(sh.coutpipe); 484 sh_close(sh.cpipe[1]); 485 sh.cpipe[1] = -1; 486 sh.coutpipe = -1; 487 } 488 else if(shp->subshell) 489 sh_subjobcheck(pid); 490 491 pw->p_flag &= ~(P_STOPPED|P_SIGNALLED); 492 if (WIFSIGNALED(wstat)) 493 { 494 pw->p_flag |= (P_DONE|P_NOTIFY|P_SIGNALLED); 495 if (WTERMCORE(wstat)) 496 pw->p_flag |= P_COREDUMP; 497 pw->p_exit = WTERMSIG(wstat); 498 /* if process in current jobs terminates from 499 * an interrupt, propogate to parent shell 500 */ 501 if(pw->p_pgrp && pw->p_pgrp==job.curpgid && pw->p_exit==SIGINT && sh_isstate(SH_STOPOK)) 502 { 503 pw->p_flag &= ~P_NOTIFY; 504 sh_offstate(SH_STOPOK); 505 kill(getpid(),SIGINT); 506 sh_onstate(SH_STOPOK); 507 } 508 } 509 else 510 { 511 pw->p_flag |= (P_DONE|P_NOTIFY); 512 pw->p_exit = pw->p_exitmin; 513 if(WEXITSTATUS(wstat) > pw->p_exitmin) 514 pw->p_exit = WEXITSTATUS(wstat); 515 } 516 #ifdef SHOPT_BGX 517 if((pw->p_flag&P_DONE) && (pw->p_flag&P_BG)) 518 { 519 job.numbjob--; 520 if(shp->st.trapcom[SIGCHLD]) 521 { 522 shp->sigflag[SIGCHLD] |= SH_SIGTRAP; 523 if(sig==0) 524 job_chldtrap(shp,shp->st.trapcom[SIGCHLD],0); 525 else 526 shp->trapnote |= SH_SIGTRAP; 527 } 528 else 529 pw->p_flag &= ~P_BG; 530 } 531 #endif /* SHOPT_BGX */ 532 if(pw->p_pgrp==0) 533 pw->p_flag &= ~P_NOTIFY; 534 } 535 if(jp && pw== &dummy) 536 { 537 jp->exitval = pw->p_exit; 538 if(pw->p_flag&P_SIGNALLED) 539 jp->exitval |= SH_EXITSIG; 540 } 541 #ifdef DEBUG 542 sfprintf(sfstderr,"ksh: job line %4d: reap pid=%d critical=%d job %d with pid %d flags=%o complete with status=%x exit=%d\n",__LINE__,getpid(),job.in_critical,pw->p_job,pid,pw->p_flag,wstat,pw->p_exit); 543 sfsync(sfstderr); 544 #endif /* DEBUG*/ 545 /* only top-level process in job should have notify set */ 546 if(px && pw != px) 547 pw->p_flag &= ~P_NOTIFY; 548 if(pid==pw->p_fgrp && pid==tcgetpgrp(JOBTTY)) 549 { 550 px = job_byjid((int)pw->p_job); 551 for(; px && (px->p_flag&P_DONE); px=px->p_nxtproc); 552 if(!px) 553 tcsetpgrp(JOBTTY,job.mypid); 554 } 555 #ifndef SHOPT_BGX 556 if(!shp->intrap && shp->st.trapcom[SIGCHLD] && pid>0 && (pwfg!=job_bypid(pid))) 557 { 558 shp->sigflag[SIGCHLD] |= SH_SIGTRAP; 559 shp->trapnote |= SH_SIGTRAP; 560 } 561 #endif 562 } 563 if(errno==ECHILD) 564 { 565 errno = oerrno; 566 #ifdef SHOPT_BGX 567 job.numbjob = 0; 568 #endif /* SHOPT_BGX */ 569 nochild = 1; 570 } 571 shp->gd->waitevent = waitevent; 572 if(sh_isoption(SH_NOTIFY) && sh_isstate(SH_TTYWAIT)) 573 { 574 outfile = sfstderr; 575 job_list(pw,JOB_NFLAG|JOB_NLFLAG); 576 job_unpost(pw,1); 577 sfsync(sfstderr); 578 } 579 if(sig) 580 signal(sig, job_waitsafe); 581 return(nochild); 582 } 583 584 /* 585 * This is the SIGCLD interrupt routine 586 */ 587 static void job_waitsafe(int sig) 588 { 589 if(job.in_critical || vmbusy()) 590 { 591 job.savesig = sig; 592 job.waitsafe++; 593 } 594 else 595 job_reap(sig); 596 } 597 598 /* 599 * initialize job control if possible 600 * if lflag is set the switching driver message will not print 601 */ 602 void job_init(Shell_t *shp, int lflag) 603 { 604 register int ntry=0; 605 job.fd = JOBTTY; 606 signal(SIGCHLD,job_waitsafe); 607 # if defined(SIGCLD) && (SIGCLD!=SIGCHLD) 608 signal(SIGCLD,job_waitsafe); 609 # endif 610 if(njob_savelist < NJOB_SAVELIST) 611 init_savelist(); 612 if(!sh_isoption(SH_INTERACTIVE)) 613 return; 614 /* use new line discipline when available */ 615 #ifdef NTTYDISC 616 # ifdef FIOLOOKLD 617 if((job.linedisc = ioctl(JOBTTY, FIOLOOKLD, 0)) <0) 618 # else 619 if(ioctl(JOBTTY,TIOCGETD,&job.linedisc) !=0) 620 # endif /* FIOLOOKLD */ 621 return; 622 if(job.linedisc!=NTTYDISC && job.linedisc!=OTTYDISC) 623 { 624 /* no job control when running with MPX */ 625 # if SHOPT_VSH 626 sh_onoption(SH_VIRAW); 627 # endif /* SHOPT_VSH */ 628 return; 629 } 630 if(job.linedisc==NTTYDISC) 631 job.linedisc = -1; 632 #endif /* NTTYDISC */ 633 634 job.mypgid = getpgrp(); 635 /* some systems have job control, but not initialized */ 636 if(job.mypgid<=0) 637 { 638 /* Get a controlling terminal and set process group */ 639 /* This should have already been done by rlogin */ 640 register int fd; 641 register char *ttynam; 642 #ifndef SIGTSTP 643 setpgid(0,shp->gd->pid); 644 #endif /*SIGTSTP */ 645 if(job.mypgid<0 || !(ttynam=ttyname(JOBTTY))) 646 return; 647 close(JOBTTY); 648 if((fd = open(ttynam,O_RDWR)) <0) 649 return; 650 if(fd!=JOBTTY) 651 sh_iorenumber(shp,fd,JOBTTY); 652 job.mypgid = shp->gd->pid; 653 #ifdef SIGTSTP 654 tcsetpgrp(JOBTTY,shp->gd->pid); 655 setpgid(0,shp->gd->pid); 656 #endif /* SIGTSTP */ 657 } 658 #ifdef SIGTSTP 659 if(possible = (setpgid(0,job.mypgid)>=0) || errno==EPERM) 660 { 661 /* wait until we are in the foreground */ 662 663 while((job.mytgid=tcgetpgrp(JOBTTY)) != job.mypgid) 664 { 665 if(job.mytgid <= 0) 666 return; 667 /* Stop this shell until continued */ 668 signal(SIGTTIN,SIG_DFL); 669 kill(shp->gd->pid,SIGTTIN); 670 /* resumes here after continue tries again */ 671 if(ntry++ > IOMAXTRY) 672 { 673 errormsg(SH_DICT,0,e_no_start); 674 return; 675 } 676 } 677 } 678 #endif /* SIGTTIN */ 679 680 #ifdef NTTYDISC 681 /* set the line discipline */ 682 if(job.linedisc>=0) 683 { 684 int linedisc = NTTYDISC; 685 # ifdef FIOPUSHLD 686 tty_get(JOBTTY,&my_stty); 687 if (ioctl(JOBTTY, FIOPOPLD, 0) < 0) 688 return; 689 if (ioctl(JOBTTY, FIOPUSHLD, &linedisc) < 0) 690 { 691 ioctl(JOBTTY, FIOPUSHLD, &job.linedisc); 692 return; 693 } 694 tty_set(JOBTTY,TCSANOW,&my_stty); 695 # else 696 if(ioctl(JOBTTY,TIOCSETD,&linedisc) !=0) 697 return; 698 # endif /* FIOPUSHLD */ 699 if(lflag==0) 700 errormsg(SH_DICT,0,e_newtty); 701 else 702 job.linedisc = -1; 703 } 704 #endif /* NTTYDISC */ 705 if(!possible) 706 return; 707 708 #ifdef SIGTSTP 709 /* make sure that we are a process group leader */ 710 setpgid(0,shp->gd->pid); 711 # if defined(SA_NOCLDSTOP) || defined(SA_NOCLDWAIT) 712 # if !defined(SA_NOCLDSTOP) 713 # define SA_NOCLDSTOP 0 714 # endif 715 # if !defined(SA_NOCLDWAIT) 716 # define SA_NOCLDWAIT 0 717 # endif 718 sigflag(SIGCHLD, SA_NOCLDSTOP|SA_NOCLDWAIT, 0); 719 # endif /* SA_NOCLDSTOP || SA_NOCLDWAIT */ 720 signal(SIGTTIN,SIG_IGN); 721 signal(SIGTTOU,SIG_IGN); 722 /* The shell now handles ^Z */ 723 signal(SIGTSTP,sh_fault); 724 tcsetpgrp(JOBTTY,shp->gd->pid); 725 # ifdef CNSUSP 726 /* set the switch character */ 727 tty_get(JOBTTY,&my_stty); 728 job.suspend = (unsigned)my_stty.c_cc[VSUSP]; 729 if(job.suspend == (unsigned char)CNSUSP) 730 { 731 my_stty.c_cc[VSUSP] = CSWTCH; 732 tty_set(JOBTTY,TCSAFLUSH,&my_stty); 733 } 734 # endif /* CNSUSP */ 735 sh_onoption(SH_MONITOR); 736 job.jobcontrol++; 737 job.mypid = shp->gd->pid; 738 #endif /* SIGTSTP */ 739 return; 740 } 741 742 743 /* 744 * see if there are any stopped jobs 745 * restore tty driver and pgrp 746 */ 747 int job_close(Shell_t* shp) 748 { 749 register struct process *pw; 750 register int count = 0, running = 0; 751 if(possible && !job.jobcontrol) 752 return(0); 753 else if(!possible && (!sh_isstate(SH_MONITOR) || sh_isstate(SH_FORKED))) 754 return(0); 755 else if(getpid() != job.mypid) 756 return(0); 757 job_lock(); 758 if(!tty_check(0)) 759 beenhere++; 760 for(pw=job.pwlist;pw;pw=pw->p_nxtjob) 761 { 762 if(!(pw->p_flag&P_STOPPED)) 763 { 764 if(!(pw->p_flag&P_DONE)) 765 running++; 766 continue; 767 } 768 if(beenhere) 769 killpg(pw->p_pgrp,SIGTERM); 770 count++; 771 } 772 if(beenhere++ == 0 && job.pwlist) 773 { 774 if(count) 775 { 776 errormsg(SH_DICT,0,e_terminate); 777 return(-1); 778 } 779 else if(running && shp->login_sh) 780 { 781 errormsg(SH_DICT,0,e_jobsrunning); 782 return(-1); 783 } 784 } 785 job_unlock(); 786 # ifdef SIGTSTP 787 if(possible && setpgid(0,job.mypgid)>=0) 788 tcsetpgrp(job.fd,job.mypgid); 789 # endif /* SIGTSTP */ 790 # ifdef NTTYDISC 791 if(job.linedisc>=0) 792 { 793 /* restore old line discipline */ 794 # ifdef FIOPUSHLD 795 tty_get(job.fd,&my_stty); 796 if (ioctl(job.fd, FIOPOPLD, 0) < 0) 797 return(0); 798 if (ioctl(job.fd, FIOPUSHLD, &job.linedisc) < 0) 799 { 800 job.linedisc = NTTYDISC; 801 ioctl(job.fd, FIOPUSHLD, &job.linedisc); 802 return(0); 803 } 804 tty_set(job.fd,TCSAFLUSH,&my_stty); 805 # else 806 if(ioctl(job.fd,TIOCSETD,&job.linedisc) !=0) 807 return(0); 808 # endif /* FIOPUSHLD */ 809 errormsg(SH_DICT,0,e_oldtty); 810 } 811 # endif /* NTTYDISC */ 812 # ifdef CNSUSP 813 if(possible && job.suspend==CNSUSP) 814 { 815 tty_get(job.fd,&my_stty); 816 my_stty.c_cc[VSUSP] = CNSUSP; 817 tty_set(job.fd,TCSAFLUSH,&my_stty); 818 } 819 # endif /* CNSUSP */ 820 job.jobcontrol = 0; 821 return(0); 822 } 823 824 static void job_set(register struct process *pw) 825 { 826 Shell_t *shp = pw->p_shp; 827 /* save current terminal state */ 828 tty_get(job.fd,&my_stty); 829 if(pw->p_flag&P_STTY) 830 { 831 /* restore terminal state for job */ 832 tty_set(job.fd,TCSAFLUSH,&pw->p_stty); 833 } 834 #ifdef SIGTSTP 835 if((pw->p_flag&P_STOPPED) || tcgetpgrp(job.fd) == shp->gd->pid) 836 tcsetpgrp(job.fd,pw->p_fgrp); 837 /* if job is stopped, resume it in the background */ 838 if(!shp->forked) 839 job_unstop(pw); 840 shp->forked = 0; 841 #endif /* SIGTSTP */ 842 } 843 844 static void job_reset(register struct process *pw) 845 { 846 /* save the terminal state for current job */ 847 #ifdef SIGTSTP 848 job_fgrp(pw,tcgetpgrp(job.fd)); 849 if(tcsetpgrp(job.fd,job.mypid) !=0) 850 return; 851 #endif /* SIGTSTP */ 852 /* force the following tty_get() to do a tcgetattr() unless fg */ 853 if(!(pw->p_flag&P_FG)) 854 tty_set(-1, 0, NIL(struct termios*)); 855 if(pw && (pw->p_flag&P_SIGNALLED) && pw->p_exit!=SIGHUP) 856 { 857 if(tty_get(job.fd,&pw->p_stty) == 0) 858 pw->p_flag |= P_STTY; 859 /* restore terminal state for job */ 860 tty_set(job.fd,TCSAFLUSH,&my_stty); 861 } 862 beenhere = 0; 863 } 864 #endif /* JOBS */ 865 866 /* 867 * wait built-in command 868 */ 869 870 void job_bwait(char **jobs) 871 { 872 register char *jp; 873 register struct process *pw; 874 register pid_t pid; 875 if(*jobs==0) 876 job_wait((pid_t)-1); 877 else while(jp = *jobs++) 878 { 879 #ifdef JOBS 880 if(*jp == '%') 881 { 882 job_lock(); 883 pw = job_bystring(jp); 884 job_unlock(); 885 if(pw) 886 pid = pw->p_pid; 887 else 888 return; 889 } 890 # if SHOPT_COSHELL 891 else if(isalpha(*jp)) 892 { 893 job_cowalk(NULL,0,jp); 894 return; 895 } 896 # endif /* SHOPT_COSHELL */ 897 else 898 #endif /* JOBS */ 899 pid = pid_fromstring(jp); 900 job_wait(-pid); 901 } 902 } 903 904 #ifdef JOBS 905 /* 906 * execute function <fun> for each job 907 */ 908 909 int job_walk(Sfio_t *file,int (*fun)(struct process*,int),int arg,char *joblist[]) 910 { 911 register struct process *pw; 912 register int r = 0; 913 register char *jobid, **jobs=joblist; 914 register struct process *px; 915 job_string = 0; 916 outfile = file; 917 by_number = 0; 918 job_lock(); 919 pw = job.pwlist; 920 job_waitsafe(SIGCHLD); 921 if(jobs==0) 922 { 923 /* do all jobs */ 924 for(;pw;pw=px) 925 { 926 px = pw->p_nxtjob; 927 if(pw->p_env != sh.jobenv) 928 continue; 929 if((*fun)(pw,arg)) 930 r = 2; 931 } 932 } 933 else if(*jobs==0) /* current job */ 934 { 935 /* skip over non-stop jobs */ 936 while(pw && (pw->p_env!=sh.jobenv || pw->p_pgrp==0)) 937 pw = pw->p_nxtjob; 938 if((*fun)(pw,arg)) 939 r = 2; 940 } 941 else while(jobid = *jobs++) 942 { 943 job_string = jobid; 944 if(*jobid==0) 945 errormsg(SH_DICT,ERROR_exit(1),e_jobusage,job_string); 946 #if SHOPT_COSHELL 947 if(isalpha(*jobid)) 948 { 949 r = job_cowalk(fun,arg,jobid); 950 by_number = 0; 951 job_unlock(); 952 return(r); 953 } 954 #endif /* SHOPT_COSHELL */ 955 if(*jobid == '%') 956 pw = job_bystring(jobid); 957 else 958 { 959 int pid = pid_fromstring(jobid); 960 if(!(pw = job_bypid(pid))) 961 { 962 pw = &dummy; 963 pw->p_shp = sh_getinterp(); 964 pw->p_pid = pid; 965 pw->p_pgrp = pid; 966 } 967 by_number = 1; 968 } 969 if((*fun)(pw,arg)) 970 r = 2; 971 by_number = 0; 972 } 973 job_unlock(); 974 return(r); 975 } 976 977 /* 978 * send signal <sig> to background process group if not disowned 979 */ 980 int job_terminate(register struct process *pw,register int sig) 981 { 982 if(pw->p_pgrp && !(pw->p_flag&P_DISOWN)) 983 job_kill(pw,sig); 984 return(0); 985 } 986 987 /* 988 * list the given job 989 * flag JOB_LFLAG for long listing 990 * flag JOB_NFLAG for list only jobs marked for notification 991 * flag JOB_PFLAG for process id(s) only 992 */ 993 994 int job_list(struct process *pw,register int flag) 995 { 996 Shell_t *shp = sh_getinterp(); 997 register struct process *px = pw; 998 register int n; 999 register const char *msg; 1000 register int msize; 1001 if(!pw || pw->p_job<=0) 1002 return(1); 1003 if(pw->p_env != shp->jobenv) 1004 return(0); 1005 if((flag&JOB_NFLAG) && (!(px->p_flag&P_NOTIFY)||px->p_pgrp==0)) 1006 return(0); 1007 if((flag&JOB_PFLAG)) 1008 { 1009 #if SHOPT_COSHELL 1010 sfprintf(outfile,"%s\n",sh_pid2str(shp,px->p_pgrp?px->p_pgrp:px->p_pid)); 1011 #else 1012 sfprintf(outfile,"%d\n",px->p_pgrp?px->p_pgrp:px->p_pid); 1013 #endif /* SHOPT_COSHELL */ 1014 return(0); 1015 } 1016 if((px->p_flag&P_DONE) && job.waitall && !(flag&JOB_LFLAG)) 1017 return(0); 1018 job_lock(); 1019 n = px->p_job; 1020 if(px==job.pwlist) 1021 msize = '+'; 1022 else if(px==job.pwlist->p_nxtjob) 1023 msize = '-'; 1024 else 1025 msize = ' '; 1026 if(flag&JOB_NLFLAG) 1027 sfputc(outfile,'\n'); 1028 sfprintf(outfile,"[%d] %c ",n, msize); 1029 do 1030 { 1031 n = 0; 1032 if(flag&JOB_LFLAG) 1033 #if SHOPT_COSHELL 1034 sfprintf(outfile,"%s\t",sh_pid2str(shp,px->p_pid)); 1035 #else 1036 sfprintf(outfile,"%d\t",px->p_pid); 1037 #endif /* SHOPT_COSHELL */ 1038 if(px->p_flag&P_SIGNALLED) 1039 msg = job_sigmsg((int)(px->p_exit)); 1040 else if(px->p_flag&P_NOTIFY) 1041 { 1042 msg = sh_translate(e_done); 1043 n = px->p_exit; 1044 } 1045 else 1046 msg = sh_translate(e_running); 1047 px->p_flag &= ~P_NOTIFY; 1048 sfputr(outfile,msg,-1); 1049 msize = strlen(msg); 1050 if(n) 1051 { 1052 sfprintf(outfile,"(%d)",(int)n); 1053 msize += (3+(n>10)+(n>100)); 1054 } 1055 if(px->p_flag&P_COREDUMP) 1056 { 1057 msg = sh_translate(e_coredump); 1058 sfputr(outfile, msg, -1); 1059 msize += strlen(msg); 1060 } 1061 sfnputc(outfile,' ',MAXMSG>msize?MAXMSG-msize:1); 1062 if(flag&JOB_LFLAG) 1063 px = px->p_nxtproc; 1064 else 1065 { 1066 while(px=px->p_nxtproc) 1067 px->p_flag &= ~P_NOTIFY; 1068 px = 0; 1069 } 1070 if(!px) 1071 hist_list(shgd->hist_ptr,outfile,pw->p_name,0,";"); 1072 else 1073 sfputr(outfile, e_nlspace, -1); 1074 } 1075 while(px); 1076 job_unlock(); 1077 return(0); 1078 } 1079 1080 /* 1081 * get the process group given the job number 1082 * This routine returns the process group number or -1 1083 */ 1084 static struct process *job_bystring(register char *ajob) 1085 { 1086 register struct process *pw=job.pwlist; 1087 register int c; 1088 if(*ajob++ != '%' || !pw) 1089 return(NIL(struct process*)); 1090 c = *ajob; 1091 if(isdigit(c)) 1092 pw = job_byjid((int)strtol(ajob, (char**)0, 10)); 1093 else if(c=='+' || c=='%') 1094 ; 1095 else if(c=='-') 1096 { 1097 if(pw) 1098 pw = job.pwlist->p_nxtjob; 1099 } 1100 else 1101 pw = job_byname(ajob); 1102 if(pw && pw->p_flag) 1103 return(pw); 1104 return(NIL(struct process*)); 1105 } 1106 1107 /* 1108 * Kill a job or process 1109 */ 1110 1111 int job_kill(register struct process *pw,register int sig) 1112 { 1113 Shell_t *shp; 1114 register pid_t pid; 1115 register int r; 1116 const char *msg; 1117 #ifdef SIGTSTP 1118 int stopsig = (sig==SIGSTOP||sig==SIGTSTP||sig==SIGTTIN||sig==SIGTTOU); 1119 #else 1120 # define stopsig 1 1121 #endif /* SIGTSTP */ 1122 job_lock(); 1123 errno = ECHILD; 1124 if(pw==0) 1125 goto error; 1126 shp = pw->p_shp; 1127 pid = pw->p_pid; 1128 #if SHOPT_COSHELL 1129 if(pw->p_cojob) 1130 r = cokill(pw->p_cojob->coshell,pw->p_cojob,sig); 1131 else 1132 #endif /* SHOPT_COSHELL */ 1133 if(by_number) 1134 { 1135 if(pid==0 && job.jobcontrol) 1136 r = job_walk(outfile, job_kill,sig, (char**)0); 1137 #ifdef SIGTSTP 1138 if(sig==SIGSTOP && pid==shp->gd->pid && shp->gd->ppid==1) 1139 { 1140 /* can't stop login shell */ 1141 errno = EPERM; 1142 r = -1; 1143 } 1144 else 1145 { 1146 if(pid>=0) 1147 { 1148 if((r = kill(pid,sig))>=0 && !stopsig) 1149 { 1150 if(pw->p_flag&P_STOPPED) 1151 pw->p_flag &= ~(P_STOPPED|P_SIGNALLED); 1152 if(sig) 1153 kill(pid,SIGCONT); 1154 } 1155 } 1156 else 1157 { 1158 if((r = killpg(-pid,sig))>=0 && !stopsig) 1159 { 1160 job_unstop(job_bypid(pw->p_pid)); 1161 if(sig) 1162 killpg(-pid,SIGCONT); 1163 } 1164 } 1165 } 1166 #else 1167 if(pid>=0) 1168 r = kill(pid,sig); 1169 else 1170 r = killpg(-pid,sig); 1171 #endif /* SIGTSTP */ 1172 } 1173 else 1174 { 1175 if(pid = pw->p_pgrp) 1176 { 1177 r = killpg(pid,sig); 1178 #ifdef SIGTSTP 1179 if(r>=0 && (sig==SIGHUP||sig==SIGTERM || sig==SIGCONT)) 1180 job_unstop(pw); 1181 #endif /* SIGTSTP */ 1182 if(r>=0) 1183 sh_delay(.05); 1184 } 1185 while(pw && pw->p_pgrp==0 && (r=kill(pw->p_pid,sig))>=0) 1186 { 1187 #ifdef SIGTSTP 1188 if(sig==SIGHUP || sig==SIGTERM) 1189 kill(pw->p_pid,SIGCONT); 1190 #endif /* SIGTSTP */ 1191 pw = pw->p_nxtproc; 1192 } 1193 } 1194 if(r<0 && job_string) 1195 { 1196 error: 1197 if(pw && by_number) 1198 msg = sh_translate(e_no_proc); 1199 else 1200 msg = sh_translate(e_no_job); 1201 if(errno == EPERM) 1202 msg = sh_translate(e_access); 1203 sfprintf(sfstderr,"kill: %s: %s\n",job_string, msg); 1204 r = 2; 1205 } 1206 sh_delay(.001); 1207 job_unlock(); 1208 return(r); 1209 } 1210 1211 /* 1212 * Similar to job_kill, but dedicated to SIGHUP handling when session is 1213 * being disconnected. 1214 */ 1215 int 1216 job_hup(struct process *pw, int sig) 1217 { 1218 struct process *px; 1219 pid_t pid; 1220 int r; 1221 1222 if (pw->p_pgrp == 0 || (pw->p_flag & P_DISOWN)) 1223 return (0); 1224 1225 #if SHOPT_COSHELL 1226 if(pw->p_cojob) { 1227 job_lock(); 1228 r = cokill(pw->p_cojob->coshell,pw->p_cojob,sig); 1229 job_unlock(); 1230 return (r); 1231 } 1232 #endif /* SHOPT_COSHELL */ 1233 1234 job_lock(); 1235 if (pw->p_pgrp != 0) { 1236 int palive = 0; 1237 1238 for (px = pw; px != NULL; px = px->p_nxtproc) { 1239 if ((px->p_flag & P_DONE) == 0) { 1240 palive = 1; 1241 break; 1242 } 1243 } 1244 /* 1245 * If all the processes have been dead, there is no guarantee 1246 * that the p_pgrp is still the valid process group that we 1247 * made, ie pid may have been recycled and same p_pgrp may 1248 * have been assigned to unrelated processes. 1249 */ 1250 if (palive) { 1251 if (killpg(pw->p_pgrp, SIGHUP) >= 0) 1252 job_unstop(pw); 1253 } 1254 } 1255 for (; pw != NULL && pw->p_pgrp == 0; pw = pw->p_nxtproc) { 1256 if (pw->p_flag & P_DONE) 1257 continue; 1258 if (kill(pw->p_pid, SIGHUP) >= 0) 1259 (void) kill(pw->p_pid, SIGCONT); 1260 pw = pw->p_nxtproc; 1261 } 1262 job_unlock(); 1263 return(0); 1264 } 1265 1266 /* 1267 * Get process structure from first letters of jobname 1268 * 1269 */ 1270 1271 static struct process *job_byname(char *name) 1272 { 1273 register struct process *pw = job.pwlist; 1274 register struct process *pz = 0; 1275 register int *flag = 0; 1276 register char *cp = name; 1277 int offset; 1278 if(!shgd->hist_ptr) 1279 return(NIL(struct process*)); 1280 if(*cp=='?') 1281 cp++,flag= &offset; 1282 for(;pw;pw=pw->p_nxtjob) 1283 { 1284 if(hist_match(shgd->hist_ptr,pw->p_name,cp,flag)>=0) 1285 { 1286 if(pz) 1287 errormsg(SH_DICT,ERROR_exit(1),e_jobusage,name-1); 1288 pz = pw; 1289 } 1290 } 1291 return(pz); 1292 } 1293 1294 #else 1295 # define job_set(x) 1296 # define job_reset(x) 1297 #endif /* JOBS */ 1298 1299 1300 1301 /* 1302 * Initialize the process posting array 1303 */ 1304 1305 void job_clear(void) 1306 { 1307 Shell_t *shp = sh_getinterp(); 1308 register struct process *pw, *px; 1309 register struct process *pwnext; 1310 register int j = BYTE(shp->gd->lim.child_max); 1311 register struct jobsave *jp,*jpnext; 1312 job_lock(); 1313 for(pw=job.pwlist; pw; pw=pwnext) 1314 { 1315 pwnext = pw->p_nxtjob; 1316 while(px=pw) 1317 { 1318 pw = pw->p_nxtproc; 1319 free((void*)px); 1320 } 1321 } 1322 for(jp=bck.list; jp;jp=jpnext) 1323 { 1324 jpnext = jp->next; 1325 free((void*)jp); 1326 } 1327 bck.list = 0; 1328 if(njob_savelist < NJOB_SAVELIST) 1329 init_savelist(); 1330 job.pwlist = NIL(struct process*); 1331 job.numpost=0; 1332 #ifdef SHOPT_BGX 1333 job.numbjob = 0; 1334 #endif /* SHOPT_BGX */ 1335 job.waitall = 0; 1336 job.curpgid = 0; 1337 job.toclear = 0; 1338 if(!job.freejobs) 1339 job.freejobs = (unsigned char*)malloc((unsigned)(j+1)); 1340 while(j >=0) 1341 job.freejobs[j--] = 0; 1342 job_unlock(); 1343 } 1344 1345 /* 1346 * put the process <pid> on the process list and return the job number 1347 * if non-zero, <join> is the process id of the job to join 1348 */ 1349 1350 int job_post(Shell_t *shp,pid_t pid, pid_t join) 1351 { 1352 register struct process *pw; 1353 register History_t *hp = shp->gd->hist_ptr; 1354 #ifdef SHOPT_BGX 1355 int val,bg=0; 1356 #else 1357 int val; 1358 #endif 1359 shp->jobenv = shp->curenv; 1360 if(job.toclear) 1361 { 1362 job_clear(); 1363 return(0); 1364 } 1365 job_lock(); 1366 #ifdef SHOPT_BGX 1367 if(join==1) 1368 { 1369 join = 0; 1370 bg = P_BG; 1371 job.numbjob++; 1372 } 1373 #endif /* SHOPT_BGX */ 1374 if(njob_savelist < NJOB_SAVELIST) 1375 init_savelist(); 1376 if(pw = job_bypid(pid)) 1377 job_unpost(pw,0); 1378 if(join) 1379 { 1380 if(pw=job_bypid(join)) 1381 val = pw->p_job; 1382 else 1383 val = job.curjobid; 1384 /* if job to join is not first move it to front */ 1385 if(val && (pw=job_byjid(val)) != job.pwlist) 1386 { 1387 job_unlink(pw); 1388 pw->p_nxtjob = job.pwlist; 1389 job.pwlist = pw; 1390 } 1391 } 1392 if(pw=freelist) 1393 freelist = pw->p_nxtjob; 1394 else 1395 pw = new_of(struct process,0); 1396 pw->p_flag = 0; 1397 job.numpost++; 1398 if(join && job.pwlist) 1399 { 1400 /* join existing current job */ 1401 pw->p_nxtjob = job.pwlist->p_nxtjob; 1402 pw->p_nxtproc = job.pwlist; 1403 pw->p_job = job.pwlist->p_job; 1404 } 1405 else 1406 { 1407 /* create a new job */ 1408 while((pw->p_job = job_alloc()) < 0) 1409 job_wait((pid_t)1); 1410 pw->p_nxtjob = job.pwlist; 1411 pw->p_nxtproc = 0; 1412 } 1413 pw->p_exitval = job.exitval; 1414 #if SHOPT_COSHELL 1415 pw->p_cojob = 0; 1416 if(shp->coshell && (pid&COPID_BIT)) 1417 { 1418 pw->p_cojob = ((struct cosh*)shp->coshell)->cojob; 1419 job.curpgid = sh_isstate(SH_MONITOR)?pid:0; 1420 } 1421 #endif /* SHOPT_COSHELL */ 1422 job.pwlist = pw; 1423 pw->p_shp = shp; 1424 pw->p_env = shp->curenv; 1425 pw->p_pid = pid; 1426 if(!shp->outpipe || shp->cpid==pid) 1427 pw->p_flag = P_EXITSAVE; 1428 pw->p_exitmin = shp->xargexit; 1429 pw->p_exit = 0; 1430 if(sh_isstate(SH_MONITOR)) 1431 { 1432 if(killpg(job.curpgid,0)<0 && errno==ESRCH) 1433 job.curpgid = pid; 1434 pw->p_fgrp = job.curpgid; 1435 } 1436 else 1437 pw->p_fgrp = 0; 1438 pw->p_pgrp = pw->p_fgrp; 1439 #ifdef DEBUG 1440 sfprintf(sfstderr,"ksh: job line %4d: post pid=%d critical=%d job=%d pid=%d pgid=%d savesig=%d join=%d\n",__LINE__,getpid(),job.in_critical,pw->p_job, 1441 pw->p_pid,pw->p_pgrp,job.savesig,join); 1442 sfsync(sfstderr); 1443 #endif /* DEBUG */ 1444 #ifdef JOBS 1445 if(hp && !sh_isstate(SH_PROFILE)) 1446 pw->p_name=hist_tell(shgd->hist_ptr,(int)hp->histind-1); 1447 else 1448 pw->p_name = -1; 1449 #endif /* JOBS */ 1450 if ((val = job_chksave(pid,pw->p_env))>=0 && !jobfork) 1451 { 1452 pw->p_exit = val; 1453 if(pw->p_exit==SH_STOPSIG) 1454 { 1455 pw->p_flag |= (P_SIGNALLED|P_STOPPED); 1456 pw->p_exit = 0; 1457 } 1458 else if(pw->p_exit >= SH_EXITSIG) 1459 { 1460 pw->p_flag |= P_DONE|P_SIGNALLED; 1461 pw->p_exit &= SH_EXITMASK; 1462 } 1463 else 1464 pw->p_flag |= (P_DONE|P_NOTIFY); 1465 } 1466 #ifdef SHOPT_BGX 1467 if(bg) 1468 { 1469 if(pw->p_flag&P_DONE) 1470 job.numbjob--; 1471 else 1472 pw->p_flag |= P_BG; 1473 } 1474 #endif /* SHOPT_BGX */ 1475 lastpid = 0; 1476 job_unlock(); 1477 return(pw->p_job); 1478 } 1479 1480 /* 1481 * Returns a process structure give a process id 1482 */ 1483 1484 static struct process *job_bypid(pid_t pid) 1485 { 1486 register struct process *pw, *px; 1487 for(pw=job.pwlist; pw; pw=pw->p_nxtjob) 1488 for(px=pw; px; px=px->p_nxtproc) 1489 { 1490 if(px->p_pid==pid) 1491 return(px); 1492 } 1493 return(NIL(struct process*)); 1494 } 1495 1496 /* 1497 * return a pointer to a job given the job id 1498 */ 1499 1500 static struct process *job_byjid(int jobid) 1501 { 1502 register struct process *pw; 1503 for(pw=job.pwlist;pw; pw = pw->p_nxtjob) 1504 { 1505 if(pw->p_job==jobid) 1506 break; 1507 } 1508 return(pw); 1509 } 1510 1511 /* 1512 * print a signal message 1513 */ 1514 static void job_prmsg(register struct process *pw) 1515 { 1516 if(pw->p_exit!=SIGINT && pw->p_exit!=SIGPIPE) 1517 { 1518 register const char *msg, *dump; 1519 msg = job_sigmsg((int)(pw->p_exit)); 1520 msg = sh_translate(msg); 1521 if(pw->p_flag&P_COREDUMP) 1522 dump = sh_translate(e_coredump); 1523 else 1524 dump = ""; 1525 if(sh_isstate(SH_INTERACTIVE)) 1526 sfprintf(sfstderr,"%s%s\n",msg,dump); 1527 else 1528 errormsg(SH_DICT,2,"%d: %s%s",pw->p_pid,msg,dump); 1529 } 1530 } 1531 1532 /* 1533 * Wait for process pid to complete 1534 * If pid < -1, then wait can be interrupted, -pid is waited for (wait builtin) 1535 * pid=0 to unpost all done processes 1536 * pid=1 to wait for at least one process to complete 1537 * pid=-1 to wait for all runing processes 1538 */ 1539 1540 int job_wait(register pid_t pid) 1541 { 1542 Shell_t *shp = sh_getinterp(); 1543 register struct process *pw=0,*px; 1544 register int jobid = 0; 1545 int nochild = 1; 1546 char intr = 0; 1547 if(pid < 0) 1548 { 1549 pid = -pid; 1550 intr = 1; 1551 } 1552 job_lock(); 1553 if(pid==0) 1554 { 1555 if(!job.waitall || !job.curjobid || !(pw = job_byjid(job.curjobid))) 1556 { 1557 job_unlock(); 1558 goto done; 1559 } 1560 jobid = pw->p_job; 1561 job.curjobid = 0; 1562 if(!(pw->p_flag&(P_DONE|P_STOPPED))) 1563 job_reap(job.savesig); 1564 } 1565 if(pid > 1) 1566 { 1567 if(pid==shp->spid) 1568 shp->spid = 0; 1569 if(!(pw=job_bypid(pid))) 1570 { 1571 /* check to see whether job status has been saved */ 1572 if((shp->exitval = job_chksave(pid,shp->curenv)) < 0) 1573 shp->exitval = ERROR_NOENT; 1574 exitset(); 1575 job_unlock(); 1576 return(nochild); 1577 } 1578 else if(intr && pw->p_env!=shp->curenv) 1579 { 1580 shp->exitval = ERROR_NOENT; 1581 job_unlock(); 1582 return(nochild); 1583 } 1584 jobid = pw->p_job; 1585 if(!intr) 1586 pw->p_flag &= ~P_EXITSAVE; 1587 if(pw->p_pgrp && job.parent!= (pid_t)-1) 1588 job_set(job_byjid(jobid)); 1589 } 1590 pwfg = pw; 1591 #ifdef DEBUG 1592 sfprintf(sfstderr,"ksh: job line %4d: wait pid=%d critical=%d job=%d pid=%d\n",__LINE__,getpid(),job.in_critical,jobid,pid); 1593 if(pw) 1594 sfprintf(sfstderr,"ksh: job line %4d: wait pid=%d critical=%d flags=%o\n",__LINE__,getpid(),job.in_critical,pw->p_flag); 1595 #endif /* DEBUG*/ 1596 errno = 0; 1597 if(shp->coutpipe>=0 && lastpid && shp->cpid==lastpid) 1598 { 1599 sh_close(shp->coutpipe); 1600 sh_close(shp->cpipe[1]); 1601 shp->cpipe[1] = shp->coutpipe = -1; 1602 } 1603 while(1) 1604 { 1605 if(job.waitsafe) 1606 { 1607 for(px=job.pwlist;px; px = px->p_nxtjob) 1608 { 1609 if(px!=pw && (px->p_flag&P_NOTIFY)) 1610 { 1611 if(sh_isoption(SH_NOTIFY)) 1612 { 1613 outfile = sfstderr; 1614 job_list(px,JOB_NFLAG|JOB_NLFLAG); 1615 sfsync(sfstderr); 1616 } 1617 else if(!sh_isoption(SH_INTERACTIVE) && (px->p_flag&P_SIGNALLED)) 1618 { 1619 job_prmsg(px); 1620 px->p_flag &= ~P_NOTIFY; 1621 } 1622 } 1623 } 1624 } 1625 if(pw && (pw->p_flag&(P_DONE|P_STOPPED))) 1626 { 1627 #ifdef SIGTSTP 1628 if(pw->p_flag&P_STOPPED) 1629 { 1630 pw->p_flag |= P_EXITSAVE; 1631 if(sh_isoption(SH_INTERACTIVE) && !sh_isstate(SH_FORKED)) 1632 { 1633 if( pw->p_exit!=SIGTTIN && pw->p_exit!=SIGTTOU) 1634 break; 1635 1636 killpg(pw->p_pgrp,SIGCONT); 1637 } 1638 else /* ignore stop when non-interactive */ 1639 pw->p_flag &= ~(P_NOTIFY|P_SIGNALLED|P_STOPPED|P_EXITSAVE); 1640 } 1641 else 1642 #endif /* SIGTSTP */ 1643 { 1644 if(pw->p_flag&P_SIGNALLED) 1645 { 1646 pw->p_flag &= ~P_NOTIFY; 1647 job_prmsg(pw); 1648 } 1649 else if(pw->p_flag&P_DONE) 1650 pw->p_flag &= ~P_NOTIFY; 1651 if(pw->p_job==jobid) 1652 { 1653 px = job_byjid(jobid); 1654 /* last process in job */ 1655 if(px!=pw) 1656 px = 0; 1657 if(px) 1658 { 1659 shp->exitval=px->p_exit; 1660 if(px->p_flag&P_SIGNALLED) 1661 shp->exitval |= SH_EXITSIG; 1662 if(intr) 1663 px->p_flag &= ~P_EXITSAVE; 1664 } 1665 } 1666 px = job_unpost(pw,1); 1667 if(!px || !job.waitall) 1668 break; 1669 pw = px; 1670 continue; 1671 } 1672 } 1673 sfsync(sfstderr); 1674 job.waitsafe = 0; 1675 nochild = job_reap(job.savesig); 1676 if(job.waitsafe) 1677 continue; 1678 if(nochild) 1679 break; 1680 if(shp->sigflag[SIGALRM]&SH_SIGTRAP) 1681 sh_timetraps(shp); 1682 if((intr && shp->trapnote) || (pid==1 && !intr)) 1683 break; 1684 } 1685 if(intr && shp->trapnote) 1686 shp->exitval = 1; 1687 pwfg = 0; 1688 job_unlock(); 1689 if(pid==1) 1690 return(nochild); 1691 exitset(); 1692 if(pid==0) 1693 goto done; 1694 if(pw->p_pgrp) 1695 { 1696 job_reset(pw); 1697 /* propogate keyboard interrupts to parent */ 1698 if((pw->p_flag&P_SIGNALLED) && pw->p_exit==SIGINT && !(shp->sigflag[SIGINT]&SH_SIGOFF)) 1699 kill(getpid(),SIGINT); 1700 #ifdef SIGTSTP 1701 else if((pw->p_flag&P_STOPPED) && pw->p_exit==SIGTSTP) 1702 { 1703 job.parent = 0; 1704 kill(getpid(),SIGTSTP); 1705 } 1706 #endif /* SIGTSTP */ 1707 } 1708 else 1709 { 1710 if(pw->p_pid == tcgetpgrp(JOBTTY)) 1711 { 1712 if(pw->p_pgrp==0) 1713 pw->p_pgrp = pw->p_pid; 1714 job_reset(pw); 1715 } 1716 tty_set(-1, 0, NIL(struct termios*)); 1717 } 1718 done: 1719 if(!job.waitall && sh_isoption(SH_PIPEFAIL)) 1720 return(nochild); 1721 if(!shp->intrap) 1722 { 1723 job_lock(); 1724 for(pw=job.pwlist; pw; pw=px) 1725 { 1726 px = pw->p_nxtjob; 1727 job_unpost(pw,0); 1728 } 1729 job_unlock(); 1730 } 1731 return(nochild); 1732 } 1733 1734 /* 1735 * move job to foreground if bgflag == 'f' 1736 * move job to background if bgflag == 'b' 1737 * disown job if bgflag == 'd' 1738 */ 1739 1740 int job_switch(register struct process *pw,int bgflag) 1741 { 1742 register const char *msg; 1743 job_lock(); 1744 if(!pw || !(pw=job_byjid((int)pw->p_job))) 1745 { 1746 job_unlock(); 1747 return(1); 1748 } 1749 if(bgflag=='d') 1750 { 1751 for(; pw; pw=pw->p_nxtproc) 1752 pw->p_flag |= P_DISOWN; 1753 job_unlock(); 1754 return(0); 1755 } 1756 #ifdef SIGTSTP 1757 if(bgflag=='b') 1758 { 1759 sfprintf(outfile,"[%d]\t",(int)pw->p_job); 1760 sh.bckpid = pw->p_pid; 1761 #ifdef SHOPT_BGX 1762 pw->p_flag |= P_BG; 1763 #endif 1764 msg = "&"; 1765 } 1766 else 1767 { 1768 job_unlink(pw); 1769 pw->p_nxtjob = job.pwlist; 1770 job.pwlist = pw; 1771 msg = ""; 1772 } 1773 hist_list(shgd->hist_ptr,outfile,pw->p_name,'&',";"); 1774 sfputr(outfile,msg,'\n'); 1775 sfsync(outfile); 1776 if(bgflag=='f') 1777 { 1778 if(!(pw=job_unpost(pw,1))) 1779 { 1780 job_unlock(); 1781 return(1); 1782 } 1783 job.waitall = 1; 1784 pw->p_flag |= P_FG; 1785 #ifdef SHOPT_BGX 1786 pw->p_flag &= ~P_BG; 1787 #endif 1788 job_wait(pw->p_pid); 1789 job.waitall = 0; 1790 } 1791 else if(pw->p_flag&P_STOPPED) 1792 job_unstop(pw); 1793 #endif /* SIGTSTP */ 1794 job_unlock(); 1795 return(0); 1796 } 1797 1798 1799 #ifdef SIGTSTP 1800 /* 1801 * Set the foreground group associated with a job 1802 */ 1803 1804 static void job_fgrp(register struct process *pw, int newgrp) 1805 { 1806 for(; pw; pw=pw->p_nxtproc) 1807 pw->p_fgrp = newgrp; 1808 } 1809 1810 /* 1811 * turn off STOP state of a process group and send CONT signals 1812 */ 1813 1814 static void job_unstop(register struct process *px) 1815 { 1816 register struct process *pw; 1817 register int num = 0; 1818 for(pw=px ;pw ;pw=pw->p_nxtproc) 1819 { 1820 if(pw->p_flag&P_STOPPED) 1821 { 1822 num++; 1823 pw->p_flag &= ~(P_STOPPED|P_SIGNALLED|P_NOTIFY); 1824 } 1825 } 1826 if(num!=0) 1827 { 1828 if(px->p_fgrp != px->p_pgrp) 1829 killpg(px->p_fgrp,SIGCONT); 1830 killpg(px->p_pgrp,SIGCONT); 1831 } 1832 } 1833 #endif /* SIGTSTP */ 1834 1835 /* 1836 * remove a job from table 1837 * If all the processes have not completed, unpost first non-completed process 1838 * Otherwise the job is removed and job_unpost returns NULL. 1839 * pwlist is reset if the first job is removed 1840 * if <notify> is non-zero, then jobs with pending notifications are unposted 1841 */ 1842 1843 static struct process *job_unpost(register struct process *pwtop,int notify) 1844 { 1845 register struct process *pw; 1846 /* make sure all processes are done */ 1847 #ifdef DEBUG 1848 sfprintf(sfstderr,"ksh: job line %4d: drop pid=%d critical=%d pid=%d env=%d\n",__LINE__,getpid(),job.in_critical,pwtop->p_pid,pwtop->p_env); 1849 sfsync(sfstderr); 1850 #endif /* DEBUG */ 1851 pwtop = pw = job_byjid((int)pwtop->p_job); 1852 #ifdef SHOPT_BGX 1853 if(pw->p_flag&P_BG) 1854 return(pw); 1855 #endif /* SHOPT_BGX */ 1856 for(; pw && (pw->p_flag&P_DONE)&&(notify||!(pw->p_flag&P_NOTIFY)||pw->p_env); pw=pw->p_nxtproc); 1857 if(pw) 1858 return(pw); 1859 if(pwtop->p_job == job.curjobid) 1860 return(0); 1861 /* all processes complete, unpost job */ 1862 job_unlink(pwtop); 1863 for(pw=pwtop; pw; pw=pw->p_nxtproc) 1864 { 1865 if(pw && pw->p_exitval) 1866 *pw->p_exitval = pw->p_exit; 1867 /* save the exit status for background jobs */ 1868 if((pw->p_flag&P_EXITSAVE) || pw->p_pid==sh.spid) 1869 { 1870 struct jobsave *jp; 1871 /* save status for future wait */ 1872 if(jp = jobsave_create(pw->p_pid)) 1873 { 1874 jp->exitval = pw->p_exit; 1875 if(pw->p_flag&P_SIGNALLED) 1876 jp->exitval |= SH_EXITSIG; 1877 } 1878 pw->p_flag &= ~P_EXITSAVE; 1879 } 1880 pw->p_flag &= ~P_DONE; 1881 job.numpost--; 1882 pw->p_nxtjob = freelist; 1883 freelist = pw; 1884 } 1885 pwtop->p_pid = 0; 1886 #ifdef DEBUG 1887 sfprintf(sfstderr,"ksh: job line %4d: free pid=%d critical=%d job=%d\n",__LINE__,getpid(),job.in_critical,pwtop->p_job); 1888 sfsync(sfstderr); 1889 #endif /* DEBUG */ 1890 job_free((int)pwtop->p_job); 1891 return((struct process*)0); 1892 } 1893 1894 /* 1895 * unlink a job form the job list 1896 */ 1897 static void job_unlink(register struct process *pw) 1898 { 1899 register struct process *px; 1900 if(pw==job.pwlist) 1901 { 1902 job.pwlist = pw->p_nxtjob; 1903 job.curpgid = 0; 1904 return; 1905 } 1906 for(px=job.pwlist;px;px=px->p_nxtjob) 1907 if(px->p_nxtjob == pw) 1908 { 1909 px->p_nxtjob = pw->p_nxtjob; 1910 return; 1911 } 1912 } 1913 1914 /* 1915 * get an unused job number 1916 * freejobs is a bit vector, 0 is unused 1917 */ 1918 1919 static int job_alloc(void) 1920 { 1921 register int j=0; 1922 register unsigned mask = 1; 1923 register unsigned char *freeword; 1924 register int jmax = BYTE(shgd->lim.child_max); 1925 /* skip to first word with a free slot */ 1926 for(j=0;job.freejobs[j] == UCHAR_MAX; j++); 1927 if(j >= jmax) 1928 { 1929 register struct process *pw; 1930 for(j=1; j < shgd->lim.child_max; j++) 1931 { 1932 if((pw=job_byjid(j))&& !job_unpost(pw,0)) 1933 break; 1934 } 1935 j /= CHAR_BIT; 1936 if(j >= jmax) 1937 return(-1); 1938 } 1939 freeword = &job.freejobs[j]; 1940 j *= CHAR_BIT; 1941 for(j++;mask&(*freeword);j++,mask <<=1); 1942 *freeword |= mask; 1943 return(j); 1944 } 1945 1946 /* 1947 * return a job number 1948 */ 1949 1950 static void job_free(register int n) 1951 { 1952 register int j = (--n)/CHAR_BIT; 1953 register unsigned mask; 1954 n -= j*CHAR_BIT; 1955 mask = 1 << n; 1956 job.freejobs[j] &= ~mask; 1957 } 1958 1959 static char *job_sigmsg(int sig) 1960 { 1961 static char signo[40]; 1962 #ifdef apollo 1963 /* 1964 * This code handles the formatting for the apollo specific signal 1965 * SIGAPOLLO. 1966 */ 1967 extern char *apollo_error(void); 1968 1969 if ( sig == SIGAPOLLO ) 1970 return( apollo_error() ); 1971 #endif /* apollo */ 1972 if(sig<=shgd->sigmax && shgd->sigmsg[sig]) 1973 return(shgd->sigmsg[sig]); 1974 #if defined(SIGRTMIN) && defined(SIGRTMAX) 1975 if(sig>=sh.gd->sigruntime[SH_SIGRTMIN] && sig<=sh.gd->sigruntime[SH_SIGRTMAX]) 1976 { 1977 static char sigrt[20]; 1978 if(sig>sh.gd->sigruntime[SH_SIGRTMIN]+(sh.gd->sigruntime[SH_SIGRTMAX]-sig<=sh.gd->sigruntime[SH_SIGRTMIN])/2) 1979 sfsprintf(sigrt,sizeof(sigrt),"SIGRTMAX-%d",sh.gd->sigruntime[SH_SIGRTMAX]-sig); 1980 else 1981 sfsprintf(sigrt,sizeof(sigrt),"SIGRTMIN+%d",sig-sh.gd->sigruntime[SH_SIGRTMIN]); 1982 return(sigrt); 1983 } 1984 #endif 1985 sfsprintf(signo,sizeof(signo),sh_translate(e_signo),sig); 1986 return(signo); 1987 } 1988 1989 /* 1990 * see whether exit status has been saved and delete it 1991 * if pid==0, then oldest saved process is deleted 1992 * If pid is not found a -1 is returned. 1993 */ 1994 static int job_chksave(register pid_t pid, long env) 1995 { 1996 register struct jobsave *jp = bck.list, *jpold=0; 1997 register int r= -1; 1998 register int count=bck.count; 1999 struct back_save *bp= &bck; 2000 again: 2001 while(jp && count-->0) 2002 { 2003 if(jp->pid==pid) 2004 break; 2005 if(pid==0 && !jp->next) 2006 break; 2007 jpold = jp; 2008 jp = jp->next; 2009 } 2010 if(!jp && pid && (bp=bp->prev)) 2011 { 2012 count = bp->count; 2013 jp = bp->list; 2014 jpold = 0; 2015 goto again; 2016 } 2017 if(jp && (env<0 || jp->env==env)) 2018 { 2019 r = 0; 2020 if(pid) 2021 r = jp->exitval; 2022 if(jpold) 2023 jpold->next = jp->next; 2024 else 2025 bp->list = jp->next; 2026 bp->count--; 2027 if(njob_savelist < NJOB_SAVELIST) 2028 { 2029 njob_savelist++; 2030 jp->next = job_savelist; 2031 job_savelist = jp; 2032 } 2033 else 2034 free((void*)jp); 2035 } 2036 return(r); 2037 } 2038 2039 void *job_subsave(void) 2040 { 2041 struct back_save *bp = new_of(struct back_save,0); 2042 job_lock(); 2043 *bp = bck; 2044 bp->prev = bck.prev; 2045 bck.count = 0; 2046 bck.list = 0; 2047 bck.prev = bp; 2048 job_unlock(); 2049 return((void*)bp); 2050 } 2051 2052 void job_subrestore(void* ptr) 2053 { 2054 register struct jobsave *jp,*jpnext; 2055 register struct back_save *bp = (struct back_save*)ptr; 2056 register struct process *pw, *px, *pwnext; 2057 struct jobsave *end=NULL; 2058 int i=0; 2059 job_lock(); 2060 for(jp=bck.list; jp; jp=jpnext,i++) 2061 { 2062 if (!(jpnext=jp->next) || jp==jpnext) 2063 end = jp; 2064 if(i>=shgd->lim.child_max) 2065 break; 2066 } 2067 if(end) 2068 end->next = bp->list; 2069 else 2070 bck.list = bp->list; 2071 bck.count += bp->count; 2072 bck.prev = bp->prev; 2073 while(bck.count > shgd->lim.child_max) 2074 job_chksave(0,-1); 2075 for(pw=job.pwlist; pw; pw=pwnext) 2076 { 2077 pwnext = pw->p_nxtjob; 2078 if(pw->p_env != sh.curenv || pw->p_pid==sh.pipepid) 2079 continue; 2080 for(px=pw; px; px=px->p_nxtproc) 2081 px->p_flag |= P_DONE; 2082 job_unpost(pw,0); 2083 } 2084 2085 free((void*)bp); 2086 job_unlock(); 2087 } 2088 2089 int sh_waitsafe(void) 2090 { 2091 return(job.waitsafe); 2092 } 2093 2094 void job_fork(pid_t parent) 2095 { 2096 #ifdef DEBUG 2097 sfprintf(sfstderr,"ksh: job line %4d: fork pid=%d critical=%d parent=%d\n",__LINE__,getpid(),job.in_critical,parent); 2098 #endif /* DEBUG */ 2099 switch (parent) 2100 { 2101 case -1: 2102 job_lock(); 2103 jobfork++; 2104 break; 2105 case 0: 2106 jobfork=0; 2107 job_unlock(); 2108 job.waitsafe = 0; 2109 job.in_critical = 0; 2110 break; 2111 default: 2112 job_chksave(parent,-1); 2113 jobfork=0; 2114 job_unlock(); 2115 break; 2116 } 2117 } 2118 2119