From 947b381fb63711fab30f7212638ef792f5aa2a3f Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Fri, 30 May 2014 14:57:19 +0200 Subject: settings: Support ~/ expansion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only the simple ~/ expansion is supported right now, since ~user expansion does not make sense for per-user config files anyway. Closes #431 and #430. On my way to this solution I tried libconfuse and json-based config files. I’m not convinced yet one of these is the solution though… --- contrib/pianobar.1 | 5 ++- src/settings.c | 100 +++++++++++++++++++++++++++++++++++++---------------- src/settings.h | 1 - 3 files changed, 73 insertions(+), 33 deletions(-) diff --git a/contrib/pianobar.1 b/contrib/pianobar.1 index 490ee23..8a311a5 100644 --- a/contrib/pianobar.1 +++ b/contrib/pianobar.1 @@ -215,9 +215,8 @@ File that is executed when event occurs. See section .B EVENTCMD .TP -.B fifo = /home/user/.config/pianobar/ctl -Location of control fifo. Defaults to $XDG_CONFIG_HOME/pianobar/ctl (which is -usually the value above). See section +.B fifo = $XDG_CONFIG_HOME/pianobar/ctl +Location of control fifo. See section .B REMOTE CONTROL .TP diff --git a/src/settings.c b/src/settings.c index d90a7d7..f03f368 100644 --- a/src/settings.c +++ b/src/settings.c @@ -34,6 +34,8 @@ THE SOFTWARE. #include #include #include +#include +#include #include @@ -43,32 +45,58 @@ THE SOFTWARE. #define streq(a, b) (strcmp (a, b) == 0) -/* tries to guess your config dir; somehow conforming to - * http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html - * @param name of the config file (can contain subdirs too) - * @param store the whole path here - * @param but only up to this size - * @return nothing +/* Get current user’s home directory */ -void BarGetXdgConfigDir (const char *filename, char *retDir, - size_t retDirN) { - char *xdgConfigDir = NULL; +static char *BarSettingsGetHome () { + char *home; + + /* try environment variable */ + if ((home = getenv ("HOME")) != NULL && strlen (home) > 0) { + return strdup (home); + } + + /* try passwd mechanism */ + struct passwd * const pw = getpwuid (getuid ()); + if (pw != NULL && pw->pw_dir != NULL && strlen (pw->pw_dir) > 0) { + return strdup (pw->pw_dir); + } + + return NULL; +} + +/* Get XDG config directory, which is set by BarSettingsRead (if not set) + */ +static char *BarGetXdgConfigDir (const char * const filename) { + assert (filename != NULL); + + char *xdgConfigDir; if ((xdgConfigDir = getenv ("XDG_CONFIG_HOME")) != NULL && strlen (xdgConfigDir) > 0) { - /* special dir: $xdg_config_home */ - snprintf (retDir, retDirN, "%s/%s", xdgConfigDir, filename); - } else { - if ((xdgConfigDir = getenv ("HOME")) != NULL && - strlen (xdgConfigDir) > 0) { - /* standard config dir: $home/.config */ - snprintf (retDir, retDirN, "%s/.config/%s", xdgConfigDir, - filename); - } else { - /* fallback: working dir */ - snprintf (retDir, retDirN, "%s", filename); - } + const size_t len = (strlen (xdgConfigDir) + 1 + + strlen (filename) + 1); + char * const concat = malloc (len * sizeof (*concat)); + snprintf (concat, len, "%s/%s", xdgConfigDir, filename); + return concat; + } + + return NULL; +} + +/* Expand ~/ to user’s home directory + */ +char *BarSettingsExpandTilde (const char * const path, const char * const home) { + assert (path != NULL); + assert (home != NULL); + + if (strncmp (path, "~/", 2) == 0) { + char * const expanded = malloc ((strlen (home) + 1 + strlen (path)-2 + 1) * + sizeof (*expanded)); + sprintf (expanded, "%s/%s", home, &path[2]); + return expanded; } + + return strdup (path); } /* initialize settings structure @@ -115,7 +143,14 @@ void BarSettingsDestroy (BarSettings_t *settings) { * @return nothing yet */ void BarSettingsRead (BarSettings_t *settings) { - char *configfiles[] = {PACKAGE "/state", PACKAGE "/config"}; + char * const configfiles[] = {PACKAGE "/state", PACKAGE "/config"}; + char * const userhome = BarSettingsGetHome (); + assert (userhome != NULL); + /* set xdg config path (if not set) */ + char * const defaultxdg = malloc (strlen (userhome) + strlen ("/.config") + 1); + sprintf (defaultxdg, "%s/.config", userhome); + setenv ("XDG_CONFIG_HOME", defaultxdg, 0); + free (defaultxdg); assert (sizeof (settings->keys) / sizeof (*settings->keys) == sizeof (dispatchActions) / sizeof (*dispatchActions)); @@ -140,8 +175,8 @@ void BarSettingsRead (BarSettings_t *settings) { settings->device = strdup ("android-generic"); settings->inkey = strdup ("R=U!LH$O2B#"); settings->outkey = strdup ("6#26FRL$ZWD"); - settings->fifo = malloc (PATH_MAX * sizeof (*settings->fifo)); - BarGetXdgConfigDir (PACKAGE "/ctl", settings->fifo, PATH_MAX); + settings->fifo = BarGetXdgConfigDir (PACKAGE "/ctl"); + assert (settings->fifo != NULL); memcpy (settings->tlsFingerprint, "\x2D\x0A\xFD\xAF\xA1\x6F\x4B\x5C\x0A" "\x43\xF3\xCB\x1D\x47\x52\xF9\x53\x55\x07\xC0", sizeof (settings->tlsFingerprint)); @@ -168,11 +203,13 @@ void BarSettingsRead (BarSettings_t *settings) { /* read config files */ for (size_t j = 0; j < sizeof (configfiles) / sizeof (*configfiles); j++) { static const char *formatMsgPrefix = "format_msg_"; - char key[256], val[256], path[PATH_MAX]; + char key[256], val[256]; FILE *configfd; - BarGetXdgConfigDir (configfiles[j], path, sizeof (path)); + char * const path = BarGetXdgConfigDir (configfiles[j]); + assert (path != NULL); if ((configfd = fopen (path, "r")) == NULL) { + free (path); continue; } @@ -283,7 +320,7 @@ void BarSettingsRead (BarSettings_t *settings) { settings->listSongFormat = strdup (val); } else if (streq ("fifo", key)) { free (settings->fifo); - settings->fifo = strdup (val); + settings->fifo = BarSettingsExpandTilde (val, userhome); } else if (streq ("autoselect", key)) { settings->autoselect = atoi (val); } else if (streq ("tls_fingerprint", key)) { @@ -330,6 +367,7 @@ void BarSettingsRead (BarSettings_t *settings) { } fclose (configfd); + free (path); } /* check environment variable if proxy is not set explicitly */ @@ -339,18 +377,21 @@ void BarSettingsRead (BarSettings_t *settings) { settings->proxy = strdup (tmpProxy); } } + + free (userhome); } /* write statefile */ void BarSettingsWrite (PianoStation_t *station, BarSettings_t *settings) { - char path[PATH_MAX]; FILE *fd; assert (settings != NULL); - BarGetXdgConfigDir (PACKAGE "/state", path, sizeof (path)); + char * const path = BarGetXdgConfigDir (PACKAGE "/state"); + assert (path != NULL); if ((fd = fopen (path, "w")) == NULL) { + free (path); return; } @@ -361,5 +402,6 @@ void BarSettingsWrite (PianoStation_t *station, BarSettings_t *settings) { } fclose (fd); + free (path); } diff --git a/src/settings.h b/src/settings.h index 5212d10..b56351e 100644 --- a/src/settings.h +++ b/src/settings.h @@ -114,6 +114,5 @@ void BarSettingsInit (BarSettings_t *); void BarSettingsDestroy (BarSettings_t *); void BarSettingsRead (BarSettings_t *); void BarSettingsWrite (PianoStation_t *, BarSettings_t *); -void BarGetXdgConfigDir (const char *, char *, size_t); #endif /* SRC_SETTINGS_H_IPL0ON9L */ -- cgit v1.2.3