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 43static void 44make_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 81void 82variable_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 97void 98variable_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 109char * 110variable_get(char *var) 111{ 112 return getenv(var); 113} 114 115int 116variable_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 125void 126variable_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 */ 161char * 162variable_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*/ 189int 190variable_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 */ 222int 223variable_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 239int 240dump_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. */ 265void 266free_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 301void 302pvariable_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 321char * 322pvariable_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} 330