70,12 → 70,19 |
/** The Program control block */ |
static pcb_t pcb; |
|
/** Number of arguments */ |
static int argc = 0; |
/** Argument vector */ |
static char **argv = NULL; |
/** Buffer holding all arguments */ |
static char *arg_buf = NULL; |
|
/** Receive a call setting pathname of the program to execute. |
* |
* @param rid |
* @param request |
*/ |
static void iloader_set_pathname(ipc_callid_t rid, ipc_call_t *request) |
static void loader_set_pathname(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_callid_t callid; |
size_t len; |
106,6 → 113,85 |
pathname = name_buf; |
} |
|
/** Receive a call setting arguments of the program to execute. |
* |
* @param rid |
* @param request |
*/ |
static void loader_set_args(ipc_callid_t rid, ipc_call_t *request) |
{ |
ipc_callid_t callid; |
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); |
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 |
*/ |
p = arg_buf; |
n = 0; |
while (p < arg_buf + buf_len) { |
arg_len = strlen(p); |
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); |
ipc_answer_0(rid, ENOMEM); |
return; |
} |
|
/* |
* Fill argv with argument pointers |
*/ |
p = arg_buf; |
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; |
} |
|
|
/** Load and run the previously selected program. |
* |
* @param rid |
112,7 → 198,7 |
* @param request |
* @return 0 on success, !0 on error. |
*/ |
static int iloader_run(ipc_callid_t rid, ipc_call_t *request) |
static int loader_run(ipc_callid_t rid, ipc_call_t *request) |
{ |
int rc; |
|
131,8 → 217,8 |
// printf("Create PCB\n"); |
elf_create_pcb(&prog_info, &pcb); |
|
pcb.argc = 0; |
pcb.argv = NULL; |
pcb.argc = argc; |
pcb.argv = argv; |
|
if (prog_info.interp == NULL) { |
/* Statically linked program */ |
189,10 → 275,12 |
// call.in_phone_hash, IPC_GET_METHOD(call)); |
switch (IPC_GET_METHOD(call)) { |
case LOADER_SET_PATHNAME: |
iloader_set_pathname(callid, &call); |
loader_set_pathname(callid, &call); |
continue; |
case LOADER_SET_ARGS: |
loader_set_args(callid, &call); |
case LOADER_RUN: |
iloader_run(callid, &call); |
loader_run(callid, &call); |
exit(0); |
continue; |
default: |
199,8 → 287,10 |
retval = ENOENT; |
break; |
} |
if ((callid & IPC_CALLID_NOTIFICATION) == 0) { |
printf("responding EINVAL to method %d\n", IPC_GET_METHOD(call)); |
if ((callid & IPC_CALLID_NOTIFICATION) == 0 && |
IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP) { |
printf("responding EINVAL to method %d\n", |
IPC_GET_METHOD(call)); |
ipc_answer_0(callid, EINVAL); |
} |
} |