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);