/[LeafOK_CVS]/lbbs/src/menu.c
ViewVC logotype

Annotation of /lbbs/src/menu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.96 - (hide annotations)
Fri Feb 13 12:38:09 2026 UTC (4 weeks, 4 days ago) by sysadm
Branch: MAIN
CVS Tags: HEAD
Changes since 1.95: +6 -0 lines
Content type: text/x-csrc
Fix build error caused by inline function under Debug mode with CMake

1 sysadm 1.80 /* SPDX-License-Identifier: GPL-3.0-or-later */
2     /*
3     * menu
4     * - configurable user interactive menu feature
5     *
6 sysadm 1.94 * Copyright (C) 2004-2026 Leaflet <leaflet@leafok.com>
7 sysadm 1.80 */
8 sysadm 1.1
9 sysadm 1.85 #ifdef HAVE_CONFIG_H
10     #include "config.h"
11     #endif
12    
13 sysadm 1.3 #include "bbs.h"
14 sysadm 1.17 #include "bbs_cmd.h"
15 sysadm 1.22 #include "bbs_cmd.h"
16 sysadm 1.67 #include "common.h"
17     #include "io.h"
18     #include "log.h"
19 sysadm 1.1 #include "menu.h"
20 sysadm 1.22 #include "screen.h"
21 sysadm 1.67 #include "user_priv.h"
22     #include <ctype.h>
23     #include <errno.h>
24 sysadm 1.89 #include <fcntl.h>
25 sysadm 1.1 #include <stdio.h>
26 sysadm 1.6 #include <stdlib.h>
27 sysadm 1.67 #include <string.h>
28 sysadm 1.40 #include <unistd.h>
29 sysadm 1.89 #include <sys/mman.h>
30     #include <sys/stat.h>
31 sysadm 1.1
32 sysadm 1.84 enum _menu_constant_t
33     {
34     MENU_SET_RESERVED_LENGTH = sizeof(int16_t) * 4,
35     };
36 sysadm 1.40
37 sysadm 1.84 static const char MENU_CONF_DELIM_WITH_SPACE[] = " ,\t\r\n";
38     static const char MENU_CONF_DELIM_WITHOUT_SPACE[] = "\r\n";
39 sysadm 1.77
40 sysadm 1.69 MENU_SET bbs_menu;
41 sysadm 1.73 MENU_SET top10_menu;
42 sysadm 1.1
43 sysadm 1.96 // External definitions for inline functions
44     extern inline MENU *get_menu(MENU_SET *p_menu_set, const char *menu_name);
45     extern inline MENU *get_menu_by_id(MENU_SET *p_menu_set, MENU_ID menu_id);
46     extern inline MENU_ITEM *get_menu_item_by_id(MENU_SET *p_menu_set, MENU_ITEM_ID menu_item_id);
47     extern inline MENU_SCREEN *get_menu_screen_by_id(MENU_SET *p_menu_set, MENU_SCREEN_ID menu_screen_id);
48    
49 sysadm 1.21 int load_menu(MENU_SET *p_menu_set, const char *conf_file)
50 sysadm 1.1 {
51 sysadm 1.89 char filepath[FILE_PATH_LEN];
52     int fd;
53 sysadm 1.90 size_t size;
54     void *p_shm;
55 sysadm 1.40 FILE *fin;
56 sysadm 1.31 int fin_line = 0;
57 sysadm 1.23 char buffer[LINE_BUFFER_LEN];
58 sysadm 1.33 char temp[LINE_BUFFER_LEN];
59 sysadm 1.31 char *p = NULL;
60     char *q = NULL;
61 sysadm 1.48 char *r = NULL;
62 sysadm 1.31 char *saveptr = NULL;
63     MENU *p_menu = NULL;
64 sysadm 1.40 MENU_ITEM *p_menu_item = NULL;
65     MENU_SCREEN *p_screen = NULL;
66     MENU_ID menu_id;
67     MENU_ITEM_ID menu_item_id;
68     MENU_SCREEN_ID screen_id;
69 sysadm 1.89
70     if (p_menu_set == NULL || conf_file == NULL)
71     {
72 sysadm 1.93 log_error("NULL pointer error");
73 sysadm 1.89 return -1;
74     }
75 sysadm 1.31
76 sysadm 1.69 // Initialize the data structure
77     memset(p_menu_set, 0, sizeof(*p_menu_set));
78    
79 sysadm 1.40 // Use trie_dict to search menu_id by menu name
80 sysadm 1.39 p_menu_set->p_menu_name_dict = trie_dict_create();
81 sysadm 1.40 if (p_menu_set->p_menu_name_dict == NULL)
82     {
83 sysadm 1.93 log_error("trie_dict_create() error");
84 sysadm 1.89 return -1;
85 sysadm 1.40 }
86    
87     // Use trie_dict to search screen_id by menu screen name
88     p_menu_set->p_menu_screen_dict = trie_dict_create();
89     if (p_menu_set->p_menu_screen_dict == NULL)
90     {
91 sysadm 1.93 log_error("trie_dict_create() error");
92 sysadm 1.89 return -1;
93 sysadm 1.40 }
94 sysadm 1.21
95     if ((fin = fopen(conf_file, "r")) == NULL)
96     {
97 sysadm 1.95 log_error("Open %s error: %d", conf_file, errno);
98 sysadm 1.31 return -2;
99 sysadm 1.21 }
100    
101 sysadm 1.40 // Allocate shared memory
102     size = MENU_SET_RESERVED_LENGTH +
103     sizeof(MENU) * MAX_MENUS +
104     sizeof(MENU_ITEM) * MAX_MENUITEMS +
105     sizeof(MENU_SCREEN) * MAX_MENUS +
106     MAX_MENU_SCR_BUF_LENGTH * MAX_MENUS;
107 sysadm 1.77
108 sysadm 1.89 strncpy(filepath, conf_file, sizeof(filepath) - 1);
109     filepath[sizeof(filepath) - 1] = '\0';
110     snprintf(p_menu_set->shm_name, sizeof(p_menu_set->shm_name), "/MENU_SHM_%s", basename(filepath));
111 sysadm 1.77
112 sysadm 1.89 if (shm_unlink(p_menu_set->shm_name) == -1 && errno != ENOENT)
113 sysadm 1.40 {
114 sysadm 1.93 log_error("shm_unlink(%s) error (%d)", p_menu_set->shm_name, errno);
115 sysadm 1.89 return -2;
116     }
117    
118     if ((fd = shm_open(p_menu_set->shm_name, O_CREAT | O_EXCL | O_RDWR, 0600)) == -1)
119     {
120 sysadm 1.93 log_error("shm_open(%s) error (%d)", p_menu_set->shm_name, errno);
121 sysadm 1.89 return -2;
122     }
123     if (ftruncate(fd, (off_t)size) == -1)
124     {
125 sysadm 1.93 log_error("ftruncate(size=%d) error (%d)", size, errno);
126 sysadm 1.89 close(fd);
127     return -2;
128     }
129 sysadm 1.77
130 sysadm 1.89 p_shm = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0L);
131     if (p_shm == MAP_FAILED)
132     {
133 sysadm 1.93 log_error("mmap() error (%d)", errno);
134 sysadm 1.89 close(fd);
135     return -2;
136     }
137 sysadm 1.77
138 sysadm 1.89 if (close(fd) < 0)
139 sysadm 1.40 {
140 sysadm 1.93 log_error("close(fd) error (%d)", errno);
141 sysadm 1.89 return -1;
142 sysadm 1.40 }
143 sysadm 1.77
144 sysadm 1.89 p_menu_set->shm_size = size;
145     p_menu_set->p_reserved = p_shm;
146    
147 sysadm 1.75 p_menu_set->p_menu_pool = (char *)(p_menu_set->p_reserved) + MENU_SET_RESERVED_LENGTH;
148     p_menu_set->p_menu_item_pool = (char *)(p_menu_set->p_menu_pool) + sizeof(MENU) * MAX_MENUS;
149     p_menu_set->p_menu_screen_pool = (char *)(p_menu_set->p_menu_item_pool) + sizeof(MENU_ITEM) * MAX_MENUITEMS;
150     p_menu_set->p_menu_screen_buf = (char *)(p_menu_set->p_menu_screen_pool) + sizeof(MENU_SCREEN) * MAX_MENUS;
151 sysadm 1.40 p_menu_set->p_menu_screen_buf_free = p_menu_set->p_menu_screen_buf;
152    
153     p_menu_set->menu_count = 0;
154     p_menu_set->menu_item_count = 0;
155     p_menu_set->menu_screen_count = 0;
156     p_menu_set->choose_step = 0;
157     p_menu_set->menu_id_path[0] = 0;
158 sysadm 1.69 p_menu_set->menu_item_pos[0] = 0;
159 sysadm 1.68 p_menu_set->allow_exit = 0;
160 sysadm 1.21
161 sysadm 1.23 while (fgets(buffer, sizeof(buffer), fin))
162 sysadm 1.3 {
163 sysadm 1.31 fin_line++;
164    
165     p = strtok_r(buffer, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
166     if (p == NULL) // Blank line
167 sysadm 1.21 {
168 sysadm 1.31 continue;
169     }
170    
171     if (*p == '#' || *p == '\r' || *p == '\n') // Comment or blank line
172     {
173     continue;
174     }
175    
176     if (*p == '%')
177     {
178     p++;
179    
180     if (strcmp(p, "menu") == 0) // BEGIN of sub-menu
181 sysadm 1.21 {
182 sysadm 1.31 if (p_menu != NULL)
183     {
184 sysadm 1.93 log_error("Incomplete menu definition in menu config line %d", fin_line);
185 sysadm 1.31 return -1;
186     }
187 sysadm 1.40
188     if (p_menu_set->menu_count >= MAX_MENUS)
189 sysadm 1.31 {
190 sysadm 1.93 log_error("Menu count (%d) exceed limit (%d)", p_menu_set->menu_count, MAX_MENUS);
191 sysadm 1.31 return -3;
192     }
193 sysadm 1.40 menu_id = (MENU_ID)p_menu_set->menu_count;
194     p_menu_set->menu_count++;
195    
196     p_menu = get_menu_by_id(p_menu_set, menu_id);
197 sysadm 1.21
198 sysadm 1.31 p_menu->item_count = 0;
199     p_menu->title.show = 0;
200 sysadm 1.40 p_menu->screen_show = 0;
201 sysadm 1.51 p_menu->page_item_limit = 0;
202 sysadm 1.62 p_menu->use_filter = 0;
203     p_menu->filter_handler = NULL;
204 sysadm 1.31
205     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
206     if (q == NULL)
207     {
208 sysadm 1.93 log_error("Error menu name in menu config line %d", fin_line);
209 sysadm 1.31 return -1;
210     }
211     p = q;
212 sysadm 1.86 while (isalnum((int)*q) || *q == '_' || *q == '-')
213 sysadm 1.31 {
214     q++;
215     }
216     if (*q != '\0')
217 sysadm 1.21 {
218 sysadm 1.93 log_error("Error menu name in menu config line %d", fin_line);
219 sysadm 1.31 return -1;
220 sysadm 1.21 }
221    
222 sysadm 1.31 if (q - p > sizeof(p_menu->name) - 1)
223 sysadm 1.21 {
224 sysadm 1.93 log_error("Too longer menu name in menu config line %d", fin_line);
225 sysadm 1.31 return -1;
226 sysadm 1.21 }
227 sysadm 1.31 strncpy(p_menu->name, p, sizeof(p_menu->name) - 1);
228     p_menu->name[sizeof(p_menu->name) - 1] = '\0';
229 sysadm 1.40
230     if (trie_dict_set(p_menu_set->p_menu_name_dict, p_menu->name, (int64_t)menu_id) != 1)
231 sysadm 1.39 {
232 sysadm 1.93 log_error("Error set menu dict [%s]", p_menu->name);
233 sysadm 1.39 }
234 sysadm 1.21
235 sysadm 1.31 // Check syntax
236     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
237     if (q != NULL)
238     {
239 sysadm 1.93 log_error("Unknown extra content in menu config line %d", fin_line);
240 sysadm 1.31 return -1;
241     }
242 sysadm 1.21
243 sysadm 1.31 while (fgets(buffer, sizeof(buffer), fin))
244     {
245     fin_line++;
246 sysadm 1.21
247 sysadm 1.31 p = strtok_r(buffer, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
248     if (p == NULL) // Blank line
249     {
250     continue;
251     }
252 sysadm 1.21
253 sysadm 1.31 if (*p == '#' || *p == '\r' || *p == '\n') // Comment or blank line
254 sysadm 1.21 {
255     continue;
256     }
257 sysadm 1.31
258     if (*p == '%') // END of sub-menu
259 sysadm 1.21 {
260 sysadm 1.31 p_menu = NULL;
261 sysadm 1.21 break;
262     }
263 sysadm 1.31 else if (*p == '!' || *p == '@')
264 sysadm 1.21 {
265 sysadm 1.31 // BEGIN of menu item
266 sysadm 1.40 if (p_menu->item_count >= MAX_ITEMS_PER_MENU)
267     {
268 sysadm 1.93 log_error("Menuitem count per menu (%d) exceed limit (%d)", p_menu->item_count, MAX_ITEMS_PER_MENU);
269 sysadm 1.40 return -1;
270     }
271     if (p_menu_set->menu_item_count >= MAX_MENUITEMS)
272 sysadm 1.31 {
273 sysadm 1.93 log_error("Menuitem count (%d) exceed limit (%d)", p_menu_set->menu_item_count, MAX_MENUITEMS);
274 sysadm 1.31 return -3;
275     }
276 sysadm 1.40 menu_item_id = (MENU_ITEM_ID)p_menu_set->menu_item_count;
277     p_menu_set->menu_item_count++;
278 sysadm 1.31
279 sysadm 1.40 p_menu->items[p_menu->item_count] = menu_item_id;
280     p_menu->item_count++;
281    
282     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
283    
284     p_menu_item->submenu = (*p == '!' ? 1 : 0);
285 sysadm 1.31
286     // Menu item action
287     p++;
288     if (strcmp(p, "..") == 0) // Return to parent menu
289     {
290     q = p + 2; // strlen("..")
291     }
292     else
293     {
294     q = p;
295 sysadm 1.86 while (isalnum((int)*q) || *q == '_' || *q == '-')
296 sysadm 1.31 {
297     q++;
298     }
299     if (*q != '\0')
300     {
301 sysadm 1.93 log_error("Error menu item action in menu config line %d", fin_line);
302 sysadm 1.31 return -1;
303     }
304     }
305    
306 sysadm 1.40 if (q - p > sizeof(p_menu_item->action) - 1)
307 sysadm 1.31 {
308 sysadm 1.93 log_error("Too longer menu action in menu config line %d", fin_line);
309 sysadm 1.31 return -1;
310     }
311 sysadm 1.40 strncpy(p_menu_item->action, p, sizeof(p_menu_item->action) - 1);
312     p_menu_item->action[sizeof(p_menu_item->action) - 1] = '\0';
313 sysadm 1.31
314     // Menu item row
315     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
316     if (q == NULL)
317     {
318 sysadm 1.93 log_error("Error menu item row in menu config line %d", fin_line);
319 sysadm 1.31 return -1;
320     }
321     p = q;
322 sysadm 1.86 while (isdigit((int)*q))
323 sysadm 1.31 {
324     q++;
325     }
326     if (*q != '\0')
327     {
328 sysadm 1.93 log_error("Error menu item row in menu config line %d", fin_line);
329 sysadm 1.31 return -1;
330     }
331 sysadm 1.40 p_menu_item->row = (int16_t)atoi(p);
332 sysadm 1.31
333     // Menu item col
334     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
335     if (q == NULL)
336     {
337 sysadm 1.93 log_error("Error menu item col in menu config line %d", fin_line);
338 sysadm 1.31 return -1;
339     }
340     p = q;
341 sysadm 1.86 while (isdigit((int)*q))
342 sysadm 1.31 {
343     q++;
344     }
345     if (*q != '\0')
346     {
347 sysadm 1.93 log_error("Error menu item col in menu config line %d", fin_line);
348 sysadm 1.31 return -1;
349     }
350 sysadm 1.40 p_menu_item->col = (int16_t)atoi(p);
351 sysadm 1.31
352     // Menu item priv
353     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
354     if (q == NULL)
355     {
356 sysadm 1.93 log_error("Error menu item priv in menu config line %d", fin_line);
357 sysadm 1.31 return -1;
358     }
359     p = q;
360 sysadm 1.86 while (isdigit((int)*q))
361 sysadm 1.31 {
362     q++;
363     }
364     if (*q != '\0')
365     {
366 sysadm 1.93 log_error("Error menu item priv in menu config line %d", fin_line);
367 sysadm 1.31 return -1;
368     }
369 sysadm 1.40 p_menu_item->priv = atoi(p);
370 sysadm 1.31
371     // Menu item level
372     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
373     if (q == NULL)
374     {
375 sysadm 1.93 log_error("Error menu item level in menu config line %d", fin_line);
376 sysadm 1.31 return -1;
377     }
378     p = q;
379 sysadm 1.86 while (isdigit((int)*q))
380 sysadm 1.31 {
381     q++;
382     }
383     if (*q != '\0')
384     {
385 sysadm 1.93 log_error("Error menu item level in menu config line %d", fin_line);
386 sysadm 1.31 return -1;
387     }
388 sysadm 1.40 p_menu_item->level = atoi(p);
389 sysadm 1.31
390     // Menu item name
391     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
392     if (q == NULL || *q != '\"')
393     {
394 sysadm 1.93 log_error("Error menu item name in menu config line %d", fin_line);
395 sysadm 1.31 return -1;
396     }
397     q++;
398     p = q;
399     while (*q != '\0' && *q != '\"')
400     {
401 sysadm 1.48 if (*q == '\\')
402     {
403     r = q;
404     while (*r != '\0')
405     {
406     *r = *(r + 1);
407     r++;
408     }
409     }
410 sysadm 1.31 q++;
411     }
412     if (*q != '\"' || *(q + 1) != '\0')
413     {
414 sysadm 1.93 log_error("Error menu item name in menu config line %d", fin_line);
415 sysadm 1.31 return -1;
416     }
417     *q = '\0';
418    
419 sysadm 1.40 if (q - p > sizeof(p_menu_item->name) - 1)
420 sysadm 1.31 {
421 sysadm 1.93 log_error("Too longer menu name in menu config line %d", fin_line);
422 sysadm 1.31 return -1;
423     }
424 sysadm 1.40 strncpy(p_menu_item->name, p, sizeof(p_menu_item->name) - 1);
425     p_menu_item->name[sizeof(p_menu_item->name) - 1] = '\0';
426 sysadm 1.31
427     // Menu item text
428     q = strtok_r(NULL, MENU_CONF_DELIM_WITHOUT_SPACE, &saveptr);
429     if (q == NULL || (q = strchr(q, '\"')) == NULL)
430     {
431 sysadm 1.93 log_error("Error menu item text in menu config line %d", fin_line);
432 sysadm 1.31 return -1;
433     }
434     q++;
435     p = q;
436     while (*q != '\0' && *q != '\"')
437     {
438 sysadm 1.48 if (*q == '\\')
439     {
440     r = q;
441     while (*r != '\0')
442     {
443     *r = *(r + 1);
444     r++;
445     }
446     }
447 sysadm 1.31 q++;
448     }
449     if (*q != '\"')
450     {
451 sysadm 1.93 log_error("Error menu item text in menu config line %d", fin_line);
452 sysadm 1.31 return -1;
453     }
454     *q = '\0';
455    
456 sysadm 1.40 if (q - p > sizeof(p_menu_item->text) - 1)
457 sysadm 1.31 {
458 sysadm 1.93 log_error("Too longer menu item text in menu config line %d", fin_line);
459 sysadm 1.31 return -1;
460     }
461 sysadm 1.40 strncpy(p_menu_item->text, p, sizeof(p_menu_item->text) - 1);
462     p_menu_item->text[sizeof(p_menu_item->text) - 1] = '\0';
463 sysadm 1.31
464     // Check syntax
465     q = strtok_r(q + 1, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
466     if (q != NULL)
467     {
468 sysadm 1.93 log_error("Unknown extra content in menu config line %d", fin_line);
469 sysadm 1.31 return -1;
470     }
471     }
472     else if (strcmp(p, "title") == 0)
473     {
474     p_menu->title.show = 1;
475    
476     // Menu title row
477     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
478     if (q == NULL)
479     {
480 sysadm 1.93 log_error("Error menu title row in menu config line %d", fin_line);
481 sysadm 1.31 return -1;
482     }
483     p = q;
484 sysadm 1.86 while (isdigit((int)*q))
485 sysadm 1.31 {
486     q++;
487     }
488     if (*q != '\0')
489     {
490 sysadm 1.93 log_error("Error menu title row in menu config line %d", fin_line);
491 sysadm 1.31 return -1;
492     }
493 sysadm 1.40 p_menu->title.row = (int16_t)atoi(p);
494 sysadm 1.31
495     // Menu title col
496     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
497     if (q == NULL)
498     {
499 sysadm 1.93 log_error("Error menu title col in menu config line %d", fin_line);
500 sysadm 1.31 return -1;
501     }
502     p = q;
503 sysadm 1.86 while (isdigit((int)*q))
504 sysadm 1.31 {
505     q++;
506     }
507     if (*q != '\0')
508     {
509 sysadm 1.93 log_error("Error menu title col in menu config line %d", fin_line);
510 sysadm 1.31 return -1;
511     }
512 sysadm 1.40 p_menu->title.col = (int16_t)atoi(p);
513 sysadm 1.31
514     // Menu title text
515     q = strtok_r(NULL, MENU_CONF_DELIM_WITHOUT_SPACE, &saveptr);
516     if (q == NULL || (q = strchr(q, '\"')) == NULL)
517     {
518 sysadm 1.93 log_error("Error menu title text in menu config line %d", fin_line);
519 sysadm 1.31 return -1;
520     }
521     q++;
522     p = q;
523     while (*q != '\0' && *q != '\"')
524     {
525 sysadm 1.48 if (*q == '\\')
526     {
527     r = q;
528     while (*r != '\0')
529     {
530     *r = *(r + 1);
531     r++;
532     }
533     }
534 sysadm 1.31 q++;
535     }
536     if (*q != '\"')
537     {
538 sysadm 1.93 log_error("Error menu title text in menu config line %d", fin_line);
539 sysadm 1.31 return -1;
540     }
541     *q = '\0';
542    
543 sysadm 1.48 if (q - p > sizeof(p_menu->title.text) - 1)
544 sysadm 1.31 {
545 sysadm 1.93 log_error("Too longer menu title text in menu config line %d", fin_line);
546 sysadm 1.31 return -1;
547     }
548     strncpy(p_menu->title.text, p, sizeof(p_menu->title.text) - 1);
549     p_menu->title.text[sizeof(p_menu->title.text) - 1] = '\0';
550    
551     // Check syntax
552     q = strtok_r(q + 1, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
553     if (q != NULL)
554     {
555 sysadm 1.93 log_error("Unknown extra content in menu config line %d", fin_line);
556 sysadm 1.31 return -1;
557     }
558 sysadm 1.21 }
559 sysadm 1.31 else if (strcmp(p, "screen") == 0)
560 sysadm 1.21 {
561 sysadm 1.40 p_menu->screen_show = 1;
562 sysadm 1.31
563     // Menu screen row
564     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
565     if (q == NULL)
566     {
567 sysadm 1.93 log_error("Error menu screen row in menu config line %d", fin_line);
568 sysadm 1.31 return -1;
569     }
570     p = q;
571 sysadm 1.86 while (isdigit((int)*q))
572 sysadm 1.31 {
573     q++;
574     }
575     if (*q != '\0')
576     {
577 sysadm 1.93 log_error("Error menu screen row in menu config line %d", fin_line);
578 sysadm 1.31 return -1;
579     }
580 sysadm 1.40 p_menu->screen_row = (int16_t)atoi(p);
581 sysadm 1.31
582     // Menu screen col
583     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
584     if (q == NULL)
585     {
586 sysadm 1.93 log_error("Error menu screen col in menu config line %d", fin_line);
587 sysadm 1.31 return -1;
588     }
589     p = q;
590 sysadm 1.86 while (isdigit((int)*q))
591 sysadm 1.31 {
592     q++;
593     }
594     if (*q != '\0')
595     {
596 sysadm 1.93 log_error("Error menu screen col in menu config line %d", fin_line);
597 sysadm 1.31 return -1;
598     }
599 sysadm 1.40 p_menu->screen_col = (int16_t)atoi(p);
600 sysadm 1.31
601     // Menu screen name
602     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
603     if (q == NULL)
604     {
605 sysadm 1.93 log_error("Error menu screen name in menu config line %d", fin_line);
606 sysadm 1.31 return -1;
607     }
608     p = q;
609 sysadm 1.86 while (isalnum((int)*q) || *q == '_' || *q == '-')
610 sysadm 1.31 {
611     q++;
612     }
613     if (*q != '\0')
614     {
615 sysadm 1.93 log_error("Error menu screen name in menu config line %d", fin_line);
616 sysadm 1.31 return -1;
617     }
618 sysadm 1.47 strncpy(p_menu->screen_name, p, sizeof(p_menu->screen_name) - 1);
619     p_menu->screen_name[sizeof(p_menu->screen_name) - 1] = '\0';
620 sysadm 1.31
621     // Check syntax
622     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
623     if (q != NULL)
624     {
625 sysadm 1.93 log_error("Unknown extra content in menu config line %d", fin_line);
626 sysadm 1.31 return -1;
627     }
628 sysadm 1.21 }
629 sysadm 1.51 else if (strcmp(p, "page") == 0)
630     {
631     // Menu page row
632     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
633     if (q == NULL)
634     {
635 sysadm 1.93 log_error("Error menu page row in menu config line %d", fin_line);
636 sysadm 1.51 return -1;
637     }
638     p = q;
639 sysadm 1.86 while (isdigit((int)*q))
640 sysadm 1.51 {
641     q++;
642     }
643     if (*q != '\0')
644     {
645 sysadm 1.93 log_error("Error menu page row in menu config line %d", fin_line);
646 sysadm 1.51 return -1;
647     }
648     p_menu->page_row = (int16_t)atoi(p);
649    
650     // Menu page col
651     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
652     if (q == NULL)
653     {
654 sysadm 1.93 log_error("Error menu page col in menu config line %d", fin_line);
655 sysadm 1.51 return -1;
656     }
657     p = q;
658 sysadm 1.86 while (isdigit((int)*q))
659 sysadm 1.51 {
660     q++;
661     }
662     if (*q != '\0')
663     {
664 sysadm 1.93 log_error("Error menu page col in menu config line %d", fin_line);
665 sysadm 1.51 return -1;
666     }
667     p_menu->page_col = (int16_t)atoi(p);
668    
669     // Menu page item limit
670     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
671     if (q == NULL)
672     {
673 sysadm 1.93 log_error("Error menu page item limit in menu config line %d", fin_line);
674 sysadm 1.51 return -1;
675     }
676     p = q;
677 sysadm 1.86 while (isdigit((int)*q))
678 sysadm 1.51 {
679     q++;
680     }
681     if (*q != '\0')
682     {
683 sysadm 1.93 log_error("Error menu page item limit in menu config line %d", fin_line);
684 sysadm 1.51 return -1;
685     }
686     p_menu->page_item_limit = (int16_t)atoi(p);
687    
688     // Check syntax
689     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
690     if (q != NULL)
691     {
692 sysadm 1.93 log_error("Unknown extra content in menu config line %d", fin_line);
693 sysadm 1.51 return -1;
694     }
695     }
696 sysadm 1.62 else if (strcmp(p, "use_filter") == 0)
697     {
698     p_menu->use_filter = 1;
699    
700     // Check syntax
701     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
702     if (q != NULL)
703     {
704 sysadm 1.93 log_error("Unknown extra content in menu config line %d", fin_line);
705 sysadm 1.62 return -1;
706     }
707     }
708 sysadm 1.31 }
709     }
710     else // BEGIN of menu screen
711     {
712 sysadm 1.40 if (p_menu_set->menu_item_count >= MAX_MENUS)
713     {
714 sysadm 1.93 log_error("Menu screen count (%d) exceed limit (%d)", p_menu_set->menu_screen_count, MAX_MENUS);
715 sysadm 1.40 return -3;
716     }
717     screen_id = (MENU_SCREEN_ID)p_menu_set->menu_screen_count;
718     p_menu_set->menu_screen_count++;
719    
720     p_screen = get_menu_screen_by_id(p_menu_set, screen_id);
721    
722 sysadm 1.31 q = p;
723 sysadm 1.86 while (isalnum((int)*q) || *q == '_' || *q == '-')
724 sysadm 1.31 {
725     q++;
726     }
727     if (*q != '\0')
728     {
729 sysadm 1.93 log_error("Error menu screen name in menu config line %d", fin_line);
730 sysadm 1.31 return -1;
731     }
732 sysadm 1.40 strncpy(p_screen->name, p, sizeof(p_screen->name) - 1);
733     p_screen->name[sizeof(p_screen->name) - 1] = '\0';
734 sysadm 1.31
735 sysadm 1.40 if (trie_dict_set(p_menu_set->p_menu_screen_dict, p_screen->name, (int64_t)screen_id) != 1)
736     {
737 sysadm 1.93 log_error("Error set menu screen dict [%s]", p_screen->name);
738 sysadm 1.40 }
739 sysadm 1.31
740     // Check syntax
741     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
742     if (q != NULL)
743     {
744 sysadm 1.93 log_error("Unknown extra content in menu config line %d", fin_line);
745 sysadm 1.31 return -1;
746     }
747    
748 sysadm 1.40 p_screen->buf_offset = p_menu_set->p_menu_screen_buf_free - p_menu_set->p_menu_screen_buf;
749     p_screen->buf_length = -1;
750    
751     // safety appending boundary
752     q = p_menu_set->p_menu_screen_buf + MAX_MENU_SCR_BUF_LENGTH * MAX_MENUS - 1;
753 sysadm 1.31
754     while (fgets(buffer, sizeof(buffer), fin))
755     {
756     fin_line++;
757    
758 sysadm 1.40 strncpy(temp, buffer, sizeof(temp) - 1); // Duplicate line for strtok_r
759     temp[sizeof(temp) - 1] = '\0';
760 sysadm 1.33 p = strtok_r(temp, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
761 sysadm 1.31 if (p != NULL && *p == '%') // END of menu screen
762 sysadm 1.21 {
763 sysadm 1.40 if (p_menu_set->p_menu_screen_buf_free + 1 > q)
764     {
765 sysadm 1.93 log_error("Menu screen buffer depleted (%p + 1 > %p)", p_menu_set->p_menu_screen_buf_free, q);
766 sysadm 1.40 return -3;
767     }
768    
769     *(p_menu_set->p_menu_screen_buf_free) = '\0';
770     p_menu_set->p_menu_screen_buf_free++;
771     p_screen->buf_length = p_menu_set->p_menu_screen_buf_free - p_menu_set->p_menu_screen_buf - p_screen->buf_offset;
772 sysadm 1.31 break;
773 sysadm 1.21 }
774 sysadm 1.31
775 sysadm 1.47 // Clear line
776     if (p_menu_set->p_menu_screen_buf_free + strlen(CTRL_SEQ_CLR_LINE) > q)
777     {
778 sysadm 1.93 log_error("Menu screen buffer depleted (%p + %d > %p)", p_menu_set->p_menu_screen_buf_free, q, strlen(CTRL_SEQ_CLR_LINE));
779 sysadm 1.47 return -3;
780     }
781     p_menu_set->p_menu_screen_buf_free = stpcpy(p_menu_set->p_menu_screen_buf_free, CTRL_SEQ_CLR_LINE);
782    
783 sysadm 1.40 p = buffer;
784     while (*p != '\0')
785 sysadm 1.21 {
786 sysadm 1.40 if (p_menu_set->p_menu_screen_buf_free + 2 > q)
787     {
788 sysadm 1.93 log_error("Menu screen buffer depleted (%p + 2 > %p)", p_menu_set->p_menu_screen_buf_free, q);
789 sysadm 1.40 return -3;
790     }
791    
792     if (*p == '\n' && p > buffer && *(p - 1) != '\r')
793     {
794     *(p_menu_set->p_menu_screen_buf_free) = '\r';
795     p_menu_set->p_menu_screen_buf_free++;
796     }
797    
798     *(p_menu_set->p_menu_screen_buf_free) = *p;
799     p++;
800     p_menu_set->p_menu_screen_buf_free++;
801 sysadm 1.21 }
802     }
803 sysadm 1.31
804 sysadm 1.40 if (p_screen->buf_length == -1)
805     {
806 sysadm 1.93 log_error("End of menu screen [%s] not found", p_screen->name);
807 sysadm 1.40 }
808 sysadm 1.21 }
809 sysadm 1.31 }
810     else // Invalid prefix
811     {
812 sysadm 1.93 log_error("Error in menu config line %d", fin_line);
813 sysadm 1.31 return -1;
814 sysadm 1.10 }
815 sysadm 1.3 }
816 sysadm 1.21 fclose(fin);
817 sysadm 1.3
818 sysadm 1.47 for (menu_id = 0; menu_id < p_menu_set->menu_count; menu_id++)
819     {
820     p_menu = get_menu_by_id(p_menu_set, menu_id);
821    
822     if (trie_dict_get(p_menu_set->p_menu_screen_dict, p_menu->screen_name, (int64_t *)(&(p_menu->screen_id))) != 1)
823     {
824 sysadm 1.93 log_error("Undefined menu screen [%s]", p);
825 sysadm 1.47 return -1;
826     }
827 sysadm 1.62
828     // Set menu->filter_handler of each menu pointing to filter
829     if (p_menu->use_filter == 1)
830     {
831     if ((p_menu->filter_handler = get_cmd_handler(p_menu->name)) == NULL)
832     {
833 sysadm 1.93 log_error("Undefined menu filter handler [%s]", p_menu->name);
834 sysadm 1.62 return -1;
835     }
836     }
837 sysadm 1.47 }
838    
839 sysadm 1.40 for (menu_item_id = 0; menu_item_id < p_menu_set->menu_item_count; menu_item_id++)
840     {
841     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
842 sysadm 1.44
843     // Set menu_item->action_cmd_handler of each menu item pointing to bbs_cmd
844     if (p_menu_item->submenu == 0)
845     {
846     if ((p_menu_item->action_cmd_handler = get_cmd_handler(p_menu_item->action)) == NULL)
847     {
848 sysadm 1.93 log_error("Undefined menu action cmd handler [%s]", p_menu_item->action);
849 sysadm 1.44 return -1;
850     }
851     }
852     // Set menu_item->action_menu_id of each menu item pointing to a submenu to the menu_id of the corresponding submenu
853     else if (strcmp(p_menu_item->action, "..") != 0)
854 sysadm 1.40 {
855     if (trie_dict_get(p_menu_set->p_menu_name_dict, p_menu_item->action, (int64_t *)&menu_id) != 1)
856     {
857 sysadm 1.93 log_error("Undefined sub menu id [%s]", p_menu_item->action);
858 sysadm 1.40 return -1;
859     }
860     p_menu_item->action_menu_id = menu_id;
861     }
862     }
863    
864     // Save status varaibles into reserved memory area
865     *((int16_t *)p_menu_set->p_reserved) = p_menu_set->menu_count;
866     *(((int16_t *)p_menu_set->p_reserved) + 1) = p_menu_set->menu_item_count;
867     *(((int16_t *)p_menu_set->p_reserved) + 2) = p_menu_set->menu_screen_count;
868 sysadm 1.2
869 sysadm 1.21 return 0;
870 sysadm 1.1 }
871    
872 sysadm 1.61 int display_menu_cursor(MENU_SET *p_menu_set, int show)
873 sysadm 1.3 {
874 sysadm 1.40 MENU_ID menu_id;
875     MENU_ITEM_ID menu_item_id;
876     MENU *p_menu;
877     MENU_ITEM *p_menu_item;
878     int16_t menu_item_pos;
879 sysadm 1.39
880 sysadm 1.40 menu_id = p_menu_set->menu_id_path[p_menu_set->choose_step];
881     p_menu = get_menu_by_id(p_menu_set, menu_id);
882     if (p_menu == NULL)
883     {
884 sysadm 1.93 log_error("get_menu_by_id(%d) return NULL pointer", menu_id);
885 sysadm 1.40 return -1;
886     }
887 sysadm 1.5
888 sysadm 1.40 menu_item_pos = p_menu_set->menu_item_pos[p_menu_set->choose_step];
889     menu_item_id = p_menu->items[menu_item_pos];
890     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
891     if (p_menu_item == NULL)
892 sysadm 1.10 {
893 sysadm 1.93 log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id);
894 sysadm 1.40 return -1;
895 sysadm 1.10 }
896 sysadm 1.5
897 sysadm 1.41 moveto(p_menu_set->menu_item_r_row[menu_item_pos], p_menu_set->menu_item_r_col[menu_item_pos] - 2);
898 sysadm 1.26 outc(show ? '>' : ' ');
899 sysadm 1.40
900     return 0;
901 sysadm 1.1 }
902    
903 sysadm 1.51 static int display_menu_current_page(MENU_SET *p_menu_set)
904 sysadm 1.1 {
905 sysadm 1.40 int16_t row = 0;
906     int16_t col = 0;
907     MENU_ID menu_id;
908     MENU_ITEM_ID menu_item_id;
909     MENU *p_menu;
910     MENU_ITEM *p_menu_item;
911 sysadm 1.51 int16_t menu_item_pos;
912     int16_t page_id = 0;
913 sysadm 1.40 MENU_SCREEN *p_menu_screen;
914 sysadm 1.3
915 sysadm 1.40 menu_id = p_menu_set->menu_id_path[p_menu_set->choose_step];
916     p_menu = get_menu_by_id(p_menu_set, menu_id);
917 sysadm 1.21 if (p_menu == NULL)
918 sysadm 1.26 {
919 sysadm 1.93 log_error("get_menu_by_id(%d) return NULL pointer", menu_id);
920 sysadm 1.21 return -1;
921 sysadm 1.26 }
922 sysadm 1.5
923 sysadm 1.51 clrline(p_menu->page_row, p_menu->page_row + p_menu->page_item_limit - 1);
924 sysadm 1.35
925 sysadm 1.21 if (p_menu->title.show)
926 sysadm 1.26 {
927 sysadm 1.48 if (p_menu->title.row == 0 && p_menu->title.col == 0)
928     {
929 sysadm 1.59 show_top(p_menu->title.text, BBS_name, "");
930 sysadm 1.48 }
931     else
932     {
933     moveto(p_menu->title.row, p_menu->title.col);
934     prints("%s", p_menu->title.text);
935     }
936 sysadm 1.26 }
937 sysadm 1.3
938 sysadm 1.40 if (p_menu->screen_show)
939 sysadm 1.10 {
940 sysadm 1.40 p_menu_screen = get_menu_screen_by_id(p_menu_set, p_menu->screen_id);
941     if (p_menu_screen == NULL)
942 sysadm 1.26 {
943 sysadm 1.93 log_error("get_menu_screen_by_id(%d) return NULL pointer", p_menu->screen_id);
944 sysadm 1.40 return -1;
945 sysadm 1.26 }
946 sysadm 1.40
947 sysadm 1.48 row = p_menu->screen_row;
948     col = p_menu->screen_col;
949    
950     moveto(row, col);
951 sysadm 1.40 prints("%s", p_menu_set->p_menu_screen_buf + p_menu_screen->buf_offset);
952 sysadm 1.10 }
953 sysadm 1.21
954 sysadm 1.51 menu_item_pos = p_menu_set->menu_item_pos[p_menu_set->choose_step];
955     page_id = p_menu_set->menu_item_page_id[menu_item_pos];
956    
957     while (menu_item_pos >= 0)
958     {
959     if (p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
960     {
961     menu_item_pos++;
962     break;
963     }
964    
965     if (menu_item_pos == 0)
966     {
967     break;
968     }
969    
970     menu_item_pos--;
971     }
972    
973     for (; menu_item_pos < p_menu->item_count; menu_item_pos++)
974     {
975     if (p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
976     {
977     break;
978     }
979    
980     menu_item_id = p_menu->items[menu_item_pos];
981     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
982    
983     if (p_menu_set->menu_item_display[menu_item_pos] == 0)
984     {
985     continue;
986     }
987    
988     row = p_menu_set->menu_item_r_row[menu_item_pos];
989     col = p_menu_set->menu_item_r_col[menu_item_pos];
990    
991     moveto(row, col);
992     prints("%s", p_menu_item->text);
993     }
994    
995     return 0;
996     }
997    
998     int display_menu(MENU_SET *p_menu_set)
999     {
1000     int16_t row = 0;
1001     int16_t col = 0;
1002     int menu_selectable = 0;
1003     MENU_ID menu_id;
1004     MENU_ITEM_ID menu_item_id;
1005     MENU *p_menu;
1006     MENU_ITEM *p_menu_item;
1007     int16_t menu_item_pos;
1008     int16_t page_id = 0;
1009     int page_item_count = 0;
1010    
1011     menu_id = p_menu_set->menu_id_path[p_menu_set->choose_step];
1012     p_menu = get_menu_by_id(p_menu_set, menu_id);
1013     if (p_menu == NULL)
1014     {
1015 sysadm 1.93 log_error("get_menu_by_id(%d) return NULL pointer", menu_id);
1016 sysadm 1.53 if (p_menu_set->choose_step > 0)
1017     {
1018     p_menu_set->choose_step--;
1019     return REDRAW;
1020     }
1021 sysadm 1.68 return EXITMENU;
1022 sysadm 1.51 }
1023    
1024 sysadm 1.75 if (p_menu->item_count <= 0) // empty menu
1025 sysadm 1.70 {
1026     moveto(p_menu->screen_row, p_menu->screen_col);
1027     clrtoeol();
1028 sysadm 1.71 prints("没有可选项");
1029 sysadm 1.70 press_any_key();
1030     return -1;
1031     }
1032    
1033 sysadm 1.51 menu_item_pos = p_menu_set->menu_item_pos[p_menu_set->choose_step];
1034     menu_item_id = p_menu->items[menu_item_pos];
1035     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1036     if (p_menu_item == NULL)
1037     {
1038 sysadm 1.93 log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id);
1039 sysadm 1.68 return EXITMENU;
1040 sysadm 1.51 }
1041    
1042     if (menu_item_pos > 0 &&
1043 sysadm 1.62 !(p_menu->use_filter ? (p_menu->filter_handler((void *)p_menu_item) == 0)
1044     : (checkpriv(&BBS_priv, 0, p_menu_item->priv) == 0 ||
1045     checklevel2(&BBS_priv, p_menu_item->level) == 0)))
1046 sysadm 1.51 {
1047     menu_selectable = 1;
1048     }
1049    
1050 sysadm 1.41 for (menu_item_pos = 0; menu_item_pos < p_menu->item_count; menu_item_pos++)
1051 sysadm 1.26 {
1052 sysadm 1.41 menu_item_id = p_menu->items[menu_item_pos];
1053 sysadm 1.40 p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1054    
1055     if (p_menu_item->row != 0)
1056 sysadm 1.26 {
1057 sysadm 1.40 row = p_menu_item->row;
1058 sysadm 1.26 }
1059 sysadm 1.40 if (p_menu_item->col != 0)
1060 sysadm 1.26 {
1061 sysadm 1.40 col = p_menu_item->col;
1062 sysadm 1.26 }
1063 sysadm 1.21
1064 sysadm 1.51 p_menu_set->menu_item_page_id[menu_item_pos] = page_id;
1065    
1066 sysadm 1.62 if (p_menu->use_filter ? (p_menu->filter_handler((void *)p_menu_item) == 0)
1067     : (checkpriv(&BBS_priv, 0, p_menu_item->priv) == 0 ||
1068     checklevel2(&BBS_priv, p_menu_item->level) == 0))
1069 sysadm 1.21 {
1070 sysadm 1.41 p_menu_set->menu_item_display[menu_item_pos] = 0;
1071     p_menu_set->menu_item_r_row[menu_item_pos] = 0;
1072     p_menu_set->menu_item_r_col[menu_item_pos] = 0;
1073 sysadm 1.21 }
1074     else
1075     {
1076 sysadm 1.41 p_menu_set->menu_item_display[menu_item_pos] = 1;
1077 sysadm 1.10
1078 sysadm 1.26 if (!menu_selectable)
1079     {
1080 sysadm 1.41 p_menu_set->menu_item_pos[p_menu_set->choose_step] = menu_item_pos;
1081 sysadm 1.26 menu_selectable = 1;
1082     }
1083 sysadm 1.3
1084 sysadm 1.41 p_menu_set->menu_item_r_row[menu_item_pos] = row;
1085     p_menu_set->menu_item_r_col[menu_item_pos] = col;
1086 sysadm 1.26
1087 sysadm 1.51 row++;
1088 sysadm 1.26
1089 sysadm 1.51 page_item_count++;
1090     if (p_menu->page_item_limit > 0 && page_item_count >= p_menu->page_item_limit)
1091     {
1092     page_id++;
1093     page_item_count = 0;
1094     row = p_menu->page_row;
1095     col = p_menu->page_col;
1096     }
1097 sysadm 1.21 }
1098 sysadm 1.10 }
1099    
1100 sysadm 1.21 if (!menu_selectable)
1101 sysadm 1.26 {
1102 sysadm 1.63 moveto(p_menu->screen_row, p_menu->screen_col);
1103 sysadm 1.66 clrtoeol();
1104 sysadm 1.71 prints("没有可选项");
1105 sysadm 1.63 press_any_key();
1106 sysadm 1.21 return -1;
1107 sysadm 1.26 }
1108 sysadm 1.3
1109 sysadm 1.53 if (display_menu_current_page(p_menu_set) != 0)
1110     {
1111     return -1;
1112     }
1113 sysadm 1.51
1114 sysadm 1.40 display_menu_cursor(p_menu_set, 1);
1115 sysadm 1.1
1116 sysadm 1.21 return 0;
1117 sysadm 1.1 }
1118    
1119 sysadm 1.40 int menu_control(MENU_SET *p_menu_set, int key)
1120 sysadm 1.12 {
1121 sysadm 1.40 MENU_ID menu_id;
1122     MENU_ITEM_ID menu_item_id;
1123 sysadm 1.21 MENU *p_menu;
1124 sysadm 1.40 MENU_ITEM *p_menu_item;
1125     int16_t menu_item_pos;
1126 sysadm 1.51 int16_t page_id;
1127     int require_page_change = 0;
1128 sysadm 1.12
1129 sysadm 1.40 if (p_menu_set->menu_count == 0)
1130     {
1131 sysadm 1.93 log_error("Empty menu set");
1132 sysadm 1.53 return EXITBBS;
1133 sysadm 1.40 }
1134 sysadm 1.12
1135 sysadm 1.40 menu_id = p_menu_set->menu_id_path[p_menu_set->choose_step];
1136     p_menu = get_menu_by_id(p_menu_set, menu_id);
1137     if (p_menu == NULL)
1138     {
1139 sysadm 1.93 log_error("get_menu_by_id(%d) return NULL pointer", menu_id);
1140 sysadm 1.53 if (p_menu_set->choose_step > 0)
1141     {
1142     p_menu_set->choose_step--;
1143     return REDRAW;
1144     }
1145     return EXITBBS;
1146 sysadm 1.40 }
1147 sysadm 1.12
1148 sysadm 1.40 if (p_menu->item_count == 0)
1149 sysadm 1.26 {
1150 sysadm 1.93 log_debug("Empty menu (%s)", p_menu->name);
1151 sysadm 1.53 if (p_menu_set->choose_step > 0)
1152     {
1153     p_menu_set->choose_step--;
1154     return REDRAW;
1155     }
1156     return EXITBBS;
1157 sysadm 1.26 }
1158 sysadm 1.3
1159 sysadm 1.40 menu_item_pos = p_menu_set->menu_item_pos[p_menu_set->choose_step];
1160 sysadm 1.51 page_id = p_menu_set->menu_item_page_id[menu_item_pos];
1161    
1162 sysadm 1.40 menu_item_id = p_menu->items[menu_item_pos];
1163     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1164     if (p_menu_item == NULL)
1165     {
1166 sysadm 1.93 log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id);
1167 sysadm 1.53 p_menu_set->menu_item_pos[p_menu_set->choose_step] = 0;
1168     return REDRAW;
1169 sysadm 1.40 }
1170 sysadm 1.3
1171 sysadm 1.21 switch (key)
1172 sysadm 1.10 {
1173 sysadm 1.21 case CR:
1174     case KEY_RIGHT:
1175 sysadm 1.40 if (p_menu_item->submenu)
1176 sysadm 1.21 {
1177 sysadm 1.40 if (strcmp(p_menu_item->action, "..") == 0)
1178 sysadm 1.26 {
1179 sysadm 1.21 return menu_control(p_menu_set, KEY_LEFT);
1180 sysadm 1.26 }
1181 sysadm 1.40 p_menu_set->choose_step++;
1182     p_menu_set->menu_id_path[p_menu_set->choose_step] = p_menu_item->action_menu_id;
1183     p_menu_set->menu_item_pos[p_menu_set->choose_step] = 0;
1184 sysadm 1.26
1185 sysadm 1.40 if (display_menu(p_menu_set) != 0)
1186 sysadm 1.26 {
1187 sysadm 1.21 return menu_control(p_menu_set, KEY_LEFT);
1188 sysadm 1.26 }
1189 sysadm 1.21 }
1190     else
1191     {
1192 sysadm 1.44 return ((*(p_menu_item->action_cmd_handler))((void *)(p_menu_item->name)));
1193 sysadm 1.21 }
1194 sysadm 1.38 break;
1195 sysadm 1.60 case KEY_ESC:
1196 sysadm 1.21 case KEY_LEFT:
1197 sysadm 1.40 if (p_menu_set->choose_step > 0)
1198 sysadm 1.21 {
1199 sysadm 1.40 p_menu_set->choose_step--;
1200 sysadm 1.72 return REDRAW;
1201 sysadm 1.21 }
1202     else
1203     {
1204 sysadm 1.68 if (p_menu_set->allow_exit)
1205     {
1206     return EXITMENU;
1207     }
1208    
1209 sysadm 1.40 display_menu_cursor(p_menu_set, 0);
1210     menu_item_pos = p_menu->item_count - 1;
1211     while (menu_item_pos >= 0)
1212 sysadm 1.26 {
1213 sysadm 1.40 menu_item_id = p_menu->items[menu_item_pos];
1214     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1215     if (p_menu_item == NULL)
1216     {
1217 sysadm 1.93 log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id);
1218 sysadm 1.40 return -1;
1219     }
1220    
1221 sysadm 1.41 if (!p_menu_set->menu_item_display[menu_item_pos] || p_menu_item->priv != 0 || p_menu_item->level != 0)
1222 sysadm 1.40 {
1223     menu_item_pos--;
1224     }
1225     else
1226     {
1227     break;
1228     }
1229 sysadm 1.26 }
1230 sysadm 1.40 p_menu_set->menu_item_pos[p_menu_set->choose_step] = menu_item_pos;
1231     display_menu_cursor(p_menu_set, 1);
1232 sysadm 1.21 }
1233 sysadm 1.38 break;
1234 sysadm 1.51 case KEY_PGUP:
1235     require_page_change = 1;
1236 sysadm 1.21 case KEY_UP:
1237 sysadm 1.40 display_menu_cursor(p_menu_set, 0);
1238 sysadm 1.21 do
1239     {
1240 sysadm 1.40 menu_item_pos--;
1241     if (menu_item_pos < 0)
1242     {
1243     menu_item_pos = p_menu->item_count - 1;
1244 sysadm 1.51 require_page_change = 0;
1245 sysadm 1.40 }
1246     menu_item_id = p_menu->items[menu_item_pos];
1247     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1248     if (p_menu_item == NULL)
1249 sysadm 1.26 {
1250 sysadm 1.93 log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id);
1251 sysadm 1.40 return -1;
1252 sysadm 1.26 }
1253 sysadm 1.51 if (require_page_change && p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
1254     {
1255     require_page_change = 0;
1256     }
1257     } while (require_page_change || !p_menu_set->menu_item_display[menu_item_pos]);
1258 sysadm 1.40 p_menu_set->menu_item_pos[p_menu_set->choose_step] = menu_item_pos;
1259 sysadm 1.51 if (p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
1260     {
1261     display_menu_current_page(p_menu_set);
1262     }
1263 sysadm 1.40 display_menu_cursor(p_menu_set, 1);
1264 sysadm 1.21 break;
1265 sysadm 1.51 case KEY_PGDN:
1266     require_page_change = 1;
1267 sysadm 1.21 case KEY_DOWN:
1268 sysadm 1.40 display_menu_cursor(p_menu_set, 0);
1269 sysadm 1.21 do
1270     {
1271 sysadm 1.40 menu_item_pos++;
1272     if (menu_item_pos >= p_menu->item_count)
1273     {
1274     menu_item_pos = 0;
1275 sysadm 1.51 require_page_change = 0;
1276 sysadm 1.40 }
1277     menu_item_id = p_menu->items[menu_item_pos];
1278     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1279     if (p_menu_item == NULL)
1280 sysadm 1.26 {
1281 sysadm 1.93 log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id);
1282 sysadm 1.40 return -1;
1283 sysadm 1.26 }
1284 sysadm 1.51 if (require_page_change && p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
1285     {
1286     require_page_change = 0;
1287     }
1288     } while (require_page_change || !p_menu_set->menu_item_display[menu_item_pos]);
1289 sysadm 1.40 p_menu_set->menu_item_pos[p_menu_set->choose_step] = menu_item_pos;
1290 sysadm 1.51 if (p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
1291     {
1292     display_menu_current_page(p_menu_set);
1293     }
1294 sysadm 1.40 display_menu_cursor(p_menu_set, 1);
1295 sysadm 1.21 break;
1296 sysadm 1.43 case KEY_HOME:
1297 sysadm 1.42 display_menu_cursor(p_menu_set, 0);
1298     menu_item_pos = 0;
1299     while (menu_item_pos < p_menu->item_count - 1)
1300     {
1301     menu_item_id = p_menu->items[menu_item_pos];
1302     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1303     if (p_menu_item == NULL)
1304     {
1305 sysadm 1.93 log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id);
1306 sysadm 1.42 return -1;
1307     }
1308    
1309     if (p_menu_set->menu_item_display[menu_item_pos])
1310     {
1311     break;
1312     }
1313    
1314     menu_item_pos++;
1315     }
1316     p_menu_set->menu_item_pos[p_menu_set->choose_step] = menu_item_pos;
1317 sysadm 1.51 if (p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
1318     {
1319     display_menu_current_page(p_menu_set);
1320     }
1321 sysadm 1.42 display_menu_cursor(p_menu_set, 1);
1322     break;
1323 sysadm 1.43 case KEY_END:
1324 sysadm 1.42 display_menu_cursor(p_menu_set, 0);
1325     menu_item_pos = p_menu->item_count - 1;
1326     while (menu_item_pos > 0)
1327     {
1328     menu_item_id = p_menu->items[menu_item_pos];
1329     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1330     if (p_menu_item == NULL)
1331     {
1332 sysadm 1.93 log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id);
1333 sysadm 1.42 return -1;
1334     }
1335    
1336     if (p_menu_set->menu_item_display[menu_item_pos])
1337     {
1338     break;
1339     }
1340    
1341     menu_item_pos--;
1342     }
1343     p_menu_set->menu_item_pos[p_menu_set->choose_step] = menu_item_pos;
1344 sysadm 1.51 if (p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
1345     {
1346     display_menu_current_page(p_menu_set);
1347     }
1348 sysadm 1.42 display_menu_cursor(p_menu_set, 1);
1349     break;
1350 sysadm 1.21 default:
1351 sysadm 1.31 if (isalnum(key))
1352 sysadm 1.21 {
1353 sysadm 1.41 for (menu_item_pos = 0; menu_item_pos < p_menu->item_count; menu_item_pos++)
1354 sysadm 1.21 {
1355 sysadm 1.41 menu_item_id = p_menu->items[menu_item_pos];
1356 sysadm 1.40 p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1357     if (p_menu_item == NULL)
1358     {
1359 sysadm 1.93 log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id);
1360 sysadm 1.40 return -1;
1361     }
1362    
1363 sysadm 1.41 if (toupper(key) == toupper(p_menu_item->name[0]) && p_menu_set->menu_item_display[menu_item_pos])
1364 sysadm 1.21 {
1365 sysadm 1.40 display_menu_cursor(p_menu_set, 0);
1366 sysadm 1.41 p_menu_set->menu_item_pos[p_menu_set->choose_step] = menu_item_pos;
1367 sysadm 1.51 if (p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
1368     {
1369     display_menu_current_page(p_menu_set);
1370     }
1371 sysadm 1.40 display_menu_cursor(p_menu_set, 1);
1372 sysadm 1.51 break;
1373 sysadm 1.21 }
1374     }
1375 sysadm 1.16 }
1376 sysadm 1.38 break;
1377 sysadm 1.3 }
1378 sysadm 1.1
1379 sysadm 1.48 return NOREDRAW;
1380 sysadm 1.1 }
1381 sysadm 1.15
1382 sysadm 1.40 int unload_menu(MENU_SET *p_menu_set)
1383 sysadm 1.15 {
1384 sysadm 1.60 if (p_menu_set == NULL)
1385     {
1386 sysadm 1.93 log_error("NULL pointer error");
1387 sysadm 1.60 return -1;
1388     }
1389    
1390 sysadm 1.39 if (p_menu_set->p_menu_name_dict != NULL)
1391     {
1392     trie_dict_destroy(p_menu_set->p_menu_name_dict);
1393 sysadm 1.46 p_menu_set->p_menu_name_dict = NULL;
1394 sysadm 1.39 }
1395    
1396 sysadm 1.40 if (p_menu_set->p_menu_screen_dict != NULL)
1397     {
1398     trie_dict_destroy(p_menu_set->p_menu_screen_dict);
1399 sysadm 1.46 p_menu_set->p_menu_screen_dict = NULL;
1400 sysadm 1.40 }
1401    
1402 sysadm 1.56 detach_menu_shm(p_menu_set);
1403 sysadm 1.40
1404 sysadm 1.89 if (shm_unlink(p_menu_set->shm_name) == -1 && errno != ENOENT)
1405 sysadm 1.40 {
1406 sysadm 1.93 log_error("shm_unlink(%s) error (%d)", p_menu_set->shm_name, errno);
1407 sysadm 1.89 return -2;
1408 sysadm 1.40 }
1409    
1410     return 0;
1411     }
1412    
1413 sysadm 1.68 int get_menu_shm_readonly(MENU_SET *p_menu_set)
1414     {
1415 sysadm 1.89 int fd;
1416 sysadm 1.68 void *p_shm;
1417 sysadm 1.89 struct stat sb;
1418     size_t size;
1419 sysadm 1.68
1420 sysadm 1.89 if (p_menu_set == NULL)
1421 sysadm 1.68 {
1422 sysadm 1.93 log_error("NULL pointer error");
1423 sysadm 1.68 return -1;
1424     }
1425    
1426 sysadm 1.89 if ((fd = shm_open(p_menu_set->shm_name, O_RDONLY, 0600)) == -1)
1427     {
1428 sysadm 1.93 log_error("shm_open(%s) error (%d)", p_menu_set->shm_name, errno);
1429 sysadm 1.89 return -2;
1430     }
1431    
1432     if (fstat(fd, &sb) < 0)
1433     {
1434 sysadm 1.93 log_error("fstat(fd) error (%d)", errno);
1435 sysadm 1.89 close(fd);
1436     return -2;
1437     }
1438    
1439     size = (size_t)sb.st_size;
1440    
1441     p_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0L);
1442     if (p_shm == MAP_FAILED)
1443     {
1444 sysadm 1.93 log_error("mmap() error (%d)", errno);
1445 sysadm 1.89 close(fd);
1446     return -2;
1447     }
1448    
1449     if (close(fd) < 0)
1450     {
1451 sysadm 1.93 log_error("close(fd) error (%d)", errno);
1452 sysadm 1.89 return -1;
1453     }
1454    
1455     p_menu_set->shm_size = size;
1456 sysadm 1.68 p_menu_set->p_reserved = p_shm;
1457 sysadm 1.89
1458 sysadm 1.75 p_menu_set->p_menu_pool = (char *)(p_menu_set->p_reserved) + MENU_SET_RESERVED_LENGTH;
1459     p_menu_set->p_menu_item_pool = (char *)(p_menu_set->p_menu_pool) + sizeof(MENU) * MAX_MENUS;
1460     p_menu_set->p_menu_screen_pool = (char *)(p_menu_set->p_menu_item_pool) + sizeof(MENU_ITEM) * MAX_MENUITEMS;
1461     p_menu_set->p_menu_screen_buf = (char *)(p_menu_set->p_menu_screen_pool) + sizeof(MENU_SCREEN) * MAX_MENUS;
1462 sysadm 1.68 p_menu_set->p_menu_screen_buf_free = p_menu_set->p_menu_screen_buf;
1463    
1464 sysadm 1.69 p_menu_set->choose_step = 0;
1465     p_menu_set->menu_id_path[0] = 0;
1466     p_menu_set->menu_item_pos[0] = 0;
1467    
1468 sysadm 1.68 return 0;
1469     }
1470    
1471 sysadm 1.56 int set_menu_shm_readonly(MENU_SET *p_menu_set)
1472 sysadm 1.40 {
1473 sysadm 1.89 if (p_menu_set == NULL)
1474     {
1475 sysadm 1.93 log_error("NULL pointer error");
1476 sysadm 1.89 return -1;
1477     }
1478 sysadm 1.54
1479 sysadm 1.91 if (p_menu_set->p_reserved != NULL && mprotect(p_menu_set->p_reserved, p_menu_set->shm_size, PROT_READ) < 0)
1480 sysadm 1.41 {
1481 sysadm 1.93 log_error("mprotect() error (%d)", errno);
1482 sysadm 1.89 return -2;
1483 sysadm 1.54 }
1484 sysadm 1.62
1485 sysadm 1.40 return 0;
1486 sysadm 1.15 }
1487 sysadm 1.18
1488 sysadm 1.56 int detach_menu_shm(MENU_SET *p_menu_set)
1489 sysadm 1.18 {
1490 sysadm 1.89 if (p_menu_set == NULL)
1491     {
1492 sysadm 1.93 log_error("NULL pointer error");
1493 sysadm 1.89 return -1;
1494     }
1495    
1496 sysadm 1.40 p_menu_set->menu_count = 0;
1497     p_menu_set->menu_item_count = 0;
1498     p_menu_set->menu_screen_count = 0;
1499     p_menu_set->choose_step = 0;
1500    
1501     p_menu_set->p_menu_pool = NULL;
1502     p_menu_set->p_menu_item_pool = NULL;
1503     p_menu_set->p_menu_screen_pool = NULL;
1504     p_menu_set->p_menu_screen_buf = NULL;
1505     p_menu_set->p_menu_screen_buf_free = NULL;
1506 sysadm 1.21
1507 sysadm 1.56 p_menu_set->p_menu_name_dict = NULL;
1508     p_menu_set->p_menu_screen_dict = NULL;
1509    
1510 sysadm 1.89 if (p_menu_set->p_reserved != NULL && munmap(p_menu_set->p_reserved, p_menu_set->shm_size) < 0)
1511 sysadm 1.40 {
1512 sysadm 1.93 log_error("munmap() error (%d)", errno);
1513 sysadm 1.89 return -2;
1514 sysadm 1.40 }
1515 sysadm 1.56
1516 sysadm 1.40 p_menu_set->p_reserved = NULL;
1517 sysadm 1.18
1518 sysadm 1.40 return 0;
1519 sysadm 1.18 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1