![]() |
|
|||
0001 /* Copyright (C) 2006 by Paolo Giarrusso - modified from glibc' execvp.c. 0002 Original copyright notice follows: 0003 0004 Copyright (C) 1991,92,1995-99,2002,2004 Free Software Foundation, Inc. 0005 This file is part of the GNU C Library. 0006 0007 The GNU C Library is free software; you can redistribute it and/or 0008 modify it under the terms of the GNU Lesser General Public 0009 License as published by the Free Software Foundation; either 0010 version 2.1 of the License, or (at your option) any later version. 0011 0012 The GNU C Library is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 Lesser General Public License for more details. 0016 0017 You should have received a copy of the GNU Lesser General Public 0018 License along with the GNU C Library; if not, write to the Free 0019 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 0020 02111-1307 USA. */ 0021 #include <unistd.h> 0022 0023 #include <stdbool.h> 0024 #include <stdlib.h> 0025 #include <string.h> 0026 #include <errno.h> 0027 #include <limits.h> 0028 0029 #ifndef TEST 0030 #include <um_malloc.h> 0031 #else 0032 #include <stdio.h> 0033 #define um_kmalloc malloc 0034 #endif 0035 #include <os.h> 0036 0037 /* Execute FILE, searching in the `PATH' environment variable if it contains 0038 no slashes, with arguments ARGV and environment from `environ'. */ 0039 int execvp_noalloc(char *buf, const char *file, char *const argv[]) 0040 { 0041 if (*file == '\0') { 0042 return -ENOENT; 0043 } 0044 0045 if (strchr (file, '/') != NULL) { 0046 /* Don't search when it contains a slash. */ 0047 execv(file, argv); 0048 } else { 0049 int got_eacces; 0050 size_t len, pathlen; 0051 char *name, *p; 0052 char *path = getenv("PATH"); 0053 if (path == NULL) 0054 path = ":/bin:/usr/bin"; 0055 0056 len = strlen(file) + 1; 0057 pathlen = strlen(path); 0058 /* Copy the file name at the top. */ 0059 name = memcpy(buf + pathlen + 1, file, len); 0060 /* And add the slash. */ 0061 *--name = '/'; 0062 0063 got_eacces = 0; 0064 p = path; 0065 do { 0066 char *startp; 0067 0068 path = p; 0069 //Let's avoid this GNU extension. 0070 //p = strchrnul (path, ':'); 0071 p = strchr(path, ':'); 0072 if (!p) 0073 p = strchr(path, '\0'); 0074 0075 if (p == path) 0076 /* Two adjacent colons, or a colon at the beginning or the end 0077 of `PATH' means to search the current directory. */ 0078 startp = name + 1; 0079 else 0080 startp = memcpy(name - (p - path), path, p - path); 0081 0082 /* Try to execute this name. If it works, execv will not return. */ 0083 execv(startp, argv); 0084 0085 /* 0086 if (errno == ENOEXEC) { 0087 } 0088 */ 0089 0090 switch (errno) { 0091 case EACCES: 0092 /* Record the we got a `Permission denied' error. If we end 0093 up finding no executable we can use, we want to diagnose 0094 that we did find one but were denied access. */ 0095 got_eacces = 1; 0096 break; 0097 case ENOENT: 0098 case ESTALE: 0099 case ENOTDIR: 0100 /* Those errors indicate the file is missing or not executable 0101 by us, in which case we want to just try the next path 0102 directory. */ 0103 case ENODEV: 0104 case ETIMEDOUT: 0105 /* Some strange filesystems like AFS return even 0106 stranger error numbers. They cannot reasonably mean 0107 anything else so ignore those, too. */ 0108 case ENOEXEC: 0109 /* We won't go searching for the shell 0110 * if it is not executable - the Linux 0111 * kernel already handles this enough, 0112 * for us. */ 0113 break; 0114 0115 default: 0116 /* Some other error means we found an executable file, but 0117 something went wrong executing it; return the error to our 0118 caller. */ 0119 return -errno; 0120 } 0121 } while (*p++ != '\0'); 0122 0123 /* We tried every element and none of them worked. */ 0124 if (got_eacces) 0125 /* At least one failure was due to permissions, so report that 0126 error. */ 0127 return -EACCES; 0128 } 0129 0130 /* Return the error from the last attempt (probably ENOENT). */ 0131 return -errno; 0132 } 0133 #ifdef TEST 0134 int main(int argc, char**argv) 0135 { 0136 char buf[PATH_MAX]; 0137 int ret; 0138 argc--; 0139 if (!argc) { 0140 os_warn("Not enough arguments\n"); 0141 return 1; 0142 } 0143 argv++; 0144 if (ret = execvp_noalloc(buf, argv[0], argv)) { 0145 errno = -ret; 0146 perror("execvp_noalloc"); 0147 } 0148 return 0; 0149 } 0150 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |