Instead of storing password in MPD_HOST environment variable (which
is passed around everywhere) allow saving password in an ~/.authinfo
file. This is especially useful if MPD is listening on default
host:port, i.e. localhost:6600, in which case all one needs to do is
to put line like
machine localhost port 6600 password some-password
to make MPD clients use “some-password” when connecting to it.
---
src/settings.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 95 insertions(+)
diff --git a/src/settings.c b/src/settings.c
index f2799df..9d0eb4e 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -32,6 +32,7 @@
#include <assert.h>
#include <string.h>
#include <stdlib.h>
+#include <stdio.h>
struct mpd_settings {
char *host;
@@ -115,6 +116,95 @@ mpd_check_port(unsigned port)
return port;
}
+static char *mpd_parse_authinfo(const char *host, unsigned port, FILE *fd)
+{
+ char line[1024], *saveptr, *kw, *val, *pwd, *str;
+ bool got_host, got_port;
+
+next_line:
+ if (!fgets(line, sizeof line, fd)) {
+ return NULL;
+ }
+
+ /* If we read partial line, discard it. */
+ /* TODO: add handling lines of arbitrary length */
+ if (!strchr(line, '\n')) {
+ while (fgets(line, sizeof line, fd) && !strchr(line, '\n')) { }
+ goto next_line;
+ }
+
+ got_host = false;
+ /* If port is zero (e.g. if socket is used), allow authinfo lines w/o
+ * a port. */
+ got_port = !port;
+ str = line;
+ pwd = NULL;
+
+ while ((kw = strtok_r(str, " \t\n", &saveptr))) {
+ val = strtok_r(NULL, " \t\n", &saveptr);
+ /* Keyword w/o value, ignore line. */
+ if (!val)
+ goto next_line;
+ str = NULL;
+
+ if (!strcmp(kw, "machine")) {
+ if (strcmp(val, host))
+ /* Different host, ignore line. */
+ goto next_line;
+ got_host = true;
+
+ } else if (!strcmp(kw, "port")) {
+ /* TODO: Do we need to detect errors or is atoi
+ * enough? */
+ if (atoi(val) != (int)port)
+ /* Different port, ignore line. */
+ goto next_line;
+ got_port = true;
+
+ } else if (!strcmp(kw, "password")) {
+ pwd = val;
+
+ } else {
+ /* Unknown keyword present, ignore line. */
+ goto next_line;
+ }
+ }
+
+ if (got_host && got_port && pwd) {
+ return strdup(pwd);
+ }
+ goto next_line;
+}
+
+static char *mpd_read_authinfo_password(const char *host, unsigned port)
+{
+ static const char *filenames[] = {
+ /* Code assumes the first entry is the longest. */
+ ".authinfo", ".netrc"
+ };
+
+ char *pwd = NULL, *home, *path;
+ unsigned i;
+ FILE *fd;
+
+ home = getenv("HOME");
+ if (!home) {
+ return NULL;
+ }
+
+ path = malloc(strlen(home) + strlen(filenames[0]) + 2);
+ for (i = 0; !pwd && i < sizeof filenames / sizeof *filenames; ++i) {
+ sprintf(path, "%s/%s", home, filenames[i]);
+ fd = fopen(path, "r");
+ if (fd) {
+ pwd = mpd_parse_authinfo(host, port, fd);
+ }
+ fclose(fd);
+ }
+ free(path);
+ return pwd;
+}
+
static unsigned
mpd_default_timeout_ms(void)
{
@@ -168,6 +258,11 @@ mpd_settings_new(const char *host, unsigned port, unsigned
timeout_ms,
? 0 /* no port for local socket */
: (port != 0 ? port : DEFAULT_PORT);
+ if (settings->host && !settings->password) {
+ settings->password = mpd_read_authinfo_password(
+ settings->host, settings->port);
+ }
+
return settings;
}
--
2.1.0.rc2.206.gedb03e5
_______________________________________________
mpd-devel mailing list
[email protected]
http://mailman.blarg.de/listinfo/mpd-devel