示例#1
0
/*
 * Validate command/agent path and argument list
 */
INTERNAL int
validate(char *file, char *args) {
	char *s;

	if (Verbose) printf("validating %s %s\n", file, args);

	if (*file == '/') return(AGENTD_STATUS_BADPATH);
	for (s = file; *s; ++s) {
		if (s[0] == '.' && s[1] == '.') return(AGENTD_STATUS_BADPATH);
		if (oneof(*s, "[]|><&*?!~`"))   return(AGENTD_STATUS_BADPATH);
	}
	if (access(file, X_OK) != SYS_OK) {
		if (access(file, F_OK) != SYS_OK) return(AGENTD_STATUS_NOFILE);
		else                              return(AGENTD_STATUS_NOEXEC);
	}

	if (oneof(*s, "<>&|*?![]{}")) return(AGENTD_STATUS_BADARGS);

	return(AGENTD_STATUS_OK);
}
示例#2
0
int
main(int argc, char *argv[])
{
	struct fstab *fs;
	struct passwd *pw;
	struct group *gr;
	struct quotafile *qfu, *qfg;
	int i, argnum, maxrun, errs, ch;
	long done = 0;
	char *name;

	errs = maxrun = 0;
	while ((ch = getopt(argc, argv, "ac:guvl:")) != -1) {
		switch(ch) {
		case 'a':
			aflag++;
			break;
		case 'c':
			if (cflag)
				usage();
			cflag = atoi(optarg);
			break;
		case 'g':
			gflag++;
			break;
		case 'u':
			uflag++;
			break;
		case 'v':
			vflag++;
			break;
		case 'l':
			maxrun = atoi(optarg);
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;
	if ((argc == 0 && !aflag) || (argc > 0 && aflag))
		usage();
	if (cflag && cflag != 32 && cflag != 64)
		usage();
	if (!gflag && !uflag) {
		gflag++;
		uflag++;
	}
	if (gflag) {
		setgrent();
		while ((gr = getgrent()) != NULL)
			(void) addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name,
			    NULL);
		endgrent();
	}
	if (uflag) {
		setpwent();
		while ((pw = getpwent()) != NULL)
			(void) addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name,
			    NULL);
		endpwent();
	}
	/*
	 * The maxrun (-l) option is now deprecated.
	 */
	if (maxrun > 0)
		warnx("the -l option is now deprecated");
	if (aflag)
		exit(checkfstab(uflag, gflag));
	if (setfsent() == 0)
		errx(1, "%s: can't open", FSTAB);
	while ((fs = getfsent()) != NULL) {
		if (((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
		     (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) &&
		    (name = blockcheck(fs->fs_spec))) {
			done |= 1 << argnum;
			qfu = NULL;
			if (uflag)
				qfu = quota_open(fs, USRQUOTA, O_CREAT|O_RDWR);
			qfg = NULL;
			if (gflag)
				qfg = quota_open(fs, GRPQUOTA, O_CREAT|O_RDWR);
			if (qfu == NULL && qfg == NULL)
				continue;
			errs += chkquota(name, qfu, qfg);
			if (qfu)
				quota_close(qfu);
			if (qfg)
				quota_close(qfg);
		}
	}
	endfsent();
	for (i = 0; i < argc; i++)
		if ((done & (1 << i)) == 0)
			fprintf(stderr, "%s not found in %s\n",
				argv[i], FSTAB);
	exit(errs);
}
示例#3
0
int
main(int argc, char **argv)
{
	struct fstab *fs;
	struct passwd *pw;
	struct group *gr;
	int gflag = 0, uflag = 0, errs = 0;
	long i, argnum, done = 0;
	char ch, *qfnp;

	while ((ch = getopt(argc, argv, "aguv")) != -1) {
		switch(ch) {
		case 'a':
			aflag++;
			break;
		case 'g':
			gflag++;
			break;
		case 'u':
			uflag++;
			break;
		case 'v':
			vflag++;
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;
	if (argc == 0 && !aflag)
		usage();
	if (!gflag && !uflag) {
		if (aflag)
			gflag++;
		uflag++;
	}
	if (gflag) {
		setgrent();
		while ((gr = getgrent()) != 0)
			addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name);
		endgrent();
	}
	if (uflag) {
		setpwent();
		while ((pw = getpwent()) != 0)
			addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name);
		endpwent();
	}
	setfsent();
	while ((fs = getfsent()) != NULL) {
		if (strcmp(fs->fs_vfstype, "ufs"))
			continue;
		if (aflag) {
			if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
				errs += repquota(fs, GRPQUOTA, qfnp);
			if (uflag && hasquota(fs, USRQUOTA, &qfnp))
				errs += repquota(fs, USRQUOTA, qfnp);
			continue;
		}
		if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
			done |= 1 << argnum;
			if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
				errs += repquota(fs, GRPQUOTA, qfnp);
			if (uflag && hasquota(fs, USRQUOTA, &qfnp))
				errs += repquota(fs, USRQUOTA, qfnp);
		}
	}
	endfsent();
	for (i = 0; i < argc; i++)
		if ((done & (1 << i)) == 0)
			warnx("%s not found in fstab", argv[i]);
	exit(errs);
}
示例#4
0
文件: exec.c 项目: geechee/iraf
/* 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);
}
示例#5
0
int
main(int argc, char **argv)
{
	struct fstab *fs;
	const char *whoami;
	long argnum, done = 0;
	int ch, i, offmode = 0, errs = 0;

	whoami = getprogname();
	if (strcmp(whoami, "quotaoff") == 0)
		offmode++;
	else if (strcmp(whoami, "quotaon") != 0)
		errx(1, "name must be quotaon or quotaoff");
	while ((ch = getopt(argc, argv, "avug")) != -1) {
		switch(ch) {
		case 'a':
			aflag++;
			break;
		case 'g':
			gflag++;
			break;
		case 'u':
			uflag++;
			break;
		case 'v':
			vflag++;
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;
	if (argc <= 0 && !aflag)
		usage();
	if (!gflag && !uflag) {
		gflag++;
		uflag++;
	}
	setfsent();
	while ((fs = getfsent()) != NULL) {
		if (strcmp(fs->fs_vfstype, "ufs") ||
		    strcmp(fs->fs_type, FSTAB_RW))
			continue;
		if (aflag) {
			if (gflag)
				errs += quotaonoff(fs, offmode, GRPQUOTA);
			if (uflag)
				errs += quotaonoff(fs, offmode, USRQUOTA);
			continue;
		}
		if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
			done |= 1 << argnum;
			if (gflag)
				errs += quotaonoff(fs, offmode, GRPQUOTA);
			if (uflag)
				errs += quotaonoff(fs, offmode, USRQUOTA);
		}
	}
	endfsent();
	for (i = 0; i < argc; i++)
		if ((done & (1 << i)) == 0)
			warnx("%s not found in fstab", argv[i]);
	exit(errs);
}
示例#6
0
int
main(int argc, char **argv)
{
	struct fstab *fs;
	struct passwd *pw;
	struct group *gr;
	struct quotaname *auxdata;
	int i, argnum, maxrun, errs;
	long done = 0;
	char ch, *name;

	errs = maxrun = 0;
	while ((ch = getopt(argc, argv, "aguvl:")) != -1) {
		switch(ch) {
		case 'a':
			aflag++;
			break;
		case 'g':
			gflag++;
			break;
		case 'u':
			uflag++;
			break;
		case 'v':
			vflag++;
			break;
		case 'l':
			maxrun = atoi(optarg);
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;
	if ((argc == 0 && !aflag) || (argc > 0 && aflag))
		usage();
	if (!gflag && !uflag) {
		gflag++;
		uflag++;
	}
	if (gflag) {
		setgrent();
		while ((gr = getgrent()) != NULL)
			addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name);
		endgrent();
	}
	if (uflag) {
		setpwent();
		while ((pw = getpwent()) != NULL)
			addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name);
		endpwent();
	}
	if (aflag)
		exit(checkfstab(1, maxrun, needchk, chkquota));
	if (setfsent() == 0)
		errx(1, "%s: can't open", FSTAB);
	while ((fs = getfsent()) != NULL) {
		if (((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) &&
		    (auxdata = needchk(fs)) &&
		    (name = blockcheck(fs->fs_spec))) {
			done |= 1 << argnum;
			errs += chkquota(name, fs->fs_file, auxdata);
		}
	}
	endfsent();
	for (i = 0; i < argc; i++)
		if ((done & (1 << i)) == 0)
			fprintf(stderr, "%s not found in %s\n",
				argv[i], FSTAB);
	exit(errs);
}
示例#7
0
int
main(int argc, char *argv[])
{
	struct fstab *fs;
	struct passwd *pw;
	struct group *gr;
	struct quotaname *auxdata;
	int i, argnum, maxrun, errs, ch;
	u_int64_t done = 0;	/* XXX supports maximum 64 filesystems */
	char *name;

	errs = maxrun = 0;
	while ((ch = getopt(argc, argv, "adguvl:")) != -1) {
		switch(ch) {
		case 'a':
			flags |= CHECK_PREEN;
			break;
		case 'd':
			flags |= CHECK_DEBUG;
			break;
		case 'g':
			gflag++;
			break;
		case 'l':
			maxrun = atoi(optarg);
			break;
		case 'u':
			uflag++;
			break;
		case 'v':
			flags |= CHECK_VERBOSE;
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;
	if ((argc == 0 && !(flags&CHECK_PREEN)) ||
	    (argc > 0 && (flags&CHECK_PREEN)))
		usage();
	if (!gflag && !uflag) {
		gflag++;
		uflag++;
	}
	if (gflag) {
		setgrent();
		while ((gr = getgrent()) != 0)
			(void) addid(gr->gr_gid, GRPQUOTA, gr->gr_name);
		endgrent();
	}
	if (uflag) {
		setpwent();
		while ((pw = getpwent()) != 0)
			(void) addid(pw->pw_uid, USRQUOTA, pw->pw_name);
		endpwent();
	}
	if (flags&CHECK_PREEN)
		exit(checkfstab(flags, maxrun, needchk, chkquota));
	if (setfsent() == 0)
		err(1, "%s: can't open", FSTAB);
	while ((fs = getfsent()) != NULL) {
		if (((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) &&
		    (auxdata = needchk(fs)) &&
		    (name = blockcheck(fs->fs_spec))) {
			done |= 1 << argnum;
			errs += chkquota(fs->fs_vfstype, name,
			    fs->fs_file, auxdata, NULL);
		}
	}
	endfsent();
	for (i = 0; i < argc; i++)
		if ((done & (1 << i)) == 0)
			fprintf(stderr, "%s not found in %s\n",
			    argv[i], FSTAB);
	exit(errs);
}
示例#8
0
文件: main.c 项目: olebole/iraf
/* 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);
}