589 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			589 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* f4open.c   (c)Copyright Sequiter Software Inc., 1988-1996.  All rights reserved. */
 | 
						|
 | 
						|
#include "d4all.h"
 | 
						|
#ifdef __TURBOC__
 | 
						|
   #pragma hdrstop
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4TEMP
 | 
						|
   #include "t4test.h"
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4WINTEL
 | 
						|
   #ifndef S4IBMOS2
 | 
						|
      #ifndef __TURBOC__
 | 
						|
         #include <sys\locking.h>
 | 
						|
         #define S4LOCKING
 | 
						|
      #endif
 | 
						|
      #ifdef __ZTC__
 | 
						|
         extern int  errno ;
 | 
						|
      #endif
 | 
						|
      #ifdef _MSC_VER
 | 
						|
         #include <sys\locking.h>
 | 
						|
      #endif
 | 
						|
   #endif
 | 
						|
   #include <share.h>
 | 
						|
#endif /* S4WINTEL */
 | 
						|
 | 
						|
#include <fcntl.h>
 | 
						|
#include <errno.h>
 | 
						|
 | 
						|
#ifdef S4TRACK_FILES
 | 
						|
   extern unsigned int numFiles ;
 | 
						|
   extern int f4print ;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef S4ERRNO
 | 
						|
   extern int errno ;
 | 
						|
#endif
 | 
						|
 | 
						|
/*
 | 
						|
**  file4openLow() generic outline:
 | 
						|
**
 | 
						|
**  - clear any postive error values
 | 
						|
**  - if CODE4 is requesting read-only open, then:
 | 
						|
**    (a) mark file as read only in FILE4 structure
 | 
						|
**    (b) set the physical file open flag to read only
 | 
						|
**  - check file physically to see if file has a physical read-only attribute
 | 
						|
**    (note that this is different than only allowed to have read-only access
 | 
						|
**     for example on a network drive) --> in some configurations it is not
 | 
						|
**    possible to make this check.  But if it is true:
 | 
						|
**    (a) mark file as read only in FILE4 structure
 | 
						|
**    (b) set the physical file open flag to read only
 | 
						|
**    (c) mark the FILE4 as exclusive open (since nobody can write to it, can
 | 
						|
**        treat it as such
 | 
						|
**  - set the shared flag based on CODE4::accessMode
 | 
						|
**    3 possible settings: OPEN4DENY_NONE, OPEN4DENY_WRITE, OPEN4DENY_RW.
 | 
						|
**    return failure if no the setting is invalid.
 | 
						|
**  - physically attempt the file open
 | 
						|
**  - if the file open failed, try to determine the cause of failure and return
 | 
						|
**    the appropriate error message.  e4open is returned if the specific
 | 
						|
**    failure cannot be determined.
 | 
						|
**
 | 
						|
**  Returns: 0 = success, e4... = failure (appropriate error condition)
 | 
						|
**
 | 
						|
**  Notes:
 | 
						|
**     This routine shouldn't generate a CodeBase error
 | 
						|
*/
 | 
						|
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
/* */
 | 
						|
#ifdef S4UNIX
 | 
						|
static int file4openLow( FILE4 *file, CODE4 *c4, const char *name )
 | 
						|
{
 | 
						|
   int rc = 0 ;
 | 
						|
   int oflag ;
 | 
						|
   #ifdef S4NO_FLOCK
 | 
						|
      struct flock lck;
 | 
						|
 | 
						|
      lck.l_whence = SEEK_SET ;
 | 
						|
      lck.l_start = 0 ;
 | 
						|
      lck.l_len = 1000000000 ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   error4set( c4, 0 ) ;  /* clear positive error values */
 | 
						|
 | 
						|
   if ( c4->readOnly == 1 )
 | 
						|
   {
 | 
						|
      file->isReadOnly = 1 ;
 | 
						|
      oflag = (int)O_RDONLY ;
 | 
						|
   }
 | 
						|
   else
 | 
						|
      oflag = (int)O_RDWR ;
 | 
						|
 | 
						|
 | 
						|
   file->hand = open( name, oflag ) ;
 | 
						|
 | 
						|
   switch ( c4->accessMode )
 | 
						|
   {
 | 
						|
      case OPEN4DENY_NONE:
 | 
						|
      case OPEN4DENY_WRITE:
 | 
						|
         #ifndef S4NO_FLOCK
 | 
						|
            rc = flock (file->hand, LOCK_SH|LOCK_NB) ;
 | 
						|
         #else
 | 
						|
            lck.l_type = F_RDLCK ;
 | 
						|
            rc = fcntl (file->hand, F_SETLK, &lck ) ;
 | 
						|
         #endif
 | 
						|
         break;
 | 
						|
      case OPEN4DENY_RW:
 | 
						|
         #ifndef S4NO_FLOCK
 | 
						|
            rc = flock (file->hand, LOCK_EX|LOCK_NB) ;
 | 
						|
         #else
 | 
						|
            lck.l_type = F_WRLCK ;
 | 
						|
            rc = fcntl (file->hand, F_SETLK, &lck ) ;
 | 
						|
         #endif
 | 
						|
         break;
 | 
						|
      default:
 | 
						|
         close(file->hand);
 | 
						|
         file->hand = -1;
 | 
						|
         return e4open;
 | 
						|
   }
 | 
						|
 | 
						|
   if (rc!=0)
 | 
						|
      return e4open;
 | 
						|
 | 
						|
   if ( file->hand < 0 )
 | 
						|
   {
 | 
						|
      /* note:  getting error classification is required to allow for
 | 
						|
         occasional recovery from exceeded file handle problems */
 | 
						|
      switch( errno )  /* try to get some clarification on the error */
 | 
						|
      {
 | 
						|
         case EACCES:
 | 
						|
            return e4permiss ;
 | 
						|
         case EMFILE:   /* allow try closing excess files and retrying */
 | 
						|
            return e4numFiles ;
 | 
						|
         case ENOENT:
 | 
						|
            return e4fileFind ;
 | 
						|
         default:
 | 
						|
            return e4open ;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
#endif /* S4UNIX */
 | 
						|
 | 
						|
#ifdef S4WIN32
 | 
						|
static int file4openLow( FILE4 *file, CODE4 *c4, const char *name )
 | 
						|
{
 | 
						|
   DWORD fdwAccess, fdwShareMode, fAttributes ;
 | 
						|
 | 
						|
   error4set( c4, 0 ) ;  /* clear positive error values */
 | 
						|
 | 
						|
   fAttributes = GetFileAttributes( name ) ;
 | 
						|
   if ( fAttributes != 0xFFFFFFFF && fAttributes & FILE_ATTRIBUTE_READONLY )
 | 
						|
   {
 | 
						|
      file->isReadOnly = 1 ;
 | 
						|
      fdwAccess = GENERIC_READ ;
 | 
						|
      #ifndef S4OFF_MULTI
 | 
						|
         file->lowAccessMode = OPEN4DENY_RW ;  /* for a file read-only can treat as exclusive */
 | 
						|
      #endif
 | 
						|
   }
 | 
						|
   else
 | 
						|
   {
 | 
						|
      if ( c4->readOnly == 1 )
 | 
						|
      {
 | 
						|
         file->isReadOnly = 1 ;
 | 
						|
         fdwAccess = GENERIC_READ ;
 | 
						|
      }
 | 
						|
      else
 | 
						|
         fdwAccess = GENERIC_WRITE | GENERIC_READ ;
 | 
						|
   }
 | 
						|
 | 
						|
   #ifdef S4OFF_MULTI
 | 
						|
      #ifdef E4DEBUG
 | 
						|
         /* open in shared mode for debugging to allow other programs to examine */
 | 
						|
         fdwShareMode = FILE_SHARE_WRITE | FILE_SHARE_READ ;
 | 
						|
      #else
 | 
						|
         /* otherwise, if single-user, file should be opened exclusively */
 | 
						|
         fdwShareMode = 0 ;
 | 
						|
      #endif
 | 
						|
   #else
 | 
						|
      switch( c4->accessMode )
 | 
						|
      {
 | 
						|
         case OPEN4DENY_NONE:
 | 
						|
            fdwShareMode = FILE_SHARE_WRITE | FILE_SHARE_READ ;
 | 
						|
            break ;
 | 
						|
         case OPEN4DENY_WRITE:
 | 
						|
            fdwShareMode = FILE_SHARE_READ ;
 | 
						|
            break ;
 | 
						|
         case OPEN4DENY_RW:
 | 
						|
            fdwShareMode = 0 ;
 | 
						|
            break ;
 | 
						|
         default:
 | 
						|
            file->hand = -1 ;
 | 
						|
            return e4open ;
 | 
						|
      }
 | 
						|
   #endif  /* S4OFF_MULTI */
 | 
						|
   file->hand = (int) CreateFile( name, fdwAccess, fdwShareMode, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 ) ;
 | 
						|
 | 
						|
   if ( file->hand == (int)INVALID_HANDLE_VALUE )
 | 
						|
   {
 | 
						|
      /* note:  getting error classification is required to allow for
 | 
						|
         occasional recovery from exceeded file handle problems */
 | 
						|
      switch( errno )  /* try to get some clarification on the error */
 | 
						|
      {
 | 
						|
         case EACCES:
 | 
						|
            return e4permiss ;
 | 
						|
         #ifdef __TURBOC__
 | 
						|
            case EINVACC:
 | 
						|
               return e4access ;
 | 
						|
         #endif
 | 
						|
         case EMFILE:   /* allow try closing excess files and retrying */
 | 
						|
            return e4numFiles ;
 | 
						|
         case ENOENT:
 | 
						|
            return e4fileFind ;
 | 
						|
         default:
 | 
						|
            return e4open ;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   #ifdef S4MULTI_THREAD
 | 
						|
      InitializeCriticalSection( &file->critical4file ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef S4ADVANCE_READ
 | 
						|
      file->advanceReadBufStatus = AR4EMPTY ;
 | 
						|
   #endif
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
#endif /* S4WIN32 */
 | 
						|
 | 
						|
#ifdef S4WIN16
 | 
						|
static int file4openLow( FILE4 *file, CODE4 *c4, const char *name )
 | 
						|
{
 | 
						|
   int oflag, sMode ;
 | 
						|
 | 
						|
   error4set( c4, 0 ) ;  /* clear positive error values */
 | 
						|
 | 
						|
   /* check the file's dos read only attrib -- which improves performance */
 | 
						|
   if ( c4->readOnly == 1 )
 | 
						|
   {
 | 
						|
      file->isReadOnly = 1 ;
 | 
						|
      oflag = (int)OF_READ ;
 | 
						|
   }
 | 
						|
   else
 | 
						|
      oflag = (int)OF_READWRITE ;
 | 
						|
 | 
						|
   #ifdef S4OFF_MULTI
 | 
						|
      #ifdef E4DEBUG
 | 
						|
         /* open in shared mode for debugging to allow other programs to examine */
 | 
						|
         sMode = (int)OF_SHARE_DENY_NONE ;
 | 
						|
      #else
 | 
						|
         /* otherwise, if single-user, file should be opened exclusively */
 | 
						|
         sMode = (int)OF_SHARE_EXCLUSIVE ;
 | 
						|
      #endif
 | 
						|
   #else
 | 
						|
      switch( c4->accessMode )
 | 
						|
      {
 | 
						|
         case OPEN4DENY_NONE:
 | 
						|
            sMode = (int)OF_SHARE_DENY_NONE ;
 | 
						|
            break ;
 | 
						|
         case OPEN4DENY_WRITE:
 | 
						|
            sMode = (int)OF_SHARE_DENY_WRITE ;
 | 
						|
            break ;
 | 
						|
         case OPEN4DENY_RW:
 | 
						|
            sMode = (int)OF_SHARE_EXCLUSIVE ;
 | 
						|
            break ;
 | 
						|
         default:
 | 
						|
            file->hand = -1 ;
 | 
						|
            return e4open ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   file->hand = _lopen( name, oflag | sMode ) ;
 | 
						|
   if ( file->hand < 0 )
 | 
						|
   {
 | 
						|
      /* note:  getting error classification is required to allow for
 | 
						|
         occasional recovery from exceeded file handle problems */
 | 
						|
      switch( errno )  /* try to get some clarification on the error */
 | 
						|
      {
 | 
						|
         case EACCES:
 | 
						|
            return e4permiss ;
 | 
						|
         #ifdef __TURBOC__
 | 
						|
            case EINVACC:
 | 
						|
               return e4access ;
 | 
						|
         #endif
 | 
						|
         case EMFILE:   /* allow try closing excess files and retrying */
 | 
						|
            return e4numFiles ;
 | 
						|
         case ENOENT:
 | 
						|
            return e4fileFind ;
 | 
						|
         default:
 | 
						|
            return e4open ;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
#endif /* S4WIN16 */
 | 
						|
 | 
						|
#ifdef S4WINTEL
 | 
						|
#ifndef S4WIN16
 | 
						|
#ifndef S4WIN32
 | 
						|
 | 
						|
#ifndef S4OS2
 | 
						|
   #ifdef __TURBOC__
 | 
						|
      #define S4USE_CHMOD
 | 
						|
   #endif
 | 
						|
   #ifdef _MSC_VER
 | 
						|
      #define S4USE_CHMOD
 | 
						|
   #endif
 | 
						|
#endif
 | 
						|
 | 
						|
static int file4openLow( FILE4 *file, CODE4 *c4, const char *name )
 | 
						|
{
 | 
						|
   #ifdef _MSC_VER
 | 
						|
      #ifdef S4USE_CHMOD
 | 
						|
         unsigned attribute ;
 | 
						|
      #endif
 | 
						|
   #endif
 | 
						|
   int oflag, shflag ;
 | 
						|
 | 
						|
   error4set( c4, 0 ) ;  /* clear positive error values */
 | 
						|
 | 
						|
   /* check the file's dos read only attrib -- which improves performance */
 | 
						|
   #ifdef S4USE_CHMOD
 | 
						|
      errno = 0 ;
 | 
						|
      #ifdef __TURBOC__
 | 
						|
         if ( _A_RDONLY & _chmod( name, 0 ) )
 | 
						|
      #endif
 | 
						|
      #ifdef _MSC_VER
 | 
						|
         _dos_getfileattr( name, &attribute ) ;
 | 
						|
         if (_A_RDONLY & attribute )
 | 
						|
      #endif
 | 
						|
      {
 | 
						|
         if ( errno == ENOENT )  /* file doesn't exist */
 | 
						|
         {
 | 
						|
            file->hand = -1 ;
 | 
						|
            if ( c4->errOpen )
 | 
						|
               return e4open ;
 | 
						|
         }
 | 
						|
         file->isReadOnly = 1 ;
 | 
						|
         #ifndef S4OFF_MULTI
 | 
						|
            file->lowAccessMode = OPEN4DENY_RW ;  /* for a file read-only can treat as exclusive */
 | 
						|
         #endif
 | 
						|
         oflag = (int)(O_BINARY | O_RDONLY) ;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
   #endif
 | 
						|
         if ( c4->readOnly == 1 )
 | 
						|
         {
 | 
						|
            file->isReadOnly = 1 ;
 | 
						|
            oflag = (int)(O_BINARY | O_RDONLY) ;
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            oflag = (int)(O_BINARY | O_RDWR) ;
 | 
						|
         }
 | 
						|
   #ifdef S4USE_CHMOD
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef S4OFF_MULTI
 | 
						|
      shflag = SH_DENYRW ;
 | 
						|
   #else
 | 
						|
      switch ( c4->accessMode )
 | 
						|
      {
 | 
						|
         case OPEN4DENY_NONE:
 | 
						|
            shflag = SH_DENYNO ;
 | 
						|
            break ;
 | 
						|
         case OPEN4DENY_WRITE:
 | 
						|
            shflag = SH_DENYWR ;
 | 
						|
            break ;
 | 
						|
         case OPEN4DENY_RW:
 | 
						|
            shflag = SH_DENYRW ;
 | 
						|
            break ;
 | 
						|
         default:
 | 
						|
            file->hand = -1 ;
 | 
						|
            return e4open ;
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   file->hand = sopen( name, oflag, shflag, 0 ) ;
 | 
						|
 | 
						|
   if ( file->hand < 0 )
 | 
						|
   {
 | 
						|
      /* note:  getting error classification is required to allow for
 | 
						|
         occasional recovery from exceeded file handle problems */
 | 
						|
      switch( errno )  /* try to get some clarification on the error */
 | 
						|
      {
 | 
						|
         case EACCES:
 | 
						|
            return e4permiss ;
 | 
						|
         #ifdef __TURBOC__
 | 
						|
            case EINVACC:
 | 
						|
               return e4access ;
 | 
						|
         #endif
 | 
						|
         case EMFILE:   /* allow try closing excess files and retrying */
 | 
						|
            return e4numFiles ;
 | 
						|
         case ENOENT:
 | 
						|
            return e4fileFind ;
 | 
						|
         default:
 | 
						|
            return e4open ;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   return 0 ;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef S4USE_CHMOD
 | 
						|
   #undef S4USE_CHMOD
 | 
						|
#endif
 | 
						|
 | 
						|
#endif /* S4WIN32 */
 | 
						|
#endif /* S4WIN16 */
 | 
						|
#endif /* S4WINTEL */
 | 
						|
 | 
						|
int S4FUNCTION file4open( FILE4 *file, CODE4 *c4, S4CONST char *name, const int doAlloc )
 | 
						|
{
 | 
						|
   int rc, len ;
 | 
						|
 | 
						|
   #ifdef E4PARM_HIGH
 | 
						|
      if ( file == 0 || c4 == 0 || name == 0 )
 | 
						|
         return error4( c4, e4parm, E90615 ) ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( error4code( c4 ) < 0 )
 | 
						|
      return e4codeBase ;
 | 
						|
 | 
						|
   #ifndef S4OPTIMIZE_OFF
 | 
						|
      code4memStartMaxSet( c4, c4->memMaxPercent ) ;  /* start optimization if not enabled and not suspended */
 | 
						|
   #endif
 | 
						|
 | 
						|
   memset( (void *)file, 0, sizeof( FILE4 ) ) ;
 | 
						|
   file->codeBase = c4 ;
 | 
						|
   file->hand = -1 ;
 | 
						|
 | 
						|
   rc = file4openLow( file, c4, name ) ;
 | 
						|
 | 
						|
   #ifdef S4SERVER
 | 
						|
      if ( rc != 0 )
 | 
						|
      {
 | 
						|
         if ( rc != 0 && rc != e4fileFind && rc != e4permiss && rc != e4access )
 | 
						|
         {
 | 
						|
            error4set( c4, 0 ) ;
 | 
						|
            rc = code4dataFileCloseAll( c4 ) ;
 | 
						|
            if ( rc < 0 )
 | 
						|
               return rc ;
 | 
						|
            rc = file4openLow( file, c4, name ) ;
 | 
						|
         }
 | 
						|
         if ( c4->readOnly == 0 && c4->readOnlyRequest == 1 )   /* try opening in read-only mode */
 | 
						|
         {
 | 
						|
            error4set( c4, 0 ) ;
 | 
						|
            c4->readOnly = 1 ;
 | 
						|
            rc = file4openLow( file, c4, name ) ;
 | 
						|
            c4->readOnly = 0 ;
 | 
						|
         }
 | 
						|
      }
 | 
						|
   #endif
 | 
						|
 | 
						|
   if ( rc != 0 )
 | 
						|
   {
 | 
						|
      if ( c4->errOpen )
 | 
						|
         return error4describe( c4, rc, E90615, name, (char *) 0, (char *) 0 ) ;
 | 
						|
      else
 | 
						|
      {
 | 
						|
         error4set( c4, r4noOpen ) ;
 | 
						|
         return r4noOpen ;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   if ( doAlloc )
 | 
						|
   {
 | 
						|
      len = strlen( name ) + 1 ;
 | 
						|
      file->nameBuf = (char *)u4allocFree( c4, (long)len ) ;
 | 
						|
      if ( file->nameBuf == 0 )
 | 
						|
      {
 | 
						|
         file4close( file ) ;
 | 
						|
         return error4( c4, e4memory, E90615 ) ;
 | 
						|
      }
 | 
						|
      file->doAllocFree = 1 ;
 | 
						|
      u4ncpy( file->nameBuf, name, (unsigned int)len ) ;
 | 
						|
      file->name = file->nameBuf ;
 | 
						|
   }
 | 
						|
   else
 | 
						|
      file->name = name ;
 | 
						|
 | 
						|
   #ifndef S4OFF_MULTI
 | 
						|
      file->lowAccessMode = c4->accessMode ;
 | 
						|
   #endif
 | 
						|
   #ifndef S4OPTIMIZE_OFF
 | 
						|
      file->fileCreated = 1 ;
 | 
						|
   #endif
 | 
						|
 | 
						|
   #ifdef S4TRACK_FILES
 | 
						|
      numFiles++ ;
 | 
						|
      if ( f4print != -1 )
 | 
						|
      {
 | 
						|
          #ifdef S4WINDOWS
 | 
						|
             #ifdef S4TESTING
 | 
						|
                if ( mem4displayPtr == 0 )
 | 
						|
                   error4( 0, e4info, E50101 ) ;
 | 
						|
                d4display_str( mem4displayPtr, "\r\nfile opened: ", 1 ) ;
 | 
						|
                d4display_str( mem4displayPtr, f4print, file->name ) ;
 | 
						|
             #else
 | 
						|
                u4writeErr( "file opened: ", 1 ) ;
 | 
						|
                u4writeErr( file->name, 0 ) ;
 | 
						|
             #endif
 | 
						|
          #else
 | 
						|
             if ( f4print )
 | 
						|
                fprintf( stdprn, "\r\nfile opened: %s", file->name ) ;
 | 
						|
             else
 | 
						|
                printf( "\r\nfile opened: %s", file->name ) ;
 | 
						|
          #endif
 | 
						|
       }
 | 
						|
   #endif
 | 
						|
 | 
						|
   return rc ;
 | 
						|
}
 | 
						|
 | 
						|
int S4FUNCTION file4openTest( FILE4 *f4 )
 | 
						|
{
 | 
						|
   return f4->hand >= 0 ;
 | 
						|
}
 |