/* fake-xterm * Behaves like xterm -S, but relays from the given fd to another pty * (written to redirect ski's console) */ #define _GNU_SOURCE #include #include #include #include void relay(int fd1, int fd2) { unsigned char buffer[1024]; fd_set fds; int max, len; int nread; FD_ZERO(&fds); max = (fd1 > fd2) ? fd1 : fd2; while (1) { FD_SET(fd1, &fds); FD_SET(fd2, &fds); switch (select(max+1, &fds, NULL, NULL, NULL)) { case -1: perror("select"); case 0: return; } if (FD_ISSET(fd1, &fds)) { switch (len = read(fd1, buffer, sizeof(buffer))) { case -1: perror("read"); case 0: return; } if (write(fd2, buffer, len) == -1) perror("write"); } if (FD_ISSET(fd2, &fds)) { switch (len = read(fd2, buffer, sizeof(buffer))) { case -1: perror("read"); case 0: return; } if (write(fd1, buffer, len) == -1) perror("write"); } } } int main(int argc, char *argv[]) { char *arg = NULL; char buffer[16]; FILE *tty; int fd, ptyfd, logfd; int i; for (i = 0; i < argc; i++) { if ((argv[i][0] == '-') && (argv[i][1] == 'S')) { arg = &argv[i][2]; break; } } if (arg == NULL) { fprintf(stderr, "fake-xterm: need -S argument\n"); return 1; } fd = atoi(&arg[2]); if ((ptyfd = getpt()) == -1) { perror("getpt"); return 1; } if ((grantpt(ptyfd) == -1) || (unlockpt(ptyfd) == -1)) { perror("grantpt"); return 1; } tty = fopen("/dev/tty", "w"); if (tty != NULL) { fprintf(tty, "\r\nConnect to %s\r\n", ptsname(ptyfd)); fclose(tty); } write(fd, "0\n", 2); /* ready */ /* wait for remote end */ if (read(ptyfd, buffer, sizeof(buffer)) == -1) { perror("read"); return 1; } relay(fd, ptyfd); close(ptyfd); close(fd); return 0; }