dvitomp fix from Akira
[mplib] / src / texk / kpathsea / pathsearch.c
1 /* pathsearch.c: look up a filename in a path.
2
3    Copyright 1993, 1994, 1995, 1997, 2007 Karl Berry.
4    Copyright 1997-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/c-pathch.h>
21 #include <kpathsea/c-fopen.h>
22 #include <kpathsea/absolute.h>
23 #include <kpathsea/expand.h>
24 #include <kpathsea/db.h>
25 #include <kpathsea/pathsearch.h>
26 #include <kpathsea/readable.h>
27 #include <kpathsea/str-list.h>
28 #include <kpathsea/str-llist.h>
29 #include <kpathsea/variable.h>
30
31 #include <time.h> /* for `time' */
32
33 #ifdef __DJGPP__
34 #include <sys/stat.h>   /* for stat bits */
35 #endif
36
37 /* The very first search is for texmf.cnf, called when someone tries to
38    initialize the TFM path or whatever.  init_path calls kpse_cnf_get
39    which calls kpse_all_path_search to find all the texmf.cnf's.  We
40    need to do various special things in this case, since we obviously
41    don't yet have the configuration files when we're searching for the
42    configuration files.  */
43 static boolean first_search = true;
44
45
46 \f
47 /* This function is called after every search (except the first, since
48    we definitely want to allow enabling the logging in texmf.cnf) to
49    record the filename(s) found in $TEXMFLOG.  */
50
51 static void
52 log_search P1C(str_list_type, filenames)
53 {
54   static FILE *log_file = NULL;
55   static boolean first_time = true; /* Need to open the log file?  */
56   
57   if (first_time) {
58     /* Get name from either envvar or config file.  */
59     string log_name = kpse_var_value ("TEXMFLOG");
60     first_time = false;
61     if (log_name) {
62       log_file = fopen (log_name, FOPEN_A_MODE);
63       if (!log_file)
64         perror (log_name);
65       free (log_name);
66     }
67   }
68
69   if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH) || log_file) {
70     unsigned e;
71
72     /* FILENAMES should never be null, but safety doesn't hurt.  */
73     for (e = 0; e < STR_LIST_LENGTH (filenames) && STR_LIST_ELT (filenames, e);
74          e++) {
75       string filename = STR_LIST_ELT (filenames, e);
76
77       /* Only record absolute filenames, for privacy.  */
78       if (log_file && kpse_absolute_p (filename, false))
79         fprintf (log_file, "%lu %s\n", (long unsigned) time (NULL),
80                  filename);
81
82       /* And show them online, if debugging.  We've already started
83          the debugging line in `search', where this is called, so
84          just print the filename here, don't use DEBUGF.  */
85       if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH)) {
86         putc (' ', stderr);
87         fputs (filename, stderr);
88       }
89     }
90   }
91 }
92 \f
93 /* Concatenate each element in DIRS with NAME (assume each ends with a
94    /, to save time).  If SEARCH_ALL is false, return the first readable
95    regular file.  Else continue to search for more.  In any case, if
96    none, return a list containing just NULL.
97
98    We keep a single buffer for the potential filenames and reallocate
99    only when necessary.  I'm not sure it's noticeably faster, but it
100    does seem cleaner.  (We do waste a bit of space in the return
101    value, though, since we don't shrink it to the final size returned.)  */
102
103 #define INIT_ALLOC 75  /* Doesn't much matter what this number is.  */
104
105 static str_list_type
106 dir_list_search P3C(str_llist_type *, dirs,  const_string, name,
107                     boolean, search_all)
108 {
109   str_llist_elt_type *elt;
110   str_list_type ret;
111   unsigned name_len = strlen (name);
112   unsigned allocated = INIT_ALLOC;
113   string potential = (string)xmalloc (allocated);
114
115   ret = str_list_init ();
116   
117   for (elt = *dirs; elt; elt = STR_LLIST_NEXT (*elt))
118     {
119       const_string dir = STR_LLIST (*elt);
120       unsigned dir_len = strlen (dir);
121       
122       while (dir_len + name_len + 1 > allocated)
123         {
124           allocated += allocated;
125           XRETALLOC (potential, allocated, char);
126         }
127       
128       strcpy (potential, dir);
129       strcat (potential, name);
130       
131       if (kpse_readable_file (potential))
132         { 
133           str_list_add (&ret, potential);
134           
135           /* Move this element towards the top of the list.  */
136           str_llist_float (dirs, elt);
137           
138           /* If caller only wanted one file returned, no need to
139              terminate the list with NULL; the caller knows to only look
140              at the first element.  */
141           if (!search_all)
142             return ret;
143
144           /* Start new filename.  */
145           allocated = INIT_ALLOC;
146           potential = (string)xmalloc (allocated);
147         }
148     }
149   
150   /* If we get here, either we didn't find any files, or we were finding
151      all the files.  But we're done with the last filename, anyway.  */
152   free (potential);
153   
154   return ret;
155 }
156 \f
157 static str_list_type
158 dir_list_search_list P3C(str_llist_type *, dirs,  const_string*, names,
159                          boolean, search_all)
160 {
161   str_llist_elt_type *elt;
162   str_list_type ret;
163   unsigned allocated = INIT_ALLOC;
164   string potential = XTALLOC(allocated, char);
165
166   ret = str_list_init ();
167
168   for (elt = *dirs; elt; elt = STR_LLIST_NEXT(*elt)) {
169       const_string dir = STR_LLIST (*elt);
170       unsigned dir_len = strlen (dir);
171       int i;
172       
173       for (i = 0; names[i]; i++) {
174           const_string name = names[i];
175           unsigned name_len;
176
177           /* Don't bother with absolute & explicit relative. */
178           if (kpse_absolute_p(name, true))
179               continue;
180           
181           name_len = strlen(name);
182
183           while (dir_len + name_len + 1 > allocated) {
184               allocated += allocated;
185               XRETALLOC (potential, allocated, char);
186           }
187
188           strcpy (potential, dir);
189           strcat (potential+dir_len, name);
190
191           if (kpse_readable_file (potential)) {
192               str_list_add (&ret, potential);
193
194               /* Move this element towards the top of the list.  */
195               str_llist_float (dirs, elt);
196
197               /* If caller only wanted one file returned, no need to
198                  terminate the list with NULL; the caller knows to only look
199                  at the first element.  */
200               if (!search_all)
201                   return ret;
202
203               /* Start new filename. */
204               allocated = INIT_ALLOC;
205               potential = XTALLOC(allocated, char);
206           }
207       }
208   }
209
210   /* If we get here, either we didn't find any files, or we were finding
211      all the files.  But we're done with the last filename, anyway.  */
212   free (potential);
213   
214   return ret;
215 }
216 \f
217 /* This is called when NAME is absolute or explicitly relative; if it's
218    readable, return (a list containing) it; otherwise, return NULL.  */
219
220 static str_list_type
221 absolute_search P1C(string, name)
222 {
223   str_list_type ret_list;
224   string found = kpse_readable_file (name);
225   
226   /* Some old compilers can't initialize structs.  */
227   ret_list = str_list_init ();
228
229   /* If NAME wasn't found, free the expansion.  */
230   if (name != found)
231     free (name);
232
233   /* Add `found' to the return list even if it's null; that tells
234      the caller we didn't find anything.  */
235   str_list_add (&ret_list, found);
236   
237   return ret_list;
238 }
239 \f
240 /* This is the hard case -- look for NAME in PATH.  If ALL is false,
241    return the first file found.  Otherwise, search all elements of PATH.  */
242
243 static str_list_type
244 path_search P4C(const_string, path,  string, name,
245                 boolean, must_exist,  boolean, all)
246 {
247   string elt;
248   str_list_type ret_list;
249   boolean done = false;
250   ret_list = str_list_init (); /* some compilers lack struct initialization */
251
252   for (elt = kpse_path_element (path); !done && elt;
253        elt = kpse_path_element (NULL)) {
254     str_list_type *found;
255     boolean allow_disk_search = true;
256
257     if (*elt == '!' && *(elt + 1) == '!') {
258       /* Those magic leading chars in a path element means don't search the
259          disk for this elt.  And move past the magic to get to the name.  */
260       allow_disk_search = false;
261       elt += 2;
262     }
263
264     /* See elt-dirs.c for side effects of this function */
265     kpse_normalize_path(elt);
266     
267     /* Try ls-R, unless we're searching for texmf.cnf.  Our caller
268        (search), also tests first_search, and does the resetting.  */
269     found = first_search ? NULL : kpse_db_search (name, elt, all);
270
271     /* Search the filesystem if (1) the path spec allows it, and either
272          (2a) we are searching for texmf.cnf ; or
273          (2b) no db exists; or 
274          (2c) no db's are relevant to this elt; or
275          (3) MUST_EXIST && NAME was not in the db.
276        In (2*), `found' will be NULL.
277        In (3),  `found' will be an empty list. */
278     if (allow_disk_search && (!found || (must_exist && !STR_LIST (*found)))) {
279       str_llist_type *dirs = kpse_element_dirs (elt);
280       if (dirs && *dirs) {
281         if (!found)
282           found = XTALLOC1 (str_list_type);
283         *found = dir_list_search (dirs, name, all);
284       }
285     }
286     
287     /* Did we find anything anywhere?  */
288     if (found && STR_LIST (*found)) {
289       if (all)
290         str_list_concat (&ret_list, *found);
291       else {
292         str_list_add (&ret_list, STR_LIST_ELT (*found, 0));
293         done = true;
294       }
295     }
296
297     /* Free the list space, if any (but not the elements).  */
298     if (found) {
299       str_list_free (found);
300       free (found);
301     }
302   }
303
304   /* Free the expanded name we were passed.  It can't be in the return
305      list, since the path directories got unconditionally prepended.  */
306   free (name);
307   
308   return ret_list;
309 }      
310 \f
311 /* Search PATH for ORIGINAL_NAME.  If ALL is false, or ORIGINAL_NAME is
312    absolute_p, check ORIGINAL_NAME itself.  Otherwise, look at each
313    element of PATH for the first readable ORIGINAL_NAME.
314    
315    Always return a list; if no files are found, the list will
316    contain just NULL.  If ALL is true, the list will be
317    terminated with NULL.  */
318
319 static string *
320 search P4C(const_string, path,  const_string, original_name,
321            boolean, must_exist,  boolean, all)
322 {
323   str_list_type ret_list;
324   string name;
325   boolean absolute_p;
326
327 #ifdef __DJGPP__
328   /* We will use `stat' heavily, so let's request for
329      the fastest possible version of `stat', by telling
330      it what members of struct stat do we really need.
331
332      We need to set this on each call because this is a
333      library function; the caller might need other options
334      from `stat'.  Thus save the flags and restore them
335      before exit.
336
337      This call tells `stat' that we do NOT need to recognize
338      executable files (neither by an extension nor by a magic
339      signature); that we do NOT need time stamp of root directories;
340      and that we do NOT need the write access bit in st_mode.
341
342      Note that `kpse_set_progname' needs the EXEC bits,
343      but it was already called by the time we get here.  */
344   unsigned short save_djgpp_flags  = _djstat_flags;
345
346   _djstat_flags = _STAT_EXEC_MAGIC | _STAT_EXEC_EXT
347                   | _STAT_ROOT_TIME | _STAT_WRITEBIT;
348 #endif
349
350   /* Make a leading ~ count as an absolute filename, and expand $FOO's.  */
351   name = kpse_expand (original_name);
352   
353   /* If the first name is absolute or explicitly relative, no need to
354      consider PATH at all.  */
355   absolute_p = kpse_absolute_p (name, true);
356   
357   if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
358     DEBUGF4 ("start search(file=%s, must_exist=%d, find_all=%d, path=%s).\n",
359              name, must_exist, all, path);
360
361   /* Find the file(s). */
362   ret_list = absolute_p ? absolute_search (name)
363                         : path_search (path, name, must_exist, all);
364   
365   /* Append NULL terminator if we didn't find anything at all, or we're
366      supposed to find ALL and the list doesn't end in NULL now.  */
367   if (STR_LIST_LENGTH (ret_list) == 0
368       || (all && STR_LIST_LAST_ELT (ret_list) != NULL))
369     str_list_add (&ret_list, NULL);
370
371   /* The very first search is for texmf.cnf.  We can't log that, since
372      we want to allow setting TEXMFLOG in texmf.cnf.  */
373   if (first_search) {
374     first_search = false;
375   } else {
376     /* Record the filenames we found, if desired.  And wrap them in a
377        debugging line if we're doing that.  */
378     if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
379       DEBUGF1 ("search(%s) =>", original_name);
380     log_search (ret_list);
381     if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
382       putc ('\n', stderr);
383   }  
384
385 #ifdef __DJGPP__
386   /* Undo any side effects.  */
387   _djstat_flags = save_djgpp_flags;
388 #endif
389
390   return STR_LIST (ret_list);
391 }
392 \f
393 /* Search PATH for NAMES.
394
395    Always return a list; if no files are found, the list will
396    contain just NULL.  If ALL is true, the list will be
397    terminated with NULL.  */
398 static string *
399 search_list P4C(const_string, path,  const_string*, names,
400                 boolean, must_exist,  boolean, all)
401 {
402   str_list_type ret_list;
403   const_string* namep;
404   string elt;
405   boolean done = false;
406   boolean all_absolute = true;
407
408 #ifdef __DJGPP__
409   /* We will use `stat' heavily, so let's request for
410      the fastest possible version of `stat', by telling
411      it what members of struct stat do we really need.
412
413      We need to set this on each call because this is a
414      library function; the caller might need other options
415      from `stat'.  Thus save the flags and restore them
416      before exit.
417
418      This call tells `stat' that we do NOT need to recognize
419      executable files (neither by an extension nor by a magic
420      signature); that we do NOT need time stamp of root directories;
421      and that we do NOT need the write access bit in st_mode.
422
423      Note that `kpse_set_progname' needs the EXEC bits,
424      but it was already called by the time we get here.  */
425   unsigned short save_djgpp_flags  = _djstat_flags;
426
427   _djstat_flags = _STAT_EXEC_MAGIC | _STAT_EXEC_EXT
428                   | _STAT_ROOT_TIME | _STAT_WRITEBIT;
429 #endif
430
431   ret_list = str_list_init();
432
433   if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH)) {
434     DEBUGF1  ("start search(files=[%s", *names);
435     for (namep = names+1; *namep != NULL; namep++) {
436       fputc(' ', stderr);
437       fputs(*namep, stderr);
438     }
439     fprintf (stderr, "], must_exist=%d, find_all=%d, path=%s).\n",
440              must_exist, all, path);
441   }
442   
443   /* FIXME: is this really true?  No need to do any expansion on names.  */
444
445   /* First catch any absolute or explicit relative names. */
446   for (namep = names; *namep; namep++) {
447       if (kpse_absolute_p(*namep, true)) {
448           if (kpse_readable_file(*namep)) {
449           str_list_add(&ret_list, xstrdup(*namep));
450           /* I know, I know... */
451           if (!all)
452               goto out;
453           }
454       } else {
455           all_absolute = false;
456       }
457   }
458   /* Shortcut: if we were only given absolute/explicit relative names,
459      we can skip the rest.  Typically, if one name is absolute, they
460      all are, because our caller derived them from each other. */
461   if (all_absolute)
462       goto out;
463
464   /* Look at each path element in turn. */
465   for (elt = kpse_path_element (path); !done && elt;
466        elt = kpse_path_element (NULL))
467   {
468     str_list_type *found;
469     boolean allow_disk_search = true;
470     if (elt[0] == '!' && elt[1] == '!') {
471       /* !! magic -> disallow disk searches. */
472       allow_disk_search = false;
473       elt += 2;
474     }
475
476     /* See elt-dirs.c for side effects of this function. */
477     kpse_normalize_path(elt);
478
479     /* Try ls-R, unless we're searching for texmf.cnf. */
480     found = first_search ? NULL : kpse_db_search_list(names, elt, all);
481
482     /* Search the filesystem if (1) the path spec allows it, and either
483          (2a) we are searching for texmf.cnf ; or
484          (2b) no db exists; or 
485          (2c) no db's are relevant to this elt; or
486          (3) MUST_EXIST && NAME was not in the db.
487        In (2*), `found' will be NULL.
488        In (3),  `found' will be an empty list. */
489     if (allow_disk_search && (!found || (must_exist && !STR_LIST(*found)))) {
490       str_llist_type *dirs = kpse_element_dirs (elt);
491       if (dirs && *dirs) {
492         if (!found)
493           found = XTALLOC1 (str_list_type);
494         *found = dir_list_search_list (dirs, names, all);
495       }
496     }
497
498     /* Did we find anything? */
499     if (found && STR_LIST (*found)) {
500       if (all) {
501         str_list_concat (&ret_list, *found);
502       } else {
503         str_list_add (&ret_list, STR_LIST_ELT (*found, 0));
504         done = true;
505       }
506     }
507   }
508
509  out:
510   /* Uniqify, since our paths can often end up finding the same file
511      more than once.  */
512   str_list_uniqify (&ret_list);
513   
514   /* Add NULL if we will be returning multiple elements.  */
515   if (STR_LIST_LENGTH (ret_list) == 0
516       || (all && STR_LIST_LAST_ELT (ret_list) != NULL))
517     str_list_add (&ret_list, NULL);
518
519   if (first_search) {
520     first_search = false;
521   } else {
522     /* Record the filenames we found, if desired.  And wrap them in a
523        debugging line if we're doing that.  */
524     if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH)) {
525       DEBUGF1 ("search([%s", *names);
526       for (namep = names+1; *namep != NULL; namep++) {
527         fputc (' ', stderr);
528         fputs (*namep, stderr);
529       }
530       fputs ("]) =>", stderr);
531     }
532     log_search (ret_list);
533     if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
534       putc ('\n', stderr);
535   }
536
537 #ifdef __DJGPP__
538   /* Undo any side effects.  */
539   _djstat_flags = save_djgpp_flags;
540 #endif
541   
542   return STR_LIST (ret_list);
543 }
544 \f
545 /* Search PATH for the first NAME according to MUST_EXIST.  */
546
547 string
548 kpse_path_search P3C(const_string, path,  const_string, name,
549                      boolean, must_exist)
550 {
551   string *ret_list = search (path, name, must_exist, false);
552   string ret = *ret_list;
553   free (ret_list);
554   return ret;
555 }
556
557 /* Many inputs, return (more or less indeterminate) one matching string.  */
558
559 string
560 kpse_path_search_list P3C(const_string, path,  const_string*, names,
561                           boolean,  must_exist)
562 {
563   string *ret_list
564     = kpse_path_search_list_generic (path, names, must_exist, false);
565   string ret = *ret_list;
566   free (ret_list);
567   return ret;
568 }
569
570 /* Search PATH for all files named NAME.  Might have been better not
571    to assert `must_exist' here, but it's too late to change.  */
572
573 string *
574 kpse_all_path_search P2C(const_string, path,  const_string, name)
575 {
576   string *ret = search (path, name, true, true);
577   return ret;
578 }
579
580
581 /* Many inputs, return list, allow specifying MUST_EXIST and ALL.  */
582
583 string *
584 kpse_path_search_list_generic P4C(const_string, path,  const_string*, names,
585                                   boolean, must_exist,  boolean, all)
586 {
587   string *ret = search_list (path, names, must_exist, all);
588   return ret;
589 }    
590
591
592 /* Many inputs, return list, MUST_EXIST and ALL always true.  */
593
594 string *
595 kpse_all_path_search_list P2C(const_string, path,  const_string*, names)
596 {
597   return kpse_path_search_list_generic (path, names, true, true);
598 }
599 \f
600 #ifdef TEST
601
602 void
603 test_path_search (const_string path, const_string file)
604 {
605   string answer;
606   string *answer_list;
607   
608   printf ("\nSearch %s for %s:\t", path, file);
609   answer = kpse_path_search (path, file);
610   puts (answer ? answer : "(nil)");
611
612   printf ("Search %s for all %s:\t", path, file);
613   answer_list = kpse_all_path_search (path, file);
614   putchar ('\n');
615   while (*answer_list)
616     {
617       putchar ('\t');
618       puts (*answer_list);
619       answer_list++;
620     }
621 }
622
623 #define TEXFONTS "/usr/local/lib/tex/fonts"
624
625 int
626 main ()
627 {
628   /* All lists end with NULL.  */
629   test_path_search (".", "nonexistent");
630   test_path_search (".", "/nonexistent");
631   test_path_search ("/k" ENV_SEP_STRING ".", "kpathsea.texi");
632   test_path_search ("/k" ENV_SEP_STRING ".", "/etc/fstab");
633   test_path_search ("." ENV_SEP_STRING TEXFONTS "//", "cmr10.tfm");
634   test_path_search ("." ENV_SEP_STRING TEXFONTS "//", "logo10.tfm");
635   test_path_search (TEXFONTS "//times" ENV_SEP_STRING "."
636                     ENV_SEP_STRING ENV_SEP_STRING, "ptmr.vf");
637   test_path_search (TEXFONTS "/adobe//" ENV_SEP_STRING
638                     "/usr/local/src/TeX+MF/typefaces//", "plcr.pfa");
639   
640   test_path_search ("~karl", ".bashrc");
641   test_path_search ("/k", "~karl/.bashrc");
642
643   xputenv ("NONEXIST", "nonexistent");
644   test_path_search (".", "$NONEXISTENT");
645   xputenv ("KPATHSEA", "kpathsea");
646   test_path_search ("/k" ENV_SEP_STRING ".", "$KPATHSEA.texi");  
647   test_path_search ("/k" ENV_SEP_STRING ".", "${KPATHSEA}.texi");  
648   test_path_search ("$KPATHSEA" ENV_SEP_STRING ".", "README");  
649   test_path_search ("." ENV_SEP_STRING "$KPATHSEA", "README");  
650   
651   return 0;
652 }
653
654 #endif /* TEST */
655
656
657 /*
658 Local variables:
659 test-compile-command: "gcc -posix -g -I. -I.. -DTEST pathsearch.c kpathsea.a"
660 End:
661 */