Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# dln_find.c

Go to the documentation of this file.

    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