ftp.nice.ch/pub/next/connectivity/infosystems/WAIStation.1.9.6.N.b.tar.gz#/WAIS/ir/futil.c

This is futil.c in view mode; [Download] [Up]

/* Wide AREA INFORMATION SERVER SOFTWARE	
   No guarantees or restrictions.  See the readme file for the full standard
   disclaimer.  
  
   3/90 Brewster
*/

/* Change log:
 * $Log:	futil.c,v $
 * Revision 1.21  92/03/24  10:30:41  jonathan
 * Added fix to pathname_directory if no directory part, it puts "./" in the
 * destination.
 * 
 * Revision 1.20  92/02/21  11:05:48  jonathan
 * added RCSIdent
 * 
 * Revision 1.19  92/02/20  14:51:19  jonathan
 * changed include for access() to sys/file.h, since that seems more portable.
 * 
 * Revision 1.18  92/02/18  11:52:43  jonathan
 * conditionalized inclusion of unistd.h for NeXT (use fcntl instead).  This
 * may be a BSD thing.
 * 
 * Revision 1.17  92/02/12  13:19:27  jonathan
 * Added "$Log" so RCS will put the log message in the header
 * 
*/

#ifndef lint
static char *RCSid = "$Header: /tmp_mnt/net/quake/proj/wais/wais-8-b5/ir/RCS/futil.c,v 1.21 92/03/24 10:30:41 jonathan Exp $";
#endif

/* ======================== */
/* ===  File Utilities  === */
/* ======================== */

#include <string.h>

#ifdef THINK_C
  /* file type info */
#include <pascal.h>		/* for CtoPstr */
#include <FileMgr.h>
#define CREATOR 		'WIS1'
#define WAIS_INDEX_FILE_TYPE 	'INDX'
#else
#include <sys/types.h> /* for stat and getuid */
#include <sys/stat.h> /* for stat */
#include <sys/param.h> /* for getwd */

/* for access() */
#include <sys/file.h>
#endif /* THINK_C */

#include "futil.h"
#include "panic.h"

/*----------------------------------------------------------------------*/

static long numFilesCurrentlyOpen = 0;
static long maxNumFilesOpenAtOneTime = 0;

FILE*
fs_fopen(fileName,mode)
char* fileName;
char* mode;
{
  FILE* file = NULL;
  char realMode[100];
  
#ifdef BSD
#define implicitBinary
#endif /* def BSD */
#ifdef ultrix
#define implicitBinary
#endif /* def ultrix */
#ifndef ANSI_LIKE
#define implicitBinary
#endif /* def ANSI_LIKE */

#ifdef implicitBinary
   /* these old os's don't handle the binary mode.  Just remove it */
   long i,j;
   for (i = 0L,j = 0; mode[i] != '\0';i++)
    { if (mode[i] != 'b')
	realMode[j++] = mode[i];
    }
   realMode[j] = '\0';
  file = fopen(fileName,realMode);
#else
  file = fopen(fileName,mode);
#endif /* def implicitBinary */
  
  if (file != NULL)
    { numFilesCurrentlyOpen++;
      if (numFilesCurrentlyOpen > maxNumFilesOpenAtOneTime)
	maxNumFilesOpenAtOneTime = numFilesCurrentlyOpen;
    }
  
  return(file);
}

/*----------------------------------------------------------------------*/

long
fs_fclose(file)
FILE* file;

{
  if (file != NULL)
    { numFilesCurrentlyOpen--;
      return(fclose(file));
    }
  else
    return(0L);
}

/*----------------------------------------------------------------------*/

long fs_fseek(file,offset,wherefrom)
FILE* file;
long offset;
long wherefrom;
{
  long result;
  
  if(NULL == file)
    return -1;
  
  result = fseek(file, offset, wherefrom);

  /*
  if(0 != result) 
    panic("A seek failed:  offset %ld, wherefrom %d.\n",offset, wherefrom);
    */
  return result;
}

/*----------------------------------------------------------------------*/

long fs_ftell(file)
FILE* file;
{
  long result;
  
  if (file == NULL)
    return(0);
    
  result = ftell(file);
  
  if(EOF == result)
    panic("A seek on an index file failed.\n");

  return(result);
}

/*----------------------------------------------------------------------*/

void grow_file(file,length)
FILE* file;
long length;
{
  long current_length;
  s_fseek(file, 0L, SEEK_END);
  current_length = s_ftell(file);
  s_fseek(file, length - current_length, SEEK_END);
}

/*----------------------------------------------------------------------*/

/* writes the high byte first, this makes reading faster */
long write_bytes(value,size,stream)
long value;
long size;
FILE* stream;
{
  long i;
  long answer;
  if((size < sizeof(long)) && (0 != (value >> (size * 8))))
    panic("In a call to write_bytes, the value %ld can not be represented in %ld bytes", value, size);
  for(i = size - 1; i >= 0; i--){
    answer = putc((value >> (i * 8)) & 0xFF, stream);
  }
  if(ferror(stream) != 0) {
    panic("Write failed");
  }
  return(answer);
}

/*----------------------------------------------------------------------*/

/* returns EOF if it gets an error */
long read_bytes(n_bytes,stream)
long n_bytes;
FILE *stream;
{
  long answer = 0;
  unsigned long ch;
  long i;
  for(i = 0; i < n_bytes; i++){
    ch = fgetc(stream);
    if(EOF == ch){
      return(EOF);
    }
    answer = (answer << 8) + (unsigned char)ch;
  }
  return(answer);
}

/*----------------------------------------------------------------------*/

long read_bytes_from_memory(n_bytes,block)
long n_bytes;
unsigned char *block;
{
  long answer = 0;
  unsigned char ch;
  long i;
  for(i = 0; i < n_bytes; i++){
    ch = *(block++);
    answer = (answer << 8) + ch;
  }
  return(answer);
}

/*----------------------------------------------------------------------*/

time_t file_write_date(filename)
char* filename;
{ /* os dependent */
#ifdef THINK_C
	return((time_t)0);  /* not implemented yet */
#else
  struct stat *buf = (struct stat*)s_malloc((size_t)sizeof(struct stat));
  time_t mtime;

  if(0 != stat(filename, buf)){
    panic("could not stat %s", filename);
  }
  mtime =  buf->st_mtime;
  s_free(buf);
  return(mtime);
#endif /* THINK_C */
}

/*----------------------------------------------------------------------*/

long file_length(stream)
FILE* stream;
/* return the length (in bytes) of a stream - leave the current
   position where it was
 */ 
{
  long position = ftell(stream);
  long end = -1;
  s_fseek(stream, 0L, SEEK_END);
  end = ftell(stream);	
  s_fseek(stream,position,SEEK_SET);
  return(end);
}

/*----------------------------------------------------------------------*/

static char *clean_path _AP((char* filename));

static char *clean_path(filename)
char *filename;
/* this takes out the '/../' and the '/./' from the path by modifying 
   the argument and returning it. The pathname passed to it must be a 
   full path. This is not optimized. */
{
#ifndef THINK_C
  char *beginning_ptr = strstr(filename, "/../");
  if(NULL != beginning_ptr){
    /* then we have something to process.
       reverse search for the beginning of the last directory,
       in order to snuff it */
    char *ptr;
    for(ptr = beginning_ptr - 1; ptr >= filename; ptr--){
      if(*ptr == '/'){
	/* then we found the beginning of the path */
	strcpy(ptr, beginning_ptr + strlen("/../") -1);
	clean_path(filename);	/* get the other occurances of /../ */
	break;
      }	
    }
  }
  /* now look for /./ */
  beginning_ptr = strstr(filename, "/./");
  if(NULL != beginning_ptr){
    strcpy(beginning_ptr, beginning_ptr + strlen("/./") -1);
    clean_path(filename);	/* get the other occurances of /./ */
  }
#endif				/* ndef THINK_C */

  return(filename);

}

/*----------------------------------------------------------------------*/
    
char *truename(filename,full_path)
char *filename;
char *full_path;
{
  /* this puts into full_path the full pathname including directory.
   */
#ifdef THINK_C
  strcpy(full_path, filename);
  return(full_path); /* do nothing */
#else
  if('/' == filename[0]){
    /* then it is complete already */
    strcpy(full_path, filename);
    clean_path(full_path);
    return(full_path);
  }
  else{
    getwd(full_path);
    s_strncat(full_path,"/",MAX_FILENAME_LEN,MAX_FILENAME_LEN);
    s_strncat(full_path,filename,MAX_FILENAME_LEN,MAX_FILENAME_LEN);
    clean_path(full_path);
    return(full_path);
  }
#endif /* THINK_C */
}

/*----------------------------------------------------------------------*/

char *pathname_name(pathname)
char *pathname;
/* returns a pointer to the leaf name part of full pathname.
   equivalent to common lisp pathname-name. */
{
#ifdef THINK_C
  char *answer = strrchr(pathname, ':');
#else
  char *answer = strrchr(pathname, '/');
#endif	/* THINK_C */

  if(NULL == answer)
    return(pathname);
  return(answer + 1);
}

/*----------------------------------------------------------------------*/

char *pathname_directory(pathname,destination)
char *pathname;
char *destination;
/* returns a pointer to a string of the directory part of
   the pathname and modifies its destination argument.
   This is the equivalent to the common lisp pathname-directory function. */
{
#ifdef THINK_C
  char *dirptr = strrchr(pathname, ':');
#else
  char *dirptr = strrchr(pathname, '/');
#endif /* THINK_C */

  if(NULL == dirptr)
#ifdef THINK_C
    strncpy(destination, pathname, MAX_FILE_NAME_LEN);
#else
    strncpy(destination, "./", MAX_FILENAME_LEN);
#endif /* THINK_C */
  else
    { strncpy(destination, pathname, MAX_FILE_NAME_LEN);
      destination[dirptr - pathname + 1] = '\0';
    }

  return(destination);
}
  
/*----------------------------------------------------------------------*/

/* Setting the Macintosh File type (requires the MacTraps library) */
/* from Util.c by Harry Morris */

#ifdef THINK_C

void 
setFileType(fileName,type,creator)
char* fileName;
FType type;
FType creator;
{ 
  FInfo info;
  OSErr error;
  
  CtoPstr(fileName);
  error = GetFInfo((StringPtr)fileName,0L,&info);
  if (error != noErr)
    panic("error - Can't get file type of file %s, code %ld\n",
          PtoCstr((char*)fileName),noErr);
  info.fdType = type;
  info.fdCreator = creator;
  error = SetFInfo((StringPtr)fileName,0L,&info);
  if (error != noErr)
    panic("error - Can't change file type of file %s, code %ld\n",
          PtoCstr((char*)fileName),noErr);
  PtoCstr((char*)fileName);
}

#endif /* THINK_C */

/*----------------------------------------------------------------------*/

char *current_user_name()
/* returns the current_user_name as a mail address */
{
  static char answer[200];
  char hostname[120];
  
#ifdef THINK_C
  strcpy(answer,"MAC"); /* could look up the name in the chooser */
#endif /* def THINK_C */

#ifdef M_XENIX
  strcpy(answer,"unknown"); /* could look up the name in the chooser */
#endif /* def M_XENIX */

#ifndef THINK_C
#ifndef M_XENIX

#include <pwd.h>  /* for getpwent */

  struct passwd *pwent = getpwuid(getuid());
  strncpy(answer, pwent->pw_name, 200);
  strncat(answer, "@", 200);
  gethostname(hostname, 120);
  strncat(answer, hostname, 200);

#endif /* ndef M_XENIX */
#endif /* ndef THINK_C */

  return(answer);
}

/*----------------------------------------------------------------------*/

boolean probe_file(filename)
char *filename;
/* return true if it is there, false otherwise.
   Can this be done faster? */
{
  if (filename == NULL)
    return(false);
  else if (access(filename,R_OK) == 0)
    return(true);
  else
    return(false);
}

/*----------------------------------------------------------------------*/

boolean probe_file_possibly_compressed(filename)
char *filename;
/* return true if it is there, false otherwise.
   Can this be done faster? */
{
  if (filename == NULL)
    return(false);
  else if (!probe_file(filename))
    { /* try the compression */
      char buffer[ MAX_FILENAME_LEN * 2 ];
      strcpy(buffer, filename);
      strcat(buffer, ".Z");
      return(probe_file(buffer));
    }
  else
    return(true);
}

/*----------------------------------------------------------------------*/

/* this opens the file for writing (append)p and then closes it again */
boolean touch_file(filename)
char *filename;
/* return false if error, true otherwise. */
{
  FILE *stream = NULL;
  if (filename == NULL)
    return(false);
  stream = s_fopen(filename, "a");
  if (NULL == stream)
    return(false);
  else
    { s_fclose(stream);
      return(true);
    }
}

/*----------------------------------------------------------------------*/

char *merge_pathnames(pathname, directory)
char *pathname;
char *directory;
{
  /* if the pathname is not complete, then it puts on the directory
     component and returns it in a static variable.  This is Unix specific */
  static char answer[MAX_FILENAME_LEN + 1];
  if((pathname[0] == '/') || (NULL == directory) || directory[0] == '\0')
    return(pathname);
  else{
    answer[0] = '\0';
    strncat(answer, directory, MAX_FILENAME_LEN);
#ifdef THINK_C
    if(directory[strlen(directory) - 1] != ':')
      strncat(answer, ":", MAX_FILENAME_LEN);
#else
    if(directory[strlen(directory) - 1] != '/')
      strncat(answer, "/", MAX_FILENAME_LEN);
#endif
    strncat(answer, pathname, MAX_FILENAME_LEN);
  }
  /* should this call truename? */
  return(answer);
}

/*----------------------------------------------------------------------*/


boolean 
read_string_from_file(stream,array,array_length)
FILE *stream;
char *array;
long array_length;
/* returns true if it wins. */
{
  long ch;
  long char_count = 0;

  array[0] = '\0';
  while(true){
    ch = fgetc(stream);
    if(EOF == ch){
      array[char_count] = '\0';
      return(false);
    }
    else if(char_count == array_length){	    
      array[char_count] = '\0';
      return(false);
    }
    else if('\0' == ch){
      array[char_count] = '\0';
      return(true);
    }
    else
      array[char_count++] = ch;
  }
}


/* counts the lines in a file */
long count_lines(stream)
FILE *stream;
{
  long answer = 1;
  char line[100];
  fseek(stream, 0L, SEEK_SET);	
  while(NULL != fgets(line,100L,stream))
    answer++;
  return(answer);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.