env.c 7.0 KB

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