source: lib/libvarnish/argv.c @ 22edaa

Revision 22edaa, 4.8 KB checked in by Dag Erling Smørgrav <des@…>, 6 years ago (diff)

Revert r3072, which was a no-op.
Add "config.h" where it's missing.

git-svn-id:  http://www.varnish-cache.org/svn/trunk/varnish-cache@3336 d4fa192b-c00b-0410-8231-f00ffab90ce4

  • Property mode set to 100644
Line 
1/*-
2 * Copyright (c) 2006 Verdens Gang AS
3 * Copyright (c) 2006-2008 Linpro AS
4 * All rights reserved.
5 *
6 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Id$
30 *
31 * const char **ParseArgv(const char *s, int comment)
32 *      Parse a command like line into an argv[]
33 *      Index zero contains NULL or an error message
34 *      "double quotes" and backslash substitution is handled.
35 *
36 * void FreeArgv(const char **argv)
37 *      Free the result of ParseArgv()
38 *
39 */
40
41#include "config.h"
42
43#include <ctype.h>
44#include <stdlib.h>
45#include <stdio.h>
46#include <stdint.h>
47
48#include "libvarnish.h"
49
50static int
51BackSlash(const char *s, char *res)
52{
53        int r;
54        char c;
55        unsigned u;
56
57        assert(*s == '\\');
58        r = c = 0;
59        switch(s[1]) {
60        case 'n':
61                c = '\n';
62                r = 2;
63                break;
64        case 'r':
65                c = '\r';
66                r = 2;
67                break;
68        case 't':
69                c = '\t';
70                r = 2;
71                break;
72        case '"':
73                c = '"';
74                r = 2;
75                break;
76        case '\\':
77                c = '\\';
78                r = 2;
79                break;
80        case '0': case '1': case '2': case '3':
81        case '4': case '5': case '6': case '7':
82                for (r = 1; r < 4; r++) {
83                        if (!isdigit(s[r]))
84                                break;
85                        if (s[r] - '0' > 7)
86                                break;
87                        c <<= 3;        /*lint !e701 signed left shift */
88                        c |= s[r] - '0';
89                }
90                break;
91        case 'x':
92                if (1 == sscanf(s + 1, "x%02x", &u)) {
93                        assert(!(u & ~0xff));
94                        c = u;  /*lint !e734 loss of precision */
95                        r = 4;
96                }
97                break;
98        default:
99                break;
100        }
101        if (res != NULL)
102                *res = c;
103        return (r);
104}
105
106static char *
107BackSlashDecode(const char *s, const char *e)
108{
109        const char *q;
110        char *p, *r;
111        int i;
112
113        p = calloc((e - s) + 1, 1);
114        if (p == NULL)
115                return (p);
116        for (r = p, q = s; q < e; ) {
117                if (*q != '\\') {
118                        *r++ = *q++;
119                        continue;
120                }
121                i = BackSlash(q, r);
122                q += i;
123                r++;
124        }
125        *r = '\0';
126        return (p);
127}
128
129static char err_invalid_backslash[] = "Invalid backslash sequence";
130static char err_missing_quote[] = "Missing '\"'";
131
132char **
133ParseArgv(const char *s, int flag)
134{
135        char **argv;
136        const char *p;
137        int nargv, largv;
138        int i, quote;
139
140        assert(s != NULL);
141        nargv = 1;
142        largv = 16;
143        argv = calloc(sizeof *argv, largv);
144        if (argv == NULL)
145                return (NULL);
146
147        for (;;) {
148                if (*s == '\0')
149                        break;
150                if (isspace(*s)) {
151                        s++;
152                        continue;
153                }
154                if ((flag & ARGV_COMMENT) && *s == '#')
155                        break;
156                if (*s == '"') {
157                        p = ++s;
158                        quote = 1;
159                } else {
160                        p = s;
161                        quote = 0;
162                }
163                while (1) {
164                        if (*s == '\\') {
165                                i = BackSlash(s, NULL);
166                                if (i == 0) {
167                                        argv[0] = err_invalid_backslash;
168                                        return (argv);
169                                }
170                                s += i;
171                                continue;
172                        }
173                        if (!quote) {
174                                if (*s == '\0' || isspace(*s))
175                                        break;
176                                if ((flag & ARGV_COMMA) && *s == ',')
177                                        break;
178                                s++;
179                                continue;
180                        }
181                        if (*s == '"')
182                                break;
183                        if (*s == '\0') {
184                                argv[0] = err_missing_quote;
185                                return (argv);
186                        }
187                        s++;
188                }
189                if (nargv + 1 >= largv) {
190                        argv = realloc(argv, sizeof (*argv) * (largv += largv));
191                        assert(argv != NULL);
192                }
193                argv[nargv++] = BackSlashDecode(p, s);
194                if (*s != '\0')
195                        s++;
196        }
197        argv[nargv++] = NULL;
198        return (argv);
199}
200
201void
202FreeArgv(char **argv)
203{
204        int i;
205
206        for (i = 1; argv[i] != NULL; i++)
207                free(argv[i]);
208        free(argv);
209}
210
211#ifdef TESTPROG
212
213#include <printf.h>
214
215static void
216PrintArgv(char **argv)
217{
218        int i;
219
220        printf("---- %p\n", argv);
221        if (argv[0] != NULL)
222                printf("err %V\n", argv[0]);
223        for (i = 1; argv[i] != NULL; i++)
224                printf("%3d %V\n", i, argv[i]);
225}
226
227static void
228Test(const char *str)
229{
230        char **av;
231
232        printf("Test: <%V>\n", str);
233        av = ParseArgv(str, 0);
234        PrintArgv(av);
235}
236
237int
238main(int argc, char **argv)
239{
240        char buf[BUFSIZ];
241
242        (void)argc;
243        (void)argv;
244
245        register_printf_render_std("V");
246
247        while (fgets(buf, sizeof buf, stdin))
248                Test(buf);
249
250        return (0);
251}
252#endif
Note: See TracBrowser for help on using the repository browser.