env.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /**
  2. * \file environment.c
  3. *
  4. * This file contains all of the routines that must be linked into
  5. * an executable to use the generated option processing. The optional
  6. * routines are in separately compiled modules so that they will not
  7. * necessarily be linked in.
  8. *
  9. * @addtogroup autoopts
  10. * @{
  11. */
  12. /*
  13. * This file is part of AutoOpts, a companion to AutoGen.
  14. * AutoOpts is free software.
  15. * AutoOpts is Copyright (C) 1992-2014 by Bruce Korb - all rights reserved
  16. *
  17. * AutoOpts is available under any one of two licenses. The license
  18. * in use must be one of these two and the choice is under the control
  19. * of the user of the license.
  20. *
  21. * The GNU Lesser General Public License, version 3 or later
  22. * See the files "COPYING.lgplv3" and "COPYING.gplv3"
  23. *
  24. * The Modified Berkeley Software Distribution License
  25. * See the file "COPYING.mbsd"
  26. *
  27. * These files have the following sha256 sums:
  28. *
  29. * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3
  30. * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3
  31. * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd
  32. */
  33. /* = = = START-STATIC-FORWARD = = = */
  34. static void
  35. do_env_opt(tOptState * os, char * env_name,
  36. tOptions * pOpts, teEnvPresetType type);
  37. /* = = = END-STATIC-FORWARD = = = */
  38. /*
  39. * doPrognameEnv - check for preset values from the ${PROGNAME}
  40. * environment variable. This is accomplished by parsing the text into
  41. * tokens, temporarily replacing the arg vector and calling
  42. * immediate_opts and/or regular_opts.
  43. */
  44. LOCAL void
  45. doPrognameEnv(tOptions * pOpts, teEnvPresetType type)
  46. {
  47. char const * env_opts = getenv(pOpts->pzPROGNAME);
  48. token_list_t* pTL;
  49. int sv_argc;
  50. proc_state_mask_t sv_flag;
  51. char ** sv_argv;
  52. /*
  53. * No such beast? Then bail now.
  54. */
  55. if (env_opts == NULL)
  56. return;
  57. /*
  58. * Tokenize the string. If there's nothing of interest, we'll bail
  59. * here immediately.
  60. */
  61. pTL = ao_string_tokenize(env_opts);
  62. if (pTL == NULL)
  63. return;
  64. /*
  65. * Substitute our $PROGNAME argument list for the real one
  66. */
  67. sv_argc = (int)pOpts->origArgCt;
  68. sv_argv = pOpts->origArgVect;
  69. sv_flag = pOpts->fOptSet;
  70. /*
  71. * We add a bogus pointer to the start of the list. The program name
  72. * has already been pulled from "argv", so it won't get dereferenced.
  73. * The option scanning code will skip the "program name" at the start
  74. * of this list of tokens, so we accommodate this way ....
  75. */
  76. {
  77. uintptr_t v = (uintptr_t)(pTL->tkn_list);
  78. pOpts->origArgVect = (void *)(v - sizeof(char *));
  79. }
  80. pOpts->origArgCt = (unsigned int)pTL->tkn_ct + 1;
  81. pOpts->fOptSet &= ~OPTPROC_ERRSTOP;
  82. pOpts->curOptIdx = 1;
  83. pOpts->pzCurOpt = NULL;
  84. switch (type) {
  85. case ENV_IMM:
  86. (void)immediate_opts(pOpts);
  87. break;
  88. case ENV_ALL:
  89. (void)immediate_opts(pOpts);
  90. pOpts->curOptIdx = 1;
  91. pOpts->pzCurOpt = NULL;
  92. /* FALLTHROUGH */
  93. case ENV_NON_IMM:
  94. (void)regular_opts(pOpts);
  95. }
  96. /*
  97. * Free up the temporary arg vector and restore the original program args.
  98. */
  99. free(pTL);
  100. pOpts->origArgVect = sv_argv;
  101. pOpts->origArgCt = (unsigned int)sv_argc;
  102. pOpts->fOptSet = sv_flag;
  103. }
  104. static void
  105. do_env_opt(tOptState * os, char * env_name,
  106. tOptions * pOpts, teEnvPresetType type)
  107. {
  108. os->pzOptArg = getenv(env_name);
  109. if (os->pzOptArg == NULL)
  110. return;
  111. os->flags = OPTST_PRESET | OPTST_ALLOC_ARG | os->pOD->fOptState;
  112. os->optType = TOPT_UNDEFINED;
  113. if ( (os->pOD->pz_DisablePfx != NULL)
  114. && (streqvcmp(os->pzOptArg, os->pOD->pz_DisablePfx) == 0)) {
  115. os->flags |= OPTST_DISABLED;
  116. os->pzOptArg = NULL;
  117. handle_opt(pOpts, os);
  118. return;
  119. }
  120. switch (type) {
  121. case ENV_IMM:
  122. /*
  123. * Process only immediate actions
  124. */
  125. if (DO_IMMEDIATELY(os->flags))
  126. break;
  127. return;
  128. case ENV_NON_IMM:
  129. /*
  130. * Process only NON immediate actions
  131. */
  132. if (DO_NORMALLY(os->flags) || DO_SECOND_TIME(os->flags))
  133. break;
  134. return;
  135. default: /* process everything */
  136. break;
  137. }
  138. /*
  139. * Make sure the option value string is persistent and consistent.
  140. *
  141. * The interpretation of the option value depends
  142. * on the type of value argument the option takes
  143. */
  144. if (OPTST_GET_ARGTYPE(os->pOD->fOptState) == OPARG_TYPE_NONE) {
  145. /*
  146. * Ignore any value.
  147. */
  148. os->pzOptArg = NULL;
  149. } else if (os->pzOptArg[0] == NUL) {
  150. /*
  151. * If the argument is the empty string and the argument is
  152. * optional, then treat it as if the option was not specified.
  153. */
  154. if ((os->pOD->fOptState & OPTST_ARG_OPTIONAL) == 0)
  155. return;
  156. os->pzOptArg = NULL;
  157. } else {
  158. AGDUPSTR(os->pzOptArg, os->pzOptArg, "option argument");
  159. os->flags |= OPTST_ALLOC_ARG;
  160. }
  161. handle_opt(pOpts, os);
  162. }
  163. /*
  164. * env_presets - check for preset values from the envrionment
  165. * This routine should process in all, immediate or normal modes....
  166. */
  167. LOCAL void
  168. env_presets(tOptions * pOpts, teEnvPresetType type)
  169. {
  170. int ct;
  171. tOptState st;
  172. char* pzFlagName;
  173. size_t spaceLeft;
  174. char zEnvName[ AO_NAME_SIZE ];
  175. /*
  176. * Finally, see if we are to look at the environment
  177. * variables for initial values.
  178. */
  179. if ((pOpts->fOptSet & OPTPROC_ENVIRON) == 0)
  180. return;
  181. doPrognameEnv(pOpts, type);
  182. ct = pOpts->presetOptCt;
  183. st.pOD = pOpts->pOptDesc;
  184. pzFlagName = zEnvName
  185. + snprintf(zEnvName, sizeof(zEnvName), "%s_", pOpts->pzPROGNAME);
  186. spaceLeft = AO_NAME_SIZE - (unsigned long)(pzFlagName - zEnvName) - 1;
  187. for (;ct-- > 0; st.pOD++) {
  188. size_t nln;
  189. /*
  190. * If presetting is disallowed, then skip this entry
  191. */
  192. if ( ((st.pOD->fOptState & OPTST_NO_INIT) != 0)
  193. || (st.pOD->optEquivIndex != NO_EQUIVALENT) )
  194. continue;
  195. /*
  196. * IF there is no such environment variable,
  197. * THEN skip this entry, too.
  198. */
  199. nln = strlen(st.pOD->pz_NAME) + 1;
  200. if (nln <= spaceLeft) {
  201. /*
  202. * Set up the option state
  203. */
  204. memcpy(pzFlagName, st.pOD->pz_NAME, nln);
  205. do_env_opt(&st, zEnvName, pOpts, type);
  206. }
  207. }
  208. /*
  209. * Special handling for ${PROGNAME_LOAD_OPTS}
  210. */
  211. if ( (pOpts->specOptIdx.save_opts != NO_EQUIVALENT)
  212. && (pOpts->specOptIdx.save_opts != 0)) {
  213. size_t nln;
  214. st.pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts + 1;
  215. if (st.pOD->pz_NAME == NULL)
  216. return;
  217. nln = strlen(st.pOD->pz_NAME) + 1;
  218. if (nln > spaceLeft)
  219. return;
  220. memcpy(pzFlagName, st.pOD->pz_NAME, nln);
  221. do_env_opt(&st, zEnvName, pOpts, type);
  222. }
  223. }
  224. /** @}
  225. *
  226. * Local Variables:
  227. * mode: C
  228. * c-file-style: "stroustrup"
  229. * indent-tabs-mode: nil
  230. * End:
  231. * end of autoopts/environment.c */