Upgraded GRUB2 to 2.00 release.
[AROS.git] / arch / all-pc / boot / grub2-aros / util / grub-editenv.c
blob175ca8e1de5b833880bd753d53422419ddd59309
1 /* grub-editenv.c - tool to edit environment block. */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <grub/types.h>
22 #include <grub/emu/misc.h>
23 #include <grub/util/misc.h>
24 #include <grub/lib/envblk.h>
25 #include <grub/i18n.h>
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <argp.h>
33 #include "progname.h"
35 #define DEFAULT_ENVBLK_SIZE 1024
36 #define DEFAULT_ENVBLK_PATH DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG
38 static struct argp_option options[] = {
39 {0, 0, 0, OPTION_DOC, N_("Commands:"), 1},
40 {"create", 0, 0, OPTION_DOC|OPTION_NO_USAGE,
41 N_("Create a blank environment block file."), 0},
42 {"list", 0, 0, OPTION_DOC|OPTION_NO_USAGE,
43 N_("List the current variables."), 0},
44 /* TRANSLATORS: "set" is a keyword. It's a summary of "set" subcommand. */
45 {N_("set [NAME=VALUE ...]"), 0, 0, OPTION_DOC|OPTION_NO_USAGE,
46 N_("Set variables."), 0},
47 /* TRANSLATORS: "unset" is a keyword. It's a summary of "unset" subcommand. */
48 {N_("unset [NAME ...]"), 0, 0, OPTION_DOC|OPTION_NO_USAGE,
49 N_("Delete variables."), 0},
51 {0, 0, 0, OPTION_DOC, N_("Options:"), -1},
52 {"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
54 { 0, 0, 0, 0, 0, 0 }
57 /* Print the version information. */
58 static void
59 print_version (FILE *stream, struct argp_state *state)
61 fprintf (stream, "%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
63 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
65 /* Set the bug report address */
66 const char *argp_program_bug_address = "<"PACKAGE_BUGREPORT">";
68 static error_t argp_parser (int key, char *arg, struct argp_state *state)
70 switch (key)
72 case 'v':
73 verbosity++;
74 break;
76 case ARGP_KEY_NO_ARGS:
77 fprintf (stderr, "%s",
78 _("You need to specify at least one command.\n"));
79 argp_usage (state);
80 break;
82 default:
83 return ARGP_ERR_UNKNOWN;
86 return 0;
89 static char *
90 help_filter (int key, const char *text, void *input __attribute__ ((unused)))
92 switch (key)
94 case ARGP_KEY_HELP_POST_DOC:
95 return xasprintf(text, DEFAULT_ENVBLK_PATH);
97 default:
98 return (char *) text;
102 struct argp argp = {
103 options, argp_parser, N_("FILENAME COMMAND"),
104 "\n"N_("\
105 Tool to edit environment block.")
106 "\v"N_("\
107 If FILENAME is `-', the default value %s is used."),
108 NULL, help_filter, NULL
111 static void
112 create_envblk_file (const char *name)
114 FILE *fp;
115 char *buf;
116 char *namenew;
118 buf = xmalloc (DEFAULT_ENVBLK_SIZE);
120 namenew = xasprintf ("%s.new", name);
121 fp = fopen (namenew, "wb");
122 if (! fp)
123 grub_util_error (_("cannot open `%s': %s"), namenew,
124 strerror (errno));
126 memcpy (buf, GRUB_ENVBLK_SIGNATURE, sizeof (GRUB_ENVBLK_SIGNATURE) - 1);
127 memset (buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1, '#',
128 DEFAULT_ENVBLK_SIZE - sizeof (GRUB_ENVBLK_SIGNATURE) + 1);
130 if (fwrite (buf, 1, DEFAULT_ENVBLK_SIZE, fp) != DEFAULT_ENVBLK_SIZE)
131 grub_util_error (_("cannot write to `%s': %s"), namenew,
132 strerror (errno));
134 fsync (fileno (fp));
135 free (buf);
136 fclose (fp);
138 if (rename (namenew, name) < 0)
139 grub_util_error (_("cannot rename the file %s to %s"), namenew, name);
140 free (namenew);
143 static grub_envblk_t
144 open_envblk_file (const char *name)
146 FILE *fp;
147 char *buf;
148 size_t size;
149 grub_envblk_t envblk;
151 fp = fopen (name, "rb");
152 if (! fp)
154 /* Create the file implicitly. */
155 create_envblk_file (name);
156 fp = fopen (name, "rb");
157 if (! fp)
158 grub_util_error (_("cannot open `%s': %s"), name,
159 strerror (errno));
162 if (fseek (fp, 0, SEEK_END) < 0)
163 grub_util_error (_("cannot seek `%s': %s"), name,
164 strerror (errno));
166 size = (size_t) ftell (fp);
168 if (fseek (fp, 0, SEEK_SET) < 0)
169 grub_util_error (_("cannot seek `%s': %s"), name,
170 strerror (errno));
172 buf = xmalloc (size);
174 if (fread (buf, 1, size, fp) != size)
175 grub_util_error (_("cannot read `%s': %s"), name,
176 strerror (errno));
178 fclose (fp);
180 envblk = grub_envblk_open (buf, size);
181 if (! envblk)
182 grub_util_error ("%s", _("invalid environment block"));
184 return envblk;
187 static void
188 list_variables (const char *name)
190 grub_envblk_t envblk;
192 auto int print_var (const char *varname, const char *value);
193 int print_var (const char *varname, const char *value)
195 printf ("%s=%s\n", varname, value);
196 return 0;
199 envblk = open_envblk_file (name);
200 grub_envblk_iterate (envblk, print_var);
201 grub_envblk_close (envblk);
204 static void
205 write_envblk (const char *name, grub_envblk_t envblk)
207 FILE *fp;
209 fp = fopen (name, "wb");
210 if (! fp)
211 grub_util_error (_("cannot open `%s': %s"), name,
212 strerror (errno));
214 if (fwrite (grub_envblk_buffer (envblk), 1, grub_envblk_size (envblk), fp)
215 != grub_envblk_size (envblk))
216 grub_util_error (_("cannot write to `%s': %s"), name,
217 strerror (errno));
219 fsync (fileno (fp));
220 fclose (fp);
223 static void
224 set_variables (const char *name, int argc, char *argv[])
226 grub_envblk_t envblk;
228 envblk = open_envblk_file (name);
229 while (argc)
231 char *p;
233 p = strchr (argv[0], '=');
234 if (! p)
235 grub_util_error (_("invalid parameter %s"), argv[0]);
237 *(p++) = 0;
239 if (! grub_envblk_set (envblk, argv[0], p))
240 grub_util_error ("%s", _("environment block too small"));
242 argc--;
243 argv++;
246 write_envblk (name, envblk);
247 grub_envblk_close (envblk);
250 static void
251 unset_variables (const char *name, int argc, char *argv[])
253 grub_envblk_t envblk;
255 envblk = open_envblk_file (name);
256 while (argc)
258 grub_envblk_delete (envblk, argv[0]);
260 argc--;
261 argv++;
264 write_envblk (name, envblk);
265 grub_envblk_close (envblk);
269 main (int argc, char *argv[])
271 const char *filename;
272 char *command;
273 int curindex, arg_count;
275 set_program_name (argv[0]);
277 grub_util_init_nls ();
279 /* Parse our arguments */
280 if (argp_parse (&argp, argc, argv, 0, &curindex, 0) != 0)
282 fprintf (stderr, "%s", _("Error in parsing command line arguments\n"));
283 exit(1);
286 arg_count = argc - curindex;
288 if (arg_count == 1)
290 filename = DEFAULT_ENVBLK_PATH;
291 command = argv[curindex++];
293 else
295 filename = argv[curindex++];
296 if (strcmp (filename, "-") == 0)
297 filename = DEFAULT_ENVBLK_PATH;
298 command = argv[curindex++];
301 if (strcmp (command, "create") == 0)
302 create_envblk_file (filename);
303 else if (strcmp (command, "list") == 0)
304 list_variables (filename);
305 else if (strcmp (command, "set") == 0)
306 set_variables (filename, argc - curindex, argv + curindex);
307 else if (strcmp (command, "unset") == 0)
308 unset_variables (filename, argc - curindex, argv + curindex);
309 else
311 char *program = xstrdup(program_name);
312 fprintf (stderr, _("Unknown command `%s'.\n"), command);
313 argp_help (&argp, stderr, ARGP_HELP_STD_USAGE, program);
314 free(program);
315 exit(1);
318 return 0;