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

Contents of /lbbs/src/menu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.76 - (show annotations)
Sat Oct 18 13:23:50 2025 UTC (4 months, 4 weeks ago) by sysadm
Branch: MAIN
Changes since 1.75: +2 -1 lines
Content type: text/x-csrc
Refine log for debug

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

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