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