Mercurial > projects > pwm
diff pwm.c @ 18:1e39a251cbe9
Use libtecla for interactive input
author | Guido Berhoerster <guido+pwm@berhoerster.name> |
---|---|
date | Thu, 24 Aug 2017 13:10:56 +0200 |
parents | a07665727c19 |
children | 5c6155c8e9b6 |
line wrap: on
line diff
--- 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 <err.h> #endif /* HAVE_ERR_H */ #include <errno.h> +#include <fcntl.h> #include <langinfo.h> #include <locale.h> #include <pwd.h> -#ifdef HAVE_READPASSPHRASE_H -#include <readpassphrase.h> -#endif /* READPASSPHRASE_H */ #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -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) {