]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
83cf7abf | 2 | * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. |
0f113f3e | 3 | * |
55e0593c | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
aa6bb135 RS |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
02790299 RL |
8 | */ |
9 | ||
07016a8a | 10 | #include "e_os.h" |
7babdf20 | 11 | #include <openssl/e_os2.h> |
49844486 | 12 | #include <openssl/err.h> |
48feaceb | 13 | #include <openssl/ui.h> |
02790299 | 14 | |
48feaceb | 15 | #ifndef OPENSSL_NO_UI_CONSOLE |
0f113f3e MC |
16 | /* |
17 | * need for #define _POSIX_C_SOURCE arises whenever you pass -ansi to gcc | |
6df617a5 | 18 | * [maybe others?], because it masks interfaces not discussed in standard, |
0f113f3e MC |
19 | * sigaction and fileno included. -pedantic would be more appropriate for the |
20 | * intended purposes, but we can't prevent users from adding -ansi. | |
6df617a5 | 21 | */ |
48feaceb RL |
22 | # if defined(OPENSSL_SYS_VXWORKS) |
23 | # include <sys/types.h> | |
0f113f3e | 24 | # endif |
48feaceb RL |
25 | |
26 | # if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS) | |
27 | # ifndef _POSIX_C_SOURCE | |
28 | # define _POSIX_C_SOURCE 2 | |
29 | # endif | |
02790299 | 30 | # endif |
48feaceb RL |
31 | # include <signal.h> |
32 | # include <stdio.h> | |
33 | # include <string.h> | |
34 | # include <errno.h> | |
35 | ||
36 | # if !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) | |
6b10d29c | 37 | # include <unistd.h> |
0f113f3e MC |
38 | /* |
39 | * If unistd.h defines _POSIX_VERSION, we conclude that we are on a POSIX | |
40 | * system and have sigaction and termios. | |
41 | */ | |
f20aa69e | 42 | # if defined(_POSIX_VERSION) && _POSIX_VERSION>=199309L |
a63d5eaa | 43 | |
48feaceb RL |
44 | # define SIGACTION |
45 | # if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY) | |
46 | # define TERMIOS | |
47 | # endif | |
a63d5eaa | 48 | |
48feaceb | 49 | # endif |
02790299 | 50 | # endif |
a63d5eaa | 51 | |
706457b7 | 52 | # include "ui_local.h" |
48feaceb | 53 | # include "internal/cryptlib.h" |
a63d5eaa | 54 | |
48feaceb RL |
55 | # ifdef OPENSSL_SYS_VMS /* prototypes for sys$whatever */ |
56 | # include <starlet.h> | |
57 | # ifdef __DECC | |
58 | # pragma message disable DOLLARID | |
59 | # endif | |
02790299 | 60 | # endif |
a63d5eaa | 61 | |
48feaceb RL |
62 | # ifdef WIN_CONSOLE_BUG |
63 | # include <windows.h> | |
64 | # ifndef OPENSSL_SYS_WINCE | |
65 | # include <wincon.h> | |
66 | # endif | |
0f113f3e | 67 | # endif |
a63d5eaa | 68 | |
0f113f3e | 69 | /* |
087d3e89 AP |
70 | * There are 6 types of terminal interface supported, TERMIO, TERMIOS, VMS, |
71 | * MSDOS, WIN32 Console and SGTTY. | |
64e6bf64 RL |
72 | * |
73 | * If someone defines one of the macros TERMIO, TERMIOS or SGTTY, it will | |
74 | * remain respected. Otherwise, we default to TERMIOS except for a few | |
75 | * systems that require something different. | |
76 | * | |
77 | * Note: we do not use SGTTY unless it's defined by the configuration. We | |
68756b12 | 78 | * may eventually opt to remove its use entirely. |
a63d5eaa RL |
79 | */ |
80 | ||
48feaceb | 81 | # if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY) |
a63d5eaa | 82 | |
48feaceb RL |
83 | # if defined(_LIBC) |
84 | # undef TERMIOS | |
85 | # define TERMIO | |
86 | # undef SGTTY | |
64e6bf64 | 87 | /* |
1fbab1dc | 88 | * We know that VMS, MSDOS, VXWORKS, use entirely other mechanisms. |
64e6bf64 | 89 | */ |
48feaceb | 90 | # elif !defined(OPENSSL_SYS_VMS) \ |
dd6b2706 P |
91 | && !defined(OPENSSL_SYS_MSDOS) \ |
92 | && !defined(OPENSSL_SYS_VXWORKS) | |
48feaceb RL |
93 | # define TERMIOS |
94 | # undef TERMIO | |
95 | # undef SGTTY | |
96 | # endif | |
3e83e686 | 97 | |
48feaceb | 98 | # endif |
4d8743f4 | 99 | |
5c8b7b4c KT |
100 | # if defined(OPENSSL_SYS_VXWORKS) |
101 | # undef TERMIOS | |
102 | # undef TERMIO | |
103 | # undef SGTTY | |
104 | # endif | |
105 | ||
48feaceb RL |
106 | # ifdef TERMIOS |
107 | # include <termios.h> | |
108 | # define TTY_STRUCT struct termios | |
109 | # define TTY_FLAGS c_lflag | |
110 | # define TTY_get(tty,data) tcgetattr(tty,data) | |
111 | # define TTY_set(tty,data) tcsetattr(tty,TCSANOW,data) | |
112 | # endif | |
a63d5eaa | 113 | |
48feaceb RL |
114 | # ifdef TERMIO |
115 | # include <termio.h> | |
116 | # define TTY_STRUCT struct termio | |
117 | # define TTY_FLAGS c_lflag | |
118 | # define TTY_get(tty,data) ioctl(tty,TCGETA,data) | |
119 | # define TTY_set(tty,data) ioctl(tty,TCSETA,data) | |
120 | # endif | |
a63d5eaa | 121 | |
48feaceb RL |
122 | # ifdef SGTTY |
123 | # include <sgtty.h> | |
124 | # define TTY_STRUCT struct sgttyb | |
125 | # define TTY_FLAGS sg_flags | |
126 | # define TTY_get(tty,data) ioctl(tty,TIOCGETP,data) | |
127 | # define TTY_set(tty,data) ioctl(tty,TIOCSETP,data) | |
128 | # endif | |
a63d5eaa | 129 | |
48feaceb RL |
130 | # if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) |
131 | # include <sys/ioctl.h> | |
132 | # endif | |
a63d5eaa | 133 | |
48feaceb RL |
134 | # ifdef OPENSSL_SYS_MSDOS |
135 | # include <conio.h> | |
136 | # endif | |
a63d5eaa | 137 | |
48feaceb RL |
138 | # ifdef OPENSSL_SYS_VMS |
139 | # include <ssdef.h> | |
140 | # include <iodef.h> | |
141 | # include <ttdef.h> | |
142 | # include <descrip.h> | |
a63d5eaa | 143 | struct IOSB { |
0f113f3e MC |
144 | short iosb$w_value; |
145 | short iosb$w_count; | |
146 | long iosb$l_info; | |
147 | }; | |
48feaceb | 148 | # endif |
a63d5eaa | 149 | |
48feaceb RL |
150 | # ifndef NX509_SIG |
151 | # define NX509_SIG 32 | |
152 | # endif | |
a63d5eaa | 153 | |
a63d5eaa | 154 | /* Define globals. They are protected by a lock */ |
48feaceb | 155 | # ifdef SIGACTION |
a63d5eaa | 156 | static struct sigaction savsig[NX509_SIG]; |
48feaceb | 157 | # else |
0f113f3e | 158 | static void (*savsig[NX509_SIG]) (int); |
48feaceb | 159 | # endif |
a63d5eaa | 160 | |
48feaceb | 161 | # ifdef OPENSSL_SYS_VMS |
a63d5eaa | 162 | static struct IOSB iosb; |
0f113f3e MC |
163 | static $DESCRIPTOR(terminal, "TT"); |
164 | static long tty_orig[3], tty_new[3]; /* XXX Is there any guarantee that this | |
165 | * will always suffice for the actual | |
166 | * structures? */ | |
a63d5eaa RL |
167 | static long status; |
168 | static unsigned short channel = 0; | |
48feaceb | 169 | # elif defined(_WIN32) && !defined(_WIN32_WCE) |
087d3e89 | 170 | static DWORD tty_orig, tty_new; |
48feaceb RL |
171 | # else |
172 | # if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__) | |
0f113f3e | 173 | static TTY_STRUCT tty_orig, tty_new; |
48feaceb | 174 | # endif |
0f113f3e | 175 | # endif |
200bc9e3 | 176 | static FILE *tty_in, *tty_out; |
a63d5eaa RL |
177 | static int is_a_tty; |
178 | ||
179 | /* Declare static functions */ | |
48feaceb | 180 | # if !defined(OPENSSL_SYS_WINCE) |
0e039aa7 | 181 | static int read_till_nl(FILE *); |
a63d5eaa RL |
182 | static void recsig(int); |
183 | static void pushsig(void); | |
184 | static void popsig(void); | |
48feaceb RL |
185 | # endif |
186 | # if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32) | |
a63d5eaa | 187 | static int noecho_fgets(char *buf, int size, FILE *tty); |
48feaceb | 188 | # endif |
b589977b | 189 | static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl); |
a63d5eaa RL |
190 | |
191 | static int read_string(UI *ui, UI_STRING *uis); | |
9ad0f681 | 192 | static int write_string(UI *ui, UI_STRING *uis); |
a63d5eaa RL |
193 | |
194 | static int open_console(UI *ui); | |
195 | static int echo_console(UI *ui); | |
196 | static int noecho_console(UI *ui); | |
197 | static int close_console(UI *ui); | |
198 | ||
0f113f3e MC |
199 | /* |
200 | * The following function makes sure that info and error strings are printed | |
201 | * before any prompt. | |
202 | */ | |
9ad0f681 | 203 | static int write_string(UI *ui, UI_STRING *uis) |
0f113f3e MC |
204 | { |
205 | switch (UI_get_string_type(uis)) { | |
206 | case UIT_ERROR: | |
207 | case UIT_INFO: | |
208 | fputs(UI_get0_output_string(uis), tty_out); | |
209 | fflush(tty_out); | |
210 | break; | |
f3b3d7f0 RS |
211 | case UIT_NONE: |
212 | case UIT_PROMPT: | |
213 | case UIT_VERIFY: | |
214 | case UIT_BOOLEAN: | |
0f113f3e MC |
215 | break; |
216 | } | |
217 | return 1; | |
218 | } | |
9ad0f681 RL |
219 | |
220 | static int read_string(UI *ui, UI_STRING *uis) | |
0f113f3e MC |
221 | { |
222 | int ok = 0; | |
223 | ||
224 | switch (UI_get_string_type(uis)) { | |
225 | case UIT_BOOLEAN: | |
226 | fputs(UI_get0_output_string(uis), tty_out); | |
227 | fputs(UI_get0_action_string(uis), tty_out); | |
228 | fflush(tty_out); | |
229 | return read_string_inner(ui, uis, | |
230 | UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, | |
231 | 0); | |
232 | case UIT_PROMPT: | |
233 | fputs(UI_get0_output_string(uis), tty_out); | |
234 | fflush(tty_out); | |
235 | return read_string_inner(ui, uis, | |
236 | UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, | |
237 | 1); | |
238 | case UIT_VERIFY: | |
239 | fprintf(tty_out, "Verifying - %s", UI_get0_output_string(uis)); | |
240 | fflush(tty_out); | |
241 | if ((ok = read_string_inner(ui, uis, | |
242 | UI_get_input_flags(uis) & | |
243 | UI_INPUT_FLAG_ECHO, 1)) <= 0) | |
244 | return ok; | |
245 | if (strcmp(UI_get0_result_string(uis), UI_get0_test_string(uis)) != 0) { | |
246 | fprintf(tty_out, "Verify failure\n"); | |
247 | fflush(tty_out); | |
248 | return 0; | |
249 | } | |
250 | break; | |
f3b3d7f0 RS |
251 | case UIT_NONE: |
252 | case UIT_INFO: | |
253 | case UIT_ERROR: | |
0f113f3e MC |
254 | break; |
255 | } | |
256 | return 1; | |
257 | } | |
a63d5eaa | 258 | |
48feaceb | 259 | # if !defined(OPENSSL_SYS_WINCE) |
a63d5eaa | 260 | /* Internal functions to read a string without echoing */ |
0e039aa7 | 261 | static int read_till_nl(FILE *in) |
0f113f3e | 262 | { |
48feaceb | 263 | # define SIZE 4 |
0f113f3e | 264 | char buf[SIZE + 1]; |
a63d5eaa | 265 | |
0f113f3e MC |
266 | do { |
267 | if (!fgets(buf, SIZE, in)) | |
268 | return 0; | |
269 | } while (strchr(buf, '\n') == NULL); | |
270 | return 1; | |
271 | } | |
a63d5eaa | 272 | |
94960c84 | 273 | static volatile sig_atomic_t intr_signal; |
48feaceb | 274 | # endif |
7c517a04 | 275 | |
b589977b | 276 | static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl) |
0f113f3e MC |
277 | { |
278 | static int ps; | |
279 | int ok; | |
280 | char result[BUFSIZ]; | |
281 | int maxsize = BUFSIZ - 1; | |
48feaceb | 282 | # if !defined(OPENSSL_SYS_WINCE) |
087d3e89 AP |
283 | char *p = NULL; |
284 | int echo_eol = !echo; | |
0f113f3e MC |
285 | |
286 | intr_signal = 0; | |
287 | ok = 0; | |
288 | ps = 0; | |
289 | ||
290 | pushsig(); | |
291 | ps = 1; | |
292 | ||
293 | if (!echo && !noecho_console(ui)) | |
294 | goto error; | |
295 | ps = 2; | |
296 | ||
297 | result[0] = '\0'; | |
48feaceb | 298 | # if defined(_WIN32) |
087d3e89 AP |
299 | if (is_a_tty) { |
300 | DWORD numread; | |
48feaceb | 301 | # if defined(CP_UTF8) |
fb5d9f1d AP |
302 | if (GetEnvironmentVariableW(L"OPENSSL_WIN32_UTF8", NULL, 0) != 0) { |
303 | WCHAR wresult[BUFSIZ]; | |
087d3e89 | 304 | |
fb5d9f1d | 305 | if (ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), |
087d3e89 | 306 | wresult, maxsize, &numread, NULL)) { |
fb5d9f1d AP |
307 | if (numread >= 2 && |
308 | wresult[numread-2] == L'\r' && | |
309 | wresult[numread-1] == L'\n') { | |
310 | wresult[numread-2] = L'\n'; | |
311 | numread--; | |
312 | } | |
313 | wresult[numread] = '\0'; | |
314 | if (WideCharToMultiByte(CP_UTF8, 0, wresult, -1, | |
315 | result, sizeof(result), NULL, 0) > 0) | |
316 | p = result; | |
317 | ||
318 | OPENSSL_cleanse(wresult, sizeof(wresult)); | |
087d3e89 | 319 | } |
fb5d9f1d | 320 | } else |
48feaceb | 321 | # endif |
087d3e89 AP |
322 | if (ReadConsoleA(GetStdHandle(STD_INPUT_HANDLE), |
323 | result, maxsize, &numread, NULL)) { | |
324 | if (numread >= 2 && | |
325 | result[numread-2] == '\r' && result[numread-1] == '\n') { | |
326 | result[numread-2] = '\n'; | |
327 | numread--; | |
087d3e89 AP |
328 | } |
329 | result[numread] = '\0'; | |
330 | p = result; | |
331 | } | |
087d3e89 | 332 | } else |
48feaceb | 333 | # elif defined(OPENSSL_SYS_MSDOS) |
0f113f3e MC |
334 | if (!echo) { |
335 | noecho_fgets(result, maxsize, tty_in); | |
336 | p = result; /* FIXME: noecho_fgets doesn't return errors */ | |
337 | } else | |
48feaceb | 338 | # endif |
087d3e89 | 339 | p = fgets(result, maxsize, tty_in); |
120fb9e4 | 340 | if (p == NULL) |
0f113f3e MC |
341 | goto error; |
342 | if (feof(tty_in)) | |
343 | goto error; | |
344 | if (ferror(tty_in)) | |
345 | goto error; | |
346 | if ((p = (char *)strchr(result, '\n')) != NULL) { | |
347 | if (strip_nl) | |
348 | *p = '\0'; | |
349 | } else if (!read_till_nl(tty_in)) | |
350 | goto error; | |
351 | if (UI_set_result(ui, uis, result) >= 0) | |
352 | ok = 1; | |
353 | ||
354 | error: | |
355 | if (intr_signal == SIGINT) | |
356 | ok = -1; | |
087d3e89 | 357 | if (echo_eol) |
0f113f3e MC |
358 | fprintf(tty_out, "\n"); |
359 | if (ps >= 2 && !echo && !echo_console(ui)) | |
360 | ok = 0; | |
361 | ||
362 | if (ps >= 1) | |
363 | popsig(); | |
48feaceb | 364 | # else |
0f113f3e | 365 | ok = 1; |
48feaceb | 366 | # endif |
a63d5eaa | 367 | |
0f113f3e MC |
368 | OPENSSL_cleanse(result, BUFSIZ); |
369 | return ok; | |
370 | } | |
a63d5eaa RL |
371 | |
372 | /* Internal functions to open, handle and close a channel to the console. */ | |
373 | static int open_console(UI *ui) | |
0f113f3e | 374 | { |
41cfbccc | 375 | CRYPTO_THREAD_write_lock(ui->lock); |
0f113f3e | 376 | is_a_tty = 1; |
a63d5eaa | 377 | |
48feaceb | 378 | # if defined(OPENSSL_SYS_VXWORKS) |
0f113f3e MC |
379 | tty_in = stdin; |
380 | tty_out = stderr; | |
48feaceb | 381 | # elif defined(_WIN32) && !defined(_WIN32_WCE) |
087d3e89 AP |
382 | if ((tty_out = fopen("conout$", "w")) == NULL) |
383 | tty_out = stderr; | |
384 | ||
385 | if (GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &tty_orig)) { | |
386 | tty_in = stdin; | |
387 | } else { | |
388 | is_a_tty = 0; | |
389 | if ((tty_in = fopen("conin$", "r")) == NULL) | |
390 | tty_in = stdin; | |
391 | } | |
0f113f3e | 392 | # else |
48feaceb RL |
393 | # ifdef OPENSSL_SYS_MSDOS |
394 | # define DEV_TTY "con" | |
395 | # else | |
396 | # define DEV_TTY "/dev/tty" | |
397 | # endif | |
0f113f3e MC |
398 | if ((tty_in = fopen(DEV_TTY, "r")) == NULL) |
399 | tty_in = stdin; | |
400 | if ((tty_out = fopen(DEV_TTY, "w")) == NULL) | |
401 | tty_out = stderr; | |
48feaceb | 402 | # endif |
a63d5eaa | 403 | |
48feaceb | 404 | # if defined(TTY_get) && !defined(OPENSSL_SYS_VMS) |
0f113f3e | 405 | if (TTY_get(fileno(tty_in), &tty_orig) == -1) { |
48feaceb | 406 | # ifdef ENOTTY |
0f113f3e MC |
407 | if (errno == ENOTTY) |
408 | is_a_tty = 0; | |
409 | else | |
48feaceb RL |
410 | # endif |
411 | # ifdef EINVAL | |
0f113f3e | 412 | /* |
e3713c36 RS |
413 | * Ariel Glenn reports that solaris can return EINVAL instead. |
414 | * This should be ok | |
0f113f3e MC |
415 | */ |
416 | if (errno == EINVAL) | |
417 | is_a_tty = 0; | |
418 | else | |
48feaceb | 419 | # endif |
276bf862 RL |
420 | # ifdef ENXIO |
421 | /* | |
422 | * Solaris can return ENXIO. | |
423 | * This should be ok | |
424 | */ | |
425 | if (errno == ENXIO) | |
426 | is_a_tty = 0; | |
427 | else | |
428 | # endif | |
429 | # ifdef EIO | |
430 | /* | |
431 | * Linux can return EIO. | |
432 | * This should be ok | |
433 | */ | |
434 | if (errno == EIO) | |
435 | is_a_tty = 0; | |
436 | else | |
437 | # endif | |
48feaceb | 438 | # ifdef ENODEV |
c901bcce RL |
439 | /* |
440 | * MacOS X returns ENODEV (Operation not supported by device), | |
441 | * which seems appropriate. | |
442 | */ | |
443 | if (errno == ENODEV) | |
444 | is_a_tty = 0; | |
445 | else | |
48feaceb | 446 | # endif |
49844486 RL |
447 | { |
448 | char tmp_num[10]; | |
449 | BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%d", errno); | |
450 | UIerr(UI_F_OPEN_CONSOLE, UI_R_UNKNOWN_TTYGET_ERRNO_VALUE); | |
451 | ERR_add_error_data(2, "errno=", tmp_num); | |
452 | ||
453 | return 0; | |
454 | } | |
0f113f3e | 455 | } |
48feaceb RL |
456 | # endif |
457 | # ifdef OPENSSL_SYS_VMS | |
0f113f3e | 458 | status = sys$assign(&terminal, &channel, 0, 0); |
18edbe65 RL |
459 | |
460 | /* if there isn't a TT device, something is very wrong */ | |
c922ebe2 RL |
461 | if (status != SS$_NORMAL) { |
462 | char tmp_num[12]; | |
463 | ||
464 | BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%%X%08X", status); | |
465 | UIerr(UI_F_OPEN_CONSOLE, UI_R_SYSASSIGN_ERROR); | |
466 | ERR_add_error_data(2, "status=", tmp_num); | |
0f113f3e | 467 | return 0; |
c922ebe2 | 468 | } |
18edbe65 RL |
469 | |
470 | status = sys$qiow(0, channel, IO$_SENSEMODE, &iosb, 0, 0, tty_orig, 12, | |
471 | 0, 0, 0, 0); | |
472 | ||
473 | /* If IO$_SENSEMODE doesn't work, this is not a terminal device */ | |
0f113f3e | 474 | if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) |
18edbe65 | 475 | is_a_tty = 0; |
48feaceb | 476 | # endif |
0f113f3e MC |
477 | return 1; |
478 | } | |
a63d5eaa RL |
479 | |
480 | static int noecho_console(UI *ui) | |
0f113f3e | 481 | { |
48feaceb | 482 | # ifdef TTY_FLAGS |
0f113f3e MC |
483 | memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig)); |
484 | tty_new.TTY_FLAGS &= ~ECHO; | |
48feaceb | 485 | # endif |
a63d5eaa | 486 | |
48feaceb | 487 | # if defined(TTY_set) && !defined(OPENSSL_SYS_VMS) |
0f113f3e MC |
488 | if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1)) |
489 | return 0; | |
48feaceb RL |
490 | # endif |
491 | # ifdef OPENSSL_SYS_VMS | |
18edbe65 RL |
492 | if (is_a_tty) { |
493 | tty_new[0] = tty_orig[0]; | |
494 | tty_new[1] = tty_orig[1] | TT$M_NOECHO; | |
495 | tty_new[2] = tty_orig[2]; | |
496 | status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12, | |
497 | 0, 0, 0, 0); | |
c922ebe2 RL |
498 | if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) { |
499 | char tmp_num[2][12]; | |
500 | ||
501 | BIO_snprintf(tmp_num[0], sizeof(tmp_num[0]) - 1, "%%X%08X", | |
502 | status); | |
503 | BIO_snprintf(tmp_num[1], sizeof(tmp_num[1]) - 1, "%%X%08X", | |
504 | iosb.iosb$w_value); | |
505 | UIerr(UI_F_NOECHO_CONSOLE, UI_R_SYSQIOW_ERROR); | |
506 | ERR_add_error_data(5, "status=", tmp_num[0], | |
507 | ",", "iosb.iosb$w_value=", tmp_num[1]); | |
18edbe65 | 508 | return 0; |
c922ebe2 | 509 | } |
18edbe65 | 510 | } |
48feaceb RL |
511 | # endif |
512 | # if defined(_WIN32) && !defined(_WIN32_WCE) | |
087d3e89 AP |
513 | if (is_a_tty) { |
514 | tty_new = tty_orig; | |
515 | tty_new &= ~ENABLE_ECHO_INPUT; | |
516 | SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), tty_new); | |
517 | } | |
48feaceb | 518 | # endif |
0f113f3e MC |
519 | return 1; |
520 | } | |
a63d5eaa RL |
521 | |
522 | static int echo_console(UI *ui) | |
0f113f3e | 523 | { |
48feaceb | 524 | # if defined(TTY_set) && !defined(OPENSSL_SYS_VMS) |
0f113f3e | 525 | memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig)); |
0f113f3e MC |
526 | if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1)) |
527 | return 0; | |
48feaceb RL |
528 | # endif |
529 | # ifdef OPENSSL_SYS_VMS | |
18edbe65 RL |
530 | if (is_a_tty) { |
531 | tty_new[0] = tty_orig[0]; | |
de03cc92 | 532 | tty_new[1] = tty_orig[1]; |
18edbe65 RL |
533 | tty_new[2] = tty_orig[2]; |
534 | status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12, | |
535 | 0, 0, 0, 0); | |
c922ebe2 RL |
536 | if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) { |
537 | char tmp_num[2][12]; | |
538 | ||
539 | BIO_snprintf(tmp_num[0], sizeof(tmp_num[0]) - 1, "%%X%08X", | |
540 | status); | |
541 | BIO_snprintf(tmp_num[1], sizeof(tmp_num[1]) - 1, "%%X%08X", | |
542 | iosb.iosb$w_value); | |
543 | UIerr(UI_F_ECHO_CONSOLE, UI_R_SYSQIOW_ERROR); | |
544 | ERR_add_error_data(5, "status=", tmp_num[0], | |
545 | ",", "iosb.iosb$w_value=", tmp_num[1]); | |
18edbe65 | 546 | return 0; |
c922ebe2 | 547 | } |
18edbe65 | 548 | } |
48feaceb RL |
549 | # endif |
550 | # if defined(_WIN32) && !defined(_WIN32_WCE) | |
087d3e89 AP |
551 | if (is_a_tty) { |
552 | tty_new = tty_orig; | |
087d3e89 AP |
553 | SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), tty_new); |
554 | } | |
48feaceb | 555 | # endif |
0f113f3e MC |
556 | return 1; |
557 | } | |
a63d5eaa RL |
558 | |
559 | static int close_console(UI *ui) | |
0f113f3e MC |
560 | { |
561 | if (tty_in != stdin) | |
562 | fclose(tty_in); | |
563 | if (tty_out != stderr) | |
564 | fclose(tty_out); | |
48feaceb | 565 | # ifdef OPENSSL_SYS_VMS |
0f113f3e | 566 | status = sys$dassgn(channel); |
c922ebe2 RL |
567 | if (status != SS$_NORMAL) { |
568 | char tmp_num[12]; | |
569 | ||
570 | BIO_snprintf(tmp_num, sizeof(tmp_num) - 1, "%%X%08X", status); | |
571 | UIerr(UI_F_CLOSE_CONSOLE, UI_R_SYSDASSGN_ERROR); | |
572 | ERR_add_error_data(2, "status=", tmp_num); | |
18edbe65 | 573 | return 0; |
c922ebe2 | 574 | } |
48feaceb | 575 | # endif |
41cfbccc | 576 | CRYPTO_THREAD_unlock(ui->lock); |
a63d5eaa | 577 | |
0f113f3e MC |
578 | return 1; |
579 | } | |
a63d5eaa | 580 | |
48feaceb | 581 | # if !defined(OPENSSL_SYS_WINCE) |
a63d5eaa RL |
582 | /* Internal functions to handle signals and act on them */ |
583 | static void pushsig(void) | |
0f113f3e | 584 | { |
48feaceb | 585 | # ifndef OPENSSL_SYS_WIN32 |
0f113f3e | 586 | int i; |
48feaceb RL |
587 | # endif |
588 | # ifdef SIGACTION | |
0f113f3e | 589 | struct sigaction sa; |
a63d5eaa | 590 | |
16f8d4eb | 591 | memset(&sa, 0, sizeof(sa)); |
0f113f3e | 592 | sa.sa_handler = recsig; |
48feaceb | 593 | # endif |
a63d5eaa | 594 | |
48feaceb | 595 | # ifdef OPENSSL_SYS_WIN32 |
0f113f3e MC |
596 | savsig[SIGABRT] = signal(SIGABRT, recsig); |
597 | savsig[SIGFPE] = signal(SIGFPE, recsig); | |
598 | savsig[SIGILL] = signal(SIGILL, recsig); | |
599 | savsig[SIGINT] = signal(SIGINT, recsig); | |
600 | savsig[SIGSEGV] = signal(SIGSEGV, recsig); | |
601 | savsig[SIGTERM] = signal(SIGTERM, recsig); | |
48feaceb | 602 | # else |
0f113f3e | 603 | for (i = 1; i < NX509_SIG; i++) { |
48feaceb | 604 | # ifdef SIGUSR1 |
0f113f3e MC |
605 | if (i == SIGUSR1) |
606 | continue; | |
48feaceb RL |
607 | # endif |
608 | # ifdef SIGUSR2 | |
0f113f3e MC |
609 | if (i == SIGUSR2) |
610 | continue; | |
48feaceb RL |
611 | # endif |
612 | # ifdef SIGKILL | |
0f113f3e MC |
613 | if (i == SIGKILL) /* We can't make any action on that. */ |
614 | continue; | |
48feaceb RL |
615 | # endif |
616 | # ifdef SIGACTION | |
0f113f3e | 617 | sigaction(i, &sa, &savsig[i]); |
48feaceb | 618 | # else |
0f113f3e | 619 | savsig[i] = signal(i, recsig); |
48feaceb | 620 | # endif |
0f113f3e | 621 | } |
48feaceb | 622 | # endif |
a63d5eaa | 623 | |
48feaceb | 624 | # ifdef SIGWINCH |
0f113f3e | 625 | signal(SIGWINCH, SIG_DFL); |
48feaceb | 626 | # endif |
0f113f3e | 627 | } |
a63d5eaa RL |
628 | |
629 | static void popsig(void) | |
0f113f3e | 630 | { |
48feaceb | 631 | # ifdef OPENSSL_SYS_WIN32 |
0f113f3e MC |
632 | signal(SIGABRT, savsig[SIGABRT]); |
633 | signal(SIGFPE, savsig[SIGFPE]); | |
634 | signal(SIGILL, savsig[SIGILL]); | |
635 | signal(SIGINT, savsig[SIGINT]); | |
636 | signal(SIGSEGV, savsig[SIGSEGV]); | |
637 | signal(SIGTERM, savsig[SIGTERM]); | |
48feaceb | 638 | # else |
0f113f3e MC |
639 | int i; |
640 | for (i = 1; i < NX509_SIG; i++) { | |
48feaceb | 641 | # ifdef SIGUSR1 |
0f113f3e MC |
642 | if (i == SIGUSR1) |
643 | continue; | |
48feaceb RL |
644 | # endif |
645 | # ifdef SIGUSR2 | |
0f113f3e MC |
646 | if (i == SIGUSR2) |
647 | continue; | |
48feaceb RL |
648 | # endif |
649 | # ifdef SIGACTION | |
0f113f3e | 650 | sigaction(i, &savsig[i], NULL); |
48feaceb | 651 | # else |
0f113f3e | 652 | signal(i, savsig[i]); |
48feaceb | 653 | # endif |
0f113f3e | 654 | } |
48feaceb | 655 | # endif |
0f113f3e | 656 | } |
a63d5eaa RL |
657 | |
658 | static void recsig(int i) | |
0f113f3e MC |
659 | { |
660 | intr_signal = i; | |
661 | } | |
48feaceb | 662 | # endif |
a63d5eaa | 663 | |
a63d5eaa | 664 | /* Internal functions specific for Windows */ |
48feaceb | 665 | # if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32) |
a63d5eaa | 666 | static int noecho_fgets(char *buf, int size, FILE *tty) |
0f113f3e MC |
667 | { |
668 | int i; | |
669 | char *p; | |
670 | ||
671 | p = buf; | |
672 | for (;;) { | |
673 | if (size == 0) { | |
674 | *p = '\0'; | |
675 | break; | |
676 | } | |
677 | size--; | |
48feaceb | 678 | # if defined(_WIN32) |
0f113f3e | 679 | i = _getch(); |
48feaceb | 680 | # else |
0f113f3e | 681 | i = getch(); |
48feaceb | 682 | # endif |
0f113f3e MC |
683 | if (i == '\r') |
684 | i = '\n'; | |
685 | *(p++) = i; | |
686 | if (i == '\n') { | |
687 | *p = '\0'; | |
688 | break; | |
689 | } | |
690 | } | |
48feaceb | 691 | # ifdef WIN_CONSOLE_BUG |
0f113f3e MC |
692 | /* |
693 | * Win95 has several evil console bugs: one of these is that the last | |
694 | * character read using getch() is passed to the next read: this is | |
695 | * usually a CR so this can be trouble. No STDIO fix seems to work but | |
696 | * flushing the console appears to do the trick. | |
697 | */ | |
698 | { | |
699 | HANDLE inh; | |
700 | inh = GetStdHandle(STD_INPUT_HANDLE); | |
701 | FlushConsoleInputBuffer(inh); | |
702 | } | |
48feaceb | 703 | # endif |
26a7d938 | 704 | return strlen(buf); |
0f113f3e | 705 | } |
48feaceb RL |
706 | # endif |
707 | ||
708 | static UI_METHOD ui_openssl = { | |
709 | "OpenSSL default user interface", | |
710 | open_console, | |
711 | write_string, | |
712 | NULL, /* No flusher is needed for command lines */ | |
713 | read_string, | |
714 | close_console, | |
715 | NULL | |
716 | }; | |
717 | ||
718 | /* The method with all the built-in console thingies */ | |
719 | UI_METHOD *UI_OpenSSL(void) | |
720 | { | |
721 | return &ui_openssl; | |
722 | } | |
723 | ||
724 | static const UI_METHOD *default_UI_meth = &ui_openssl; | |
725 | ||
726 | #else | |
727 | ||
728 | static const UI_METHOD *default_UI_meth = NULL; | |
729 | ||
a63d5eaa | 730 | #endif |
48feaceb RL |
731 | |
732 | void UI_set_default_method(const UI_METHOD *meth) | |
733 | { | |
734 | default_UI_meth = meth; | |
735 | } | |
736 | ||
737 | const UI_METHOD *UI_get_default_method(void) | |
738 | { | |
739 | return default_UI_meth; | |
740 | } |