commit ccfdce0900819580b2f6b0941015ac2fbdc71809
parent d73960aadcda4fdf4f787cdf5f0b435873e57bc9
Author: Naveen Narayanan zerous <zerous@nocebo.space>
Date: Sat, 23 Dec 2017 16:10:07 +0300
Add printpass, delete, and mkdirp. Add log.c
- implement a common logging interface
- use basename, readpassphrase
- fixed compiler warnings
Diffstat:
Makefile | | | 3 | ++- |
log.c | | | 61 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
pass.c | | | 282 | ++++++++++++++++++++++++++++++++++++------------------------------------------- |
pass.h | | | 3 | +++ |
readpassphrase.c | | | 187 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
readpassphrase.h | | | 31 | +++++++++++++++++++++++++++++++ |
6 files changed, 414 insertions(+), 153 deletions(-)
diff --git a/Makefile b/Makefile
@@ -3,7 +3,8 @@ VERSION = 0.1
include config.mk
OBJ = pass.o \
- log.o
+ log.o \
+ readpassphrase.o
BIN = pass
diff --git a/log.c b/log.c
@@ -1,4 +1,7 @@
#include <errno.h>
+#include <gpgme.h>
+#include <limits.h>
+#include <sys/stat.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -13,7 +16,30 @@ static char *progname;
static void
vlog(char *msg, va_list ap)
{
+ char file[PATH_MAX];
+ const char *home;
+ FILE *fp;
+ struct stat sb;
+
if (debug) {
+ if (!(home = getenv("HOME"))) {
+ fprintf(stderr, "$HOME not set, cannot determine password-store location");
+ exit(1);
+ }
+ snprintf(file, sizeof(file), "%s/.pass.log", home);
+
+ if (!stat(file,&sb))
+ remove(file);
+ else {
+ if((fp = fopen(file, "ab"))) {
+ fprintf(fp, "%s: ", progname);
+ vfprintf(fp, msg, ap);
+ fputc('\n', fp);
+ } else {
+ fprintf(stderr, "fopen %s: %s", file, strerror(errno));
+ }
+ }
+ } else {
fprintf(stderr, "%s: ", progname);
vfprintf(stderr, msg, ap);
fputc('\n', stderr);
@@ -71,6 +97,41 @@ logwarnx(char *msg, ...)
}
void
+loggpg(gpgme_error_t gerr, char *msg, ...)
+{
+ char buf[512];
+ va_list ap;
+
+ va_start(ap, msg);
+ snprintf(buf, sizeof(buf), "%s: %s", msg, gpgme_strerror(gerr));
+ vlog(msg, ap);
+ va_end(ap);
+}
+
+void
+loggpgx(char *msg, ...)
+{
+ va_list ap;
+
+ va_start(ap, msg);
+ vlog(msg, ap);
+ va_end(ap);
+}
+
+void
+fatalgpg(gpgme_error_t gerr, char *msg, ...)
+{
+ char buf[512];
+ va_list ap;
+
+ va_start(ap, msg);
+ snprintf(buf, sizeof(buf), "%s: %s", msg, gpgme_strerror(gerr));
+ vlog(buf, ap);
+ va_end(ap);
+ exit(1);
+}
+
+void
fatal(char *msg, ...)
{
char buf[512];
diff --git a/pass.c b/pass.c
@@ -1,9 +1,9 @@
-#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <gpgme.h>
#include <getopt.h>
#include <limits.h>
+#include <libgen.h>
#include <locale.h>
#include <pwd.h>
#include <stdio.h>
@@ -13,6 +13,9 @@
#include <unistd.h>
#include "pass.h"
+#include "readpassphrase.h"
+
+static char file[PATH_MAX];
void
initgpgme(void)
@@ -27,139 +30,96 @@ initgpgme(void)
}
void
-find (char *item)
-{
- (void)item;
-}
-
-void
-delete (char *item)
+delete(char *item)
{
- (void)item;
-}
-
-void
-list(void)
-{
-
+ char *home;
+ int r;
+ struct sb;
+
+ if (!(home = getenv("HOME")))
+ fatalx("$HOME not set, cannot determine password-store location");
+ snprintf(file, sizeof(file), "%s/.password-store/%s.gpg", home, item);
+ printf("Are you sure you would like to delete %s? [y/N] ", item);
+ if ((r = getchar()) == 'N')
+ exit(0);
+ else if (r == 'y') {
+ if (remove(file)) {
+ if (debug)
+ logwarn("rm %s", item);
+ else {
+ fatal("rm %s", item);
+ }
+ }
+ printf("removed '%s'\n", file);
+ }
}
-
void
usage(void)
{
- return;
+ printf("usage\n");
+ exit(0);
}
void
printpass(char *item)
{
- char file[PATH_MAX], uid[128], buf[512];
+ char buf[512];
const char* home;
- int fin;
- FILE* fp;
- /*mode_t mode = S_IRWXU;*/
+ int fin, a, ret;
+
gpgme_data_t in, out;
gpgme_error_t gpgerr;
gpgme_ctx_t ctx;
- /*gpgme_key_t key;*/
- /*gpgme_key_t keys[2];*/
gpgme_protocol_t proto;
- gpgme_decrypt_result_t res;
-
- /*
- * Algo:
- * Check if file exists
- * If it does
- * get the uid
- * create gpg objects
- * open file
- * decrypt
- * print data
- */
-
- (void)uid;
initgpgme();
proto = GPGME_PROTOCOL_OpenPGP;
if (!(home = getenv("HOME")))
- errx(1, "$HOME not set, cannot determine password-store location");
+ fatalx("$HOME not set, cannot determine password-store location");
snprintf(file, sizeof(file), "%s/.password-store/%s.gpg", home, item);
- /*printf("file: %s\n", file);*/
-
/* Check if file exists */
fin = open(file, O_RDONLY);
if (fin == -1) {
- if (debug)
fatal("%s is not in password store.", file);
- else
- errx(1, "%s is not in password store.", item);
}
-
-
- if (gpgme_err_code(gpgme_new(&ctx)) != GPG_ERR_NO_ERROR)
- errx(1, "gpme_new");
+ gpgerr = gpgme_new(&ctx);
+ if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR) {
+ fatalgpg(gpgerr, "Error: gpgme_new: %s");
+ }
gpgerr = gpgme_set_protocol(ctx, proto);
if (gpgme_err_code(gpgerr) == GPG_ERR_INV_VALUE)
- errx(1, "gpgme_set_protocol");
+ fatalgpg(gpgerr, "Error: gpgme_set_protocol");
gpgerr = gpgme_data_new_from_file(&in, file, 1);
if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR)
- err(1, "gpgme_data_new_from_fd: %s\n", gpgme_strerror(gpgerr));
+ fatalgpg(gpgerr, "Error: gpgme_data_new_from_file");
gpgerr = gpgme_data_new(&out);
if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR)
- err(1, "gpgme_data_new: %s\n", gpgme_strerror(gpgerr));
-
- /* set ascii armor */
- /*gpgme_set_armor(ctx, 1);*/
+ fatalgpg(gpgerr, "Error: gpgme_data_new");
/* decrypt */
gpgerr = gpgme_op_decrypt(ctx, in, out);
if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR)
- err(1, " gpgme_op_decrypt: %s\n", gpgme_strerror(gpgerr));
-
- (void)res;
- /*res = gpgme_op_decrypt_result(ctx);*/
- /*printf("res: %s\n, %d\n, %s\n",*/
- /*res->unsupported_algorithm,*/
- /*res->wrong_key_usage,*/
- /*res->file_name);*/
-
- /* print contents of data object */
- /*int ret = gpgme_data_seek(out, 0, SEEK_SET); */
- /*printf("here\n");*/
- /*if (ret) {*/
- /*printf("here\n");*/
-
- /*printf("gpgme_data_get_encoding: %s", gpgme_data_get_encoding(out));*/
-
+ fatalgpg(gpgerr, "Error: gpgme_op_decrypt");
- int a, ret;
ret = gpgme_data_seek(out, 0, SEEK_SET);
if (ret)
- err(1, "gpgme_data_seek");
+ fatalx("gpgme_data_seek");
if ((a = gpgme_data_read(out, buf, 100)) > 0) {
- /*printf("a : %d", a);*/
buf[a] = '\0';
}
printf("%s\n", buf);
- /*if ((gpgme_data_read(out, buf, 2)) > 0) {*/
- /*fwrite(buf, ret, 1, stdout);*/
- /*printf("%s", buf);*/
- /*}*/
- /*if (ret < 0)*/
- /*err(1, "can not find key: %s\n", gpgme_strerror(gpgerr));*/
- /*}*/
-
- /*gpgme_key_release(key);*/
+
gpgme_data_release(in);
gpgme_data_release(out);
gpgme_release(ctx);
+
close(fin);
}
@@ -172,7 +132,7 @@ getuserid(char *u)
int i;
if (!(home = getenv("HOME")))
- errx(1, "$HOME not set, cannot determine password-store location");
+ fatalx("$HOME not set, cannot determine password-store location");
snprintf(file, sizeof(file), "%s/.password-store/.gpg-id", home);
fp = fopen(file, "r");
@@ -182,40 +142,12 @@ getuserid(char *u)
}
void
-insert(char *item)
+mkdirp(const char *tp)
{
- char t[PATH_MAX];
- char *tp, *i, *gfile;
- const char *home;
- char file[PATH_MAX];
- FILE *fp, *fin, *fout;
+ char *i;
int r;
- char uid[128];
mode_t mode = S_IRWXU;
- gpgme_data_t in, out;
- gpgme_error_t gpgerr;
- gpgme_ctx_t ctx;
- gpgme_key_t key;
- gpgme_key_t keys[2];
- gpgme_protocol_t proto;
-
- initgpgme();
- proto = GPGME_PROTOCOL_OpenPGP;
- memcpy(t, item, strlen(item)+1);
- if (!(home = getenv("HOME")))
- errx(1, "$HOME not set, cannot determine password-store location");
- snprintf(file, sizeof(file), "%s/.password-store", home);
-
- tp = t;
- if ((i = strrchr(tp, '/'))) {
- gfile = i + 1;
- } else
- gfile = item;
-#ifdef DEBUG
- printf("gfile: %s\n", gfile);
-#endif
-
while ((i = strchr(tp, '/'))) {
*i = '\0';
snprintf(file, sizeof(file), "%s/%s", file, tp);
@@ -224,38 +156,81 @@ insert(char *item)
if (errno == EEXIST)
;
else
- err(1, "mkdir");
+ fatal("mkdir");
}
tp = i + 1;
}
- snprintf(file, sizeof(file), "%s/%s", file, gfile);
+}
+
+void
+insert(char *item)
+{
+ gpgme_data_t in, out;
+ gpgme_error_t gpgerr;
+ gpgme_ctx_t ctx;
+ gpgme_key_t key;
+ gpgme_key_t keys[2];
+ gpgme_protocol_t proto;
+
+ char *filename, t[PATH_MAX];
+ const char *home;
+ FILE *fp, *fin, *fout;
+ char uid[128], pass[128];
+
+ key = NULL;
+
+ if (!(home = getenv("HOME")))
+ fatalx("$HOME not set, cannot determine password-store location");
+ snprintf(file, sizeof(file), "%s/.password-store", home);
+
+ filename = basename(item);
+ mkdirp(item);
- /* TO-DO:
- * * Have to check if the file exists
- * * if it does
- * ask if user wants to overwrite the file
- * * re-confirm password before writing to file
- */
+ snprintf(file, sizeof(file), "%s/%s", file, filename);
+
+ snprintf(t, sizeof(t), "%s.gpg", file);
+ if ((fp = fopen(t, "r"))) {
+ printf("An entry already exists for %s. Overwrite it? [y/N] ", filename);
+ if (getchar() == 'N') {
+ logdbgx("Don't overwrite");
+ exit(1);
+ }
+ }
printf("file: %s\n", file);
if (!(fp = fopen(file, "w+b")))
- err(1, "fopen");
- printf("Enter password for %s: ", item);
- while ((r = getchar()) != '\n' && r != EOF) {
- if (fputc(r, fp) == EOF)
- err(1, "fputc");
+ fatal("fopen: %s", file);
+ readpassphrase("Enter password: ", pass, 128, RPP_ECHO_OFF);
+ memcpy(t, pass, strlen(pass) + 1);
+ readpassphrase("Retype password: ", pass, 128, RPP_ECHO_OFF);
+ if (!strcmp(pass, t))
+ {
+ int i = 0;
+ while(t[i] != '\0') {
+ if (fputc(t[i], fp) == EOF)
+ fatal("fputc: %s", file);
+ i++;
+ }
+ } else {
+ if (debug)
+ fatalx("Passwords don't match.");
+ else
+ fatalx("Passwords don't match.");
}
-
fclose(fp);
-
getuserid(uid);
- if (gpgme_err_code(gpgme_new(&ctx)) != GPG_ERR_NO_ERROR)
- errx(1, "gpme_new");
+ proto = GPGME_PROTOCOL_OpenPGP;
+ initgpgme();
+ gpgerr = gpgme_new(&ctx);
+ if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR)
+ fatalgpg(gpgerr, "gpme_new");
gpgerr = gpgme_set_protocol(ctx, proto);
if (gpgme_err_code(gpgerr) == GPG_ERR_INV_VALUE)
- errx(1, "gpgme_set_protocol");
+ fatalgpg(gpgerr, "gpgme_set_protocol");
+
+ gpgme_set_armor(ctx, 1);
if (gpgme_op_keylist_start(ctx, uid, 0) != GPG_ERR_INV_VALUE)
while (!(gpgerr = gpgme_op_keylist_next(ctx, &key))) {
@@ -263,38 +238,36 @@ insert(char *item)
break;
}
}
- /* throw an error if the respective key isn't found */
if (gpgme_err_code(gpgerr) == GPG_ERR_EOF)
- err(1, "can not find key: %s\n", gpgme_strerror(gpgerr));
+ fatalgpg(gpgerr, "can not find key");
keys[0] = key;
keys[1] = NULL;
- /* set ascii armor */
- gpgme_set_armor(ctx, 1);
-
fin = fopen(file, "r");
memcpy(t, file, strlen(file) + 1);
snprintf(file, sizeof(file), "%s.gpg", file);
fout = fopen(file, "w");
+
gpgerr = gpgme_data_new_from_stream(&in, fin);
if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR)
- errx(1, "gpgme_data_new_from_file %s", gpgme_strerror(gpgerr));
+ fatalgpg(gpgerr, "gpgme_data_new_from_stream");
gpgerr = gpgme_data_new_from_stream(&out, fout);
gpgme_data_set_encoding(out, GPGME_DATA_ENCODING_ARMOR);
if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR)
- errx(1, "gpgme_data_new: %s", gpgme_strerror(gpgerr));
+ fatalgpg(gpgerr, "gpgme_data_new_from_stream");
gpgerr = gpgme_op_encrypt(ctx, keys,
GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
if (gpgme_err_code(gpgerr) != GPG_ERR_NO_ERROR)
- errx(1, "gpgme_op_encrypt: %s", gpgme_strerror(gpgerr));
+ fatalgpg(gpgerr, "gpgme_op_encrypt");
gpgme_key_release(key);
gpgme_data_release(in);
gpgme_data_release(out);
gpgme_release(ctx);
+
fclose(fin);
fclose(fout);
if (remove(t))
@@ -311,7 +284,7 @@ isinit(void) /* check if .password-store exists */
struct stat sb;
if (!(home = getenv("HOME")))
- errx(1, "$HOME not set, cannot determine password-store location");
+ fatalx("$HOME not set, cannot determine password-store location");
snprintf(file, sizeof(file), "%s/.password-store", home);
@@ -335,31 +308,36 @@ initpass(char *pgpid)
FILE *gpg;
mode_t mode = S_IRWXU;
+ if (!pgpid) {
+ usage();
+ }
+
+
if (!isinit())
{
if (!(home = getenv("HOME")))
- errx(1, "$HOME not set, cannot determine password-store location");
+ fatalx("$HOME not set, cannot determine password-store location");
snprintf(file, sizeof(file), "%s/.password-store", home);
if (mkdir(file, mode))
- err(1, "mkdir");
+ fatal("mkdir");
snprintf(file, sizeof(file), "%s/.password-store/.gpg-id", home);
#ifdef DEBUG
printf("file: %s", file);
#endif
if (!(gpg = fopen(file, "a")))
- err(1, "fopen");
+ fatal("fopen");
if (fputs(pgpid, gpg) == EOF)
- err(1, "fputs");
+ fatal("fputs");
printf("Password store initialized for %s\n", pgpid);
fclose(gpg);
} else {
- errx(1, "Password store initialized for %s\n", pgpid);
+ printf("Password store initialized for %s\n", pgpid);
}
}
@@ -367,6 +345,12 @@ int
main(int argc, char** argv)
{
debug = 0;
+
+ for (char *s = *argv, i = 0; i < argc; i++) {
+ if (!strcmp("-d", s))
+ debug = 1;
+ s++;
+ }
if (debug)
loginit("pass");
if (argc > 1)
@@ -377,18 +361,12 @@ main(int argc, char** argv)
initpass(*(argv + 1));
else if (!strcmp("insert", *argv))
insert(*(argv + 1));
- else if (!strcmp("ls", *argv))
- list();
else if (!strcmp("rm", *argv))
delete(*(argv + 1));
- else if (!strcmp("find", *argv))
- find(*(argv + 1));
else
printpass(*argv);
- } else {
- list();
- }
+ }
return 0;
}
diff --git a/pass.h b/pass.h
@@ -9,3 +9,6 @@ void logwarn(char *, ...);
void logwarnx(char *, ...);
void fatal(char *, ...);
void fatalx(char *, ...);
+void loggpg(gpgme_error_t, char *, ...);
+void loggpgx(char *, ...);
+void fatalgpg(gpgme_error_t, char *, ...);
diff --git a/readpassphrase.c b/readpassphrase.c
@@ -0,0 +1,187 @@
+/* $OpenBSD: readpassphrase.c,v 1.25 2015/09/14 10:45:27 guenther Exp $ */
+
+/*
+ * Copyright (c) 2000-2002, 2007, 2010
+ * Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * 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 <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <pwd.h>
+#include <signal.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "readpassphrase.h"
+
+#ifdef TCSASOFT
+#define _T_FLUSH (TCSAFLUSH|TCSASOFT)
+#else
+#define _T_FLUSH (TCSAFLUSH)
+#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
+ (void)tcsetattr(input, _T_FLUSH, &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, _T_FLUSH, &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);
+}
+
+static void handler(int s)
+{
+ signo[s] = 1;
+}
diff --git a/readpassphrase.h b/readpassphrase.h
@@ -0,0 +1,31 @@
+/* $OpenBSD: readpassphrase.h,v 1.5 2003/06/17 21:56:23 millert Exp $ */
+
+/*
+ * Copyright (c) 2000, 2002 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * 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.
+ */
+
+#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 */
+
+char *readpassphrase(const char *, char *, size_t, int);