]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
3c2bdd7d | 2 | * Copyright 2001-2021 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 | ||
d5f9166b | 10 | #include "internal/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 | |
650c6687 | 130 | # if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) && ! (defined(OPENSSL_SYS_TANDEM) && defined(_SPT_MODEL_)) |
48feaceb RL |
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 | { |
cd3f8c1b RS |
375 | if (!CRYPTO_THREAD_write_lock(ui->lock)) |
376 | return 0; | |
0f113f3e | 377 | is_a_tty = 1; |
a63d5eaa | 378 | |
48feaceb | 379 | # if defined(OPENSSL_SYS_VXWORKS) |
0f113f3e MC |
380 | tty_in = stdin; |
381 | tty_out = stderr; | |
48feaceb | 382 | # elif defined(_WIN32) && !defined(_WIN32_WCE) |
087d3e89 AP |
383 | if ((tty_out = fopen("conout$", "w")) == NULL) |
384 | tty_out = stderr; | |
385 | ||
386 | if (GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &tty_orig)) { | |
387 | tty_in = stdin; | |
388 | } else { | |
389 | is_a_tty = 0; | |
390 | if ((tty_in = fopen("conin$", "r")) == NULL) | |
391 | tty_in = stdin; | |
392 | } | |
0f113f3e | 393 | # else |
48feaceb RL |
394 | # ifdef OPENSSL_SYS_MSDOS |
395 | # define DEV_TTY "con" | |
396 | # else | |
397 | # define DEV_TTY "/dev/tty" | |
398 | # endif | |
0f113f3e MC |
399 | if ((tty_in = fopen(DEV_TTY, "r")) == NULL) |
400 | tty_in = stdin; | |
401 | if ((tty_out = fopen(DEV_TTY, "w")) == NULL) | |
402 | tty_out = stderr; | |
48feaceb | 403 | # endif |
a63d5eaa | 404 | |
48feaceb | 405 | # if defined(TTY_get) && !defined(OPENSSL_SYS_VMS) |
0f113f3e | 406 | if (TTY_get(fileno(tty_in), &tty_orig) == -1) { |
48feaceb | 407 | # ifdef ENOTTY |
0f113f3e MC |
408 | if (errno == ENOTTY) |
409 | is_a_tty = 0; | |
410 | else | |
48feaceb RL |
411 | # endif |
412 | # ifdef EINVAL | |
0f113f3e | 413 | /* |
e3713c36 RS |
414 | * Ariel Glenn reports that solaris can return EINVAL instead. |
415 | * This should be ok | |
0f113f3e MC |
416 | */ |
417 | if (errno == EINVAL) | |
418 | is_a_tty = 0; | |
419 | else | |
48feaceb | 420 | # endif |
276bf862 RL |
421 | # ifdef ENXIO |
422 | /* | |
423 | * Solaris can return ENXIO. | |
424 | * This should be ok | |
425 | */ | |
426 | if (errno == ENXIO) | |
427 | is_a_tty = 0; | |
428 | else | |
429 | # endif | |
430 | # ifdef EIO | |
431 | /* | |
432 | * Linux can return EIO. | |
433 | * This should be ok | |
434 | */ | |
435 | if (errno == EIO) | |
436 | is_a_tty = 0; | |
437 | else | |
438 | # endif | |
08239483 MZ |
439 | # ifdef EPERM |
440 | /* | |
441 | * Linux can return EPERM (Operation not permitted), | |
442 | * e.g. if a daemon executes openssl via fork()+execve() | |
443 | * This should be ok | |
444 | */ | |
445 | if (errno == EPERM) | |
446 | is_a_tty = 0; | |
447 | else | |
448 | # endif | |
48feaceb | 449 | # ifdef ENODEV |
c901bcce RL |
450 | /* |
451 | * MacOS X returns ENODEV (Operation not supported by device), | |
452 | * which seems appropriate. | |
453 | */ | |
454 | if (errno == ENODEV) | |
a150f8e1 | 455 | is_a_tty = 0; |
c901bcce | 456 | else |
48feaceb | 457 | # endif |
49844486 | 458 | { |
a150f8e1 RL |
459 | ERR_raise_data(ERR_LIB_UI, UI_R_UNKNOWN_TTYGET_ERRNO_VALUE, |
460 | "errno=%d", errno); | |
49844486 RL |
461 | return 0; |
462 | } | |
0f113f3e | 463 | } |
48feaceb RL |
464 | # endif |
465 | # ifdef OPENSSL_SYS_VMS | |
0f113f3e | 466 | status = sys$assign(&terminal, &channel, 0, 0); |
18edbe65 RL |
467 | |
468 | /* if there isn't a TT device, something is very wrong */ | |
c922ebe2 | 469 | if (status != SS$_NORMAL) { |
a150f8e1 RL |
470 | ERR_raise_data(ERR_LIB_UI, UI_R_SYSASSIGN_ERROR, |
471 | "status=%%X%08X", status); | |
0f113f3e | 472 | return 0; |
c922ebe2 | 473 | } |
18edbe65 RL |
474 | |
475 | status = sys$qiow(0, channel, IO$_SENSEMODE, &iosb, 0, 0, tty_orig, 12, | |
476 | 0, 0, 0, 0); | |
477 | ||
478 | /* If IO$_SENSEMODE doesn't work, this is not a terminal device */ | |
0f113f3e | 479 | if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) |
18edbe65 | 480 | is_a_tty = 0; |
48feaceb | 481 | # endif |
0f113f3e MC |
482 | return 1; |
483 | } | |
a63d5eaa RL |
484 | |
485 | static int noecho_console(UI *ui) | |
0f113f3e | 486 | { |
48feaceb | 487 | # ifdef TTY_FLAGS |
0f113f3e MC |
488 | memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig)); |
489 | tty_new.TTY_FLAGS &= ~ECHO; | |
48feaceb | 490 | # endif |
a63d5eaa | 491 | |
48feaceb | 492 | # if defined(TTY_set) && !defined(OPENSSL_SYS_VMS) |
0f113f3e MC |
493 | if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1)) |
494 | return 0; | |
48feaceb RL |
495 | # endif |
496 | # ifdef OPENSSL_SYS_VMS | |
18edbe65 RL |
497 | if (is_a_tty) { |
498 | tty_new[0] = tty_orig[0]; | |
499 | tty_new[1] = tty_orig[1] | TT$M_NOECHO; | |
500 | tty_new[2] = tty_orig[2]; | |
501 | status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12, | |
502 | 0, 0, 0, 0); | |
c922ebe2 | 503 | if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) { |
a150f8e1 RL |
504 | ERR_raise_data(ERR_LIB_UI, UI_R_SYSQIOW_ERROR, |
505 | "status=%%X%08X, iosb.iosb$w_value=%%X%08X", | |
506 | status, iosb.iosb$w_value); | |
18edbe65 | 507 | return 0; |
c922ebe2 | 508 | } |
18edbe65 | 509 | } |
48feaceb RL |
510 | # endif |
511 | # if defined(_WIN32) && !defined(_WIN32_WCE) | |
087d3e89 AP |
512 | if (is_a_tty) { |
513 | tty_new = tty_orig; | |
514 | tty_new &= ~ENABLE_ECHO_INPUT; | |
515 | SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), tty_new); | |
516 | } | |
48feaceb | 517 | # endif |
0f113f3e MC |
518 | return 1; |
519 | } | |
a63d5eaa RL |
520 | |
521 | static int echo_console(UI *ui) | |
0f113f3e | 522 | { |
48feaceb | 523 | # if defined(TTY_set) && !defined(OPENSSL_SYS_VMS) |
0f113f3e | 524 | memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig)); |
0f113f3e MC |
525 | if (is_a_tty && (TTY_set(fileno(tty_in), &tty_new) == -1)) |
526 | return 0; | |
48feaceb RL |
527 | # endif |
528 | # ifdef OPENSSL_SYS_VMS | |
18edbe65 RL |
529 | if (is_a_tty) { |
530 | tty_new[0] = tty_orig[0]; | |
de03cc92 | 531 | tty_new[1] = tty_orig[1]; |
18edbe65 RL |
532 | tty_new[2] = tty_orig[2]; |
533 | status = sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12, | |
534 | 0, 0, 0, 0); | |
c922ebe2 | 535 | if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL)) { |
a150f8e1 RL |
536 | ERR_raise_data(ERR_LIB_UI, UI_R_SYSQIOW_ERROR, |
537 | "status=%%X%08X, iosb.iosb$w_value=%%X%08X", | |
538 | status, iosb.iosb$w_value); | |
18edbe65 | 539 | return 0; |
c922ebe2 | 540 | } |
18edbe65 | 541 | } |
48feaceb RL |
542 | # endif |
543 | # if defined(_WIN32) && !defined(_WIN32_WCE) | |
087d3e89 AP |
544 | if (is_a_tty) { |
545 | tty_new = tty_orig; | |
087d3e89 AP |
546 | SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), tty_new); |
547 | } | |
48feaceb | 548 | # endif |
0f113f3e MC |
549 | return 1; |
550 | } | |
a63d5eaa RL |
551 | |
552 | static int close_console(UI *ui) | |
0f113f3e | 553 | { |
5bea0e2e TM |
554 | int ret = 1; |
555 | ||
0f113f3e MC |
556 | if (tty_in != stdin) |
557 | fclose(tty_in); | |
558 | if (tty_out != stderr) | |
559 | fclose(tty_out); | |
48feaceb | 560 | # ifdef OPENSSL_SYS_VMS |
0f113f3e | 561 | status = sys$dassgn(channel); |
c922ebe2 | 562 | if (status != SS$_NORMAL) { |
a150f8e1 RL |
563 | ERR_raise_data(ERR_LIB_UI, UI_R_SYSDASSGN_ERROR, |
564 | "status=%%X%08X", status); | |
5bea0e2e | 565 | ret = 0; |
c922ebe2 | 566 | } |
48feaceb | 567 | # endif |
41cfbccc | 568 | CRYPTO_THREAD_unlock(ui->lock); |
a63d5eaa | 569 | |
5bea0e2e | 570 | return ret; |
0f113f3e | 571 | } |
a63d5eaa | 572 | |
48feaceb | 573 | # if !defined(OPENSSL_SYS_WINCE) |
a63d5eaa RL |
574 | /* Internal functions to handle signals and act on them */ |
575 | static void pushsig(void) | |
0f113f3e | 576 | { |
48feaceb | 577 | # ifndef OPENSSL_SYS_WIN32 |
0f113f3e | 578 | int i; |
48feaceb RL |
579 | # endif |
580 | # ifdef SIGACTION | |
0f113f3e | 581 | struct sigaction sa; |
a63d5eaa | 582 | |
16f8d4eb | 583 | memset(&sa, 0, sizeof(sa)); |
0f113f3e | 584 | sa.sa_handler = recsig; |
48feaceb | 585 | # endif |
a63d5eaa | 586 | |
48feaceb | 587 | # ifdef OPENSSL_SYS_WIN32 |
0f113f3e MC |
588 | savsig[SIGABRT] = signal(SIGABRT, recsig); |
589 | savsig[SIGFPE] = signal(SIGFPE, recsig); | |
590 | savsig[SIGILL] = signal(SIGILL, recsig); | |
591 | savsig[SIGINT] = signal(SIGINT, recsig); | |
592 | savsig[SIGSEGV] = signal(SIGSEGV, recsig); | |
593 | savsig[SIGTERM] = signal(SIGTERM, recsig); | |
48feaceb | 594 | # else |
0f113f3e | 595 | for (i = 1; i < NX509_SIG; i++) { |
48feaceb | 596 | # ifdef SIGUSR1 |
0f113f3e MC |
597 | if (i == SIGUSR1) |
598 | continue; | |
48feaceb RL |
599 | # endif |
600 | # ifdef SIGUSR2 | |
0f113f3e MC |
601 | if (i == SIGUSR2) |
602 | continue; | |
48feaceb RL |
603 | # endif |
604 | # ifdef SIGKILL | |
0f113f3e MC |
605 | if (i == SIGKILL) /* We can't make any action on that. */ |
606 | continue; | |
48feaceb RL |
607 | # endif |
608 | # ifdef SIGACTION | |
0f113f3e | 609 | sigaction(i, &sa, &savsig[i]); |
48feaceb | 610 | # else |
0f113f3e | 611 | savsig[i] = signal(i, recsig); |
48feaceb | 612 | # endif |
0f113f3e | 613 | } |
48feaceb | 614 | # endif |
a63d5eaa | 615 | |
48feaceb | 616 | # ifdef SIGWINCH |
0f113f3e | 617 | signal(SIGWINCH, SIG_DFL); |
48feaceb | 618 | # endif |
0f113f3e | 619 | } |
a63d5eaa RL |
620 | |
621 | static void popsig(void) | |
0f113f3e | 622 | { |
48feaceb | 623 | # ifdef OPENSSL_SYS_WIN32 |
0f113f3e MC |
624 | signal(SIGABRT, savsig[SIGABRT]); |
625 | signal(SIGFPE, savsig[SIGFPE]); | |
626 | signal(SIGILL, savsig[SIGILL]); | |
627 | signal(SIGINT, savsig[SIGINT]); | |
628 | signal(SIGSEGV, savsig[SIGSEGV]); | |
629 | signal(SIGTERM, savsig[SIGTERM]); | |
48feaceb | 630 | # else |
0f113f3e MC |
631 | int i; |
632 | for (i = 1; i < NX509_SIG; i++) { | |
48feaceb | 633 | # ifdef SIGUSR1 |
0f113f3e MC |
634 | if (i == SIGUSR1) |
635 | continue; | |
48feaceb RL |
636 | # endif |
637 | # ifdef SIGUSR2 | |
0f113f3e MC |
638 | if (i == SIGUSR2) |
639 | continue; | |
48feaceb RL |
640 | # endif |
641 | # ifdef SIGACTION | |
0f113f3e | 642 | sigaction(i, &savsig[i], NULL); |
48feaceb | 643 | # else |
0f113f3e | 644 | signal(i, savsig[i]); |
48feaceb | 645 | # endif |
0f113f3e | 646 | } |
48feaceb | 647 | # endif |
0f113f3e | 648 | } |
a63d5eaa RL |
649 | |
650 | static void recsig(int i) | |
0f113f3e MC |
651 | { |
652 | intr_signal = i; | |
653 | } | |
48feaceb | 654 | # endif |
a63d5eaa | 655 | |
a63d5eaa | 656 | /* Internal functions specific for Windows */ |
48feaceb | 657 | # if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32) |
a63d5eaa | 658 | static int noecho_fgets(char *buf, int size, FILE *tty) |
0f113f3e MC |
659 | { |
660 | int i; | |
661 | char *p; | |
662 | ||
663 | p = buf; | |
664 | for (;;) { | |
665 | if (size == 0) { | |
666 | *p = '\0'; | |
667 | break; | |
668 | } | |
669 | size--; | |
48feaceb | 670 | # if defined(_WIN32) |
0f113f3e | 671 | i = _getch(); |
48feaceb | 672 | # else |
0f113f3e | 673 | i = getch(); |
48feaceb | 674 | # endif |
0f113f3e MC |
675 | if (i == '\r') |
676 | i = '\n'; | |
677 | *(p++) = i; | |
678 | if (i == '\n') { | |
679 | *p = '\0'; | |
680 | break; | |
681 | } | |
682 | } | |
48feaceb | 683 | # ifdef WIN_CONSOLE_BUG |
0f113f3e MC |
684 | /* |
685 | * Win95 has several evil console bugs: one of these is that the last | |
686 | * character read using getch() is passed to the next read: this is | |
687 | * usually a CR so this can be trouble. No STDIO fix seems to work but | |
688 | * flushing the console appears to do the trick. | |
689 | */ | |
690 | { | |
691 | HANDLE inh; | |
692 | inh = GetStdHandle(STD_INPUT_HANDLE); | |
693 | FlushConsoleInputBuffer(inh); | |
694 | } | |
48feaceb | 695 | # endif |
26a7d938 | 696 | return strlen(buf); |
0f113f3e | 697 | } |
48feaceb RL |
698 | # endif |
699 | ||
700 | static UI_METHOD ui_openssl = { | |
701 | "OpenSSL default user interface", | |
702 | open_console, | |
703 | write_string, | |
704 | NULL, /* No flusher is needed for command lines */ | |
705 | read_string, | |
706 | close_console, | |
707 | NULL | |
708 | }; | |
709 | ||
710 | /* The method with all the built-in console thingies */ | |
711 | UI_METHOD *UI_OpenSSL(void) | |
712 | { | |
713 | return &ui_openssl; | |
714 | } | |
715 | ||
716 | static const UI_METHOD *default_UI_meth = &ui_openssl; | |
717 | ||
718 | #else | |
719 | ||
720 | static const UI_METHOD *default_UI_meth = NULL; | |
721 | ||
a63d5eaa | 722 | #endif |
48feaceb RL |
723 | |
724 | void UI_set_default_method(const UI_METHOD *meth) | |
725 | { | |
726 | default_UI_meth = meth; | |
727 | } | |
728 | ||
729 | const UI_METHOD *UI_get_default_method(void) | |
730 | { | |
731 | return default_UI_meth; | |
732 | } |