source: mainline/uspace/lib/c/generic/loader.c@ 99d3123

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 99d3123 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 8.7 KB
RevLine 
[45454e9b]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
[937aeee]33 */
[45454e9b]34
35#include <ipc/loader.h>
[bfd1546]36#include <ipc/services.h>
[79ae36dd]37#include <ns.h>
[45454e9b]38#include <libc.h>
[0993087]39#include <task.h>
[19f857a]40#include <str.h>
[45454e9b]41#include <stdlib.h>
42#include <async.h>
43#include <errno.h>
44#include <vfs/vfs.h>
45#include <loader/loader.h>
[79ae36dd]46#include "private/loader.h"
[45454e9b]47
48/** Connect to a new program loader.
49 *
50 * Spawns a new program loader task and returns the connection structure.
[937aeee]51 *
52 * @param name Symbolic name to set on the newly created task.
53 *
[f77c1c9]54 * @return Error code.
[45454e9b]55 */
[b7fd2a0]56errno_t loader_spawn(const char *name)
[45454e9b]57{
[b7fd2a0]58 return (errno_t) __SYSCALL2(SYS_PROGRAM_SPAWN_LOADER,
[9eb3623]59 (sysarg_t) name, str_size(name));
[bfd1546]60}
[45454e9b]61
[bfd1546]62loader_t *loader_connect(void)
63{
[937aeee]64 loader_t *ldr = malloc(sizeof(loader_t));
[45454e9b]65 if (ldr == NULL)
66 return NULL;
[a35b458]67
[79ae36dd]68 async_sess_t *sess =
[f9b2cb4c]69 service_connect_blocking(SERVICE_LOADER, INTERFACE_LOADER, 0);
[79ae36dd]70 if (sess == NULL) {
71 free(ldr);
72 return NULL;
73 }
[a35b458]74
[79ae36dd]75 ldr->sess = sess;
[937aeee]76 return ldr;
[45454e9b]77}
78
79/** Get ID of the new task.
80 *
81 * Retrieves the ID of the new task from the loader.
82 *
[937aeee]83 * @param ldr Loader connection structure.
84 * @param task_id Points to a variable where the ID should be stored.
85 *
[cde999a]86 * @return Zero on success or an error code.
[937aeee]87 *
[45454e9b]88 */
[b7fd2a0]89errno_t loader_get_task_id(loader_t *ldr, task_id_t *task_id)
[45454e9b]90{
91 /* Get task ID. */
[79ae36dd]92 async_exch_t *exch = async_exchange_begin(ldr->sess);
[a35b458]93
[937aeee]94 ipc_call_t answer;
[79ae36dd]95 aid_t req = async_send_0(exch, LOADER_GET_TASKID, &answer);
[b7fd2a0]96 errno_t rc = async_data_read_start(exch, task_id, sizeof(task_id_t));
[a35b458]97
[79ae36dd]98 async_exchange_end(exch);
[a35b458]99
[45454e9b]100 if (rc != EOK) {
[50b581d]101 async_forget(req);
[b7fd2a0]102 return (errno_t) rc;
[45454e9b]103 }
[a35b458]104
[79ae36dd]105 async_wait_for(req, &rc);
[b7fd2a0]106 return (errno_t) rc;
[45454e9b]107}
108
[622cdbe]109/** Set current working directory for the loaded task.
110 *
111 * Sets the current working directory for the loaded task.
112 *
113 * @param ldr Loader connection structure.
114 *
[cde999a]115 * @return Zero on success or an error code.
[622cdbe]116 *
117 */
[b7fd2a0]118errno_t loader_set_cwd(loader_t *ldr)
[622cdbe]119{
[79ae36dd]120 char *cwd = (char *) malloc(MAX_PATH_LEN + 1);
[622cdbe]121 if (!cwd)
122 return ENOMEM;
[a35b458]123
[d96d9bc]124 if (vfs_cwd_get(cwd, MAX_PATH_LEN + 1) != EOK)
[79ae36dd]125 str_cpy(cwd, MAX_PATH_LEN + 1, "/");
[a35b458]126
[79ae36dd]127 size_t len = str_length(cwd);
[a35b458]128
[79ae36dd]129 async_exch_t *exch = async_exchange_begin(ldr->sess);
[a35b458]130
[622cdbe]131 ipc_call_t answer;
[79ae36dd]132 aid_t req = async_send_0(exch, LOADER_SET_CWD, &answer);
[b7fd2a0]133 errno_t rc = async_data_write_start(exch, cwd, len);
[a35b458]134
[79ae36dd]135 async_exchange_end(exch);
[622cdbe]136 free(cwd);
[a35b458]137
[622cdbe]138 if (rc != EOK) {
[50b581d]139 async_forget(req);
[b7fd2a0]140 return (errno_t) rc;
[622cdbe]141 }
[a35b458]142
[79ae36dd]143 async_wait_for(req, &rc);
[b7fd2a0]144 return (errno_t) rc;
[622cdbe]145}
146
[bb9ec2d]147/** Set the program to load.
[45454e9b]148 *
[937aeee]149 * @param ldr Loader connection structure.
[bb9ec2d]150 * @param name Name to set for the spawned program.
151 * @param file Program file.
[937aeee]152 *
[cde999a]153 * @return Zero on success or an error code.
[937aeee]154 *
[45454e9b]155 */
[b7fd2a0]156errno_t loader_set_program(loader_t *ldr, const char *name, int file)
[45454e9b]157{
[79ae36dd]158 async_exch_t *exch = async_exchange_begin(ldr->sess);
[bb9ec2d]159
[937aeee]160 ipc_call_t answer;
[bb9ec2d]161 aid_t req = async_send_0(exch, LOADER_SET_PROGRAM, &answer);
162
[b7fd2a0]163 errno_t rc = async_data_write_start(exch, name, str_size(name) + 1);
[bb9ec2d]164 if (rc == EOK) {
165 async_exch_t *vfs_exch = vfs_exchange_begin();
166 rc = vfs_pass_handle(vfs_exch, file, exch);
167 vfs_exchange_end(vfs_exch);
168 }
169
[79ae36dd]170 async_exchange_end(exch);
[bb9ec2d]171
[45454e9b]172 if (rc != EOK) {
[50b581d]173 async_forget(req);
[b7fd2a0]174 return (errno_t) rc;
[45454e9b]175 }
[bb9ec2d]176
[79ae36dd]177 async_wait_for(req, &rc);
[b7fd2a0]178 return (errno_t) rc;
[45454e9b]179}
180
[bb9ec2d]181/** Set the program to load by path.
182 *
183 * @param ldr Loader connection structure.
184 * @param path Program path.
185 *
[cde999a]186 * @return Zero on success or an error code.
[bb9ec2d]187 *
188 */
[b7fd2a0]189errno_t loader_set_program_path(loader_t *ldr, const char *path)
[bb9ec2d]190{
191 const char *name = str_rchr(path, '/');
192 if (name == NULL) {
193 name = path;
194 } else {
195 name++;
196 }
[a35b458]197
[f77c1c9]198 int fd;
[b7fd2a0]199 errno_t rc = vfs_lookup(path, 0, &fd);
[f77c1c9]200 if (rc != EOK) {
201 return rc;
[bb9ec2d]202 }
[a35b458]203
[f77c1c9]204 rc = loader_set_program(ldr, name, fd);
[9c4cf0d]205 vfs_put(fd);
[bb9ec2d]206 return rc;
207}
208
209
[45454e9b]210/** Set command-line arguments for the program.
211 *
212 * Sets the vector of command-line arguments to be passed to the loaded
213 * program. By convention, the very first argument is typically the same as
214 * the command used to execute the program.
215 *
[937aeee]216 * @param ldr Loader connection structure.
217 * @param argv NULL-terminated array of pointers to arguments.
218 *
[cde999a]219 * @return Zero on success or an error code.
[937aeee]220 *
[45454e9b]221 */
[b7fd2a0]222errno_t loader_set_args(loader_t *ldr, const char *const argv[])
[45454e9b]223{
[937aeee]224 /*
[45454e9b]225 * Serialize the arguments into a single array. First
226 * compute size of the buffer needed.
227 */
[a000878c]228 const char *const *ap = argv;
[937aeee]229 size_t buffer_size = 0;
[45454e9b]230 while (*ap != NULL) {
[9eb3623]231 buffer_size += str_size(*ap) + 1;
[937aeee]232 ap++;
[45454e9b]233 }
[a35b458]234
[937aeee]235 char *arg_buf = malloc(buffer_size);
236 if (arg_buf == NULL)
237 return ENOMEM;
[a35b458]238
[45454e9b]239 /* Now fill the buffer with null-terminated argument strings */
240 ap = argv;
[937aeee]241 char *dp = arg_buf;
[a35b458]242
[45454e9b]243 while (*ap != NULL) {
[6eb2e96]244 str_cpy(dp, buffer_size - (dp - arg_buf), *ap);
[9eb3623]245 dp += str_size(*ap) + 1;
[937aeee]246 ap++;
[45454e9b]247 }
[a35b458]248
[45454e9b]249 /* Send serialized arguments to the loader */
[79ae36dd]250 async_exch_t *exch = async_exchange_begin(ldr->sess);
[a35b458]251
[937aeee]252 ipc_call_t answer;
[79ae36dd]253 aid_t req = async_send_0(exch, LOADER_SET_ARGS, &answer);
[b7fd2a0]254 errno_t rc = async_data_write_start(exch, (void *) arg_buf,
[79ae36dd]255 buffer_size);
[a35b458]256
[79ae36dd]257 async_exchange_end(exch);
258 free(arg_buf);
[a35b458]259
[45454e9b]260 if (rc != EOK) {
[50b581d]261 async_forget(req);
[b7fd2a0]262 return (errno_t) rc;
[45454e9b]263 }
[a35b458]264
[45454e9b]265 async_wait_for(req, &rc);
[b7fd2a0]266 return (errno_t) rc;
[937aeee]267}
[45454e9b]268
[bb9ec2d]269/** Add a file to the task's inbox.
[937aeee]270 *
[bb9ec2d]271 * @param ldr Loader connection structure.
272 * @param name Identification of the file.
273 * @param file The file's descriptor.
[937aeee]274 *
[cde999a]275 * @return Zero on success or an error code.
[937aeee]276 *
277 */
[b7fd2a0]278errno_t loader_add_inbox(loader_t *ldr, const char *name, int file)
[937aeee]279{
[79ae36dd]280 async_exch_t *exch = async_exchange_begin(ldr->sess);
[7171760]281 async_exch_t *vfs_exch = vfs_exchange_begin();
[a35b458]282
[bb9ec2d]283 aid_t req = async_send_0(exch, LOADER_ADD_INBOX, NULL);
[a35b458]284
[b7fd2a0]285 errno_t rc = async_data_write_start(exch, name, str_size(name) + 1);
[bb9ec2d]286 if (rc == EOK) {
287 rc = vfs_pass_handle(vfs_exch, file, exch);
[7171760]288 }
[a35b458]289
[bb9ec2d]290 async_exchange_end(vfs_exch);
[7171760]291 async_exchange_end(exch);
[a35b458]292
[bb9ec2d]293 if (rc == EOK) {
294 async_wait_for(req, &rc);
295 } else {
[50b581d]296 async_forget(req);
[937aeee]297 }
[a35b458]298
[b7fd2a0]299 return (errno_t) rc;
[45454e9b]300}
301
[4470e26]302/** Instruct loader to load the program.
303 *
304 * If this function succeeds, the program has been successfully loaded
305 * and is ready to be executed.
306 *
[937aeee]307 * @param ldr Loader connection structure.
308 *
[cde999a]309 * @return Zero on success or an error code.
[937aeee]310 *
[4470e26]311 */
[b7fd2a0]312errno_t loader_load_program(loader_t *ldr)
[4470e26]313{
[79ae36dd]314 async_exch_t *exch = async_exchange_begin(ldr->sess);
[b7fd2a0]315 errno_t rc = async_req_0_0(exch, LOADER_LOAD);
[79ae36dd]316 async_exchange_end(exch);
[a35b458]317
[79ae36dd]318 return rc;
[4470e26]319}
320
[45454e9b]321/** Instruct loader to execute the program.
[4470e26]322 *
323 * Note that this function blocks until the loader actually replies
324 * so you cannot expect this function to return if you are debugging
325 * the task and its thread is stopped.
[45454e9b]326 *
[79ae36dd]327 * After using this function, no further operations can be performed
328 * on the loader structure and it is deallocated.
[45454e9b]329 *
[937aeee]330 * @param ldr Loader connection structure.
331 *
[cde999a]332 * @return Zero on success or an error code.
[937aeee]333 *
[45454e9b]334 */
[b7fd2a0]335errno_t loader_run(loader_t *ldr)
[45454e9b]336{
[79ae36dd]337 async_exch_t *exch = async_exchange_begin(ldr->sess);
[b7fd2a0]338 errno_t rc = async_req_0_0(exch, LOADER_RUN);
[79ae36dd]339 async_exchange_end(exch);
[a35b458]340
[45454e9b]341 if (rc != EOK)
342 return rc;
[a35b458]343
[79ae36dd]344 async_hangup(ldr->sess);
345 free(ldr);
[a35b458]346
[45454e9b]347 return EOK;
348}
349
350/** Cancel the loader session.
351 *
[79ae36dd]352 * Tell the loader not to load any program and terminate.
353 * After using this function, no further operations can be performed
354 * on the loader structure and it is deallocated.
[45454e9b]355 *
[937aeee]356 * @param ldr Loader connection structure.
357 *
[cde999a]358 * @return Zero on success or an error code.
[937aeee]359 *
[45454e9b]360 */
361void loader_abort(loader_t *ldr)
362{
[79ae36dd]363 async_hangup(ldr->sess);
364 free(ldr);
[45454e9b]365}
366
367/** @}
368 */
Note: See TracBrowser for help on using the repository browser.