home *** CD-ROM | disk | FTP | other *** search
- /*
- ** 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 <stdio.h>
- # include <sys/types.h>
- # include <ctype.h>
- # 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);
- }