1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* env.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: cacharle <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2020/02/28 09:21:24 by cacharle #+# #+# */
/* Updated: 2020/10/10 18:08:17 by charles ### ########.fr */
/* */
/* ************************************************************************** */
/*
** \file env.c
** \brief Environment manipulation
*/
#include "minishell.h"
#include "eval.h"
#define ENV_VEC_DEFAULT_SIZE 64
/*
** \brief Convert array of string to environment hash table
** \param envp array of string (each in the format `name=value`)
** \return Environment hash table or NULL on error
*/
t_env env_from_array(char **envp)
{
t_env env;
if ((env = ft_vecnew(ENV_VEC_DEFAULT_SIZE)) == NULL)
return (NULL);
while (*envp != NULL)
{
if (ft_vecpush_safe(env, ft_strdup(*envp)) == NULL)
{
ft_vecdestroy(env, free);
return (NULL);
}
envp++;
}
return (ft_vecpush(env, NULL));
}
/*
** \brief Search a key in environment
** \param env Searched environment
** \param key Searched key
** \param found_index If found_index != NULL and key is found
** put the index in the env array of key in found_index
** \return Value after '=' in environment variable array
** or NULL if not found
*/
char *env_search(t_env env, char *key, size_t *found_index)
{
size_t i;
size_t key_len;
i = 0;
while (i < env->size - 1)
{
key_len = ft_strlen(key);
if (ft_strncmp(env->data[i], key, key_len) == 0
&& ft_strlen(env->data[i]) > key_len
&& ((char**)env->data)[i][key_len] == '=')
{
if (found_index != NULL)
*found_index = i;
return (ft_strchr(env->data[i], '=') + 1);
}
i++;
}
return (NULL);
}
/*
** \brief Insert or update an environment variable
** \param env Updated environment
** \param key Name of the variable to update
** \param value New value of the variable
** \return The full variable (i.e `key=value`) or NULL on error
*/
char *env_export(t_env env, char *key, char *value)
{
char *joined;
size_t found_index;
if ((joined = ft_strjoin3(key, "=", value)) == NULL)
return (NULL);
if (env_search(env, key, &found_index) == NULL)
{
if (ft_vecinsert(env, env->size - 1, joined) == NULL)
return (NULL);
}
else
{
free(env->data[found_index]);
env->data[found_index] = joined;
}
return (joined);
}
/*
** \brief Buffer containning the string representation of the status code
** and returned by env_search_first_match if asked for $?
*/
static char g_status_buf[64] = {'\0'};
/*
** \brief Search the environment for a potential key located
** at the start of haystack
** \param haystack Potential key
** \return The value assiciated with the key or NULL if not found
*/
char *env_search_first_match(t_env env, const char *haystack)
{
size_t len;
size_t i;
size_t key_len;
if (!ft_isalnum(*haystack) && *haystack != '_' && *haystack != '?')
return ("$");
if (ft_isdigit(*haystack))
return (NULL);
len = 0;
while (ft_isalnum(haystack[len]) || haystack[len] == '_')
len++;
if (haystack[0] == '?')
return (ft_itoa_cpy(g_status_buf, g_state.last_status));
if (len == 0)
return (NULL);
i = -1;
while (++i < env->size - 1)
{
key_len = ft_strchr(env->data[i], '=') - (char*)env->data[i];
if (len != key_len)
continue ;
if (ft_strncmp((char*)env->data[i], haystack, len) == 0)
return (ft_strchr(env->data[i], '=') + 1);
}
return (NULL);
}
size_t env_key_len(char *key, bool allow_status)
{
size_t i;
if (allow_status && *key == '?')
return (1);
if (ft_isdigit(*key))
return (0);
i = 0;
while (ft_isalnum(key[i]) || key[i] == '_')
i++;
return (i);
}
|