summaryrefslogtreecommitdiff
path: root/recordio.c
diff options
context:
space:
mode:
Diffstat (limited to 'recordio.c')
-rw-r--r--recordio.c165
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],": ");
+}