Example #1
0
/* Called by c_read() when eof is read - close fd if it is the co-process fd */
void
coproc_read_close(int fd)
{
	if (coproc.read >= 0 && fd == coproc.read) {
		coproc_readw_close(fd);
		close(coproc.read);
		coproc.read = -1;
	}
}
Example #2
0
/*
 * Called only when a process in j has exited/stopped (ie, called only
 * from j_sigchld()).  If no processes are running, the job status
 * and state are updated, asynchronous job notification is done and,
 * if unneeded, the job is removed.
 *
 * If jobs are compiled in then this routine expects sigchld to be blocked.
 */
static void
check_job(Job *j)
{
	int	jstate;
	Proc	*p;

	/* XXX debugging (nasty - interrupt routine using shl_out) */
	if (!(j->flags & JF_STARTED)) {
		internal_errorf(0, "check_job: job started (flags 0x%x)",
		    j->flags);
		return;
	}

	jstate = PRUNNING;
	for (p=j->proc_list; p != (Proc *) 0; p = p->next) {
		if (p->state == PRUNNING)
			return;	/* some processes still running */
		if (p->state > jstate)
			jstate = p->state;
	}
	j->state = jstate;

	switch (j->last_proc->state) {
	case PEXITED:
		j->status = WEXITSTATUS(j->last_proc->status);
		break;
	case PSIGNALLED:
		j->status = 128 + WTERMSIG(j->last_proc->status);
		break;
	default:
		j->status = 0;
		break;
	}

	/* Note when co-process dies: can't be done in j_wait() nor
	 * remove_job() since neither may be called for non-interactive
	 * shells.
	 */
	if (j->state == PEXITED || j->state == PSIGNALLED) {
		/* No need to keep co-process input any more
		 * (at least, this is what ksh93d thinks)
		 */
		if (coproc.job == j) {
			coproc.job = (void *) 0;
			/* XXX would be nice to get the closes out of here
			 * so they aren't done in the signal handler.
			 * Would mean a check in coproc_getfd() to
			 * do "if job == 0 && write >= 0, close write".
			 */
			coproc_write_close(coproc.write);
		}
		/* Do we need to keep the output? */
		if (j->coproc_id && j->coproc_id == coproc.id &&
		    --coproc.njobs == 0)
			coproc_readw_close(coproc.read);
	}

	j->flags |= JF_CHANGED;
#ifdef JOBS
	if (Flag(FMONITOR) && !(j->flags & JF_XXCOM)) {
		/* Only put stopped jobs at the front to avoid confusing
		 * the user (don't want finished jobs effecting %+ or %-)
		 */
		if (j->state == PSTOPPED)
			put_job(j, PJ_ON_FRONT);
		if (Flag(FNOTIFY) &&
		    (j->flags & (JF_WAITING|JF_W_ASYNCNOTIFY)) != JF_WAITING) {
			/* Look for the real file descriptor 2 */
			{
				struct env *ep;
				int fd = 2;

				for (ep = e; ep; ep = ep->oenv)
					if (ep->savefd && ep->savefd[2])
						fd = ep->savefd[2];
				shf_reopen(fd, SHF_WR, shl_j);
			}
			/* Can't call j_notify() as it removes jobs.  The job
			 * must stay in the job list as j_waitj() may be
			 * running with this job.
			 */
			j_print(j, JP_MEDIUM, shl_j);
			shf_flush(shl_j);
			if (!(j->flags & JF_WAITING) && j->state != PSTOPPED)
				remove_job(j, "notify");
		}
	}
#endif /* JOBS */
	if (!Flag(FMONITOR) && !(j->flags & (JF_WAITING|JF_FG)) &&
	    j->state != PSTOPPED) {
		if (j == async_job || (j->flags & JF_KNOWN)) {
			j->flags |= JF_ZOMBIE;
			j->job = -1;
			nzombie++;
		} else
			remove_job(j, "checkjob");
	}
}
Example #3
0
File: jobs.c Project: adtools/abcsh
/*
 * Called only when a process in j has exited/stopped (ie, called only
 * from j_sigchld()).  If no processes are running, the job status
 * and state are updated, asynchronous job notification is done and,
 * if unneeded, the job is removed.
 *
 * If jobs are compiled in then this routine expects sigchld to be blocked.
 */
static void
check_job(Job *j)
{
        int     jstate;
        Proc    *p;

        /* XXX debugging (nasty - interrupt routine using shl_out) */
        if (!(j->flags & JF_STARTED)) {
                internal_errorf(0, "check_job: job started (flags 0x%x)",
                        j->flags);
                return;
        }

        jstate = PRUNNING;
        for (p=j->proc_list; p != (Proc *) 0; p = p->next) {
                if (p->state == PRUNNING)
                        return; /* some processes still running */
                if (p->state > jstate)
                        jstate = p->state;
        }
        j->state = jstate;

        switch (j->last_proc->state) {
        case PEXITED:
                j->status = WEXITSTATUS(j->last_proc->status);
                break;
        case PSIGNALLED:
                j->status = 128 + WTERMSIG(j->last_proc->status);
                break;
        default:
                j->status = 0;
                break;
        }

        /* Note when co-process dies: can't be done in j_wait() nor
         * remove_job() since neither may be called for non-interactive
         * shells.
         */
        if (j->state == PEXITED || j->state == PSIGNALLED) {
                /* No need to keep co-process input any more
                 * (at leasst, this is what ksh93d thinks)
                 */
                if (coproc.job == j) {
                        coproc.job = (void *) 0;
                        /* XXX would be nice to get the closes out of here
                         * so they aren't done in the signal handler.
                         * Would mean a check in coproc_getfd() to
                         * do "if job == 0 && write >= 0, close write".
                         */
                        coproc_write_close(coproc.write);
                }
                /* Do we need to keep the output? */
                if (j->coproc_id && j->coproc_id == coproc.id &&
                        --coproc.njobs == 0)
                                coproc_readw_close(coproc.read);
        }

        j->flags |= JF_CHANGED;
        if (!(j->flags & (JF_WAITING|JF_FG))
            && j->state != PSTOPPED)
        {
                if (j == async_job || (j->flags & JF_KNOWN)) {
                        j->flags |= JF_ZOMBIE;
                        j->job = -1;
                        nzombie++;
                } else
                        remove_job(j, "checkjob");
        }
}