Ruby  1.9.3p448(2013-06-27revision41675)
dln_find.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  dln_find.c -
4 
5  $Author: nobu $
6  created at: Tue Jan 18 17:05:06 JST 1994
7 
8  Copyright (C) 1993-2007 Yukihiro Matsumoto
9 
10 **********************************************************************/
11 
12 #ifdef RUBY_EXPORT
13 #include "ruby/ruby.h"
14 #define dln_notimplement rb_notimplement
15 #define dln_memerror rb_memerror
16 #define dln_exit rb_exit
17 #define dln_loaderror rb_loaderror
18 #define dln_warning rb_warning
19 #define dln_warning_arg
20 #else
21 #define dln_notimplement --->>> dln not implemented <<<---
22 #define dln_memerror abort
23 #define dln_exit exit
24 #define dln_warning fprintf
25 #define dln_warning_arg stderr,
26 static void dln_loaderror(const char *format, ...);
27 #endif
28 #include "dln.h"
29 
30 #ifdef HAVE_STDLIB_H
31 # include <stdlib.h>
32 #endif
33 
34 #ifdef USE_DLN_A_OUT
35 char *dln_argv0;
36 #endif
37 
38 #if defined(HAVE_ALLOCA_H)
39 #include <alloca.h>
40 #endif
41 
42 #ifdef HAVE_STRING_H
43 # include <string.h>
44 #else
45 # include <strings.h>
46 #endif
47 
48 #ifndef xmalloc
49 void *xmalloc();
50 void *xcalloc();
51 void *xrealloc();
52 #endif
53 
54 #define free(x) xfree(x)
55 
56 #include <stdio.h>
57 #if defined(_WIN32)
58 #include "missing/file.h"
59 #endif
60 #include <sys/types.h>
61 #include <sys/stat.h>
62 
63 #ifndef S_ISDIR
64 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
65 #endif
66 
67 #ifdef HAVE_SYS_PARAM_H
68 # include <sys/param.h>
69 #endif
70 #ifndef MAXPATHLEN
71 # define MAXPATHLEN 1024
72 #endif
73 
74 #ifdef HAVE_UNISTD_H
75 # include <unistd.h>
76 #endif
77 
78 #ifndef _WIN32
79 char *getenv();
80 #endif
81 
82 static char *dln_find_1(const char *fname, const char *path, char *buf, size_t size, int exe_flag);
83 
84 char *
85 dln_find_exe_r(const char *fname, const char *path, char *buf, size_t size)
86 {
87  char *envpath = 0;
88 
89  if (!path) {
90  path = getenv(PATH_ENV);
91  if (path) path = envpath = strdup(path);
92  }
93 
94  if (!path) {
95 #if defined(_WIN32)
96  path = "/usr/local/bin;/usr/ucb;/usr/bin;/bin;.";
97 #else
98  path = "/usr/local/bin:/usr/ucb:/usr/bin:/bin:.";
99 #endif
100  }
101  buf = dln_find_1(fname, path, buf, size, 1);
102  if (envpath) free(envpath);
103  return buf;
104 }
105 
106 char *
107 dln_find_file_r(const char *fname, const char *path, char *buf, size_t size)
108 {
109  if (!path) path = ".";
110  return dln_find_1(fname, path, buf, size, 0);
111 }
112 
113 static char fbuf[MAXPATHLEN];
114 
115 char *
116 dln_find_exe(const char *fname, const char *path)
117 {
118  return dln_find_exe_r(fname, path, fbuf, sizeof(fbuf));
119 }
120 
121 char *
122 dln_find_file(const char *fname, const char *path)
123 {
124  return dln_find_file_r(fname, path, fbuf, sizeof(fbuf));
125 }
126 
127 static char *
128 dln_find_1(const char *fname, const char *path, char *fbuf, size_t size,
129  int exe_flag /* non 0 if looking for executable. */)
130 {
131  register const char *dp;
132  register const char *ep;
133  register char *bp;
134  struct stat st;
135  size_t i, fnlen, fspace;
136 #ifdef DOSISH
137  static const char extension[][5] = {
138  EXECUTABLE_EXTS,
139  };
140  size_t j;
141  int is_abs = 0, has_path = 0;
142  const char *ext = 0;
143 #endif
144  const char *p = fname;
145 
146  static const char pathname_too_long[] = "openpath: pathname too long (ignored)\n\
147 \tDirectory \"%.*s\"%s\n\tFile \"%.*s\"%s\n";
148 #define PATHNAME_TOO_LONG() dln_warning(dln_warning_arg pathname_too_long, \
149  ((bp - fbuf) > 100 ? 100 : (int)(bp - fbuf)), fbuf, \
150  ((bp - fbuf) > 100 ? "..." : ""), \
151  (fnlen > 100 ? 100 : (int)fnlen), fname, \
152  (fnlen > 100 ? "..." : ""))
153 
154 #define RETURN_IF(expr) if (expr) return (char *)fname;
155 
156  RETURN_IF(!fname);
157  fnlen = strlen(fname);
158  if (fnlen >= size) {
160  "openpath: pathname too long (ignored)\n\tFile \"%.*s\"%s\n",
161  (fnlen > 100 ? 100 : (int)fnlen), fname,
162  (fnlen > 100 ? "..." : ""));
163  return NULL;
164  }
165 #ifdef DOSISH
166 # ifndef CharNext
167 # define CharNext(p) ((p)+1)
168 # endif
169 # ifdef DOSISH_DRIVE_LETTER
170  if (((p[0] | 0x20) - 'a') < 26 && p[1] == ':') {
171  p += 2;
172  is_abs = 1;
173  }
174 # endif
175  switch (*p) {
176  case '/': case '\\':
177  is_abs = 1;
178  p++;
179  }
180  has_path = is_abs;
181  while (*p) {
182  switch (*p) {
183  case '/': case '\\':
184  has_path = 1;
185  ext = 0;
186  p++;
187  break;
188  case '.':
189  ext = p;
190  p++;
191  break;
192  default:
193  p = CharNext(p);
194  }
195  }
196  if (ext) {
197  for (j = 0; STRCASECMP(ext, extension[j]); ) {
198  if (++j == sizeof(extension) / sizeof(extension[0])) {
199  ext = 0;
200  break;
201  }
202  }
203  }
204  ep = bp = 0;
205  if (!exe_flag) {
206  RETURN_IF(is_abs);
207  }
208  else if (has_path) {
209  RETURN_IF(ext);
210  i = p - fname;
211  if (i + 1 > size) goto toolong;
212  fspace = size - i - 1;
213  bp = fbuf;
214  ep = p;
215  memcpy(fbuf, fname, i + 1);
216  goto needs_extension;
217  }
218  p = fname;
219 #endif
220 
221  if (*p == '.' && *++p == '.') ++p;
222  RETURN_IF(*p == '/');
223  RETURN_IF(exe_flag && strchr(fname, '/'));
224 
225 #undef RETURN_IF
226 
227  for (dp = path;; dp = ++ep) {
228  register size_t l;
229 
230  /* extract a component */
231  ep = strchr(dp, PATH_SEP[0]);
232  if (ep == NULL)
233  ep = dp+strlen(dp);
234 
235  /* find the length of that component */
236  l = ep - dp;
237  bp = fbuf;
238  fspace = size - 2;
239  if (l > 0) {
240  /*
241  ** If the length of the component is zero length,
242  ** start from the current directory. If the
243  ** component begins with "~", start from the
244  ** user's $HOME environment variable. Otherwise
245  ** take the path literally.
246  */
247 
248  if (*dp == '~' && (l == 1 ||
249 #if defined(DOSISH)
250  dp[1] == '\\' ||
251 #endif
252  dp[1] == '/')) {
253  char *home;
254 
255  home = getenv("HOME");
256  if (home != NULL) {
257  i = strlen(home);
258  if (fspace < i)
259  goto toolong;
260  fspace -= i;
261  memcpy(bp, home, i);
262  bp += i;
263  }
264  dp++;
265  l--;
266  }
267  if (l > 0) {
268  if (fspace < l)
269  goto toolong;
270  fspace -= l;
271  memcpy(bp, dp, l);
272  bp += l;
273  }
274 
275  /* add a "/" between directory and filename */
276  if (ep[-1] != '/')
277  *bp++ = '/';
278  }
279 
280  /* now append the file name */
281  i = fnlen;
282  if (fspace < i) {
283  toolong:
285  goto next;
286  }
287  fspace -= i;
288  memcpy(bp, fname, i + 1);
289 
290 #if defined(DOSISH)
291  if (exe_flag && !ext) {
292  needs_extension:
293  for (j = 0; j < sizeof(extension) / sizeof(extension[0]); j++) {
294  if (fspace < strlen(extension[j])) {
296  continue;
297  }
298  strlcpy(bp + i, extension[j], fspace);
299  if (stat(fbuf, &st) == 0)
300  return fbuf;
301  }
302  goto next;
303  }
304 #endif /* _WIN32 or __EMX__ */
305 
306  if (stat(fbuf, &st) == 0) {
307  if (exe_flag == 0) return fbuf;
308  /* looking for executable */
309  if (!S_ISDIR(st.st_mode) && eaccess(fbuf, X_OK) == 0)
310  return fbuf;
311  }
312  next:
313  /* if not, and no other alternatives, life is bleak */
314  if (*ep == '\0') {
315  return NULL;
316  }
317 
318  /* otherwise try the next component in the search path */
319  }
320 }
#define PATHNAME_TOO_LONG()
#define X_OK
Definition: file.h:18
size_t strlen(const char *)
#define CharNext(p)
Definition: eval_intern.h:219
int i
Definition: win32ole.c:776
#define RETURN_IF(expr)
char * dln_find_file_r(const char *fname, const char *path, char *buf, size_t size)
Definition: dln_find.c:107
#define bp()
Definition: debug.h:27
int eaccess(const char *path, int mode)
Definition: file.c:1039
#define MAXPATHLEN
Definition: dln_find.c:71
static void dln_loaderror(const char *format,...)
#define dp(v)
Definition: debug.h:23
Win32OLEIDispatch * p
Definition: win32ole.c:778
void * xrealloc()
#define dln_warning
Definition: dln_find.c:24
static char * dln_find_1(const char *fname, const char *path, char *buf, size_t size, int exe_flag)
Definition: dln_find.c:128
char * dln_find_exe_r(const char *fname, const char *path, char *buf, size_t size)
Definition: dln_find.c:85
#define S_ISDIR(m)
Definition: dln_find.c:64
char * dln_find_exe(const char *fname, const char *path)
Definition: dln_find.c:116
#define strdup(s)
Definition: util.h:69
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:3913
#define PATH_ENV
Definition: defines.h:288
#define NULL
#define dln_warning_arg
Definition: dln_find.c:25
void * xcalloc()
char * strchr(char *, char)
RUBY_EXTERN size_t strlcpy(char *, const char *, size_t)
Definition: strlcpy.c:44
int size
Definition: encoding.c:51
static char fbuf[MAXPATHLEN]
Definition: dln_find.c:113
#define STRCASECMP(s1, s2)
Definition: ruby.h:1466
char * getenv()
#define PATH_SEP
Definition: defines.h:284
char * dln_find_file(const char *fname, const char *path)
Definition: dln_find.c:122
void * xmalloc()
#define free(x)
Definition: dln_find.c:54
#define stat(path, st)
Definition: win32.h:201