popt 1.13
|
00001 00005 /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING 00006 file accompanying popt source distributions, available from 00007 ftp://ftp.rpm.org/pub/rpm/dist. */ 00008 00009 #include "system.h" 00010 00011 #define POPT_ARGV_ARRAY_GROW_DELTA 5 00012 00013 int poptDupArgv(int argc, const char **argv, 00014 int * argcPtr, const char *** argvPtr) 00015 { 00016 size_t nb = (argc + 1) * sizeof(*argv); 00017 const char ** argv2; 00018 char * dst; 00019 int i; 00020 00021 if (argc <= 0 || argv == NULL) /* XXX can't happen */ 00022 return POPT_ERROR_NOARG; 00023 for (i = 0; i < argc; i++) { 00024 if (argv[i] == NULL) 00025 return POPT_ERROR_NOARG; 00026 nb += strlen(argv[i]) + 1; 00027 } 00028 00029 dst = malloc(nb); 00030 if (dst == NULL) /* XXX can't happen */ 00031 return POPT_ERROR_MALLOC; 00032 argv2 = (void *) dst; 00033 dst += (argc + 1) * sizeof(*argv); 00034 00035 for (i = 0; i < argc; i++) { 00036 argv2[i] = dst; 00037 dst += strlen(strcpy(dst, argv[i])) + 1; 00038 } 00039 argv2[argc] = NULL; 00040 00041 if (argvPtr) { 00042 *argvPtr = argv2; 00043 } else { 00044 free(argv2); 00045 argv2 = NULL; 00046 } 00047 if (argcPtr) 00048 *argcPtr = argc; 00049 return 0; 00050 } 00051 00052 int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr) 00053 { 00054 const char * src; 00055 char quote = '\0'; 00056 int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA; 00057 const char ** argv = malloc(sizeof(*argv) * argvAlloced); 00058 int argc = 0; 00059 size_t buflen = strlen(s) + 1; 00060 char * buf, * bufOrig = NULL; 00061 int rc = POPT_ERROR_MALLOC; 00062 00063 if (argv == NULL) return rc; 00064 buf = bufOrig = calloc(1, buflen); 00065 if (buf == NULL) { 00066 free(argv); 00067 return rc; 00068 } 00069 argv[argc] = buf; 00070 00071 for (src = s; *src != '\0'; src++) { 00072 if (quote == *src) { 00073 quote = '\0'; 00074 } else if (quote != '\0') { 00075 if (*src == '\\') { 00076 src++; 00077 if (!*src) { 00078 rc = POPT_ERROR_BADQUOTE; 00079 goto exit; 00080 } 00081 if (*src != quote) *buf++ = '\\'; 00082 } 00083 *buf++ = *src; 00084 } else if (_isspaceptr(src)) { 00085 if (*argv[argc] != '\0') { 00086 buf++, argc++; 00087 if (argc == argvAlloced) { 00088 argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA; 00089 argv = realloc(argv, sizeof(*argv) * argvAlloced); 00090 if (argv == NULL) goto exit; 00091 } 00092 argv[argc] = buf; 00093 } 00094 } else switch (*src) { 00095 case '"': 00096 case '\'': 00097 quote = *src; 00098 /*@switchbreak@*/ break; 00099 case '\\': 00100 src++; 00101 if (!*src) { 00102 rc = POPT_ERROR_BADQUOTE; 00103 goto exit; 00104 } 00105 /*@fallthrough@*/ 00106 default: 00107 *buf++ = *src; 00108 /*@switchbreak@*/ break; 00109 } 00110 } 00111 00112 if (strlen(argv[argc])) { 00113 argc++, buf++; 00114 } 00115 00116 rc = poptDupArgv(argc, argv, argcPtr, argvPtr); 00117 00118 exit: 00119 if (bufOrig) free(bufOrig); 00120 if (argv) free(argv); 00121 return rc; 00122 } 00123 00124 /* still in the dev stage. 00125 * return values, perhaps 1== file erro 00126 * 2== line to long 00127 * 3== umm.... more? 00128 */ 00129 int poptConfigFileToString(FILE *fp, char ** argstrp, /*@unused@*/ int flags) 00130 { 00131 char line[999]; 00132 char * argstr; 00133 char * p; 00134 char * q; 00135 char * x; 00136 size_t t; 00137 size_t argvlen = 0; 00138 size_t maxlinelen = sizeof(line); 00139 size_t linelen; 00140 size_t maxargvlen = (size_t)480; 00141 00142 *argstrp = NULL; 00143 00144 /* | this_is = our_line 00145 * p q x 00146 */ 00147 00148 if (fp == NULL) 00149 return POPT_ERROR_NULLARG; 00150 00151 argstr = calloc(maxargvlen, sizeof(*argstr)); 00152 if (argstr == NULL) return POPT_ERROR_MALLOC; 00153 00154 while (fgets(line, (int)maxlinelen, fp) != NULL) { 00155 p = line; 00156 00157 /* loop until first non-space char or EOL */ 00158 while( *p != '\0' && _isspaceptr(p) ) 00159 p++; 00160 00161 linelen = strlen(p); 00162 if (linelen >= maxlinelen-1) { 00163 free(argstr); 00164 return POPT_ERROR_OVERFLOW; /* XXX line too long */ 00165 } 00166 00167 if (*p == '\0' || *p == '\n') continue; /* line is empty */ 00168 if (*p == '#') continue; /* comment line */ 00169 00170 q = p; 00171 00172 while (*q != '\0' && (!_isspaceptr(q)) && *q != '=') 00173 q++; 00174 00175 if (_isspaceptr(q)) { 00176 /* a space after the name, find next non space */ 00177 *q++='\0'; 00178 while( *q != '\0' && _isspaceptr(q) ) q++; 00179 } 00180 if (*q == '\0') { 00181 /* single command line option (ie, no name=val, just name) */ 00182 q[-1] = '\0'; /* kill off newline from fgets() call */ 00183 argvlen += (t = q - p) + (sizeof(" --")-1); 00184 if (argvlen >= maxargvlen) { 00185 maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2; 00186 argstr = realloc(argstr, maxargvlen); 00187 if (argstr == NULL) return POPT_ERROR_MALLOC; 00188 } 00189 strcat(argstr, " --"); 00190 strcat(argstr, p); 00191 continue; 00192 } 00193 if (*q != '=') 00194 continue; /* XXX for now, silently ignore bogus line */ 00195 00196 /* *q is an equal sign. */ 00197 *q++ = '\0'; 00198 00199 /* find next non-space letter of value */ 00200 while (*q != '\0' && _isspaceptr(q)) 00201 q++; 00202 if (*q == '\0') 00203 continue; /* XXX silently ignore missing value */ 00204 00205 /* now, loop and strip all ending whitespace */ 00206 x = p + linelen; 00207 while (_isspaceptr(--x)) 00208 *x = '\0'; /* null out last char if space (including fgets() NL) */ 00209 00210 /* rest of line accept */ 00211 t = x - p; 00212 argvlen += t + (sizeof("' --='")-1); 00213 if (argvlen >= maxargvlen) { 00214 maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2; 00215 argstr = realloc(argstr, maxargvlen); 00216 if (argstr == NULL) return POPT_ERROR_MALLOC; 00217 } 00218 strcat(argstr, " --"); 00219 strcat(argstr, p); 00220 strcat(argstr, "=\""); 00221 strcat(argstr, q); 00222 strcat(argstr, "\""); 00223 } 00224 00225 *argstrp = argstr; 00226 return 0; 00227 }