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

Contents of /lbbs/src/menu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.72 - (show annotations)
Mon Oct 13 05:30:33 2025 UTC (5 months ago) by sysadm
Branch: MAIN
Changes since 1.71: +1 -8 lines
Content type: text/x-csrc
Force redraw screen on return from submenu

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 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 = p_menu_set->p_reserved + MENU_SET_RESERVED_LENGTH;
1399 p_menu_set->p_menu_item_pool = p_menu_set->p_menu_pool + sizeof(MENU) * MAX_MENUS;
1400 p_menu_set->p_menu_screen_pool = p_menu_set->p_menu_item_pool + sizeof(MENU_ITEM) * MAX_MENUITEMS;
1401 p_menu_set->p_menu_screen_buf = 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