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

Contents of /lbbs/src/menu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.91 - (show annotations)
Thu Nov 20 01:02:15 2025 UTC (3 months, 3 weeks ago) by sysadm
Branch: MAIN
Changes since 1.90: +2 -8 lines
Content type: text/x-csrc
Refact set_xxxx_shm_readonly() with mprotect()

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

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