Quizzer

 view release on metacpan or  search on metacpan

exercises/compile-tcsh/tcsh-6.10.00/sh.proc.c  view on Meta::CPAN

#ifdef SHORT_STRINGS
		xputchar('\r' | QUOTE), xputchar('\n');
#else /* !SHORT_STRINGS */
		xprintf("\215\n");	/* \215 is a quoted ^M */
#endif /* !SHORT_STRINGS */
		(void) pprint(pp, NUMBER | NAME | REASON);
		if ((jobflags & PSTOPPED) == 0)
		    pflush(pp);
		{
		    extern Char GettingInput;

		    if (GettingInput) {
			errno = 0;
			(void) Rawmode();
#ifdef notdef
			/*
			 * don't really want to do that, because it
			 * will erase our message in case of multi-line
			 * input
			 */
			ClearLines();
#endif /* notdef */
			ClearDisp();
			Refresh();
		    }
		}
	    }
	    else {
		fp->p_flags |= PNEEDNOTE;
		neednote++;
	    }
	}
    }
#if defined(BSDJOBS) || defined(HAVEwait3)
    goto loop;
#endif /* BSDJOBS || HAVEwait3 */
}

void
pnote()
{
    register struct process *pp;
    int     flags;
#ifdef BSDSIGS
    sigmask_t omask;
#endif /* BSDSIGS */

    neednote = 0;
    for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) {
	if (pp->p_flags & PNEEDNOTE) {
#ifdef BSDSIGS
	    omask = sigblock(sigmask(SIGCHLD));
#else /* !BSDSIGS */
	    (void) sighold(SIGCHLD);
#endif /* !BSDSIGS */
	    pp->p_flags &= ~PNEEDNOTE;
	    flags = pprint(pp, NUMBER | NAME | REASON);
	    if ((flags & (PRUNNING | PSTOPPED)) == 0)
		pflush(pp);
#ifdef BSDSIGS
	    (void) sigsetmask(omask);
#else /* !BSDSIGS */
	    (void) sigrelse(SIGCHLD);
#endif /* !BSDSIGS */
	}
    }
}


static void
pfree(pp)
    struct process *pp;
{	
    xfree((ptr_t) pp->p_command);
    if (pp->p_cwd && --pp->p_cwd->di_count == 0)
	if (pp->p_cwd->di_next == 0)
	    dfree(pp->p_cwd);
    xfree((ptr_t) pp);
}


/*
 * pwait - wait for current job to terminate, maintaining integrity
 *	of current and previous job indicators.
 */
void
pwait()
{
    register struct process *fp, *pp;
#ifdef BSDSIGS
    sigmask_t omask;
#endif /* BSDSIGS */

    /*
     * Here's where dead procs get flushed.
     */
#ifdef BSDSIGS
    omask = sigblock(sigmask(SIGCHLD));
#else /* !BSDSIGS */
    (void) sighold(SIGCHLD);
#endif /* !BSDSIGS */
    for (pp = (fp = &proclist)->p_next; pp != NULL; pp = (fp = pp)->p_next)
	if (pp->p_procid == 0) {
	    fp->p_next = pp->p_next;
	    pfree(pp);
	    pp = fp;
	}
#ifdef BSDSIGS
    (void) sigsetmask(omask);
#else /* !BSDSIGS */
    (void) sigrelse(SIGCHLD);
# ifdef notdef
    if (setintr)
	sigignore(SIGINT);
# endif /* notdef */
#endif /* !BSDSIGS */
    pjwait(pcurrjob);
}


/*
 * pjwait - wait for a job to finish or become stopped
 *	It is assumed to be in the foreground state (PFOREGND)
 */
void
pjwait(pp)
    register struct process *pp;
{
    register struct process *fp;
    int     jobflags, reason;
#ifdef BSDSIGS
    sigmask_t omask;
#endif /* BSDSIGS */
#ifdef UNRELSIGS
    signalfun_t inthandler;
#endif /* UNRELSIGS */
    while (pp->p_procid != pp->p_jobid)
	pp = pp->p_friends;
    fp = pp;

    do {
	if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING)
	    xprintf(CGETS(17, 1, "BUG: waiting for background job!\n"));
    } while ((fp = fp->p_friends) != pp);
    /*
     * Now keep pausing as long as we are not interrupted (SIGINT), and the
     * target process, or any of its friends, are running
     */
    fp = pp;
#ifdef BSDSIGS
    omask = sigblock(sigmask(SIGCHLD));
#endif /* BSDSIGS */
#ifdef UNRELSIGS
    if (setintr)
        inthandler = signal(SIGINT, SIG_IGN);
#endif /* UNRELSIGS */
    for (;;) {
#ifndef BSDSIGS
	(void) sighold(SIGCHLD);
#endif /* !BSDSIGS */
	jobflags = 0;
	do
	    jobflags |= fp->p_flags;
	while ((fp = (fp->p_friends)) != pp);
	if ((jobflags & PRUNNING) == 0)
	    break;
#ifdef JOBDEBUG
	xprintf("%d starting to sigpause for  SIGCHLD on %d\n",
		getpid(), fp->p_procid);
#endif /* JOBDEBUG */
#ifdef BSDSIGS
	/* (void) sigpause(sigblock((sigmask_t) 0) &~ sigmask(SIGCHLD)); */
	(void) sigpause(omask & ~sigmask(SIGCHLD));
#else /* !BSDSIGS */
	(void) sigpause(SIGCHLD);
#endif /* !BSDSIGS */
    }
#ifdef JOBDEBUG
	xprintf("%d returned from sigpause loop\n", getpid());
#endif /* JOBDEBUG */
#ifdef BSDSIGS
    (void) sigsetmask(omask);
#else /* !BSDSIGS */
    (void) sigrelse(SIGCHLD);
#endif /* !BSDSIGS */
#ifdef UNRELSIGS
    if (setintr)
        (void) signal(SIGINT, inthandler);
#endif /* UNRELSIGS */
#ifdef BSDJOBS
    if (tpgrp > 0)		/* get tty back */
	(void) tcsetpgrp(FSHTTY, tpgrp);
#endif /* BSDJOBS */
    if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) ||
	!eq(dcwd->di_name, fp->p_cwd->di_name)) {
	if (jobflags & PSTOPPED) {
	    xputchar('\n');
	    if (adrof(STRlistjobs)) {
		Char   *jobcommand[3];

		jobcommand[0] = STRjobs;
		if (eq(varval(STRlistjobs), STRlong))
		    jobcommand[1] = STRml;
		else
		    jobcommand[1] = NULL;
		jobcommand[2] = NULL;

		dojobs(jobcommand, NULL);
		(void) pprint(pp, SHELLDIR);
	    }
	    else
		(void) pprint(pp, AREASON | SHELLDIR);
	}
	else
	    (void) pprint(pp, AREASON | SHELLDIR);
    }
    if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr &&
	(!gointr || !eq(gointr, STRminus))) {
	if ((jobflags & PSTOPPED) == 0)
	    pflush(pp);
	pintr1(0);
	/* NOTREACHED */
    }
    reason = 0;
    fp = pp;
    do {
	if (fp->p_reason)
	    reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ?
		fp->p_reason | META : fp->p_reason;
    } while ((fp = fp->p_friends) != pp);
    /*
     * Don't report on backquoted jobs, cause it will mess up 
     * their output.
     */
    if ((reason != 0) && (adrof(STRprintexitvalue)) && 
	(pp->p_flags & PBACKQ) == 0)
	xprintf(CGETS(17, 2, "Exit %d\n"), reason);
    set(STRstatus, putn(reason), VAR_READWRITE);
    if (reason && exiterr)
	exitstat();
    pflush(pp);
}

/*
 * dowait - wait for all processes to finish
 */

/*ARGSUSED*/
void
dowait(v, c)
    Char **v;
    struct command *c;
{
    register struct process *pp;
#ifdef BSDSIGS
    sigmask_t omask;
#endif /* BSDSIGS */

    USE(c);
    USE(v);
    pjobs++;
#ifdef BSDSIGS
    omask = sigblock(sigmask(SIGCHLD));
loop:
#else /* !BSDSIGS */
    if (setintr)
	(void) sigrelse(SIGINT);
loop:
    (void) sighold(SIGCHLD);
#endif /* !BSDSIGS */
    for (pp = proclist.p_next; pp; pp = pp->p_next)
	if (pp->p_procid &&	/* pp->p_procid == pp->p_jobid && */
	    pp->p_flags & PRUNNING) {
#ifdef BSDSIGS
	    (void) sigpause((sigmask_t) 0);
#else /* !BSDSIGS */
	    (void) sigpause(SIGCHLD);
#endif /* !BSDSIGS */
	    goto loop;
	}
#ifdef BSDSIGS
    (void) sigsetmask(omask);
#else /* !BSDSIGS */
    (void) sigrelse(SIGCHLD);
#endif /* !BSDSIGS */
    pjobs = 0;
}

/*
 * pflushall - flush all jobs from list (e.g. at fork())
 */
static void
pflushall()
{
    register struct process *pp;

    for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
	if (pp->p_procid)
	    pflush(pp);
}

/*
 * pflush - flag all process structures in the same job as the
 *	the argument process for deletion.  The actual free of the
 *	space is not done here since pflush is called at interrupt level.
 */
static void
pflush(pp)
    register struct process *pp;
{
    register struct process *np;
    register int idx;

    if (pp->p_procid == 0) {
	xprintf(CGETS(17, 3, "BUG: process flushed twice"));
	return;
    }
    while (pp->p_procid != pp->p_jobid)
	pp = pp->p_friends;
    pclrcurr(pp);
    if (pp == pcurrjob)
	pcurrjob = 0;
    idx = pp->p_index;
    np = pp;
    do {
	np->p_index = np->p_procid = 0;
	np->p_flags &= ~PNEEDNOTE;
    } while ((np = np->p_friends) != pp);
    if (idx == pmaxindex) {
	for (np = proclist.p_next, idx = 0; np; np = np->p_next)
	    if (np->p_index > idx)
		idx = np->p_index;
	pmaxindex = idx;
    }
}

/*
 * pclrcurr - make sure the given job is not the current or previous job;
 *	pp MUST be the job leader
 */
static void
pclrcurr(pp)

exercises/compile-tcsh/tcsh-6.10.00/sh.proc.c  view on Meta::CPAN

	    case SIGTTIN:
	    case SIGTTOU:
		if ((jobflags & PRUNNING) == 0) {
# ifdef SUSPENDED
		    xprintf(CGETS(17, 12, "%S: Already suspended\n"), cp);
# else /* !SUSPENDED */
		    xprintf(CGETS(17, 13, "%S: Already stopped\n"), cp);
# endif /* !SUSPENDED */
		    err1++;
		    goto cont;
		}
		break;
		/*
		 * suspend a process, kill -CONT %, then type jobs; the shell
		 * says it is suspended, but it is running; thanks jaap..
		 */
	    case SIGCONT:
		if (!pstart(pp, 0)) {
		    pp->p_procid = 0;
		    stderror(ERR_NAME|ERR_BADJOB, pp->p_command,
			     strerror(errno));
		}
		goto cont;
	    default:
		break;
	    }
#endif /* BSDJOBS */
	    if (killpg(pp->p_jobid, signum) < 0) {
		xprintf("%S: %s\n", cp, strerror(errno));
		err1++;
	    }
#ifdef BSDJOBS
	    if (signum == SIGTERM || signum == SIGHUP)
		(void) killpg(pp->p_jobid, SIGCONT);
#endif /* BSDJOBS */
	}
	else if (!(Isdigit(*cp) || *cp == '-'))
	    stderror(ERR_NAME | ERR_JOBARGS);
	else {
#ifndef WINNT_NATIVE
	    pid = atoi(short2str(cp));
#else
		pid = strtoul(short2str(cp),NULL,0);
#endif /* WINNT_NATIVE */
	    if (kill(pid, signum) < 0) {
		xprintf("%d: %s\n", pid, strerror(errno));
		err1++;
		goto cont;
	    }
#ifdef BSDJOBS
	    if (signum == SIGTERM || signum == SIGHUP)
		(void) kill(pid, SIGCONT);
#endif /* BSDJOBS */
	}
cont:
	v++;
    }
    if (gargv)
	blkfree(gargv), gargv = 0;
#ifdef BSDSIGS
    (void) sigsetmask(omask);
#else /* !BSDSIGS */
    (void) sigrelse(SIGCHLD);
    if (setintr)
	(void) sigrelse(SIGINT);
#endif /* !BSDSIGS */
    if (err1)
	stderror(ERR_SILENT);
}

/*
 * pstart - start the job in foreground/background
 */
int
pstart(pp, foregnd)
    register struct process *pp;
    int     foregnd;
{
    int rv = 0;
    register struct process *np;
#ifdef BSDSIGS
    sigmask_t omask;
#endif /* BSDSIGS */
    /* We don't use jobflags in this function right now (see below) */
    /* long    jobflags = 0; */

#ifdef BSDSIGS
    omask = sigblock(sigmask(SIGCHLD));
#else /* !BSDSIGS */
    (void) sighold(SIGCHLD);
#endif
    np = pp;
    do {
	/* We don't use jobflags in this function right now (see below) */
	/* jobflags |= np->p_flags; */
	if (np->p_flags & (PRUNNING | PSTOPPED)) {
	    np->p_flags |= PRUNNING;
	    np->p_flags &= ~PSTOPPED;
	    if (foregnd)
		np->p_flags |= PFOREGND;
	    else
		np->p_flags &= ~PFOREGND;
	}
    } while ((np = np->p_friends) != pp);
    if (!foregnd)
	pclrcurr(pp);
    (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND);
#ifdef BSDJOBS
    if (foregnd) {
	rv = tcsetpgrp(FSHTTY, pp->p_jobid);
    }
    /*
     * 1. child process of csh (shell script) receives SIGTTIN/SIGTTOU
     * 2. parent process (csh) receives SIGCHLD
     * 3. The "csh" signal handling function pchild() is invoked
     *    with a SIGCHLD signal.
     * 4. pchild() calls wait3(WNOHANG) which returns 0.
     *    The child process is NOT ready to be waited for at this time.
     *    pchild() returns without picking-up the correct status
     *    for the child process which generated the SIGCHILD.
     * 5. CONSEQUENCE : csh is UNaware that the process is stopped
     * 6. THIS LINE HAS BEEN COMMENTED OUT : if (jobflags&PSTOPPED)
     * 	  (beto@aixwiz.austin.ibm.com - aug/03/91)
     * 7. I removed the line completely and added extra checks for
     *    pstart, so that if a job gets attached to and dies inside
     *    a debugger it does not confuse the shell. [christos]
     * 8. on the nec sx-4 there seems to be a problem, which requires
     *    a syscall(151, getpid(), getpid()) in osinit. Don't ask me
     *    what this is doing. [schott@rzg.mpg.de]
     */

    if (rv != -1)
	rv = killpg(pp->p_jobid, SIGCONT);
#endif /* BSDJOBS */
#ifdef BSDSIGS
    (void) sigsetmask(omask);
#else /* !BSDSIGS */
    (void) sigrelse(SIGCHLD);
#endif /* !BSDSIGS */
    return rv != -1;
}

void
panystop(neednl)
    bool    neednl;
{
    register struct process *pp;

    chkstop = 2;
    for (pp = proclist.p_next; pp; pp = pp->p_next)
	if (pp->p_flags & PSTOPPED)
	    stderror(ERR_STOPPED, neednl ? "\n" : "");
}

struct process *
pfind(cp)
    Char   *cp;
{
    register struct process *pp, *np;

    if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) {
	if (pcurrent == NULL)
	    stderror(ERR_NAME | ERR_JOBCUR);
	return (pcurrent);
    }
    if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) {
	if (pprevious == NULL)
	    stderror(ERR_NAME | ERR_JOBPREV);
	return (pprevious);
    }
    if (Isdigit(cp[1])) {
	int     idx = atoi(short2str(cp + 1));

	for (pp = proclist.p_next; pp; pp = pp->p_next)
	    if (pp->p_index == idx && pp->p_procid == pp->p_jobid)
		return (pp);
	stderror(ERR_NAME | ERR_NOSUCHJOB);
    }
    np = NULL;
    for (pp = proclist.p_next; pp; pp = pp->p_next)
	if (pp->p_procid == pp->p_jobid) {
	    if (cp[1] == '?') {
		register Char *dp;

		for (dp = pp->p_command; *dp; dp++) {
		    if (*dp != cp[2])
			continue;
		    if (prefix(cp + 2, dp))
			goto match;
		}
	    }
	    else if (prefix(cp + 1, pp->p_command)) {
	match:
		if (np)
		    stderror(ERR_NAME | ERR_AMBIG);
		np = pp;

exercises/compile-tcsh/tcsh-6.10.00/sh.proc.c  view on Meta::CPAN

 * It is usually just the value of tpgrp.
 */

int
pfork(t, wanttty)
    struct command *t;		/* command we are forking for */
    int     wanttty;
{
    register int pid;
    bool    ignint = 0;
    int     pgrp;
#ifdef BSDSIGS
    sigmask_t omask = 0;
#endif /* BSDSIGS */
#ifdef SIGSYNCH
    sigvec_t osv;
    static sigvec_t nsv = {synch_handler, (sigset_t) ~0, 0};
#endif /* SIGSYNCH */

    /*
     * A child will be uninterruptible only under very special conditions.
     * Remember that the semantics of '&' is implemented by disconnecting the
     * process from the tty so signals do not need to ignored just for '&'.
     * Thus signals are set to default action for children unless: we have had
     * an "onintr -" (then specifically ignored) we are not playing with
     * signals (inherit action)
     */
    if (setintr)
	ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
	    || (gointr && eq(gointr, STRminus));

#ifdef COHERENT
    ignint |= gointr && eq(gointr, STRminus);
#endif /* COHERENT */

    /*
     * Check for maximum nesting of 16 processes to avoid Forking loops
     */
    if (child == 16)
	stderror(ERR_NESTING, 16);
#ifdef SIGSYNCH
    if (mysigvec(SIGSYNCH, &nsv, &osv))
	stderror(ERR_SYSTEM, "pfork: sigvec set", strerror(errno));
#endif /* SIGSYNCH */
    /*
     * Hold SIGCHLD until we have the process installed in our table.
     */
    if (wanttty < 0) {
#ifdef BSDSIGS
	omask = sigblock(sigmask(SIGCHLD));
#else /* !BSDSIGS */
	(void) sighold(SIGCHLD);
#endif /* !BSDSIGS */
    }
    while ((pid = fork()) == -1)
	if (setintr == 0)
	    (void) sleep(FORKSLEEP);
	else {
	    if (wanttty < 0)
#ifdef BSDSIGS
		(void) sigsetmask(omask);
#else /* !BSDSIGS */
		(void) sigrelse(SIGCHLD);
	    (void) sigrelse(SIGINT);
#endif /* !BSDSIGS */
	    stderror(ERR_NOPROC);
	}
    if (pid == 0) {
	settimes();
	pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
	pflushall();
	pcurrjob = NULL;
#if !defined(BSDTIMES) && !defined(_SEQUENT_) 
	timesdone = 0;
#endif /* !defined(BSDTIMES) && !defined(_SEQUENT_) */
	child++;
	if (setintr) {
	    setintr = 0;	/* until I think otherwise */
#ifndef BSDSIGS
	    if (wanttty < 0)
		(void) sigrelse(SIGCHLD);
#endif /* !BSDSIGS */
	    /*
	     * Children just get blown away on SIGINT, SIGQUIT unless "onintr
	     * -" seen.
	     */
	    (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
	    (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
#ifdef BSDJOBS
	    if (wanttty >= 0) {
		/* make stoppable */
		(void) signal(SIGTSTP, SIG_DFL);
		(void) signal(SIGTTIN, SIG_DFL);
		(void) signal(SIGTTOU, SIG_DFL);
	    }
#endif /* BSDJOBS */
	    (void) signal(SIGTERM, parterm);
	}
	else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) {
	    (void) signal(SIGINT, SIG_IGN);
	    (void) signal(SIGQUIT, SIG_IGN);
	}
#ifdef OREO
	sigignore(SIGIO);	/* ignore SIGIO in child too */
#endif /* OREO */

	pgetty(wanttty, pgrp);
	/*
	 * Nohup and nice apply only to NODE_COMMAND's but it would be nice
	 * (?!?) if you could say "nohup (foo;bar)" Then the parser would have
	 * to know about nice/nohup/time
	 */
	if (t->t_dflg & F_NOHUP)
	    (void) signal(SIGHUP, SIG_IGN);
	if (t->t_dflg & F_NICE) {
	    int nval = SIGN_EXTEND_CHAR(t->t_nice);
#ifdef BSDNICE
	    (void) setpriority(PRIO_PROCESS, 0, nval);
#else /* !BSDNICE */
	    (void) nice(nval);
#endif /* !BSDNICE */
	}
#ifdef F_VER
        if (t->t_dflg & F_VER) {
	    tsetenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53);
	    dohash(NULL, NULL);
	}
#endif /* F_VER */
#ifdef SIGSYNCH
	/* rfw 8/89 now parent can continue */
	if (kill(getppid(), SIGSYNCH))
	    stderror(ERR_SYSTEM, "pfork child: kill", strerror(errno));
#endif /* SIGSYNCH */

    }
    else {
#ifdef POSIXJOBS
        if (wanttty >= 0) {
	    /*
	     * `Walking' process group fix from Beto Appleton.
	     * (beto@aixwiz.austin.ibm.com)
	     * If setpgid fails at this point that means that
	     * our process leader has died. We flush the current
	     * job and become the process leader ourselves.
	     * The parent will figure that out later.
	     */
	    pgrp = pcurrjob ? pcurrjob->p_jobid : pid;
	    if (setpgid(pid, pgrp) == -1 && errno == EPERM) {
		pcurrjob = NULL;
		/* 
		 * We don't care if this causes an error here;
		 * then we are already in the right process group
		 */
		(void) setpgid(pid, pgrp = pid);
	    }
	}
#endif /* POSIXJOBS */
	palloc(pid, t);
#ifdef SIGSYNCH
	/*
	 * rfw 8/89 Wait for child to own terminal.  Solves half of ugly
	 * synchronization problem.  With this change, we know that the only
	 * reason setpgrp to a previous process in a pipeline can fail is that
	 * the previous process has already exited. Without this hack, he may
	 * either have exited or not yet started to run.  Two uglies become
	 * one.
	 */
	(void) sigpause(omask & ~SYNCHMASK);
	if (mysigvec(SIGSYNCH, &osv, NULL))
	    stderror(ERR_SYSTEM, "pfork parent: sigvec restore",
		     strerror(errno));
#endif /* SIGSYNCH */

	if (wanttty < 0) {
#ifdef BSDSIGS
	    (void) sigsetmask(omask);
#else /* !BSDSIGS */
	    (void) sigrelse(SIGCHLD);
#endif /* !BSDSIGS */
	}
    }
    return (pid);
}

static void
okpcntl()
{
    if (tpgrp == -1)
	stderror(ERR_JOBCONTROL);
    if (tpgrp == 0)
	stderror(ERR_JOBCTRLSUB);
}


static void
setttypgrp(pgrp)
    int pgrp;
{
    /*
     * If we are piping out a builtin, eg. 'echo | more' things can go
     * out of sequence, i.e. the more can run before the echo. This
     * can happen even if we have vfork, since the echo will be forked
     * with the regular fork. In this case, we need to set the tty
     * pgrp ourselves. If that happens, then the process will be still
     * alive. And the tty process group will already be set.
     * This should fix the famous sequent problem as a side effect:
     *    The controlling terminal is lost if all processes in the
     *    terminal process group are zombies. In this case tcgetpgrp()
     *    returns 0. If this happens we must set the terminal process
     *    group again.
     */
    if (tcgetpgrp(FSHTTY) != pgrp) {
#ifdef POSIXJOBS
        /*
	 * tcsetpgrp will set SIGTTOU to all the the processes in 
	 * the background according to POSIX... We ignore this here.
	 */
	signalfun_t old = sigset(SIGTTOU, SIG_IGN);
#endif
	(void) tcsetpgrp(FSHTTY, pgrp);
# ifdef POSIXJOBS
	(void) sigset(SIGTTOU, old);
# endif

    }
}


/*
 * if we don't have vfork(), things can still go in the wrong order
 * resulting in the famous 'Stopped (tty output)'. But some systems
 * don't permit the setpgid() call, (these are more recent secure
 * systems such as ibm's aix), when they do. Then we'd rather print 
 * an error message than hang the shell!
 * I am open to suggestions how to fix that.
 */

exercises/compile-tcsh/tcsh-6.10.00/sh.proc.c  view on Meta::CPAN

pgetty(wanttty, pgrp)
    int     wanttty, pgrp;
{
#ifdef BSDJOBS
# if defined(BSDSIGS) && defined(POSIXJOBS)
    sigmask_t omask = 0;
# endif /* BSDSIGS && POSIXJOBS */

# ifdef JOBDEBUG
    xprintf("wanttty %d pid %d opgrp%d pgrp %d tpgrp %d\n", 
	    wanttty, getpid(), pgrp, mygetpgrp(), tcgetpgrp(FSHTTY));
# endif /* JOBDEBUG */
# ifdef POSIXJOBS
    /*
     * christos: I am blocking the tty signals till I've set things
     * correctly....
     */
    if (wanttty > 0)
#  ifdef BSDSIGS
	omask = sigblock(sigmask(SIGTSTP)|sigmask(SIGTTIN));
#  else /* !BSDSIGS */
    {
	(void) sighold(SIGTSTP);
	(void) sighold(SIGTTIN);
    }
#  endif /* !BSDSIGS */
# endif /* POSIXJOBS */

# ifndef POSIXJOBS
    if (wanttty > 0)
	setttypgrp(pgrp);
# endif /* !POSIXJOBS */

    /*
     * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
     * Don't check for tpgrp >= 0 so even non-interactive shells give
     * background jobs process groups Same for the comparison in the other part
     * of the #ifdef
     */
    if (wanttty >= 0) {
	if (setpgid(0, pgrp) == -1) {
# ifdef POSIXJOBS
	    /* Walking process group fix; see above */
	    if (setpgid(0, pgrp = getpid()) == -1) {
# endif /* POSIXJOBS */
		stderror(ERR_SYSTEM, "setpgid child:\n", strerror(errno));
		xexit(0);
# ifdef POSIXJOBS
	    }
	    wanttty = pgrp;  /* Now we really want the tty, since we became the
			      * the process group leader
			      */
# endif /* POSIXJOBS */
	}
    }

# ifdef POSIXJOBS
    if (wanttty > 0)
	setttypgrp(pgrp);
#  ifdef BSDSIGS
    (void) sigsetmask(omask);
#  else /* BSDSIGS */
    (void) sigrelse(SIGTSTP);
    (void) sigrelse(SIGTTIN);
#  endif /* !BSDSIGS */
# endif /* POSIXJOBS */

# ifdef JOBDEBUG
    xprintf("wanttty %d pid %d pgrp %d tpgrp %d\n", 
	    wanttty, getpid(), mygetpgrp(), tcgetpgrp(FSHTTY));
# endif /* JOBDEBUG */

    if (tpgrp > 0)
	tpgrp = 0;		/* gave tty away */
#endif /* BSDJOBS */
}



( run in 2.053 seconds using v1.01-cache-2.11-cpan-302cb4679cc )