aboutsummaryrefslogtreecommitdiff
path: root/rtty.c
diff options
context:
space:
mode:
Diffstat (limited to 'rtty.c')
-rw-r--r--rtty.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/rtty.c b/rtty.c
new file mode 100644
index 0000000..9f64c6d
--- /dev/null
+++ b/rtty.c
@@ -0,0 +1,123 @@
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/select.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define MAXBUF 2048
+
+int
+main(int argc, char *argv[])
+{
+ char bufin[MAXBUF], bufout[MAXBUF], *bi, *bo, in[30], **nargv, out[30];
+ fd_set rfds0, rfds1;
+ int fdin, fdout, i, n;
+ struct timeval tv;
+
+ /* Create named pipes. */
+ sprintf(in, "/var/tmp/rtty.in.%d", getpid());
+ sprintf(out, "/var/tmp/rtty.out.%d", getpid());
+ if(mkfifo(in, 0644) == -1 || mkfifo(out, 0664) == -1)
+ if(errno != EEXIST)
+ err(1, "mkfifo");
+
+ if(fork() == 0){
+ /* Redirect standard in, out. */
+ if(!(fdin = open(in, O_RDONLY)))
+ err(1, "open");
+ if(!(fdout = open(out, O_WRONLY)))
+ err(1, "open");
+ dup2(fdin, 0);
+ dup2(fdout, 1);
+
+ /* Create new argument vector. */
+ if(!(nargv = malloc(sizeof(char *)*(argc+1))))
+ err(1, "malloc");
+ nargv[0] = "ssh";
+ nargv[1] = "-tt";
+ for(i = 1; i < argc; i++)
+ nargv[i+1] = argv[i];
+ nargv[argc+1] = NULL;
+
+ /* Exec into ssh. */
+ execvp("ssh", nargv);
+ err(1, "execvp");
+ }
+
+ if(!(fdin = open(in, O_WRONLY)))
+ err(1, "open");
+ if(!(fdout = open(out, O_RDONLY)))
+ err(1, "open");
+
+ dprintf(fdin, "export TERM=tty43 PAGER=cat EDITOR=ed\n");
+
+ FD_ZERO(&rfds0);
+ FD_ZERO(&rfds1);
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 1;
+
+ for(;;){
+ /*
+ * User input is read from standard in and copied the
+ * input pipe. It is saved in bufin for later use.
+ */
+ FD_SET(0, &rfds0);
+ if(select(0+1, &rfds0, NULL, NULL, &tv) > 0){
+ n = read(0, bufin, MAXBUF);
+ bufin[n] = 0;
+ dprintf(fdin, "%s", bufin);
+ fflush(stdout);
+ }
+
+ /*
+ * System output is read from the output pipe and copied
+ * to standard out for the user to see.
+ */
+ FD_SET(fdout, &rfds1);
+ if(select(fdout+1, &rfds1, NULL, NULL, &tv) > 0){
+ n = read(fdout, bufout, MAXBUF);
+ if(!n) continue;
+ bufout[n] = 0;
+
+ /*
+ * Bufin and bufout are copied to the temporary
+ * pointers bi and bo. Bo is incremented in order
+ * to skip any potential repetition of the command
+ * given by the user on standard in. (It is assumed
+ * that the typed command fits in bufin, i.e. is
+ * not larger than MAXBUF.)
+ */
+ bi = bufin;
+ bo = bufout;
+ for(;;){
+ if(*bo == '\n'){
+ bo++;
+ break;
+ }
+ if(*bo == 13){
+ bo++;
+ continue;
+ }
+ if(*bi != *bo){
+ bo = bufout;
+ break;
+ }
+ bi++; bo++;
+ }
+
+ /*
+ * Bo is printed and bufin is cleared, so as not
+ * to perform the skip again, incorrectly.
+ */
+ printf("%s", bo);
+ fflush(stdout);
+ bufin[0] = 0;
+ }
+ }
+
+}