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