4 * Created on: Aug 14, 2008
5 * Author: Stefan Bucur <stefanb@zytor.com>
8 #include <sys/module.h>
19 #define DBG_PRINT(fmt, args...) dprintf("[EXEC] " fmt, ##args)
21 struct elf_module
*__syslinux_current
= NULL
;
23 int get_module_type(struct elf_module
*module
)
25 if(module
->main_func
) return EXEC_MODULE
;
29 jmp_buf __process_exit_jmp
;
32 int spawnv(const char *name
, const char **argv
)
38 struct elf_module
*previous
;
39 malloc_tag_t prev_mem_tag
;
41 struct elf_module
*module
= module_alloc(name
);
46 res
= module_load(module
);
48 module_unload(module
);
52 if (module
->main_func
== NULL
) {
53 // We can't execute without a main function
54 module_unload(module
);
57 /*if (module->main_func != NULL) {
58 const char **last_arg = argv;
60 while (*last_arg != NULL)
63 // Setup the memory allocation context
64 old_tag = __mem_get_tag_global();
65 __mem_set_tag_global(module);
67 // Execute the program
68 ret_val = (*(module->main_func))(last_arg - argv, argv);
70 // Clean up the allocation context
71 __free_tagged(module);
72 // Restore the allocation context
73 __mem_set_tag_global(old_tag);
75 // We can't execute without a main function
76 module_unload(module);
79 // Set up the process context
80 previous
= __syslinux_current
;
81 prev_mem_tag
= __mem_get_tag_global();
83 // Setup the new process context
84 __syslinux_current
= module
;
85 __mem_set_tag_global((malloc_tag_t
)module
);
87 // Generate a new process copy of argv (on the stack)
89 for (arg
= argv
; *arg
; arg
++)
92 args
= alloca((argc
+1) * sizeof(char *));
94 for (arg
= argv
, argp
= args
; *arg
; arg
++, argp
++) {
95 size_t l
= strlen(*arg
)+1;
97 memcpy(*argp
, *arg
, l
);
102 // Execute the program
103 ret_val
= setjmp(module
->u
.x
.process_exit
);
106 ret_val
--; /* Valid range is 0-255 */
107 else if (!module
->main_func
)
110 exit((module
->main_func
)(argc
, args
)); /* Actually run! */
112 // Clean up the allocation context
113 __free_tagged(module
);
114 // Restore the allocation context
115 __mem_set_tag_global(prev_mem_tag
);
116 // Restore the process context
117 __syslinux_current
= previous
;
119 res
= module_unload(module
);
125 return ((unsigned int)ret_val
& 0xFF);
128 int spawnl(const char *name
, const char *arg
, ...)
131 * NOTE: We assume the standard ABI specification for the i386
132 * architecture. This code may not work if used in other
133 * circumstances, including non-variadic functions, different
134 * architectures and calling conventions.
136 return spawnv(name
, &arg
);
141 * Load a module and runs its start function.
143 * For library modules the start function is module->init_func and for
144 * executable modules its module->main_func.
146 * "name" is the name of the module to load.
148 * "argv" and "argc" are only passed to module->main_func, for library
149 * modules these arguments can be NULL and 0, respectively.
151 * "argv" is an array of arguments to pass to module->main_func.
152 * argv[0] must be a pointer to "name" and argv[argc] must be NULL.
154 * "argc" is the number of arguments in "argv".
156 int spawn_load(const char *name
, int argc
, char **argv
)
158 int res
, ret_val
= 0;
159 struct elf_module
*previous
;
160 //malloc_tag_t prev_mem_tag;
161 struct elf_module
*module
= module_alloc(name
);
162 struct elf_module
*cur_module
;
165 dprintf("enter: name = %s", name
);
170 if (get_module_type(module
) == EXEC_MODULE
) {
171 if (!argc
|| !argv
|| strcmp(argv
[0], name
)) {
177 cur_module
= module_current();
178 if (!strcmp(cur_module
->name
, module
->name
)) {
179 dprintf("We is running this module %s already!", module
->name
);
181 module_unload(cur_module
);
184 res
= module_load(module
);
188 type
= get_module_type(module
);
190 dprintf("type = %d, prev = %s, cur = %s",
191 type
, cur_module
->name
, module
->name
);
193 if(type
==EXEC_MODULE
)
195 previous
= __syslinux_current
;
196 //prev_mem_tag = __mem_get_tag_global();
198 // Setup the new process context
199 __syslinux_current
= module
;
200 //__mem_set_tag_global((malloc_tag_t)module);
202 // Execute the program
203 ret_val
= setjmp(module
->u
.x
.process_exit
);
206 ret_val
--; /* Valid range is 0-255 */
207 else if (!module
->main_func
)
210 exit((module
->main_func
)(argc
, argv
)); /* Actually run! */
212 // Clean up the allocation context
213 //__free_tagged(module);
214 // Restore the allocation context
215 //__mem_set_tag_global(prev_mem_tag);
216 // Restore the process context
217 __syslinux_current
= previous
;
219 res
= module_unload(module
);
227 _module_unload(module
);