⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eval.c

📁 Android 一些工具
💻 C
📖 第 1 页 / 共 2 页
字号:
	return sys_path;}static intparse_command_args(int argc, char **argv, int *use_syspath){	int sv_argc = argc;	char *cp, c;	*use_syspath = 0;	for (;;) {		argv++;		if (--argc == 0)			break;		cp = *argv;		if (*cp++ != '-')			break;		if (*cp == '-' && cp[1] == 0) {			argv++;			argc--;			break;		}		while ((c = *cp++)) {			switch (c) {			case 'p':				*use_syspath = 1;				break;			default:				/* run 'typecmd' for other options */				return 0;			}		}	}	return sv_argc - argc;}int vforked = 0;/* * Execute a simple command. */STATIC voidevalcommand(union node *cmd, int flags, struct backcmd *backcmd){	struct stackmark smark;	union node *argp;	struct arglist arglist;	struct arglist varlist;	char **argv;	int argc;	char **envp;	int varflag;	struct strlist *sp;	int mode;	int pip[2];	struct cmdentry cmdentry;	struct job *jp;	struct jmploc jmploc;	struct jmploc *volatile savehandler;	char *volatile savecmdname;	volatile struct shparam saveparam;	struct localvar *volatile savelocalvars;	volatile int e;	char *lastarg;	const char *path = pathval();	volatile int temp_path;#if __GNUC__	/* Avoid longjmp clobbering */	(void) &argv;	(void) &argc;	(void) &lastarg;	(void) &flags;#endif	vforked = 0;	/* First expand the arguments. */	TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));	setstackmark(&smark);	back_exitstatus = 0;	arglist.lastp = &arglist.list;	varflag = 1;	/* Expand arguments, ignoring the initial 'name=value' ones */	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {		char *p = argp->narg.text;		if (varflag && is_name(*p)) {			do {				p++;			} while (is_in_name(*p));			if (*p == '=')				continue;		}		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);		varflag = 0;	}	*arglist.lastp = NULL;	expredir(cmd->ncmd.redirect);	/* Now do the initial 'name=value' ones we skipped above */	varlist.lastp = &varlist.list;	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {		char *p = argp->narg.text;		if (!is_name(*p))			break;		do			p++;		while (is_in_name(*p));		if (*p != '=')			break;		expandarg(argp, &varlist, EXP_VARTILDE);	}	*varlist.lastp = NULL;	argc = 0;	for (sp = arglist.list ; sp ; sp = sp->next)		argc++;	argv = stalloc(sizeof (char *) * (argc + 1));	for (sp = arglist.list ; sp ; sp = sp->next) {		TRACE(("evalcommand arg: %s\n", sp->text));		*argv++ = sp->text;	}	*argv = NULL;	lastarg = NULL;	if (iflag && funcnest == 0 && argc > 0)		lastarg = argv[-1];	argv -= argc;	/* Print the command if xflag is set. */	if (xflag) {		char sep = 0;		out2str(ps4val());		for (sp = varlist.list ; sp ; sp = sp->next) {			if (sep != 0)				outc(sep, &errout);			out2str(sp->text);			sep = ' ';		}		for (sp = arglist.list ; sp ; sp = sp->next) {			if (sep != 0)				outc(sep, &errout);			out2str(sp->text);			sep = ' ';		}		outc('\n', &errout);		flushout(&errout);	}	/* Now locate the command. */	if (argc == 0) {		cmdentry.cmdtype = CMDSPLBLTIN;		cmdentry.u.bltin = bltincmd;	} else {		static const char PATH[] = "PATH=";		int cmd_flags = DO_ERR;		/*		 * Modify the command lookup path, if a PATH= assignment		 * is present		 */		for (sp = varlist.list; sp; sp = sp->next)			if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0)				path = sp->text + sizeof(PATH) - 1;		do {			int argsused, use_syspath;			find_command(argv[0], &cmdentry, cmd_flags, path);			if (cmdentry.cmdtype == CMDUNKNOWN) {				exitstatus = 127;				flushout(&errout);				goto out;			}			/* implement the 'command' builtin here */			if (cmdentry.cmdtype != CMDBUILTIN ||			    cmdentry.u.bltin != bltincmd)				break;			cmd_flags |= DO_NOFUNC;			argsused = parse_command_args(argc, argv, &use_syspath);			if (argsused == 0) {				/* use 'type' builting to display info */				cmdentry.u.bltin = typecmd;				break;			}			argc -= argsused;			argv += argsused;			if (use_syspath)				path = syspath() + 5;		} while (argc != 0);		if (cmdentry.cmdtype == CMDSPLBLTIN && cmd_flags & DO_NOFUNC)			/* posix mandates that 'command <splbltin>' act as if			   <splbltin> was a normal builtin */			cmdentry.cmdtype = CMDBUILTIN;	}	/* Fork off a child process if necessary. */	if (cmd->ncmd.backgnd	 || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)	 || ((flags & EV_BACKCMD) != 0	    && ((cmdentry.cmdtype != CMDBUILTIN && cmdentry.cmdtype != CMDSPLBLTIN)		 || cmdentry.u.bltin == dotcmd		 || cmdentry.u.bltin == evalcmd))) {		INTOFF;		jp = makejob(cmd, 1);		mode = cmd->ncmd.backgnd;		if (flags & EV_BACKCMD) {			mode = FORK_NOJOB;			if (sh_pipe(pip) < 0)				error("Pipe call failed");		}#ifdef DO_SHAREDVFORK		/* It is essential that if DO_SHAREDVFORK is defined that the		 * child's address space is actually shared with the parent as		 * we rely on this.		 */		if (cmdentry.cmdtype == CMDNORMAL) {			pid_t	pid;			savelocalvars = localvars;			localvars = NULL;			vforked = 1;			switch (pid = vfork()) {			case -1:				TRACE(("Vfork failed, errno=%d\n", errno));				INTON;				error("Cannot vfork");				break;			case 0:				/* Make sure that exceptions only unwind to				 * after the vfork(2)				 */				if (setjmp(jmploc.loc)) {					if (exception == EXSHELLPROC) {						/* We can't progress with the vfork,						 * so, set vforked = 2 so the parent						 * knows, and _exit();						 */						vforked = 2;						_exit(0);					} else {						_exit(exerrno);					}				}				savehandler = handler;				handler = &jmploc;				listmklocal(varlist.list, VEXPORT | VNOFUNC);				forkchild(jp, cmd, mode, vforked);				break;			default:				handler = savehandler;	/* restore from vfork(2) */				poplocalvars();				localvars = savelocalvars;				if (vforked == 2) {					vforked = 0;					(void)waitpid(pid, NULL, 0);					/* We need to progress in a normal fork fashion */					goto normal_fork;				}				vforked = 0;				forkparent(jp, cmd, mode, pid);				goto parent;			}		} else {normal_fork:#endif			if (forkshell(jp, cmd, mode) != 0)				goto parent;	/* at end of routine */			FORCEINTON;#ifdef DO_SHAREDVFORK		}#endif		if (flags & EV_BACKCMD) {			if (!vforked) {				FORCEINTON;			}			close(pip[0]);			if (pip[1] != 1) {				close(1);				copyfd(pip[1], 1);				close(pip[1]);			}		}		flags |= EV_EXIT;	}	/* This is the child process if a fork occurred. */	/* Execute the command. */	switch (cmdentry.cmdtype) {	case CMDFUNCTION:#ifdef DEBUG		trputs("Shell function:  ");  trargs(argv);#endif		redirect(cmd->ncmd.redirect, REDIR_PUSH);		saveparam = shellparam;		shellparam.malloc = 0;		shellparam.reset = 1;		shellparam.nparam = argc - 1;		shellparam.p = argv + 1;		shellparam.optnext = NULL;		INTOFF;		savelocalvars = localvars;		localvars = NULL;		INTON;		if (setjmp(jmploc.loc)) {			if (exception == EXSHELLPROC) {				freeparam((volatile struct shparam *)				    &saveparam);			} else {				freeparam(&shellparam);				shellparam = saveparam;			}			poplocalvars();			localvars = savelocalvars;			handler = savehandler;			longjmp(handler->loc, 1);		}		savehandler = handler;		handler = &jmploc;		listmklocal(varlist.list, 0);		/* stop shell blowing its stack */		if (++funcnest > 1000)			error("too many nested function calls");		evaltree(cmdentry.u.func, flags & EV_TESTED);		funcnest--;		INTOFF;		poplocalvars();		localvars = savelocalvars;		freeparam(&shellparam);		shellparam = saveparam;		handler = savehandler;		popredir();		INTON;		if (evalskip == SKIPFUNC) {			evalskip = 0;			skipcount = 0;		}		if (flags & EV_EXIT)			exitshell(exitstatus);		break;	case CMDBUILTIN:	case CMDSPLBLTIN:#ifdef DEBUG		trputs("builtin command:  ");  trargs(argv);#endif		mode = (cmdentry.u.bltin == execcmd) ? 0 : REDIR_PUSH;		if (flags == EV_BACKCMD) {			memout.nleft = 0;			memout.nextc = memout.buf;			memout.bufsize = 64;			mode |= REDIR_BACKQ;		}		e = -1;		savehandler = handler;		savecmdname = commandname;		handler = &jmploc;		if (!setjmp(jmploc.loc)) {			/* We need to ensure the command hash table isn't			 * corruped by temporary PATH assignments.			 * However we must ensure the 'local' command works!			 */			if (path != pathval() && (cmdentry.u.bltin == hashcmd ||			    cmdentry.u.bltin == typecmd)) {				savelocalvars = localvars;				localvars = 0;				mklocal(path - 5 /* PATH= */, 0);				temp_path = 1;			} else				temp_path = 0;			redirect(cmd->ncmd.redirect, mode);			/* exec is a special builtin, but needs this list... */			cmdenviron = varlist.list;			/* we must check 'readonly' flag for all builtins */			listsetvar(varlist.list,				cmdentry.cmdtype == CMDSPLBLTIN ? 0 : VNOSET);			commandname = argv[0];			/* initialize nextopt */			argptr = argv + 1;			optptr = NULL;			/* and getopt */#ifndef __linux__			optreset = 1;#endif			optind = 1;			exitstatus = cmdentry.u.bltin(argc, argv);		} else {			e = exception;			exitstatus = e == EXINT ? SIGINT + 128 :					e == EXEXEC ? exerrno : 2;		}		handler = savehandler;		flushall();		out1 = &output;		out2 = &errout;		freestdout();		if (temp_path) {			poplocalvars();			localvars = savelocalvars;		}		cmdenviron = NULL;		if (e != EXSHELLPROC) {			commandname = savecmdname;			if (flags & EV_EXIT)				exitshell(exitstatus);		}		if (e != -1) {			if ((e != EXERROR && e != EXEXEC)			    || cmdentry.cmdtype == CMDSPLBLTIN)				exraise(e);			FORCEINTON;		}		if (cmdentry.u.bltin != execcmd)			popredir();		if (flags == EV_BACKCMD) {			backcmd->buf = memout.buf;			backcmd->nleft = memout.nextc - memout.buf;			memout.buf = NULL;		}		break;	default:#ifdef DEBUG		trputs("normal command:  ");  trargs(argv);#endif		clearredir(vforked);		redirect(cmd->ncmd.redirect, vforked ? REDIR_VFORK : 0);		if (!vforked)			for (sp = varlist.list ; sp ; sp = sp->next)				setvareq(sp->text, VEXPORT|VSTACK);		envp = environment();		shellexec(argv, envp, path, cmdentry.u.index, vforked);		break;	}	goto out;parent:	/* parent process gets here (if we forked) */	if (mode == FORK_FG) {	/* argument to fork */		exitstatus = waitforjob(jp);	} else if (mode == FORK_NOJOB) {		backcmd->fd = pip[0];		close(pip[1]);		backcmd->jp = jp;	}	FORCEINTON;out:	if (lastarg)		/* dsl: I think this is intended to be used to support		 * '_' in 'vi' command mode during line editing...		 * However I implemented that within libedit itself.		 */		setvar("_", lastarg, 0);	popstackmark(&smark);	if (eflag && exitstatus && !(flags & EV_TESTED))		exitshell(exitstatus);}/* * Search for a command.  This is called before we fork so that the * location of the command will be available in the parent as well as * the child.  The check for "goodname" is an overly conservative * check that the name will not be subject to expansion. */STATIC voidprehash(union node *n){	struct cmdentry entry;	if (n->type == NCMD && n->ncmd.args)		if (goodname(n->ncmd.args->narg.text))			find_command(n->ncmd.args->narg.text, &entry, 0,				     pathval());}/* * Builtin commands.  Builtin commands whose functions are closely * tied to evaluation are implemented here. *//* * No command given. */intbltincmd(int argc, char **argv){	/*	 * Preserve exitstatus of a previous possible redirection	 * as POSIX mandates	 */	return back_exitstatus;}/* * Handle break and continue commands.  Break, continue, and return are * all handled by setting the evalskip flag.  The evaluation routines * above all check this flag, and if it is set they start skipping * commands rather than executing them.  The variable skipcount is * the number of loops to break/continue, or the number of function * levels to return.  (The latter is always 1.)  It should probably * be an error to break out of more loops than exist, but it isn't * in the standard shell so we don't make it one here. */intbreakcmd(int argc, char **argv){	int n = argc > 1 ? number(argv[1]) : 1;	if (n > loopnest)		n = loopnest;	if (n > 0) {		evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;		skipcount = n;	}	return 0;}/* * The return command. */intreturncmd(int argc, char **argv){	int ret = argc > 1 ? number(argv[1]) : exitstatus;	if (funcnest) {		evalskip = SKIPFUNC;		skipcount = 1;		return ret;	}	else {		/* Do what ksh does; skip the rest of the file */		evalskip = SKIPFILE;		skipcount = 1;		return ret;	}}intfalsecmd(int argc, char **argv){	return 1;}inttruecmd(int argc, char **argv){	return 0;}intexeccmd(int argc, char **argv){	if (argc > 1) {		struct strlist *sp;		iflag = 0;		/* exit on error */		mflag = 0;		optschanged();		for (sp = cmdenviron; sp; sp = sp->next)			setvareq(sp->text, VEXPORT|VSTACK);		shellexec(argv + 1, environment(), pathval(), 0, 0);	}	return 0;}static intconv_time(clock_t ticks, char *seconds, size_t l){	static clock_t tpm = 0;	clock_t mins;	int i;	mins = ticks / tpm;	snprintf(seconds, l, "%.4f", (ticks - mins * tpm) * 60.0 / tpm );	if (seconds[0] == '6' && seconds[1] == '0') {		/* 59.99995 got rounded up... */		mins++;		strlcpy(seconds, "0.0", l);		return mins;	}	/* suppress trailing zeros */	i = strlen(seconds) - 1;	for (; seconds[i] == '0' && seconds[i - 1] != '.'; i--)		seconds[i] = 0;	return mins;}inttimescmd(int argc, char **argv){	struct tms tms;	int u, s, cu, cs;	char us[8], ss[8], cus[8], css[8];	nextopt("");	times(&tms);	u = conv_time(tms.tms_utime, us, sizeof(us));	s = conv_time(tms.tms_stime, ss, sizeof(ss));	cu = conv_time(tms.tms_cutime, cus, sizeof(cus));	cs = conv_time(tms.tms_cstime, css, sizeof(css));	outfmt(out1, "%dm%ss %dm%ss\n%dm%ss %dm%ss\n",		u, us, s, ss, cu, cus, cs, css);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -