Пример #1
0
/* PR_CACHETASK -- Cache the process containing the named logical task.
 * If the process is already connected merely returns its pid, else connect
 * the process and return its pid.
 */
int 
pr_cachetask (
    char *ltname		/* logical task name	*/
)
{
	register int  pid;
	struct	ltask *ltp;
	FILE	*fdummy;

	ltp = ltasksrch ("", ltname);
	if (ltp->lt_flags & (LT_SCRIPT|LT_BUILTIN))
	    return (ERR);
	if ((pid = pr_pnametopid(findexe(ltp->lt_pkp,ltp->lt_pname))) == NULL) {
	    pid = pr_connect (findexe(ltp->lt_pkp,ltp->lt_pname), "\n", &fdummy,
		&fdummy, stdin, stdout, stderr, 0,0,0, 0);
	    pr_disconnect (pid);
	}

	return (pid);
}
Пример #2
0
/* PR_SETCACHE -- Set the size of the process cache.  This is automatically
 * called whenever the value of the parameter cl.szprcache is set.  Changing
 * the cache size on an active cache causes the cache to be flushed and all
 * locked processes to be reconnected.
 */
void 
pr_setcache (int new_szprcache)
{
	struct	process *pr;
	char	pname[MAXSUBPROC][SZ_PATHNAME+1];
	int	nprocs=0, pid, i;
	FILE	*fdummy;

	if (pr_head == NULL)
	    pr_initcache();
	else {
	    /* Get the names of any processes currently locked into the cache,
	     * then dump the cache.
	     */
	    for (pr=pr_head;  pr != NULL;  pr=pr->pr_dn)
		if (pr->pr_pid != NULL && (pr->pr_flags & P_LOCKED))
		    strcpy (pname[nprocs++], pr->pr_name);
	    pr_dumpcache (0, 1);
	}

	/* Set the new value of sz_prcache. */
	sz_prcache = new_szprcache;
	if (sz_prcache < 2)
	    sz_prcache = 2;
	else if (sz_prcache > MAXSUBPROC)
	    sz_prcache = MAXSUBPROC;

	/* Relink the empty cache for sz_prcache cache slots. */
	pr_initcache();

	/* Attempt to recache the formerly locked processes.  There must be
	 * at least one empty slot left for new subprocesses.
	 */
	if (nprocs+1 > sz_prcache)
	    nprocs = sz_prcache-1;

	for (i=0;  i < nprocs;  i++) {
	    pid = pr_connect (findexe(NULL,pname[i]), "\n", &fdummy, &fdummy,
		stdin, stdout, stderr, 0,0,0, 0);
	    pr_disconnect (pid);
	    pr_lock (pid);
	}
}
Пример #3
0
/*
 *  relfile(prog, mod) -- find related file.
 *
 *  Given that prog is the argv[0] by which this program was executed,
 *  and assuming that it was set by the shell or other equally correct
 *  invoker, relfile finds the location of a related file and returns
 *  it in an allocated string.  It takes the location of prog, appends
 *  mod, and canonizes the result; thus if argv[0] is icont or its path,
 *  relfile(argv[0],"/../iconx") finds the location of iconx.
 */
char *relfile(char *prog, char *mod) {
   static char baseloc[MaxPath];
   char buf[MaxPath];

   if (baseloc[0] == 0) {		/* if argv[0] not already found */

      if (findexe(prog, baseloc, sizeof(baseloc)) == NULL) {
         fprintf(stderr, "cannot find location of %s\n", prog);
         exit(EXIT_FAILURE);
         }
      if (followsym(baseloc, buf, sizeof(buf)) != NULL)
         strcpy(baseloc, buf);
   }

   strcpy(buf, baseloc);		/* start with base location */
   strcat(buf, mod);			/* append adjustment */
   canonize(buf);			/* canonize result */
   if (mod[strlen(mod)-1] == '/')	/* if trailing slash wanted */
      strcat(buf, "/");			/* append to result */
   return salloc(buf);			/* return allocated string */
   }
Пример #4
0
Файл: bkg.c Проект: geechee/iraf
/* 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);
	}
}
Пример #5
0
/* EXECNEWTASK -- Called from the EXEC instruction after all param and stdio
 * processing for the new task is complete.  Here we actually run the new task,
 * either directly in the case of a builtin function, or as a new case for
 * main()'s loop.  Do not set newtask to NULL so that run() can tell what it
 * exec'd.
 */
void
execnewtask (void)
{
	/* VMS C V2.1 cannot handle this (see below).
	 * register struct pfile *pfp;
	 */
	static	struct pfile *pfp;

	struct	param *pp;
	FILE	*fopen();

	if (newtask == NULL)
	    /* if this ever happens, i don't want to know about it. */
	    return;
	
	currentask->t_pc = pc;		/* instruction after EXEC	*/

	if (cldebug)
	    eprintf ("execnewtask: pc = %d\n", pc);

	if (newtask->t_flags & T_BUILTIN) {
	    /* set yyin in case a builtin reads someday; none do now.
	     * unlink newtask's fake param file and reset top of dictionary
	     *   to what it was before the fake param file was added; it is
	     *   still there, however, for the builtin to use. this is done
	     *   since some builtins (eg task) want to add things that are
	     *   to stay on the dictionary and the tools all start at topd.
	     * the return is back to run(); it will continue since it will
	     *   see that newtask was just a builtin.
	     * note that we do not reset pf_n, as with other fake pfiles,
	     *   as this is the way builtins get their number of arguments
	     *   (it's faster than building them a $nargs).
	     */
	    yyin = newtask->t_in = currentask->t_in;	/* inherit pipe */
	    newtask->t_out = currentask->t_out;
	    newtask->t_modep = currentask->t_modep;	/* inherit mode */

	    /* VMS C 2.1 Optimizer cannot handle this.
	     * parhead = dereference (reference (pfile, parhead)->pf_npf);
	     */
	    pfp = reference (pfile, parhead);
	    parhead = dereference (pfp->pf_npf);

	    topd = currentask->t_topd;
	    currentask = newtask;
	    newtask->t_flags |= T_RUNNING;

	    if (cldebug)
		eprintf ("execnewtask: calling new task@%x\n", newtask);
	    if (cltrace)
		eprintf ("\t----- exec %s %s -----\n",
		    (newtask->t_flags & T_FOREIGN) ? "foreign" : "builtin",
		    newtask->t_ltp->lt_lname);

	    (*newtask->t_ltp->lt_f)();
	    oneof();		/* proceed as though this task saw eof	  */
	    return;
	}

	pfp = newtask->t_pfp;

	/* If the new task is a cl, we are not running in background and
	 * its t_in is stdin, it is interactive.  Note that when a package
	 * is loaded by a script task rather than interactively by the user,
	 * the t_in of the cl() in the package script task will be reading
	 * from the calling script task rather than from the original stdin
	 * (the user terminal), hence is not interactive.  If this task is
	 * flagged interactive, taskunwind() may elect to restart it on an
	 * error so save present state for restor().
	 */
	if (newtask->t_flags & T_CL) {
	    if (cldebug)
		eprintf ("execnewtask: new task is the CL\n");
	    if (cltrace)
		eprintf ("\t----- exec cl -----\n");

	    /* Call set_clio to set the command input and output streams
	     * t_in and t_out for a cl() or package_name() command.
	     */
	    set_clio (newtask);

	    /* This code is a temporary patch to allow packages to be 
	     * loaded from within scripts regardless of whether there 
	     * are enclosing brackets.  If a CL statement is executed
	     * within a script which is itself called within another
	     * script, then we will do an implicit keep before the CL.
	     */
	    if (topcs + 2*TASKSIZ <= STACKSIZ)
		if ((strcmp (newtask->t_ltp->lt_lname, "cl") == 0) ||
 		    (strcmp (newtask->t_ltp->lt_lname, "clbye") == 0))
		    if ((currentask->t_flags &  T_SCRIPT) &&
		        (prevtask->t_flags & T_SCRIPT))
			keep(prevtask);

	    /* If newtask is cleof(), close the input stream of the current
	     * task (the task whose input contained the cleof), and reopen
	     * as the null file.
	     */
	    if (newtask->t_flags & T_CLEOF) {
		if (currentask->t_in != stdin)
		    fclose (currentask->t_in);
		if (currentask != firstask)
		    currentask->t_in = fopen ("dev$null", "r");
	    }

	    if (!(firstask->t_flags & T_BATCH) &&
		 (newtask->t_in == stdin) && (newtask->t_out == stdout)) {
		newtask->t_flags |= T_INTERACTIVE;
		newtask->t_topd = topd;
		newtask->t_topos = topos;
		newtask->t_topcs = topcs;
		newtask->t_curpack = curpack;
	    }
	}

	/* Standardize the pfile.
	 * Set (or create if necessary) `$nargs', number of command line args,
	 *   based on pf_n which is set for each command line argument by
	 *   posargset, et al.
	 * If this ltask had no paramfile and we built one up from the
	 *   command line, then we need to add a `mode' param.  If it did have
	 *   a paramfile, then pfileload has already added it for us.
	 *   Point t_modep to the mode param for newtask.
	 */
	pp = paramfind (pfp, "$nargs", 0, YES);
	if (pp == NULL || (XINT)pp == ERR) {
	    char nabuf[FAKEPARAMLEN];
	    sprintf (nabuf, "$nargs,i,h,%d\n", pfp->pf_n);
	    pp = addparam (pfp, nabuf, NULL);
	    pp->p_mode |= M_FAKE;		/* never flush out $nargs */
	} else
	    pp->p_val.v_i = pfp->pf_n;

	if (pfp->pf_flags & PF_FAKE) {
	    newtask->t_modep = addparam (pfp, "mode,s,h,q\n", NULL);
	    /* pf_n will be used by paramsrch() to count positional arg
	     * matches; see it and param.h.
	     */
	    pfp->pf_n = 0;
	} else {
	    newtask->t_modep = paramfind (pfp, "mode", 0, YES);
	}

	if (newtask->t_modep == NULL)
	    cl_error (E_IERR, "no mode param for task `%s'",
		newtask->t_ltp->lt_lname);

	/* If task is being run in menu mode, call up eparam so that the user
	 * can edit/inspect the parameters.  If eparam is exited with ctrl/c
	 * do not run the task or update the pfile.  The parameter editor
	 * will make a copy of the task's pfile(s), edit it, and if necessary
	 * update the incore version created earlier by callnewtask().
	 */
	if ((taskmode(newtask) & M_MENU) || (newtask->t_flags & T_PSET)) {
	    if (epset (newtask->t_ltp->lt_lname) == ERR) {
		if (newtask->t_flags & T_PSET)
		    cl_error (E_UERR, "parameter file not updated");
		else
		    cl_error (E_UERR, "menu mode task execution aborted");
	    }
	}

	/* Set up bascode so new task has a good place to start building
	 * code.  See how the pc is set up before each call to the parser in
	 * main() loop.
	 */
	newtask->t_bascode = topos + 1;

	/* Set up io paths.  If the new task is cl(), it's command input
	 * and output streams are connected to those of the task which
	 * called currentask.  If the currentask is the firstask, there
	 * was no caller (no prevtask), so we must watch out for that.
	 * In the case of a script, commands are read from the script.
	 * In the case of a process, commands are read from the process.
	 */
	if (newtask->t_flags & T_PSET) {
	    newtask->t_in = fopen ("dev$null", "r");
	    newtask->t_out = newtask->t_stdout;

	} else if (newtask->t_flags & T_SCRIPT) {
	    if (cltrace)
		eprintf ("\t----- exec script %s (%s) -----\n",
		    newtask->t_ltp->lt_lname, newtask->t_ltp->lt_pname);

	    newtask->t_in = fopen (newtask->t_ltp->lt_pname, "r");
	    if (newtask->t_in == NULL)
		cl_error (E_UERR|E_P, "can not open script file `%s'",
		    newtask->t_ltp->lt_pname);
	    newtask->t_out = newtask->t_stdout;

	} else if (newtask->t_flags & T_CL) {
	    /* The command streams t_in and t_out have already been
	     * set up above by set_clio() in the test for T_INTERACTIVE.
	     */
	    /* Do nothing */

	} else {
	    char    startup_msg[SZ_STARTUPMSG+1];
	    int     timeit;

	    /* Connect to an executable process.
	     */
	    mk_startupmsg (newtask, startup_msg, SZ_STARTUPMSG);
	    timeit = (newtask->t_flags & T_TIMEIT) != 0;
	    if (cltrace)
		eprintf ("\t----- exec external task %s -----\n",
		    newtask->t_ltp->lt_lname);
	    newtask->t_pid = pr_connect (
		findexe (newtask->t_ltp->lt_pkp, newtask->t_ltp->lt_pname),
		startup_msg,
		&newtask->t_in, &newtask->t_out,
		newtask->t_stdin, newtask->t_stdout, newtask->t_stderr,
		newtask->t_stdgraph, newtask->t_stdimage, newtask->t_stdplot,
		timeit);
	}

	yyin = newtask->t_in;	/* set the input for the parser	*/

	/* Tell parser what to expect.
	 */
	parse_state = PARSE_FREE;
	if (newtask->t_flags & T_SCRIPT) {
	    proc_script = (newtask->t_flags & T_PSET) ? NO : procscript(yyin);

	    if (proc_script) {
		parse_state = PARSE_BODY;
		/* Skip to the BEGIN statement */
		newtask->t_scriptln = skip_to (yyin, "begin");
		if (newtask->t_scriptln == ERR)
		    cl_error (E_UERR, "No BEGIN statement in procedure script");

		/* Reset pointer here.
		 */
		proc_script = NO;
	    }
	}

	/* Log a start message for script and executable tasks.
	 */
	if (keeplog() && log_trace())
	    if (newtask->t_flags & T_SCRIPT || newtask->t_pid != -1) {
	    	char  logmsg[SZ_LINE];
	    	sprintf (logmsg, "Start (%s)", newtask->t_ltp->lt_pname);
	    	putlog (newtask, logmsg);
	    }

	newtask->t_flags |= T_RUNNING;
	currentask = newtask;	/* continue as new the new task; at last. */

	if (cldebug)
	    eprintf ("Returning from execnewtask.yyin, ct_in, nt_in:%d %d %d\n",
		yyin, currentask->t_in, newtask->t_in);
}