loader.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008 Jiri Svoboda
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00035 #include <ipc/loader.h>
00036 #include <ipc/services.h>
00037 #include <ipc/ns.h>
00038 #include <libc.h>
00039 #include <task.h>
00040 #include <str.h>
00041 #include <stdlib.h>
00042 #include <async.h>
00043 #include <errno.h>
00044 #include <vfs/vfs.h>
00045 #include <loader/loader.h>
00046 
00057 int loader_spawn(const char *name)
00058 {
00059         return __SYSCALL2(SYS_PROGRAM_SPAWN_LOADER,
00060             (sysarg_t) name, str_size(name));
00061 }
00062 
00063 loader_t *loader_connect(void)
00064 {
00065         int phone_id = service_connect_blocking(SERVICE_LOAD, 0, 0);
00066         if (phone_id < 0)
00067                 return NULL;
00068         
00069         loader_t *ldr = malloc(sizeof(loader_t));
00070         if (ldr == NULL)
00071                 return NULL;
00072         
00073         ldr->phone_id = phone_id;
00074         return ldr;
00075 }
00076 
00087 int loader_get_task_id(loader_t *ldr, task_id_t *task_id)
00088 {
00089         /* Get task ID. */
00090         ipc_call_t answer;
00091         aid_t req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer);
00092         int rc = async_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t));
00093         if (rc != EOK) {
00094                 async_wait_for(req, NULL);
00095                 return rc;
00096         }
00097         
00098         sysarg_t retval;
00099         async_wait_for(req, &retval);
00100         return (int) retval;
00101 }
00102 
00112 int loader_set_cwd(loader_t *ldr)
00113 {
00114         char *cwd;
00115         size_t len;
00116 
00117         cwd = (char *) malloc(MAX_PATH_LEN + 1);
00118         if (!cwd)
00119                 return ENOMEM;
00120         if (!getcwd(cwd, MAX_PATH_LEN + 1))
00121                 str_cpy(cwd, MAX_PATH_LEN + 1, "/"); 
00122         len = str_length(cwd);
00123         
00124         ipc_call_t answer;
00125         aid_t req = async_send_0(ldr->phone_id, LOADER_SET_CWD, &answer);
00126         int rc = async_data_write_start(ldr->phone_id, cwd, len);
00127         free(cwd);
00128         if (rc != EOK) {
00129                 async_wait_for(req, NULL);
00130                 return rc;
00131         }
00132         
00133         sysarg_t retval;
00134         async_wait_for(req, &retval);
00135         return (int) retval;
00136 }
00137 
00150 int loader_set_pathname(loader_t *ldr, const char *path)
00151 {
00152         size_t pa_len;
00153         char *pa = absolutize(path, &pa_len);
00154         if (!pa)
00155                 return 0;
00156         
00157         /* Send program pathname */
00158         ipc_call_t answer;
00159         aid_t req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer);
00160         int rc = async_data_write_start(ldr->phone_id, (void *) pa, pa_len);
00161         if (rc != EOK) {
00162                 free(pa);
00163                 async_wait_for(req, NULL);
00164                 return rc;
00165         }
00166         
00167         free(pa);
00168         
00169         sysarg_t retval;
00170         async_wait_for(req, &retval);
00171         return (int) retval;
00172 }
00173 
00186 int loader_set_args(loader_t *ldr, const char *const argv[])
00187 {
00188         /*
00189          * Serialize the arguments into a single array. First
00190          * compute size of the buffer needed.
00191          */
00192         const char *const *ap = argv;
00193         size_t buffer_size = 0;
00194         while (*ap != NULL) {
00195                 buffer_size += str_size(*ap) + 1;
00196                 ap++;
00197         }
00198         
00199         char *arg_buf = malloc(buffer_size);
00200         if (arg_buf == NULL)
00201                 return ENOMEM;
00202         
00203         /* Now fill the buffer with null-terminated argument strings */
00204         ap = argv;
00205         char *dp = arg_buf;
00206         
00207         while (*ap != NULL) {
00208                 str_cpy(dp, buffer_size - (dp - arg_buf), *ap);
00209                 dp += str_size(*ap) + 1;
00210                 ap++;
00211         }
00212         
00213         /* Send serialized arguments to the loader */
00214         ipc_call_t answer;
00215         aid_t req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
00216         sysarg_t rc = async_data_write_start(ldr->phone_id, (void *) arg_buf, buffer_size);
00217         if (rc != EOK) {
00218                 async_wait_for(req, NULL);
00219                 return rc;
00220         }
00221         
00222         async_wait_for(req, &rc);
00223         if (rc != EOK)
00224                 return rc;
00225         
00226         /* Free temporary buffer */
00227         free(arg_buf);
00228         
00229         return EOK;
00230 }
00231 
00244 int loader_set_files(loader_t *ldr, fdi_node_t *const files[])
00245 {
00246         /*
00247          * Serialize the arguments into a single array. First
00248          * compute size of the buffer needed.
00249          */
00250         fdi_node_t *const *ap = files;
00251         size_t count = 0;
00252         while (*ap != NULL) {
00253                 count++;
00254                 ap++;
00255         }
00256         
00257         fdi_node_t *files_buf;
00258         files_buf = (fdi_node_t *) malloc(count * sizeof(fdi_node_t));
00259         if (files_buf == NULL)
00260                 return ENOMEM;
00261         
00262         /* Fill the buffer */
00263         size_t i;
00264         for (i = 0; i < count; i++)
00265                 files_buf[i] = *files[i];
00266         
00267         /* Send serialized files to the loader */
00268         ipc_call_t answer;
00269         aid_t req = async_send_0(ldr->phone_id, LOADER_SET_FILES, &answer);
00270         sysarg_t rc = async_data_write_start(ldr->phone_id, (void *) files_buf,
00271             count * sizeof(fdi_node_t));
00272         if (rc != EOK) {
00273                 async_wait_for(req, NULL);
00274                 return rc;
00275         }
00276         
00277         async_wait_for(req, &rc);
00278         if (rc != EOK)
00279                 return rc;
00280         
00281         /* Free temporary buffer */
00282         free(files_buf);
00283         
00284         return EOK;
00285 }
00286 
00297 int loader_load_program(loader_t *ldr)
00298 {
00299         return (int) async_req_0_0(ldr->phone_id, LOADER_LOAD);
00300 }
00301 
00316 int loader_run(loader_t *ldr)
00317 {
00318         int rc = async_req_0_0(ldr->phone_id, LOADER_RUN);
00319         if (rc != EOK)
00320                 return rc;
00321         
00322         async_hangup(ldr->phone_id);
00323         ldr->phone_id = 0;
00324         return EOK;
00325 }
00326 
00338 void loader_abort(loader_t *ldr)
00339 {
00340         async_hangup(ldr->phone_id);
00341         ldr->phone_id = 0;
00342 }
00343 

Generated on Thu Jun 2 07:45:46 2011 for HelenOS/USB by  doxygen 1.4.7