X-Git-Url: https://git.distorted.org.uk/~mdw/disorder/blobdiff_plain/c12575c6cea802f894df6ca8b04c1b3656496592..c8a277f4ccdf4c392135769a4f0585dd7df5ae19:/lib/client.c diff --git a/lib/client.c b/lib/client.c index 521a4c7..55cfe1c 100644 --- a/lib/client.c +++ b/lib/client.c @@ -50,7 +50,6 @@ #include "authhash.h" #include "client-common.h" #include "rights.h" -#include "trackdb.h" #include "kvp.h" /** @brief Client handle contents */ @@ -151,12 +150,6 @@ static int check_response(disorder_client *c, char **rp) { } } -/** @brief Marker for a command body */ -static const char disorder_body[1]; - -/** @brief Marker for a list of args */ -static const char disorder_list[1]; - /** @brief Issue a command and parse a simple response * @param c Client * @param rp Where to store result, or NULL @@ -172,16 +165,23 @@ static const char disorder_list[1]; * NB that the response will NOT be converted to the local encoding * nor will quotes be stripped. See dequote(). * - * Put @ref disorder_body in the argument list followed by a char ** + * Put @ref disorder__body in the argument list followed by a char ** * and int giving the body to follow the command. If the int is @c -1 * then the list is assumed to be NULL-terminated. This may be used * only once. * - * Put @ref disorder_list in the argument list followed by a char ** + * Put @ref disorder__list in the argument list followed by a char ** * and int giving a list of arguments to include. If the int is @c -1 * then the list is assumed to be NULL-terminated. This may be used * any number of times. * + * Put @ref disorder__integer in the argument list followed by a long to + * send its value in decimal. This may be used any number of times. + * + * Put @ref disorder__time in the argument list followed by a time_t + * to send its value in decimal. This may be used any number of + * times. + * * Usually you would call this via one of the following interfaces: * - disorder_simple() */ @@ -204,11 +204,11 @@ static int disorder_simple_v(disorder_client *c, dynstr_init(&d); dynstr_append_string(&d, cmd); while((arg = va_arg(ap, const char *))) { - if(arg == disorder_body) { + if(arg == disorder__body) { body = va_arg(ap, char **); nbody = va_arg(ap, int); has_body = 1; - } else if(arg == disorder_list) { + } else if(arg == disorder__list) { char **list = va_arg(ap, char **); int nlist = va_arg(ap, int); if(nlist < 0) { @@ -219,6 +219,18 @@ static int disorder_simple_v(disorder_client *c, dynstr_append(&d, ' '); dynstr_append_string(&d, quoteutf8(arg)); } + } else if(arg == disorder__integer) { + long n = va_arg(ap, long); + char buffer[16]; + snprintf(buffer, sizeof buffer, "%ld", n); + dynstr_append(&d, ' '); + dynstr_append_string(&d, buffer); + } else if(arg == disorder__time) { + time_t n = va_arg(ap, time_t); + char buffer[16]; + snprintf(buffer, sizeof buffer, "%lld", (long long)n); + dynstr_append(&d, ' '); + dynstr_append_string(&d, buffer); } else { dynstr_append(&d, ' '); dynstr_append_string(&d, quoteutf8(arg)); @@ -285,6 +297,59 @@ static int disorder_simple(disorder_client *c, return ret; } +/** @brief Issue a command and split the response + * @param c Client + * @param vecp Where to store results + * @param nvecp Where to store count of results + * @param expected Expected count (or -1 to not check) + * @param cmd Command + * @return 0 on success, non-0 on error + * + * The remaining arguments are command arguments, terminated by (char + * *)0. They should be in UTF-8. + * + * 5xx responses count as errors. + * + * @p rp will NOT be filled in for xx9 responses (where it is just + * commentary for a command where it would normally be meaningful). + * + * NB that the response will NOT be converted to the local encoding + * nor will quotes be stripped. See dequote(). + */ +static int disorder_simple_split(disorder_client *c, + char ***vecp, + int *nvecp, + int expected, + const char *cmd, ...) { + va_list ap; + int ret; + char *r; + char **vec; + int nvec; + + va_start(ap, cmd); + ret = disorder_simple_v(c, &r, cmd, ap); + va_end(ap); + if(!ret) { + vec = split(r, &nvec, SPLIT_QUOTES, 0, 0); + xfree(r); + if(expected < 0 || nvec == expected) { + *vecp = vec; + *nvecp = nvec; + } else { + disorder_error(0, "malformed reply to %s", cmd); + c->last = "malformed reply"; + ret = -1; + free_strings(nvec, vec); + } + } + if(ret) { + *vecp = NULL; + *nvecp = 0; + } + return ret; +} + /** @brief Dequote a result string * @param rc 0 on success, non-0 on error * @param rp Where result string is stored (UTF-8) @@ -455,13 +520,13 @@ int disorder_connect(disorder_client *c) { return -1; } password = config->password; - /* Maybe we can read the database */ - if(!password && trackdb_readable()) { - trackdb_init(TRACKDB_NO_RECOVER|TRACKDB_NO_UPGRADE); - trackdb_open(TRACKDB_READ_ONLY); - password = trackdb_get_password(username); - trackdb_close(); - } + /* If we're connecting as 'root' guess that we're the system root + * user (or the jukebox user), both of which can use the privileged + * socket. They can also furtle with the db directly: that is why + * privileged socket does not represent a privilege escalation. */ + if(!password + && !strcmp(username, "root")) + password = "anything will do for root"; if(!password) { /* Oh well */ c->last = "no password"; @@ -709,46 +774,6 @@ int disorder_log(disorder_client *c, struct sink *s) { return 0; } -/** @brief Add a scheduled event - * @param c Client - * @param when When to trigger the event - * @param priority Event priority ("normal" or "junk") - * @param action What action to perform - * @param ... Action-specific arguments - * @return 0 on success, non-0 on error - * - * For action @c "play" the next argument is the track. - * - * For action @c "set-global" next argument is the global preference name - * and the final argument the value to set it to, or (char *)0 to unset it. - */ -int disorder_schedule_add(disorder_client *c, - time_t when, - const char *priority, - const char *action, - ...) { - va_list ap; - char when_str[64]; - int rc; - - snprintf(when_str, sizeof when_str, "%lld", (long long)when); - va_start(ap, action); - if(!strcmp(action, "play")) - rc = disorder_simple(c, 0, "schedule-add", when_str, priority, - action, va_arg(ap, char *), - (char *)0); - else if(!strcmp(action, "set-global")) { - const char *key = va_arg(ap, char *); - const char *value = va_arg(ap, char *); - rc = disorder_simple(c, 0,"schedule-add", when_str, priority, - action, key, value, - (char *)0); - } else - disorder_fatal(0, "unknown action '%s'", action); - va_end(ap); - return rc; -} - #include "client-stubs.c" /*