vaseboot/VasEBoot-core/normal/dyncmd.c

211 lines
4.5 KiB
C

/* dyncmd.c - support dynamic command */
/*
* VasEBoot -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* VasEBoot 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.
*
* VasEBoot 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 VasEBoot. If not, see <http://www.gnu.org/licenses/>.
*/
#include <VasEBoot/dl.h>
#include <VasEBoot/mm.h>
#include <VasEBoot/env.h>
#include <VasEBoot/misc.h>
#include <VasEBoot/command.h>
#include <VasEBoot/normal.h>
#include <VasEBoot/extcmd.h>
#include <VasEBoot/script_sh.h>
#include <VasEBoot/i18n.h>
VasEBoot_command_t
VasEBoot_dyncmd_get_cmd (VasEBoot_command_t cmd)
{
VasEBoot_extcmd_t extcmd = cmd->data;
char *modname;
char *name;
VasEBoot_dl_t mod;
modname = extcmd->data;
mod = VasEBoot_dl_load (modname);
if (!mod)
return NULL;
VasEBoot_free (modname);
VasEBoot_dl_ref (mod);
name = (char *) cmd->name;
VasEBoot_unregister_extcmd (extcmd);
cmd = VasEBoot_command_find (name);
VasEBoot_free (name);
return cmd;
}
static VasEBoot_err_t
VasEBoot_dyncmd_dispatcher (struct VasEBoot_extcmd_context *ctxt,
int argc, char **args)
{
char *modname;
VasEBoot_dl_t mod;
VasEBoot_err_t ret;
VasEBoot_extcmd_t extcmd = ctxt->extcmd;
VasEBoot_command_t cmd = extcmd->cmd;
char *name;
modname = extcmd->data;
mod = VasEBoot_dl_load (modname);
if (!mod)
return VasEBoot_errno;
VasEBoot_free (modname);
VasEBoot_dl_ref (mod);
name = (char *) cmd->name;
VasEBoot_unregister_extcmd (extcmd);
cmd = VasEBoot_command_find (name);
if (cmd)
{
if (cmd->flags & VasEBoot_COMMAND_FLAG_BLOCKS &&
cmd->flags & VasEBoot_COMMAND_FLAG_EXTCMD)
ret = VasEBoot_extcmd_dispatcher (cmd, argc, args, ctxt->script);
else
ret = (cmd->func) (cmd, argc, args);
}
else
ret = VasEBoot_errno;
VasEBoot_free (name);
return ret;
}
/* Read the file command.lst for auto-loading. */
void
read_command_list (const char *prefix)
{
if (prefix)
{
char *filename;
filename = VasEBoot_xasprintf ("%s/" VasEBoot_TARGET_CPU "-" VasEBoot_PLATFORM
"/command.lst", prefix);
if (filename)
{
VasEBoot_file_t file;
file = VasEBoot_file_open (filename);
if (file)
{
char *buf = NULL;
VasEBoot_command_t ptr, last = 0, next;
/* Override previous commands.lst. */
for (ptr = VasEBoot_command_list; ptr; ptr = next)
{
next = ptr->next;
if (ptr->flags & VasEBoot_COMMAND_FLAG_DYNCMD)
{
if (last)
last->next = ptr->next;
else
VasEBoot_command_list = ptr->next;
VasEBoot_free (ptr->data); /* extcmd struct */
VasEBoot_free (ptr);
}
else
last = ptr;
}
for (;; VasEBoot_free (buf))
{
char *p, *name, *modname;
VasEBoot_extcmd_t cmd;
int prio = 0;
buf = VasEBoot_file_getline (file);
if (! buf)
break;
name = buf;
while (VasEBoot_isspace (name[0]))
name++;
if (*name == '*')
{
name++;
prio++;
}
if (! VasEBoot_isgraph (name[0]))
continue;
p = VasEBoot_strchr (name, ':');
if (! p)
continue;
*p = '\0';
p++;
while (*p == ' ' || *p == '\t')
p++;
if (! VasEBoot_isgraph (*p))
continue;
if (VasEBoot_dl_get (p))
continue;
name = VasEBoot_strdup (name);
if (! name)
continue;
modname = VasEBoot_strdup (p);
if (! modname)
{
VasEBoot_free (name);
continue;
}
cmd = VasEBoot_register_extcmd_prio (name,
VasEBoot_dyncmd_dispatcher,
VasEBoot_COMMAND_FLAG_BLOCKS
| VasEBoot_COMMAND_FLAG_EXTCMD
| VasEBoot_COMMAND_FLAG_DYNCMD,
0, N_("module isn't loaded"),
0, prio);
if (! cmd)
{
VasEBoot_free (name);
VasEBoot_free (modname);
continue;
}
cmd->data = modname;
/* Update the active flag. */
VasEBoot_command_find (name);
}
VasEBoot_file_close (file);
}
VasEBoot_free (filename);
}
}
/* Ignore errors. */
VasEBoot_errno = VasEBoot_ERR_NONE;
}