aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Makefile.am5
-rw-r--r--lib/envop.c484
-rw-r--r--lib/envop.h68
-rw-r--r--lib/wildmatch.c140
-rw-r--r--src/comp.c16
-rw-r--r--src/pies.c278
-rw-r--r--src/pies.h5
-rw-r--r--src/prog.h1
-rw-r--r--src/progman.c310
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/Makefile.am11
-rw-r--r--tests/env.at65
-rw-r--r--tests/envop.at101
-rw-r--r--tests/envtest.c209
-rw-r--r--tests/redirect.at2
-rw-r--r--tests/testsuite.at3
16 files changed, 1410 insertions, 289 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 4aa9d3e..7b4eb42 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -21,6 +21,8 @@ noinst_HEADERS = libpies.h grecsasrt.h
21libpies_a_SOURCES=\ 21libpies_a_SOURCES=\
22 addrfmt.c\ 22 addrfmt.c\
23 arraymember.c\ 23 arraymember.c\
24 envop.c\
25 envop.h\
24 grecsasrt.c\ 26 grecsasrt.c\
25 mkfilename.c\ 27 mkfilename.c\
26 netrc.c\ 28 netrc.c\
@@ -30,7 +32,8 @@ libpies_a_SOURCES=\
30 safe_strcmp.c\ 32 safe_strcmp.c\
31 split3.c\ 33 split3.c\
32 strtotok.c\ 34 strtotok.c\
33 url.c 35 url.c\
36 wildmatch.c
34 37
35libpies_a_LIBADD=\ 38libpies_a_LIBADD=\
36 $(LIBOBJS)\ 39 $(LIBOBJS)\
diff --git a/lib/envop.c b/lib/envop.c
new file mode 100644
index 0000000..79083f7
--- /dev/null
+++ b/lib/envop.c
@@ -0,0 +1,484 @@
1/* Environment modification functions for GNU Pies.
2 Copyright (C) 2019 Sergey Poznyakoff
3
4 GNU Pies is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Pies is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
16
17#ifdef HAVE_CONFIG_H
18# include <config.h>
19#endif
20#include <stdlib.h>
21#include <string.h>
22#include <errno.h>
23#include <ctype.h>
24#include "envop.h"
25#include "wordsplit.h"
26
27environ_t *
28environ_create (char **def)
29{
30 size_t i;
31 environ_t *env = malloc (sizeof (*env));
32
33 if (!env)
34 return NULL;
35
36 if (!def)
37 {
38 static char *nullenv[] = { NULL };
39 def = nullenv;
40 }
41
42 for (i = 0; def[i]; i++)
43 ;
44 env->env_count = 0;
45 env->env_max = i + 1;
46 env->env_base = calloc (env->env_max, sizeof (env->env_base[0]));
47 if (!env->env_base)
48 {
49 free (env);
50 return NULL;
51 }
52
53 for (i = 0; def[i]; i++)
54 {
55 if (!(env->env_base[i] = strdup (def[i])))
56 {
57 environ_free (env);
58 return NULL;
59 }
60 env->env_count++;
61 }
62 env->env_base[i] = NULL;
63 return env;
64}
65
66void
67environ_free (environ_t *env)
68{
69 size_t i;
70 for (i = 0; i < env->env_count; i++)
71 free (env->env_base[i]);
72 free (env->env_base);
73}
74
75static ssize_t
76getenvind (environ_t *env, char const *name, char **pval)
77{
78 size_t i;
79
80 for (i = 0; i < env->env_count; i++)
81 {
82 char const *p;
83 char *q;
84
85 for (p = name, q = env->env_base[i]; *p == *q; p++, q++)
86 if (*p == '=')
87 break;
88 if ((*p == 0 || *p == '=') && *q == '=')
89 {
90 if (pval)
91 *pval = q + 1;
92 return i;
93 }
94 }
95 return -1;
96}
97
98static ssize_t
99environ_alloc (environ_t *env)
100{
101 size_t n;
102 if (env->env_count + 1 >= env->env_max)
103 {
104 char **p;
105 if (env->env_base == NULL)
106 {
107 n = 64;
108 p = calloc (n, sizeof (p[0]));
109 if (!p)
110 return -1;
111 }
112 else
113 {
114 n = env->env_max;
115 if ((size_t) -1 / 3 * 2 / sizeof (p[0]) <= n)
116 {
117 errno = ENOMEM;
118 return -1;
119 }
120 n += (n + 1) / 2;
121 p = realloc (env->env_base, n * sizeof (p[0]));
122 if (!p)
123 return -1;
124 }
125 env->env_base = p;
126 env->env_max = n;
127 }
128 n = env->env_count++;
129 env->env_base[env->env_count] = NULL;
130 return n;
131}
132
133static int
134environ_add_alloced (environ_t *env, char *def)
135{
136 ssize_t n;
137 n = getenvind (env, def, NULL);
138 if (n == -1)
139 {
140 n = environ_alloc (env);
141 if (n == -1)
142 return -1;
143 }
144 free (env->env_base[n]);
145 env->env_base[n] = def;
146 return 0;
147}
148
149int
150environ_add (environ_t *env, char const *def)
151{
152 char *defcp = strdup (def);
153 if (!defcp)
154 return -1;
155 if (environ_add_alloced (env, defcp))
156 {
157 free (defcp);
158 return -1;
159 }
160 return 0;
161}
162
163int
164environ_set (environ_t *env, char const *name, char const *value)
165{
166 size_t len;
167 char *def;
168 struct wordsplit ws;
169
170 if (!name)
171 {
172 errno = EINVAL;
173 return -1;
174 }
175 if (!value)
176 return environ_unset (env, name);
177
178 ws.ws_env = (char const **) env->env_base;
179 if (wordsplit (value, &ws,
180 WRDSF_NOSPLIT
181 | WRDSF_QUOTE
182 | WRDSF_NOCMD /* FIXME */
183 | WRDSF_SQUEEZE_DELIMS
184 | WRDSF_CESCAPES
185 | WRDSF_ENV
186 | WRDSF_PATHEXPAND))
187 {
188 int ec = errno;
189 if (ws.ws_errno != WRDSE_USAGE) /* FIXME */
190 wordsplit_free (&ws);
191 errno = ec;
192 return -1;
193 }
194
195 if (strcmp (name, ":") == 0)
196 {
197 wordsplit_free (&ws);
198 return 0;
199 }
200
201 len = strlen (name) + strlen (ws.ws_wordv[0]) + 2;
202 def = malloc (len);
203 if (!def)
204 {
205 int ec = errno;
206 wordsplit_free (&ws);
207 errno = ec;
208 return -1;
209 }
210 strcat (strcat (strcpy (def, name), "="), ws.ws_wordv[0]);
211 wordsplit_free (&ws);
212 if (environ_add_alloced (env, def))
213 {
214 free (def);