X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/feda7bfaefd9e5fb705d6893f26428a3109e7226..b94e827f906d4c725ab73a18c02300d32bdfc6a9:/lib/configuration.c diff --git a/lib/configuration.c b/lib/configuration.c index 932c54b..62ccf1b 100644 --- a/lib/configuration.c +++ b/lib/configuration.c @@ -1,6 +1,6 @@ /* * This file is part of DisOrder. - * Copyright (C) 2004-2010 Richard Kettlewell + * Copyright (C) 2004-2011, 2013 Richard Kettlewell * Portions copyright (C) 2007 Mark Wooding * * This program is free software: you can redistribute it and/or modify @@ -25,12 +25,20 @@ #include #include #include -#include +#if HAVE_UNISTD_H +# include +#endif #include #include -#include -#include -#include +#if HAVE_PWD_H +# include +#endif +#if HAVE_LANGINFO_H +# include +#endif +#if HAVE_PCRE_H +# include +#endif #include #include "rights.h" @@ -44,7 +52,9 @@ #include "charset.h" #include "defs.h" #include "printf.h" -#include "regsub.h" +#if HAVE_PCRE_H +# include "regsub.h" +#endif #include "signame.h" #include "authhash.h" #include "vector.h" @@ -200,8 +210,13 @@ static int set_collections(const struct config_state *cs, /* Defaults */ if(!module) module = "fs"; +#if HAVE_LANGINFO_H if(!encoding) encoding = nl_langinfo(CODESET); +#else + if(!encoding) + encoding = "ascii"; +#endif cl = ADDRESS(cs->config, struct collectionlist); ++cl->n; cl->s = xrealloc(cl->s, cl->n * sizeof (struct collection)); @@ -323,33 +338,6 @@ static int set_string_accum(const struct config_state *cs, return 0; } -static int set_restrict(const struct config_state *cs, - const struct conf *whoami, - int nvec, char **vec) { - unsigned r = 0; - int n, i; - - static const struct restriction { - const char *name; - unsigned bit; - } restrictions[] = { - { "remove", RESTRICT_REMOVE }, - { "scratch", RESTRICT_SCRATCH }, - { "move", RESTRICT_MOVE }, - }; - - for(n = 0; n < nvec; ++n) { - if((i = TABLE_FIND(restrictions, name, vec[n])) < 0) { - disorder_error(0, "%s:%d: invalid restriction '%s'", - cs->path, cs->line, vec[n]); - return -1; - } - r |= restrictions[i].bit; - } - VALUE(cs->config, unsigned) = r; - return 0; -} - static int parse_sample_format(const struct config_state *cs, struct stream_header *format, int nvec, char **vec) { @@ -422,6 +410,7 @@ static int set_sample_format(const struct config_state *cs, nvec, vec); } +#if HAVE_PCRE_H static int set_namepart(const struct config_state *cs, const struct conf *whoami, int nvec, char **vec) { @@ -507,6 +496,7 @@ static int set_transform(const struct config_state *cs, ++tl->n; return 0; } +#endif static int set_rights(const struct config_state *cs, const struct conf *whoami, @@ -588,6 +578,7 @@ static void free_collectionlist(struct config *c, xfree(cll->s); } +#if HAVE_PCRE_H static void free_namepartlist(struct config *c, const struct conf *whoami) { struct namepartlist *npl = ADDRESS(c, struct namepartlist); @@ -620,6 +611,7 @@ static void free_transformlist(struct config *c, } xfree(tl->t); } +#endif static void free_netaddress(struct config *c, const struct conf *whoami) { @@ -640,9 +632,10 @@ static const struct conftype type_stringlist_accum = { set_stringlist_accum, free_stringlistlist }, type_string_accum = { set_string_accum, free_stringlist }, type_sample_format = { set_sample_format, free_none }, - type_restrict = { set_restrict, free_none }, +#if HAVE_PCRE_H type_namepart = { set_namepart, free_namepartlist }, type_transform = { set_transform, free_transformlist }, +#endif type_netaddress = { set_netaddress, free_netaddress }, type_rights = { set_rights, free_string }; @@ -685,7 +678,7 @@ static int validate_isabspath(const struct config_state *cs, for(n = 0; n < nvec; ++n) if(vec[n][0] != '/') { - disorder_error(errno, "%s:%d: %s: not an absolute path", + disorder_error(0, "%s:%d: %s: not an absolute path", cs->path, cs->line, vec[n]); return -1; } @@ -725,7 +718,7 @@ static int validate_isreg(const struct config_state *cs, static int validate_player(const struct config_state *cs, int nvec, char attribute((unused)) **vec) { - if(nvec < 2) { + if(nvec && nvec < 2) { disorder_error(0, "%s:%d: should be at least 'player PATTERN MODULE'", cs->path, cs->line); return -1; @@ -742,7 +735,7 @@ static int validate_player(const struct config_state *cs, static int validate_tracklength(const struct config_state *cs, int nvec, char attribute((unused)) **vec) { - if(nvec < 2) { + if(nvec && nvec < 2) { disorder_error(0, "%s:%d: should be at least 'tracklength PATTERN MODULE'", cs->path, cs->line); return -1; @@ -750,24 +743,6 @@ static int validate_tracklength(const struct config_state *cs, return 0; } -/** @brief Validate an allow directive - * @param cs Configuration state - * @param nvec Length of (proposed) new value - * @param vec Elements of new value - * @return 0 on success, non-0 on error - * - * Obsolete - only used for parsing legacy configuration. - */ -static int validate_allow(const struct config_state *cs, - int nvec, - char attribute((unused)) **vec) { - if(nvec != 2) { - disorder_error(0, "%s:%d: must be 'allow NAME PASS'", cs->path, cs->line); - return -1; - } - return 0; -} - /** @brief Validate a non-negative (@c long) integer * @param cs Configuration state * @param nvec Length of (proposed) new value @@ -777,6 +752,7 @@ static int validate_allow(const struct config_state *cs, static int validate_non_negative(const struct config_state *cs, int nvec, char **vec) { long n; + char errbuf[1024]; if(nvec < 1) { disorder_error(0, "%s:%d: missing argument", cs->path, cs->line); @@ -787,7 +763,8 @@ static int validate_non_negative(const struct config_state *cs, return -1; } if(xstrtol(&n, vec[0], 0, 0)) { - disorder_error(0, "%s:%d: %s", cs->path, cs->line, strerror(errno)); + disorder_error(0, "%s:%d: %s", cs->path, cs->line, + format_error(ec_errno, errno, errbuf, sizeof errbuf)); return -1; } if(n < 0) { @@ -806,6 +783,7 @@ static int validate_non_negative(const struct config_state *cs, static int validate_positive(const struct config_state *cs, int nvec, char **vec) { long n; + char errbuf[1024]; if(nvec < 1) { disorder_error(0, "%s:%d: missing argument", cs->path, cs->line); @@ -816,7 +794,8 @@ static int validate_positive(const struct config_state *cs, return -1; } if(xstrtol(&n, vec[0], 0, 0)) { - disorder_error(0, "%s:%d: %s", cs->path, cs->line, strerror(errno)); + disorder_error(0, "%s:%d: %s", cs->path, cs->line, + format_error(ec_errno, errno, errbuf, sizeof errbuf)); return -1; } if(n <= 0) { @@ -1057,7 +1036,6 @@ static int validate_destaddr(const struct config_state attribute((unused)) *cs, /** @brief All configuration items */ static const struct conf conf[] = { { C(alias), &type_string, validate_alias }, - { C(allow), &type_stringlist_accum, validate_allow }, { C(api), &type_string, validate_backend }, { C(authorization_algorithm), &type_string, validate_algo }, { C(broadcast), &type_netaddress, validate_destaddr }, @@ -1072,17 +1050,17 @@ static const struct conf conf[] = { { C(dbversion), &type_integer, validate_positive }, { C(default_rights), &type_rights, validate_any }, { C(device), &type_string, validate_any }, - { C(gap), &type_integer, validate_non_negative }, { C(history), &type_integer, validate_positive }, { C(home), &type_string, validate_isabspath }, { C(listen), &type_netaddress, validate_any }, - { C(lock), &type_boolean, validate_any }, { C(mail_sender), &type_string, validate_any }, { C(mixer), &type_string, validate_any }, { C(mount_rescan), &type_boolean, validate_any }, { C(multicast_loop), &type_boolean, validate_any }, { C(multicast_ttl), &type_integer, validate_non_negative }, +#if HAVE_PCRE_H { C(namepart), &type_namepart, validate_any }, +#endif { C(new_bias), &type_integer, validate_positive }, { C(new_bias_age), &type_integer, validate_positive }, { C(new_max), &type_integer, validate_positive }, @@ -1097,15 +1075,14 @@ static const struct conf conf[] = { { C(playlist_lock_timeout), &type_integer, validate_positive }, { C(playlist_max) , &type_integer, validate_positive }, { C(plugins), &type_string_accum, validate_isdir }, - { C(prefsync), &type_integer, validate_positive }, { C(queue_pad), &type_integer, validate_positive }, { C(refresh), &type_integer, validate_positive }, { C(refresh_min), &type_integer, validate_non_negative }, { C(reminder_interval), &type_integer, validate_positive }, { C(remote_userman), &type_boolean, validate_any }, { C(replay_min), &type_integer, validate_non_negative }, - { C2(restrict, restrictions), &type_restrict, validate_any }, { C(rtp_delay_threshold), &type_integer, validate_positive }, + { C(rtp_mode), &type_string, validate_any }, { C(rtp_verbose), &type_boolean, validate_any }, { C(sample_format), &type_sample_format, validate_sample_format }, { C(scratch), &type_string_accum, validate_isreg }, @@ -1119,8 +1096,9 @@ static const struct conf conf[] = { { C(stopword), &type_string_accum, validate_any }, { C(templates), &type_string_accum, validate_isdir }, { C(tracklength), &type_stringlist_accum, validate_tracklength }, +#if HAVE_PCRE_H { C(transform), &type_transform, validate_any }, - { C(trust), &type_string_accum, validate_any }, +#endif { C(url), &type_string, validate_url }, { C(user), &type_string, validate_isauser }, { C(username), &type_string, validate_any }, @@ -1168,6 +1146,7 @@ static int config_set_args(const struct config_state *cs, va_list ap; struct vector v[1]; char *s; + int rc; vector_init(v); vector_append(v, (char *)which); @@ -1176,7 +1155,7 @@ static int config_set_args(const struct config_state *cs, vector_append(v, s); va_end(ap); vector_terminate(v); - int rc = config_set(cs, v->nvec, v->vec); + rc = config_set(cs, v->nvec, v->vec); xfree(v->vec); return rc; } @@ -1333,7 +1312,6 @@ static struct config *config_default(void) { cs.line = 0; cs.config = c; /* Strings had better be xstrdup'd as they will get freed at some point. */ - c->gap = 0; c->history = 60; c->home = xstrdup(pkgstatedir); if(!(pw = getpwuid(getuid()))) @@ -1342,10 +1320,8 @@ static struct config *config_default(void) { c->username = xstrdup(logname); c->refresh = 15; c->refresh_min = 1; - c->prefsync = 0; c->signal = SIGKILL; c->alias = xstrdup("{/artist}{/album}{/title}{ext}"); - c->lock = 1; c->device = xstrdup("default"); c->nice_rescan = 10; c->speaker_command = 0; @@ -1393,6 +1369,7 @@ static struct config *config_default(void) { c->broadcast_from.af = -1; c->listen.af = -1; c->connect.af = -1; + c->rtp_mode = xstrdup("auto"); return c; } @@ -1444,9 +1421,12 @@ void config_free(struct config *c) { static void config_postdefaults(struct config *c, int server) { struct config_state cs; +#if HAVE_PCRE_H const struct conf *whoami; int n; +#endif +#if HAVE_PCRE_H static const char *namepart[][4] = { { "title", "/([0-9]+ *[-:]? *)?([^/]+)\\.[a-zA-Z0-9]+$", "$2", "display" }, { "title", "/([^/]+)\\.[a-zA-Z0-9]+$", "$1", "sort" }, @@ -1464,10 +1444,12 @@ static void config_postdefaults(struct config *c, { "dir", "[[:punct:]]", "", "sort", "g", } }; #define NTRANSFORM (int)(sizeof transform / sizeof *transform) +#endif cs.path = ""; cs.line = 0; cs.config = c; +#if HAVE_PCRE_H if(!c->namepart.n) { whoami = find("namepart"); for(n = 0; n < NNAMEPART; ++n) @@ -1478,13 +1460,15 @@ static void config_postdefaults(struct config *c, for(n = 0; n < NTRANSFORM; ++n) set_transform(&cs, whoami, 5, (char **)transform[n]); } +#endif if(!c->api) { if(c->speaker_command) c->api = xstrdup("command"); else if(c->broadcast.af != -1) c->api = xstrdup("rtp"); else if(config_uaudio_apis) - c->api = xstrdup(config_uaudio_apis[0]->name); + c->api = xstrdup(uaudio_default(config_uaudio_apis, + UAUDIO_API_SERVER)->name); else c->api = xstrdup(""); } @@ -1514,18 +1498,7 @@ static void config_postdefaults(struct config *c, |RIGHT_MOVE__MASK |RIGHT_SCRATCH__MASK |RIGHT_REMOVE__MASK); - /* The idea is to approximate the meaning of the old 'restrict' directive - * in the default rights if they are not overridden. */ - if(c->restrictions & RESTRICT_SCRATCH) - r |= RIGHT_SCRATCH_MINE|RIGHT_SCRATCH_RANDOM; - else - r |= RIGHT_SCRATCH_ANY; - if(!(c->restrictions & RESTRICT_MOVE)) - r |= RIGHT_MOVE_ANY; - if(c->restrictions & RESTRICT_REMOVE) - r |= RIGHT_REMOVE_MINE; - else - r |= RIGHT_REMOVE_ANY; + r |= RIGHT_SCRATCH_ANY|RIGHT_MOVE_ANY|RIGHT_REMOVE_ANY; c->default_rights = rights_string(r); } } @@ -1596,10 +1569,12 @@ int config_read(int server, disorder_error(0, "'nice_server' cannot be changed without a restart"); /* ...but we accept the new config anyway */ } +#if HAVE_PCRE_H if(namepartlist_compare(&c->namepart, &oldconfig->namepart)) { disorder_error(0, "'namepart' settings cannot be changed without a restart"); failed = 1; } +#endif if(stringlist_compare(&c->stopword, &oldconfig->stopword)) { disorder_error(0, "'stopword' settings cannot be changed without a restart"); failed = 1; @@ -1612,18 +1587,6 @@ int config_read(int server, /* everything is good so we shall use the new config */ config_free(config); /* warn about obsolete directives */ - if(c->restrictions) - disorder_error(0, "'restrict' will be removed in a future version"); - if(c->allow.n) - disorder_error(0, "'allow' will be removed in a future version"); - if(c->trust.n) - disorder_error(0, "'trust' will be removed in a future version"); - if(!c->lock) - disorder_error(0, "'lock' will be removed in a future version"); - if(c->gap) - disorder_error(0, "'gap' will be removed in a future version"); - if(c->prefsync) - disorder_error(0, "'prefsync' will be removed in a future version"); config = c; return 0; } @@ -1689,6 +1652,7 @@ static int stringlist_compare(const struct stringlist *a, return 0; } +#if HAVE_PCRE_H /** @brief Order two namepart definitions * @param a First namepart definition * @param b Second namepart definition @@ -1734,13 +1698,15 @@ static int namepartlist_compare(const struct namepartlist *a, else return 0; } +#endif /** @brief Verify configuration table. * @return The number of problems found */ int config_verify(void) { int fails = 0; - for(size_t n = 1; n < sizeof conf / sizeof *conf; ++n) + size_t n; + for(n = 1; n < sizeof conf / sizeof *conf; ++n) if(strcmp(conf[n-1].name, conf[n].name) >= 0) { fprintf(stderr, "%s >= %s\n", conf[n-1].name, conf[n].name); ++fails;