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

Contents of /lbbs/src/menu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.78 - (show annotations)
Wed Oct 29 07:36:38 2025 UTC (4 months, 2 weeks ago) by sysadm
Branch: MAIN
Changes since 1.77: +0 -2 lines
Content type: text/x-csrc
Refine

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

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