Download
jcs
/subtext
/user_settings.c
(View History)
jcs user_settings: Accept capital X in terminal cols/lines response | Latest amendment: 578 on 2024-01-10 |
1 | /* |
2 | * Copyright (c) 2022 joshua stein <jcs@jcs.org> |
3 | * |
4 | * Permission to use, copy, modify, and distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above |
6 | * copyright notice and this permission notice appear in all copies. |
7 | * |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ |
16 | |
17 | #include <stdarg.h> |
18 | #include <stdio.h> |
19 | #include <stdlib.h> |
20 | #include <string.h> |
21 | |
22 | #include "subtext.h" |
23 | #include "ansi.h" |
24 | #include "session.h" |
25 | #include "user.h" |
26 | #include "user_settings.h" |
27 | #include "util.h" |
28 | |
29 | void user_settings_password(struct session *s); |
30 | void user_settings_username(struct session *s); |
31 | |
32 | void |
33 | user_settings_renegotiate(struct session *s) |
34 | { |
35 | unsigned short c; |
36 | short cols, lines; |
37 | char *tsize; |
38 | |
39 | session_printf(s, |
40 | "Does this terminal support VT100 escape sequences? [Y/n] "); |
41 | session_flush(s); |
42 | |
43 | try_again: |
44 | c = session_input_char(s); |
45 | if (s->ending) |
46 | return; |
47 | if (c == 0 || c > 255) |
48 | goto try_again; |
49 | if (c == 'n' || c == 'N') { |
50 | session_printf(s, "%c\r\n", c == 'N' ? 'N' : 'n'); |
51 | session_flush(s); |
52 | s->vt100 = false; |
53 | } else if (c == '\r' || c == 'Y' || c == 'y') { |
54 | session_printf(s, "%c\r\n", c == 'Y' ? 'Y' : 'y'); |
55 | session_flush(s); |
56 | s->vt100 = true; |
57 | } |
58 | |
59 | if (!s->vt100) { |
60 | session_printf(s, |
61 | "Does this terminal support VT52 escape sequences? [Y/n] "); |
62 | session_flush(s); |
63 | |
64 | try_again2: |
65 | c = session_input_char(s); |
66 | if (s->ending) |
67 | return; |
68 | if (c == 0 || c > 255) |
69 | goto try_again2; |
70 | if (c == 'n' || c == 'N') { |
71 | session_printf(s, "%c\r\n", c == 'N' ? 'N' : 'n'); |
72 | session_flush(s); |
73 | s->vt52 = false; |
74 | } else if (c == '\r' || c == 'Y' || c == 'y') { |
75 | session_printf(s, "%c\r\n", c == 'Y' ? 'Y' : 'y'); |
76 | session_flush(s); |
77 | s->vt52 = true; |
78 | } |
79 | } |
80 | |
81 | if (s->vt100) |
82 | ansi_probe_screen_size(s); |
83 | |
84 | get_terminal_size: |
85 | session_printf(s, |
86 | "Terminal size (columns x rows) [%dx%d] ", s->terminal_columns, |
87 | s->terminal_lines); |
88 | session_flush(s); |
89 | |
90 | tsize = session_field_input(s, 10, 10, NULL, false, 0); |
91 | if (tsize == NULL) |
92 | return; |
93 | session_output(s, "\r\n", 2); |
94 | session_flush(s); |
95 | if (tsize[0] == '\0') { |
96 | xfree(&tsize); |
97 | return; |
98 | } |
99 | |
100 | if (sscanf(tsize, "%d%*[xX]%d", &cols, &lines) != 2) { |
101 | session_printf(s, "Invalid response, must be in format %dx%d\r\n", |
102 | s->terminal_columns, s->terminal_lines); |
103 | session_flush(s); |
104 | xfree(&tsize); |
105 | goto get_terminal_size; |
106 | } |
107 | |
108 | if (cols < MIN_TERMINAL_COLUMNS || lines < MIN_TERMINAL_LINES) { |
109 | session_printf(s, "Terminal too small, must be at least " |
110 | "%dx%d\r\n", MIN_TERMINAL_COLUMNS, MIN_TERMINAL_LINES); |
111 | session_flush(s); |
112 | xfree(&tsize); |
113 | goto get_terminal_size; |
114 | } |
115 | |
116 | s->terminal_columns = cols; |
117 | s->terminal_lines = lines; |
118 | session_logf(s, "Changed terminal size to %dx%d", cols, lines); |
119 | } |
120 | |
121 | void |
122 | user_settings_username(struct session *s) |
123 | { |
124 | char *username = NULL, *error = NULL; |
125 | |
126 | if (!s->user) { |
127 | session_printf(s, "{{B}}Error{{/B}}: Guest accounts " |
128 | "cannot change username\r\n"); |
129 | return; |
130 | } |
131 | |
132 | while (!s->ending) { |
133 | session_printf(s, "{{B}}Username:{{/B}} "); |
134 | session_flush(s); |
135 | username = session_field_input(s, DB_USERNAME_LENGTH, |
136 | DB_USERNAME_LENGTH, s->user->username, false, 0); |
137 | session_output(s, "\r\n", 2); |
138 | session_flush(s); |
139 | |
140 | if (username == NULL || s->ending) |
141 | break; |
142 | |
143 | if (username[0] == '\0') { |
144 | session_printf(s, "{{B}}Error:{{/B}} " |
145 | "Username cannot be blank\r\n"); |
146 | xfree(&username); |
147 | username = NULL; |
148 | continue; |
149 | } |
150 | |
151 | if (strcmp(s->user->username, username) == 0) |
152 | break; |
153 | |
154 | if (user_valid_username(s->user, username, &error) != 1) { |
155 | session_printf(s, "{{B}}Error:{{/B}} %s\r\n", error); |
156 | xfree(&error); |
157 | xfree(&username); |
158 | username = NULL; |
159 | continue; |
160 | } |
161 | |
162 | session_logf(s, "User changed username from %s to %s", |
163 | s->user->username, username); |
164 | strlcpy(s->user->username, username, sizeof(s->user->username)); |
165 | user_save(s->user); |
166 | user_cache_usernames(); |
167 | session_printf(s, "{{B}}Your username has been " |
168 | "changed to %s{{/B}}\r\n", s->user->username); |
169 | break; |
170 | } |
171 | |
172 | if (username != NULL) |
173 | xfree(&username); |
174 | } |
175 | |
176 | void |
177 | user_settings_menu(struct session *s) |
178 | { |
179 | static const struct session_menu_option opts[] = { |
180 | { 'r', "Rr", "Renegotiate terminal" }, |
181 | { 'p', "Pp", "Change password" }, |
182 | { 'u', "Uu", "Change username" }, |
183 | { 'q', "QqXx", "Return to main menu" }, |
184 | { '?', "?", "List menu options" }, |
185 | }; |
186 | static const char prompt_help[] = |
187 | "R:Renegotiate P:Password U:Username Q:Return ?:Help"; |
188 | char c; |
189 | bool show_help = true; |
190 | bool done = false; |
191 | |
192 | session_logf(s, "User settings menu"); |
193 | |
194 | while (!done) { |
195 | c = session_menu(s, "Settings", "Settings", (char *)prompt_help, |
196 | opts, nitems(opts), show_help, NULL, NULL); |
197 | show_help = false; |
198 | |
199 | switch (c) { |
200 | case 'r': |
201 | user_settings_renegotiate(s); |
202 | break; |
203 | case 'p': |
204 | user_change_password(s, s->user); |
205 | break; |
206 | case 'u': |
207 | user_settings_username(s); |
208 | break; |
209 | case '?': |
210 | show_help = true; |
211 | break; |
212 | default: |
213 | done = true; |
214 | break; |
215 | } |
216 | } |
217 | } |