# HG changeset patch # User Mikael Berthe # Date 1445105850 -7200 # Node ID ccd4ffa41a1bfde64496b3ba0600410afcbb6b48 # Parent 170597f5365bd5e62168b151511796f7a63df8b6 Use XDG configuration directory if a config file exists If $XDG_CONFIG_HOME (or $HOME/.config) contains a file "mcabber/mcabberrc" it is used and $XDG_CONFIG_HOME/mcabber becomes the main mcabber configuration directory. (The ~/.mcabber/mcabberrc is still checked first.) diff -r 170597f5365b -r ccd4ffa41a1b mcabber/mcabber/api.h --- a/mcabber/mcabber/api.h Mon Oct 12 17:19:19 2015 +0200 +++ b/mcabber/mcabber/api.h Sat Oct 17 20:17:30 2015 +0200 @@ -4,7 +4,7 @@ #include #include // For MCABBER_BRANCH -#define MCABBER_API_VERSION 39 +#define MCABBER_API_VERSION 40 #define MCABBER_API_MIN 38 #define MCABBER_BRANCH_DEV 1 diff -r 170597f5365b -r ccd4ffa41a1b mcabber/mcabber/settings.c --- a/mcabber/mcabber/settings.c Mon Oct 12 17:19:19 2015 +0200 +++ b/mcabber/mcabber/settings.c Sat Oct 17 20:17:30 2015 +0200 @@ -1,7 +1,7 @@ /* * settings.c -- Configuration stuff * - * Copyright (C) 2005-2010 Mikael Berthe + * Copyright (C) 2005-2015 Mikael Berthe * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,6 +22,7 @@ #include #include #include +#include #include "config.h" #include "settings.h" @@ -87,6 +88,83 @@ #endif } +// settings_get_mcabber_config_dir() +// Returns the mcabber configuration directory. +// The directory is looked up for only once (and the string is never freed, +// but we might change this later). +const gchar *settings_get_mcabber_config_dir(void) +{ + static char *config_dir; + char *home_dir; + GString *sfilename; + FILE *fp; + + if (config_dir) + return config_dir; + + home_dir = getenv("HOME"); + if (!home_dir) { + scr_log_print(LPRINT_LOG, "Can't find home dir!"); + fprintf(stderr, "Can't find home dir!\n"); + return NULL; + } + + sfilename = g_string_new(""); + + // First try: $HOME/.mcabber/mcabberrc + g_string_printf(sfilename, "%s/.mcabber/mcabberrc", home_dir); + if ((fp = fopen(sfilename->str, "r")) != NULL) { + fclose(fp); + config_dir = g_strdup_printf("%s/.mcabber", home_dir); + } + + // Second guess: Try to use the XDG standard configuration directory + if (!config_dir) { + char *xdg_config_dir = g_strdup(getenv("XDG_CONFIG_HOME")); + if (!xdg_config_dir || !*xdg_config_dir) { + // Free the string if it is non-null but empty + if (xdg_config_dir) g_free(xdg_config_dir); + xdg_config_dir = g_strdup_printf("%s/.config", home_dir); + } + + if (xdg_config_dir) { + int fd = -1; + struct stat statbuf; + + if (*xdg_config_dir) + fd = stat(xdg_config_dir, &statbuf); + + // If the XDG configuration directory exists, see if we can find a + // configuration file for mcabber inside. + if (fd != -1) { + char *xdg_mcabber_dir = g_strdup_printf("%s/mcabber", xdg_config_dir); + g_string_printf(sfilename, "%s/mcabberrc", xdg_mcabber_dir); + if ((fp = fopen(sfilename->str, "r")) != NULL) { + fclose(fp); + config_dir = xdg_mcabber_dir; + } else { + g_free(xdg_mcabber_dir); + } + } + g_free(xdg_config_dir); + } + } + + // Last guess: home directory itself... + if (!config_dir) { + g_string_printf(sfilename, "%s/.mcabberrc", home_dir); + if ((fp = fopen(sfilename->str, "r")) != NULL) { + fclose(fp); + config_dir = g_strdup(home_dir); + } else { + scr_log_print(LPRINT_NORMAL, "Cannot find/open any configuration file!\n"); + } + } + + g_string_free(sfilename, TRUE); + return config_dir; +} + // cfg_read_file(filename, mainfile) // Read and parse config file "filename". If filename is NULL, // try to open the configuration file at the default locations. @@ -104,42 +182,32 @@ int err = 0; if (!filename) { - // Use default config file locations - char *home; - GString *sfilename; + const gchar *mcabber_conf_dir; + gchar *def_filename; if (!mainfile) { scr_LogPrint(LPRINT_LOGNORM, "No file name provided"); return -1; } - home = getenv("HOME"); - if (!home) { - scr_LogPrint(LPRINT_LOG, "Can't find home dir!"); - fprintf(stderr, "Can't find home dir!\n"); + mcabber_conf_dir = settings_get_mcabber_config_dir(); + if (!mcabber_conf_dir) + return -1; + + def_filename = g_strdup_printf("%s/mcabberrc", mcabber_conf_dir); + if ((fp = fopen(def_filename, "r")) == NULL) { + fprintf(stderr, "Cannot open config file!\n"); + g_free(def_filename); err = -1; goto cfg_read_file_return; } - sfilename = g_string_new(""); - g_string_printf(sfilename, "%s/.mcabber/mcabberrc", home); - if ((fp = fopen(sfilename->str, "r")) == NULL) { - // 2nd try... - g_string_printf(sfilename, "%s/.mcabberrc", home); - if ((fp = fopen(sfilename->str, "r")) == NULL) { - fprintf(stderr, "Cannot open config file!\n"); - g_string_free(sfilename, TRUE); - err = -1; - goto cfg_read_file_return; - } - } // Check configuration file permissions // As it could contain sensitive data, we make it user-readable only. - checkset_perm(sfilename->str, TRUE); - scr_LogPrint(LPRINT_LOGNORM, "Reading %s", sfilename->str); + checkset_perm(def_filename, TRUE); + scr_log_print(LPRINT_LOGNORM, "Reading %s", def_filename); // Check mcabber dir. Here we just warn, we don't change the modes. - g_string_printf(sfilename, "%s/.mcabber/", home); - checkset_perm(sfilename->str, FALSE); - g_string_free(sfilename, TRUE); + checkset_perm(mcabber_conf_dir, FALSE); + g_free(def_filename); } else { // filename was specified if ((fp = fopen(filename, "r")) == NULL) { diff -r 170597f5365b -r ccd4ffa41a1b mcabber/mcabber/settings.h --- a/mcabber/mcabber/settings.h Mon Oct 12 17:19:19 2015 +0200 +++ b/mcabber/mcabber/settings.h Sat Oct 17 20:17:30 2015 +0200 @@ -30,6 +30,7 @@ typedef gchar *(*settings_guard_t)(const gchar *key, const gchar *new_value); void settings_init(void); +const gchar *settings_get_mcabber_config_dir(void); int cfg_read_file(char *filename, guint mainfile); guint parse_assigment(gchar *assignment, gchar **pkey, gchar **pval); gboolean settings_set_guard(const gchar *key, settings_guard_t guard);