Remove pth dependency
[platform/upstream/gpg2.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   { "WAYLAND_DISPLAY" },         /* For the Wayland display engine.  */
74   { "XDG_SESSION_TYPE" },        /* Used by Qt and other non-GTK toolkits
75                                     to check for x11 or wayland.  */
76   { "QT_QPA_PLATFORM" },         /* Used by Qt to explicitly request
77                                     x11 or wayland; in particular, needed
78                                     to make Qt use Wayland on Gnome.  */
79   { "GTK_IM_MODULE" },           /* Used by gtk to select gtk input
80                                     modules (eg "scim-bridge").  */
81   { "DBUS_SESSION_BUS_ADDRESS" },/* Used by GNOME3 to talk to gcr over
82                                     dbus */
83   { "QT_IM_MODULE" },            /* Used by Qt to select qt input
84                                       modules (eg "xim").  */
85   { "INSIDE_EMACS" },            /* Set by Emacs before running a
86                                     process.  */
87   { "PINENTRY_USER_DATA", "pinentry-user-data"}
88                                  /* Used for communication with
89                                     non-standard Pinentries.  */
90 };
91
92
93 /* Track last allocated arraysize of all objects ever created.  If
94    nothing has ever been allocated we use INITIAL_ARRAYSIZE and we
95    will never use more than MAXDEFAULT_ARRAYSIZE for initial
96    allocation.  Note that this is not reentrant if used with a
97    preemptive thread model.  */
98 static size_t lastallocatedarraysize;
99 #define INITIAL_ARRAYSIZE 8  /* Let's use the number of stdenvnames.  */
100 #define CHUNK_ARRAYSIZE 10
101 #define MAXDEFAULT_ARRAYSIZE (INITIAL_ARRAYSIZE + CHUNK_ARRAYSIZE * 5)
102
103
104 /* Return the names of standard environment variables one after the
105    other.  The caller needs to set the value at the address of
106    ITERATOR initially to 0 and then call this function until it
107    returns NULL.  If ITERATOR is NULL, a single comma delimited string
108    with the names is returned; NULL is never returned in this case and
109    R_ASSNAME is ignored.  */
110 const char *
111 session_env_list_stdenvnames (int *iterator, const char **r_assname)
112 {
113   int idx;
114   static char *commastring;
115
116   if (!iterator)
117     {
118       if (!commastring)
119         {
120           size_t len = 0;
121           char *p;
122
123           for (idx = 0; idx < DIM (stdenvnames); idx++)
124             len += strlen (stdenvnames[idx].name) + 1;
125           commastring = xtrymalloc (len);
126           if (!commastring)
127             {
128               log_error ("%s: error allocating string: %s\n", __func__,
129                          gpg_strerror (gpg_error_from_syserror ()));
130               return "GPG_TTY,TERM,DISPLAY";
131             }
132           p = commastring;
133           for (idx = 0; idx < DIM (stdenvnames); idx++)
134             {
135               if (idx)
136                 *p++ = ',';
137               p = stpcpy (p, stdenvnames[idx].name);
138             }
139           gpgrt_annotate_leaked_object (commastring);
140         }
141       return commastring;
142     }
143
144   idx = *iterator;
145   if (idx < 0 || idx >= DIM (stdenvnames))
146     return NULL;
147   *iterator = idx + 1;
148   if (r_assname)
149     *r_assname = stdenvnames[idx].assname;
150   return stdenvnames[idx].name;
151 }
152
153
154 /* Create a new session environment object.  Return NULL and sets
155    ERRNO on failure. */
156 session_env_t
157 session_env_new (void)
158 {
159   session_env_t se;
160
161   se = xtrycalloc (1, sizeof *se);
162   if (se)
163     {
164       se->arraysize = (lastallocatedarraysize?
165                        lastallocatedarraysize : INITIAL_ARRAYSIZE);
166       se->array = xtrycalloc (se->arraysize, sizeof *se->array);
167       if (!se->array)
168         {
169           xfree (se);
170           se = NULL;
171         }
172     }
173
174   return se;
175 }
176
177
178 /* Release a session environment object.  */
179 void
180 session_env_release (session_env_t se)
181 {
182   int idx;
183
184   if (!se)
185     return;
186
187   if (se->arraysize > INITIAL_ARRAYSIZE
188       && se->arraysize <= MAXDEFAULT_ARRAYSIZE
189       && se->arraysize > lastallocatedarraysize)
190     lastallocatedarraysize = se->arraysize;
191
192   for (idx=0; idx < se->arrayused; idx++)
193     if (se->array[idx])
194       xfree (se->array[idx]);
195   xfree (se->array);
196   xfree (se);
197 }
198
199
200 static gpg_error_t
201 delete_var (session_env_t se, const char *name)
202 {
203   int idx;
204
205   for (idx=0; idx < se->arrayused; idx++)
206     if (se->array[idx] && !strcmp (se->array[idx]->name, name))
207       {
208         xfree (se->array[idx]);
209         se->array[idx] = NULL;
210       }
211   return 0;
212 }
213
214
215 static gpg_error_t
216 update_var (session_env_t se, const char *string, size_t namelen,
217             const char *explicit_value, int set_default)
218 {
219   int idx;
220   int freeidx = -1;
221   const char *value;
222   size_t valuelen;
223   struct variable_s *var;
224
225   if (explicit_value)
226     value = explicit_value;
227   else
228     value = string + namelen + 1;
229   valuelen = strlen (value);
230
231   for (idx=0; idx < se->arrayused; idx++)
232     {
233       if (!se->array[idx])
234         freeidx = idx;
235       else if (!strncmp (se->array[idx]->name, string, namelen)
236                && strlen (se->array[idx]->name) == namelen)
237         {
238           if (strlen (se->array[idx]->value) == valuelen)
239             {
240               /* The new value has the same length.  We can update it
241                  in-place.  */
242               memcpy (se->array[idx]->value, value, valuelen);
243               se->array[idx]->is_default = !!set_default;
244               return 0;
245             }
246           /* Prepare for update.  */
247           freeidx = idx;
248         }
249     }
250
251   if (freeidx == -1)
252     {
253       if (se->arrayused == se->arraysize)
254         {
255           /* Reallocate the array. */
256           size_t newsize;
257           struct variable_s **newarray;
258
259           newsize = se->arraysize + CHUNK_ARRAYSIZE;
260           newarray = xtrycalloc (newsize, sizeof *newarray);
261           if (!newarray)
262             return gpg_error_from_syserror ();
263           for (idx=0; idx < se->arrayused; idx++)
264             newarray[idx] = se->array[idx];
265           se->arraysize = newsize;
266           xfree (se->array);
267           se->array = newarray;
268         }
269       freeidx = se->arrayused++;
270     }
271
272   /* Allocate new memory and return an error if that didn't worked.
273      Allocating it first allows us to keep the old value; it doesn't
274      matter that arrayused has already been incremented in case of a
275      new entry - it will then pint to a NULL slot.  */
276   var = xtrymalloc (sizeof *var + namelen + 1 + valuelen);
277   if (!var)
278     return gpg_error_from_syserror ();
279   var->is_default = !!set_default;
280   memcpy (var->name, string, namelen);
281   var->name[namelen] = '\0';
282   var->value = var->name + namelen + 1;
283   strcpy (var->value, value);
284
285   xfree (se->array[freeidx]);
286   se->array[freeidx] = var;
287   return 0;
288 }
289
290
291 /* Set or update an environment variable of the session environment.
292    String is similar to the putval(3) function but it is reentrant and
293    takes a copy.  In particular it exhibits this behaviour:
294
295           <NAME>            Delete envvar NAME
296           <KEY>=            Set envvar NAME to the empty string
297           <KEY>=<VALUE>     Set envvar NAME to VALUE
298
299    On success 0 is returned; on error an gpg-error code.  */
300 gpg_error_t
301 session_env_putenv (session_env_t se, const char *string)
302 {
303   const char *s;
304
305   if (!string || !*string)
306     return gpg_error (GPG_ERR_INV_VALUE);
307   s = strchr (string, '=');
308   if (s == string)
309     return gpg_error (GPG_ERR_INV_VALUE);
310   if (!s)
311     return delete_var (se, string);
312   else
313     return update_var (se, string, s - string, NULL, 0);
314 }
315
316
317 /* Same as session_env_putenv but with name and value given as distict
318    values.  */
319 gpg_error_t
320 session_env_setenv (session_env_t se, const char *name, const char *value)
321 {
322   if (!name || !*name)
323     return gpg_error (GPG_ERR_INV_VALUE);
324   if (!value)
325     return delete_var (se, name);
326   else
327     return update_var (se, name, strlen (name), value, 0);
328 }
329
330
331
332
333 /* Return the value of the environment variable NAME from the SE
334    object.  If the variable does not exist, NULL is returned.  The
335    returned value is valid as long as SE is valid and as long it has
336    not been removed or updated by a call to session_env_putenv.  The
337    caller MUST not change the returned value. */
338 char *
339 session_env_getenv (session_env_t se, const char *name)
340 {
341   int idx;
342
343   if (!se || !name || !*name)
344     return NULL;
345
346   for (idx=0; idx < se->arrayused; idx++)
347     if (se->array[idx] && !strcmp (se->array[idx]->name, name))
348       return se->array[idx]->is_default? NULL : se->array[idx]->value;
349   return NULL;
350 }
351
352
353 /* Return the value of the environment variable NAME from the SE
354    object.  The returned value is valid as long as SE is valid and as
355    long it has not been removed or updated by a call to
356    session_env_putenv.  If the variable does not exist, the function
357    tries to return the value trough a call to getenv; if that returns
358    a value, this value is recorded and used.  If no value could be
359    found, returns NULL.  The caller must not change the returned
360    value. */
361 char *
362 session_env_getenv_or_default (session_env_t se, const char *name,
363                                int *r_default)
364 {
365   int idx;
366   char *defvalue;
367
368   if (r_default)
369     *r_default = 0;
370   if (!se || !name || !*name)
371     return NULL;
372
373   for (idx=0; idx < se->arrayused; idx++)
374     if (se->array[idx] && !strcmp (se->array[idx]->name, name))
375       {
376         if (r_default && se->array[idx]->is_default)
377           *r_default = 1;
378         return se->array[idx]->value;
379       }
380
381   /* Get the default value with an additional fallback for GPG_TTY.  */
382   defvalue = getenv (name);
383   if ((!defvalue || !*defvalue) && !strcmp (name, "GPG_TTY")
384       && gnupg_ttyname (0))
385     {
386       defvalue = gnupg_ttyname (0);
387     }
388   if (defvalue)
389     {
390       /* Record the default value for later use so that we are safe
391          from later modifications of the environment.  We need to take
392          a copy to better cope with the rules of putenv(3).  We ignore
393          the error of the update function because we can't return an
394          explicit error anyway and the following scan would then fail
395          anyway. */
396       update_var (se, name, strlen (name), defvalue, 1);
397
398       for (idx=0; idx < se->arrayused; idx++)
399         if (se->array[idx] && !strcmp (se->array[idx]->name, name))
400           {
401             if (r_default && se->array[idx]->is_default)
402               *r_default = 1;
403             return se->array[idx]->value;
404           }
405     }
406
407   return NULL;
408 }
409
410
411 /* List the entire environment stored in SE.  The caller initially
412    needs to set the value of ITERATOR to 0 and then call this function
413    until it returns NULL.  The value is returned at R_VALUE.  If
414    R_DEFAULT is not NULL, the default flag is stored on return.  The
415    default flag indicates that the value has been taken from the
416    process's environment.  The caller must not change the returned
417    name or value.  */
418 char *
419 session_env_listenv (session_env_t se, int *iterator,
420                      const char **r_value, int *r_default)
421 {
422   int idx = *iterator;
423
424   if (!se || idx < 0)
425     return NULL;
426
427   for (; idx < se->arrayused; idx++)
428     if (se->array[idx])
429       {
430         *iterator = idx+1;
431         if (r_default)
432           *r_default = se->array[idx]->is_default;
433         if (r_value)
434           *r_value = se->array[idx]->value;
435         return se->array[idx]->name;
436       }
437   return NULL;
438 }