2 #if !defined(_WIN32) || (defined(_WIN32) && defined(__CYGWIN32__))
7 /* Is vxworks broken w.r.t. termios? --tlyu */
15 typedef struct sigaction osiginfo
;
17 typedef struct krb5_sigtype (*osiginfo
)();
20 static void catch_signals(osiginfo
*);
21 static void restore_signals(osiginfo
*);
22 static krb5_sigtype
intrfunc(int sig
);
24 static krb5_error_code
setup_tty(FILE*, int, struct termios
*, osiginfo
*);
25 static krb5_error_code
restore_tty(FILE*, struct termios
*, osiginfo
*);
27 static volatile int got_int
; /* should be sig_atomic_t */
29 krb5_error_code KRB5_CALLCONV
36 krb5_prompt prompts
[])
38 int fd
, i
, scratchchar
;
41 krb5_error_code errcode
;
42 struct termios saveparm
;
45 errcode
= KRB5_LIBOS_CANTREADPWD
;
52 fputs(banner
, stdout
);
57 * Get a non-buffered stream on stdin.
60 fd
= dup(STDIN_FILENO
);
62 return KRB5_LIBOS_CANTREADPWD
;
66 if (setvbuf(fp
, NULL
, _IONBF
, 0))
69 for (i
= 0; i
< num_prompts
; i
++) {
70 errcode
= KRB5_LIBOS_CANTREADPWD
;
71 /* fgets() takes int, but krb5_data.length is unsigned. */
72 if (prompts
[i
].reply
->length
> INT_MAX
)
75 errcode
= setup_tty(fp
, prompts
[i
].hidden
, &saveparm
, &osigint
);
79 /* put out the prompt */
80 (void)fputs(prompts
[i
].prompt
, stdout
);
81 (void)fputs(": ", stdout
);
83 (void)memset(prompts
[i
].reply
->data
, 0, prompts
[i
].reply
->length
);
86 retp
= fgets(prompts
[i
].reply
->data
, (int)prompts
[i
].reply
->length
,
88 if (prompts
[i
].hidden
)
92 errcode
= KRB5_LIBOS_PWDINTR
;
94 errcode
= KRB5_LIBOS_CANTREADPWD
;
95 restore_tty(fp
, &saveparm
, &osigint
);
99 /* replace newline with null */
100 retp
= strchr(prompts
[i
].reply
->data
, '\n');
104 /* flush rest of input line */
106 scratchchar
= getc(fp
);
107 } while (scratchchar
!= EOF
&& scratchchar
!= '\n');
110 errcode
= restore_tty(fp
, &saveparm
, &osigint
);
113 prompts
[i
].reply
->length
= strlen(prompts
[i
].reply
->data
);
124 static krb5_sigtype
intrfunc(int sig
)
130 catch_signals(osiginfo
*osigint
)
135 sigemptyset(&sa
.sa_mask
);
137 sa
.sa_handler
= intrfunc
;
138 sigaction(SIGINT
, &sa
, osigint
);
140 *osigint
= signal(SIGINT
, intrfunc
);
145 restore_signals(osiginfo
*osigint
)
148 sigaction(SIGINT
, osigint
, NULL
);
150 signal(SIGINT
, *osigint
);
154 static krb5_error_code
155 setup_tty(FILE *fp
, int hidden
, struct termios
*saveparm
, osiginfo
*osigint
)
159 struct termios tparm
;
161 ret
= KRB5_LIBOS_CANTREADPWD
;
162 catch_signals(osigint
);
169 if (tcgetattr(fd
, &tparm
) < 0)
172 #ifndef ECHO_PASSWORD
174 tparm
.c_lflag
&= ~(ECHO
|ECHONL
);
176 tparm
.c_lflag
|= ISIG
|ICANON
;
177 if (tcsetattr(STDIN_FILENO
, TCSANOW
, &tparm
) < 0)
181 /* If we're losing, restore signal handlers. */
183 restore_signals(osigint
);
187 static krb5_error_code
188 restore_tty(FILE* fp
, struct termios
*saveparm
, osiginfo
*osigint
)
195 ret
= tcsetattr(fd
, TCSANOW
, saveparm
);
197 ret
= KRB5_LIBOS_CANTREADPWD
;
201 restore_signals(osigint
);
205 #else /* non-Cygwin Windows, or Mac */
211 krb5_error_code KRB5_CALLCONV
212 krb5_prompter_posix(krb5_context context
,
217 krb5_prompt prompts
[])
220 DWORD old_mode
, new_mode
;
223 krb5_error_code errcode
= 0;
226 handle
= GetStdHandle(STD_INPUT_HANDLE
);
227 if (handle
== INVALID_HANDLE_VALUE
)
229 if (!GetConsoleMode(handle
, &old_mode
))
233 new_mode
|= ( ENABLE_LINE_INPUT
| ENABLE_PROCESSED_INPUT
);
234 new_mode
&= ~( ENABLE_ECHO_INPUT
);
236 if (!SetConsoleMode(handle
, new_mode
))
239 if (!SetConsoleMode(handle
, old_mode
))
248 fputs(banner
, stdout
);
252 for (i
= 0; i
< num_prompts
; i
++) {
253 if (prompts
[i
].hidden
) {
254 if (!SetConsoleMode(handle
, new_mode
)) {
260 fputs(prompts
[i
].prompt
,stdout
);
263 memset(prompts
[i
].reply
->data
, 0, prompts
[i
].reply
->length
);
265 if (fgets(prompts
[i
].reply
->data
, prompts
[i
].reply
->length
, stdin
)
267 if (prompts
[i
].hidden
)
269 errcode
= KRB5_LIBOS_CANTREADPWD
;
272 if (prompts
[i
].hidden
)
274 /* fgets always null-terminates the returned string */
276 /* replace newline with null */
277 if ((ptr
= strchr(prompts
[i
].reply
->data
, '\n')))
279 else /* flush rest of input line */
281 scratchchar
= getchar();
282 } while (scratchchar
!= EOF
&& scratchchar
!= '\n');
284 prompts
[i
].reply
->length
= strlen(prompts
[i
].reply
->data
);
286 if (!SetConsoleMode(handle
, old_mode
)) {
294 for (i
= 0; i
< num_prompts
; i
++) {
295 memset(prompts
[i
].reply
->data
, 0, prompts
[i
].reply
->length
);
303 krb5_error_code KRB5_CALLCONV
304 krb5_prompter_posix(krb5_context context
,
309 krb5_prompt prompts
[])
314 #endif /* Windows or Mac */
317 krb5int_set_prompt_types(krb5_context context
, krb5_prompt_type
*types
)
319 context
->prompt_types
= types
;
324 krb5_get_prompt_types(krb5_context context
)
326 return context
->prompt_types
;