Subversion Repositories HelenOS

Rev

Rev 3470 | Rev 3569 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3469 svoboda 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 <string.h>
39
#include <stdlib.h>
40
#include <async.h>
41
#include <errno.h>
42
#include <vfs/vfs.h>
43
#include <loader/loader.h>
44
 
45
/** Connect to a new program loader.
46
 *
47
 * Spawns a new program loader task and returns the connection structure.
48
 * @return  Pointer to the loader connection structure (should be
49
 *      de-allocated using free() after use).
50
 */
51
loader_t *loader_spawn(void)
52
{
53
    int phone_id, rc;
54
    loader_t *ldr;
55
 
56
    /*
57
     * Ask kernel to spawn a new loader task.
58
     */
59
    rc = __SYSCALL1(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id);
60
    if (rc != 0)
61
        return NULL;
62
 
63
    /*
64
     * Say hello so that the loader knows the incoming connection's
65
     * phone hash.
66
     */
67
    rc = async_req_0_0(phone_id, LOADER_HELLO);
68
    if (rc != EOK)
69
        return NULL;
70
 
71
    ldr = malloc(sizeof(loader_t));
72
    if (ldr == NULL)
73
        return NULL;
74
 
75
    ldr->phone_id = phone_id;
76
    return ldr;
77
}
78
 
79
/** Get ID of the new task.
80
 *
81
 * Retrieves the ID of the new task from the loader.
82
 *
83
 * @param ldr       Loader connection structure.
84
 * @param task_id   Points to a variable where the ID should be stored.
85
 * @return      Zero on success or negative error code.
86
 */
87
int loader_get_task_id(loader_t *ldr, task_id_t *task_id)
88
{
89
    ipc_call_t answer;
90
    aid_t req;
91
    int rc;
92
    ipcarg_t retval;
93
 
94
    /* Get task ID. */
95
    req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer);
96
    rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id));
97
    if (rc != EOK) {
98
        async_wait_for(req, NULL);
99
        return rc;
100
    }
101
 
102
    async_wait_for(req, &retval);
103
    return (int)retval;
104
}
105
 
106
/** Set pathname of the program to load.
107
 *
108
 * Sets the name of the program file to load. The name can be relative
109
 * to the current working directory (it will be absolutized before
110
 * sending to the loader).
111
 *
112
 * @param ldr       Loader connection structure.
113
 * @param path      Pathname of the program file.
114
 * @return      Zero on success or negative error code.
115
 */
116
int loader_set_pathname(loader_t *ldr, const char *path)
117
{
118
    ipc_call_t answer;
119
    aid_t req;
120
    int rc;
121
    ipcarg_t retval;
122
 
123
    char *pa;
124
    size_t pa_len;
125
 
126
    pa = absolutize(path, &pa_len);
127
    if (!pa)
128
        return 0;
129
 
130
    /* Send program pathname */
131
    req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer);
132
    rc = ipc_data_write_start(ldr->phone_id, (void *)pa, pa_len);
133
    if (rc != EOK) {
134
        async_wait_for(req, NULL);
135
        return rc;
136
    }
137
 
138
    free(pa);
139
 
140
    async_wait_for(req, &retval);
141
    return (int)retval;
142
}
143
 
144
 
145
/** Set command-line arguments for the program.
146
 *
147
 * Sets the vector of command-line arguments to be passed to the loaded
148
 * program. By convention, the very first argument is typically the same as
149
 * the command used to execute the program.
150
 *
151
 * @param ldr       Loader connection structure.
152
 * @param argv      NULL-terminated array of pointers to arguments.
153
 * @return      Zero on success or negative error code.
154
 */
155
int loader_set_args(loader_t *ldr, char *const argv[])
156
{
157
    aid_t req;
158
    ipc_call_t answer;
159
    ipcarg_t rc;
160
 
161
    char *const *ap;
162
    char *dp;
163
    char *arg_buf;
164
    size_t buffer_size;
165
 
166
    /*
167
     * Serialize the arguments into a single array. First
168
     * compute size of the buffer needed.
169
     */
170
    ap = argv;
171
    buffer_size = 0;
172
    while (*ap != NULL) {
173
        buffer_size += strlen(*ap) + 1;
174
        ++ap;
175
    }
176
 
177
    arg_buf = malloc(buffer_size);
178
    if (arg_buf == NULL) return ENOMEM;
179
 
180
    /* Now fill the buffer with null-terminated argument strings */
181
    ap = argv;
182
    dp = arg_buf;
183
    while (*ap != NULL) {
184
        strcpy(dp, *ap);
185
        dp += strlen(*ap) + 1;
186
 
187
        ++ap;
188
    }
189
 
190
    /* Send serialized arguments to the loader */
191
 
192
    req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
193
    rc = ipc_data_write_start(ldr->phone_id, (void *)arg_buf, buffer_size);
194
    if (rc != EOK) {
195
        async_wait_for(req, NULL);
196
        return rc;
197
    }
198
 
199
    async_wait_for(req, &rc);
200
    if (rc != EOK) return rc;
201
 
202
    /* Free temporary buffer */
203
    free(arg_buf);
204
 
205
    return EOK;
206
}
207
 
3470 svoboda 208
/** Instruct loader to load the program.
209
 *
210
 * If this function succeeds, the program has been successfully loaded
211
 * and is ready to be executed.
212
 *
213
 * @param ldr       Loader connection structure.
214
 * @return      Zero on success or negative error code.
215
 */
216
int loader_load_program(loader_t *ldr)
217
{
218
    int rc;
219
 
220
    rc = async_req_0_0(ldr->phone_id, LOADER_LOAD);
221
    if (rc != EOK)
222
        return rc;
223
 
224
    return EOK;
225
}
226
 
3469 svoboda 227
/** Instruct loader to execute the program.
228
 *
3470 svoboda 229
 * Note that this function blocks until the loader actually replies
230
 * so you cannot expect this function to return if you are debugging
231
 * the task and its thread is stopped.
232
 *
3469 svoboda 233
 * After using this function, no further operations must be performed
234
 * on the loader structure. It should be de-allocated using free().
235
 *
236
 * @param ldr       Loader connection structure.
237
 * @return      Zero on success or negative error code.
238
 */
3470 svoboda 239
int loader_run(loader_t *ldr)
3469 svoboda 240
{
241
    int rc;
242
 
243
    rc = async_req_0_0(ldr->phone_id, LOADER_RUN);
244
    if (rc != EOK)
245
        return rc;
246
 
247
    return EOK;
248
}
249
 
250
/** Cancel the loader session.
251
 *
252
 * Tells the loader not to load any program and terminate.
253
 * After using this function, no further operations must be performed
254
 * on the loader structure. It should be de-allocated using free().
255
 *
256
 * @param ldr       Loader connection structure.
257
 * @return      Zero on success or negative error code.
258
 */
259
void loader_abort(loader_t *ldr)
260
{
261
    ipc_hangup(ldr->phone_id);
262
    ldr->phone_id = 0;
263
}
264
 
265
/** @}
266
 */