ts_functions.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /*! \file
3  * \brief Thread safe replacement functions
4  *
5  * Copyright (c) 2012-2022 by the developers. See the LICENSE file for details.
6  * If nothing else is specified, functions return zero to indicate success
7  * and a negative value to indicate an error.
8  */
9 
10 
11 /* ========================================================================== */
12 /* Include headers */
13 
14 #include "posix.h" /* Include this first because of feature test macros */
15 
16 #include "main.h"
17 
18 
19 /* ========================================================================== */
20 /*! \addtogroup MAIN
21  *
22  * The POSIX \c getenv() function is not required to be thread safe. Therefore
23  * we must provide our own. It was considered to clone the getenv_r() function
24  * from BSD, but this function has no buffer management and is inconvenient to
25  * use. The function \c ts_getenv() dynamically allocate or resize the thread
26  * local buffer internally.
27  *
28  * \note
29  * A copy of the enviroment is used, therefore all modifications of the
30  * enviroment at runtime are invisible via \c ts_getenv(). \c ts_environ_init()
31  * and \c ts_environ_exit() must be called to create and destroy this copy of
32  * the enviroment.
33  */
34 /*! @{ */
35 
36 
37 /* ========================================================================== */
38 /* Constants */
39 
40 /*! \brief Message prefix for MAIN module */
41 #define MAIN_ERR_PREFIX "MAIN: "
42 
43 
44 /* ========================================================================== */
45 /* Variables */
46 
47 static char** environ_copy = NULL;
48 static char* environ_data = NULL;
49 
50 
51 /* ========================================================================== */
52 /*! \brief Copy environment variables
53  *
54  * Must be called once before \c ts_getenv() is used and before additional
55  * threads are created.
56  */
57 
58 void ts_environ_init(void)
59 {
60  size_t i = 0;
61  size_t di;
62  size_t len = 0;
63  size_t alen;
64 
65  /* Calculate size of strings */
66  while(NULL != posix_environ[i])
67  {
68  len += strlen(posix_environ[i]) + (size_t) 1;
69  ++i;
70  }
71  /* Calculate size of NULL-terminated pointer array */
72  alen = sizeof(char*) * ++i;
73 
74  /* Allocate memory for pointer array */
75  environ_copy = (char**) malloc(alen);
76  if(NULL != environ_copy)
77  {
78  environ_copy[0] = NULL;
79 
80  /* Allocate memory for string data */
81  environ_data = (char*) malloc(len);
82  if(NULL != environ_data)
83  {
84  i = 0;
85  di = 0;
86  while(NULL != posix_environ[i])
87  {
88  strcpy(&environ_data[di], posix_environ[i]);
89  environ_copy[i] = &environ_data[di];
90  di += strlen(posix_environ[i]) + (size_t) 1;
91  ++i;
92  }
93  environ_copy[i] = NULL;
94  }
95  }
96 
97  return;
98 }
99 
100 
101 /* ========================================================================== */
102 /*! \brief Destroy copy of environment variables
103  *
104  * Call this function once after last use of \c ts_getenv() .
105  */
106 
107 void ts_environ_exit(void)
108 {
109  posix_free((void*) environ_data);
110  posix_free((void*) environ_copy);
111 
112  return;
113 }
114 
115 
116 /* ========================================================================== */
117 /*! \brief Thread safe replacement for \c getenv()
118  *
119  * \param[in] name Name of the requested environment variable
120  * \param[in,out] buf Pointer to pointer to buffer for result
121  *
122  * Dereferenced \e buf must be either \c NULL or an existing dynamically
123  * allocated buffer that can be resized with \c realloc() if required.
124  *
125  * The buffer pointed to by \e buf is created or resized so that it can hold the
126  * result and the value of the environment variable \e name is copied to it.
127  *
128  * The caller is responsible to free the memory allocated for the buffer on
129  * success.
130  *
131  * \return
132  * - 0 on success
133  * - Negative value on error
134  */
135 
136 int ts_getenv(const char* name, const char** buf)
137 {
138  int res = -1;
139  size_t i;
140  size_t len;
141  char* content;
142  char* tmp;
143 
144  if(NULL != environ_copy && NULL != buf)
145  {
146  /* Search for variable in copy of environment */
147  i = 0;
148  while(NULL != environ_copy[i])
149  {
150  len = strlen(name);
151  if(!strncmp(environ_copy[i], name, len))
152  {
153  if('=' == environ_copy[i][len])
154  {
155  /* Found => Copy content to target buffer */
156  content = &environ_copy[i][++len];
157  len = strlen(content);
158  tmp = (char*) posix_realloc((void*) *buf, ++len);
159  if(NULL != tmp)
160  {
161  strcpy(tmp, content);
162  *buf = tmp;
163  res = 0;
164  }
165  break;
166  }
167  }
168  ++i;
169  }
170  /* Check for error */
171  if(res)
172  {
173  posix_free((void*) *buf);
174  *buf = NULL;
175  }
176  }
177 
178  return(res);
179 }
180 
181 
182 /*! @} */
183 
184 /* EOF */
ts_environ_exit
void ts_environ_exit(void)
Destroy copy of environment variables.
Definition: ts_functions.c:107
ts_environ_init
void ts_environ_init(void)
Copy environment variables.
Definition: ts_functions.c:58
ts_getenv
int ts_getenv(const char *name, const char **buf)
Thread safe replacement for getenv()
Definition: ts_functions.c:136

Generated at 2024-04-27 using  doxygen