Commit | Line | Data |
---|---|---|
62402cb1 MP |
1 | /* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING |
2 | file accompanying popt source distributions, available from | |
3 | ftp://ftp.redhat.com/pub/code/popt */ | |
4 | ||
5 | #ifdef HAVE_CONFIG_H | |
6 | #include "config.h" | |
7 | #endif | |
8 | ||
9 | #include <ctype.h> | |
10 | #include <stdlib.h> | |
11 | #include <string.h> | |
12 | ||
13 | #include "popt.h" | |
14 | ||
15 | int poptParseArgvString(char * s, int * argcPtr, char *** argvPtr) { | |
16 | char * buf = strcpy(alloca(strlen(s) + 1), s); | |
17 | char * bufStart = buf; | |
18 | char * src, * dst; | |
19 | char quote = '\0'; | |
20 | int argvAlloced = 5; | |
21 | char ** argv = malloc(sizeof(*argv) * argvAlloced); | |
22 | char ** argv2; | |
23 | int argc = 0; | |
24 | int i; | |
25 | ||
26 | src = s; | |
27 | dst = buf; | |
28 | argv[argc] = buf; | |
29 | ||
30 | memset(buf, '\0', strlen(s) + 1); | |
31 | ||
32 | while (*src) { | |
33 | if (quote == *src) { | |
34 | quote = '\0'; | |
35 | } else if (quote) { | |
36 | if (*src == '\\') { | |
37 | src++; | |
38 | if (!*src) { | |
39 | free(argv); | |
40 | return POPT_ERROR_BADQUOTE; | |
41 | } | |
42 | if (*src != quote) *buf++ = '\\'; | |
43 | } | |
44 | *buf++ = *src; | |
45 | } else if (isspace(*src)) { | |
46 | if (*argv[argc]) { | |
47 | buf++, argc++; | |
48 | if (argc == argvAlloced) { | |
49 | argvAlloced += 5; | |
50 | argv = realloc(argv, sizeof(*argv) * argvAlloced); | |
51 | } | |
52 | argv[argc] = buf; | |
53 | } | |
54 | } else switch (*src) { | |
55 | case '"': | |
56 | case '\'': | |
57 | quote = *src; | |
58 | break; | |
59 | case '\\': | |
60 | src++; | |
61 | if (!*src) { | |
62 | free(argv); | |
63 | return POPT_ERROR_BADQUOTE; | |
64 | } | |
65 | /* fallthrough */ | |
66 | default: | |
67 | *buf++ = *src; | |
68 | } | |
69 | ||
70 | src++; | |
71 | } | |
72 | ||
73 | if (strlen(argv[argc])) { | |
74 | argc++, buf++; | |
75 | } | |
76 | ||
77 | dst = malloc(argc * sizeof(*argv) + (buf - bufStart)); | |
78 | argv2 = (void *) dst; | |
79 | dst += argc * sizeof(*argv); | |
80 | memcpy(argv2, argv, argc * sizeof(*argv)); | |
81 | memcpy(dst, bufStart, buf - bufStart); | |
82 | ||
83 | for (i = 0; i < argc; i++) { | |
84 | argv2[i] = dst + (argv[i] - bufStart); | |
85 | } | |
86 | ||
87 | free(argv); | |
88 | ||
89 | *argvPtr = argv2; | |
90 | *argcPtr = argc; | |
91 | ||
92 | return 0; | |
93 | } |