/*
 * 
 * readpass.c
 * 
 * Author: Tatu Ylonen <ylo@cs.hut.fi>
 * 
 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
 *                    All rights reserved
 * 
 * Created: Mon Jul 10 22:08:59 1995 ylo
 * 
 * Functions for reading passphrases and passwords.
 * 
 */

#include "includes.h"
RCSID("$Id: readpass.c,v 1.3 1999/11/25 00:54:59 damien Exp $");

#include "xmalloc.h"
#include "ssh.h"

/* Saved old terminal mode for read_passphrase. */
static struct termios saved_tio;

/* Old interrupt signal handler for read_passphrase. */
static void (*old_handler) (int sig) = NULL;

/* Interrupt signal handler for read_passphrase. */

void 
intr_handler(int sig)
{
	/* Restore terminal modes. */
	tcsetattr(fileno(stdin), TCSANOW, &saved_tio);
	/* Restore the old signal handler. */
	signal(sig, old_handler);
	/* Resend the signal, with the old handler. */
	kill(getpid(), sig);
}

/*
 * Reads a passphrase from /dev/tty with echo turned off.  Returns the
 * passphrase (allocated with xmalloc).  Exits if EOF is encountered. The
 * passphrase if read from stdin if from_stdin is true (as is the case with
 * ssh-keygen).
 */

char *
read_passphrase(const char *prompt, int from_stdin)
{
	char buf[1024], *cp;
	struct termios tio;
	FILE *f;

	if (from_stdin)
		f = stdin;
	else {
		/*
		 * Read the passphrase from /dev/tty to make it possible to
		 * ask it even when stdin has been redirected.
		 */
		f = fopen("/dev/tty", "r");
		if (!f) {
			/* No controlling terminal and no DISPLAY.  Nowhere to read. */
			fprintf(stderr, "You have no controlling tty and no DISPLAY.  Cannot read passphrase.\n");
			exit(1);
		}
	}

	/* Display the prompt (on stderr because stdout might be redirected). */
	fflush(stdout);
	fprintf(stderr, "%s", prompt);
	fflush(stderr);

	/* Get terminal modes. */
	tcgetattr(fileno(f), &tio);
	saved_tio = tio;
	/* Save signal handler and set the new handler. */
	old_handler = signal(SIGINT, intr_handler);

	/* Set new terminal modes disabling all echo. */
	tio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
	tcsetattr(fileno(f), TCSANOW, &tio);

	/* Read the passphrase from the terminal. */
	if (fgets(buf, sizeof(buf), f) == NULL) {
		/* Got EOF.  Just exit. */
		/* Restore terminal modes. */
		tcsetattr(fileno(f), TCSANOW, &saved_tio);
		/* Restore the signal handler. */
		signal(SIGINT, old_handler);
		/* Print a newline (the prompt probably didn\'t have one). */
		fprintf(stderr, "\n");
		/* Close the file. */
		if (f != stdin)
			fclose(f);
		exit(1);
	}
	/* Restore terminal modes. */
	tcsetattr(fileno(f), TCSANOW, &saved_tio);
	/* Restore the signal handler. */
	(void) signal(SIGINT, old_handler);
	/* Remove newline from the passphrase. */
	if (strchr(buf, '\n'))
		*strchr(buf, '\n') = 0;
	/* Allocate a copy of the passphrase. */
	cp = xstrdup(buf);
	/*
	 * Clear the buffer so we don\'t leave copies of the passphrase
	 * laying around.
	 */
	memset(buf, 0, sizeof(buf));
	/* Print a newline since the prompt probably didn\'t have one. */
	fprintf(stderr, "\n");
	/* Close the file. */
	if (f != stdin)
		fclose(f);
	return cp;
}
