home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / Source / WAIS / ir / futil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-02  |  11.7 KB  |  527 lines

  1. /* Wide AREA INFORMATION SERVER SOFTWARE    
  2.    No guarantees or restrictions.  See the readme file for the full standard
  3.    disclaimer.  
  4.   
  5.    3/90 Brewster
  6. */
  7.  
  8.  
  9. /* ======================== */
  10. /* ===  File Utilities  === */
  11. /* ======================== */
  12.  
  13. #include "futil.h"
  14. #include "panic.h"
  15. #include <string.h>
  16.  
  17. #ifdef THINK_C
  18.   /* file type info */
  19. #include <pascal.h>        /* for CtoPstr */
  20. #include <FileMgr.h>
  21. #define FType long
  22. #define CREATOR         'WIS1'
  23. #define WAIS_INDEX_FILE_TYPE     'INDX'
  24. #else
  25. #include <sys/types.h> /* for stat and getuid */
  26. #include <sys/stat.h> /* for stat */
  27. #include <sys/param.h> /* for getwd */
  28. #endif /* THINK_C */
  29.  
  30. #ifdef ANSI_LIKE
  31. #include <stdarg.h>
  32. #else    
  33. #include <varargs.h>
  34. #endif
  35.  
  36. /*----------------------------------------------------------------------*/
  37.  
  38. static long numFilesCurrentlyOpen = 0;
  39. static long maxNumFilesOpenAtOneTime = 0;
  40.  
  41. FILE*
  42. fs_fopen(fileName,mode)
  43. char* fileName;
  44. char* mode;
  45. {
  46.   FILE* file = NULL;
  47.   char realMode[100];
  48.   
  49. #ifdef BSD
  50. #define implicitBinary
  51. #endif /* def BSD */
  52. #ifdef ultrix
  53. #define implicitBinary
  54. #endif /* def ultrix */
  55. #ifndef ANSI_LIKE
  56. #define implicitBinary
  57. #endif /* def ANSI_LIKE */
  58.  
  59. #ifdef implicitBinary
  60.    /* these old os's don't handle the binary mode.  Just remove it */
  61.    long i,j;
  62.    for (i = 0L,j = 0; mode[i] != '\0';i++)
  63.     { if (mode[i] != 'b')
  64.     realMode[j++] = mode[i];
  65.     }
  66.    realMode[j] = '\0';
  67.   file = fopen(fileName,realMode);
  68. #else
  69.   file = fopen(fileName,mode);
  70. #endif /* def implicitBinary */
  71.   
  72.   if (file != NULL)
  73.     { numFilesCurrentlyOpen++;
  74.       if (numFilesCurrentlyOpen > maxNumFilesOpenAtOneTime)
  75.     maxNumFilesOpenAtOneTime = numFilesCurrentlyOpen;
  76.     }
  77.   
  78.   return(file);
  79. }
  80.  
  81. /*----------------------------------------------------------------------*/
  82.  
  83. long
  84. fs_fclose(file)
  85. FILE* file;
  86.  
  87. {
  88.   if (file != NULL)
  89.     { numFilesCurrentlyOpen--;
  90.       return(fclose(file));
  91.     }
  92.   else
  93.     return(0L);
  94. }
  95.  
  96. /*----------------------------------------------------------------------*/
  97.  
  98. long fs_fseek(file,offset,wherefrom)
  99. FILE* file;
  100. long offset;
  101. long wherefrom;
  102. {
  103.   long result;
  104.   
  105.   if(NULL == file)
  106.     return -1;
  107.   
  108.   result = fseek(file, offset, wherefrom);
  109.  
  110.   /*
  111.   if(0 != result) 
  112.     panic("A seek failed:  offset %ld, wherefrom %d.\n",offset, wherefrom);
  113.     */
  114.   return result;
  115. }
  116.  
  117. /*----------------------------------------------------------------------*/
  118.  
  119. long fs_ftell(file)
  120. FILE* file;
  121. {
  122.   long result;
  123.   
  124.   if (file == NULL)
  125.     return(0);
  126.     
  127.   result = ftell(file);
  128.   
  129.   if(EOF == result)
  130.     panic("A seek on an index file failed.\n");
  131.  
  132.   return(result);
  133. }
  134.  
  135. /*----------------------------------------------------------------------*/
  136.  
  137. void grow_file(file,length)
  138. FILE* file;
  139. long length;
  140. {
  141.   long current_length;
  142.   s_fseek(file, 0L, SEEK_END);
  143.   current_length = s_ftell(file);
  144.   s_fseek(file, length - current_length, SEEK_END);
  145. }
  146.  
  147. /*----------------------------------------------------------------------*/
  148.  
  149. /* writes the high byte first, this makes reading faster */
  150. long write_bytes(value,size,stream)
  151. long value;
  152. long size;
  153. FILE* stream;
  154. {
  155.   long i;
  156.   long answer;
  157.   if((size < sizeof(long)) && (0 != (value >> (size * 8))))
  158.     panic("In a call to write_bytes, the value %ld can not be represented in %ld bytes", value, size);
  159.   for(i = size - 1; i >= 0; i--){
  160.     answer = putc((value >> (i * 8)) & 0xFF, stream);
  161.   }
  162.   if(ferror(stream) != 0) {
  163.     panic("Write failed");
  164.   }
  165.   return(answer);
  166. }
  167.  
  168. /*----------------------------------------------------------------------*/
  169.  
  170. /* returns EOF if it gets an error */
  171. long read_bytes(n_bytes,stream)
  172. long n_bytes;
  173. FILE *stream;
  174. {
  175.   long answer = 0;
  176.   unsigned long ch;
  177.   long i;
  178.   for(i = 0; i < n_bytes; i++){
  179.     ch = fgetc(stream);
  180.     if(EOF == ch){
  181.       return(EOF);
  182.     }
  183.     answer = (answer << 8) + (unsigned char)ch;
  184.   }
  185.   return(answer);
  186. }
  187.  
  188. /*----------------------------------------------------------------------*/
  189.  
  190. long read_bytes_from_memory(n_bytes,block)
  191. long n_bytes;
  192. unsigned char *block;
  193. {
  194.   long answer = 0;
  195.   unsigned char ch;
  196.   long i;
  197.   for(i = 0; i < n_bytes; i++){
  198.     ch = *(block++);
  199.     answer = (answer << 8) + ch;
  200.   }
  201.   return(answer);
  202. }
  203.  
  204. /*----------------------------------------------------------------------*/
  205.  
  206. time_t file_write_date(filename)
  207. char* filename;
  208. { /* os dependent */
  209. #ifdef THINK_C
  210.     return((time_t)0);  /* not implemented yet */
  211. #else
  212.   struct stat *buf = (struct stat*)s_malloc((size_t)sizeof(struct stat));
  213.   time_t mtime;
  214.  
  215.   if(0 != stat(filename, buf)){
  216.     panic("could not stat %s", filename);
  217.   }
  218.   mtime =  buf->st_mtime;
  219.   s_free(buf);
  220.   return(mtime);
  221. #endif /* THINK_C */
  222. }
  223.  
  224. /*----------------------------------------------------------------------*/
  225.  
  226. long file_length(stream)
  227. FILE* stream;
  228. /* return the length (in bytes) of a stream - leave the current
  229.    position where it was
  230.  */ 
  231. {
  232.   long position = ftell(stream);
  233.   long end = -1;
  234.   s_fseek(stream, 0L, SEEK_END);
  235.   end = ftell(stream);    
  236.   s_fseek(stream,position,SEEK_SET);
  237.   return(end);
  238. }
  239.  
  240. /*----------------------------------------------------------------------*/
  241.  
  242. static char *clean_path _AP((char* filename));
  243.  
  244. static char *clean_path(filename)
  245. char *filename;
  246. /* this takes out the '/../' and the '/./' from the path by modifying 
  247.    the argument and returning it. The pathname passed to it must be a 
  248.    full path. This is not optimized. */
  249. {
  250. #ifndef THINK_C
  251.   char *beginning_ptr = strstr(filename, "/../");
  252.   if(NULL != beginning_ptr){
  253.     /* then we have something to process.
  254.        reverse search for the beginning of the last directory,
  255.        in order to snuff it */
  256.     char *ptr;
  257.     for(ptr = beginning_ptr - 1; ptr >= filename; ptr--){
  258.       if(*ptr == '/'){
  259.     /* then we found the beginning of the path */
  260.     strcpy(ptr, beginning_ptr + strlen("/../") -1);
  261.     clean_path(filename);    /* get the other occurances of /../ */
  262.     break;
  263.       }    
  264.     }
  265.   }
  266.   /* now look for /./ */
  267.   beginning_ptr = strstr(filename, "/./");
  268.   if(NULL != beginning_ptr){
  269.     strcpy(beginning_ptr, beginning_ptr + strlen("/./") -1);
  270.     clean_path(filename);    /* get the other occurances of /./ */
  271.   }
  272. #endif                /* ndef THINK_C */
  273.  
  274.   return(filename);
  275.  
  276. }
  277.  
  278. /*----------------------------------------------------------------------*/
  279.     
  280. char *truename(filename,full_path)
  281. char *filename;
  282. char *full_path;
  283. {
  284.   /* this puts into full_path the full pathname including directory.
  285.    */
  286. #ifdef THINK_C
  287.   strcpy(full_path, filename);
  288.   return(full_path); /* do nothing */
  289. #else
  290.   if('/' == filename[0]){
  291.     /* then it is complete already */
  292.     strcpy(full_path, filename);
  293.     clean_path(full_path);
  294.     return(full_path);
  295.   }
  296.   else{
  297.     getwd(full_path);
  298.     s_strncat(full_path,"/",MAX_FILENAME_LEN,MAX_FILENAME_LEN);
  299.     s_strncat(full_path,filename,MAX_FILENAME_LEN,MAX_FILENAME_LEN);
  300.     clean_path(full_path);
  301.     return(full_path);
  302.   }
  303. #endif /* THINK_C */
  304. }
  305.  
  306. /*----------------------------------------------------------------------*/
  307.  
  308. char *pathname_name(pathname)
  309. char *pathname;
  310. /* returns a pointer to the leaf name part of full pathname.
  311.    equivalent to common lisp pathname-name. */
  312. {
  313. #ifdef THINK_C
  314.   char *answer = strrchr(pathname, ':');
  315. #else
  316.   char *answer = strrchr(pathname, '/');
  317. #endif    /* THINK_C */
  318.  
  319.   if(NULL == answer)
  320.     return(pathname);
  321.   return(answer + 1);
  322. }
  323.  
  324. /*----------------------------------------------------------------------*/
  325.  
  326. char *pathname_directory(pathname,destination)
  327. char *pathname;
  328. char *destination;
  329. /* returns a pointer to a string of the directory part of
  330.    the pathname and modifies its destination argument.
  331.    This is the equivalent to the common lisp pathname-directory function. */
  332. {
  333. #ifdef THINK_C
  334.   char *dirptr = strrchr(pathname, ':');
  335. #else
  336.   char *dirptr = strrchr(pathname, '/');
  337. #endif /* THINK_C */
  338.  
  339.   if(NULL == dirptr)
  340.     strcpy(destination, pathname);
  341.   else
  342.     { strcpy(destination, pathname);
  343.       destination[dirptr - pathname + 1] = '\0';
  344.     }
  345.  
  346.   return(destination);
  347. }
  348.   
  349. /*----------------------------------------------------------------------*/
  350.  
  351. /* Setting the Macintosh File type (requires the MacTraps library) */
  352. /* from Util.c by Harry Morris */
  353.  
  354. #ifdef THINK_C
  355.  
  356. void 
  357. setFileType(fileName,type,creator)
  358. char* fileName;
  359. FType type;
  360. FType creator;
  361.   FInfo info;
  362.   OSErr error;
  363.   
  364.   CtoPstr(fileName);
  365.   error = GetFInfo((StringPtr)fileName,0L,&info);
  366.   if (error != noErr)
  367.     panic("error - Can't get file type of file %s, code %ld\n",
  368.           PtoCstr((char*)fileName),noErr);
  369.   info.fdType = type;
  370.   info.fdCreator = creator;
  371.   error = SetFInfo((StringPtr)fileName,0L,&info);
  372.   if (error != noErr)
  373.     panic("error - Can't change file type of file %s, code %ld\n",
  374.           PtoCstr((char*)fileName),noErr);
  375.   PtoCstr((char*)fileName);
  376. }
  377.  
  378. #endif /* THINK_C */
  379.  
  380. /*----------------------------------------------------------------------*/
  381.  
  382. char *current_user_name()
  383. /* returns the current_user_name as a mail address */
  384. {
  385.   static char answer[200];
  386.   char hostname[120];
  387.   
  388. #ifdef THINK_C
  389.   strcpy(answer,"MAC"); /* could look up the name in the chooser */
  390. #endif /* def THINK_C */
  391.  
  392. #ifdef M_XENIX
  393.   strcpy(answer,"unknown"); /* could look up the name in the chooser */
  394. #endif /* def M_XENIX */
  395.  
  396. #ifndef THINK_C
  397. #ifndef M_XENIX
  398.  
  399. #include <pwd.h>  /* for getpwent */
  400.  
  401.   struct passwd *pwent = getpwuid(getuid());
  402.   strncpy(answer, pwent->pw_name, 200);
  403.   strncat(answer, "@", 200);
  404.   gethostname(hostname, 120);
  405.   strncat(answer, hostname, 200);
  406.  
  407. #endif /* ndef M_XENIX */
  408. #endif /* ndef THINK_C */
  409.  
  410.   return(answer);
  411. }
  412.  
  413. /*----------------------------------------------------------------------*/
  414.  
  415. boolean probe_file(filename)
  416. char *filename;
  417. /* return true if it is there, false otherwise.
  418.    Can this be done faster? */
  419. {
  420.   FILE *stream = NULL;
  421.  
  422.   if (filename == NULL)
  423.     return(false);
  424.  
  425.   stream = s_fopen(filename, "r");
  426.  
  427.   if (NULL == stream)
  428.     return(false);
  429.   else
  430.     { s_fclose(stream);
  431.       return(true);
  432.     }
  433. }
  434.  
  435. /*----------------------------------------------------------------------*/
  436.  
  437. /* this opens the file for writing (append)p and then closes it again */
  438. boolean touch_file(filename)
  439. char *filename;
  440. /* return false if error, true otherwise. */
  441. {
  442.   FILE *stream = NULL;
  443.   if (filename == NULL)
  444.     return(false);
  445.   stream = s_fopen(filename, "a");
  446.   if (NULL == stream)
  447.     return(false);
  448.   else
  449.     { s_fclose(stream);
  450.       return(true);
  451.     }
  452. }
  453.  
  454. /*----------------------------------------------------------------------*/
  455.  
  456. char *merge_pathnames(pathname, directory)
  457. char *pathname;
  458. char *directory;
  459. {
  460.   /* if the pathname is not complete, then it puts on the directory
  461.      component and returns it in a static variable.  This is Unix specific */
  462.   static char answer[MAX_FILENAME_LEN + 1];
  463.   if((pathname[0] == '/') || (NULL == directory) || directory[0] == '\0')
  464.     return(pathname);
  465.   else{
  466.     answer[0] = '\0';
  467.     strncat(answer, directory, MAX_FILENAME_LEN);
  468. #ifdef THINK_C
  469.     if(directory[strlen(directory) - 1] != ':')
  470.       strncat(answer, ":", MAX_FILENAME_LEN);
  471. #else
  472.     if(directory[strlen(directory) - 1] != '/')
  473.       strncat(answer, "/", MAX_FILENAME_LEN);
  474. #endif
  475.     strncat(answer, pathname, MAX_FILENAME_LEN);
  476.   }
  477.   /* should this call truename? */
  478.   return(answer);
  479. }
  480.  
  481. /*----------------------------------------------------------------------*/
  482.  
  483.  
  484. boolean 
  485. read_string_from_file(stream,array,array_length)
  486. FILE *stream;
  487. char *array;
  488. long array_length;
  489. /* returns true if it wins. */
  490. {
  491.   char ch;
  492.   long char_count = 0;
  493.  
  494.   array[0] = '\0';
  495.   while(true){
  496.     ch = fgetc(stream);
  497.     if(EOF == ch){
  498.       array[char_count] = '\0';
  499.       return(false);
  500.     }
  501.     else if(char_count == array_length){        
  502.       array[char_count] = '\0';
  503.       return(false);
  504.     }
  505.     else if('\0' == ch){
  506.       array[char_count] = '\0';
  507.       return(true);
  508.     }
  509.     else
  510.       array[char_count++] = ch;
  511.   }
  512. }
  513.  
  514.  
  515. /* counts the lines in a file */
  516. long count_lines(stream)
  517. FILE *stream;
  518. {
  519.   long answer = 1;
  520.   char line[100];
  521.   fseek(stream, 0L, SEEK_SET);    
  522.   while(NULL != fgets(line,100L,stream))
  523.     answer++;
  524.   return(answer);
  525. }
  526.