diff options
Diffstat (limited to 'recordio.c')
-rw-r--r-- | recordio.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/recordio.c b/recordio.c new file mode 100644 index 0000000..09277d9 --- /dev/null +++ b/recordio.c @@ -0,0 +1,165 @@ +#include "sig.h" +#include "substdio.h" +#include "strerr.h" +#include "str.h" +#include "byte.h" +#include "readwrite.h" +#include "exit.h" +#include "fmt.h" +#include "select.h" + +#define FATAL "recordio: fatal: " + +char pid[FMT_ULONG + 10]; + +char recordbuf[512]; +substdio ssrecord = SUBSTDIO_FDBUF(write,2,recordbuf,sizeof recordbuf); + +void record(buf,len,direction) +char *buf; +int len; /* 1...256 */ +char *direction; +{ + int i; + + while (len) { + substdio_puts(&ssrecord,pid); + substdio_puts(&ssrecord,direction); + + i = byte_chr(buf,len,'\n'); + substdio_put(&ssrecord,buf,i); + + if (i == len) { + substdio_puts(&ssrecord,"+\n"); + substdio_flush(&ssrecord); + return; + } + + substdio_puts(&ssrecord," \n"); + substdio_flush(&ssrecord); + buf += i + 1; + len -= i + 1; + } +} + +int leftstatus = 0; +char leftbuf[256]; +int leftlen; +int leftpos; + +int rightstatus = 0; +char rightbuf[256]; +int rightlen; +int rightpos; + +void doit(fdleft,fdright) +int fdleft; /* copy from 0 to fdleft */ +int fdright; /* copy from fdright to 1 */ +{ + fd_set rfds; + fd_set wfds; + int nfds; + int r; + + nfds = 2; + if (nfds <= fdleft) nfds = fdleft + 1; + if (nfds <= fdright) nfds = fdright + 1; + /* XXX: will overflow select buf if too many fds are open */ + + for (;;) { + FD_ZERO(&rfds); + FD_ZERO(&wfds); + + if (leftstatus == 0) FD_SET(0,&rfds); + if (leftstatus == 1) FD_SET(fdleft,&wfds); + + if (rightstatus == 0) FD_SET(fdright,&rfds); + if (rightstatus == 1) FD_SET(1,&wfds); + + if (select(nfds,&rfds,&wfds,(fd_set *) 0,(struct timeval *) 0) == -1) + continue; + + if (FD_ISSET(0,&rfds)) { + r = read(0,leftbuf,sizeof leftbuf); + if (r <= 0) { + leftstatus = -1; + close(fdleft); + substdio_puts(&ssrecord,pid); + substdio_puts(&ssrecord," < [EOF]\n"); + substdio_flush(&ssrecord); + } + else { + leftstatus = 1; leftpos = 0; leftlen = r; + record(leftbuf,r," < "); + } + } + + if (FD_ISSET(fdleft,&wfds)) { + r = write(fdleft,leftbuf + leftpos,leftlen - leftpos); + if (r == -1) break; + leftpos += r; + if (leftpos == leftlen) leftstatus = 0; + } + + if (FD_ISSET(fdright,&rfds)) { + r = read(fdright,rightbuf,sizeof rightbuf); + if (r <= 0) { + substdio_puts(&ssrecord,pid); + substdio_puts(&ssrecord," > [EOF]\n"); + substdio_flush(&ssrecord); + break; + } + else { + rightstatus = 1; rightpos = 0; rightlen = r; + record(rightbuf,r," > "); + } + } + + if (FD_ISSET(1,&wfds)) { + r = write(1,rightbuf + rightpos,rightlen - rightpos); + if (r == -1) break; + rightpos += r; + if (rightpos == rightlen) rightstatus = 0; + } + } + + _exit(0); +} + +void main(argc,argv) +int argc; +char **argv; +{ + int piin[2]; + int piout[2]; + + pid[fmt_ulong(pid,(unsigned long) getpid())] = 0; + + if (argc < 2) + strerr_die1x(100,"recordio: usage: recordio program [ arg ... ]"); + + if (pipe(piin) == -1) + strerr_die2sys(111,FATAL,"unable to create pipe: "); + if (pipe(piout) == -1) + strerr_die2sys(111,FATAL,"unable to create pipe: "); + + switch(fork()) { + case -1: + strerr_die2sys(111,FATAL,"unable to fork: "); + case 0: + sig_pipeignore(); + close(piin[0]); + close(piout[1]); + doit(piin[1],piout[0]); + } + + close(piin[1]); + close(piout[0]); + if (fd_move(0,piin[0]) == -1) + strerr_die2sys(111,FATAL,"unable to move descriptors: "); + if (fd_move(1,piout[1]) == -1) + strerr_die2sys(111,FATAL,"unable to move descriptors: "); + + execvp(argv[1],argv + 1); + strerr_die4sys(111,FATAL,"unable to run ",argv[1],": "); +} |