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