--- /dev/null
+/*
+ * promptusr.c --- prompt user for input/output
+ */
+
+#include "k5-int.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <termios.h>
+#include <signal.h>
+#include <setjmp.h>
+
+typedef struct _krb5_uio {
+ krb5_magic magic;
+ int flags;
+ char * prompt;
+ char * response;
+ struct _krb5_uio *next;
+} *krb5_uio;
+
+#define KRB5_UIO_GETRESPONSE 0x0001
+#define KRB5_UIO_ECHORESPONSE 0x0002
+#define KRB5_UIO_FREE_PROMPT 0x0004
+
+static jmp_buf pwd_jump;
+
+static krb5_sigtype
+intr_routine(signo)
+ int signo;
+{
+ longjmp(pwd_jump, 1);
+ /*NOTREACHED*/
+}
+
+krb5_error_code
+krb5_os_get_tty_uio(context, uio)
+ krb5_context context;
+ krb5_uio uio;
+{
+ krb5_error_code retval;
+ krb5_sigtype (*ointrfunc)();
+ krb5_uio p;
+ struct termios echo_control, save_control;
+ int fd;
+ char read_string[BUFSIZ];
+ char *cp;
+ char ch;
+
+ /* get the file descriptor associated with stdin */
+ fd=fileno(stdin);
+
+ if (tcgetattr(fd, &echo_control) == -1)
+ return errno;
+
+ save_control = echo_control;
+ echo_control.c_lflag &= ~(ECHO|ECHONL);
+
+ if (setjmp(pwd_jump)) {
+ retval = KRB5_LIBOS_PWDINTR; /* we were interrupted... */
+ goto cleanup;
+ }
+ /* save intrfunc */
+ ointrfunc = signal(SIGINT, intr_routine);
+
+ for (p = uio; p; p = p->next) {
+ if (p->prompt) {
+ fputs(p->prompt, stdout);
+ fflush(stdout);
+ }
+ if ((p->flags & KRB5_UIO_GETRESPONSE) == 0)
+ continue;
+
+ if ((p->flags & KRB5_UIO_ECHORESPONSE) == 0)
+ if (tcsetattr(fd, TCSANOW, &echo_control) == -1)
+ return errno;
+
+ if (fgets(read_string, sizeof(read_string), stdin) == NULL) {
+ (void) putchar('\n');
+ retval = KRB5_LIBOS_CANTREADPWD;
+ goto cleanup;
+ }
+
+ /* replace newline with null */
+ if ((cp = strchr(read_string, '\n')))
+ *cp = '\0';
+ else /* flush rest of input line */
+ do {
+ ch = getchar();
+ } while (ch != EOF && ch != '\n');
+ read_string[sizeof(read_string)-1] = 0;
+
+ if ((p->response = malloc(strlen(read_string)+1)) == NULL) {
+ errno = ENOMEM;
+ goto cleanup;
+ }
+ strcpy(p->response, read_string);
+
+ if ((p->flags & KRB5_UIO_ECHORESPONSE) == 0) {
+ (void) putchar('\n');
+ if (tcsetattr(fd, TCSANOW, &save_control) == -1) {
+ retval = errno;
+ goto cleanup;
+ }
+ }
+ }
+ retval = 0;
+
+ cleanup:
+ (void) signal(SIGINT, ointrfunc);
+ if (retval) {
+ for (p = uio; p; p = p->next) {
+ if (p->response) {
+ memset(p->response, 0, strlen(p->response));
+ free(p->response);
+ p->response = 0;
+ }
+ }
+ }
+ memset(read_string, 0, sizeof(read_string));
+ tcsetattr(fd, TCSANOW, &save_control);
+ return retval;
+}
+
+void
+krb5_free_uio(context, uio)
+ krb5_context context;
+ krb5_uio uio;
+{
+ krb5_uio p, next;
+
+ for (p = uio; p; p = next) {
+ next = p->next;
+ if (p->prompt && (p->flags & KRB5_UIO_FREE_PROMPT))
+ free(p->prompt);
+ if (p->response)
+ free(p->response);
+ free(p);
+ }
+}
+
+#ifdef TEST_DRIVER
+
+struct _krb5_uio uio_a = { 0, KRB5_UIO_GETRESPONSE, "Password 1: " };
+struct _krb5_uio uio_b = { 0, KRB5_UIO_GETRESPONSE |
+ KRB5_UIO_ECHORESPONSE, "Password 2: " };
+struct _krb5_uio uio_c = { 0, KRB5_UIO_GETRESPONSE, "Password 3: " };
+
+
+void
+main(int argc, char **argv)
+{
+ uio_a.next = &uio_b;
+ uio_b.next = &uio_c;
+
+ krb5_os_get_tty_uio(0, &uio_a);
+ exit(0);
+}
+
+#endif
+
+
+
+