int console_get_userpass_input(prompts_t *p, unsigned char *in, int inlen) { HANDLE hin, hout; size_t curr_prompt; /* * Zero all the results, in case we abort half-way through. */ { int i; for (i = 0; i < (int)p->n_prompts; i++) prompt_set_result(p->prompts[i], ""); } /* * The prompts_t might contain a message to be displayed but no * actual prompt. More usually, though, it will contain * questions that the user needs to answer, in which case we * need to ensure that we're able to get the answers. */ if (p->n_prompts) { if (console_batch_mode) return 0; hin = GetStdHandle(STD_INPUT_HANDLE); if (hin == INVALID_HANDLE_VALUE) { fprintf(stderr, "Cannot get standard input handle\n"); cleanup_exit(1); } } /* * And if we have anything to print, we need standard output. */ if ((p->name_reqd && p->name) || p->instruction || p->n_prompts) { hout = GetStdHandle(STD_OUTPUT_HANDLE); if (hout == INVALID_HANDLE_VALUE) { fprintf(stderr, "Cannot get standard output handle\n"); cleanup_exit(1); } } /* * Preamble. */ /* We only print the `name' caption if we have to... */ if (p->name_reqd && p->name) { size_t l = strlen(p->name); console_data_untrusted(hout, p->name, l); if (p->name[l-1] != '\n') console_data_untrusted(hout, "\n", 1); } /* ...but we always print any `instruction'. */ if (p->instruction) { size_t l = strlen(p->instruction); console_data_untrusted(hout, p->instruction, l); if (p->instruction[l-1] != '\n') console_data_untrusted(hout, "\n", 1); } for (curr_prompt = 0; curr_prompt < p->n_prompts; curr_prompt++) { DWORD savemode, newmode; int len; prompt_t *pr = p->prompts[curr_prompt]; GetConsoleMode(hin, &savemode); newmode = savemode | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT; if (!pr->echo) newmode &= ~ENABLE_ECHO_INPUT; else newmode |= ENABLE_ECHO_INPUT; SetConsoleMode(hin, newmode); console_data_untrusted(hout, pr->prompt, strlen(pr->prompt)); len = 0; while (1) { DWORD ret = 0; BOOL r; prompt_ensure_result_size(pr, len * 5 / 4 + 512); r = ReadFile(hin, pr->result + len, pr->resultsize - len - 1, &ret, NULL); if (!r || ret == 0) { len = -1; break; } len += ret; if (pr->result[len - 1] == '\n') { len--; if (pr->result[len - 1] == '\r') len--; break; } } SetConsoleMode(hin, savemode); if (!pr->echo) { DWORD dummy; WriteFile(hout, "\r\n", 2, &dummy, NULL); } if (len < 0) { return 0; /* failure due to read error */ } pr->result[len] = '\0'; } return 1; /* success */ }
int console_get_userpass_input(prompts_t *p, unsigned char *in, int inlen) { size_t curr_prompt; FILE *outfp = NULL; int infd; /* * Zero all the results, in case we abort half-way through. */ { int i; for (i = 0; i < p->n_prompts; i++) prompt_set_result(p->prompts[i], ""); } if (p->n_prompts && console_batch_mode) return 0; console_open(&outfp, &infd); /* * Preamble. */ /* We only print the `name' caption if we have to... */ if (p->name_reqd && p->name) { size_t l = strlen(p->name); console_prompt_text(outfp, p->name, l); if (p->name[l-1] != '\n') console_prompt_text(outfp, "\n", 1); } /* ...but we always print any `instruction'. */ if (p->instruction) { size_t l = strlen(p->instruction); console_prompt_text(outfp, p->instruction, l); if (p->instruction[l-1] != '\n') console_prompt_text(outfp, "\n", 1); } for (curr_prompt = 0; curr_prompt < p->n_prompts; curr_prompt++) { struct termios oldmode, newmode; int len; prompt_t *pr = p->prompts[curr_prompt]; tcgetattr(infd, &oldmode); newmode = oldmode; newmode.c_lflag |= ISIG | ICANON; if (!pr->echo) newmode.c_lflag &= ~ECHO; else newmode.c_lflag |= ECHO; tcsetattr(infd, TCSANOW, &newmode); console_prompt_text(outfp, pr->prompt, strlen(pr->prompt)); len = 0; while (1) { int ret; prompt_ensure_result_size(pr, len * 5 / 4 + 512); ret = read(infd, pr->result + len, pr->resultsize - len - 1); if (ret <= 0) { len = -1; break; } len += ret; if (pr->result[len - 1] == '\n') { len--; break; } } tcsetattr(infd, TCSANOW, &oldmode); if (!pr->echo) console_prompt_text(outfp, "\n", 1); if (len < 0) { console_close(outfp, infd); return 0; /* failure due to read error */ } pr->result[len] = '\0'; } console_close(outfp, infd); return 1; /* success */ }