136
#define CFG_GET_BOOL_DEFAULT(setting,key,var,def) \
139
config_setting_lookup_bool((setting), (key), &(var));
140
#define CFG_GET_STRING_DEFAULT(setting,key,var,def) \
143
config_setting_lookup_string((setting), (key), (const char **) &(var)); \
144
if(var != NULL) var = g_strdup(var);
146
gboolean loadConfig(char *filename, CfgFile *lcfg) {
151
if(config_read_file(&hcfg, filename) == CONFIG_FALSE) {
152
#ifdef HAVE_LIBCONFIG_ERROR_MACROS
153
const char *efn = config_error_file(&hcfg);
154
g_printerr ("Error reading config file [%s:%d]: %s\n", (efn ? efn : filename), config_error_line(&hcfg), config_error_text(&hcfg));
156
g_printerr ("Error reading config file %s!\n", filename);
158
config_destroy(&hcfg);
162
#define GETREQ_SETTING_T(varn, sectn) \
163
config_setting_t *(varn) = config_lookup(&hcfg, (sectn)); \
165
g_error ("Missing section %s in config file %s!", (sectn), filename); \
166
config_destroy(&hcfg); \
170
// config_setting_t *s_ssh = config_lookup(&hcfg, "SSH");
171
GETREQ_SETTING_T(s_ssh, "SSH");
172
config_setting_t *s_paths = config_lookup(&hcfg, "Paths");
173
config_setting_t *s_screen = config_lookup(&hcfg, "Screen");
174
config_setting_t *s_appearance = config_lookup(&hcfg, "Appearance");
175
config_setting_t *s_notify = config_lookup(&hcfg, "Notify");
176
config_setting_t *s_hooks = config_lookup(&hcfg, "Hooks");
132
xmlXPathObjectPtr evalXPath(xmlXPathContextPtr context, const gchar *xpath) {
133
xmlXPathObjectPtr result = xmlXPathEvalExpression(BAD_CAST(xpath), context);
135
g_warning("xmlXPathEvalExpression '%s' failed!\n", xpath);
142
char *getXPropStr(const xmlNodePtr nodes[], const gchar *attr, const gchar *defval) {
146
for(i = 0; nodes[i]; i++) {
147
val = xmlGetProp(nodes[i], BAD_CAST(attr));
150
gchar *ret = g_strdup((gchar *)val);
157
return g_strdup(defval);
162
int getXPropInt(const xmlNodePtr nodes[], const gchar *attr, const int defval) {
163
gchar *sval = getXPropStr(nodes, attr, NULL);
168
int ival = atoi(sval);
175
int getXPropBool(const xmlNodePtr nodes[], const gchar *attr, const gboolean defval) {
176
gchar *val = getXPropStr(nodes, attr, NULL);
182
if(g_ascii_strncasecmp(val, "false", 1) == 0 ||
183
g_ascii_strncasecmp(val, "no", 1) == 0) {
188
if(g_ascii_strncasecmp(val, "true", 1) == 0 ||
189
g_ascii_strncasecmp(val, "yes", 1) == 0) {
203
xmlNodeSetPtr getXNodes(xmlXPathContextPtr context, const gchar *xpath) {
204
xmlXPathObjectPtr xobj = xmlXPathEvalExpression(BAD_CAST(xpath), context);
205
xmlNodeSetPtr ret = xobj->nodesetval;
206
xmlXPathFreeNodeSetList(xobj);
211
xmlNodePtr getXNode(xmlXPathContextPtr context, const gchar *xpath) {
212
xmlNodeSetPtr set = getXNodes(context, xpath);
213
xmlNodePtr ret = NULL;
215
if(!xmlXPathNodeSetIsEmpty(set))
216
ret = set->nodeTab[0];
218
xmlXPathFreeNodeSet(set);
222
gboolean loadConfig(const gchar *filename, CfgFile *lcfg) {
223
/* Parse hosts.xml document. */
224
xmlDocPtr xcfg = xmlParseFile(filename);
228
/* Allocate XPath context. */
229
xmlXPathContextPtr xctx = xmlXPathNewContext(xcfg);
231
g_error("%s: xmlXPathNewContext failed!\n", filename);
235
xmlNodePtr s_ssh[2] = {getXNode(xctx, "/apt-dater/ssh"), NULL};
236
xmlNodePtr s_path[2] = {getXNode(xctx, "/apt-dater/paths"), NULL};
237
xmlNodePtr s_screen[2] = {getXNode(xctx, "/apt-dater/screen"), NULL};
238
xmlNodePtr s_appearance[2] = {getXNode(xctx, "/apt-dater/appearance"), NULL};
239
xmlNodePtr s_notify[2] = {getXNode(xctx, "/apt-dater/notify"), NULL};
240
xmlNodePtr s_hooks[2] = {getXNode(xctx, "/apt-dater/hooks"), NULL};
177
241
#ifdef FEAT_AUTOREF
178
config_setting_t *s_autoref = config_lookup(&hcfg, "AutoRef");
242
xmlNodePtr s_autoref[2] = {getXNode(xctx, "/apt-dater/auto-ref"), NULL};
180
244
#ifdef FEAT_HISTORY
181
config_setting_t *s_history = config_lookup(&hcfg, "History");
245
xmlNodePtr s_history[2] = {getXNode(xctx, "/apt-dater/history"), NULL};
183
247
#ifdef FEAT_TCLFILTER
184
config_setting_t *s_tclfilter = config_lookup(&hcfg, "TCLFilter");
248
xmlNodePtr s_tclfilter[2] = {getXNode(xctx, "/apt-dater/tcl-filter"), NULL};
188
config_setting_lookup_string(s_ssh, "OptionalCmdFlags", (const char **) &h);
189
lcfg->ssh_optflags = (h ? g_strdup(h) : NULL);
251
lcfg->ssh_optflags = getXPropStr(s_ssh, "opt-cmd-flags", NULL);
252
lcfg->ssh_cmd = getXPropStr(s_ssh, "cmd", "/usr/bin/ssh");
253
lcfg->sftp_cmd = getXPropStr(s_ssh, "sftp-cmd", "/usr/bin/sftp");
191
CFG_GET_STRING_DEFAULT(s_paths, "HostsFile", lcfg->hostsfile, g_strdup_printf("%s/%s/%s", g_get_user_config_dir(), PROG_NAME, "hosts.config"));
192
CFG_GET_STRING_DEFAULT(s_paths, "StatsDir", lcfg->statsdir, g_strdup_printf("%s/%s/%s", g_get_user_cache_dir(), PROG_NAME, "stats"));
255
lcfg->hostsfile = getXPropStr(s_path, "hosts-file", g_strdup_printf("%s/%s/%s", g_get_user_config_dir(), PROG_NAME, "hosts.xml"));
256
lcfg->statsdir = getXPropStr(s_path, "stats-dir", g_strdup_printf("%s/%s/%s", g_get_user_cache_dir(), PROG_NAME, "stats"));
193
257
g_mkdir_with_parents(lcfg->statsdir, S_IRWXU | S_IRWXG | S_IRWXO);
195
CFG_GET_STRING_DEFAULT(s_screen, "RCFile", lcfg->screenrcfile, g_strdup_printf("%s/%s/%s", g_get_user_config_dir(), PROG_NAME, "screenrc"));
196
CFG_GET_STRING_DEFAULT(s_screen, "Title", lcfg->screentitle, g_strdup("%m # %U%H"));
199
if(config_setting_lookup_string(s_ssh, "Cmd", (const char **) &h) == CONFIG_FALSE) {
200
g_printerr ("%s: Config option SSH.Cmd not set!", filename);
203
lcfg->ssh_cmd = g_strdup(h);
206
if(config_setting_lookup_string(s_ssh, "SFTPCmd", (const char **) &h) == CONFIG_FALSE) {
207
g_printerr ("%s: Config option SSH.SFTPCmd not set!", filename);
210
lcfg->sftp_cmd = g_strdup(h);
212
config_setting_lookup_bool(s_ssh, "SpawnAgent", &(lcfg->ssh_agent));
214
config_setting_t *s_addkeys = config_setting_get_member(s_ssh, "AddKeys");
215
if(s_addkeys != NULL) {
216
if(config_setting_type(s_addkeys) == CONFIG_TYPE_STRING) {
217
lcfg->ssh_add = g_new0(char*, 2);
218
lcfg->ssh_add[0] = g_strdup(config_setting_get_string(s_addkeys));
220
else if(config_setting_type(s_addkeys) == CONFIG_TYPE_ARRAY) {
221
int len = config_setting_length(s_addkeys);
224
lcfg->ssh_add = g_new0(char*, len + 1);
225
for(i = 0; i<len; i++) {
226
config_setting_t *e = config_setting_get_elem(s_addkeys, i++);
227
lcfg->ssh_add[i] = g_strdup(config_setting_get_string(e));
231
g_printerr ("%s: setting %s must be a single string or an array of strings", filename, config_setting_name(s_addkeys));
235
CFG_GET_BOOL_DEFAULT(s_screen, "NoDumps", lcfg->dump_screen, FALSE);
236
lcfg->dump_screen = !lcfg->dump_screen;
238
CFG_GET_BOOL_DEFAULT(s_screen, "QueryMaintainer", lcfg->query_maintainer, FALSE);
241
if(config_setting_lookup_string(s_appearance, "Colors", (const char **) &h) != CONFIG_FALSE)
242
lcfg->colors = g_strsplit(h, ";", -1);
259
lcfg->screenrcfile = getXPropStr(s_screen, "rc-file", g_strdup_printf("%s/%s/%s", g_get_user_config_dir(), PROG_NAME, "screenrc"));
260
lcfg->screentitle = getXPropStr(s_screen, "title", g_strdup("%m # %U%H"));
263
lcfg->ssh_agent = getXPropBool(s_ssh, "spawn-agent", FALSE);
265
xmlNodeSetPtr s_addkeys = getXNodes(xctx, "/apt-dater/ssh/add-key");
266
if(!xmlXPathNodeSetIsEmpty(s_addkeys)) {
267
lcfg->ssh_add = g_new0(char*, s_addkeys->nodeNr + 1);
269
for(i = 0; i < s_addkeys->nodeNr; i++) {
270
lcfg->ssh_add[i] = g_strdup((gchar *)xmlGetProp(s_addkeys->nodeTab[i], BAD_CAST("name")));
273
xmlXPathFreeNodeSet(s_addkeys);
275
lcfg->dump_screen = !getXPropBool(s_screen, "no-dumps", FALSE);
276
lcfg->query_maintainer = getXPropBool(s_screen, "query-maintainer", FALSE);
278
gchar *colors = getXPropStr(s_appearance, "colors", "menu brightgreen blue;status brightgreen blue;selector black red;");
280
lcfg->colors = g_strsplit(colors, ";", -1);
244
282
#ifdef FEAT_TCLFILTER
245
config_setting_lookup_string(&s_tclfilter, "FilterExp", &(lcfg->filterexp));
246
config_setting_lookup_string(&s_tclfilter, "FilterFile", &(lcfg->filterfile));
283
lcfg->filterexp = getXPropStr(s_tclfilter, "filter-exp", NULL);
284
lcfg->filterfile = getXPropStr(s_tclfilter, "filter-file", NULL);
249
287
#ifdef FEAT_AUTOREF
250
CFG_GET_BOOL_DEFAULT(s_autoref, "Enabled", lcfg->auto_refresh, TRUE);
288
lcfg->auto_refresh = getXPropBool(s_autoref, "enabled", TRUE);
253
CFG_GET_BOOL_DEFAULT(s_notify, "Beep", lcfg->beep, TRUE);
254
CFG_GET_BOOL_DEFAULT(s_notify, "Flash", lcfg->flash, TRUE);
291
lcfg->beep = getXPropBool(s_notify, "beep", TRUE);
292
lcfg->flash = getXPropBool(s_notify, "flash", TRUE);
256
294
#ifdef FEAT_HISTORY
257
CFG_GET_BOOL_DEFAULT(s_history, "Record", lcfg->record_history, TRUE);
258
CFG_GET_STRING_DEFAULT(s_history, "ErrPattern", lcfg->history_errpattern, "((?<!no )error|warning|fail)");
295
lcfg->record_history = getXPropBool(s_history, "record", TRUE);
296
lcfg->history_errpattern = getXPropStr(s_history, "err-pattern", "((?<!no )error|warning|fail)");
261
CFG_GET_STRING_DEFAULT(s_hooks, "PreUpgrade", lcfg->hook_pre_upgrade, "/etc/apt-dater/pre-upg.d");
262
CFG_GET_STRING_DEFAULT(s_hooks, "PreRefresh", lcfg->hook_pre_refresh, "/etc/apt-dater/pre-ref.d");
263
CFG_GET_STRING_DEFAULT(s_hooks, "PreInstall", lcfg->hook_pre_install, "/etc/apt-dater/pre-ins.d");
264
CFG_GET_STRING_DEFAULT(s_hooks, "PreConnect", lcfg->hook_pre_connect, "/etc/apt-dater/pre-con.d");
266
CFG_GET_STRING_DEFAULT(s_hooks, "PostUpgrade", lcfg->hook_post_upgrade, "/etc/apt-dater/post-upg.d");
267
CFG_GET_STRING_DEFAULT(s_hooks, "PostRefresh", lcfg->hook_post_refresh, "/etc/apt-dater/post-ref.d");
268
CFG_GET_STRING_DEFAULT(s_hooks, "PostInstall", lcfg->hook_post_install, "/etc/apt-dater/post-ins.d");
269
CFG_GET_STRING_DEFAULT(s_hooks, "PostConnect", lcfg->hook_post_connect, "/etc/apt-dater/post-con.d");
271
CFG_GET_STRING_DEFAULT(s_hooks, "PluginDir", lcfg->plugindir, "/etc/apt-dater/plugins");
274
config_destroy(&hcfg);
299
lcfg->hook_pre_upgrade = getXPropStr(s_hooks, "pre-upgrade", "/etc/apt-dater/pre-upg.d");
300
lcfg->hook_pre_refresh = getXPropStr(s_hooks, "pre-refresh", "/etc/apt-dater/pre-ref.d");
301
lcfg->hook_pre_install = getXPropStr(s_hooks, "pre-install", "/etc/apt-dater/pre-ins.d");
302
lcfg->hook_pre_connect = getXPropStr(s_hooks, "pre-connect", "/etc/apt-dater/pre-con.d");
304
lcfg->hook_post_upgrade = getXPropStr(s_hooks, "post-upgrade", "/etc/apt-dater/post-upg.d");
305
lcfg->hook_post_refresh = getXPropStr(s_hooks, "post-refresh", "/etc/apt-dater/post-ref.d");
306
lcfg->hook_post_install = getXPropStr(s_hooks, "post-install", "/etc/apt-dater/post-ins.d");
307
lcfg->hook_post_connect = getXPropStr(s_hooks, "post-connect", "/etc/apt-dater/post-con.d");
309
lcfg->plugindir = getXPropStr(s_hooks, "plugin-dir", "/etc/apt-dater/plugins");
278
#define HCFG_GET_STRING(setting,var,def) \
280
if(config_setting_lookup_string( cfghost, (setting), (const char **) &var) == CONFIG_FALSE) \
281
if(config_setting_lookup_string(cfggroup, (setting), (const char **) &var) == CONFIG_FALSE) \
282
config_setting_lookup_string(cfghosts, (setting), (const char **) &var); \
283
if(var != NULL) var = g_strdup(var)
285
#define HCFG_GET_INT(setting,var,def) \
287
if(config_setting_lookup_int( cfghost, (setting), &var) == CONFIG_FALSE) \
288
if(config_setting_lookup_int(cfggroup, (setting), &var) == CONFIG_FALSE) \
289
config_setting_lookup_int(cfghosts, (setting), &var)
291
GList *loadHosts (const char *filename) {
295
if(config_read_file(&hcfg, filename) == CONFIG_FALSE) {
296
#ifdef HAVE_LIBCONFIG_ERROR_MACROS
297
const char *efn = config_error_file(&hcfg);
298
g_printerr ("Error reading host file [%s:%d]: %s\n", (efn ? efn : filename), config_error_line(&hcfg), config_error_text(&hcfg));
300
g_printerr ("Error reading host file %s!\n", filename);
302
config_destroy(&hcfg);
306
config_setting_t *cfghosts = config_lookup(&hcfg, "Hosts");
307
if(cfghosts == NULL) {
308
g_printerr ("%s: No Hosts entries found.\n", filename);
309
config_destroy(&hcfg);
314
GList *loadHosts (const gchar *filename) {
315
/* Parse hosts.xml document. */
316
xmlDocPtr xcfg = xmlParseFile(filename);
320
/* Allocate XPath context. */
321
xmlXPathContextPtr xctx = xmlXPathNewContext(xcfg);
323
g_error("%s: xmlXPathNewContext failed!\n", filename);
327
/* Lookup global host template node. */
328
xmlXPathObjectPtr defaults = evalXPath(xctx, "/hosts/default");
329
xmlNodePtr defhost = NULL;
330
if(!xmlXPathNodeSetIsEmpty(defaults->nodesetval))
331
defhost = defaults->nodesetval->nodeTab[0];
332
xmlXPathFreeObject(defaults);
334
/* Iterate over /hosts/group nodes. */
335
xmlXPathObjectPtr groups = evalXPath(xctx, "/hosts/group");
315
config_setting_t *cfggroup;
316
for(i=0; (cfggroup = config_setting_get_elem(cfghosts, i)); i++) {
319
CFG_GET_STRING_DEFAULT(cfggroup, "Title", group, config_setting_name(cfggroup));
321
config_setting_t *cfghost;
322
for(j=0; (cfghost = config_setting_get_elem(cfggroup, j)); j++) {
323
if(cfghost->type != CONFIG_TYPE_GROUP)
326
HostNode *hostnode = g_new0(HostNode, 1);
337
GList *hostlist = NULL;
338
for(i = 0; i < groups->nodesetval->nodeNr; i++) {
339
xmlNodePtr group = groups->nodesetval->nodeTab[i];
341
xmlChar *groupname = xmlGetProp(group, BAD_CAST("name"));
343
g_printerr("%s: The group element #%d does not have a name attribute!\n", filename, i+1);
348
xmlXPathObjectPtr hosts = evalXPath(xctx, "host");
349
if(xmlXPathNodeSetIsEmpty(hosts->nodesetval)) {
350
xmlXPathFreeObject(hosts);
352
g_warning("%s: The group '%s' is empty!\n", filename, groupname);
356
/* Iterate over /hosts/group/host nodes. */
358
for(j = 0; j < hosts->nodesetval->nodeNr; j++) {
359
xmlNodePtr host = hosts->nodesetval->nodeTab[j];
360
xmlNodePtr cfgnodes[4] = {host, group, defhost, NULL};
362
xmlChar *hostname = xmlGetProp(host, BAD_CAST("name"));
364
g_printerr("%s: The host element #%d of group '%s' does not have a name attribute!\n", filename, j+1, groupname);
366
xmlXPathFreeObject(hosts);
367
xmlXPathFreeObject(groups);
372
HostNode *hostnode = g_new0(HostNode, 1);
328
hostnode->_type = T_HOSTNODE;
374
hostnode->_type = T_HOSTNODE;
330
hostnode->hostname = g_strdup(cfghost->name);
331
HCFG_GET_STRING("Comment", hostnode->comment, NULL);
332
HCFG_GET_STRING("Type", hostnode->type, "generic-ssh");
333
HCFG_GET_STRING("SSHUser", hostnode->ssh_user, NULL);
334
HCFG_GET_STRING("SSHHost", hostnode->ssh_host, NULL);
335
HCFG_GET_INT("SSHPort", hostnode->ssh_port, 0);
336
HCFG_GET_STRING("SSHIdentity", hostnode->identity_file, NULL);
338
hostnode->group = g_strdup(group);
340
hostnode->statsfile = g_strdup_printf("%s/%s:%d.stat", cfg->statsdir, hostnode->hostname, hostnode->ssh_port);
341
hostnode->fdlock = -1;
342
hostnode->uuid[0] = 0;
343
hostnode->tagged = FALSE;
345
getUpdatesFromStat(hostnode);
347
hosts = g_list_append(hosts, hostnode);
376
hostnode->hostname = g_strdup((gchar *)hostname);
377
hostnode->comment = getXPropStr(cfgnodes, "comment", NULL);
378
hostnode->type = getXPropStr(cfgnodes, "type", "generic-ssh");
379
hostnode->ssh_user = getXPropStr(cfgnodes, "ssh-user", NULL);
380
hostnode->ssh_host = getXPropStr(cfgnodes, "ssh-host", NULL);
381
hostnode->ssh_port = getXPropInt(cfgnodes, "ssh-port", 0);
382
hostnode->identity_file = getXPropStr(cfgnodes, "ssh-id", NULL);
384
hostnode->group = g_strdup((gchar *)groupname);
386
hostnode->statsfile = g_strdup_printf("%s/%s:%d.stat", cfg->statsdir, hostnode->hostname, hostnode->ssh_port);
387
hostnode->fdlock = -1;
388
hostnode->uuid[0] = 0;
389
hostnode->tagged = FALSE;
391
getUpdatesFromStat(hostnode);
393
hostlist = g_list_append(hostlist, hostnode);
398
xmlXPathFreeObject(hosts);
351
config_destroy(&hcfg);
402
xmlXPathFreeObject(groups);