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