From 2270f77beaa9fc19ae267018f0a3006946f0a72b Mon Sep 17 00:00:00 2001 From: bean Date: Wed, 2 Jul 2008 07:20:11 +0000 Subject: [PATCH] 2008-07-02 Bean * conf/common.rmk (bin_UTILITIES): Add grub-editenv. (grub_editenv_SOURCES): New variable. (pkglib_MODULES): Add loadenv.mod. (loadenv_mod_SOURCES): New variable. (loadenv_mod_CFLAGS): Likewise. (loadenv_mod_LDFLAGS): Likewise. * include/grub/envblk.h: New file. * util/envblk.c: New file. * util/grub-editenv.c: New file. * commands/loadenv.c: New file. --- ChangeLog | 17 +++ commands/loadenv.c | 257 ++++++++++++++++++++++++++++++++ conf/common.mk | 332 ++++++++++++++++++++++++++++-------------- conf/common.rmk | 32 ++-- include/grub/envblk.h | 45 ++++++ util/envblk.c | 156 ++++++++++++++++++++ util/grub-editenv.c | 258 ++++++++++++++++++++++++++++++++ 7 files changed, 973 insertions(+), 124 deletions(-) create mode 100644 commands/loadenv.c create mode 100644 include/grub/envblk.h create mode 100644 util/envblk.c create mode 100644 util/grub-editenv.c diff --git a/ChangeLog b/ChangeLog index a27213f08..f27f59b6f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2008-07-02 Bean + + * conf/common.rmk (bin_UTILITIES): Add grub-editenv. + (grub_editenv_SOURCES): New variable. + (pkglib_MODULES): Add loadenv.mod. + (loadenv_mod_SOURCES): New variable. + (loadenv_mod_CFLAGS): Likewise. + (loadenv_mod_LDFLAGS): Likewise. + + * include/grub/envblk.h: New file. + + * util/envblk.c: New file. + + * util/grub-editenv.c: New file. + + * commands/loadenv.c: New file. + 2008-07-01 Pavel Roskin * include/multiboot2.h (struct multiboot_tag_module): Use char, diff --git a/commands/loadenv.c b/commands/loadenv.c new file mode 100644 index 000000000..735968318 --- /dev/null +++ b/commands/loadenv.c @@ -0,0 +1,257 @@ +/* loadenv.c - command to load/save environment variable. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct grub_arg_option options[] = + { + {"file", 'f', 0, "specify filename", 0, ARG_TYPE_PATHNAME}, + {0, 0, 0, 0, 0, 0} + }; + +char buffer[GRUB_ENVBLK_MAXLEN]; +grub_envblk_t envblk; + +static grub_file_t +read_envblk_file (char *filename, void NESTED_FUNC_ATTR read_hook (grub_disk_addr_t sector, unsigned offset, unsigned length)) +{ + char *buf = 0; + grub_file_t file; + + if (! filename) + { + char *prefix; + + prefix = grub_env_get ("prefix"); + if (prefix) + { + int len; + + len = grub_strlen (prefix); + buf = grub_malloc (len + 1 + sizeof (GRUB_ENVBLK_DEFCFG)); + grub_strcpy (buf, prefix); + buf[len] = '/'; + grub_strcpy (buf + len + 1, GRUB_ENVBLK_DEFCFG); + filename = buf; + } + else + { + grub_error (GRUB_ERR_FILE_NOT_FOUND, "prefix is not found"); + return 0; + } + } + + file = grub_file_open (filename); + grub_free (buf); + if (! file) + return 0; + + if (read_hook) + { + if (! file->device->disk) + { + grub_file_close (file); + grub_error (GRUB_ERR_BAD_DEVICE, + "this command is available only for disk devices."); + return 0; + } + file->read_hook = read_hook; + } + + if (grub_file_read (file, buffer, GRUB_ENVBLK_MAXLEN) != GRUB_ENVBLK_MAXLEN) + { + grub_file_close (file); + grub_error (GRUB_ERR_BAD_FILE_TYPE, "file too short"); + return 0; + } + + envblk = grub_envblk_find (buffer); + if (! envblk) + { + grub_file_close (file); + grub_error (GRUB_ERR_BAD_FILE_TYPE, "environment block not found"); + return 0; + } + + return file; +} + +static grub_err_t +grub_cmd_load_env (struct grub_arg_list *state, + int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) + +{ + grub_file_t file; + + auto int hook (char *name, char *value); + int hook (char *name, char *value) + { + grub_env_set (name, value); + + return 0; + } + + file = read_envblk_file ((state[0].set) ? state[0].arg : 0, 0); + if (! file) + return grub_errno; + + grub_file_close (file); + + grub_envblk_iterate (envblk, hook); + + return grub_errno; +} + +static grub_err_t +grub_cmd_list_env (struct grub_arg_list *state, + int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) +{ + grub_file_t file; + + auto int hook (char *name, char *value); + int hook (char *name, char *value) + { + grub_printf ("%s=%s\n", name, value); + + return 0; + } + + file = read_envblk_file ((state[0].set) ? state[0].arg : 0, 0); + if (! file) + return grub_errno; + + grub_file_close (file); + + grub_envblk_iterate (envblk, hook); + + return grub_errno; +} + +static grub_err_t +grub_cmd_save_env (struct grub_arg_list *state, int argc, char **args) +{ + grub_file_t file; + grub_disk_t disk; + grub_disk_addr_t addr[GRUB_ENVBLK_MAXLEN >> GRUB_DISK_SECTOR_BITS]; + char buf[GRUB_DISK_SECTOR_SIZE]; + grub_disk_addr_t part_start = 0; + int num = 0; + + auto void NESTED_FUNC_ATTR hook (grub_disk_addr_t sector, unsigned offset, + unsigned length); + + void NESTED_FUNC_ATTR hook (grub_disk_addr_t sector, + unsigned offset, unsigned length) + { + if ((offset != 0) || (length != GRUB_DISK_SECTOR_SIZE)) + return; + + if (num < (GRUB_ENVBLK_MAXLEN >> GRUB_DISK_SECTOR_BITS)) + addr[num++] = sector; + } + + if (! argc) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "No variable is specified"); + + file = read_envblk_file ((state[0].set) ? state[0].arg : 0, hook); + if (! file) + return grub_errno; + + file->read_hook = 0; + + if (num != GRUB_ENVBLK_MAXLEN >> GRUB_DISK_SECTOR_BITS) + { + grub_error (GRUB_ERR_BAD_DEVICE, "invalid blocklist"); + goto quit; + } + + disk = file->device->disk; + if (disk->partition) + part_start = grub_partition_get_start (disk->partition); + + for (num = 0; num < (GRUB_ENVBLK_MAXLEN >> GRUB_DISK_SECTOR_BITS); num++) + { + if (grub_disk_read (disk, addr[num] - part_start, 0, + GRUB_DISK_SECTOR_SIZE, buf)) + goto quit; + + if (grub_memcmp (&buffer[num << GRUB_DISK_SECTOR_BITS], buf, + GRUB_DISK_SECTOR_SIZE)) + { + grub_error (GRUB_ERR_BAD_DEVICE, "invalid blocklist"); + goto quit; + } + } + + while (argc) + { + char *value; + + value = grub_env_get (args[0]); + if (value) + { + if (grub_envblk_insert (envblk, args[0], value)) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "environment block too small"); + goto quit; + } + } + + argc--; + args++; + } + + for (num = 0; num < (GRUB_ENVBLK_MAXLEN >> GRUB_DISK_SECTOR_BITS); num++) + if (grub_disk_write (disk, addr[num] - part_start, 0, + GRUB_DISK_SECTOR_SIZE, + &buffer[num << GRUB_DISK_SECTOR_BITS])) + goto quit; + +quit: + grub_file_close (file); + + return grub_errno; +} + +GRUB_MOD_INIT(loadenv) +{ + (void) mod; + grub_register_command ("load_env", grub_cmd_load_env, GRUB_COMMAND_FLAG_BOTH, + "load_env [-f FILE]", "Load variables from environment block file.", options); + grub_register_command ("list_env", grub_cmd_list_env, GRUB_COMMAND_FLAG_BOTH, + "list_env [-f FILE]", "List variables from environment block file.", options); + grub_register_command ("save_env", grub_cmd_save_env, GRUB_COMMAND_FLAG_BOTH, + "save_env [-f FILE] variable_name [...]", "Save variables to environment block file.", options); +} + +GRUB_MOD_FINI(loadenv) +{ + grub_unregister_command ("load_env"); + grub_unregister_command ("list_env"); + grub_unregister_command ("save_env"); +} diff --git a/conf/common.mk b/conf/common.mk index 9228f1cbf..a889f3be9 100644 --- a/conf/common.mk +++ b/conf/common.mk @@ -426,6 +426,37 @@ grub_fstest_init.c: grub_fstest_init.lst $(filter-out grub_fstest_init.c,$(grub_ rm -f $@; sh $(srcdir)/geninit.sh $< $(filter %.c,$^) > $@ DISTCLEANFILES += grub_fstest_init.c +# for grub-editenv +bin_UTILITIES += grub-editenv +grub_editenv_SOURCES = util/grub-editenv.c util/envblk.c util/misc.c kern/misc.c kern/err.c +CLEANFILES += grub-editenv grub_editenv-util_grub_editenv.o grub_editenv-util_envblk.o grub_editenv-util_misc.o grub_editenv-kern_misc.o grub_editenv-kern_err.o +MOSTLYCLEANFILES += grub_editenv-util_grub_editenv.d grub_editenv-util_envblk.d grub_editenv-util_misc.d grub_editenv-kern_misc.d grub_editenv-kern_err.d + +grub-editenv: $(grub_editenv_DEPENDENCIES) grub_editenv-util_grub_editenv.o grub_editenv-util_envblk.o grub_editenv-util_misc.o grub_editenv-kern_misc.o grub_editenv-kern_err.o + $(CC) -o $@ grub_editenv-util_grub_editenv.o grub_editenv-util_envblk.o grub_editenv-util_misc.o grub_editenv-kern_misc.o grub_editenv-kern_err.o $(LDFLAGS) $(grub_editenv_LDFLAGS) + +grub_editenv-util_grub_editenv.o: util/grub-editenv.c $(util/grub-editenv.c_DEPENDENCIES) + $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_editenv_CFLAGS) -MD -c -o $@ $< +-include grub_editenv-util_grub_editenv.d + +grub_editenv-util_envblk.o: util/envblk.c $(util/envblk.c_DEPENDENCIES) + $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_editenv_CFLAGS) -MD -c -o $@ $< +-include grub_editenv-util_envblk.d + +grub_editenv-util_misc.o: util/misc.c $(util/misc.c_DEPENDENCIES) + $(CC) -Iutil -I$(srcdir)/util $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_editenv_CFLAGS) -MD -c -o $@ $< +-include grub_editenv-util_misc.d + +grub_editenv-kern_misc.o: kern/misc.c $(kern/misc.c_DEPENDENCIES) + $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_editenv_CFLAGS) -MD -c -o $@ $< +-include grub_editenv-kern_misc.d + +grub_editenv-kern_err.o: kern/err.c $(kern/err.c_DEPENDENCIES) + $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_editenv_CFLAGS) -MD -c -o $@ $< +-include grub_editenv-kern_err.d + +CLEANFILES += grub-editenv + # For update-grub update-grub: util/update-grub.in config.status ./config.status --file=$@:$< @@ -1940,7 +1971,7 @@ pkglib_MODULES += hello.mod boot.mod terminal.mod ls.mod \ cmp.mod cat.mod help.mod font.mod search.mod \ loopback.mod fs_uuid.mod configfile.mod echo.mod \ terminfo.mod test.mod blocklist.mod hexdump.mod \ - read.mod sleep.mod + read.mod sleep.mod loadenv.mod # For hello.mod. hello_mod_SOURCES = hello/hello.c @@ -2913,6 +2944,193 @@ partmap-hexdump_mod-commands_hexdump.lst: commands/hexdump.c $(commands/hexdump. hexdump_mod_CFLAGS = $(COMMON_CFLAGS) hexdump_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For read.mod. +read_mod_SOURCES = commands/read.c +CLEANFILES += read.mod mod-read.o mod-read.c pre-read.o read_mod-commands_read.o und-read.lst +ifneq ($(read_mod_EXPORTS),no) +CLEANFILES += def-read.lst +DEFSYMFILES += def-read.lst +endif +MOSTLYCLEANFILES += read_mod-commands_read.d +UNDSYMFILES += und-read.lst + +read.mod: pre-read.o mod-read.o + -rm -f $@ + $(TARGET_CC) $(read_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^ + $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@ + +pre-read.o: $(read_mod_DEPENDENCIES) read_mod-commands_read.o + -rm -f $@ + $(TARGET_CC) $(read_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ read_mod-commands_read.o + +mod-read.o: mod-read.c + $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(read_mod_CFLAGS) -c -o $@ $< + +mod-read.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'read' $< > $@ || (rm -f $@; exit 1) + +ifneq ($(read_mod_EXPORTS),no) +def-read.lst: pre-read.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 read/' > $@ +endif + +und-read.lst: pre-read.o + echo 'read' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +read_mod-commands_read.o: commands/read.c $(commands/read.c_DEPENDENCIES) + $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(read_mod_CFLAGS) -MD -c -o $@ $< +-include read_mod-commands_read.d + +CLEANFILES += cmd-read_mod-commands_read.lst fs-read_mod-commands_read.lst partmap-read_mod-commands_read.lst +COMMANDFILES += cmd-read_mod-commands_read.lst +FSFILES += fs-read_mod-commands_read.lst +PARTMAPFILES += partmap-read_mod-commands_read.lst + +cmd-read_mod-commands_read.lst: commands/read.c $(commands/read.c_DEPENDENCIES) gencmdlist.sh + set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(read_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh read > $@ || (rm -f $@; exit 1) + +fs-read_mod-commands_read.lst: commands/read.c $(commands/read.c_DEPENDENCIES) genfslist.sh + set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(read_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh read > $@ || (rm -f $@; exit 1) + +partmap-read_mod-commands_read.lst: commands/read.c $(commands/read.c_DEPENDENCIES) genpartmaplist.sh + set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(read_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh read > $@ || (rm -f $@; exit 1) + + +read_mod_CFLAGS = $(COMMON_CFLAGS) +read_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For sleep.mod. +sleep_mod_SOURCES = commands/sleep.c +CLEANFILES += sleep.mod mod-sleep.o mod-sleep.c pre-sleep.o sleep_mod-commands_sleep.o und-sleep.lst +ifneq ($(sleep_mod_EXPORTS),no) +CLEANFILES += def-sleep.lst +DEFSYMFILES += def-sleep.lst +endif +MOSTLYCLEANFILES += sleep_mod-commands_sleep.d +UNDSYMFILES += und-sleep.lst + +sleep.mod: pre-sleep.o mod-sleep.o + -rm -f $@ + $(TARGET_CC) $(sleep_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^ + $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@ + +pre-sleep.o: $(sleep_mod_DEPENDENCIES) sleep_mod-commands_sleep.o + -rm -f $@ + $(TARGET_CC) $(sleep_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ sleep_mod-commands_sleep.o + +mod-sleep.o: mod-sleep.c + $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sleep_mod_CFLAGS) -c -o $@ $< + +mod-sleep.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'sleep' $< > $@ || (rm -f $@; exit 1) + +ifneq ($(sleep_mod_EXPORTS),no) +def-sleep.lst: pre-sleep.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 sleep/' > $@ +endif + +und-sleep.lst: pre-sleep.o + echo 'sleep' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +sleep_mod-commands_sleep.o: commands/sleep.c $(commands/sleep.c_DEPENDENCIES) + $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sleep_mod_CFLAGS) -MD -c -o $@ $< +-include sleep_mod-commands_sleep.d + +CLEANFILES += cmd-sleep_mod-commands_sleep.lst fs-sleep_mod-commands_sleep.lst partmap-sleep_mod-commands_sleep.lst +COMMANDFILES += cmd-sleep_mod-commands_sleep.lst +FSFILES += fs-sleep_mod-commands_sleep.lst +PARTMAPFILES += partmap-sleep_mod-commands_sleep.lst + +cmd-sleep_mod-commands_sleep.lst: commands/sleep.c $(commands/sleep.c_DEPENDENCIES) gencmdlist.sh + set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sleep_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh sleep > $@ || (rm -f $@; exit 1) + +fs-sleep_mod-commands_sleep.lst: commands/sleep.c $(commands/sleep.c_DEPENDENCIES) genfslist.sh + set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sleep_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh sleep > $@ || (rm -f $@; exit 1) + +partmap-sleep_mod-commands_sleep.lst: commands/sleep.c $(commands/sleep.c_DEPENDENCIES) genpartmaplist.sh + set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sleep_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh sleep > $@ || (rm -f $@; exit 1) + + +sleep_mod_CFLAGS = $(COMMON_CFLAGS) +sleep_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For loadenv.mod. +loadenv_mod_SOURCES = commands/loadenv.c util/envblk.c +CLEANFILES += loadenv.mod mod-loadenv.o mod-loadenv.c pre-loadenv.o loadenv_mod-commands_loadenv.o loadenv_mod-util_envblk.o und-loadenv.lst +ifneq ($(loadenv_mod_EXPORTS),no) +CLEANFILES += def-loadenv.lst +DEFSYMFILES += def-loadenv.lst +endif +MOSTLYCLEANFILES += loadenv_mod-commands_loadenv.d loadenv_mod-util_envblk.d +UNDSYMFILES += und-loadenv.lst + +loadenv.mod: pre-loadenv.o mod-loadenv.o + -rm -f $@ + $(TARGET_CC) $(loadenv_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^ + $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@ + +pre-loadenv.o: $(loadenv_mod_DEPENDENCIES) loadenv_mod-commands_loadenv.o loadenv_mod-util_envblk.o + -rm -f $@ + $(TARGET_CC) $(loadenv_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ loadenv_mod-commands_loadenv.o loadenv_mod-util_envblk.o + +mod-loadenv.o: mod-loadenv.c + $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -c -o $@ $< + +mod-loadenv.c: moddep.lst genmodsrc.sh + sh $(srcdir)/genmodsrc.sh 'loadenv' $< > $@ || (rm -f $@; exit 1) + +ifneq ($(loadenv_mod_EXPORTS),no) +def-loadenv.lst: pre-loadenv.o + $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 loadenv/' > $@ +endif + +und-loadenv.lst: pre-loadenv.o + echo 'loadenv' > $@ + $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ + +loadenv_mod-commands_loadenv.o: commands/loadenv.c $(commands/loadenv.c_DEPENDENCIES) + $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -MD -c -o $@ $< +-include loadenv_mod-commands_loadenv.d + +CLEANFILES += cmd-loadenv_mod-commands_loadenv.lst fs-loadenv_mod-commands_loadenv.lst partmap-loadenv_mod-commands_loadenv.lst +COMMANDFILES += cmd-loadenv_mod-commands_loadenv.lst +FSFILES += fs-loadenv_mod-commands_loadenv.lst +PARTMAPFILES += partmap-loadenv_mod-commands_loadenv.lst + +cmd-loadenv_mod-commands_loadenv.lst: commands/loadenv.c $(commands/loadenv.c_DEPENDENCIES) gencmdlist.sh + set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh loadenv > $@ || (rm -f $@; exit 1) + +fs-loadenv_mod-commands_loadenv.lst: commands/loadenv.c $(commands/loadenv.c_DEPENDENCIES) genfslist.sh + set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh loadenv > $@ || (rm -f $@; exit 1) + +partmap-loadenv_mod-commands_loadenv.lst: commands/loadenv.c $(commands/loadenv.c_DEPENDENCIES) genpartmaplist.sh + set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh loadenv > $@ || (rm -f $@; exit 1) + + +loadenv_mod-util_envblk.o: util/envblk.c $(util/envblk.c_DEPENDENCIES) + $(TARGET_CC) -Iutil -I$(srcdir)/util $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -MD -c -o $@ $< +-include loadenv_mod-util_envblk.d + +CLEANFILES += cmd-loadenv_mod-util_envblk.lst fs-loadenv_mod-util_envblk.lst partmap-loadenv_mod-util_envblk.lst +COMMANDFILES += cmd-loadenv_mod-util_envblk.lst +FSFILES += fs-loadenv_mod-util_envblk.lst +PARTMAPFILES += partmap-loadenv_mod-util_envblk.lst + +cmd-loadenv_mod-util_envblk.lst: util/envblk.c $(util/envblk.c_DEPENDENCIES) gencmdlist.sh + set -e; $(TARGET_CC) -Iutil -I$(srcdir)/util $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh loadenv > $@ || (rm -f $@; exit 1) + +fs-loadenv_mod-util_envblk.lst: util/envblk.c $(util/envblk.c_DEPENDENCIES) genfslist.sh + set -e; $(TARGET_CC) -Iutil -I$(srcdir)/util $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh loadenv > $@ || (rm -f $@; exit 1) + +partmap-loadenv_mod-util_envblk.lst: util/envblk.c $(util/envblk.c_DEPENDENCIES) genpartmaplist.sh + set -e; $(TARGET_CC) -Iutil -I$(srcdir)/util $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(loadenv_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh loadenv > $@ || (rm -f $@; exit 1) + + +loadenv_mod_CFLAGS = $(COMMON_CFLAGS) +loadenv_mod_LDFLAGS = $(COMMON_LDFLAGS) + # Misc. pkglib_MODULES += gzio.mod elf.mod @@ -3027,115 +3245,3 @@ partmap-gzio_mod-io_gzio.lst: io/gzio.c $(io/gzio.c_DEPENDENCIES) genpartmaplist gzio_mod_CFLAGS = $(COMMON_CFLAGS) gzio_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For read.mod. -read_mod_SOURCES = commands/read.c -CLEANFILES += read.mod mod-read.o mod-read.c pre-read.o read_mod-commands_read.o und-read.lst -ifneq ($(read_mod_EXPORTS),no) -CLEANFILES += def-read.lst -DEFSYMFILES += def-read.lst -endif -MOSTLYCLEANFILES += read_mod-commands_read.d -UNDSYMFILES += und-read.lst - -read.mod: pre-read.o mod-read.o - -rm -f $@ - $(TARGET_CC) $(read_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^ - $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@ - -pre-read.o: $(read_mod_DEPENDENCIES) read_mod-commands_read.o - -rm -f $@ - $(TARGET_CC) $(read_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ read_mod-commands_read.o - -mod-read.o: mod-read.c - $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(read_mod_CFLAGS) -c -o $@ $< - -mod-read.c: moddep.lst genmodsrc.sh - sh $(srcdir)/genmodsrc.sh 'read' $< > $@ || (rm -f $@; exit 1) - -ifneq ($(read_mod_EXPORTS),no) -def-read.lst: pre-read.o - $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 read/' > $@ -endif - -und-read.lst: pre-read.o - echo 'read' > $@ - $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ - -read_mod-commands_read.o: commands/read.c $(commands/read.c_DEPENDENCIES) - $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(read_mod_CFLAGS) -MD -c -o $@ $< --include read_mod-commands_read.d - -CLEANFILES += cmd-read_mod-commands_read.lst fs-read_mod-commands_read.lst partmap-read_mod-commands_read.lst -COMMANDFILES += cmd-read_mod-commands_read.lst -FSFILES += fs-read_mod-commands_read.lst -PARTMAPFILES += partmap-read_mod-commands_read.lst - -cmd-read_mod-commands_read.lst: commands/read.c $(commands/read.c_DEPENDENCIES) gencmdlist.sh - set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(read_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh read > $@ || (rm -f $@; exit 1) - -fs-read_mod-commands_read.lst: commands/read.c $(commands/read.c_DEPENDENCIES) genfslist.sh - set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(read_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh read > $@ || (rm -f $@; exit 1) - -partmap-read_mod-commands_read.lst: commands/read.c $(commands/read.c_DEPENDENCIES) genpartmaplist.sh - set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(read_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh read > $@ || (rm -f $@; exit 1) - - -read_mod_CFLAGS = $(COMMON_CFLAGS) -read_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For sleep.mod. -sleep_mod_SOURCES = commands/sleep.c -CLEANFILES += sleep.mod mod-sleep.o mod-sleep.c pre-sleep.o sleep_mod-commands_sleep.o und-sleep.lst -ifneq ($(sleep_mod_EXPORTS),no) -CLEANFILES += def-sleep.lst -DEFSYMFILES += def-sleep.lst -endif -MOSTLYCLEANFILES += sleep_mod-commands_sleep.d -UNDSYMFILES += und-sleep.lst - -sleep.mod: pre-sleep.o mod-sleep.o - -rm -f $@ - $(TARGET_CC) $(sleep_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ $^ - $(STRIP) --strip-unneeded -K grub_mod_init -K grub_mod_fini -R .note -R .comment $@ - -pre-sleep.o: $(sleep_mod_DEPENDENCIES) sleep_mod-commands_sleep.o - -rm -f $@ - $(TARGET_CC) $(sleep_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ sleep_mod-commands_sleep.o - -mod-sleep.o: mod-sleep.c - $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sleep_mod_CFLAGS) -c -o $@ $< - -mod-sleep.c: moddep.lst genmodsrc.sh - sh $(srcdir)/genmodsrc.sh 'sleep' $< > $@ || (rm -f $@; exit 1) - -ifneq ($(sleep_mod_EXPORTS),no) -def-sleep.lst: pre-sleep.o - $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 sleep/' > $@ -endif - -und-sleep.lst: pre-sleep.o - echo 'sleep' > $@ - $(NM) -u -P -p $< | cut -f1 -d' ' >> $@ - -sleep_mod-commands_sleep.o: commands/sleep.c $(commands/sleep.c_DEPENDENCIES) - $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sleep_mod_CFLAGS) -MD -c -o $@ $< --include sleep_mod-commands_sleep.d - -CLEANFILES += cmd-sleep_mod-commands_sleep.lst fs-sleep_mod-commands_sleep.lst partmap-sleep_mod-commands_sleep.lst -COMMANDFILES += cmd-sleep_mod-commands_sleep.lst -FSFILES += fs-sleep_mod-commands_sleep.lst -PARTMAPFILES += partmap-sleep_mod-commands_sleep.lst - -cmd-sleep_mod-commands_sleep.lst: commands/sleep.c $(commands/sleep.c_DEPENDENCIES) gencmdlist.sh - set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sleep_mod_CFLAGS) -E $< | sh $(srcdir)/gencmdlist.sh sleep > $@ || (rm -f $@; exit 1) - -fs-sleep_mod-commands_sleep.lst: commands/sleep.c $(commands/sleep.c_DEPENDENCIES) genfslist.sh - set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sleep_mod_CFLAGS) -E $< | sh $(srcdir)/genfslist.sh sleep > $@ || (rm -f $@; exit 1) - -partmap-sleep_mod-commands_sleep.lst: commands/sleep.c $(commands/sleep.c_DEPENDENCIES) genpartmaplist.sh - set -e; $(TARGET_CC) -Icommands -I$(srcdir)/commands $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(sleep_mod_CFLAGS) -E $< | sh $(srcdir)/genpartmaplist.sh sleep > $@ || (rm -f $@; exit 1) - - -sleep_mod_CFLAGS = $(COMMON_CFLAGS) -sleep_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/conf/common.rmk b/conf/common.rmk index f34a2bf3b..ecb8e040b 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -94,6 +94,11 @@ grub_fstest_init.c: grub_fstest_init.lst $(filter-out grub_fstest_init.c,$(grub_ rm -f $@; sh $(srcdir)/geninit.sh $< $(filter %.c,$^) > $@ DISTCLEANFILES += grub_fstest_init.c +# for grub-editenv +bin_UTILITIES += grub-editenv +grub_editenv_SOURCES = util/grub-editenv.c util/envblk.c util/misc.c kern/misc.c kern/err.c +CLEANFILES += grub-editenv + # For update-grub update-grub: util/update-grub.in config.status ./config.status --file=$@:$< @@ -282,7 +287,7 @@ pkglib_MODULES += hello.mod boot.mod terminal.mod ls.mod \ cmp.mod cat.mod help.mod font.mod search.mod \ loopback.mod fs_uuid.mod configfile.mod echo.mod \ terminfo.mod test.mod blocklist.mod hexdump.mod \ - read.mod sleep.mod + read.mod sleep.mod loadenv.mod # For hello.mod. hello_mod_SOURCES = hello/hello.c @@ -369,6 +374,21 @@ hexdump_mod_SOURCES = commands/hexdump.c hexdump_mod_CFLAGS = $(COMMON_CFLAGS) hexdump_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For read.mod. +read_mod_SOURCES = commands/read.c +read_mod_CFLAGS = $(COMMON_CFLAGS) +read_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For sleep.mod. +sleep_mod_SOURCES = commands/sleep.c +sleep_mod_CFLAGS = $(COMMON_CFLAGS) +sleep_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For loadenv.mod. +loadenv_mod_SOURCES = commands/loadenv.c util/envblk.c +loadenv_mod_CFLAGS = $(COMMON_CFLAGS) +loadenv_mod_LDFLAGS = $(COMMON_LDFLAGS) + # Misc. pkglib_MODULES += gzio.mod elf.mod @@ -381,13 +401,3 @@ elf_mod_LDFLAGS = $(COMMON_LDFLAGS) gzio_mod_SOURCES = io/gzio.c gzio_mod_CFLAGS = $(COMMON_CFLAGS) gzio_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For read.mod. -read_mod_SOURCES = commands/read.c -read_mod_CFLAGS = $(COMMON_CFLAGS) -read_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For sleep.mod. -sleep_mod_SOURCES = commands/sleep.c -sleep_mod_CFLAGS = $(COMMON_CFLAGS) -sleep_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/include/grub/envblk.h b/include/grub/envblk.h new file mode 100644 index 000000000..5c1157e8f --- /dev/null +++ b/include/grub/envblk.h @@ -0,0 +1,45 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_ENVBLK_HEADER +#define GRUB_ENVBLK_HEADER 1 + +#define GRUB_ENVBLK_SIGNATURE 0x764e6547 /* GeNv */ + +#define GRUB_ENVBLK_MAXLEN 8192 + +#define GRUB_ENVBLK_DEFCFG "grubenv" + +#ifndef ASM_FILE + +struct grub_envblk +{ + grub_uint32_t signature; + grub_uint16_t length; + char data[0]; +} __attribute__ ((packed)); +typedef struct grub_envblk *grub_envblk_t; + +grub_envblk_t grub_envblk_find (char *buf); +int grub_envblk_insert (grub_envblk_t envblk, char *name, char *value); +void grub_envblk_delete (grub_envblk_t envblk, char *name); +void grub_envblk_iterate (grub_envblk_t envblk, int hook (char *name, char *value)); + +#endif + +#endif /* ! GRUB_ENVBLK_HEADER */ diff --git a/util/envblk.c b/util/envblk.c new file mode 100644 index 000000000..9cea7d6f9 --- /dev/null +++ b/util/envblk.c @@ -0,0 +1,156 @@ +/* envblk.c - Common function for environment block. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include + +grub_envblk_t +grub_envblk_find (char *buf) +{ + grub_uint32_t *pd; + int len; + + pd = (grub_uint32_t *) buf; + + for (len = GRUB_ENVBLK_MAXLEN - 6; len > 0; len -= 4, pd++) + if (*pd == GRUB_ENVBLK_SIGNATURE) + { + grub_envblk_t p; + + p = (grub_envblk_t) pd; + if (p->length <= len) + return p; + } + + return 0; +} + +int +grub_envblk_insert (grub_envblk_t envblk, char *name, char *value) +{ + char *p, *pend; + char *found = 0; + int nl; + + nl = grub_strlen (name); + p = envblk->data; + pend = p + envblk->length; + + while (*p) + { + if ((! found) && (! grub_memcmp (name, p, nl)) && (p[nl] == '=')) + found = p + nl + 1; + + p += grub_strlen (p) + 1; + if (p >= pend) + return 1; + } + + if (found) + { + int len1, len2; + + len1 = grub_strlen (found); + len2 = grub_strlen (value); + if ((p - envblk->data) + 1 - len1 + len2 > envblk->length) + return 1; + + grub_memcpy (found + len2 + 1, found + len1 + 1, (p - found) - len1); + grub_strcpy (found, value); + } + else + { + int len2 = grub_strlen (value); + + if ((p - envblk->data) + nl + 1 + len2 + 2 > envblk->length) + return 1; + + grub_strcpy (p, name); + p[nl] = '='; + grub_strcpy (p + nl + 1, value); + p[nl + 1 + len2 + 1] = 0; + } + + return 0; +} + +void +grub_envblk_delete (grub_envblk_t envblk, char *name) +{ + char *p, *pend; + char *found = 0; + int nl; + + nl = grub_strlen (name); + p = envblk->data; + pend = p + envblk->length; + + while (*p) + { + if ((! found) && (! grub_memcmp (name, p, nl)) && (p[nl] == '=')) + found = p; + + p += grub_strlen (p) + 1; + if (p >= pend) + return; + } + + if (found) + { + int len; + + len = grub_strlen (found); + grub_memcpy (found, found + len + 1, (p - found) - len); + } +} + +void +grub_envblk_iterate (grub_envblk_t envblk, + int hook (char *name, char *value)) +{ + char *p, *pend; + + p = envblk->data; + pend = p + envblk->length; + + while (*p) + { + char *v; + int r; + + v = grub_strchr (p, '='); + if (v) + { + *v = 0; + r = hook (p, v + 1); + *v = '='; + } + else + r = hook (p, ""); + + if (r) + break; + + p += grub_strlen (p) + 1; + if (p >= pend) + break; + } +} diff --git a/util/grub-editenv.c b/util/grub-editenv.c new file mode 100644 index 000000000..b2b2d679b --- /dev/null +++ b/util/grub-editenv.c @@ -0,0 +1,258 @@ +/* grub-editenv.c - tool to edit environment block. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +void +grub_putchar (int c) +{ + putchar (c); +} + +void +grub_refresh (void) +{ + fflush (stdout); +} + +void * +grub_term_get_current (void) +{ + return 0; +} + +int +grub_getkey (void) +{ + return 0; +} + +char * +grub_env_get (const char *name __attribute__ ((unused))) +{ + return NULL; +} + +static struct option options[] = { + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {"verbose", no_argument, 0, 'v'}, + {0, 0, 0, 0} +}; + +char buffer[GRUB_ENVBLK_MAXLEN]; +grub_envblk_t envblk; + +static void +usage (int status) +{ + if (status) + fprintf (stderr, "Try ``grub-editenv --help'' for more information.\n"); + else + printf ("\ +Usage: grub-editenv [OPTIONS] FILENAME COMMAND\n\ +\n\ +Tool to edit environment block.\n\ +\nCommands:\n\ + create create a blank environment block file\n\ + info show information about the environment block\n\ + list list the current variables\n\ + set [name=value] ... change/delete variables\n\ + clear delete all variables\n\ +\nOptions:\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", PACKAGE_BUGREPORT); + + exit (status); +} + +int +create_envblk_file (char *name) +{ + FILE *f; + grub_envblk_t p; + + f = fopen (name, "wb"); + if (! f) + return 1; + + /* Just in case OS don't save 0s. */ + memset (buffer, -1, sizeof (buffer)); + + p = (grub_envblk_t) &buffer[0]; + p->signature = GRUB_ENVBLK_SIGNATURE; + p->length = sizeof (buffer) - sizeof (struct grub_envblk); + p->data[0] = p->data[1] = 0; + + fwrite (buffer, sizeof (buffer), 1, f); + + fclose (f); + return 0; +} + +FILE * +open_envblk_file (char *name) +{ + FILE *f; + + f = fopen (name, "r+b"); + if (! f) + grub_util_error ("Can\'t open file %s", name); + + if (fread (buffer, 1, sizeof (buffer), f) != sizeof (buffer)) + grub_util_error ("The envblk file is too short"); + + envblk = grub_envblk_find (buffer); + if (! envblk) + grub_util_error ("Can\'t find environment block"); + + return f; +} + +static void +cmd_info (void) +{ + printf ("Envblk offset: %d\n", envblk->data - buffer); + printf ("Envblk length: %d\n", envblk->length); +} + +static void +cmd_list (void) +{ + auto int hook (char *name, char *value); + int hook (char *name, char *value) + { + printf ("%s=%s\n", name, value); + return 0; + } + + grub_envblk_iterate (envblk, hook); +} + +static void +cmd_set (int argc, char *argv[]) +{ + while (argc) + { + char *p; + + p = strchr (argv[0], '='); + if (! p) + grub_util_error ("Invalid parameter"); + + *(p++) = 0; + + if (*p) + { + if (grub_envblk_insert (envblk, argv[0], p)) + grub_util_error ("Environment block too small"); + } + else + grub_envblk_delete (envblk, argv[0]); + + argc--; + argv++; + } +} + +static void +cmd_clear (void) +{ + envblk->data[0] = envblk->data[1] = 0; +} + +int +main (int argc, char *argv[]) +{ + FILE *f; + + progname = "grub-editenv"; + + /* Check for options. */ + while (1) + { + int c = getopt_long (argc, argv, "hVv", options, 0); + + if (c == -1) + break; + else + switch (c) + { + case 'h': + usage (0); + break; + + case 'V': + printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION); + return 0; + + case 'v': + verbosity++; + break; + + default: + usage (1); + break; + } + } + + /* Obtain PATH. */ + if (optind + 1 >= argc) + { + fprintf (stderr, "Not enough parameter.\n"); + usage (1); + } + + if (! strcmp (argv[optind + 1], "create")) + return create_envblk_file (argv[optind]); + + f = open_envblk_file (argv[optind]); + + optind++; + if (! strcmp (argv[optind], "info")) + cmd_info (); + else if (! strcmp (argv[optind], "list")) + cmd_list (); + else + { + if (! strcmp (argv[optind], "set")) + cmd_set (argc - optind - 1, argv + optind + 1); + else if (! strcmp (argv[optind], "clear")) + cmd_clear (); + + fseek (f, 0, SEEK_SET); + fwrite (buffer, sizeof (buffer), 1, f); + } + fclose (f); + + return 0; +}