environment.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*
  2. * $Id: environment.c,v 4.13 2007/04/15 19:01:18 bkorb Exp $
  3. * Time-stamp: "2007-04-15 11:50:35 bkorb"
  4. *
  5. * This file contains all of the routines that must be linked into
  6. * an executable to use the generated option processing. The optional
  7. * routines are in separately compiled modules so that they will not
  8. * necessarily be linked in.
  9. */
  10. /*
  11. * Automated Options copyright 1992-2007 Bruce Korb
  12. *
  13. * Automated Options is free software.
  14. * You may redistribute it and/or modify it under the terms of the
  15. * GNU General Public License, as published by the Free Software
  16. * Foundation; either version 2, or (at your option) any later version.
  17. *
  18. * Automated Options is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with Automated Options. See the file "COPYING". If not,
  25. * write to: The Free Software Foundation, Inc.,
  26. * 51 Franklin Street, Fifth Floor,
  27. * Boston, MA 02110-1301, USA.
  28. *
  29. * As a special exception, Bruce Korb gives permission for additional
  30. * uses of the text contained in his release of AutoOpts.
  31. *
  32. * The exception is that, if you link the AutoOpts library with other
  33. * files to produce an executable, this does not by itself cause the
  34. * resulting executable to be covered by the GNU General Public License.
  35. * Your use of that executable is in no way restricted on account of
  36. * linking the AutoOpts library code into it.
  37. *
  38. * This exception does not however invalidate any other reasons why
  39. * the executable file might be covered by the GNU General Public License.
  40. *
  41. * This exception applies only to the code released by Bruce Korb under
  42. * the name AutoOpts. If you copy code from other sources under the
  43. * General Public License into a copy of AutoOpts, as the General Public
  44. * License permits, the exception does not apply to the code that you add
  45. * in this way. To avoid misleading anyone as to the status of such
  46. * modified files, you must delete this exception notice from them.
  47. *
  48. * If you write modifications of your own for AutoOpts, it is your choice
  49. * whether to permit this exception to apply to your modifications.
  50. * If you do not wish that, delete this exception notice.
  51. */
  52. /* = = = START-STATIC-FORWARD = = = */
  53. /* static forward declarations maintained by :mkfwd */
  54. static void
  55. checkEnvOpt(tOptState * os, char * env_name,
  56. tOptions* pOpts, teEnvPresetType type);
  57. /* = = = END-STATIC-FORWARD = = = */
  58. /*
  59. * doPrognameEnv - check for preset values from the ${PROGNAME}
  60. * environment variable. This is accomplished by parsing the text into
  61. * tokens, temporarily replacing the arg vector and calling
  62. * doImmediateOpts and/or doRegularOpts.
  63. */
  64. LOCAL void
  65. doPrognameEnv( tOptions* pOpts, teEnvPresetType type )
  66. {
  67. char const* pczOptStr = getenv( pOpts->pzPROGNAME );
  68. token_list_t* pTL;
  69. int sv_argc;
  70. tAoUI sv_flag;
  71. char** sv_argv;
  72. /*
  73. * IF there is no such environment variable
  74. * *or* there is, but we are doing immediate opts and there are
  75. * no immediate opts to do (--help inside $PROGNAME is silly,
  76. * but --no-load-defs is not, so that is marked)
  77. * THEN bail out now. (
  78. */
  79. if ( (pczOptStr == NULL)
  80. || ( (type == ENV_IMM)
  81. && ((pOpts->fOptSet & OPTPROC_HAS_IMMED) == 0) ) )
  82. return;
  83. /*
  84. * Tokenize the string. If there's nothing of interest, we'll bail
  85. * here immediately.
  86. */
  87. pTL = ao_string_tokenize( pczOptStr );
  88. if (pTL == NULL)
  89. return;
  90. /*
  91. * Substitute our $PROGNAME argument list for the real one
  92. */
  93. sv_argc = pOpts->origArgCt;
  94. sv_argv = pOpts->origArgVect;
  95. sv_flag = pOpts->fOptSet;
  96. /*
  97. * We add a bogus pointer to the start of the list. The program name
  98. * has already been pulled from "argv", so it won't get dereferenced.
  99. * The option scanning code will skip the "program name" at the start
  100. * of this list of tokens, so we accommodate this way ....
  101. */
  102. pOpts->origArgVect = (char**)(pTL->tkn_list - 1);
  103. pOpts->origArgCt = pTL->tkn_ct + 1;
  104. pOpts->fOptSet &= ~OPTPROC_ERRSTOP;
  105. pOpts->curOptIdx = 1;
  106. pOpts->pzCurOpt = NULL;
  107. switch (type) {
  108. case ENV_IMM:
  109. /*
  110. * We know the OPTPROC_HAS_IMMED bit is set.
  111. */
  112. (void)doImmediateOpts( pOpts );
  113. break;
  114. case ENV_NON_IMM:
  115. (void)doRegularOpts( pOpts );
  116. break;
  117. default:
  118. /*
  119. * Only to immediate opts if the OPTPROC_HAS_IMMED bit is set.
  120. */
  121. if (pOpts->fOptSet & OPTPROC_HAS_IMMED) {
  122. (void)doImmediateOpts( pOpts );
  123. pOpts->curOptIdx = 1;
  124. pOpts->pzCurOpt = NULL;
  125. }
  126. (void)doRegularOpts( pOpts );
  127. break;
  128. }
  129. /*
  130. * Free up the temporary arg vector and restore the original program args.
  131. */
  132. free( pTL );
  133. pOpts->origArgVect = sv_argv;
  134. pOpts->origArgCt = sv_argc;
  135. pOpts->fOptSet = sv_flag;
  136. }
  137. static void
  138. checkEnvOpt(tOptState * os, char * env_name,
  139. tOptions* pOpts, teEnvPresetType type)
  140. {
  141. os->pzOptArg = getenv( env_name );
  142. if (os->pzOptArg == NULL)
  143. return;
  144. os->flags = OPTST_PRESET | OPTST_ALLOC_ARG | os->pOD->fOptState;
  145. os->optType = TOPT_UNDEFINED;
  146. if ( (os->pOD->pz_DisablePfx != NULL)
  147. && (streqvcmp( os->pzOptArg, os->pOD->pz_DisablePfx ) == 0)) {
  148. os->flags |= OPTST_DISABLED;
  149. os->pzOptArg = NULL;
  150. }
  151. switch (type) {
  152. case ENV_IMM:
  153. /*
  154. * Process only immediate actions
  155. */
  156. if (DO_IMMEDIATELY(os->flags))
  157. break;
  158. return;
  159. case ENV_NON_IMM:
  160. /*
  161. * Process only NON immediate actions
  162. */
  163. if (DO_NORMALLY(os->flags) || DO_SECOND_TIME(os->flags))
  164. break;
  165. return;
  166. default: /* process everything */
  167. break;
  168. }
  169. /*
  170. * Make sure the option value string is persistent and consistent.
  171. *
  172. * The interpretation of the option value depends
  173. * on the type of value argument the option takes
  174. */
  175. if (os->pzOptArg != NULL) {
  176. if (OPTST_GET_ARGTYPE(os->pOD->fOptState) == OPARG_TYPE_NONE) {
  177. os->pzOptArg = NULL;
  178. } else if ( (os->pOD->fOptState & OPTST_ARG_OPTIONAL)
  179. && (*os->pzOptArg == NUL)) {
  180. os->pzOptArg = NULL;
  181. } else if (*os->pzOptArg == NUL) {
  182. os->pzOptArg = zNil;
  183. } else {
  184. AGDUPSTR( os->pzOptArg, os->pzOptArg, "option argument" );
  185. os->flags |= OPTST_ALLOC_ARG;
  186. }
  187. }
  188. handleOption( pOpts, os );
  189. }
  190. /*
  191. * doEnvPresets - check for preset values from the envrionment
  192. * This routine should process in all, immediate or normal modes....
  193. */
  194. LOCAL void
  195. doEnvPresets( tOptions* pOpts, teEnvPresetType type )
  196. {
  197. int ct;
  198. tOptState st;
  199. char* pzFlagName;
  200. size_t spaceLeft;
  201. char zEnvName[ AO_NAME_SIZE ];
  202. /*
  203. * Finally, see if we are to look at the environment
  204. * variables for initial values.
  205. */
  206. if ((pOpts->fOptSet & OPTPROC_ENVIRON) == 0)
  207. return;
  208. doPrognameEnv( pOpts, type );
  209. ct = pOpts->presetOptCt;
  210. st.pOD = pOpts->pOptDesc;
  211. pzFlagName = zEnvName
  212. + snprintf( zEnvName, sizeof( zEnvName ), "%s_", pOpts->pzPROGNAME );
  213. spaceLeft = AO_NAME_SIZE - (pzFlagName - zEnvName) - 1;
  214. for (;ct-- > 0; st.pOD++) {
  215. /*
  216. * If presetting is disallowed, then skip this entry
  217. */
  218. if ( ((st.pOD->fOptState & OPTST_NO_INIT) != 0)
  219. || (st.pOD->optEquivIndex != NO_EQUIVALENT) )
  220. continue;
  221. /*
  222. * IF there is no such environment variable,
  223. * THEN skip this entry, too.
  224. */
  225. if (strlen( st.pOD->pz_NAME ) >= spaceLeft)
  226. continue;
  227. /*
  228. * Set up the option state
  229. */
  230. strcpy( pzFlagName, st.pOD->pz_NAME );
  231. checkEnvOpt(&st, zEnvName, pOpts, type);
  232. }
  233. /*
  234. * Special handling for ${PROGNAME_LOAD_OPTS}
  235. */
  236. if (pOpts->specOptIdx.save_opts != 0) {
  237. st.pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts + 1;
  238. strcpy( pzFlagName, st.pOD->pz_NAME );
  239. checkEnvOpt(&st, zEnvName, pOpts, type);
  240. }
  241. }
  242. /*
  243. * Local Variables:
  244. * mode: C
  245. * c-file-style: "stroustrup"
  246. * indent-tabs-mode: nil
  247. * End:
  248. * end of autoopts/environment.c */