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