AmendHub

Download

jcs

/

subtext

/

main_menu.c

 

(View History)

jcs   *: Minor cleanups, remove dead variables, fix some error paths Latest amendment: 580 on 2024-01-24

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 <stdio.h>
18 #include <string.h>
19
20 #include "subtext.h"
21 #include "db.h"
22 #include "logger.h"
23 #include "main_menu.h"
24
25 struct main_menu_option *main_menu_options = NULL;
26
27 struct main_menu_option *
28 main_menu_parse(char *opts, size_t len)
29 {
30 char *line = NULL, *action = NULL, *menu_key = NULL, *all_keys = NULL,
31 *label = NULL;
32 size_t n, m, linelen, lastsep, linenum, ret_size;
33 short actionid, ret_count;
34 struct main_menu_option *ret = NULL;
35
36 ret_count = 0;
37 ret_size = 0;
38
39 #define LINESIZE 1024
40 line = xmalloc(LINESIZE);
41 if (line == NULL)
42 goto parse_done;
43 action = xmalloc(LINESIZE);
44 if (action == NULL)
45 goto parse_done;
46 menu_key = xmalloc(LINESIZE);
47 if (menu_key == NULL)
48 goto parse_done;
49 all_keys = xmalloc(LINESIZE);
50 if (all_keys == NULL)
51 goto parse_done;
52 label = xmalloc(LINESIZE);
53 if (label == NULL)
54 goto parse_done;
55
56 for (n = 0, lastsep = 0, linenum = 0; n <= len; n++) {
57 if (!(n == len || opts[n] == '\r'))
58 continue;
59
60 linenum++;
61 linelen = MIN(n - lastsep, LINESIZE - 1);
62 if (n == len && linelen)
63 linelen--;
64 memcpy(line, opts + lastsep, linelen);
65 line[linelen] = '\0';
66 lastsep = n + 1;
67
68 if (line[0] == '\0' || line[0] == '#' || line[0] == '\r')
69 continue;
70
71 /* BOARD_SHOW_FIRST:B:Bb:Message Board */
72
73 /* sscanf won't match %[^:] for an empty section ("A::Aa:aa") */
74 action[0] = '\0';
75 for (m = 0; m < linelen; m++) {
76 if (line[m] == ':') {
77 memcpy(action, line, m);
78 action[m] = '\0';
79 linelen -= m + 1;
80 memmove(line, line + m + 1, linelen + 1);
81 break;
82 }
83 }
84 if (action[0] == '\0') {
85 logger_printf("[views] Error parsing main_menu.txt on line "
86 "%ld: no action found", linenum);
87 ret_count = 0;
88 break;
89 }
90
91 actionid = ACTION_NONE;
92 if (strcmp(action, "BOARD_LIST_BOARDS") == 0)
93 actionid = ACTION_BOARD_LIST_BOARDS;
94 else if (strcmp(action, "BOARD_LIST_FTN_AREAS") == 0)
95 actionid = ACTION_BOARD_LIST_FTN_AREAS;
96 else if (strcmp(action, "BOARD_SHOW_FIRST") == 0)
97 actionid = ACTION_BOARD_SHOW_FIRST;
98 else if (strcmp(action, "BOARD_SHOW_1") == 0)
99 actionid = ACTION_BOARD_SHOW_1;
100 else if (strcmp(action, "BOARD_SHOW_2") == 0)
101 actionid = ACTION_BOARD_SHOW_2;
102 else if (strcmp(action, "BOARD_SHOW_3") == 0)
103 actionid = ACTION_BOARD_SHOW_3;
104 else if (strcmp(action, "BOARD_SHOW_4") == 0)
105 actionid = ACTION_BOARD_SHOW_4;
106 else if (strcmp(action, "BOARD_SHOW_5") == 0)
107 actionid = ACTION_BOARD_SHOW_5;
108 else if (strcmp(action, "BOARD_SHOW_6") == 0)
109 actionid = ACTION_BOARD_SHOW_6;
110 else if (strcmp(action, "BOARD_SHOW_7") == 0)
111 actionid = ACTION_BOARD_SHOW_7;
112 else if (strcmp(action, "BOARD_SHOW_8") == 0)
113 actionid = ACTION_BOARD_SHOW_8;
114 else if (strcmp(action, "BOARD_SHOW_9") == 0)
115 actionid = ACTION_BOARD_SHOW_9;
116 else if (strcmp(action, "BOARD_SHOW_10") == 0)
117 actionid = ACTION_BOARD_SHOW_10;
118 else if (strcmp(action, "CHAT") == 0)
119 actionid = ACTION_CHAT;
120 else if (strcmp(action, "FILES_MENU") == 0)
121 actionid = ACTION_FILES_MENU;
122 else if (strcmp(action, "GOODBYE") == 0)
123 actionid = ACTION_GOODBYE;
124 else if (strcmp(action, "RECENT_LOGINS") == 0)
125 actionid = ACTION_RECENT_LOGINS;
126 else if (strcmp(action, "MAIL_COMPOSE") == 0)
127 actionid = ACTION_MAIL_COMPOSE;
128 else if (strcmp(action, "MAIL_MENU") == 0)
129 actionid = ACTION_MAIL_MENU;
130 else if (strcmp(action, "MOTD") == 0)
131 actionid = ACTION_MOTD;
132 else if (strcmp(action, "PAGE_SEND_OR_ANSWER") == 0)
133 actionid = ACTION_PAGE_SEND_OR_ANSWER;
134 else if (strcmp(action, "SETTINGS_OR_SIGNUP") == 0)
135 actionid = ACTION_SETTINGS_OR_SIGNUP;
136 else if (strcmp(action, "SHOW_MENU") == 0)
137 actionid = ACTION_SHOW_MENU;
138 else if (strcmp(action, "SYSOP_MENU") == 0)
139 actionid = ACTION_SYSOP_MENU;
140 else if (strcmp(action, "WHOS_ONLINE") == 0)
141 actionid = ACTION_WHOS_ONLINE;
142 else {
143 logger_printf("[views] Error parsing main_menu.txt on line "
144 "%ld: invalid action \"%s\"", linenum, action);
145 ret_count = 0;
146 break;
147 }
148
149 menu_key[0] = '\0';
150 for (m = 0; m < linelen; m++) {
151 if (line[m] == ':') {
152 memcpy(menu_key, line, m);
153 menu_key[m] = '\0';
154 linelen -= m + 1;
155 memmove(line, line + m + 1, linelen + 1);
156 break;
157 }
158 }
159 /* menu_key can be 1 or 0 characters */
160 if (strlen(menu_key) > 1) {
161 logger_printf("[views] Error parsing main_menu.txt on line "
162 "%ld: Menu Key can only be 1 character", linenum);
163 ret_count = 0;
164 break;
165 }
166
167 all_keys[0] = '\0';
168 for (m = 0; m < linelen; m++) {
169 if (line[m] == ':') {
170 memcpy(all_keys, line, m);
171 all_keys[m] = '\0';
172 linelen -= m + 1;
173 memmove(line, line + m + 1, linelen + 1);
174 break;
175 }
176 }
177 if (all_keys[0] == '\0') {
178 logger_printf("[views] Error parsing main_menu.txt on line "
179 "%ld: All Keys field cannot be empty", linenum);
180 ret_count = 0;
181 break;
182 }
183
184 if (line[0] == '\0') {
185 logger_printf("[views] Error parsing main_menu.txt on line "
186 "%ld: Label cannot be empty", linenum);
187 ret_count = 0;
188 break;
189 }
190 strlcpy(label, line, LINESIZE);
191
192 if (!grow_to_fit(&ret, &ret_size,
193 sizeof(struct main_menu_option) * ret_count,
194 sizeof(struct main_menu_option), 4)) {
195 ret_count = 0;
196 break;
197 }
198
199 ret[ret_count].action = actionid;
200 ret[ret_count].menu_key = menu_key[0];
201 strlcpy(ret[ret_count].all_keys, all_keys,
202 sizeof(ret[ret_count].all_keys));
203 strlcpy(ret[ret_count].label, label, sizeof(ret[ret_count].label));
204 ret_count++;
205 }
206
207 parse_done:
208 if (line)
209 xfree(&line);
210 if (action)
211 xfree(&action);
212 if (menu_key)
213 xfree(&menu_key);
214 if (all_keys)
215 xfree(&all_keys);
216 if (label)
217 xfree(&label);
218
219 if (ret_count == 0) {
220 if (ret)
221 xfree(&ret);
222 return NULL;
223 }
224
225 if (!grow_to_fit(&ret, &ret_size,
226 sizeof(struct main_menu_option) * ret_count,
227 sizeof(struct main_menu_option), 1)) {
228 if (ret)
229 xfree(&ret);
230 return NULL;
231 }
232
233 ret[ret_count].action = ACTION_NONE;
234 ret[ret_count].menu_key = 0;
235 ret[ret_count].all_keys[0] = '\0';
236 ret[ret_count].label[0] = '\0';
237
238 return ret;
239 #undef LINESIZE
240 }