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