]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - usr.sbin/sysinstall/variable.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / usr.sbin / sysinstall / variable.c
1 /*
2  * The new sysinstall program.
3  *
4  * This is probably the last program in the `sysinstall' line - the next
5  * generation being essentially a complete rewrite.
6  *
7  * $FreeBSD$
8  *
9  * Copyright (c) 1995
10  *      Jordan Hubbard.  All rights reserved.
11  * Copyright (c) 2001 
12  *      Murray Stokely.  All rights reserved.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer,
19  *    verbatim and that no modifications are made prior to this
20  *    point in the file.
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the
23  *    documentation and/or other materials provided with the distribution.
24  *
25  * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  */
38
39 #include "sysinstall.h"
40
41 /* Routines for dealing with variable lists */
42
43 static void
44 make_variable(char *var, char *value, int dirty)
45 {
46     Variable *vp;
47
48     /* Trim leading and trailing whitespace */
49     var = string_skipwhite(string_prune(var));
50
51     if (!var || !*var)
52         return;
53
54
55     /* Now search to see if it's already in the list */
56     for (vp = VarHead; vp; vp = vp->next) {
57         if (!strcmp(vp->name, var)) {
58             if (vp->dirty && !dirty)
59                 return;
60             setenv(var, value, 1);
61             free(vp->value);
62             vp->value = strdup(value);
63             if (dirty != -1)
64                 vp->dirty = dirty;
65             return;
66         }
67     }
68
69     setenv(var, value, 1);
70     /* No?  Create a new one */
71     vp = (Variable *)safe_malloc(sizeof(Variable));
72     vp->name = strdup(var);
73     vp->value = strdup(value);
74     if (dirty == -1)
75         dirty = 0;
76     vp->dirty = dirty;
77     vp->next = VarHead;
78     VarHead = vp;
79 }
80
81 void
82 variable_set(char *var, int dirty)
83 {
84     char tmp[1024], *cp;
85
86     if (!var)
87         msgFatal("NULL variable name & value passed.");
88     else if (!*var)
89         msgDebug("Warning:  Zero length name & value passed to variable_set()\n");
90     SAFE_STRCPY(tmp, var);
91     if ((cp = index(tmp, '=')) == NULL)
92         msgFatal("Invalid variable format: %s", var);
93     *(cp++) = '\0';
94     make_variable(tmp, string_skipwhite(cp), dirty);
95 }
96
97 void
98 variable_set2(char *var, char *value, int dirty)
99 {
100     if (!var || !value)
101         msgFatal("Null name or value passed to set_variable2(%s) = %s!",
102                 var ? var : "", value ? value : "");
103     else if (!*var || !*value)
104         msgDebug("Warning:  Zero length name or value passed to variable_set2(%s) = %s\n",
105                 var, value);
106     make_variable(var, value, dirty);
107 }
108
109 char *
110 variable_get(char *var)
111 {
112     return getenv(var);
113 }
114
115 int
116 variable_cmp(char *var, char *value)
117 {
118     char *val;
119
120     if ((val = variable_get(var)))
121         return strcmp(val, value);
122     return -1;
123 }
124
125 void
126 variable_unset(char *var)
127 {
128     Variable *vp;
129     char name[512], *cp;
130
131     if ((cp = index(var, '=')) != NULL)
132         sstrncpy(name, var, cp - var);
133     else
134         SAFE_STRCPY(name, var);
135     unsetenv(name);
136     /* Now search to see if it's in our list, if we have one.. */
137     if (!VarHead)
138         return;
139     else if (!VarHead->next && !strcmp(VarHead->name, name)) {
140         safe_free(VarHead->name);
141         safe_free(VarHead->value);
142         free(VarHead);
143         VarHead = NULL;
144     }
145     else {
146         for (vp = VarHead; vp; vp = vp->next) {
147             if (!strcmp(vp->name, name)) {
148                 Variable *save = vp->next;
149
150                 safe_free(vp->name);
151                 safe_free(vp->value);
152                 *vp = *save;
153                 safe_free(save);
154                 break;
155             }
156         }
157     }
158 }
159
160 /* Prompt user for the name of a variable */
161 char *
162 variable_get_value(char *var, char *prompt, int dirty)
163 {
164     char *cp;
165
166     cp = variable_get(var);
167     if (cp && variable_get(VAR_NONINTERACTIVE))
168         return cp;
169     else if ((cp = msgGetInput(cp, "%s", prompt)) != NULL)
170         variable_set2(var, cp, dirty);
171     else
172         cp = NULL;
173     return cp;
174 }
175
176 /* Check if value passed in data (in the form "variable=value") is
177  * valid, and it's status compared to the value of variable stored in
178  * env
179  *
180  * Possible return values :
181  * -3: Invalid line, the data string is NOT set as an env variable
182  * -2: Invalid line, the data string is set as an env variable
183  * -1: Invalid line
184  *  0: Valid line, is NOT equal to env version
185  *  1: Valid line, is equal to env version
186  *  2: Valid line, value empty - e.g. foo=""
187  *  3: Valid line, does not exist in env
188 */
189 int
190 variable_check2(char *data)
191 {
192     char *cp, *cp2, *cp3, tmp[256];
193
194     if (data == NULL)
195         return -1;
196     SAFE_STRCPY(tmp, data);
197     if ((cp = index(tmp, '=')) != NULL) {
198         *(cp++) = '\0';
199         if (*cp == '"') {       /* smash quotes if present */
200             ++cp;
201             if ((cp3 = index(cp, '"')) != NULL)
202                 *cp3 = '\0';
203         }
204         else if ((cp3 = index(cp, ',')) != NULL)
205             *cp3 = '\0';
206         cp2 = variable_get(tmp);
207         if (cp2 != NULL) {
208             if (*cp == '\0')
209                 return 2;
210             else
211                 return strcmp(cp, cp2) == 0 ? 1 : 0;
212         }
213         else
214             return 3;
215     }
216     else
217         return variable_get(tmp) != NULL ? -2 : -3;
218
219
220 /* Check if the value passed in data (in the form "variable=value") is
221    equal to the value of variable stored in env */
222 int
223 variable_check(char *data)
224 {
225     int ret;
226     ret = variable_check2(data);
227
228     switch(ret) {
229     case -2:
230     case 1:
231     case 2:
232         return TRUE;
233         /* NOT REACHED */
234     default:
235         return FALSE;
236     }
237 }
238
239 int
240 dump_variables(dialogMenuItem *unused)
241 {
242     FILE *fp;
243     Variable *vp;
244
245     if (isDebug())
246         msgDebug("Writing %s variables to file..\n", ProgName);
247
248     fp = fopen("/etc/sysinstall.vars", "w");
249     if (!fp) {
250         msgConfirm("Unable to write to /etc/sysinstall.vars: %s",
251                    strerror(errno));
252         return DITEM_FAILURE;
253     }
254
255     for (vp = VarHead; vp; vp = vp->next)
256         fprintf(fp, "%s=\"%s\" (%d)\n", vp->name, vp->value, vp->dirty);
257
258     fclose(fp);
259
260     return DITEM_SUCCESS;
261 }
262
263 /* Free all of the variables, useful to really start over as when the
264    user selects "restart" from the interrupt menu. */
265 void
266 free_variables(void)
267 {
268     Variable *vp;
269
270     /* Free the variables from our list, if we have one.. */
271     if (!VarHead)
272         return;
273     else if (!VarHead->next) {
274         unsetenv(VarHead->name);
275         safe_free(VarHead->name);
276         safe_free(VarHead->value);
277         free(VarHead);
278         VarHead = NULL;
279     }
280     else {
281         for (vp = VarHead; vp; ) {
282             Variable *save = vp;
283             unsetenv(vp->name);
284             safe_free(vp->name);
285             safe_free(vp->value);
286             vp = vp->next;
287             safe_free(save);
288         }
289         VarHead = NULL;
290     }
291 }
292
293 /*
294  * Persistent variables.  The variables modified by these functions
295  * are not cleared between invocations of sysinstall.  This is useful
296  * to allow the user to completely restart sysinstall, without having
297  * it load all of the modules again from the installation media which
298  * are still in memory.
299  */
300
301 void
302 pvariable_set(char *var)
303 {
304     char *p;
305     char tmp[1024];
306
307     if (!var)
308         msgFatal("NULL variable name & value passed.");
309     else if (!*var)
310         msgDebug("Warning:  Zero length name & value passed to variable_set()\n");
311     /* Add a trivial namespace to whatever name the caller chooses. */
312     SAFE_STRCPY(tmp, "SYSINSTALL_PVAR");
313     if (index(var, '=') == NULL)
314         msgFatal("Invalid variable format: %s", var);
315     strlcat(tmp, var, 1024); 
316     p = strchr(tmp, '=');
317     *p = '\0';
318     setenv(tmp, p + 1, 1);
319 }
320
321 char *
322 pvariable_get(char *var)
323 {
324     char tmp[1024];
325
326     SAFE_STRCPY(tmp, "SYSINSTALL_PVAR");
327     strlcat(tmp, var, 1024);
328     return getenv(tmp);
329 }