Skip to content

Commit 947b381

Browse files
committed
settings: Support ~/ expansion
Only the simple ~/ expansion is supported right now, since ~user expansion does not make sense for per-user config files anyway. Closes PromyLOPh#431 and PromyLOPh#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…
1 parent 81c9327 commit 947b381

File tree

3 files changed

+73
-33
lines changed

3 files changed

+73
-33
lines changed

contrib/pianobar.1

+2-3
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,8 @@ File that is executed when event occurs. See section
215215
.B EVENTCMD
216216

217217
.TP
218-
.B fifo = /home/user/.config/pianobar/ctl
219-
Location of control fifo. Defaults to $XDG_CONFIG_HOME/pianobar/ctl (which is
220-
usually the value above). See section
218+
.B fifo = $XDG_CONFIG_HOME/pianobar/ctl
219+
Location of control fifo. See section
221220
.B REMOTE CONTROL
222221

223222
.TP

src/settings.c

+71-29
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ THE SOFTWARE.
3434
#include <stdio.h>
3535
#include <limits.h>
3636
#include <assert.h>
37+
#include <sys/types.h>
38+
#include <pwd.h>
3739

3840
#include <piano.h>
3941

@@ -43,32 +45,58 @@ THE SOFTWARE.
4345

4446
#define streq(a, b) (strcmp (a, b) == 0)
4547

46-
/* tries to guess your config dir; somehow conforming to
47-
* http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
48-
* @param name of the config file (can contain subdirs too)
49-
* @param store the whole path here
50-
* @param but only up to this size
51-
* @return nothing
48+
/* Get current user’s home directory
5249
*/
53-
void BarGetXdgConfigDir (const char *filename, char *retDir,
54-
size_t retDirN) {
55-
char *xdgConfigDir = NULL;
50+
static char *BarSettingsGetHome () {
51+
char *home;
52+
53+
/* try environment variable */
54+
if ((home = getenv ("HOME")) != NULL && strlen (home) > 0) {
55+
return strdup (home);
56+
}
57+
58+
/* try passwd mechanism */
59+
struct passwd * const pw = getpwuid (getuid ());
60+
if (pw != NULL && pw->pw_dir != NULL && strlen (pw->pw_dir) > 0) {
61+
return strdup (pw->pw_dir);
62+
}
63+
64+
return NULL;
65+
}
66+
67+
/* Get XDG config directory, which is set by BarSettingsRead (if not set)
68+
*/
69+
static char *BarGetXdgConfigDir (const char * const filename) {
70+
assert (filename != NULL);
71+
72+
char *xdgConfigDir;
5673

5774
if ((xdgConfigDir = getenv ("XDG_CONFIG_HOME")) != NULL &&
5875
strlen (xdgConfigDir) > 0) {
59-
/* special dir: $xdg_config_home */
60-
snprintf (retDir, retDirN, "%s/%s", xdgConfigDir, filename);
61-
} else {
62-
if ((xdgConfigDir = getenv ("HOME")) != NULL &&
63-
strlen (xdgConfigDir) > 0) {
64-
/* standard config dir: $home/.config */
65-
snprintf (retDir, retDirN, "%s/.config/%s", xdgConfigDir,
66-
filename);
67-
} else {
68-
/* fallback: working dir */
69-
snprintf (retDir, retDirN, "%s", filename);
70-
}
76+
const size_t len = (strlen (xdgConfigDir) + 1 +
77+
strlen (filename) + 1);
78+
char * const concat = malloc (len * sizeof (*concat));
79+
snprintf (concat, len, "%s/%s", xdgConfigDir, filename);
80+
return concat;
81+
}
82+
83+
return NULL;
84+
}
85+
86+
/* Expand ~/ to user’s home directory
87+
*/
88+
char *BarSettingsExpandTilde (const char * const path, const char * const home) {
89+
assert (path != NULL);
90+
assert (home != NULL);
91+
92+
if (strncmp (path, "~/", 2) == 0) {
93+
char * const expanded = malloc ((strlen (home) + 1 + strlen (path)-2 + 1) *
94+
sizeof (*expanded));
95+
sprintf (expanded, "%s/%s", home, &path[2]);
96+
return expanded;
7197
}
98+
99+
return strdup (path);
72100
}
73101

74102
/* initialize settings structure
@@ -115,7 +143,14 @@ void BarSettingsDestroy (BarSettings_t *settings) {
115143
* @return nothing yet
116144
*/
117145
void BarSettingsRead (BarSettings_t *settings) {
118-
char *configfiles[] = {PACKAGE "/state", PACKAGE "/config"};
146+
char * const configfiles[] = {PACKAGE "/state", PACKAGE "/config"};
147+
char * const userhome = BarSettingsGetHome ();
148+
assert (userhome != NULL);
149+
/* set xdg config path (if not set) */
150+
char * const defaultxdg = malloc (strlen (userhome) + strlen ("/.config") + 1);
151+
sprintf (defaultxdg, "%s/.config", userhome);
152+
setenv ("XDG_CONFIG_HOME", defaultxdg, 0);
153+
free (defaultxdg);
119154

120155
assert (sizeof (settings->keys) / sizeof (*settings->keys) ==
121156
sizeof (dispatchActions) / sizeof (*dispatchActions));
@@ -140,8 +175,8 @@ void BarSettingsRead (BarSettings_t *settings) {
140175
settings->device = strdup ("android-generic");
141176
settings->inkey = strdup ("R=U!LH$O2B#");
142177
settings->outkey = strdup ("6#26FRL$ZWD");
143-
settings->fifo = malloc (PATH_MAX * sizeof (*settings->fifo));
144-
BarGetXdgConfigDir (PACKAGE "/ctl", settings->fifo, PATH_MAX);
178+
settings->fifo = BarGetXdgConfigDir (PACKAGE "/ctl");
179+
assert (settings->fifo != NULL);
145180
memcpy (settings->tlsFingerprint, "\x2D\x0A\xFD\xAF\xA1\x6F\x4B\x5C\x0A"
146181
"\x43\xF3\xCB\x1D\x47\x52\xF9\x53\x55\x07\xC0",
147182
sizeof (settings->tlsFingerprint));
@@ -168,11 +203,13 @@ void BarSettingsRead (BarSettings_t *settings) {
168203
/* read config files */
169204
for (size_t j = 0; j < sizeof (configfiles) / sizeof (*configfiles); j++) {
170205
static const char *formatMsgPrefix = "format_msg_";
171-
char key[256], val[256], path[PATH_MAX];
206+
char key[256], val[256];
172207
FILE *configfd;
173208

174-
BarGetXdgConfigDir (configfiles[j], path, sizeof (path));
209+
char * const path = BarGetXdgConfigDir (configfiles[j]);
210+
assert (path != NULL);
175211
if ((configfd = fopen (path, "r")) == NULL) {
212+
free (path);
176213
continue;
177214
}
178215

@@ -283,7 +320,7 @@ void BarSettingsRead (BarSettings_t *settings) {
283320
settings->listSongFormat = strdup (val);
284321
} else if (streq ("fifo", key)) {
285322
free (settings->fifo);
286-
settings->fifo = strdup (val);
323+
settings->fifo = BarSettingsExpandTilde (val, userhome);
287324
} else if (streq ("autoselect", key)) {
288325
settings->autoselect = atoi (val);
289326
} else if (streq ("tls_fingerprint", key)) {
@@ -330,6 +367,7 @@ void BarSettingsRead (BarSettings_t *settings) {
330367
}
331368

332369
fclose (configfd);
370+
free (path);
333371
}
334372

335373
/* check environment variable if proxy is not set explicitly */
@@ -339,18 +377,21 @@ void BarSettingsRead (BarSettings_t *settings) {
339377
settings->proxy = strdup (tmpProxy);
340378
}
341379
}
380+
381+
free (userhome);
342382
}
343383

344384
/* write statefile
345385
*/
346386
void BarSettingsWrite (PianoStation_t *station, BarSettings_t *settings) {
347-
char path[PATH_MAX];
348387
FILE *fd;
349388

350389
assert (settings != NULL);
351390

352-
BarGetXdgConfigDir (PACKAGE "/state", path, sizeof (path));
391+
char * const path = BarGetXdgConfigDir (PACKAGE "/state");
392+
assert (path != NULL);
353393
if ((fd = fopen (path, "w")) == NULL) {
394+
free (path);
354395
return;
355396
}
356397

@@ -361,5 +402,6 @@ void BarSettingsWrite (PianoStation_t *station, BarSettings_t *settings) {
361402
}
362403

363404
fclose (fd);
405+
free (path);
364406
}
365407

src/settings.h

-1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,5 @@ void BarSettingsInit (BarSettings_t *);
114114
void BarSettingsDestroy (BarSettings_t *);
115115
void BarSettingsRead (BarSettings_t *);
116116
void BarSettingsWrite (PianoStation_t *, BarSettings_t *);
117-
void BarGetXdgConfigDir (const char *, char *, size_t);
118117

119118
#endif /* SRC_SETTINGS_H_IPL0ON9L */

0 commit comments

Comments
 (0)