예제 #1
0
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 */
}
예제 #2
0
파일: uxcons.c 프로젝트: chemhack/putty
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 */
}