#include "sfdchdr.h"
#if !defined(FNDELAY) && defined(O_NDELAY)
#define FNDELAY O_NDELAY
#endif
typedef struct _filter_s
{ Sfdisc_t disc;
Sfio_t* filter;
char raw[1024];
char* next;
char* endb;
} Filter_t;
#if __STD_C
static ssize_t filterread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)
#else
static ssize_t filterread(f, buf, n, disc)
Sfio_t* f;
Void_t* buf;
size_t n;
Sfdisc_t* disc;
#endif
{
Filter_t* fi;
ssize_t r, w;
fi = (Filter_t*)disc;
for(;;)
{ if(!fi->next)
fi->next = fi->endb = fi->raw;
else
{
errno = 0;
if((r = sfread(fi->filter,buf,n)) > 0)
return r;
if(errno != EWOULDBLOCK)
return 0;
}
if(fi->next >= fi->endb)
{ if((r = sfrd(f,fi->raw,sizeof(fi->raw),disc)) > 0)
{ fi->next = fi->raw;
fi->endb = fi->raw+r;
}
else
{
sfset(fi->filter,SF_READ,0);
close(sffileno(fi->filter));
sfset(fi->filter,SF_READ,1);
}
}
if((w = fi->endb - fi->next) > 0)
{ errno = 0;
if((w = sfwrite(fi->filter,fi->next,w)) > 0)
fi->next += w;
else if(errno != EWOULDBLOCK)
return 0;
else sleep(1);
}
}
}
#if __STD_C
static ssize_t filterwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)
#else
static ssize_t filterwrite(f, buf, n, disc)
Sfio_t* f;
Void_t* buf;
size_t n;
Sfdisc_t* disc;
#endif
{
return -1;
}
#if __STD_C
static Sfoff_t filterseek(Sfio_t* f, Sfoff_t addr, int offset, Sfdisc_t* disc)
#else
static Sfoff_t filterseek(f, addr, offset, disc)
Sfio_t* f;
Sfoff_t addr;
int offset;
Sfdisc_t* disc;
#endif
{ f = NIL(Sfio_t*);
addr = 0;
offset = 0;
disc = NIL(Sfdisc_t*);
return (Sfoff_t)(-1);
}
#if __STD_C
static int filterexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc)
#else
static int filterexcept(f,type,data,disc)
Sfio_t* f;
int type;
Void_t* data;
Sfdisc_t* disc;
#endif
{
if(type == SF_FINAL || type == SF_DPOP)
{ sfclose(((Filter_t*)disc)->filter);
free(disc);
}
return 0;
}
#if __STD_C
int sfdcfilter(Sfio_t* f, const char* cmd)
#else
int sfdcfilter(f, cmd)
Sfio_t* f;
char* cmd;
#endif
{
reg Filter_t* fi;
reg Sfio_t* filter;
if(!(filter = sfpopen(NIL(Sfio_t*),cmd,"r+")) )
return -1;
sfsetbuf(filter,NIL(Void_t*),0);
sfset(filter,SF_READ,0);
fcntl(sffileno(filter),F_SETFL,FNDELAY);
sfset(filter,SF_READ,1);
sfset(filter,SF_WRITE,0);
fcntl(sffileno(filter),F_SETFL,FNDELAY);
sfset(filter,SF_WRITE,1);
if(!(fi = (Filter_t*)malloc(sizeof(Filter_t))) )
{ sfclose(filter);
return -1;
}
fi->disc.readf = filterread;
fi->disc.writef = filterwrite;
fi->disc.seekf = filterseek;
fi->disc.exceptf = filterexcept;
fi->filter = filter;
fi->next = fi->endb = NIL(char*);
if(sfdisc(f,(Sfdisc_t*)fi) != (Sfdisc_t*)fi)
{ sfclose(filter);
free(fi);
return -1;
}
return 0;
}