2999
|
1 /* progname.c: the executable name we were invoked as; general initialization. |
|
2 |
|
3 Copyright (C) 1994, 96, 97 Karl Berry. |
|
4 |
|
5 This library is free software; you can redistribute it and/or |
|
6 modify it under the terms of the GNU Library General Public |
|
7 License as published by the Free Software Foundation; either |
|
8 version 2 of the License, or (at your option) any later version. |
|
9 |
|
10 This library is distributed in the hope that it will be useful, |
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 Library General Public License for more details. |
|
14 |
|
15 You should have received a copy of the GNU Library General Public |
|
16 License along with this library; if not, write to the Free Software |
|
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|
18 |
|
19 #include <kpathsea/config.h> |
|
20 #include <kpathsea/absolute.h> |
|
21 #include <kpathsea/c-pathch.h> |
|
22 #include <kpathsea/c-stat.h> |
|
23 #include <kpathsea/pathsearch.h> |
3172
|
24 /* For kpse_reset_progname */ |
|
25 #include <kpathsea/tex-file.h> |
2999
|
26 |
|
27 #ifdef WIN32 |
|
28 #include <kpathsea/c-pathmx.h> |
|
29 #endif |
|
30 |
|
31 /* NeXT does not define the standard macros, but has the equivalent. |
|
32 WIN32 doesn't define them either, and doesn't have them. |
|
33 From: Gregor Hoffleit <flight@mathi.uni-heidelberg.de>. */ |
|
34 #ifndef S_IXUSR |
|
35 #ifdef WIN32 |
|
36 #define S_IXUSR 0 |
|
37 #define S_IXGRP 0 |
|
38 #define S_IXOTH 0 |
|
39 #else /* not WIN32 */ |
|
40 #define S_IXUSR 0100 |
|
41 #endif /* not WIN32 */ |
|
42 #endif /* not S_IXUSR */ |
|
43 #ifndef S_IXGRP |
|
44 #define S_IXGRP 0010 |
|
45 #endif |
|
46 #ifndef S_IXOTH |
|
47 #define S_IXOTH 0001 |
|
48 #endif |
|
49 |
|
50 #ifndef HAVE_PROGRAM_INVOCATION_NAME |
|
51 /* Don't redefine the variables if glibc already has. */ |
3172
|
52 string program_invocation_name = NULL; |
|
53 string program_invocation_short_name = NULL; |
2999
|
54 #endif |
3172
|
55 /* And the variable for the program we pretend to be. */ |
|
56 string kpse_program_name = NULL; |
2999
|
57 |
|
58 /* Return directory for NAME. This is "." if NAME contains no directory |
|
59 separators (should never happen for selfdir), else whatever precedes |
|
60 the final directory separator, but with multiple separators stripped. |
|
61 For example, `my_dirname ("/foo//bar.baz")' returns "/foo". Always |
|
62 return a new string. */ |
|
63 |
|
64 static string |
|
65 my_dirname P1C(const_string, name) |
|
66 { |
|
67 string ret; |
|
68 unsigned loc = strlen (name); |
|
69 |
|
70 for (loc = strlen (name); loc > 0 && !IS_DIR_SEP (name[loc-1]); loc--) |
|
71 ; |
|
72 |
|
73 if (loc) { |
|
74 /* If have ///a, must return /, so don't strip off everything. */ |
|
75 unsigned limit = NAME_BEGINS_WITH_DEVICE (name) ? 3 : 1; |
|
76 while (loc > limit && IS_DIR_SEP (name[loc-1]) |
|
77 && !IS_DEVICE_SEP (name[loc-1])) { |
|
78 loc--; |
|
79 } |
|
80 ret = xmalloc (loc + 1); |
|
81 strncpy (ret, name, loc); |
|
82 ret[loc] = 0; |
|
83 } else { |
|
84 /* No directory separators at all, so return the current directory. |
|
85 The way this is used in kpathsea, this should never happen. */ |
|
86 ret = xstrdup ("."); |
|
87 } |
|
88 |
|
89 return ret; |
|
90 } |
|
91 |
|
92 #ifndef WIN32 |
|
93 /* From a standalone program `ll' to expand symlinks written by Kimbo Mundy. |
|
94 Don't bother to compile if we don't have symlinks; thus we can assume |
|
95 / as the separator. Also don't try to use basename, etc., or |
|
96 handle arbitrary filename length. Mixed case function names because |
|
97 that's what kimbo liked. */ |
|
98 |
|
99 #ifdef S_ISLNK |
|
100 static int ll_verbose = 0; |
|
101 static int ll_loop = 0; |
|
102 |
|
103 #undef BSIZE |
|
104 #define BSIZE 2048 /* sorry */ |
|
105 |
|
106 |
|
107 /* Read link FN into SYM. */ |
|
108 |
|
109 static void |
|
110 ReadSymLink (fn, sym) |
|
111 char *fn, *sym; |
|
112 { |
|
113 register int n = readlink (fn, sym, BSIZE); |
|
114 if (n < 0) { |
|
115 perror (fn); |
|
116 exit (1); |
|
117 } |
|
118 sym[n] = 0; |
|
119 } |
|
120 |
|
121 |
|
122 /* Strip first component from S, and also return it in a static buffer. */ |
|
123 |
|
124 static char * |
|
125 StripFirst (s) |
|
126 register char *s; |
|
127 { |
|
128 static char buf[BSIZE]; |
|
129 register char *s1; |
|
130 |
|
131 /* Find the end of the first path element */ |
|
132 for (s1 = s; *s1 && (*s1 != '/' || s1 == s); s1++) |
|
133 ; |
|
134 |
|
135 /* Copy it into buf and null-terminate it. */ |
|
136 strncpy (buf, s, s1 - s); |
|
137 buf[s1 - s] = 0; |
|
138 |
|
139 /* Skip over the leading / (if any) */ |
|
140 if (*s1 == '/') |
|
141 ++s1; |
|
142 |
|
143 /* Squeeze out the element */ |
|
144 while ((*s++ = *s1++) != 0) |
|
145 ; |
|
146 |
|
147 return buf; |
|
148 } |
|
149 |
|
150 |
|
151 /* Strip last component from S, and also return it in a static buffer. */ |
|
152 |
|
153 static char * |
|
154 StripLast (s) |
|
155 register char *s; |
|
156 { |
|
157 static char buf[BSIZE]; |
|
158 register char *s1; |
|
159 |
|
160 for (s1 = s + strlen (s); s1 > s && *s1 != '/'; s1--) |
|
161 ; |
|
162 strcpy (buf, s1 + (*s1 == '/')); |
|
163 *s1 = 0; |
|
164 |
|
165 return buf; |
|
166 } |
|
167 |
|
168 |
|
169 /* Copy first path element from B to A, removing it from B. */ |
|
170 |
|
171 static void |
|
172 CopyFirst (a, b) |
|
173 register char *a; |
|
174 char *b; |
|
175 { |
|
176 register int length = strlen (a); |
|
177 |
|
178 if (length > 0 && a[length - 1] != '/') { |
|
179 a[length] = '/'; |
|
180 a[length + 1] = 0; |
|
181 } |
|
182 strcat (a, StripFirst (b)); |
|
183 } |
|
184 |
|
185 /* Returns NULL on error. Prints intermediate results if global |
|
186 `ll_verbose' is nonzero. */ |
|
187 |
|
188 #define EX(s) (strlen (s) && strcmp (s, "/") ? "/" : "") |
|
189 #define EXPOS EX(post) |
|
190 #define EXPRE EX(pre) |
|
191 |
|
192 static char * |
|
193 expand_symlinks (s) |
|
194 char *s; |
|
195 { |
|
196 static char pre[BSIZE]; /* return value */ |
|
197 char post[BSIZE], sym[BSIZE], tmp[BSIZE], before[BSIZE]; |
|
198 char *cp; |
|
199 char a; |
|
200 struct stat st; |
|
201 int done; |
|
202 |
|
203 /* Check for symlink loops. It's difficult to check for all the |
|
204 possibilities ourselves, so let the kernel do it. And make it |
|
205 conditional so that people can see where the infinite loop is |
|
206 being caused (see engtools#1536). */ |
|
207 if (!ll_loop) { |
|
208 FILE *f = fopen (s, "r"); |
|
209 if (!f && errno == ELOOP) { |
|
210 /* Not worried about other errors, we'll get to them in due course. */ |
|
211 perror (s); |
|
212 return NULL; |
|
213 } |
3172
|
214 if (f) fclose (f); |
2999
|
215 } |
|
216 |
|
217 strcpy (post, s); |
|
218 strcpy (pre, ""); |
|
219 |
|
220 while (strlen (post) != 0) { |
|
221 CopyFirst (pre, post); |
|
222 |
|
223 if (lstat (pre, &st) != 0) { |
|
224 fprintf (stderr, "lstat(%s) failed ...\n", pre); |
|
225 perror (pre); |
|
226 return NULL; |
|
227 } |
|
228 |
|
229 if (S_ISLNK (st.st_mode)) { |
|
230 ReadSymLink (pre, sym); |
|
231 |
|
232 if (!strncmp (sym, "/", 1)) { |
|
233 if (ll_verbose) |
|
234 printf ("[%s]%s%s -> [%s]%s%s\n", pre, EXPOS, post, sym, EXPOS,post); |
|
235 strcpy (pre, ""); |
|
236 |
|
237 } else { |
|
238 a = pre[0]; /* handle links through the root */ |
|
239 strcpy (tmp, StripLast (pre)); |
|
240 if (!strlen (pre) && a == '/') |
|
241 strcpy (pre, "/"); |
|
242 |
|
243 if (ll_verbose) { |
|
244 sprintf (before, "%s%s[%s]%s%s", pre, EXPRE, tmp, EXPOS, post); |
|
245 printf ("%s -> %s%s[%s]%s%s\n", before, pre, EXPRE, sym, EXPOS,post); |
|
246 } |
|
247 |
|
248 /* Strip "../" path elements from the front of sym; print |
|
249 new result if there were any such elements. */ |
|
250 done = 0; |
|
251 a = pre[0]; /* handle links through the root */ |
|
252 while (!strncmp (sym, "..", 2) |
|
253 && (sym[2] == 0 || sym[2] == '/') |
|
254 && strlen (pre) != 0 |
|
255 && strcmp (pre, ".") |
|
256 && strcmp (pre, "..") |
|
257 && (strlen (pre) < 3 |
|
258 || strcmp (pre + strlen (pre) - 3, "/.."))) { |
|
259 done = 1; |
|
260 StripFirst (sym); |
|
261 StripLast (pre); |
|
262 } |
|
263 |
|
264 if (done && ll_verbose) { |
|
265 for (cp = before; *cp;) |
|
266 *cp++ = ' '; |
|
267 if (strlen (sym)) |
|
268 printf ("%s == %s%s%s%s%s\n", before, pre, EXPRE, sym, EXPOS,post); |
|
269 else |
|
270 printf ("%s == %s%s%s\n", before, pre, EXPOS, post); |
|
271 } |
|
272 if (!strlen (pre) && a == '/') |
|
273 strcpy (pre, "/"); |
|
274 } |
|
275 |
|
276 if (strlen (post) != 0 && strlen (sym) != 0) |
|
277 strcat (sym, "/"); |
|
278 |
|
279 strcat (sym, post); |
|
280 strcpy (post, sym); |
|
281 } |
|
282 } |
|
283 |
|
284 return pre; |
|
285 } |
|
286 #else /* not S_ISLNK */ |
|
287 #define expand_symlinks(s) (s) |
|
288 #endif /* not S_ISLNK */ |
|
289 |
|
290 /* Remove .'s and ..'s in DIR, to avoid problems with relative symlinks |
|
291 as the program name, etc. This does not canonicalize symlinks. */ |
|
292 |
|
293 static string |
|
294 remove_dots P1C(string, dir) |
|
295 { |
|
296 #ifdef AMIGA |
|
297 return dir; |
|
298 #else |
|
299 string c; |
|
300 unsigned len; |
|
301 string ret = (string) ""; /* We always reassign. */ |
|
302 |
|
303 for (c = kpse_filename_component (dir); c; |
|
304 c = kpse_filename_component (NULL)) { |
|
305 if (STREQ (c, ".")) { |
|
306 /* If leading ., replace with cwd. Else ignore. */ |
|
307 if (*ret == 0) { |
|
308 ret = xgetcwd (); |
|
309 } |
|
310 |
|
311 } else if (STREQ (c, "..")) { |
|
312 /* If leading .., start with my_dirname (cwd). Else remove last |
|
313 component from ret, if any. */ |
|
314 if (*ret == 0) { |
|
315 string dot = xgetcwd (); |
|
316 ret = my_dirname (dot); |
|
317 free (dot); |
|
318 } else { |
|
319 unsigned last; |
|
320 for (last = strlen (ret); |
|
321 last > (NAME_BEGINS_WITH_DEVICE (ret) ? 2 : 0); |
|
322 last--) { |
|
323 if (IS_DIR_SEP (ret[last - 1])) { |
|
324 /* If we have `/../', that's the same as `/'. */ |
|
325 if (last > 1) { |
|
326 ret[last] = 0; |
|
327 } |
|
328 break; |
|
329 } |
|
330 } |
|
331 } |
|
332 |
|
333 } else { |
|
334 /* Not . or ..; just append. Include a directory separator unless |
|
335 our string already ends with one. This also changes all directory |
|
336 separators into the canonical DIR_SEP_STRING. */ |
|
337 string temp; |
|
338 len = strlen (ret); |
|
339 temp = concat3 (ret, ((len > 0 && ret[len - 1] == DIR_SEP) |
|
340 || (NAME_BEGINS_WITH_DEVICE (c) && *ret == 0)) |
|
341 ? "" : DIR_SEP_STRING, |
|
342 c); |
|
343 if (*ret) |
|
344 free (ret); |
|
345 ret = temp; |
|
346 } |
|
347 } |
|
348 |
|
349 /* Remove a trailing /, just in case it snuck in. */ |
|
350 len = strlen (ret); |
|
351 if (len > 0 && ret[len - 1] == DIR_SEP) { |
|
352 ret[len - 1] = 0; |
|
353 } |
|
354 |
|
355 return ret; |
|
356 #endif /* not AMIGA */ |
|
357 } |
|
358 |
|
359 /* Return directory ARGV0 comes from. Check PATH if ARGV0 is not |
|
360 absolute. */ |
|
361 |
|
362 static string |
|
363 selfdir P1C(const_string, argv0) |
|
364 { |
|
365 string ret = NULL; |
|
366 string self = NULL; |
|
367 |
|
368 if (kpse_absolute_p (argv0, true)) { |
|
369 self = xstrdup (argv0); |
|
370 } else { |
|
371 #ifdef AMIGA |
|
372 #include <dos.h> |
|
373 #include <proto/dos.h> |
|
374 #include <proto/exec.h> |
|
375 BPTR lock; |
|
376 struct DosLibrary *DOSBase |
|
377 = (struct DosLibrary *) OpenLibrary ("dos.library", 0L); |
|
378 assert (DOSBase); |
|
379 |
|
380 self = xmalloc (BUFSIZ); |
|
381 lock = findpath (argv0); |
|
382 if (lock != ((BPTR) -1)) { |
3172
|
383 if (getpath (lock, self) == -1) { |
2999
|
384 *self = '\0'; |
3172
|
385 } else { |
|
386 strcat (self,DIR_SEP_STRING); |
|
387 strcat (self,argv0); |
|
388 } |
2999
|
389 UnLock (lock); |
|
390 } |
|
391 CloseLibrary((struct Library *) DOSBase); |
|
392 #else /* not AMIGA */ |
|
393 string elt; |
|
394 struct stat s; |
|
395 |
|
396 /* Have to check PATH. But don't call kpse_path_search since we don't |
|
397 want to search any ls-R's or do anything special with //'s. */ |
|
398 for (elt = kpse_path_element (getenv ("PATH")); !self && elt; |
|
399 elt = kpse_path_element (NULL)) { |
|
400 string name = concat3 (elt, DIR_SEP_STRING, argv0); |
|
401 |
|
402 /* In order to do this perfectly, we'd have to check the owner bits only |
|
403 if we are the file owner, and the group bits only if we belong |
|
404 to the file group. That's a lot of work, though, and it's not |
|
405 likely that kpathsea will ever be used with a program that's |
|
406 only executable by some classes and not others. See the |
|
407 `file_status' function in execute_cmd.c in bash for what's |
|
408 necessary if we were to do it right. */ |
|
409 if (stat (name, &s) == 0 && s.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) { |
3172
|
410 /* Do not stop at directories. */ |
|
411 if (!S_ISDIR(s.st_mode)) |
|
412 self = name; |
2999
|
413 } |
|
414 } |
|
415 #endif /* not AMIGA */ |
|
416 } |
3026
|
417 |
|
418 /* If argv0 is somehow dir/exename, `self' will still be NULL. */ |
|
419 if (!self) |
|
420 self = concat3 (".", DIR_SEP_STRING, argv0); |
|
421 |
2999
|
422 ret = my_dirname (remove_dots (expand_symlinks (self))); |
|
423 |
|
424 free (self); |
|
425 |
|
426 return ret; |
|
427 } |
|
428 #endif /* not WIN32 */ |
|
429 |
|
430 void |
3172
|
431 kpse_set_program_name P2C(const_string, argv0, const_string, progname) |
2999
|
432 { |
|
433 string ext, sdir, sdir_parent, sdir_grandparent; |
|
434 string s = getenv ("KPATHSEA_DEBUG"); |
3172
|
435 #ifdef WIN32 |
|
436 string debug_output = getenv("KPATHSEA_DEBUG_OUTPUT"); |
|
437 int err, olderr; |
|
438 #endif |
2999
|
439 |
|
440 /* Set debugging stuff first, in case we end up doing debuggable stuff |
|
441 during this initialization. */ |
|
442 if (s) { |
|
443 kpathsea_debug |= atoi (s); |
|
444 } |
|
445 |
3172
|
446 #ifndef HAVE_PROGRAM_INVOCATION_NAME |
|
447 #if defined(WIN32) |
|
448 /* redirect stderr to debug_output. Easier to send logfiles. */ |
|
449 if (debug_output) { |
|
450 if ((err = _open(debug_output, _O_CREAT | _O_TRUNC | _O_RDWR, |
|
451 _S_IREAD | _S_IWRITE)) == -1) { |
|
452 WARNING1("Can't open %s for stderr redirection!\n", debug_output); |
|
453 perror(debug_output); |
|
454 } else if ((olderr = _dup(fileno(stderr))) == -1) { |
|
455 WARNING("Can't dup() stderr!\n"); |
|
456 close(err); |
|
457 } else if (_dup2(err, fileno(stderr)) == -1) { |
|
458 WARNING1("Can't redirect stderr to %s!\n", debug_output); |
|
459 close(olderr); |
|
460 close(err); |
|
461 } else { |
|
462 close(err); |
|
463 } |
|
464 } |
2999
|
465 /* Win95 always gives the short filename for argv0, not the long one. |
|
466 There is only this way to catch it. It makes all the selfdir stuff |
|
467 useless for win32. */ |
3172
|
468 { |
|
469 char path[PATH_MAX], *fp; |
|
470 HANDLE hnd; |
|
471 WIN32_FIND_DATA ffd; |
2999
|
472 |
3172
|
473 /* SearchPath() always gives back an absolute directory */ |
|
474 if (SearchPath(NULL, argv0, ".exe", PATH_MAX, path, &fp) == 0) |
|
475 FATAL1("Can't determine where the executable %s is.\n", argv0); |
|
476 if ((hnd = FindFirstFile(path, &ffd)) == NULL) |
|
477 FATAL1("The following path points to an invalid file : %s\n", path); |
|
478 /* slashify the dirname */ |
|
479 for (fp = path; fp && *fp; fp++) |
|
480 if (IS_DIR_SEP(*fp)) *fp = DIR_SEP; |
|
481 /* sdir will be the directory where the executable resides, ie: c:/TeX/bin */ |
|
482 sdir = my_dirname(path); |
|
483 program_invocation_name = xstrdup(ffd.cFileName); |
2999
|
484 } |
|
485 |
3172
|
486 #elif defined(__DJGPP__) |
|
487 |
|
488 /* DJGPP programs support long filenames on Windows 95, but ARGV0 there |
|
489 is always made with the short 8+3 aliases of all the pathname elements. |
|
490 If long names are supported, we need to convert that to a long name. |
|
491 |
|
492 All we really need is to call `_truename', but most of the code |
|
493 below is required to deal with the special case of networked drives. */ |
|
494 if (pathconf (argv0, _PC_NAME_MAX) > 12) { |
|
495 char long_progname[PATH_MAX]; |
|
496 |
|
497 if (_truename (argv0, long_progname)) { |
|
498 char *fp; |
|
499 |
|
500 if (long_progname[1] != ':') { |
|
501 /* A complication: `_truename' returns network-specific string at |
|
502 the beginning of `long_progname' when the program resides on a |
|
503 networked drive, and DOS calls cannot grok such pathnames. We |
|
504 need to convert the filesystem name back to a drive letter. */ |
|
505 char rootname[PATH_MAX], rootdir[4]; |
|
506 |
|
507 if (argv0[0] && argv0[1] == ':') |
|
508 rootdir[0] = argv0[0]; /* explicit drive in `argv0' */ |
|
509 else |
|
510 rootdir[0] = getdisk () + 'A'; |
|
511 rootdir[1] = ':'; |
|
512 rootdir[2] = '\\'; |
|
513 rootdir[3] = '\0'; |
|
514 if (_truename (rootdir, rootname)) { |
|
515 /* Find out where `rootname' ends in `long_progname' and replace |
|
516 it with the drive letter. */ |
|
517 int root_len = strlen (rootname); |
|
518 |
|
519 if (IS_DIR_SEP (rootname[root_len - 1])) |
|
520 root_len--; /* keep the trailing slash */ |
|
521 long_progname[0] = rootdir[0]; |
|
522 long_progname[1] = ':'; |
|
523 memmove (long_progname + 2, long_progname + root_len, |
|
524 strlen (long_progname + root_len) + 1); |
|
525 } |
|
526 } |
|
527 |
|
528 /* Convert everything to canonical form. */ |
|
529 if (long_progname[0] >= 'A' && long_progname[0] <= 'Z') |
|
530 long_progname[0] += 'a' - 'A'; /* make drive lower case, for beauty */ |
|
531 for (fp = long_progname; *fp; fp++) |
|
532 if (IS_DIR_SEP (*fp)) |
|
533 *fp = DIR_SEP; |
|
534 |
|
535 program_invocation_name = xstrdup (long_progname); |
|
536 } |
|
537 else |
|
538 /* If `_truename' failed, God help them, because we won't... */ |
|
539 program_invocation_name = xstrdup (argv0); |
|
540 } |
|
541 else |
|
542 program_invocation_name = xstrdup (argv0); |
|
543 |
|
544 #else /* !WIN32 && !__DJGPP__ */ |
|
545 |
|
546 program_invocation_name = xstrdup (argv0); |
|
547 |
2999
|
548 #endif |
3172
|
549 #endif /* not HAVE_PROGRAM_INVOCATION_NAME */ |
2999
|
550 |
3172
|
551 /* We need to find SELFAUTOLOC *before* removing the ".exe" suffix from |
|
552 the program_name, otherwise the PATH search inside selfdir will fail, |
|
553 since `prog' doesn't exists as a file, there's `prog.exe' instead. */ |
2999
|
554 #ifndef WIN32 |
|
555 sdir = selfdir (program_invocation_name); |
|
556 #endif |
3172
|
557 /* SELFAUTODIR is actually the parent of the invocation directory, |
|
558 and SELFAUTOPARENT the grandparent. This is how teTeX did it. */ |
2999
|
559 xputenv ("SELFAUTOLOC", sdir); |
|
560 sdir_parent = my_dirname (sdir); |
|
561 xputenv ("SELFAUTODIR", sdir_parent); |
|
562 sdir_grandparent = my_dirname (sdir_parent); |
|
563 xputenv ("SELFAUTOPARENT", sdir_grandparent); |
|
564 |
|
565 free (sdir); |
|
566 free (sdir_parent); |
|
567 free (sdir_grandparent); |
3172
|
568 |
3865
|
569 #ifndef HAVE_PROGRAM_INVOCATION_NAME |
3172
|
570 program_invocation_short_name = (string)basename (program_invocation_name); |
|
571 #endif |
|
572 |
|
573 if (progname) { |
|
574 kpse_program_name = xstrdup (progname); |
|
575 } else { |
|
576 /* If configured --enable-shared and running from the build directory |
|
577 with the wrapper scripts (e.g., for make check), the binaries will |
|
578 be named foo.exe instead of foo. Or possibly if we're running on a |
|
579 DOSISH system. */ |
|
580 ext = find_suffix (program_invocation_short_name); |
|
581 if (ext && FILESTRCASEEQ (ext, "exe")) { |
|
582 kpse_program_name = remove_suffix (program_invocation_short_name); |
|
583 } else { |
|
584 kpse_program_name = xstrdup (program_invocation_short_name); |
|
585 } |
|
586 } |
2999
|
587 } |
|
588 |
3172
|
589 /* This function is deprecated, because when we pretend to have a different |
|
590 name it will look for _that_ name in the PATH if program_invocation_name |
|
591 is not defined. */ |
|
592 void |
|
593 kpse_set_progname P1C(const_string, argv0) |
|
594 { |
|
595 kpse_set_program_name (argv0, NULL); |
|
596 } |
|
597 |
2999
|
598 #ifdef TEST |
|
599 void |
|
600 main (int argc, char **argv) |
|
601 { |
|
602 puts (remove_dots ("/w/kpathsea")); |
|
603 puts (remove_dots ("/w//kpathsea")); |
|
604 puts (remove_dots ("/w/./kpathsea")); |
|
605 puts (remove_dots (".")); |
|
606 puts (remove_dots ("./")); |
|
607 puts (remove_dots ("./.")); |
|
608 puts (remove_dots ("../kpathsea")); |
|
609 puts (remove_dots ("/../w/kpathsea")); |
|
610 puts (remove_dots ("/../w/kpathsea/.")); |
|
611 } |
|
612 /* |
|
613 Local variables: |
|
614 standalone-compile-command: "gcc -g -I. -I.. -DTEST progname.c STATIC/libkpathsea.a" |
|
615 End: |
|
616 */ |
|
617 #endif /* TEST */ |