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

Contents of /lbbs/src/menu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.75 - (show annotations)
Sat Oct 18 12:06:10 2025 UTC (4 months, 4 weeks ago) by sysadm
Branch: MAIN
Changes since 1.74: +10 -10 lines
Content type: text/x-csrc
Refine code to keep compatible with gcc -Wpedantic option

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

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