1 /* grub-editenv.c - tool to edit environment block. */
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/>.
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>
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},
57 /* Print the version information. */
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
)
76 case ARGP_KEY_NO_ARGS
:
77 fprintf (stderr
, "%s",
78 _("You need to specify at least one command.\n"));
83 return ARGP_ERR_UNKNOWN
;
90 help_filter (int key
, const char *text
, void *input
__attribute__ ((unused
)))
94 case ARGP_KEY_HELP_POST_DOC
:
95 return xasprintf(text
, DEFAULT_ENVBLK_PATH
);
103 options
, argp_parser
, N_("FILENAME COMMAND"),
105 Tool to edit environment block.")
107 If FILENAME is `-', the default value %s is used."),
108 NULL
, help_filter
, NULL
112 create_envblk_file (const char *name
)
118 buf
= xmalloc (DEFAULT_ENVBLK_SIZE
);
120 namenew
= xasprintf ("%s.new", name
);
121 fp
= fopen (namenew
, "wb");
123 grub_util_error (_("cannot open `%s': %s"), namenew
,
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
,
138 if (rename (namenew
, name
) < 0)
139 grub_util_error (_("cannot rename the file %s to %s"), namenew
, name
);
144 open_envblk_file (const char *name
)
149 grub_envblk_t envblk
;
151 fp
= fopen (name
, "rb");
154 /* Create the file implicitly. */
155 create_envblk_file (name
);
156 fp
= fopen (name
, "rb");
158 grub_util_error (_("cannot open `%s': %s"), name
,
162 if (fseek (fp
, 0, SEEK_END
) < 0)
163 grub_util_error (_("cannot seek `%s': %s"), name
,
166 size
= (size_t) ftell (fp
);
168 if (fseek (fp
, 0, SEEK_SET
) < 0)
169 grub_util_error (_("cannot seek `%s': %s"), name
,
172 buf
= xmalloc (size
);
174 if (fread (buf
, 1, size
, fp
) != size
)
175 grub_util_error (_("cannot read `%s': %s"), name
,
180 envblk
= grub_envblk_open (buf
, size
);
182 grub_util_error ("%s", _("invalid environment block"));
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
);
199 envblk
= open_envblk_file (name
);
200 grub_envblk_iterate (envblk
, print_var
);
201 grub_envblk_close (envblk
);
205 write_envblk (const char *name
, grub_envblk_t envblk
)
209 fp
= fopen (name
, "wb");
211 grub_util_error (_("cannot open `%s': %s"), name
,
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
,
224 set_variables (const char *name
, int argc
, char *argv
[])
226 grub_envblk_t envblk
;
228 envblk
= open_envblk_file (name
);
233 p
= strchr (argv
[0], '=');
235 grub_util_error (_("invalid parameter %s"), argv
[0]);
239 if (! grub_envblk_set (envblk
, argv
[0], p
))
240 grub_util_error ("%s", _("environment block too small"));
246 write_envblk (name
, envblk
);
247 grub_envblk_close (envblk
);
251 unset_variables (const char *name
, int argc
, char *argv
[])
253 grub_envblk_t envblk
;
255 envblk
= open_envblk_file (name
);
258 grub_envblk_delete (envblk
, argv
[0]);
264 write_envblk (name
, envblk
);
265 grub_envblk_close (envblk
);
269 main (int argc
, char *argv
[])
271 const char *filename
;
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"));
286 arg_count
= argc
- curindex
;
290 filename
= DEFAULT_ENVBLK_PATH
;
291 command
= argv
[curindex
++];
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
);
311 char *program
= xstrdup(program_name
);
312 fprintf (stderr
, _("Unknown command `%s'.\n"), command
);
313 argp_help (&argp
, stderr
, ARGP_HELP_STD_USAGE
, program
);