/* * GRUB -- GRand Unified Bootloader * Copyright (C) 2013 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GRUB is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GRUB. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include GRUB_MOD_LICENSE ("GPLv3+"); /* Helper for syslinux_file. */ static grub_err_t syslinux_file_getline (char **line, int cont __attribute__ ((unused)), void *data __attribute__ ((unused))) { *line = 0; return GRUB_ERR_NONE; } static const struct grub_arg_option options[] = { {"root", 'r', 0, N_("root directory of the syslinux disk [default=/]."), N_("DIR"), ARG_TYPE_STRING}, {"cwd", 'c', 0, N_("current directory of syslinux [default is parent directory of input file]."), N_("DIR"), ARG_TYPE_STRING}, {"isolinux", 'i', 0, N_("assume input is an isolinux configuration file."), 0, 0}, {"pxelinux", 'p', 0, N_("assume input is a pxelinux configuration file."), 0, 0}, {"syslinux", 's', 0, N_("assume input is a syslinux configuration file."), 0, 0}, {0, 0, 0, 0, 0, 0} }; enum { OPTION_ROOT, OPTION_CWD, OPTION_ISOLINUX, OPTION_PXELINUX, OPTION_SYSLINUX }; static grub_err_t syslinux_file (grub_extcmd_context_t ctxt, const char *filename) { char *result; const char *root = ctxt->state[OPTION_ROOT].set ? ctxt->state[OPTION_ROOT].arg : "/"; const char *cwd = ctxt->state[OPTION_CWD].set ? ctxt->state[OPTION_CWD].arg : NULL; grub_syslinux_flavour_t flav = GRUB_SYSLINUX_UNKNOWN; char *cwdf = NULL; grub_menu_t menu; if (ctxt->state[OPTION_ISOLINUX].set) flav = GRUB_SYSLINUX_ISOLINUX; if (ctxt->state[OPTION_PXELINUX].set) flav = GRUB_SYSLINUX_PXELINUX; if (ctxt->state[OPTION_SYSLINUX].set) flav = GRUB_SYSLINUX_SYSLINUX; if (!cwd) { char *p; cwdf = grub_strdup (filename); if (!cwdf) return grub_errno; p = grub_strrchr (cwdf, '/'); if (!p) { grub_free (cwdf); cwd = "/"; cwdf = NULL; } else { *p = '\0'; cwd = cwdf; } } grub_dprintf ("syslinux", "transforming syslinux config %s, root = %s, cwd = %s\n", filename, root, cwd); result = grub_syslinux_config_file (root, root, cwd, cwd, filename, flav); if (!result) return grub_errno; grub_dprintf ("syslinux", "syslinux config transformed\n"); menu = grub_env_get_menu (); if (! menu) { menu = grub_zalloc (sizeof (*menu)); if (! menu) { grub_free (result); return grub_errno; } grub_env_set_menu (menu); } grub_normal_parse_line (result, syslinux_file_getline, NULL); grub_print_error (); grub_free (result); grub_free (cwdf); return GRUB_ERR_NONE; } static grub_err_t grub_cmd_syslinux_source (grub_extcmd_context_t ctxt, int argc, char **args) { int new_env, extractor; grub_err_t ret; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); extractor = (ctxt->extcmd->cmd->name[0] == 'e'); new_env = (ctxt->extcmd->cmd->name[extractor ? (sizeof ("extract_syslinux_entries_") - 1) : (sizeof ("syslinux_") - 1)] == 'c'); if (new_env) grub_cls (); if (new_env && !extractor) grub_env_context_open (); if (extractor) grub_env_extractor_open (!new_env); ret = syslinux_file (ctxt, args[0]); if (new_env) { grub_menu_t menu; menu = grub_env_get_menu (); if (menu && menu->size) grub_show_menu (menu, 1, 0); if (!extractor) grub_env_context_close (); } if (extractor) grub_env_extractor_close (!new_env); return ret; } static grub_extcmd_t cmd_source, cmd_configfile; static grub_extcmd_t cmd_source_extract, cmd_configfile_extract; GRUB_MOD_INIT(syslinuxcfg) { cmd_source = grub_register_extcmd ("syslinux_source", grub_cmd_syslinux_source, 0, N_("FILE"), /* TRANSLATORS: "syslinux config" means "config as used by syslinux". */ N_("Execute syslinux config in same context"), options); cmd_configfile = grub_register_extcmd ("syslinux_configfile", grub_cmd_syslinux_source, 0, N_("FILE"), N_("Execute syslinux config in new context"), options); cmd_source_extract = grub_register_extcmd ("extract_syslinux_entries_source", grub_cmd_syslinux_source, 0, N_("FILE"), N_("Execute syslinux config in same context taking only menu entries"), options); cmd_configfile_extract = grub_register_extcmd ("extract_syslinux_entries_configfile", grub_cmd_syslinux_source, 0, N_("FILE"), N_("Execute syslinux config in new context taking only menu entries"), options); } GRUB_MOD_FINI(syslinuxcfg) { grub_unregister_extcmd (cmd_source); grub_unregister_extcmd (cmd_configfile); grub_unregister_extcmd (cmd_source_extract); grub_unregister_extcmd (cmd_configfile_extract); }