diff options
-rw-r--r-- | lib/Makefile.am | 5 | ||||
-rw-r--r-- | lib/envop.c | 484 | ||||
-rw-r--r-- | lib/envop.h | 68 | ||||
-rw-r--r-- | lib/wildmatch.c | 140 | ||||
-rw-r--r-- | src/comp.c | 16 | ||||
-rw-r--r-- | src/pies.c | 278 | ||||
-rw-r--r-- | src/pies.h | 5 | ||||
-rw-r--r-- | src/prog.h | 1 | ||||
-rw-r--r-- | src/progman.c | 310 | ||||
-rw-r--r-- | tests/.gitignore | 1 | ||||
-rw-r--r-- | tests/Makefile.am | 11 | ||||
-rw-r--r-- | tests/env.at | 65 | ||||
-rw-r--r-- | tests/envop.at | 101 | ||||
-rw-r--r-- | tests/envtest.c | 209 | ||||
-rw-r--r-- | tests/redirect.at | 2 | ||||
-rw-r--r-- | tests/testsuite.at | 3 |
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 | |||
21 | libpies_a_SOURCES=\ | 21 | libpies_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 | ||
35 | libpies_a_LIBADD=\ | 38 | libpies_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 | |||
27 | environ_t * | ||
28 | environ_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 | |||
66 | void | ||
67 | environ_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 | |||
75 | static ssize_t | ||
76 | getenvind (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 | |||
98 | static ssize_t | ||
99 | environ_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 | |||
133 | static int | ||
134 | environ_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 | |||
149 | int | ||
150 | environ_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 | |||
163 | int | ||
164 | environ_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); | ||