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