xref: /dflybsd-src/usr.sbin/installer/libinstaller/confed.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /*
286d7f5d3SJohn Marino  * Copyright (c)2004 The DragonFly Project.  All rights reserved.
386d7f5d3SJohn Marino  *
486d7f5d3SJohn Marino  * Redistribution and use in source and binary forms, with or without
586d7f5d3SJohn Marino  * modification, are permitted provided that the following conditions
686d7f5d3SJohn Marino  * are met:
786d7f5d3SJohn Marino  *
886d7f5d3SJohn Marino  *   Redistributions of source code must retain the above copyright
986d7f5d3SJohn Marino  *   notice, this list of conditions and the following disclaimer.
1086d7f5d3SJohn Marino  *
1186d7f5d3SJohn Marino  *   Redistributions in binary form must reproduce the above copyright
1286d7f5d3SJohn Marino  *   notice, this list of conditions and the following disclaimer in
1386d7f5d3SJohn Marino  *   the documentation and/or other materials provided with the
1486d7f5d3SJohn Marino  *   distribution.
1586d7f5d3SJohn Marino  *
1686d7f5d3SJohn Marino  *   Neither the name of the DragonFly Project nor the names of its
1786d7f5d3SJohn Marino  *   contributors may be used to endorse or promote products derived
1886d7f5d3SJohn Marino  *   from this software without specific prior written permission.
1986d7f5d3SJohn Marino  *
2086d7f5d3SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2186d7f5d3SJohn Marino  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2286d7f5d3SJohn Marino  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2386d7f5d3SJohn Marino  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2486d7f5d3SJohn Marino  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
2586d7f5d3SJohn Marino  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2686d7f5d3SJohn Marino  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2786d7f5d3SJohn Marino  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2886d7f5d3SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2986d7f5d3SJohn Marino  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3086d7f5d3SJohn Marino  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
3186d7f5d3SJohn Marino  * OF THE POSSIBILITY OF SUCH DAMAGE.
3286d7f5d3SJohn Marino  */
3386d7f5d3SJohn Marino 
3486d7f5d3SJohn Marino /*
3586d7f5d3SJohn Marino  * confed.c
3686d7f5d3SJohn Marino  * Functions for working with configuration files.
3786d7f5d3SJohn Marino  * Inspired by (but not derived from) sysinstall's variable.c
3886d7f5d3SJohn Marino  * $Id: confed.c,v 1.16 2005/02/06 21:05:18 cpressey Exp $
3986d7f5d3SJohn Marino  */
4086d7f5d3SJohn Marino 
4186d7f5d3SJohn Marino #include <sys/stat.h>
4286d7f5d3SJohn Marino 
4386d7f5d3SJohn Marino #include <ctype.h>
4486d7f5d3SJohn Marino #include <stdarg.h>
4586d7f5d3SJohn Marino #include <stdio.h>
4686d7f5d3SJohn Marino #include <stdlib.h>
4786d7f5d3SJohn Marino #include <string.h>
4886d7f5d3SJohn Marino #include <time.h>
4986d7f5d3SJohn Marino #include <unistd.h>
5086d7f5d3SJohn Marino 
5186d7f5d3SJohn Marino #include "libaura/mem.h"
5286d7f5d3SJohn Marino #include "libaura/dict.h"
5386d7f5d3SJohn Marino #include "libdfui/system.h"
5486d7f5d3SJohn Marino 
5586d7f5d3SJohn Marino #include "confed.h"
5686d7f5d3SJohn Marino #include "commands.h"
5786d7f5d3SJohn Marino #include "functions.h"
5886d7f5d3SJohn Marino 
5986d7f5d3SJohn Marino /*
6086d7f5d3SJohn Marino  * Create a new, empty set of in-memory config variable settings.
6186d7f5d3SJohn Marino  */
6286d7f5d3SJohn Marino struct config_vars *
config_vars_new(void)6386d7f5d3SJohn Marino config_vars_new(void)
6486d7f5d3SJohn Marino {
6586d7f5d3SJohn Marino 	struct config_vars *cvs;
6686d7f5d3SJohn Marino 
6786d7f5d3SJohn Marino 	AURA_MALLOC(cvs, config_vars);
6886d7f5d3SJohn Marino 
6986d7f5d3SJohn Marino 	cvs->d = aura_dict_new(1, AURA_DICT_SORTED_LIST);
7086d7f5d3SJohn Marino 
7186d7f5d3SJohn Marino 	return(cvs);
7286d7f5d3SJohn Marino }
7386d7f5d3SJohn Marino 
7486d7f5d3SJohn Marino /*
7586d7f5d3SJohn Marino  * Deallocate the memory used by a set of config variable settings.
7686d7f5d3SJohn Marino  */
7786d7f5d3SJohn Marino void
config_vars_free(struct config_vars * cvs)7886d7f5d3SJohn Marino config_vars_free(struct config_vars *cvs)
7986d7f5d3SJohn Marino {
8086d7f5d3SJohn Marino 	if (cvs == NULL)
8186d7f5d3SJohn Marino 		return;
8286d7f5d3SJohn Marino 
8386d7f5d3SJohn Marino 	aura_dict_free(cvs->d);
8486d7f5d3SJohn Marino 
8586d7f5d3SJohn Marino 	AURA_FREE(cvs, config_vars);
8686d7f5d3SJohn Marino }
8786d7f5d3SJohn Marino 
8886d7f5d3SJohn Marino /*
8986d7f5d3SJohn Marino  * Get the value of a configuration variable in a set of settings
9086d7f5d3SJohn Marino  * and return it, or a (constant) 0-length string if not found.
9186d7f5d3SJohn Marino  */
9286d7f5d3SJohn Marino const char *
config_var_get(const struct config_vars * cvs,const char * name)9386d7f5d3SJohn Marino config_var_get(const struct config_vars *cvs, const char *name)
9486d7f5d3SJohn Marino {
9586d7f5d3SJohn Marino 	void *rv;
9686d7f5d3SJohn Marino 	size_t rv_len;
9786d7f5d3SJohn Marino 
9886d7f5d3SJohn Marino 	aura_dict_fetch(cvs->d, name, strlen(name) + 1, &rv, &rv_len);
9986d7f5d3SJohn Marino 	if (rv == NULL)
10086d7f5d3SJohn Marino 		return("");
10186d7f5d3SJohn Marino 	else
10286d7f5d3SJohn Marino 		return(rv);
10386d7f5d3SJohn Marino }
10486d7f5d3SJohn Marino 
10586d7f5d3SJohn Marino /*
10686d7f5d3SJohn Marino  * Set the value of a configuration variable.  If the named variable
10786d7f5d3SJohn Marino  * does not exist within the given set, a new one is created.
10886d7f5d3SJohn Marino  */
10986d7f5d3SJohn Marino int
config_var_set(struct config_vars * cvs,const char * name,const char * value)11086d7f5d3SJohn Marino config_var_set(struct config_vars *cvs, const char *name, const char *value)
11186d7f5d3SJohn Marino {
11286d7f5d3SJohn Marino 	aura_dict_store(cvs->d,
11386d7f5d3SJohn Marino 	    name, strlen(name) + 1,
11486d7f5d3SJohn Marino 	    value, strlen(value) + 1);
11586d7f5d3SJohn Marino 	return(1);
11686d7f5d3SJohn Marino }
11786d7f5d3SJohn Marino 
11886d7f5d3SJohn Marino /*
11986d7f5d3SJohn Marino  * Write a set of configuration variable settings to a file.
12086d7f5d3SJohn Marino  */
12186d7f5d3SJohn Marino int
config_vars_write(const struct config_vars * cvs,int config_type,const char * fmt,...)12286d7f5d3SJohn Marino config_vars_write(const struct config_vars *cvs, int config_type,
12386d7f5d3SJohn Marino     const char *fmt, ...)
12486d7f5d3SJohn Marino {
12586d7f5d3SJohn Marino 	FILE *f;
12686d7f5d3SJohn Marino 	va_list args;
12786d7f5d3SJohn Marino 	char *filename;
12886d7f5d3SJohn Marino 	void *rk, *rv;
12986d7f5d3SJohn Marino 	size_t rk_len, rv_len;
13086d7f5d3SJohn Marino 
13186d7f5d3SJohn Marino 	va_start(args, fmt);
13286d7f5d3SJohn Marino 	vasprintf(&filename, fmt, args);
13386d7f5d3SJohn Marino 	va_end(args);
13486d7f5d3SJohn Marino 
13586d7f5d3SJohn Marino 	if ((f = fopen(filename, "a")) == NULL)
13686d7f5d3SJohn Marino 		return(0);
13786d7f5d3SJohn Marino 
13886d7f5d3SJohn Marino 	switch (config_type) {
13986d7f5d3SJohn Marino 	case CONFIG_TYPE_SH:
14086d7f5d3SJohn Marino 
14186d7f5d3SJohn Marino 		aura_dict_rewind(cvs->d);
14286d7f5d3SJohn Marino 		while (!aura_dict_eof(cvs->d)) {
14386d7f5d3SJohn Marino 			aura_dict_get_current_key(cvs->d, &rk, &rk_len),
14486d7f5d3SJohn Marino 			aura_dict_fetch(cvs->d, rk, rk_len, &rv, &rv_len);
14586d7f5d3SJohn Marino 			fprintf(f, "%s=\"%s\"\t# via installer configuration\n",
14686d7f5d3SJohn Marino 			    (char *)rk, (char *)rv);
14786d7f5d3SJohn Marino 			aura_dict_next(cvs->d);
14886d7f5d3SJohn Marino 		}
14986d7f5d3SJohn Marino 		break;
15086d7f5d3SJohn Marino 	case CONFIG_TYPE_RESOLV:
15186d7f5d3SJohn Marino 		aura_dict_rewind(cvs->d);
15286d7f5d3SJohn Marino 		while (!aura_dict_eof(cvs->d)) {
15386d7f5d3SJohn Marino 			aura_dict_get_current_key(cvs->d, &rk, &rk_len),
15486d7f5d3SJohn Marino 			aura_dict_fetch(cvs->d, rk, rk_len, &rv, &rv_len);
15586d7f5d3SJohn Marino 			fprintf(f, "%s\t\t%s\n", (char *)rk, (char *)rv);
15686d7f5d3SJohn Marino 			aura_dict_next(cvs->d);
15786d7f5d3SJohn Marino 		}
15886d7f5d3SJohn Marino 		break;
15986d7f5d3SJohn Marino 	default:
16086d7f5d3SJohn Marino 		fclose(f);
16186d7f5d3SJohn Marino 		return(0);
16286d7f5d3SJohn Marino 	}
16386d7f5d3SJohn Marino 
16486d7f5d3SJohn Marino 	fclose(f);
16586d7f5d3SJohn Marino 	return(1);
16686d7f5d3SJohn Marino }
16786d7f5d3SJohn Marino 
16886d7f5d3SJohn Marino /*
16986d7f5d3SJohn Marino  * Read variables from a file.
17086d7f5d3SJohn Marino  * Returns 1 if the variables could be read successfully, 0 if not.
17186d7f5d3SJohn Marino  */
17286d7f5d3SJohn Marino int
config_vars_read(struct i_fn_args * a,struct config_vars * cvs,int config_type __unused,const char * fmt,...)17386d7f5d3SJohn Marino config_vars_read(struct i_fn_args *a, struct config_vars *cvs,
17486d7f5d3SJohn Marino 		 int config_type __unused, const char *fmt, ...)
17586d7f5d3SJohn Marino {
17686d7f5d3SJohn Marino 	struct commands *cmds;
17786d7f5d3SJohn Marino 	char *filename, *tmp_filename, line[1024], *value;
17886d7f5d3SJohn Marino 	FILE *f, *script;
17986d7f5d3SJohn Marino 	va_list args;
18086d7f5d3SJohn Marino 
18186d7f5d3SJohn Marino 	va_start(args, fmt);
18286d7f5d3SJohn Marino 	vasprintf(&filename, fmt, args);
18386d7f5d3SJohn Marino 	va_end(args);
18486d7f5d3SJohn Marino 
18586d7f5d3SJohn Marino 	asprintf(&tmp_filename, "%sextract_vars", a->tmp);
18686d7f5d3SJohn Marino 	script = fopen(tmp_filename, "w");
18786d7f5d3SJohn Marino 	free(tmp_filename);
18886d7f5d3SJohn Marino 	if (script == NULL)
18986d7f5d3SJohn Marino 		return(0);
19086d7f5d3SJohn Marino 
19186d7f5d3SJohn Marino 	fprintf(script, "set | %susr/bin/sort >%senv.before\n", a->os_root, a->tmp);
19286d7f5d3SJohn Marino 	fprintf(script, ". %s%s\n", a->os_root, filename);
19386d7f5d3SJohn Marino 	fprintf(script, "set | %susr/bin/sort >%senv.after\n", a->os_root, a->tmp);
19486d7f5d3SJohn Marino 	fprintf(script, "%susr/bin/comm -1 -3 %senv.before %senv.after | \\\n",
19586d7f5d3SJohn Marino 	    a->os_root, a->tmp, a->tmp);
19686d7f5d3SJohn Marino 	fprintf(script, "    %susr/bin/awk -F= '{ print $1 }' | \\\n", a->os_root);
19786d7f5d3SJohn Marino 	fprintf(script, "    while read __VARNAME; do\n");
19886d7f5d3SJohn Marino 	fprintf(script, "        echo -n ${__VARNAME}=\n");
19986d7f5d3SJohn Marino 	fprintf(script, "        eval echo ' $'${__VARNAME}\n");
20086d7f5d3SJohn Marino 	fprintf(script, "    done\n");
20186d7f5d3SJohn Marino 	fprintf(script, "%sbin/rm -f %senv.before %senv.after\n",
20286d7f5d3SJohn Marino 	    a->os_root, a->tmp, a->tmp);
20386d7f5d3SJohn Marino 	fclose(script);
20486d7f5d3SJohn Marino 
20586d7f5d3SJohn Marino 	cmds = commands_new();
20686d7f5d3SJohn Marino 	command_add(cmds, "%sbin/sh %sextract_vars >%sextracted_vars.txt",
20786d7f5d3SJohn Marino 	    a->os_root, a->tmp, a->tmp);
20886d7f5d3SJohn Marino 	temp_file_add(a, "extracted_vars.txt");
20986d7f5d3SJohn Marino 	if (!commands_execute(a, cmds)) {
21086d7f5d3SJohn Marino 		commands_free(cmds);
21186d7f5d3SJohn Marino 		return(0);
21286d7f5d3SJohn Marino 	}
21386d7f5d3SJohn Marino 	commands_free(cmds);
21486d7f5d3SJohn Marino 
21586d7f5d3SJohn Marino 	/*
21686d7f5d3SJohn Marino 	 * Delete the script immediately.
21786d7f5d3SJohn Marino 	 */
21886d7f5d3SJohn Marino 	asprintf(&tmp_filename, "%sextract_vars", a->tmp);
21986d7f5d3SJohn Marino 	(void)unlink(tmp_filename);	/* not much we can do if it fails */
22086d7f5d3SJohn Marino 	free(tmp_filename);
22186d7f5d3SJohn Marino 
22286d7f5d3SJohn Marino 	asprintf(&tmp_filename, "%sextracted_vars.txt", a->tmp);
22386d7f5d3SJohn Marino 	f = fopen(tmp_filename, "r");
22486d7f5d3SJohn Marino 	free(tmp_filename);
22586d7f5d3SJohn Marino 	if (f == NULL)
22686d7f5d3SJohn Marino 		return(0);
22786d7f5d3SJohn Marino 	while (fgets(line, 1024, f) != NULL) {
22886d7f5d3SJohn Marino 		if (strlen(line) > 0)
22986d7f5d3SJohn Marino 			line[strlen(line) - 1] = '\0';
23086d7f5d3SJohn Marino 		/* split line at first = */
23186d7f5d3SJohn Marino 		for (value = line; *value != '=' && *value != '\0'; value++)
23286d7f5d3SJohn Marino 			;
23386d7f5d3SJohn Marino 		if (*value == '\0')
23486d7f5d3SJohn Marino 			break;
23586d7f5d3SJohn Marino 		*value = '\0';
23686d7f5d3SJohn Marino 		value++;
23786d7f5d3SJohn Marino 		config_var_set(cvs, line, value);
23886d7f5d3SJohn Marino 	}
23986d7f5d3SJohn Marino 	fclose(f);
24086d7f5d3SJohn Marino 
24186d7f5d3SJohn Marino 	return(1);
24286d7f5d3SJohn Marino }
243