]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ntp/sntp/libopts/environment.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ntp / sntp / libopts / environment.c
1
2 /*
3  *  $Id: environment.c,v 4.13 2007/04/15 19:01:18 bkorb Exp $
4  * Time-stamp:      "2007-04-15 11:50:35 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
12 /*
13  *  Automated Options copyright 1992-2007 Bruce Korb
14  *
15  *  Automated Options is free software.
16  *  You may redistribute it and/or modify it under the terms of the
17  *  GNU General Public License, as published by the Free Software
18  *  Foundation; either version 2, or (at your option) any later version.
19  *
20  *  Automated Options is distributed in the hope that it will be useful,
21  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
22  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  *  GNU General Public License for more details.
24  *
25  *  You should have received a copy of the GNU General Public License
26  *  along with Automated Options.  See the file "COPYING".  If not,
27  *  write to:  The Free Software Foundation, Inc.,
28  *             51 Franklin Street, Fifth Floor,
29  *             Boston, MA  02110-1301, USA.
30  *
31  * As a special exception, Bruce Korb gives permission for additional
32  * uses of the text contained in his release of AutoOpts.
33  *
34  * The exception is that, if you link the AutoOpts library with other
35  * files to produce an executable, this does not by itself cause the
36  * resulting executable to be covered by the GNU General Public License.
37  * Your use of that executable is in no way restricted on account of
38  * linking the AutoOpts library code into it.
39  *
40  * This exception does not however invalidate any other reasons why
41  * the executable file might be covered by the GNU General Public License.
42  *
43  * This exception applies only to the code released by Bruce Korb under
44  * the name AutoOpts.  If you copy code from other sources under the
45  * General Public License into a copy of AutoOpts, as the General Public
46  * License permits, the exception does not apply to the code that you add
47  * in this way.  To avoid misleading anyone as to the status of such
48  * modified files, you must delete this exception notice from them.
49  *
50  * If you write modifications of your own for AutoOpts, it is your choice
51  * whether to permit this exception to apply to your modifications.
52  * If you do not wish that, delete this exception notice.
53  */
54
55 /* = = = START-STATIC-FORWARD = = = */
56 /* static forward declarations maintained by :mkfwd */
57 static void
58 checkEnvOpt(tOptState * os, char * env_name,
59             tOptions* pOpts, teEnvPresetType type);
60 /* = = = END-STATIC-FORWARD = = = */
61
62 /*
63  *  doPrognameEnv - check for preset values from the ${PROGNAME}
64  *  environment variable.  This is accomplished by parsing the text into
65  *  tokens, temporarily replacing the arg vector and calling
66  *  doImmediateOpts and/or doRegularOpts.
67  */
68 LOCAL void
69 doPrognameEnv( tOptions* pOpts, teEnvPresetType type )
70 {
71     char const*   pczOptStr = getenv( pOpts->pzPROGNAME );
72     token_list_t* pTL;
73     int           sv_argc;
74     tAoUI         sv_flag;
75     char**        sv_argv;
76
77     /*
78      *  IF there is no such environment variable
79      *   *or* there is, but we are doing immediate opts and there are
80      *        no immediate opts to do (--help inside $PROGNAME is silly,
81      *        but --no-load-defs is not, so that is marked)
82      *  THEN bail out now.  (
83      */
84     if (  (pczOptStr == NULL)
85        || (  (type == ENV_IMM)
86           && ((pOpts->fOptSet & OPTPROC_HAS_IMMED) == 0)  )  )
87         return;
88
89     /*
90      *  Tokenize the string.  If there's nothing of interest, we'll bail
91      *  here immediately.
92      */
93     pTL = ao_string_tokenize( pczOptStr );
94     if (pTL == NULL)
95         return;
96
97     /*
98      *  Substitute our $PROGNAME argument list for the real one
99      */
100     sv_argc = pOpts->origArgCt;
101     sv_argv = pOpts->origArgVect;
102     sv_flag = pOpts->fOptSet;
103
104     /*
105      *  We add a bogus pointer to the start of the list.  The program name
106      *  has already been pulled from "argv", so it won't get dereferenced.
107      *  The option scanning code will skip the "program name" at the start
108      *  of this list of tokens, so we accommodate this way ....
109      */
110     pOpts->origArgVect = (char**)(pTL->tkn_list - 1);
111     pOpts->origArgCt   = pTL->tkn_ct   + 1;
112     pOpts->fOptSet    &= ~OPTPROC_ERRSTOP;
113
114     pOpts->curOptIdx   = 1;
115     pOpts->pzCurOpt    = NULL;
116
117     switch (type) {
118     case ENV_IMM:
119         /*
120          *  We know the OPTPROC_HAS_IMMED bit is set.
121          */
122         (void)doImmediateOpts( pOpts );
123         break;
124
125     case ENV_NON_IMM:
126         (void)doRegularOpts( pOpts );
127         break;
128
129     default:
130         /*
131          *  Only to immediate opts if the OPTPROC_HAS_IMMED bit is set.
132          */
133         if (pOpts->fOptSet & OPTPROC_HAS_IMMED) {
134             (void)doImmediateOpts( pOpts );
135             pOpts->curOptIdx = 1;
136             pOpts->pzCurOpt  = NULL;
137         }
138         (void)doRegularOpts( pOpts );
139         break;
140     }
141
142     /*
143      *  Free up the temporary arg vector and restore the original program args.
144      */
145     free( pTL );
146     pOpts->origArgVect = sv_argv;
147     pOpts->origArgCt   = sv_argc;
148     pOpts->fOptSet     = sv_flag;
149 }
150
151 static void
152 checkEnvOpt(tOptState * os, char * env_name,
153             tOptions* pOpts, teEnvPresetType type)
154 {
155     os->pzOptArg = getenv( env_name );
156     if (os->pzOptArg == NULL)
157         return;
158
159     os->flags    = OPTST_PRESET | OPTST_ALLOC_ARG | os->pOD->fOptState;
160     os->optType  = TOPT_UNDEFINED;
161
162     if (  (os->pOD->pz_DisablePfx != NULL)
163        && (streqvcmp( os->pzOptArg, os->pOD->pz_DisablePfx ) == 0)) {
164         os->flags |= OPTST_DISABLED;
165         os->pzOptArg = NULL;
166     }
167
168     switch (type) {
169     case ENV_IMM:
170         /*
171          *  Process only immediate actions
172          */
173         if (DO_IMMEDIATELY(os->flags))
174             break;
175         return;
176
177     case ENV_NON_IMM:
178         /*
179          *  Process only NON immediate actions
180          */
181         if (DO_NORMALLY(os->flags) || DO_SECOND_TIME(os->flags))
182             break;
183         return;
184
185     default: /* process everything */
186         break;
187     }
188
189     /*
190      *  Make sure the option value string is persistent and consistent.
191      *
192      *  The interpretation of the option value depends
193      *  on the type of value argument the option takes
194      */
195     if (os->pzOptArg != NULL) {
196         if (OPTST_GET_ARGTYPE(os->pOD->fOptState) == OPARG_TYPE_NONE) {
197             os->pzOptArg = NULL;
198         } else if (  (os->pOD->fOptState & OPTST_ARG_OPTIONAL)
199                      && (*os->pzOptArg == NUL)) {
200             os->pzOptArg = NULL;
201         } else if (*os->pzOptArg == NUL) {
202             os->pzOptArg = zNil;
203         } else {
204             AGDUPSTR( os->pzOptArg, os->pzOptArg, "option argument" );
205             os->flags |= OPTST_ALLOC_ARG;
206         }
207     }
208
209     handleOption( pOpts, os );
210 }
211
212 /*
213  *  doEnvPresets - check for preset values from the envrionment
214  *  This routine should process in all, immediate or normal modes....
215  */
216 LOCAL void
217 doEnvPresets( tOptions* pOpts, teEnvPresetType type )
218 {
219     int        ct;
220     tOptState  st;
221     char*      pzFlagName;
222     size_t     spaceLeft;
223     char       zEnvName[ AO_NAME_SIZE ];
224
225     /*
226      *  Finally, see if we are to look at the environment
227      *  variables for initial values.
228      */
229     if ((pOpts->fOptSet & OPTPROC_ENVIRON) == 0)
230         return;
231
232     doPrognameEnv( pOpts, type );
233
234     ct  = pOpts->presetOptCt;
235     st.pOD = pOpts->pOptDesc;
236
237     pzFlagName = zEnvName
238         + snprintf( zEnvName, sizeof( zEnvName ), "%s_", pOpts->pzPROGNAME );
239     spaceLeft = AO_NAME_SIZE - (pzFlagName - zEnvName) - 1;
240
241     for (;ct-- > 0; st.pOD++) {
242         /*
243          *  If presetting is disallowed, then skip this entry
244          */
245         if (  ((st.pOD->fOptState & OPTST_NO_INIT) != 0)
246            || (st.pOD->optEquivIndex != NO_EQUIVALENT)  )
247             continue;
248
249         /*
250          *  IF there is no such environment variable,
251          *  THEN skip this entry, too.
252          */
253         if (strlen( st.pOD->pz_NAME ) >= spaceLeft)
254             continue;
255
256         /*
257          *  Set up the option state
258          */
259         strcpy( pzFlagName, st.pOD->pz_NAME );
260         checkEnvOpt(&st, zEnvName, pOpts, type);
261     }
262
263     /*
264      *  Special handling for ${PROGNAME_LOAD_OPTS}
265      */
266     if (pOpts->specOptIdx.save_opts != 0) {
267         st.pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts + 1;
268         strcpy( pzFlagName, st.pOD->pz_NAME );
269         checkEnvOpt(&st, zEnvName, pOpts, type);
270     }
271 }
272
273 /*
274  * Local Variables:
275  * mode: C
276  * c-file-style: "stroustrup"
277  * indent-tabs-mode: nil
278  * End:
279  * end of autoopts/environment.c */