/* Expands tildes in the file name. Based on code from ssh/misc.c. */ char * tilde_expand(const char *filename1) { const char *filename, *path, *sep; char user[128], *out; struct passwd *pw; u_int len, slash; int rv; if (*filename1 != '~') goto no_change; filename = filename1 + 1; path = strchr(filename, '/'); if (path != NULL && path > filename) { /* ~user/path */ slash = path - filename; if (slash > sizeof(user) - 1) goto no_change; memcpy(user, filename, slash); user[slash] = '\0'; if ((pw = getpwnam(user)) == NULL) goto no_change; } else if ((pw = getpwuid(getuid())) == NULL) /* ~/path */ goto no_change; /* Make sure directory has a trailing '/' */ len = strlen(pw->pw_dir); if (len == 0 || pw->pw_dir[len - 1] != '/') sep = "/"; else sep = ""; /* Skip leading '/' from specified path */ if (path != NULL) filename = path + 1; if ((rv = asprintf(&out, "%s%s%s", pw->pw_dir, sep, filename)) == -1) cu_err(1, "asprintf"); if (rv >= MAXPATHLEN) { free(out); goto no_change; } return (out); no_change: out = strdup(filename1); if (out == NULL) cu_err(1, "strdup"); return (out); }
void connect_command(void) { const char *cmd; pid_t pid; /* * Fork a program with: * 0 <-> remote tty in * 1 <-> remote tty out * 2 <-> local tty stderr */ cmd = get_input("Local command?"); if (cmd == NULL || *cmd == '\0') return; restore_termios(); switch (pid = fork()) { case -1: cu_err(1, "fork"); case 0: if (signal(SIGINT, SIG_DFL) == SIG_ERR) _exit(1); if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) _exit(1); /* attach stdout and stdin to line */ if (dup2(line_fd, STDOUT_FILENO) == -1) _exit(1); if (dup2(line_fd, STDIN_FILENO) == -1) _exit(1); if (closefrom(STDERR_FILENO + 1) != 0) _exit(1); execl(_PATH_BSHELL, "sh", "-c", cmd, (void*)NULL); _exit(1); default: while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) /* nothing */; break; } set_termios(); }
void pipe_command(void) { const char *cmd; pid_t pid; int fd; cmd = get_input("Local command?"); if (cmd == NULL || *cmd == '\0') return; restore_termios(); switch (pid = fork()) { case -1: cu_err(1, "fork"); case 0: fd = open(_PATH_DEVNULL, O_RDWR); if (fd < 0 || dup2(fd, STDIN_FILENO) == -1) _exit(1); close(fd); if (signal(SIGINT, SIG_DFL) == SIG_ERR) _exit(1); if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) _exit(1); /* attach stdout to line */ if (dup2(line_fd, STDOUT_FILENO) == -1) _exit(1); if (closefrom(STDERR_FILENO + 1) != 0) _exit(1); execl(_PATH_BSHELL, "sh", "-c", cmd, (void*)NULL); _exit(1); default: while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) /* nothing */; break; } set_termios(); }
void set_termios(void) { struct termios tio; if (!isatty(STDIN_FILENO)) return; memcpy(&tio, &saved_tio, sizeof(tio)); tio.c_lflag &= ~(ICANON|IEXTEN|ECHO); tio.c_iflag &= ~(INPCK|ICRNL); tio.c_oflag &= ~OPOST; tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; tio.c_cc[VDISCARD] = _POSIX_VDISABLE; tio.c_cc[VDSUSP] = _POSIX_VDISABLE; tio.c_cc[VINTR] = _POSIX_VDISABLE; tio.c_cc[VLNEXT] = _POSIX_VDISABLE; tio.c_cc[VQUIT] = _POSIX_VDISABLE; tio.c_cc[VSUSP] = _POSIX_VDISABLE; if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio) != 0) cu_err(1, "tcsetattr"); }
void xmodem_send(const char *file) { FILE *f; u_char buf[3 + XMODEM_BLOCK + 2], c; size_t len, pktlen; uint8_t num; uint16_t crc; int crc_mode; u_int i, total; struct termios tio; struct sigaction act, oact; f = fopen(file, "r"); if (f == NULL) { cu_warn("%s", file); return; } memset(&act, 0, sizeof(act)); sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = xmodem_signal; if (sigaction(SIGINT, &act, &oact) != 0) cu_err(1, "sigaction"); xmodem_stop = 0; if (isatty(STDIN_FILENO)) { memcpy(&tio, &saved_tio, sizeof(tio)); tio.c_lflag &= ~ECHO; if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio) != 0) cu_err(1, "tcsetattr"); } tcflush(line_fd, TCIFLUSH); if (xmodem_read(&c) != 0) goto fail; if (c == XMODEM_C) crc_mode = 1; else if (c == XMODEM_NAK) crc_mode = 0; else { cu_warnx("%s: unexpected response \%03hho", file, c); goto fail; } num = 1; total = 1; pktlen = 3 + XMODEM_BLOCK + (crc_mode ? 2 : 1); for (;;) { len = fread(buf + 3, 1, XMODEM_BLOCK, f); if (len == 0) break; memset(buf + 3 + len, XMODEM_SUB, XMODEM_BLOCK - len); buf[0] = XMODEM_SOH; buf[1] = num; buf[2] = 255 - num; if (crc_mode) { crc = xmodem_crc16(buf + 3, XMODEM_BLOCK); buf[3 + XMODEM_BLOCK] = crc >> 8; buf[3 + XMODEM_BLOCK + 1] = crc & 0xFF; } else { buf[3 + XMODEM_BLOCK] = 0; for (i = 0; i < XMODEM_BLOCK; i++) buf[3 + XMODEM_BLOCK] += buf[3 + i]; } for (i = 0; i < XMODEM_RETRIES; i++) { if (xmodem_stop) { errno = EINTR; goto fail; } cu_warnx("%s: sending block %u (attempt %u)", file, total, 1 + i); if (xmodem_write(buf, pktlen) != 0) goto fail; if (xmodem_read(&c) != 0) goto fail; if (c == XMODEM_ACK) break; if (c != XMODEM_NAK) { cu_warnx("%s: unexpected response \%03hho", file, c); } } if (i == XMODEM_RETRIES) { cu_warnx("%s: too many retries", file); goto out; } if (len < XMODEM_BLOCK) break; num++; total++; }