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