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