1 /** 2 * \file initialize.c 3 * 4 * initialize the libopts data structures. 5 * 6 * @addtogroup autoopts 7 * @{ 8 */ 9 /* 10 * This file is part of AutoOpts, a companion to AutoGen. 11 * AutoOpts is free software. 12 * AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved 13 * 14 * AutoOpts is available under any one of two licenses. The license 15 * in use must be one of these two and the choice is under the control 16 * of the user of the license. 17 * 18 * The GNU Lesser General Public License, version 3 or later 19 * See the files "COPYING.lgplv3" and "COPYING.gplv3" 20 * 21 * The Modified Berkeley Software Distribution License 22 * See the file "COPYING.mbsd" 23 * 24 * These files have the following sha256 sums: 25 * 26 * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 27 * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 28 * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd 29 */ 30 31 /* = = = START-STATIC-FORWARD = = = */ 32 static tSuccess 33 do_presets(tOptions * opts); 34 /* = = = END-STATIC-FORWARD = = = */ 35 36 /** 37 * Make sure the option descriptor is there and that we understand it. 38 * This should be called from any user entry point where one needs to 39 * worry about validity. (Some entry points are free to assume that 40 * the call is not the first to the library and, thus, that this has 41 * already been called.) 42 * 43 * Upon successful completion, pzProgName and pzProgPath are set. 44 * 45 * @param[in,out] opts program options descriptor 46 * @param[in] pname name of program, from argv[] 47 * @returns SUCCESS or FAILURE 48 */ 49 LOCAL tSuccess 50 validate_struct(tOptions * opts, char const * pname) 51 { 52 if (opts == NULL) { 53 fputs(zno_opt_arg, stderr); 54 return FAILURE; 55 } 56 print_exit = ((opts->fOptSet & OPTPROC_SHELL_OUTPUT) != 0); 57 58 /* 59 * IF the client has enabled translation and the translation procedure 60 * is available, then go do it. 61 */ 62 if ( ((opts->fOptSet & OPTPROC_TRANSLATE) != 0) 63 && (opts->pTransProc != NULL) 64 && (option_xlateable_txt.field_ct != 0) ) { 65 /* 66 * If option names are not to be translated at all, then do not do 67 * it for configuration parsing either. (That is the bit that really 68 * gets tested anyway.) 69 */ 70 if ((opts->fOptSet & OPTPROC_NO_XLAT_MASK) == OPTPROC_NXLAT_OPT) 71 opts->fOptSet |= OPTPROC_NXLAT_OPT_CFG; 72 opts->pTransProc(); 73 } 74 75 /* 76 * IF the struct version is not the current, and also 77 * either too large (?!) or too small, 78 * THEN emit error message and fail-exit 79 */ 80 if ( ( opts->structVersion != OPTIONS_STRUCT_VERSION ) 81 && ( (opts->structVersion > OPTIONS_STRUCT_VERSION ) 82 || (opts->structVersion < OPTIONS_MINIMUM_VERSION ) 83 ) ) { 84 fprintf(stderr, zwrong_ver, pname, NUM_TO_VER(opts->structVersion)); 85 if (opts->structVersion > OPTIONS_STRUCT_VERSION ) 86 fputs(ztoo_new, stderr); 87 else 88 fputs(ztoo_old, stderr); 89 90 fwrite(ao_ver_string, sizeof(ao_ver_string) - 1, 1, stderr); 91 return FAILURE; 92 } 93 94 /* 95 * If the program name hasn't been set, then set the name and the path 96 * and the set of equivalent characters. 97 */ 98 if (opts->pzProgName == NULL) { 99 char const * pz = strrchr(pname, DIRCH); 100 char const ** pp = 101 (char const **)(void **)&(opts->pzProgName); 102 103 if (pz != NULL) 104 *pp = pz+1; 105 else 106 *pp = pname; 107 108 pz = pathfind(getenv("PATH"), (char *)pname, "rx"); 109 if (pz != NULL) 110 pname = VOIDP(pz); 111 112 pp = (char const **)VOIDP(&(opts->pzProgPath)); 113 *pp = pname; 114 115 /* 116 * when comparing long names, these are equivalent 117 */ 118 strequate(zSepChars); 119 } 120 121 return SUCCESS; 122 } 123 124 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 125 * 126 * DO PRESETS 127 * 128 * The next several routines do the immediate action pass on the command 129 * line options, then the environment variables, then the config files in 130 * reverse order. Once done with that, the order is reversed and all 131 * the config files and environment variables are processed again, this 132 * time only processing the non-immediate action options. do_presets() 133 * will then return for optionProcess() to do the final pass on the command 134 * line arguments. 135 */ 136 137 /** 138 * scan the command line for immediate action options. 139 * This is only called the first time through. 140 * While this procedure is active, the OPTPROC_IMMEDIATE is true. 141 * 142 * @param pOpts program options descriptor 143 * @returns SUCCESS or FAILURE 144 */ 145 LOCAL tSuccess 146 immediate_opts(tOptions * opts) 147 { 148 tSuccess res; 149 150 opts->fOptSet |= OPTPROC_IMMEDIATE; 151 opts->curOptIdx = 1; /* start by skipping program name */ 152 opts->pzCurOpt = NULL; 153 154 /* 155 * Examine all the options from the start. We process any options that 156 * are marked for immediate processing. 157 */ 158 for (;;) { 159 tOptState opt_st = OPTSTATE_INITIALIZER(PRESET); 160 161 res = next_opt(opts, &opt_st); 162 switch (res) { 163 case FAILURE: goto failed_option; 164 case PROBLEM: res = SUCCESS; goto leave; 165 case SUCCESS: break; 166 } 167 168 /* 169 * IF this is an immediate-attribute option, then do it. 170 */ 171 if (! DO_IMMEDIATELY(opt_st.flags)) 172 continue; 173 174 if (! SUCCESSFUL(handle_opt(opts, &opt_st))) 175 break; 176 } failed_option:; 177 178 if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) 179 (*opts->pUsageProc)(opts, EXIT_FAILURE); 180 181 leave: 182 183 opts->fOptSet &= ~OPTPROC_IMMEDIATE; 184 return res; 185 } 186 187 /** 188 * check for preset values from a config files or envrionment variables 189 * 190 * @param[in,out] opts the structure with the option names to check 191 */ 192 static tSuccess 193 do_presets(tOptions * opts) 194 { 195 tOptDesc * od = NULL; 196 197 if (! SUCCESSFUL(immediate_opts(opts))) 198 return FAILURE; 199 200 /* 201 * IF this option set has a --save-opts option, then it also 202 * has a --load-opts option. See if a command line option has disabled 203 * option presetting. 204 */ 205 if ( (opts->specOptIdx.save_opts != NO_EQUIVALENT) 206 && (opts->specOptIdx.save_opts != 0)) { 207 od = opts->pOptDesc + opts->specOptIdx.save_opts + 1; 208 if (DISABLED_OPT(od)) 209 return SUCCESS; 210 } 211 212 /* 213 * Until we return from this procedure, disable non-presettable opts 214 */ 215 opts->fOptSet |= OPTPROC_PRESETTING; 216 /* 217 * IF there are no config files, 218 * THEN do any environment presets and leave. 219 */ 220 if (opts->papzHomeList == NULL) { 221 env_presets(opts, ENV_ALL); 222 } 223 else { 224 env_presets(opts, ENV_IMM); 225 226 /* 227 * Check to see if environment variables have disabled presetting. 228 */ 229 if ((od != NULL) && ! DISABLED_OPT(od)) 230 intern_file_load(opts); 231 232 /* 233 * ${PROGRAM_LOAD_OPTS} value of "no" cannot disable other environment 234 * variable options. Only the loading of .rc files. 235 */ 236 env_presets(opts, ENV_NON_IMM); 237 } 238 opts->fOptSet &= ~OPTPROC_PRESETTING; 239 240 return SUCCESS; 241 } 242 243 /** 244 * AutoOpts initialization 245 * 246 * @param[in,out] opts the structure to initialize 247 * @param[in] a_ct program argument count 248 * @param[in] a_v program argument vector 249 */ 250 LOCAL bool 251 ao_initialize(tOptions * opts, int a_ct, char ** a_v) 252 { 253 if ((opts->fOptSet & OPTPROC_INITDONE) != 0) 254 return true; 255 256 opts->origArgCt = (unsigned int)a_ct; 257 opts->origArgVect = a_v; 258 opts->fOptSet |= OPTPROC_INITDONE; 259 260 if (HAS_pzPkgDataDir(opts)) 261 program_pkgdatadir = opts->pzPkgDataDir; 262 263 if (! SUCCESSFUL(do_presets(opts))) 264 return false; 265 266 /* 267 * IF option name conversion was suppressed but it is not suppressed 268 * for the command line, then it's time to translate option names. 269 * Usage text will not get retranslated. 270 */ 271 if ( ((opts->fOptSet & OPTPROC_TRANSLATE) != 0) 272 && (opts->pTransProc != NULL) 273 && ((opts->fOptSet & OPTPROC_NO_XLAT_MASK) == OPTPROC_NXLAT_OPT_CFG) 274 ) { 275 opts->fOptSet &= ~OPTPROC_NXLAT_OPT_CFG; 276 (*opts->pTransProc)(); 277 } 278 279 if ((opts->fOptSet & OPTPROC_REORDER) != 0) 280 optionSort(opts); 281 282 opts->curOptIdx = 1; 283 opts->pzCurOpt = NULL; 284 return true; 285 } 286 287 /** @} 288 * 289 * Local Variables: 290 * mode: C 291 * c-file-style: "stroustrup" 292 * indent-tabs-mode: nil 293 * End: 294 * end of autoopts/initialize.c */ 295