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