json: Fix t-decrypt-verify.out for GnuPG >= 2.3.
[gpgme.git] / src / get-env.c
1 /* get_env.c - A getenv() replacement.
2  * Copyright (C) 2003, 2004 g10 Code GmbH
3  *
4  * This file is part of GPGME.
5  *
6  * GPGME is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * GPGME is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see <https://gnu.org/licenses/>.
18  * SPDX-License-Identifier: LGPL-2.1-or-later
19  */
20
21 #if HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <string.h>
27
28 #include "util.h"
29
30 \f
31 /* Retrieve the environment variable NAME and return a copy of it in a
32    malloc()'ed buffer in *VALUE.  If the environment variable is not
33    set, return NULL in *VALUE.  */
34
35 #ifdef HAVE_GETENV_R
36 #define INITIAL_GETENV_SIZE 32
37
38 gpgme_error_t
39 _gpgme_getenv (const char *name, char **value)
40 {
41   size_t len = INITIAL_GETENV_SIZE;
42   char *env_value;
43
44   env_value = malloc (len);
45
46   while (1)
47     {
48       *value = env_value;
49       if (!env_value)
50         return gpg_error_from_syserror ();
51
52       if (getenv_r (name, env_value, len) == 0)
53         break;
54
55       if (errno == ERANGE)
56         {
57           len *= 2;
58           env_value = realloc (env_value, len);
59         }
60       else
61         {
62           int saved = errno;
63
64           free (env_value);
65           *value = NULL;
66           if (errno == ENOENT)
67             return 0;
68           else
69           return gpg_error_from_errno (saved);
70         }
71     }
72
73   return 0;
74 }
75 #else
76 #ifndef HAVE_THREAD_SAFE_GETENV
77 GPGRT_LOCK_DEFINE (environ_lock);
78 #endif
79
80 gpgme_error_t
81 _gpgme_getenv (const char *name, char **value)
82 {
83   char *env_value;
84   gpgme_error_t err = 0;
85
86 #ifndef HAVE_THREAD_SAFE_GETENV
87   gpg_err_code_t rc;
88
89   rc= gpgrt_lock_lock (&environ_lock);
90   if (rc)
91     {
92       err = gpg_error (rc);
93       goto leave;
94     }
95 #endif
96   env_value = getenv (name);
97   if (!env_value)
98     *value = NULL;
99   else
100     {
101       *value = strdup (env_value);
102       if (!*value)
103         err = gpg_error_from_syserror ();
104     }
105 #ifndef HAVE_THREAD_SAFE_GETENV
106   rc = gpgrt_lock_unlock (&environ_lock);
107   if (rc)
108     err = gpg_error (rc);
109  leave:
110 #endif
111   return err;
112 }
113 #endif