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

📄 execlp.c

📁 操作系统源代码
💻 C
字号:
/* execlp(3) and execvp(3) * * Author: Terrence W. Holm      July 1988 *//* FIXES - Dec 1989 - Jan 1990 Bruce Evans. *	 - Don't use search path when file name contains a '/' *anywhere*. *	 - Invoke sh(1) on command files. *	 - Use PATH_MAX and check strings fit in buffer. *	 - Use stdargs, with the unjustified assumption that va_start() turns *	   the arg list into a char *[].  Strictly, the arg list should be *	   copied, "wasting" up to ARG_MAX bytes. *//*  Execlp(3) and execvp(3) are like execl(3) and execv(3), *  except that they use the environment variable $PATH as *  a search list of possible locations for the executable *  file, if <file> does not contain a '/', and they attempt *  to run non-binary executable files using sh(1). * *  The path search list is a list of directory names separated *  by ':'s. If a colon appears at the beginning or end of the *  list, or two appear together, then an empty prefix is tried. *  If $PATH is not in the environment, it defaults to "". * *  For example, if <file> is "ls", and the $PATH is *  ":/usr/local/bin:/bin:/usr/bin", then  ./ls, *  /usr/local/bin/ls, /bin/ls and /usr/bin/ls are tried until *  an exectable one is found. If the direct attempt to exec it *  fails, the arg list is modified to begin with "sh" and the *  absolute name of <file>, and an exec of /bin/sh is tried. *  If this fails, no further attempts are made. * *  This function only returns after an error.  It returns -1 *  and sets errno like execv(). */#include <sys/types.h>#include <lib.h>#include <errno.h>#include <limits.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <stdarg.h>#undef NULL#define NULL 0			/* kludge for ACK not understanding void * */#define MAX_NUM_ARGS 512	/* maximum number of arguments to execvp */extern char **environ;		/* environment pointer */#ifdef _ANSIint execlp(const char *file, const char *arg, ...)#elseint execlp(file)char *file;#endif{  register va_list argp;  register int result;  va_start(argp, file);  result = execvp(file, (char **) argp);  va_end(argp);  return(result);}#ifdef _ANSIint execvp(const char *file, char *const argv[])#elseint execvp(file, argv)char *file;char **argv;#endif{  int i, best_errno;  char **envtop;  size_t flength;  char *searchpath;  size_t slength;  char *split;  char execpath[PATH_MAX + 1];  char *arg2[MAX_NUM_ARGS + 3];	/* place to copy argv */  /* POSIX requires argv to be immutable.  Unfortunately, we have to change it   * during execution.  To keep POSIX happy, a copy is made and the copy    * changed.  The question arises: how big should the copy be?  Allocating   * space dynamically requires using malloc, which itself takes up a lot   * of space.  The solution chosen here is to limit the number of arguments   * to MAX_NUM_ARGS and set this value fairly high.  This solution is simpler   * and is probably adequate.  Only programs with huge numbers of very short   * arguments will get an error (if the arguments are large, ARG_MAX will   * be exceeded.   */  if (strchr(file, '/') != NULL || (searchpath = getenv("PATH")) == NULL)	searchpath = "";  flength = strlen(file);  best_errno = ENOENT;  while (1) {	split = strchr(searchpath, ':');	if (split == NULL)		slength = strlen(searchpath);	else		slength = split - searchpath;	if (slength + flength >= sizeof execpath - 2) {		errno = ENAMETOOLONG;	/* too bad if premature */		return(-1);	}	strncpy(execpath, searchpath, slength);	if (slength != 0) execpath[slength++] = '/';	strcpy(execpath + slength, file);	/* Don't try to avoid execv() for non-existent files, since the Minix	 * shell doesn't, and it is not clear whether access() or stat() work	 * right when this code is set-uid.	 */	execv(execpath, argv);	switch (errno) {	    case EACCES:		best_errno = errno;	/* more useful than ENOENT */	    case ENOENT:		if (split == NULL) {			/* No more path components. */			errno = best_errno;			return(-1);		}		searchpath = split + 1;	/* try next in path */		break;	    case ENOEXEC:		/* Assume a command file and invoke sh(1) on it.  Replace arg0		 * (which is usually a short name for the command) by the full		 * name of the command file.		 */		/* Copy the arg pointers from argv to arg2,  moving them up by		 * 1, overlaying the assumed NULL at the end, to make room 		 * for "sh" at the beginning.		 */		i = 0;		if (argv != NULL)		{			while (argv[i] != 0) {				if (i >= MAX_NUM_ARGS) {					/* Copy failed.  Not enough room. */					errno = ENOEXEC;					return(-1);				}				arg2[i + 1] = argv[i];				i++;			}		}		arg2[0] = "sh";		/* exec the shell */		arg2[1] = execpath;	/* full path */		arg2[i + 1] = NULL;	/* terminator */		/* Count the environment pointers. */		for (envtop = environ; *envtop != NULL; ) envtop++;		/* Try only /bin/sh, like the Minix shell.  Lose if the user		 * has a different shell or the command has #!another/shell.		 */		__execve("/bin/sh", arg2, environ, i + 1, (int)(envtop - environ));		/* Oops, no shell?   Give up. */		errno = ENOEXEC;		return(-1);	    default:		return(-1);	/* probably  ENOMEM or E2BIG */	}  }}

⌨️ 快捷键说明

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