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