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
intr_routine(int signo)33 intr_routine(int signo)
34 {
35 longjmp(pwd_jump, 1);
36 /*NOTREACHED*/
37 }
38
39 /*ARGSUSED*/
40 krb5_error_code
krb5_os_get_tty_uio(krb5_context context,krb5_uio uio)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
krb5_free_uio(krb5_context context,krb5_uio uio)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
main(int argc,char ** argv)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