Coverage Report

Created: 2023-05-19 06:16

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