Ruby 2.0.0p353(2013-11-22revision43784)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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