]> git.proxmox.com Git - grub2.git/blob - util/grub-editenv.c
Import grub2_2.02+dfsg1.orig.tar.xz
[grub2.git] / util / grub-editenv.c
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.
5 *
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.
10 *
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.
15 *
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/>.
18 */
19
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>
26 #include <grub/emu/hostfile.h>
27 #include <grub/util/install.h>
28
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
34 #pragma GCC diagnostic ignored "-Wmissing-declarations"
35 #include <argp.h>
36 #pragma GCC diagnostic error "-Wmissing-prototypes"
37 #pragma GCC diagnostic error "-Wmissing-declarations"
38
39
40 #include "progname.h"
41
42 #define DEFAULT_ENVBLK_PATH DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG
43
44 static struct argp_option options[] = {
45 {0, 0, 0, OPTION_DOC, N_("Commands:"), 1},
46 {"create", 0, 0, OPTION_DOC|OPTION_NO_USAGE,
47 N_("Create a blank environment block file."), 0},
48 {"list", 0, 0, OPTION_DOC|OPTION_NO_USAGE,
49 N_("List the current variables."), 0},
50 /* TRANSLATORS: "set" is a keyword. It's a summary of "set" subcommand. */
51 {N_("set [NAME=VALUE ...]"), 0, 0, OPTION_DOC|OPTION_NO_USAGE,
52 N_("Set variables."), 0},
53 /* TRANSLATORS: "unset" is a keyword. It's a summary of "unset" subcommand. */
54 {N_("unset [NAME ...]"), 0, 0, OPTION_DOC|OPTION_NO_USAGE,
55 N_("Delete variables."), 0},
56
57 {0, 0, 0, OPTION_DOC, N_("Options:"), -1},
58 {"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
59
60 { 0, 0, 0, 0, 0, 0 }
61 };
62
63 /* Print the version information. */
64 static void
65 print_version (FILE *stream, struct argp_state *state)
66 {
67 fprintf (stream, "%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
68 }
69 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
70
71 /* Set the bug report address */
72 const char *argp_program_bug_address = "<"PACKAGE_BUGREPORT">";
73
74 static error_t argp_parser (int key, char *arg, struct argp_state *state)
75 {
76 switch (key)
77 {
78 case 'v':
79 verbosity++;
80 break;
81
82 case ARGP_KEY_NO_ARGS:
83 fprintf (stderr, "%s",
84 _("You need to specify at least one command.\n"));
85 argp_usage (state);
86 break;
87
88 default:
89 return ARGP_ERR_UNKNOWN;
90 }
91
92 return 0;
93 }
94
95 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
96
97 static char *
98 help_filter (int key, const char *text, void *input __attribute__ ((unused)))
99 {
100 switch (key)
101 {
102 case ARGP_KEY_HELP_POST_DOC:
103 return xasprintf (text, DEFAULT_ENVBLK_PATH, DEFAULT_ENVBLK_PATH);
104
105 default:
106 return (char *) text;
107 }
108 }
109
110 #pragma GCC diagnostic error "-Wformat-nonliteral"
111
112 struct argp argp = {
113 options, argp_parser, N_("FILENAME COMMAND"),
114 "\n"N_("\
115 Tool to edit environment block.")
116 "\v"N_("\
117 If FILENAME is `-', the default value %s is used.\n\n\
118 There is no `delete' command; if you want to delete the whole environment\n\
119 block, use `rm %s'."),
120 NULL, help_filter, NULL
121 };
122
123 static grub_envblk_t
124 open_envblk_file (const char *name)
125 {
126 FILE *fp;
127 char *buf;
128 size_t size;
129 grub_envblk_t envblk;
130
131 fp = grub_util_fopen (name, "rb");
132 if (! fp)
133 {
134 /* Create the file implicitly. */
135 grub_util_create_envblk_file (name);
136 fp = grub_util_fopen (name, "rb");
137 if (! fp)
138 grub_util_error (_("cannot open `%s': %s"), name,
139 strerror (errno));
140 }
141
142 if (fseek (fp, 0, SEEK_END) < 0)
143 grub_util_error (_("cannot seek `%s': %s"), name,
144 strerror (errno));
145
146 size = (size_t) ftell (fp);
147
148 if (fseek (fp, 0, SEEK_SET) < 0)
149 grub_util_error (_("cannot seek `%s': %s"), name,
150 strerror (errno));
151
152 buf = xmalloc (size);
153
154 if (fread (buf, 1, size, fp) != size)
155 grub_util_error (_("cannot read `%s': %s"), name,
156 strerror (errno));
157
158 fclose (fp);
159
160 envblk = grub_envblk_open (buf, size);
161 if (! envblk)
162 grub_util_error ("%s", _("invalid environment block"));
163
164 return envblk;
165 }
166
167 static int
168 print_var (const char *varname, const char *value,
169 void *hook_data __attribute__ ((unused)))
170 {
171 printf ("%s=%s\n", varname, value);
172 return 0;
173 }
174
175 static void
176 list_variables (const char *name)
177 {
178 grub_envblk_t envblk;
179
180 envblk = open_envblk_file (name);
181 grub_envblk_iterate (envblk, NULL, print_var);
182 grub_envblk_close (envblk);
183 }
184
185 static void
186 write_envblk (const char *name, grub_envblk_t envblk)
187 {
188 FILE *fp;
189
190 fp = grub_util_fopen (name, "wb");
191 if (! fp)
192 grub_util_error (_("cannot open `%s': %s"), name,
193 strerror (errno));
194
195 if (fwrite (grub_envblk_buffer (envblk), 1, grub_envblk_size (envblk), fp)
196 != grub_envblk_size (envblk))
197 grub_util_error (_("cannot write to `%s': %s"), name,
198 strerror (errno));
199
200 grub_util_file_sync (fp);
201 fclose (fp);
202 }
203
204 static void
205 set_variables (const char *name, int argc, char *argv[])
206 {
207 grub_envblk_t envblk;
208
209 envblk = open_envblk_file (name);
210 while (argc)
211 {
212 char *p;
213
214 p = strchr (argv[0], '=');
215 if (! p)
216 grub_util_error (_("invalid parameter %s"), argv[0]);
217
218 *(p++) = 0;
219
220 if (! grub_envblk_set (envblk, argv[0], p))
221 grub_util_error ("%s", _("environment block too small"));
222
223 argc--;
224 argv++;
225 }
226
227 write_envblk (name, envblk);
228 grub_envblk_close (envblk);
229 }
230
231 static void
232 unset_variables (const char *name, int argc, char *argv[])
233 {
234 grub_envblk_t envblk;
235
236 envblk = open_envblk_file (name);
237 while (argc)
238 {
239 grub_envblk_delete (envblk, argv[0]);
240
241 argc--;
242 argv++;
243 }
244
245 write_envblk (name, envblk);
246 grub_envblk_close (envblk);
247 }
248
249 int
250 main (int argc, char *argv[])
251 {
252 const char *filename;
253 char *command;
254 int curindex, arg_count;
255
256 grub_util_host_init (&argc, &argv);
257
258 /* Parse our arguments */
259 if (argp_parse (&argp, argc, argv, 0, &curindex, 0) != 0)
260 {
261 fprintf (stderr, "%s", _("Error in parsing command line arguments\n"));
262 exit(1);
263 }
264
265 arg_count = argc - curindex;
266
267 if (arg_count == 1)
268 {
269 filename = DEFAULT_ENVBLK_PATH;
270 command = argv[curindex++];
271 }
272 else
273 {
274 filename = argv[curindex++];
275 if (strcmp (filename, "-") == 0)
276 filename = DEFAULT_ENVBLK_PATH;
277 command = argv[curindex++];
278 }
279
280 if (strcmp (command, "create") == 0)
281 grub_util_create_envblk_file (filename);
282 else if (strcmp (command, "list") == 0)
283 list_variables (filename);
284 else if (strcmp (command, "set") == 0)
285 set_variables (filename, argc - curindex, argv + curindex);
286 else if (strcmp (command, "unset") == 0)
287 unset_variables (filename, argc - curindex, argv + curindex);
288 else
289 {
290 char *program = xstrdup(program_name);
291 fprintf (stderr, _("Unknown command `%s'.\n"), command);
292 argp_help (&argp, stderr, ARGP_HELP_STD_USAGE, program);
293 free(program);
294 exit(1);
295 }
296
297 return 0;
298 }