diff --git a/fs/procfs/fs_procfsproc.c b/fs/procfs/fs_procfsproc.c index bcf1dba69b..59da3613ef 100644 --- a/fs/procfs/fs_procfsproc.c +++ b/fs/procfs/fs_procfsproc.c @@ -1,7 +1,7 @@ /**************************************************************************** * fs/procfs/fs_procfsproc.c * - * Copyright (C) 2013-2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2013-2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -92,6 +93,7 @@ /**************************************************************************** * Private Type Definitions ****************************************************************************/ + /* This enumeration identifies all of the task/thread nodes that can be * accessed via the procfs file system. */ @@ -108,6 +110,9 @@ enum proc_node_e PROC_GROUP, /* Group directory */ PROC_GROUP_STATUS, /* Task group status */ PROC_GROUP_FD /* Group file descriptors */ +#ifndef CONFIG_DISABLE_ENVIRON + , PROC_GROUP_ENV /* Group environment variables */ +#endif }; /* This structure associates a relative path name with an node in the task @@ -141,6 +146,18 @@ struct proc_dir_s pid_t pid; /* ID of task/thread for attributes */ }; +/* This structure used with the env_foreach() callback */ + +struct proc_envinfo_s +{ + FAR struct proc_file_s *procfile; + FAR char *buffer; + FAR off_t offset; + size_t buflen; + size_t remaining; + size_t totalsize; +}; + /**************************************************************************** * Private Data ****************************************************************************/ @@ -177,6 +194,12 @@ static ssize_t proc_groupstatus(FAR struct proc_file_s *procfile, static ssize_t proc_groupfd(FAR struct proc_file_s *procfile, FAR struct tcb_s *tcb, FAR char *buffer, size_t buflen, off_t offset); +#ifndef CONFIG_DISABLE_ENVIRON +static int proc_groupenv_callback(FAR void *arg, FAR const char *pair); +static ssize_t proc_groupenv(FAR struct proc_file_s *procfile, + FAR struct tcb_s *tcb, FAR char *buffer, size_t buflen, + off_t offset); +#endif /* File system methods */ @@ -270,6 +293,14 @@ static const struct proc_node_s g_groupfd = "group/fd", "fd", (uint8_t)PROC_GROUP_FD, DTYPE_FILE /* Group file descriptors */ }; +#ifndef CONFIG_DISABLE_ENVIRON +static const struct proc_node_s g_groupenv = +{ + "group/env", "env", (uint8_t)PROC_GROUP_ENV, DTYPE_FILE /* Group environment variables */ +}; + +#endif + /* This is the list of all nodes */ static FAR const struct proc_node_s * const g_nodeinfo[] = @@ -283,7 +314,11 @@ static FAR const struct proc_node_s * const g_nodeinfo[] = &g_group, /* Group directory */ &g_groupstatus, /* Task group status */ &g_groupfd /* Group file descriptors */ +#ifndef CONFIG_DISABLE_ENVIRON + , &g_groupenv /* Group environment variables */ +#endif }; + #define PROC_NNODES (sizeof(g_nodeinfo)/sizeof(FAR const struct proc_node_s * const)) /* This is the list of all level0 nodes */ @@ -306,6 +341,9 @@ static FAR const struct proc_node_s * const g_groupinfo[] = { &g_groupstatus, /* Task group status */ &g_groupfd /* Group file descriptors */ +#ifndef CONFIG_DISABLE_ENVIRON + , &g_groupenv /* Group environment variables */ +#endif }; #define PROC_NGROUPNODES (sizeof(g_groupinfo)/sizeof(FAR const struct proc_node_s * const)) @@ -1001,6 +1039,121 @@ static ssize_t proc_groupfd(FAR struct proc_file_s *procfile, return totalsize; } +/**************************************************************************** + * Name: proc_groupenv_callback + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_ENVIRON +static int proc_groupenv_callback(FAR void *arg, FAR const char *pair) +{ + FAR struct proc_envinfo_s *info = (FAR struct proc_envinfo_s *)arg; + FAR const char *src; + FAR const char *value; + FAR char *dest; + char name[16 + 1]; + size_t linesize; + size_t copysize; + int namelen; + + DEBUGASSERT(arg != NULL && pair != NULL); + + /* Parse the name from the name/value pair */ + + value = NULL; + namelen = 0; + + for (src = pair, dest = name; *src != '=' && *src != '\0'; src++) + { + if (namelen < 16) + { + *dest++ = *src; + namelen++; + } + } + + /* NUL terminate the name string */ + + *dest = '\0'; + + /* Skip over the '=' to get the value */ + + if (*src == '=') + { + value = src + 1; + } + else + { + value = ""; + } + + /* Output the header */ + + linesize = snprintf(info->procfile->line, STATUS_LINELEN, "%-16s %s\n", + name, value); + copysize = procfs_memcpy(info->procfile->line, linesize, info->buffer, + info->remaining, &info->offset); + + info->totalsize += copysize; + info->buffer += copysize; + info->remaining -= copysize; + + if (info->totalsize >= info->buflen) + { + return 1; + } + + return 0; +} +#endif + +/**************************************************************************** + * Name: proc_groupenv + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_ENVIRON +static ssize_t proc_groupenv(FAR struct proc_file_s *procfile, + FAR struct tcb_s *tcb, FAR char *buffer, size_t buflen, + off_t offset) +{ + FAR struct task_group_s *group = tcb->group; + size_t linesize; + size_t copysize; + struct proc_envinfo_s info; + + DEBUGASSERT(group); + + /* Initialize the info structure */ + + info.procfile = procfile; + info.buffer = buffer; + info.offset = offset; + info.buflen = buflen; + info.remaining = buflen; + info.totalsize = 0; + + /* Output the header */ + + linesize = snprintf(info.procfile->line, STATUS_LINELEN, "\n%-16s %s\n", + "VAR", "VALUE"); + copysize = procfs_memcpy(info.procfile->line, linesize, info.buffer, + info.remaining, &info.offset); + + info.totalsize += copysize; + info.buffer += copysize; + info.remaining -= copysize; + + if (info.totalsize >= info.buflen) + { + return info.totalsize; + } + + /* Generate output for each environment variable */ + + (void)env_foreach(group, proc_groupenv_callback, &info); + return info.totalsize; +} +#endif + /**************************************************************************** * Name: proc_open ****************************************************************************/ @@ -1188,6 +1341,12 @@ static ssize_t proc_read(FAR struct file *filep, FAR char *buffer, ret = proc_groupfd(procfile, tcb, buffer, buflen, filep->f_pos); break; +#ifndef CONFIG_DISABLE_ENVIRON + case PROC_GROUP_ENV: /* Group environment variables */ + ret = proc_groupenv(procfile, tcb, buffer, buflen, filep->f_pos); + break; +#endif + default: ret = -EINVAL; break; diff --git a/include/nuttx/environ.h b/include/nuttx/environ.h new file mode 100644 index 0000000000..1e4c1131b3 --- /dev/null +++ b/include/nuttx/environ.h @@ -0,0 +1,106 @@ +/**************************************************************************** + * include/nuttx/environ.h + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_ENVIRON_H +#define __INCLUDE_NUTTX_ENVIRON_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef CONFIG_DISABLE_ENVIRON + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Callback function used with env_foreach() */ + +typedef int (*env_foreach_t)(FAR void *arg, FAR const char *pair); + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: env_foreach + * + * Description: + * Search the provided environment structure for the variable of the + * specified name. + * + * This is an internal OS function and should not be used by applications. + * + * Input Parameters: + * group - The task group containing environment array to be searched. + * cb - The callback function to be invoked for each environment + * variable. + * + * Returned Value: + * Zero if the all environment variables have been traversed. A non-zero + * value means that the callback function requested early termination by + * returning a nonzero value. + * + * Assumptions: + * - Not called from an interrupt handler + * - Pre-emption is disabled by caller + * + ****************************************************************************/ + +struct task_group_s; /* Forward reference */ +int env_foreach(FAR struct task_group_s *group, env_foreach_t cb, + FAR void *arg); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* !CONFIG_DISABLE_ENVIRON */ +#endif /* __INCLUDE_NUTTX_ENVIRON_H */ diff --git a/sched/environ/Make.defs b/sched/environ/Make.defs index 2ecb98abca..3309e0b931 100644 --- a/sched/environ/Make.defs +++ b/sched/environ/Make.defs @@ -37,7 +37,7 @@ ifneq ($(CONFIG_DISABLE_ENVIRON),y) CSRCS += env_getenvironptr.c env_dup.c env_release.c env_findvar.c CSRCS += env_removevar.c env_clearenv.c env_getenv.c env_putenv.c -CSRCS += env_setenv.c env_unsetenv.c +CSRCS += env_setenv.c env_unsetenv.c env_foreach.c # Include environ build support diff --git a/sched/environ/env_dup.c b/sched/environ/env_dup.c index 35a95608be..8ce8673d57 100644 --- a/sched/environ/env_dup.c +++ b/sched/environ/env_dup.c @@ -64,8 +64,8 @@ * exact duplicate of the parent task's environment. * * Input Parameters: - * group The child task group to receive the newly allocated copy of the - * parent task groups environment structure. + * group - The child task group to receive the newly allocated copy of the + * parent task groups environment structure. * * Returned Value: * zero on success diff --git a/sched/environ/env_findvar.c b/sched/environ/env_findvar.c index 23e7fe964f..f44d91e4dc 100644 --- a/sched/environ/env_findvar.c +++ b/sched/environ/env_findvar.c @@ -59,9 +59,11 @@ static bool env_cmpname(const char *pszname, const char *peqname) { /* Search until we find anything different in the two names */ - for (; *pszname == *peqname; pszname++, peqname++); + for (; *pszname == *peqname; pszname++, peqname++) + { + } - /* On sucess, pszname will end with '\0' and peqname with '=' */ + /* On success, pszname will end with '\0' and peqname with '=' */ if (*pszname == '\0' && *peqname == '=') { @@ -83,26 +85,26 @@ static bool env_cmpname(const char *pszname, const char *peqname) * specified name. * * Input Parameters: - * group The task group containging environment array to be searched. - * pname The variable name to find + * group - The task group containing environment array to be searched. + * pname - The variable name to find * * Returned Value: * A pointer to the name=value string in the environment * * Assumptions: * - Not called from an interrupt handler - * - Pre-emptions is disabled by caller + * - Pre-emption is disabled by caller * ****************************************************************************/ -FAR char *env_findvar(FAR struct task_group_s *group, const char *pname) +FAR char *env_findvar(FAR struct task_group_s *group, FAR const char *pname) { - char *ptr; - char *end; + FAR char *ptr; + FAR char *end; /* Verify input parameters */ - DEBUGASSERT(group && pname); + DEBUGASSERT(group != NULL && pname != NULL); /* Search for a name=value string with matching name */ @@ -117,6 +119,3 @@ FAR char *env_findvar(FAR struct task_group_s *group, const char *pname) } #endif /* CONFIG_DISABLE_ENVIRON */ - - - diff --git a/sched/environ/env_foreach.c b/sched/environ/env_foreach.c new file mode 100644 index 0000000000..8caca1d961 --- /dev/null +++ b/sched/environ/env_foreach.c @@ -0,0 +1,111 @@ +/**************************************************************************** + * sched/environ/env_foreach.c + * + * Copyright (C) 2018 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#ifndef CONFIG_DISABLE_ENVIRON + +#include +#include +#include + +#include + +#include "environ/environ.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: env_foreach + * + * Description: + * Search the provided environment structure for the variable of the + * specified name. + * + * Input Parameters: + * group - The task group containing environment array to be searched. + * cb - The callback function to be invoked for each environment + * variable. + * + * Returned Value: + * Zero if the all environment variables have been traversed. A non-zero + * value means that the callback function requested early termination by + * returning a nonzero value. + * + * Assumptions: + * - Not called from an interrupt handler + * - Pre-emptions is disabled by caller + * + ****************************************************************************/ + +int env_foreach(FAR struct task_group_s *group, env_foreach_t cb, FAR void *arg) +{ + FAR char *ptr; + FAR char *end; + int ret = OK; + + /* Verify input parameters */ + + DEBUGASSERT(group != NULL && cb != NULL); + + /* Search for a name=value string with matching name */ + + end = &group->tg_envp[group->tg_envsize]; + for (ptr = group->tg_envp; ptr < end; ptr += (strlen(ptr) + 1)) + { + /* Perform the callback */ + + ret = cb(arg, ptr); + + /* Terminate the traversal early if the callback so requests by + * returning a non-zero value. + */ + + if (ret != 0) + { + break; + } + } + + return ret; +} + +#endif /* CONFIG_DISABLE_ENVIRON */ diff --git a/sched/environ/env_getenv.c b/sched/environ/env_getenv.c index 682e67fc9c..260d31655c 100644 --- a/sched/environ/env_getenv.c +++ b/sched/environ/env_getenv.c @@ -71,7 +71,7 @@ * ****************************************************************************/ -FAR char *getenv(const char *name) +FAR char *getenv(FAR const char *name) { FAR struct tcb_s *rtcb; FAR struct task_group_s *group; diff --git a/sched/environ/env_release.c b/sched/environ/env_release.c index 1ce40c631d..61a113559b 100644 --- a/sched/environ/env_release.c +++ b/sched/environ/env_release.c @@ -62,8 +62,8 @@ * environ to NULL. * * Input Parameters: - * group Identifies the task group containing the environment structure - * to be released. + * group - Identifies the task group containing the environment structure + * to be released. * * Returned Value: * None @@ -75,7 +75,7 @@ void env_release(FAR struct task_group_s *group) { - DEBUGASSERT(group); + DEBUGASSERT(group != NULL); /* Free any allocate environment strings */ diff --git a/sched/environ/env_removevar.c b/sched/environ/env_removevar.c index cebad6ef5d..0ac54e7100 100644 --- a/sched/environ/env_removevar.c +++ b/sched/environ/env_removevar.c @@ -57,15 +57,16 @@ * Remove the referenced name=value pair from the environment * * Input Parameters: - * group The task group with the environment containing the name=value pair - * pvar A pointer to the name=value pair in the restroom + * group - The task group with the environment containing the name=value + * pair + * pvar - A pointer to the name=value pair in the restroom * * Returned Value: * Zero on success * * Assumptions: * - Not called from an interrupt handler - * - Caller has pre-emptions disabled + * - Caller has pre-emption disabled * - Caller will reallocate the environment structure to the correct size * ****************************************************************************/ @@ -76,7 +77,7 @@ int env_removevar(FAR struct task_group_s *group, FAR char *pvar) int alloc; /* Size of the allocated environment */ int ret = ERROR; - DEBUGASSERT(group && pvar); + DEBUGASSERT(group != NULL && pvar != NULL); /* Verify that the pointer lies within the environment region */ diff --git a/sched/environ/environ.h b/sched/environ/environ.h index 7ad59626e5..1899cc26e2 100644 --- a/sched/environ/environ.h +++ b/sched/environ/environ.h @@ -1,7 +1,8 @@ /**************************************************************************** * sched/environ/environ.h * - * Copyright (C) 2007, 2009, 2013-2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2009, 2013-2014, 2018 Gregory Nutt. All rights + * reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -48,8 +49,8 @@ ****************************************************************************/ #ifdef CONFIG_DISABLE_ENVIRON -# define env_dup(group) (0) -# define env_release(group) (0) +# define env_dup(group) (0) +# define env_release(group) (0) #else /**************************************************************************** @@ -68,14 +69,94 @@ extern "C" * Public Function Prototypes ****************************************************************************/ -/* Functions used by the task/pthread creation and destruction logic */ +/**************************************************************************** + * Name: env_dup + * + * Description: + * Copy the internal environment structure of a task. This is the action + * that is performed when a new task is created: The new task has a private, + * exact duplicate of the parent task's environment. + * + * Input Parameters: + * group - The child task group to receive the newly allocated copy of the + * parent task groups environment structure. + * + * Returned Value: + * zero on success + * + * Assumptions: + * Not called from an interrupt handler. + * + ****************************************************************************/ int env_dup(FAR struct task_group_s *group); + +/**************************************************************************** + * Name: env_release + * + * Description: + * env_release() is called only from group_leave() when the last member of + * a task group exits. The env_release() function clears the environment + * of all name-value pairs and sets the value of the external variable + * environ to NULL. + * + * Input Parameters: + * group - Identifies the task group containing the environment structure + * to be released. + * + * Returned Value: + * None + * + * Assumptions: + * Not called from an interrupt handler + * + ****************************************************************************/ + void env_release(FAR struct task_group_s *group); -/* Functions used internally by the environment handling logic */ +/**************************************************************************** + * Name: env_findvar + * + * Description: + * Search the provided environment structure for the variable of the + * specified name. + * + * Input Parameters: + * group - The task group containing environment array to be searched. + * pname - The variable name to find + * + * Returned Value: + * A pointer to the name=value string in the environment + * + * Assumptions: + * - Not called from an interrupt handler + * - Pre-emption is disabled by caller + * + ****************************************************************************/ FAR char *env_findvar(FAR struct task_group_s *group, FAR const char *pname); + +/**************************************************************************** + * Name: env_removevar + * + * Description: + * Remove the referenced name=value pair from the environment + * + * Input Parameters: + * group - The task group with the environment containing the name=value + * pair + * pvar - A pointer to the name=value pair in the restroom + * + * Returned Value: + * Zero on success + * + * Assumptions: + * - Not called from an interrupt handler + * - Caller has pre-emption disabled + * - Caller will reallocate the environment structure to the correct size + * + ****************************************************************************/ + int env_removevar(FAR struct task_group_s *group, FAR char *pvar); #undef EXTERN