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 = VOIDP(&(opts->pzProgName)); 101 102 if (pz != NULL) 103 *pp = pz+1; 104 else 105 *pp = pname; 106 107 pz = pathfind(getenv("PATH"), pname, "rx"); 108 if (pz != NULL) 109 pname = VOIDP(pz); 110 111 pp = (char const **)VOIDP(&(opts->pzProgPath)); 112 *pp = pname; 113 114 /* 115 * when comparing long names, these are equivalent 116 */ 117 strequate(zSepChars); 118 } 119 120 return SUCCESS; 121 } 122 123 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 124 * 125 * DO PRESETS 126 * 127 * The next several routines do the immediate action pass on the command 128 * line options, then the environment variables, then the config files in 129 * reverse order. Once done with that, the order is reversed and all 130 * the config files and environment variables are processed again, this 131 * time only processing the non-immediate action options. do_presets() 132 * will then return for optionProcess() to do the final pass on the command 133 * line arguments. 134 */ 135 136 /** 137 * scan the command line for immediate action options. 138 * This is only called the first time through. 139 * While this procedure is active, the OPTPROC_IMMEDIATE is true. 140 * 141 * @param pOpts program options descriptor 142 * @returns SUCCESS or FAILURE 143 */ 144 LOCAL tSuccess 145 immediate_opts(tOptions * opts) 146 { 147 tSuccess res; 148 149 opts->fOptSet |= OPTPROC_IMMEDIATE; 150 opts->curOptIdx = 1; /* start by skipping program name */ 151 opts->pzCurOpt = NULL; 152 153 /* 154 * Examine all the options from the start. We process any options that 155 * are marked for immediate processing. 156 */ 157 for (;;) { 158 tOptState opt_st = OPTSTATE_INITIALIZER(PRESET); 159 160 res = next_opt(opts, &opt_st); 161 switch (res) { 162 case FAILURE: goto failed_option; 163 case PROBLEM: res = SUCCESS; goto leave; 164 case SUCCESS: break; 165 } 166 167 /* 168 * IF this is an immediate-attribute option, then do it. 169 */ 170 if (! DO_IMMEDIATELY(opt_st.flags)) 171 continue; 172 173 if (! SUCCESSFUL(handle_opt(opts, &opt_st))) 174 break; 175 } failed_option:; 176 177 if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) 178 (*opts->pUsageProc)(opts, EXIT_FAILURE); 179 180 leave: 181 182 opts->fOptSet &= ~OPTPROC_IMMEDIATE; 183 return res; 184 } 185 186 /** 187 * check for preset values from a config files or envrionment variables 188 * 189 * @param[in,out] opts the structure with the option names to check 190 */ 191 static tSuccess 192 do_presets(tOptions * opts) 193 { 194 tOptDesc * od = NULL; 195 196 if (! SUCCESSFUL(immediate_opts(opts))) 197 return FAILURE; 198 199 /* 200 * IF this option set has a --save-opts option, then it also 201 * has a --load-opts option. See if a command line option has disabled 202 * option presetting. 203 */ 204 if ( (opts->specOptIdx.save_opts != NO_EQUIVALENT) 205 && (opts->specOptIdx.save_opts != 0)) { 206 od = opts->pOptDesc + opts->specOptIdx.save_opts + 1; 207 if (DISABLED_OPT(od)) 208 return SUCCESS; 209 } 210 211 /* 212 * Until we return from this procedure, disable non-presettable opts 213 */ 214 opts->fOptSet |= OPTPROC_PRESETTING; 215 /* 216 * IF there are no config files, 217 * THEN do any environment presets and leave. 218 */ 219 if (opts->papzHomeList == NULL) { 220 env_presets(opts, ENV_ALL); 221 } 222 else { 223 env_presets(opts, ENV_IMM); 224 225 /* 226 * Check to see if environment variables have disabled presetting. 227 */ 228 if ((od != NULL) && ! DISABLED_OPT(od)) 229 intern_file_load(opts); 230 231 /* 232 * ${PROGRAM_LOAD_OPTS} value of "no" cannot disable other environment 233 * variable options. Only the loading of .rc files. 234 */ 235 env_presets(opts, ENV_NON_IMM); 236 } 237 opts->fOptSet &= ~OPTPROC_PRESETTING; 238 239 return SUCCESS; 240 } 241 242 /** 243 * AutoOpts initialization 244 * 245 * @param[in,out] opts the structure to initialize 246 * @param[in] a_ct program argument count 247 * @param[in] a_v program argument vector 248 */ 249 LOCAL bool 250 ao_initialize(tOptions * opts, int a_ct, char ** a_v) 251 { 252 if ((opts->fOptSet & OPTPROC_INITDONE) != 0) 253 return true; 254 255 opts->origArgCt = (unsigned int)a_ct; 256 opts->origArgVect = a_v; 257 opts->fOptSet |= OPTPROC_INITDONE; 258 259 if (HAS_pzPkgDataDir(opts)) 260 program_pkgdatadir = opts->pzPkgDataDir; 261 262 if (! SUCCESSFUL(do_presets(opts))) 263 return false; 264 265 /* 266 * IF option name conversion was suppressed but it is not suppressed 267 * for the command line, then it's time to translate option names. 268 * Usage text will not get retranslated. 269 */ 270 if ( ((opts->fOptSet & OPTPROC_TRANSLATE) != 0) 271 && (opts->pTransProc != NULL) 272 && ((opts->fOptSet & OPTPROC_NO_XLAT_MASK) == OPTPROC_NXLAT_OPT_CFG) 273 ) { 274 opts->fOptSet &= ~OPTPROC_NXLAT_OPT_CFG; 275 (*opts->pTransProc)(); 276 } 277 278 if ((opts->fOptSet & OPTPROC_REORDER) != 0) 279 optionSort(opts); 280 281 opts->curOptIdx = 1; 282 opts->pzCurOpt = NULL; 283 return true; 284 } 285 286 /** @} 287 * 288 * Local Variables: 289 * mode: C 290 * c-file-style: "stroustrup" 291 * indent-tabs-mode: nil 292 * End: 293 * end of autoopts/initialize.c */ 294