Subversion Repositories HelenOS

Rev

Rev 4345 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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