|
Ruby 1.9.2p290(2011-07-09revision32553)
|
00001 /********************************************************************** 00002 00003 dln.c - 00004 00005 $Author: nobu $ 00006 created at: Tue Jan 18 17:05:06 JST 1994 00007 00008 Copyright (C) 1993-2007 Yukihiro Matsumoto 00009 00010 **********************************************************************/ 00011 00012 #ifdef RUBY_EXPORT 00013 #include "ruby/ruby.h" 00014 #define dln_notimplement rb_notimplement 00015 #define dln_memerror rb_memerror 00016 #define dln_exit rb_exit 00017 #define dln_loaderror rb_loaderror 00018 #else 00019 #define dln_notimplement --->>> dln not implemented <<<--- 00020 #define dln_memerror abort 00021 #define dln_exit exit 00022 static void dln_loaderror(const char *format, ...); 00023 #endif 00024 #include "dln.h" 00025 00026 #ifdef HAVE_STDLIB_H 00027 # include <stdlib.h> 00028 #endif 00029 00030 #ifdef USE_DLN_A_OUT 00031 char *dln_argv0; 00032 #endif 00033 00034 #if defined(HAVE_ALLOCA_H) 00035 #include <alloca.h> 00036 #endif 00037 00038 #ifdef HAVE_STRING_H 00039 # include <string.h> 00040 #else 00041 # include <strings.h> 00042 #endif 00043 00044 #ifndef xmalloc 00045 void *xmalloc(); 00046 void *xcalloc(); 00047 void *xrealloc(); 00048 #endif 00049 00050 #define free(x) xfree(x) 00051 00052 #include <stdio.h> 00053 #if defined(_WIN32) 00054 #include "missing/file.h" 00055 #endif 00056 #include <sys/types.h> 00057 #include <sys/stat.h> 00058 00059 #ifndef S_ISDIR 00060 # define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR) 00061 #endif 00062 00063 #ifdef HAVE_SYS_PARAM_H 00064 # include <sys/param.h> 00065 #endif 00066 #ifndef MAXPATHLEN 00067 # define MAXPATHLEN 1024 00068 #endif 00069 00070 #ifdef HAVE_UNISTD_H 00071 # include <unistd.h> 00072 #endif 00073 00074 #ifndef _WIN32 00075 char *getenv(); 00076 #endif 00077 00078 static char *dln_find_1(const char *fname, const char *path, char *buf, size_t size, int exe_flag); 00079 00080 char * 00081 dln_find_exe_r(const char *fname, const char *path, char *buf, size_t size) 00082 { 00083 char *envpath = 0; 00084 00085 if (!path) { 00086 path = getenv(PATH_ENV); 00087 if (path) path = envpath = strdup(path); 00088 } 00089 00090 if (!path) { 00091 #if defined(_WIN32) 00092 path = "/usr/local/bin;/usr/ucb;/usr/bin;/bin;."; 00093 #else 00094 path = "/usr/local/bin:/usr/ucb:/usr/bin:/bin:."; 00095 #endif 00096 } 00097 buf = dln_find_1(fname, path, buf, size, 1); 00098 if (envpath) free(envpath); 00099 return buf; 00100 } 00101 00102 char * 00103 dln_find_file_r(const char *fname, const char *path, char *buf, size_t size) 00104 { 00105 if (!path) path = "."; 00106 return dln_find_1(fname, path, buf, size, 0); 00107 } 00108 00109 static char fbuf[MAXPATHLEN]; 00110 00111 char * 00112 dln_find_exe(const char *fname, const char *path) 00113 { 00114 return dln_find_exe_r(fname, path, fbuf, sizeof(fbuf)); 00115 } 00116 00117 char * 00118 dln_find_file(const char *fname, const char *path) 00119 { 00120 return dln_find_file_r(fname, path, fbuf, sizeof(fbuf)); 00121 } 00122 00123 static char * 00124 dln_find_1(const char *fname, const char *path, char *fbuf, size_t size, 00125 int exe_flag /* non 0 if looking for executable. */) 00126 { 00127 register const char *dp; 00128 register const char *ep; 00129 register char *bp; 00130 struct stat st; 00131 size_t i, fspace; 00132 #ifdef DOSISH 00133 static const char extension[][5] = { 00134 EXECUTABLE_EXTS, 00135 }; 00136 size_t j; 00137 int is_abs = 0, has_path = 0; 00138 const char *ext = 0; 00139 #endif 00140 const char *p = fname; 00141 00142 static const char pathname_too_long[] = "openpath: pathname too long (ignored)\n\ 00143 \tDirectory \"%.*s\"\n\tFile \"%s\"\n"; 00144 #define PATHNAME_TOO_LONG() fprintf(stderr, pathname_too_long, (int)(bp - fbuf), fbuf, fname) 00145 00146 #define RETURN_IF(expr) if (expr) return (char *)fname; 00147 00148 RETURN_IF(!fname); 00149 #ifdef DOSISH 00150 # ifndef CharNext 00151 # define CharNext(p) ((p)+1) 00152 # endif 00153 # ifdef DOSISH_DRIVE_LETTER 00154 if (((p[0] | 0x20) - 'a') < 26 && p[1] == ':') { 00155 p += 2; 00156 is_abs = 1; 00157 } 00158 # endif 00159 switch (*p) { 00160 case '/': case '\\': 00161 is_abs = 1; 00162 p++; 00163 } 00164 has_path = is_abs; 00165 while (*p) { 00166 switch (*p) { 00167 case '/': case '\\': 00168 has_path = 1; 00169 ext = 0; 00170 p++; 00171 break; 00172 case '.': 00173 ext = p; 00174 p++; 00175 break; 00176 default: 00177 p = CharNext(p); 00178 } 00179 } 00180 if (ext) { 00181 for (j = 0; STRCASECMP(ext, extension[j]); ) { 00182 if (++j == sizeof(extension) / sizeof(extension[0])) { 00183 ext = 0; 00184 break; 00185 } 00186 } 00187 } 00188 ep = bp = 0; 00189 if (!exe_flag) { 00190 RETURN_IF(is_abs); 00191 } 00192 else if (has_path) { 00193 RETURN_IF(ext); 00194 i = p - fname; 00195 if (i + 1 > size) goto toolong; 00196 fspace = size - i - 1; 00197 bp = fbuf; 00198 ep = p; 00199 memcpy(fbuf, fname, i + 1); 00200 goto needs_extension; 00201 } 00202 p = fname; 00203 #endif 00204 00205 if (*p == '.' && *++p == '.') ++p; 00206 RETURN_IF(*p == '/'); 00207 RETURN_IF(exe_flag && strchr(fname, '/')); 00208 00209 #undef RETURN_IF 00210 00211 for (dp = path;; dp = ++ep) { 00212 register size_t l; 00213 00214 /* extract a component */ 00215 ep = strchr(dp, PATH_SEP[0]); 00216 if (ep == NULL) 00217 ep = dp+strlen(dp); 00218 00219 /* find the length of that component */ 00220 l = ep - dp; 00221 bp = fbuf; 00222 fspace = size - 2; 00223 if (l > 0) { 00224 /* 00225 ** If the length of the component is zero length, 00226 ** start from the current directory. If the 00227 ** component begins with "~", start from the 00228 ** user's $HOME environment variable. Otherwise 00229 ** take the path literally. 00230 */ 00231 00232 if (*dp == '~' && (l == 1 || 00233 #if defined(DOSISH) 00234 dp[1] == '\\' || 00235 #endif 00236 dp[1] == '/')) { 00237 char *home; 00238 00239 home = getenv("HOME"); 00240 if (home != NULL) { 00241 i = strlen(home); 00242 if (fspace < i) 00243 goto toolong; 00244 fspace -= i; 00245 memcpy(bp, home, i); 00246 bp += i; 00247 } 00248 dp++; 00249 l--; 00250 } 00251 if (l > 0) { 00252 if (fspace < l) 00253 goto toolong; 00254 fspace -= l; 00255 memcpy(bp, dp, l); 00256 bp += l; 00257 } 00258 00259 /* add a "/" between directory and filename */ 00260 if (ep[-1] != '/') 00261 *bp++ = '/'; 00262 } 00263 00264 /* now append the file name */ 00265 i = strlen(fname); 00266 if (fspace < i) { 00267 toolong: 00268 PATHNAME_TOO_LONG(); 00269 goto next; 00270 } 00271 fspace -= i; 00272 memcpy(bp, fname, i + 1); 00273 00274 #if defined(DOSISH) 00275 if (exe_flag && !ext) { 00276 needs_extension: 00277 for (j = 0; j < sizeof(extension) / sizeof(extension[0]); j++) { 00278 if (fspace < strlen(extension[j])) { 00279 PATHNAME_TOO_LONG(); 00280 continue; 00281 } 00282 strlcpy(bp + i, extension[j], fspace); 00283 if (stat(fbuf, &st) == 0) 00284 return fbuf; 00285 } 00286 goto next; 00287 } 00288 #endif /* _WIN32 or __EMX__ */ 00289 00290 if (stat(fbuf, &st) == 0) { 00291 if (exe_flag == 0) return fbuf; 00292 /* looking for executable */ 00293 if (!S_ISDIR(st.st_mode) && eaccess(fbuf, X_OK) == 0) 00294 return fbuf; 00295 } 00296 next: 00297 /* if not, and no other alternatives, life is bleak */ 00298 if (*ep == '\0') { 00299 return NULL; 00300 } 00301 00302 /* otherwise try the next component in the search path */ 00303 } 00304 } 00305
1.7.3