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

Reply via email to