Subversion Repositories HelenOS

Rev

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