X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/63ad732fd2031c8775ddf98cd538c8759c4537df..07bc035e2ec3e4fb109fb36ad5f1fd751a960e70:/lib/configuration.c diff --git a/lib/configuration.c b/lib/configuration.c index 2dcf8f9..95720a3 100644 --- a/lib/configuration.c +++ b/lib/configuration.c @@ -39,6 +39,7 @@ #include #include +#include "rights.h" #include "configuration.h" #include "mem.h" #include "log.h" @@ -130,28 +131,55 @@ static int set_collections(const struct config_state *cs, const struct conf *whoami, int nvec, char **vec) { struct collectionlist *cl; + const char *root, *encoding, *module; - if(nvec != 3) { - error(0, "%s:%d: '%s' requires three arguments", + switch(nvec) { + case 1: + module = 0; + encoding = 0; + root = vec[0]; + break; + case 2: + module = vec[0]; + encoding = 0; + root = vec[1]; + break; + case 3: + module = vec[0]; + encoding = vec[1]; + root = vec[2]; + break; + case 0: + error(0, "%s:%d: '%s' requires at least one argument", + cs->path, cs->line, whoami->name); + return -1; + default: + error(0, "%s:%d: '%s' requires at most three arguments", cs->path, cs->line, whoami->name); return -1; } - if(vec[2][0] != '/') { + /* Sanity check root */ + if(root[0] != '/') { error(0, "%s:%d: collection root must start with '/'", cs->path, cs->line); return -1; } - if(vec[2][1] && vec[2][strlen(vec[2])-1] == '/') { + if(root[1] && root[strlen(root)-1] == '/') { error(0, "%s:%d: collection root must not end with '/'", cs->path, cs->line); return -1; } + /* Defaults */ + if(!module) + module = "fs"; + if(!encoding) + encoding = nl_langinfo(CODESET); cl = ADDRESS(cs->config, struct collectionlist); ++cl->n; cl->s = xrealloc(cl->s, cl->n * sizeof (struct collection)); - cl->s[cl->n - 1].module = xstrdup(vec[0]); - cl->s[cl->n - 1].encoding = xstrdup(vec[1]); - cl->s[cl->n - 1].root = xstrdup(vec[2]); + cl->s[cl->n - 1].module = xstrdup(module); + cl->s[cl->n - 1].encoding = xstrdup(encoding); + cl->s[cl->n - 1].root = xstrdup(root); return 0; } @@ -489,6 +517,23 @@ static int set_backend(const struct config_state *cs, return 0; } +static int set_rights(const struct config_state *cs, + const struct conf *whoami, + int nvec, char **vec) { + if(nvec != 1) { + error(0, "%s:%d: '%s' requires one argument", + cs->path, cs->line, whoami->name); + return -1; + } + if(parse_rights(vec[0], 0, 1)) { + error(0, "%s:%d: invalid rights string '%s'", + cs->path, cs->line, vec[0]); + return -1; + } + *ADDRESS(cs->config, char *) = vec[0]; + return 0; +} + /* free functions */ static void free_none(struct config attribute((unused)) *c, @@ -587,6 +632,7 @@ static const struct conftype type_restrict = { set_restrict, free_none }, type_namepart = { set_namepart, free_namepartlist }, type_transform = { set_transform, free_transformlist }, + type_rights = { set_rights, free_none }, type_backend = { set_backend, free_none }; /* specific validation routine */ @@ -899,13 +945,17 @@ static const struct conf conf[] = { { C(checkpoint_min), &type_integer, validate_non_negative }, { C(collection), &type_collections, validate_any }, { C(connect), &type_stringlist, validate_addrport }, + { C(cookie_login_lifetime), &type_integer, validate_positive }, + { C(cookie_key_lifetime), &type_integer, validate_positive }, { 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_stringlist, validate_port }, { C(lock), &type_boolean, validate_any }, + { C(mail_sender), &type_string, validate_any }, { C(mixer), &type_string, validate_ischr }, { C(multicast_loop), &type_boolean, validate_any }, { C(multicast_ttl), &type_integer, validate_non_negative }, @@ -926,6 +976,7 @@ static const struct conf conf[] = { { C(scratch), &type_string_accum, validate_isreg }, { C(short_display), &type_integer, validate_positive }, { C(signal), &type_signal, validate_any }, + { C(smtp_server), &type_string, validate_any }, { C(sox_generation), &type_integer, validate_non_negative }, { C(speaker_backend), &type_backend, validate_any }, { C(speaker_command), &type_string, validate_any }, @@ -1022,14 +1073,79 @@ static int config_include(struct config *c, const char *path) { return ret; } +static const char *const default_stopwords[] = { + "stopword", + + "01", + "02", + "03", + "04", + "05", + "06", + "07", + "08", + "09", + "1", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18", + "19", + "2", + "20", + "21", + "22", + "23", + "24", + "25", + "26", + "27", + "28", + "29", + "3", + "30", + "4", + "5", + "6", + "7", + "8", + "9", + "a", + "am", + "an", + "and", + "as", + "for", + "i", + "im", + "in", + "is", + "of", + "on", + "the", + "to", + "too", + "we", +}; +#define NDEFAULT_STOPWORDS (sizeof default_stopwords / sizeof *default_stopwords) + /** @brief Make a new default configuration */ static struct config *config_default(void) { struct config *c = xmalloc(sizeof *c); const char *logname; struct passwd *pw; + struct config_state cs; + cs.path = ""; + cs.line = 0; + cs.config = c; /* Strings had better be xstrdup'd as they will get freed at some point. */ - c->gap = 2; + c->gap = 0; c->history = 60; c->home = xstrdup(pkgstatedir); if(!(pw = getpwuid(getuid()))) @@ -1058,6 +1174,11 @@ static struct config *config_default(void) { c->mixer = xstrdup("/dev/mixer"); c->channel = xstrdup("pcm"); c->dbversion = 2; + c->cookie_login_lifetime = 86400; + c->cookie_key_lifetime = 86400 * 7; + c->smtp_server = xstrdup("127.0.0.1"); + if(config_set(&cs, (int)NDEFAULT_STOPWORDS, (char **)default_stopwords)) + exit(1); return c; } @@ -1163,7 +1284,26 @@ static void config_postdefaults(struct config *c, c->sample_format.bits = 16; c->sample_format.endian = ENDIAN_NATIVE; break; - } + } + if(!c->default_rights) { + rights_type r = RIGHTS__MASK & ~(RIGHT_ADMIN|RIGHT_REGISTER + |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; + c->default_rights = rights_string(r); + } } /** @brief (Re-)read the config file @@ -1206,6 +1346,13 @@ int config_read(int server) { config_postdefaults(c, server); /* everything is good so we shall use the new config */ config_free(config); + /* warn about obsolete directives */ + if(c->restrictions) + error(0, "'restrict' will be removed in a future version"); + if(c->allow.n) + error(0, "'allow' will be removed in a future version"); + if(c->trust.n) + error(0, "'trust' will be removed in a future version"); config = c; return 0; }