/src/neomutt/mutt/envlist.c
Line | Count | Source (jump to first uncovered line) |
1 | | /** |
2 | | * @file |
3 | | * Private copy of the environment variables |
4 | | * |
5 | | * @authors |
6 | | * Copyright (C) 2018-2023 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 <string.h> |
33 | | #include "envlist.h" |
34 | | #include "memory.h" |
35 | | #include "string2.h" |
36 | | |
37 | | /** |
38 | | * envlist_free - Free the private copy of the environment |
39 | | * @param envp Environment to free |
40 | | */ |
41 | | void envlist_free(char ***envp) |
42 | 0 | { |
43 | 0 | if (!envp || !*envp) |
44 | 0 | return; |
45 | | |
46 | 0 | for (char **p = *envp; p && *p; p++) |
47 | 0 | FREE(p); |
48 | |
|
49 | 0 | FREE(envp); |
50 | 0 | } |
51 | | |
52 | | /** |
53 | | * envlist_init - Create a copy of the environment |
54 | | * @param envp Environment to copy |
55 | | * @retval ptr Copy of the environment |
56 | | */ |
57 | | char **envlist_init(char **envp) |
58 | 0 | { |
59 | 0 | if (!envp) |
60 | 0 | return NULL; |
61 | | |
62 | 0 | char **src = NULL; |
63 | 0 | char **dst = NULL; |
64 | 0 | int count = 0; |
65 | 0 | for (src = envp; src && *src; src++) |
66 | 0 | count++; |
67 | |
|
68 | 0 | char **env_copy = mutt_mem_calloc(count + 1, sizeof(char *)); |
69 | 0 | for (src = envp, dst = env_copy; src && *src; src++, dst++) |
70 | 0 | *dst = mutt_str_dup(*src); |
71 | |
|
72 | 0 | return env_copy; |
73 | 0 | } |
74 | | |
75 | | /** |
76 | | * envlist_set - Set an environment variable |
77 | | * @param envp Environment to modify |
78 | | * @param name Name of the variable |
79 | | * @param value New value |
80 | | * @param overwrite Should the variable be overwritten? |
81 | | * @retval true Success: variable set, or overwritten |
82 | | * @retval false Variable exists and overwrite was false |
83 | | * |
84 | | * It's broken out because some other parts of neomutt (filter.c) need to |
85 | | * set/overwrite environment variables in EnvList before calling exec(). |
86 | | */ |
87 | | bool envlist_set(char ***envp, const char *name, const char *value, bool overwrite) |
88 | 0 | { |
89 | 0 | if (!envp || !*envp || !name || (name[0] == '\0')) |
90 | 0 | return false; |
91 | | |
92 | | // Find a matching entry |
93 | 0 | int count = 0; |
94 | 0 | int match = -1; |
95 | 0 | char *str = NULL; |
96 | 0 | for (; (str = (*envp)[count]); count++) |
97 | 0 | { |
98 | 0 | size_t len = mutt_str_startswith(str, name); |
99 | 0 | if ((len != 0) && (str[len] == '=')) |
100 | 0 | { |
101 | 0 | if (!overwrite) |
102 | 0 | return false; |
103 | 0 | match = count; |
104 | 0 | break; |
105 | 0 | } |
106 | 0 | } |
107 | | |
108 | | // Format var=value string |
109 | 0 | char work[1024] = { 0 }; |
110 | 0 | snprintf(work, sizeof(work), "%s=%s", name, NONULL(value)); |
111 | |
|
112 | 0 | if (match >= 0) |
113 | 0 | { |
114 | | // match found, overwrite |
115 | 0 | mutt_str_replace(&(*envp)[match], work); |
116 | 0 | } |
117 | 0 | else |
118 | 0 | { |
119 | | // not found, add a new entry |
120 | 0 | mutt_mem_realloc(envp, (count + 2) * sizeof(char *)); |
121 | 0 | (*envp)[count] = mutt_str_dup(work); |
122 | 0 | (*envp)[count + 1] = NULL; |
123 | 0 | } |
124 | |
|
125 | 0 | return true; |
126 | 0 | } |
127 | | |
128 | | /** |
129 | | * envlist_unset - Unset an environment variable |
130 | | * @param envp Environment to modify |
131 | | * @param name Variable to unset |
132 | | * @retval true Success: Variable unset |
133 | | * @retval false Error: Variable doesn't exist |
134 | | */ |
135 | | bool envlist_unset(char ***envp, const char *name) |
136 | 0 | { |
137 | 0 | if (!envp || !*envp || !name || (name[0] == '\0')) |
138 | 0 | return false; |
139 | | |
140 | 0 | int count = 0; |
141 | 0 | for (; (*envp)[count]; count++) |
142 | 0 | ; // do nothing |
143 | |
|
144 | 0 | char *str = NULL; |
145 | 0 | for (int match = 0; (str = (*envp)[match]); match++) |
146 | 0 | { |
147 | 0 | size_t len = mutt_str_startswith(str, name); |
148 | 0 | if ((len != 0) && (str[len] == '=')) |
149 | 0 | { |
150 | 0 | FREE(&(*envp)[match]); |
151 | | // Move down the later entries |
152 | 0 | memmove(&(*envp)[match], &(*envp)[match + 1], (count - match) * sizeof(char *)); |
153 | | // Shrink the array |
154 | 0 | mutt_mem_realloc(envp, count * sizeof(char *)); |
155 | 0 | return true; |
156 | 0 | } |
157 | 0 | } |
158 | 0 | return false; |
159 | 0 | } |