da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
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* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Job control for UNIX Shell
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * David Korn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Labs
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Written October, 1982
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Rewritten April, 1988
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Revised January, 1992
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "defs.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <wait.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "io.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "jobs.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "history.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !defined(WCONTINUED) || !defined(WIFCONTINUED)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# undef WCONTINUED
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define WCONTINUED 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# undef WIFCONTINUED
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define WIFCONTINUED(wstat) (0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define NJOB_SAVELIST 4
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * temporary hack to get W* macros to work
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#undef wait
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define wait ______wait
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
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 */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct jobsave
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct jobsave *next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pid_t pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned short exitval;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct jobsave *job_savelist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int njob_savelist;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinstatic struct process *pwfg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void init_savelist(void)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct jobsave *jp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(njob_savelist < NJOB_SAVELIST)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jp = newof(0,struct jobsave,1,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jp->next = job_savelist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_savelist = jp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin njob_savelist++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstruct back_save
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int count;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct jobsave *list;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define BYTE(n) (((n)+CHAR_BIT-1)/CHAR_BIT)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define MAXMSG 25
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SH_STOPSIG (SH_EXITSIG<<1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef VSUSP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# ifndef CNSUSP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# ifdef _POSIX_VDISABLE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define CNSUSP _POSIX_VDISABLE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define CNSUSP 0
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* _POSIX_VDISABLE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* CNSUSP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# ifndef CSWTCH
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# ifdef CSUSP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define CSWTCH CSUSP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define CSWTCH ('z'&037)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* CSUSP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* CSWTCH */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* VSUSP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Process states */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define P_EXITSAVE 01
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define P_STOPPED 02
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define P_NOTIFY 04
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define P_SIGNALLED 010
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define P_STTY 020
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define P_DONE 040
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define P_COREDUMP 0100
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define P_DISOWN 0200
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define P_FG 0400
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#ifdef SHOPT_BGX
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#define P_BG 01000
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int job_chksave(pid_t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct process *job_bypid(pid_t);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct process *job_byjid(int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char *job_sigmsg(int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int job_alloc(void);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void job_free(int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct process *job_unpost(struct process*,int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void job_unlink(struct process*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void job_prmsg(struct process*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct process *freelist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char beenhere;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char possible;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct process dummy;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char by_number;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic Sfio_t *outfile;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic pid_t lastpid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct back_save bck;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef JOBS
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static void job_set(struct process*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static void job_reset(struct process*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static void job_waitsafe(int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static struct process *job_byname(char*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static struct process *job_bystring(char*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static struct termios my_stty; /* terminal state for shell */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static char *job_string;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin extern const char e_coredump[];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* JOBS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTSTP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static void job_unstop(struct process*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static void job_fgrp(struct process*, int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# ifndef _lib_tcgetpgrp
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# ifdef TIOCGPGRP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static int _i_;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define tcgetpgrp(a) (ioctl(a, TIOCGPGRP, &_i_)>=0?_i_:-1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* TIOCGPGRP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int tcsetpgrp(int fd,pid_t pgrp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int pgid = pgrp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# ifdef TIOCGPGRP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(ioctl(fd, TIOCSPGRP, &pgid));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* TIOCGPGRP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* _lib_tcgetpgrp */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define job_unstop(pw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# undef CNSUSP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifndef OTTYDISC
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# undef NTTYDISC
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* OTTYDISC */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef JOBS
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef int (*Waitevent_f)(int,long,int);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#ifdef SHOPT_BGX
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzvoid job_chldtrap(Shell_t *shp, const char *trap, int unpost)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz{
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz register struct process *pw,*pwnext;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz pid_t bckpid;
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner int oldexit,trapnote;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz job_lock();
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz shp->sigflag[SIGCHLD] &= ~SH_SIGTRAP;
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner trapnote = shp->trapnote;
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner shp->trapnote = 0;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz for(pw=job.pwlist;pw;pw=pwnext)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz pwnext = pw->p_nxtjob;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if((pw->p_flag&(P_BG|P_DONE)) != (P_BG|P_DONE))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz continue;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz pw->p_flag &= ~P_BG;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz bckpid = shp->bckpid;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz oldexit = shp->savexit;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz shp->bckpid = pw->p_pid;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz shp->savexit = pw->p_exit;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(pw->p_flag&P_SIGNALLED)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz shp->savexit |= SH_EXITSIG;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz sh_trap(trap,0);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if(pw->p_pid==bckpid && unpost)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner job_unpost(pw,0);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz shp->savexit = oldexit;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz shp->bckpid = bckpid;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner shp->trapnote = trapnote;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz job_unlock();
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz}
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz/*
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz * return next on link list of jobsave free list
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzstatic struct jobsave *jobsave_create(pid_t pid)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz{
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz register struct jobsave *jp = job_savelist;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz job_chksave(pid);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(++bck.count > sh.lim.child_max)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz job_chksave(0);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(jp)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz njob_savelist--;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz job_savelist = jp->next;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz else
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz jp = newof(0,struct jobsave,1,0);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(jp)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz jp->pid = pid;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz jp->next = bck.list;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz bck.list = jp;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz jp->exitval = 0;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz return(jp);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz}
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Reap one job
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * When called with sig==0, it does a blocking wait
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint job_reap(register int sig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register pid_t pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *pw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct process *px;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int flags;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct jobsave *jp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int nochild=0, oerrno, wstat;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Waitevent_f waitevent = sh.waitevent;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static int wcontinued = WCONTINUED;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (vmbusy())
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin errormsg(SH_DICT,ERROR_warn(0),"vmbusy() inside job_reap() -- should not happen");
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (getenv("_AST_KSH_VMBUSY_ABORT"))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin abort();
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef DEBUG
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sfprintf(sfstderr,"ksh: job line %4d: reap pid=%d critical=%d signal=%d\n",__LINE__,getpid(),job.in_critical,sig) <=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin write(2,"waitsafe\n",9);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsync(sfstderr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* DEBUG */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.savesig = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags = WNOHANG|WUNTRACED|wcontinued;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags = WUNTRACED|wcontinued;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh.waitevent = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin oerrno = errno;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!(flags&WNOHANG) && !sh.intrap && job.pwlist)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_onstate(SH_TTYWAIT);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(waitevent && (*waitevent)(-1,-1L,0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags |= WNOHANG;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pid = waitpid((pid_t)-1,&wstat,flags);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_offstate(SH_TTYWAIT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * some systems (linux 2.6) may return EINVAL
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * when there are no continued children
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pid<0 && errno==EINVAL && (flags&WCONTINUED))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pid = waitpid((pid_t)-1,&wstat,flags&=~WCONTINUED);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_sigcheck();
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if(pid<0 && errno==EINTR && (sig||job.savesig))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pid<=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin flags |= WNOHANG;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.waitsafe++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jp = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin lastpid = pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(pw=job_bypid(pid)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef DEBUG
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 */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (WIFCONTINUED(wstat) && wcontinued)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw = &dummy;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_exit = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_pgrp = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin pw->p_exitmin = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(job.toclear)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_clear();
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz jp = jobsave_create(pid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin lastpid = pw->p_pid = pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin px = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(jp && WIFSTOPPED(wstat))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jp->exitval = SH_STOPSIG;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTSTP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin px=job_byjid(pw->p_job);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(WIFSTOPPED(wstat))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(px)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* move to top of job list */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlink(px);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin px->p_nxtjob = job.pwlist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.pwlist = px;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag |= (P_NOTIFY|P_SIGNALLED|P_STOPPED);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin pw->p_exit = WSTOPSIG(wstat);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_pgrp && pw->p_pgrp==job.curpgid && sh_isstate(SH_STOPOK))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_fault(pw->p_exit);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (WIFCONTINUED(wstat) && wcontinued)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag &= ~(P_NOTIFY|P_SIGNALLED|P_STOPPED);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check for coprocess completion */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pid==sh.cpid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_close(sh.coutpipe);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_close(sh.cpipe[1]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh.cpipe[1] = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh.coutpipe = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if(sh.subshell)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_subjobcheck(pid);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin pw->p_flag &= ~(P_STOPPED|P_SIGNALLED);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (WIFSIGNALED(wstat))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag |= (P_DONE|P_NOTIFY|P_SIGNALLED);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (WTERMCORE(wstat))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag |= P_COREDUMP;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_exit = WTERMSIG(wstat);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* if process in current jobs terminates from
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * an interrupt, propogate to parent shell
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_pgrp && pw->p_pgrp==job.curpgid && pw->p_exit==SIGINT && sh_isstate(SH_STOPOK))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag &= ~P_NOTIFY;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_offstate(SH_STOPOK);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_fault(SIGINT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_onstate(SH_STOPOK);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag |= (P_DONE|P_NOTIFY);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin pw->p_exit = pw->p_exitmin;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(WEXITSTATUS(wstat) > pw->p_exitmin)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_exit = WEXITSTATUS(wstat);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#ifdef SHOPT_BGX
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if((pw->p_flag&P_DONE) && (pw->p_flag&P_BG))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz job.numbjob--;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(sh.st.trapcom[SIGCHLD])
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz sh.sigflag[SIGCHLD] |= SH_SIGTRAP;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(sig==0)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz job_chldtrap(&sh,sh.st.trapcom[SIGCHLD],0);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz else
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz sh.trapnote |= SH_SIGTRAP;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz else
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz pw->p_flag &= ~P_BG;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_pgrp==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag &= ~P_NOTIFY;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(jp && pw== &dummy)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jp->exitval = pw->p_exit;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_flag&P_SIGNALLED)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jp->exitval |= SH_EXITSIG;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef DEBUG
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 sfsync(sfstderr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* DEBUG*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* only top-level process in job should have notify set */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(px && pw != px)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag &= ~P_NOTIFY;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(pid==pw->p_fgrp && pid==tcgetpgrp(JOBTTY))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin px = job_byjid((int)pw->p_job);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin for(; px && (px->p_flag&P_DONE); px=px->p_nxtproc);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!px)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin tcsetpgrp(JOBTTY,job.mypid);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#ifndef SHOPT_BGX
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(!sh.intrap && sh.st.trapcom[SIGCHLD] && pid>0 && (pwfg!=job_bypid(pid)))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh.sigflag[SIGCHLD] |= SH_SIGTRAP;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh.trapnote |= SH_SIGTRAP;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(errno==ECHILD)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errno = oerrno;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#ifdef SHOPT_BGX
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz job.numbjob = 0;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nochild = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh.waitevent = waitevent;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isoption(SH_NOTIFY) && sh_isstate(SH_TTYWAIT))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin outfile = sfstderr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_list(pw,JOB_NFLAG|JOB_NLFLAG);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unpost(pw,1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsync(sfstderr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(sig, job_waitsafe);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(nochild);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This is the SIGCLD interrupt routine
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void job_waitsafe(int sig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(job.in_critical || vmbusy())
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.savesig = sig;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.waitsafe++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_reap(sig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * initialize job control if possible
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if lflag is set the switching driver message will not print
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinvoid job_init(Shell_t *shp, int lflag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register int ntry=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.fd = JOBTTY;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(SIGCHLD,job_waitsafe);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# if defined(SIGCLD) && (SIGCLD!=SIGCHLD)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(SIGCLD,job_waitsafe);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(njob_savelist < NJOB_SAVELIST)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin init_savelist();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!sh_isoption(SH_INTERACTIVE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* use new line discipline when available */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef NTTYDISC
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# ifdef FIOLOOKLD
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((job.linedisc = ioctl(JOBTTY, FIOLOOKLD, 0)) <0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(ioctl(JOBTTY,TIOCGETD,&job.linedisc) !=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* FIOLOOKLD */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(job.linedisc!=NTTYDISC && job.linedisc!=OTTYDISC)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* no job control when running with MPX */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# if SHOPT_VSH
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_onoption(SH_VIRAW);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* SHOPT_VSH */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(job.linedisc==NTTYDISC)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.linedisc = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* NTTYDISC */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.mypgid = getpgrp();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* some systems have job control, but not initialized */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(job.mypgid<=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Get a controlling terminal and set process group */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* This should have already been done by rlogin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int fd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *ttynam;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifndef SIGTSTP
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin setpgid(0,shp->pid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(job.mypgid<0 || !(ttynam=ttyname(JOBTTY)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(JOBTTY);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((fd = open(ttynam,O_RDWR)) <0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(fd!=JOBTTY)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_iorenumber(shp,fd,JOBTTY);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin job.mypgid = shp->pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTSTP
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin tcsetpgrp(JOBTTY,shp->pid);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin setpgid(0,shp->pid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTSTP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(possible = (setpgid(0,job.mypgid)>=0) || errno==EPERM)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* wait until we are in the foreground */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while((job.mytgid=tcgetpgrp(JOBTTY)) != job.mypgid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(job.mytgid == -1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Stop this shell until continued */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(SIGTTIN,SIG_DFL);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin kill(shp->pid,SIGTTIN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* resumes here after continue tries again */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(ntry++ > IOMAXTRY)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,0,e_no_start);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTTIN */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef NTTYDISC
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set the line discipline */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(job.linedisc>=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int linedisc = NTTYDISC;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# ifdef FIOPUSHLD
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tty_get(JOBTTY,&my_stty);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (ioctl(JOBTTY, FIOPOPLD, 0) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (ioctl(JOBTTY, FIOPUSHLD, &linedisc) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ioctl(JOBTTY, FIOPUSHLD, &job.linedisc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tty_set(JOBTTY,TCSANOW,&my_stty);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(ioctl(JOBTTY,TIOCSETD,&linedisc) !=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* FIOPUSHLD */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(lflag==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,0,e_newtty);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.linedisc = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* NTTYDISC */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!possible)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTSTP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make sure that we are a process group leader */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin setpgid(0,shp->pid);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# if defined(SA_NOCLDSTOP) || defined(SA_NOCLDWAIT)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# if !defined(SA_NOCLDSTOP)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# define SA_NOCLDSTOP 0
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# endif
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# if !defined(SA_NOCLDWAIT)
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# define SA_NOCLDWAIT 0
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sigflag(SIGCHLD, SA_NOCLDSTOP|SA_NOCLDWAIT, 0);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# endif /* SA_NOCLDSTOP || SA_NOCLDWAIT */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(SIGTTIN,SIG_IGN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(SIGTTOU,SIG_IGN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* The shell now handles ^Z */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin signal(SIGTSTP,sh_fault);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin tcsetpgrp(JOBTTY,shp->pid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# ifdef CNSUSP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* set the switch character */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tty_get(JOBTTY,&my_stty);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.suspend = (unsigned)my_stty.c_cc[VSUSP];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(job.suspend == (unsigned char)CNSUSP)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin my_stty.c_cc[VSUSP] = CSWTCH;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tty_set(JOBTTY,TCSAFLUSH,&my_stty);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* CNSUSP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_onoption(SH_MONITOR);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.jobcontrol++;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin job.mypid = shp->pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * see if there are any stopped jobs
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * restore tty driver and pgrp
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinint job_close(Shell_t* shp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *pw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int count = 0, running = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(possible && !job.jobcontrol)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(!possible && (!sh_isstate(SH_MONITOR) || sh_isstate(SH_FORKED)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(getpid() != job.mypid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_lock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!tty_check(0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin beenhere++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(pw=job.pwlist;pw;pw=pw->p_nxtjob)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(pw->p_flag&P_STOPPED))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(pw->p_flag&P_DONE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin running++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(beenhere)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin killpg(pw->p_pgrp,SIGTERM);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin count++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(beenhere++ == 0 && job.pwlist)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(count)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,0,e_terminate);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if(running && shp->login_sh)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,0,e_jobsrunning);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# ifdef SIGTSTP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(possible && setpgid(0,job.mypgid)>=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tcsetpgrp(job.fd,job.mypgid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# ifdef NTTYDISC
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(job.linedisc>=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* restore old line discipline */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# ifdef FIOPUSHLD
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tty_get(job.fd,&my_stty);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (ioctl(job.fd, FIOPOPLD, 0) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (ioctl(job.fd, FIOPUSHLD, &job.linedisc) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.linedisc = NTTYDISC;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ioctl(job.fd, FIOPUSHLD, &job.linedisc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tty_set(job.fd,TCSAFLUSH,&my_stty);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(ioctl(job.fd,TIOCSETD,&job.linedisc) !=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* FIOPUSHLD */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,0,e_oldtty);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* NTTYDISC */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# ifdef CNSUSP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(possible && job.suspend==CNSUSP)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tty_get(job.fd,&my_stty);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin my_stty.c_cc[VSUSP] = CNSUSP;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tty_set(job.fd,TCSAFLUSH,&my_stty);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# endif /* CNSUSP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.jobcontrol = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void job_set(register struct process *pw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save current terminal state */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tty_get(job.fd,&my_stty);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_flag&P_STTY)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* restore terminal state for job */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tty_set(job.fd,TCSAFLUSH,&pw->p_stty);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTSTP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((pw->p_flag&P_STOPPED) || tcgetpgrp(job.fd) == sh.pid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tcsetpgrp(job.fd,pw->p_fgrp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* if job is stopped, resume it in the background */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unstop(pw);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void job_reset(register struct process *pw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save the terminal state for current job */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTSTP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_fgrp(pw,tcgetpgrp(job.fd));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(tcsetpgrp(job.fd,job.mypid) !=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* force the following tty_get() to do a tcgetattr() unless fg */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(pw->p_flag&P_FG))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tty_set(-1, 0, NIL(struct termios*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw && (pw->p_flag&P_SIGNALLED) && pw->p_exit!=SIGHUP)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(tty_get(job.fd,&pw->p_stty) == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag |= P_STTY;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* restore terminal state for job */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tty_set(job.fd,TCSAFLUSH,&my_stty);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin beenhere = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* JOBS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * wait built-in command
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinvoid job_bwait(char **jobs)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *jp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *pw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register pid_t pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*jobs==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_wait((pid_t)-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else while(jp = *jobs++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef JOBS
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*jp == '%')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_lock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw = job_bystring(jp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pid = pw->p_pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* JOBS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pid = (int)strtol(jp, (char**)0, 10);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_wait(-pid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef JOBS
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * execute function <fun> for each job
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint job_walk(Sfio_t *file,int (*fun)(struct process*,int),int arg,char *joblist[])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *pw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int r = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *jobid, **jobs=joblist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *px;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_string = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin outfile = file;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin by_number = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_lock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw = job.pwlist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(jobs==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* do all jobs */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(;pw;pw=px)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin px = pw->p_nxtjob;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_env != sh.jobenv)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((*fun)(pw,arg))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = 2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(*jobs==0) /* current job */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* skip over non-stop jobs */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(pw && (pw->p_env!=sh.jobenv || pw->p_pgrp==0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw = pw->p_nxtjob;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((*fun)(pw,arg))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = 2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else while(jobid = *jobs++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_string = jobid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*jobid==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_exit(1),e_jobusage,job_string);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*jobid == '%')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw = job_bystring(jobid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int pid = (int)strtol(jobid, (char**)0, 10);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pid<0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jobid++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(isdigit(*jobid))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jobid++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*jobid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_exit(1),e_jobusage,job_string);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(pw = job_bypid(pid)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw = &dummy;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_pid = pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_pgrp = pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin by_number = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((*fun)(pw,arg))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = 2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin by_number = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(r);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * send signal <sig> to background process group if not disowned
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint job_terminate(register struct process *pw,register int sig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_pgrp && !(pw->p_flag&P_DISOWN))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_kill(pw,sig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
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 */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint job_list(struct process *pw,register int flag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *px = pw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register const char *msg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int msize;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!pw || pw->p_job<=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_env != sh.jobenv)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((flag&JOB_NFLAG) && (!(px->p_flag&P_NOTIFY)||px->p_pgrp==0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((flag&JOB_PFLAG))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(outfile,"%d\n",px->p_pgrp?px->p_pgrp:px->p_pid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((px->p_flag&P_DONE) && job.waitall && !(flag&JOB_LFLAG))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_lock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = px->p_job;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(px==job.pwlist)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin msize = '+';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(px==job.pwlist->p_nxtjob)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin msize = '-';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin msize = ' ';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(flag&JOB_NLFLAG)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputc(outfile,'\n');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(outfile,"[%d] %c ",n, msize);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin do
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(flag&JOB_LFLAG)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(outfile,"%d\t",px->p_pid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(px->p_flag&P_SIGNALLED)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin msg = job_sigmsg((int)(px->p_exit));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(px->p_flag&P_NOTIFY)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin msg = sh_translate(e_done);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = px->p_exit;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin msg = sh_translate(e_running);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin px->p_flag &= ~P_NOTIFY;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputr(outfile,msg,-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin msize = strlen(msg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(outfile,"(%d)",(int)n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin msize += (3+(n>10)+(n>100));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(px->p_flag&P_COREDUMP)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin msg = sh_translate(e_coredump);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputr(outfile, msg, -1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin msize += strlen(msg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfnputc(outfile,' ',MAXMSG>msize?MAXMSG-msize:1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(flag&JOB_LFLAG)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin px = px->p_nxtproc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(px=px->p_nxtproc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin px->p_flag &= ~P_NOTIFY;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin px = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!px)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin hist_list(sh.hist_ptr,outfile,pw->p_name,0,";");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputr(outfile, e_nlspace, -1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(px);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * get the process group given the job number
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This routine returns the process group number or -1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct process *job_bystring(register char *ajob)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *pw=job.pwlist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*ajob++ != '%' || !pw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(NIL(struct process*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = *ajob;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(isdigit(c))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw = job_byjid((int)strtol(ajob, (char**)0, 10));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(c=='+' || c=='%')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(c=='-')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw = job.pwlist->p_nxtjob;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw = job_byname(ajob);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw && pw->p_flag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(pw);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(NIL(struct process*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Kill a job or process
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint job_kill(register struct process *pw,register int sig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register pid_t pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin const char *msg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTSTP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int stopsig = (sig==SIGSTOP||sig==SIGTSTP||sig==SIGTTIN||sig==SIGTTOU);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define stopsig 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_lock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errno = ECHILD;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto error;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pid = pw->p_pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(by_number)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pid==0 && job.jobcontrol)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = job_walk(outfile, job_kill,sig, (char**)0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTSTP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sig==SIGSTOP && pid==sh.pid && sh.ppid==1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* can't stop login shell */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errno = EPERM;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pid>=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((r = kill(pid,sig))>=0 && !stopsig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_flag&P_STOPPED)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag &= ~(P_STOPPED|P_SIGNALLED);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin kill(pid,SIGCONT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((r = killpg(-pid,sig))>=0 && !stopsig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unstop(job_bypid(pw->p_pid));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin killpg(-pid,SIGCONT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pid>=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = kill(pid,sig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = killpg(-pid,sig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pid = pw->p_pgrp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = killpg(pid,sig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTSTP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(r>=0 && (sig==SIGHUP||sig==SIGTERM || sig==SIGCONT))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unstop(pw);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(r>=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_delay(.05);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(pw && pw->p_pgrp==0 && (r=kill(pw->p_pid,sig))>=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTSTP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sig==SIGHUP || sig==SIGTERM)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin kill(pw->p_pid,SIGCONT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw = pw->p_nxtproc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(r<0 && job_string)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw && by_number)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin msg = sh_translate(e_no_proc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin msg = sh_translate(e_no_job);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(errno == EPERM)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin msg = sh_translate(e_access);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr,"kill: %s: %s\n",job_string, msg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = 2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_delay(.001);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(r);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Get process structure from first letters of jobname
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct process *job_byname(char *name)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *pw = job.pwlist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *pz = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int *flag = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char *cp = name;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int offset;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!sh.hist_ptr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(NIL(struct process*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*cp=='?')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cp++,flag= &offset;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(;pw;pw=pw->p_nxtjob)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(hist_match(sh.hist_ptr,pw->p_name,cp,flag)>=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pz)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,ERROR_exit(1),e_jobusage,name-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pz = pw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(pz);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define job_set(x)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin# define job_reset(x)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* JOBS */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Initialize the process posting array
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinvoid job_clear(void)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *pw, *px;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *pwnext;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int j = BYTE(sh.lim.child_max);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct jobsave *jp,*jpnext;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_lock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(pw=job.pwlist; pw; pw=pwnext)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pwnext = pw->p_nxtjob;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(px=pw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw = pw->p_nxtproc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free((void*)px);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(jp=bck.list; jp;jp=jpnext)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jpnext = jp->next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free((void*)jp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bck.list = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(njob_savelist < NJOB_SAVELIST)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin init_savelist();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.pwlist = NIL(struct process*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.numpost=0;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#ifdef SHOPT_BGX
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz job.numbjob = 0;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.waitall = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.curpgid = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.toclear = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!job.freejobs)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.freejobs = (unsigned char*)malloc((unsigned)(j+1));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(j >=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.freejobs[j--] = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
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 */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint job_post(pid_t pid, pid_t join)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *pw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register History_t *hp = sh.hist_ptr;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#ifdef SHOPT_BGX
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz int val,bg=0;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int val;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh.jobenv = sh.curenv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(job.toclear)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_clear();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_lock();
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#ifdef SHOPT_BGX
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(join==1)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz join = 0;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz bg = P_BG;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz job.numbjob++;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(njob_savelist < NJOB_SAVELIST)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz init_savelist();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw = job_bypid(pid))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unpost(pw,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(join && (pw=job_bypid(join)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* if job to join is not first move it to front */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((pw=job_byjid(pw->p_job)) != job.pwlist)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlink(pw);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_nxtjob = job.pwlist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.pwlist = pw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw=freelist)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin freelist = pw->p_nxtjob;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw = new_of(struct process,0);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz pw->p_flag = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.numpost++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(join && job.pwlist)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* join existing current job */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_nxtjob = job.pwlist->p_nxtjob;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_nxtproc = job.pwlist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_job = job.pwlist->p_job;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* create a new job */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while((pw->p_job = job_alloc()) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_wait((pid_t)1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_nxtjob = job.pwlist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_nxtproc = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.pwlist = pw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_env = sh.curenv;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_pid = pid;
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if(!sh.outpipe || (sh_isoption(SH_PIPEFAIL) && job.waitall))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz pw->p_flag = P_EXITSAVE;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin pw->p_exitmin = sh.xargexit;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin pw->p_exit = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isstate(SH_MONITOR))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(killpg(job.curpgid,0)<0 && errno==ESRCH)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.curpgid = pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_fgrp = job.curpgid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_fgrp = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_pgrp = pw->p_fgrp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef DEBUG
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 pw->p_pid,pw->p_pgrp,job.savesig,join);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsync(sfstderr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* DEBUG */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef JOBS
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(hp && !sh_isstate(SH_PROFILE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_name=hist_tell(sh.hist_ptr,(int)hp->histind-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_name = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* JOBS */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if ((val = job_chksave(pid)) >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin pw->p_exit = val;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_exit==SH_STOPSIG)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag |= (P_SIGNALLED|P_STOPPED);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_exit = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz else if(pw->p_exit >= SH_EXITSIG)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz pw->p_flag |= P_DONE|P_SIGNALLED;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz pw->p_exit &= SH_EXITMASK;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag |= (P_DONE|P_NOTIFY);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#ifdef SHOPT_BGX
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(bg && !(pw->p_flag&P_DONE))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz pw->p_flag |= P_BG;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif /* SHOPT_BGX */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin lastpid = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(pw->p_job);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Returns a process structure give a process id
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct process *job_bypid(pid_t pid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *pw, *px;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(pw=job.pwlist; pw; pw=pw->p_nxtjob)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(px=pw; px; px=px->p_nxtproc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(px->p_pid==pid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(px);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(NIL(struct process*));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return a pointer to a job given the job id
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct process *job_byjid(int jobid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *pw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(pw=job.pwlist;pw; pw = pw->p_nxtjob)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_job==jobid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(pw);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * print a signal message
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void job_prmsg(register struct process *pw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_exit!=SIGINT && pw->p_exit!=SIGPIPE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register const char *msg, *dump;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin msg = job_sigmsg((int)(pw->p_exit));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin msg = sh_translate(msg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_flag&P_COREDUMP)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dump = sh_translate(e_coredump);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin dump = "";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isstate(SH_INTERACTIVE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr,"%s%s\n",msg,dump);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errormsg(SH_DICT,2,"%d: %s%s",pw->p_pid,msg,dump);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
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 */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinint job_wait(register pid_t pid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *pw=0,*px;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int jobid = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin int nochild = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char intr = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pid <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pid==0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pid = -pid;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin intr = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_lock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pid > 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(pid==sh.spid)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh.spid = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(pw=job_bypid(pid)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* check to see whether job status has been saved */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((sh.exitval = job_chksave(pid)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh.exitval = ERROR_NOENT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin exitset();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return(nochild);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(intr && pw->p_env!=sh.curenv)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh.exitval = ERROR_NOENT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return(nochild);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jobid = pw->p_job;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!intr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag &= ~P_EXITSAVE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_pgrp && job.parent!= (pid_t)-1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_set(job_byjid(jobid));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin pwfg = pw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef DEBUG
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 if(pw)
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 errno = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(sh.coutpipe>=0 && sh.cpid==lastpid)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_close(sh.coutpipe);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh_close(sh.cpipe[1]);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sh.cpipe[1] = sh.coutpipe = -1;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(job.waitsafe)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(px=job.pwlist;px; px = px->p_nxtjob)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(px!=pw && (px->p_flag&P_NOTIFY))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isoption(SH_NOTIFY))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin outfile = sfstderr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_list(px,JOB_NFLAG|JOB_NLFLAG);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsync(sfstderr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(!sh_isoption(SH_INTERACTIVE) && (px->p_flag&P_SIGNALLED))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_prmsg(px);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin px->p_flag &= ~P_NOTIFY;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw && (pw->p_flag&(P_DONE|P_STOPPED)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTSTP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_flag&P_STOPPED)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag |= P_EXITSAVE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isoption(SH_INTERACTIVE) && !sh_isstate(SH_FORKED))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if( pw->p_exit!=SIGTTIN && pw->p_exit!=SIGTTOU)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin killpg(pw->p_pgrp,SIGCONT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else /* ignore stop when non-interactive */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag &= ~(P_NOTIFY|P_SIGNALLED|P_STOPPED|P_EXITSAVE);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_flag&P_SIGNALLED)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag &= ~P_NOTIFY;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_prmsg(pw);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(pw->p_flag&P_DONE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag &= ~P_NOTIFY;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_job==jobid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin px = job_byjid(jobid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* last process in job */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh_isoption(SH_PIPEFAIL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* last non-zero exit */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(;px;px=px->p_nxtproc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(px->p_exit)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!px)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin px = pw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(px!=pw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin px = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(px)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh.exitval=px->p_exit;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(px->p_flag&P_SIGNALLED)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh.exitval |= SH_EXITSIG;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(intr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin px->p_flag &= ~P_EXITSAVE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz px = job_unpost(pw,1);
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner if(!px || !sh_isoption(SH_PIPEFAIL) || !job.waitall)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw = px;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsync(sfstderr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.waitsafe = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nochild = job_reap(job.savesig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(job.waitsafe)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(nochild)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(sh.sigflag[SIGALRM]&SH_SIGTRAP)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_timetraps();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((intr && sh.trapnote) || (pid==1 && !intr))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin pwfg = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pid==1)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return(nochild);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin exitset();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_pgrp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_reset(pw);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* propogate keyboard interrupts to parent */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((pw->p_flag&P_SIGNALLED) && pw->p_exit==SIGINT && !(sh.sigflag[SIGINT]&SH_SIGOFF))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_fault(SIGINT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTSTP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if((pw->p_flag&P_STOPPED) && pw->p_exit==SIGTSTP)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.parent = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh_fault(SIGTSTP);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(pw->p_pid == tcgetpgrp(JOBTTY))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(pw->p_pgrp==0)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin pw->p_pgrp = pw->p_pid;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin job_reset(pw);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tty_set(-1, 0, NIL(struct termios*));
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chindone:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!job.waitall && sh_isoption(SH_PIPEFAIL))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return(nochild);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!sh.intrap)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_lock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(pw=job.pwlist; pw; pw=px)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin px = pw->p_nxtjob;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unpost(pw,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return(nochild);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * move job to foreground if bgflag == 'f'
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * move job to background if bgflag == 'b'
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * disown job if bgflag == 'd'
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint job_switch(register struct process *pw,int bgflag)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register const char *msg;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_lock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!pw || !(pw=job_byjid((int)pw->p_job)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(bgflag=='d')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(; pw; pw=pw->p_nxtproc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag |= P_DISOWN;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTSTP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(bgflag=='b')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(outfile,"[%d]\t",(int)pw->p_job);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sh.bckpid = pw->p_pid;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#ifdef SHOPT_BGX
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz pw->p_flag |= P_BG;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin msg = "&";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlink(pw);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_nxtjob = job.pwlist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.pwlist = pw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin msg = "";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin hist_list(sh.hist_ptr,outfile,pw->p_name,'&',";");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputr(outfile,msg,'\n');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsync(outfile);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(bgflag=='f')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(!(pw=job_unpost(pw,1)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.waitall = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag |= P_FG;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#ifdef SHOPT_BGX
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz pw->p_flag &= ~P_BG;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_wait(pw->p_pid);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.waitall = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(pw->p_flag&P_STOPPED)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unstop(pw);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef SIGTSTP
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Set the foreground group associated with a job
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void job_fgrp(register struct process *pw, int newgrp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(; pw; pw=pw->p_nxtproc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_fgrp = newgrp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * turn off STOP state of a process group and send CONT signals
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void job_unstop(register struct process *px)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *pw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int num = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(pw=px ;pw ;pw=pw->p_nxtproc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_flag&P_STOPPED)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin num++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag &= ~(P_STOPPED|P_SIGNALLED|P_NOTIFY);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(num!=0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(px->p_fgrp != px->p_pgrp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin killpg(px->p_fgrp,SIGCONT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin killpg(px->p_pgrp,SIGCONT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* SIGTSTP */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
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
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic struct process *job_unpost(register struct process *pwtop,int notify)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *pw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* make sure all processes are done */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef DEBUG
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 sfsync(sfstderr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* DEBUG */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pwtop = pw = job_byjid((int)pwtop->p_job);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#ifdef SHOPT_BGX
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(pw->p_flag&P_BG)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz return(pw);
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 if(pw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(pw);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* all processes complete, unpost job */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlink(pwtop);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(pw=pwtop; pw; pw=pw->p_nxtproc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save the exit status for background jobs */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if((pw->p_flag&P_EXITSAVE) || pw->p_pid==sh.spid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct jobsave *jp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* save status for future wait */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(jp = jobsave_create(pw->p_pid))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jp->exitval = pw->p_exit;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw->p_flag&P_SIGNALLED)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jp->exitval |= SH_EXITSIG;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag &= ~P_EXITSAVE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_flag &= ~P_DONE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.numpost--;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pw->p_nxtjob = freelist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin freelist = pw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner pwtop->p_pid = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef DEBUG
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr,"ksh: job line %4d: free pid=%d critical=%d job=%d\n",__LINE__,getpid(),job.in_critical,pwtop->p_job);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsync(sfstderr);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* DEBUG */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_free((int)pwtop->p_job);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((struct process*)0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * unlink a job form the job list
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void job_unlink(register struct process *pw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *px;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pw==job.pwlist)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.pwlist = pw->p_nxtjob;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.curpgid = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(px=job.pwlist;px;px=px->p_nxtjob)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(px->p_nxtjob == pw)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin px->p_nxtjob = pw->p_nxtjob;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * get an unused job number
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * freejobs is a bit vector, 0 is unused
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int job_alloc(void)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int j=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned mask = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char *freeword;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int jmax = BYTE(sh.lim.child_max);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* skip to first word with a free slot */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(j=0;job.freejobs[j] == UCHAR_MAX; j++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(j >= jmax)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *pw;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(j=1; j < sh.lim.child_max; j++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((pw=job_byjid(j))&& !job_unpost(pw,0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin j /= CHAR_BIT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(j >= jmax)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin freeword = &job.freejobs[j];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin j *= CHAR_BIT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(j++;mask&(*freeword);j++,mask <<=1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *freeword |= mask;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(j);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return a job number
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void job_free(register int n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int j = (--n)/CHAR_BIT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned mask;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n -= j*CHAR_BIT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mask = 1 << n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.freejobs[j] &= ~mask;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char *job_sigmsg(int sig)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static char signo[40];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef apollo
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This code handles the formatting for the apollo specific signal
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * SIGAPOLLO.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin extern char *apollo_error(void);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ( sig == SIGAPOLLO )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return( apollo_error() );
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* apollo */
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(sig<=sh.sigmax && sh.sigmsg[sig])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(sh.sigmsg[sig]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(SIGRTMIN) && defined(SIGRTMAX)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(sig>=sh.sigruntime[SH_SIGRTMIN] && sig<=sh.sigruntime[SH_SIGRTMAX])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static char sigrt[20];
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 else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin sfsprintf(sigrt,sizeof(sigrt),"SIGRTMIN+%d",sig-sh.sigruntime[SH_SIGRTMIN]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(sigrt);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfsprintf(signo,sizeof(signo),sh_translate(e_signo),sig);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(signo);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
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 */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int job_chksave(register pid_t pid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct jobsave *jp = bck.list, *jpold=0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int r= -1;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz register int count=bck.count;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz while(jp && count-->0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(jp->pid==pid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pid==0 && !jp->next)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jpold = jp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jp = jp->next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(jp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(pid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = jp->exitval;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(jpold)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jpold->next = jp->next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bck.list = jp->next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bck.count--;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(njob_savelist < NJOB_SAVELIST)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin njob_savelist++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin jp->next = job_savelist;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_savelist = jp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free((void*)jp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(r);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinvoid *job_subsave(void)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct back_save *bp = new_of(struct back_save,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_lock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *bp = bck;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bck.count = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bck.list = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return((void*)bp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinvoid job_subrestore(void* ptr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register struct jobsave *jp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct back_save *bp = (struct back_save*)ptr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register struct process *pw, *px, *pwnext;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin struct jobsave *jpnext;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_lock();
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin for(jp=bck.list; jp; jp=jpnext)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin jpnext = jp->next;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if(jp->pid==sh.spid)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin jp->next = bp->list;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin bp->list = jp;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz bp->count++;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin job_chksave(jp->pid);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(pw=job.pwlist; pw; pw=pwnext)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pwnext = pw->p_nxtjob;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if(pw->p_env != sh.curenv || pw->p_pid==sh.pipepid)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(px=pw; px; px=px->p_nxtproc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin px->p_flag |= P_DONE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unpost(pw,0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin /*
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin * queue up old lists for disposal by job_reap()
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin bck = *bp;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin free((void*)bp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint sh_waitsafe(void)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return(job.waitsafe);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinvoid job_fork(pid_t parent)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef DEBUG
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr,"ksh: job line %4d: fork pid=%d critical=%d parent=%d\n",__LINE__,getpid(),job.in_critical,parent);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* DEBUG */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (parent)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case -1:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_lock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 0:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.waitsafe = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job.in_critical = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner job_chksave(parent);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin job_unlock();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}