Rev 3386 | Rev 4263 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3386 | Rev 4153 | ||
---|---|---|---|
Line 32... | Line 32... | ||
32 | */ |
32 | */ |
33 | /** @file |
33 | /** @file |
34 | */ |
34 | */ |
35 | 35 | ||
36 | #include <task.h> |
36 | #include <task.h> |
37 | #include <ipc/ipc.h> |
- | |
38 | #include <ipc/loader.h> |
- | |
39 | #include <libc.h> |
37 | #include <libc.h> |
40 | #include <string.h> |
- | |
41 | #include <stdlib.h> |
38 | #include <stdlib.h> |
42 | #include <async.h> |
- | |
43 | #include <errno.h> |
39 | #include <errno.h> |
- | 40 | #include <loader/loader.h> |
|
44 | #include <vfs/vfs.h> |
41 | #include <string.h> |
45 | 42 | ||
46 | task_id_t task_get_id(void) |
43 | task_id_t task_get_id(void) |
47 | { |
44 | { |
48 | task_id_t task_id; |
45 | task_id_t task_id; |
49 | 46 | ||
50 | (void) __SYSCALL1(SYS_TASK_GET_ID, (sysarg_t) &task_id); |
47 | (void) __SYSCALL1(SYS_TASK_GET_ID, (sysarg_t) &task_id); |
51 | 48 | ||
52 | return task_id; |
49 | return task_id; |
53 | } |
50 | } |
54 | 51 | ||
55 | static int task_spawn_loader(void) |
52 | /** Set the task name. |
56 | { |
53 | * |
57 | int phone_id, rc; |
- | |
58 | - | ||
59 | rc = __SYSCALL1(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id); |
54 | * @param name The new name, typically the command used to execute the |
60 | if (rc != 0) |
- | |
61 | return rc; |
55 | * program. |
62 | - | ||
63 | return phone_id; |
56 | * @return Zero on success or negative error code. |
64 | } |
57 | */ |
65 | - | ||
66 | static int loader_set_args(int phone_id, const char *argv[]) |
58 | int task_set_name(const char *name) |
67 | { |
59 | { |
68 | aid_t req; |
- | |
69 | ipc_call_t answer; |
- | |
70 | ipcarg_t rc; |
- | |
71 | - | ||
72 | const char **ap; |
- | |
73 | char *dp; |
- | |
74 | char *arg_buf; |
- | |
75 | size_t buffer_size; |
- | |
76 | size_t len; |
- | |
77 | - | ||
78 | /* |
- | |
79 | * Serialize the arguments into a single array. First |
- | |
80 | * compute size of the buffer needed. |
- | |
81 | */ |
- | |
82 | ap = argv; |
- | |
83 | buffer_size = 0; |
- | |
84 | while (*ap != NULL) { |
- | |
85 | buffer_size += strlen(*ap) + 1; |
- | |
86 | ++ap; |
- | |
87 | } |
- | |
88 | - | ||
89 | arg_buf = malloc(buffer_size); |
- | |
90 | if (arg_buf == NULL) return ENOMEM; |
- | |
91 | - | ||
92 | /* Now fill the buffer with null-terminated argument strings */ |
- | |
93 | ap = argv; |
- | |
94 | dp = arg_buf; |
- | |
95 | while (*ap != NULL) { |
- | |
96 | strcpy(dp, *ap); |
- | |
97 | dp += strlen(*ap) + 1; |
- | |
98 | - | ||
99 | ++ap; |
- | |
100 | } |
- | |
101 | - | ||
102 | /* Send serialized arguments to the loader */ |
- | |
103 | - | ||
104 | req = async_send_0(phone_id, LOADER_SET_ARGS, &answer); |
- | |
105 | rc = ipc_data_write_start(phone_id, (void *)arg_buf, buffer_size); |
60 | return __SYSCALL2(SYS_TASK_SET_NAME, (sysarg_t) name, strlen(name)); |
106 | if (rc != EOK) { |
- | |
107 | async_wait_for(req, NULL); |
- | |
108 | return rc; |
- | |
109 | } |
- | |
110 | - | ||
111 | async_wait_for(req, &rc); |
- | |
112 | if (rc != EOK) return rc; |
- | |
113 | - | ||
114 | /* Free temporary buffer */ |
- | |
115 | free(arg_buf); |
- | |
116 | - | ||
117 | return EOK; |
- | |
118 | } |
61 | } |
119 | 62 | ||
120 | /** Create a new task by running an executable from VFS. |
63 | /** Create a new task by running an executable from the filesystem. |
- | 64 | * |
|
- | 65 | * This is really just a convenience wrapper over the more complicated |
|
- | 66 | * loader API. |
|
121 | * |
67 | * |
122 | * @param path pathname of the binary to execute |
68 | * @param path pathname of the binary to execute |
123 | * @param argv command-line arguments |
69 | * @param argv command-line arguments |
124 | * @return ID of the newly created task or zero on error. |
70 | * @return ID of the newly created task or zero on error. |
125 | */ |
71 | */ |
126 | task_id_t task_spawn(const char *path, const char *argv[]) |
72 | task_id_t task_spawn(const char *path, char *const argv[]) |
127 | { |
73 | { |
128 | int phone_id; |
- | |
129 | ipc_call_t answer; |
74 | loader_t *ldr; |
130 | aid_t req; |
75 | task_id_t task_id; |
131 | int rc; |
76 | int rc; |
132 | ipcarg_t retval; |
- | |
133 | - | ||
134 | char *pa; |
- | |
135 | size_t pa_len; |
- | |
136 | - | ||
137 | pa = absolutize(path, &pa_len); |
- | |
138 | if (!pa) |
- | |
139 | return 0; |
- | |
140 | 77 | ||
141 | /* Spawn a program loader */ |
78 | /* Connect to a program loader. */ |
142 | phone_id = task_spawn_loader(); |
79 | ldr = loader_connect(); |
143 | if (phone_id < 0) |
80 | if (ldr == NULL) |
144 | return 0; |
81 | return 0; |
145 | 82 | ||
146 | /* |
- | |
147 | * Say hello so that the loader knows the incoming connection's |
- | |
148 | * phone hash. |
83 | /* Get task ID. */ |
149 | */ |
- | |
150 | rc = async_req_0_0(phone_id, LOADER_HELLO); |
84 | rc = loader_get_task_id(ldr, &task_id); |
151 | if (rc != EOK) |
85 | if (rc != EOK) |
152 | return 0; |
86 | goto error; |
153 | 87 | ||
154 | /* Send program pathname */ |
88 | /* Send program pathname. */ |
155 | req = async_send_0(phone_id, LOADER_SET_PATHNAME, &answer); |
- | |
156 | rc = ipc_data_write_start(phone_id, (void *)pa, pa_len); |
89 | rc = loader_set_pathname(ldr, path); |
157 | if (rc != EOK) { |
90 | if (rc != EOK) |
158 | async_wait_for(req, NULL); |
- | |
159 | return 1; |
91 | goto error; |
160 | } |
- | |
161 | 92 | ||
- | 93 | /* Send arguments. */ |
|
162 | async_wait_for(req, &retval); |
94 | rc = loader_set_args(ldr, argv); |
163 | if (retval != EOK) |
95 | if (rc != EOK) |
164 | goto error; |
96 | goto error; |
165 | 97 | ||
166 | /* Send arguments */ |
98 | /* Load the program. */ |
167 | rc = loader_set_args(phone_id, argv); |
99 | rc = loader_load_program(ldr); |
168 | if (rc != EOK) |
100 | if (rc != EOK) |
169 | goto error; |
101 | goto error; |
170 | 102 | ||
171 | /* Request loader to start the program */ |
103 | /* Run it. */ |
172 | rc = async_req_0_0(phone_id, LOADER_RUN); |
104 | rc = loader_run(ldr); |
173 | if (rc != EOK) |
105 | if (rc != EOK) |
174 | goto error; |
106 | goto error; |
175 | 107 | ||
176 | /* Success */ |
108 | /* Success */ |
- | 109 | ||
177 | ipc_hangup(phone_id); |
110 | free(ldr); |
178 | return 1; |
111 | return task_id; |
179 | 112 | ||
180 | /* Error exit */ |
113 | /* Error exit */ |
181 | error: |
114 | error: |
182 | ipc_hangup(phone_id); |
115 | loader_abort(ldr); |
- | 116 | free(ldr); |
|
- | 117 | ||
183 | return 0; |
118 | return 0; |
184 | } |
119 | } |
185 | 120 | ||
186 | /** @} |
121 | /** @} |
187 | */ |
122 | */ |