fs/proc and sched/environ: Add support for a procfs entry that will permit examining the environment of any task.

This commit is contained in:
Gregory Nutt 2018-08-10 10:16:39 -06:00
parent 672c6a5405
commit 25fa50d504
10 changed files with 486 additions and 29 deletions

View file

@ -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 <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -57,6 +57,7 @@
#include <nuttx/arch.h>
#include <nuttx/sched.h>
#include <nuttx/kmalloc.h>
#include <nuttx/environ.h>
#include <nuttx/fs/fs.h>
#include <nuttx/fs/procfs.h>
#include <nuttx/fs/dirent.h>
@ -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;

106
include/nuttx/environ.h Normal file
View file

@ -0,0 +1,106 @@
/****************************************************************************
* include/nuttx/environ.h
*
* Copyright (C) 2018 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.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_ENVIRON_H
#define __INCLUDE_NUTTX_ENVIRON_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#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 */

View file

@ -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

View file

@ -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

View file

@ -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 */

111
sched/environ/env_foreach.c Normal file
View file

@ -0,0 +1,111 @@
/****************************************************************************
* sched/environ/env_foreach.c
*
* Copyright (C) 2018 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>
#ifndef CONFIG_DISABLE_ENVIRON
#include <stdbool.h>
#include <string.h>
#include <sched.h>
#include <nuttx/environ.h>
#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 */

View file

@ -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;

View file

@ -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 */

View file

@ -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 */

View file

@ -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 <gnutt@nuttx.org>
*
* 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