]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/lib/syslinux_parse.c
44649d416503e44c9fa7d68e8223caff0cfaf3f6
[Ventoy.git] / GRUB2 / MOD_SRC / grub-2.04 / grub-core / lib / syslinux_parse.c
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2013 Free Software Foundation, Inc.
4 *
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <grub/mm.h>
20 #include <grub/file.h>
21 #include <grub/normal.h>
22 #include <grub/syslinux_parse.h>
23
24 struct syslinux_say
25 {
26 struct syslinux_say *next;
27 struct syslinux_say *prev;
28 char msg[0];
29 };
30
31 struct initrd_list
32 {
33 struct initrd_list *next;
34 char *file;
35 };
36
37 struct syslinux_menuentry
38 {
39 struct syslinux_menuentry *next;
40 struct syslinux_menuentry *prev;
41 char *label;
42 char *extlabel;
43 char *kernel_file;
44 struct initrd_list *initrds;
45 struct initrd_list *initrds_last;
46 char *append;
47 char *argument;
48 char *help;
49 char *comments;
50 grub_size_t commentslen;
51 char hotkey;
52 int make_default;
53 struct syslinux_say *say;
54
55 enum { KERNEL_NO_KERNEL, KERNEL_LINUX, KERNEL_CHAINLOADER,
56 KERNEL_BIN, KERNEL_PXE, KERNEL_CHAINLOADER_BPB,
57 KERNEL_COM32, KERNEL_COM, KERNEL_IMG, KERNEL_CONFIG, LOCALBOOT }
58 entry_type;
59 };
60
61 struct syslinux_menu
62 {
63 struct syslinux_menu *parent;
64 struct syslinux_menuentry *entries;
65 char *def;
66 char *comments;
67 char *background;
68 const char *root_read_directory;
69 const char *root_target_directory;
70 const char *current_read_directory;
71 const char *current_target_directory;
72 const char *filename;
73 grub_size_t commentslen;
74 unsigned long timeout;
75 struct syslinux_say *say;
76 grub_syslinux_flavour_t flavour;
77 };
78
79 struct output_buffer
80 {
81 grub_size_t alloc;
82 grub_size_t ptr;
83 char *buf;
84 };
85
86 static grub_err_t
87 syslinux_parse_real (struct syslinux_menu *menu);
88 static grub_err_t
89 config_file (struct output_buffer *outbuf,
90 const char *root, const char *target_root,
91 const char *cwd, const char *target_cwd,
92 const char *fname, struct syslinux_menu *parent,
93 grub_syslinux_flavour_t flav);
94 static grub_err_t
95 print_entry (struct output_buffer *outbuf,
96 struct syslinux_menu *menu,
97 const char *str);
98
99 static grub_err_t
100 ensure_space (struct output_buffer *outbuf, grub_size_t len)
101 {
102 grub_size_t newlen;
103 char *newbuf;
104 if (len < outbuf->alloc - outbuf->ptr)
105 return GRUB_ERR_NONE;
106 newlen = (outbuf->ptr + len + 10) * 2;
107 newbuf = grub_realloc (outbuf->buf, newlen);
108 if (!newbuf)
109 return grub_errno;
110 outbuf->alloc = newlen;
111 outbuf->buf = newbuf;
112 return GRUB_ERR_NONE;
113 }
114
115 static grub_err_t
116 print (struct output_buffer *outbuf, const char *str, grub_size_t len)
117 {
118 grub_err_t err;
119 err = ensure_space (outbuf, len);
120 if (err)
121 return err;
122 grub_memcpy (&outbuf->buf[outbuf->ptr], str, len);
123 outbuf->ptr += len;
124 return GRUB_ERR_NONE;
125 }
126
127 static grub_err_t
128 add_comment (struct syslinux_menu *menu, const char *comment, int nl)
129 {
130 if (menu->entries)
131 {
132 if (menu->entries->commentslen == 0 && *comment == 0)
133 return GRUB_ERR_NONE;
134 menu->entries->comments = grub_realloc (menu->entries->comments,
135 menu->entries->commentslen
136 + 2 + grub_strlen (comment));
137 if (!menu->entries->comments)
138 return grub_errno;
139 menu->entries->commentslen
140 += grub_stpcpy (menu->entries->comments + menu->entries->commentslen,
141 comment)
142 - (menu->entries->comments + menu->entries->commentslen);
143 if (nl)
144 menu->entries->comments[menu->entries->commentslen++] = '\n';
145 menu->entries->comments[menu->entries->commentslen] = '\0';
146 }
147 else
148 {
149 if (menu->commentslen == 0 && *comment == 0)
150 return GRUB_ERR_NONE;
151 menu->comments = grub_realloc (menu->comments, menu->commentslen
152 + 2 + grub_strlen (comment));
153 if (!menu->comments)
154 return grub_errno;
155 menu->commentslen += grub_stpcpy (menu->comments + menu->commentslen,
156 comment)
157 - (menu->comments + menu->commentslen);
158 if (nl)
159 menu->comments[menu->commentslen++] = '\n';
160 menu->comments[menu->commentslen] = '\0';
161 }
162 return GRUB_ERR_NONE;
163 }
164
165
166 #define print_string(x) do { err = print (outbuf, x, sizeof (x) - 1); if (err) return err; } while (0)
167
168 static grub_err_t
169 print_num (struct output_buffer *outbuf, int n)
170 {
171 char buf[20];
172 grub_snprintf (buf, sizeof (buf), "%d", n);
173 return print (outbuf, buf, grub_strlen (buf));
174 }
175
176 static grub_err_t
177 label (const char *line, struct syslinux_menu *menu)
178 {
179 struct syslinux_menuentry *entry;
180
181 entry = grub_malloc (sizeof (*entry));
182 if (!entry)
183 return grub_errno;
184 grub_memset (entry, 0, sizeof (*entry));
185 entry->label = grub_strdup (line);
186 if (!entry->label)
187 {
188 grub_free (entry);
189 return grub_errno;
190 }
191 entry->next = menu->entries;
192 entry->prev = NULL;
193 if (menu->entries)
194 menu->entries->prev = entry;
195 menu->entries = entry;
196 return GRUB_ERR_NONE;
197 }
198
199 static grub_err_t
200 kernel (const char *line, struct syslinux_menu *menu)
201 {
202 const char *end = line + grub_strlen (line);
203
204 if (!menu->entries)
205 return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
206
207 menu->entries->kernel_file = grub_strdup (line);
208 if (!menu->entries->kernel_file)
209 return grub_errno;
210
211 menu->entries->entry_type = KERNEL_LINUX;
212
213 if (end - line >= 2 && grub_strcmp (end - 2, ".0") == 0)
214 menu->entries->entry_type = KERNEL_PXE;
215
216 if (end - line >= 4 && grub_strcasecmp (end - 4, ".bin") == 0)
217 menu->entries->entry_type = KERNEL_BIN;
218
219 if (end - line >= 3 && grub_strcasecmp (end - 3, ".bs") == 0)
220 menu->entries->entry_type = KERNEL_CHAINLOADER;
221
222 if (end - line >= 4 && grub_strcasecmp (end - 4, ".bss") == 0)
223 menu->entries->entry_type = KERNEL_CHAINLOADER_BPB;
224
225 if (end - line >= 4 && grub_strcasecmp (end - 4, ".c32") == 0)
226 menu->entries->entry_type = KERNEL_COM32;
227
228 if (end - line >= 4 && grub_strcasecmp (end - 4, ".cbt") == 0)
229 menu->entries->entry_type = KERNEL_COM;
230
231 if (end - line >= 4 && grub_strcasecmp (end - 4, ".com") == 0)
232 menu->entries->entry_type = KERNEL_COM;
233
234 if (end - line >= 4 && grub_strcasecmp (end - 4, ".img") == 0)
235 menu->entries->entry_type = KERNEL_IMG;
236
237 return GRUB_ERR_NONE;
238 }
239
240 static grub_err_t
241 cmd_linux (const char *line, struct syslinux_menu *menu)
242 {
243 if (!menu->entries)
244 return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
245
246 menu->entries->kernel_file = grub_strdup (line);
247 if (!menu->entries->kernel_file)
248 return grub_errno;
249 menu->entries->entry_type = KERNEL_LINUX;
250
251 return GRUB_ERR_NONE;
252 }
253
254 static grub_err_t
255 cmd_boot (const char *line, struct syslinux_menu *menu)
256 {
257 if (!menu->entries)
258 return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
259
260 menu->entries->kernel_file = grub_strdup (line);
261 if (!menu->entries->kernel_file)
262 return grub_errno;
263 menu->entries->entry_type = KERNEL_CHAINLOADER;
264
265 return GRUB_ERR_NONE;
266 }
267
268 static grub_err_t
269 cmd_bss (const char *line, struct syslinux_menu *menu)
270 {
271 if (!menu->entries)
272 return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
273
274 menu->entries->kernel_file = grub_strdup (line);
275 if (!menu->entries->kernel_file)
276 return grub_errno;
277 menu->entries->entry_type = KERNEL_CHAINLOADER_BPB;
278
279 return GRUB_ERR_NONE;
280 }
281
282 static grub_err_t
283 cmd_pxe (const char *line, struct syslinux_menu *menu)
284 {
285 if (!menu->entries)
286 return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
287
288 menu->entries->kernel_file = grub_strdup (line);
289 if (!menu->entries->kernel_file)
290 return grub_errno;
291 menu->entries->entry_type = KERNEL_PXE;
292
293 return GRUB_ERR_NONE;
294 }
295
296 static grub_err_t
297 cmd_fdimage (const char *line, struct syslinux_menu *menu)
298 {
299 if (!menu->entries)
300 return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
301
302 menu->entries->kernel_file = grub_strdup (line);
303 if (!menu->entries->kernel_file)
304 return grub_errno;
305 menu->entries->entry_type = KERNEL_IMG;
306
307 return GRUB_ERR_NONE;
308 }
309
310 static grub_err_t
311 cmd_comboot (const char *line, struct syslinux_menu *menu)
312 {
313 if (!menu->entries)
314 return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
315
316 menu->entries->kernel_file = grub_strdup (line);
317 if (!menu->entries->kernel_file)
318 return grub_errno;
319 menu->entries->entry_type = KERNEL_COM;
320
321 return GRUB_ERR_NONE;
322 }
323
324 static grub_err_t
325 cmd_com32 (const char *line, struct syslinux_menu *menu)
326 {
327 if (!menu->entries)
328 return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
329
330 menu->entries->kernel_file = grub_strdup (line);
331 if (!menu->entries->kernel_file)
332 return grub_errno;
333 menu->entries->entry_type = KERNEL_COM32;
334
335 return GRUB_ERR_NONE;
336 }
337
338 static grub_err_t
339 cmd_config (const char *line, struct syslinux_menu *menu)
340 {
341 const char *space;
342 if (!menu->entries)
343 return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
344
345 for (space = line; *space && !grub_isspace (*space); space++);
346 menu->entries->kernel_file = grub_strndup (line, space - line);
347 if (!menu->entries->kernel_file)
348 return grub_errno;
349 for (; *space && grub_isspace (*space); space++);
350 if (*space)
351 {
352 menu->entries->argument = grub_strdup (space);
353 if (!menu->entries->argument)
354 return grub_errno;
355 }
356 menu->entries->entry_type = KERNEL_CONFIG;
357
358 return GRUB_ERR_NONE;
359 }
360
361 static grub_err_t
362 cmd_append (const char *line, struct syslinux_menu *menu)
363 {
364 if (!menu->entries)
365 return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
366
367 menu->entries->append = grub_strdup (line);
368 if (!menu->entries->append)
369 return grub_errno;
370
371 return GRUB_ERR_NONE;
372 }
373
374 static grub_err_t
375 cmd_initrd (const char *line, struct syslinux_menu *menu)
376 {
377 struct initrd_list *ninitrd;
378 const char *comma;
379 if (!menu->entries)
380 return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
381
382 while (*line)
383 {
384 for (comma = line; *comma && *comma != ','; comma++);
385
386 ninitrd = grub_malloc (sizeof (*ninitrd));
387 if (!ninitrd)
388 return grub_errno;
389 ninitrd->file = grub_strndup (line, comma - line);
390 if (!ninitrd->file)
391 {
392 grub_free (ninitrd);
393 return grub_errno;
394 }
395 ninitrd->next = NULL;
396 if (menu->entries->initrds_last)
397 menu->entries->initrds_last->next = ninitrd;
398 else
399 {
400 menu->entries->initrds_last = ninitrd;
401 menu->entries->initrds = ninitrd;
402 }
403
404 line = comma;
405 while (*line == ',')
406 line++;
407 }
408
409 return GRUB_ERR_NONE;
410 }
411
412 static grub_err_t
413 cmd_default (const char *line, struct syslinux_menu *menu)
414 {
415 menu->def = grub_strdup (line);
416 if (!menu->def)
417 return grub_errno;
418
419 return GRUB_ERR_NONE;
420 }
421
422 static grub_err_t
423 cmd_timeout (const char *line, struct syslinux_menu *menu)
424 {
425 menu->timeout = grub_strtoul (line, NULL, 0);
426 return GRUB_ERR_NONE;
427 }
428
429 static grub_err_t
430 cmd_menudefault (const char *line __attribute__ ((unused)),
431 struct syslinux_menu *menu)
432 {
433 if (!menu->entries)
434 return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
435
436 menu->entries->make_default = 1;
437 return GRUB_ERR_NONE;
438 }
439
440 static grub_err_t
441 cmd_menubackground (const char *line,
442 struct syslinux_menu *menu)
443 {
444 menu->background = grub_strdup (line);
445 return GRUB_ERR_NONE;
446 }
447
448 static grub_err_t
449 cmd_localboot (const char *line,
450 struct syslinux_menu *menu)
451 {
452 if (!menu->entries)
453 return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
454
455 menu->entries->kernel_file = grub_strdup (line);
456 if (!menu->entries->kernel_file)
457 return grub_errno;
458 menu->entries->entry_type = LOCALBOOT;
459
460 return GRUB_ERR_NONE;
461 }
462
463 static grub_err_t
464 cmd_extlabel (const char *line, struct syslinux_menu *menu)
465 {
466 const char *in;
467 char *out;
468
469 if (!menu->entries)
470 return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
471
472 menu->entries->extlabel = grub_malloc (grub_strlen (line) + 1);
473 if (!menu->entries->extlabel)
474 return grub_errno;
475 in = line;
476 out = menu->entries->extlabel;
477 while (*in)
478 {
479 if (in[0] == '^' && in[1])
480 {
481 menu->entries->hotkey = grub_tolower (in[1]);
482 in++;
483 }
484 *out++ = *in++;
485 }
486 *out = 0;
487
488 return GRUB_ERR_NONE;
489 }
490
491
492 static grub_err_t
493 cmd_say (const char *line, struct syslinux_menu *menu)
494 {
495 struct syslinux_say *nsay;
496 nsay = grub_malloc (sizeof (*nsay) + grub_strlen (line) + 1);
497 if (!nsay)
498 return grub_errno;
499 nsay->prev = NULL;
500 if (menu->entries)
501 {
502 nsay->next = menu->entries->say;
503 menu->entries->say = nsay;
504 }
505 else
506 {
507 nsay->next = menu->say;
508 menu->say = nsay;
509 }
510
511 if (nsay->next)
512 nsay->next->prev = nsay;
513
514 grub_memcpy (nsay->msg, line, grub_strlen (line) + 1);
515 return GRUB_ERR_NONE;
516 }
517
518 static char *
519 get_read_filename (struct syslinux_menu *menu,
520 const char *filename)
521 {
522 return grub_xasprintf ("%s/%s",
523 filename[0] == '/' ? menu->root_read_directory
524 : menu->current_read_directory, filename);
525 }
526
527 static char *
528 get_target_filename (struct syslinux_menu *menu,
529 const char *filename)
530 {
531 return grub_xasprintf ("%s/%s",
532 filename[0] == '/' ? menu->root_target_directory
533 : menu->current_target_directory, filename);
534 }
535
536 static grub_err_t
537 syslinux_parse (const char *filename,
538 struct syslinux_menu *menu)
539 {
540 const char *old_filename = menu->filename;
541 grub_err_t ret;
542 char *nf;
543 nf = get_read_filename (menu, filename);
544 if (!nf)
545 return grub_errno;
546 menu->filename = nf;
547 ret = syslinux_parse_real (menu);
548 if (ret == GRUB_ERR_FILE_NOT_FOUND
549 || ret == GRUB_ERR_BAD_FILENAME)
550 {
551 grub_errno = ret = GRUB_ERR_NONE;
552 add_comment (menu, "# File ", 0);
553 add_comment (menu, nf, 0);
554 add_comment (menu, " not found", 1);
555 }
556 grub_free (nf);
557 menu->filename = old_filename;
558 return ret;
559 }
560
561 struct
562 {
563 const char *name1;
564 const char *name2;
565 grub_err_t (*parse) (const char *line, struct syslinux_menu *menu);
566 } commands[] = {
567 /* FIXME: support tagname. */
568 {"include", NULL, syslinux_parse},
569 {"menu", "include", syslinux_parse},
570 {"label", NULL, label},
571 {"kernel", NULL, kernel},
572 {"linux", NULL, cmd_linux},
573 {"boot", NULL, cmd_boot},
574 {"bss", NULL, cmd_bss},
575 {"pxe", NULL, cmd_pxe},
576 {"fdimage", NULL, cmd_fdimage},
577 {"comboot", NULL, cmd_comboot},
578 {"com32", NULL, cmd_com32},
579 {"config", NULL, cmd_config},
580 {"append", NULL, cmd_append},
581 /* FIXME: ipappend not supported. */
582 {"localboot", NULL, cmd_localboot},
583 {"initrd", NULL, cmd_initrd},
584 {"default", NULL, cmd_default},
585 {"menu", "label", cmd_extlabel},
586 /* FIXME: MENU LABEL not supported. */
587 /* FIXME: MENU HIDDEN not supported. */
588 /* FIXME: MENU SEPARATOR not supported. */
589 /* FIXME: MENU INDENT not supported. */
590 /* FIXME: MENU DISABLE not supported. */
591 /* FIXME: MENU HIDE not supported. */
592 {"menu", "default", cmd_menudefault},
593 /* FIXME: MENU PASSWD not supported. */
594 /* FIXME: MENU MASTER PASSWD not supported. */
595 {"menu", "background", cmd_menubackground},
596 /* FIXME: MENU BEGIN not supported. */
597 /* FIXME: MENU GOTO not supported. */
598 /* FIXME: MENU EXIT not supported. */
599 /* FIXME: MENU QUIT not supported. */
600 /* FIXME: MENU START not supported. */
601 /* FIXME: MENU AUTOBOOT not supported. */
602 /* FIXME: MENU TABMSG not supported. */
603 /* FIXME: MENU NOTABMSG not supported. */
604 /* FIXME: MENU PASSPROMPT not supported. */
605 /* FIXME: MENU COLOR not supported. */
606 /* FIXME: MENU MSGCOLOR not supported. */
607 /* FIXME: MENU WIDTH not supported. */
608 /* FIXME: MENU MARGIN not supported. */
609 /* FIXME: MENU PASSWORDMARGIN not supported. */
610 /* FIXME: MENU ROWS not supported. */
611 /* FIXME: MENU TABMSGROW not supported. */
612 /* FIXME: MENU CMDLINEROW not supported. */
613 /* FIXME: MENU ENDROW not supported. */
614 /* FIXME: MENU PASSWORDROW not supported. */
615 /* FIXME: MENU TIMEOUTROW not supported. */
616 /* FIXME: MENU HELPMSGROW not supported. */
617 /* FIXME: MENU HELPMSGENDROW not supported. */
618 /* FIXME: MENU HIDDENROW not supported. */
619 /* FIXME: MENU HSHIFT not supported. */
620 /* FIXME: MENU VSHIFT not supported. */
621 {"timeout", NULL, cmd_timeout},
622 /* FIXME: TOTALTIMEOUT not supported. */
623 /* FIXME: ONTIMEOUT not supported. */
624 /* FIXME: ONERROR not supported. */
625 /* FIXME: SERIAL not supported. */
626 /* FIXME: CONSOLE not supported. */
627 /* FIXME: FONT not supported. */
628 /* FIXME: KBDMAP not supported. */
629 {"say", NULL, cmd_say},
630 /* FIXME: DISPLAY not supported. */
631 /* FIXME: F* not supported. */
632
633 /* Commands to control interface behaviour which aren't needed with GRUB.
634 If they are important in your environment please contact GRUB team.
635 */
636 {"prompt", NULL, NULL},
637 {"nocomplete", NULL, NULL},
638 {"noescape", NULL, NULL},
639 {"implicit", NULL, NULL},
640 {"allowoptions", NULL, NULL}
641 };
642
643 static grub_err_t
644 helptext (const char *line, grub_file_t file, struct syslinux_menu *menu)
645 {
646 char *help;
647 char *buf = NULL;
648 grub_size_t helplen, alloclen = 0;
649
650 help = grub_strdup (line);
651 if (!help)
652 return grub_errno;
653 helplen = grub_strlen (line);
654 while ((grub_free (buf), buf = grub_file_getline (file)))
655 {
656 char *ptr;
657 grub_size_t needlen;
658 for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++);
659 if (grub_strncasecmp (ptr, "endtext", sizeof ("endtext") - 1) == 0)
660 {
661 ptr += sizeof ("endtext") - 1;
662 for (; *ptr && (grub_isspace (*ptr) || *ptr == '\n' || *ptr == '\r');
663 ptr++);
664 if (!*ptr)
665 {
666 menu->entries->help = help;
667 grub_free (buf);
668 return GRUB_ERR_NONE;
669 }
670 }
671 needlen = helplen + 1 + grub_strlen (buf);
672 if (alloclen < needlen)
673 {
674 alloclen = 2 * needlen;
675 help = grub_realloc (help, alloclen);
676 if (!help)
677 {
678 grub_free (buf);
679 return grub_errno;
680 }
681 }
682 helplen += grub_stpcpy (help + helplen, buf) - (help + helplen);
683 }
684
685 grub_free (buf);
686 grub_free (help);
687 return grub_errno;
688 }
689
690
691 static grub_err_t
692 syslinux_parse_real (struct syslinux_menu *menu)
693 {
694 grub_file_t file;
695 char *buf = NULL;
696 grub_err_t err = GRUB_ERR_NONE;
697
698 file = grub_file_open (menu->filename, GRUB_FILE_TYPE_CONFIG);
699 if (!file)
700 return grub_errno;
701 while ((grub_free (buf), buf = grub_file_getline (file)))
702 {
703 const char *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
704 char *end;
705 unsigned i;
706 end = buf + grub_strlen (buf);
707 while (end > buf && (end[-1] == '\n' || end[-1] == '\r'))
708 end--;
709 *end = 0;
710 for (ptr1 = buf; *ptr1 && grub_isspace (*ptr1); ptr1++);
711 if (*ptr1 == '#' || *ptr1 == 0)
712 {
713 err = add_comment (menu, ptr1, 1);
714 if (err)
715 goto fail;
716 continue;
717 }
718 for (ptr2 = ptr1; !grub_isspace (*ptr2) && *ptr2; ptr2++);
719 for (ptr3 = ptr2; grub_isspace (*ptr3) && *ptr3; ptr3++);
720 for (ptr4 = ptr3; !grub_isspace (*ptr4) && *ptr4; ptr4++);
721 for (ptr5 = ptr4; grub_isspace (*ptr5) && *ptr5; ptr5++);
722 for (i = 0; i < ARRAY_SIZE(commands); i++)
723 if (grub_strlen (commands[i].name1) == (grub_size_t) (ptr2 - ptr1)
724 && grub_strncasecmp (commands[i].name1, ptr1, ptr2 - ptr1) == 0
725 && (commands[i].name2 == NULL
726 || (grub_strlen (commands[i].name2)
727 == (grub_size_t) (ptr4 - ptr3)
728 && grub_strncasecmp (commands[i].name2, ptr3, ptr4 - ptr3)
729 == 0)))
730 break;
731 if (i == ARRAY_SIZE(commands))
732 {
733 if (sizeof ("text") - 1 == ptr2 - ptr1
734 && grub_strncasecmp ("text", ptr1, ptr2 - ptr1) == 0
735 && (sizeof ("help") - 1 == ptr4 - ptr3
736 && grub_strncasecmp ("help", ptr3, ptr4 - ptr3) == 0))
737 {
738 if (helptext (ptr5, file, menu))
739 return 1;
740 continue;
741 }
742
743 add_comment (menu, " # UNSUPPORTED command '", 0);
744 add_comment (menu, ptr1, 0);
745 add_comment (menu, "'", 1);
746
747 continue;
748 }
749 if (commands[i].parse)
750 {
751 err = commands[i].parse (commands[i].name2
752 ? ptr5 : ptr3, menu);
753 if (err)
754 goto fail;
755 }
756 }
757 fail:
758 grub_file_close (file);
759 return err;
760 }
761
762 static grub_err_t
763 print_escaped (struct output_buffer *outbuf,
764 const char *from, const char *to)
765 {
766 const char *ptr;
767 grub_err_t err;
768 if (!to)
769 to = from + grub_strlen (from);
770 err = ensure_space (outbuf, (to - from) * 4 + 2);
771 if (err)
772 return err;
773 outbuf->buf[outbuf->ptr++] = '\'';
774 for (ptr = from; *ptr && ptr < to; ptr++)
775 {
776 if (*ptr == '\'')
777 {
778 outbuf->buf[outbuf->ptr++] = '\'';
779 outbuf->buf[outbuf->ptr++] = '\\';
780 outbuf->buf[outbuf->ptr++] = '\'';
781 outbuf->buf[outbuf->ptr++] = '\'';
782 }
783 else
784 outbuf->buf[outbuf->ptr++] = *ptr;
785 }
786 outbuf->buf[outbuf->ptr++] = '\'';
787 return GRUB_ERR_NONE;
788 }
789
790 static grub_err_t
791 print_file (struct output_buffer *outbuf,
792 struct syslinux_menu *menu, const char *from, const char *to)
793 {
794 grub_err_t err;
795 if (!to)
796 to = from + grub_strlen (from);
797 err = print_escaped (outbuf, from[0] == '/'
798 ? menu->root_target_directory
799 : menu->current_target_directory, NULL);
800 if (err)
801 return err;
802
803 err = print (outbuf, "/", 1);
804 if (err)
805 return err;
806 return print_escaped (outbuf, from, to);
807 }
808
809 /*
810 * Makefile.am mimics this when generating tests/syslinux/ubuntu10.04_grub.cfg,
811 * so changes here may need to be reflected there too.
812 */
813 static void
814 simplify_filename (char *str)
815 {
816 char *iptr, *optr = str;
817 for (iptr = str; *iptr; iptr++)
818 {
819 if (*iptr == '/' && optr != str && optr[-1] == '/')
820 continue;
821 if (iptr[0] == '/' && iptr[1] == '.' && iptr[2] == '/')
822 {
823 iptr += 2;
824 continue;
825 }
826 if (iptr[0] == '/' && iptr[1] == '.' && iptr[2] == '.'
827 && iptr[3] == '/')
828 {
829 iptr += 3;
830 while (optr >= str && *optr != '/')
831 optr--;
832 if (optr < str)
833 {
834 str[0] = '/';
835 optr = str;
836 }
837 optr++;
838 continue;
839 }
840 *optr++ = *iptr;
841 }
842 *optr = '\0';
843 }
844
845 static grub_err_t
846 print_config (struct output_buffer *outbuf,
847 struct syslinux_menu *menu,
848 const char *filename, const char *basedir)
849 {
850 struct syslinux_menu *menuptr;
851 grub_err_t err = GRUB_ERR_NONE;
852 char *new_cwd = NULL;
853 char *new_target_cwd = NULL;
854 char *newname = NULL;
855 int depth = 0;
856
857 new_cwd = get_read_filename (menu, basedir);
858 if (!new_cwd)
859 {
860 err = grub_errno;
861 goto out;
862 }
863 new_target_cwd = get_target_filename (menu, basedir);
864 if (!new_target_cwd)
865 {
866 err = grub_errno;
867 goto out;
868 }
869 newname = get_read_filename (menu, filename);
870 if (!newname)
871 {
872 err = grub_errno;
873 goto out;
874 }
875 simplify_filename (newname);
876
877 print_string ("#");
878 print_file (outbuf, menu, filename, NULL);
879 print_string (" ");
880 err = print (outbuf, newname, grub_strlen (newname));
881 if (err)
882 return err;
883 print_string (":\n");
884
885 for (menuptr = menu; menuptr; menuptr = menuptr->parent, depth++)
886 if (grub_strcmp (menuptr->filename, newname) == 0
887 || depth > 20)
888 break;
889 if (menuptr)
890 {
891 print_string (" syslinux_configfile -r ");
892 print_file (outbuf, menu, "/", NULL);
893 print_string (" -c ");
894 print_file (outbuf, menu, basedir, NULL);
895 print_string (" ");
896 print_file (outbuf, menu, filename, NULL);
897 print_string ("\n");
898 }
899 else
900 {
901 err = config_file (outbuf, menu->root_read_directory,
902 menu->root_target_directory, new_cwd, new_target_cwd,
903 newname, menu, menu->flavour);
904 if (err == GRUB_ERR_FILE_NOT_FOUND
905 || err == GRUB_ERR_BAD_FILENAME)
906 {
907 grub_errno = err = GRUB_ERR_NONE;
908 print_string ("# File ");
909 err = print (outbuf, newname, grub_strlen (newname));
910 if (err)
911 goto out;
912 print_string (" not found\n");
913 }
914 }
915
916 out:
917 grub_free (newname);
918 grub_free (new_cwd);
919 grub_free (new_target_cwd);
920 return err;
921 }
922
923 static grub_err_t
924 write_entry (struct output_buffer *outbuf,
925 struct syslinux_menu *menu,
926 struct syslinux_menuentry *curentry)
927 {
928 grub_err_t err;
929 if (curentry->comments)
930 {
931 err = print (outbuf, curentry->comments,
932 grub_strlen (curentry->comments));
933 if (err)
934 return err;
935 }
936 {
937 struct syslinux_say *say;
938 for (say = curentry->say; say && say->next; say = say->next);
939 for (; say && say->prev; say = say->prev)
940 {
941 print_string ("echo ");
942 if (print_escaped (outbuf, say->msg, NULL)) return grub_errno;
943 print_string ("\n");
944 }
945 }
946
947 /* FIXME: support help text. */
948 switch (curentry->entry_type)
949 {
950 case KERNEL_LINUX:
951 {
952 const char *ptr;
953 const char *initrd = NULL, *initrde= NULL;
954 for (ptr = curentry->append; ptr && *ptr; ptr++)
955 if ((ptr == curentry->append || grub_isspace (ptr[-1]))
956 && grub_strncasecmp (ptr, "initrd=", sizeof ("initrd=") - 1)
957 == 0)
958 break;
959 if (ptr && *ptr)
960 {
961 initrd = ptr + sizeof ("initrd=") - 1;
962 for (initrde = initrd; *initrde && !grub_isspace (*initrde); initrde++);
963 }
964 print_string (" if test x$ventoy_linux_16 = x1; then "
965 "linux_suffix=16; else linux_suffix= ; fi\n");
966 print_string (" linux$linux_suffix ");
967 print_file (outbuf, menu, curentry->kernel_file, NULL);
968 print_string (" ");
969 if (curentry->append)
970 {
971 err = print (outbuf, curentry->append, grub_strlen (curentry->append));
972 if (err)
973 return err;
974 }
975 print_string ("\n");
976 if (initrd || curentry->initrds)
977 {
978 struct initrd_list *lst;
979 print_string (" initrd$linux_suffix ");
980 if (initrd)
981 {
982 print_file (outbuf, menu, initrd, initrde);
983 print_string (" ");
984 }
985 for (lst = curentry->initrds; lst; lst = lst->next)
986 {
987 print_file (outbuf, menu, lst->file, NULL);
988 print_string (" ");
989 }
990
991 print_string ("\n");
992 }
993 print_string ("boot\n");
994 }
995 break;
996 case KERNEL_CHAINLOADER:
997 print_string (" chainloader ");
998 print_file (outbuf, menu, curentry->kernel_file, NULL);
999 print_string ("\n");
1000 break;
1001 case KERNEL_CHAINLOADER_BPB:
1002 print_string (" chainloader --bpb ");
1003 print_file (outbuf, menu, curentry->kernel_file, NULL);
1004 print_string ("\n");
1005 break;
1006 case LOCALBOOT:
1007 /* FIXME: support -1. */
1008 /* FIXME: PXELINUX. */
1009 {
1010 int n = grub_strtol (curentry->kernel_file, NULL, 0);
1011 if (n >= 0 && n <= 0x02)
1012 {
1013 print_string (" root=fd");
1014 if (print_num (outbuf, n))
1015 return grub_errno;
1016 print_string (";\n chainloader +1;\n");
1017
1018 break;
1019 }
1020 if (n >= 0x80 && n < 0x8a)
1021 {
1022 print_string (" root=hd");
1023 if (print_num (outbuf, n - 0x80))
1024 return grub_errno;
1025 print_string (";\n chainloader +1;\n");
1026 break;
1027 }
1028 print_string (" # UNSUPPORTED localboot type ");
1029 print_string ("\ntrue;\n");
1030 if (print_num (outbuf, n))
1031 return grub_errno;
1032 print_string ("\n");
1033 break;
1034 }
1035 case KERNEL_COM32:
1036 case KERNEL_COM:
1037 {
1038 char *basename = NULL;
1039
1040 {
1041 char *ptr;
1042 for (ptr = curentry->kernel_file; *ptr; ptr++)
1043 if (*ptr == '/' || *ptr == '\\')
1044 basename = ptr;
1045 }
1046 if (!basename)
1047 basename = curentry->kernel_file;
1048 else
1049 basename++;
1050 if (grub_strcasecmp (basename, "chain.c32") == 0)
1051 {
1052 char *file = NULL;
1053 int is_fd = -1, devn = 0;
1054 int part = -1;
1055 int swap = 0;
1056 char *ptr;
1057 for (ptr = curentry->append; *ptr; )
1058 {
1059 while (grub_isspace (*ptr))
1060 ptr++;
1061 /* FIXME: support mbr: and boot. */
1062 if (ptr[0] == 'h' && ptr[1] == 'd')
1063 {
1064 is_fd = 0;
1065 devn = grub_strtoul (ptr + 2, &ptr, 0);
1066 continue;
1067 }
1068 if (grub_strncasecmp (ptr, "file=", 5) == 0)
1069 {
1070 file = ptr + 5;
1071 for (ptr = file; *ptr && !grub_isspace (*ptr); ptr++);
1072 if (*ptr)
1073 {
1074 *ptr = 0;
1075 ptr++;
1076 }
1077 continue;
1078 }
1079 if (grub_strncasecmp (ptr, "swap", sizeof ("swap") - 1) == 0)
1080 {
1081 swap = 1;
1082 ptr += sizeof ("swap") - 1;
1083 continue;
1084 }
1085
1086 if (ptr[0] == 'f' && ptr[1] == 'd')
1087 {
1088 is_fd = 1;
1089 devn = grub_strtoul (ptr + 2, &ptr, 0);
1090 continue;
1091 }
1092 if (grub_isdigit (ptr[0]))
1093 {
1094 part = grub_strtoul (ptr, &ptr, 0);
1095 continue;
1096 }
1097 /* FIXME: isolinux, ntldr, cmldr, *dos, seg, hide
1098 FIXME: sethidden. */
1099 print_string (" # UNSUPPORTED option ");
1100 if (print (outbuf, ptr, grub_strlen (ptr)))
1101 return 0;
1102 print_string ("\n");
1103 break;
1104 }
1105 if (is_fd == -1)
1106 {
1107 print_string (" # no drive specified\n");
1108 break;
1109 }
1110 if (!*ptr)
1111 {
1112 print_string (is_fd ? " root=fd": " root=hd");
1113 if (print_num (outbuf, devn))
1114 return grub_errno;
1115 if (part != -1)
1116 {
1117 print_string (",");
1118 if (print_num (outbuf, part + 1))
1119 return grub_errno;
1120 }
1121 print_string (";\n");
1122 if (file)
1123 {
1124 print_string (" chainloader ");
1125 print_file (outbuf, menu, file, NULL);
1126 print_string (";\n");
1127 }
1128 else
1129 print_string (" chainloader +1;\n");
1130 if (swap)
1131 print_string (" drivemap -s hd0 \"root\";\n");
1132 }
1133 break;
1134 }
1135
1136 if (grub_strcasecmp (basename, "mboot.c32") == 0)
1137 {
1138 char *ptr;
1139 int first = 1;
1140 int is_kernel = 1;
1141 for (ptr = curentry->append; *ptr; )
1142 {
1143 char *ptrr = ptr;
1144 while (*ptr && !grub_isspace (*ptr))
1145 ptr++;
1146 if (ptrr + 2 == ptr && ptrr[0] == '-' && ptrr[1] == '-')
1147 {
1148 print_string ("\n");
1149 first = 1;
1150 continue;
1151 }
1152 if (first)
1153 {
1154 if (is_kernel)
1155 print_string (" multiboot ");
1156 else
1157 print_string (" module ");
1158 first = 0;
1159 is_kernel = 0;
1160 if (print_file (outbuf, menu, ptrr, ptr))
1161 return grub_errno;
1162 continue;
1163 }
1164 if (print_escaped (outbuf, ptrr, ptr))
1165 return grub_errno;
1166 }
1167 break;
1168 }
1169
1170 if (grub_strcasecmp (basename, "ifcpu64.c32") == 0)
1171 {
1172 char *lm, *lme, *pae = 0, *paee = 0, *i386s = 0, *i386e = 0;
1173 char *ptr;
1174 ptr = curentry->append;
1175 while (grub_isspace (*ptr))
1176 ptr++;
1177 lm = ptr;
1178 while (*ptr && !grub_isspace (*ptr))
1179 ptr++;
1180 lme = ptr;
1181 while (grub_isspace (*ptr))
1182 ptr++;
1183 if (ptr[0] == '-' && ptr[1] == '-')
1184 {
1185 ptr += 2;
1186 while (grub_isspace (*ptr))
1187 ptr++;
1188 pae = ptr;
1189 while (*ptr && !grub_isspace (*ptr))
1190 ptr++;
1191 paee = ptr;
1192 }
1193 while (grub_isspace (*ptr))
1194 ptr++;
1195 if (ptr[0] == '-' && ptr[1] == '-')
1196 {
1197 ptr += 2;
1198 while (grub_isspace (*ptr))
1199 ptr++;
1200 i386s = ptr;
1201 while (*ptr && !grub_isspace (*ptr))
1202 ptr++;
1203 i386e = ptr;
1204 }
1205 *lme = '\0';
1206 if (paee)
1207 *paee = '\0';
1208 if (i386e)
1209 *i386e = '\0';
1210 if (!i386s)
1211 {
1212 i386s = pae;
1213 pae = 0;
1214 }
1215 print_string ("if cpuid --long-mode; then true;\n");
1216 if (print_entry (outbuf, menu, lm))
1217 return grub_errno;
1218 if (pae)
1219 {
1220 print_string ("elif cpuid --pae; then true;\n");
1221 if (print_entry (outbuf, menu, pae))
1222 return grub_errno;
1223 }
1224 print_string ("else\n");
1225 if (print_entry (outbuf, menu, i386s))
1226 return grub_errno;
1227 print_string ("fi\n");
1228 break;
1229 }
1230
1231 if (grub_strcasecmp (basename, "reboot.c32") == 0)
1232 {
1233 print_string (" reboot\n");
1234 break;
1235 }
1236
1237 if (grub_strcasecmp (basename, "poweroff.com") == 0)
1238 {
1239 print_string (" halt\n");
1240 break;
1241 }
1242
1243 if (grub_strcasecmp (basename, "whichsys.c32") == 0)
1244 {
1245 grub_syslinux_flavour_t flavour = GRUB_SYSLINUX_ISOLINUX;
1246 const char *flav[] =
1247 {
1248 [GRUB_SYSLINUX_ISOLINUX] = "iso",
1249 [GRUB_SYSLINUX_PXELINUX] = "pxe",
1250 [GRUB_SYSLINUX_SYSLINUX] = "sys"
1251 };
1252 char *ptr;
1253 for (ptr = curentry->append; *ptr; )
1254 {
1255 char *bptr, c;
1256 while (grub_isspace (*ptr))
1257 ptr++;
1258 if (grub_strncasecmp (ptr, "-iso-", 5) == 0)
1259 {
1260 ptr += sizeof ("-iso-") - 1;
1261 flavour = GRUB_SYSLINUX_ISOLINUX;
1262 continue;
1263 }
1264 if (grub_strncasecmp (ptr, "-pxe-", 5) == 0)
1265 {
1266 ptr += sizeof ("-pxe-") - 1;
1267 flavour = GRUB_SYSLINUX_PXELINUX;
1268 continue;
1269 }
1270 if (grub_strncasecmp (ptr, "-sys-", 5) == 0)
1271 {
1272 ptr += sizeof ("-sys-") - 1;
1273 flavour = GRUB_SYSLINUX_SYSLINUX;
1274 continue;
1275 }
1276 bptr = ptr;
1277 while (*ptr && !grub_isspace (*ptr))
1278 ptr++;
1279 c = *ptr;
1280 *ptr = '\0';
1281 if (menu->flavour == GRUB_SYSLINUX_UNKNOWN
1282 && flavour == GRUB_SYSLINUX_ISOLINUX)
1283 {
1284 print_string ("if [ x$syslinux_flavour = xiso -o x$syslinux_flavour = x ]; then true;\n");
1285 menu->flavour = GRUB_SYSLINUX_ISOLINUX;
1286 print_entry (outbuf, menu, bptr);
1287 menu->flavour = GRUB_SYSLINUX_UNKNOWN;
1288 print_string ("fi\n");
1289 }
1290 else if (menu->flavour == GRUB_SYSLINUX_UNKNOWN)
1291 {
1292 print_string ("if [ x$syslinux_flavour = x");
1293 err = print (outbuf, flav[flavour], grub_strlen (flav[flavour]));
1294 if (err)
1295 return err;
1296 print_string (" ]; then true;\n");
1297 menu->flavour = flavour;
1298 print_entry (outbuf, menu, bptr);
1299 menu->flavour = GRUB_SYSLINUX_UNKNOWN;
1300 print_string ("fi\n");
1301 }
1302 if (menu->flavour != GRUB_SYSLINUX_UNKNOWN
1303 && menu->flavour == flavour)
1304 print_entry (outbuf, menu, bptr);
1305 *ptr = c;
1306 }
1307 break;
1308 }
1309
1310 if (grub_strcasecmp (basename, "menu.c32") == 0 ||
1311 grub_strcasecmp (basename, "vesamenu.c32") == 0)
1312 {
1313 char *ptr;
1314 char *end;
1315
1316 ptr = curentry->append;
1317 if (!ptr)
1318 return grub_errno;
1319
1320 while (*ptr)
1321 {
1322 end = ptr;
1323 for (end = ptr; *end && !grub_isspace (*end); end++);
1324 if (*end)
1325 *end++ = '\0';
1326
1327 /* "~" is supposed to be current file, so let's skip it */
1328 if (grub_strcmp (ptr, "~") != 0)
1329 {
1330 err = print_config (outbuf, menu, ptr, "");
1331 if (err != GRUB_ERR_NONE)
1332 break;
1333 }
1334 for (ptr = end; *ptr && grub_isspace (*ptr); ptr++);
1335 }
1336 err = GRUB_ERR_NONE;
1337 break;
1338 }
1339
1340 /* FIXME: gdb, GFXBoot, Hdt, Ifcpu, Ifplop, Kbdmap,
1341 FIXME: Linux, Lua, Meminfo, rosh, Sanbboot */
1342
1343 print_string (" # UNSUPPORTED com(32) ");
1344 err = print (outbuf, basename, grub_strlen (basename));
1345 if (err)
1346 return err;
1347 print_string ("\ntrue;\n");
1348 break;
1349 }
1350 case KERNEL_CONFIG:
1351 {
1352 const char *ap;
1353 ap = curentry->append;
1354 if (!ap)
1355 ap = curentry->argument;
1356 if (!ap)
1357 ap = "";
1358 print_config (outbuf, menu, curentry->kernel_file, ap);
1359 }
1360 break;
1361 case KERNEL_NO_KERNEL:
1362 /* FIXME: support this. */
1363 case KERNEL_BIN:
1364 case KERNEL_PXE:
1365 case KERNEL_IMG:
1366 print_string (" # UNSUPPORTED entry type ");
1367 if (print_num (outbuf, curentry->entry_type))
1368 return grub_errno;
1369 print_string ("\ntrue;\n");
1370 break;
1371 }
1372 return GRUB_ERR_NONE;
1373 }
1374
1375 static grub_err_t
1376 print_entry (struct output_buffer *outbuf,
1377 struct syslinux_menu *menu,
1378 const char *str)
1379 {
1380 struct syslinux_menuentry *curentry;
1381 for (curentry = menu->entries; curentry; curentry = curentry->next)
1382 if (grub_strcasecmp (curentry->label, str) == 0)
1383 {
1384 grub_err_t err;
1385 err = write_entry (outbuf, menu, curentry);
1386 if (err)
1387 return err;
1388 }
1389 return GRUB_ERR_NONE;
1390 }
1391
1392 static void
1393 free_menu (struct syslinux_menu *menu)
1394 {
1395 struct syslinux_say *say, *nsay;
1396 struct syslinux_menuentry *entry, *nentry;
1397
1398 grub_free (menu->def);
1399 grub_free (menu->comments);
1400 grub_free (menu->background);
1401 for (say = menu->say; say ; say = nsay)
1402 {
1403 nsay = say->next;
1404 grub_free (say);
1405 }
1406
1407 for (entry = menu->entries; entry ; entry = nentry)
1408 {
1409 nentry = entry->next;
1410 struct initrd_list *initrd, *ninitrd;
1411
1412 for (initrd = entry->initrds; initrd ; initrd = ninitrd)
1413 {
1414 ninitrd = initrd->next;
1415 grub_free (initrd->file);
1416 grub_free (initrd);
1417 }
1418
1419 grub_free (entry->comments);
1420 grub_free (entry->kernel_file);
1421 grub_free (entry->label);
1422 grub_free (entry->extlabel);
1423 grub_free (entry->append);
1424 grub_free (entry->help);
1425 grub_free (entry);
1426 }
1427 }
1428
1429 static grub_err_t
1430 config_file (struct output_buffer *outbuf,
1431 const char *root, const char *target_root,
1432 const char *cwd, const char *target_cwd,
1433 const char *fname, struct syslinux_menu *parent,
1434 grub_syslinux_flavour_t flav)
1435 {
1436 const char *data;
1437 grub_err_t err;
1438 struct syslinux_menu menu;
1439 struct syslinux_menuentry *curentry, *lentry;
1440 struct syslinux_say *say;
1441
1442 grub_memset (&menu, 0, sizeof (menu));
1443 menu.flavour = flav;
1444 menu.root_read_directory = root;
1445 menu.root_target_directory = target_root;
1446 menu.current_read_directory = cwd;
1447 menu.current_target_directory = target_cwd;
1448
1449 menu.filename = fname;
1450 menu.parent = parent;
1451
1452 data = grub_env_get("vtdebug_flag");
1453 if (data && data[0])
1454 {
1455 menu.timeout = 100;
1456 }
1457
1458 err = syslinux_parse_real (&menu);
1459 if (err)
1460 return err;
1461
1462 for (say = menu.say; say && say->next; say = say->next);
1463 for (; say && say->prev; say = say->prev)
1464 {
1465 print_string ("echo ");
1466 err = print_escaped (outbuf, say->msg, NULL);
1467 if (err)
1468 return err;
1469 print_string ("\n");
1470 }
1471
1472 if (menu.background)
1473 {
1474 print_string (" background_image ");
1475 err = print_file (outbuf, &menu, menu.background, NULL);
1476 if (err)
1477 return err;
1478 print_string ("\n");
1479 }
1480
1481 if (menu.comments)
1482 {
1483 err = print (outbuf, menu.comments, grub_strlen (menu.comments));
1484 if (err)
1485 return err;
1486 }
1487
1488 if (menu.timeout == 0 && menu.entries && menu.def)
1489 {
1490 err = print_entry (outbuf, &menu, menu.def);
1491 if (err)
1492 return err;
1493 }
1494 else if (menu.entries)
1495 {
1496 for (curentry = menu.entries; curentry->next; curentry = curentry->next);
1497 lentry = curentry;
1498
1499 print_string ("set timeout=");
1500 err = print_num (outbuf, (menu.timeout + 9) / 10);
1501 if (err)
1502 return err;
1503 print_string ("\n");
1504
1505 if (menu.def)
1506 {
1507 print_string (" default=");
1508 err = print_escaped (outbuf, menu.def, NULL);
1509 if (err)
1510 return err;
1511 print_string ("\n");
1512 }
1513 for (curentry = lentry; curentry; curentry = curentry->prev)
1514 {
1515 print_string ("menuentry ");
1516 err = print_escaped (outbuf,
1517 curentry->extlabel ? : curentry->label, NULL);
1518 if (err)
1519 return err;
1520 if (curentry->hotkey)
1521 {
1522 char hk[] = { curentry->hotkey, '\0' };
1523 print_string (" --hotkey '");
1524 print_string (hk);
1525 print_string ("'");
1526 }
1527 print_string (" --id ");
1528 err = print_escaped (outbuf, curentry->label, NULL);
1529 if (err)
1530 return err;
1531 print_string (" {\n");
1532
1533 err = write_entry (outbuf, &menu, curentry);
1534 if (err)
1535 return err;
1536
1537 print_string ("}\n");
1538 }
1539 }
1540 free_menu (&menu);
1541 return GRUB_ERR_NONE;
1542 }
1543
1544 char *
1545 grub_syslinux_config_file (const char *base, const char *target_base,
1546 const char *cwd, const char *target_cwd,
1547 const char *fname, grub_syslinux_flavour_t flav)
1548 {
1549 struct output_buffer outbuf = { 0, 0, 0 };
1550 grub_err_t err;
1551 err = config_file (&outbuf, base, target_base, cwd, target_cwd,
1552 fname, NULL, flav);
1553 if (err)
1554 return NULL;
1555 err = print (&outbuf, "\0", 1);
1556 if (err)
1557 return NULL;
1558 return outbuf.buf;
1559 }