#include "sig.h" #include "buffer.h" #include "strerr.h" #include "str.h" #include "byte.h" #include "readwrite.h" #include "exit.h" #include "fmt.h" #include "iopause.h" #include "pathexec.h" #define FATAL "recordio: fatal: " char pid[FMT_ULONG]; char recordbuf[512]; buffer ssrecord = BUFFER_INIT(write,2,recordbuf,sizeof recordbuf); void record(char *buf,int len,char *direction) /* 1 <= len <= 256 */ { int i; while (len) { buffer_puts(&ssrecord,pid); buffer_puts(&ssrecord,direction); i = byte_chr(buf,len,'\n'); buffer_put(&ssrecord,buf,i); if (i == len) { buffer_puts(&ssrecord,"+\n"); buffer_flush(&ssrecord); return; } buffer_puts(&ssrecord," \n"); buffer_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(int fdleft,int fdright) /* copy 0 -> fdleft, copy fdright -> 1 */ { struct taia stamp; struct taia deadline; iopause_fd x[4]; int xlen; iopause_fd *io0; iopause_fd *ioleft; iopause_fd *io1; iopause_fd *ioright; int r; for (;;) { xlen = 0; io0 = 0; if (leftstatus == 0) { io0 = &x[xlen++]; io0->fd = 0; io0->events = IOPAUSE_READ; } ioleft = 0; if (leftstatus == 1) { ioleft = &x[xlen++]; ioleft->fd = fdleft; ioleft->events = IOPAUSE_WRITE; } ioright = 0; if (rightstatus == 0) { ioright = &x[xlen++]; ioright->fd = fdright; ioright->events = IOPAUSE_READ; } io1 = 0; if (rightstatus == 1) { io1 = &x[xlen++]; io1->fd = 1; io1->events = IOPAUSE_WRITE; } taia_now(&stamp); taia_uint(&deadline,3600); taia_add(&deadline,&stamp,&deadline); iopause(x,xlen,&deadline,&stamp); if (io0 && io0->revents) { r = read(0,leftbuf,sizeof leftbuf); if (r <= 0) { leftstatus = -1; close(fdleft); buffer_puts(&ssrecord,pid); buffer_puts(&ssrecord," < [EOF]\n"); buffer_flush(&ssrecord); } else { leftstatus = 1; leftpos = 0; leftlen = r; record(leftbuf,r," < "); } } if (ioleft && ioleft->revents) { r = write(fdleft,leftbuf + leftpos,leftlen - leftpos); if (r == -1) break; leftpos += r; if (leftpos == leftlen) leftstatus = 0; } if (ioright && ioright->revents) { r = read(fdright,rightbuf,sizeof rightbuf); if (r <= 0) { buffer_puts(&ssrecord,pid); buffer_puts(&ssrecord," > [EOF]\n"); buffer_flush(&ssrecord); break; } rightstatus = 1; rightpos = 0; rightlen = r; record(rightbuf,r," > "); } if (io1 && io1->revents) { r = write(1,rightbuf + rightpos,rightlen - rightpos); if (r == -1) break; rightpos += r; if (rightpos == rightlen) rightstatus = 0; } } _exit(0); } main(int argc,char **argv,char **envp) { int piin[2]; int piout[2]; pid[fmt_ulong(pid,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_ignore(sig_pipe); 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: "); pathexec_run(argv[1],argv + 1,envp); strerr_die4sys(111,FATAL,"unable to run ",argv[1],": "); }