/* * 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. */ #include "dvips.h" /* The copyright notice in that file is included too! */ #ifdef KPATHSEA #include #include #include #include #include extern char name[]; #else #include #if !defined(WIN32) extern int fclose(); /* these added to keep SunOS happy */ extern int pclose(); extern char *getenv(); #endif #ifdef OS2 #include FILE *fat_fopen(); #endif extern char *newstring P1H(char *) ; #if defined(SYSV) || defined(VMS) || defined(__THINK__) || defined(MSDOS) || defined(OS2) || defined(ATARIST) || defined(WIN32) #define MAXPATHLEN (2000) #else #include /* for MAXPATHLEN */ #endif #if !defined(MSDOS) && !defined(OS2) && !defined(WIN32) #ifndef VMS #ifndef MVSXA #ifndef VMCMS /* IBM: VM/CMS */ #ifndef __THINK__ #ifndef ATARIST #include #endif #endif #endif #endif /* IBM: VM/CMS */ #endif #endif #endif /* KPATHSEA */ /* * * We hope MAXPATHLEN is enough -- only rudimentary checking is done! */ #ifndef SECURE extern int secure ; #endif #ifdef DEBUG extern integer debug_flag; #endif /* DEBUG */ extern char *mfmode ; extern int actualdpi ; int to_close ; #ifdef KPATHSEA #ifndef UNCOMPRESS #define UNCOMPRESS "uncompress" #endif #ifndef GUNZIP #define GUNZIP "gzip -d" #endif #ifndef BUNZIP2 #define BUNZIP2 "bzip2 -d" #endif #endif #ifdef KPATHSEA char *realnameoffile ; FILE * search P3C(kpse_file_format_type, format, char *, file, 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 */ 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); #ifndef AMIGA if ((format == figpath || format == headerpath) && ((len > 2 && FILESTRCASEEQ (found_name + len - 2, ".Z")) || (len > 3 && FILESTRCASEEQ (found_name + len - 3, ".gz")))) { /* FIXME : use zlib instead of gzip ! */ char *cmd = concat3 (GUNZIP, " -c ", found_name); ret = popen (cmd, "r"); to_close = USE_PCLOSE ; } else { #endif /* not AMIGA */ ret = fopen (found_name, mode); to_close = USE_FCLOSE ; #ifndef AMIGA } #endif /* not AMIGA */ 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. Sigh. */ realnameoffile = found_name; strcpy(name, realnameoffile); } else ret = NULL; return ret; } /* end search */ FILE * pksearch P6C(char *, path, char *, file, char *, mode, halfword, dpi, 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 */ #else /* ! KPATHSEA */ char realnameoffile[MAXPATHLEN] ; extern char *figpath, *pictpath, *headerpath ; FILE * search P3C(char *, path, char *, file, char *, mode) { register char *nam ; /* index into fname */ register FILE *fd ; /* file desc of file */ char fname[MAXPATHLEN] ; /* to store file name */ static char *home = 0 ; /* home is where the heart is */ int len = strlen(file) ; int tryz = 0 ; if (len>=3 && ((file[len-2] == '.' && file[len-1] == 'Z') || (file[len-3] == '.' && file[len-2] == 'g' && file[len-1] == 'z')) && (path==figpath || path==pictpath || path==headerpath)) tryz = file[len-1] ; to_close = USE_FCLOSE ; #ifdef MVSXA char fname_safe[256]; register int i, firstext, lastext, lastchar; #endif #ifdef VMCMS /* IBM: VM/CMS - we don't have paths or dirsep's but we strip off filename if there is a Unix path dirsep */ register char *lastdirsep ; lastdirsep = strrchr(file, '/') ; if ( NULL != lastdirsep ) file = lastdirsep + 1 ; if ((fd=fopen(file,mode)) != NULL) { return(fd) ; } else { return(NULL) ; } #else if (*file == DIRSEP || NAME_BEGINS_WITH_DEVICE(file)) { /* if full path name */ if ((fd=fopen(file,mode)) != NULL) { strcpy(realnameoffile, file) ; if (tryz) { char *cmd = mymalloc(strlen(file) + 20) ; strcpy(cmd, (tryz=='z' ? "gzip -d <" : "compress -d <")) ; strcat(cmd, file) ; fclose(fd) ; fd = popen(cmd, "r") ; to_close = USE_PCLOSE ; free(cmd) ; } return(fd) ; } else return(NULL) ; } #endif /* IBM: VM/CMS */ #if defined MSDOS || defined OS2 || defined(ATARIST) || defined(WIN32) if ( isalpha(file[0]) && file[1]==':' ) { /* if full path name */ if ((fd=fopen(file,mode)) != NULL) { strcpy(realnameoffile, file) ; return(fd) ; } else return(NULL) ; } if (*file == '/') {/* if full path name with unix DIRSEP less drive code */ if ((fd=fopen(file,mode)) != NULL) { strcpy(realnameoffile, file) ; return(fd) ; } else return(NULL) ; } #endif do { /* copy the current directory into fname */ nam = fname; /* copy till PATHSEP */ if (*path == '~') { char *p = nam ; path++ ; while (*path && *path != PATHSEP && *path != DIRSEP) *p++ = *path++ ; *p = 0 ; if (*nam == 0) { if (home == 0) { if (0 != (home = getenv("HOME"))) home = newstring(home) ; else home = "." ; } strcpy(fname, home) ; } else { #if defined MSDOS || defined OS2 error("! ~username in path???") ; #else #ifdef WIN32 /* FIXME: at least under NT, it should be possible to retrieve the HOME DIR for a given user */ error("! ~username in path???") ; #else #ifdef VMS error("! ~username in path???") ; #else #ifdef ATARIST error("! ~username in path???") ; #else #ifdef VMCMS /* IBM: VM/CMS */ error("! ~username in path???") ; #else #ifdef MVSXA /* IBM: MVS/XA */ error("! ~username in path???") ; #else #ifdef __THINK__ error("! ~username in path???") ; #else struct passwd *pw = getpwnam(fname) ; if (pw) strcpy(fname, pw->pw_dir) ; else error("no such user") ; #endif #endif /* IBM: VM/CMS */ #endif #endif #endif #endif #endif } nam = fname + strlen(fname) ; } while (*path != PATHSEP && *path) *nam++ = *path++; *nam = 0 ; #ifndef VMS #ifndef __THINK__ if (nam == fname) *nam++ = '.'; /* null component is current dir */ if (*file != '\0') { if ((nam != fname) && *(nam-1) != DIRSEP) /* GNW 1992.07.09 */ *nam++ = DIRSEP; /* add separator */ (void)strcpy(nam,file); /* tack the file on */ } else *nam = '\0' ; #else (void)strcpy(nam,file); /* tack the file on */ #endif #else (void)strcpy(nam,file); /* tack the file on */ #endif #ifdef MVSXA nam = fname; if (strchr(nam,'=') != NULL) { (void) strcpy(fname_safe,fname); /* save fname */ firstext = strchr(nam, '=') - nam + 2; lastext = strrchr(nam, '.') - nam + 1; lastchar = strlen(nam) - 1; (void) strcpy(fname,"dd:"); /* initialize fname */ nam=&fname[3]; for (i=lastext; i<=lastchar; i++) *nam++ = fname_safe[i] ; *nam++ = '(' ; for (i=firstext; i MAXPATHLEN) error("! overran allocated storage in search()"); #ifdef DEBUG if (dd(D_PATHS)) (void)fprintf(stderr,"search: Trying to open %s\n", fname) ; #endif if ((fd=fopen(fname,mode)) != NULL) { strcpy(realnameoffile, fname) ; if (tryz) { char *cmd = mymalloc(strlen(file) + 20) ; strcpy(cmd, (tryz=='z' ? "gzip -d <" : "compress -d <")) ; strcat(cmd, file) ; fclose(fd) ; fd = popen(cmd, "r") ; to_close = USE_PCLOSE ; } return(fd); } /* skip over PATHSEP and try again */ } while (*(path++)); return(NULL); } /* end search */ FILE * pksearch P6C(char *, path, char *, file, char *, mode, char *, n, halfword, dpi, halfword, vdpi) { register char *nam ; /* index into fname */ register FILE *fd ; /* file desc of file */ char fname[MAXPATHLEN] ; /* to store file name */ static char *home = 0 ; /* home is where the heart is */ int sub ; if (*file == DIRSEP) { /* if full path name */ if ((fd=fopen(file,mode)) != NULL) return(fd) ; else return(NULL) ; } #if defined MSDOS || defined OS2 || defined(WIN32) if ( isalpha(file[0]) && file[1]==':' ) { /* if full path name */ if ((fd=fopen(file,mode)) != NULL) return(fd) ; else return(NULL) ; } #endif do { /* copy the current directory into fname */ nam = fname; sub = 0 ; /* copy till PATHSEP */ if (*path == '~') { char *p = nam ; path++ ; while (*path && *path != PATHSEP && *path != DIRSEP) *p++ = *path++ ; *p = 0 ; if (*nam == 0) { if (home == 0) { if (0 != (home = getenv("HOME"))) home = newstring(home) ; else home = "." ; } strcpy(fname, home) ; } else { #if defined MSDOS || defined OS2 error("! ~username in path???") ; #else #ifdef WIN32 error("! ~username in path???") ; #else #ifdef VMS error("! ~username in path???") ; #else #ifdef ATARIST error("! ~username in path???") ; #else #ifdef VMCMS /* IBM: VM/CMS */ error("! ~username in path???") ; #else #ifdef MVSXA /* IBM: MVS/XA */ error("! ~username in path???") ; #else #ifdef __THINK__ error("! ~username in path???") ; #else struct passwd *pw = getpwnam(fname) ; if (pw) strcpy(fname, pw->pw_dir) ; else error("no such user") ; #endif #endif /* IBM: VM/CMS */ #endif #endif #endif #endif #endif } nam = fname + strlen(fname) ; } /* copy till PATHSEP */ while (*path != PATHSEP && *path) { if (*path == '%') { sub = 1 ; path++ ; switch(*path) { case 'b': sprintf(nam, "%d", actualdpi) ; break ; case 'd': sprintf(nam, "%d", dpi) ; break ; case 'f': strcpy(nam, n) ; break ; case 'm': if (mfmode == 0) if (actualdpi == 300) mfmode = "imagen" ; else if (actualdpi == 400) mfmode = "nexthi" ; else if (actualdpi == 635) mfmode = "linolo" ; else if (actualdpi == 1270) mfmode = "linohi" ; else if (actualdpi == 2540) mfmode = "linosuper" ; if (mfmode == 0) error("! MF mode not set, but used in pk path") ; strcpy(nam, mfmode) ; break ; case 'p': strcpy(nam, "pk") ; break ; case '%': strcpy(nam, "%") ; break ; default: fprintf(stderr, "Format character: %c\n", *path) ; error("! bad format character in pk path") ; } nam = fname + strlen(fname) ; if (*path) path++ ; } else *nam++ = *path++; } #ifndef VMS #ifndef __THINK__ if (nam == fname) *nam++ = '.'; /* null component is current dir */ #endif #endif /* VMS */ if (sub == 0 && *file) { #ifndef VMS /* change suggested by MG */ if ((nam != fname) && *(nam-1) != DIRSEP) /* GNW 1992.07.09 */ *nam++ = DIRSEP ; #endif strcpy(nam, file) ; } else *nam = 0 ; #ifdef MVSXA /* IBM: MVS/XA */ if (fname[0] == '/') { fname[0] = '\''; strcat(&fname[strlen(fname)],"\'"); } if (fname[0] == '.') fname[0] = ' '; if (fname[1] == '.') fname[1] = ' '; #endif /* IBM: MVS/XA */ /* belated check -- bah! */ if (strlen(fname) + 1 > MAXPATHLEN) error("! overran allocated storage in search()"); #ifdef DEBUG if (dd(D_PATHS)) (void)fprintf(stderr,"pksearch: Trying to open %s\n", fname) ; #endif if ((fd=fopen(fname,mode)) != NULL) return(fd); /* skip over PATHSEP and try again */ } while (*(path++)); return(NULL); } /* end search */ #endif /* KPATHSEA */ /* 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 P2C(register char *, n, register char *, t) { FILE *tf ; if (dd(D_FILES)) { fprintf(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 P2C(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(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 P1C(FILE *, f) { switch(to_close) { case USE_PCLOSE: return pclose(f) ; case USE_FCLOSE: return fclose(f) ; default: return -1 ; } }