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#include "system.h"
6
7#define POPT_ARGV_ARRAY_GROW_DELTA 5
8
9int 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}
37
38int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
39{
40    const char * src;
41    char quote = '\0';
42    int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
43    const char ** argv = malloc(sizeof(*argv) * argvAlloced);
44    int argc = 0;
45    int buflen = strlen(s) + 1;
46    char *buf0 = calloc(buflen, 1);
47    char *buf = buf0;
48
49    argv[argc] = buf;
50
51    for (src = s; *src; src++) {
52	if (quote == *src) {
53	    quote = '\0';
54	} else if (quote) {
55	    if (*src == '\\') {
56		src++;
57		if (!*src) {
58		    free(argv);
59		    free(buf0);
60		    return POPT_ERROR_BADQUOTE;
61		}
62		if (*src != quote) *buf++ = '\\';
63	    }
64	    *buf++ = *src;
65	} else if (isspace(*src)) {
66	    if (*argv[argc]) {
67		buf++, argc++;
68		if (argc == argvAlloced) {
69		    argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
70		    argv = realloc(argv, sizeof(*argv) * argvAlloced);
71		}
72		argv[argc] = buf;
73	    }
74	} else switch (*src) {
75	  case '"':
76	  case '\'':
77	    quote = *src;
78	    break;
79	  case '\\':
80	    src++;
81	    if (!*src) {
82		free(argv);
83		free(buf0);
84		return POPT_ERROR_BADQUOTE;
85	    }
86	    /*@fallthrough@*/
87	  default:
88	    *buf++ = *src;
89	    break;
90	}
91    }
92
93    if (strlen(argv[argc])) {
94	argc++, buf++;
95    }
96
97    (void) poptDupArgv(argc, argv, argcPtr, argvPtr);
98
99    free(argv);
100    free(buf0);
101    return 0;
102}
103