da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1982-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Job control for UNIX Shell
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * David Korn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Labs
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Written October, 1982
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Rewritten April, 1988
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Revised January, 1992
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * temporary hack to get W* macros to work
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This struct saves a link list of processes that have non-zero exit
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * status, have had $! saved, but haven't been waited for
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* _POSIX_VDISABLE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* CNSUSP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* CSUSP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* CSWTCH */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* VSUSP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Process states */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char *job_sigmsg(int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int job_alloc(void);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void job_free(int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static void job_waitsafe(int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static struct termios my_stty; /* terminal state for shell */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin extern const char e_coredump[];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* JOBS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define tcgetpgrp(a) (ioctl(a, TIOCGPGRP, &_i_)>=0?_i_:-1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* TIOCGPGRP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* TIOCGPGRP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* _lib_tcgetpgrp */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* OTTYDISC */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzvoid job_chldtrap(Shell_t *shp, const char *trap, int unpost)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if((pw->p_flag&(P_BG|P_DONE)) != (P_BG|P_DONE))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz * return next on link list of jobsave free list
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzstatic struct jobsave *jobsave_create(pid_t pid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Reap one job
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * When called with sig==0, it does a blocking wait
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin errormsg(SH_DICT,ERROR_warn(0),"vmbusy() inside job_reap() -- should not happen");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sfprintf(sfstderr,"ksh: job line %4d: reap pid=%d critical=%d signal=%d\n",__LINE__,getpid(),job.in_critical,sig) <=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* DEBUG */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * some systems (linux 2.6) may return EINVAL
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * when there are no continued children
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if(pid<0 && errno==EINTR && (sig||job.savesig))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 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);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* DEBUG */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* move to top of job list */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_pgrp && pw->p_pgrp==job.curpgid && sh_isstate(SH_STOPOK))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for coprocess completion */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* if process in current jobs terminates from
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * an interrupt, propogate to parent shell
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_pgrp && pw->p_pgrp==job.curpgid && pw->p_exit==SIGINT && sh_isstate(SH_STOPOK))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 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);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* DEBUG*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* only top-level process in job should have notify set */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin for(; px && (px->p_flag&P_DONE); px=px->p_nxtproc);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!sh.intrap && sh.st.trapcom[SIGCHLD] && pid>0 && (pwfg!=job_bypid(pid)))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This is the SIGCLD interrupt routine
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * initialize job control if possible
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if lflag is set the switching driver message will not print
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* use new line discipline when available */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* FIOLOOKLD */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* no job control when running with MPX */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* SHOPT_VSH */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* NTTYDISC */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* some systems have job control, but not initialized */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Get a controlling terminal and set process group */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* This should have already been done by rlogin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(possible = (setpgid(0,job.mypgid)>=0) || errno==EPERM)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* wait until we are in the foreground */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Stop this shell until continued */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* resumes here after continue tries again */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTTIN */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set the line discipline */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* FIOPUSHLD */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* NTTYDISC */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make sure that we are a process group leader */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# if defined(SA_NOCLDSTOP) || defined(SA_NOCLDWAIT)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# endif /* SA_NOCLDSTOP || SA_NOCLDWAIT */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* The shell now handles ^Z */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set the switch character */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* CNSUSP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * see if there are any stopped jobs
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * restore tty driver and pgrp
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(!possible && (!sh_isstate(SH_MONITOR) || sh_isstate(SH_FORKED)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* restore old line discipline */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* FIOPUSHLD */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* NTTYDISC */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* CNSUSP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save current terminal state */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* restore terminal state for job */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((pw->p_flag&P_STOPPED) || tcgetpgrp(job.fd) == sh.pid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* if job is stopped, resume it in the background */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save the terminal state for current job */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* force the following tty_get() to do a tcgetattr() unless fg */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw && (pw->p_flag&P_SIGNALLED) && pw->p_exit!=SIGHUP)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* restore terminal state for job */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* JOBS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * wait built-in command
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* JOBS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * execute function <fun> for each job
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint job_walk(Sfio_t *file,int (*fun)(struct process*,int),int arg,char *joblist[])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int r = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* do all jobs */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* skip over non-stop jobs */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(r);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * send signal <sig> to background process group if not disowned
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint job_terminate(register struct process *pw,register int sig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * list the given job
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * flag JOB_LFLAG for long listing
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * flag JOB_NFLAG for list only jobs marked for notification
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * flag JOB_PFLAG for process id(s) only
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((flag&JOB_NFLAG) && (!(px->p_flag&P_NOTIFY)||px->p_pgrp==0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(outfile,"%d\n",px->p_pgrp?px->p_pgrp:px->p_pid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((px->p_flag&P_DONE) && job.waitall && !(flag&JOB_LFLAG))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * get the process group given the job number
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This routine returns the process group number or -1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct process *job_bystring(register char *ajob)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(c=='-')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Kill a job or process
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint job_kill(register struct process *pw,register int sig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int stopsig = (sig==SIGSTOP||sig==SIGTSTP||sig==SIGTTIN||sig==SIGTTOU);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* can't stop login shell */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(r>=0 && (sig==SIGHUP||sig==SIGTERM || sig==SIGCONT))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(pw && pw->p_pgrp==0 && (r=kill(pw->p_pid,sig))>=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(r);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Get process structure from first letters of jobname
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* JOBS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Initialize the process posting array
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.freejobs = (unsigned char*)malloc((unsigned)(j+1));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(j >=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * put the process <pid> on the process list and return the job number
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if non-zero, <join> is the process id of the job to join
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* if job to join is not first move it to front */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* join existing current job */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* create a new job */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if(!sh.outpipe || (sh_isoption(SH_PIPEFAIL) && job.waitall))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 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,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* DEBUG */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* JOBS */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Returns a process structure give a process id
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return a pointer to a job given the job id
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * print a signal message
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Wait for process pid to complete
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If pid < -1, then wait can be interrupted, -pid is waited for (wait builtin)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * pid=0 to unpost all done processes
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * pid=1 to wait for at least one process to complete
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * pid=-1 to wait for all runing processes
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check to see whether job status has been saved */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr,"ksh: job line %4d: wait pid=%d critical=%d job=%d pid=%d\n",__LINE__,getpid(),job.in_critical,jobid,pid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr,"ksh: job line %4d: wait pid=%d critical=%d flags=%o\n",__LINE__,getpid(),job.in_critical,pw->p_flag);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* DEBUG*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(!sh_isoption(SH_INTERACTIVE) && (px->p_flag&P_SIGNALLED))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isoption(SH_INTERACTIVE) && !sh_isstate(SH_FORKED))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else /* ignore stop when non-interactive */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag &= ~(P_NOTIFY|P_SIGNALLED|P_STOPPED|P_EXITSAVE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* last process in job */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* last non-zero exit */
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if(!px || !sh_isoption(SH_PIPEFAIL) || !job.waitall)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* propogate keyboard interrupts to parent */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((pw->p_flag&P_SIGNALLED) && pw->p_exit==SIGINT && !(sh.sigflag[SIGINT]&SH_SIGOFF))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * move job to foreground if bgflag == 'f'
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * move job to background if bgflag == 'b'
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * disown job if bgflag == 'd'
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Set the foreground group associated with a job
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void job_fgrp(register struct process *pw, int newgrp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * turn off STOP state of a process group and send CONT signals
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * remove a job from table
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If all the processes have not completed, unpost first non-completed process
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Otherwise the job is removed and job_unpost returns NULL.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * pwlist is reset if the first job is removed
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if <notify> is non-zero, then jobs with pending notifications are unposted
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct process *job_unpost(register struct process *pwtop,int notify)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make sure all processes are done */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 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);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* DEBUG */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(; pw && (pw->p_flag&P_DONE)&&(notify||!(pw->p_flag&P_NOTIFY)||pw->p_env); pw=pw->p_nxtproc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* all processes complete, unpost job */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save the exit status for background jobs */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((pw->p_flag&P_EXITSAVE) || pw->p_pid==sh.spid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save status for future wait */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr,"ksh: job line %4d: free pid=%d critical=%d job=%d\n",__LINE__,getpid(),job.in_critical,pwtop->p_job);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* DEBUG */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((struct process*)0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * unlink a job form the job list
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * get an unused job number
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * freejobs is a bit vector, 0 is unused
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int j=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* skip to first word with a free slot */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(j);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return a job number
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int j = (--n)/CHAR_BIT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This code handles the formatting for the apollo specific signal
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * SIGAPOLLO.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin extern char *apollo_error(void);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return( apollo_error() );
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* apollo */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(sig>=sh.sigruntime[SH_SIGRTMIN] && sig<=sh.sigruntime[SH_SIGRTMAX])
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(sig>sh.sigruntime[SH_SIGRTMIN]+(sh.sigruntime[SH_SIGRTMAX]-sig<=sh.sigruntime[SH_SIGRTMIN])/2)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfsprintf(sigrt,sizeof(sigrt),"SIGRTMAX-%d",sh.sigruntime[SH_SIGRTMAX]-sig);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfsprintf(sigrt,sizeof(sigrt),"SIGRTMIN+%d",sig-sh.sigruntime[SH_SIGRTMIN]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsprintf(signo,sizeof(signo),sh_translate(e_signo),sig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * see whether exit status has been saved and delete it
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if pid==0, then oldest saved process is deleted
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If pid is not found a -1 is returned.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int r= -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(r);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((void*)bp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct back_save *bp = (struct back_save*)ptr;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(pw->p_env != sh.curenv || pw->p_pid==sh.pipepid)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin * queue up old lists for disposal by job_reap()
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr,"ksh: job line %4d: fork pid=%d critical=%d parent=%d\n",__LINE__,getpid(),job.in_critical,parent);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* DEBUG */