wordexp_stub.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /* Copyright 1995-1996 University Corporation for Atmospheric Research/Unidata
  2. *
  3. * Portions of this software were developed by the Unidata Program at the
  4. * University Corporation for Atmospheric Research.
  5. *
  6. * Access and use of this software shall impose the following obligations
  7. * and understandings on the user. The user is granted the right, without
  8. * any fee or cost, to use, copy, modify, alter, enhance and distribute
  9. * this software, and any derivative works thereof, and its supporting
  10. * documentation for any purpose whatsoever, provided that this entire
  11. * notice appears in all copies of the software, derivative works and
  12. * supporting documentation. Further, UCAR requests that the user credit
  13. * UCAR/Unidata in any publications that result from the use of this
  14. * software or in any product that includes this software. The names UCAR
  15. * and/or Unidata, however, may not be used in any advertising or publicity
  16. * to endorse or promote any products or commercial entity unless specific
  17. * written permission is obtained from UCAR/Unidata. The user also
  18. * understands that UCAR/Unidata is not obligated to provide the user with
  19. * any support, consulting, training or assistance of any kind with regard
  20. * to the use, operation and performance of this software nor to provide
  21. * the user with any updates, revisions, new versions or "bug fixes."
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
  24. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  25. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  26. * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
  27. * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
  28. * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  29. * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  30. * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
  31. */
  32. /* $Id: wordexp_stub.c,v 1.1 2001/03/08 16:49:37 andersen Exp $ */
  33. /*
  34. * Hack to provide POSIX 1003.2-1992 _interface_.
  35. * This version is NOT fully functional.
  36. *
  37. * This is a place holder till I can cut down the glibc version
  38. * or make it somewhat modular or something. -Erik
  39. */
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <ctype.h>
  43. #include <wordexp.h>
  44. /*
  45. * Translate return value from wordexp() into a string
  46. */
  47. const char *
  48. s_wrde_err(int wrde_err)
  49. {
  50. switch(wrde_err) {
  51. case 0: return "No Error";
  52. case WRDE_NOSPACE: return "WRDE_NOSPACE";
  53. case WRDE_BADCHAR: return "WRDE_BADCHAR";
  54. case WRDE_BADVAL: return "WRDE_BADVAL";
  55. case WRDE_CMDSUB: return "WRDE_CMDSUB";
  56. case WRDE_SYNTAX: return "WRDE_SYNTAX";
  57. }
  58. /* default */
  59. return "Unknown Error";
  60. }
  61. /*ARGSUSED*/
  62. int
  63. wordexp(const char *words, wordexp_t *pwordexp, int flags)
  64. {
  65. const char *ccp;
  66. char **argv;
  67. const char *buf;
  68. size_t argc;
  69. enum states {ARGSTART, IN_QUOTE, NOT_IN_QUOTE, DONE};
  70. enum classes {EOS, SPACE, QUOTE, OTHER};
  71. int state = ARGSTART;
  72. char *argbuf;
  73. const char *sp;
  74. char *dp;
  75. int status = 0;
  76. if(words == NULL || pwordexp == NULL)
  77. return 0;
  78. /* devour leading white space */
  79. for(ccp = words; *ccp != 0 && isspace(*ccp); ccp++)
  80. /*EMPTY*/;
  81. /* skip comments */
  82. if(*ccp == '#')
  83. {
  84. pwordexp->we_wordc = 0;
  85. pwordexp->we_wordv = NULL;
  86. return 0;
  87. }
  88. /* If every other character was a space ... */
  89. #define MAXNARGS(str) ((strlen(str) +1)/2 +1)
  90. argv = (char **)calloc(MAXNARGS(ccp), sizeof(char *));
  91. if(argv == NULL)
  92. return WRDE_NOSPACE;
  93. buf = ccp;
  94. argbuf = malloc(strlen(words)+1); /* where each arg is built */
  95. if (argbuf == NULL)
  96. {
  97. free(argv);
  98. return WRDE_NOSPACE;
  99. }
  100. sp = buf;
  101. dp = argbuf;
  102. argc = 0;
  103. while(state != DONE)
  104. {
  105. int class;
  106. if (*sp == 0)
  107. class = EOS;
  108. else if (isspace(*sp))
  109. class = SPACE;
  110. else if (*sp == '"')
  111. class = QUOTE;
  112. else
  113. class = OTHER;
  114. switch (state) {
  115. case ARGSTART:
  116. switch(class) {
  117. case EOS:
  118. state = DONE;
  119. break;
  120. case SPACE:
  121. sp++;
  122. break;
  123. case QUOTE:
  124. sp++;
  125. state = IN_QUOTE;
  126. break;
  127. case OTHER:
  128. *dp++ = *sp++;
  129. state = NOT_IN_QUOTE;
  130. break;
  131. }
  132. break;
  133. case IN_QUOTE:
  134. switch(class) {
  135. case EOS: /* unmatched quote */
  136. state = DONE;
  137. status = WRDE_SYNTAX;
  138. break;
  139. case QUOTE:
  140. sp++;
  141. state = NOT_IN_QUOTE;
  142. break;
  143. case SPACE:
  144. case OTHER:
  145. *dp++ = *sp++;
  146. break;
  147. }
  148. break;
  149. case NOT_IN_QUOTE:
  150. switch(class) {
  151. case EOS:
  152. *dp = 0;
  153. dp = argbuf;
  154. argv[argc++] = strdup(argbuf);
  155. state = DONE;
  156. break;
  157. case SPACE:
  158. *dp = 0;
  159. dp = argbuf;
  160. argv[argc++] = strdup(argbuf);
  161. sp++;
  162. state = ARGSTART;
  163. break;
  164. case QUOTE:
  165. sp++;
  166. state = IN_QUOTE;
  167. break;
  168. case OTHER:
  169. *dp++ = *sp++;
  170. break;
  171. }
  172. break;
  173. }
  174. }
  175. argv[argc] = NULL;
  176. pwordexp->we_wordc = argc;
  177. pwordexp->we_wordv = argv;
  178. free(argbuf);
  179. return status;
  180. }
  181. void
  182. wordfree(wordexp_t *pwordexp)
  183. {
  184. if(pwordexp == NULL || pwordexp->we_wordv == NULL)
  185. return;
  186. if(*pwordexp->we_wordv)
  187. free(*pwordexp->we_wordv);
  188. free(pwordexp->we_wordv);
  189. }
  190. #if TEST
  191. #include <stdio.h>
  192. #include <stdlib.h>
  193. #include <string.h>
  194. int
  195. main(int argc, char *argv[])
  196. {
  197. char strbuf[1024];
  198. wordexp_t wrdexp;
  199. int status;
  200. char **cpp;
  201. while(fgets(strbuf, sizeof(strbuf), stdin) != NULL)
  202. {
  203. {
  204. char *cp = strrchr(strbuf,'\n');
  205. if(cp)
  206. *cp = 0;
  207. }
  208. fprintf(stdout, "\t%s\n", strbuf);
  209. status = wordexp(strbuf, &wrdexp, WRDE_SHOWERR);
  210. if(status)
  211. {
  212. fprintf(stderr, "wordexp: %s\n", s_wrde_err(status));
  213. continue;
  214. }
  215. /* else */
  216. fprintf(stdout, "\t%d:\n", wrdexp.we_wordc);
  217. for(cpp = wrdexp.we_wordv;
  218. cpp < &wrdexp.we_wordv[wrdexp.we_wordc]; cpp++)
  219. {
  220. fprintf(stdout, "\t\t%s\n", *cpp);
  221. }
  222. wordfree(&wrdexp);
  223. }
  224. exit(EXIT_SUCCESS);
  225. }
  226. #endif /* TEST */