diff --git a/ChangeLog.argp-grub-setup b/ChangeLog.argp-grub-setup new file mode 100644 index 0000000..50e1b2c --- /dev/null +++ b/ChangeLog.argp-grub-setup @@ -0,0 +1,3 @@ +2010-09-13 Yves Blusseau + + * util/i386/pc/grub-setup.c: Use argp instead of getopt. diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c index 987e2d0..f23f1ac 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/i386/pc/grub-setup.c @@ -51,7 +51,7 @@ static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_P #include "progname.h" #define _GNU_SOURCE 1 -#include +#include #define DEFAULT_BOOT_FILE "boot.img" #define DEFAULT_CORE_FILE "core.img" @@ -563,54 +563,140 @@ unable_to_embed: grub_device_close (root_dev); } -static struct option options[] = - { - {"boot-image", required_argument, 0, 'b'}, - {"core-image", required_argument, 0, 'c'}, - {"directory", required_argument, 0, 'd'}, - {"device-map", required_argument, 0, 'm'}, - {"root-device", required_argument, 0, 'r'}, - {"force", no_argument, 0, 'f'}, - {"skip-fs-probe", no_argument, 0, 's'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"verbose", no_argument, 0, 'v'}, - {0, 0, 0, 0} - }; - +/* Print the version information. */ static void -usage (int status) +print_version (FILE *stream, struct argp_state *state) { - if (status) - fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); - else - printf (_("\ -Usage: %s [OPTION]... DEVICE\n\ -\n\ + fprintf (stream, "%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); +} +void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; + +const char *argp_program_bug_address = "<"PACKAGE_BUGREPORT">"; + +static struct argp_option options[] = { + {"boot-image", 'b', N_("FILE"), 0, + N_("Use FILE as the boot image [default=")DEFAULT_BOOT_FILE"]", 0}, + {"core-image", 'c', N_("FILE"), 0, + N_("Use FILE as the core image [default=")DEFAULT_CORE_FILE"]", 0}, + {"directory", 'd', N_("DIR"), 0, + N_("Use GRUB files in the directory DIR [default=")DEFAULT_DIRECTORY"]", 0}, + {"device-map", 'm', N_("FILE"), 0, + N_("Use FILE as the device map [default=")DEFAULT_DEVICE_MAP"]", 0}, + {"root-device", 'r', N_("DEV"), 0, + N_("Use DEV as the root device [default=guessed]"), 0}, + {"force", 'f', 0, 0, + N_("Install even if problems are detected"), 0}, + {"skip-fs-probe",'s',0, 0, + N_("Do not probe for filesystems in DEVICE"), 0}, + {"verbose", 'v', 0, 0, + N_("Print verbose messages."), 0}, + { 0, 0, 0, 0, 0, 0 } +}; + +struct arguments +{ + char *boot_file; /* --boot-file */ + char *core_file; /* --core-file */ + char *dir; /* --directory */ + char *dev_map; /* --device-map */ + char *root_dev; /* --root-device */ + int force; /* --force */ + int fs_probe; /* --skip-fs-probe */ + char *device; /* DEVICE */ +}; + +static error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + /* Get the input argument from argp_parse, which we + know is a pointer to our arguments structure. */ + struct arguments *arguments = state->input; + + char *p; + + switch (key) + { + case 'b': + if (arguments->boot_file) + free (arguments->boot_file); + + arguments->boot_file = xstrdup (arg); + break; + + case 'c': + if (arguments->core_file) + free (arguments->core_file); + + arguments->core_file = xstrdup (arg); + break; + + case 'd': + if (arguments->dir) + free (arguments->dir); + + arguments->dir = xstrdup (arg); + break; + + case 'm': + if (arguments->dev_map) + free (arguments->dev_map); + + arguments->dev_map = xstrdup (arg); + break; + + case 'r': + if (arguments->root_dev) + free (arguments->root_dev); + + arguments->root_dev = xstrdup (arg); + break; + + case 'f': + arguments->force = 1; + break; + + case 's': + arguments->fs_probe = 0; + break; + + case 'v': + verbosity++; + break; + + case ARGP_KEY_ARG: + if (state->arg_num == 0) + arguments->device = arg; + else + { + /* Too many arguments. */ + fprintf (stderr, _("Unknown extra argument `%s'.\n"), arg); + argp_usage (state); + } + break; + + case ARGP_KEY_NO_ARGS: + fprintf (stderr, _("No device is specified.\n")); + argp_usage (state); + break; + + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +static struct argp argp = { + options, argp_parser, "DEVICE", +"\n\ Set up images to boot from DEVICE.\n\ -DEVICE must be a GRUB device (e.g. `(hd0,1)').\n\ -\n\ -You should not normally run %s directly. Use grub-install instead.\n\ -\n\ - -b, --boot-image=FILE use FILE as the boot image [default=%s]\n\ - -c, --core-image=FILE use FILE as the core image [default=%s]\n\ - -d, --directory=DIR use GRUB files in the directory DIR [default=%s]\n\ - -m, --device-map=FILE use FILE as the device map [default=%s]\n\ - -r, --root-device=DEV use DEV as the root device [default=guessed]\n\ - -f, --force install even if problems are detected\n\ - -s, --skip-fs-probe do not probe for filesystems in DEVICE\n\ - -h, --help display this message and exit\n\ - -V, --version print version information and exit\n\ - -v, --verbose print verbose messages\n\ \n\ -Report bugs to <%s>.\n\ -"), - program_name, program_name, - DEFAULT_BOOT_FILE, DEFAULT_CORE_FILE, DEFAULT_DIRECTORY, - DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT); +You should not normally run this program directly. Use grub-install instead.\n\ +\v\ +DEVICE must be an OS device (e.g. /dev/sda1).", + NULL, NULL, NULL +}; - exit (status); -} static char * get_device_name (char *dev) @@ -627,107 +713,35 @@ get_device_name (char *dev) int main (int argc, char *argv[]) { - char *boot_file = 0; - char *core_file = 0; - char *dir = 0; - char *dev_map = 0; - char *root_dev = 0; + struct arguments arguments; + char *root_dev; char *dest_dev; - int must_embed = 0, force = 0, fs_probe = 1; + int must_embed = 0; set_program_name (argv[0]); grub_util_init_nls (); - /* Check for options. */ - while (1) - { - int c = getopt_long (argc, argv, "b:c:d:m:r:hVvf", options, 0); - - if (c == -1) - break; - else - switch (c) - { - case 'b': - if (boot_file) - free (boot_file); - - boot_file = xstrdup (optarg); - break; + /* Default values. */ + arguments.boot_file = 0; + arguments.core_file = 0; + arguments.dir = 0; + arguments.dev_map = 0; + arguments.root_dev = 0; + arguments.force = 0; + arguments.fs_probe = 1; + arguments.device = 0; - case 'c': - if (core_file) - free (core_file); + /* Parse our arguments */ + argp_parse (&argp, argc, argv, 0, 0, &arguments); - core_file = xstrdup (optarg); - break; - - case 'd': - if (dir) - free (dir); - - dir = xstrdup (optarg); - break; - - case 'm': - if (dev_map) - free (dev_map); - - dev_map = xstrdup (optarg); - break; - - case 'r': - if (root_dev) - free (root_dev); - - root_dev = xstrdup (optarg); - break; - - case 'f': - force = 1; - break; - - case 's': - fs_probe = 0; - break; - - case 'h': - usage (0); - break; - - case 'V': - printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); - return 0; - - case 'v': - verbosity++; - break; - - default: - usage (1); - break; - } - } + root_dev = arguments.root_dev; if (verbosity > 1) grub_env_set ("debug", "all"); - /* Obtain DEST_DEV. */ - if (optind >= argc) - { - fprintf (stderr, _("No device is specified.\n")); - usage (1); - } - - if (optind + 1 != argc) - { - fprintf (stderr, _("Unknown extra argument `%s'.\n"), argv[optind + 1]); - usage (1); - } - /* Initialize the emulated biosdisk driver. */ - grub_util_biosdisk_init (dev_map ? : DEFAULT_DEVICE_MAP); + grub_util_biosdisk_init (arguments.dev_map ? : DEFAULT_DEVICE_MAP); /* Initialize all modules. */ grub_init_all (); @@ -739,14 +753,14 @@ main (int argc, char *argv[]) grub_mdraid_init (); grub_lvm_init (); - dest_dev = get_device_name (argv[optind]); + dest_dev = get_device_name (arguments.device); if (! dest_dev) { /* Possibly, the user specified an OS device file. */ - dest_dev = grub_util_get_grub_dev (argv[optind]); + dest_dev = grub_util_get_grub_dev (arguments.device); if (! dest_dev) { - fprintf (stderr, _("Invalid device `%s'.\n"), argv[optind]); + fprintf (stderr, _("Invalid device `%s'.\n"), arguments.device); usage (1); } } @@ -767,7 +781,9 @@ main (int argc, char *argv[]) } else { - root_dev = grub_util_get_grub_dev (grub_guess_root_device (dir ? : DEFAULT_DIRECTORY)); + root_dev = + grub_util_get_grub_dev (grub_guess_root_device + (arguments.dir ? : DEFAULT_DIRECTORY)); if (! root_dev) { grub_util_info ("guessing the root device failed, because of `%s'", @@ -796,29 +812,30 @@ main (int argc, char *argv[]) devicelist = grub_util_raid_getmembers (dest_dev); for (i = 0; devicelist[i]; i++) - { - setup (dir ? : DEFAULT_DIRECTORY, - boot_file ? : DEFAULT_BOOT_FILE, - core_file ? : DEFAULT_CORE_FILE, - root_dev, grub_util_get_grub_dev (devicelist[i]), 1, force, fs_probe); + { + setup (arguments.dir ? : DEFAULT_DIRECTORY, + arguments.boot_file ? : DEFAULT_BOOT_FILE, + arguments.core_file ? : DEFAULT_CORE_FILE, + root_dev, grub_util_get_grub_dev (devicelist[i]), 1, + arguments.force, arguments.fs_probe); } } else #endif /* Do the real work. */ - setup (dir ? : DEFAULT_DIRECTORY, - boot_file ? : DEFAULT_BOOT_FILE, - core_file ? : DEFAULT_CORE_FILE, - root_dev, dest_dev, must_embed, force, fs_probe); + setup (arguments.dir ? : DEFAULT_DIRECTORY, + arguments.boot_file ? : DEFAULT_BOOT_FILE, + arguments.core_file ? : DEFAULT_CORE_FILE, + root_dev, dest_dev, must_embed, arguments.force, arguments.fs_probe); /* Free resources. */ grub_fini_all (); grub_util_biosdisk_fini (); - free (boot_file); - free (core_file); - free (dir); - free (dev_map); + free (arguments.boot_file); + free (arguments.core_file); + free (arguments.dir); + free (arguments.dev_map); free (root_dev); free (dest_dev);