xref: /netbsd/external/bsd/ntp/dist/sntp/libopts/restore.c (revision 6550d01e)
1 /*	$NetBSD: restore.c,v 1.1.1.1 2009/12/13 16:57:21 kardel Exp $	*/
2 
3 
4 /*
5  *  restore.c  Id: 6f5237ba2586755d8ca354f325fc00e7fa1395ec
6  * Time-stamp:      "2007-07-04 11:34:40 bkorb"
7  *
8  *  This module's routines will save the current option state to memory
9  *  and restore it.  If saved prior to the initial optionProcess call,
10  *  then the initial state will be restored.
11  *
12  *  This file is part of AutoOpts, a companion to AutoGen.
13  *  AutoOpts is free software.
14  *  AutoOpts is copyright (c) 1992-2009 by Bruce Korb - all rights reserved
15  *
16  *  AutoOpts is available under any one of two licenses.  The license
17  *  in use must be one of these two and the choice is under the control
18  *  of the user of the license.
19  *
20  *   The GNU Lesser General Public License, version 3 or later
21  *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
22  *
23  *   The Modified Berkeley Software Distribution License
24  *      See the file "COPYING.mbsd"
25  *
26  *  These files have the following md5sums:
27  *
28  *  43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3
29  *  06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3
30  *  66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd
31  */
32 
33 /*
34  *  optionFixupSavedOpts  Really, it just wipes out option state for
35  *  options that are troublesome to copy.  viz., stacked strings and
36  *  hierarcicaly valued option args.  We do duplicate string args that
37  *  have been marked as allocated though.
38  */
39 static void
40 fixupSavedOptionArgs(tOptions* pOpts)
41 {
42     tOptions* p   = pOpts->pSavedState;
43     tOptDesc* pOD = pOpts->pOptDesc;
44     int       ct  = pOpts->optCt;
45 
46     /*
47      *  Make sure that allocated stuff is only referenced in the
48      *  archived copy of the data.
49      */
50     for (; ct-- > 0; pOD++)  {
51         switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
52         case OPARG_TYPE_STRING:
53             if (pOD->fOptState & OPTST_STACKED) {
54                 tOptDesc* q = p->pOptDesc + (pOD - pOpts->pOptDesc);
55                 q->optCookie = NULL;
56             }
57             if (pOD->fOptState & OPTST_ALLOC_ARG) {
58                 tOptDesc* q = p->pOptDesc + (pOD - pOpts->pOptDesc);
59                 AGDUPSTR(q->optArg.argString, pOD->optArg.argString, "arg");
60             }
61             break;
62 
63         case OPARG_TYPE_HIERARCHY:
64         {
65             tOptDesc* q = p->pOptDesc + (pOD - pOpts->pOptDesc);
66             q->optCookie = NULL;
67         }
68         }
69     }
70 }
71 
72 /*=export_func optionSaveState
73  *
74  * what:  saves the option state to memory
75  * arg:   tOptions*, pOpts, program options descriptor
76  *
77  * doc:
78  *
79  *  This routine will allocate enough memory to save the current option
80  *  processing state.  If this routine has been called before, that memory
81  *  will be reused.  You may only save one copy of the option state.  This
82  *  routine may be called before optionProcess(3AO).  If you do call it
83  *  before the first call to optionProcess, then you may also change the
84  *  contents of argc/argv after you call optionRestore(3AO)
85  *
86  *  In fact, more strongly put: it is safest to only use this function
87  *  before having processed any options.  In particular, the saving and
88  *  restoring of stacked string arguments and hierarchical values is
89  *  disabled.  The values are not saved.
90  *
91  * err:   If it fails to allocate the memory,
92  *        it will print a message to stderr and exit.
93  *        Otherwise, it will always succeed.
94 =*/
95 void
96 optionSaveState(tOptions* pOpts)
97 {
98     tOptions* p = (tOptions*)pOpts->pSavedState;
99 
100     if (p == NULL) {
101         size_t sz = sizeof( *pOpts ) + (pOpts->optCt * sizeof( tOptDesc ));
102         p = AGALOC( sz, "saved option state" );
103         if (p == NULL) {
104             tCC* pzName = pOpts->pzProgName;
105             if (pzName == NULL) {
106                 pzName = pOpts->pzPROGNAME;
107                 if (pzName == NULL)
108                     pzName = zNil;
109             }
110             fprintf( stderr, zCantSave, pzName, sz );
111             exit( EXIT_FAILURE );
112         }
113 
114         pOpts->pSavedState = p;
115     }
116 
117     memcpy( p, pOpts, sizeof( *p ));
118     memcpy( p + 1, pOpts->pOptDesc, p->optCt * sizeof( tOptDesc ));
119 
120     fixupSavedOptionArgs(pOpts);
121 }
122 
123 
124 /*=export_func optionRestore
125  *
126  * what:  restore option state from memory copy
127  * arg:   tOptions*, pOpts, program options descriptor
128  *
129  * doc:  Copy back the option state from saved memory.
130  *       The allocated memory is left intact, so this routine can be
131  *       called repeatedly without having to call optionSaveState again.
132  *       If you are restoring a state that was saved before the first call
133  *       to optionProcess(3AO), then you may change the contents of the
134  *       argc/argv parameters to optionProcess.
135  *
136  * err:  If you have not called @code{optionSaveState} before, a diagnostic is
137  *       printed to @code{stderr} and exit is called.
138 =*/
139 void
140 optionRestore( tOptions* pOpts )
141 {
142     tOptions* p = (tOptions*)pOpts->pSavedState;
143 
144     if (p == NULL) {
145         tCC* pzName = pOpts->pzProgName;
146         if (pzName == NULL) {
147             pzName = pOpts->pzPROGNAME;
148             if (pzName == NULL)
149                 pzName = zNil;
150         }
151         fprintf( stderr, zNoState, pzName );
152         exit( EXIT_FAILURE );
153     }
154 
155     pOpts->pSavedState = NULL;
156     optionFree(pOpts);
157 
158     memcpy( pOpts, p, sizeof( *p ));
159     memcpy( pOpts->pOptDesc, p+1, p->optCt * sizeof( tOptDesc ));
160     pOpts->pSavedState = p;
161 
162     fixupSavedOptionArgs(pOpts);
163 }
164 
165 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
166 
167 /*=export_func optionFree
168  *
169  * what:  free allocated option processing memory
170  * arg:   tOptions*, pOpts, program options descriptor
171  *
172  * doc:   AutoOpts sometimes allocates memory and puts pointers to it in the
173  *        option state structures.  This routine deallocates all such memory.
174  *
175  * err:   As long as memory has not been corrupted,
176  *        this routine is always successful.
177 =*/
178 void
179 optionFree( tOptions* pOpts )
180 {
181  free_saved_state:
182     {
183         tOptDesc* p = pOpts->pOptDesc;
184         int ct = pOpts->optCt;
185         do  {
186             if (p->fOptState & OPTST_ALLOC_ARG) {
187                 AGFREE(p->optArg.argString);
188                 p->optArg.argString = NULL;
189                 p->fOptState &= ~OPTST_ALLOC_ARG;
190             }
191 
192             switch (OPTST_GET_ARGTYPE(p->fOptState)) {
193             case OPARG_TYPE_STRING:
194 #ifdef WITH_LIBREGEX
195                 if (  (p->fOptState & OPTST_STACKED)
196                    && (p->optCookie != NULL)) {
197                     p->optArg.argString = ".*";
198                     optionUnstackArg(pOpts, p);
199                 }
200 #else
201                 /* leak memory */;
202 #endif
203                 break;
204 
205             case OPARG_TYPE_HIERARCHY:
206                 if (p->optCookie != NULL)
207                     unloadNestedArglist(p->optCookie);
208                 break;
209             }
210 
211             p->optCookie = NULL;
212         } while (p++, --ct > 0);
213     }
214     if (pOpts->pSavedState != NULL) {
215         tOptions * p = (tOptions*)pOpts->pSavedState;
216         memcpy( pOpts, p, sizeof( *p ));
217         memcpy( pOpts->pOptDesc, p+1, p->optCt * sizeof( tOptDesc ));
218         AGFREE( pOpts->pSavedState );
219         pOpts->pSavedState = NULL;
220         goto free_saved_state;
221     }
222 }
223 /*
224  * Local Variables:
225  * mode: C
226  * c-file-style: "stroustrup"
227  * indent-tabs-mode: nil
228  * End:
229  * end of autoopts/restore.c */
230