Exemple #1
0
/* BKG_JOBSTATUS -- Print the status of one or more background jobs.
 * format jobno, elapsed clock time, status, user command, e.g.:
 *
 *		[1]   1:34  Running	command_1
 *		[2]  14:09  Stopped	command_2
 *		[3]   1:34 +Done 	command_3
 *		[4]   1:34  Exit 23	command_4
 *
 * A job will remain in the job table until another job is submitted which uses
 * the same slot.
 */
void 
bkg_jobstatus (
    FILE *fp,			/* output file		*/
    int job			/* job(s)		*/
)
{
	register struct _bkgjob *bk;
	register int	j, n, ch;
	register char	*ip;
	long	seconds;
	char	*outstr = NULL;

	bkg_update (1);
	for (bk=jobtable, j=1;  j <= NBKG;  j++, bk++)
	    if ((job == 0 && bk->b_jobno) || job == j) {
		/* Print jobno.  */
		fprintf (fp, "    [%d] ", j);

		/* If the clock is still running b_clock contains the start
		 * time.  If the job terminated it contains the elapsed time
		 * at job termination.
		 */
		if (busy(j))
		    seconds = c_clktime (bk->b_clock);
		else
		    seconds = bk->b_clock;
		fprintf (fp, "%6.0m ", (float)seconds / 60.0);
		fputc ((j == lastjobno) ? '+' : ' ', fp);
		    
		/* Print job status.
		 */
		if (busy(j)) {
		    if (bk->b_flags & J_SERVICE)
			outstr = "Stopped";
		    else
			outstr = "Running";
		} else if (bk->b_flags & J_KILLED) {
		    outstr = "Killed";
		} else if (bk->b_exitcode == OK) {
		    outstr = "Done";
		} else
		    sprintf (outstr, "Exit %d", bk->b_exitcode);
		fprintf (fp, "%-10s", outstr);

		/* Finally, print user command followed by newline.
		 */
		n = c_envgeti ("ttyncols") - (8 + 8 + 10) - 1;
		ip = bk->b_cmd;
		while (--n >= 0 && (ch = *ip++) != EOS)
		    if (ch == '\n' || ch == '\t')
			fputc (' ', fp);
		    else
			fputc (ch, fp);
		fputc ('\n', fp);
	    }
}
Exemple #2
0
/* BKG_WAIT -- Wait for a background job to terminate.  If job=0, wait for
 * all bkg jobs to terminate.
 */
void 
bkg_wait (register int job)
{
	register int	j;
	int	active_jobs;

	if (job < 0 || job > NBKG)
	    return;

	do {
	    bkg_update (1);
	    if (job && !busy(job))
		return;
	    else {
		for (active_jobs=0, j=1;  j <= NBKG;  j++)
		    if (busy (j)) {
			active_jobs++;
			c_tsleep (WAIT_PERIOD);
			break;
		    }
	    }
	} while (active_jobs);
}
Exemple #3
0
/* BKG_KILL -- Kill a background job.  If job=0, kill all background jobs.
 * If the job cannot be killed assume it is because it died unexpectedly.
 */
void 
bkg_kill (int job)
{
	register struct _bkgjob *bk;
	register int	j;

	bkg_update (1);
	if (job < 0 || job > NBKG)
	    eprintf ("[%d] invalid job number\n", job);
	else {
	    for (bk=jobtable, j=1;  j <= NBKG;  j++, bk++) {
		if ((job == 0 && busy(j)) || job == j) {
		    if (!busy(j))
			eprintf ("[%d] not in use\n", j);
		    else if (c_prkill (bk->b_jobno) == ERR)
			bkg_close (j, 2);
		    else {
			bk->b_flags |= J_KILLED;
			bkg_close (j, 2);
		    }
		}
	    }
	}
}
Exemple #4
0
/* BKG_JOBACTIVE -- Determine if a background job is active, i.e., if the
 * job is still running.  It does not matter if the job is waiting for
 * service.
 */
int 
bkg_jobactive (int job)
{
	bkg_update (1);
	return (busy (job));
}
Exemple #5
0
/* BKG_SPAWN -- Spawn a new background job.  Called by main() when we have
 * seen an '&'.
 */
void 
bkg_spawn (
    char *cmd		/* command entered by user to spawn job	*/
)
{
	register struct _bkgjob *bk;
	register int	jobno, stat;
	char	clprocess[SZ_PATHNAME];
	char	*wbkgfile();
	char	*bkgfile;

	/* Find first unused slot in a circular search.
	 */
	bkg_update (1);
	jobno = (lastjobno == NBKG) ? 1 : lastjobno + 1;
	while (jobno != lastjobno) {
	    if (!busy (jobno))
		break;
	    if (jobno++ >= NBKG)
		jobno = 1;
	}
	if (jobno == lastjobno)
	    cl_error (E_UERR, "no more background job slots");

	/* Write bkgfile.  Delete any dreg bkg communication files.
	 */
	bkg_delfiles (jobno);
	bkgfile = wbkgfile (jobno, cmd, NULL);

	/* Spawn bkg job.
	 */
	sprintf (clprocess, "%s%s", CLDIR, CLPROCESS);
	intr_disable();
	jobtable[jobno-1].b_jobno = stat =
	    c_propdpr (findexe (firstask->t_curpack, clprocess),
		bkgfile, bkgmsg);

	if (stat == NULL) {
	    c_delete (bkgfile);
	    intr_enable();
	    cl_error (E_IERR, "cannot spawn background CL");
	} else {
	    bk = &jobtable[jobno-1];
	    bk->b_flags = J_RUNNING;
	    bk->b_clock = c_clktime (0L);
            bk->b_verbose = 2;
	    strncpy (bk->b_cmd, cmd, SZ_CMD);
	    *(bk->b_cmd+SZ_CMD) = EOS;
	    intr_enable();
	}

	eprintf ("[%d]\n", lastjobno = jobno);

	/* Make a logfile entry, saying we started the background job.
	 */
	if (keeplog() && log_background()) {
	    char  buf[SZ_LINE];
	    sprintf (buf, "Start [%d]", jobno);
	    putlog (0, buf);
	}
}
Exemple #6
0
/* EXECUTE -- Each loop corresponds to an exec in the interpreted code.
 * This occurs when a script task or process is ready to run.  In background
 * mode, we skip the preliminaries and jump right in and interpret the
 * compiled code.
 */
static void
execute (int mode)
{
	int	parsestat;
	XINT	old_parhead;
	char	*curcmd();

	alldone = 0;
	gologout = 0;
	if (mode == BACKGROUND) {
	    if (setjmp (jumpcom))
		onerr();
	    goto bkg;
	}

	/* Called when control stack contains only the firsttask.  ONEOF sets
	 * alldone true when eof/bye is seen and currentask=firstask,
	 * terminating the loop and returning to main.
	 */
	do {
	    /* Bkg_update() checks for blocked or finished bkg jobs and prints
	     * a message if it finds one.  This involves one or more access()
	     * calls so don't call it more than every 5 seconds.  The errenv
	     * jump vector is used by cl_error() for error restart.  The JUMPCOM
	     * vector is used to intercept system errors which would otherwise
	     * restart the CL.
	     */
	    if (currentask->t_flags & T_INTERACTIVE) {
		static	long last_clktime;

		if (c_clktime (last_clktime) > BKG_QUANTUM) {
		    last_clktime = c_clktime (0L);
		    bkg_update (1);
		}
		validerrenv = 1;
		setjmp (errenv);
		ninterrupts = 0;
		if (setjmp (jumpcom))
		    onerr();
	    } else if (!(currentask->t_flags & T_SCRIPT))
		setjmp (intenv);
    
	    pc = currentask->t_bascode;
	    currentask->t_topd = topd;
	    currentask->t_topcs = topcs;
	    recursion = 0;
	    errlev = 0;
	    c_erract (OK);
	    yeof = 0;

	    /* In the new CL the parser needs to know more about parameters
	     * than before.  Hence param files may be read in during parsing.
	     * Since we discard the dictionary after parsing we must unlink
	     * these param files, and re-read them when the
	     * program is run.  This is inefficient but appears to work.
	     */
	    old_parhead = parhead;

	    if (gologout)
		yeof++;
	    else {
		yy_startblock (LOG);		/* start new history blk   */
		parsestat = yyparse();		/* parse command block	   */
		topd = currentask->t_topd;	/* discard addconst()'s    */
		topcs = currentask->t_topcs;	/* discard compiler temps  */
		parhead = old_parhead;		/* forget param files.	   */
		if (parsestat != 0)
		    cl_error (E_IERR, "parser gagged");
	    }

	    if (dobkg) {
		bkg_spawn (curcmd());
	    } else {
bkg:
		if (yeof)
		    oneof();			/* restores previous task  */
		else {
		    /* set stack above pc, point pc back to code */
		    topos = basos = pc - 1;
		    pc = currentask->t_bascode;
		}

		if (!alldone)
		    run();			/* run code starting at pc */
	    }
	} until (alldone);
}