source: mainline/uspace/lib/libc/generic/loader.c@ 7faabb7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7faabb7 was 0993087, checked in by Jiri Svoboda <jirik.svoboda@…>, 17 years ago

Fix bugs in getting task ID from loader (was breaking ppc32).

  • Property mode set to 100644
File size: 6.6 KB
Line 
1/*
2 * Copyright (c) 2008 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32/** @file
33 */
34
35#include <ipc/ipc.h>
36#include <ipc/loader.h>
37#include <libc.h>
38#include <task.h>
39#include <string.h>
40#include <stdlib.h>
41#include <async.h>
42#include <errno.h>
43#include <vfs/vfs.h>
44#include <loader/loader.h>
45
46/** Connect to a new program loader.
47 *
48 * Spawns a new program loader task and returns the connection structure.
49 * @return Pointer to the loader connection structure (should be
50 * de-allocated using free() after use).
51 */
52loader_t *loader_spawn(void)
53{
54 int phone_id, rc;
55 loader_t *ldr;
56
57 /*
58 * Ask kernel to spawn a new loader task.
59 */
60 rc = __SYSCALL1(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id);
61 if (rc != 0)
62 return NULL;
63
64 /*
65 * Say hello so that the loader knows the incoming connection's
66 * phone hash.
67 */
68 rc = async_req_0_0(phone_id, LOADER_HELLO);
69 if (rc != EOK)
70 return NULL;
71
72 ldr = malloc(sizeof(loader_t));
73 if (ldr == NULL)
74 return NULL;
75
76 ldr->phone_id = phone_id;
77 return ldr;
78}
79
80/** Get ID of the new task.
81 *
82 * Retrieves the ID of the new task from the loader.
83 *
84 * @param ldr Loader connection structure.
85 * @param task_id Points to a variable where the ID should be stored.
86 * @return Zero on success or negative error code.
87 */
88int loader_get_task_id(loader_t *ldr, task_id_t *task_id)
89{
90 ipc_call_t answer;
91 aid_t req;
92 int rc;
93 ipcarg_t retval;
94
95 /* Get task ID. */
96 req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer);
97 rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t));
98 if (rc != EOK) {
99 async_wait_for(req, NULL);
100 return rc;
101 }
102
103 async_wait_for(req, &retval);
104 return (int)retval;
105}
106
107/** Set pathname of the program to load.
108 *
109 * Sets the name of the program file to load. The name can be relative
110 * to the current working directory (it will be absolutized before
111 * sending to the loader).
112 *
113 * @param ldr Loader connection structure.
114 * @param path Pathname of the program file.
115 * @return Zero on success or negative error code.
116 */
117int loader_set_pathname(loader_t *ldr, const char *path)
118{
119 ipc_call_t answer;
120 aid_t req;
121 int rc;
122 ipcarg_t retval;
123
124 char *pa;
125 size_t pa_len;
126
127 pa = absolutize(path, &pa_len);
128 if (!pa)
129 return 0;
130
131 /* Send program pathname */
132 req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer);
133 rc = ipc_data_write_start(ldr->phone_id, (void *)pa, pa_len);
134 if (rc != EOK) {
135 async_wait_for(req, NULL);
136 return rc;
137 }
138
139 free(pa);
140
141 async_wait_for(req, &retval);
142 return (int)retval;
143}
144
145
146/** Set command-line arguments for the program.
147 *
148 * Sets the vector of command-line arguments to be passed to the loaded
149 * program. By convention, the very first argument is typically the same as
150 * the command used to execute the program.
151 *
152 * @param ldr Loader connection structure.
153 * @param argv NULL-terminated array of pointers to arguments.
154 * @return Zero on success or negative error code.
155 */
156int loader_set_args(loader_t *ldr, char *const argv[])
157{
158 aid_t req;
159 ipc_call_t answer;
160 ipcarg_t rc;
161
162 char *const *ap;
163 char *dp;
164 char *arg_buf;
165 size_t buffer_size;
166
167 /*
168 * Serialize the arguments into a single array. First
169 * compute size of the buffer needed.
170 */
171 ap = argv;
172 buffer_size = 0;
173 while (*ap != NULL) {
174 buffer_size += strlen(*ap) + 1;
175 ++ap;
176 }
177
178 arg_buf = malloc(buffer_size);
179 if (arg_buf == NULL) return ENOMEM;
180
181 /* Now fill the buffer with null-terminated argument strings */
182 ap = argv;
183 dp = arg_buf;
184 while (*ap != NULL) {
185 strcpy(dp, *ap);
186 dp += strlen(*ap) + 1;
187
188 ++ap;
189 }
190
191 /* Send serialized arguments to the loader */
192
193 req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
194 rc = ipc_data_write_start(ldr->phone_id, (void *)arg_buf, buffer_size);
195 if (rc != EOK) {
196 async_wait_for(req, NULL);
197 return rc;
198 }
199
200 async_wait_for(req, &rc);
201 if (rc != EOK) return rc;
202
203 /* Free temporary buffer */
204 free(arg_buf);
205
206 return EOK;
207}
208
209/** Instruct loader to load the program.
210 *
211 * If this function succeeds, the program has been successfully loaded
212 * and is ready to be executed.
213 *
214 * @param ldr Loader connection structure.
215 * @return Zero on success or negative error code.
216 */
217int loader_load_program(loader_t *ldr)
218{
219 int rc;
220
221 rc = async_req_0_0(ldr->phone_id, LOADER_LOAD);
222 if (rc != EOK)
223 return rc;
224
225 return EOK;
226}
227
228/** Instruct loader to execute the program.
229 *
230 * Note that this function blocks until the loader actually replies
231 * so you cannot expect this function to return if you are debugging
232 * the task and its thread is stopped.
233 *
234 * After using this function, no further operations must be performed
235 * on the loader structure. It should be de-allocated using free().
236 *
237 * @param ldr Loader connection structure.
238 * @return Zero on success or negative error code.
239 */
240int loader_run(loader_t *ldr)
241{
242 int rc;
243
244 rc = async_req_0_0(ldr->phone_id, LOADER_RUN);
245 if (rc != EOK)
246 return rc;
247
248 return EOK;
249}
250
251/** Cancel the loader session.
252 *
253 * Tells the loader not to load any program and terminate.
254 * After using this function, no further operations must be performed
255 * on the loader structure. It should be de-allocated using free().
256 *
257 * @param ldr Loader connection structure.
258 * @return Zero on success or negative error code.
259 */
260void loader_abort(loader_t *ldr)
261{
262 ipc_hangup(ldr->phone_id);
263 ldr->phone_id = 0;
264}
265
266/** @}
267 */
Note: See TracBrowser for help on using the repository browser.