| Commit | Line | Data |
|---|---|---|
| 337ad0df DH |
1 | /* |
| 2 | * Copyright (c)2004 The DragonFly Project. All rights reserved. | |
| 21c1c48a | 3 | * |
| 337ad0df DH |
4 | * Redistribution and use in source and binary forms, with or without |
| 5 | * modification, are permitted provided that the following conditions | |
| 6 | * are met: | |
| 21c1c48a | 7 | * |
| 337ad0df DH |
8 | * Redistributions of source code must retain the above copyright |
| 9 | * notice, this list of conditions and the following disclaimer. | |
| 21c1c48a | 10 | * |
| 337ad0df DH |
11 | * Redistributions in binary form must reproduce the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer in | |
| 13 | * the documentation and/or other materials provided with the | |
| 14 | * distribution. | |
| 21c1c48a | 15 | * |
| 337ad0df DH |
16 | * Neither the name of the DragonFly Project nor the names of its |
| 17 | * contributors may be used to endorse or promote products derived | |
| 21c1c48a SW |
18 | * from this software without specific prior written permission. |
| 19 | * | |
| 337ad0df DH |
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
| 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
| 24 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |
| 25 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
| 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
| 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
| 21c1c48a | 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. |
| 337ad0df DH |
32 | */ |
| 33 | ||
| 34 | /* | |
| 35 | * confed.c | |
| 36 | * Functions for working with configuration files. | |
| 37 | * Inspired by (but not derived from) sysinstall's variable.c | |
| 38 | * $Id: confed.c,v 1.16 2005/02/06 21:05:18 cpressey Exp $ | |
| 39 | */ | |
| 40 | ||
| 41 | #include <sys/stat.h> | |
| 42 | ||
| 43 | #include <ctype.h> | |
| 44 | #include <stdarg.h> | |
| 45 | #include <stdio.h> | |
| 46 | #include <stdlib.h> | |
| 47 | #include <string.h> | |
| 48 | #include <time.h> | |
| 49 | #include <unistd.h> | |
| 50 | ||
| bc3d4063 SW |
51 | #include "libaura/mem.h" |
| 52 | #include "libaura/dict.h" | |
| 53 | #include "libdfui/system.h" | |
| 337ad0df DH |
54 | |
| 55 | #include "confed.h" | |
| 56 | #include "commands.h" | |
| 57 | #include "functions.h" | |
| 58 | ||
| 59 | /* | |
| 60 | * Create a new, empty set of in-memory config variable settings. | |
| 61 | */ | |
| 62 | struct config_vars * | |
| 63 | config_vars_new(void) | |
| 64 | { | |
| 65 | struct config_vars *cvs; | |
| 66 | ||
| 67 | AURA_MALLOC(cvs, config_vars); | |
| 68 | ||
| 69 | cvs->d = aura_dict_new(1, AURA_DICT_SORTED_LIST); | |
| 70 | ||
| 71 | return(cvs); | |
| 72 | } | |
| 73 | ||
| 74 | /* | |
| 75 | * Deallocate the memory used by a set of config variable settings. | |
| 76 | */ | |
| 77 | void | |
| 78 | config_vars_free(struct config_vars *cvs) | |
| 79 | { | |
| 80 | if (cvs == NULL) | |
| 81 | return; | |
| 82 | ||
| 83 | aura_dict_free(cvs->d); | |
| 84 | ||
| 85 | AURA_FREE(cvs, config_vars); | |
| 86 | } | |
| 87 | ||
| 88 | /* | |
| 89 | * Get the value of a configuration variable in a set of settings | |
| 90 | * and return it, or a (constant) 0-length string if not found. | |
| 91 | */ | |
| 92 | const char * | |
| 93 | config_var_get(const struct config_vars *cvs, const char *name) | |
| 94 | { | |
| 95 | void *rv; | |
| 96 | size_t rv_len; | |
| 97 | ||
| 98 | aura_dict_fetch(cvs->d, name, strlen(name) + 1, &rv, &rv_len); | |
| 99 | if (rv == NULL) | |
| 100 | return(""); | |
| 101 | else | |
| 102 | return(rv); | |
| 103 | } | |
| 104 | ||
| 105 | /* | |
| 106 | * Set the value of a configuration variable. If the named variable | |
| 107 | * does not exist within the given set, a new one is created. | |
| 108 | */ | |
| 109 | int | |
| 110 | config_var_set(struct config_vars *cvs, const char *name, const char *value) | |
| 111 | { | |
| 112 | aura_dict_store(cvs->d, | |
| 113 | name, strlen(name) + 1, | |
| 114 | value, strlen(value) + 1); | |
| 115 | return(1); | |
| 116 | } | |
| 117 | ||
| 118 | /* | |
| 119 | * Write a set of configuration variable settings to a file. | |
| 120 | */ | |
| 121 | int | |
| 10f4bf95 SW |
122 | config_vars_write(const struct config_vars *cvs, int config_type, |
| 123 | const char *fmt, ...) | |
| 337ad0df DH |
124 | { |
| 125 | FILE *f; | |
| 126 | va_list args; | |
| 127 | char *filename; | |
| 337ad0df DH |
128 | void *rk, *rv; |
| 129 | size_t rk_len, rv_len; | |
| 130 | ||
| 131 | va_start(args, fmt); | |
| 132 | vasprintf(&filename, fmt, args); | |
| 133 | va_end(args); | |
| 134 | ||
| 135 | if ((f = fopen(filename, "a")) == NULL) | |
| 136 | return(0); | |
| 137 | ||
| 337ad0df DH |
138 | switch (config_type) { |
| 139 | case CONFIG_TYPE_SH: | |
| 140 | ||
| 141 | aura_dict_rewind(cvs->d); | |
| 142 | while (!aura_dict_eof(cvs->d)) { | |
| 337ad0df DH |
143 | aura_dict_get_current_key(cvs->d, &rk, &rk_len), |
| 144 | aura_dict_fetch(cvs->d, rk, rk_len, &rv, &rv_len); | |
| 10f4bf95 SW |
145 | fprintf(f, "%s=\"%s\"\t# via installer configuration\n", |
| 146 | (char *)rk, (char *)rv); | |
| 337ad0df DH |
147 | aura_dict_next(cvs->d); |
| 148 | } | |
| 337ad0df DH |
149 | break; |
| 150 | case CONFIG_TYPE_RESOLV: | |
| 151 | aura_dict_rewind(cvs->d); | |
| 152 | while (!aura_dict_eof(cvs->d)) { | |
| 153 | aura_dict_get_current_key(cvs->d, &rk, &rk_len), | |
| 154 | aura_dict_fetch(cvs->d, rk, rk_len, &rv, &rv_len); | |
| 155 | fprintf(f, "%s\t\t%s\n", (char *)rk, (char *)rv); | |
| 156 | aura_dict_next(cvs->d); | |
| 157 | } | |
| 158 | break; | |
| 159 | default: | |
| 160 | fclose(f); | |
| 161 | return(0); | |
| 162 | } | |
| 21c1c48a | 163 | |
| 337ad0df DH |
164 | fclose(f); |
| 165 | return(1); | |
| 166 | } | |
| 167 | ||
| 168 | /* | |
| 169 | * Read variables from a file. | |
| 170 | * Returns 1 if the variables could be read successfully, 0 if not. | |
| 171 | */ | |
| 172 | int | |
| 173 | config_vars_read(struct i_fn_args *a, struct config_vars *cvs, | |
| 174 | int config_type __unused, const char *fmt, ...) | |
| 175 | { | |
| 176 | struct commands *cmds; | |
| 177 | char *filename, *tmp_filename, line[1024], *value; | |
| 178 | FILE *f, *script; | |
| 179 | va_list args; | |
| 180 | ||
| 181 | va_start(args, fmt); | |
| 182 | vasprintf(&filename, fmt, args); | |
| 183 | va_end(args); | |
| 184 | ||
| 185 | asprintf(&tmp_filename, "%sextract_vars", a->tmp); | |
| 186 | script = fopen(tmp_filename, "w"); | |
| 187 | free(tmp_filename); | |
| 188 | if (script == NULL) | |
| 189 | return(0); | |
| 21c1c48a | 190 | |
| 337ad0df DH |
191 | fprintf(script, "set | %susr/bin/sort >%senv.before\n", a->os_root, a->tmp); |
| 192 | fprintf(script, ". %s%s\n", a->os_root, filename); | |
| 193 | fprintf(script, "set | %susr/bin/sort >%senv.after\n", a->os_root, a->tmp); | |
| 194 | fprintf(script, "%susr/bin/comm -1 -3 %senv.before %senv.after | \\\n", | |
| 195 | a->os_root, a->tmp, a->tmp); | |
| 196 | fprintf(script, " %susr/bin/awk -F= '{ print $1 }' | \\\n", a->os_root); | |
| 197 | fprintf(script, " while read __VARNAME; do\n"); | |
| 198 | fprintf(script, " echo -n ${__VARNAME}=\n"); | |
| 199 | fprintf(script, " eval echo ' $'${__VARNAME}\n"); | |
| 200 | fprintf(script, " done\n"); | |
| 201 | fprintf(script, "%sbin/rm -f %senv.before %senv.after\n", | |
| 202 | a->os_root, a->tmp, a->tmp); | |
| 203 | fclose(script); | |
| 204 | ||
| 205 | cmds = commands_new(); | |
| 9b76398f SW |
206 | command_add(cmds, "%sbin/sh %sextract_vars >%sextracted_vars.txt", |
| 207 | a->os_root, a->tmp, a->tmp); | |
| 337ad0df DH |
208 | temp_file_add(a, "extracted_vars.txt"); |
| 209 | if (!commands_execute(a, cmds)) { | |
| 210 | commands_free(cmds); | |
| 211 | return(0); | |
| 212 | } | |
| 213 | commands_free(cmds); | |
| 214 | ||
| 215 | /* | |
| 216 | * Delete the script immediately. | |
| 217 | */ | |
| 218 | asprintf(&tmp_filename, "%sextract_vars", a->tmp); | |
| 219 | (void)unlink(tmp_filename); /* not much we can do if it fails */ | |
| 220 | free(tmp_filename); | |
| 221 | ||
| 222 | asprintf(&tmp_filename, "%sextracted_vars.txt", a->tmp); | |
| 223 | f = fopen(tmp_filename, "r"); | |
| 224 | free(tmp_filename); | |
| 225 | if (f == NULL) | |
| 226 | return(0); | |
| 227 | while (fgets(line, 1024, f) != NULL) { | |
| 228 | if (strlen(line) > 0) | |
| 229 | line[strlen(line) - 1] = '\0'; | |
| 230 | /* split line at first = */ | |
| 231 | for (value = line; *value != '=' && *value != '\0'; value++) | |
| 232 | ; | |
| 233 | if (*value == '\0') | |
| 234 | break; | |
| 235 | *value = '\0'; | |
| 236 | value++; | |
| 237 | config_var_set(cvs, line, value); | |
| 238 | } | |
| 239 | fclose(f); | |
| 240 | ||
| 241 | return(1); | |
| 242 | } |