Line data Source code
1 : /* SPDX-License-Identifier: GPL-3.0-or-later */
2 : /* Copyright 2026 Peter Csaszar */
3 :
4 : /**
5 : * @file password_harness.c
6 : * @brief Minimal driver for terminal_read_password used by TEST-87 PTY tests.
7 : *
8 : * Exercises src/platform/posix/terminal.c::terminal_read_password directly
9 : * without requiring the full tg-tui login path or a mock Telegram server.
10 : *
11 : * Usage (chosen via argv[1]):
12 : *
13 : * password_harness prompt
14 : * Prompt once with terminal_read_password and print either
15 : * "ACCEPTED:<value>\n" on success (rc >= 0)
16 : * "ERROR\n" when the function returns -1
17 : * Exits 0 on success, 1 on error.
18 : *
19 : * password_harness prompt_then_echo
20 : * Prompt once with terminal_read_password, print "ACCEPTED:<value>\n",
21 : * then read a second line with fgets() and print "ECHO:<value>\n".
22 : * Used to verify echo is restored on return: if the echo was still
23 : * suppressed, the second read would not be visible on the PTY.
24 : * Exits 0.
25 : *
26 : * password_harness prompt_big
27 : * Same as "prompt" but with a 512-byte buffer for the 256-char input
28 : * test. Prints "ACCEPTED:<value>" and "LEN:<n>\n", exits 0.
29 : */
30 :
31 : #include "platform/terminal.h"
32 :
33 : #include <stdio.h>
34 : #include <string.h>
35 : #include <stdlib.h>
36 :
37 : #define SMALL_BUF 128
38 : #define BIG_BUF 512
39 :
40 4 : static int do_prompt_once(size_t cap) {
41 : char buf[BIG_BUF];
42 4 : if (cap > sizeof(buf)) cap = sizeof(buf);
43 4 : memset(buf, 0, cap);
44 4 : int rc = terminal_read_password("Password", buf, cap);
45 4 : if (rc < 0) {
46 1 : printf("ERROR\n");
47 1 : fflush(stdout);
48 1 : return 1;
49 : }
50 : /* Intentionally print the resulting buffer so the test can assert the
51 : * backspace- and long-input- handling works. The PTY output the test
52 : * inspects is the harness's own stdout, not the child's echoed input. */
53 3 : printf("ACCEPTED:%s\n", buf);
54 3 : printf("LEN:%d\n", rc);
55 3 : fflush(stdout);
56 3 : return 0;
57 : }
58 :
59 6 : int main(int argc, char **argv) {
60 6 : if (argc < 2) {
61 0 : fprintf(stderr, "usage: password_harness <mode>\n");
62 0 : return 2;
63 : }
64 :
65 6 : if (strcmp(argv[1], "prompt") == 0) {
66 3 : return do_prompt_once(SMALL_BUF);
67 : }
68 :
69 3 : if (strcmp(argv[1], "prompt_big") == 0) {
70 1 : return do_prompt_once(BIG_BUF);
71 : }
72 :
73 2 : if (strcmp(argv[1], "prompt_then_echo") == 0) {
74 : char pw[SMALL_BUF];
75 2 : memset(pw, 0, sizeof(pw));
76 2 : int rc = terminal_read_password("Password", pw, sizeof(pw));
77 2 : if (rc < 0) {
78 0 : printf("ERROR\n");
79 0 : fflush(stdout);
80 0 : return 1;
81 : }
82 2 : printf("ACCEPTED:%s\n", pw);
83 2 : fflush(stdout);
84 :
85 : /* Second read: ordinary line with no echo manipulation. If the
86 : * first call failed to restore termios (ECHO bit still cleared),
87 : * the user's typed characters would not appear on the PTY master
88 : * and the test would see no "CONFIRM" string followed by typed
89 : * text on screen. */
90 : char line[SMALL_BUF];
91 2 : if (!fgets(line, sizeof(line), stdin)) {
92 0 : printf("ECHO_ERROR\n");
93 0 : fflush(stdout);
94 0 : return 1;
95 : }
96 2 : size_t n = strlen(line);
97 4 : while (n > 0 && (line[n-1] == '\n' || line[n-1] == '\r'))
98 2 : line[--n] = '\0';
99 2 : printf("ECHO:%s\n", line);
100 2 : fflush(stdout);
101 2 : return 0;
102 : }
103 :
104 0 : fprintf(stderr, "unknown mode: %s\n", argv[1]);
105 0 : return 2;
106 : }
|