exec.c

来自「Android 一些工具」· C语言 代码 · 共 1,064 行 · 第 1/2 页

C
1,064
字号
		}		while (stat(fullname, &statb) < 0) {#ifdef SYSV			if (errno == EINTR)				continue;#endif			if (errno != ENOENT && errno != ENOTDIR)				e = errno;			goto loop;		}		e = EACCES;	/* if we fail, this will be the error */		if (!S_ISREG(statb.st_mode))			goto loop;		if (pathopt) {		/* this is a %func directory */			if (act & DO_NOFUNC)				goto loop;			stalloc(strlen(fullname) + 1);			readcmdfile(fullname);			if ((cmdp = cmdlookup(name, 0)) == NULL ||			    cmdp->cmdtype != CMDFUNCTION)				error("%s not defined in %s", name, fullname);			stunalloc(fullname);			goto success;		}#ifdef notdef		/* XXX this code stops root executing stuff, and is buggy		   if you need a group from the group list. */		if (statb.st_uid == geteuid()) {			if ((statb.st_mode & 0100) == 0)				goto loop;		} else if (statb.st_gid == getegid()) {			if ((statb.st_mode & 010) == 0)				goto loop;		} else {			if ((statb.st_mode & 01) == 0)				goto loop;		}#endif		TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));		INTOFF;		if (act & DO_ALTPATH) {			stalloc(strlen(fullname) + 1);			cmdp = &loc_cmd;		} else			cmdp = cmdlookup(name, 1);		cmdp->cmdtype = CMDNORMAL;		cmdp->param.index = idx;		INTON;		goto success;	}	/* We failed.  If there was an entry for this command, delete it */	if (cmdp)		delete_cmd_entry();	if (act & DO_ERR)		outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC));	entry->cmdtype = CMDUNKNOWN;	return;builtin_success:	INTOFF;	if (act & DO_ALTPATH)		cmdp = &loc_cmd;	else		cmdp = cmdlookup(name, 1);	if (cmdp->cmdtype == CMDFUNCTION)		/* DO_NOFUNC must have been set */		cmdp = &loc_cmd;	cmdp->cmdtype = CMDBUILTIN;	cmdp->param.bltin = bltin;	INTON;success:	cmdp->rehash = 0;	entry->cmdtype = cmdp->cmdtype;	entry->u = cmdp->param;}/* * Search the table of builtin commands. */int(*find_builtin(name))(int, char **)	char *name;{	const struct builtincmd *bp;	for (bp = builtincmd ; bp->name ; bp++) {		if (*bp->name == *name && equal(bp->name, name))			return bp->builtin;	}	return 0;}int(*find_splbltin(name))(int, char **)	char *name;{	const struct builtincmd *bp;	for (bp = splbltincmd ; bp->name ; bp++) {		if (*bp->name == *name && equal(bp->name, name))			return bp->builtin;	}	return 0;}/* * At shell startup put special builtins into hash table. * ensures they are executed first (see posix). * We stop functions being added with the same name * (as they are impossible to call) */voidhash_special_builtins(void){	const struct builtincmd *bp;	struct tblentry *cmdp;	for (bp = splbltincmd ; bp->name ; bp++) {		cmdp = cmdlookup(bp->name, 1);		cmdp->cmdtype = CMDSPLBLTIN;		cmdp->param.bltin = bp->builtin;	}}/* * Called when a cd is done.  Marks all commands so the next time they * are executed they will be rehashed. */voidhashcd(void){	struct tblentry **pp;	struct tblentry *cmdp;	for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {		for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {			if (cmdp->cmdtype == CMDNORMAL			 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))				cmdp->rehash = 1;		}	}}/* * Fix command hash table when PATH changed. * Called before PATH is changed.  The argument is the new value of PATH; * pathval() still returns the old value at this point. * Called with interrupts off. */voidchangepath(const char *newval){	const char *old, *new;	int idx;	int firstchange;	int bltin;	old = pathval();	new = newval;	firstchange = 9999;	/* assume no change */	idx = 0;	bltin = -1;	for (;;) {		if (*old != *new) {			firstchange = idx;			if ((*old == '\0' && *new == ':')			 || (*old == ':' && *new == '\0'))				firstchange++;			old = new;	/* ignore subsequent differences */		}		if (*new == '\0')			break;		if (*new == '%' && bltin < 0 && prefix("builtin", new + 1))			bltin = idx;		if (*new == ':') {			idx++;		}		new++, old++;	}	if (builtinloc < 0 && bltin >= 0)		builtinloc = bltin;		/* zap builtins */	if (builtinloc >= 0 && bltin < 0)		firstchange = 0;	clearcmdentry(firstchange);	builtinloc = bltin;}/* * Clear out command entries.  The argument specifies the first entry in * PATH which has changed. */STATIC voidclearcmdentry(int firstchange){	struct tblentry **tblp;	struct tblentry **pp;	struct tblentry *cmdp;	INTOFF;	for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {		pp = tblp;		while ((cmdp = *pp) != NULL) {			if ((cmdp->cmdtype == CMDNORMAL &&			     cmdp->param.index >= firstchange)			 || (cmdp->cmdtype == CMDBUILTIN &&			     builtinloc >= firstchange)) {				*pp = cmdp->next;				ckfree(cmdp);			} else {				pp = &cmdp->next;			}		}	}	INTON;}/* * Delete all functions. */#ifdef mkinitMKINIT void deletefuncs(void);MKINIT void hash_special_builtins(void);INIT {	hash_special_builtins();}SHELLPROC {	deletefuncs();}#endifvoiddeletefuncs(void){	struct tblentry **tblp;	struct tblentry **pp;	struct tblentry *cmdp;	INTOFF;	for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {		pp = tblp;		while ((cmdp = *pp) != NULL) {			if (cmdp->cmdtype == CMDFUNCTION) {				*pp = cmdp->next;				freefunc(cmdp->param.func);				ckfree(cmdp);			} else {				pp = &cmdp->next;			}		}	}	INTON;}/* * Locate a command in the command hash table.  If "add" is nonzero, * add the command to the table if it is not already present.  The * variable "lastcmdentry" is set to point to the address of the link * pointing to the entry, so that delete_cmd_entry can delete the * entry. */struct tblentry **lastcmdentry;STATIC struct tblentry *cmdlookup(const char *name, int add){	int hashval;	const char *p;	struct tblentry *cmdp;	struct tblentry **pp;	p = name;	hashval = *p << 4;	while (*p)		hashval += *p++;	hashval &= 0x7FFF;	pp = &cmdtable[hashval % CMDTABLESIZE];	for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {		if (equal(cmdp->cmdname, name))			break;		pp = &cmdp->next;	}	if (add && cmdp == NULL) {		INTOFF;		cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB					+ strlen(name) + 1);		cmdp->next = NULL;		cmdp->cmdtype = CMDUNKNOWN;		cmdp->rehash = 0;		strcpy(cmdp->cmdname, name);		INTON;	}	lastcmdentry = pp;	return cmdp;}/* * Delete the command entry returned on the last lookup. */STATIC voiddelete_cmd_entry(void){	struct tblentry *cmdp;	INTOFF;	cmdp = *lastcmdentry;	*lastcmdentry = cmdp->next;	ckfree(cmdp);	INTON;}#ifdef notdefvoidgetcmdentry(char *name, struct cmdentry *entry){	struct tblentry *cmdp = cmdlookup(name, 0);	if (cmdp) {		entry->u = cmdp->param;		entry->cmdtype = cmdp->cmdtype;	} else {		entry->cmdtype = CMDUNKNOWN;		entry->u.index = 0;	}}#endif/* * Add a new command entry, replacing any existing command entry for * the same name - except special builtins. */STATIC voidaddcmdentry(char *name, struct cmdentry *entry){	struct tblentry *cmdp;	INTOFF;	cmdp = cmdlookup(name, 1);	if (cmdp->cmdtype != CMDSPLBLTIN) {		if (cmdp->cmdtype == CMDFUNCTION) {			freefunc(cmdp->param.func);		}		cmdp->cmdtype = entry->cmdtype;		cmdp->param = entry->u;	}	INTON;}/* * Define a shell function. */voiddefun(char *name, union node *func){	struct cmdentry entry;	INTOFF;	entry.cmdtype = CMDFUNCTION;	entry.u.func = copyfunc(func);	addcmdentry(name, &entry);	INTON;}/* * Delete a function if it exists. */intunsetfunc(char *name){	struct tblentry *cmdp;	if ((cmdp = cmdlookup(name, 0)) != NULL &&	    cmdp->cmdtype == CMDFUNCTION) {		freefunc(cmdp->param.func);		delete_cmd_entry();		return (0);	}	return (1);}/* * Locate and print what a word is... * also used for 'command -[v|V]' */inttypecmd(int argc, char **argv){	struct cmdentry entry;	struct tblentry *cmdp;	char * const *pp;	struct alias *ap;	int err = 0;	char *arg;	int c;	int V_flag = 0;	int v_flag = 0;	int p_flag = 0;	while ((c = nextopt("vVp")) != 0) {		switch (c) {		case 'v': v_flag = 1; break;		case 'V': V_flag = 1; break;		case 'p': p_flag = 1; break;		}	}	if (p_flag && (v_flag || V_flag))		error("cannot specify -p with -v or -V");	while ((arg = *argptr++)) {		if (!v_flag)			out1str(arg);		/* First look at the keywords */		for (pp = parsekwd; *pp; pp++)			if (**pp == *arg && equal(*pp, arg))				break;		if (*pp) {			if (v_flag)				err = 1;			else				out1str(" is a shell keyword\n");			continue;		}		/* Then look at the aliases */		if ((ap = lookupalias(arg, 1)) != NULL) {			if (!v_flag)				out1fmt(" is an alias for \n");			out1fmt("%s\n", ap->val);			continue;		}		/* Then check if it is a tracked alias */		if ((cmdp = cmdlookup(arg, 0)) != NULL) {			entry.cmdtype = cmdp->cmdtype;			entry.u = cmdp->param;		} else {			/* Finally use brute force */			find_command(arg, &entry, DO_ABS, pathval());		}		switch (entry.cmdtype) {		case CMDNORMAL: {			if (strchr(arg, '/') == NULL) {				const char *path = pathval();				char *name;				int j = entry.u.index;				do {					name = padvance(&path, arg);					stunalloc(name);				} while (--j >= 0);				if (!v_flag)					out1fmt(" is%s ",					    cmdp ? " a tracked alias for" : "");				out1fmt("%s\n", name);			} else {				if (access(arg, X_OK) == 0) {					if (!v_flag)						out1fmt(" is ");					out1fmt("%s\n", arg);				} else {					if (!v_flag)						out1fmt(": %s\n",						    strerror(errno));					else						err = 126;				}			} 			break;		}		case CMDFUNCTION:			if (!v_flag)				out1str(" is a shell function\n");			else				out1fmt("%s\n", arg);			break;		case CMDBUILTIN:			if (!v_flag)				out1str(" is a shell builtin\n");			else				out1fmt("%s\n", arg);			break;		case CMDSPLBLTIN:			if (!v_flag)				out1str(" is a special shell builtin\n");			else				out1fmt("%s\n", arg);			break;		default:			if (!v_flag)				out1str(": not found\n");			err = 127;			break;		}	}	return err;}

⌨️ 快捷键说明

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