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

Contents of /lbbs/src/menu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.71 - (show annotations)
Wed Jul 2 04:17:33 2025 UTC (8 months, 2 weeks ago) by sysadm
Branch: MAIN
Changes since 1.70: +2 -2 lines
Content type: text/x-csrc
Support UTF8 instead of GBK

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

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