1 /* ----------------------------------------------------------------------- *
3 * Copyright 2004-2009 H. Peter Anvin - All Rights Reserved
4 * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
9 * Boston MA 02110-1301, USA; either version 2 of the License, or
10 * (at your option) any later version; incorporated herein by reference.
12 * ----------------------------------------------------------------------- */
23 #include <syslinux/adv.h>
24 #include <syslinux/config.h>
29 const char *empty_string
;
31 /* Root menu, starting menu, hidden menu, and list of all menus */
32 struct menu
*root_menu
, *start_menu
, *hide_menu
, *menu_list
;
34 /* These are global parameters regardless of which menu we're displaying */
35 int shiftkey
= 0; /* Only display menu if shift key pressed */
38 long long totaltimeout
= 0;
40 /* Keep track of global default */
41 static int has_ui
= 0; /* DEFAULT only counts if UI is found */
42 static const char *globaldefault
= NULL
;
43 static bool menusave
= false; /* True if there is any "menu save" */
45 /* Linked list of all entires, hidden or not; used by unlabel() */
46 static struct menu_entry
*all_entries
;
47 static struct menu_entry
**all_entries_end
= &all_entries
;
49 static const struct messages messages
[MSG_COUNT
] = {
50 [MSG_AUTOBOOT
] = {"autoboot", "Automatic boot in # second{,s}..."},
51 [MSG_TAB
] = {"tabmsg", "Press [Tab] to edit options"},
52 [MSG_NOTAB
] = {"notabmsg", ""},
53 [MSG_PASSPROMPT
] = {"passprompt", "Password required"},
56 #define astrdup(x) ({ char *__x = (x); \
57 size_t __n = strlen(__x) + 1; \
58 char *__p = alloca(__n); \
59 if ( __p ) memcpy(__p, __x, __n); \
62 /* Must match enum kernel_type */
63 const char *const kernel_types
[] = {
79 * Search the list of all menus for a specific label
81 static struct menu
*find_menu(const char *label
)
85 for (m
= menu_list
; m
; m
= m
->next
) {
86 if (!strcmp(label
, m
->label
))
95 static char *skipspace(char *p
)
97 while (*p
&& my_isspace(*p
))
103 /* Strip ^ from a string, returning a new reference to the same refstring
105 static const char *strip_caret(const char *str
)
121 return refstr_get(str
);
123 r
= q
= refstr_alloc(strlen(str
) - carets
);
124 for (p
= str
; *p
; p
++)
128 *q
= '\0'; /* refstr_alloc() already did this... */
133 /* Check to see if we are at a certain keyword (case insensitive) */
134 /* Returns a pointer to the first character past the keyword */
135 static char *looking_at(char *line
, const char *kwd
)
140 while (*p
&& *q
&& ((*p
^ *q
) & ~0x20) == 0) {
146 return NULL
; /* Didn't see the keyword */
148 return my_isspace(*p
) ? p
: NULL
; /* Must be EOL or whitespace */
151 static struct menu
*new_menu(struct menu
*parent
,
152 struct menu_entry
*parent_entry
, const char *label
)
154 struct menu
*m
= calloc(1, sizeof(struct menu
));
158 m
->title
= refstr_get(empty_string
);
163 m
->parent_entry
= parent_entry
;
164 parent_entry
->action
= MA_SUBMENU
;
165 parent_entry
->submenu
= m
;
167 for (i
= 0; i
< MSG_COUNT
; i
++)
168 m
->messages
[i
] = refstr_get(parent
->messages
[i
]);
170 memcpy(m
->mparm
, parent
->mparm
, sizeof m
->mparm
);
172 m
->allowedit
= parent
->allowedit
;
173 m
->timeout
= parent
->timeout
;
174 m
->save
= parent
->save
;
175 m
->immediate
= parent
->immediate
;
177 m
->ontimeout
= refstr_get(parent
->ontimeout
);
178 m
->onerror
= refstr_get(parent
->onerror
);
179 m
->menu_master_passwd
= refstr_get(parent
->menu_master_passwd
);
180 m
->menu_background
= refstr_get(parent
->menu_background
);
182 m
->color_table
= copy_color_table(parent
->color_table
);
184 for (i
= 0; i
< 12; i
++) {
185 m
->fkeyhelp
[i
].textname
= refstr_get(parent
->fkeyhelp
[i
].textname
);
186 m
->fkeyhelp
[i
].background
=
187 refstr_get(parent
->fkeyhelp
[i
].background
);
191 for (i
= 0; i
< MSG_COUNT
; i
++)
192 m
->messages
[i
] = refstrdup(messages
[i
].defmsg
);
193 for (i
= 0; i
< NPARAMS
; i
++)
194 m
->mparm
[i
] = mparm
[i
].value
;
196 m
->allowedit
= true; /* Allow edits of the command line */
197 m
->color_table
= default_color_table();
209 enum kernel_type type
;
212 const char *menulabel
;
215 unsigned int ipappend
;
216 unsigned int menuhide
;
217 unsigned int menudefault
;
218 unsigned int menuseparator
;
219 unsigned int menudisabled
;
220 unsigned int menuindent
;
221 enum menu_action action
;
224 struct menu
*submenu
;
227 /* Menu currently being parsed */
228 static struct menu
*current_menu
;
230 static void clear_label_data(struct labeldata
*ld
)
232 refstr_put(ld
->label
);
233 refstr_put(ld
->kernel
);
234 refstr_put(ld
->append
);
235 refstr_put(ld
->initrd
);
236 refstr_put(ld
->menulabel
);
237 refstr_put(ld
->passwd
);
239 memset(ld
, 0, sizeof *ld
);
242 static struct menu_entry
*new_entry(struct menu
*m
)
244 struct menu_entry
*me
;
246 if (m
->nentries
>= m
->nentries_space
) {
247 if (!m
->nentries_space
)
248 m
->nentries_space
= 1;
250 m
->nentries_space
<<= 1;
252 m
->menu_entries
= realloc(m
->menu_entries
, m
->nentries_space
*
253 sizeof(struct menu_entry
*));
256 me
= calloc(1, sizeof(struct menu_entry
));
258 me
->entry
= m
->nentries
;
259 m
->menu_entries
[m
->nentries
++] = me
;
260 *all_entries_end
= me
;
261 all_entries_end
= &me
->next
;
266 static void consider_for_hotkey(struct menu
*m
, struct menu_entry
*me
)
268 const char *p
= strchr(me
->displayname
, '^');
270 if (me
->action
!= MA_DISABLED
) {
272 unsigned char hotkey
= p
[1] & ~0x20;
273 if (!m
->menu_hotkeys
[hotkey
]) {
275 m
->menu_hotkeys
[hotkey
] = me
;
281 static void record(struct menu
*m
, struct labeldata
*ld
, const char *append
)
284 struct menu_entry
*me
;
285 const struct syslinux_ipappend_strings
*ipappend
;
288 return; /* Nothing defined */
290 /* Hidden entries are recorded on a special "hidden menu" */
295 char ipoptions
[4096], *ipp
;
301 me
->displayname
= ld
->menulabel
302 ? refstr_get(ld
->menulabel
) : refstr_get(ld
->label
);
303 me
->label
= refstr_get(ld
->label
);
304 me
->passwd
= refstr_get(ld
->passwd
);
305 me
->helptext
= ld
->helptext
;
307 me
->action
= ld
->action
? ld
->action
: MA_CMD
;
308 me
->save
= ld
->save
? (ld
->save
> 0) : m
->save
;
309 me
->immediate
= ld
->immediate
? (ld
->immediate
> 0) : m
->immediate
;
311 if (ld
->menuindent
) {
314 rsprintf(&dn
, "%*s%s", ld
->menuindent
, "", me
->displayname
);
315 refstr_put(me
->displayname
);
316 me
->displayname
= dn
;
319 if (ld
->menuseparator
) {
320 refstr_put(me
->displayname
);
321 me
->displayname
= refstr_get(empty_string
);
324 if (ld
->menuseparator
|| ld
->menudisabled
) {
325 me
->action
= MA_DISABLED
;
326 refstr_put(me
->label
);
328 refstr_put(me
->passwd
);
333 consider_for_hotkey(m
, me
);
335 switch (me
->action
) {
341 ipp
+= sprintf(ipp
, " initrd=%s", ld
->initrd
);
344 ipappend
= syslinux_ipappend_strings();
345 for (i
= 0; i
< ipappend
->count
; i
++) {
346 if ((ld
->ipappend
& (1U << i
)) && ipappend
->ptr
[i
])
347 ipp
+= sprintf(ipp
, " %s", ipappend
->ptr
[i
]);
354 if (!a
|| (a
[0] == '-' && !a
[1]))
357 if (ld
->type
== KT_KERNEL
) {
358 rsprintf(&me
->cmdline
, "%s%s%s%s", ld
->kernel
, s
, a
, ipoptions
);
360 rsprintf(&me
->cmdline
, ".%s %s%s%s%s",
361 kernel_types
[ld
->type
], ld
->kernel
, s
, a
, ipoptions
);
367 me
->cmdline
= refstr_get(ld
->kernel
);
372 me
->submenu
= ld
->submenu
;
379 if (ld
->menudefault
&& me
->action
== MA_CMD
)
380 m
->defentry
= m
->nentries
- 1;
383 clear_label_data(ld
);
386 static struct menu
*begin_submenu(const char *tag
)
388 struct menu_entry
*me
;
393 me
= new_entry(current_menu
);
394 me
->displayname
= refstrdup(tag
);
395 return new_menu(current_menu
, me
, refstr_get(me
->displayname
));
398 static struct menu
*end_submenu(void)
400 return current_menu
->parent
? current_menu
->parent
: current_menu
;
403 static struct menu_entry
*find_label(const char *str
)
406 struct menu_entry
*me
;
410 while (*p
&& !my_isspace(*p
))
413 /* p now points to the first byte beyond the kernel name */
416 for (me
= all_entries
; me
; me
= me
->next
) {
417 if (!strncmp(str
, me
->label
, pos
) && !me
->label
[pos
])
424 static const char *unlabel(const char *str
)
426 /* Convert a CLI-style command line to an executable command line */
429 struct menu_entry
*me
;
433 while (*p
&& !my_isspace(*p
))
436 /* p now points to the first byte beyond the kernel name */
439 for (me
= all_entries
; me
; me
= me
->next
) {
440 if (!strncmp(str
, me
->label
, pos
) && !me
->label
[pos
]) {
441 /* Found matching label */
442 rsprintf(&q
, "%s%s", me
->cmdline
, p
);
451 static const char *refdup_word(char **p
)
456 while (*ep
&& !my_isspace(*ep
))
460 return refstrndup(sp
, ep
- sp
);
463 int my_isxdigit(char c
)
467 return (uc
- '0') < 10 || ((uc
| 0x20) - 'a') < 6;
470 unsigned int hexval(char c
)
472 unsigned char uc
= c
| 0x20;
479 return uc
- 'a' + 10;
482 unsigned int hexval2(const char *p
)
484 return (hexval(p
[0]) << 4) + hexval(p
[1]);
487 uint32_t parse_argb(char **p
)
499 while (my_isxdigit(*ep
))
509 (hexval(sp
[0]) * 0x11 << 16) +
510 (hexval(sp
[1]) * 0x11 << 8) + (hexval(sp
[2]) * 0x11);
514 (hexval(sp
[0]) * 0x11 << 24) +
515 (hexval(sp
[1]) * 0x11 << 16) +
516 (hexval(sp
[2]) * 0x11 << 8) + (hexval(sp
[3]) * 0x11);
518 case 6: /* #rrggbb */
519 case 9: /* #rrrgggbbb */
520 case 12: /* #rrrrggggbbbb */
524 (hexval2(sp
+ 0) << 16) +
525 (hexval2(sp
+ dl
) << 8) + hexval2(sp
+ dl
* 2);
527 case 8: /* #aarrggbb */
528 /* #aaarrrgggbbb is indistinguishable from #rrrrggggbbbb,
529 assume the latter is a more common format */
530 case 16: /* #aaaarrrrggggbbbb */
533 (hexval2(sp
+ 0) << 24) +
534 (hexval2(sp
+ dl
) << 16) +
535 (hexval2(sp
+ dl
* 2) << 8) + hexval2(sp
+ dl
* 3);
538 argb
= 0xffff0000; /* Bright red (error indication) */
546 * Parser state. This is global so that including multiple
547 * files work as expected, which is that everything works the
548 * same way as if the files had been concatenated together.
550 static const char *append
= NULL
;
551 static unsigned int ipappend
= 0;
552 static struct labeldata ld
;
554 static int parse_one_config(const char *filename
);
556 static char *is_kernel_type(char *cmdstr
, enum kernel_type
*type
)
558 const char *const *p
;
560 enum kernel_type t
= KT_NONE
;
562 for (p
= kernel_types
; *p
; p
++, t
++) {
563 if ((q
= looking_at(cmdstr
, *p
))) {
572 static char *is_message_name(char *cmdstr
, enum message_number
*msgnr
)
575 enum message_number i
;
577 for (i
= 0; i
< MSG_COUNT
; i
++) {
578 if ((q
= looking_at(cmdstr
, messages
[i
].name
))) {
587 static char *is_fkey(char *cmdstr
, int *fkeyno
)
592 if ((cmdstr
[0] | 0x20) != 'f')
595 no
= strtoul(cmdstr
+ 1, &q
, 10);
599 if (no
< 0 || no
> 12)
602 *fkeyno
= (no
== 0) ? 10 : no
- 1;
606 static void parse_config_file(FILE * f
)
608 char line
[MAX_LINE
], *p
, *ep
, ch
;
609 enum kernel_type type
= -1;
610 enum message_number msgnr
= -1;
612 struct menu
*m
= current_menu
;
614 while (fgets(line
, sizeof line
, f
)) {
615 p
= strchr(line
, '\r');
618 p
= strchr(line
, '\n');
624 if (looking_at(p
, "menu")) {
625 p
= skipspace(p
+ 4);
627 if (looking_at(p
, "label")) {
629 refstr_put(ld
.menulabel
);
630 ld
.menulabel
= refstrdup(skipspace(p
+ 5));
631 } else if (m
->parent_entry
) {
632 refstr_put(m
->parent_entry
->displayname
);
633 m
->parent_entry
->displayname
= refstrdup(skipspace(p
+ 5));
634 consider_for_hotkey(m
->parent
, m
->parent_entry
);
636 /* MENU LABEL -> MENU TITLE on submenu */
637 refstr_put(m
->title
);
638 m
->title
= strip_caret(m
->parent_entry
->displayname
);
641 } else if (looking_at(p
, "title")) {
642 refstr_put(m
->title
);
643 m
->title
= refstrdup(skipspace(p
+ 5));
644 if (m
->parent_entry
) {
645 /* MENU TITLE -> MENU LABEL on submenu */
646 if (m
->parent_entry
->displayname
== m
->label
) {
647 refstr_put(m
->parent_entry
->displayname
);
648 m
->parent_entry
->displayname
= refstr_get(m
->title
);
651 } else if (looking_at(p
, "default")) {
654 } else if (m
->parent_entry
) {
655 m
->parent
->defentry
= m
->parent_entry
->entry
;
657 } else if (looking_at(p
, "hide")) {
659 } else if (looking_at(p
, "passwd")) {
661 refstr_put(ld
.passwd
);
662 ld
.passwd
= refstrdup(skipspace(p
+ 6));
663 } else if (m
->parent_entry
) {
664 refstr_put(m
->parent_entry
->passwd
);
665 m
->parent_entry
->passwd
= refstrdup(skipspace(p
+ 6));
667 } else if (looking_at(p
, "shiftkey")) {
669 } else if (looking_at(p
, "save")) {
675 } else if (looking_at(p
, "nosave")) {
680 } else if (looking_at(p
, "immediate")) {
685 } else if (looking_at(p
, "noimmediate")) {
689 m
->immediate
= false;
690 } else if (looking_at(p
, "onerror")) {
691 refstr_put(m
->onerror
);
692 m
->onerror
= refstrdup(skipspace(p
+ 7));
693 } else if (looking_at(p
, "master")) {
694 p
= skipspace(p
+ 6);
695 if (looking_at(p
, "passwd")) {
696 refstr_put(m
->menu_master_passwd
);
697 m
->menu_master_passwd
= refstrdup(skipspace(p
+ 6));
699 } else if ((ep
= looking_at(p
, "include"))) {
701 } else if ((ep
= looking_at(p
, "background"))) {
703 refstr_put(m
->menu_background
);
704 m
->menu_background
= refdup_word(&p
);
705 } else if ((ep
= looking_at(p
, "hidden"))) {
707 } else if ((ep
= looking_at(p
, "clear"))) {
709 } else if ((ep
= is_message_name(p
, &msgnr
))) {
710 refstr_put(m
->messages
[msgnr
]);
711 m
->messages
[msgnr
] = refstrdup(skipspace(ep
));
712 } else if ((ep
= looking_at(p
, "color")) ||
713 (ep
= looking_at(p
, "colour"))) {
715 struct color_table
*cptr
;
717 cptr
= m
->color_table
;
718 for (i
= 0; i
< menu_color_table_size
; i
++) {
719 if ((ep
= looking_at(p
, cptr
->name
))) {
722 if (looking_at(p
, "*")) {
725 refstr_put(cptr
->ansi
);
726 cptr
->ansi
= refdup_word(&p
);
731 if (looking_at(p
, "*"))
734 cptr
->argb_fg
= parse_argb(&p
);
738 if (looking_at(p
, "*"))
741 cptr
->argb_bg
= parse_argb(&p
);
743 /* Parse a shadow mode */
746 if (ch
== 'n') /* none */
747 cptr
->shadow
= SHADOW_NONE
;
748 else if (ch
== 's') /* std, standard */
749 cptr
->shadow
= SHADOW_NORMAL
;
750 else if (ch
== 'a') /* all */
751 cptr
->shadow
= SHADOW_ALL
;
752 else if (ch
== 'r') /* rev, reverse */
753 cptr
->shadow
= SHADOW_REVERSE
;
761 } else if ((ep
= looking_at(p
, "msgcolor")) ||
762 (ep
= looking_at(p
, "msgcolour"))) {
763 unsigned int fg_mask
= MSG_COLORS_DEF_FG
;
764 unsigned int bg_mask
= MSG_COLORS_DEF_BG
;
765 enum color_table_shadow shadow
= MSG_COLORS_DEF_SHADOW
;
769 if (!looking_at(p
, "*"))
770 fg_mask
= parse_argb(&p
);
774 if (!looking_at(p
, "*"))
775 bg_mask
= parse_argb(&p
);
780 shadow
= SHADOW_NONE
;
783 shadow
= SHADOW_NORMAL
;
789 shadow
= SHADOW_REVERSE
;
792 /* go with default */
797 set_msg_colors_global(m
->color_table
, fg_mask
, bg_mask
, shadow
);
798 } else if (looking_at(p
, "separator")) {
799 record(m
, &ld
, append
);
800 ld
.label
= refstr_get(empty_string
);
801 ld
.menuseparator
= 1;
802 record(m
, &ld
, append
);
803 } else if (looking_at(p
, "disable") || looking_at(p
, "disabled")) {
805 } else if (looking_at(p
, "indent")) {
806 ld
.menuindent
= atoi(skipspace(p
+ 6));
807 } else if (looking_at(p
, "begin")) {
808 record(m
, &ld
, append
);
809 m
= current_menu
= begin_submenu(skipspace(p
+ 5));
810 } else if (looking_at(p
, "end")) {
811 record(m
, &ld
, append
);
812 m
= current_menu
= end_submenu();
813 } else if (looking_at(p
, "quit")) {
816 } else if (looking_at(p
, "goto")) {
818 ld
.action
= MA_GOTO_UNRES
;
819 refstr_put(ld
.kernel
);
820 ld
.kernel
= refstrdup(skipspace(p
+ 4));
822 } else if (looking_at(p
, "exit")) {
823 p
= skipspace(p
+ 4);
824 if (ld
.label
&& m
->parent
) {
826 /* This is really just a goto, except for the marker */
827 ld
.action
= MA_EXIT_UNRES
;
828 refstr_put(ld
.kernel
);
829 ld
.kernel
= refstrdup(p
);
832 ld
.submenu
= m
->parent
;
835 } else if (looking_at(p
, "start")) {
837 } else if ((ep
= looking_at(p
, "resolution"))) {
839 x
= strtoul(ep
, &ep
, 0);
840 y
= strtoul(skipspace(ep
), NULL
, 0);
841 set_resolution(x
, y
);
843 /* Unknown, check for layout parameters */
844 enum parameter_number mp
;
845 for (mp
= 0; mp
< NPARAMS
; mp
++) {
846 if ((ep
= looking_at(p
, mparm
[mp
].name
))) {
847 m
->mparm
[mp
] = atoi(skipspace(ep
));
852 } else if (looking_at(p
, "text")) {
856 } cmd
= TEXT_UNKNOWN
;
857 int len
= ld
.helptext
? strlen(ld
.helptext
) : 0;
860 p
= skipspace(p
+ 4);
862 if (looking_at(p
, "help"))
865 while (fgets(line
, sizeof line
, f
)) {
867 if (looking_at(p
, "endtext"))
876 ld
.helptext
= realloc(ld
.helptext
, len
+ xlen
+ 1);
877 memcpy(ld
.helptext
+ len
, line
, xlen
+ 1);
882 } else if ((ep
= is_fkey(p
, &fkeyno
))) {
884 if (m
->fkeyhelp
[fkeyno
].textname
) {
885 refstr_put(m
->fkeyhelp
[fkeyno
].textname
);
886 m
->fkeyhelp
[fkeyno
].textname
= NULL
;
888 if (m
->fkeyhelp
[fkeyno
].background
) {
889 refstr_put(m
->fkeyhelp
[fkeyno
].background
);
890 m
->fkeyhelp
[fkeyno
].background
= NULL
;
893 refstr_put(m
->fkeyhelp
[fkeyno
].textname
);
894 m
->fkeyhelp
[fkeyno
].textname
= refdup_word(&p
);
897 m
->fkeyhelp
[fkeyno
].background
= refdup_word(&p
);
899 } else if ((ep
= looking_at(p
, "include"))) {
904 file
= refdup_word(&p
);
907 record(m
, &ld
, append
);
908 m
= current_menu
= begin_submenu(p
);
909 parse_one_config(file
);
910 record(m
, &ld
, append
);
911 m
= current_menu
= end_submenu();
913 parse_one_config(file
);
917 } else if (looking_at(p
, "append")) {
918 const char *a
= refstrdup(skipspace(p
+ 6));
920 refstr_put(ld
.append
);
926 } else if (looking_at(p
, "initrd")) {
927 const char *a
= refstrdup(skipspace(p
+ 6));
929 refstr_put(ld
.initrd
);
934 } else if (looking_at(p
, "label")) {
935 p
= skipspace(p
+ 5);
936 record(m
, &ld
, append
);
937 ld
.label
= refstrdup(p
);
938 ld
.kernel
= refstrdup(p
);
945 ld
.ipappend
= ipappend
;
946 ld
.menudefault
= ld
.menuhide
= ld
.menuseparator
=
947 ld
.menudisabled
= ld
.menuindent
= 0;
948 } else if ((ep
= is_kernel_type(p
, &type
))) {
950 refstr_put(ld
.kernel
);
951 ld
.kernel
= refstrdup(skipspace(ep
));
954 } else if (looking_at(p
, "timeout")) {
955 m
->timeout
= (atoi(skipspace(p
+ 7)) * CLK_TCK
+ 9) / 10;
956 } else if (looking_at(p
, "totaltimeout")) {
957 totaltimeout
= (atoll(skipspace(p
+ 13)) * CLK_TCK
+ 9) / 10;
958 } else if (looking_at(p
, "ontimeout")) {
959 m
->ontimeout
= refstrdup(skipspace(p
+ 9));
960 } else if (looking_at(p
, "allowoptions")) {
961 m
->allowedit
= !!atoi(skipspace(p
+ 12));
962 } else if (looking_at(p
, "ipappend")) {
964 ld
.ipappend
= atoi(skipspace(p
+ 8));
966 ipappend
= atoi(skipspace(p
+ 8));
967 } else if (looking_at(p
, "default")) {
968 refstr_put(globaldefault
);
969 globaldefault
= refstrdup(skipspace(p
+ 7));
970 } else if (looking_at(p
, "ui")) {
976 static int parse_one_config(const char *filename
)
980 if (!strcmp(filename
, "~"))
981 filename
= syslinux_config_file();
983 dprintf("Opening config file: %s ", filename
);
985 f
= fopen(filename
, "r");
986 dprintf("%s\n", f
? "ok" : "failed");
991 parse_config_file(f
);
997 static void resolve_gotos(void)
999 struct menu_entry
*me
;
1002 for (me
= all_entries
; me
; me
= me
->next
) {
1003 if (me
->action
== MA_GOTO_UNRES
|| me
->action
== MA_EXIT_UNRES
) {
1004 m
= find_menu(me
->cmdline
);
1005 refstr_put(me
->cmdline
);
1009 me
->action
--; /* Drop the _UNRES */
1011 me
->action
= MA_DISABLED
;
1017 void parse_configs(char **argv
)
1019 const char *filename
;
1021 struct menu_entry
*me
;
1023 empty_string
= refstrdup("");
1025 /* Initialize defaults for the root and hidden menus */
1026 hide_menu
= new_menu(NULL
, NULL
, refstrdup(".hidden"));
1027 root_menu
= new_menu(NULL
, NULL
, refstrdup(".top"));
1028 start_menu
= root_menu
;
1030 /* Other initialization */
1031 memset(&ld
, 0, sizeof(struct labeldata
));
1033 /* Actually process the files */
1034 current_menu
= root_menu
;
1036 parse_one_config("~");
1038 while ((filename
= *argv
++))
1039 parse_one_config(filename
);
1042 /* On final EOF process the last label statement */
1043 record(current_menu
, &ld
, append
);
1045 /* Common postprocessing */
1048 /* Handle global default */
1049 if (has_ui
&& globaldefault
) {
1050 me
= find_label(globaldefault
);
1051 if (me
&& me
->menu
!= hide_menu
) {
1052 me
->menu
->defentry
= me
->entry
;
1053 start_menu
= me
->menu
;
1057 /* If "menu save" is active, let the ADV override the global default */
1060 const char *lbl
= syslinux_getadv(ADV_MENUSAVE
, &len
);
1063 lstr
= refstr_alloc(len
);
1064 memcpy(lstr
, lbl
, len
); /* refstr_alloc() adds the final null */
1065 me
= find_label(lstr
);
1066 if (me
&& me
->menu
!= hide_menu
) {
1067 me
->menu
->defentry
= me
->entry
;
1068 start_menu
= me
->menu
;
1074 /* Final per-menu initialization, with all labels known */
1075 for (m
= menu_list
; m
; m
= m
->next
) {
1076 m
->curentry
= m
->defentry
; /* All menus start at their defaults */
1079 m
->ontimeout
= unlabel(m
->ontimeout
);
1081 m
->onerror
= unlabel(m
->onerror
);