summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipsk/search.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipsk/search.c')
-rw-r--r--Build/source/texk/dvipsk/search.c358
1 files changed, 358 insertions, 0 deletions
diff --git a/Build/source/texk/dvipsk/search.c b/Build/source/texk/dvipsk/search.c
new file mode 100644
index 00000000000..ca6b3cda6a6
--- /dev/null
+++ b/Build/source/texk/dvipsk/search.c
@@ -0,0 +1,358 @@
+/*
+ * The search routine takes a directory list, separated by PATHSEP, and
+ * tries to open a file. Null directory components indicate current
+ * directory. In an environment variable, null directory components
+ * indicate substitution of the default path list at that point.
+ * This source file assumes KPATHSEA is defined.
+ */
+#include "dvips.h" /* The copyright notice in that file is included too! */
+
+#ifndef KPATHSEA
+"goodbye, search.c can only be compiled with -DKPATHSEA"
+#endif
+
+#include "protos_add.h" /* external declarations */
+
+#include <kpathsea/c-ctype.h>
+#include <kpathsea/tex-file.h>
+#include <kpathsea/tex-glyph.h>
+#include <kpathsea/absolute.h>
+#include <kpathsea/c-pathch.h>
+#include <kpathsea/variable.h>
+
+#ifdef WIN32
+#undef fopen
+#undef popen
+#undef pclose
+extern FILE *generic_fsyscp_fopen(const char *name, const char *mode);
+#define fopen(file, fmode) generic_fsyscp_fopen(file, fmode)
+#define popen(pcmd, pmode) fsyscp_popen(pcmd, pmode)
+#define pclose(pstream) _pclose(pstream)
+
+#undef FATAL_PERROR
+#if defined (KPSE_COMPAT_API)
+#define FATAL_PERROR(str) do { \
+ win32_fprintf (stderr, "%s: ", kpse_def->invocation_name); \
+ win32_perror (str); exit (EXIT_FAILURE); } while (0)
+#else
+/* If there is no global variable available, just output the error */
+#define FATAL_PERROR(str) do { \
+ win32_perror (str); exit (EXIT_FAILURE); } while (0)
+#endif
+
+#endif
+
+#ifndef GUNZIP
+#define GUNZIP "gzip -d"
+#endif
+
+int to_close; /* use fclose or pclose? */
+char *realnameoffile;
+
+/* Return safely quoted version of NAME. That means using "..." on
+ Windows and '...' on Unix, with any occurrences of the quote char
+ quoted with a \. Result is always in new memory; NAME is unchanged.
+ This is a generic function; if we end up needing it in other
+ programs, we should move it to kpathsea. */
+
+#ifdef WIN32
+#define QUOTE '"'
+#else
+#define QUOTE '\''
+#endif
+
+static char *
+quote_name (const char *name)
+{
+ char *quoted = xmalloc (strlen (name) * 2 + 3);
+ char *q = quoted;
+ const char *p = name;
+
+ *q++ = QUOTE;
+ while (*p) {
+ if (*p == QUOTE)
+ *q++ = QUOTE;
+ *q++ = *p++;
+ }
+ *q++ = QUOTE;
+ *q = 0;
+
+ return quoted;
+}
+
+
+/* On Windows, return PROG with SELFAUTOLOC prepended, and / separators
+ changed to \. On Unix, return a copy of PROG. Result is always in
+ new memory. No safeness or other quoting is done on PROG.
+
+ This is necessary because Windows likes to run programs out of the
+ current directory. So for security, we want to ensure that we are
+ invoking programs from our own binary directory, not via PATH.
+
+ This is a generic function; if we end up needing it in other
+ programs, we should move it to kpathsea. */
+
+#ifdef WIN32
+#include <kpathsea/concatn.h>
+#endif
+
+static char *
+selfautoloc_prog (const char *prog)
+{
+ char *ret;
+#ifdef WIN32
+ char *p, *q, *r;
+ /* Get value of SELFAUTOLOC, but \ works better for path separator. */
+ char *selfautoloc = kpse_var_value ("SELFAUTOLOC");
+ for (p = selfautoloc; *p; p++) {
+ if (*p == '/')
+ *p = '\\';
+ }
+ q = xstrdup (prog);
+ r = q;
+ while (*r && *r != ' ' && *r != '\t')
+ r++;
+ if (*r == '\0')
+ ret = concatn ("\"", selfautoloc, "\\", q, "\"", NULL);
+ else {
+ *r = '\0';
+ r++;
+ if (*r)
+ ret = concatn ("\"", selfautoloc, "\\", q, "\" ", r, NULL);
+ else
+ ret = concatn ("\"", selfautoloc, "\\", q, "\"", NULL);
+ }
+ free (q);
+ free (selfautoloc);
+
+#else /* not WIN32 */
+ ret = xstrdup (prog);
+#endif
+
+ return ret;
+}
+
+
+
+FILE *
+search(kpse_file_format_type format, const char *file, const char *mode)
+{
+ FILE *ret;
+ string found_name;
+
+ /* This change suggested by maj@cl.cam.ac.uk to disallow reading of
+ arbitrary files. Further modified by Y. Oiwa. */
+#ifndef SECURE
+ if (secure == 2) {
+#endif
+ /* an absolute path is denied */
+ if (kpse_absolute_p (file, false))
+ return NULL;
+
+ if (file[0] == '.' && file[1] == '.' && IS_DIR_SEP(file[2])) {
+ /* a relative path starting with ../ is denied */
+ return NULL;
+ } else {
+ /* a relative path containing /../ is denied */
+ const char *p;
+
+ if (file[0] != '\0') {
+ for(p = file + 1; *p && ((p = strstr(p, "..")) != NULL); p += 2) {
+ /* p[2] is valid, because p points to string starting with ".." */
+ /* p[-1] is valid, because p does not point the top of file */
+ if ((p[2] == '\0' || IS_DIR_SEP(p[2])) && IS_DIR_SEP(p[-1])) {
+ return NULL;
+ }
+ }
+ }
+ }
+#ifndef SECURE
+ }
+#endif
+ /* Most file looked for through here must exist -- the exception is
+ VF's. Bitmap fonts go through pksearch. */
+ found_name = kpse_find_file (file, format,
+ format != vfpath && format != ofmpath);
+ if (found_name) {
+ unsigned len = strlen (found_name);
+ if ((format == figpath || format == headerpath)
+ && ((len > 2 && FILESTRCASEEQ (found_name + len - 2, ".Z"))
+ || (len > 3 && FILESTRCASEEQ (found_name + len - 3, ".gz")))) {
+ /* automatically but safely decompress. */
+ char *quoted_name = quote_name (found_name);
+ char *cmd;
+ char *prog = selfautoloc_prog (GUNZIP);
+ cmd = concat3 (prog, " -c ", quoted_name);
+ ret = popen (cmd, "r");
+ if (dd(D_FILES)) {
+ fprintf_str(stderr, "popen(%s) %s\n", cmd,
+ ret == NULL ? "failed" : "succeeded");
+ }
+ SET_BINARY(fileno(ret));
+ to_close = USE_PCLOSE;
+ free (cmd);
+ free (quoted_name);
+ free (prog);
+ } else {
+ ret = fopen (found_name, mode);
+ to_close = USE_FCLOSE;
+ }
+ if (!ret)
+ FATAL_PERROR (found_name);
+
+ /* Free result of previous search. */
+ if (realnameoffile)
+ free (realnameoffile);
+
+ /* Save in `name' and `realnameoffile' because other routines
+ access those globals. */
+ realnameoffile = found_name;
+ strcpy(name, realnameoffile);
+ } else
+ ret = NULL;
+
+ return ret;
+} /* end search */
+
+
+FILE *
+pksearch(const char *file, const char *mode, halfword dpi,
+ const char **name_ret, int *dpi_ret)
+{
+ FILE *ret;
+ kpse_glyph_file_type font_file;
+ string found_name = kpse_find_pk (file, dpi, &font_file);
+
+ if (found_name) {
+ ret = fopen (found_name, mode);
+ if (!ret)
+ FATAL_PERROR (name);
+
+ /* Free result of previous search. */
+ if (realnameoffile)
+ free (realnameoffile);
+ /* Save in `name' and `realnameoffile' because other routines
+ access those globals. Sigh. */
+ realnameoffile = found_name;
+ strcpy(name, realnameoffile);
+ *name_ret = font_file.name;
+ *dpi_ret = font_file.dpi;
+ } else
+ ret = NULL;
+
+ return ret;
+} /* end search */
+
+
+/* do we report file openings? */
+
+#ifdef DEBUG
+# ifdef fopen
+# undef fopen
+# endif
+# ifdef VMCMS /* IBM: VM/CMS */
+# define fopen cmsfopen
+# endif /* IBM: VM/CMS */
+FILE *
+my_real_fopen(register const char *n, register const char *t)
+{
+ FILE *tf;
+ if (dd(D_FILES)) {
+ fprintf_str(stderr, "<%s(%s)> ", n, t);
+ tf = fopen(n, t);
+ if (tf == 0)
+ fprintf(stderr, "failed\n");
+ else
+ fprintf(stderr, "succeeded\n");
+ } else
+ tf = fopen(n, t);
+#ifdef OS2
+ if (tf == (FILE *)NULL)
+ tf = fat_fopen(n, t); /* try again with filename truncated to 8.3 */
+#endif
+ return tf;
+}
+#endif
+
+#ifdef OS2
+/* truncate filename at end of fname to FAT filesystem 8.3 limit */
+/* if truncated, return fopen() with new name */
+FILE *
+fat_fopen(char *fname, char *t)
+{
+ char *np; /* pointer to name within path */
+ char nbuf[13], *ns, *nd;
+ char n[MAXPATHLEN];
+ int ni, ne;
+ FILE *tf;
+ strcpy(n, fname);
+ for (ns=n; *ns; ns++) {
+ if (*ns=='/')
+ *ns=DIRSEP;
+ }
+ np = strrchr(n,DIRSEP);
+ if (np==(char *)NULL)
+ np = n;
+ else
+ np++;
+ /* fail if it contains more than one '.' */
+ ni = 0;
+ for (ns=np; *ns; ns++) {
+ if (*ns=='.')
+ ni++;
+ }
+ if (ni>1)
+ return (FILE *)NULL;
+ /* copy it to nbuf, truncating to 8.3 */
+ ns = np;
+ nd = nbuf;
+ ni = 0;
+ while ((*ns!='.') && (*ns) && (ni<8)) {
+ *nd++ = *ns++;
+ ni++;
+ }
+ while ((*ns!='.') && (*ns)) {
+ ns++;
+ ni++;
+ }
+ ne = 0;
+ if (*ns=='.') {
+ *nd++ = *ns++;
+ while ((*ns!='.') && (*ns) && (ne<3)) {
+ *nd++ = *ns++;
+ ne++;
+ }
+ while (*ns) {
+ ns++;
+ ne++;
+ }
+ }
+ *nd++='\0';
+ if ((ni>8) || (ne>3)) {
+ strcpy(np,nbuf);
+ /* now code copied from my_real_fopen() */
+ if (dd(D_FILES)) {
+ fprintf_str(stderr, "<%s(%s)> ", n, t);
+ tf = fopen(n, t);
+ if (tf == 0)
+ fprintf(stderr, "failed\n");
+ else
+ fprintf(stderr, "succeeded\n");
+ }
+ else
+ tf = fopen(n, t);
+ return tf;
+ }
+ return (FILE *)NULL;
+}
+#endif
+
+int
+close_file(FILE *f)
+{
+ switch(to_close) {
+case USE_PCLOSE: return pclose(f);
+case USE_FCLOSE: return fclose(f);
+default: return -1;
+ }
+}