Was this ever committed? On Wed Dec 03 2014 at 12:13:43 PM Michal Nazarewicz <[email protected]> wrote:
> From: Michal Nazarewicz <[email protected]> > > 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/fd_util.c | 23 ++++++++++++ > src/fd_util.h | 8 ++++ > src/settings.c | 117 ++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++ > 3 files changed, 148 insertions(+) > > diff --git a/src/fd_util.c b/src/fd_util.c > index 09373e3..3a21ce5 100644 > --- a/src/fd_util.c > +++ b/src/fd_util.c > @@ -38,6 +38,8 @@ > #include <stdbool.h> > #include <fcntl.h> > #include <errno.h> > +#include <sys/stat.h> > +#include <sys/types.h> > > #ifdef WIN32 > #include <winsock2.h> > @@ -117,3 +119,24 @@ socket_cloexec_nonblock(int domain, int type, int > protocol) > > return fd; > } > + > +FILE * > +mpd_fopen(const char *path) > +{ > + int fd = -1; > + > +#ifdef O_CLOEXEC > + fd = open(path, O_RDONLY | O_CLOEXEC); > + if (fd < 0 && errno != EINVAL) > + return NULL; > +#endif > + > + if (fd < 0) { > + fd = open(path, O_RDONLY); > + if (fd == -1) > + return NULL; > + fd_set_cloexec(fd, true); > + } > + > + return fdopen(fd, "r"); > +} > diff --git a/src/fd_util.h b/src/fd_util.h > index f0c13c9..858896d 100644 > --- a/src/fd_util.h > +++ b/src/fd_util.h > @@ -36,6 +36,8 @@ > #ifndef FD_UTIL_H > #define FD_UTIL_H > > +#include <stdio.h> > + > /** > * Wrapper for socket(), which sets the CLOEXEC and the NONBLOCK flag > * (atomically if supported by the OS). > @@ -43,4 +45,10 @@ > int > socket_cloexec_nonblock(int domain, int type, int protocol); > > +/** > + * Opens FILE for reading (mode="r") setting O_CLOEXEC flag. > + */ > +FILE * > +mpd_fopen(const char *path); > + > #endif > diff --git a/src/settings.c b/src/settings.c > index f153452..5a27dc7 100644 > --- a/src/settings.c > +++ b/src/settings.c > @@ -29,10 +29,13 @@ > #include <mpd/settings.h> > #include "config.h" > > +#include "fd_util.h" > + > #include <assert.h> > #include <ctype.h> > #include <string.h> > #include <stdlib.h> > +#include <stdio.h> > > #ifdef ENABLE_TCP > # ifdef WIN32 > @@ -146,6 +149,115 @@ mpd_check_port(unsigned port) > return port; > } > > +#ifdef ENABLE_TCP > + > +static char * > +mpd_parse_authinfo_line(const char *host, unsigned port, char *line) > +{ > + /* If port is zero (e.g. if socket is used), allow authinfo lines > w/o > + * a port. */ > + bool got_host = false, got_port = !port; > + char *pwd = NULL, *saveptr, *kw, *val; > + > + while ((kw = strtok_r(line, " \t\n", &saveptr))) { > + val = strtok_r(NULL, " \t\n", &saveptr); > + /* Ignore line if there's a keyword w/o value. */ > + if (!val) > + return NULL; > + line = NULL; > + > + if (!strcmp(kw, "machine")) { > + /* Ignore line if hosts differ. */ > + if (strcmp(val, host)) > + return NULL; > + got_host = true; > + > + } else if (!strcmp(kw, "port")) { > + /* Ignore line if ports differ. */ > + if (!port || mpd_parse_port(val) != port) > + return NULL; > + got_port = true; > + > + } else if (!strcmp(kw, "password")) { > + pwd = val; > + > + } else { > + /* Unknown keyword present, ignore line. */ > + return NULL; > + } > + } > + > + return got_host && got_port ? pwd : NULL; > +} > + > +static char * > +mpd_parse_authinfo(const char *host, unsigned port, FILE *fd) > +{ > + char line[1024], *pwd = NULL; > + > + do { > + if (!fgets(line, sizeof line, fd)) { > + return NULL; > + } > + > + if (!strchr(line, '\n')) { > + /* Discard partial lines. TODO: handle lines of > + * arbitrary length */ > + while (fgets(line, sizeof line, fd) && > + !strchr(line, '\n')) { } > + } else { > + pwd = mpd_parse_authinfo_line(host, port, line); > + } > + } while (!pwd); > + > + return strdup(pwd); > +} > + > +static char * > +mpd_read_authinfo_password(const char *host, unsigned port) > +{ > + static const char *const filenames[] = { > + /* Code assumes the first entry is the longest. */ > + ".authinfo", ".netrc" > + }; > + > + char *str = getenv("HOME"); > + if (!str) { > + return NULL; > + } > + > + size_t i = strlen(str); > + char *path = malloc(i + strlen(filenames[0]) + 2); > + memcpy(path, str, i); > + path[i] = '/'; > + str = path + i + 1; > + > + char *pwd = NULL; > + for (i = 0; !pwd && i < sizeof filenames / sizeof *filenames; ++i) > { > + strcpy(str, filenames[i]); > + FILE *fd = mpd_fopen(path); > + if (fd) { > + pwd = mpd_parse_authinfo(host, port, fd); > + fclose(fd); > + } > + } > + free(path); > + return pwd; > +} > + > +#else > + > +static char * > +mpd_read_authinfo_password(const char *host, unsigned port) > +{ > + host = host; > + port = port; > + return NULL; > +} > + > +#endif > + > + > static unsigned > mpd_default_timeout_ms(void) > { > @@ -199,6 +311,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.2.0.rc0.207.ga3a616c > > _______________________________________________ > mpd-devel mailing list > [email protected] > http://mailman.blarg.de/listinfo/mpd-devel >
_______________________________________________ mpd-devel mailing list [email protected] http://mailman.blarg.de/listinfo/mpd-devel
