diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-02-24 00:55:03 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-02-24 00:55:03 +0000 |
commit | 9afa9ba9673370d98d433ba24c06282ca8f1e5e8 (patch) | |
tree | 09db74238be5826797c359dbd5d2d5ca411c1a4b /dln_find.c | |
parent | 5fe5eb264d79e4ffa7c77b1a09d1de69469fffb9 (diff) | |
download | ruby-9afa9ba9673370d98d433ba24c06282ca8f1e5e8.tar.gz |
* dln_find.c: split from dln.c.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26746 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'dln_find.c')
-rw-r--r-- | dln_find.c | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/dln_find.c b/dln_find.c new file mode 100644 index 0000000000..728ace86d3 --- /dev/null +++ b/dln_find.c @@ -0,0 +1,304 @@ +/********************************************************************** + + dln.c - + + $Author$ + created at: Tue Jan 18 17:05:06 JST 1994 + + Copyright (C) 1993-2007 Yukihiro Matsumoto + +**********************************************************************/ + +#ifdef RUBY_EXPORT +#include "ruby/ruby.h" +#define dln_notimplement rb_notimplement +#define dln_memerror rb_memerror +#define dln_exit rb_exit +#define dln_loaderror rb_loaderror +#else +#define dln_notimplement --->>> dln not implemented <<<--- +#define dln_memerror abort +#define dln_exit exit +static void dln_loaderror(const char *format, ...); +#endif +#include "dln.h" + +#ifdef HAVE_STDLIB_H +# include <stdlib.h> +#endif + +#ifdef USE_DLN_A_OUT +char *dln_argv0; +#endif + +#if defined(HAVE_ALLOCA_H) +#include <alloca.h> +#endif + +#ifdef HAVE_STRING_H +# include <string.h> +#else +# include <strings.h> +#endif + +#ifndef xmalloc +void *xmalloc(); +void *xcalloc(); +void *xrealloc(); +#endif + +#define free(x) xfree(x) + +#include <stdio.h> +#if defined(_WIN32) +#include "missing/file.h" +#endif +#include <sys/types.h> +#include <sys/stat.h> + +#ifndef S_ISDIR +# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR) +#endif + +#ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> +#endif +#ifndef MAXPATHLEN +# define MAXPATHLEN 1024 +#endif + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#ifndef _WIN32 +char *getenv(); +#endif + +static char *dln_find_1(const char *fname, const char *path, char *buf, size_t size, int exe_flag); + +char * +dln_find_exe_r(const char *fname, const char *path, char *buf, size_t size) +{ + char *envpath = 0; + + if (!path) { + path = getenv(PATH_ENV); + if (path) path = envpath = strdup(path); + } + + if (!path) { +#if defined(_WIN32) + path = "/usr/local/bin;/usr/ucb;/usr/bin;/bin;."; +#else + path = "/usr/local/bin:/usr/ucb:/usr/bin:/bin:."; +#endif + } + buf = dln_find_1(fname, path, buf, size, 1); + if (envpath) free(envpath); + return buf; +} + +char * +dln_find_file_r(const char *fname, const char *path, char *buf, size_t size) +{ + if (!path) path = "."; + return dln_find_1(fname, path, buf, size, 0); +} + +static char fbuf[MAXPATHLEN]; + +char * +dln_find_exe(const char *fname, const char *path) +{ + return dln_find_exe_r(fname, path, fbuf, sizeof(fbuf)); +} + +char * +dln_find_file(const char *fname, const char *path) +{ + return dln_find_file_r(fname, path, fbuf, sizeof(fbuf)); +} + +static char * +dln_find_1(const char *fname, const char *path, char *fbuf, size_t size, + int exe_flag /* non 0 if looking for executable. */) +{ + register const char *dp; + register const char *ep; + register char *bp; + struct stat st; + size_t i, fspace; +#ifdef DOSISH + static const char extension[][5] = { + EXECUTABLE_EXTS, + }; + size_t j; + int is_abs = 0, has_path = 0; + const char *ext = 0; +#endif + const char *p = fname; + + static const char pathname_too_long[] = "openpath: pathname too long (ignored)\n\ +\tDirectory \"%.*s\"\n\tFile \"%s\"\n"; +#define PATHNAME_TOO_LONG() fprintf(stderr, pathname_too_long, (int)(bp - fbuf), fbuf, fname) + +#define RETURN_IF(expr) if (expr) return (char *)fname; + + RETURN_IF(!fname); +#ifdef DOSISH +# ifndef CharNext +# define CharNext(p) ((p)+1) +# endif +# ifdef DOSISH_DRIVE_LETTER + if (((p[0] | 0x20) - 'a') < 26 && p[1] == ':') { + p += 2; + is_abs = 1; + } +# endif + switch (*p) { + case '/': case '\\': + is_abs = 1; + p++; + } + has_path = is_abs; + while (*p) { + switch (*p) { + case '/': case '\\': + has_path = 1; + ext = 0; + p++; + break; + case '.': + ext = p; + p++; + break; + default: + p = CharNext(p); + } + } + if (ext) { + for (j = 0; STRCASECMP(ext, extension[j]); ) { + if (++j == sizeof(extension) / sizeof(extension[0])) { + ext = 0; + break; + } + } + } + ep = bp = 0; + if (!exe_flag) { + RETURN_IF(is_abs); + } + else if (has_path) { + RETURN_IF(ext); + i = p - fname; + if (i + 1 > size) goto toolong; + fspace = size - i - 1; + bp = fbuf; + ep = p; + memcpy(fbuf, fname, i + 1); + goto needs_extension; + } + p = fname; +#endif + + if (*p == '.' && *++p == '.') ++p; + RETURN_IF(*p == '/'); + RETURN_IF(exe_flag && strchr(fname, '/')); + +#undef RETURN_IF + + for (dp = path;; dp = ++ep) { + register size_t l; + + /* extract a component */ + ep = strchr(dp, PATH_SEP[0]); + if (ep == NULL) + ep = dp+strlen(dp); + + /* find the length of that component */ + l = ep - dp; + bp = fbuf; + fspace = size - 2; + if (l > 0) { + /* + ** If the length of the component is zero length, + ** start from the current directory. If the + ** component begins with "~", start from the + ** user's $HOME environment variable. Otherwise + ** take the path literally. + */ + + if (*dp == '~' && (l == 1 || +#if defined(DOSISH) + dp[1] == '\\' || +#endif + dp[1] == '/')) { + char *home; + + home = getenv("HOME"); + if (home != NULL) { + i = strlen(home); + if (fspace < i) + goto toolong; + fspace -= i; + memcpy(bp, home, i); + bp += i; + } + dp++; + l--; + } + if (l > 0) { + if (fspace < l) + goto toolong; + fspace -= l; + memcpy(bp, dp, l); + bp += l; + } + + /* add a "/" between directory and filename */ + if (ep[-1] != '/') + *bp++ = '/'; + } + + /* now append the file name */ + i = strlen(fname); + if (fspace < i) { + toolong: + PATHNAME_TOO_LONG(); + goto next; + } + fspace -= i; + memcpy(bp, fname, i + 1); + +#if defined(DOSISH) + if (exe_flag && !ext) { + needs_extension: + for (j = 0; j < sizeof(extension) / sizeof(extension[0]); j++) { + if (fspace < strlen(extension[j])) { + PATHNAME_TOO_LONG(); + continue; + } + strlcpy(bp + i, extension[j], fspace); + if (stat(fbuf, &st) == 0) + return fbuf; + } + goto next; + } +#endif /* _WIN32 or __EMX__ */ + + if (stat(fbuf, &st) == 0) { + if (exe_flag == 0) return fbuf; + /* looking for executable */ + if (!S_ISDIR(st.st_mode) && eaccess(fbuf, X_OK) == 0) + return fbuf; + } + next: + /* if not, and no other alternatives, life is bleak */ + if (*ep == '\0') { + return NULL; + } + + /* otherwise try the next component in the search path */ + } +} |