Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4344 → Rev 4345

/branches/dynload/uspace/srv/loader/main.c
27,12 → 27,12
*/
 
/** @addtogroup loader
* @brief Loads and runs programs from VFS.
* @brief Loads and runs programs from VFS.
* @{
*/
*/
/**
* @file
* @brief Loads and runs programs from VFS.
* @brief Loads and runs programs from VFS.
*
* The program loader is a special init binary. Its image is used
* to create a new task upon a @c task_spawn syscall. The syscall
90,17 → 90,18
ipc_callid_t callid;
task_id_t task_id;
size_t len;
 
task_id = task_get_id();
 
if (!ipc_data_read_receive(&callid, &len)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
if (len > sizeof(task_id)) len = sizeof(task_id);
 
if (len > sizeof(task_id))
len = sizeof(task_id);
ipc_data_read_finalize(callid, &task_id, len);
ipc_answer_0(rid, EOK);
}
116,13 → 117,13
ipc_callid_t callid;
size_t len;
char *name_buf;
 
if (!ipc_data_write_receive(&callid, &len)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
name_buf = malloc(len + 1);
if (!name_buf) {
ipc_answer_0(callid, ENOMEM);
129,15 → 130,15
ipc_answer_0(rid, ENOMEM);
return;
}
 
ipc_data_write_finalize(callid, name_buf, len);
ipc_answer_0(rid, EOK);
 
if (pathname != NULL) {
free(pathname);
pathname = NULL;
}
 
name_buf[len] = '\0';
pathname = name_buf;
}
153,23 → 154,23
size_t buf_len, arg_len;
char *p;
int n;
 
if (!ipc_data_write_receive(&callid, &buf_len)) {
ipc_answer_0(callid, EINVAL);
ipc_answer_0(rid, EINVAL);
return;
}
 
if (arg_buf != NULL) {
free(arg_buf);
arg_buf = NULL;
}
 
if (argv != NULL) {
free(argv);
argv = NULL;
}
 
arg_buf = malloc(buf_len + 1);
if (!arg_buf) {
ipc_answer_0(callid, ENOMEM);
176,12 → 177,12
ipc_answer_0(rid, ENOMEM);
return;
}
 
ipc_data_write_finalize(callid, arg_buf, buf_len);
ipc_answer_0(rid, EOK);
 
arg_buf[buf_len] = '\0';
 
/*
* Count number of arguments
*/
192,10 → 193,10
p = p + arg_len + 1;
++n;
}
 
/* Allocate argv */
argv = malloc((n + 1) * sizeof(char *));
 
if (argv == NULL) {
free(arg_buf);
ipc_answer_0(callid, ENOMEM);
202,7 → 203,7
ipc_answer_0(rid, ENOMEM);
return;
}
 
/*
* Fill argv with argument pointers
*/
210,12 → 211,12
n = 0;
while (p < arg_buf + buf_len) {
argv[n] = p;
 
arg_len = strlen(p);
p = p + arg_len + 1;
++n;
}
 
argc = n;
argv[n] = NULL;
}
229,7 → 230,7
static int loader_load(ipc_callid_t rid, ipc_call_t *request)
{
int rc;
 
rc = elf_load_file(pathname, 0, 0, &prog_info);
if (rc < 0) {
DPRINTF("Failed to load executable '%s'.\n", pathname);
236,12 → 237,12
ipc_answer_0(rid, EINVAL);
return 1;
}
 
elf_create_pcb(&prog_info, &pcb);
 
pcb.argc = argc;
pcb.argv = argv;
 
if (prog_info.interp == NULL) {
/* Statically linked program */
is_dyn_linked = false;
248,7 → 249,7
ipc_answer_0(rid, EOK);
return 0;
}
 
printf("Load ELF interpreter '%s'\n", prog_info.interp);
rc = elf_load_file(prog_info.interp, 0, 0, &interp_info);
if (rc < 0) {
257,7 → 258,7
ipc_answer_0(rid, EINVAL);
return 1;
}
 
printf("Run interpreter.\n");
printf("entry point: 0x%lx\n", interp_info.entry);
printf("pcb address: 0x%lx\n", &pcb);
265,7 → 266,7
 
is_dyn_linked = true;
ipc_answer_0(rid, EOK);
 
return 0;
}
 
278,18 → 279,21
*/
static void loader_run(ipc_callid_t rid, ipc_call_t *request)
{
const char *cp;
/* Set the task name. */
task_set_name(pathname);
 
cp = strrchr(pathname, '/');
cp = (cp == NULL) ? pathname : (cp + 1);
task_set_name(cp);
if (is_dyn_linked == true) {
/* Dynamically linked program */
DPRINTF("Run ELF interpreter.\n");
DPRINTF("Entry point: 0x%lx\n", interp_info.entry);
close_console();
 
ipc_answer_0(rid, EOK);
program_run(interp_info.entry, &pcb);
 
} else {
/* Statically linked program */
close_console();
310,24 → 314,25
ipc_callid_t callid;
ipc_call_t call;
int retval;
 
/* Already have a connection? */
if (connected) {
ipc_answer_0(iid, ELIMIT);
return;
}
 
connected = true;
/* Accept the connection */
ipc_answer_0(iid, EOK);
 
/* Ignore parameters, the connection is already open */
(void)iid; (void)icall;
 
(void) iid;
(void) icall;
while (1) {
callid = async_get_call(&call);
 
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
exit(0);
364,18 → 369,18
int main(int argc, char *argv[])
{
ipcarg_t phonead;
 
connected = false;
/* Set a handler of incomming connections. */
async_set_client_connection(loader_connection);
 
/* Register at naming service. */
if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0)
return -1;
async_manager();
 
/* Never reached */
return 0;
}