1 /**
2 * @file
3 * Private copy of the environment variables
4 *
5 * @authors
6 * Copyright (C) 2018 Richard Russon <rich@flatcap.org>
7 *
8 * @copyright
9 * This program is free software: you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 2 of the License, or (at your option) any later
12 * version.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 /**
24 * @page mutt_envlist Private copy of the environment variables
25 *
26 * Private copy of the environment variables
27 */
28
29 #include "config.h"
30 #include <stdbool.h>
31 #include <stdio.h>
32 #include "envlist.h"
33 #include "memory.h"
34 #include "string2.h"
35
36 char **EnvList = NULL; ///< Private copy of the environment variables
37
38 /**
39 * mutt_envlist_free - Free the private copy of the environment
40 */
mutt_envlist_free(void)41 void mutt_envlist_free(void)
42 {
43 if (!EnvList)
44 return;
45
46 for (char **p = EnvList; p && *p; p++)
47 FREE(p);
48
49 FREE(&EnvList);
50 }
51
52 /**
53 * mutt_envlist_init - Create a copy of the environment
54 * @param envp Environment variables
55 */
mutt_envlist_init(char * envp[])56 void mutt_envlist_init(char *envp[])
57 {
58 if (EnvList)
59 mutt_envlist_free();
60
61 if (!envp)
62 return;
63
64 char **src = NULL, **dst = NULL;
65 int count = 0;
66 for (src = envp; src && *src; src++)
67 count++;
68
69 EnvList = mutt_mem_calloc(count + 1, sizeof(char *));
70 for (src = envp, dst = EnvList; src && *src; src++, dst++)
71 *dst = mutt_str_dup(*src);
72 }
73
74 /**
75 * mutt_envlist_set - Set an environment variable
76 * @param name Name of the variable
77 * @param value New value
78 * @param overwrite Should the variable be overwritten?
79 * @retval true Success: variable set, or overwritten
80 * @retval false Variable exists and overwrite was false
81 *
82 * It's broken out because some other parts of neomutt (filter.c) need to
83 * set/overwrite environment variables in EnvList before calling exec().
84 */
mutt_envlist_set(const char * name,const char * value,bool overwrite)85 bool mutt_envlist_set(const char *name, const char *value, bool overwrite)
86 {
87 if (!name)
88 return false;
89
90 char **envp = EnvList;
91 char work[1024];
92
93 /* Look for current slot to overwrite */
94 int count = 0;
95 while (envp && *envp)
96 {
97 size_t len = mutt_str_startswith(*envp, name);
98 if ((len != 0) && ((*envp)[len] == '='))
99 {
100 if (!overwrite)
101 return false;
102 break;
103 }
104 envp++;
105 count++;
106 }
107
108 /* Format var=value string */
109 snprintf(work, sizeof(work), "%s=%s", name, NONULL(value));
110
111 if (envp && *envp)
112 {
113 /* slot found, overwrite */
114 mutt_str_replace(envp, work);
115 }
116 else
117 {
118 /* not found, add new slot */
119 mutt_mem_realloc(&EnvList, sizeof(char *) * (count + 2));
120 EnvList[count] = mutt_str_dup(work);
121 EnvList[count + 1] = NULL;
122 }
123 return true;
124 }
125
126 /**
127 * mutt_envlist_unset - Unset an environment variable
128 * @param name Variable to unset
129 * @retval true Success: Variable unset
130 * @retval false Error: Variable doesn't exist
131 */
mutt_envlist_unset(const char * name)132 bool mutt_envlist_unset(const char *name)
133 {
134 if (!name || (name[0] == '\0'))
135 return false;
136
137 char **envp = EnvList;
138
139 int count = 0;
140 while (envp && *envp)
141 {
142 size_t len = mutt_str_startswith(*envp, name);
143 if ((len != 0) && ((*envp)[len] == '='))
144 {
145 FREE(envp);
146 /* shuffle down */
147 char **save = envp++;
148 while (*envp)
149 {
150 *save++ = *envp++;
151 count++;
152 }
153 *save = NULL;
154 mutt_mem_realloc(&EnvList, sizeof(char *) * (count + 1));
155 return true;
156 }
157 envp++;
158 count++;
159 }
160 return false;
161 }
162
163 /**
164 * mutt_envlist_getlist - Get the private environment
165 * @retval ptr Array of strings
166 *
167 * @note The caller must not free the strings
168 */
mutt_envlist_getlist(void)169 char **mutt_envlist_getlist(void)
170 {
171 return EnvList;
172 }
173