Back to index

tetex-bin  3.0
search.c
Go to the documentation of this file.
00001 /*
00002  *   The search routine takes a directory list, separated by PATHSEP, and
00003  *   tries to open a file.  Null directory components indicate current
00004  *   directory.  In an environment variable, null directory components
00005  *   indicate substitution of the default path list at that point.
00006  */
00007 #include "dvips.h" /* The copyright notice in that file is included too! */
00008 #ifdef KPATHSEA
00009 #include <kpathsea/c-ctype.h>
00010 #include <kpathsea/tex-file.h>
00011 #include <kpathsea/tex-glyph.h>
00012 extern char name[];
00013 #else
00014 #include <ctype.h>
00015 #if !defined(WIN32)
00016 extern int fclose();         /* these added to keep SunOS happy */
00017 extern int pclose();
00018 extern char *getenv();
00019 #endif
00020 #ifdef OS2
00021 #include <stdlib.h>
00022 FILE *fat_fopen();
00023 #endif
00024 
00025 extern char *newstring P1H(char *) ;
00026 
00027 #if defined(SYSV) || defined(VMS) || defined(__THINK__) || defined(MSDOS) || defined(OS2) || defined(ATARIST) || defined(WIN32)
00028 #define MAXPATHLEN (2000)
00029 #else
00030 #include <sys/param.h>          /* for MAXPATHLEN */
00031 #endif
00032 #if !defined(MSDOS) && !defined(OS2) && !defined(WIN32)
00033 #ifndef VMS
00034 #ifndef MVSXA
00035 #ifndef VMCMS /* IBM: VM/CMS */
00036 #ifndef __THINK__
00037 #ifndef ATARIST
00038 #include <pwd.h>
00039 #endif
00040 #endif
00041 #endif
00042 #endif  /* IBM: VM/CMS */
00043 #endif
00044 #endif
00045 #endif /* KPATHSEA */
00046 /*
00047  *
00048  *   We hope MAXPATHLEN is enough -- only rudimentary checking is done!
00049  */
00050 
00051 #ifdef SECURE
00052 extern Boolean secure;
00053 #endif
00054 #ifdef DEBUG
00055 extern integer debug_flag;
00056 #endif  /* DEBUG */
00057 extern char *mfmode ;
00058 extern int actualdpi ;
00059 int to_close ;
00060 
00061 #ifdef KPATHSEA
00062 #ifndef UNCOMPRESS
00063 #define UNCOMPRESS      "uncompress"
00064 #endif
00065 
00066 #ifndef GUNZIP
00067 #define GUNZIP          "gzip -d"
00068 #endif
00069 
00070 #ifndef BUNZIP2
00071 #define BUNZIP2         "bzip2 -d"
00072 #endif
00073 
00074 #endif
00075 
00076 #ifdef KPATHSEA
00077 char *realnameoffile ;
00078 
00079 FILE *
00080 search P3C(kpse_file_format_type, format, char *, file, char *, mode)
00081 {
00082   FILE *ret;
00083   string found_name;
00084 
00085 #ifdef SECURE
00086   /* This change suggested by maj@cl.cam.ac.uk to disallow reading of
00087      arbitrary files.  */
00088   if (secure && kpse_absolute_p (file)) return NULL;
00089 #endif
00090 
00091   /* Most file looked for through here must exist -- the exception is
00092      VF's. Bitmap fonts go through pksearch. */
00093   found_name = kpse_find_file (file, format, format != vfpath &&
00094                                                 format != ofmpath);
00095   if (found_name) {
00096     unsigned len = strlen (found_name);
00097 #ifndef AMIGA
00098     if ((format == figpath || format == headerpath)
00099         && ((len > 2 && FILESTRCASEEQ (found_name + len - 2, ".Z"))
00100             || (len > 3 && FILESTRCASEEQ (found_name + len - 3, ".gz")))) {
00101 /* FIXME : use zlib instead of gzip ! */
00102       char *cmd = concat3 (GUNZIP, " -c ", found_name);
00103       ret = popen (cmd, "r");
00104       to_close = USE_PCLOSE ;
00105     } else {
00106 #endif /* not AMIGA */
00107       ret = fopen (found_name, mode);
00108       to_close = USE_FCLOSE ;
00109 #ifndef AMIGA
00110     }
00111 #endif /* not AMIGA */
00112     if (!ret)
00113       FATAL_PERROR (found_name);
00114     /* Free result of previous search.  */
00115     if (realnameoffile)
00116       free (realnameoffile);
00117     /* Save in `name' and `realnameoffile' because other routines
00118        access those globals.  Sigh.  */
00119     realnameoffile = found_name;
00120     strcpy(name, realnameoffile);
00121   } else
00122     ret = NULL;
00123 
00124   return ret;
00125 }               /* end search */
00126 
00127 FILE *
00128 pksearch P6C(char *, path, char *, file, char *, mode,
00129             halfword, dpi, char **, name_ret, int *, dpi_ret)
00130 {
00131   FILE *ret;
00132   kpse_glyph_file_type font_file;
00133   string found_name = kpse_find_pk (file, dpi, &font_file);
00134   
00135   if (found_name)
00136     {
00137       ret = fopen (found_name, mode);
00138       if (!ret)
00139         FATAL_PERROR (name);
00140 
00141       /* Free result of previous search.  */
00142       if (realnameoffile)
00143        free (realnameoffile);
00144       /* Save in `name' and `realnameoffile' because other routines
00145         access those globals.  Sigh.  */
00146       realnameoffile = found_name;
00147       strcpy(name, realnameoffile);
00148       *name_ret = font_file.name;
00149       *dpi_ret = font_file.dpi;
00150     }
00151   else
00152     ret = NULL;
00153 
00154   return ret;
00155 }               /* end search */
00156 #else /* ! KPATHSEA */
00157 char realnameoffile[MAXPATHLEN] ;
00158 
00159 extern char *figpath, *pictpath, *headerpath ;
00160 FILE *
00161 search P3C(char *, path, char *, file, char *, mode)
00162 {
00163    register char *nam ;                 /* index into fname */
00164    register FILE *fd ;                  /* file desc of file */
00165    char fname[MAXPATHLEN] ;             /* to store file name */
00166    static char *home = 0 ;              /* home is where the heart is */
00167    int len = strlen(file) ;
00168    int tryz = 0 ;
00169    if (len>=3 &&
00170         ((file[len-2] == '.' && file[len-1] == 'Z') ||
00171          (file[len-3] == '.' && file[len-2] == 'g' && file[len-1] == 'z')) &&
00172         (path==figpath || path==pictpath || path==headerpath))
00173       tryz = file[len-1] ;
00174    to_close = USE_FCLOSE ;
00175 #ifdef MVSXA
00176 char fname_safe[256];
00177 register int i, firstext, lastext, lastchar;
00178 #endif
00179 #ifdef VMCMS /* IBM: VM/CMS - we don't have paths or dirsep's but we strip off
00180                              filename if there is a Unix path dirsep    */
00181    register char *lastdirsep ;
00182    lastdirsep = strrchr(file, '/') ;
00183    if ( NULL != lastdirsep ) file = lastdirsep + 1 ;
00184    if ((fd=fopen(file,mode)) != NULL) {
00185       return(fd) ;
00186    } else {
00187       return(NULL) ;
00188    }
00189 #else
00190    if (*file == DIRSEP 
00191        || NAME_BEGINS_WITH_DEVICE(file)) {               /* if full path name */
00192       if ((fd=fopen(file,mode)) != NULL) {
00193          strcpy(realnameoffile, file) ;
00194          if (tryz) {
00195             char *cmd = mymalloc(strlen(file) + 20) ;
00196             strcpy(cmd, (tryz=='z' ? "gzip -d <" : "compress -d <")) ;
00197             strcat(cmd, file) ;
00198             fclose(fd) ;
00199             fd = popen(cmd, "r") ;
00200             to_close = USE_PCLOSE ;
00201             free(cmd) ;
00202          }
00203          return(fd) ;
00204       } else
00205          return(NULL) ;
00206    }
00207 #endif   /* IBM: VM/CMS */
00208 
00209 #if defined MSDOS || defined OS2 || defined(ATARIST) || defined(WIN32)
00210    if ( isalpha(file[0]) && file[1]==':' ) {   /* if full path name */
00211       if ((fd=fopen(file,mode)) != NULL) {
00212          strcpy(realnameoffile, file) ;
00213          return(fd) ;
00214       } else
00215          return(NULL) ;
00216    }
00217    if (*file == '/') {/* if full path name with unix DIRSEP less drive code */
00218       if ((fd=fopen(file,mode)) != NULL) {
00219          strcpy(realnameoffile, file) ;
00220          return(fd) ;
00221       } else
00222          return(NULL) ;
00223    }
00224 #endif
00225 
00226    do {
00227       /* copy the current directory into fname */
00228       nam = fname;
00229       /* copy till PATHSEP */
00230       if (*path == '~') {
00231          char *p = nam ;
00232          path++ ;
00233          while (*path && *path != PATHSEP && *path != DIRSEP)
00234             *p++ = *path++ ;
00235          *p = 0 ;
00236          if (*nam == 0) {
00237             if (home == 0) {
00238                if (0 != (home = getenv("HOME")))
00239                   home = newstring(home) ;
00240                else
00241                   home = "." ;
00242             }
00243             strcpy(fname, home) ;
00244          } else {
00245 #if defined MSDOS || defined OS2
00246             error("! ~username in path???") ;
00247 #else
00248 #ifdef WIN32
00249            /* FIXME: at least under NT, it should be possible to 
00250               retrieve the HOME DIR for a given user */
00251             error("! ~username in path???") ;
00252 #else
00253 #ifdef VMS
00254             error("! ~username in path???") ;
00255 #else
00256 #ifdef ATARIST
00257             error("! ~username in path???") ;
00258 #else
00259 #ifdef VMCMS  /* IBM: VM/CMS */
00260             error("! ~username in path???") ;
00261 #else
00262 #ifdef MVSXA  /* IBM: MVS/XA */
00263             error("! ~username in path???") ;
00264 #else
00265 #ifdef __THINK__
00266             error("! ~username in path???") ;
00267 #else
00268             struct passwd *pw = getpwnam(fname) ;
00269             if (pw)
00270                strcpy(fname, pw->pw_dir) ;
00271             else
00272                error("no such user") ;
00273 #endif
00274 #endif  /* IBM: VM/CMS */
00275 #endif
00276 #endif
00277 #endif
00278 #endif
00279 #endif
00280          }
00281          nam = fname + strlen(fname) ;
00282       }
00283       while (*path != PATHSEP && *path) *nam++ = *path++;
00284       *nam = 0 ;
00285 #ifndef VMS
00286 #ifndef __THINK__
00287       if (nam == fname) *nam++ = '.';   /* null component is current dir */
00288 
00289       if (*file != '\0') {
00290          if ((nam != fname) && *(nam-1) != DIRSEP) /* GNW 1992.07.09 */
00291             *nam++ = DIRSEP;                  /* add separator */
00292          (void)strcpy(nam,file);                   /* tack the file on */
00293       }
00294       else
00295          *nam = '\0' ;
00296 #else
00297       (void)strcpy(nam,file);                   /* tack the file on */
00298 #endif
00299 #else
00300       (void)strcpy(nam,file);                   /* tack the file on */
00301 #endif
00302 #ifdef MVSXA
00303 nam = fname;
00304 if (strchr(nam,'=') != NULL) {
00305    (void) strcpy(fname_safe,fname);  /* save fname */
00306    firstext = strchr(nam, '=') - nam + 2;
00307    lastext = strrchr(nam, '.') - nam + 1;
00308    lastchar  = strlen(nam) - 1;
00309 
00310    (void) strcpy(fname,"dd:");  /* initialize fname */
00311    nam=&fname[3];
00312    for (i=lastext; i<=lastchar; i++) *nam++ = fname_safe[i] ;
00313            *nam++  = '(' ;
00314    for (i=firstext; i<lastext-1; i++) *nam++ = fname_safe[i] ;
00315            *nam++  = ')' ;
00316            *nam++  = 0   ;
00317    }
00318    else {
00319       if (fname[0] == '/') {
00320          fname[0] = '\'';
00321          strcat(&fname[strlen(fname)],"\'");
00322       }
00323       if (fname[0] == '.') fname[0] = ' ';
00324       if (fname[1] == '.') fname[1] = ' ';
00325    }
00326 #endif
00327 
00328       /* belated check -- bah! */
00329       if ((nam - fname) + strlen(file) + 1 > MAXPATHLEN)
00330          error("! overran allocated storage in search()");
00331 
00332 #ifdef DEBUG
00333       if (dd(D_PATHS))
00334          (void)fprintf(stderr,"search: Trying to open %s\n", fname) ;
00335 #endif
00336       if ((fd=fopen(fname,mode)) != NULL) {
00337          strcpy(realnameoffile, fname) ;
00338          if (tryz) {
00339             char *cmd = mymalloc(strlen(file) + 20) ;
00340             strcpy(cmd, (tryz=='z' ? "gzip -d <" : "compress -d <")) ;
00341             strcat(cmd, file) ;
00342             fclose(fd) ;
00343             fd = popen(cmd, "r") ;
00344             to_close = USE_PCLOSE ;
00345          }
00346          return(fd);
00347       }
00348 
00349    /* skip over PATHSEP and try again */
00350    } while (*(path++));
00351 
00352    return(NULL);
00353 
00354 }               /* end search */
00355 
00356 FILE *
00357 pksearch P6C(char *, path, char *, file, char *, mode,
00358             char *, n, halfword, dpi, halfword, vdpi)
00359 {
00360    register char *nam ;                 /* index into fname */
00361    register FILE *fd ;                  /* file desc of file */
00362    char fname[MAXPATHLEN] ;             /* to store file name */
00363    static char *home = 0 ;              /* home is where the heart is */
00364    int sub ;
00365 
00366    if (*file == DIRSEP) {               /* if full path name */
00367       if ((fd=fopen(file,mode)) != NULL)
00368          return(fd) ;
00369       else
00370          return(NULL) ;
00371    }
00372 #if defined MSDOS || defined OS2 || defined(WIN32)
00373    if ( isalpha(file[0]) && file[1]==':' ) {  /* if full path name */
00374       if ((fd=fopen(file,mode)) != NULL)
00375          return(fd) ;
00376       else
00377          return(NULL) ;
00378    }
00379 #endif
00380    do {
00381       /* copy the current directory into fname */
00382       nam = fname;
00383       sub = 0 ;
00384       /* copy till PATHSEP */
00385       if (*path == '~') {
00386          char *p = nam ;
00387          path++ ;
00388          while (*path && *path != PATHSEP && *path != DIRSEP)
00389             *p++ = *path++ ;
00390          *p = 0 ;
00391          if (*nam == 0) {
00392             if (home == 0) {
00393                if (0 != (home = getenv("HOME")))
00394                   home = newstring(home) ;
00395                else
00396                   home = "." ;
00397             }
00398             strcpy(fname, home) ;
00399          } else {
00400 #if defined MSDOS || defined OS2
00401             error("! ~username in path???") ;
00402 #else
00403 #ifdef WIN32
00404             error("! ~username in path???") ;
00405 #else
00406 #ifdef VMS
00407             error("! ~username in path???") ;
00408 #else
00409 #ifdef ATARIST
00410             error("! ~username in path???") ;
00411 #else
00412 #ifdef VMCMS  /* IBM: VM/CMS */
00413             error("! ~username in path???") ;
00414 #else
00415 #ifdef MVSXA  /* IBM: MVS/XA */
00416             error("! ~username in path???") ;
00417 #else
00418 #ifdef __THINK__
00419             error("! ~username in path???") ;
00420 #else
00421             struct passwd *pw = getpwnam(fname) ;
00422             if (pw)
00423                strcpy(fname, pw->pw_dir) ;
00424             else
00425                error("no such user") ;
00426 #endif
00427 #endif /* IBM: VM/CMS */
00428 #endif
00429 #endif
00430 #endif
00431 #endif
00432 #endif
00433          }
00434          nam = fname + strlen(fname) ;
00435       }
00436       /* copy till PATHSEP */
00437       while (*path != PATHSEP && *path) {
00438          if (*path == '%') {
00439             sub = 1 ;
00440             path++ ;
00441             switch(*path) {
00442                case 'b': sprintf(nam, "%d", actualdpi) ; break ;
00443                case 'd': sprintf(nam, "%d", dpi) ; break ;
00444                case 'f': strcpy(nam, n) ; break ;
00445                case 'm': if (mfmode == 0)
00446                             if (actualdpi == 300) mfmode = "imagen" ;
00447                             else if (actualdpi == 400) mfmode = "nexthi" ;
00448                             else if (actualdpi == 635) mfmode = "linolo" ;
00449                             else if (actualdpi == 1270) mfmode = "linohi" ;
00450                             else if (actualdpi == 2540) mfmode = "linosuper" ;
00451                          if (mfmode == 0)
00452                             error("! MF mode not set, but used in pk path") ;
00453                          strcpy(nam, mfmode) ;
00454                          break ;
00455                case 'p': strcpy(nam, "pk") ; break ;
00456                case '%': strcpy(nam, "%") ; break ;
00457                default:  fprintf(stderr, "Format character: %c\n", *path) ;
00458                          error("! bad format character in pk path") ;
00459             }
00460             nam = fname + strlen(fname) ;
00461             if (*path)
00462                path++ ;
00463          } else
00464             *nam++ = *path++;
00465       }
00466 #ifndef VMS
00467 #ifndef __THINK__
00468       if (nam == fname) *nam++ = '.';   /* null component is current dir */
00469 #endif
00470 #endif /* VMS */
00471       if (sub == 0 && *file) {
00472 #ifndef VMS
00473          /* change suggested by MG */
00474          if ((nam != fname) && *(nam-1) != DIRSEP) /* GNW 1992.07.09 */
00475             *nam++ = DIRSEP ;
00476 #endif
00477          strcpy(nam, file) ;
00478       } else
00479          *nam = 0 ;
00480 
00481 #ifdef MVSXA   /* IBM: MVS/XA */
00482       if (fname[0] == '/') {
00483          fname[0] = '\'';
00484          strcat(&fname[strlen(fname)],"\'");
00485       }
00486       if (fname[0] == '.') fname[0] = ' ';
00487       if (fname[1] == '.') fname[1] = ' ';
00488 #endif         /* IBM: MVS/XA */
00489       /* belated check -- bah! */
00490       if (strlen(fname) + 1 > MAXPATHLEN)
00491          error("! overran allocated storage in search()");
00492 
00493 #ifdef DEBUG
00494       if (dd(D_PATHS))
00495          (void)fprintf(stderr,"pksearch: Trying to open %s\n", fname) ;
00496 #endif
00497       if ((fd=fopen(fname,mode)) != NULL)
00498          return(fd);
00499 
00500    /* skip over PATHSEP and try again */
00501    } while (*(path++));
00502 
00503    return(NULL);
00504 
00505 }               /* end search */
00506 #endif /* KPATHSEA */
00507 
00508 /* do we report file openings? */
00509 
00510 #ifdef DEBUG
00511 #  ifdef fopen
00512 #    undef fopen
00513 #  endif
00514 #  ifdef VMCMS  /* IBM: VM/CMS */
00515 #    define fopen cmsfopen
00516 #  endif /* IBM: VM/CMS */
00517 FILE *my_real_fopen P2C(register char *, n, register char *, t)
00518 {
00519    FILE *tf ;
00520    if (dd(D_FILES)) {
00521       fprintf(stderr, "<%s(%s)> ", n, t) ;
00522       tf = fopen(n, t) ;
00523       if (tf == 0)
00524          fprintf(stderr, "failed\n") ;
00525       else
00526          fprintf(stderr, "succeeded\n") ;
00527    } else
00528       tf = fopen(n, t) ;
00529 #ifdef OS2
00530    if (tf == (FILE *)NULL)
00531      tf = fat_fopen(n, t); /* try again with filename truncated to 8.3 */
00532 #endif
00533    return tf ;
00534 }
00535 #endif
00536 
00537 #ifdef OS2
00538 /* truncate filename at end of fname to FAT filesystem 8.3 limit */
00539 /* if truncated, return fopen() with new name */
00540 FILE *fat_fopen P2C(char *, fname, char *, t)
00541 {
00542    char *np;  /* pointer to name within path */
00543    char nbuf[13], *ns, *nd;
00544    char n[MAXPATHLEN];
00545    int ni, ne;
00546    FILE *tf;
00547    strcpy(n, fname);
00548    for (ns=n; *ns; ns++) {
00549       if (*ns=='/')
00550          *ns=DIRSEP;
00551    }
00552    np = strrchr(n,DIRSEP);
00553    if (np==(char *)NULL)
00554       np = n;
00555    else
00556       np++;
00557    /* fail if it contains more than one '.' */
00558    ni = 0;
00559    for (ns=np; *ns; ns++) {
00560       if (*ns=='.')
00561          ni++;
00562    }
00563    if (ni>1)
00564       return (FILE *)NULL;
00565    /* copy it to nbuf, truncating to 8.3 */
00566    ns = np;
00567    nd = nbuf;
00568    ni = 0;
00569    while ((*ns!='.') && (*ns) && (ni<8)) {
00570       *nd++ = *ns++;
00571       ni++;
00572    }
00573    while ((*ns!='.') && (*ns)) {
00574       ns++;
00575       ni++;
00576    }
00577    ne = 0;
00578    if (*ns=='.') {
00579       *nd++ = *ns++;
00580       while ((*ns!='.') && (*ns) && (ne<3)) {
00581          *nd++ = *ns++;
00582          ne++;
00583       }
00584       while (*ns) {
00585          ns++;
00586          ne++;
00587       }
00588    }
00589    *nd++='\0';
00590    if ((ni>8) || (ne>3)) {
00591       strcpy(np,nbuf);
00592       /* now code copied from my_real_fopen() */
00593       if (dd(D_FILES)) {
00594          fprintf(stderr, "<%s(%s)> ", n, t) ;
00595          tf = fopen(n, t) ;
00596          if (tf == 0)
00597             fprintf(stderr, "failed\n") ;
00598          else
00599             fprintf(stderr, "succeeded\n") ;
00600       }
00601       else
00602          tf = fopen(n, t) ;
00603       return tf;
00604    }
00605    return (FILE *)NULL;
00606 }
00607 #endif
00608 
00609 int close_file P1C(FILE *, f)
00610 {
00611    switch(to_close) {
00612 case USE_PCLOSE:  return pclose(f) ;
00613 case USE_FCLOSE:  return fclose(f) ;
00614 default:          return -1 ;
00615    }
00616 }