chiark / gitweb /
gpg agent lockup fix: Interrupt main loop when active_connections_value==0
[gnupg2.git] / common / session-env.c
1 /* session-env.c - Session environment helper functions.
2  * Copyright (C) 2009 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * This file is free software; you can redistribute it and/or modify
7  * it under the terms of either
8  *
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.
12  *
13  * or
14  *
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.
18  *
19  * or both in parallel, as here.
20  *
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.
25  *
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/>.
28  */
29
30 #include <config.h>
31 #include <stdlib.h>
32 #include <errno.h>
33 #include <ctype.h>
34 #include <assert.h>
35 #include <unistd.h>
36
37 #include "util.h"
38 #include "session-env.h"
39
40
41 struct variable_s
42 {
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.  */
46 };
47
48
49
50 /* The session environment object.  */
51 struct session_environment_s
52 {
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.  */
56 };
57
58
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.  */
62 static struct
63 {
64   const char *name;
65   const char *assname;  /* Name used by Assuan or NULL.  */
66 } stdenvnames[] = {
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
76                                     dbus */
77   { "QT_IM_MODULE" },            /* Used by Qt to select qt input
78                                       modules (eg "xim").  */
79   { "INSIDE_EMACS" },            /* Set by Emacs before running a
80                                     process.  */
81   { "PINENTRY_USER_DATA", "pinentry-user-data"}
82                                  /* Used for communication with
83                                     non-standard Pinentries.  */
84 };
85
86
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)
96
97
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
101    NULL.  */
102 const char *
103 session_env_list_stdenvnames (int *iterator, const char **r_assname)
104 {
105   int idx = *iterator;
106
107   if (idx < 0 || idx >= DIM (stdenvnames))
108     return NULL;
109   *iterator = idx + 1;
110   if (r_assname)
111     *r_assname = stdenvnames[idx].assname;
112   return stdenvnames[idx].name;
113 }
114
115
116 /* Create a new session environment object.  Return NULL and sets
117    ERRNO on failure. */
118 session_env_t
119 session_env_new (void)
120 {
121   session_env_t se;
122
123   se = xtrycalloc (1, sizeof *se);
124   if (se)
125     {
126       se->arraysize = (lastallocatedarraysize?
127                        lastallocatedarraysize : INITIAL_ARRAYSIZE);
128       se->array = xtrycalloc (se->arraysize, sizeof *se->array);
129       if (!se->array)
130         {
131           xfree (se);
132           se = NULL;
133         }
134     }
135
136   return se;
137 }
138
139
140 /* Release a session environment object.  */
141 void
142 session_env_release (session_env_t se)
143 {
144   int idx;
145
146   if (!se)
147     return;
148
149   if (se->arraysize > INITIAL_ARRAYSIZE
150       && se->arraysize <= MAXDEFAULT_ARRAYSIZE
151       && se->arraysize > lastallocatedarraysize)
152     lastallocatedarraysize = se->arraysize;
153
154   for (idx=0; idx < se->arrayused; idx++)
155     if (se->array[idx])
156       xfree (se->array[idx]);
157   xfree (se->array);
158   xfree (se);
159 }
160
161
162 static gpg_error_t
163 delete_var (session_env_t se, const char *name)
164 {
165   int idx;
166
167   for (idx=0; idx < se->arrayused; idx++)
168     if (se->array[idx] && !strcmp (se->array[idx]->name, name))
169       {
170         xfree (se->array[idx]);
171         se->array[idx] = NULL;
172       }
173   return 0;
174 }
175
176
177 static gpg_error_t
178 update_var (session_env_t se, const char *string, size_t namelen,
179             const char *explicit_value, int set_default)
180 {
181   int idx;
182   int freeidx = -1;
183   const char *value;
184   size_t valuelen;
185   struct variable_s *var;
186
187   if (explicit_value)
188     value = explicit_value;
189   else
190     value = string + namelen + 1;
191   valuelen = strlen (value);
192
193   for (idx=0; idx < se->arrayused; idx++)
194     {
195       if (!se->array[idx])
196         freeidx = idx;
197       else if (!strncmp (se->array[idx]->name, string, namelen)
198                && strlen (se->array[idx]->name) == namelen)
199         {
200           if (strlen (se->array[idx]->value) == valuelen)
201             {
202               /* The new value has the same length.  We can update it
203                  in-place.  */
204               memcpy (se->array[idx]->value, value, valuelen);
205               se->array[idx]->is_default = !!set_default;
206               return 0;
207             }
208           /* Prepare for update.  */
209           freeidx = idx;
210         }
211     }
212
213   if (freeidx == -1)
214     {
215       if (se->arrayused == se->arraysize)
216         {
217           /* Reallocate the array. */
218           size_t newsize;
219           struct variable_s **newarray;
220
221           newsize = se->arraysize + CHUNK_ARRAYSIZE;
222           newarray = xtrycalloc (newsize, sizeof *newarray);
223           if (!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;
228           xfree (se->array);
229           se->array = newarray;
230         }
231       freeidx = se->arrayused++;
232     }
233
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);
239   if (!var)
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);
246
247   xfree (se->array[freeidx]);
248   se->array[freeidx] = var;
249   return 0;
250 }
251
252
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:
256
257           <NAME>            Delete envvar NAME
258           <KEY>=            Set envvar NAME to the empty string
259           <KEY>=<VALUE>     Set envvar NAME to VALUE
260
261    On success 0 is returned; on error an gpg-error code.  */
262 gpg_error_t
263 session_env_putenv (session_env_t se, const char *string)
264 {
265   const char *s;
266
267   if (!string || !*string)
268     return gpg_error (GPG_ERR_INV_VALUE);
269   s = strchr (string, '=');
270   if (s == string)
271     return gpg_error (GPG_ERR_INV_VALUE);
272   if (!s)
273     return delete_var (se, string);
274   else
275     return update_var (se, string, s - string, NULL, 0);
276 }
277
278
279 /* Same as session_env_putenv but with name and value given as distict
280    values.  */
281 gpg_error_t
282 session_env_setenv (session_env_t se, const char *name, const char *value)
283 {
284   if (!name || !*name)
285     return gpg_error (GPG_ERR_INV_VALUE);
286   if (!value)
287     return delete_var (se, name);
288   else
289     return update_var (se, name, strlen (name), value, 0);
290 }
291
292
293
294
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. */
300 char *
301 session_env_getenv (session_env_t se, const char *name)
302 {
303   int idx;
304
305   if (!se || !name || !*name)
306     return NULL;
307
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;
311   return NULL;
312 }
313
314
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
322    value. */
323 char *
324 session_env_getenv_or_default (session_env_t se, const char *name,
325                                int *r_default)
326 {
327   int idx;
328   char *defvalue;
329
330   if (r_default)
331     *r_default = 0;
332   if (!se || !name || !*name)
333     return NULL;
334
335   for (idx=0; idx < se->arrayused; idx++)
336     if (se->array[idx] && !strcmp (se->array[idx]->name, name))
337       {
338         if (r_default && se->array[idx]->is_default)
339           *r_default = 1;
340         return se->array[idx]->value;
341       }
342
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))
347     {
348       defvalue = gnupg_ttyname (0);
349     }
350   if (defvalue)
351     {
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
357          anyway. */
358       update_var (se, name, strlen (name), defvalue, 1);
359
360       for (idx=0; idx < se->arrayused; idx++)
361         if (se->array[idx] && !strcmp (se->array[idx]->name, name))
362           {
363             if (r_default && se->array[idx]->is_default)
364               *r_default = 1;
365             return se->array[idx]->value;
366           }
367     }
368
369   return NULL;
370 }
371
372
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
379    name or value.  */
380 char *
381 session_env_listenv (session_env_t se, int *iterator,
382                      const char **r_value, int *r_default)
383 {
384   int idx = *iterator;
385
386   if (!se || idx < 0)
387     return NULL;
388
389   for (; idx < se->arrayused; idx++)
390     if (se->array[idx])
391       {
392         *iterator = idx+1;
393         if (r_default)
394           *r_default = se->array[idx]->is_default;
395         if (r_value)
396           *r_value = se->array[idx]->value;
397         return se->array[idx]->name;
398       }
399   return NULL;
400 }