Subversion Repositories HelenOS

Rev

Rev 4476 | 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.  *
  51.  * @param name Symbolic name to set on the newly created task.
  52.  *
  53.  * @return Pointer to the loader connection structure (should be
  54.  *         deallocated using free() after use).
  55.  *
  56.  */
  57. int loader_spawn(const char *name)
  58. {
  59.     return __SYSCALL2(SYS_PROGRAM_SPAWN_LOADER,
  60.         (sysarg_t) name, str_size(name));
  61. }
  62.  
  63. loader_t *loader_connect(void)
  64. {
  65.     int phone_id = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_LOAD, 0, 0);
  66.     if (phone_id < 0)
  67.         return NULL;
  68.    
  69.     loader_t *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.  *
  84.  * @return Zero on success or negative error code.
  85.  *
  86.  */
  87. int loader_get_task_id(loader_t *ldr, task_id_t *task_id)
  88. {
  89.     /* Get task ID. */
  90.     ipc_call_t answer;
  91.     aid_t req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer);
  92.     int rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t));
  93.     if (rc != EOK) {
  94.         async_wait_for(req, NULL);
  95.         return rc;
  96.     }
  97.    
  98.     ipcarg_t retval;
  99.     async_wait_for(req, &retval);
  100.     return (int) retval;
  101. }
  102.  
  103. /** Set pathname of the program to load.
  104.  *
  105.  * Sets the name of the program file to load. The name can be relative
  106.  * to the current working directory (it will be absolutized before
  107.  * sending to the loader).
  108.  *
  109.  * @param ldr  Loader connection structure.
  110.  * @param path Pathname of the program file.
  111.  *
  112.  * @return Zero on success or negative error code.
  113.  *
  114.  */
  115. int loader_set_pathname(loader_t *ldr, const char *path)
  116. {
  117.     size_t pa_len;
  118.     char *pa = absolutize(path, &pa_len);
  119.     if (!pa)
  120.         return 0;
  121.    
  122.     /* Send program pathname */
  123.     ipc_call_t answer;
  124.     aid_t req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer);
  125.     int rc = ipc_data_write_start(ldr->phone_id, (void *) pa, pa_len);
  126.     if (rc != EOK) {
  127.         async_wait_for(req, NULL);
  128.         return rc;
  129.     }
  130.    
  131.     free(pa);
  132.    
  133.     ipcarg_t retval;
  134.     async_wait_for(req, &retval);
  135.     return (int) retval;
  136. }
  137.  
  138. /** Set command-line arguments for the program.
  139.  *
  140.  * Sets the vector of command-line arguments to be passed to the loaded
  141.  * program. By convention, the very first argument is typically the same as
  142.  * the command used to execute the program.
  143.  *
  144.  * @param ldr  Loader connection structure.
  145.  * @param argv NULL-terminated array of pointers to arguments.
  146.  *
  147.  * @return Zero on success or negative error code.
  148.  *
  149.  */
  150. int loader_set_args(loader_t *ldr, char *const argv[])
  151. {
  152.     /*
  153.      * Serialize the arguments into a single array. First
  154.      * compute size of the buffer needed.
  155.      */
  156.     char *const *ap = argv;
  157.     size_t buffer_size = 0;
  158.     while (*ap != NULL) {
  159.         buffer_size += str_size(*ap) + 1;
  160.         ap++;
  161.     }
  162.    
  163.     char *arg_buf = malloc(buffer_size);
  164.     if (arg_buf == NULL)
  165.         return ENOMEM;
  166.    
  167.     /* Now fill the buffer with null-terminated argument strings */
  168.     ap = argv;
  169.     char *dp = arg_buf;
  170.    
  171.     while (*ap != NULL) {
  172.         str_cpy(dp, buffer_size - (dp - arg_buf), *ap);
  173.         dp += str_size(*ap) + 1;
  174.         ap++;
  175.     }
  176.    
  177.     /* Send serialized arguments to the loader */
  178.     ipc_call_t answer;
  179.     aid_t req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
  180.     ipcarg_t rc = ipc_data_write_start(ldr->phone_id, (void *) arg_buf, buffer_size);
  181.     if (rc != EOK) {
  182.         async_wait_for(req, NULL);
  183.         return rc;
  184.     }
  185.    
  186.     async_wait_for(req, &rc);
  187.     if (rc != EOK)
  188.         return rc;
  189.    
  190.     /* Free temporary buffer */
  191.     free(arg_buf);
  192.    
  193.     return EOK;
  194. }
  195.  
  196. /** Set preset files for the program.
  197.  *
  198.  * Sets the vector of preset files to be passed to the loaded
  199.  * program. By convention, the first three files represent stdin,
  200.  * stdout and stderr respectively.
  201.  *
  202.  * @param ldr   Loader connection structure.
  203.  * @param files NULL-terminated array of pointers to files.
  204.  *
  205.  * @return Zero on success or negative error code.
  206.  *
  207.  */
  208. int loader_set_files(loader_t *ldr, inode_t *const files[])
  209. {
  210.     /*
  211.      * Serialize the arguments into a single array. First
  212.      * compute size of the buffer needed.
  213.      */
  214.     inode_t *const *ap = files;
  215.     size_t count = 0;
  216.     while (*ap != NULL) {
  217.         count++;
  218.         ap++;
  219.     }
  220.    
  221.     inode_t *files_buf = (inode_t *) malloc(count * sizeof(inode_t));
  222.     if (files_buf == NULL)
  223.         return ENOMEM;
  224.    
  225.     /* Fill the buffer */
  226.     size_t i;
  227.     for (i = 0; i < count; i++)
  228.         files_buf[i] = *files[i];
  229.    
  230.     /* Send serialized files to the loader */
  231.     ipc_call_t answer;
  232.     aid_t req = async_send_0(ldr->phone_id, LOADER_SET_FILES, &answer);
  233.     ipcarg_t rc = ipc_data_write_start(ldr->phone_id, (void *) files_buf,
  234.         count * sizeof(inode_t));
  235.     if (rc != EOK) {
  236.         async_wait_for(req, NULL);
  237.         return rc;
  238.     }
  239.    
  240.     async_wait_for(req, &rc);
  241.     if (rc != EOK)
  242.         return rc;
  243.    
  244.     /* Free temporary buffer */
  245.     free(files_buf);
  246.    
  247.     return EOK;
  248. }
  249.  
  250. /** Instruct loader to load the program.
  251.  *
  252.  * If this function succeeds, the program has been successfully loaded
  253.  * and is ready to be executed.
  254.  *
  255.  * @param ldr Loader connection structure.
  256.  *
  257.  * @return Zero on success or negative error code.
  258.  *
  259.  */
  260. int loader_load_program(loader_t *ldr)
  261. {
  262.     return (int) async_req_0_0(ldr->phone_id, LOADER_LOAD);
  263. }
  264.  
  265. /** Instruct loader to execute the program.
  266.  *
  267.  * Note that this function blocks until the loader actually replies
  268.  * so you cannot expect this function to return if you are debugging
  269.  * the task and its thread is stopped.
  270.  *
  271.  * After using this function, no further operations must be performed
  272.  * on the loader structure. It should be de-allocated using free().
  273.  *
  274.  * @param ldr Loader connection structure.
  275.  *
  276.  * @return Zero on success or negative error code.
  277.  *
  278.  */
  279. int loader_run(loader_t *ldr)
  280. {
  281.     int rc = async_req_0_0(ldr->phone_id, LOADER_RUN);
  282.     if (rc != EOK)
  283.         return rc;
  284.    
  285.     ipc_hangup(ldr->phone_id);
  286.     ldr->phone_id = 0;
  287.     return EOK;
  288. }
  289.  
  290. /** Cancel the loader session.
  291.  *
  292.  * Tells the loader not to load any program and terminate.
  293.  * After using this function, no further operations must be performed
  294.  * on the loader structure. It should be de-allocated using free().
  295.  *
  296.  * @param ldr Loader connection structure.
  297.  *
  298.  * @return Zero on success or negative error code.
  299.  *
  300.  */
  301. void loader_abort(loader_t *ldr)
  302. {
  303.     ipc_hangup(ldr->phone_id);
  304.     ldr->phone_id = 0;
  305. }
  306.  
  307. /** @}
  308.  */
  309.