poptparse.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /** \ingroup popt
  2. * \file popt/poptparse.c
  3. */
  4. /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
  5. file accompanying popt source distributions, available from
  6. ftp://ftp.rpm.org/pub/rpm/dist. */
  7. #include "system.h"
  8. #define POPT_ARGV_ARRAY_GROW_DELTA 5
  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. if (argc <= 0 || argv == NULL) /* XXX can't happen */
  17. return POPT_ERROR_NOARG;
  18. for (i = 0; i < argc; i++) {
  19. if (argv[i] == NULL)
  20. return POPT_ERROR_NOARG;
  21. nb += strlen(argv[i]) + 1;
  22. }
  23. dst = malloc(nb);
  24. if (dst == NULL) /* XXX can't happen */
  25. return POPT_ERROR_MALLOC;
  26. argv2 = (void *) dst;
  27. dst += (argc + 1) * sizeof(*argv);
  28. *dst = '\0';
  29. for (i = 0; i < argc; i++) {
  30. argv2[i] = dst;
  31. dst = stpcpy(dst, argv[i]);
  32. dst++; /* trailing NUL */
  33. }
  34. argv2[argc] = NULL;
  35. if (argvPtr) {
  36. *argvPtr = argv2;
  37. } else {
  38. free(argv2);
  39. argv2 = NULL;
  40. }
  41. if (argcPtr)
  42. *argcPtr = argc;
  43. return 0;
  44. }
  45. int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
  46. {
  47. const char * src;
  48. char quote = '\0';
  49. int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
  50. const char ** argv = malloc(sizeof(*argv) * argvAlloced);
  51. int argc = 0;
  52. size_t buflen = strlen(s) + 1;
  53. char * buf, * bufOrig = NULL;
  54. int rc = POPT_ERROR_MALLOC;
  55. if (argv == NULL) return rc;
  56. buf = bufOrig = calloc((size_t)1, buflen);
  57. if (buf == NULL) {
  58. free(argv);
  59. return rc;
  60. }
  61. argv[argc] = buf;
  62. for (src = s; *src != '\0'; src++) {
  63. if (quote == *src) {
  64. quote = '\0';
  65. } else if (quote != '\0') {
  66. if (*src == '\\') {
  67. src++;
  68. if (!*src) {
  69. rc = POPT_ERROR_BADQUOTE;
  70. goto exit;
  71. }
  72. if (*src != quote) *buf++ = '\\';
  73. }
  74. *buf++ = *src;
  75. } else if (_isspaceptr(src)) {
  76. if (*argv[argc] != '\0') {
  77. buf++, argc++;
  78. if (argc == argvAlloced) {
  79. argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
  80. argv = realloc(argv, sizeof(*argv) * argvAlloced);
  81. if (argv == NULL) goto exit;
  82. }
  83. argv[argc] = buf;
  84. }
  85. } else switch (*src) {
  86. case '"':
  87. case '\'':
  88. quote = *src;
  89. /*@switchbreak@*/ break;
  90. case '\\':
  91. src++;
  92. if (!*src) {
  93. rc = POPT_ERROR_BADQUOTE;
  94. goto exit;
  95. }
  96. /*@fallthrough@*/
  97. default:
  98. *buf++ = *src;
  99. /*@switchbreak@*/ break;
  100. }
  101. }
  102. if (strlen(argv[argc])) {
  103. argc++, buf++;
  104. }
  105. rc = poptDupArgv(argc, argv, argcPtr, argvPtr);
  106. exit:
  107. if (bufOrig) free(bufOrig);
  108. if (argv) free(argv);
  109. return rc;
  110. }
  111. /* still in the dev stage.
  112. * return values, perhaps 1== file erro
  113. * 2== line to long
  114. * 3== umm.... more?
  115. */
  116. int poptConfigFileToString(FILE *fp, char ** argstrp,
  117. /*@unused@*/ UNUSED(int flags))
  118. {
  119. char line[999];
  120. char * argstr;
  121. char * p;
  122. char * q;
  123. char * x;
  124. size_t t;
  125. size_t argvlen = 0;
  126. size_t maxlinelen = sizeof(line);
  127. size_t linelen;
  128. size_t maxargvlen = (size_t)480;
  129. *argstrp = NULL;
  130. /* | this_is = our_line
  131. * p q x
  132. */
  133. if (fp == NULL)
  134. return POPT_ERROR_NULLARG;
  135. argstr = calloc(maxargvlen, sizeof(*argstr));
  136. if (argstr == NULL) return POPT_ERROR_MALLOC;
  137. while (fgets(line, (int)maxlinelen, fp) != NULL) {
  138. p = line;
  139. /* loop until first non-space char or EOL */
  140. while( *p != '\0' && _isspaceptr(p) )
  141. p++;
  142. linelen = strlen(p);
  143. if (linelen >= maxlinelen-1) {
  144. free(argstr);
  145. return POPT_ERROR_OVERFLOW; /* XXX line too long */
  146. }
  147. if (*p == '\0' || *p == '\n') continue; /* line is empty */
  148. if (*p == '#') continue; /* comment line */
  149. q = p;
  150. while (*q != '\0' && (!_isspaceptr(q)) && *q != '=')
  151. q++;
  152. if (_isspaceptr(q)) {
  153. /* a space after the name, find next non space */
  154. *q++='\0';
  155. while( *q != '\0' && _isspaceptr(q) ) q++;
  156. }
  157. if (*q == '\0') {
  158. /* single command line option (ie, no name=val, just name) */
  159. q[-1] = '\0'; /* kill off newline from fgets() call */
  160. argvlen += (t = (size_t)(q - p)) + (sizeof(" --")-1);
  161. if (argvlen >= maxargvlen) {
  162. maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
  163. argstr = realloc(argstr, maxargvlen);
  164. if (argstr == NULL) return POPT_ERROR_MALLOC;
  165. }
  166. strcat(argstr, " --");
  167. strcat(argstr, p);
  168. continue;
  169. }
  170. if (*q != '=')
  171. continue; /* XXX for now, silently ignore bogus line */
  172. /* *q is an equal sign. */
  173. *q++ = '\0';
  174. /* find next non-space letter of value */
  175. while (*q != '\0' && _isspaceptr(q))
  176. q++;
  177. if (*q == '\0')
  178. continue; /* XXX silently ignore missing value */
  179. /* now, loop and strip all ending whitespace */
  180. x = p + linelen;
  181. while (_isspaceptr(--x))
  182. *x = '\0'; /* null out last char if space (including fgets() NL) */
  183. /* rest of line accept */
  184. t = (size_t)(x - p);
  185. argvlen += t + (sizeof("' --='")-1);
  186. if (argvlen >= maxargvlen) {
  187. maxargvlen = (t > maxargvlen) ? t*2 : maxargvlen*2;
  188. argstr = realloc(argstr, maxargvlen);
  189. if (argstr == NULL) return POPT_ERROR_MALLOC;
  190. }
  191. strcat(argstr, " --");
  192. strcat(argstr, p);
  193. strcat(argstr, "=\"");
  194. strcat(argstr, q);
  195. strcat(argstr, "\"");
  196. }
  197. *argstrp = argstr;
  198. return 0;
  199. }