1 /* se4ssiobn-env.c - session environment helper functions.
2 * Copyright (C) 2009 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
28 #include "session-env.h"
33 char *value; /* Pointer into NAME to the Nul terminated value. */
34 int is_default; /* The value is a default one. */
35 char name[1]; /* Nul terminated Name and space for the value. */
40 /* The session environment object. */
41 struct session_environment_s
43 size_t arraysize; /* Allocated size or ARRAY. */
44 size_t arrayused; /* Used size of ARRAY. */
45 struct variable_s **array; /* Array of variables. NULL slots are unused. */
49 /* A list of environment vribales we pass from the acual user
50 (e.g. gpgme) down to the pinentry. We do not handle the locale
51 settings because they do not only depend on envvars. */
55 const char *assname; /* Name used by Assuan or NULL. */
57 { "GPG_TTY", "ttyname" }, /* GnuPG specific envvar. */
58 { "TERM", "ttytype" }, /* Used to set ttytype. */
59 { "DISPLAY", "display" }, /* The X-Display. */
60 { "XAUTHORITY","xauthority"}, /* Xlib Authentication. */
61 { "XMODIFIERS" }, /* Used by Xlib to select X input
62 modules (eg "@im=SCIM"). */
63 { "GTK_IM_MODULE" }, /* Used by gtk to select gtk input
64 modules (eg "scim-bridge"). */
65 { "QT_IM_MODULE" }, /* Used by Qt to select qt input
66 modules (eg "xim"). */
67 { "PINENTRY_USER_DATA", "pinentry-user-data"}
68 /* Used for communication with
69 non-standard Pinentries. */
73 /* Track last allocated arraysize of all objects ever created. If
74 nothing has ever been allocated we use INITIAL_ARRAYSIZE and we
75 will never use more than MAXDEFAULT_ARRAYSIZE for initial
76 allocation. Note that this is not reentrant if used with a
77 preemptive thread model. */
78 static size_t lastallocatedarraysize;
79 #define INITIAL_ARRAYSIZE 8 /* Let's use the number of stdenvnames. */
80 #define CHUNK_ARRAYSIZE 10
81 #define MAXDEFAULT_ARRAYSIZE (INITIAL_ARRAYSIZE + CHUNK_ARRAYSIZE * 5)
84 /* Return the names of standard environment variables one after the
85 other. The caller needs to set the value at the address of
86 ITERATOR initally to 0 and then call this function until it returns
89 session_env_list_stdenvnames (int *iterator, const char **r_assname)
93 if (idx < 0 || idx >= DIM (stdenvnames))
97 *r_assname = stdenvnames[idx].assname;
98 return stdenvnames[idx].name;
102 /* Create a new session environment object. Return NULL and sets
105 session_env_new (void)
109 se = xtrycalloc (1, sizeof *se);
112 se->arraysize = (lastallocatedarraysize?
113 lastallocatedarraysize : INITIAL_ARRAYSIZE);
114 se->array = xtrycalloc (se->arraysize, sizeof *se->array);
126 /* Release a session environment object. */
128 session_env_release (session_env_t se)
135 if (se->arraysize > INITIAL_ARRAYSIZE
136 && se->arraysize <= MAXDEFAULT_ARRAYSIZE
137 && se->arraysize > lastallocatedarraysize)
138 lastallocatedarraysize = se->arraysize;
140 for (idx=0; idx < se->arrayused; idx++)
142 xfree (se->array[idx]);
149 delete_var (session_env_t se, const char *name)
153 for (idx=0; idx < se->arrayused; idx++)
154 if (se->array[idx] && !strcmp (se->array[idx]->name, name))
156 xfree (se->array[idx]);
157 se->array[idx] = NULL;
164 update_var (session_env_t se, const char *string, size_t namelen,
165 const char *explicit_value, int set_default)
171 struct variable_s *var;
174 value = explicit_value;
176 value = string + namelen + 1;
177 valuelen = strlen (value);
179 for (idx=0; idx < se->arrayused; idx++)
183 else if (!strncmp (se->array[idx]->name, string, namelen)
184 && strlen (se->array[idx]->name) == namelen)
186 if (strlen (se->array[idx]->value) == valuelen)
188 /* The new value has the same length. We can update it
190 memcpy (se->array[idx]->value, value, valuelen);
191 se->array[idx]->is_default = !!set_default;
194 /* Prepare for update. */
201 if (se->arrayused == se->arraysize)
203 /* Reallocate the array. */
205 struct variable_s **newarray;
207 newsize = se->arraysize + CHUNK_ARRAYSIZE;
208 newarray = xtrycalloc (newsize, sizeof *newarray);
210 return gpg_error_from_syserror ();
211 for (idx=0; idx < se->arrayused; idx++)
212 newarray[idx] = se->array[idx];
213 se->arraysize = newsize;
215 se->array = newarray;
217 freeidx = se->arrayused++;
220 /* Allocate new memory and return an error if that didn't worked.
221 Allocating it first allows us to keep the old value; it doesn't
222 matter that arrayused has already been incremented in case of a
223 new entry - it will then pint to a NULL slot. */
224 var = xtrymalloc (sizeof *var + namelen + 1 + valuelen);
226 return gpg_error_from_syserror ();
227 var->is_default = !!set_default;
228 memcpy (var->name, string, namelen);
229 var->name[namelen] = '\0';
230 var->value = var->name + namelen + 1;
231 strcpy (var->value, value);
233 xfree (se->array[freeidx]);
234 se->array[freeidx] = var;
239 /* Set or update an environment variable of the session environment.
240 String is similar to the putval(3) function but it is reentrant and
241 takes a copy. In particular it exhibits this behaviour:
243 <NAME> Delete envvar NAME
244 <KEY>= Set envvar NAME to the empty string
245 <KEY>=<VALUE> Set envvar NAME to VALUE
247 On success 0 is returned; on error an gpg-error code. */
249 session_env_putenv (session_env_t se, const char *string)
253 if (!string || !*string)
254 return gpg_error (GPG_ERR_INV_VALUE);
255 s = strchr (string, '=');
257 return gpg_error (GPG_ERR_INV_VALUE);
259 return delete_var (se, string);
261 return update_var (se, string, s - string, NULL, 0);
265 /* Same as session_env_putenv but with name and value given as distict
268 session_env_setenv (session_env_t se, const char *name, const char *value)
271 return gpg_error (GPG_ERR_INV_VALUE);
273 return delete_var (se, name);
275 return update_var (se, name, strlen (name), value, 0);
281 /* Return the value of the environment variable NAME from the SE
282 object. If the variable does not exist, NULL is returned. The
283 returned value is valid as long as SE is valid and as long it has
284 not been removed or updated by a call to session_env_putenv. The
285 caller MUST not change the returned value. */
287 session_env_getenv (session_env_t se, const char *name)
291 if (!se || !name || !*name)
294 for (idx=0; idx < se->arrayused; idx++)
295 if (se->array[idx] && !strcmp (se->array[idx]->name, name))
296 return se->array[idx]->is_default? NULL : se->array[idx]->value;
301 /* Return the value of the environment variable NAME from the SE
302 object. The returned value is valid as long as SE is valid and as
303 long it has not been removed or updated by a call to
304 session_env_putenv. If the variable does not exist, the fucntion
305 tries to return the value trough a call to getenv; if that returns
306 a value, this value is recorded and and used. If no value could be
307 found, returns NULL. The caller must not change the returned
310 session_env_getenv_or_default (session_env_t se, const char *name,
318 if (!se || !name || !*name)
321 for (idx=0; idx < se->arrayused; idx++)
322 if (se->array[idx] && !strcmp (se->array[idx]->name, name))
324 if (r_default && se->array[idx]->is_default)
326 return se->array[idx]->value;
329 /* Get the default value with and additional fallback for GPG_TTY. */
330 defvalue = getenv (name);
331 if ((!defvalue || !*defvalue) && !strcmp (name, "GPG_TTY") && ttyname (0))
332 defvalue = ttyname (0);
335 /* Record the default value for later use so that we are safe
336 from later modifications of the environment. We need to take
337 a copy to better cope with the rules of putenv(3). We ignore
338 the error of the update function because we can't return an
339 explicit error anyway and the following scan would then fail
341 update_var (se, name, strlen (name), defvalue, 1);
343 for (idx=0; idx < se->arrayused; idx++)
344 if (se->array[idx] && !strcmp (se->array[idx]->name, name))
346 if (r_default && se->array[idx]->is_default)
348 return se->array[idx]->value;
356 /* List the entire environment stored in SE. The caller initially
357 needs to set the value of ITERATOR to 0 and then call this function
358 until it returns NULL. The value is retruned at R_VALUE. If
359 R_DEFAULT is not NULL, the default flag is stored on return. The
360 default flag indicates that the value has been taken from the
361 process' environment. The caller must not change the returned
364 session_env_listenv (session_env_t se, int *iterator,
365 const char **r_value, int *r_default)
372 for (; idx < se->arrayused; idx++)
377 *r_default = se->array[idx]->is_default;
379 *r_value = se->array[idx]->value;
380 return se->array[idx]->name;