1 /* 2 * promptusr.c --- prompt user for input/output 3 */ 4 5 #include <k5-int.h> 6 #if !defined(_WIN32) 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 #ifdef HAVE_UNISTD_H 11 #include <unistd.h> 12 #endif 13 #include <termios.h> 14 #include <signal.h> 15 #include <setjmp.h> 16 17 typedef struct _krb5_uio { 18 krb5_magic magic; 19 int flags; 20 char * prompt; 21 char * response; 22 struct _krb5_uio *next; 23 } *krb5_uio; 24 25 #define KRB5_UIO_GETRESPONSE 0x0001 26 #define KRB5_UIO_ECHORESPONSE 0x0002 27 #define KRB5_UIO_FREE_PROMPT 0x0004 28 29 static jmp_buf pwd_jump; 30 31 /*ARGSUSED*/ 32 static krb5_sigtype 33 intr_routine(int signo) 34 { 35 longjmp(pwd_jump, 1); 36 /*NOTREACHED*/ 37 } 38 39 /*ARGSUSED*/ 40 krb5_error_code 41 krb5_os_get_tty_uio(krb5_context context, krb5_uio uio) 42 { 43 volatile krb5_error_code retval; 44 krb5_sigtype (*volatile ointrfunc)(); 45 krb5_uio p; 46 struct termios echo_control, save_control; 47 int fd; 48 char read_string[BUFSIZ]; 49 char *cp; 50 int ch; 51 52 /* get the file descriptor associated with stdin */ 53 fd=fileno(stdin); 54 55 if (tcgetattr(fd, &echo_control) == -1) 56 return errno; 57 58 save_control = echo_control; 59 echo_control.c_lflag &= ~(ECHO|ECHONL); 60 61 if (setjmp(pwd_jump)) { 62 retval = KRB5_LIBOS_PWDINTR; /* we were interrupted... */ 63 goto cleanup; 64 } 65 /* save intrfunc */ 66 ointrfunc = signal(SIGINT, intr_routine); 67 68 for (p = uio; p; p = p->next) { 69 if (p->prompt) { 70 fputs(p->prompt, stdout); 71 fflush(stdout); 72 } 73 if ((p->flags & KRB5_UIO_GETRESPONSE) == 0) 74 continue; 75 76 if ((p->flags & KRB5_UIO_ECHORESPONSE) == 0) 77 if (tcsetattr(fd, TCSANOW, &echo_control) == -1) 78 return errno; 79 80 if (fgets(read_string, sizeof(read_string), stdin) == NULL) { 81 (void) putchar('\n'); 82 retval = KRB5_LIBOS_CANTREADPWD; 83 goto cleanup; 84 } 85 86 /* replace newline with null */ 87 if ((cp = strchr(read_string, '\n'))) 88 *cp = '\0'; 89 else /* flush rest of input line */ 90 do { 91 ch = getchar(); 92 } while (ch != EOF && ch != '\n'); 93 read_string[sizeof(read_string)-1] = 0; 94 95 if ((p->response = malloc(strlen(read_string)+1)) == NULL) { 96 errno = ENOMEM; 97 goto cleanup; 98 } 99 strcpy(p->response, read_string); 100 101 if ((p->flags & KRB5_UIO_ECHORESPONSE) == 0) { 102 (void) putchar('\n'); 103 if (tcsetattr(fd, TCSANOW, &save_control) == -1) { 104 retval = errno; 105 goto cleanup; 106 } 107 } 108 } 109 retval = 0; 110 111 cleanup: 112 (void) signal(SIGINT, ointrfunc); 113 if (retval) { 114 for (p = uio; p; p = p->next) { 115 if (p->response) { 116 memset(p->response, 0, strlen(p->response)); 117 free(p->response); 118 p->response = 0; 119 } 120 } 121 } 122 memset(read_string, 0, sizeof(read_string)); 123 tcsetattr(fd, TCSANOW, &save_control); 124 return retval; 125 } 126 127 /*ARGSUSED*/ 128 void 129 krb5_free_uio(krb5_context context, krb5_uio uio) 130 { 131 krb5_uio p, next; 132 133 for (p = uio; p; p = next) { 134 next = p->next; 135 if (p->prompt && (p->flags & KRB5_UIO_FREE_PROMPT)) 136 free(p->prompt); 137 if (p->response) 138 free(p->response); 139 free(p); 140 } 141 } 142 143 #ifdef TEST_DRIVER 144 145 struct _krb5_uio uio_a = { 0, KRB5_UIO_GETRESPONSE, "Password 1: " }; 146 struct _krb5_uio uio_b = { 0, KRB5_UIO_GETRESPONSE | 147 KRB5_UIO_ECHORESPONSE, "Password 2: " }; 148 struct _krb5_uio uio_c = { 0, KRB5_UIO_GETRESPONSE, "Password 3: " }; 149 150 151 void 152 main(int argc, char **argv) 153 { 154 uio_a.next = &uio_b; 155 uio_b.next = &uio_c; 156 157 krb5_os_get_tty_uio(0, &uio_a); 158 exit(0); 159 } 160 161 #endif 162 163 #endif /* !_MSODS */ 164