misc.c is too crowded with different things to perform any
sane unit testing due to its dependencies. So, in order to re-write
the #ifdef'ed tests for the argv_* family of functions into unit
tests I moved them into a dedicated file.
Signed-off-by: Heiko Hund <heiko.hund@sophos.com>
Acked-by: David Sommerseth <davids@redhat.com>
Message-Id: <1477672963-5724-2-git-send-email-heiko.hund@sophos.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg12811.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
... | ... |
@@ -1301,6 +1301,7 @@ AC_CONFIG_FILES([ |
1301 | 1301 |
tests/unit_tests/plugins/Makefile |
1302 | 1302 |
tests/unit_tests/plugins/auth-pam/Makefile |
1303 | 1303 |
tests/unit_tests/example_test/Makefile |
1304 |
+ tests/unit_tests/openvpn/Makefile |
|
1304 | 1305 |
vendor/Makefile |
1305 | 1306 |
sample/Makefile |
1306 | 1307 |
doc/Makefile |
42 | 43 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,411 @@ |
0 |
+/* |
|
1 |
+ * OpenVPN -- An application to securely tunnel IP networks |
|
2 |
+ * over a single TCP/UDP port, with support for SSL/TLS-based |
|
3 |
+ * session authentication and key exchange, |
|
4 |
+ * packet encryption, packet authentication, and |
|
5 |
+ * packet compression. |
|
6 |
+ * |
|
7 |
+ * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> |
|
8 |
+ * |
|
9 |
+ * This program is free software; you can redistribute it and/or modify |
|
10 |
+ * it under the terms of the GNU General Public License version 2 |
|
11 |
+ * as published by the Free Software Foundation. |
|
12 |
+ * |
|
13 |
+ * This program is distributed in the hope that it will be useful, |
|
14 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
15 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
16 |
+ * GNU General Public License for more details. |
|
17 |
+ * |
|
18 |
+ * You should have received a copy of the GNU General Public License |
|
19 |
+ * along with this program (see the file COPYING included with this |
|
20 |
+ * distribution); if not, write to the Free Software Foundation, Inc., |
|
21 |
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
22 |
+ * |
|
23 |
+ * |
|
24 |
+ * A printf-like function (that only recognizes a subset of standard printf |
|
25 |
+ * format operators) that prints arguments to an argv list instead |
|
26 |
+ * of a standard string. This is used to build up argv arrays for passing |
|
27 |
+ * to execve. |
|
28 |
+ */ |
|
29 |
+ |
|
30 |
+#ifdef HAVE_CONFIG_H |
|
31 |
+#include "config.h" |
|
32 |
+#elif defined(_MSC_VER) |
|
33 |
+#include "config-msvc.h" |
|
34 |
+#endif |
|
35 |
+ |
|
36 |
+#include "syshead.h" |
|
37 |
+ |
|
38 |
+#include "argv.h" |
|
39 |
+#include "options.h" |
|
40 |
+ |
|
41 |
+void |
|
42 |
+argv_init (struct argv *a) |
|
43 |
+{ |
|
44 |
+ a->capacity = 0; |
|
45 |
+ a->argc = 0; |
|
46 |
+ a->argv = NULL; |
|
47 |
+ a->system_str = NULL; |
|
48 |
+} |
|
49 |
+ |
|
50 |
+struct argv |
|
51 |
+argv_new (void) |
|
52 |
+{ |
|
53 |
+ struct argv ret; |
|
54 |
+ argv_init (&ret); |
|
55 |
+ return ret; |
|
56 |
+} |
|
57 |
+ |
|
58 |
+void |
|
59 |
+argv_reset (struct argv *a) |
|
60 |
+{ |
|
61 |
+ size_t i; |
|
62 |
+ for (i = 0; i < a->argc; ++i) |
|
63 |
+ free (a->argv[i]); |
|
64 |
+ free (a->argv); |
|
65 |
+ free (a->system_str); |
|
66 |
+ argv_init (a); |
|
67 |
+} |
|
68 |
+ |
|
69 |
+static void |
|
70 |
+argv_extend (struct argv *a, const size_t newcap) |
|
71 |
+{ |
|
72 |
+ if (newcap > a->capacity) |
|
73 |
+ { |
|
74 |
+ char **newargv; |
|
75 |
+ size_t i; |
|
76 |
+ ALLOC_ARRAY_CLEAR (newargv, char *, newcap); |
|
77 |
+ for (i = 0; i < a->argc; ++i) |
|
78 |
+ newargv[i] = a->argv[i]; |
|
79 |
+ free (a->argv); |
|
80 |
+ a->argv = newargv; |
|
81 |
+ a->capacity = newcap; |
|
82 |
+ } |
|
83 |
+} |
|
84 |
+ |
|
85 |
+static void |
|
86 |
+argv_grow (struct argv *a, const size_t add) |
|
87 |
+{ |
|
88 |
+ const size_t newargc = a->argc + add + 1; |
|
89 |
+ ASSERT (newargc > a->argc); |
|
90 |
+ argv_extend (a, adjust_power_of_2 (newargc)); |
|
91 |
+} |
|
92 |
+ |
|
93 |
+static void |
|
94 |
+argv_append (struct argv *a, char *str) /* str must have been malloced or be NULL */ |
|
95 |
+{ |
|
96 |
+ argv_grow (a, 1); |
|
97 |
+ a->argv[a->argc++] = str; |
|
98 |
+} |
|
99 |
+ |
|
100 |
+static void |
|
101 |
+argv_system_str_append (struct argv *a, const char *str, const bool enquote) |
|
102 |
+{ |
|
103 |
+ if (str) |
|
104 |
+ { |
|
105 |
+ char *newstr; |
|
106 |
+ |
|
107 |
+ /* compute length of new system_str */ |
|
108 |
+ size_t l = strlen (str) + 1; /* space for new string plus trailing '\0' */ |
|
109 |
+ if (a->system_str) |
|
110 |
+ l += strlen (a->system_str) + 1; /* space for existing string + space (" ") separator */ |
|
111 |
+ if (enquote) |
|
112 |
+ l += 2; /* space for two quotes */ |
|
113 |
+ |
|
114 |
+ /* build new system_str */ |
|
115 |
+ newstr = (char *) malloc (l); |
|
116 |
+ newstr[0] = '\0'; |
|
117 |
+ check_malloc_return (newstr); |
|
118 |
+ if (a->system_str) |
|
119 |
+ { |
|
120 |
+ strcpy (newstr, a->system_str); |
|
121 |
+ strcat (newstr, " "); |
|
122 |
+ } |
|
123 |
+ if (enquote) |
|
124 |
+ strcat (newstr, "\""); |
|
125 |
+ strcat (newstr, str); |
|
126 |
+ if (enquote) |
|
127 |
+ strcat (newstr, "\""); |
|
128 |
+ free (a->system_str); |
|
129 |
+ a->system_str = newstr; |
|
130 |
+ } |
|
131 |
+} |
|
132 |
+ |
|
133 |
+static char * |
|
134 |
+argv_extract_cmd_name (const char *path) |
|
135 |
+{ |
|
136 |
+ char *ret = NULL; |
|
137 |
+ if (path) |
|
138 |
+ { |
|
139 |
+ char *path_cp = string_alloc(path, NULL); /* POSIX basename() implementaions may modify its arguments */ |
|
140 |
+ const char *bn = basename (path_cp); |
|
141 |
+ if (bn) |
|
142 |
+ { |
|
143 |
+ char *dot = NULL; |
|
144 |
+ ret = string_alloc (bn, NULL); |
|
145 |
+ dot = strrchr (ret, '.'); |
|
146 |
+ if (dot) |
|
147 |
+ *dot = '\0'; |
|
148 |
+ free(path_cp); |
|
149 |
+ if (ret[0] == '\0') |
|
150 |
+ { |
|
151 |
+ free(ret); |
|
152 |
+ ret = NULL; |
|
153 |
+ } |
|
154 |
+ } |
|
155 |
+ } |
|
156 |
+ return ret; |
|
157 |
+} |
|
158 |
+ |
|
159 |
+const char * |
|
160 |
+argv_system_str (const struct argv *a) |
|
161 |
+{ |
|
162 |
+ return a->system_str; |
|
163 |
+} |
|
164 |
+ |
|
165 |
+static struct argv |
|
166 |
+argv_clone (const struct argv *a, const size_t headroom) |
|
167 |
+{ |
|
168 |
+ struct argv r; |
|
169 |
+ size_t i; |
|
170 |
+ |
|
171 |
+ argv_init (&r); |
|
172 |
+ for (i = 0; i < headroom; ++i) |
|
173 |
+ argv_append (&r, NULL); |
|
174 |
+ if (a) |
|
175 |
+ { |
|
176 |
+ for (i = 0; i < a->argc; ++i) |
|
177 |
+ argv_append (&r, string_alloc (a->argv[i], NULL)); |
|
178 |
+ r.system_str = string_alloc (a->system_str, NULL); |
|
179 |
+ } |
|
180 |
+ return r; |
|
181 |
+} |
|
182 |
+ |
|
183 |
+struct argv |
|
184 |
+argv_insert_head (const struct argv *a, const char *head) |
|
185 |
+{ |
|
186 |
+ struct argv r; |
|
187 |
+ char *s; |
|
188 |
+ |
|
189 |
+ r = argv_clone (a, 1); |
|
190 |
+ r.argv[0] = string_alloc (head, NULL); |
|
191 |
+ s = r.system_str; |
|
192 |
+ r.system_str = string_alloc (head, NULL); |
|
193 |
+ if (s) |
|
194 |
+ { |
|
195 |
+ argv_system_str_append (&r, s, false); |
|
196 |
+ free (s); |
|
197 |
+ } |
|
198 |
+ return r; |
|
199 |
+} |
|
200 |
+ |
|
201 |
+char * |
|
202 |
+argv_term (const char **f) |
|
203 |
+{ |
|
204 |
+ const char *p = *f; |
|
205 |
+ const char *term = NULL; |
|
206 |
+ size_t termlen = 0; |
|
207 |
+ |
|
208 |
+ if (*p == '\0') |
|
209 |
+ return NULL; |
|
210 |
+ |
|
211 |
+ while (true) |
|
212 |
+ { |
|
213 |
+ const int c = *p; |
|
214 |
+ if (c == '\0') |
|
215 |
+ break; |
|
216 |
+ if (term) |
|
217 |
+ { |
|
218 |
+ if (!isspace (c)) |
|
219 |
+ ++termlen; |
|
220 |
+ else |
|
221 |
+ break; |
|
222 |
+ } |
|
223 |
+ else |
|
224 |
+ { |
|
225 |
+ if (!isspace (c)) |
|
226 |
+ { |
|
227 |
+ term = p; |
|
228 |
+ termlen = 1; |
|
229 |
+ } |
|
230 |
+ } |
|
231 |
+ ++p; |
|
232 |
+ } |
|
233 |
+ *f = p; |
|
234 |
+ |
|
235 |
+ if (term) |
|
236 |
+ { |
|
237 |
+ char *ret; |
|
238 |
+ ASSERT (termlen > 0); |
|
239 |
+ ret = malloc (termlen + 1); |
|
240 |
+ check_malloc_return (ret); |
|
241 |
+ memcpy (ret, term, termlen); |
|
242 |
+ ret[termlen] = '\0'; |
|
243 |
+ return ret; |
|
244 |
+ } |
|
245 |
+ else |
|
246 |
+ return NULL; |
|
247 |
+} |
|
248 |
+ |
|
249 |
+const char * |
|
250 |
+argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags) |
|
251 |
+{ |
|
252 |
+ if (a->argv) |
|
253 |
+ return print_argv ((const char **)a->argv, gc, flags); |
|
254 |
+ else |
|
255 |
+ return ""; |
|
256 |
+} |
|
257 |
+ |
|
258 |
+void |
|
259 |
+argv_msg (const int msglev, const struct argv *a) |
|
260 |
+{ |
|
261 |
+ struct gc_arena gc = gc_new (); |
|
262 |
+ msg (msglev, "%s", argv_str (a, &gc, 0)); |
|
263 |
+ gc_free (&gc); |
|
264 |
+} |
|
265 |
+ |
|
266 |
+void |
|
267 |
+argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix) |
|
268 |
+{ |
|
269 |
+ struct gc_arena gc = gc_new (); |
|
270 |
+ msg (msglev, "%s: %s", prefix, argv_str (a, &gc, 0)); |
|
271 |
+ gc_free (&gc); |
|
272 |
+} |
|
273 |
+ |
|
274 |
+void |
|
275 |
+argv_printf (struct argv *a, const char *format, ...) |
|
276 |
+{ |
|
277 |
+ va_list arglist; |
|
278 |
+ va_start (arglist, format); |
|
279 |
+ argv_printf_arglist (a, format, 0, arglist); |
|
280 |
+ va_end (arglist); |
|
281 |
+ } |
|
282 |
+ |
|
283 |
+void |
|
284 |
+argv_printf_cat (struct argv *a, const char *format, ...) |
|
285 |
+{ |
|
286 |
+ va_list arglist; |
|
287 |
+ va_start (arglist, format); |
|
288 |
+ argv_printf_arglist (a, format, APA_CAT, arglist); |
|
289 |
+ va_end (arglist); |
|
290 |
+} |
|
291 |
+ |
|
292 |
+void |
|
293 |
+argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist) |
|
294 |
+{ |
|
295 |
+ struct gc_arena gc = gc_new (); |
|
296 |
+ char *term; |
|
297 |
+ const char *f = format; |
|
298 |
+ |
|
299 |
+ if (!(flags & APA_CAT)) |
|
300 |
+ argv_reset (a); |
|
301 |
+ argv_extend (a, 1); /* ensure trailing NULL */ |
|
302 |
+ |
|
303 |
+ while ((term = argv_term (&f)) != NULL) |
|
304 |
+ { |
|
305 |
+ if (term[0] == '%') |
|
306 |
+ { |
|
307 |
+ if (!strcmp (term, "%s")) |
|
308 |
+ { |
|
309 |
+ char *s = va_arg (arglist, char *); |
|
310 |
+ if (!s) |
|
311 |
+ s = ""; |
|
312 |
+ argv_append (a, string_alloc (s, NULL)); |
|
313 |
+ argv_system_str_append (a, s, true); |
|
314 |
+ } |
|
315 |
+ else if (!strcmp (term, "%sc")) |
|
316 |
+ { |
|
317 |
+ char *s = va_arg (arglist, char *); |
|
318 |
+ if (s) |
|
319 |
+ { |
|
320 |
+ int nparms; |
|
321 |
+ char *parms[MAX_PARMS+1]; |
|
322 |
+ int i; |
|
323 |
+ |
|
324 |
+ nparms = parse_line (s, parms, MAX_PARMS, "SCRIPT-ARGV", 0, D_ARGV_PARSE_CMD, &gc); |
|
325 |
+ if (nparms) |
|
326 |
+ { |
|
327 |
+ for (i = 0; i < nparms; ++i) |
|
328 |
+ argv_append (a, string_alloc (parms[i], NULL)); |
|
329 |
+ } |
|
330 |
+ else |
|
331 |
+ argv_append (a, string_alloc (s, NULL)); |
|
332 |
+ |
|
333 |
+ argv_system_str_append (a, s, false); |
|
334 |
+ } |
|
335 |
+ else |
|
336 |
+ { |
|
337 |
+ argv_append (a, string_alloc ("", NULL)); |
|
338 |
+ argv_system_str_append (a, "echo", false); |
|
339 |
+ } |
|
340 |
+ } |
|
341 |
+ else if (!strcmp (term, "%d")) |
|
342 |
+ { |
|
343 |
+ char numstr[64]; |
|
344 |
+ openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int)); |
|
345 |
+ argv_append (a, string_alloc (numstr, NULL)); |
|
346 |
+ argv_system_str_append (a, numstr, false); |
|
347 |
+ } |
|
348 |
+ else if (!strcmp (term, "%u")) |
|
349 |
+ { |
|
350 |
+ char numstr[64]; |
|
351 |
+ openvpn_snprintf (numstr, sizeof (numstr), "%u", va_arg (arglist, unsigned int)); |
|
352 |
+ argv_append (a, string_alloc (numstr, NULL)); |
|
353 |
+ argv_system_str_append (a, numstr, false); |
|
354 |
+ } |
|
355 |
+ else if (!strcmp (term, "%s/%d")) |
|
356 |
+ { |
|
357 |
+ char numstr[64]; |
|
358 |
+ char *s = va_arg (arglist, char *); |
|
359 |
+ |
|
360 |
+ if (!s) |
|
361 |
+ s = ""; |
|
362 |
+ |
|
363 |
+ openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int)); |
|
364 |
+ |
|
365 |
+ { |
|
366 |
+ const size_t len = strlen(s) + strlen(numstr) + 2; |
|
367 |
+ char *combined = (char *) malloc (len); |
|
368 |
+ check_malloc_return (combined); |
|
369 |
+ |
|
370 |
+ strcpy (combined, s); |
|
371 |
+ strcat (combined, "/"); |
|
372 |
+ strcat (combined, numstr); |
|
373 |
+ argv_append (a, combined); |
|
374 |
+ argv_system_str_append (a, combined, false); |
|
375 |
+ } |
|
376 |
+ } |
|
377 |
+ else if (!strcmp (term, "%s%sc")) |
|
378 |
+ { |
|
379 |
+ char *s1 = va_arg (arglist, char *); |
|
380 |
+ char *s2 = va_arg (arglist, char *); |
|
381 |
+ char *combined; |
|
382 |
+ char *cmd_name; |
|
383 |
+ |
|
384 |
+ if (!s1) s1 = ""; |
|
385 |
+ if (!s2) s2 = ""; |
|
386 |
+ combined = (char *) malloc (strlen(s1) + strlen(s2) + 1); |
|
387 |
+ check_malloc_return (combined); |
|
388 |
+ strcpy (combined, s1); |
|
389 |
+ strcat (combined, s2); |
|
390 |
+ argv_append (a, combined); |
|
391 |
+ |
|
392 |
+ cmd_name = argv_extract_cmd_name (combined); |
|
393 |
+ if (cmd_name) |
|
394 |
+ { |
|
395 |
+ argv_system_str_append (a, cmd_name, false); |
|
396 |
+ free (cmd_name); |
|
397 |
+ } |
|
398 |
+ } |
|
399 |
+ else |
|
400 |
+ ASSERT (0); |
|
401 |
+ free (term); |
|
402 |
+ } |
|
403 |
+ else |
|
404 |
+ { |
|
405 |
+ argv_append (a, term); |
|
406 |
+ argv_system_str_append (a, term, false); |
|
407 |
+ } |
|
408 |
+ } |
|
409 |
+ gc_free (&gc); |
|
410 |
+} |
0 | 411 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,76 @@ |
0 |
+/* |
|
1 |
+ * OpenVPN -- An application to securely tunnel IP networks |
|
2 |
+ * over a single TCP/UDP port, with support for SSL/TLS-based |
|
3 |
+ * session authentication and key exchange, |
|
4 |
+ * packet encryption, packet authentication, and |
|
5 |
+ * packet compression. |
|
6 |
+ * |
|
7 |
+ * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> |
|
8 |
+ * |
|
9 |
+ * This program is free software; you can redistribute it and/or modify |
|
10 |
+ * it under the terms of the GNU General Public License version 2 |
|
11 |
+ * as published by the Free Software Foundation. |
|
12 |
+ * |
|
13 |
+ * This program is distributed in the hope that it will be useful, |
|
14 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
15 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
16 |
+ * GNU General Public License for more details. |
|
17 |
+ * |
|
18 |
+ * You should have received a copy of the GNU General Public License |
|
19 |
+ * along with this program (see the file COPYING included with this |
|
20 |
+ * distribution); if not, write to the Free Software Foundation, Inc., |
|
21 |
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
22 |
+ * |
|
23 |
+ * |
|
24 |
+ * A printf-like function (that only recognizes a subset of standard printf |
|
25 |
+ * format operators) that prints arguments to an argv list instead |
|
26 |
+ * of a standard string. This is used to build up argv arrays for passing |
|
27 |
+ * to execve. |
|
28 |
+ */ |
|
29 |
+ |
|
30 |
+#ifndef ARGV_H |
|
31 |
+#define ARGV_H |
|
32 |
+ |
|
33 |
+#include "buffer.h" |
|
34 |
+ |
|
35 |
+struct argv { |
|
36 |
+ size_t capacity; |
|
37 |
+ size_t argc; |
|
38 |
+ char **argv; |
|
39 |
+ char *system_str; |
|
40 |
+}; |
|
41 |
+ |
|
42 |
+void argv_init (struct argv *a); |
|
43 |
+struct argv argv_new (void); |
|
44 |
+void argv_reset (struct argv *a); |
|
45 |
+char *argv_term (const char **f); |
|
46 |
+const char *argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags); |
|
47 |
+struct argv argv_insert_head (const struct argv *a, const char *head); |
|
48 |
+void argv_msg (const int msglev, const struct argv *a); |
|
49 |
+void argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix); |
|
50 |
+const char *argv_system_str (const struct argv *a); |
|
51 |
+ |
|
52 |
+#define APA_CAT (1<<0) /* concatentate onto existing struct argv list */ |
|
53 |
+void argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist); |
|
54 |
+ |
|
55 |
+void argv_printf (struct argv *a, const char *format, ...) |
|
56 |
+#ifdef __GNUC__ |
|
57 |
+#if __USE_MINGW_ANSI_STDIO |
|
58 |
+ __attribute__ ((format (gnu_printf, 2, 3))) |
|
59 |
+#else |
|
60 |
+ __attribute__ ((format (__printf__, 2, 3))) |
|
61 |
+#endif |
|
62 |
+#endif |
|
63 |
+ ; |
|
64 |
+ |
|
65 |
+void argv_printf_cat (struct argv *a, const char *format, ...) |
|
66 |
+#ifdef __GNUC__ |
|
67 |
+#if __USE_MINGW_ANSI_STDIO |
|
68 |
+ __attribute__ ((format (gnu_printf, 2, 3))) |
|
69 |
+#else |
|
70 |
+ __attribute__ ((format (__printf__, 2, 3))) |
|
71 |
+#endif |
|
72 |
+#endif |
|
73 |
+ ; |
|
74 |
+ |
|
75 |
+#endif |
... | ... |
@@ -1588,465 +1588,6 @@ adjust_power_of_2 (size_t u) |
1588 | 1588 |
} |
1589 | 1589 |
|
1590 | 1590 |
/* |
1591 |
- * A printf-like function (that only recognizes a subset of standard printf |
|
1592 |
- * format operators) that prints arguments to an argv list instead |
|
1593 |
- * of a standard string. This is used to build up argv arrays for passing |
|
1594 |
- * to execve. |
|
1595 |
- */ |
|
1596 |
- |
|
1597 |
-void |
|
1598 |
-argv_init (struct argv *a) |
|
1599 |
-{ |
|
1600 |
- a->capacity = 0; |
|
1601 |
- a->argc = 0; |
|
1602 |
- a->argv = NULL; |
|
1603 |
- a->system_str = NULL; |
|
1604 |
-} |
|
1605 |
- |
|
1606 |
-struct argv |
|
1607 |
-argv_new (void) |
|
1608 |
-{ |
|
1609 |
- struct argv ret; |
|
1610 |
- argv_init (&ret); |
|
1611 |
- return ret; |
|
1612 |
-} |
|
1613 |
- |
|
1614 |
-void |
|
1615 |
-argv_reset (struct argv *a) |
|
1616 |
-{ |
|
1617 |
- size_t i; |
|
1618 |
- for (i = 0; i < a->argc; ++i) |
|
1619 |
- free (a->argv[i]); |
|
1620 |
- free (a->argv); |
|
1621 |
- free (a->system_str); |
|
1622 |
- argv_init (a); |
|
1623 |
-} |
|
1624 |
- |
|
1625 |
-static void |
|
1626 |
-argv_extend (struct argv *a, const size_t newcap) |
|
1627 |
-{ |
|
1628 |
- if (newcap > a->capacity) |
|
1629 |
- { |
|
1630 |
- char **newargv; |
|
1631 |
- size_t i; |
|
1632 |
- ALLOC_ARRAY_CLEAR (newargv, char *, newcap); |
|
1633 |
- for (i = 0; i < a->argc; ++i) |
|
1634 |
- newargv[i] = a->argv[i]; |
|
1635 |
- free (a->argv); |
|
1636 |
- a->argv = newargv; |
|
1637 |
- a->capacity = newcap; |
|
1638 |
- } |
|
1639 |
-} |
|
1640 |
- |
|
1641 |
-static void |
|
1642 |
-argv_grow (struct argv *a, const size_t add) |
|
1643 |
-{ |
|
1644 |
- const size_t newargc = a->argc + add + 1; |
|
1645 |
- ASSERT (newargc > a->argc); |
|
1646 |
- argv_extend (a, adjust_power_of_2 (newargc)); |
|
1647 |
-} |
|
1648 |
- |
|
1649 |
-static void |
|
1650 |
-argv_append (struct argv *a, char *str) /* str must have been malloced or be NULL */ |
|
1651 |
-{ |
|
1652 |
- argv_grow (a, 1); |
|
1653 |
- a->argv[a->argc++] = str; |
|
1654 |
-} |
|
1655 |
- |
|
1656 |
-static void |
|
1657 |
-argv_system_str_append (struct argv *a, const char *str, const bool enquote) |
|
1658 |
-{ |
|
1659 |
- if (str) |
|
1660 |
- { |
|
1661 |
- char *newstr; |
|
1662 |
- |
|
1663 |
- /* compute length of new system_str */ |
|
1664 |
- size_t l = strlen (str) + 1; /* space for new string plus trailing '\0' */ |
|
1665 |
- if (a->system_str) |
|
1666 |
- l += strlen (a->system_str) + 1; /* space for existing string + space (" ") separator */ |
|
1667 |
- if (enquote) |
|
1668 |
- l += 2; /* space for two quotes */ |
|
1669 |
- |
|
1670 |
- /* build new system_str */ |
|
1671 |
- newstr = (char *) malloc (l); |
|
1672 |
- newstr[0] = '\0'; |
|
1673 |
- check_malloc_return (newstr); |
|
1674 |
- if (a->system_str) |
|
1675 |
- { |
|
1676 |
- strcpy (newstr, a->system_str); |
|
1677 |
- strcat (newstr, " "); |
|
1678 |
- } |
|
1679 |
- if (enquote) |
|
1680 |
- strcat (newstr, "\""); |
|
1681 |
- strcat (newstr, str); |
|
1682 |
- if (enquote) |
|
1683 |
- strcat (newstr, "\""); |
|
1684 |
- free (a->system_str); |
|
1685 |
- a->system_str = newstr; |
|
1686 |
- } |
|
1687 |
-} |
|
1688 |
- |
|
1689 |
-static char * |
|
1690 |
-argv_extract_cmd_name (const char *path) |
|
1691 |
-{ |
|
1692 |
- char *ret = NULL; |
|
1693 |
- if (path) |
|
1694 |
- { |
|
1695 |
- char *path_cp = string_alloc(path, NULL); /* POSIX basename() implementaions may modify its arguments */ |
|
1696 |
- const char *bn = basename (path_cp); |
|
1697 |
- if (bn) |
|
1698 |
- { |
|
1699 |
- char *dot = NULL; |
|
1700 |
- ret = string_alloc (bn, NULL); |
|
1701 |
- dot = strrchr (ret, '.'); |
|
1702 |
- if (dot) |
|
1703 |
- *dot = '\0'; |
|
1704 |
- free(path_cp); |
|
1705 |
- if (ret[0] == '\0') |
|
1706 |
- { |
|
1707 |
- free(ret); |
|
1708 |
- ret = NULL; |
|
1709 |
- } |
|
1710 |
- } |
|
1711 |
- } |
|
1712 |
- return ret; |
|
1713 |
-} |
|
1714 |
- |
|
1715 |
-const char * |
|
1716 |
-argv_system_str (const struct argv *a) |
|
1717 |
-{ |
|
1718 |
- return a->system_str; |
|
1719 |
-} |
|
1720 |
- |
|
1721 |
-struct argv |
|
1722 |
-argv_clone (const struct argv *a, const size_t headroom) |
|
1723 |
-{ |
|
1724 |
- struct argv r; |
|
1725 |
- size_t i; |
|
1726 |
- |
|
1727 |
- argv_init (&r); |
|
1728 |
- for (i = 0; i < headroom; ++i) |
|
1729 |
- argv_append (&r, NULL); |
|
1730 |
- if (a) |
|
1731 |
- { |
|
1732 |
- for (i = 0; i < a->argc; ++i) |
|
1733 |
- argv_append (&r, string_alloc (a->argv[i], NULL)); |
|
1734 |
- r.system_str = string_alloc (a->system_str, NULL); |
|
1735 |
- } |
|
1736 |
- return r; |
|
1737 |
-} |
|
1738 |
- |
|
1739 |
-struct argv |
|
1740 |
-argv_insert_head (const struct argv *a, const char *head) |
|
1741 |
-{ |
|
1742 |
- struct argv r; |
|
1743 |
- char *s; |
|
1744 |
- |
|
1745 |
- r = argv_clone (a, 1); |
|
1746 |
- r.argv[0] = string_alloc (head, NULL); |
|
1747 |
- s = r.system_str; |
|
1748 |
- r.system_str = string_alloc (head, NULL); |
|
1749 |
- if (s) |
|
1750 |
- { |
|
1751 |
- argv_system_str_append (&r, s, false); |
|
1752 |
- free (s); |
|
1753 |
- } |
|
1754 |
- return r; |
|
1755 |
-} |
|
1756 |
- |
|
1757 |
-char * |
|
1758 |
-argv_term (const char **f) |
|
1759 |
-{ |
|
1760 |
- const char *p = *f; |
|
1761 |
- const char *term = NULL; |
|
1762 |
- size_t termlen = 0; |
|
1763 |
- |
|
1764 |
- if (*p == '\0') |
|
1765 |
- return NULL; |
|
1766 |
- |
|
1767 |
- while (true) |
|
1768 |
- { |
|
1769 |
- const int c = *p; |
|
1770 |
- if (c == '\0') |
|
1771 |
- break; |
|
1772 |
- if (term) |
|
1773 |
- { |
|
1774 |
- if (!isspace (c)) |
|
1775 |
- ++termlen; |
|
1776 |
- else |
|
1777 |
- break; |
|
1778 |
- } |
|
1779 |
- else |
|
1780 |
- { |
|
1781 |
- if (!isspace (c)) |
|
1782 |
- { |
|
1783 |
- term = p; |
|
1784 |
- termlen = 1; |
|
1785 |
- } |
|
1786 |
- } |
|
1787 |
- ++p; |
|
1788 |
- } |
|
1789 |
- *f = p; |
|
1790 |
- |
|
1791 |
- if (term) |
|
1792 |
- { |
|
1793 |
- char *ret; |
|
1794 |
- ASSERT (termlen > 0); |
|
1795 |
- ret = malloc (termlen + 1); |
|
1796 |
- check_malloc_return (ret); |
|
1797 |
- memcpy (ret, term, termlen); |
|
1798 |
- ret[termlen] = '\0'; |
|
1799 |
- return ret; |
|
1800 |
- } |
|
1801 |
- else |
|
1802 |
- return NULL; |
|
1803 |
-} |
|
1804 |
- |
|
1805 |
-const char * |
|
1806 |
-argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags) |
|
1807 |
-{ |
|
1808 |
- if (a->argv) |
|
1809 |
- return print_argv ((const char **)a->argv, gc, flags); |
|
1810 |
- else |
|
1811 |
- return ""; |
|
1812 |
-} |
|
1813 |
- |
|
1814 |
-void |
|
1815 |
-argv_msg (const int msglev, const struct argv *a) |
|
1816 |
-{ |
|
1817 |
- struct gc_arena gc = gc_new (); |
|
1818 |
- msg (msglev, "%s", argv_str (a, &gc, 0)); |
|
1819 |
- gc_free (&gc); |
|
1820 |
-} |
|
1821 |
- |
|
1822 |
-void |
|
1823 |
-argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix) |
|
1824 |
-{ |
|
1825 |
- struct gc_arena gc = gc_new (); |
|
1826 |
- msg (msglev, "%s: %s", prefix, argv_str (a, &gc, 0)); |
|
1827 |
- gc_free (&gc); |
|
1828 |
-} |
|
1829 |
- |
|
1830 |
-void |
|
1831 |
-argv_printf (struct argv *a, const char *format, ...) |
|
1832 |
-{ |
|
1833 |
- va_list arglist; |
|
1834 |
- va_start (arglist, format); |
|
1835 |
- argv_printf_arglist (a, format, 0, arglist); |
|
1836 |
- va_end (arglist); |
|
1837 |
- } |
|
1838 |
- |
|
1839 |
-void |
|
1840 |
-argv_printf_cat (struct argv *a, const char *format, ...) |
|
1841 |
-{ |
|
1842 |
- va_list arglist; |
|
1843 |
- va_start (arglist, format); |
|
1844 |
- argv_printf_arglist (a, format, APA_CAT, arglist); |
|
1845 |
- va_end (arglist); |
|
1846 |
-} |
|
1847 |
- |
|
1848 |
-void |
|
1849 |
-argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist) |
|
1850 |
-{ |
|
1851 |
- struct gc_arena gc = gc_new (); |
|
1852 |
- char *term; |
|
1853 |
- const char *f = format; |
|
1854 |
- |
|
1855 |
- if (!(flags & APA_CAT)) |
|
1856 |
- argv_reset (a); |
|
1857 |
- argv_extend (a, 1); /* ensure trailing NULL */ |
|
1858 |
- |
|
1859 |
- while ((term = argv_term (&f)) != NULL) |
|
1860 |
- { |
|
1861 |
- if (term[0] == '%') |
|
1862 |
- { |
|
1863 |
- if (!strcmp (term, "%s")) |
|
1864 |
- { |
|
1865 |
- char *s = va_arg (arglist, char *); |
|
1866 |
- if (!s) |
|
1867 |
- s = ""; |
|
1868 |
- argv_append (a, string_alloc (s, NULL)); |
|
1869 |
- argv_system_str_append (a, s, true); |
|
1870 |
- } |
|
1871 |
- else if (!strcmp (term, "%sc")) |
|
1872 |
- { |
|
1873 |
- char *s = va_arg (arglist, char *); |
|
1874 |
- if (s) |
|
1875 |
- { |
|
1876 |
- int nparms; |
|
1877 |
- char *parms[MAX_PARMS+1]; |
|
1878 |
- int i; |
|
1879 |
- |
|
1880 |
- nparms = parse_line (s, parms, MAX_PARMS, "SCRIPT-ARGV", 0, D_ARGV_PARSE_CMD, &gc); |
|
1881 |
- if (nparms) |
|
1882 |
- { |
|
1883 |
- for (i = 0; i < nparms; ++i) |
|
1884 |
- argv_append (a, string_alloc (parms[i], NULL)); |
|
1885 |
- } |
|
1886 |
- else |
|
1887 |
- argv_append (a, string_alloc (s, NULL)); |
|
1888 |
- |
|
1889 |
- argv_system_str_append (a, s, false); |
|
1890 |
- } |
|
1891 |
- else |
|
1892 |
- { |
|
1893 |
- argv_append (a, string_alloc ("", NULL)); |
|
1894 |
- argv_system_str_append (a, "echo", false); |
|
1895 |
- } |
|
1896 |
- } |
|
1897 |
- else if (!strcmp (term, "%d")) |
|
1898 |
- { |
|
1899 |
- char numstr[64]; |
|
1900 |
- openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int)); |
|
1901 |
- argv_append (a, string_alloc (numstr, NULL)); |
|
1902 |
- argv_system_str_append (a, numstr, false); |
|
1903 |
- } |
|
1904 |
- else if (!strcmp (term, "%u")) |
|
1905 |
- { |
|
1906 |
- char numstr[64]; |
|
1907 |
- openvpn_snprintf (numstr, sizeof (numstr), "%u", va_arg (arglist, unsigned int)); |
|
1908 |
- argv_append (a, string_alloc (numstr, NULL)); |
|
1909 |
- argv_system_str_append (a, numstr, false); |
|
1910 |
- } |
|
1911 |
- else if (!strcmp (term, "%s/%d")) |
|
1912 |
- { |
|
1913 |
- char numstr[64]; |
|
1914 |
- char *s = va_arg (arglist, char *); |
|
1915 |
- |
|
1916 |
- if (!s) |
|
1917 |
- s = ""; |
|
1918 |
- |
|
1919 |
- openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int)); |
|
1920 |
- |
|
1921 |
- { |
|
1922 |
- const size_t len = strlen(s) + strlen(numstr) + 2; |
|
1923 |
- char *combined = (char *) malloc (len); |
|
1924 |
- check_malloc_return (combined); |
|
1925 |
- |
|
1926 |
- strcpy (combined, s); |
|
1927 |
- strcat (combined, "/"); |
|
1928 |
- strcat (combined, numstr); |
|
1929 |
- argv_append (a, combined); |
|
1930 |
- argv_system_str_append (a, combined, false); |
|
1931 |
- } |
|
1932 |
- } |
|
1933 |
- else if (!strcmp (term, "%s%sc")) |
|
1934 |
- { |
|
1935 |
- char *s1 = va_arg (arglist, char *); |
|
1936 |
- char *s2 = va_arg (arglist, char *); |
|
1937 |
- char *combined; |
|
1938 |
- char *cmd_name; |
|
1939 |
- |
|
1940 |
- if (!s1) s1 = ""; |
|
1941 |
- if (!s2) s2 = ""; |
|
1942 |
- combined = (char *) malloc (strlen(s1) + strlen(s2) + 1); |
|
1943 |
- check_malloc_return (combined); |
|
1944 |
- strcpy (combined, s1); |
|
1945 |
- strcat (combined, s2); |
|
1946 |
- argv_append (a, combined); |
|
1947 |
- |
|
1948 |
- cmd_name = argv_extract_cmd_name (combined); |
|
1949 |
- if (cmd_name) |
|
1950 |
- { |
|
1951 |
- argv_system_str_append (a, cmd_name, false); |
|
1952 |
- free (cmd_name); |
|
1953 |
- } |
|
1954 |
- } |
|
1955 |
- else |
|
1956 |
- ASSERT (0); |
|
1957 |
- free (term); |
|
1958 |
- } |
|
1959 |
- else |
|
1960 |
- { |
|
1961 |
- argv_append (a, term); |
|
1962 |
- argv_system_str_append (a, term, false); |
|
1963 |
- } |
|
1964 |
- } |
|
1965 |
- gc_free (&gc); |
|
1966 |
-} |
|
1967 |
- |
|
1968 |
-#ifdef ARGV_TEST |
|
1969 |
-void |
|
1970 |
-argv_test (void) |
|
1971 |
-{ |
|
1972 |
- struct gc_arena gc = gc_new (); |
|
1973 |
- const char *s; |
|
1974 |
- |
|
1975 |
- struct argv a; |
|
1976 |
- |
|
1977 |
- argv_init (&a); |
|
1978 |
- argv_printf (&a, "%sc foo bar %s", "c:\\\\src\\\\test\\\\jyargs.exe", "foo bar"); |
|
1979 |
- argv_msg_prefix (M_INFO, &a, "ARGV"); |
|
1980 |
- msg (M_INFO, "ARGV-S: %s", argv_system_str(&a)); |
|
1981 |
- /*openvpn_execve_check (&a, NULL, 0, "command failed");*/ |
|
1982 |
- |
|
1983 |
- argv_printf (&a, "%sc %s %s", "c:\\\\src\\\\test files\\\\batargs.bat", "foo", "bar"); |
|
1984 |
- argv_msg_prefix (M_INFO, &a, "ARGV"); |
|
1985 |
- msg (M_INFO, "ARGV-S: %s", argv_system_str(&a)); |
|
1986 |
- /*openvpn_execve_check (&a, NULL, 0, "command failed");*/ |
|
1987 |
- |
|
1988 |
- argv_printf (&a, "%s%sc foo bar %s %s/%d %d %u", "/foo", "/bar.exe", "one two", "1.2.3.4", 24, -69, 96); |
|
1989 |
- argv_msg_prefix (M_INFO, &a, "ARGV"); |
|
1990 |
- msg (M_INFO, "ARGV-S: %s", argv_system_str(&a)); |
|
1991 |
- /*openvpn_execve_check (&a, NULL, 0, "command failed");*/ |
|
1992 |
- |
|
1993 |
- argv_printf (&a, "this is a %s test of int %d unsigned %u", "FOO", -69, 42); |
|
1994 |
- s = argv_str (&a, &gc, PA_BRACKET); |
|
1995 |
- printf ("PF: %s\n", s); |
|
1996 |
- printf ("PF-S: %s\n", argv_system_str(&a)); |
|
1997 |
- |
|
1998 |
- { |
|
1999 |
- struct argv b = argv_insert_head (&a, "MARK"); |
|
2000 |
- s = argv_str (&b, &gc, PA_BRACKET); |
|
2001 |
- printf ("PF: %s\n", s); |
|
2002 |
- printf ("PF-S: %s\n", argv_system_str(&b)); |
|
2003 |
- argv_reset (&b); |
|
2004 |
- } |
|
2005 |
- |
|
2006 |
- argv_printf (&a, "%sc foo bar %d", "\"multi term\" command following \\\"spaces", 99); |
|
2007 |
- s = argv_str (&a, &gc, PA_BRACKET); |
|
2008 |
- printf ("PF: %s\n", s); |
|
2009 |
- printf ("PF-S: %s\n", argv_system_str(&a)); |
|
2010 |
- argv_reset (&a); |
|
2011 |
- |
|
2012 |
- s = argv_str (&a, &gc, PA_BRACKET); |
|
2013 |
- printf ("PF: %s\n", s); |
|
2014 |
- printf ("PF-S: %s\n", argv_system_str(&a)); |
|
2015 |
- argv_reset (&a); |
|
2016 |
- |
|
2017 |
- argv_printf (&a, "foo bar %d", 99); |
|
2018 |
- argv_printf_cat (&a, "bar %d foo %sc", 42, "nonesuch"); |
|
2019 |
- argv_printf_cat (&a, "cool %s %d u %s/%d end", "frood", 4, "hello", 7); |
|
2020 |
- s = argv_str (&a, &gc, PA_BRACKET); |
|
2021 |
- printf ("PF: %s\n", s); |
|
2022 |
- printf ("PF-S: %s\n", argv_system_str(&a)); |
|
2023 |
- argv_reset (&a); |
|
2024 |
- |
|
2025 |
-#if 0 |
|
2026 |
- { |
|
2027 |
- char line[512]; |
|
2028 |
- while (fgets (line, sizeof(line), stdin) != NULL) |
|
2029 |
- { |
|
2030 |
- char *term; |
|
2031 |
- const char *f = line; |
|
2032 |
- int i = 0; |
|
2033 |
- |
|
2034 |
- while ((term = argv_term (&f)) != NULL) |
|
2035 |
- { |
|
2036 |
- printf ("[%d] '%s'\n", i, term); |
|
2037 |
- ++i; |
|
2038 |
- free (term); |
|
2039 |
- } |
|
2040 |
- } |
|
2041 |
- } |
|
2042 |
-#endif |
|
2043 |
- |
|
2044 |
- argv_reset (&a); |
|
2045 |
- gc_free (&gc); |
|
2046 |
-} |
|
2047 |
-#endif |
|
2048 |
- |
|
2049 |
-/* |
|
2050 | 1591 |
* Remove security-sensitive strings from control message |
2051 | 1592 |
* so that they will not be output to log file. |
2052 | 1593 |
*/ |
... | ... |
@@ -25,6 +25,7 @@ |
25 | 25 |
#ifndef MISC_H |
26 | 26 |
#define MISC_H |
27 | 27 |
|
28 |
+#include "argv.h" |
|
28 | 29 |
#include "basic.h" |
29 | 30 |
#include "common.h" |
30 | 31 |
#include "integer.h" |
... | ... |
@@ -37,14 +38,6 @@ |
37 | 37 |
/* forward declarations */ |
38 | 38 |
struct plugin_list; |
39 | 39 |
|
40 |
-/* used by argv_x functions */ |
|
41 |
-struct argv { |
|
42 |
- size_t capacity; |
|
43 |
- size_t argc; |
|
44 |
- char **argv; |
|
45 |
- char *system_str; |
|
46 |
-}; |
|
47 |
- |
|
48 | 40 |
/* |
49 | 41 |
* Handle environmental variable lists |
50 | 42 |
*/ |
... | ... |
@@ -325,45 +318,6 @@ extern int script_security; /* GLOBAL */ |
325 | 325 |
/* return the next largest power of 2 */ |
326 | 326 |
size_t adjust_power_of_2 (size_t u); |
327 | 327 |
|
328 |
-/* |
|
329 |
- * A printf-like function (that only recognizes a subset of standard printf |
|
330 |
- * format operators) that prints arguments to an argv list instead |
|
331 |
- * of a standard string. This is used to build up argv arrays for passing |
|
332 |
- * to execve. |
|
333 |
- */ |
|
334 |
-void argv_init (struct argv *a); |
|
335 |
-struct argv argv_new (void); |
|
336 |
-void argv_reset (struct argv *a); |
|
337 |
-char *argv_term (const char **f); |
|
338 |
-const char *argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags); |
|
339 |
-struct argv argv_insert_head (const struct argv *a, const char *head); |
|
340 |
-void argv_msg (const int msglev, const struct argv *a); |
|
341 |
-void argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix); |
|
342 |
-const char *argv_system_str (const struct argv *a); |
|
343 |
- |
|
344 |
-#define APA_CAT (1<<0) /* concatentate onto existing struct argv list */ |
|
345 |
-void argv_printf_arglist (struct argv *a, const char *format, const unsigned int flags, va_list arglist); |
|
346 |
- |
|
347 |
-void argv_printf (struct argv *a, const char *format, ...) |
|
348 |
-#ifdef __GNUC__ |
|
349 |
-#if __USE_MINGW_ANSI_STDIO |
|
350 |
- __attribute__ ((format (gnu_printf, 2, 3))) |
|
351 |
-#else |
|
352 |
- __attribute__ ((format (__printf__, 2, 3))) |
|
353 |
-#endif |
|
354 |
-#endif |
|
355 |
- ; |
|
356 |
- |
|
357 |
-void argv_printf_cat (struct argv *a, const char *format, ...) |
|
358 |
-#ifdef __GNUC__ |
|
359 |
-#if __USE_MINGW_ANSI_STDIO |
|
360 |
- __attribute__ ((format (gnu_printf, 2, 3))) |
|
361 |
-#else |
|
362 |
- __attribute__ ((format (__printf__, 2, 3))) |
|
363 |
-#endif |
|
364 |
-#endif |
|
365 |
- ; |
|
366 |
- |
|
367 | 328 |
#define COMPAT_FLAG_QUERY 0 /** compat_flags operator: Query for a flag */ |
368 | 329 |
#define COMPAT_FLAG_SET (1<<0) /** compat_flags operator: Set a compat flag */ |
369 | 330 |
#define COMPAT_NAMES (1<<1) /** compat flag: --compat-names set */ |
6 | 6 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,15 @@ |
0 |
+AUTOMAKE_OPTIONS = foreign |
|
1 |
+ |
|
2 |
+check_PROGRAMS = argv_testdriver |
|
3 |
+ |
|
4 |
+TESTS = $(check_PROGRAMS) |
|
5 |
+ |
|
6 |
+openvpn_srcdir = $(top_srcdir)/src/openvpn |
|
7 |
+compat_srcdir = $(top_srcdir)/src/compat |
|
8 |
+ |
|
9 |
+argv_testdriver_CFLAGS = @TEST_CFLAGS@ -I$(openvpn_srcdir) -I$(compat_srcdir) |
|
10 |
+argv_testdriver_LDFLAGS = @TEST_LDFLAGS@ -L$(openvpn_srcdir) -Wl,--wrap=parse_line |
|
11 |
+argv_testdriver_SOURCES = test_argv.c \ |
|
12 |
+ $(openvpn_srcdir)/platform.c \ |
|
13 |
+ $(openvpn_srcdir)/buffer.c \ |
|
14 |
+ $(openvpn_srcdir)/argv.c |
0 | 15 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,194 @@ |
0 |
+#include "config.h" |
|
1 |
+#include "syshead.h" |
|
2 |
+ |
|
3 |
+#include <stdio.h> |
|
4 |
+#include <unistd.h> |
|
5 |
+#include <stdlib.h> |
|
6 |
+#include <stdarg.h> |
|
7 |
+#include <string.h> |
|
8 |
+#include <setjmp.h> |
|
9 |
+#include <cmocka.h> |
|
10 |
+#include <assert.h> |
|
11 |
+ |
|
12 |
+#include "argv.h" |
|
13 |
+#include "buffer.h" |
|
14 |
+ |
|
15 |
+/* |
|
16 |
+ * Dummy symbols that need to be defined due to them being |
|
17 |
+ * referenced in #include'd header files and their includes |
|
18 |
+ */ |
|
19 |
+unsigned int x_debug_level; |
|
20 |
+bool dont_mute (unsigned int flags) { return true; } |
|
21 |
+void assert_failed (const char *filename, int line, const char *condition) { exit(0); } |
|
22 |
+void out_of_memory (void) { } |
|
23 |
+void x_msg (const unsigned int flags, const char *format, ...) { } |
|
24 |
+ |
|
25 |
+/* |
|
26 |
+ * This is defined here to prevent #include'ing misc.h |
|
27 |
+ * which makes things difficult beyond any recognition |
|
28 |
+ */ |
|
29 |
+size_t |
|
30 |
+adjust_power_of_2 (size_t u) |
|
31 |
+{ |
|
32 |
+ size_t ret = 1; |
|
33 |
+ |
|
34 |
+ while (ret < u) |
|
35 |
+ { |
|
36 |
+ ret <<= 1; |
|
37 |
+ assert (ret > 0); |
|
38 |
+ } |
|
39 |
+ |
|
40 |
+ return ret; |
|
41 |
+} |
|
42 |
+ |
|
43 |
+/* Defines for use in the tests and the mock parse_line() */ |
|
44 |
+#define PATH1 "/s p a c e" |
|
45 |
+#define PATH2 "/foo bar/baz" |
|
46 |
+#define PARAM1 "param1" |
|
47 |
+#define PARAM2 "param two" |
|
48 |
+#define SCRIPT_CMD "\"" PATH1 PATH2 "\"" PARAM1 "\"" PARAM2 "\"" |
|
49 |
+ |
|
50 |
+int |
|
51 |
+__wrap_parse_line (const char *line, char **p, const int n, const char *file, |
|
52 |
+ const int line_num, int msglevel, struct gc_arena *gc) |
|
53 |
+{ |
|
54 |
+ p[0] = PATH1 PATH2; |
|
55 |
+ p[1] = PARAM1; |
|
56 |
+ p[2] = PARAM2; |
|
57 |
+ return 3; |
|
58 |
+} |
|
59 |
+ |
|
60 |
+static void |
|
61 |
+argv_printf__multiple_spaces_in_format__parsed_as_one (void **state) |
|
62 |
+{ |
|
63 |
+ struct argv a = argv_new (); |
|
64 |
+ |
|
65 |
+ argv_printf (&a, " %s %s %d ", PATH1, PATH2, 42); |
|
66 |
+ assert_int_equal (a.argc, 3); |
|
67 |
+ |
|
68 |
+ argv_reset (&a); |
|
69 |
+} |
|
70 |
+ |
|
71 |
+static void |
|
72 |
+argv_printf_cat__multiple_spaces_in_format__parsed_as_one (void **state) |
|
73 |
+{ |
|
74 |
+ struct argv a = argv_new (); |
|
75 |
+ |
|
76 |
+ argv_printf (&a, "%s ", PATH1); |
|
77 |
+ argv_printf_cat (&a, " %s %s", PATH2, PARAM1); |
|
78 |
+ assert_int_equal (a.argc, 3); |
|
79 |
+ |
|
80 |
+ argv_reset (&a); |
|
81 |
+} |
|
82 |
+ |
|
83 |
+static void |
|
84 |
+argv_printf__combined_path_with_spaces__argc_correct (void **state) |
|
85 |
+{ |
|
86 |
+ struct argv a = argv_new (); |
|
87 |
+ |
|
88 |
+ argv_printf (&a, "%s%sc", PATH1, PATH2); |
|
89 |
+ assert_int_equal (a.argc, 1); |
|
90 |
+ |
|
91 |
+ argv_printf (&a, "%s%sc %d", PATH1, PATH2, 42); |
|
92 |
+ assert_int_equal (a.argc, 2); |
|
93 |
+ |
|
94 |
+ argv_printf (&a, "foo %s%sc %s x y", PATH2, PATH1, "foo"); |
|
95 |
+ assert_int_equal (a.argc, 5); |
|
96 |
+ |
|
97 |
+ argv_reset (&a); |
|
98 |
+} |
|
99 |
+ |
|
100 |
+static void |
|
101 |
+argv_printf__script_command__argc_correct (void **state) |
|
102 |
+{ |
|
103 |
+ struct argv a = argv_new (); |
|
104 |
+ |
|
105 |
+ argv_printf (&a, "%sc", SCRIPT_CMD); |
|
106 |
+ assert_int_equal (a.argc, 3); |
|
107 |
+ |
|
108 |
+ argv_printf (&a, "bar baz %sc %d %s", SCRIPT_CMD, 42, PATH1); |
|
109 |
+ assert_int_equal (a.argc, 7); |
|
110 |
+ |
|
111 |
+ argv_reset (&a); |
|
112 |
+} |
|
113 |
+ |
|
114 |
+static void |
|
115 |
+argv_printf_cat__used_twice__argc_correct (void **state) |
|
116 |
+{ |
|
117 |
+ struct argv a = argv_new (); |
|
118 |
+ |
|
119 |
+ argv_printf (&a, "%s %s %s", PATH1, PATH2, PARAM1); |
|
120 |
+ argv_printf_cat (&a, "%s", PARAM2); |
|
121 |
+ argv_printf_cat (&a, "foo"); |
|
122 |
+ assert_int_equal (a.argc, 5); |
|
123 |
+ |
|
124 |
+ argv_reset (&a); |
|
125 |
+} |
|
126 |
+ |
|
127 |
+static void |
|
128 |
+argv_str__multiple_argv__correct_output (void **state) |
|
129 |
+{ |
|
130 |
+ struct argv a = argv_new (); |
|
131 |
+ struct gc_arena gc = gc_new (); |
|
132 |
+ const char *output; |
|
133 |
+ |
|
134 |
+ argv_printf (&a, "%s%sc", PATH1, PATH2); |
|
135 |
+ argv_printf_cat (&a, "%s", PARAM1); |
|
136 |
+ argv_printf_cat (&a, "%s", PARAM2); |
|
137 |
+ output = argv_str (&a, &gc, PA_BRACKET); |
|
138 |
+ assert_string_equal (output, "[" PATH1 PATH2 "] [" PARAM1 "] [" PARAM2 "]"); |
|
139 |
+ |
|
140 |
+ argv_reset (&a); |
|
141 |
+ gc_free (&gc); |
|
142 |
+} |
|
143 |
+ |
|
144 |
+static void |
|
145 |
+argv_insert_head__empty_argv__head_only (void **state) |
|
146 |
+{ |
|
147 |
+ struct argv a = argv_new (); |
|
148 |
+ struct argv b; |
|
149 |
+ |
|
150 |
+ b = argv_insert_head (&a, PATH1); |
|
151 |
+ assert_int_equal (b.argc, 1); |
|
152 |
+ assert_string_equal (b.argv[0], PATH1); |
|
153 |
+ argv_reset (&b); |
|
154 |
+ |
|
155 |
+ argv_reset (&a); |
|
156 |
+} |
|
157 |
+ |
|
158 |
+static void |
|
159 |
+argv_insert_head__non_empty_argv__head_added (void **state) |
|
160 |
+{ |
|
161 |
+ struct argv a = argv_new (); |
|
162 |
+ struct argv b; |
|
163 |
+ int i; |
|
164 |
+ |
|
165 |
+ argv_printf (&a, "%s", PATH2); |
|
166 |
+ b = argv_insert_head (&a, PATH1); |
|
167 |
+ assert_int_equal (b.argc, a.argc + 1); |
|
168 |
+ for (i = 0; i < b.argc; i++) { |
|
169 |
+ if (i == 0) |
|
170 |
+ assert_string_equal (b.argv[i], PATH1); |
|
171 |
+ else |
|
172 |
+ assert_string_equal (b.argv[i], a.argv[i - 1]); |
|
173 |
+ } |
|
174 |
+ argv_reset (&b); |
|
175 |
+ |
|
176 |
+ argv_reset (&a); |
|
177 |
+} |
|
178 |
+ |
|
179 |
+int |
|
180 |
+main(void) |
|
181 |
+{ |
|
182 |
+ const struct CMUnitTest tests[] = { |
|
183 |
+ cmocka_unit_test (argv_printf__multiple_spaces_in_format__parsed_as_one), |
|
184 |
+ cmocka_unit_test (argv_printf_cat__multiple_spaces_in_format__parsed_as_one), |
|
185 |
+ cmocka_unit_test (argv_printf__combined_path_with_spaces__argc_correct), |
|
186 |
+ cmocka_unit_test (argv_printf__script_command__argc_correct), |
|
187 |
+ cmocka_unit_test (argv_printf_cat__used_twice__argc_correct), |
|
188 |
+ cmocka_unit_test (argv_str__multiple_argv__correct_output), |
|
189 |
+ cmocka_unit_test (argv_insert_head__non_empty_argv__head_added), |
|
190 |
+ }; |
|
191 |
+ |
|
192 |
+ return cmocka_run_group_tests_name ("argv", tests, NULL, NULL); |
|
193 |
+} |