summaryrefslogtreecommitdiff
path: root/src/preline.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/preline.c')
-rw-r--r--src/preline.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/src/preline.c b/src/preline.c
new file mode 100644
index 0000000..fb4af06
--- /dev/null
+++ b/src/preline.c
@@ -0,0 +1,86 @@
+#include <unistd.h>
+#include "fd.h"
+#include "buffer.h"
+#include "exit.h"
+#include "wait.h"
+#include "env.h"
+#include "sig.h"
+#include "getoptb.h"
+#include "logmsg.h"
+
+#define WHO "preline"
+
+void die_usage()
+{
+ logmsg(WHO,100,USAGE,"preline cmd [ arg ... ]");
+}
+
+int flagufline = 1; char *ufline;
+int flagrpline = 1; char *rpline;
+int flagdtline = 1; char *dtline;
+
+char outbuf[BUFFER_OUTSIZE];
+buffer bo = BUFFER_INIT(write,1,outbuf,sizeof(outbuf));
+char inbuf[BUFFER_INSIZE];
+buffer bi = BUFFER_INIT(read,0,inbuf,sizeof(inbuf));
+
+int main(int argc, char **argv)
+{
+ int opt;
+ int pi[2];
+ int pid;
+ int wstat;
+
+ sig_pipeignore();
+
+ if (!(ufline = env_get("UFLINE"))) die_usage();
+ if (!(rpline = env_get("RPLINE"))) die_usage();
+ if (!(dtline = env_get("DTLINE"))) die_usage();
+
+ while ((opt = getopt(argc,argv,"frdFRD")) != opteof)
+ switch (opt) {
+ case 'f': flagufline = 0; break;
+ case 'r': flagrpline = 0; break;
+ case 'd': flagdtline = 0; break;
+ case 'F': flagufline = 1; break;
+ case 'R': flagrpline = 1; break;
+ case 'D': flagdtline = 1; break;
+ default: die_usage();
+ }
+ argc -= optind;
+ argv += optind;
+ if (!*argv) die_usage();
+
+ if (pipe(pi) == -1)
+ logmsg(WHO,111,FATAL,"unable to create pipe");
+
+ pid = fork();
+ if (pid == -1)
+ logmsg(WHO,111,FATAL,"unable to fork");
+
+ if (pid == 0) {
+ close(pi[1]);
+ if (fd_move(0,pi[0]) == -1)
+ logmsg(WHO,111,FATAL,"unable to set up fds");
+ sig_pipedefault();
+ execvp(*argv,argv);
+ logmsg(WHO,errno,FATAL,B("unable to run: ",*argv));
+ }
+ close(pi[0]);
+ if (fd_move(1,pi[1]) == -1)
+ logmsg(WHO,111,FATAL,"unable to set up fds");
+
+ if (flagufline) buffer_puts(&bo,ufline);
+ if (flagrpline) buffer_puts(&bo,rpline);
+ if (flagdtline) buffer_puts(&bo,dtline);
+ if (buffer_copy(&bo,&bi) != 0)
+ logmsg(WHO,111,FATAL,"unable to copy input");
+ buffer_flush(&bo);
+ close(1);
+
+ if (wait_pid(&wstat,pid) == -1)
+ logmsg(WHO,111,FATAL,"wait failed");
+ if (wait_crashed(wstat))
+ logmsg(WHO,111,FATAL,"child crashed");
+ _exit(wait_exitcode(wstat));
+}