• 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 

Generated on Wed Sep 8 2010 21:50:20 for Ruby by  doxygen 1.7.1