238 lines
5.1 KiB
C
238 lines
5.1 KiB
C
/*
|
|
* exec.c
|
|
*
|
|
* Created on: Aug 14, 2008
|
|
* Author: Stefan Bucur <stefanb@zytor.com>
|
|
*/
|
|
|
|
#include <sys/module.h>
|
|
#include <sys/exec.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <setjmp.h>
|
|
#include <setjmp.h>
|
|
#include <alloca.h>
|
|
#include <dprintf.h>
|
|
|
|
#define DBG_PRINT(fmt, args...) dprintf("[EXEC] " fmt, ##args)
|
|
|
|
struct elf_module *__syslinux_current = NULL;
|
|
|
|
int get_module_type(struct elf_module *module)
|
|
{
|
|
if(module->main_func) return EXEC_MODULE;
|
|
return LIB_MODULE;
|
|
}
|
|
|
|
jmp_buf __process_exit_jmp;
|
|
|
|
#if 0
|
|
int spawnv(const char *name, const char **argv)
|
|
{
|
|
int res, ret_val = 0;
|
|
const char **arg;
|
|
int argc;
|
|
char **argp, **args;
|
|
struct elf_module *previous;
|
|
malloc_tag_t prev_mem_tag;
|
|
|
|
struct elf_module *module = module_alloc(name);
|
|
|
|
if (module == NULL)
|
|
return -1;
|
|
|
|
res = module_load(module);
|
|
if (res != 0) {
|
|
module_unload(module);
|
|
return res;
|
|
}
|
|
|
|
if (module->main_func == NULL) {
|
|
// We can't execute without a main function
|
|
module_unload(module);
|
|
return -1;
|
|
}
|
|
/*if (module->main_func != NULL) {
|
|
const char **last_arg = argv;
|
|
void *old_tag;
|
|
while (*last_arg != NULL)
|
|
last_arg++;
|
|
|
|
// Setup the memory allocation context
|
|
old_tag = __mem_get_tag_global();
|
|
__mem_set_tag_global(module);
|
|
|
|
// Execute the program
|
|
ret_val = (*(module->main_func))(last_arg - argv, argv);
|
|
|
|
// Clean up the allocation context
|
|
__free_tagged(module);
|
|
// Restore the allocation context
|
|
__mem_set_tag_global(old_tag);
|
|
} else {
|
|
// We can't execute without a main function
|
|
module_unload(module);
|
|
return -1;
|
|
}*/
|
|
// Set up the process context
|
|
previous = __syslinux_current;
|
|
prev_mem_tag = __mem_get_tag_global();
|
|
|
|
// Setup the new process context
|
|
__syslinux_current = module;
|
|
__mem_set_tag_global((malloc_tag_t)module);
|
|
|
|
// Generate a new process copy of argv (on the stack)
|
|
argc = 0;
|
|
for (arg = argv; *arg; arg++)
|
|
argc++;
|
|
|
|
args = alloca((argc+1) * sizeof(char *));
|
|
|
|
for (arg = argv, argp = args; *arg; arg++, argp++) {
|
|
size_t l = strlen(*arg)+1;
|
|
*argp = alloca(l);
|
|
memcpy(*argp, *arg, l);
|
|
}
|
|
|
|
*args = NULL;
|
|
|
|
// Execute the program
|
|
ret_val = setjmp(module->u.x.process_exit);
|
|
|
|
if (ret_val)
|
|
ret_val--; /* Valid range is 0-255 */
|
|
else if (!module->main_func)
|
|
ret_val = -1;
|
|
else
|
|
exit((module->main_func)(argc, args)); /* Actually run! */
|
|
|
|
// Clean up the allocation context
|
|
__free_tagged(module);
|
|
// Restore the allocation context
|
|
__mem_set_tag_global(prev_mem_tag);
|
|
// Restore the process context
|
|
__syslinux_current = previous;
|
|
|
|
res = module_unload(module);
|
|
|
|
if (res != 0) {
|
|
return res;
|
|
}
|
|
|
|
return ((unsigned int)ret_val & 0xFF);
|
|
}
|
|
|
|
int spawnl(const char *name, const char *arg, ...)
|
|
{
|
|
/*
|
|
* NOTE: We assume the standard ABI specification for the i386
|
|
* architecture. This code may not work if used in other
|
|
* circumstances, including non-variadic functions, different
|
|
* architectures and calling conventions.
|
|
*/
|
|
return spawnv(name, &arg);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Load a module and runs its start function.
|
|
*
|
|
* For library modules the start function is module->init_func and for
|
|
* executable modules its module->main_func.
|
|
*
|
|
* "name" is the name of the module to load.
|
|
*
|
|
* "argv" and "argc" are only passed to module->main_func, for library
|
|
* modules these arguments can be NULL and 0, respectively.
|
|
*
|
|
* "argv" is an array of arguments to pass to module->main_func.
|
|
* argv[0] must be a pointer to "name" and argv[argc] must be NULL.
|
|
*
|
|
* "argc" is the number of arguments in "argv".
|
|
*/
|
|
int spawn_load(const char *name, int argc, char **argv)
|
|
{
|
|
int res, ret_val = 0;
|
|
struct elf_module *previous;
|
|
//malloc_tag_t prev_mem_tag;
|
|
struct elf_module *module = module_alloc(name);
|
|
struct elf_module *cur_module;
|
|
int type;
|
|
|
|
dprintf("enter: name = %s", name);
|
|
|
|
if (module == NULL)
|
|
return -1;
|
|
|
|
if (get_module_type(module) == EXEC_MODULE) {
|
|
if (!argc || !argv || strcmp(argv[0], name)) {
|
|
dprintf("invalid args for %s\n", name);
|
|
res = -1;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
cur_module = module_current();
|
|
if (!strcmp(cur_module->name, module->name)) {
|
|
dprintf("We is running this module %s already!", module->name);
|
|
|
|
module_unload(cur_module);
|
|
}
|
|
|
|
res = module_load(module);
|
|
if (res != 0) {
|
|
dprintf("failed to load module %s\n", module->name);
|
|
goto out;
|
|
}
|
|
|
|
type = get_module_type(module);
|
|
|
|
dprintf("type = %d, prev = %s, cur = %s",
|
|
type, cur_module->name, module->name);
|
|
|
|
if(type==EXEC_MODULE)
|
|
{
|
|
previous = __syslinux_current;
|
|
//prev_mem_tag = __mem_get_tag_global();
|
|
|
|
// Setup the new process context
|
|
__syslinux_current = module;
|
|
//__mem_set_tag_global((malloc_tag_t)module);
|
|
|
|
// Execute the program
|
|
ret_val = setjmp(module->u.x.process_exit);
|
|
|
|
if (ret_val)
|
|
ret_val--; /* Valid range is 0-255 */
|
|
else if (!module->main_func)
|
|
ret_val = -1;
|
|
else
|
|
exit((module->main_func)(argc, argv)); /* Actually run! */
|
|
|
|
// Clean up the allocation context
|
|
//__free_tagged(module);
|
|
// Restore the allocation context
|
|
//__mem_set_tag_global(prev_mem_tag);
|
|
// Restore the process context
|
|
__syslinux_current = previous;
|
|
|
|
res = module_unload(module);
|
|
|
|
if (res != 0)
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
if (res)
|
|
_module_unload(module);
|
|
return res;
|
|
}
|
|
|
|
void exec_term(void)
|
|
{
|
|
modules_term();
|
|
}
|