1 /* session-env.c - Session environment helper functions.
2 * Copyright (C) 2009 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * This file is free software; you can redistribute it and/or modify
7 * it under the terms of either
9 * - the GNU Lesser General Public License as published by the Free
10 * Software Foundation; either version 3 of the License, or (at
11 * your option) any later version.
15 * - the GNU General Public License as published by the Free
16 * Software Foundation; either version 2 of the License, or (at
17 * your option) any later version.
19 * or both in parallel, as here.
21 * This file is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, see <https://www.gnu.org/licenses/>.
38 #include "session-env.h"
43 char *value; /* Pointer into NAME to the Nul terminated value. */
44 int is_default; /* The value is a default one. */
45 char name[1]; /* Nul terminated Name and space for the value. */
50 /* The session environment object. */
51 struct session_environment_s
53 size_t arraysize; /* Allocated size or ARRAY. */
54 size_t arrayused; /* Used size of ARRAY. */
55 struct variable_s **array; /* Array of variables. NULL slots are unused. */
59 /* A list of environment variables we pass from the actual user
60 (e.g. gpgme) down to the pinentry. We do not handle the locale
61 settings because they do not only depend on envvars. */
65 const char *assname; /* Name used by Assuan or NULL. */
67 { "GPG_TTY", "ttyname" }, /* GnuPG specific envvar. */
68 { "TERM", "ttytype" }, /* Used to set ttytype. */
69 { "DISPLAY", "display" }, /* The X-Display. */
70 { "XAUTHORITY","xauthority"}, /* Xlib Authentication. */
71 { "XMODIFIERS" }, /* Used by Xlib to select X input
72 modules (eg "@im=SCIM"). */
73 { "GTK_IM_MODULE" }, /* Used by gtk to select gtk input
74 modules (eg "scim-bridge"). */
75 { "DBUS_SESSION_BUS_ADDRESS" },/* Used by GNOME3 to talk to gcr over
77 { "QT_IM_MODULE" }, /* Used by Qt to select qt input
78 modules (eg "xim"). */
79 { "INSIDE_EMACS" }, /* Set by Emacs before running a
81 { "PINENTRY_USER_DATA", "pinentry-user-data"}
82 /* Used for communication with
83 non-standard Pinentries. */
87 /* Track last allocated arraysize of all objects ever created. If
88 nothing has ever been allocated we use INITIAL_ARRAYSIZE and we
89 will never use more than MAXDEFAULT_ARRAYSIZE for initial
90 allocation. Note that this is not reentrant if used with a
91 preemptive thread model. */
92 static size_t lastallocatedarraysize;
93 #define INITIAL_ARRAYSIZE 8 /* Let's use the number of stdenvnames. */
94 #define CHUNK_ARRAYSIZE 10
95 #define MAXDEFAULT_ARRAYSIZE (INITIAL_ARRAYSIZE + CHUNK_ARRAYSIZE * 5)
98 /* Return the names of standard environment variables one after the
99 other. The caller needs to set the value at the address of
100 ITERATOR initially to 0 and then call this function until it returns
103 session_env_list_stdenvnames (int *iterator, const char **r_assname)
107 if (idx < 0 || idx >= DIM (stdenvnames))
111 *r_assname = stdenvnames[idx].assname;
112 return stdenvnames[idx].name;
116 /* Create a new session environment object. Return NULL and sets
119 session_env_new (void)
123 se = xtrycalloc (1, sizeof *se);
126 se->arraysize = (lastallocatedarraysize?
127 lastallocatedarraysize : INITIAL_ARRAYSIZE);
128 se->array = xtrycalloc (se->arraysize, sizeof *se->array);
140 /* Release a session environment object. */
142 session_env_release (session_env_t se)
149 if (se->arraysize > INITIAL_ARRAYSIZE
150 && se->arraysize <= MAXDEFAULT_ARRAYSIZE
151 && se->arraysize > lastallocatedarraysize)
152 lastallocatedarraysize = se->arraysize;
154 for (idx=0; idx < se->arrayused; idx++)
156 xfree (se->array[idx]);
163 delete_var (session_env_t se, const char *name)
167 for (idx=0; idx < se->arrayused; idx++)
168 if (se->array[idx] && !strcmp (se->array[idx]->name, name))
170 xfree (se->array[idx]);
171 se->array[idx] = NULL;
178 update_var (session_env_t se, const char *string, size_t namelen,
179 const char *explicit_value, int set_default)
185 struct variable_s *var;
188 value = explicit_value;
190 value = string + namelen + 1;
191 valuelen = strlen (value);
193 for (idx=0; idx < se->arrayused; idx++)
197 else if (!strncmp (se->array[idx]->name, string, namelen)
198 && strlen (se->array[idx]->name) == namelen)
200 if (strlen (se->array[idx]->value) == valuelen)
202 /* The new value has the same length. We can update it
204 memcpy (se->array[idx]->value, value, valuelen);
205 se->array[idx]->is_default = !!set_default;
208 /* Prepare for update. */
215 if (se->arrayused == se->arraysize)
217 /* Reallocate the array. */
219 struct variable_s **newarray;
221 newsize = se->arraysize + CHUNK_ARRAYSIZE;
222 newarray = xtrycalloc (newsize, sizeof *newarray);
224 return gpg_error_from_syserror ();
225 for (idx=0; idx < se->arrayused; idx++)
226 newarray[idx] = se->array[idx];
227 se->arraysize = newsize;
229 se->array = newarray;
231 freeidx = se->arrayused++;
234 /* Allocate new memory and return an error if that didn't worked.
235 Allocating it first allows us to keep the old value; it doesn't
236 matter that arrayused has already been incremented in case of a
237 new entry - it will then pint to a NULL slot. */
238 var = xtrymalloc (sizeof *var + namelen + 1 + valuelen);
240 return gpg_error_from_syserror ();
241 var->is_default = !!set_default;
242 memcpy (var->name, string, namelen);
243 var->name[namelen] = '\0';
244 var->value = var->name + namelen + 1;
245 strcpy (var->value, value);
247 xfree (se->array[freeidx]);
248 se->array[freeidx] = var;
253 /* Set or update an environment variable of the session environment.
254 String is similar to the putval(3) function but it is reentrant and
255 takes a copy. In particular it exhibits this behaviour:
257 <NAME> Delete envvar NAME
258 <KEY>= Set envvar NAME to the empty string
259 <KEY>=<VALUE> Set envvar NAME to VALUE
261 On success 0 is returned; on error an gpg-error code. */
263 session_env_putenv (session_env_t se, const char *string)
267 if (!string || !*string)
268 return gpg_error (GPG_ERR_INV_VALUE);
269 s = strchr (string, '=');
271 return gpg_error (GPG_ERR_INV_VALUE);
273 return delete_var (se, string);
275 return update_var (se, string, s - string, NULL, 0);
279 /* Same as session_env_putenv but with name and value given as distict
282 session_env_setenv (session_env_t se, const char *name, const char *value)
285 return gpg_error (GPG_ERR_INV_VALUE);
287 return delete_var (se, name);
289 return update_var (se, name, strlen (name), value, 0);
295 /* Return the value of the environment variable NAME from the SE
296 object. If the variable does not exist, NULL is returned. The
297 returned value is valid as long as SE is valid and as long it has
298 not been removed or updated by a call to session_env_putenv. The
299 caller MUST not change the returned value. */
301 session_env_getenv (session_env_t se, const char *name)
305 if (!se || !name || !*name)
308 for (idx=0; idx < se->arrayused; idx++)
309 if (se->array[idx] && !strcmp (se->array[idx]->name, name))
310 return se->array[idx]->is_default? NULL : se->array[idx]->value;
315 /* Return the value of the environment variable NAME from the SE
316 object. The returned value is valid as long as SE is valid and as
317 long it has not been removed or updated by a call to
318 session_env_putenv. If the variable does not exist, the function
319 tries to return the value trough a call to getenv; if that returns
320 a value, this value is recorded and and used. If no value could be
321 found, returns NULL. The caller must not change the returned
324 session_env_getenv_or_default (session_env_t se, const char *name,
332 if (!se || !name || !*name)
335 for (idx=0; idx < se->arrayused; idx++)
336 if (se->array[idx] && !strcmp (se->array[idx]->name, name))
338 if (r_default && se->array[idx]->is_default)
340 return se->array[idx]->value;
343 /* Get the default value with an additional fallback for GPG_TTY. */
344 defvalue = getenv (name);
345 if ((!defvalue || !*defvalue) && !strcmp (name, "GPG_TTY")
346 && gnupg_ttyname (0))
348 defvalue = gnupg_ttyname (0);
352 /* Record the default value for later use so that we are safe
353 from later modifications of the environment. We need to take
354 a copy to better cope with the rules of putenv(3). We ignore
355 the error of the update function because we can't return an
356 explicit error anyway and the following scan would then fail
358 update_var (se, name, strlen (name), defvalue, 1);
360 for (idx=0; idx < se->arrayused; idx++)
361 if (se->array[idx] && !strcmp (se->array[idx]->name, name))
363 if (r_default && se->array[idx]->is_default)
365 return se->array[idx]->value;
373 /* List the entire environment stored in SE. The caller initially
374 needs to set the value of ITERATOR to 0 and then call this function
375 until it returns NULL. The value is returned at R_VALUE. If
376 R_DEFAULT is not NULL, the default flag is stored on return. The
377 default flag indicates that the value has been taken from the
378 process' environment. The caller must not change the returned
381 session_env_listenv (session_env_t se, int *iterator,
382 const char **r_value, int *r_default)
389 for (; idx < se->arrayused; idx++)
394 *r_default = se->array[idx]->is_default;
396 *r_value = se->array[idx]->value;
397 return se->array[idx]->name;