#define INCL_DOSDATETIME
#define INCL_DOSMISC

/* OS/2 header files */

#include <os2def16.h>
#include <bsedos16.h>
#include <doscalls.h>
#include <error.h>
#include <sysbits.h>

/* C run-time header files */

#include <dos.h>
#include <limits.h>
#include <stdio.h>

/* local header files */
#include "cutilc.h"
#include "doswrite.h"

#define FPF_SEG(fp) (*((unsigned far *)&(fp) + 1))

extern pascal ENTER_DLL_CONFORM (void);

extern pascal EXIT_DLL_CONFORM (unsigned int);

unsigned long power10c (int pos);

unsigned far pascal DOSWRITE (
  unsigned   hf, 
  char far * bBuf, 
  unsigned   cbBuf,
  unsigned far * pcbBytesWritten)
{
  unsigned int rc;
  unsigned int usHandType;
  unsigned int usFlagWord;

  ENTER_DLL_CONFORM ();

  rc = DOSPWRITE (
         hf, 
         (char far *) bBuf, 
         cbBuf, 
         (unsigned far *) pcbBytesWritten);

  if ((*pcbBytesWritten != cbBuf) || (rc == 112))
  {
    DosQHandType (hf, &usHandType, &usFlagWord);
    if ((usHandType & 0x00FF) == 0)
    {
      EraseFiles ((unsigned long) cbBuf);
      return (EXIT_DLL_CONFORM (DOSPWRITE (
                                  hf,
                                  (char far *) bBuf,
                                  cbBuf, 
                                  (unsigned far *) pcbBytesWritten)));
    }
  }

  EXIT_DLL_CONFORM (rc);
}


void EraseFiles (unsigned long ulBytesToWrite)
{
  int      hControlFile;
  unsigned int usAction;
  unsigned long  ulFilePointer;
  unsigned int usBytesRead;
  unsigned long  ulBytesDeleted;
  unsigned int rc;
  unsigned long ulMaxDelDirSize;
  unsigned int  usDrive;
  unsigned long ulLogicalMap;

  struct _MEMVARS
  {
    char     szStoredFilePath [MAXPATHLEN];
    char     szDelDirName [MAXPATHLEN]; 
    char     szControlFileName [MAXPATHLEN]; 
    struct   _DELFILEINFO DelFileInfo;
  };
 
  struct _MEMVARS *MemVars;

  MemVars = NULL;
  if (DOSALLOCSEG (
        sizeof (struct _MEMVARS),
        & FPF_SEG (MemVars),
        0))
  { 
    return;     
  }

  /* Get target disk */
  DosQCurDisk (&usDrive, &ulLogicalMap);
  MemVars->szDelDirName [0] = (char) (usDrive - 1) + 'A';
  MemVars->szDelDirName [1] = ':';
  MemVars->szDelDirName [2] = '\\';
  MemVars->szDelDirName [3] = '\0';

  /* Get environment variables */
  if (!GetEnvironmentVars ((char far *) (MemVars->szDelDirName), (unsigned long far *) &ulMaxDelDirSize))
  {
    DOSFREESEG (FPF_SEG (MemVars));
    return;
  }

  strcpyfc ((char far *) (MemVars->szControlFileName), (char far *) (MemVars->szDelDirName));
  strcatfc ((char far *) (MemVars->szControlFileName), (char far *) "\\CONTROL.DEL");

  /* Open the control file */
  if (!DOSOPEN (
         (char far *) (MemVars->szControlFileName),
         (int far *) &hControlFile,
         (unsigned far *) &usAction,
         0L,
         0,
         (1 << 4) | 1,
         (1 << 13) | (1 << 4) | 2,
         0L))
  {
    /* Delete files until enough space for write, no more files, or error */
    ulBytesDeleted = 0L;
    do 
    {
      /* Place file pointer at last record */
      rc = DOSCHGFILEPTR (
             hControlFile, 
             0,
             2,                      /* move from end of file */
             (unsigned long far *) &ulFilePointer);

      rc = DOSCHGFILEPTR (
             hControlFile, 
             ulFilePointer - (unsigned long) (sizeof (struct _DELFILEINFO)),
             0,                     /* move from beginning of file */
             (unsigned long far *) &ulFilePointer);

      /* Read in last record */
      if (!rc)  
        rc = DOSREAD (
               hControlFile,
               (void far *) &(MemVars->DelFileInfo),
               sizeof (struct _DELFILEINFO),
               (unsigned far *) &usBytesRead);

      /* Truncate off last record */
      if (!rc)
        rc = DOSNEWSIZE (hControlFile, ulFilePointer);

      /* Delete this file */
      if (!rc)
      {
        strcpyfc ((char far *) (MemVars->szStoredFilePath), (char far *) (MemVars->szDelDirName));
        strcatfc ((char far *) (MemVars->szStoredFilePath), (char far *) "\\");
        strcatfc ((char far *) (MemVars->szStoredFilePath), MemVars->DelFileInfo.szStoredName);
        rc = DOSFORCEDELETE ((PSZ) (MemVars->szStoredFilePath), 0L);
      }

      /* Update count of bytes successfully deleted */
      if (!rc)
        ulBytesDeleted += MemVars->DelFileInfo.ulFileSize;

    /* Continue until enough files deleted */
    } while (
        (ulFilePointer != 0) && 
        (ulBytesToWrite < ulBytesDeleted) &&
        (rc = 0));

    /* Close control file */
    DOSCLOSE (hControlFile);
  } 
  DOSFREESEG (FPF_SEG (MemVars));
}


/***************************************************************************/
/*                                                                         */
/* GetEnvironmentVars                                                      */
/*                                                                         */
/* Get name and maximum size of delete directory from environment.         */
/*                                                                         */
/***************************************************************************/

unsigned int GetEnvironmentVars (
  char          far szDelDirName [], 
  unsigned long far *pulMaxDelDirSize)
{
  unsigned int usEnvSegment, usCmdOffset;
  char far *    pszEnvironment;
  char far *    pszDelDirParm;
  unsigned int  i;
  unsigned int  bDoubleNull;

  struct _gevMEMVARS
  {
    char   szEnvStringBuf [MAXENVIRONMENTSTRINGLEN];
  };
 
  struct _gevMEMVARS *MemVars;

  MemVars = NULL;
  if (DOSALLOCSEG (
        sizeof (struct _gevMEMVARS),
        & FPF_SEG (MemVars),
        0))
  { 
    return FALSE;
  }

  
  /* Get pointer to environment */
  DOSGETENV (&usEnvSegment, &usCmdOffset);
  pszEnvironment = MAKEP (usEnvSegment, 0); 

  /* Find our environment variables (format DELDIR=drive:dirname,size) */
  bDoubleNull = FALSE;
  do
  {
    /* Search for our environment variable */
    pszDelDirParm = strstrfc (pszEnvironment, (char far *) "DELDIR");
    if (pszDelDirParm)
    {
      /* Get local copy of our environment variable */
      strcpyfc ((char far *) (MemVars->szEnvStringBuf), (char far *) pszDelDirParm);

      /* Convert all drive letters to upper case */
      for (i = 1; i < strlenfc ((char far *) (MemVars->szEnvStringBuf)); i++)
      {
        if ((MemVars->szEnvStringBuf) [i] == ':')
          if (((MemVars->szEnvStringBuf) [i - 1] >= 'a') && ((MemVars->szEnvStringBuf) [i - 1] <= 'z'))
            (MemVars->szEnvStringBuf) [i - 1] -= 'a' - 'A';
      }
      /* Get pointer to start of dir name */
      pszDelDirParm = strstrfc ((char far *) (MemVars->szEnvStringBuf), (char far *) szDelDirName);
    }

    while (*pszEnvironment != '\0')
      pszEnvironment++;
    if (*(pszEnvironment+1) == '\0')
      bDoubleNull = TRUE;
    else
      pszEnvironment++;

  } while (!bDoubleNull && !pszDelDirParm);

  if (pszDelDirParm)
  {
    /* Get copy of dir path */
    for (i = 0;
        (*pszDelDirParm != ' ') && (*pszDelDirParm != ',') && 
          (*pszDelDirParm != ';') && (*pszDelDirParm != '\0'); 
        i++)
    {
      szDelDirName [i] = *pszDelDirParm++;
    }
    szDelDirName [i] = '\0';

    /* Scan to dir size parm */
    while (!(*pszDelDirParm >= '0' && *pszDelDirParm <= '9') &&
           (*pszDelDirParm != ';' && *pszDelDirParm != '\0'))
      pszDelDirParm++;

    /* If dir size parm not found then return unsuccessful */
    if (*pszDelDirParm == ';' || *pszDelDirParm == '\0')
    {
      DOSFREESEG (FPF_SEG (MemVars));
      return (FALSE);
    }

    /* Get max dir size */
    *pulMaxDelDirSize = atolc ((char far *) pszDelDirParm) << 10;

    /* return environment variables found */
    DOSFREESEG (FPF_SEG (MemVars));
    return TRUE;
  }
  else
  {
    /* return variables not found */
    DOSFREESEG (FPF_SEG (MemVars));
    return FALSE;
  }
  DOSFREESEG (FPF_SEG (MemVars));  /* just in case */
}


char far * strstrfc (
 char far * pszString1, 
 char far * pszString2)
{
  int        Str1Len, Str2Len;
  char far * pszCurPos;

  Str1Len = strlenfc (pszString1);
  Str2Len = strlenfc (pszString2);

  if (Str1Len >= Str2Len)
  {
    for (pszCurPos = pszString1; 
         pszCurPos <= (pszString1 + Str1Len);
         pszCurPos++)
    {
      if (strncmpfc (pszCurPos, pszString2, Str2Len) == 0)
        return (pszCurPos);
    }
  }
  return (NULL);
}

unsigned long atolc (char far * pszString)
{
  char far *    pszCurrentPos;
  unsigned long Total;
  int           pos, Found;

  Found = FALSE;
  while ((*pszString != '\0') && (!Found))
  {
    if ((*pszString >= '0') && (*pszString <= '9'))
      Found = TRUE;
    else
      pszString++;
  }

  if (Found)
  {
    pszCurrentPos = pszString;

    while ((*pszCurrentPos >= '0') && (*pszCurrentPos <= '9'))
      pszCurrentPos++;

    pos = 0;
    Total = 0L;

    do 
    {
      pszCurrentPos--;
      Total = Total + ulongmulc ((unsigned long) (*pszCurrentPos - '0'),
                                 power10c (pos));
      pos++;
    } while (pszCurrentPos > pszString);

    return (Total);
  }
  else
  {
    return (0L);
  }  
}


unsigned long power10c (int pos)
{
  unsigned long total;
  int i;

  if (pos == 0)
    return (1L);

  total = 10L;
  for (i = 1; i < pos; i++)
    total = ulongmulc (total, 10L);
  return total;
}

