Custom-driver code for MYDRIVER

The following driver code supports MYDRIVER:
#include <plcstdrv.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/fcntl.h>

extern char *malloc();
externerrno;
 
static int DrOpen();
static int DrRead();
static int DrWrite();
static int DrClose();

#define CTRLDELIM 0x01/* fake delimiter (CTRL-A) */
#define REALDELIM 0x7c/* real delimiter (|)  */
#define ESCAPSIGN 0x5c/* escape sign(\)  */
#define ENDRECORD 0x0a/* end of record  (\n) */

int fd;

/*---------------------------------------------------------------------
 * DrConfig()
 *
 * Input  : (char *)driver name
 *  (void *)method table
 *
 * Return : PL_RTN_OK
 *
 * Schema : Fills in the driver table 
 *-------------------------------------------------------------------*/

int
DrConfig(driver,methodtable)
char*driver;
void*methodtable;
{
pl_inherit_methods("Delimited", methodtable);
pl_set_method_function(methodtable, PL_MTH_OPEN, DrOpen);
pl_set_method_function(methodtable, PL_MTH_RAWREAD, DrRead);
pl_set_method_function(methodtable, PL_MTH_RAWWRITE, DrWrite);
pl_set_method_function(methodtable, PL_MTH_CLOSE, DrClose);
pl_lock_globals();

return PL_RTN_OK;
}
/*--------------------------------------------------------------------
 * DrOpen()
 *
 * Input  : (devicearray *) devdevice array structure
 *
 * Return : PL_RTN_FAILerror
 *  PL_RTN_OK  open succeeded
 *
 * Schema : Open the specific file for that driver thread
 *  Note that the custom driver thread is bound to its
 *  own CPU VP, therefore it is safe to have globals like fd
 *------------------------------------------------------------------*/

static int
DrOpen(dev)
devicearray*dev;
{
fd = open(dev->filename, O_RDONLY);
if (fd < 0)
{
return PL_RTN_FAIL;
}

return PL_RTN_OK;
}



/*--------------------------------------------------------------------
 * DrRead() 
 *
 * Input  : (char *) bfoutput buffer to write record to
 *  (int)size size of output buffer
 *  (int *)  countnumber of bytes written to output buffer
 *
 * Return : PL_RTN_FAILerror
 *  PL_RTN_OK returning buffer
 *  PL_RTN_EOFreturning the last buffer, no more data
 *
 *
 * Schema : Reads from input and fill up data buffer provided by the
 *  caller. Here, the caller expect a record where the delimiter
 *  is |. Our custom driver changes all CTRL-A into | and
 *  escapes the already existing | from input.
 *------------------------------------------------------------------*/

static int
DrRead(bf, size, count)
char*bf;
int size;
int*count;
{
int rtn;/* return value  */
int n; /* bytes read in */
static char*bftemp = 0;/* temp buffer*/
char*p; /* pointer to temp buff  */
char*start; /* start of output buffer*/
static off_tcurrseek = 0;  /* current seek in input */
int escaped = 0;/* did we escape last character */
start = bf;

if (bftemp == 0)
{
if ( (bftemp = malloc(size)) == 0 )
{
return PL_RTN_FAIL;
}
}


/*
 * read data in
 */
errno = 0;
do
{
n = read(fd, bftemp, size);
} while (n == -1 

 errno == 4);

rtn = (n < 0) ? PL_RTN_FAIL : (n == size) ? PL_RTN_OK : PL_RTN_EOF;

currseek += n;

p = bftemp;

/*
 * format output buffer
 */
while (size)
{
if (*p == REALDELIM)
{ 
*bf = ESCAPSIGN; 
escaped = 1;
}
else if (*p == CTRLDELIM)
{
*bf = REALDELIM;
}
else
{
*bf = *p;
}

size--;
bf++;

if (escaped 

 size)
{
*bf++ = *p;
escaped = 0;
size--;
}

p++;
  
if ((int) (p - bftemp) == n)
break;
}

if (escaped)
{
p--;
rtn = PL_RTN_OK;
}

if ((int) (p - bftemp) != n)
{
currseek -= (off_t) (n - (p - bftemp));
lseek(fd, currseek, SEEK_SET);
}

if (rtn == PL_RTN_EOF)
{
*bf = 0;
}

*count = (int) (bf - start);

return rtn;
}


static int
DrWrite(bf, size)
char*bf;
int  size;
{
return PL_RTN_OK;
}


static int
DrClose(device)
devicearray *device;
{
close(fd);

return PL_RTN_OK;
}