/* * promptusr.c --- prompt user for input/output */ #include "k5-int.h" #if !defined(_MSDOS) && !defined(_WIN32) && !defined(_MACINTOSH) #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include 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 #endif /* !_MSODS || _!MACINTOSH */