#ifdef SYSVIO
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/fcntl.h>

#ifndef _NFILE
#define _NFILE 20
#endif

#undef fopen
#undef freopen
#undef fdopen
#undef fflush
#undef fread
#undef fgetc
#undef getw
#undef gets
#undef fgets
#undef fseek
#undef ftell
#undef __filbuf

typedef struct {
    FILE *fp;
    long pos;
}
xxFILE;

static xxFILE *xxfiles = (xxFILE *)NULL;
static int xxnfiles = 0;

#define XXOK(p) ((p) && fileno(p) < xxnfiles && xxfiles[fileno(p)].fp == (p))
#define XXPOS(p) (xxfiles[fileno(p)].pos)

static void
xxinit(fp)
    FILE *fp;
{
    int fd;

    if (!fp || (fp->_flag & (_IOREAD|_IORW|_IOMYBUF)) != _IOREAD)
	return;

    fd = fileno(fp);

    if (fd >= xxnfiles) {
	int max = fd+_NFILE;

	if (xxfiles)
	    xxfiles = (xxFILE *)realloc((void *)xxfiles,
					sizeof(xxFILE)*(max+1));
	else
	    xxfiles = (xxFILE *)malloc(sizeof(xxFILE)*(max+1));

	if (!xxfiles)
	    return;

	while (xxnfiles <= max)
	    xxfiles[xxnfiles++].fp = (FILE *)NULL;
    }

    if ((xxfiles[fd].pos = lseek(fd, (long)0, SEEK_CUR)) >= 0)
	xxfiles[fd].fp = fp;
    else
	xxfiles[fd].fp = (FILE *)NULL;
}

static long
xxlseek(fp, offset, ptrname)
    FILE *fp;
    long offset;
    int ptrname;
{
    long pos = offset, cur;
    unsigned char *ptr;

    /* assume XXOK(fp) */

    if (ptrname == SEEK_END) {
	if (fseek(fp, offset, ptrname))
	    return -1;

	XXPOS(fp) = lseek(fileno(fp), 0, SEEK_CUR);
	return XXPOS(fp) - fp->_cnt;
    }

    cur = XXPOS(fp);

    if (ptrname == SEEK_CUR)
	pos += cur - fp->_cnt;

    ptr = (pos - cur) + (fp->_ptr + fp->_cnt);

    if (ptr < fp->_base || fp->_ptr + fp->_cnt <= ptr) {
	if (fseek(fp, offset, ptrname))
	    return -1;

	XXPOS(fp) = lseek(fileno(fp), 0, SEEK_CUR);
	return XXPOS(fp) - fp->_cnt;
    }

    fp->_cnt -= ptr - fp->_ptr;
    fp->_ptr = ptr;
    return pos;
}

FILE *
xxfopen(filename, type)
    char *filename;
    char *type;
{
    FILE *fp = fopen(filename, type);

    xxinit(fp);
    return fp;
}

FILE *
xxfreopen(filename, type, fp)
    char *filename;
    char *type;
    FILE *fp;
{
    xxinit(fp = freopen(filename, type, fp));
    return fp;
}

FILE *
xxfdopen(fd, type)
    int fd;
    char *type;
{
    FILE *fp = fdopen(fd, type);

    xxinit(fp);
    return fp;
}

int
xxfflush(fp)
    FILE *fp;
{
    int rc = fflush(fp);

    if (XXOK(fp))
	XXPOS(fp) = lseek(fileno(fp), 0, SEEK_CUR);

    return rc;
}

int
xxfread(ptr, size, nitems, fp)
    void *ptr;
    int size;
    int nitems;
    FILE *fp;
{
    int noseek = (fp && (size <= fp->_cnt));

    size = fread(ptr, size, nitems, fp);

    if (!noseek && XXOK(fp))
	XXPOS(fp) = lseek(fileno(fp), 0, SEEK_CUR);

    return size;
}

int
xxfgetc(fp)
    FILE *fp;
{
    int c = fgetc(fp);

    if (XXOK(fp))
	XXPOS(fp) = lseek(fileno(fp), 0, SEEK_CUR);

    return c;
}

int
xxgetw(fp)
    FILE *fp;
{
    int w = getw(fp);

    if (XXOK(fp))
	XXPOS(fp) = lseek(fileno(fp), 0, SEEK_CUR);

    return w;
}

char *
xxgets(s)
    char *s;
{
    s = gets(s);

    if (XXOK(stdin))
	XXPOS(stdin) = lseek(fileno(stdin), 0, SEEK_CUR);

    return s;
}

char *
xxfgets(s, n, fp)
    char *s;
    int n;
    FILE *fp;
{
    s = fgets(s, n, fp);

    if (XXOK(fp))
	XXPOS(fp) = lseek(fileno(fp), 0, SEEK_CUR);

    return s;
}

int
xxfseek(fp, offset, ptrname)
    FILE *fp;
    long offset;
    int ptrname;
{
    if (XXOK(fp))
	return (xxlseek(fp, offset, ptrname) >= 0) ? 0 : -1;
    else
	return fseek(fp, offset, ptrname);
}

long
xxftell(fp)
    FILE *fp;
{
    if (XXOK(fp))
	return xxlseek(fp, 0, SEEK_CUR);
    else
	return ftell(fp);
}

int
xx__filbuf(fp)
    FILE *fp;
{
    int c = __filbuf(fp);

    if (XXOK(fp))
	XXPOS(fp) = lseek(fileno(fp), 0, SEEK_CUR);

    return c;
}
#endif /* SYSVIO */
