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