File: conffile.c

package info (click to toggle)
debfoster 2.7-2.1
  • links: PTS
  • area: main
  • in suites: bullseye, buster, sid, stretch
  • size: 1,188 kB
  • sloc: sh: 4,243; ansic: 2,397; perl: 39; makefile: 26; sed: 16
file content (154 lines) | stat: -rw-r--r-- 4,383 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

#include "AVLTree.h"
#include "error.h"
#include "conffile.h"
#include "status.h"
#include "config.h"
#include "intl.h"

#define READBUF 4096

/* Various files */
#define KEEPERS VAR"/lib/debfoster/keepers"
#define STATUSFILE VAR"/lib/dpkg/status"
#define AVAILABLEFILE VAR"/lib/dpkg/available"
#define CONFIG_FILE ETC"/debfoster.conf"

/* Only simple space-separated arguments can be given */
#define INSTALLCOMMAND "apt-get install"
#define REMOVECOMMAND "apt-get --purge remove"
#define INFOCOMMAND "dpkg -s"

/* Default policies for packages */
#define MAXPRIORITY "standard"

static AVLTree *options = NULL;

#define StringConfigVal(s) const char *s = NULL; \
	static void set_##s(const char *str) { s = xstrdup(str); }

static void set_bool(int *holder, const char *val) {
	if(!strcasecmp(val, "y") || !strcasecmp(val, "yes")
	|| !strcasecmp(val, "t") || !strcasecmp(val, "true")
	|| !strcasecmp(val, "1") || !strcasecmp(val, "on"))
		*holder = 1;
	else if(!strcasecmp(val, "n") || !strcasecmp(val, "no")
 	     || !strcasecmp(val, "f") || !strcasecmp(val, "false")
 	     || !strcasecmp(val, "0") || !strcasecmp(val, "off"))
		*holder = 0;
	else error_exit(ERROR_CONFIG, _("Not a truth value: \"%s\"\n"), val);
}

#define BoolConfigVal(b) int b = 0; \
	static void set_##b(const char *str) { set_bool(&b, str); }

StringConfigVal(KeeperFile)
StringConfigVal(DpkgStatus)
StringConfigVal(DpkgAvailable)
StringConfigVal(InstallCmd)
StringConfigVal(RemoveCmd)
StringConfigVal(InfoCmd)
StringConfigVal(MaxPriority)
StringConfigVal(KeepSections)
StringConfigVal(NokeepSections)
StringConfigVal(GuessDepends)

BoolConfigVal(UseHold)
BoolConfigVal(UseEssential)
BoolConfigVal(UsePreDepends)
BoolConfigVal(UseRecommends)
BoolConfigVal(UseSuggests)
BoolConfigVal(UseTasks)

BoolConfigVal(NegativeKeepers)

BoolConfigVal(Quiet)
BoolConfigVal(Force)
BoolConfigVal(Verbose)

static int optcmp(const option_t a, const option_t b) {
	return strcasecmp(a->key, b->key);
}

option_t find_option(const char *key) {
	struct option_t o;
	AVLNode *c;

	o.key = key;

	c = AVLSearch(options, &o);

	return c?c->item:NULL;
}

static void add_option(const char *key, void (*set)(const char *), const char *def) {
	option_t o;
	o = xmalloc(sizeof *o);
	o->key = xstrdup(key);
	o->set = set;
	set(def);
	if(!AVLInsert(options, o))
		perror_exit(ERROR_CONFIG, key);
}

void readconfig(const char *config) {
	FILE *f;
	char buf[READBUF];
	option_t o;
	char *key, *value;
	int lineno = 0;

	if(!config)
		config = CONFIG_FILE;

	options = AVLAllocTree((AVLCompare)optcmp);

	/* Seed tree with defaults for all options */
	add_option("KeeperFile",    set_KeeperFile,    KEEPERS);
	add_option("DpkgStatus",    set_DpkgStatus,    STATUSFILE);
	add_option("DpkgAvailable", set_DpkgAvailable, AVAILABLEFILE);
	add_option("InstallCmd",    set_InstallCmd,    INSTALLCOMMAND);
	add_option("RemoveCmd",     set_RemoveCmd,     REMOVECOMMAND);
	add_option("InfoCmd",       set_InfoCmd,       INFOCOMMAND);
	add_option("MaxPriority",   set_MaxPriority,   MAXPRIORITY);
	add_option("KeepSections",  set_KeepSections,  "");
	add_option("NokeepSections",  set_NokeepSections, "");
	add_option("GuessDepends",  set_GuessDepends, "");

	add_option("UseHold",       set_UseHold,       "yes");
	add_option("UseEssential",  set_UseEssential,  "yes");
	add_option("UsePreDepends", set_UsePreDepends, "yes");
	add_option("UseRecommends", set_UseRecommends, "yes");
	add_option("UseSuggests",   set_UseSuggests,   "no");
	add_option("UseTasks",      set_UseTasks,      "no");

	add_option("NegativeKeepers", set_NegativeKeepers, "no");

	add_option("Quiet",         set_Quiet,         "no");
	add_option("Force",         set_Force,         "no");
	add_option("Verbose",       set_Verbose,       "no");

	/* Read the options but fail if there's no default for it */
	f = fopen(config, "r");
	if(f) {
		while(fgets(buf, READBUF, f)) {
			lineno++;
			key = chop(buf);
			if(*key && *key != '#') {
				value = strchr(key, '=');
				if(!value)
					error_exit(ERROR_CONFIG, _("Syntax error in %s:%d\n"), CONFIG_FILE, lineno);
				*value++ = '\0';
				key = chop(key);
				if(!(o = find_option(key)))
					error_exit(ERROR_CONFIG, _("Unknown option `%s' at %s:%d\n"), key, CONFIG_FILE, lineno);
				o->set(chop(value));
			}
		}
	}
}