#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include "const-c.inc"
// Platform include files are injected here.
// See Makefile.PL for details
//
#include "platform.h"
//Read from an fd until eof or error condition
//Returns SV containing all the data
// AKA "slurp";
SV * slurp(pTHX_ int fd, int read_size){
SV* buffer;
char *buf;
int ret;
int len=0;
buffer=newSV(read_size);
do {
SvGROW(buffer, len+read_size); //Grow the buffer if required
buf=SvPVX(buffer); //Get pointer to memory..
ret=read(fd, buf+len, read_size); //Do the read,offset to current traked len
if(ret>=0){
len+=ret; //track total length
buf=SvPVX(buffer);
buf[len]='\0'; //Add null for shits and giggles
}
else{
//break;
//fprintf(stderr, "ERROR IN slurp\n");
return &PL_sv_undef;
}
}
while(ret>0);
SvPOK_on(buffer); //Make it a string
SvCUR_set(buffer,len); //Set the length
sv_2mortal(buffer); //Decrement ref count
return buffer;
}
SV *accept_multiple_next_addr;
struct sockaddr *accept_multiple_next_buf;
SV *max_file_desc;
#if defined(IO_FD_OS_DARWIN)
#define KEVENT kevent64
#define KEVENT_S struct kevent64_s
#endif
#if defined(IO_FD_OS_BSD)
#define KEVENT kevent
#define KEVENT_S struct kevent
#endif
#define ADJUST_SOCKADDR_SIZE(addr) \
struct sockaddr * a=(struct sockaddr *)SvPVX(addr);\
switch(a->sa_family){\
case AF_INET:\
SvCUR_set(addr, sizeof(struct sockaddr_in));\
break;\
case AF_INET6:\
SvCUR_set(addr, sizeof(struct sockaddr_in6));\
break;\
case AF_UNIX:\
SvCUR_set(addr, sizeof(struct sockaddr_un));\
break;\
default:\
break;\
}\
MODULE = IO::FD PACKAGE = IO::FD
INCLUDE: const-xs.inc
BOOT:
//boot strap the mutliple accept buffer
accept_multiple_next_addr=newSV(sizeof(struct sockaddr_storage));
accept_multiple_next_buf=(struct sockaddr *)SvPVX(accept_multiple_next_addr);
//locate the $^F variable
//max_file_desc=get_sv("^F",0);
INCLUDE_COMMAND: cat "xs-include/socket.c"
INCLUDE_COMMAND: $^X "xs-include/sendfile.pl"
INCLUDE_COMMAND: cat "xs-include/mkfifo.c"
INCLUDE_COMMAND: $^X "xs-include/mkfifoat.pl"
INCLUDE_COMMAND: cat "xs-include/file.c"
INCLUDE_COMMAND: cat "xs-include/experimental.c"
INCLUDE_COMMAND: cat "xs-include/temp.c"
INCLUDE_COMMAND: cat "xs-include/send-recv.c"
void
readline(fd)
SV *fd
INIT:
SV *irs;
int ret;
int count;
SV* buffer;
char *buf;
int do_loop=1;
int tmp;
PPCODE:
if(SvOK(fd)&& SvIOK(fd)){
irs=get_sv("/",0);
if(irs){
#Found variable. Read records
if(SvOK(irs)){
if(SvROK(irs)){
//fprintf(stderr, "DOING RECORD READ\n");
//SLURP RECORDS
SV* v=SvRV(irs); //Dereference to get SV
tmp=SvIV(v); //The integer value of the sv
buffer=newSV(tmp); //Allocate buffer at record size
buf=SvPVX(buffer); //Get the pointer we need
ret=read(SvIV(fd), buf, tmp); //Do the read into buffer
//fprintf(stderr, "read return: %d\n", ret);
SvPOK_on(buffer); //Make a string
if(ret>=0){
buf[ret]='\0'; //Set null just in case
SvCUR_set(buffer,ret); //Set the length of the string
EXTEND(SP,1); //Extend stack
mPUSHs(buffer); //Push record
XSRETURN(1);
}
else {
XSRETURN_UNDEF;
}
}
else {
Perl_croak( aTHX_ "IO::FD::readline does not split lines");
}
}
else{
//fprintf(stderr, "DOING SLURP READ\n");
//SLURP entire file
EXTEND(SP,1);
PUSHs(slurp(aTHX_ SvIV(fd), 4096));
XSRETURN(1);
}
}
else {
//not found.. this isn't good
}
}
else{
XSRETURN_UNDEF;
}
#Naming
#TODO:
# TODO ioctl
# poll
# select ... perl compatiable version
# dir ... not normally on FDs?
# readline?
# Add IPC::Open2 and IPC::Open3 emulations