/*********************************************************************
d4port.c   (c)Copyright Sequiter Software Inc., 1996.
All rights reserved.

This example test program tests low-level functions.

*********************************************************************/

#include "d4port.h"

int main()
{
   long lenl ;
   int  lens ;
   long bscheckl = 2020175445;
   int  bschecks = 2020175445;
   unsigned char testBuf[5] ;
   unsigned char testunix[17], testxinu[5], testnuxi[5] ;
   char teststr[6] ;


   int  rc, myfile, i, status ;
   int bigbits =0;                  /*boolean*/
   int iserror = EXIT_SUCCESS ;
   char ch ;
   pid_t pid;
   double powc, powc2,atofcheck;
   const double value = 9.876 ;
   size_t size_var = 1;
   char strtest[15];
   char *str;
   int dec, sign;
   #ifndef S4NO_FTIME
      struct timeb tp ;
   #else
      struct timeval tp;
   #endif


   setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
/*S464BIT*************************************************/
   if (sizeof(long) == 8)
   {
      bigbits = 1 ;
      fprintf(stdout, "   #define S464BIT\n");
   }
   else if (sizeof(long) == 4)
      fprintf(stdout, "/* #define S464BIT            */\n");
   else
   {
      fprintf(stderr, "ERROR: Unknown bit system\n");
      iserror = EXIT_FAILURE ;
   }

/*S4BYTEORDER_3210****************************************/
/*S4BYTEORDER_2301****************************************/

   if (bigbits)
   {
      lens = 0x01020408 ;
      memcpy( testBuf, (void *)&lens, 4 ) ;
   }
   else
   {
      lenl = 0x01020408 ;
      memcpy( testBuf, (void *)&lenl, 4 ) ;
   }

   memcpy( testunix, "\001\002\004\010", 4 ) ;   /* S4BYTEORDER_3210 */
   memcpy( testnuxi, "\002\001\010\004", 4 ) ;   /* S4BYTEORDER_2301 */
   memcpy( testxinu, "\010\004\002\001", 4 ) ;   /* default */

   if ( memcmp( testunix , testBuf, 4 ) )
      if ( memcmp( testnuxi , testBuf, 4 ) )
         if ( memcmp( testxinu , testBuf, 4 ) )
         {
            fprintf(stderr, "ERROR: Unknown byte ordering\n");
            iserror = EXIT_FAILURE ;
         }
         else
         {
            fprintf(stdout, "/* #define S4BYTEORDER_2301   */\n");
            fprintf(stdout, "/* #define S4BYTEORDER_3210   */\n");
         }
      else
      {
         fprintf(stdout, "   #define S4BYTEORDER_2301   \n");
         fprintf(stdout, "/* #define S4BYTEORDER_3210   */\n");
      }
   else
   {
      fprintf(stdout, "/* #define S4BYTEORDER_2301   */\n");
      fprintf(stdout, "   #define S4BYTEORDER_3210   \n");
   }

/*S4BYTE_SWAP*********************************************/
/*OPENING FILE********************************************/
   myfile = open("d4test", O_RDWR|O_CREAT|O_TRUNC, 0666);
   if ( myfile < 0 )
   {
      fprintf(stderr, "ERROR: Function open() is failing with 'O_CREAT | O_TRUNC | O_RDWR'\n" );
      iserror = EXIT_FAILURE ;
      switch ( (int) errno )
      {
      case EACCES :
         fprintf(stderr, "ERRNO == EACCES: Permission denied\n" ) ;
         break ;
      case EINVAL :
         fprintf(stderr, "ERRNO == EINVAL: Invalid mode and permission setting\n" ) ;
         break ;
      case EEXIST :
         fprintf(stderr, "ERRNO == EEXIST: O_CREAT and O_EXCL specified but file already exists\n" );
         break ;
      case EMFILE :
         fprintf(stderr, "ERRNO == EMFILE: No more file handles available\n" ) ;
         break ;
      case ENOENT :
         fprintf(stderr, "ERRNO == ENOENT: File not found or directory not present\n" ) ;
         break ;
      default:
         fprintf(stderr, "ERRNO VALUE NOT RECOGNIZED\n" ) ;
      }
   }
   rc = lseek( myfile, 10, SEEK_SET ) ;
   if ( rc != 10 )
   {
      fprintf(stderr, "ERROR: Function lseek() is failing to seek past EOF(1)\n" );
      iserror = EXIT_FAILURE ;
      switch ( (int) errno )
      {
      case EBADF :
         fprintf(stderr, "ERRNO == EBADF: file handle is invalid\n" ) ;
         break ;
      case EINVAL :
         fprintf(stderr, "ERRNO == EINVAL: Invalid mode and permission setting\n" ) ;
         break ;
      default:
         fprintf(stderr, "ERRNO VALUE NOT RECOGNIZED\n" ) ;
      }
   }
   if (bigbits)
      rc = write(myfile, &bschecks, 4)  ;
   else
      rc = write(myfile, &bscheckl, 4)  ;
   if ( rc != 4 )
   {
      fprintf(stderr, "ERROR: Function write() is failing to write past EOF\n" );
      iserror = EXIT_FAILURE ;
      switch ( (int) errno )
      {
      case EBADF :
         fprintf(stderr, "ERRNO == EBADF: file handle is invalid\n" ) ;
         break ;
      case ENOSPC :
         fprintf(stderr, "ERRNO == ENOSPC: system out of disk space\n" ) ;
         break ;
      default:
         fprintf(stderr, "ERRNO VALUE NOT RECOGNIZED\n" ) ;
      }
   }
   rc = filelen(myfile);
   if(rc != 14)
   {
      fprintf(stderr, "ERROR: File length is incorrect(1)\n");
      iserror = EXIT_FAILURE ;
   }
   lseek(myfile, 10, SEEK_SET ) ;
   for (i=0; i<4; i++)
   {
      rc=read(myfile,&teststr[i],size_var);
      if (rc!=1)
      {
          fprintf(stderr, "ERROR: Problems reading from the file.\nUnable to continue\n");
          iserror = EXIT_FAILURE ;
          break;
      }
   }
   if (strncmp(teststr, "Unix",4) )
      if (strncmp(teststr, "xinU",4) )
      {
         fprintf(stderr, "ERROR: Writing error\n");
         iserror = EXIT_FAILURE ;
      }
      else
         fprintf(stdout,"   #define S4BYTE_SWAP\n");
   else
      fprintf(stdout,"/* #define S4BYTE_SWAP        */\n");

   rc = close( myfile ) ;
   if ( rc < 0 )
   {
      fprintf(stderr, "ERROR: Closing file(1)\n");
      iserror = EXIT_FAILURE ;
      switch ( (int) errno )
      {
      case EBADF :
         fprintf(stderr, "ERRNO == EBADF: file handle is invalid\n" ) ;
         break ;
      default:
         fprintf(stderr, "ERRNO VALUE NOT RECOGNIZED\n" ) ;
      }
   }

   myfile = open( "d4test", O_RDWR , 0666 ) ;
   if ( myfile < 0 )
   {
      fprintf(stderr, "ERROR: function open() is failing with 'O_RDWR'\n");
      iserror = EXIT_FAILURE ;
      switch ( (int) errno )
      {
      case EACCES :
         fprintf(stderr, "ERRNO == EACCES: Permission denied\n" ) ;
         break ;
      case EINVAL :
         fprintf(stderr, "ERRNO == EINVAL: Invalid mode and permission setting\n" ) ;
         break ;
      case EEXIST :
         fprintf(stderr, "ERRNO == EEXIST: O_CREAT and O_EXCL specified but file already exists\n" );
         break ;
      case EMFILE :
         fprintf(stderr, "ERRNO == EMFILE: No more file handles available\n" ) ;
         break ;
      case ENOENT :
         fprintf(stderr, "ERRNO == ENOENT: File not found or directory not present\n" ) ;
         break ;
      default:
         fprintf(stderr, "ERRNO VALUE NOT RECOGNIZED\n" ) ;
      }
   }

/*Checking filelength(2)*************************************/
   rc = filelen(myfile);
   if(rc != 14)
   {
      fprintf(stderr, "ERROR: File length is incorrect(2)\n");
      iserror = EXIT_FAILURE ;
   }
   #ifndef S4NO_CHSIZE
      rc=chsize(myfile, 200);
   #else
      rc=ftruncate(myfile, 200);
   #endif
   if ( rc < 0 )
   {
      fprintf(stderr, "\nERROR: Changing file size \n" ) ;
      iserror = EXIT_FAILURE ;
   }

   rc = filelen(myfile);
   if(rc != 200)
   {
      fprintf(stderr, "ERROR: File length is incorrect(3)\n");
      iserror = EXIT_FAILURE ;
   }

   rc = lseek( myfile, T4LOCK_POS, 0 ) ;
   if ( rc != T4LOCK_POS )
   {
      fprintf(stderr, "ERROR: Function lseek() is failing to seek past EOF(2)\n" );
      iserror = EXIT_FAILURE ;
      switch ( (int) errno )
      {
      case EBADF :
         fprintf(stderr, "ERRNO == EBADF: file handle is invalid\n" ) ;
         break ;
      case EINVAL :
         fprintf(stderr, "ERRNO == EINVAL: Invalid mode and permission setting\n" ) ;
         break ;
      default:
         fprintf(stderr, "ERRNO VALUE NOT RECOGNIZED\n" ) ;
      }
   }

   #ifdef S4LOCKF
      rc = lockf( myfile, F_TLOCK, 1 ) ;
   #else
      rc = locking( myfile, LK_NBLCK, 1 ) ;
   #endif
   if ( rc < 0 )
   {
      iserror = EXIT_FAILURE ;
      fprintf(stderr, "ERROR: Function lock() is failing to lock past EOF\n" );
      switch ( (int) errno )
      {
      case EBADF :
         fprintf(stderr, "ERRNO == EBADF: file handle is invalid\n" ) ;
         break ;
      case EINVAL :
         fprintf(stderr, "ERRNO == EINVAL: Invalid mode and permission setting\n" ) ;
         break ;
      default:
         fprintf(stderr, "ERRNO VALUE NOT RECOGNIZED\n" ) ;
      }
   }
   rc = lseek( myfile, T4LOCK_POS, 0 ) ;
   if ( rc != T4LOCK_POS )
   {
      fprintf(stderr,"ERROR: Function lseek() is failing to seek past EOF(3)\n" );
      iserror = EXIT_FAILURE ;
      switch ( (int) errno )
      {
      case EBADF :
         fprintf(stderr, "ERRNO == EBADF: file handle is invalid\n" ) ;
         break ;
      case EINVAL :
         fprintf(stderr, "ERRNO == EINVAL: Invalid mode and permission setting\n" ) ;
         break ;
      default:
         fprintf(stderr, "ERRNO VALUE NOT RECOGNIZED\n" ) ;
      }
   }

   #ifdef S4LOCKF
      rc = lockf( myfile, F_ULOCK, 1 ) ;
   #else
      rc = locking( myfile, LK_UNLCK, 1 ) ;
   #endif
   if ( rc < 0 )
   {
      fprintf(stderr, "ERROR: Function unlock() is failing to unlock file\n" );
      iserror = EXIT_FAILURE ;
      switch ( (int) errno )
      {
      case EBADF :
         fprintf(stderr, "ERRNO == EBADF: file handle is invalid\n" ) ;
         break ;
      case EINVAL :
         fprintf(stderr, "ERRNO == EINVAL: Invalid mode and permission setting\n" ) ;
         break ;
      default:
         fprintf(stderr, "ERRNO VALUE NOT RECOGNIZED\n" ) ;
      }
   }


/*S4NO_NEGATIVE_LOCK**************************************/
   rc = lseek(myfile, -10, SEEK_SET );    /*rc should = -10 */
   #ifdef S4LOCKF
      rc = lockf( myfile, F_LOCK, 5 ) ;
   #else
      rc = locking( myfile, LK_NBLCK, 5 ) ;
   #endif
   if (rc != 0 )
   {
      fprintf(stderr, "ERROR: Locking\n");
      iserror = EXIT_FAILURE ;
   }
   if ( (pid=fork()) <0)
   {
      fprintf(stderr, "ERROR: Fork(1)\n");
      iserror = EXIT_FAILURE ;
   }
   else if (pid == 0)
   {
      int lockfail = 0;

      rc = lseek(myfile, -15, SEEK_SET );    /*rc should = -15 */
      #ifdef S4LOCKF
         rc = lockf( myfile, F_TLOCK, 3 ) ;
      #else
         rc = locking( myfile, LK_NBLCK, 3 ) ;
      #endif
      if (rc < 0 )
          lockfail = 1;
      rc = lseek(myfile, 0, SEEK_SET );    /*rc should = 0 */
      #ifdef S4LOCKF
         rc = lockf( myfile, F_TLOCK, 5 ) ;
      #else
         rc = locking( myfile, LK_NBLCK, 5 ) ;
      #endif
      if (rc != 0 )
         lockfail = 1;
      exit(lockfail) ;
   }
   while(wait(&status)!=pid)
      ;
   if ((WIFEXITED(status)==0))
   {
      fprintf(stderr, "ERROR: Fork(2)\n");
      iserror = EXIT_FAILURE ;
   }
   if (WEXITSTATUS(status))
      fprintf(stdout,"   #define S4NO_NEGATIVE_LOCK  \n");
   else
      fprintf(stdout,"/* #define S4NO_NEGATIVE_LOCK */\n");


   rc = close( myfile ) ;
   if ( rc < 0 )
   {
      fprintf(stderr, "ERROR: Closing file(2)\n");
      iserror = EXIT_FAILURE ;
      switch ( (int) errno )
      {
      case EBADF :
         fprintf(stderr, "ERRNO == EBADF: file handle is invalid\n" ) ;
         break ;
      default:
         fprintf(stderr, "ERRNO VALUE NOT RECOGNIZED\n" ) ;
      }
   }

/*S4DATA_ALIGN************************************************/
/*   testunix[1]='U';*/
   /*testunix[2]='n';*/
   /*testunix[3]='i';*/
   /*testunix[4]='x';*/
   /*if (signal(SIGBUS, sig_bus) == SIG_ERR)*/
   /*{*/
      /*fprintf(stderr, "ERROR: Unable to catch bus errors\n");*/
      /*iserror = EXIT_FAILURE ;*/
   /*}*/
   /*bscheckl = *((long *)(testunix+1));*/
   /*if (!buserr)*/
      /*fprintf(stdout, "/ #define S4DATA_ALIGN       /\n");*/
        fprintf(stdout, "   #define S4DATA_ALIGN\n"); 

/*S4MEMCMP************************************************/
   rc = memcmp( "\320", "\120", 1 ) ;
   if (rc <= 0)   /* memcmp assumes signed bytes -- not usable */
      fprintf(stdout,"   #define S4MEMCMP\n");
   else
      fprintf(stdout,"/* #define S4MEMCMP           */\n");

/*Checking for unsigned bytes*******************************/
   ch = -5 ;
   if ( ch != -5 )
   {
      fprintf(stderr, "ERROR: compiled using unsigned byte default\n" ) ;
      fprintf(stderr, "See your compiler documentation for\n" ) ;
      fprintf(stderr, "'signed byte compilation' information.\n" ) ;
      iserror = EXIT_FAILURE ;
   }


/***********************************************************/
   fprintf(stdout, "\n");


/*S4LOCKF****************************************************/
   #ifndef S4LOCKF
      fprintf(stdout, "/* #define S4LOCKF           */\n");
   #else
      fprintf(stdout, "   #define S4LOCKF\n");
   #endif

/*S4NO_ATOF**************************************************/
   #ifndef S4NO_ATOF
      fprintf(stdout, "/* #define S4NO_ATOF          */\n");
      atofcheck = atof("-152.5e1gobbledigook");
      if (atofcheck != -1525)
      {
         fprintf(stderr, "ERROR: atof() does not produce a correct result\n");
         iserror = EXIT_FAILURE ;
      }
   #else
      fprintf(stdout, "   #define S4NO_ATOF\n");
   #endif

/*S4NO_CHSIZE************************************************/
   #ifndef S4NO_CHSIZE
      fprintf(stdout, "/* #define S4NO_CHSIZE        */\n");
   #else
      fprintf(stdout, "   #define S4NO_CHSIZE\n");
   #endif

/*S4NO_ECVT****************************************************/
   #ifndef S4NO_ECVT
      str=ecvt(value, 10, &dec, &sign);
      if (strncmp(str,"98760000",8))
      {
         fprintf(stderr,"ERROR: ecvt() returned incorrect results\n");
         iserror = EXIT_FAILURE ;
      }
      fprintf(stdout,"/* #define S4NO_ECVT          */\n");
   #else
      fprintf(stdout,"   #define S4NO_ECVT\n");
   #endif

/*S4NO_FCVT****************************************************/
   #ifndef S4NO_FCVT
      str= fcvt(value, 5, &dec, &sign);
      if (strncmp(str, "987600",6))
      {
         fprintf(stderr, "ERROR: fcvt() returned incorrect results\n");
         iserror = EXIT_FAILURE ;
      }
      fprintf(stdout,"/* #define S4NO_FCVT          */\n");
   #else
      fprintf(stdout,"   #define S4NO_FCVT\n");
   #endif

/*S4NO_FILELENGTH********************************************/
   #ifndef S4NO_FILELENGTH
      fprintf(stdout, "/* #define S4NO_FILELENGTH    */\n");
   #else
      fprintf(stdout, "   #define S4NO_FILELENGTH\n");
   #endif

/*S4NO_FTIME*************************************************/
   #ifndef S4NO_FTIME
      ftime(&tp);
      fprintf(stdout, "/* #define S4NO_FTIME         */\n");
   #else
      gettimeofday(&tp, NULL);
      fprintf(stdout, "   #define S4NO_FTIME\n");
   #endif

/*S4NO_MEMMOVE***********************************************/
   #ifndef S4NO_MEMMOVE 
      strcpy(strtest, "unixxxxxxx");
      memmove(&strtest[2], &strtest[0],4);
      if (strcmp(strtest, "ununixxxxx"))
      {
         fprintf(stdout,"   #define S4NO_MEMMOVE\n");
      }
      else
      {
         strcpy(strtest, "xxxxxxunix");
         memmove(&strtest[4], &strtest[6],4);
         if (strcmp(strtest, "xxxxunixix"))
         {
            fprintf(stdout,"   #define S4NO_MEMMOVE\n");
         }
         else
             fprintf(stdout,"/* #define S4NO_MEMMOVE       */\n");
      }
   #else
      fprintf(stdout,"/* #define S4NO_MEMMOVE       */\n");
   #endif

/*S4NO_POW***************************************************/
   #ifndef S4NO_POW
      powc = pow(10.0, 2.0);
      if (powc == 100.0)
         fprintf(stdout,"/* #define S4NO_POW           */\n");
      else
      {
         powc2 = floor(powc + 0.5);
         if (powc2 == 100.0)
            fprintf(stdout,"/* #define S4NO_POW           */ /* Not 100%% precise */\n");
         else
            fprintf(stdout,"   #define S4NO_POW\n");
      }
   #else
      fprintf(stdout, "#define S4NO_POW\n");
   #endif

/*S4NO_RENAME**************************************************/
   #ifndef S4NO_RENAME
      fprintf(stdout, "/* #define S4NO_RENAME        */\n");
      rc = rename("d4test", "d4erik");
   #else
      fprintf(stdout, "   #define S4NO_RENAME\n");
      rc = system("mv d4test d4erik");
   #endif
   if (rc<0)
   {
      fprintf(stderr, "ERROR: Unable to change filename\n");
      iserror = EXIT_FAILURE ;
      switch ( (int) errno )
      {
      case EACCES :
         fprintf(stderr, "ERRNO == EACCES: Permission denied\n" ) ;
         break ;
      case ENOENT :
         fprintf(stderr, "ERRNO == ENOENT: No such file or directory\n" ) ;
         break ;
      default:
         fprintf(stderr, "ERRNO VALUE NOT RECOGNIZED\n" ) ;
      }
   }

/*S4NO_REMOVE*****************************************************/
   #ifndef S4NO_REMOVE
      fprintf(stdout, "/* #define S4NO_REMOVE        */\n");
      rc =remove("d4erik");
   #else
      fprintf(stdout, "   #define S4NO_REMOVE\n");
      rc =unlink("d4erik");
   #endif
   if (rc<0)
   {
      fprintf(stdout,"\nERROR: Unable to remove file\n" ) ;
      iserror = EXIT_FAILURE ;
      switch ( (int) errno )
      {
      case EACCES :
         fprintf(stderr,"ERRNO == EACCES: Permission denied\n" ) ;
         break ;
      default:
         fprintf(stderr,"ERRNO VALUE NOT RECOGNIZED\n" ) ;
      }
   }

/*S4NO_NO_SIZE_T**********************************************/
   #ifndef S4NO_SIZE_T
      fprintf(stdout, "/* #define S4NO_SIZE_T        */\n");
   #else
      fprintf(stdout, "   #define S4NO_SIZE_T\n");
   #endif

/*S4NO_STRLWR**************************************************/
   #ifndef S4NO_STRLWR
   strcpy(strtest, "UNIX ROCKS");
      strlwr(strtest);
      rc = strcmp(strtest, "unix rocks");
      if (rc)
      {
         fprintf(stderr, "ERROR: The strlwr() function does not work properly: %s\n", strtest);
         iserror = EXIT_FAILURE ;
      }
      fprintf(stdout, "/* #define S4NO_STRLWR        */\n") ;
   #else
      fprintf(stdout, "   #define S4NO_STRLWR\n") ;
   #endif

/*S4NO_STRUPR**************************************************/
   #ifndef S4NO_STRUPR
      strcpy(strtest, "unix rocks");
      strupr(strtest);
      rc = strcmp(strtest, "UNIX ROCKS");
      if (rc)
      {
         fprintf(stderr, "ERROR: The strupr() function does not work properly: %s\n", strtest);
         iserror = EXIT_FAILURE ;
      }
      fprintf(stdout, "/* #define S4NO_STRUPR        */\n") ;
   #else
      fprintf(stdout, "   #define S4NO_STRUPR\n") ;
   #endif

/*S4NO_STRNICMP*************************************************/
   #ifndef S4NO_STRNICMP
      strcpy(strtest, "UnIx RoCkS");
      rc = strnicmp(strtest, "uNiX rOcXx",8);
      if (rc)
      {
         fprintf(stderr, "ERROR: The strnicmp() function does not work properly: %s\n", strtest);
         iserror = EXIT_FAILURE ;
      }
      fprintf(stdout, "/* #define S4NO_STRNICMP      */\n") ;
   #else
      fprintf(stdout, "   #define S4NO_STRNICMP\n") ;
   #endif
   exit(iserror);
}

/*static void sig_bus(int signo)*/
/*{*/
   /*if(signo == SIGBUS )*/
   /*{*/
      /*buserr = 1;*/
      /*fprintf(stdout,"   #define S4DATA_ALIGN\n");*/
   /*}*/
   /*else*/
      /*fprintf(stderr, "received signal %d\n", signo);*/
/*}*/

static int filelen(int myfile)
{
   #ifndef S4NO_FILELENGTH
      return filelength(myfile);
   #else
      struct stat strStat ;
      if (fstat( myfile, &strStat) )
         fprintf(stderr, "ERROR: file length function\n");
      return ( (long)strStat.st_size ) ;
   #endif
}