xref: /illumos-gate/usr/src/lib/gss_mechs/mech_krb5/krb5/os/promptusr.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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