projects/pwm

changeset 18:1e39a251cbe9

Use libtecla for interactive input
author Guido Berhoerster <guido+pwm@berhoerster.name>
date Thu Aug 24 13:10:56 2017 +0200 (2017-08-24)
parents a08ef0674d8e
children 5c6155c8e9b6
files Makefile cmd.c compat.h compat/readpassphrase.c compat/readpassphrase.h pager.c pwm.c pwm.h
line diff
     1.1 --- a/Makefile	Sat Aug 12 10:41:52 2017 +0200
     1.2 +++ b/Makefile	Thu Aug 24 13:10:56 2017 +0200
     1.3 @@ -82,7 +82,6 @@
     1.4    HAVE_ERR_H ?=		1
     1.5    HAVE_GETRANDOM ?=	0
     1.6    HAVE_SYS_QUEUE_H ?=	0
     1.7 -  HAVE_READPASSPHRASE_H ?= 0
     1.8    HAVE_SETPROGNAME ?=	0
     1.9    HAVE_SYS_TREE_H ?=	0
    1.10  else ifneq ($(findstring $(OS_NAME),FreeBSD DragonFly),)
    1.11 @@ -91,7 +90,6 @@
    1.12    HAVE_ERR_H ?=		1
    1.13    HAVE_GETRANDOM ?=	0
    1.14    HAVE_SYS_QUEUE_H ?=	1
    1.15 -  HAVE_READPASSPHRASE_H ?= 1
    1.16    HAVE_SETPROGNAME ?=	1
    1.17    HAVE_SYS_TREE_H ?=	1
    1.18  else ifeq ($(OS_NAME),NetBSD)
    1.19 @@ -100,7 +98,6 @@
    1.20    HAVE_ERR_H ?=		1
    1.21    HAVE_GETRANDOM ?=	0
    1.22    HAVE_SYS_QUEUE_H ?=	1
    1.23 -  HAVE_READPASSPHRASE_H ?= 0
    1.24    HAVE_SYS_TREE_H ?=	1
    1.25    HAVE_SETPROGNAME ?=	1
    1.26  else ifeq ($(OS_NAME),OpenBSD)
    1.27 @@ -109,7 +106,6 @@
    1.28    HAVE_ERR_H ?=		1
    1.29    HAVE_GETRANDOM ?=	0
    1.30    HAVE_SYS_QUEUE_H ?=	1
    1.31 -  HAVE_READPASSPHRASE_H ?= 1
    1.32    HAVE_SYS_TREE_H ?=	1
    1.33    HAVE_SETPROGNAME ?=	1
    1.34  else ifeq ($(OS_NAME),SunOS)
    1.35 @@ -125,7 +121,6 @@
    1.36      HAVE_GETRANDOM ?=	1
    1.37    endif
    1.38    HAVE_SYS_QUEUE_H ?=	0
    1.39 -  HAVE_READPASSPHRASE_H ?= 0
    1.40    HAVE_SYS_TREE_H ?=	0
    1.41    HAVE_SETPROGNAME ?=	0
    1.42  else
    1.43 @@ -134,7 +129,6 @@
    1.44    HAVE_ERR_H ?=		0
    1.45    HAVE_GETRANDOM ?=	0
    1.46    HAVE_SYS_QUEUE_H ?=	0
    1.47 -  HAVE_READPASSPHRASE_H ?= 0
    1.48    HAVE_SETPROGNAME ?=	0
    1.49    HAVE_SYS_TREE_H ?=	0
    1.50  endif
    1.51 @@ -157,7 +151,7 @@
    1.52  
    1.53  XCPPFLAGS =	-DPACKAGE=\"$(PACKAGE)\" \
    1.54  		-DVERSION=\"$(VERSION)\"
    1.55 -LDLIBS =	-lpws -lnettle
    1.56 +LDLIBS =	-ltecla -lcurses -lpws -lnettle
    1.57  ifeq ($(HAVE_ASPRINTF),1)
    1.58    XCPPFLAGS +=	-DHAVE_ASPRINTF
    1.59  else
    1.60 @@ -177,11 +171,6 @@
    1.61  else
    1.62    OBJS +=	compat/err.o
    1.63  endif
    1.64 -ifeq ($(HAVE_READPASSPHRASE_H),1)
    1.65 -  XCPPFLAGS +=	-DHAVE_READPASSPHRASE_H
    1.66 -else
    1.67 -  OBJS +=	compat/readpassphrase.o
    1.68 -endif
    1.69  ifeq ($(HAVE_SETPROGNAME),1)
    1.70    XCPPFLAGS +=	-DHAVE_SETPROGNAME
    1.71  else
     2.1 --- a/cmd.c	Sat Aug 12 10:41:52 2017 +0200
     2.2 +++ b/cmd.c	Thu Aug 24 13:10:56 2017 +0200
     2.3 @@ -29,9 +29,6 @@
     2.4  #endif /* HAVE_ERR_H */
     2.5  #include <errno.h>
     2.6  #include <limits.h>
     2.7 -#ifdef	HAVE_READPASSPHRASE_H
     2.8 -#include <readpassphrase.h>
     2.9 -#endif /* READPASSPHRASE_H */
    2.10  #include <regex.h>
    2.11  #include <stdlib.h>
    2.12  #include <string.h>
    2.13 @@ -860,43 +857,24 @@
    2.14  static enum cmd_return
    2.15  cmd_changepassword(struct pwm_ctx *ctx, int argc, char *argv[])
    2.16  {
    2.17 -	size_t	password_len;
    2.18 -	char	password_buf[PWS3_MAX_PASSWORD_LEN + 1];
    2.19 -	char	confirm_buf[PWS3_MAX_PASSWORD_LEN + 1];
    2.20 +	size_t	len;
    2.21  
    2.22  	if (argc > 2) {
    2.23  		return (CMD_USAGE);
    2.24  	} else if (argc == 2) {
    2.25 -		password_len = strlen(argv[1]);
    2.26 -		if (password_len == 0) {
    2.27 +		len = strlen(argv[1]);
    2.28 +		if (len == 0) {
    2.29  			pwm_err(ctx, "password must not be empty");
    2.30  			return (CMD_ERR);
    2.31 -		} else if (password_len + 1 > sizeof (ctx->password)) {
    2.32 +		} else if (len + 1 > sizeof (ctx->password)) {
    2.33  			pwm_err(ctx, "password too long");
    2.34  			return (CMD_ERR);
    2.35  		}
    2.36 -		memcpy(ctx->password, argv[1], password_len + 1);
    2.37 +		memcpy(ctx->password, argv[1], len + 1);
    2.38  	} else {
    2.39 -		if (readpassphrase("Enter password: ", password_buf,
    2.40 -		    sizeof (password_buf), RPP_ECHO_OFF | RPP_REQUIRE_TTY) ==
    2.41 -		    NULL) {
    2.42 -			err(1, "readpassphrase");
    2.43 -		}
    2.44 -		password_len = strlen(password_buf);
    2.45 -		if (password_len == 0) {
    2.46 -			pwm_err(ctx, "password must not be empty");
    2.47 +		if (pwm_read_password(ctx, 1) != 0) {
    2.48  			return (CMD_ERR);
    2.49  		}
    2.50 -		if (readpassphrase("Confirm password: ", confirm_buf,
    2.51 -		    sizeof (confirm_buf),
    2.52 -		    RPP_ECHO_OFF | RPP_REQUIRE_TTY) == NULL) {
    2.53 -			err(1, "readpassphrase");
    2.54 -		}
    2.55 -		if (strcmp(password_buf, confirm_buf) != 0) {
    2.56 -			pwm_err(ctx, "passwords do not match");
    2.57 -			return (CMD_ERR);
    2.58 -		}
    2.59 -		memcpy(ctx->password, password_buf, password_len + 1);
    2.60  	}
    2.61  
    2.62  	return (CMD_OK);
     3.1 --- a/compat.h	Sat Aug 12 10:41:52 2017 +0200
     3.2 +++ b/compat.h	Thu Aug 24 13:10:56 2017 +0200
     3.3 @@ -43,10 +43,6 @@
     3.4  #include "compat/queue.h"
     3.5  #endif /* !HAVE_SYS_QUEUE_H */
     3.6  
     3.7 -#ifndef	HAVE_READPASSPHRASE_H
     3.8 -#include "compat/readpassphrase.h"
     3.9 -#endif /* !HAVE_READPASSPHRASE_H */
    3.10 -
    3.11  #ifndef	HAVE_SETPROGNAME
    3.12  #include "compat/setprogname.h"
    3.13  #endif /* !HAVE_SETPROGNAME */
     4.1 --- a/compat/readpassphrase.c	Sat Aug 12 10:41:52 2017 +0200
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,209 +0,0 @@
     4.4 -/*	$OpenBSD: readpassphrase.c,v 1.24 2013/11/24 23:51:29 deraadt Exp $	*/
     4.5 -
     4.6 -/*
     4.7 - * Copyright (c) 2000-2002, 2007, 2010
     4.8 - *	Todd C. Miller <Todd.Miller@courtesan.com>
     4.9 - *
    4.10 - * Permission to use, copy, modify, and distribute this software for any
    4.11 - * purpose with or without fee is hereby granted, provided that the above
    4.12 - * copyright notice and this permission notice appear in all copies.
    4.13 - *
    4.14 - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    4.15 - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    4.16 - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    4.17 - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    4.18 - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    4.19 - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    4.20 - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    4.21 - *
    4.22 - * Sponsored in part by the Defense Advanced Research Projects
    4.23 - * Agency (DARPA) and Air Force Research Laboratory, Air Force
    4.24 - * Materiel Command, USAF, under agreement number F39502-99-1-0512.
    4.25 - */
    4.26 -
    4.27 -#include <ctype.h>
    4.28 -#include <errno.h>
    4.29 -#include <fcntl.h>
    4.30 -#ifdef	HAVE_PATHS_H
    4.31 -#include <paths.h>
    4.32 -#endif /* HAVE_PATHS_H */
    4.33 -#include <pwd.h>
    4.34 -#include <signal.h>
    4.35 -#include <string.h>
    4.36 -#include <termios.h>
    4.37 -#include <unistd.h>
    4.38 -#include "readpassphrase.h"
    4.39 -
    4.40 -#ifndef TCSASOFT
    4.41 -#define TCSASOFT 0
    4.42 -#endif /* !TCSASOFT */
    4.43 -
    4.44 -#ifndef	_NSIG
    4.45 -#ifdef NSIG
    4.46 -#define	_NSIG NSIG
    4.47 -#else /* NSIG */
    4.48 -#define	_NSIG 128
    4.49 -#endif /* NSIG */
    4.50 -#endif /* !_NSIG */
    4.51 -
    4.52 -#ifndef	_PATH_TTY
    4.53 -#define	_PATH_TTY	"/dev/tty"
    4.54 -#endif
    4.55 -
    4.56 -static volatile sig_atomic_t signo[_NSIG];
    4.57 -
    4.58 -static void handler(int);
    4.59 -
    4.60 -char *
    4.61 -readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
    4.62 -{
    4.63 -	ssize_t nr;
    4.64 -	int input, output, save_errno, i, need_restart;
    4.65 -	char ch, *p, *end;
    4.66 -	struct termios term, oterm;
    4.67 -	struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm;
    4.68 -	struct sigaction savetstp, savettin, savettou, savepipe;
    4.69 -
    4.70 -	/* I suppose we could alloc on demand in this case (XXX). */
    4.71 -	if (bufsiz == 0) {
    4.72 -		errno = EINVAL;
    4.73 -		return(NULL);
    4.74 -	}
    4.75 -
    4.76 -restart:
    4.77 -	for (i = 0; i < _NSIG; i++)
    4.78 -		signo[i] = 0;
    4.79 -	nr = -1;
    4.80 -	save_errno = 0;
    4.81 -	need_restart = 0;
    4.82 -	/*
    4.83 -	 * Read and write to /dev/tty if available.  If not, read from
    4.84 -	 * stdin and write to stderr unless a tty is required.
    4.85 -	 */
    4.86 -	if ((flags & RPP_STDIN) ||
    4.87 -	    (input = output = open(_PATH_TTY, O_RDWR)) == -1) {
    4.88 -		if (flags & RPP_REQUIRE_TTY) {
    4.89 -			errno = ENOTTY;
    4.90 -			return(NULL);
    4.91 -		}
    4.92 -		input = STDIN_FILENO;
    4.93 -		output = STDERR_FILENO;
    4.94 -	}
    4.95 -
    4.96 -	/*
    4.97 -	 * Turn off echo if possible.
    4.98 -	 * If we are using a tty but are not the foreground pgrp this will
    4.99 -	 * generate SIGTTOU, so do it *before* installing the signal handlers.
   4.100 -	 */
   4.101 -	if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) {
   4.102 -		memcpy(&term, &oterm, sizeof(term));
   4.103 -		if (!(flags & RPP_ECHO_ON))
   4.104 -			term.c_lflag &= ~(ECHO | ECHONL);
   4.105 -#ifdef VSTATUS
   4.106 -		if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)
   4.107 -			term.c_cc[VSTATUS] = _POSIX_VDISABLE;
   4.108 -#endif /* VSTATUS */
   4.109 -		(void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term);
   4.110 -	} else {
   4.111 -		memset(&term, 0, sizeof(term));
   4.112 -		term.c_lflag |= ECHO;
   4.113 -		memset(&oterm, 0, sizeof(oterm));
   4.114 -		oterm.c_lflag |= ECHO;
   4.115 -	}
   4.116 -
   4.117 -	/*
   4.118 -	 * Catch signals that would otherwise cause the user to end
   4.119 -	 * up with echo turned off in the shell.  Don't worry about
   4.120 -	 * things like SIGXCPU and SIGVTALRM for now.
   4.121 -	 */
   4.122 -	sigemptyset(&sa.sa_mask);
   4.123 -	sa.sa_flags = 0;		/* don't restart system calls */
   4.124 -	sa.sa_handler = handler;
   4.125 -	(void)sigaction(SIGALRM, &sa, &savealrm);
   4.126 -	(void)sigaction(SIGHUP, &sa, &savehup);
   4.127 -	(void)sigaction(SIGINT, &sa, &saveint);
   4.128 -	(void)sigaction(SIGPIPE, &sa, &savepipe);
   4.129 -	(void)sigaction(SIGQUIT, &sa, &savequit);
   4.130 -	(void)sigaction(SIGTERM, &sa, &saveterm);
   4.131 -	(void)sigaction(SIGTSTP, &sa, &savetstp);
   4.132 -	(void)sigaction(SIGTTIN, &sa, &savettin);
   4.133 -	(void)sigaction(SIGTTOU, &sa, &savettou);
   4.134 -
   4.135 -	if (!(flags & RPP_STDIN))
   4.136 -		(void)write(output, prompt, strlen(prompt));
   4.137 -	end = buf + bufsiz - 1;
   4.138 -	p = buf;
   4.139 -	while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') {
   4.140 -		if (p < end) {
   4.141 -			if ((flags & RPP_SEVENBIT))
   4.142 -				ch &= 0x7f;
   4.143 -			if (isalpha((unsigned char)ch)) {
   4.144 -				if ((flags & RPP_FORCELOWER))
   4.145 -					ch = (char)tolower((unsigned char)ch);
   4.146 -				if ((flags & RPP_FORCEUPPER))
   4.147 -					ch = (char)toupper((unsigned char)ch);
   4.148 -			}
   4.149 -			*p++ = ch;
   4.150 -		}
   4.151 -	}
   4.152 -	*p = '\0';
   4.153 -	save_errno = errno;
   4.154 -	if (!(term.c_lflag & ECHO))
   4.155 -		(void)write(output, "\n", 1);
   4.156 -
   4.157 -	/* Restore old terminal settings and signals. */
   4.158 -	if (memcmp(&term, &oterm, sizeof(term)) != 0) {
   4.159 -		while (tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm) == -1 &&
   4.160 -		    errno == EINTR && !signo[SIGTTOU])
   4.161 -			continue;
   4.162 -	}
   4.163 -	(void)sigaction(SIGALRM, &savealrm, NULL);
   4.164 -	(void)sigaction(SIGHUP, &savehup, NULL);
   4.165 -	(void)sigaction(SIGINT, &saveint, NULL);
   4.166 -	(void)sigaction(SIGQUIT, &savequit, NULL);
   4.167 -	(void)sigaction(SIGPIPE, &savepipe, NULL);
   4.168 -	(void)sigaction(SIGTERM, &saveterm, NULL);
   4.169 -	(void)sigaction(SIGTSTP, &savetstp, NULL);
   4.170 -	(void)sigaction(SIGTTIN, &savettin, NULL);
   4.171 -	(void)sigaction(SIGTTOU, &savettou, NULL);
   4.172 -	if (input != STDIN_FILENO)
   4.173 -		(void)close(input);
   4.174 -
   4.175 -	/*
   4.176 -	 * If we were interrupted by a signal, resend it to ourselves
   4.177 -	 * now that we have restored the signal handlers.
   4.178 -	 */
   4.179 -	for (i = 0; i < _NSIG; i++) {
   4.180 -		if (signo[i]) {
   4.181 -			kill(getpid(), i);
   4.182 -			switch (i) {
   4.183 -			case SIGTSTP:
   4.184 -			case SIGTTIN:
   4.185 -			case SIGTTOU:
   4.186 -				need_restart = 1;
   4.187 -			}
   4.188 -		}
   4.189 -	}
   4.190 -	if (need_restart)
   4.191 -		goto restart;
   4.192 -
   4.193 -	if (save_errno)
   4.194 -		errno = save_errno;
   4.195 -	return(nr == -1 ? NULL : buf);
   4.196 -}
   4.197 -
   4.198 -#if 0
   4.199 -char *
   4.200 -getpass(const char *prompt)
   4.201 -{
   4.202 -	static char buf[_PASSWORD_LEN + 1];
   4.203 -
   4.204 -	return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF));
   4.205 -}
   4.206 -#endif
   4.207 -
   4.208 -static void handler(int s)
   4.209 -{
   4.210 -
   4.211 -	signo[s] = 1;
   4.212 -}
     5.1 --- a/compat/readpassphrase.h	Sat Aug 12 10:41:52 2017 +0200
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,38 +0,0 @@
     5.4 -/*	$OpenBSD: readpassphrase.h,v 1.5 2003/06/17 21:56:23 millert Exp $	*/
     5.5 -
     5.6 -/*
     5.7 - * Copyright (c) 2000, 2002 Todd C. Miller <Todd.Miller@courtesan.com>
     5.8 - *
     5.9 - * Permission to use, copy, modify, and distribute this software for any
    5.10 - * purpose with or without fee is hereby granted, provided that the above
    5.11 - * copyright notice and this permission notice appear in all copies.
    5.12 - *
    5.13 - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    5.14 - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    5.15 - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    5.16 - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    5.17 - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    5.18 - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    5.19 - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    5.20 - *
    5.21 - * Sponsored in part by the Defense Advanced Research Projects
    5.22 - * Agency (DARPA) and Air Force Research Laboratory, Air Force
    5.23 - * Materiel Command, USAF, under agreement number F39502-99-1-0512.
    5.24 - */
    5.25 -
    5.26 -#ifndef _READPASSPHRASE_H_
    5.27 -#define _READPASSPHRASE_H_
    5.28 -
    5.29 -#define RPP_ECHO_OFF    0x00		/* Turn off echo (default). */
    5.30 -#define RPP_ECHO_ON     0x01		/* Leave echo on. */
    5.31 -#define RPP_REQUIRE_TTY 0x02		/* Fail if there is no tty. */
    5.32 -#define RPP_FORCELOWER  0x04		/* Force input to lower case. */
    5.33 -#define RPP_FORCEUPPER  0x08		/* Force input to upper case. */
    5.34 -#define RPP_SEVENBIT    0x10		/* Strip the high bit from input. */
    5.35 -#define RPP_STDIN       0x20		/* Read from stdin, not /dev/tty */
    5.36 -
    5.37 -#include <sys/types.h>
    5.38 -
    5.39 -char * readpassphrase(const char *, char *, size_t, int);
    5.40 -
    5.41 -#endif /* !_READPASSPHRASE_H_ */
     6.1 --- a/pager.c	Sat Aug 12 10:41:52 2017 +0200
     6.2 +++ b/pager.c	Thu Aug 24 13:10:56 2017 +0200
     6.3 @@ -28,6 +28,7 @@
     6.4  #endif /* HAVE_ERR_H */
     6.5  #include <errno.h>
     6.6  #include <fcntl.h>
     6.7 +#include <libtecla.h>
     6.8  #include <limits.h>
     6.9  #include <signal.h>
    6.10  #include <stdio.h>
    6.11 @@ -46,22 +47,6 @@
    6.12  #include "pager.h"
    6.13  #include "util.h"
    6.14  
    6.15 -#ifndef	TCSASOFT
    6.16 -#define	TCSASOFT 0
    6.17 -#endif /* !TCSASOFT */
    6.18 -
    6.19 -#ifndef	_NSIG
    6.20 -#ifdef NSIG
    6.21 -#define	_NSIG NSIG
    6.22 -#else /* NSIG */
    6.23 -#define	_NSIG 128
    6.24 -#endif /* NSIG */
    6.25 -#endif /* !_NSIG */
    6.26 -
    6.27 -#ifndef	_PATH_TTY
    6.28 -#define	_PATH_TTY	"/dev/tty"
    6.29 -#endif
    6.30 -
    6.31  struct pager {
    6.32  	TAILQ_HEAD(lines_head, lines_entry) lines_head;
    6.33  	FILE		*fp;
    6.34 @@ -74,123 +59,22 @@
    6.35  	char		*line;
    6.36  };
    6.37  
    6.38 -static volatile sig_atomic_t signals[_NSIG];
    6.39 +static int
    6.40 +getch_prompt(GetLine *gl, const char *prompt)
    6.41 +{
    6.42 +	int	c;
    6.43 +	int	saved_echo_mode;
    6.44  
    6.45 -static void
    6.46 -sig_handler(int signo)
    6.47 -{
    6.48 -	signals[signo] = 1;
    6.49 -}
    6.50 -
    6.51 -static int
    6.52 -getch_prompt(const char *prompt)
    6.53 -{
    6.54 -	int		retval = -1;
    6.55 -	int		signo;
    6.56 -	int		fd;
    6.57 -	struct termios	saved_term;
    6.58 -	struct termios	term;
    6.59 -	struct sigaction sa;
    6.60 -	struct sigaction saved_sa_hup;
    6.61 -	struct sigaction saved_sa_int;
    6.62 -	struct sigaction saved_sa_quit;
    6.63 -	struct sigaction saved_sa_pipe;
    6.64 -	struct sigaction saved_sa_alrm;
    6.65 -	struct sigaction saved_sa_term;
    6.66 -	struct sigaction saved_sa_tstp;
    6.67 -	struct sigaction saved_sa_ttin;
    6.68 -	struct sigaction saved_sa_ttou;
    6.69 -	char		c;
    6.70 -	int		need_restart = 0;
    6.71 -
    6.72 -	printf("%s", prompt);
    6.73 -	fflush(stdout);
    6.74 -
    6.75 -restart:
    6.76 -	for (signo = 0; signo < _NSIG; signo++) {
    6.77 -		signals[signo] = 0;
    6.78 -	}
    6.79 -
    6.80 -	fd = open(_PATH_TTY, O_RDONLY);
    6.81 -	if (fd < 0) {
    6.82 -		return (-1);
    6.83 -	}
    6.84 -
    6.85 -	if (tcgetattr(fd, &saved_term) != 0) {
    6.86 -		close(fd);
    6.87 -		return (-1);
    6.88 -	}
    6.89 -	memcpy(&term, &saved_term, sizeof (struct termios));
    6.90 -
    6.91 -	/* enter raw mode and turn echo off */
    6.92 -	term.c_lflag &= ~(ICANON | ECHO);
    6.93 -	while ((tcsetattr(fd, TCSAFLUSH | TCSASOFT, &term) < 0) &&
    6.94 -	    (errno != EINTR)) {
    6.95 -		continue;
    6.96 -	}
    6.97 -
    6.98 -	/* install temporary signal handler */
    6.99 -	sigemptyset(&sa.sa_mask);
   6.100 -	sa.sa_flags = 0;
   6.101 -	sa.sa_handler = sig_handler;
   6.102 -	sigaction(SIGHUP, &sa, &saved_sa_hup);
   6.103 -	sigaction(SIGINT, &sa, &saved_sa_int);
   6.104 -	sigaction(SIGQUIT, &sa, &saved_sa_quit);
   6.105 -	sigaction(SIGPIPE, &sa, &saved_sa_pipe);
   6.106 -	sigaction(SIGALRM, &sa, &saved_sa_alrm);
   6.107 -	sigaction(SIGTERM, &sa, &saved_sa_term);
   6.108 -	sigaction(SIGTSTP, &sa, &saved_sa_tstp);
   6.109 -	sigaction(SIGTTIN, &sa, &saved_sa_ttin);
   6.110 -	sigaction(SIGTTOU, &sa, &saved_sa_ttou);
   6.111 -
   6.112 -	/* read key */
   6.113 -	if (read(fd, &c, 1) == sizeof (c)) {
   6.114 -		retval = c;
   6.115 -	}
   6.116 -
   6.117 -	/* restore previous mode and echo setting */
   6.118 -	do {
   6.119 -		while ((tcsetattr(fd, TCSAFLUSH | TCSASOFT,
   6.120 -		    &saved_term) < 0) && (errno != EINTR)) {
   6.121 -			continue;
   6.122 -		}
   6.123 -	} while ((tcgetattr(fd, &term) == 0) &&
   6.124 -	    (term.c_lflag != saved_term.c_lflag));
   6.125 -
   6.126 -	/* restore previous signal handlers */
   6.127 -	sigaction(SIGHUP, &saved_sa_hup, &sa);
   6.128 -	sigaction(SIGINT, &saved_sa_int, &sa);
   6.129 -	sigaction(SIGQUIT, &saved_sa_quit, &sa);
   6.130 -	sigaction(SIGPIPE, &saved_sa_pipe, &sa);
   6.131 -	sigaction(SIGALRM, &saved_sa_alrm, &sa);
   6.132 -	sigaction(SIGTERM, &saved_sa_term, &sa);
   6.133 -	sigaction(SIGTSTP, &saved_sa_tstp, &sa);
   6.134 -	sigaction(SIGTTIN, &saved_sa_ttin, &sa);
   6.135 -	sigaction(SIGTTOU, &saved_sa_ttou, &sa);
   6.136 +	/* prompt with echo off */
   6.137 +	saved_echo_mode = gl_echo_mode(gl, -1);
   6.138 +	gl_echo_mode(gl, 0);
   6.139 +	c = gl_query_char(gl, prompt, '\0');
   6.140 +	gl_echo_mode(gl, saved_echo_mode);
   6.141  
   6.142  	/* erase prompt */
   6.143  	printf("\r%*s\r", (int)strlen(prompt), "");
   6.144 -	fflush(stdout);
   6.145  
   6.146 -	while ((close(fd) < 0) && (errno != EINTR)) {
   6.147 -		continue;
   6.148 -	}
   6.149 -
   6.150 -	/* re-raise signals received */
   6.151 -	for (signo = 0; signo < _NSIG; signo++) {
   6.152 -		if (signals[signo]) {
   6.153 -			raise(signo);
   6.154 -			if ((signo == SIGTSTP) || (signo == SIGTTIN) ||
   6.155 -			    (signo == SIGTTOU)) {
   6.156 -				need_restart = 1;
   6.157 -			}
   6.158 -		}
   6.159 -	}
   6.160 -	if (need_restart) {
   6.161 -		goto restart;
   6.162 -	}
   6.163 -
   6.164 -	return (retval);
   6.165 +	return (c);
   6.166  }
   6.167  
   6.168  struct pager *
   6.169 @@ -370,6 +254,7 @@
   6.170  	struct winsize	ws;
   6.171  #endif /* TIOCGWINSZ */
   6.172  	unsigned int	row = 0;
   6.173 +	GetLine		*gl;
   6.174  	struct lines_entry *entry;
   6.175  
   6.176  	is_interactive = (isatty(STDIN_FILENO) && (pager->fp == stdout));
   6.177 @@ -384,12 +269,18 @@
   6.178  	}
   6.179  #endif /* TIOCGWINSZ */
   6.180  
   6.181 +	gl = new_GetLine(10, 0);
   6.182 +	if (gl == NULL) {
   6.183 +		err(1, "new_GetLine");
   6.184 +	}
   6.185 +
   6.186  	TAILQ_FOREACH(entry, &pager->lines_head, entry) {
   6.187  		if (is_interactive) {
   6.188  			mbsnprint(cols, entry->line, pager->fp);
   6.189  			row++;
   6.190 -			if (row == rows - 1) {
   6.191 -				getch_prompt("--More--");
   6.192 +			if ((TAILQ_NEXT(entry, entry) != NULL) &&
   6.193 +			    (row == rows - 1)) {
   6.194 +				getch_prompt(gl, "--More--");
   6.195  				row = 0;
   6.196  			}
   6.197  		} else {
   6.198 @@ -397,4 +288,6 @@
   6.199  			fflush(pager->fp);
   6.200  		}
   6.201  	}
   6.202 +
   6.203 +	del_GetLine(gl);
   6.204  }
     7.1 --- a/pwm.c	Sat Aug 12 10:41:52 2017 +0200
     7.2 +++ b/pwm.c	Thu Aug 24 13:10:56 2017 +0200
     7.3 @@ -27,12 +27,10 @@
     7.4  #include <err.h>
     7.5  #endif /* HAVE_ERR_H */
     7.6  #include <errno.h>
     7.7 +#include <fcntl.h>
     7.8  #include <langinfo.h>
     7.9  #include <locale.h>
    7.10  #include <pwd.h>
    7.11 -#ifdef	HAVE_READPASSPHRASE_H
    7.12 -#include <readpassphrase.h>
    7.13 -#endif /* READPASSPHRASE_H */
    7.14  #include <stdlib.h>
    7.15  #include <stdio.h>
    7.16  #include <string.h>
    7.17 @@ -47,9 +45,17 @@
    7.18  #include "tok.h"
    7.19  #include "util.h"
    7.20  
    7.21 -#ifndef	PWM_LINE_MAX
    7.22 -#define	PWM_LINE_MAX	16384
    7.23 -#endif /* !PWM_LINE_MAX */
    7.24 +#ifndef	PWM_HISTORY_ENTRIES_MAX
    7.25 +#define	PWM_HISTORY_ENTRIES_MAX	1024
    7.26 +#endif /* !PWM_HISTORY_MAX */
    7.27 +
    7.28 +#ifndef	PWM_HISTORY_LINES_MAX
    7.29 +#define	PWM_HISTORY_LINES_MAX	256
    7.30 +#endif /* !PWM_HISTORY_LINES_MAX */
    7.31 +
    7.32 +#ifndef	PWM_HISTORY_MAX
    7.33 +#define	PWM_HISTORY_MAX	(PWM_HISTORY_LINES_MAX * PWM_LINE_MAX)
    7.34 +#endif /* !PWM_HISTORY_MAX */
    7.35  
    7.36  static void
    7.37  usage(void)
    7.38 @@ -76,49 +82,53 @@
    7.39  }
    7.40  
    7.41  static int
    7.42 +complete_nothing(WordCompletion *cpl, void *data, const char *line,
    7.43 +    int word_end)
    7.44 +{
    7.45 +	return (0);
    7.46 +}
    7.47 +
    7.48 +static int
    7.49  run_input_loop(struct pwm_ctx *ctx, int is_interactive)
    7.50  {
    7.51  	int		retval = -1;
    7.52 +	char		prompt[8 + 2 + 1];
    7.53 +	GetLine		*gl = NULL;
    7.54  	char		buf[PWM_LINE_MAX];
    7.55 +	char		*line = buf;
    7.56  	int		c;
    7.57  	int		argc = 0;
    7.58  	char		**argv = NULL;
    7.59  	struct cmd	*cmd;
    7.60  	int		i;
    7.61  
    7.62 +	snprintf(prompt, sizeof (prompt), "%.*s> ", 8, getprogname());
    7.63 +
    7.64 +	/* initialize libtecla */
    7.65 +	gl = new_GetLine(PWM_LINE_MAX, PWM_HISTORY_MAX);
    7.66 +	if (gl == NULL) {
    7.67 +		err(1, "new_GetLine");
    7.68 +	}
    7.69 +	gl_limit_history(gl, PWM_HISTORY_LINES_MAX);
    7.70 +	/* disable default filename completion */
    7.71 +	gl_customize_completion(gl, NULL, complete_nothing);
    7.72 +
    7.73  	for (;;) {
    7.74  		cmd = NULL;
    7.75 -		if (fgets(buf, (int)sizeof (buf), stdin) == NULL) {
    7.76 -			if (ferror(stdin)) {
    7.77 -				/* error */
    7.78 -				warn("failed to read command");
    7.79 -				goto out;
    7.80 -			} else if (feof(stdin)) {
    7.81 -				/* EOF */
    7.82 +		line = gl_get_line(gl, prompt, NULL, -1);
    7.83 +		if (line == NULL) {
    7.84 +			switch (gl_return_status(gl)) {
    7.85 +			case GLR_EOF:
    7.86  				break;
    7.87 +			case GLR_ERROR:
    7.88 +				warnx("gl_get_line: %s",
    7.89 +				    gl_error_message(gl, NULL, 0));
    7.90  			}
    7.91 -		}
    7.92 -		if ((buf[strlen(buf) - 1] != '\n') && !feof(stdin)) {
    7.93 -			/* line was truncated */
    7.94 -			fprintf(stderr, "line too long\n");
    7.95 -			if (is_interactive) {
    7.96 -				/* skip input to next newline */
    7.97 -				do {
    7.98 -					errno = 0;
    7.99 -					c = fgetc(stdin);
   7.100 -					if ((c == EOF) && (errno != 0)) {
   7.101 -						warn("failed to read command");
   7.102 -						goto out;
   7.103 -					}
   7.104 -				} while ((c != '\n') && (c != EOF));
   7.105 -			} else {
   7.106 -				/* fatal error in non-interactive mode */
   7.107 -				goto out;
   7.108 -			}
   7.109 +			break;
   7.110  		}
   7.111  
   7.112  		/* tokenize line */
   7.113 -		switch(tok_tokenize(buf, &argc, &argv)) {
   7.114 +		switch (tok_tokenize(line, &argc, &argv)) {
   7.115  		case TOK_ERR_SYSTEM_ERROR:
   7.116  			err(1, "tok_tokenize");
   7.117  		case TOK_ERR_UNTERMINATED_QUOTE:
   7.118 @@ -183,6 +193,75 @@
   7.119  		free(argv[i]);
   7.120  	}
   7.121  	free(argv);
   7.122 +	del_GetLine(gl);
   7.123 +
   7.124 +	return (retval);
   7.125 +}
   7.126 +
   7.127 +int
   7.128 +pwm_read_password(struct pwm_ctx *ctx, int is_new_password)
   7.129 +{
   7.130 +	int	retval = -1;
   7.131 +	GetLine	*gl = NULL;
   7.132 +	char	*line;
   7.133 +	size_t	len;
   7.134 +	char	password_buf[sizeof (ctx->password)] = { '\0' };
   7.135 +
   7.136 +	/* initialize libtecla */
   7.137 +	gl = new_GetLine(sizeof (password_buf) - 1, 0);
   7.138 +	if (gl == NULL) {
   7.139 +		err(1, "new_GetLine");
   7.140 +	}
   7.141 +	/* disable default filename completion */
   7.142 +	gl_customize_completion(gl, NULL, complete_nothing);
   7.143 +	gl_echo_mode(gl, 0);
   7.144 +
   7.145 +	line = gl_get_line(gl, is_new_password ? "New password: " :
   7.146 +	    "Password: ", NULL, -1);
   7.147 +	putchar('\n');
   7.148 +	if (line == NULL) {
   7.149 +		if (gl_return_status(gl) == GLR_ERROR) {
   7.150 +			errx(1, "gl_get_line: %s", gl_error_message(gl, NULL,
   7.151 +			    0));
   7.152 +		}
   7.153 +		goto out;
   7.154 +	}
   7.155 +	len = strlen(line);
   7.156 +	if ((len > 0) && (line[len - 1] == '\n')) {
   7.157 +		line[--len] = '\0';
   7.158 +	}
   7.159 +	if (len == 0) {
   7.160 +		fprintf(stderr, "password must not be empty\n");
   7.161 +		goto out;
   7.162 +	}
   7.163 +	strcpy(password_buf, line);
   7.164 +
   7.165 +	/* confirm the entered password entered */
   7.166 +	if (is_new_password) {
   7.167 +		line = gl_get_line(gl, "Confirm password: ", NULL, -1);
   7.168 +		putchar('\n');
   7.169 +		if (line == NULL) {
   7.170 +			if (gl_return_status(gl) == GLR_ERROR) {
   7.171 +				errx(1, "gl_get_line: %s", gl_error_message(gl,
   7.172 +				    NULL, 0));
   7.173 +			}
   7.174 +			goto out;
   7.175 +		}
   7.176 +		len = strlen(line);
   7.177 +		if ((len > 0) && (line[len - 1] == '\n')) {
   7.178 +			line[--len] = '\0';
   7.179 +		}
   7.180 +		if (strcmp(password_buf, line) != 0) {
   7.181 +			fprintf(stderr, "passwords do not match\n");
   7.182 +			goto out;
   7.183 +		}
   7.184 +	}
   7.185 +
   7.186 +	strcpy(ctx->password, password_buf);
   7.187 +	retval = 0;
   7.188 +
   7.189 +out:
   7.190 +	del_GetLine(gl);
   7.191  
   7.192  	return (retval);
   7.193  }
   7.194 @@ -253,7 +332,6 @@
   7.195  	struct passwd	*passwd;
   7.196  	char		*pwm_dirname = NULL;
   7.197  	FILE		*fp = NULL;
   7.198 -	char		password_buf[PWS3_MAX_PASSWORD_LEN + 1];
   7.199  
   7.200  	setprogname(argv[0]);
   7.201  
   7.202 @@ -343,27 +421,8 @@
   7.203  		    ctx.password, sizeof (ctx.password)) != 0) {
   7.204  			goto out;
   7.205  		}
   7.206 -	} else {
   7.207 -		if (readpassphrase("Enter password: ", ctx.password,
   7.208 -		    sizeof (ctx.password), RPP_ECHO_OFF | RPP_REQUIRE_TTY) ==
   7.209 -		    NULL) {
   7.210 -			err(1, "readpassphrase");
   7.211 -		}
   7.212 -		if (ctx.password[0] == '\0') {
   7.213 -			fprintf(stderr, "password must not be empty\n");
   7.214 -			goto out;
   7.215 -		}
   7.216 -		if (fp == NULL) {
   7.217 -			if (readpassphrase("Confirm password: ", password_buf,
   7.218 -			    sizeof (password_buf),
   7.219 -			    RPP_ECHO_OFF | RPP_REQUIRE_TTY) == NULL) {
   7.220 -				err(1, "readpassphrase");
   7.221 -			}
   7.222 -			if (strcmp(ctx.password, password_buf) != 0) {
   7.223 -				fprintf(stderr, "passwords do not match\n");
   7.224 -				goto out;
   7.225 -			}
   7.226 -		}
   7.227 +	} else if (pwm_read_password(&ctx, (fp == NULL)) != 0) {
   7.228 +		goto out;
   7.229  	}
   7.230  	if (fp != NULL) {
   7.231  		if (pwfile_read_file(&ctx, fp) != 0) {
     8.1 --- a/pwm.h	Sat Aug 12 10:41:52 2017 +0200
     8.2 +++ b/pwm.h	Thu Aug 24 13:10:56 2017 +0200
     8.3 @@ -24,8 +24,13 @@
     8.4  #ifndef	PWM_H
     8.5  #define	PWM_H
     8.6  
     8.7 +#include <libtecla.h>
     8.8  #include <pws.h>
     8.9  
    8.10 +#ifndef	PWM_LINE_MAX
    8.11 +#define	PWM_LINE_MAX	16384
    8.12 +#endif /* !PWM_LINE_MAX */
    8.13 +
    8.14  struct pwm_ctx {
    8.15  	const char	*prev_cmd;
    8.16  	char		*errmsg;
    8.17 @@ -38,5 +43,6 @@
    8.18  };
    8.19  
    8.20  void	pwm_err(struct pwm_ctx *, char *, ...);
    8.21 +int	pwm_read_password(struct pwm_ctx *, int);
    8.22  
    8.23  #endif /* PWM_H */