1 /* kpsewhich -- standalone path lookup and variable expansion for Kpathsea.
2 Ideas from Thomas Esser, Pierre MacKay, and many others.
3
4 Copyright 1995-2013 Karl Berry & 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-ctype.h>
21 #include <kpathsea/c-pathch.h>
22 #include <kpathsea/expand.h>
23 #include <kpathsea/getopt.h>
24 #include <kpathsea/line.h>
25 #include <kpathsea/pathsearch.h>
26 #include <kpathsea/proginit.h>
27 #include <kpathsea/str-list.h>
28 #include <kpathsea/tex-file.h>
29 #include <kpathsea/tex-glyph.h>
30 #include <kpathsea/variable.h>
31 #include <kpathsea/version.h>
32
33 #ifdef WIN32
34 #undef fputs
35 #undef puts
36 #define fputs win32_fputs
37 #define puts win32_puts
38 #endif
39
40 /* For variable and path expansion. (-expand-var, -expand-path,
41 -show-path) */
42 string var_to_expand = NULL;
43 string braces_to_expand = NULL;
44 string path_to_expand = NULL;
45 string path_to_show = NULL;
46 string var_to_value = NULL;
47
48 /* Base resolution. (-D, -dpi) */
49 unsigned dpi = 600;
50
51 /* The engine name, for '$engine' construct in texmf.cnf. (-engine) */
52 string engine = NULL;
53
54 /* Interactively ask for names to look up? (-interactive) */
55 boolean interactive = false;
56
57 /* The device name, for $MAKETEX_MODE. (-mode) */
58 string mode = NULL;
59
60 /* Search the disk as well as ls-R? (-must-exist, -mktex) */
61 boolean must_exist = false;
62
63 /* The program name, for `.PROG' construct in texmf.cnf. (-program) */
64 string progname = NULL;
65
66 /* Safe input and output names to check. (-safe-in-name and -safe-out-name) */
67 string safe_in_name = NULL;
68 string safe_out_name = NULL;
69
70 /* Return all matches, not just the first one? (-all) */
71 boolean show_all = false;
72
73 /* Only match files in given subdirs. (-subdir) */
74 str_list_type subdir_paths;
75
76 /* The file type and path for lookups. (-format, -path) */
77 kpse_file_format_type user_format = kpse_last_format;
78 string user_format_string;
79 string user_path;
80
81
82
83 /* Define one-word abbreviations for those format types which
84 can otherwise only be specified by strings containing spaces. */
85
86 typedef struct
87 {
88 const_string abbr;
89 kpse_file_format_type format;
90 } format_abbr_type;
91
92 static format_abbr_type format_abbrs[]
93 = { { "bitmapfont", kpse_any_glyph_format },
94 { "mpsupport", kpse_mpsupport_format },
95 { "doc", kpse_texdoc_format },
96 { "source", kpse_texsource_format },
97 { "trofffont", kpse_troff_font_format },
98 { "dvipsconfig", kpse_dvips_config_format },
99 { "web2c", kpse_web2c_format },
100 { "othertext", kpse_program_text_format },
101 { "otherbin", kpse_program_binary_format },
102 { "miscfont", kpse_miscfonts_format },
103 { "cmap", kpse_cmap_format },
104 { "pdftexconfig", kpse_pdftex_config_format },
105 { NULL, kpse_last_format } };
106
107 /* The function to look up STR in the abbr table above.
108 This is called only on a user-specified format string.
109 Return `kpse_last_format' if no match. */
110
111 static kpse_file_format_type
format_abbr(const_string str)112 format_abbr (const_string str)
113 {
114 kpse_file_format_type ret = kpse_last_format;
115 unsigned a = 0;
116
117 while (format_abbrs[a].abbr != NULL) {
118 if (STREQ (str, format_abbrs[a].abbr)) {
119 ret = format_abbrs[a].format;
120 break;
121 }
122 a++;
123 }
124
125 return ret;
126 }
127
128
129
130 /* Return the <number> substring in `<name>.<number><stuff>', if S has
131 that form. If it doesn't, return 0. */
132
133 static unsigned
find_dpi(string s)134 find_dpi (string s)
135 {
136 unsigned dpi_number = 0;
137 const_string extension = find_suffix (s);
138
139 if (extension != NULL)
140 sscanf (extension, "%u", &dpi_number);
141
142 return dpi_number;
143 }
144
145
146
147 /* Return true if FTRY (the candidate suffix) matches NAME. If
148 IS_FILENAME is true, the check is simply that FTRY is a suffix of
149 NAME. If false (that is, NAME is a format), then FTRY and NAME must
150 be entirely equal. */
151
152 static boolean
try_suffix(boolean is_filename,string name,unsigned name_len,const_string ftry)153 try_suffix (boolean is_filename, string name, unsigned name_len,
154 const_string ftry)
155 {
156 unsigned try_len;
157
158 if (!ftry || ! *ftry) {
159 return false;
160 }
161
162 try_len = strlen (ftry);
163 if (try_len > name_len) {
164 /* Candidate is longer than what we're looking for. */
165 return false;
166 }
167 if (!is_filename && try_len < name_len) {
168 /* We're doing format names, not file names, and candidate is
169 shorter than what we're looking for. E.g., do not find `lua'
170 when looking for `clua'. */
171 return false;
172 }
173
174 if (FILESTRCASEEQ (name + name_len - try_len, ftry)) {
175 return true;
176 }
177
178 return false;
179 }
180
181
182
183 /* Use the file type from -format if that was previously determined
184 (i.e., the user_format global variable), else guess dynamically from
185 NAME. Return kpse_last_format if undeterminable. This function is
186 also used to parse the -format string, a case we distinguish via
187 is_filename being false.
188
189 A few filenames have been hard-coded for format types that
190 differ from what would be inferred from their extensions. */
191
192 static kpse_file_format_type
find_format(kpathsea kpse,string name,boolean is_filename)193 find_format (kpathsea kpse, string name, boolean is_filename)
194 {
195 kpse_file_format_type ret = kpse_last_format;
196
197 if (is_filename && user_format != kpse_last_format) {
198 ret = user_format; /* just return what we already computed */
199
200 } else if (FILESTRCASEEQ (name, "config.ps")) {
201 ret = kpse_dvips_config_format;
202 } else if (FILESTRCASEEQ (name, "fmtutil.cnf")) {
203 ret = kpse_web2c_format;
204 } else if (FILESTRCASEEQ (name, "glyphlist.txt")) {
205 ret = kpse_fontmap_format;
206 } else if (FILESTRCASEEQ (name, "mktex.cnf")) {
207 ret = kpse_web2c_format;
208 } else if (FILESTRCASEEQ (name, "pdfglyphlist.txt")) {
209 ret = kpse_fontmap_format;
210 } else if (FILESTRCASEEQ (name, "pdftex.cfg")) {
211 ret = kpse_pdftex_config_format;
212 } else if (FILESTRCASEEQ (name, "texglyphlist.txt")) {
213 ret = kpse_fontmap_format;
214 } else if (FILESTRCASEEQ (name, "texmf.cnf")) {
215 ret = kpse_cnf_format;
216 } else if (FILESTRCASEEQ (name, "updmap.cfg")) {
217 ret = kpse_web2c_format;
218 } else if (FILESTRCASEEQ (name, "XDvi")) {
219 ret = kpse_program_text_format;
220 } else {
221 if (!is_filename) {
222 /* Look for kpsewhich-specific format abbreviations. */
223 ret = format_abbr (name);
224 }
225
226 if (ret == kpse_last_format) {
227 int f = 0; /* kpse_file_format_type */
228 unsigned name_len = strlen (name);
229
230 while (f != kpse_last_format) {
231 const_string *ext;
232 const_string ftry;
233 boolean found = false;
234
235 if (!kpse->format_info[f].type)
236 kpathsea_init_format (kpse, (kpse_file_format_type) f);
237
238 /* Just to abbreviate this lengthy call. */
239 #define TRY_SUFFIX(ftry) try_suffix (is_filename, name, name_len, (ftry))
240
241 if (!is_filename) {
242 /* Allow the long name, but only in the format options. We don't
243 want a filename confused with a format name. */
244 ftry = kpse->format_info[f].type;
245 found = TRY_SUFFIX (ftry);
246 }
247 for (ext = kpse->format_info[f].suffix; !found && ext && *ext; ext++) {
248 found = TRY_SUFFIX (*ext);
249 }
250 for (ext=kpse->format_info[f].alt_suffix; !found && ext && *ext;ext++){
251 found = TRY_SUFFIX (*ext);
252 }
253
254 if (found)
255 break;
256 f++;
257 }
258 ret = f;
259 }
260 }
261 return ret;
262 }
263
264
265
266 /* Return newly-allocated NULL-terminated list of strings from MATCHES
267 that are prefixed with any of the subdirectories in SUBDIRS. That
268 is, for a string S in MATCHES, its dirname must end with one of the
269 elements in SUBDIRS. For instance, if subdir=foo/bar, that will
270 match a string foo/bar/baz or /some/texmf/foo/bar/baz.
271
272 We don't reallocate the actual strings, just the list elements.
273 Perhaps later we will implement wildcards or // or something. */
274
275 static string *
subdir_match(str_list_type subdirs,string * matches)276 subdir_match (str_list_type subdirs, string *matches)
277 {
278 string *ret = XTALLOC1 (string);
279 unsigned len = 1;
280 unsigned e;
281 unsigned m;
282 #if defined(WIN32)
283 string p;
284
285 for (e = 0; e < STR_LIST_LENGTH (subdirs); e++) {
286 for (p = STR_LIST_ELT (subdirs, e); *p; p++) {
287 if (*p == '\\')
288 *p = '/';
289 else if (IS_KANJI(p))
290 p++;
291 }
292 }
293 #endif
294
295 for (m = 0; matches[m]; m++) {
296 unsigned loc;
297 string s = xstrdup (matches[m]);
298 for (loc = strlen (s); loc > 0 && !IS_DIR_SEP_CH (s[loc-1]); loc--)
299 ;
300 while (loc > 0 && IS_DIR_SEP_CH (s[loc-1])) {
301 loc--;
302 }
303 s[loc] = 0; /* wipe out basename */
304
305 for (e = 0; e < STR_LIST_LENGTH (subdirs); e++) {
306 string subdir = STR_LIST_ELT (subdirs, e);
307 unsigned subdir_len = strlen (subdir);
308 while (subdir_len > 0 && IS_DIR_SEP_CH (subdir[subdir_len-1])) {
309 subdir_len--;
310 subdir[subdir_len] = 0; /* remove trailing slashes from subdir spec */
311 }
312 if (FILESTRCASEEQ (subdir, s + loc - subdir_len)) {
313 /* matched, save this one. */
314 XRETALLOC (ret, len + 1, string);
315 ret[len-1] = matches[m];
316 len++;
317 }
318 }
319 free (s);
320 }
321 ret[len-1] = NULL;
322 return ret;
323 }
324
325
326
327 /* Look up a single filename NAME. Return 0 if success, 1 if failure. */
328
329 static unsigned
lookup(kpathsea kpse,string name)330 lookup (kpathsea kpse, string name)
331 {
332 int i;
333 string ret = NULL;
334 string *ret_list = NULL;
335
336 if (user_path) {
337 /* Translate ; to : if that's our ENV_SEP. See cnf.c. */
338 if (IS_ENV_SEP (':')) {
339 string loc;
340 for (loc = user_path; *loc; loc++) {
341 if (*loc == ';')
342 *loc = ':';
343 }
344 }
345 user_path = kpathsea_path_expand (kpse, user_path);
346 if (show_all) {
347 ret_list = kpathsea_all_path_search (kpse, user_path, name);
348 } else {
349 ret = kpathsea_path_search (kpse, user_path, name, must_exist);
350 }
351
352 } else {
353 /* No user-specified search path, check user format or guess from NAME. */
354 kpse_file_format_type fmt = find_format (kpse, name, true);
355
356 switch (fmt) {
357 case kpse_pk_format:
358 case kpse_gf_format:
359 case kpse_any_glyph_format:
360 {
361 kpse_glyph_file_type glyph_ret;
362 string temp = remove_suffix (name);
363 /* Try to extract the resolution from the name. */
364 unsigned local_dpi = find_dpi (name);
365 if (!local_dpi)
366 local_dpi = dpi;
367 ret = kpathsea_find_glyph (kpse, temp,
368 local_dpi, fmt, &glyph_ret);
369 if (temp != name)
370 free (temp);
371 }
372 break;
373
374 case kpse_last_format:
375 /* If the suffix isn't recognized, assume it's a tex file. */
376 fmt = kpse_tex_format;
377 /* fall through */
378
379 default:
380 if (show_all) {
381 ret_list = kpathsea_find_file_generic (kpse, name, fmt,
382 must_exist, true);
383 } else {
384 ret = kpathsea_find_file (kpse, name, fmt, must_exist);
385 }
386 }
387 }
388
389 /* Turn single return into a null-terminated list for uniform treatment. */
390 if (ret) {
391 ret_list = XTALLOC (2, string);
392 ret_list[0] = ret;
393 ret_list[1] = NULL;
394 }
395
396 /* Filter by subdirectories, if specified. */
397 if (STR_LIST_LENGTH (subdir_paths) > 0) {
398 string *new_list = subdir_match (subdir_paths, ret_list);
399 free (ret_list);
400 ret_list = new_list;
401 }
402
403 /* Print output. */
404 if (ret_list) {
405 for (i = 0; ret_list[i]; i++)
406 puts (ret_list[i]);
407 /* Save whether we found anything */
408 ret = ret_list[0];
409 free (ret_list);
410 }
411
412 return ret == NULL;
413 }
414
415 /* Help message. */
416
417 #define USAGE "\n\
418 Standalone path lookup and expansion for Kpathsea.\n\
419 The default is to look up each FILENAME in turn and report its\n\
420 first match (if any) to standard output.\n\
421 \n\
422 When looking up format (.fmt/.base/.mem) files, it is usually necessary\n\
423 to also use -engine, or nothing will be returned; in particular,\n\
424 -engine=/ will return matching format files for any engine.\n\
425 \n\
426 -all output all matches, one per line.\n\
427 -debug=NUM set debugging flags.\n\
428 -D, -dpi=NUM use a base resolution of NUM; default 600.\n\
429 -engine=STRING set engine name to STRING.\n\
430 -expand-braces=STRING output variable and brace expansion of STRING.\n\
431 -expand-path=STRING output complete path expansion of STRING.\n\
432 -expand-var=STRING output variable expansion of STRING.\n\
433 -format=NAME use file type NAME (see list below).\n\
434 -help print this message and exit.\n\
435 -interactive ask for additional filenames to look up.\n\
436 [-no]-mktex=FMT disable/enable mktexFMT generation (FMT=pk/mf/tex/tfm).\n\
437 -mode=STRING set device name for $MAKETEX_MODE to STRING; no default.\n\
438 -must-exist search the disk as well as ls-R if necessary.\n\
439 -path=STRING search in the path STRING.\n\
440 -progname=STRING set program name to STRING.\n\
441 -safe-in-name=STRING check if STRING is ok to open for input.\n\
442 -safe-out-name=STRING check if STRING is ok to open for output.\n\
443 -show-path=NAME output search path for file type NAME (list below).\n\
444 -subdir=STRING only output matches whose directory ends with STRING.\n\
445 -var-value=STRING output the value of variable $STRING.\n\
446 -version print version number and exit.\n \
447 "
448
449 static void
help_message(kpathsea kpse,string * argv)450 help_message (kpathsea kpse, string *argv)
451 {
452 int f; /* kpse_file_format_type */
453
454 printf ("Usage: %s [OPTION]... [FILENAME]...\n", argv[0]);
455 fputs (USAGE, stdout);
456 putchar ('\n');
457 fputs (kpathsea_bug_address, stdout);
458
459 /* Have to set this for init_format to work. */
460 kpathsea_set_program_name (kpse, argv[0], progname);
461
462 puts ("\nRecognized format names and their (abbreviations) and suffixes:");
463 for (f = 0; f < kpse_last_format; f++) {
464 const_string *ext;
465 kpathsea_init_format (kpse, (kpse_file_format_type)f);
466 printf ("%s", kpse->format_info[f].type);
467
468 /* Show abbreviation if we accept one. We repeatedly go through the
469 abbr list here, but it's so short, it doesn't matter. */
470 {
471 unsigned a = 0;
472 while (format_abbrs[a].abbr != NULL) {
473 if (f == format_abbrs[a].format) {
474 printf (" (%s)", format_abbrs[a].abbr);
475 break;
476 }
477 a++;
478 }
479 }
480
481 /* Regular suffixes. */
482 putchar (':');
483 for (ext = kpse->format_info[f].suffix; ext && *ext; ext++) {
484 putchar (' ');
485 fputs (*ext, stdout);
486 }
487
488 if (kpse->format_info[f].alt_suffix) {
489 /* leave extra space between default and alt suffixes */
490 putchar (' ');
491 }
492 for (ext = kpse->format_info[f].alt_suffix; ext && *ext; ext++) {
493 putchar (' ');
494 fputs (*ext, stdout);
495 }
496
497 putchar ('\n');
498 }
499
500 exit (0);
501 }
502
503
504 /* Reading the options. */
505
506 /* This macro tests whether getopt found an option ``A''.
507 Assumes the option index is in the variable `option_index', and the
508 option table in a variable `long_options'. */
509 #define ARGUMENT_IS(a) STREQ (long_options[option_index].name, a)
510
511 /* SunOS cc can't initialize automatic structs. */
512 static struct option long_options[]
513 = { { "D", 1, 0, 0 },
514 { "all", 0, (int *) &show_all, 1 },
515 { "debug", 1, 0, 0 },
516 { "dpi", 1, 0, 0 },
517 { "engine", 1, 0, 0 },
518 { "expand-braces", 1, 0, 0 },
519 { "expand-path", 1, 0, 0 },
520 { "expand-var", 1, 0, 0 },
521 { "format", 1, 0, 0 },
522 { "help", 0, 0, 0 },
523 { "interactive", 0, (int *) &interactive, 1 },
524 { "mktex", 1, 0, 0 },
525 { "mode", 1, 0, 0 },
526 { "must-exist", 0, (int *) &must_exist, 1 },
527 { "path", 1, 0, 0 },
528 { "no-mktex", 1, 0, 0 },
529 { "progname", 1, 0, 0 },
530 { "safe-in-name", 1, 0, 0 },
531 { "safe-out-name", 1, 0, 0 },
532 { "subdir", 1, 0, 0 },
533 { "show-path", 1, 0, 0 },
534 { "var-value", 1, 0, 0 },
535 { "version", 0, 0, 0 },
536 { 0, 0, 0, 0 } };
537
538 static void
read_command_line(kpathsea kpse,int argc,string * argv)539 read_command_line (kpathsea kpse, int argc, string *argv)
540 {
541 int g; /* `getopt' return code. */
542 int option_index;
543
544 for (;;) {
545 g = getopt_long_only (argc, argv, "", long_options, &option_index);
546
547 if (g == -1)
548 break;
549
550 if (g == '?')
551 exit (1); /* Unknown option. */
552
553 assert (g == 0); /* We have no short option names. */
554
555 if (ARGUMENT_IS ("debug")) {
556 kpse->debug |= atoi (optarg);
557
558 } else if (ARGUMENT_IS ("dpi") || ARGUMENT_IS ("D")) {
559 dpi = atoi (optarg);
560
561 } else if (ARGUMENT_IS ("engine")) {
562 engine = optarg;
563
564 } else if (ARGUMENT_IS ("expand-braces")) {
565 braces_to_expand = optarg;
566
567 } else if (ARGUMENT_IS ("expand-path")) {
568 path_to_expand = optarg;
569
570 } else if (ARGUMENT_IS ("expand-var")) {
571 var_to_expand = optarg;
572
573 } else if (ARGUMENT_IS ("format")) {
574 user_format_string = optarg;
575
576 } else if (ARGUMENT_IS ("help")) {
577 help_message (kpse, argv);
578
579 } else if (ARGUMENT_IS ("mktex")) {
580 kpathsea_maketex_option (kpse, optarg, true);
581 must_exist = 1; /* otherwise it never gets called */
582
583 } else if (ARGUMENT_IS ("mode")) {
584 mode = optarg;
585
586 } else if (ARGUMENT_IS ("no-mktex")) {
587 kpathsea_maketex_option (kpse, optarg, false);
588 must_exist = 0;
589
590 } else if (ARGUMENT_IS ("path")) {
591 user_path = optarg;
592
593 } else if (ARGUMENT_IS ("progname")) {
594 progname = optarg;
595
596 } else if (ARGUMENT_IS ("safe-in-name")) {
597 safe_in_name = optarg;
598
599 } else if (ARGUMENT_IS ("safe-out-name")) {
600 safe_out_name = optarg;
601
602 } else if (ARGUMENT_IS ("show-path")) {
603 path_to_show = optarg;
604 user_format_string = optarg;
605
606 } else if (ARGUMENT_IS ("subdir")) {
607 str_list_add (&subdir_paths, optarg);
608
609 } else if (ARGUMENT_IS ("var-value")) {
610 var_to_value = optarg;
611
612 } else if (ARGUMENT_IS ("version")) {
613 puts (kpathsea_version_string);
614 puts ("Copyright 2013 Karl Berry & Olaf Weber.\n\
615 License LGPLv2.1+: GNU Lesser GPL version 2.1 or later <http://gnu.org/licenses/lgpl.html>\n\
616 This is free software: you are free to change and redistribute it.\n\
617 There is NO WARRANTY, to the extent permitted by law.\n");
618 exit (0);
619 }
620
621 /* Else it was just a flag; getopt has already done the assignment. */
622 }
623
624 if (user_path && user_format_string) {
625 fprintf (stderr, "-path (%s) and -format (%s) are mutually exclusive.\n",
626 user_path, user_format_string);
627 fputs ("Try `kpsewhich --help' for more information.\n", stderr);
628 exit (1);
629 }
630
631 if (optind == argc
632 && !var_to_expand && !braces_to_expand && !path_to_expand
633 && !path_to_show && !var_to_value
634 && !safe_in_name && !safe_out_name) {
635 fputs ("Missing argument. Try `kpsewhich --help' for more information.\n",
636 stderr);
637 exit (1);
638 }
639 }
640
641
642
643 /* Initializations that may depend on the options. */
644
645 static void
init_more(kpathsea kpse)646 init_more (kpathsea kpse)
647 {
648 if (engine)
649 kpathsea_xputenv (kpse, "engine", engine);
650
651 /* Disable all mktex programs unless they were explicitly enabled on our
652 command line. */
653 #define DISABLE_MKTEX(fmt) \
654 kpathsea_set_program_enabled (kpse, fmt, false, kpse_src_cmdline - 1)
655 DISABLE_MKTEX (kpse_pk_format);
656 DISABLE_MKTEX (kpse_mf_format);
657 DISABLE_MKTEX (kpse_tex_format);
658 DISABLE_MKTEX (kpse_tfm_format);
659 DISABLE_MKTEX (kpse_fmt_format);
660 DISABLE_MKTEX (kpse_ofm_format);
661 DISABLE_MKTEX (kpse_ocp_format);
662
663 /* NULL for no fallback font. */
664 kpathsea_init_prog (kpse, uppercasify (kpse->program_name), dpi, mode, NULL);
665
666 /* Have to do this after setting the program name. */
667 if (user_format_string) {
668 user_format = find_format (kpse, user_format_string, false);
669 if (user_format == kpse_last_format) {
670 WARNING1 ("kpsewhich: Ignoring unknown file type `%s'",
671 user_format_string);
672 }
673 }
674 }
675
676
677
678 int
main(int argc,string * argv)679 main (int argc, string *argv)
680 {
681 #ifdef WIN32
682 string *av, enc;
683 int ac;
684 #endif
685 unsigned unfound = 0;
686 kpathsea kpse = kpathsea_new();
687
688 /* Read options, then dependent initializations. */
689 read_command_line (kpse, argc, argv);
690
691 kpathsea_set_program_name (kpse, argv[0], progname);
692 #ifdef WIN32
693 if(strstr(kpse->program_name,"xetex") || strstr(kpse->program_name,"xelatex")
694 || strstr(kpse->program_name,"uptex") || strstr(kpse->program_name,"uplatex")
695 || strstr(kpse->program_name,"dvipdfm") || strstr(kpse->program_name,"extractbb")
696 || strstr(kpse->program_name,"xbb") || strstr(kpse->program_name,"ebb")
697 || strstr(kpse->program_name,"dvips"))
698 {
699 enc = kpathsea_var_value (kpse, "command_line_encoding");
700 if (get_command_line_args_utf8(enc, &ac, &av)) {
701 optind = 0;
702 read_command_line (kpse, ac, av);
703 argv = av;
704 argc = ac;
705 }
706 }
707 #endif
708 init_more (kpse);
709
710
711 /* Perform actions. */
712
713 /* Variable expansion. */
714 if (var_to_expand)
715 puts (kpathsea_var_expand (kpse, var_to_expand));
716
717 /* Brace expansion. */
718 if (braces_to_expand)
719 puts (kpathsea_brace_expand (kpse, braces_to_expand));
720
721 /* Path expansion. */
722 if (path_to_expand)
723 puts (kpathsea_path_expand (kpse, path_to_expand));
724
725 /* Show a search path. */
726 if (path_to_show) {
727 if (user_format != kpse_last_format) {
728 if (!kpse->format_info[user_format].type) /* needed if arg was numeric */
729 kpathsea_init_format (kpse, user_format);
730 puts (kpse->format_info[user_format].path);
731 } else {
732 WARNING ("kpsewhich: Cannot show path for unknown file type");
733 }
734 }
735
736 /* Var to value. */
737 if (var_to_value) {
738 const_string value = kpathsea_var_value (kpse, var_to_value);
739 if (!value) {
740 unfound++;
741 value = "";
742 }
743 puts (value);
744 }
745
746 if (safe_in_name) {
747 if (!kpathsea_in_name_ok_silent (kpse, safe_in_name))
748 unfound++;
749 }
750
751 if (safe_out_name) {
752 if (!kpathsea_out_name_ok_silent (kpse, safe_out_name))
753 unfound++;
754 }
755
756 /* --subdir must imply --all, since we filter here after doing the
757 search, rather than inside the search itself. */
758 if (STR_LIST_LENGTH (subdir_paths) > 0) {
759 show_all = 1;
760 }
761
762 /* Usual case: look up each given filename. */
763 for (; optind < argc; optind++) {
764 unfound += lookup (kpse, argv[optind]);
765 }
766
767 if (interactive) {
768 for (;;) {
769 string name = read_line (stdin);
770 if (!name || STREQ (name, "q") || STREQ (name, "quit"))
771 break;
772 unfound += lookup (kpse, name);
773 free (name);
774 }
775 }
776
777 kpathsea_finish (kpse);
778 return unfound > 255 ? 1 : unfound;
779 }
780