/* ** Patched for MS-DOS compatibility by Stephen Trier ** March, April and May, 1990. This file is in the ** public domain. */ #ifndef lint static char *sccsid="@(#)getpath.c 2.5 (smail) 9/15/87"; #endif # include # include # include # include "defs.h" extern enum edebug debug; /* how verbose we are */ extern char *pathfile; /* location of path database */ /* ** ** getpath(): look up key in ascii sorted path database. ** */ getpath( key, path , cost) char *key; /* what we are looking for */ char *path; /* where the path results go */ int *cost; /* where the cost results go */ { long pos, middle, hi, lo; static long pathlength = 0; register char *s; int c; static FILE *file; int flag; DEBUG("getpath: looking for '%s'\n", key); if(pathlength == 0) { /* open file on first use */ #ifndef MSDOS if((file = fopen(pathfile, "r")) == NULL) { #else /* * All of the MS-DOS modifications in this section * deal with the MS-DOS \r\n line-ending vs. the UNIX * \n-only newline. The solution is to read the file * in binary mode, and then deal with special characters * like ^Z as special cases. -SCT */ if((file = fopen(pathfile, "rb")) == NULL) { #endif (void) printf("can't access %s.\n", pathfile); pathlength = -1; } else { (void) fseek(file, 0L, 2); /* find length */ pathlength = ftell(file); } } if( pathlength == -1 ) return( EX_OSFILE ); lo = 0; hi = pathlength; (void) strcpy( path, key ); (void) strcat( path, "\t" ); /* ** "Binary search routines are never written right the first time around." ** - Robert G. Sheldon. */ for( ;; ) { pos = middle = ( hi+lo+1 )/2; (void) fseek(file, pos, 0); /* find midpoint */ if(pos != 0) while(((c = getc(file)) != EOF) && (c != '\n')) ; /* go to beginning of next line */ if(c == EOF) { return(EX_NOHOST); } for( flag = 0, s = path; flag == 0; s++ ) { /* match??? */ if( *s == '\0' ) { goto solved; } if((c = getc(file)) == EOF) { return(EX_NOHOST); } flag = lower(c) - lower(*s); #ifdef MSDOS if (c == '\x1A') /* Deal with ^Z -SCT */ c = EOF; #endif } if(lo >= middle) { /* failure? */ return(EX_NOHOST); } if((c != EOF) && (flag < 0)) { /* close window */ lo = middle; } else { hi = middle - 1; } } /* ** Now just copy the result. */ solved: #ifndef MSDOS while(((c = getc(file)) != EOF) && (c != '\t') && (c != '\n')) { #else while(((c = getc(file)) != EOF) && (c != '\t') && (c != '\n') && (c != '\x0D')) { #endif *path++ = c; } *path = '\0'; /* ** See if the next field on the line is numeric. ** If so, use it as the cost for the route. */ if(c == '\t') { int tcost = -1; while(((c = getc(file)) != EOF) && isdigit(c)) { if(tcost < 0) tcost = 0; tcost *= 10; tcost += c - '0'; } if(tcost >= 0) *cost = tcost; } return (EX_OK); }