summaryrefslogtreecommitdiff
path: root/nuttx/binfmt/binfmt_exepath.c
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-12-16 21:15:27 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-12-16 21:15:27 +0000
commit3dfe9f3ba541f759e690bc112cb9025737970d5a (patch)
tree966aa2197272d9b52e3e25177cd78cea2751ade2 /nuttx/binfmt/binfmt_exepath.c
parent2fe1350cbd4c9deefa22a2c5785621a258e7a81c (diff)
downloadnuttx-3dfe9f3ba541f759e690bc112cb9025737970d5a.tar.gz
nuttx-3dfe9f3ba541f759e690bc112cb9025737970d5a.tar.bz2
nuttx-3dfe9f3ba541f759e690bc112cb9025737970d5a.zip
Add basic hooks to support a PATH variable (more is needed)
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5440 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/binfmt/binfmt_exepath.c')
-rw-r--r--nuttx/binfmt/binfmt_exepath.c285
1 files changed, 285 insertions, 0 deletions
diff --git a/nuttx/binfmt/binfmt_exepath.c b/nuttx/binfmt/binfmt_exepath.c
new file mode 100644
index 000000000..c81588975
--- /dev/null
+++ b/nuttx/binfmt/binfmt_exepath.c
@@ -0,0 +1,285 @@
+/****************************************************************************
+ * binfmt/binfmt_exepath.c
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/binfmt/binfmt.h>
+
+#if !defined(CONFIG_BINFMT_DISABLE) && defined(CONFIG_BINFMT_EXEPATH)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct exepath_s
+{
+ FAR char *next; /* Pointer to the next (unterminated) value in the PATH variable */
+ char path[1];
+};
+#define SIZEOF_EXEPATH_S(n) (sizeof(struct exepath_s) + (n) - 1)
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: exepath_init
+ *
+ * Description:
+ * Initialize for the traversal of each value in the PATH variable. The
+ * usage is sequence is as follows:
+ *
+ * 1) Call exepath_init() to initialze for the traversal. exepath_init()
+ * will return an opaque handle that can then be provided to
+ * exepath_next() and exepath_release().
+ * 2) Call exepath_next() repeatedly to examine every file that lies
+ * in the directories of the PATH variable
+ * 3) Call exepath_release() to free resources set aside by exepath_init().
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * On success, exepath_init() return a non-NULL, opaque handle that may
+ * subsequently be used in calls to exepath_next() and exepath_release().
+ * On error, a NULL handle value will be returned. The most likely cause
+ * of an error would be that the there is no value associated with the
+ * PATH variable.
+ *
+ ****************************************************************************/
+
+EXEPATH_HANDLE exepath_init(void)
+{
+ FAR struct exepath_s *exepath;
+ FAR char *path;
+
+ /* Get the value of the PATH variable */
+
+ path = getenv("PATH");
+ if (!path)
+ {
+ /* getenv() will return a NULL value if the PATH variable does not
+ * exist in the environment.
+ */
+
+ return (EXEPATH_HANDLE)NULL;
+ }
+
+ /* Allocate a container for the PATH variable contents */
+
+ exepath = (FAR struct exepath_s *)kmalloc(SIZEOF_EXEPATH_S(strlen(path) + 1));
+ if (!exepath)
+ {
+ /* Ooops.. we are out of memory */
+
+ return (EXEPATH_HANDLE)NULL;
+ }
+
+ /* Populate the container */
+
+ strcpy(exepath->path, path);
+ exepath->next = exepath->path;
+
+ /* And return the containing cast to an opaque handle */
+
+ return (EXEPATH_HANDLE)exepath;
+}
+
+ /****************************************************************************
+ * Name: exepath_next
+ *
+ * Description:
+ * Traverse all possible values in the PATH variable in attempt to find
+ * the full path to an executable file when only a relative path is
+ * provided.
+ *
+ * Input Parameters:
+ * handle - The handle value returned by exepath_init
+ * relpath - The relative path to the file to be found.
+ *
+ * Returned Value:
+ * On success, a non-NULL pointer to a null-terminated string is provided.
+ * This is the full path to a file that exists in the file system. This
+ * function will verify that the file exists (but will not verify that it
+ * is marked executable).
+ *
+ * NOTE: The string pointer return in the success case points to allocated
+ * memory. This memory must be freed by the called by calling kfree().
+ *
+ * NULL is returned if no path is found to any file with the provided
+ * 'relpath' from any absolute path in the file variable. In this case,
+ * there is no point in calling exepath_next() further; exepath_release()
+ * must be called to release resources set aside by expath_init().
+ *
+ ****************************************************************************/
+
+FAR char *exepath_next(EXEPATH_HANDLE handle, FAR const char *relpath)
+{
+ FAR struct exepath_s *exepath = (FAR struct exepath_s *)handle;
+ struct stat buf;
+ FAR char *endptr;
+ FAR char *path;
+ FAR char *fullpath;
+ int pathlen;
+ int ret;
+
+ /* Verify that a value handle and relative path were provided */
+
+ DEBUGASSERT(exepath && relpath);
+ DEBUGASSERT(relpath[0] != '\0' && relpath[0] != '/');
+
+ /* Loop until (1) we find a file with this relative path from one of the
+ * absolute paths in the PATH variable, or (2) all of the absolute paths
+ * in the PATH variable have been considered.
+ */
+
+ for (;;)
+ {
+ /* Make sure that exepath->next points to the beginning of a string */
+
+ path = exepath->next;
+ if (*path == '\0')
+ {
+ /* If it points to a NULL it means that either (1) the PATH varialbe
+ * is empty, or (2) we have already examined all of the paths in the
+ * path variable.
+ */
+
+ return (FAR char *)NULL;
+ }
+
+ /* Okay... 'path' points to the beginning of the string. The string may
+ * be termined either with (1) ':' which separates the path from the
+ * next path in the list, or (2) NUL which marks the end of the list.
+ */
+
+ endptr = strchr(path, ':');
+ if (!endptr)
+ {
+ /* If strchr returns NUL it means that ':' does not appear in the
+ * string. Therefore, this must be the final path in the PATH
+ * variable content.
+ */
+
+ endptr = &path[strlen(path)];
+ exepath->next = endptr;
+ DEBUGASSERT(*endptr == '\0');
+ }
+ else
+ {
+ DEBUGASSERT(*endptr == ':');
+ exepath->next = endptr + 1;
+ *endptr = '\0';
+ }
+
+ pathlen = strlen(path) + strlen(relpath) + 2;
+ fullpath = (FAR char *)kmalloc(pathlen);
+ if (!fullpath)
+ {
+ /* Failed to allocate memory */
+
+ return (FAR char *)NULL;
+ }
+
+ /* Construct the full path */
+
+ sprintf(fullpath, "%s/%s", path, relpath);
+
+ /* Verify that a regular file exists at this path */
+
+ ret = stat(fullpath, &buf);;
+ if (ret == OK && S_ISREG(buf.st_mode))
+ {
+ return fullpath;
+ }
+
+ /* Failed to stat the file. Just free the allocated memory and
+ * continue to try the next path.
+ */
+
+ kfree(fullpath);
+ }
+
+ /* We will not get here */
+}
+
+/****************************************************************************
+ * Name: exepath_release
+ *
+ * Description:
+ * Release all resources set aside by exepath_release when the handle value
+ * was created. The handle value is invalid on return from this function.
+ * Attempts to all exepath_next() or exepath_release() with such a 'stale'
+ * handle will result in undefined (i.e., not good) behavior.
+ *
+ * Input Parameters:
+ * handle - The handle value returned by exepath_init
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void exepath_release(EXEPATH_HANDLE handle)
+{
+ kfree(handle);
+}
+
+#endif /* !CONFIG_BINFMT_DISABLE && CONFIG_BINFMT_EXEPATH */
+