#include #include #include #include #include #include #include #include #include #include #include #include /* External global variables */ char msg_str[4096]; long transfer_timeout = 10L; /* Local global variables */ static int ctrl_fd = -1; static struct timeval timeout; /* Local function prototypes. */ static int get_reply(void), ptym_open(char *), ptys_open(char *), ssh_connect(char *, char *, char *), tty_raw(int); static size_t pipe_write(int, char *, size_t); static void scp_quit(void); #define INCORRECT -1 #define SUCCESS 0 /*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ main() $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/ int main(int argc, char *argv[]) { int cmd_length, status; char *cmd; if (argc != 5) { (void)fprintf(stderr, "Usage: %s \n", argv[0]); exit(1); } (void)fprintf(stdout, "--> Connecting...\n"); if ((status = ssh_connect(argv[1], argv[2], argv[3])) == INCORRECT) { (void)fprintf(stderr, "ERROR: Failed to make ssh connection (%d) : %s\n", status, msg_str); exit(1); } (void)fprintf(stdout, " -- Connected : %s\n", msg_str); if ((status = get_reply()) != SUCCESS) { (void)fprintf(stderr, "ERROR: Failed to read prompt (%d) : %s\n", status, msg_str); exit(1); } (void)fprintf(stdout, "--> Sending command : %s ...\n", argv[4]); cmd_length = strlen(argv[4]); if ((cmd = malloc(cmd_length + 1)) == NULL) { (void)fprintf(stderr, "ERROR: malloc() error : %s\n", strerror(errno)); exit(1); } (void)strcpy(cmd, argv[4]); cmd[cmd_length] = '\n'; if ((status = pipe_write(ctrl_fd, cmd, cmd_length + 1)) != cmd_length + 1) { (void)fprintf(stderr, "ERROR: Failed to write() command to pipe [%d] : %s\n", status, strerror(errno)); } if ((status = get_reply()) != SUCCESS) { (void)fprintf(stderr, "ERROR: Failed to read prompt (%d) : %s\n", status, msg_str); exit(1); } scp_quit(); exit(0); } /*+++++++++++++++++++++++++++++ ssh_connect() +++++++++++++++++++++++++++*/ static int ssh_connect(char *host, char *user, char *passwd) { int fdm, len, status, pipe_fd[2]; char pts_name[11], *ptr; if ((fdm = ptym_open(pts_name)) < 0) { (void)fprintf(stderr, "ERROR: ptym_open() error.\n"); return(INCORRECT); } /* Prepare pipes for parent/child synchronization. */ if (pipe(pipe_fd) == -1) { (void)fprintf(stderr, "ERROR: pipe() error : %s\n", strerror(errno)); status = INCORRECT; } else { pid_t ctrl_pid; if ((ctrl_pid = fork()) == 0) /* Child process */ { char *args[5], dummy; int fds; setsid(); if ((fds = ptys_open(pts_name)) < 0) { (void)fprintf(stderr, "ERROR: ptys_open() error.\n"); (void)close(fdm); return(INCORRECT); } (void)close(fdm); (void)tty_raw(fds); /* Synchronize with parent. */ (void)close(pipe_fd[1]); if (read(pipe_fd[0], &dummy, 1) != 1) { (void)close(pipe_fd[0]); (void)fprintf(stderr, "ERROR: read() error : %s\n", strerror(errno)); return(INCORRECT); } (void)close(pipe_fd[0]); dup2(fds, STDIN_FILENO); dup2(fds, STDOUT_FILENO); dup2(fds, STDERR_FILENO); if (fds > 2) { close(fds); } args[0] = "ssh"; args[1] = "-l"; args[2] = user; args[3] = host; args[4] = NULL; (void)execvp("ssh", args); (void)fprintf(stderr, "ERROR: execvp() error : %s\n", strerror(errno)); _exit(INCORRECT); } else if (ctrl_pid > 0) /* Parent process. */ { (void)tty_raw(fdm); ctrl_fd = fdm; /* Synchronize with child. */ (void)close(pipe_fd[0]); if (pipe_write(pipe_fd[1], "", 1) != 1) { (void)fprintf(stderr, "ERROR: write() error : %s\n", strerror(errno)); (void)close(pipe_fd[1]); return(INCORRECT); } (void)close(pipe_fd[1]); if ((status = get_reply()) == SUCCESS) { if (strstr(msg_str, "assword:") != NULL) { size_t length = strlen(passwd) + 1; char *str_passwd; if ((str_passwd = malloc(length)) == NULL) { (void)fprintf(stderr, "malloc() error\n"); exit(1); } (void)memcpy(str_passwd, passwd, length - 1); str_passwd[length - 1] = '\n'; if ((status = pipe_write(ctrl_fd, str_passwd, length)) != length) { if (errno != 0) { (void)fprintf(stderr, "ERROR: pipe_write() error (%d) : %s\n", status, strerror(errno)); } status = INCORRECT; } else { if ((status = get_reply()) != SUCCESS) { (void)fprintf(stderr, "ERROR: get_repy() error\n"); status = INCORRECT; } } } else { status = INCORRECT; } } else { (void)fprintf(stderr, "ERROR: get_reply() error (%d).\n", status); } } else /* Failed to fork(). */ { (void)fprintf(stderr, "ERROR: fork() error : %s\n", strerror(errno)); status = INCORRECT; } } return(status); } /*+++++++++++++++++++++++++++++ scp_quit() ++++++++++++++++++++++++++++++*/ void scp_quit(void) { if (ctrl_fd != -1) { int status; char cmd[5]; (void)fprintf(stdout, "--> Sending exit on control connection.\n"); cmd[0] = 'e'; cmd[1] = 'x'; cmd[2] = 'i'; cmd[3] = 't'; cmd[4] = '\n'; if ((status = pipe_write(ctrl_fd, cmd, 5)) != 5) { cmd[4] = '\0'; (void)fprintf(stderr, "ERROR: Failed to write() command to pipe [%d] : %s\n", cmd, status, strerror(errno)); status = INCORRECT; } else { if ((status = get_reply()) != SUCCESS) { (void)fprintf(stderr, "ERROR: Failed to read reply [%d]\n", status); } } (void)close(ctrl_fd); ctrl_fd = -1; } return; } /*----------------------------- pipe_write() ----------------------------*/ static size_t pipe_write(int fd, char *buf, size_t count) { if (fd != -1) { int status; fd_set wset; /* Initialise descriptor set */ FD_ZERO(&wset); FD_SET(fd, &wset); timeout.tv_usec = 0L; timeout.tv_sec = transfer_timeout; /* Wait for message x seconds and then continue. */ status = select(fd + 1, NULL, &wset, NULL, &timeout); if (status == 0) { /* Timeout has arrived. */ (void)fprintf(stderr, "There is no reply from pipe, failed to send command %s\n.", buf); } else if (FD_ISSET(fd, &wset)) { return(write(fd, buf, count)); } else { (void)fprintf(stderr, "ERROR: select() error : %s\n", strerror(errno)); } } errno = 0; return(INCORRECT); } /*----------------------------- get_reply() -----------------------------*/ static int get_reply(void) { int status; fd_set rset; FD_ZERO(&rset); FD_SET(ctrl_fd, &rset); timeout.tv_usec = 0L; timeout.tv_sec = transfer_timeout; status = select(ctrl_fd + 1, &rset, NULL, NULL, &timeout); if (status == 0) { (void)fprintf(stderr, "ERROR: select() timeout.\n"); } else if (FD_ISSET(ctrl_fd, &rset)) { if ((status = read(ctrl_fd, msg_str, 4096)) < 0) { (void)fprintf(stderr, "ERROR: read() error : %s\n", strerror(errno)); } else { msg_str[status] = '\0'; if (status == 0) { (void)fprintf(stderr, "ERROR: Other side closed the pipe.\n"); } else { char *ptr = msg_str; while (*ptr) { if (*ptr == '\n') { *ptr = ' '; } ptr++; } if (status == 1) { (void)fprintf(stdout, "<-- get_reply() reading ONE Byte %d\n", (int)msg_str[0]); } else { (void)fprintf(stdout, "<-- get_reply() reading %d Bytes : %s\n", status, msg_str); } return(SUCCESS); } } } else { (void)fprintf(stderr, "ERROR: select() error : %s\n", strerror(errno)); } return(INCORRECT); } /*----------------------------- ptym_open() -----------------------------*/ static int ptym_open(char *pts_name) { int fd; char *pos1, *pos2; (void)strcpy(pts_name, "/dev/ptyXY"); for (pos1 = "pqrstuvwxyzPQRST"; *pos1 != '\0'; pos1++) { pts_name[8] = *pos1; for (pos2 = "0123456789abcdef"; *pos2 != '\0'; pos2++) { pts_name[9] = *pos2; if ((fd = open(pts_name, O_RDWR)) == -1) { if (errno == ENOENT) { return (-1); } else { continue; } } pts_name[5] = 't'; return(fd); } } return(-1); } /*----------------------------- ptys_open() -----------------------------*/ static int ptys_open(char *pts_name) { int fds; if ((fds = open(pts_name, O_RDWR)) < 0) { return(-1); } #if defined(TIOCSCTTY) && !defined(CIBAUD) if (ioctl(fds, TIOCSCTTY, (char *) 0) < 0) { (void)close(fds); return(-1); } #endif return(fds); } /*------------------------------ tty_raw() ------------------------------*/ static int tty_raw(int fd) { struct termios buf; if (tcgetattr(fd, &buf) < 0) { return(-1); } buf.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); buf.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); buf.c_cflag &= ~(CSIZE | PARENB); buf.c_cflag |= CS8; buf.c_oflag &= ~(OPOST); buf.c_cc[VMIN] = 1; buf.c_cc[VTIME] = 0; if (tcsetattr(fd, TCSANOW, &buf) < 0) { return(-1); } return(0); }