#include #include #include #include #include #include #include #include #include #define INIT "export TERM=tty43 EDITOR=ed PAGER='pr -ptl23'\n" #define MAXBUF 2048 void sigchld() { exit(0); } 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, offset; struct timeval tv; signal(SIGCHLD, sigchld); /* 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+10)))) err(1, "malloc"); offset = -1; #ifdef SSHPASS nargv[++offset] = "sshpass"; nargv[++offset] = "-ePass"; #endif nargv[++offset] = "ssh"; nargv[++offset] = "-tt"; #ifndef SSHPASS nargv[++offset] = "-oBatchMode=yes"; #endif for(i = 1; i < argc; i++) nargv[i+offset] = argv[i]; nargv[argc+offset] = NULL; /* Exec into ssh. */ execvp(nargv[0], nargv); err(1, "execvp"); } if(!(fdin = open(in, O_WRONLY))) err(1, "open"); if(!(fdout = open(out, O_RDONLY))) err(1, "open"); dprintf(fdin, INIT); 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; } } }