Coverage Report

Created: 2023-06-07 06:15

/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
}