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

📄 eval.c

📁 Android 一些工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	$NetBSD: eval.c,v 1.81.2.1 2005/06/13 22:03:51 tron Exp $	*//*- * Copyright (c) 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include <sys/cdefs.h>#ifndef lint#if 0static char sccsid[] = "@(#)eval.c	8.9 (Berkeley) 6/8/95";#else__RCSID("$NetBSD: eval.c,v 1.81.2.1 2005/06/13 22:03:51 tron Exp $");#endif#endif /* not lint */#include <stdlib.h>#include <signal.h>#include <stdio.h>#include <unistd.h>#ifdef __linux__#include <fcntl.h>#else#include <sys/fcntl.h>#endif#include <sys/times.h>#include <sys/param.h>#include <sys/types.h>#include <sys/wait.h>/* * Evaluate a command. */#include "shell.h"#include "nodes.h"#include "syntax.h"#include "expand.h"#include "parser.h"#include "jobs.h"#include "eval.h"#include "builtins.h"#include "options.h"#include "exec.h"#include "redir.h"#include "input.h"#include "output.h"#include "trap.h"#include "var.h"#include "memalloc.h"#include "error.h"#include "show.h"#include "mystring.h"#include "main.h"#ifndef SMALL#include "myhistedit.h"#endif/* flags in argument to evaltree */#define EV_EXIT 01		/* exit after evaluating tree */#define EV_TESTED 02		/* exit status is checked; ignore -e flag */#define EV_BACKCMD 04		/* command executing within back quotes */int evalskip;			/* set if we are skipping commands */STATIC int skipcount;		/* number of levels to skip */MKINIT int loopnest;		/* current loop nesting level */int funcnest;			/* depth of function calls */char *commandname;struct strlist *cmdenviron;int exitstatus;			/* exit status of last command */int back_exitstatus;		/* exit status of backquoted command */STATIC void evalloop(union node *, int);STATIC void evalfor(union node *, int);STATIC void evalcase(union node *, int);STATIC void evalsubshell(union node *, int);STATIC void expredir(union node *);STATIC void evalpipe(union node *);STATIC void evalcommand(union node *, int, struct backcmd *);STATIC void prehash(union node *);/* * Called to reset things after an exception. */#ifdef mkinitINCLUDE "eval.h"RESET {	evalskip = 0;	loopnest = 0;	funcnest = 0;}SHELLPROC {	exitstatus = 0;}#endifstatic intsh_pipe(int fds[2]){	int nfd;	if (pipe(fds))		return -1;	if (fds[0] < 3) {		nfd = fcntl(fds[0], F_DUPFD, 3);		if (nfd != -1) {			close(fds[0]);			fds[0] = nfd;		}	}	if (fds[1] < 3) {		nfd = fcntl(fds[1], F_DUPFD, 3);		if (nfd != -1) {			close(fds[1]);			fds[1] = nfd;		}	}	return 0;}/* * The eval commmand. */intevalcmd(int argc, char **argv){        char *p;        char *concat;        char **ap;        if (argc > 1) {                p = argv[1];                if (argc > 2) {                        STARTSTACKSTR(concat);                        ap = argv + 2;                        for (;;) {                                while (*p)                                        STPUTC(*p++, concat);                                if ((p = *ap++) == NULL)                                        break;                                STPUTC(' ', concat);                        }                        STPUTC('\0', concat);                        p = grabstackstr(concat);                }                evalstring(p, EV_TESTED);        }        return exitstatus;}/* * Execute a command or commands contained in a string. */voidevalstring(char *s, int flag){	union node *n;	struct stackmark smark;	setstackmark(&smark);	setinputstring(s, 1);	while ((n = parsecmd(0)) != NEOF) {		evaltree(n, flag);		popstackmark(&smark);	}	popfile();	popstackmark(&smark);}/* * Evaluate a parse tree.  The value is left in the global variable * exitstatus. */voidevaltree(union node *n, int flags){	if (n == NULL) {		TRACE(("evaltree(NULL) called\n"));		exitstatus = 0;		goto out;	}#ifdef WITH_HISTORY	displayhist = 1;	/* show history substitutions done with fc */#endif	TRACE(("pid %d, evaltree(%p: %d, %d) called\n",	    getpid(), n, n->type, flags));	switch (n->type) {	case NSEMI:		evaltree(n->nbinary.ch1, flags & EV_TESTED);		if (evalskip)			goto out;		evaltree(n->nbinary.ch2, flags);		break;	case NAND:		evaltree(n->nbinary.ch1, EV_TESTED);		if (evalskip || exitstatus != 0)			goto out;		evaltree(n->nbinary.ch2, flags);		break;	case NOR:		evaltree(n->nbinary.ch1, EV_TESTED);		if (evalskip || exitstatus == 0)			goto out;		evaltree(n->nbinary.ch2, flags);		break;	case NREDIR:		expredir(n->nredir.redirect);		redirect(n->nredir.redirect, REDIR_PUSH);		evaltree(n->nredir.n, flags);		popredir();		break;	case NSUBSHELL:		evalsubshell(n, flags);		break;	case NBACKGND:		evalsubshell(n, flags);		break;	case NIF: {		evaltree(n->nif.test, EV_TESTED);		if (evalskip)			goto out;		if (exitstatus == 0)			evaltree(n->nif.ifpart, flags);		else if (n->nif.elsepart)			evaltree(n->nif.elsepart, flags);		else			exitstatus = 0;		break;	}	case NWHILE:	case NUNTIL:		evalloop(n, flags);		break;	case NFOR:		evalfor(n, flags);		break;	case NCASE:		evalcase(n, flags);		break;	case NDEFUN:		defun(n->narg.text, n->narg.next);		exitstatus = 0;		break;	case NNOT:		evaltree(n->nnot.com, EV_TESTED);		exitstatus = !exitstatus;		break;	case NPIPE:		evalpipe(n);		break;	case NCMD:		evalcommand(n, flags, (struct backcmd *)NULL);		break;	default:		out1fmt("Node type = %d\n", n->type);		flushout(&output);		break;	}out:	if (pendingsigs)		dotrap();	if ((flags & EV_EXIT) != 0)		exitshell(exitstatus);}STATIC voidevalloop(union node *n, int flags){	int status;	loopnest++;	status = 0;	for (;;) {		evaltree(n->nbinary.ch1, EV_TESTED);		if (evalskip) {skipping:	  if (evalskip == SKIPCONT && --skipcount <= 0) {				evalskip = 0;				continue;			}			if (evalskip == SKIPBREAK && --skipcount <= 0)				evalskip = 0;			break;		}		if (n->type == NWHILE) {			if (exitstatus != 0)				break;		} else {			if (exitstatus == 0)				break;		}		evaltree(n->nbinary.ch2, flags & EV_TESTED);		status = exitstatus;		if (evalskip)			goto skipping;	}	loopnest--;	exitstatus = status;}STATIC voidevalfor(union node *n, int flags){	struct arglist arglist;	union node *argp;	struct strlist *sp;	struct stackmark smark;	int status = 0;	setstackmark(&smark);	arglist.lastp = &arglist.list;	for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);		if (evalskip)			goto out;	}	*arglist.lastp = NULL;	loopnest++;	for (sp = arglist.list ; sp ; sp = sp->next) {		setvar(n->nfor.var, sp->text, 0);		evaltree(n->nfor.body, flags & EV_TESTED);		status = exitstatus;		if (evalskip) {			if (evalskip == SKIPCONT && --skipcount <= 0) {				evalskip = 0;				continue;			}			if (evalskip == SKIPBREAK && --skipcount <= 0)				evalskip = 0;			break;		}	}	loopnest--;	exitstatus = status;out:	popstackmark(&smark);}STATIC voidevalcase(union node *n, int flags){	union node *cp;	union node *patp;	struct arglist arglist;	struct stackmark smark;	int status = 0;	setstackmark(&smark);	arglist.lastp = &arglist.list;	expandarg(n->ncase.expr, &arglist, EXP_TILDE);	for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {			if (casematch(patp, arglist.list->text)) {				if (evalskip == 0) {					evaltree(cp->nclist.body, flags);					status = exitstatus;				}				goto out;			}		}	}out:	exitstatus = status;	popstackmark(&smark);}/* * Kick off a subshell to evaluate a tree. */STATIC voidevalsubshell(union node *n, int flags){	struct job *jp;	int backgnd = (n->type == NBACKGND);	expredir(n->nredir.redirect);	INTOFF;	jp = makejob(n, 1);	if (forkshell(jp, n, backgnd) == 0) {		INTON;		if (backgnd)			flags &=~ EV_TESTED;		redirect(n->nredir.redirect, 0);		/* never returns */		evaltree(n->nredir.n, flags | EV_EXIT);	}	if (! backgnd)		exitstatus = waitforjob(jp);	INTON;}/* * Compute the names of the files in a redirection list. */STATIC voidexpredir(union node *n){	union node *redir;	for (redir = n ; redir ; redir = redir->nfile.next) {		struct arglist fn;		fn.lastp = &fn.list;		switch (redir->type) {		case NFROMTO:		case NFROM:		case NTO:		case NCLOBBER:		case NAPPEND:			expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);			redir->nfile.expfname = fn.list->text;			break;		case NFROMFD:		case NTOFD:			if (redir->ndup.vname) {				expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);				fixredir(redir, fn.list->text, 1);			}			break;		}	}}/* * Evaluate a pipeline.  All the processes in the pipeline are children * of the process creating the pipeline.  (This differs from some versions * of the shell, which make the last process in a pipeline the parent * of all the rest.) */STATIC voidevalpipe(union node *n){	struct job *jp;	struct nodelist *lp;	int pipelen;	int prevfd;	int pip[2];	TRACE(("evalpipe(0x%lx) called\n", (long)n));	pipelen = 0;	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)		pipelen++;	INTOFF;	jp = makejob(n, pipelen);	prevfd = -1;	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {		prehash(lp->n);		pip[1] = -1;		if (lp->next) {			if (sh_pipe(pip) < 0) {				close(prevfd);				error("Pipe call failed");			}		}		if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {			INTON;			if (prevfd > 0) {				close(0);				copyfd(prevfd, 0);				close(prevfd);			}			if (pip[1] >= 0) {				close(pip[0]);				if (pip[1] != 1) {					close(1);					copyfd(pip[1], 1);					close(pip[1]);				}			}			evaltree(lp->n, EV_EXIT);		}		if (prevfd >= 0)			close(prevfd);		prevfd = pip[0];		close(pip[1]);	}	if (n->npipe.backgnd == 0) {		exitstatus = waitforjob(jp);		TRACE(("evalpipe:  job done exit status %d\n", exitstatus));	}	INTON;}/* * Execute a command inside back quotes.  If it's a builtin command, we * want to save its output in a block obtained from malloc.  Otherwise * we fork off a subprocess and get the output of the command via a pipe. * Should be called with interrupts off. */voidevalbackcmd(union node *n, struct backcmd *result){	int pip[2];	struct job *jp;	struct stackmark smark;		/* unnecessary */	setstackmark(&smark);	result->fd = -1;	result->buf = NULL;	result->nleft = 0;	result->jp = NULL;	if (n == NULL) {		goto out;	}#ifdef notyet	/*	 * For now we disable executing builtins in the same	 * context as the shell, because we are not keeping	 * enough state to recover from changes that are	 * supposed only to affect subshells. eg. echo "`cd /`"	 */	if (n->type == NCMD) {		exitstatus = oexitstatus;		evalcommand(n, EV_BACKCMD, result);	} else#endif	{		INTOFF;		if (sh_pipe(pip) < 0)			error("Pipe call failed");		jp = makejob(n, 1);		if (forkshell(jp, n, FORK_NOJOB) == 0) {			FORCEINTON;			close(pip[0]);			if (pip[1] != 1) {				close(1);				copyfd(pip[1], 1);				close(pip[1]);			}			eflag = 0;			evaltree(n, EV_EXIT);			/* NOTREACHED */		}		close(pip[1]);		result->fd = pip[0];		result->jp = jp;		INTON;	}out:	popstackmark(&smark);	TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",		result->fd, result->buf, result->nleft, result->jp));}static const char *syspath(void){	static char *sys_path = NULL;#ifndef __linux__    	static int mib[] = {CTL_USER, USER_CS_PATH};#endif	static char def_path[] = "PATH=/usr/bin:/bin:/usr/sbin:/sbin";	if (sys_path == NULL) {#ifndef __linux__		size_t len;		if (sysctl(mib, 2, 0, &len, 0, 0) != -1 &&		    (sys_path = ckmalloc(len + 5)) != NULL &&		    sysctl(mib, 2, sys_path + 5, &len, 0, 0) != -1) {			memcpy(sys_path, "PATH=", 5);		} else#endif		{			ckfree(sys_path);			/* something to keep things happy */			sys_path = def_path;		}	}

⌨️ 快捷键说明

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