# HG changeset patch # User Guido Berhoerster # Date 1503573056 -7200 # Node ID 1e39a251cbe9fa672fc18d736b1fc8ac3dda03c4 # Parent a08ef0674d8ee9449d069eb9973d27eeb5f923a5 Use libtecla for interactive input diff -r a08ef0674d8e -r 1e39a251cbe9 Makefile --- a/Makefile Sat Aug 12 10:41:52 2017 +0200 +++ b/Makefile Thu Aug 24 13:10:56 2017 +0200 @@ -82,7 +82,6 @@ HAVE_ERR_H ?= 1 HAVE_GETRANDOM ?= 0 HAVE_SYS_QUEUE_H ?= 0 - HAVE_READPASSPHRASE_H ?= 0 HAVE_SETPROGNAME ?= 0 HAVE_SYS_TREE_H ?= 0 else ifneq ($(findstring $(OS_NAME),FreeBSD DragonFly),) @@ -91,7 +90,6 @@ HAVE_ERR_H ?= 1 HAVE_GETRANDOM ?= 0 HAVE_SYS_QUEUE_H ?= 1 - HAVE_READPASSPHRASE_H ?= 1 HAVE_SETPROGNAME ?= 1 HAVE_SYS_TREE_H ?= 1 else ifeq ($(OS_NAME),NetBSD) @@ -100,7 +98,6 @@ HAVE_ERR_H ?= 1 HAVE_GETRANDOM ?= 0 HAVE_SYS_QUEUE_H ?= 1 - HAVE_READPASSPHRASE_H ?= 0 HAVE_SYS_TREE_H ?= 1 HAVE_SETPROGNAME ?= 1 else ifeq ($(OS_NAME),OpenBSD) @@ -109,7 +106,6 @@ HAVE_ERR_H ?= 1 HAVE_GETRANDOM ?= 0 HAVE_SYS_QUEUE_H ?= 1 - HAVE_READPASSPHRASE_H ?= 1 HAVE_SYS_TREE_H ?= 1 HAVE_SETPROGNAME ?= 1 else ifeq ($(OS_NAME),SunOS) @@ -125,7 +121,6 @@ HAVE_GETRANDOM ?= 1 endif HAVE_SYS_QUEUE_H ?= 0 - HAVE_READPASSPHRASE_H ?= 0 HAVE_SYS_TREE_H ?= 0 HAVE_SETPROGNAME ?= 0 else @@ -134,7 +129,6 @@ HAVE_ERR_H ?= 0 HAVE_GETRANDOM ?= 0 HAVE_SYS_QUEUE_H ?= 0 - HAVE_READPASSPHRASE_H ?= 0 HAVE_SETPROGNAME ?= 0 HAVE_SYS_TREE_H ?= 0 endif @@ -157,7 +151,7 @@ XCPPFLAGS = -DPACKAGE=\"$(PACKAGE)\" \ -DVERSION=\"$(VERSION)\" -LDLIBS = -lpws -lnettle +LDLIBS = -ltecla -lcurses -lpws -lnettle ifeq ($(HAVE_ASPRINTF),1) XCPPFLAGS += -DHAVE_ASPRINTF else @@ -177,11 +171,6 @@ else OBJS += compat/err.o endif -ifeq ($(HAVE_READPASSPHRASE_H),1) - XCPPFLAGS += -DHAVE_READPASSPHRASE_H -else - OBJS += compat/readpassphrase.o -endif ifeq ($(HAVE_SETPROGNAME),1) XCPPFLAGS += -DHAVE_SETPROGNAME else diff -r a08ef0674d8e -r 1e39a251cbe9 cmd.c --- a/cmd.c Sat Aug 12 10:41:52 2017 +0200 +++ b/cmd.c Thu Aug 24 13:10:56 2017 +0200 @@ -29,9 +29,6 @@ #endif /* HAVE_ERR_H */ #include #include -#ifdef HAVE_READPASSPHRASE_H -#include -#endif /* READPASSPHRASE_H */ #include #include #include @@ -860,43 +857,24 @@ static enum cmd_return cmd_changepassword(struct pwm_ctx *ctx, int argc, char *argv[]) { - size_t password_len; - char password_buf[PWS3_MAX_PASSWORD_LEN + 1]; - char confirm_buf[PWS3_MAX_PASSWORD_LEN + 1]; + size_t len; if (argc > 2) { return (CMD_USAGE); } else if (argc == 2) { - password_len = strlen(argv[1]); - if (password_len == 0) { + len = strlen(argv[1]); + if (len == 0) { pwm_err(ctx, "password must not be empty"); return (CMD_ERR); - } else if (password_len + 1 > sizeof (ctx->password)) { + } else if (len + 1 > sizeof (ctx->password)) { pwm_err(ctx, "password too long"); return (CMD_ERR); } - memcpy(ctx->password, argv[1], password_len + 1); + memcpy(ctx->password, argv[1], len + 1); } else { - if (readpassphrase("Enter password: ", password_buf, - sizeof (password_buf), RPP_ECHO_OFF | RPP_REQUIRE_TTY) == - NULL) { - err(1, "readpassphrase"); - } - password_len = strlen(password_buf); - if (password_len == 0) { - pwm_err(ctx, "password must not be empty"); + if (pwm_read_password(ctx, 1) != 0) { return (CMD_ERR); } - if (readpassphrase("Confirm password: ", confirm_buf, - sizeof (confirm_buf), - RPP_ECHO_OFF | RPP_REQUIRE_TTY) == NULL) { - err(1, "readpassphrase"); - } - if (strcmp(password_buf, confirm_buf) != 0) { - pwm_err(ctx, "passwords do not match"); - return (CMD_ERR); - } - memcpy(ctx->password, password_buf, password_len + 1); } return (CMD_OK); diff -r a08ef0674d8e -r 1e39a251cbe9 compat.h --- a/compat.h Sat Aug 12 10:41:52 2017 +0200 +++ b/compat.h Thu Aug 24 13:10:56 2017 +0200 @@ -43,10 +43,6 @@ #include "compat/queue.h" #endif /* !HAVE_SYS_QUEUE_H */ -#ifndef HAVE_READPASSPHRASE_H -#include "compat/readpassphrase.h" -#endif /* !HAVE_READPASSPHRASE_H */ - #ifndef HAVE_SETPROGNAME #include "compat/setprogname.h" #endif /* !HAVE_SETPROGNAME */ diff -r a08ef0674d8e -r 1e39a251cbe9 compat/readpassphrase.c --- a/compat/readpassphrase.c Sat Aug 12 10:41:52 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,209 +0,0 @@ -/* $OpenBSD: readpassphrase.c,v 1.24 2013/11/24 23:51:29 deraadt Exp $ */ - -/* - * Copyright (c) 2000-2002, 2007, 2010 - * Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Sponsored in part by the Defense Advanced Research Projects - * Agency (DARPA) and Air Force Research Laboratory, Air Force - * Materiel Command, USAF, under agreement number F39502-99-1-0512. - */ - -#include -#include -#include -#ifdef HAVE_PATHS_H -#include -#endif /* HAVE_PATHS_H */ -#include -#include -#include -#include -#include -#include "readpassphrase.h" - -#ifndef TCSASOFT -#define TCSASOFT 0 -#endif /* !TCSASOFT */ - -#ifndef _NSIG -#ifdef NSIG -#define _NSIG NSIG -#else /* NSIG */ -#define _NSIG 128 -#endif /* NSIG */ -#endif /* !_NSIG */ - -#ifndef _PATH_TTY -#define _PATH_TTY "/dev/tty" -#endif - -static volatile sig_atomic_t signo[_NSIG]; - -static void handler(int); - -char * -readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) -{ - ssize_t nr; - int input, output, save_errno, i, need_restart; - char ch, *p, *end; - struct termios term, oterm; - struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm; - struct sigaction savetstp, savettin, savettou, savepipe; - - /* I suppose we could alloc on demand in this case (XXX). */ - if (bufsiz == 0) { - errno = EINVAL; - return(NULL); - } - -restart: - for (i = 0; i < _NSIG; i++) - signo[i] = 0; - nr = -1; - save_errno = 0; - need_restart = 0; - /* - * Read and write to /dev/tty if available. If not, read from - * stdin and write to stderr unless a tty is required. - */ - if ((flags & RPP_STDIN) || - (input = output = open(_PATH_TTY, O_RDWR)) == -1) { - if (flags & RPP_REQUIRE_TTY) { - errno = ENOTTY; - return(NULL); - } - input = STDIN_FILENO; - output = STDERR_FILENO; - } - - /* - * Turn off echo if possible. - * If we are using a tty but are not the foreground pgrp this will - * generate SIGTTOU, so do it *before* installing the signal handlers. - */ - if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) { - memcpy(&term, &oterm, sizeof(term)); - if (!(flags & RPP_ECHO_ON)) - term.c_lflag &= ~(ECHO | ECHONL); -#ifdef VSTATUS - if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) - term.c_cc[VSTATUS] = _POSIX_VDISABLE; -#endif /* VSTATUS */ - (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term); - } else { - memset(&term, 0, sizeof(term)); - term.c_lflag |= ECHO; - memset(&oterm, 0, sizeof(oterm)); - oterm.c_lflag |= ECHO; - } - - /* - * Catch signals that would otherwise cause the user to end - * up with echo turned off in the shell. Don't worry about - * things like SIGXCPU and SIGVTALRM for now. - */ - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; /* don't restart system calls */ - sa.sa_handler = handler; - (void)sigaction(SIGALRM, &sa, &savealrm); - (void)sigaction(SIGHUP, &sa, &savehup); - (void)sigaction(SIGINT, &sa, &saveint); - (void)sigaction(SIGPIPE, &sa, &savepipe); - (void)sigaction(SIGQUIT, &sa, &savequit); - (void)sigaction(SIGTERM, &sa, &saveterm); - (void)sigaction(SIGTSTP, &sa, &savetstp); - (void)sigaction(SIGTTIN, &sa, &savettin); - (void)sigaction(SIGTTOU, &sa, &savettou); - - if (!(flags & RPP_STDIN)) - (void)write(output, prompt, strlen(prompt)); - end = buf + bufsiz - 1; - p = buf; - while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') { - if (p < end) { - if ((flags & RPP_SEVENBIT)) - ch &= 0x7f; - if (isalpha((unsigned char)ch)) { - if ((flags & RPP_FORCELOWER)) - ch = (char)tolower((unsigned char)ch); - if ((flags & RPP_FORCEUPPER)) - ch = (char)toupper((unsigned char)ch); - } - *p++ = ch; - } - } - *p = '\0'; - save_errno = errno; - if (!(term.c_lflag & ECHO)) - (void)write(output, "\n", 1); - - /* Restore old terminal settings and signals. */ - if (memcmp(&term, &oterm, sizeof(term)) != 0) { - while (tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm) == -1 && - errno == EINTR && !signo[SIGTTOU]) - continue; - } - (void)sigaction(SIGALRM, &savealrm, NULL); - (void)sigaction(SIGHUP, &savehup, NULL); - (void)sigaction(SIGINT, &saveint, NULL); - (void)sigaction(SIGQUIT, &savequit, NULL); - (void)sigaction(SIGPIPE, &savepipe, NULL); - (void)sigaction(SIGTERM, &saveterm, NULL); - (void)sigaction(SIGTSTP, &savetstp, NULL); - (void)sigaction(SIGTTIN, &savettin, NULL); - (void)sigaction(SIGTTOU, &savettou, NULL); - if (input != STDIN_FILENO) - (void)close(input); - - /* - * If we were interrupted by a signal, resend it to ourselves - * now that we have restored the signal handlers. - */ - for (i = 0; i < _NSIG; i++) { - if (signo[i]) { - kill(getpid(), i); - switch (i) { - case SIGTSTP: - case SIGTTIN: - case SIGTTOU: - need_restart = 1; - } - } - } - if (need_restart) - goto restart; - - if (save_errno) - errno = save_errno; - return(nr == -1 ? NULL : buf); -} - -#if 0 -char * -getpass(const char *prompt) -{ - static char buf[_PASSWORD_LEN + 1]; - - return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF)); -} -#endif - -static void handler(int s) -{ - - signo[s] = 1; -} diff -r a08ef0674d8e -r 1e39a251cbe9 compat/readpassphrase.h --- a/compat/readpassphrase.h Sat Aug 12 10:41:52 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* $OpenBSD: readpassphrase.h,v 1.5 2003/06/17 21:56:23 millert Exp $ */ - -/* - * Copyright (c) 2000, 2002 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Sponsored in part by the Defense Advanced Research Projects - * Agency (DARPA) and Air Force Research Laboratory, Air Force - * Materiel Command, USAF, under agreement number F39502-99-1-0512. - */ - -#ifndef _READPASSPHRASE_H_ -#define _READPASSPHRASE_H_ - -#define RPP_ECHO_OFF 0x00 /* Turn off echo (default). */ -#define RPP_ECHO_ON 0x01 /* Leave echo on. */ -#define RPP_REQUIRE_TTY 0x02 /* Fail if there is no tty. */ -#define RPP_FORCELOWER 0x04 /* Force input to lower case. */ -#define RPP_FORCEUPPER 0x08 /* Force input to upper case. */ -#define RPP_SEVENBIT 0x10 /* Strip the high bit from input. */ -#define RPP_STDIN 0x20 /* Read from stdin, not /dev/tty */ - -#include - -char * readpassphrase(const char *, char *, size_t, int); - -#endif /* !_READPASSPHRASE_H_ */ diff -r a08ef0674d8e -r 1e39a251cbe9 pager.c --- a/pager.c Sat Aug 12 10:41:52 2017 +0200 +++ b/pager.c Thu Aug 24 13:10:56 2017 +0200 @@ -28,6 +28,7 @@ #endif /* HAVE_ERR_H */ #include #include +#include #include #include #include @@ -46,22 +47,6 @@ #include "pager.h" #include "util.h" -#ifndef TCSASOFT -#define TCSASOFT 0 -#endif /* !TCSASOFT */ - -#ifndef _NSIG -#ifdef NSIG -#define _NSIG NSIG -#else /* NSIG */ -#define _NSIG 128 -#endif /* NSIG */ -#endif /* !_NSIG */ - -#ifndef _PATH_TTY -#define _PATH_TTY "/dev/tty" -#endif - struct pager { TAILQ_HEAD(lines_head, lines_entry) lines_head; FILE *fp; @@ -74,123 +59,22 @@ char *line; }; -static volatile sig_atomic_t signals[_NSIG]; - -static void -sig_handler(int signo) -{ - signals[signo] = 1; -} - static int -getch_prompt(const char *prompt) +getch_prompt(GetLine *gl, const char *prompt) { - int retval = -1; - int signo; - int fd; - struct termios saved_term; - struct termios term; - struct sigaction sa; - struct sigaction saved_sa_hup; - struct sigaction saved_sa_int; - struct sigaction saved_sa_quit; - struct sigaction saved_sa_pipe; - struct sigaction saved_sa_alrm; - struct sigaction saved_sa_term; - struct sigaction saved_sa_tstp; - struct sigaction saved_sa_ttin; - struct sigaction saved_sa_ttou; - char c; - int need_restart = 0; - - printf("%s", prompt); - fflush(stdout); - -restart: - for (signo = 0; signo < _NSIG; signo++) { - signals[signo] = 0; - } - - fd = open(_PATH_TTY, O_RDONLY); - if (fd < 0) { - return (-1); - } + int c; + int saved_echo_mode; - if (tcgetattr(fd, &saved_term) != 0) { - close(fd); - return (-1); - } - memcpy(&term, &saved_term, sizeof (struct termios)); - - /* enter raw mode and turn echo off */ - term.c_lflag &= ~(ICANON | ECHO); - while ((tcsetattr(fd, TCSAFLUSH | TCSASOFT, &term) < 0) && - (errno != EINTR)) { - continue; - } - - /* install temporary signal handler */ - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sa.sa_handler = sig_handler; - sigaction(SIGHUP, &sa, &saved_sa_hup); - sigaction(SIGINT, &sa, &saved_sa_int); - sigaction(SIGQUIT, &sa, &saved_sa_quit); - sigaction(SIGPIPE, &sa, &saved_sa_pipe); - sigaction(SIGALRM, &sa, &saved_sa_alrm); - sigaction(SIGTERM, &sa, &saved_sa_term); - sigaction(SIGTSTP, &sa, &saved_sa_tstp); - sigaction(SIGTTIN, &sa, &saved_sa_ttin); - sigaction(SIGTTOU, &sa, &saved_sa_ttou); - - /* read key */ - if (read(fd, &c, 1) == sizeof (c)) { - retval = c; - } - - /* restore previous mode and echo setting */ - do { - while ((tcsetattr(fd, TCSAFLUSH | TCSASOFT, - &saved_term) < 0) && (errno != EINTR)) { - continue; - } - } while ((tcgetattr(fd, &term) == 0) && - (term.c_lflag != saved_term.c_lflag)); - - /* restore previous signal handlers */ - sigaction(SIGHUP, &saved_sa_hup, &sa); - sigaction(SIGINT, &saved_sa_int, &sa); - sigaction(SIGQUIT, &saved_sa_quit, &sa); - sigaction(SIGPIPE, &saved_sa_pipe, &sa); - sigaction(SIGALRM, &saved_sa_alrm, &sa); - sigaction(SIGTERM, &saved_sa_term, &sa); - sigaction(SIGTSTP, &saved_sa_tstp, &sa); - sigaction(SIGTTIN, &saved_sa_ttin, &sa); - sigaction(SIGTTOU, &saved_sa_ttou, &sa); + /* prompt with echo off */ + saved_echo_mode = gl_echo_mode(gl, -1); + gl_echo_mode(gl, 0); + c = gl_query_char(gl, prompt, '\0'); + gl_echo_mode(gl, saved_echo_mode); /* erase prompt */ printf("\r%*s\r", (int)strlen(prompt), ""); - fflush(stdout); - while ((close(fd) < 0) && (errno != EINTR)) { - continue; - } - - /* re-raise signals received */ - for (signo = 0; signo < _NSIG; signo++) { - if (signals[signo]) { - raise(signo); - if ((signo == SIGTSTP) || (signo == SIGTTIN) || - (signo == SIGTTOU)) { - need_restart = 1; - } - } - } - if (need_restart) { - goto restart; - } - - return (retval); + return (c); } struct pager * @@ -370,6 +254,7 @@ struct winsize ws; #endif /* TIOCGWINSZ */ unsigned int row = 0; + GetLine *gl; struct lines_entry *entry; is_interactive = (isatty(STDIN_FILENO) && (pager->fp == stdout)); @@ -384,12 +269,18 @@ } #endif /* TIOCGWINSZ */ + gl = new_GetLine(10, 0); + if (gl == NULL) { + err(1, "new_GetLine"); + } + TAILQ_FOREACH(entry, &pager->lines_head, entry) { if (is_interactive) { mbsnprint(cols, entry->line, pager->fp); row++; - if (row == rows - 1) { - getch_prompt("--More--"); + if ((TAILQ_NEXT(entry, entry) != NULL) && + (row == rows - 1)) { + getch_prompt(gl, "--More--"); row = 0; } } else { @@ -397,4 +288,6 @@ fflush(pager->fp); } } + + del_GetLine(gl); } diff -r a08ef0674d8e -r 1e39a251cbe9 pwm.c --- a/pwm.c Sat Aug 12 10:41:52 2017 +0200 +++ b/pwm.c Thu Aug 24 13:10:56 2017 +0200 @@ -27,12 +27,10 @@ #include #endif /* HAVE_ERR_H */ #include +#include #include #include #include -#ifdef HAVE_READPASSPHRASE_H -#include -#endif /* READPASSPHRASE_H */ #include #include #include @@ -47,9 +45,17 @@ #include "tok.h" #include "util.h" -#ifndef PWM_LINE_MAX -#define PWM_LINE_MAX 16384 -#endif /* !PWM_LINE_MAX */ +#ifndef PWM_HISTORY_ENTRIES_MAX +#define PWM_HISTORY_ENTRIES_MAX 1024 +#endif /* !PWM_HISTORY_MAX */ + +#ifndef PWM_HISTORY_LINES_MAX +#define PWM_HISTORY_LINES_MAX 256 +#endif /* !PWM_HISTORY_LINES_MAX */ + +#ifndef PWM_HISTORY_MAX +#define PWM_HISTORY_MAX (PWM_HISTORY_LINES_MAX * PWM_LINE_MAX) +#endif /* !PWM_HISTORY_MAX */ static void usage(void) @@ -76,49 +82,53 @@ } static int +complete_nothing(WordCompletion *cpl, void *data, const char *line, + int word_end) +{ + return (0); +} + +static int run_input_loop(struct pwm_ctx *ctx, int is_interactive) { int retval = -1; + char prompt[8 + 2 + 1]; + GetLine *gl = NULL; char buf[PWM_LINE_MAX]; + char *line = buf; int c; int argc = 0; char **argv = NULL; struct cmd *cmd; int i; + snprintf(prompt, sizeof (prompt), "%.*s> ", 8, getprogname()); + + /* initialize libtecla */ + gl = new_GetLine(PWM_LINE_MAX, PWM_HISTORY_MAX); + if (gl == NULL) { + err(1, "new_GetLine"); + } + gl_limit_history(gl, PWM_HISTORY_LINES_MAX); + /* disable default filename completion */ + gl_customize_completion(gl, NULL, complete_nothing); + for (;;) { cmd = NULL; - if (fgets(buf, (int)sizeof (buf), stdin) == NULL) { - if (ferror(stdin)) { - /* error */ - warn("failed to read command"); - goto out; - } else if (feof(stdin)) { - /* EOF */ + line = gl_get_line(gl, prompt, NULL, -1); + if (line == NULL) { + switch (gl_return_status(gl)) { + case GLR_EOF: break; + case GLR_ERROR: + warnx("gl_get_line: %s", + gl_error_message(gl, NULL, 0)); } - } - if ((buf[strlen(buf) - 1] != '\n') && !feof(stdin)) { - /* line was truncated */ - fprintf(stderr, "line too long\n"); - if (is_interactive) { - /* skip input to next newline */ - do { - errno = 0; - c = fgetc(stdin); - if ((c == EOF) && (errno != 0)) { - warn("failed to read command"); - goto out; - } - } while ((c != '\n') && (c != EOF)); - } else { - /* fatal error in non-interactive mode */ - goto out; - } + break; } /* tokenize line */ - switch(tok_tokenize(buf, &argc, &argv)) { + switch (tok_tokenize(line, &argc, &argv)) { case TOK_ERR_SYSTEM_ERROR: err(1, "tok_tokenize"); case TOK_ERR_UNTERMINATED_QUOTE: @@ -183,6 +193,75 @@ free(argv[i]); } free(argv); + del_GetLine(gl); + + return (retval); +} + +int +pwm_read_password(struct pwm_ctx *ctx, int is_new_password) +{ + int retval = -1; + GetLine *gl = NULL; + char *line; + size_t len; + char password_buf[sizeof (ctx->password)] = { '\0' }; + + /* initialize libtecla */ + gl = new_GetLine(sizeof (password_buf) - 1, 0); + if (gl == NULL) { + err(1, "new_GetLine"); + } + /* disable default filename completion */ + gl_customize_completion(gl, NULL, complete_nothing); + gl_echo_mode(gl, 0); + + line = gl_get_line(gl, is_new_password ? "New password: " : + "Password: ", NULL, -1); + putchar('\n'); + if (line == NULL) { + if (gl_return_status(gl) == GLR_ERROR) { + errx(1, "gl_get_line: %s", gl_error_message(gl, NULL, + 0)); + } + goto out; + } + len = strlen(line); + if ((len > 0) && (line[len - 1] == '\n')) { + line[--len] = '\0'; + } + if (len == 0) { + fprintf(stderr, "password must not be empty\n"); + goto out; + } + strcpy(password_buf, line); + + /* confirm the entered password entered */ + if (is_new_password) { + line = gl_get_line(gl, "Confirm password: ", NULL, -1); + putchar('\n'); + if (line == NULL) { + if (gl_return_status(gl) == GLR_ERROR) { + errx(1, "gl_get_line: %s", gl_error_message(gl, + NULL, 0)); + } + goto out; + } + len = strlen(line); + if ((len > 0) && (line[len - 1] == '\n')) { + line[--len] = '\0'; + } + if (strcmp(password_buf, line) != 0) { + fprintf(stderr, "passwords do not match\n"); + goto out; + } + } + + strcpy(ctx->password, password_buf); + retval = 0; + +out: + del_GetLine(gl); return (retval); } @@ -253,7 +332,6 @@ struct passwd *passwd; char *pwm_dirname = NULL; FILE *fp = NULL; - char password_buf[PWS3_MAX_PASSWORD_LEN + 1]; setprogname(argv[0]); @@ -343,27 +421,8 @@ ctx.password, sizeof (ctx.password)) != 0) { goto out; } - } else { - if (readpassphrase("Enter password: ", ctx.password, - sizeof (ctx.password), RPP_ECHO_OFF | RPP_REQUIRE_TTY) == - NULL) { - err(1, "readpassphrase"); - } - if (ctx.password[0] == '\0') { - fprintf(stderr, "password must not be empty\n"); - goto out; - } - if (fp == NULL) { - if (readpassphrase("Confirm password: ", password_buf, - sizeof (password_buf), - RPP_ECHO_OFF | RPP_REQUIRE_TTY) == NULL) { - err(1, "readpassphrase"); - } - if (strcmp(ctx.password, password_buf) != 0) { - fprintf(stderr, "passwords do not match\n"); - goto out; - } - } + } else if (pwm_read_password(&ctx, (fp == NULL)) != 0) { + goto out; } if (fp != NULL) { if (pwfile_read_file(&ctx, fp) != 0) { diff -r a08ef0674d8e -r 1e39a251cbe9 pwm.h --- a/pwm.h Sat Aug 12 10:41:52 2017 +0200 +++ b/pwm.h Thu Aug 24 13:10:56 2017 +0200 @@ -24,8 +24,13 @@ #ifndef PWM_H #define PWM_H +#include #include +#ifndef PWM_LINE_MAX +#define PWM_LINE_MAX 16384 +#endif /* !PWM_LINE_MAX */ + struct pwm_ctx { const char *prev_cmd; char *errmsg; @@ -38,5 +43,6 @@ }; void pwm_err(struct pwm_ctx *, char *, ...); +int pwm_read_password(struct pwm_ctx *, int); #endif /* PWM_H */