Exemplo n.º 1
0
Arquivo: exec.c Projeto: geechee/iraf
/* CALLNEWTASK -- Called from CALL instruction to push and setup a new task
 *   structure.  If find a known ltask with given name create a new task on
 *   control stack, set up newtask and defaults for the pseudofiles.
 *   Pseudofiles may be effected by other instructions before it gets to exec.
 * Make sure we have a pfile list; either try to read it if task is 
 *   supposed to have a real one or manufacture the beginnings of one if it
 *   isn't and set PF_FAKE.  New task runs with a copy of the pfile if it
 *   wasn't fake.  Guard against making more than one copy.  Also, don't dup
 *   the cl's params to maintain the meaning of "firstask".  Things like mode,
 *   logfile and abbreviations should be global and permanent.
 * Special case for package names essentially runs a cl but with a new curpack,
 *   the only real semantic intent of "running" a package.
 *   This lets a package name given as a command appear to change the current
 *   package and yet remain interactive.  Since it really is a new task, state
 *   saving and restoring on error will work right and we also achieve an
 *   ability to have multiple package defn's in a script ltask.
 *   Any parameter references will refer to the cl's also.
 */
void
callnewtask (
  char	*name
)
{
	/* x1 and x2 are just place holders to call breakout().
	 */
	char	*x1, *pk, *t, *x2;	
	struct	ltask *ltp;
	int	flags, ltflags;

	if (cldebug)
	    eprintf ("callnewtask: name=%s, currentask=%x\n", name, currentask);

	/* Save current dictionary and stack pointers. they get restored when
	 * the new task dies normally and the current task is to continue.
	 * save pc when get to the EXEC instruction so it continues from there.
	 */
	currentask->t_topos = topos;	/* save these two just in case 	*/
	currentask->t_basos = basos;	/* something is left on the stk	*/
	currentask->t_topcs = topcs;	/* save before adding newtask	*/
	currentask->t_topd  = topd;	/* save before adding pfile	*/
	currentask->t_curpack = curpack;/* save in case changing to a new one*/
	c_envmark (&currentask->t_envp);/* save env stack pointer	*/
	currentask->t_pno = 0;		/* set only if task defines pkg	*/

	newtask = pushtask();
	flags = 0;

	/* Search for the command to run.  A leading '$' signifies that
	 * execution is to be time but is not part of the name.  Set ltp
	 * and newtask->t_pfp depending on whether we are running a task or
	 * a package.
	 */
	if (*name == '$') {
	    flags |= T_TIMEIT;
	    name++;
	}

	breakout (name, &x1, &pk, &t, &x2);
	ltp = cmdsrch (pk, t);

	if (ltp->lt_flags & LT_CL) {
	    /* Change curpack if LT_PACCL. (cmdsrch() set lt_pkp).  Just
	     * changing packages; use cl's ltask and pfile.  Push a new cl()
	     * on the control stack, with the T_PKGCL and T_CL flags set.
	     */
	    if (ltp->lt_flags & LT_PACCL) {
		flags |= T_PKGCL;
		curpack = ltp->lt_pkp;
	    } else if (ltp->lt_flags & LT_CLEOF)
		flags |= T_CLEOF;

	    ltp = firstask->t_ltp;
	    newtask->t_pfp = firstask->t_pfp;

	    /* Initialize the lexical analyzer (necessary to recognize BOL).
	     */
	    lexinit();

	} else {
	    if (ltp->lt_flags & LT_PFILE) {
		register struct pfile *pfp;

		/* This task has a real pfile. read in if not already in
		 * core.  Copy if not already one and not just cl.
		 */
		newtask->t_pfp = NULL;
		if ((pfp = pfilefind (ltp)) == NULL)
		    pfp = pfileload (ltp);
		if (!(pfp->pf_flags & PF_COPY) && ltp != firstask->t_ltp)
		    pfp = pfilecopy (pfp);
		newtask->t_pfp = pfp;

		/* Also load any pset files associated with the main pfile.
		 * These are linked into a list with the main pfile at the
		 * head of the list, pointed to by the task descriptor.
		 */
		if (pfp->pf_flags & PF_PSETREF) {
		    register struct param *pp;
		    struct  operand o;
		    char    *pset;

		    for (pp = pfp->pf_pp;  pp != NULL;  pp = pp->p_np) {
			if (!(pp->p_type & PT_PSET))
			    continue;
			o = pp->p_valo;
			if (opundef(&o) || *(pset = o.o_val.v_s) == EOS)
			    pset = pp->p_name;
			pfp = pfp->pf_npset = pfilecopy (pfilesrch (pset));
			pfp->pf_psetp = pp;
		    }
		}

	    } else {
		/* This task does not have a real pfile so start a fake one.
		 */
		newtask->t_pfp = newpfile (ltp);
		newtask->t_pfp->pf_flags = PF_FAKE;
	    }
	}

	newtask->t_pfp->pf_n = 0;	/* init number of command line args */
	newtask->t_ltp = ltp;
	newtask->t_pid = -1;		/* gets set if do a real exec	*/
	newtask->t_stdin = currentask->t_stdin;	/* inherit files	*/
	newtask->t_stdout = currentask->t_stdout;
	newtask->t_stderr = currentask->t_stderr;
	newtask->t_stdgraph = currentask->t_stdgraph;
	newtask->t_stdimage = currentask->t_stdimage;
	newtask->t_stdplot = currentask->t_stdplot;

	/* Init i/o redirection for a foreign task.
	 */
	newtask->ft_in = newtask->ft_out = newtask->ft_err = NULL;

	/* Set up flags describing the kind of task we are about to run. the
	 * absence of any of these flags will imply a genuine executable task.
	 * the flags in t_flags are more of a convenience than anything since
	 * later tests could use the same tests used here.
	 */
	ltflags = ltp->lt_flags;

	if (ltflags & LT_PSET) {
	    flags = (T_SCRIPT|T_PSET);
	} else if (ltflags & LT_SCRIPT) {
	    newtask->t_scriptln = 0;
	    flags = T_SCRIPT;
	} else if (ltflags & LT_FOREIGN) {
	    flags = T_BUILTIN | T_FOREIGN;	/* a type of builtin */
	} else if (ltflags & LT_BUILTIN) {
	    flags = T_BUILTIN;
	} else if (ltflags & LT_CL) {
	    /* Or, not assign: preserve T_PKGCL and T_CLEOF flags if set. */
	    flags |= T_CL;
	}

	if (ltflags & LT_STDINB)
	    flags |= T_STDINB;
	if (ltflags & LT_STDOUTB)
	    flags |= T_STDOUTB;

	newtask->t_flags = flags;
}
Exemplo n.º 2
0
Arquivo: main.c Projeto: olebole/iraf
/* LOGIN -- Hand-craft the first cl process.  Push the first task to become
 * currentask, set up clpackage at pachead and set cl as its first ltask.
 * Add the builtin function ltasks.  Run the startup file as the stdin of cl.
 * If any of this fails, we die.
 */
static void
login (char *cmd)
{ 
	register struct task *tp;
	register char *ip, *op;
	struct	ltask *ltp;
	struct	operand o;
	char	*loginfile = LOGINFILE;
	char	alt_loginfile[SZ_PATHNAME];
	char	clstartup[SZ_PATHNAME];
	char	clprocess[SZ_PATHNAME];
	char	*arglist;

	strcpy (clstartup, HOSTLIB);
	strcat (clstartup, CLSTARTUP);
	strcpy (clprocess, CLDIR);
	strcat (clprocess, CLPROCESS);

	tp = firstask = currentask = pushtask();
	tp->t_in = tp->t_stdin = stdin;
	tp->t_out = tp->t_stdout = stdout;
	tp->t_stderr = stderr;
	tp->t_stdgraph = fdopen (STDGRAPH, "w");
	tp->t_stdimage = fdopen (STDIMAGE, "w");
	tp->t_stdplot  = fdopen (STDPLOT,  "w");
	tp->t_pid = -1;
	tp->t_flags |= (T_INTERACTIVE|T_CL);

	/* Make root package.  Avoid use of newpac() since pointers are not
	 * yet set right.
	 */
	pachead = topd;
	curpack = (struct package *) memneed (PACKAGESIZ);
	curpack->pk_name = comdstr (ROOTPACKAGE);
	curpack->pk_ltp = NULL;
	curpack->pk_pfp = NULL;
	curpack->pk_npk = NULL;
	curpack->pk_flags = 0;

	/* Make first ltask.
	 */
	ltp = newltask (curpack, "cl", clprocess, (struct ltask *) NULL);
	tp->t_ltp = ltp;
	ltp->lt_flags |= (LT_PFILE|LT_CL);

	tp->t_pfp = pfileload (ltp);	/* call newpfile(), read cl.par */
	tp->t_pfp->pf_npf = NULL;
	setclmodes (tp);		/* uses cl's params		*/

	setbuiltins (curpack);		/* add more ltasks off clpackage*/

	/* Define the second package, the "clpackage", and make it the
	 * current package (default package at startup).  Tasks subsequently
	 * defined by the startup script will get put in clpackage.
	 */
	curpack = newpac (CLPACKAGE, "bin$");

	/* Compile code that will run the startup script then, if it exists
 	 * in the current directory, a login.cl script.  We need to do as
	 * much by hand here as the forever loop in main would have if this
	 * code came from calling yyparse().
	 */
	if (c_access (clstartup,0,0) == NO)
	    cl_error (E_FERR, "Cannot find startup file `%s'", clstartup);

	currentask->t_bascode = 0;
	pc = 0;
	o.o_type = OT_STRING;
	o.o_val.v_s = clstartup;
	compile (CALL, "cl");
	compile (PUSHCONST, &o);
	compile (REDIRIN);
	compile (EXEC);
	compile (FIXLANGUAGE);

	/* The following is to permit error recovery in the event that an
	 * error occurs while reading the user's LOGIN.CL file.
	 */
	validerrenv = 1;
	if (setjmp (errenv)) {
	    eprintf ("Error while reading login.cl file");
	    eprintf (" - may need to rebuild with mkiraf\n");
	    eprintf ("Fatal startup error.  CL dies.\n");
	    clexit();
	}
	ninterrupts = 0;
	if (setjmp (jumpcom))
	    onerr();

	/* Nondestructively decompose the host command line into the startup
	 * filename and/or the argument string.
	 */
	if (strncmp (cmd, "-f", 2) == 0) {
	    for (ip=cmd+2;  *ip && isspace(*ip);  ip++)
		;
	    for (op=alt_loginfile;  *ip && ! isspace(*ip);  *op++ = *ip++)
		;
	    *op = EOS;

	    for (  ;  *ip && isspace(*ip);  ip++)
		;
	    arglist = ip;

	} else {
	    *alt_loginfile = EOS;
	    arglist = cmd;
	}

	/* Copy any user supplied host command line arguments into the
	 * CL parameter $args to use in the startup script (for instance).
	 */
	o.o_type = OT_STRING;
	strcpy (o.o_val.v_s, arglist);
	compile (PUSHCONST, &o);
	compile (ASSIGN, "args");

	if (alt_loginfile[0]) {
	    if (c_access (alt_loginfile,0,0) == NO)
		printf ("Warning: script file %s not found\n", alt_loginfile);
	    else {
		o.o_val.v_s = alt_loginfile;
		compile (CALL, "cl");
		compile (PUSHCONST, &o);
		compile (REDIRIN);
		compile (EXEC);
	    }

        } else if (c_access (loginfile,0,0) == NO) {
            char *home = envget ("HOME");
            char global[SZ_LINE];

            memset (global, 0, SZ_LINE);
            sprintf (global, "%s/.iraf/login.cl", home);
            if (c_access (global, 0, 0) == YES) {
                o.o_val.v_s = global;
                compile (CALL, "cl");
                compile (PUSHCONST, &o);
                compile (REDIRIN);
                compile (EXEC);
            } else {
                printf ("Warning: no login.cl found in login directory\n");
            }

	} else {
	    o.o_val.v_s = loginfile;
	    compile (CALL, "cl");
	    compile (PUSHCONST, &o);
	    compile (REDIRIN);
	    compile (EXEC);
	}

	compile (END);
	topos = basos = pc - 1;
	pc = 0;
	run();			/* returns after doing the first EXEC	*/

	/* Add nothing here that will effect the dictionary or the stacks.
	 */
	if (cldebug)
	    printf ("topd, pachead, parhead: %u, %u, %u\n",
		topd, pachead, parhead);
}