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