static char * adjust_file (const char *in, grub_size_t len) { const char *comma, *ptr, *rest; char *ret, *outptr; int overhead = 0; int part = -1, subpart = -1; if (in[0] != '(') return grub_legacy_escape (in, len); for (ptr = in + 1; ptr < in + len && *ptr && *ptr != ')' && *ptr != ','; ptr++) if (*ptr == '\'' || *ptr == '\\') overhead++; comma = ptr; if (*comma != ',') return grub_legacy_escape (in, len); part = grub_strtoull (comma + 1, (char **) &rest, 0); if (rest[0] == ',' && rest[1] >= 'a' && rest[1] <= 'z') { subpart = rest[1] - 'a'; rest += 2; } for (ptr = rest; ptr < in + len && *ptr; ptr++) if (*ptr == '\'' || *ptr == '\\') overhead++; /* 35 is enough for any 2 numbers. */ ret = grub_malloc (ptr - in + overhead + 35); if (!ret) return NULL; outptr = ret; for (ptr = in; ptr < in + len && ptr <= comma; ptr++) { if (*ptr == '\'' || *ptr == '\\') *outptr++ = '\\'; *outptr++ = *ptr; } if (subpart != -1) grub_snprintf (outptr, 35, "%d,%d", part + 1, subpart + 1); else grub_snprintf (outptr, 35, "%d", part + 1); while (*outptr) outptr++; for (ptr = rest; ptr < in + len; ptr++) { if (*ptr == '\'' || *ptr == '\\') *outptr++ = '\\'; *outptr++ = *ptr; } *outptr = 0; return ret; }
char * grub_legacy_parse (const char *buf, char **entryname, char **suffix) { const char *ptr; const char *cmdname; unsigned i, cmdnum; char *args[ARRAY_SIZE (legacy_commands[0].argt)]; *suffix = NULL; for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); if (!*ptr || *ptr == '#') { char *ret; int len = grub_strlen (buf); ret = grub_malloc (len + 2); grub_memcpy (ret, buf, len); if (len && ret[len - 1] == '\n') ret[len] = 0; else { ret[len] = '\n'; ret[len + 1] = 0; } return ret; } cmdname = ptr; for (ptr = buf; *ptr && !grub_isspace (*ptr) && *ptr != '='; ptr++); for (cmdnum = 0; cmdnum < ARRAY_SIZE (legacy_commands); cmdnum++) if (grub_strncmp (legacy_commands[cmdnum].name, cmdname, ptr - cmdname) == 0 && legacy_commands[cmdnum].name[ptr - cmdname] == 0 && (!(*entryname != NULL && (legacy_commands[cmdnum].flags & FLAG_NO_MENUENTRY))) && (!(*entryname == NULL && (legacy_commands[cmdnum].flags & FLAG_MENUENTRY_ONLY)))) break; if (cmdnum == ARRAY_SIZE (legacy_commands)) return grub_xasprintf ("# Unsupported legacy command: %s\n", buf); for (; grub_isspace (*ptr) || *ptr == '='; ptr++); if (legacy_commands[cmdnum].flags & FLAG_TITLE) { const char *ptr2; ptr2 = ptr + grub_strlen (ptr); while (ptr2 > ptr && grub_isspace (*(ptr2 - 1))) ptr2--; *entryname = grub_strndup (ptr, ptr2 - ptr); return NULL; } if (legacy_commands[cmdnum].flags & FLAG_TERMINAL) { int dumb = 0, lines = 24; #ifdef TODO int no_echo = 0, no_edit = 0; #endif int hercules = 0; int console = 0, serial = 0, graphics = 0; /* Big enough for any possible resulting command. */ char outbuf[512] = ""; char *outptr; while (*ptr) { /* "[--timeout=SECS] [--silent]" " [console] [serial] [hercules]"*/ if (grub_memcmp (ptr, "--dumb", sizeof ("--dumb") - 1) == 0) dumb = 1; #ifdef TODO if (grub_memcmp (ptr, "--no-echo", sizeof ("--no-echo") - 1) == 0) no_echo = 1; if (grub_memcmp (ptr, "--no-edit", sizeof ("--no-edit") - 1) == 0) no_edit = 1; #endif if (grub_memcmp (ptr, "--lines=", sizeof ("--lines=") - 1) == 0) { lines = grub_strtoul (ptr + sizeof ("--lines=") - 1, 0, 0); if (grub_errno) { lines = 24; grub_errno = GRUB_ERR_NONE; } } if (grub_memcmp (ptr, "console", sizeof ("console") - 1) == 0) console = 1; if (grub_memcmp (ptr, "serial", sizeof ("serial") - 1) == 0) serial = 1; if (grub_memcmp (ptr, "hercules", sizeof ("hercules") - 1) == 0) hercules = 1; if (grub_memcmp (ptr, "graphics", sizeof ("graphics") - 1) == 0) graphics = 1; while (*ptr && !grub_isspace (*ptr)) ptr++; while (*ptr && grub_isspace (*ptr)) ptr++; } if (!console && !serial && !hercules && !graphics) return grub_strdup ("terminal_input; terminal_output; terminfo\n"); outptr = outbuf; if (graphics) outptr = grub_stpcpy (outptr, "insmod all_video; "); outptr = grub_stpcpy (outptr, "terminal_input "); if (serial) outptr = grub_stpcpy (outptr, "serial "); if (console || hercules || graphics) outptr = grub_stpcpy (outptr, "console "); outptr = grub_stpcpy (outptr, "; terminal_output "); if (serial) outptr = grub_stpcpy (outptr, "serial "); if (console) outptr = grub_stpcpy (outptr, "console "); if (hercules) outptr = grub_stpcpy (outptr, "mda_text "); if (graphics) outptr = grub_stpcpy (outptr, "gfxterm "); outptr = grub_stpcpy (outptr, "; "); *outptr = '\0'; if (serial) { grub_snprintf (outptr, outbuf + sizeof (outbuf) - outptr, "terminfo serial -g 80x%d %s; ", lines, dumb ? "dumb" : "vt100"); outptr += grub_strlen (outptr); } grub_strcpy (outptr, "\n"); return grub_strdup (outbuf); } grub_memset (args, 0, sizeof (args)); { int hold_arg = 0; const char *curarg = NULL; for (i = 0; i < legacy_commands[cmdnum].argc; i++) { grub_size_t curarglen; if (hold_arg) { ptr = curarg; hold_arg = 0; } for (; grub_isspace (*ptr); ptr++); curarg = ptr; if (!*curarg) break; for (; *ptr && !grub_isspace (*ptr); ptr++); if (i != legacy_commands[cmdnum].argc - 1 || (legacy_commands[cmdnum].flags & FLAG_IGNORE_REST)) curarglen = ptr - curarg; else { curarglen = grub_strlen (curarg); while (curarglen > 0 && grub_isspace (curarg[curarglen - 1])) curarglen--; } if (*ptr) ptr++; switch (legacy_commands[cmdnum].argt[i]) { case TYPE_FILE_NO_CONSUME: hold_arg = 1; case TYPE_PARTITION: case TYPE_FILE: args[i] = adjust_file (curarg, curarglen); break; case TYPE_REST_VERBATIM: { char *outptr, *outptr0; int overhead = 3; ptr = curarg; while (*ptr) { for (; *ptr && grub_isspace (*ptr); ptr++); for (; *ptr && !grub_isspace (*ptr); ptr++) if (*ptr == '\'') overhead += 3; if (*ptr) ptr++; overhead += 3; } outptr0 = args[i] = grub_malloc (overhead + (ptr - curarg)); if (!outptr0) return NULL; ptr = curarg; outptr = outptr0; while (*ptr) { for (; *ptr && grub_isspace (*ptr); ptr++); if (outptr != outptr0) *outptr++ = ' '; *outptr++ = '\''; for (; *ptr && !grub_isspace (*ptr); ptr++) { if (*ptr == '\'') { *outptr++ = '\''; *outptr++ = '\\'; *outptr++ = '\''; *outptr++ = '\''; } else *outptr++ = *ptr; } *outptr++ = '\''; if (*ptr) ptr++; } *outptr++ = 0; } break; case TYPE_VERBATIM: args[i] = grub_legacy_escape (curarg, curarglen); break; case TYPE_WITH_CONFIGFILE_OPTION: case TYPE_FORCE_OPTION: case TYPE_NOAPM_OPTION: case TYPE_TYPE_OR_NOMEM_OPTION: case TYPE_OPTION: if (is_option (legacy_commands[cmdnum].argt[i], curarg, curarglen)) { args[i] = grub_strndup (curarg, curarglen); break; } args[i] = grub_strdup (""); hold_arg = 1; break; case TYPE_INT: { const char *brk; int base = 10; brk = curarg; if (brk[0] == '0' && brk[1] == 'x') { base = 16; brk += 2; } else if (brk[0] == '0') base = 8; for (; *brk && brk < curarg + curarglen; brk++) { if (base == 8 && (*brk == '8' || *brk == '9')) break; if (grub_isdigit (*brk)) continue; if (base != 16) break; if (!(*brk >= 'a' && *brk <= 'f') && !(*brk >= 'A' && *brk <= 'F')) break; } if (brk == curarg) args[i] = grub_strdup ("0"); else args[i] = grub_strndup (curarg, brk - curarg); } break; case TYPE_VBE_MODE: { unsigned mod; struct grub_vesa_mode_table_entry *modedesc; mod = grub_strtoul (curarg, 0, 0); if (grub_errno) { mod = 0; grub_errno = GRUB_ERR_NONE; } if (mod < GRUB_VESA_MODE_TABLE_START || mod > GRUB_VESA_MODE_TABLE_END) { args[i] = grub_strdup ("auto"); break; } modedesc = &grub_vesa_mode_table[mod - GRUB_VESA_MODE_TABLE_START]; if (!modedesc->width) { args[i] = grub_strdup ("auto"); break; } args[i] = grub_xasprintf ("%ux%ux%u", modedesc->width, modedesc->height, modedesc->depth); break; } case TYPE_BOOL: if (curarglen == 2 && curarg[0] == 'o' && curarg[1] == 'n') args[i] = grub_strdup ("1"); else args[i] = grub_strdup ("0"); break; } } } while (legacy_commands[cmdnum].argc > 0 && args[legacy_commands[cmdnum].argc - 1] == NULL && (legacy_commands[cmdnum].flags & FLAG_FALLBACK_AVAILABLE) && args[legacy_commands[cmdnum + 1].argc] == NULL) cmdnum++; for (; i < legacy_commands[cmdnum].argc; i++) switch (legacy_commands[cmdnum].argt[i]) { case TYPE_FILE_NO_CONSUME: case TYPE_PARTITION: case TYPE_FILE: case TYPE_REST_VERBATIM: case TYPE_VERBATIM: case TYPE_WITH_CONFIGFILE_OPTION: case TYPE_FORCE_OPTION: case TYPE_NOAPM_OPTION: case TYPE_TYPE_OR_NOMEM_OPTION: case TYPE_OPTION: args[i] = grub_strdup (""); break; case TYPE_BOOL: case TYPE_INT: args[i] = grub_strdup ("0"); break; case TYPE_VBE_MODE: args[i] = grub_strdup ("auto"); break; } if (legacy_commands[cmdnum].flags & FLAG_COLOR_INVERT) { char *corig = args[legacy_commands[cmdnum].argc - 1]; char *slash = grub_strchr (corig, '/'); char *invert; grub_size_t len; len = grub_strlen (corig); if (!slash) { grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid color specification `%s'"), args[0]); return NULL; } invert = grub_malloc (len + 1); if (!invert) return NULL; grub_memcpy (invert, slash + 1, len - (slash - corig) - 1); invert[len - (slash - args[0]) - 1] = '/'; grub_memcpy (invert + len - (slash - corig), corig, slash - corig); invert[len] = 0; args[legacy_commands[cmdnum].argc] = invert; } if (legacy_commands[cmdnum].suffix) { *suffix = grub_xasprintf (legacy_commands[cmdnum].suffix, args[legacy_commands[cmdnum].suffixarg]); if (*suffix) return NULL; } { char *ret = grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], args[2], args[3]); grub_free (args[0]); grub_free (args[1]); grub_free (args[2]); grub_free (args[3]); return ret; } }
int main (int argc, char **argv) { FILE *in, *out; char *entryname = NULL; char *buf = NULL; size_t bufsize = 0; char *suffix = xstrdup (""); int suffixlen = 0; if (argc >= 2 && argv[1][0] == '-') { fprintf (stdout, "Usage: %s [INFILE [OUTFILE]]\n", argv[0]); return 0; } if (argc >= 2) { in = fopen (argv[1], "r"); if (!in) { fprintf (stderr, "Couldn't open %s for reading: %s\n", argv[1], strerror (errno)); return 1; } } else in = stdin; if (argc >= 3) { out = fopen (argv[2], "w"); if (!out) { if (in != stdin) fclose (in); fprintf (stderr, "Couldn't open %s for writing: %s\n", argv[2], strerror (errno)); return 1; } } else out = stdout; while (1) { char *parsed; if (getline (&buf, &bufsize, in) < 0) break; { char *oldname = NULL; char *newsuffix; oldname = entryname; parsed = grub_legacy_parse (buf, &entryname, &newsuffix); if (newsuffix) { suffixlen += strlen (newsuffix); suffix = xrealloc (suffix, suffixlen + 1); strcat (suffix, newsuffix); } if (oldname != entryname && oldname) fprintf (out, "}\n\n"); if (oldname != entryname) { char *escaped = grub_legacy_escape (entryname, strlen (entryname)); fprintf (out, "menuentry \'%s\' {\n", escaped); free (escaped); free (oldname); } } if (parsed) fprintf (out, "%s%s", entryname ? " " : "", parsed); free (parsed); parsed = NULL; } if (entryname) fprintf (out, "}\n\n"); fwrite (suffix, 1, suffixlen, out); free (buf); free (suffix); free (entryname); if (in != stdin) fclose (in); if (out != stdout) fclose (out); return 0; }