1
2/*
3 *  $Id: 8700c8e91e8094c455392c691d9b6a7d62222240 $
4 * Time-stamp:      "2009-07-20 20:12:24 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 *  This file is part of AutoOpts, a companion to AutoGen.
12 *  AutoOpts is free software.
13 *  AutoOpts is copyright (c) 1992-2009 by Bruce Korb - all rights reserved
14 *
15 *  AutoOpts is available under any one of two licenses.  The license
16 *  in use must be one of these two and the choice is under the control
17 *  of the user of the license.
18 *
19 *   The GNU Lesser General Public License, version 3 or later
20 *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
21 *
22 *   The Modified Berkeley Software Distribution License
23 *      See the file "COPYING.mbsd"
24 *
25 *  These files have the following md5sums:
26 *
27 *  43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3
28 *  06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3
29 *  66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd
30 */
31
32/* = = = START-STATIC-FORWARD = = = */
33/* static forward declarations maintained by mk-fwd */
34static void
35checkEnvOpt(tOptState * os, char * env_name,
36            tOptions* pOpts, teEnvPresetType type);
37/* = = = END-STATIC-FORWARD = = = */
38
39/*
40 *  doPrognameEnv - check for preset values from the ${PROGNAME}
41 *  environment variable.  This is accomplished by parsing the text into
42 *  tokens, temporarily replacing the arg vector and calling
43 *  doImmediateOpts and/or doRegularOpts.
44 */
45LOCAL void
46doPrognameEnv( tOptions* pOpts, teEnvPresetType type )
47{
48    char const*   pczOptStr = getenv( pOpts->pzPROGNAME );
49    token_list_t* pTL;
50    int           sv_argc;
51    tAoUI         sv_flag;
52    char**        sv_argv;
53
54    /*
55     *  No such beast?  Then bail now.
56     */
57    if (pczOptStr == NULL)
58        return;
59
60    /*
61     *  Tokenize the string.  If there's nothing of interest, we'll bail
62     *  here immediately.
63     */
64    pTL = ao_string_tokenize( pczOptStr );
65    if (pTL == NULL)
66        return;
67
68    /*
69     *  Substitute our $PROGNAME argument list for the real one
70     */
71    sv_argc = pOpts->origArgCt;
72    sv_argv = pOpts->origArgVect;
73    sv_flag = pOpts->fOptSet;
74
75    /*
76     *  We add a bogus pointer to the start of the list.  The program name
77     *  has already been pulled from "argv", so it won't get dereferenced.
78     *  The option scanning code will skip the "program name" at the start
79     *  of this list of tokens, so we accommodate this way ....
80     */
81    pOpts->origArgVect = (char**)(pTL->tkn_list - 1);
82    pOpts->origArgCt   = pTL->tkn_ct   + 1;
83    pOpts->fOptSet    &= ~OPTPROC_ERRSTOP;
84
85    pOpts->curOptIdx   = 1;
86    pOpts->pzCurOpt    = NULL;
87
88    switch (type) {
89    case ENV_IMM:
90        (void)doImmediateOpts( pOpts );
91        break;
92
93    case ENV_ALL:
94        (void)doImmediateOpts( pOpts );
95        pOpts->curOptIdx = 1;
96        pOpts->pzCurOpt  = NULL;
97        /* FALLTHROUGH */
98
99    case ENV_NON_IMM:
100        (void)doRegularOpts( pOpts );
101    }
102
103    /*
104     *  Free up the temporary arg vector and restore the original program args.
105     */
106    free( pTL );
107    pOpts->origArgVect = sv_argv;
108    pOpts->origArgCt   = sv_argc;
109    pOpts->fOptSet     = sv_flag;
110}
111
112static void
113checkEnvOpt(tOptState * os, char * env_name,
114            tOptions* pOpts, teEnvPresetType type)
115{
116    os->pzOptArg = getenv( env_name );
117    if (os->pzOptArg == NULL)
118        return;
119
120    os->flags    = OPTST_PRESET | OPTST_ALLOC_ARG | os->pOD->fOptState;
121    os->optType  = TOPT_UNDEFINED;
122
123    if (  (os->pOD->pz_DisablePfx != NULL)
124       && (streqvcmp( os->pzOptArg, os->pOD->pz_DisablePfx ) == 0)) {
125        os->flags |= OPTST_DISABLED;
126        os->pzOptArg = NULL;
127    }
128
129    switch (type) {
130    case ENV_IMM:
131        /*
132         *  Process only immediate actions
133         */
134        if (DO_IMMEDIATELY(os->flags))
135            break;
136        return;
137
138    case ENV_NON_IMM:
139        /*
140         *  Process only NON immediate actions
141         */
142        if (DO_NORMALLY(os->flags) || DO_SECOND_TIME(os->flags))
143            break;
144        return;
145
146    default: /* process everything */
147        break;
148    }
149
150    /*
151     *  Make sure the option value string is persistent and consistent.
152     *
153     *  The interpretation of the option value depends
154     *  on the type of value argument the option takes
155     */
156    if (os->pzOptArg != NULL) {
157        if (OPTST_GET_ARGTYPE(os->pOD->fOptState) == OPARG_TYPE_NONE) {
158            os->pzOptArg = NULL;
159        } else if (  (os->pOD->fOptState & OPTST_ARG_OPTIONAL)
160                     && (*os->pzOptArg == NUL)) {
161            os->pzOptArg = NULL;
162        } else if (*os->pzOptArg == NUL) {
163            os->pzOptArg = zNil;
164        } else {
165            AGDUPSTR( os->pzOptArg, os->pzOptArg, "option argument" );
166            os->flags |= OPTST_ALLOC_ARG;
167        }
168    }
169
170    handleOption( pOpts, os );
171}
172
173/*
174 *  doEnvPresets - check for preset values from the envrionment
175 *  This routine should process in all, immediate or normal modes....
176 */
177LOCAL void
178doEnvPresets( tOptions* pOpts, teEnvPresetType type )
179{
180    int        ct;
181    tOptState  st;
182    char*      pzFlagName;
183    size_t     spaceLeft;
184    char       zEnvName[ AO_NAME_SIZE ];
185
186    /*
187     *  Finally, see if we are to look at the environment
188     *  variables for initial values.
189     */
190    if ((pOpts->fOptSet & OPTPROC_ENVIRON) == 0)
191        return;
192
193    doPrognameEnv( pOpts, type );
194
195    ct  = pOpts->presetOptCt;
196    st.pOD = pOpts->pOptDesc;
197
198    pzFlagName = zEnvName
199        + snprintf( zEnvName, sizeof( zEnvName ), "%s_", pOpts->pzPROGNAME );
200    spaceLeft = AO_NAME_SIZE - (pzFlagName - zEnvName) - 1;
201
202    for (;ct-- > 0; st.pOD++) {
203        /*
204         *  If presetting is disallowed, then skip this entry
205         */
206        if (  ((st.pOD->fOptState & OPTST_NO_INIT) != 0)
207           || (st.pOD->optEquivIndex != NO_EQUIVALENT)  )
208            continue;
209
210        /*
211         *  IF there is no such environment variable,
212         *  THEN skip this entry, too.
213         */
214        if (strlen( st.pOD->pz_NAME ) >= spaceLeft)
215            continue;
216
217        /*
218         *  Set up the option state
219         */
220        strcpy( pzFlagName, st.pOD->pz_NAME );
221        checkEnvOpt(&st, zEnvName, pOpts, type);
222    }
223
224    /*
225     *  Special handling for ${PROGNAME_LOAD_OPTS}
226     */
227    if (  (pOpts->specOptIdx.save_opts != NO_EQUIVALENT)
228       && (pOpts->specOptIdx.save_opts != 0)) {
229        st.pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts + 1;
230        strcpy( pzFlagName, st.pOD->pz_NAME );
231        checkEnvOpt(&st, zEnvName, pOpts, type);
232    }
233}
234
235/*
236 * Local Variables:
237 * mode: C
238 * c-file-style: "stroustrup"
239 * indent-tabs-mode: nil
240 * End:
241 * end of autoopts/environment.c */
242