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 | ||
b348deae | 5 | #include "system.h" |
62402cb1 | 6 | |
b348deae | 7 | #define POPT_ARGV_ARRAY_GROW_DELTA 5 |
62402cb1 | 8 | |
b348deae MP |
9 | int poptDupArgv(int argc, const char **argv, |
10 | int * argcPtr, const char *** argvPtr) | |
11 | { | |
12 | size_t nb = (argc + 1) * sizeof(*argv); | |
13 | const char ** argv2; | |
14 | char * dst; | |
15 | int i; | |
16 | ||
17 | for (i = 0; i < argc; i++) { | |
18 | if (argv[i] == NULL) | |
19 | return POPT_ERROR_NOARG; | |
20 | nb += strlen(argv[i]) + 1; | |
21 | } | |
22 | ||
23 | dst = malloc(nb); | |
24 | argv2 = (void *) dst; | |
25 | dst += (argc + 1) * sizeof(*argv); | |
26 | ||
27 | for (i = 0; i < argc; i++) { | |
28 | argv2[i] = dst; | |
29 | dst += strlen(strcpy(dst, argv[i])) + 1; | |
30 | } | |
31 | argv2[argc] = NULL; | |
32 | ||
33 | *argvPtr = argv2; | |
34 | *argcPtr = argc; | |
35 | return 0; | |
36 | } | |
62402cb1 | 37 | |
b348deae MP |
38 | int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr) |
39 | { | |
40 | const char * src; | |
62402cb1 | 41 | char quote = '\0'; |
b348deae MP |
42 | int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA; |
43 | const char ** argv = malloc(sizeof(*argv) * argvAlloced); | |
62402cb1 | 44 | int argc = 0; |
b348deae MP |
45 | int buflen = strlen(s) + 1; |
46 | char * buf = memset(alloca(buflen), 0, buflen); | |
62402cb1 | 47 | |
62402cb1 MP |
48 | argv[argc] = buf; |
49 | ||
b348deae | 50 | for (src = s; *src; src++) { |
62402cb1 MP |
51 | if (quote == *src) { |
52 | quote = '\0'; | |
53 | } else if (quote) { | |
54 | if (*src == '\\') { | |
55 | src++; | |
56 | if (!*src) { | |
57 | free(argv); | |
58 | return POPT_ERROR_BADQUOTE; | |
59 | } | |
60 | if (*src != quote) *buf++ = '\\'; | |
61 | } | |
62 | *buf++ = *src; | |
63 | } else if (isspace(*src)) { | |
64 | if (*argv[argc]) { | |
65 | buf++, argc++; | |
66 | if (argc == argvAlloced) { | |
b348deae | 67 | argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA; |
62402cb1 MP |
68 | argv = realloc(argv, sizeof(*argv) * argvAlloced); |
69 | } | |
70 | argv[argc] = buf; | |
71 | } | |
72 | } else switch (*src) { | |
73 | case '"': | |
74 | case '\'': | |
75 | quote = *src; | |
76 | break; | |
77 | case '\\': | |
78 | src++; | |
79 | if (!*src) { | |
80 | free(argv); | |
81 | return POPT_ERROR_BADQUOTE; | |
82 | } | |
b348deae | 83 | /*@fallthrough@*/ |
62402cb1 MP |
84 | default: |
85 | *buf++ = *src; | |
b348deae | 86 | break; |
62402cb1 | 87 | } |
62402cb1 MP |
88 | } |
89 | ||
90 | if (strlen(argv[argc])) { | |
91 | argc++, buf++; | |
92 | } | |
93 | ||
b348deae | 94 | (void) poptDupArgv(argc, argv, argcPtr, argvPtr); |
62402cb1 MP |
95 | |
96 | free(argv); | |
97 | ||
62402cb1 MP |
98 | return 0; |
99 | } |