Subversion Repositories HelenOS

Rev

Rev 3896 | Rev 4055 | 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, strlen(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 += strlen(*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.     while (*ap != NULL) {
  182.         strcpy(dp, *ap);
  183.         dp += strlen(*ap) + 1;
  184.  
  185.         ++ap;
  186.     }
  187.  
  188.     /* Send serialized arguments to the loader */
  189.  
  190.     req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
  191.     rc = ipc_data_write_start(ldr->phone_id, (void *)arg_buf, buffer_size);
  192.     if (rc != EOK) {
  193.         async_wait_for(req, NULL);
  194.         return rc;
  195.     }
  196.  
  197.     async_wait_for(req, &rc);
  198.     if (rc != EOK) return rc;
  199.  
  200.     /* Free temporary buffer */
  201.     free(arg_buf);
  202.  
  203.     return EOK;
  204. }
  205.  
  206. /** Instruct loader to load the program.
  207.  *
  208.  * If this function succeeds, the program has been successfully loaded
  209.  * and is ready to be executed.
  210.  *
  211.  * @param ldr       Loader connection structure.
  212.  * @return      Zero on success or negative error code.
  213.  */
  214. int loader_load_program(loader_t *ldr)
  215. {
  216.     int rc;
  217.  
  218.     rc = async_req_0_0(ldr->phone_id, LOADER_LOAD);
  219.     if (rc != EOK)
  220.         return rc;
  221.  
  222.     return EOK;
  223. }
  224.  
  225. /** Instruct loader to execute the program.
  226.  *
  227.  * Note that this function blocks until the loader actually replies
  228.  * so you cannot expect this function to return if you are debugging
  229.  * the task and its thread is stopped.
  230.  *
  231.  * After using this function, no further operations must be performed
  232.  * on the loader structure. It should be de-allocated using free().
  233.  *
  234.  * @param ldr       Loader connection structure.
  235.  * @return      Zero on success or negative error code.
  236.  */
  237. int loader_run(loader_t *ldr)
  238. {
  239.     int rc;
  240.  
  241.     rc = async_req_0_0(ldr->phone_id, LOADER_RUN);
  242.     if (rc != EOK)
  243.         return rc;
  244.  
  245.     return EOK;
  246. }
  247.  
  248. /** Cancel the loader session.
  249.  *
  250.  * Tells the loader not to load any program and terminate.
  251.  * After using this function, no further operations must be performed
  252.  * on the loader structure. It should be de-allocated using free().
  253.  *
  254.  * @param ldr       Loader connection structure.
  255.  * @return      Zero on success or negative error code.
  256.  */
  257. void loader_abort(loader_t *ldr)
  258. {
  259.     ipc_hangup(ldr->phone_id);
  260.     ldr->phone_id = 0;
  261. }
  262.  
  263. /** @}
  264.  */
  265.