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

📄 exec.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1980, 1991, 1993 *	The Regents of the University of California.  All rights reserved. * * 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. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. 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. */#ifndef lintstatic char sccsid[] = "@(#)exec.c	8.1 (Berkeley) 5/31/93";#endif /* not lint */#include <sys/types.h>#include <sys/param.h>#include <dirent.h>#include <fcntl.h>#include <sys/stat.h>#include <errno.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#if __STDC__# include <stdarg.h>#else# include <varargs.h>#endif #include "csh.h"#include "extern.h"/* * System level search and execute of a command.  We look in each directory * for the specified command name.  If the name contains a '/' then we * execute only the full path name.  If there is no search path then we * execute only full path names. */extern char **environ;/* * As we search for the command we note the first non-trivial error * message for presentation to the user.  This allows us often * to show that a file has the wrong mode/no access when the file * is not in the last component of the search path, so we must * go on after first detecting the error. */static char *exerr;		/* Execution error message */static Char *expath;		/* Path for exerr *//* * Xhash is an array of HSHSIZ bits (HSHSIZ / 8 chars), which are used * to hash execs.  If it is allocated (havhash true), then to tell * whether ``name'' is (possibly) present in the i'th component * of the variable path, you look at the bit in xhash indexed by * hash(hashname("name"), i).  This is setup automatically * after .login is executed, and recomputed whenever ``path'' is * changed. * The two part hash function is designed to let texec() call the * more expensive hashname() only once and the simple hash() several * times (once for each path component checked). * Byte size is assumed to be 8. */#define	HSHSIZ		8192	/* 1k bytes */#define HSHMASK		(HSHSIZ - 1)#define HSHMUL		243static char xhash[HSHSIZ / 8];#define hash(a, b)	(((a) * HSHMUL + (b)) & HSHMASK)#define bit(h, b)	((h)[(b) >> 3] & 1 << ((b) & 7))	/* bit test */#define bis(h, b)	((h)[(b) >> 3] |= 1 << ((b) & 7))	/* bit set */static int hits, misses;/* Dummy search path for just absolute search when no path */static Char *justabs[] = {STRNULL, 0};static void	pexerr __P((void));static void	texec __P((Char *, Char **));static int	hashname __P((Char *));static void 	tellmewhat __P((struct wordent *));static int	executable __P((Char *, Char *, bool));static int	iscommand __P((Char *));void/*ARGSUSED*/doexec(v, t)    Char **v;    struct command *t;{    register Char *dp, **pv, **av, *sav;    register struct varent *pathv;    register bool slash;    register int hashval = 0, hashval1, i;    Char   *blk[2];    /*     * Glob the command name. We will search $path even if this does something,     * as in sh but not in csh.  One special case: if there is no PATH, then we     * execute only commands which start with '/'.     */    blk[0] = t->t_dcom[0];    blk[1] = 0;    gflag = 0, tglob(blk);    if (gflag) {	pv = globall(blk);	if (pv == 0) {	    setname(vis_str(blk[0]));	    stderror(ERR_NAME | ERR_NOMATCH);	}	gargv = 0;    }    else	pv = saveblk(blk);    trim(pv);    exerr = 0;    expath = Strsave(pv[0]);    Vexpath = expath;    pathv = adrof(STRpath);    if (pathv == 0 && expath[0] != '/') {	blkfree(pv);	pexerr();    }    slash = any(short2str(expath), '/');    /*     * Glob the argument list, if necessary. Otherwise trim off the quote bits.     */    gflag = 0;    av = &t->t_dcom[1];    tglob(av);    if (gflag) {	av = globall(av);	if (av == 0) {	    blkfree(pv);	    setname(vis_str(expath));	    stderror(ERR_NAME | ERR_NOMATCH);	}	gargv = 0;    }    else	av = saveblk(av);    blkfree(t->t_dcom);    t->t_dcom = blkspl(pv, av);    xfree((ptr_t) pv);    xfree((ptr_t) av);    av = t->t_dcom;    trim(av);    if (*av == NULL || **av == '\0')	pexerr();    xechoit(av);		/* Echo command if -x */    /*     * Since all internal file descriptors are set to close on exec, we don't     * need to close them explicitly here.  Just reorient ourselves for error     * messages.     */    SHIN = 0;    SHOUT = 1;    SHERR = 2;    OLDSTD = 0;    /*     * We must do this AFTER any possible forking (like `foo` in glob) so that     * this shell can still do subprocesses.     */    (void) sigsetmask((sigset_t) 0);    /*     * If no path, no words in path, or a / in the filename then restrict the     * command search.     */    if (pathv == 0 || pathv->vec[0] == 0 || slash)	pv = justabs;    else	pv = pathv->vec;    sav = Strspl(STRslash, *av);/* / command name for postpending */    Vsav = sav;    if (havhash)	hashval = hashname(*av);    i = 0;    hits++;    do {	/*	 * Try to save time by looking at the hash table for where this command	 * could be.  If we are doing delayed hashing, then we put the names in	 * one at a time, as the user enters them.  This is kinda like Korn	 * Shell's "tracked aliases".	 */	if (!slash && pv[0][0] == '/' && havhash) {	    hashval1 = hash(hashval, i);	    if (!bit(xhash, hashval1))		goto cont;	}	if (pv[0][0] == 0 || eq(pv[0], STRdot))	/* don't make ./xxx */	    texec(*av, av);	else {	    dp = Strspl(*pv, sav);	    Vdp = dp;	    texec(dp, av);	    Vdp = 0;	    xfree((ptr_t) dp);	}	misses++;cont:	pv++;	i++;    } while (*pv);    hits--;    Vsav = 0;    xfree((ptr_t) sav);    pexerr();}static voidpexerr(){    /* Couldn't find the damn thing */    if (expath) {	setname(vis_str(expath));	Vexpath = 0;	xfree((ptr_t) expath);	expath = 0;    }    else	setname("");    if (exerr)	stderror(ERR_NAME | ERR_STRING, exerr);    stderror(ERR_NAME | ERR_COMMAND);}/* * Execute command f, arg list t. * Record error message if not found. * Also do shell scripts here. */static voidtexec(sf, st)    Char   *sf;    register Char **st;{    register char **t;    register char *f;    register struct varent *v;    register Char **vp;    Char   *lastsh[2];    int     fd;    unsigned char c;    Char   *st0, **ost;    /* The order for the conversions is significant */    t = short2blk(st);    f = short2str(sf);    Vt = t;    errno = 0;			/* don't use a previous error */    (void) execve(f, t, environ);    Vt = 0;    blkfree((Char **) t);    switch (errno) {    case ENOEXEC:	/*	 * From: casper@fwi.uva.nl (Casper H.S. Dik) If we could not execute	 * it, don't feed it to the shell if it looks like a binary!	 */	if ((fd = open(f, O_RDONLY)) != -1) {	    if (read(fd, (char *) &c, 1) == 1) {		if (!Isprint(c) && (c != '\n' && c != '\t')) {		    (void) close(fd);		    /*		     * We *know* what ENOEXEC means.		     */		    stderror(ERR_ARCH, f, strerror(errno));		}	    }#ifdef _PATH_BSHELL	    else		c = '#';#endif	    (void) close(fd);	}	/*	 * If there is an alias for shell, then put the words of the alias in	 * front of the argument list replacing the command name. Note no	 * interpretation of the words at this point.	 */	v = adrof1(STRshell, &aliases);	if (v == 0) {	    vp = lastsh;	    vp[0] = adrof(STRshell) ? value(STRshell) : STR_SHELLPATH;	    vp[1] = NULL;#ifdef _PATH_BSHELL	    if (fd != -1 && c != '#')		vp[0] = STR_BSHELL;#endif	}	else	    vp = v->vec;	st0 = st[0];	st[0] = sf;	ost = st;	st = blkspl(vp, st);	/* Splice up the new arglst */	ost[0] = st0;	sf = *st;	/* The order for the conversions is significant */	t = short2blk(st);	f = short2str(sf);	xfree((ptr_t) st);	Vt = t;	(void) execve(f, t, environ);	Vt = 0;	blkfree((Char **) t);	/* The sky is falling, the sky is falling! */    case ENOMEM:	stderror(ERR_SYSTEM, f, strerror(errno));    case ENOENT:	break;    default:	if (exerr == 0) {	    exerr = strerror(errno);	    if (expath)		xfree((ptr_t) expath);	    expath = Strsave(sf);	    Vexpath = expath;	}    }}/*ARGSUSED*/voidexecash(t, kp)    Char  **t;    register struct command *kp;{    int     saveIN, saveOUT, saveDIAG, saveSTD;    int     oSHIN;    int     oSHOUT;    int     oSHERR;    int     oOLDSTD;    jmp_buf osetexit;

⌨️ 快捷键说明

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