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