author | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-01-01 11:25:55 (GMT) |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-01-01 11:33:04 (GMT) |
commit | 24e6dfa7cffceea0cac0f3cc349192788f040939 (patch) (side-by-side diff) | |
tree | c2bd53e9bc58873c8187e6bd622ae152b35d1d51 /src | |
parent | 2bdd70d698c63d32f25b4f1142e09f5eaef4812a (diff) | |
download | wydawca-24e6dfa7cffceea0cac0f3cc349192788f040939.tar.gz wydawca-24e6dfa7cffceea0cac0f3cc349192788f040939.tar.bz2 |
Update copyright years. Switch to a familiar style.
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/backup.c | 251 | ||||
-rw-r--r-- | src/builtin.c | 337 | ||||
-rw-r--r-- | src/builtin.h | 14 | ||||
-rw-r--r-- | src/cmdline.opt | 93 | ||||
-rw-r--r-- | src/config.c | 2398 | ||||
-rw-r--r-- | src/dictionary.c | 305 | ||||
-rw-r--r-- | src/directive.c | 1152 | ||||
-rw-r--r-- | src/diskio.c | 1155 | ||||
-rw-r--r-- | src/exec.c | 253 | ||||
-rw-r--r-- | src/gpg.c | 527 | ||||
-rw-r--r-- | src/interval.c | 161 | ||||
-rw-r--r-- | src/job.c | 572 | ||||
-rw-r--r-- | src/lock.c | 434 | ||||
-rw-r--r-- | src/mail.c | 1069 | ||||
-rw-r--r-- | src/mail.h | 9 | ||||
-rw-r--r-- | src/meta.c | 221 | ||||
-rw-r--r-- | src/net.c | 415 | ||||
-rw-r--r-- | src/null.c | 68 | ||||
-rw-r--r-- | src/pidfile.c | 104 | ||||
-rw-r--r-- | src/process.c | 469 | ||||
-rw-r--r-- | src/pushd.c | 206 | ||||
-rw-r--r-- | src/report.c | 45 | ||||
-rw-r--r-- | src/sql.c | 272 | ||||
-rw-r--r-- | src/sql.h | 55 | ||||
-rw-r--r-- | src/tcpwrap.c | 85 | ||||
-rw-r--r-- | src/timer.c | 309 | ||||
-rw-r--r-- | src/triplet.c | 1270 | ||||
-rw-r--r-- | src/txtacc.c | 228 | ||||
-rw-r--r-- | src/userprivs.c | 160 | ||||
-rw-r--r-- | src/verify.c | 538 | ||||
-rw-r--r-- | src/vtab.c | 97 | ||||
-rw-r--r-- | src/watcher.c | 379 | ||||
-rw-r--r-- | src/wydawca.c | 608 | ||||
-rw-r--r-- | src/wydawca.h | 735 |
35 files changed, 7197 insertions, 7799 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index e042272..2c8f3c4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ # This file is part of Wydawca -# Copyright (C) 2007, 2009-2011 Sergey Poznyakoff +# Copyright (C) 2007, 2009-2013 Sergey Poznyakoff # # Wydawca is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/src/backup.c b/src/backup.c index c5c55de..7119ae1 100644 --- a/src/backup.c +++ b/src/backup.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2011, 2012 Sergey Poznyakoff + Copyright (C) 2011-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -19,147 +19,138 @@ char const *simple_backup_suffix = "~"; static const char * -split_filename (char const *file, char **pdir) +split_filename(char const *file, char **pdir) { - const char *p = strrchr (file, '/'); - - if (!p) - { - *pdir = grecs_strdup ("."); - p = file; - } - else - { - size_t len = p - file; - char *dir = grecs_malloc (len + 1); - memcpy (dir, file, len); - dir[len] = 0; - *pdir = dir; - p++; - } - return p; + const char *p = strrchr(file, '/'); + + if (!p) { + *pdir = grecs_strdup("."); + p = file; + } else { + size_t len = p - file; + char *dir = grecs_malloc(len + 1); + memcpy(dir, file, len); + dir[len] = 0; + *pdir = dir; + p++; + } + return p; } #define MINSUFSIZE 8 #define ISDIGIT(c) ('0' <= (c) && (c) <= '9') static char * -get_backup_suffix (char const *file, enum backup_type type) +get_backup_suffix(char const *file, enum backup_type type) { - char *dirname; - const char *basename; - size_t baselen; - DIR *dir; - struct dirent *ent; - char *lastsuf = NULL; - size_t lastsuflen = 0; - size_t lastsufsize = 0; - int carry = 0; - char *newsuf; - char *q; - - if (type == simple_backups) - return grecs_strdup (simple_backup_suffix); - - basename = split_filename (file, &dirname); - baselen = strlen (basename); - dir = opendir (dirname); - if (!dir) - { - int ec = errno; - free (dirname); - errno = ec; - return NULL; - } - - while ((ent = readdir (dir))) - { - size_t len = strlen (ent->d_name); - const char *p; - size_t suflen; - - if (len < baselen + 4 || memcmp (ent->d_name, basename, baselen)) - continue; - p = ent->d_name + baselen; - suflen = len - baselen; - if (p[0] == '.' && p[1] == '~' && p[suflen-1] == '~' && - (suflen > lastsuflen - || (suflen == lastsuflen && - memcmp (p, lastsuf, lastsuflen) > 0))) - { - carry = 1; - for (q = (char*) p + suflen - 2; q > p + 1 && ISDIGIT (*q); q--) - if (*q != '9') - carry = 0; - q++; - if (!ISDIGIT (*q)) - continue; - - if (suflen > lastsufsize) - { - lastsufsize = suflen; - if (!lastsuf) - { - if (lastsufsize < MINSUFSIZE) - lastsufsize = MINSUFSIZE; - lastsuf = grecs_malloc (lastsufsize); + char *dirname; + const char *basename; + size_t baselen; + DIR *dir; + struct dirent *ent; + char *lastsuf = NULL; + size_t lastsuflen = 0; + size_t lastsufsize = 0; + int carry = 0; + char *newsuf; + char *q; + + if (type == simple_backups) + return grecs_strdup(simple_backup_suffix); + + basename = split_filename(file, &dirname); + baselen = strlen(basename); + dir = opendir(dirname); + if (!dir) { + int ec = errno; + free(dirname); + errno = ec; + return NULL; + } + + while ((ent = readdir(dir))) { + size_t len = strlen(ent->d_name); + const char *p; + size_t suflen; + + if (len < baselen + 4 || + memcmp(ent->d_name, basename, baselen)) + continue; + p = ent->d_name + baselen; + suflen = len - baselen; + if (p[0] == '.' && p[1] == '~' && p[suflen - 1] == '~' && + (suflen > lastsuflen + || (suflen == lastsuflen && + memcmp(p, lastsuf, lastsuflen) > 0))) { + carry = 1; + for (q = (char *)p + suflen - 2; + q > p + 1 && ISDIGIT(*q); q--) + if (*q != '9') + carry = 0; + q++; + if (!ISDIGIT(*q)) + continue; + + if (suflen > lastsufsize) { + lastsufsize = suflen; + if (!lastsuf) { + if (lastsufsize < MINSUFSIZE) + lastsufsize = MINSUFSIZE; + lastsuf = grecs_malloc(lastsufsize); + } else + lastsuf = grecs_realloc(lastsuf, + lastsufsize); + } + memcpy(lastsuf, p, suflen); + lastsuflen = suflen; } - else - lastsuf = grecs_realloc (lastsuf, lastsufsize); - } - memcpy (lastsuf, p, suflen); - lastsuflen = suflen; } - } - closedir (dir); - free (dirname); - - if (lastsuf) - { - size_t newsuflen; - - newsuflen = lastsuflen + carry; - newsuf = grecs_malloc (newsuflen + 1); - newsuf[0] = '.'; - newsuf[1] = '~'; - newsuf[2] = '0'; - memcpy (newsuf + 2 + carry, lastsuf + 2, lastsuflen - 3); - newsuf[newsuflen-1] = '~'; - newsuf[newsuflen] = 0; - - for (q = newsuf + newsuflen - 2; *q == '9'; q--) - *q = '0'; - ++*q; - free (lastsuf); - } - else if (type == numbered_existing_backups) - newsuf = grecs_strdup (simple_backup_suffix); - else - newsuf = grecs_strdup (".~1~"); - return newsuf; + closedir(dir); + free(dirname); + + if (lastsuf) { + size_t newsuflen; + + newsuflen = lastsuflen + carry; + newsuf = grecs_malloc(newsuflen + 1); + newsuf[0] = '.'; + newsuf[1] = '~'; + newsuf[2] = '0'; + memcpy(newsuf + 2 + carry, lastsuf + 2, lastsuflen - 3); + newsuf[newsuflen - 1] = '~'; + newsuf[newsuflen] = 0; + + for (q = newsuf + newsuflen - 2; *q == '9'; q--) + *q = '0'; + ++*q; + free(lastsuf); + } else if (type == numbered_existing_backups) + newsuf = grecs_strdup(simple_backup_suffix); + else + newsuf = grecs_strdup(".~1~"); + return newsuf; } char * -find_backup_file_name (char const *file, enum backup_type type) +find_backup_file_name(char const *file, enum backup_type type) { - size_t flen; - char *suffix; - char *newname; - - if (type == no_backups) - { - errno = 0; - return NULL; - } - - suffix = get_backup_suffix (file, type); - if (!suffix) - return NULL; - flen = strlen (file); - newname = grecs_malloc (flen + strlen (suffix) + 1); - memcpy (newname, file, flen); - strcpy (newname + flen, suffix); - free (suffix); - /* FIXME: Check newname length */ - return newname; + size_t flen; + char *suffix; + char *newname; + + if (type == no_backups) { + errno = 0; + return NULL; + } + + suffix = get_backup_suffix(file, type); + if (!suffix) + return NULL; + flen = strlen(file); + newname = grecs_malloc(flen + strlen(suffix) + 1); + memcpy(newname, file, flen); + strcpy(newname + flen, suffix); + free(suffix); + /* FIXME: Check newname length */ + return newname; } diff --git a/src/builtin.c b/src/builtin.c index f031897..72b73cd 100644 --- a/src/builtin.c +++ b/src/builtin.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2009-2011 Sergey Poznyakoff + Copyright (C) 2009-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -22,21 +22,21 @@ #endif int -builtin_init (struct dictionary *dict) +builtin_init(struct dictionary *dict) { - return 0; + return 0; } int -builtin_done (struct dictionary *dict) +builtin_done(struct dictionary *dict) { - return 0; + return 0; } void * -builtin_open (struct dictionary *dict) +builtin_open(struct dictionary *dict) { - return dict; + return dict; } #define CMP_EXACT 0 @@ -52,216 +52,203 @@ builtin_open (struct dictionary *dict) typedef int (*strcmp_fn) (const char *, const char *, int flags); static int -cmp_exact (const char *pat, const char *str, int flags) +cmp_exact(const char *pat, const char *str, int flags) { - return strcmp (pat, str) == 0; + return strcmp(pat, str) == 0; } static int -cmp_exact_ci (const char *pat, const char *str, int flags) +cmp_exact_ci(const char *pat, const char *str, int flags) { - return strcmp (pat, str) == 0; + return strcmp(pat, str) == 0; } static int -cmp_fnmatch (const char *pat, const char *str, int flags) +cmp_fnmatch(const char *pat, const char *str, int flags) { - return fnmatch (pat, str, flags) == 0; + return fnmatch(pat, str, flags) == 0; } static int -cmp_regex (const char *pat, const char *str, int flags) +cmp_regex(const char *pat, const char *str, int flags) { - int rc; - regex_t regex; - - rc = regcomp (®ex, pat, flags); - if (rc) - { - char errbuf[512]; - - regerror (rc, ®ex, errbuf, sizeof (errbuf)); - logmsg (LOG_ERR, _("%s: cannot compile regexp: %s"), pat, errbuf); - return 0; - } - - rc = regexec (®ex, str, 0, NULL, 0); - regfree (®ex); - return rc == 0; + int rc; + regex_t regex; + + rc = regcomp(®ex, pat, flags); + if (rc) { + char errbuf[512]; + + regerror(rc, ®ex, errbuf, sizeof(errbuf)); + logmsg(LOG_ERR, _("%s: cannot compile regexp: %s"), pat, + errbuf); + return 0; + } + + rc = regexec(®ex, str, 0, NULL, 0); + regfree(®ex); + return rc == 0; } int -parse_cmp_type (const char *pat, strcmp_fn *cmpfn, int *rf) +parse_cmp_type(const char *pat, strcmp_fn * cmpfn, int *rf) { - size_t len = strcspn (pat, ","); - int flags = 0; - int cmp; - - if (STRMATCH ("exact", pat, len)) - cmp = CMP_EXACT; - else if (STRMATCH ("fnmatch", pat, len)) - cmp = CMP_FNMATCH; - else if (STRMATCH ("regex", pat, len)) - cmp = CMP_REGEX; - else - return 1; - - pat += len; - if (*pat) - { - while (*++pat) - { - switch (*pat) - { - case 'i': - flags |= RF_ICASE; - break; - - case 'b': - flags |= RF_BASIC; - break; - - default: - logmsg (LOG_NOTICE, _("unrecognized comparison flag: %c"), *pat); - } + size_t len = strcspn(pat, ","); + int flags = 0; + int cmp; + + if (STRMATCH("exact", pat, len)) + cmp = CMP_EXACT; + else if (STRMATCH("fnmatch", pat, len)) + cmp = CMP_FNMATCH; + else if (STRMATCH("regex", pat, len)) + cmp = CMP_REGEX; + else + return 1; + + pat += len; + if (*pat) { + while (*++pat) { + switch (*pat) { + case 'i': + flags |= RF_ICASE; + break; + + case 'b': + flags |= RF_BASIC; + break; + + default: + logmsg(LOG_NOTICE, + _("unrecognized comparison flag: %c"), + *pat); + } + } + } + + switch (cmp) { + case CMP_EXACT: + *cmpfn = (flags & RF_ICASE) ? cmp_exact_ci : cmp_exact; + break; + + case CMP_FNMATCH: + *cmpfn = cmp_fnmatch; + *rf = FNM_NOESCAPE | FNM_PERIOD | + ((flags & RF_ICASE) ? FNM_CASEFOLD : 0); + break; + + case CMP_REGEX: + *cmpfn = cmp_regex; + *rf = ((flags & RF_BASIC) ? 0 : REG_EXTENDED) | REG_NOSUB; + if (flags & RF_ICASE) + *rf |= REG_ICASE; + break; } - } - - switch (cmp) - { - case CMP_EXACT: - *cmpfn = (flags & RF_ICASE) ? cmp_exact_ci : cmp_exact; - break; - - case CMP_FNMATCH: - *cmpfn = cmp_fnmatch; - *rf = FNM_NOESCAPE | FNM_PERIOD | - ((flags & RF_ICASE) ? FNM_CASEFOLD : 0); - break; - - case CMP_REGEX: - *cmpfn = cmp_regex; - *rf = ((flags & RF_BASIC) ? 0 : REG_EXTENDED) | REG_NOSUB; - if (flags & RF_ICASE) - *rf |= REG_ICASE; - break; - } - return 0; + return 0; } -struct builtin_data_storage -{ - struct txtacc *acc; - char **wp; +struct builtin_data_storage { + struct txtacc *acc; + char **wp; }; static int default_ncol[] = { - 4, /* project-uploader: name, realname, email, pubkey */ - 2, /* project-owner: email, realname */ + 4, /* project-uploader: name, realname, email, pubkey */ + 2, /* project-owner: email, realname */ }; int -builtin_lookup (struct dictionary *dict, void *handle, const char *req) +builtin_lookup(struct dictionary *dict, void *handle, const char *req) { - int i; - int rc; - size_t count = 0; - struct txtacc *acc; - int flags = 0; - strcmp_fn cmpfn = cmp_exact; - struct builtin_data_storage *bds; - int ncol = default_ncol[dict->id]; - - if (dict->parmc == 0) - { - dict->nrow = dict->ncol = 0; - return 0; - } + int i; + int rc; + size_t count = 0; + struct txtacc *acc; + int flags = 0; + strcmp_fn cmpfn = cmp_exact; + struct builtin_data_storage *bds; + int ncol = default_ncol[dict->id]; + + if (dict->parmc == 0) { + dict->nrow = dict->ncol = 0; + return 0; + } - acc = txtacc_create (); + acc = txtacc_create(); - for (i = 0; i < dict->parmc; i++) - { - char *pat = dict->parmv[i]; + for (i = 0; i < dict->parmc; i++) { + char *pat = dict->parmv[i]; - if (pat[0] == '/') - { - pat++; - if (*pat != '/' && parse_cmp_type (pat, &cmpfn, &flags) == 0) - continue; - } + if (pat[0] == '/') { + pat++; + if (*pat != '/' + && parse_cmp_type(pat, &cmpfn, &flags) == 0) + continue; + } + + if (i + ncol >= dict->parmc) + break; + + if (cmpfn(pat, req, flags)) { + size_t j; + for (j = 1; j <= ncol; j++) { + char *val = dict->parmv[i + j]; + txtacc_grow(acc, val, strlen(val) + 1); + } + count++; + } - if (i + ncol >= dict->parmc) - break; - - if (cmpfn (pat, req, flags)) - { - size_t j; - for (j = 1; j <= ncol; j++) - { - char *val = dict->parmv[i + j]; - txtacc_grow (acc, val, strlen (val) + 1); - } - count++; + i += ncol; } - i += ncol; - } - - dict->nrow = count; - dict->ncol = ncol; - - if (count == 0) - { - txtacc_free (acc); - bds = NULL; - rc = 1; - } - else - { - size_t i; - char *p; - - bds = grecs_malloc (sizeof (*bds)); - count *= ncol; - bds->wp = grecs_calloc (count, sizeof (bds->wp[0])); - bds->acc = acc; - p = txtacc_finish (acc, 0); - - for (i = 0; i < count; i++) - { - bds->wp[i] = p; - p += strlen (p) + 1; + dict->nrow = count; + dict->ncol = ncol; + + if (count == 0) { + txtacc_free(acc); + bds = NULL; + rc = 1; + } else { + size_t i; + char *p; + + bds = grecs_malloc(sizeof(*bds)); + count *= ncol; + bds->wp = grecs_calloc(count, sizeof(bds->wp[0])); + bds->acc = acc; + p = txtacc_finish(acc, 0); + + for (i = 0; i < count; i++) { + bds->wp[i] = p; + p += strlen(p) + 1; + } + rc = 0; } - rc = 0; - } - dict->storage = bds; + dict->storage = bds; - return rc; + return rc; } int -builtin_free_result (struct dictionary *dict, void *handle) +builtin_free_result(struct dictionary *dict, void *handle) { - if (dict->storage) - { - struct builtin_data_storage *bds = dict->storage; - txtacc_free (bds->acc); - free (bds->wp); - free (bds); - dict->storage = NULL; - } - return 0; + if (dict->storage) { + struct builtin_data_storage *bds = dict->storage; + txtacc_free(bds->acc); + free(bds->wp); + free(bds); + dict->storage = NULL; + } + return 0; } int -builtin_get (struct dictionary *dict, void *handle, - unsigned nrow, unsigned ncol) +builtin_get(struct dictionary *dict, void *handle, unsigned nrow, + unsigned ncol) { - struct builtin_data_storage *bds = dict->storage; - char *str = bds->wp[nrow * dict->ncol + ncol]; - dictionary_copy_result (dict, str, strlen (str)); - return 0; + struct builtin_data_storage *bds = dict->storage; + char *str = bds->wp[nrow * dict->ncol + ncol]; + dictionary_copy_result(dict, str, strlen(str)); + return 0; } - diff --git a/src/builtin.h b/src/builtin.h index 7e5245d..a5bcfbc 100644 --- a/src/builtin.h +++ b/src/builtin.h @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2009-2011 Sergey Poznyakoff + Copyright (C) 2009-2013 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -14,9 +14,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -int builtin_init (struct dictionary *); -int builtin_done (struct dictionary *); -void *builtin_open (struct dictionary *); -int builtin_get (struct dictionary *, void *, unsigned, unsigned); -int builtin_lookup (struct dictionary *, void *, const char *); -int builtin_free_result (struct dictionary *, void *); +int builtin_init(struct dictionary *); +int builtin_done(struct dictionary *); +void *builtin_open(struct dictionary *); +int builtin_get(struct dictionary *, void *, unsigned, unsigned); +int builtin_lookup(struct dictionary *, void *, const char *); +int builtin_free_result(struct dictionary *, void *); diff --git a/src/cmdline.opt b/src/cmdline.opt index c9554b8..6f2fbf6 100644 --- a/src/cmdline.opt +++ b/src/cmdline.opt @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon -*- c -*- - Copyright (C) 2007, 2009-2012 Sergey Poznyakoff + Copyright (C) 2007, 2009-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -22,29 +22,30 @@ static struct grecs_list *tag_list; static int string_cmp (const void *elt1, const void *elt2) { - return strcmp ((const char *)elt1, (const char *)elt2); + return strcmp ((const char *)elt1, (const char *)elt2); } int selected_spools () { - return (source_list != NULL || tag_list != NULL); + return (source_list != NULL || tag_list != NULL); } int enabled_spool_p (const struct spool *spool) { - if (source_list || tag_list) - return (source_list && grecs_list_locate (source_list, spool->source_dir)) - || (tag_list && grecs_list_locate (tag_list, spool->tag)); - return 1; + if (source_list || tag_list) + return (source_list && + grecs_list_locate (source_list, spool->source_dir)) || + (tag_list && grecs_list_locate (tag_list, spool->tag)); + return 1; } OPTIONS_BEGIN("wydawca", [<wydawca synchronizes files from a set of upload directories with the corresponding distribution sites>], [<UID [UID...]>], [<gnu>], - [<copyright_year=2007-2012>], + [<copyright_year=2007-2013>], [<copyright_holder=Sergey Poznyakoff>]) GROUP(Selecting program mode) @@ -105,23 +106,21 @@ END OPTION(spool,S,TAG, [<process only spool with the given tag (may be used multiple times)>]) BEGIN - if (!tag_list) - { - tag_list = grecs_list_create (); - tag_list->cmp = string_cmp; - } - grecs_list_append (tag_list, optarg); + if (!tag_list) { + tag_list = grecs_list_create(); + tag_list->cmp = string_cmp; + } + grecs_list_append(tag_list, optarg); END OPTION(source,s,SOURCE-DIR, [<process only spool with the given source (may be used multiple times)>]) BEGIN - if (!source_list) - { - source_list = grecs_list_create (); - source_list->cmp = string_cmp; - } - grecs_list_append (source_list, optarg); + if (!source_list) { + source_list = grecs_list_create(); + source_list->cmp = string_cmp; + } + grecs_list_append(source_list, optarg); END GROUP(Logging) @@ -143,7 +142,7 @@ GROUP(Preprocessor control) OPTION(include-directory,I,DIR, [<add include directory>]) BEGIN - grecs_preproc_add_include_dir (optarg); + grecs_preproc_add_include_dir(optarg); END OPTION(define,D,SYMBOL[=VALUE], @@ -152,15 +151,14 @@ BEGIN char *p; if (!pp_cmd_acc) - pp_cmd_acc = txtacc_create (); - txtacc_grow (pp_cmd_acc, " \"-D", 4); - for (p = optarg; *p; p++) - { - if (*p == '\\' || *p == '"') - txtacc_1grow (pp_cmd_acc, '\\'); - txtacc_1grow (pp_cmd_acc, *p); - } - txtacc_1grow (pp_cmd_acc, '"'); + pp_cmd_acc = txtacc_create (); + txtacc_grow(pp_cmd_acc, " \"-D", 4); + for (p = optarg; *p; p++) { + if (*p == '\\' || *p == '"') + txtacc_1grow(pp_cmd_acc, '\\'); + txtacc_1grow(pp_cmd_acc, *p); + } + txtacc_1grow(pp_cmd_acc, '"'); END OPTION(preprocessor,,COMMAND, @@ -186,21 +184,21 @@ END OPTION(dump-grammar-trace,,, [<dump configuration grammar traces>]) BEGIN - grecs_gram_trace (1); + grecs_gram_trace(1); END OPTION(dump-lex-trace,,, [<dump lexical analyzer traces>]) BEGIN - grecs_lex_trace (1); + grecs_lex_trace(1); END GROUP([<Additional help>]) OPTION(config-help,,, [<show configuration file summary>]) BEGIN - config_help (); - exit (0); + config_help(); + exit(0); END OPTIONS_END @@ -208,18 +206,17 @@ OPTIONS_END void parse_options(int argc, char *argv[]) { - GETOPT(argc, argv) - if (pp_cmd_acc && grecs_preprocessor) - { - char *cmd; - size_t len = strlen (grecs_preprocessor); - txtacc_1grow (pp_cmd_acc, 0); - txtacc_grow (pp_cmd_acc, grecs_preprocessor, len + 1); - cmd = txtacc_finish (pp_cmd_acc, 1); - txtacc_free (pp_cmd_acc); - memmove (cmd + len + 1, cmd, strlen (cmd) + 1); - memcpy (cmd, grecs_preprocessor, len); - cmd[len] = ' '; - grecs_preprocessor = cmd; - } + GETOPT(argc, argv); + if (pp_cmd_acc && grecs_preprocessor) { + char *cmd; + size_t len = strlen(grecs_preprocessor); + txtacc_1grow(pp_cmd_acc, 0); + txtacc_grow(pp_cmd_acc, grecs_preprocessor, len + 1); + cmd = txtacc_finish(pp_cmd_acc, 1); + txtacc_free(pp_cmd_acc); + memmove(cmd + len + 1, cmd, strlen(cmd) + 1); + memcpy(cmd, grecs_preprocessor, len); + cmd[len] = ' '; + grecs_preprocessor = cmd; + } } diff --git a/src/config.c b/src/config.c index 509b0d5..7cc667a 100644 --- a/src/config.c +++ b/src/config.c @@ -17,48 +17,42 @@ #include "wydawca.h" #include "sql.h" #include <mail.h> - -struct keyword -{ - char *name; - int tok; +struct keyword { + char *name; + int tok; }; static int -keyword_to_tok (const char *str, struct keyword *kw, int *pres) +keyword_to_tok(const char *str, struct keyword *kw, int *pres) { - for (; kw->name; kw++) - if (strcmp (kw->name, str) == 0) - { - *pres = kw->tok; - return 0; - } - return 1; + for (; kw->name; kw++) + if (strcmp(kw->name, str) == 0) { + *pres = kw->tok; + return 0; + } + return 1; } static int -tok_to_keyword (int tok, struct keyword *kw, const char **pres) +tok_to_keyword(int tok, struct keyword *kw, const char **pres) { - for (; kw->name; kw++) - if (kw->tok == tok) - { - *pres = kw->name; - return 0; - } - return 1; + for (; kw->name; kw++) + if (kw->tok == tok) { + *pres = kw->name; + return 0; + } + return 1; } - static struct archive_descr default_archive_descr = { - archive_none, - NULL, - no_backups + archive_none, + NULL, + no_backups }; static struct dictionary *default_dictionary[dictionary_count]; static struct notification *default_notification = NULL; - /* safe_file_name: convert a file name possibly containig relative specs (../) into a safer form using only direct descendence. @@ -70,1485 +64,1371 @@ static struct notification *default_notification = NULL; ../file --> NULL */ char * -safe_file_name (char *file_name) +safe_file_name(char *file_name) { - int len; - char *p; - - if (!file_name) - return file_name; - - len = strlen (file_name); - - /* Empty string is returned as is */ - if (len == 0) - return file_name; - - /* delete trailing delimiter if any */ - if (len && file_name[len-1] == '/') - file_name[len-1] = 0; - - /* Eliminate any ./ and /../ */ - for (p = strchr (file_name, '.'); p; p = strchr (p, '.')) - { - if (p[1] == '/' && (p == file_name || p[-1] == '/')) - { - char *q, *s; - - s = p + 2; - q = p; - while ((*q++ = *s++)) - ; - continue; - } - else if (p[1] == '.' && (p[2] == 0 || p[2] == '/')) - { - if (p == file_name) - return NULL; - if (p[-1] == '/') - /* found */ - { - char *q, *s; - - s = p + 2; - - /* Find previous delimiter */ - for (q = p-2; *q != '/' && q >= file_name; q--) - ; - - if (q < file_name) - { - q = file_name; - s++; + int len; + char *p; + + if (!file_name) + return file_name; + + len = strlen(file_name); + + /* Empty string is returned as is */ + if (len == 0) + return file_name; + + /* delete trailing delimiter if any */ + if (len && file_name[len - 1] == '/') + file_name[len - 1] = 0; + + /* Eliminate any ./ and /../ */ + for (p = strchr(file_name, '.'); p; p = strchr(p, '.')) { + if (p[1] == '/' && (p == file_name || p[-1] == '/')) { + char *q, *s; + + s = p + 2; + q = p; + while ((*q++ = *s++)) ; + continue; + } else if (p[1] == '.' && (p[2] == 0 || p[2] == '/')) { + if (p == file_name) + return NULL; + if (p[-1] == '/') { + /* found */ + char *q, *s; + + s = p + 2; + + /* Find previous delimiter */ + for (q = p - 2; *q != '/' && q >= file_name; + q--) ; + + if (q < file_name) { + q = file_name; + s++; + } + + /* Copy stuff */ + p = q; + while ((*q++ = *s++)) ; + continue; + } } - /* Copy stuff */ - p = q; - while ((*q++ = *s++)) - ; - continue; - } + p++; } - p++; - } - - if (file_name[0] == 0) - { - file_name[0] = '/'; - file_name[1] = 0; - } + if (file_name[0] == 0) { + file_name[0] = '/'; + file_name[1] = 0; + } - return file_name; + return file_name; } /* Same as safe_file_name, but returns an allocated copy. */ char * -safe_file_name_alloc (const char *file_name) +safe_file_name_alloc(const char *file_name) { - char *s = grecs_strdup (file_name); - char *ns = safe_file_name (s); - if (!ns) - free (s); - return ns; + char *s = grecs_strdup(file_name); + char *ns = safe_file_name(s); + if (!ns) + free(s); + return ns; } - static struct keyword event_tab[] = { - { "success", ev_success }, - { "bad-ownership", ev_bad_ownership }, - { "bad-directive-signature", ev_bad_directive_signature }, - { "bad-detached-signature", ev_bad_detached_signature }, - { "check-failure", ev_check_fail }, - { NULL } + { "success", ev_success }, + { "bad-ownership", ev_bad_ownership }, + { "bad-directive-signature", ev_bad_directive_signature }, + { "bad-detached-signature", ev_bad_detached_signature }, + { "check-failure", ev_check_fail }, + {NULL} }; const char * -notification_event_str (enum notification_event evt) +notification_event_str(enum notification_event evt) { - const char *ret; - if (tok_to_keyword (evt, event_tab, &ret)) - { - grecs_error (NULL, 0, - _("INTERNAL ERROR: unknown notification event number: %d"), - evt); - return NULL; - } - return ret; + const char *ret; + if (tok_to_keyword(evt, event_tab, &ret)) { + grecs_error(NULL, 0, + _("INTERNAL ERROR: " + "unknown notification event number: %d"), + evt); + return NULL; + } + return ret; } int -string_to_notification_event (grecs_locus_t *locus, const char *val, - enum notification_event *pret) +string_to_notification_event(grecs_locus_t * locus, const char *val, + enum notification_event *pret) { - int res; - if (keyword_to_tok (val, event_tab, &res)) - { - grecs_error (locus, 0, _("unknown notification event: %s"), val); - return 1; - } - *pret = res; - return 0; + int res; + if (keyword_to_tok(val, event_tab, &res)) { + grecs_error(locus, 0, + _("unknown notification event: %s"), val); + return 1; + } + *pret = res; + return 0; } static struct keyword target_tab[] = { - { "read", notify_read }, /* Read recipients from the message headers */ - { "message", notify_read }, - { "admin", notify_admin}, /* System administrator */ - { "owner", notify_owner }, /* Project admin */ - { "user", notify_user }, /* User (uploader) */ - { NULL } + { "read", notify_read }, /* Read recipients from the message + headers */ + { "message", notify_read }, + { "admin", notify_admin }, /* System administrator */ + { "owner", notify_owner }, /* Project admin */ + { "user", notify_user }, /* User (uploader) */ + { NULL } }; - const char * -notification_target_str (enum notification_target tgt) +notification_target_str(enum notification_target tgt) { - const char *ret; - if (tok_to_keyword (tgt, target_tab, &ret)) - { - grecs_error (NULL, 0, - _("INTERNAL ERROR: unknown notification target number: %d"), - tgt); - return NULL; - } - return ret; + const char *ret; + if (tok_to_keyword(tgt, target_tab, &ret)) { + grecs_error(NULL, 0, + _("INTERNAL ERROR: " + "unknown notification target number: %d"), + tgt); + return NULL; + } + return ret; } int -string_to_notification_target (grecs_locus_t *locus, const char *val, - enum notification_target *pret) +string_to_notification_target(grecs_locus_t * locus, const char *val, + enum notification_target *pret) { - int res; - if (keyword_to_tok (val, target_tab, &res)) - { - grecs_error (locus, 0, - _("unknown notification target: %s"), - val); - return 1; - } - *pret = res; - return 0; + int res; + if (keyword_to_tok(val, target_tab, &res)) { + grecs_error(locus, 0, + _("unknown notification target: %s"), val); + return 1; + } + *pret = res; + return 0; } - int -assert_string_arg (grecs_locus_t *locus, - enum grecs_callback_command cmd, - const grecs_value_t *value) +assert_string_arg(grecs_locus_t * locus, + enum grecs_callback_command cmd, const grecs_value_t * value) { - if (cmd != grecs_callback_set_value) - { - grecs_error (locus, 0, _("Unexpected block statement")); - return 1; - } - if (!value || value->type != GRECS_TYPE_STRING) - { - grecs_error (&value->locus, 0, _("expected scalar value as a tag")); - return 1; - } - return 0; + if (cmd != grecs_callback_set_value) { + grecs_error(locus, 0, _("Unexpected block statement")); + return 1; + } + if (!value || value->type != GRECS_TYPE_STRING) { + grecs_error(&value->locus, 0, + _("expected scalar value as a tag")); + return 1; + } + return 0; } grecs_value_t * -get_arg (grecs_locus_t *locus, grecs_value_t *value, unsigned n, int type) +get_arg(grecs_locus_t * locus, grecs_value_t * value, unsigned n, int type) { - if (n >= value->v.arg.c) - { - grecs_error (locus, 0, _("not enough arguments")); - return NULL; - } - value = value->v.arg.v[n]; - if (value->type != type) - { - grecs_error (&value->locus, 0, _("argument %d has wrong type"), n); - return NULL; - } - return value; + if (n >= value->v.arg.c) { + grecs_error(locus, 0, _("not enough arguments")); + return NULL; + } + value = value->v.arg.v[n]; + if (value->type != type) { + grecs_error(&value->locus, 0, _("argument %d has wrong type"), + n); + return NULL; + } + return value; } - static int -cb_mailer (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_mailer(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - int rc; - - if (assert_string_arg (locus, cmd, value)) - return 1; - rc = mu_mailer_create (&mailer, value->v.string); - if (rc) - grecs_error (&value->locus, 0, _("cannot create mailer `%s': %s"), - value->v.string, mu_strerror (rc)); - return rc; + int rc; + + if (assert_string_arg(locus, cmd, value)) + return 1; + rc = mu_mailer_create(&mailer, value->v.string); + if (rc) + grecs_error(&value->locus, 0, + _("cannot create mailer `%s': %s"), + value->v.string, + mu_strerror(rc)); + return rc; } static int -cb_email_address (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_email_address(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - int rc = 1; - mu_address_t addr = NULL; - - switch (value->type) - { - case GRECS_TYPE_STRING: - rc = mu_address_create (&addr, value->v.string); - if (rc) - { - grecs_error (&value->locus, 0, _("%s: invalid email address: %s"), - value->v.string, mu_strerror (rc)); - return rc; - } - break; - - case GRECS_TYPE_LIST: - { + int rc = 1; + mu_address_t addr = NULL; struct grecs_list_entry *ep; - for (ep = value->v.list->head; ep; ep = ep->next) - { - const grecs_value_t *vp = ep->data; - mu_address_t a; - if (assert_string_arg (locus, cmd, vp)) - return 1; - - rc = mu_address_create (&a, vp->v.string); - if (rc == 0) - rc = mu_address_union (&addr, a); - else - { - grecs_error (&value->locus, 0, - _("%s: invalid email address: %s"), - vp->v.string, mu_strerror (rc)); - } - mu_address_destroy (&a); - if (rc) - break; - } - } - break; - - case GRECS_TYPE_ARRAY: - grecs_error (locus, 0, _("too many arguments")); - return 1; - } - - *(mu_address_t*) varptr = addr; - return rc; + switch (value->type) { + case GRECS_TYPE_STRING: + rc = mu_address_create(&addr, value->v.string); + if (rc) { + grecs_error(&value->locus, 0, + _("%s: invalid email address: %s"), + value->v.string, mu_strerror(rc)); + return rc; + } + break; + + case GRECS_TYPE_LIST: + for (ep = value->v.list->head; ep; ep = ep->next) { + const grecs_value_t *vp = ep->data; + mu_address_t a; + if (assert_string_arg(locus, cmd, vp)) + return 1; + + rc = mu_address_create(&a, vp->v.string); + if (rc == 0) + rc = mu_address_union(&addr, a); + else { + grecs_error(&value->locus, 0, + _("%s: invalid email address: %s"), + vp->v.string, + mu_strerror(rc)); + } + mu_address_destroy(&a); + if (rc) + break; + } + break; + + case GRECS_TYPE_ARRAY: + grecs_error(locus, 0, _("too many arguments")); + return 1; + } + + *(mu_address_t *) varptr = addr; + return rc; } static int -cb_interval (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_interval(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - int rc; - time_t interval; - const char *endp; - - /* FIXME 1: Support arrays */ - if (assert_string_arg (locus, cmd, value)) - return 1; - - /* FIXME 2: Support ISO intervals? */ - rc = parse_time_interval (value->v.string, &interval, &endp); - if (rc) - grecs_error (&value->locus, 0, - _("unrecognized interval format (near `%s')"), - endp); - else - *(time_t*) varptr = interval; - return 0; + int rc; + time_t interval; + const char *endp; + + /* FIXME 1: Support arrays */ + if (assert_string_arg(locus, cmd, value)) + return 1; + + /* FIXME 2: Support ISO intervals? */ + rc = parse_time_interval(value->v.string, &interval, &endp); + if (rc) + grecs_error(&value->locus, 0, + _("unrecognized interval format (near `%s')"), + endp); + else + *(time_t *) varptr = interval; + return 0; } static int -cb_absolute_name (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_absolute_name(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - char *word; - - /* FIXME 1: Support arrays */ - if (assert_string_arg (locus, cmd, value)) - return 1; - - word = safe_file_name ((char*)value->v.string); - if (!word || word[0] != '/') - grecs_error (&value->locus, 0, _("must be an absolute file name")); - else - *(char**) varptr = word; - return 0; + char *word; + + /* FIXME 1: Support arrays */ + if (assert_string_arg(locus, cmd, value)) + return 1; + + word = safe_file_name((char *)value->v.string); + if (!word || word[0] != '/') + grecs_error(&value->locus, 0, + _("must be an absolute file name")); + else + *(char **)varptr = word; + return 0; } static int -cb_set_umask (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_set_umask(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - char *p; - mode_t m; - - if (assert_string_arg (locus, cmd, value)) - return 1; - m = strtoul (value->v.string, &p, 8) & 0777; - if (*p) - grecs_error (&value->locus, 0, _("invalid umask (near %s)"), p); - else - umask (m); - return 0; + char *p; + mode_t m; + + if (assert_string_arg(locus, cmd, value)) + return 1; + m = strtoul(value->v.string, &p, 8) & 0777; + if (*p) + grecs_error(&value->locus, 0, _("invalid umask (near %s)"), p); + else + umask(m); + return 0; } - static struct keyword stat_tab[] = { - { "errors", STAT_ERRORS }, - { "warnings", STAT_WARNINGS }, - { "bad-signatures", STAT_BAD_SIGNATURE }, - { "access-violations", STAT_ACCESS_VIOLATIONS }, - { "complete-triplets", STAT_COMPLETE_TRIPLETS }, - { "incomplete-triplets", STAT_INCOMPLETE_TRIPLETS }, - { "bad-triplets", STAT_BAD_TRIPLETS }, - { "expired-triplets", STAT_EXPIRED_TRIPLETS }, - { "triplet-success", STAT_TRIPLET_SUCCESS }, - { "uploads", STAT_UPLOADS }, - { "archives", STAT_ARCHIVES }, - { "symlinks", STAT_SYMLINKS }, - { "rmsymlinks", STAT_RMSYMLINKS }, - { NULL }, + { "errors", STAT_ERRORS }, + { "warnings", STAT_WARNINGS }, + { "bad-signatures", STAT_BAD_SIGNATURE }, + { "access-violations", STAT_ACCESS_VIOLATIONS }, + { "complete-triplets", STAT_COMPLETE_TRIPLETS }, + { "incomplete-triplets", STAT_INCOMPLETE_TRIPLETS }, + { "bad-triplets", STAT_BAD_TRIPLETS }, + { "expired-triplets", STAT_EXPIRED_TRIPLETS }, + { "triplet-success", STAT_TRIPLET_SUCCESS }, + { "uploads", STAT_UPLOADS }, + { "archives", STAT_ARCHIVES }, + { "symlinks", STAT_SYMLINKS }, + { "rmsymlinks", STAT_RMSYMLINKS }, + { NULL }, }; static int -parse_single_statmask (grecs_locus_t *locus, const grecs_value_t *val, - unsigned long *pmask, int *invert) +parse_single_statmask(grecs_locus_t * locus, const grecs_value_t * val, + unsigned long *pmask, int *invert) { - const char *arg; - int x; - - if (val->type != GRECS_TYPE_STRING) - { - grecs_error (&val->locus, 0, _("expected scalar value but found list")); - return 1; - } - - arg = val->v.string; - - if (strcmp (arg, "all") == 0) - { - *pmask = STAT_MASK_ALL; - *invert = 1; - return 0; - } - else if (strcmp (arg, "none") == 0) - { - *pmask = STAT_MASK_NONE; - *invert = 0; - return 0; - } - - if (keyword_to_tok (arg, stat_tab, &x)) - { - grecs_error (&val->locus, 0, _("unknown statistics type: %s"), arg); - return 1; - } - *pmask = STAT_MASK (x); - return 0; + const char *arg; + int x; + + if (val->type != GRECS_TYPE_STRING) { + grecs_error(&val->locus, 0, + _("expected scalar value but found list")); + return 1; + } + + arg = val->v.string; + + if (strcmp(arg, "all") == 0) { + *pmask = STAT_MASK_ALL; + *invert = 1; + return 0; + } else if (strcmp(arg, "none") == 0) { + *pmask = STAT_MASK_NONE; + *invert = 0; + return 0; + } + + if (keyword_to_tok(arg, stat_tab, &x)) { + grecs_error(&val->locus, 0, _("unknown statistics type: %s"), + arg); + return 1; + } + *pmask = STAT_MASK(x); + return 0; } static int -parse_statmask (grecs_locus_t *loc, grecs_value_t *val, unsigned long *pmask) +parse_statmask(grecs_locus_t * loc, grecs_value_t * val, unsigned long *pmask) { - int err = 0; - int invert = 0; - unsigned long mask = 0; - - switch (val->type) - { - case GRECS_TYPE_STRING: - err = parse_single_statmask (loc, val, &mask, &invert); - break; - - case GRECS_TYPE_ARRAY: - { + int err = 0; + int invert = 0; + unsigned long mask = 0; int i; - - for (i = 0; i < val->v.arg.c; i++) - { - unsigned long x; - if (parse_single_statmask (loc, val->v.arg.v[i], &x, &invert)) - err = 1; - else if (invert) - mask &= ~x; - else - mask |= x; - } - } - break; - - case GRECS_TYPE_LIST: - { struct grecs_list_entry *ep; - for (ep = val->v.list->head; ep; ep = ep->next) - { - const grecs_value_t *vp = ep->data; - unsigned long x; - - if (parse_single_statmask (loc, vp, &x, &invert)) - err = 1; - else if (invert) - mask &= ~x; - else - mask |= x; - } - } - break; - } - if (!err) - *pmask = mask; - return err; + switch (val->type) { + case GRECS_TYPE_STRING: + err = parse_single_statmask(loc, val, &mask, &invert); + break; + + case GRECS_TYPE_ARRAY: + for (i = 0; i < val->v.arg.c; i++) { + unsigned long x; + if (parse_single_statmask(loc, val->v.arg.v[i], + &x, &invert)) + err = 1; + else if (invert) + mask &= ~x; + else + mask |= x; + } + break; + + case GRECS_TYPE_LIST: + for (ep = val->v.list->head; ep; ep = ep->next) { + const grecs_value_t *vp = ep->data; + unsigned long x; + + if (parse_single_statmask(loc, vp, &x, &invert)) + err = 1; + else if (invert) + mask &= ~x; + else + mask |= x; + } + break; + } + if (!err) + *pmask = mask; + return err; } static int -cb_statistics (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_statistics(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - return parse_statmask (locus, value, varptr); + return parse_statmask(locus, value, varptr); } - static int -cb_sql_host (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_sql_host(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - struct sqlconn *pconn = varptr; - char *p; - - if (assert_string_arg (locus, cmd, value)) - return 1; - - p = strchr (value->v.string, ':'); - if (p) - { - /* FIXME: Modifies constant string */ - *p++ = 0; - if (p[0] == '/') - { - pconn->socket = grecs_strdup (p); - pconn->host = grecs_strdup ("localhost"); - } - else - { - char *end; - unsigned long n = strtoul (p, &end, 10); - if (*end) - { - grecs_error (&value->locus, 0, - _("invalid port number (near %s)"), end); - return 0; - } - if (n == 0 || n > USHRT_MAX) - { - grecs_error (&value->locus, 0, - _("port number out of range 1..%d"), - USHRT_MAX); - return 0; - } - pconn->port = n; - /* Save host name */ - pconn->host = grecs_strdup (value->v.string); - } - } - else - pconn->host = grecs_strdup (value->v.string); - return 0; + struct sqlconn *pconn = varptr; + char *p; + + if (assert_string_arg(locus, cmd, value)) + return 1; + + p = strchr(value->v.string, ':'); + if (p) { + /* FIXME: Modifies constant string */ + *p++ = 0; + if (p[0] == '/') { + pconn->socket = grecs_strdup(p); + pconn->host = grecs_strdup("localhost"); + } else { + char *end; + unsigned long n = strtoul(p, &end, 10); + if (*end) { + grecs_error(&value->locus, 0, + _("invalid port number (near %s)"), + end); + return 0; + } + if (n == 0 || n > USHRT_MAX) { + grecs_error(&value->locus, 0, + _("port number out of range 1..%d"), + USHRT_MAX); + return 0; + } + pconn->port = n; + /* Save host name */ + pconn->host = grecs_strdup(value->v.string); + } + } else + pconn->host = grecs_strdup(value->v.string); + return 0; } static int -cb_sql (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_sql(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - struct sqlconn *pconn; - void **pdata = cb_data; - - switch (cmd) { - case grecs_callback_section_begin: - if (!value || value->type != GRECS_TYPE_STRING) - { - grecs_error(value ? &value->locus : locus, 0, - _("tag must be a string")); + struct sqlconn *pconn; + void **pdata = cb_data; + + switch (cmd) { + case grecs_callback_section_begin: + if (!value || value->type != GRECS_TYPE_STRING) { + grecs_error(value ? &value->locus : locus, 0, + _("tag must be a string")); + return 0; + } + pconn = grecs_zalloc(sizeof(*pconn)); + pconn->ident = strdup(value->v.string); + *pdata = pconn; + break; + + case grecs_callback_section_end: + pconn = *pdata; + sql_register_conn(pconn); + free(pconn); + *pdata = NULL; + break; + + case grecs_callback_set_value: + grecs_error(locus, 0, _("invalid use of block statement")); + } return 0; - } - pconn = grecs_zalloc (sizeof (*pconn)); - pconn->ident = strdup (value->v.string); - *pdata = pconn; - break; - - case grecs_callback_section_end: - pconn = *pdata; - sql_register_conn (pconn); - free (pconn); - *pdata = NULL; - break; - - case grecs_callback_set_value: - grecs_error (locus, 0, _("invalid use of block statement")); - } - return 0; } static struct grecs_keyword sql_kw[] = { - { "config-file", N_("file"), N_("Read MySQL configuration from <file>"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct sqlconn, config_file) }, - { "config-group", N_("name"), - N_("Read the named group from the SQL configuration file"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct sqlconn, config_group) }, - { "host", N_("host"), N_("Set SQL server hostname or IP address"), - grecs_type_string, GRECS_DFLT, - NULL, 0, cb_sql_host }, - { "database", N_("dbname"), N_("Set database name"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct sqlconn, database), }, - { "user", N_("name"), N_("Set SQL user name"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct sqlconn, user) }, - { "password", N_("arg"), N_("Set SQL user password"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct sqlconn, password) }, - { "ssl-ca", N_("file"), N_("File name of the Certificate Authority (CA) certificate"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct sqlconn, cacert) }, - { NULL } + { "config-file", N_("file"), + N_("Read MySQL configuration from <file>"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct sqlconn, config_file) }, + { "config-group", N_("name"), + N_("Read the named group from the SQL configuration file"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct sqlconn, config_group) }, + { "host", N_("host"), + N_("Set SQL server hostname or IP address"), + grecs_type_string, GRECS_DFLT, + NULL, 0, cb_sql_host }, + { "database", N_("dbname"), N_("Set database name"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct sqlconn, database), }, + { "user", N_("name"), N_("Set SQL user name"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct sqlconn, user) }, + { "password", N_("arg"), N_("Set SQL user password"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct sqlconn, password) }, + { "ssl-ca", N_("file"), + N_("File name of the Certificate Authority (CA) certificate"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct sqlconn, cacert) }, + { NULL } }; - static int -cb_syslog_facility (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_syslog_facility(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - if (assert_string_arg (locus, cmd, value)) - return 1; + if (assert_string_arg(locus, cmd, value)) + return 1; - if (mu_string_to_syslog_facility (value->v.string, varptr)) - grecs_error (&value->locus, 0, _("Unknown syslog facility `%s'"), - value->v.string); - return 0; + if (mu_string_to_syslog_facility(value->v.string, varptr)) + grecs_error(&value->locus, 0, + _("Unknown syslog facility `%s'"), + value->v.string); + return 0; } - static int -cb_define_message (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_define_message(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - const char *ident; - - if (cmd != grecs_callback_set_value) - { - grecs_error (locus, 0, _("Unexpected block statement")); - return 1; - } - if (!value || value->type != GRECS_TYPE_ARRAY || value->v.arg.c != 2) - { - grecs_error (locus, 0, _("expected two arguments")); - return 1; - } - - if (value->v.arg.v[0]->type != GRECS_TYPE_STRING) - { - grecs_error (&value->v.arg.v[0]->locus, 0, - _("first argument not a string")); - return 1; - } - ident = value->v.arg.v[0]->v.string; - - if (value->v.arg.v[1]->type != GRECS_TYPE_STRING) - { - grecs_error (&value->v.arg.v[1]->locus, 0, - _("second argument not a string")); - return 1; - } - - register_message_template (ident, value->v.arg.v[1]->v.string); - return 0; -} + const char *ident; - + if (cmd != grecs_callback_set_value) { + grecs_error(locus, 0, _("Unexpected block statement")); + return 1; + } + if (!value || value->type != GRECS_TYPE_ARRAY || value->v.arg.c != 2) { + grecs_error(locus, 0, _("expected two arguments")); + return 1; + } + + if (value->v.arg.v[0]->type != GRECS_TYPE_STRING) { + grecs_error(&value->v.arg.v[0]->locus, 0, + _("first argument not a string")); + return 1; + } + ident = value->v.arg.v[0]->v.string; + if (value->v.arg.v[1]->type != GRECS_TYPE_STRING) { + grecs_error(&value->v.arg.v[1]->locus, 0, + _("second argument not a string")); + return 1; + } + + register_message_template(ident, value->v.arg.v[1]->v.string); + return 0; +} + static struct grecs_keyword syslog_kw[] = { - { "facility", - N_("name"), - N_("Set syslog facility. Arg is one of the following: user, daemon, " - "auth, authpriv, mail, cron, local0 through local7 (case-insensitive), " - "or a facility number."), - grecs_type_string, GRECS_DFLT, - &log_facility, 0, cb_syslog_facility }, - { "tag", N_("string"), N_("Tag syslog messages with this string"), - grecs_type_string, GRECS_DFLT, - &syslog_tag }, - { "print-priority", N_("arg"), N_("Prefix each message with its priority"), - grecs_type_bool, GRECS_DFLT, - &syslog_include_prio }, - { NULL }, + { "facility", + N_("name"), + N_("Set syslog facility. Arg is one of the following: user, daemon, " + "auth, authpriv, mail, cron, local0 through local7 " + "(case-insensitive), or a facility number."), + grecs_type_string, GRECS_DFLT, + &log_facility, 0, cb_syslog_facility }, + { "tag", N_("string"), N_("Tag syslog messages with this string"), + grecs_type_string, GRECS_DFLT, + &syslog_tag }, + { "print-priority", N_("arg"), + N_("Prefix each message with its priority"), + grecs_type_bool, GRECS_DFLT, + &syslog_include_prio }, + { NULL }, }; - -static struct keyword backup_tab[] = -{ - { "none", no_backups }, - { "off", no_backups }, - { "simple", simple_backups }, - { "never", simple_backups }, - { "existing", numbered_existing_backups }, - { "nil", numbered_existing_backups }, - { "numbered", numbered_backups }, - { "t", numbered_backups }, - { NULL } +static struct keyword backup_tab[] = { + { "none", no_backups }, + { "off", no_backups }, + { "simple", simple_backups }, + { "never", simple_backups }, + { "existing", numbered_existing_backups }, + { "nil", numbered_existing_backups }, + { "numbered", numbered_backups }, + { "t", numbered_backups }, + { NULL } }; static enum backup_type -get_backup_version (grecs_locus_t *locus, const char *ctx, const char *version) +get_backup_version(grecs_locus_t * locus, const char *ctx, const char *version) { - int d; - - if (version == 0 || *version == 0) - return numbered_existing_backups; - else if (keyword_to_tok (version, backup_tab, &d)) - { - if (ctx) - grecs_error (locus, 0, _("%s: ambiguous backup type `%s'"), - ctx, version); - else - grecs_error (locus, 0, _("ambiguous backup type `%s'"), version); - return no_backups; - } - return d; + int d; + + if (version == 0 || *version == 0) + return numbered_existing_backups; + else if (keyword_to_tok(version, backup_tab, &d)) { + if (ctx) + grecs_error(locus, 0, + _("%s: ambiguous backup type `%s'"), ctx, + version); + else + grecs_error(locus, 0, _("ambiguous backup type `%s'"), + version); + return no_backups; + } + return d; } static int -cb_backup (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_backup(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - enum backup_type *ptype = varptr; + enum backup_type *ptype = varptr; - if (assert_string_arg (locus, cmd, value)) - return 1; - *ptype = get_backup_version (&value->locus, NULL, value->v.string); - return 0; + if (assert_string_arg(locus, cmd, value)) + return 1; + *ptype = get_backup_version(&value->locus, NULL, value->v.string); + return 0; } static struct grecs_keyword archive_kw[] = { - { "name", N_("file-or-dir"), N_("Name of archive file or directory"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct archive_descr, name) }, - { "backup", N_("type"), N_("Define backup type"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct archive_descr, backup_type), - cb_backup }, - { NULL } + { "name", N_("file-or-dir"), + N_("Name of archive file or directory"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct archive_descr, name) }, + { "backup", N_("type"), + N_("Define backup type"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct archive_descr, backup_type), + cb_backup }, + { NULL } }; static int -cb_archive (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_archive(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - struct archive_descr *arch = varptr; - void **pdata = cb_data; - - switch (cmd) - { - case grecs_callback_section_begin: - *pdata = arch; - /* fallthrough */ - case grecs_callback_set_value: - if (!value) - { - grecs_error (locus, 0, _("expected tag")); - return 1; - } + struct archive_descr *arch = varptr; + void **pdata = cb_data; + + switch (cmd) { + case grecs_callback_section_begin: + *pdata = arch; + /* fallthrough */ + case grecs_callback_set_value: + if (!value) { + grecs_error(locus, 0, _("expected tag")); + return 1; + } - if (value->type != GRECS_TYPE_STRING) - { - grecs_error (&value->locus, 0, - _("expected scalar value but found list")); - return 1; - } + if (value->type != GRECS_TYPE_STRING) { + grecs_error(&value->locus, 0, + _("expected scalar value but found list")); + return 1; + } - if (strcmp (value->v.string, "none") == 0) - arch->type = archive_none; - else if (strcmp (value->v.string, "tar") == 0) - arch->type = archive_tar; - else if (strcmp (value->v.string, "directory") == 0) - arch->type = archive_directory; - else - { - grecs_error (&value->locus, 0, _("unknown archive type")); - return 1; - } - if (cmd == grecs_callback_section_begin) - return 0; - break; + if (strcmp(value->v.string, "none") == 0) + arch->type = archive_none; + else if (strcmp(value->v.string, "tar") == 0) + arch->type = archive_tar; + else if (strcmp(value->v.string, "directory") == 0) + arch->type = archive_directory; + else { + grecs_error(&value->locus, 0, + _("unknown archive type")); + return 1; + } + if (cmd == grecs_callback_section_begin) + return 0; + break; - case grecs_callback_section_end: - break; - } + case grecs_callback_section_end: + break; + } - if (arch->type == archive_none) - return 0; + if (arch->type == archive_none) + return 0; - if (arch->name == NULL) - { - grecs_error (locus, 0, _("at least archive name must be set")); - return 1; - } + if (arch->name == NULL) { + grecs_error(locus, 0, _("at least archive name must be set")); + return 1; + } - if (arch->type == archive_tar && arch->backup_type != no_backups) - { - grecs_warning (locus, 0, _("backup type ignored for this archive type")); - return 1; - } + if (arch->type == archive_tar && arch->backup_type != no_backups) { + grecs_warning(locus, 0, + _("backup type ignored for this archive type")); + return 1; + } - return 0; + return 0; } - static struct grecs_keyword mail_statistics_kw[] = { - { "message", N_("text"), N_("Message text"), - grecs_type_string, GRECS_DFLT, &admin_stat_message }, - { "statistics", - N_("items"), N_("Send mail if one or more of these items are set"), - grecs_type_string, GRECS_DFLT, &mail_admin_mask, 0, cb_statistics }, - { "gpg-sign", - N_("key"), N_("Sign message with this key"), - grecs_type_string, GRECS_DFLT, &admin_stat_sign_key }, - { NULL } + { "message", N_("text"), + N_("Message text"), + grecs_type_string, GRECS_DFLT, &admin_stat_message }, + { "statistics", N_("items"), + N_("Send mail if one or more of these items are set"), + grecs_type_string, GRECS_DFLT, &mail_admin_mask, 0, cb_statistics }, + { "gpg-sign", + N_("key"), N_("Sign message with this key"), + grecs_type_string, GRECS_DFLT, &admin_stat_sign_key }, + { NULL } }; - - static int -cb_event (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_event(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - enum notification_event *pev = varptr; + enum notification_event *pev = varptr; - if (assert_string_arg (locus, cmd, value)) - return 1; - string_to_notification_event (&value->locus, value->v.string, pev); - return 0; + if (assert_string_arg(locus, cmd, value)) + return 1; + string_to_notification_event(&value->locus, value->v.string, pev); + return 0; } static int -cb_recipient (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_recipient(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - enum notification_target *tgt = varptr; + enum notification_target *tgt = varptr; - if (assert_string_arg (locus, cmd, value)) - return 1; - string_to_notification_target (&value->locus, value->v.string, tgt); - return 0; + if (assert_string_arg(locus, cmd, value)) + return 1; + string_to_notification_target(&value->locus, value->v.string, tgt); + return 0; } static struct grecs_keyword notify_event_kw[] = { - { "event", N_("ev-id"), N_("Event on which to notify"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct notification, ev), cb_event }, - { "recipient", N_("who"), N_("Notify this recipient"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct notification, tgt), - cb_recipient }, - { "message", N_("text-or-id"), - N_("Text of the notification or identifier of a defined message template"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct notification, msg) }, - { "gpg-sign", N_("key"), - N_("Sign message with this key"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct notification, sign_keys) }, - { NULL } + { "event", N_("ev-id"), + N_("Event on which to notify"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct notification, ev), cb_event }, + { "recipient", N_("who"), N_("Notify this recipient"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct notification, tgt), + cb_recipient }, + { "message", N_("text-or-id"), + N_("Text of the notification or identifier of a defined " + "message template"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct notification, msg) }, + { "gpg-sign", N_("key"), + N_("Sign message with this key"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct notification, sign_keys) }, + { NULL } }; static int -cb_notify_event (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_notify_event(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - struct notification *ntf; - void **pdata = cb_data; - - switch (cmd) { - case grecs_callback_section_begin: - ntf = grecs_zalloc (sizeof (*ntf)); - *pdata = ntf; - break; - - case grecs_callback_section_end: - ntf = *pdata; - if (!ntf->msg) - grecs_error (locus, 0, _("missing message definition")); - else - { - struct notification **p = (struct notification **) varptr; - ntf->next = *p; - *p = ntf; - /* FIXME: check ev and tgt? */ - } - break; - - case grecs_callback_set_value: - grecs_error (locus, 0, _("invalid use of block statement")); - } - return 0; -} + struct notification *ntf; + void **pdata = cb_data; + + switch (cmd) { + case grecs_callback_section_begin: + ntf = grecs_zalloc(sizeof(*ntf)); + *pdata = ntf; + break; + + case grecs_callback_section_end: + ntf = *pdata; + if (!ntf->msg) + grecs_error(locus, 0, _("missing message definition")); + else { + struct notification **p = + (struct notification **)varptr; + ntf->next = *p; + *p = ntf; + /* FIXME: check ev and tgt? */ + } + break; + case grecs_callback_set_value: + grecs_error(locus, 0, _("invalid use of block statement")); + } + return 0; +} - static enum dictionary_type -string_to_dictionary_type (const char *str) +string_to_dictionary_type(const char *str) { - if (strcmp (str, "sql") == 0) - return dictionary_sql; - else if (strcmp (str, "builtin") == 0) - return dictionary_builtin; - else if (strcmp (str, "external") == 0) - return dictionary_external; - else - return dictionary_none; + if (strcmp(str, "sql") == 0) + return dictionary_sql; + else if (strcmp(str, "builtin") == 0) + return dictionary_builtin; + else if (strcmp(str, "external") == 0) + return dictionary_external; + else + return dictionary_none; } static int -cb_dictionary_type (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_dictionary_type(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - enum dictionary_type *ptype = varptr; - - if (assert_string_arg (locus, cmd, value)) - return 1; - *ptype = string_to_dictionary_type (value->v.string); - if (*ptype == dictionary_none) - grecs_error (&value->locus, 0, - _("unknown dictionary type: %s"), value->v.string); - return 0; + enum dictionary_type *ptype = varptr; + + if (assert_string_arg(locus, cmd, value)) + return 1; + *ptype = string_to_dictionary_type(value->v.string); + if (*ptype == dictionary_none) + grecs_error(&value->locus, 0, + _("unknown dictionary type: %s"), value->v.string); + return 0; } static int -cb_dictionary_params (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_dictionary_params(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - struct dictionary *meth = varptr; - size_t size; - - if (cmd != grecs_callback_set_value) - { - grecs_error (locus, 0, _("Unexpected block statement")); - return 1; - } - if (!value || value->type != GRECS_TYPE_LIST) - { - grecs_error (value ? &value->locus : locus, 0, _("expected list value")); - return 1; - } - - size = grecs_list_size (value->v.list); - if (size == 0) - { - meth->parmc = 0; - meth->parmv = NULL; - } - else - { - int i; - struct grecs_list_entry *ep; - - meth->parmc = size; - meth->parmv = grecs_calloc (size + 1, sizeof (meth->parmv[0])); - - for (i = 0, ep = value->v.list->head; ep; ep = ep->next, i++) - { - const grecs_value_t *vp = ep->data; - - if (assert_string_arg (locus, cmd, vp)) - break; - - meth->parmv[i] = grecs_strdup (vp->v.string); + struct dictionary *meth = varptr; + size_t size; + + if (cmd != grecs_callback_set_value) { + grecs_error(locus, 0, _("Unexpected block statement")); + return 1; } - meth->parmv[i] = NULL; - } - return 0; + if (!value || value->type != GRECS_TYPE_LIST) { + grecs_error(value ? &value->locus : locus, 0, + _("expected list value")); + return 1; + } + + size = grecs_list_size(value->v.list); + if (size == 0) { + meth->parmc = 0; + meth->parmv = NULL; + } else { + int i; + struct grecs_list_entry *ep; + + meth->parmc = size; + meth->parmv = grecs_calloc(size + 1, sizeof(meth->parmv[0])); + + for (i = 0, ep = value->v.list->head; ep; ep = ep->next, i++) { + const grecs_value_t *vp = ep->data; + + if (assert_string_arg(locus, cmd, vp)) + break; + + meth->parmv[i] = grecs_strdup(vp->v.string); + } + meth->parmv[i] = NULL; + } + return 0; } static struct grecs_keyword dictionary_kw[] = { - { "type", N_("type"), N_("Dictionary type"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct dictionary, type), - cb_dictionary_type }, - { "query", N_("string"), N_("Query template"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct dictionary, query) }, - { "params", N_("arg"), N_("Set dictionary parameters"), - grecs_type_string, GRECS_LIST, - NULL, 0, cb_dictionary_params }, - { NULL } + { "type", N_("type"), + N_("Dictionary type"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct dictionary, type), + cb_dictionary_type }, + { "query", N_("string"), N_("Query template"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct dictionary, query) }, + { "params", N_("arg"), N_("Set dictionary parameters"), + grecs_type_string, GRECS_LIST, + NULL, 0, cb_dictionary_params }, + { NULL } }; int -string_to_dictionary_id (grecs_locus_t *locus, - const char *str, enum dictionary_id *idp) +string_to_dictionary_id(grecs_locus_t * locus, + const char *str, enum dictionary_id *idp) { - static struct keyword id_tab[] = { - { "project-uploader", project_uploader_dict }, - { "project-owner", project_owner_dict }, - { NULL } - }; - int res; - - if (keyword_to_tok (str, id_tab, &res)) - { - grecs_error (locus, 0, _("unknown dictionary ID: %s"), str); - return 1; - } - *idp = res; - return 0; + static struct keyword id_tab[] = { + {"project-uploader", project_uploader_dict}, + {"project-owner", project_owner_dict}, + {NULL} + }; + int res; + + if (keyword_to_tok(str, id_tab, &res)) { + grecs_error(locus, 0, _("unknown dictionary ID: %s"), str); + return 1; + } + *idp = res; + return 0; } static int -cb_dictionary (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_dictionary(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - struct dictionary **pmeth, *meth; - void **pdata = cb_data; - enum dictionary_id id; - - switch (cmd) { - case grecs_callback_section_begin: - if (!value || value->type != GRECS_TYPE_STRING) - { - grecs_error(value ? &value->locus : locus, 0, - _("tag must be a string")); + struct dictionary **pmeth, *meth; + void **pdata = cb_data; + enum dictionary_id id; + + switch (cmd) { + case grecs_callback_section_begin: + if (!value || value->type != GRECS_TYPE_STRING) { + grecs_error(value ? &value->locus : locus, 0, + _("tag must be a string")); + return 0; + } + if (string_to_dictionary_id(&value->locus, + value->v.string, &id)) + return 1; + pmeth = (struct dictionary **)varptr + id; + *pmeth = dictionary_new(id, dictionary_builtin); + *pdata = *pmeth; + break; + + case grecs_callback_section_end: + meth = *pdata; + switch (meth->type) { + case dictionary_sql: + if (meth->parmc == 0 || !meth->parmv[0]) { + grecs_error(locus, 0, + _("SQL connection is not " + "declared")); + meth->type = dictionary_none; + } else if (!sql_connection_exists_p(meth->parmv[0])) { + grecs_error(locus, 0, + _("SQL connection `%s' " + "not declared"), + meth->parmv[0]); + meth->type = dictionary_none; + } + break; + + default: + /* FIXME: More checks ? */ + break; + } + *pdata = NULL; + break; + + case grecs_callback_set_value: + grecs_error(locus, 0, _("invalid use of block statement")); + } return 0; - } - if (string_to_dictionary_id (&value->locus, value->v.string, &id)) - return 1; - pmeth = (struct dictionary **) varptr + id; - *pmeth = dictionary_new (id, dictionary_builtin); - *pdata = *pmeth; - break; - - case grecs_callback_section_end: - meth = *pdata; - switch (meth->type) - { - case dictionary_sql: - if (meth->parmc == 0 || !meth->parmv[0]) - { - grecs_error (locus, 0, _("SQL connection is not declared")); - meth->type = dictionary_none; - } - else if (!sql_connection_exists_p (meth->parmv[0])) - { - grecs_error (locus, 0, _("SQL connection `%s' not declared"), - meth->parmv[0]); - meth->type = dictionary_none; - } - break; - - default: - /* FIXME: More checks ? */ - break; - } - *pdata = NULL; - break; - - case grecs_callback_set_value: - grecs_error (locus, 0, _("invalid use of block statement")); - } - return 0; } static int -cb_url (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_url(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - mu_url_t *purl = varptr, url; - int rc; - - if (assert_string_arg (locus, cmd, value)) - return 1; - rc = mu_url_create (&url, value->v.string); - if (rc) - { - grecs_error (&value->locus, 0, _("cannot create URL `%s': %s"), - value->v.string, mu_strerror (rc)); - return rc; - } - *purl = url; - return 0; + mu_url_t *purl = varptr, url; + int rc; + + if (assert_string_arg(locus, cmd, value)) + return 1; + rc = mu_url_create(&url, value->v.string); + if (rc) { + grecs_error(&value->locus, 0, _("cannot create URL `%s': %s"), + value->v.string, mu_strerror(rc)); + return rc; + } + *purl = url; + return 0; } - static struct grecs_keyword spool_kw[] = { - { "url", N_("arg"), N_("URL corresponding to this spool"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct spool, url) }, - { "alias", N_("arg"), N_("Aliases"), - grecs_type_string, GRECS_LIST, - NULL, offsetof(struct spool, aliases) }, - { "source", N_("dir"), N_("Source directory"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct spool, source_dir) }, - { "destination", N_("dir"), N_("Destination directory"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct spool, dest_url), - cb_url }, - { "file-sweep-time", N_("interval"), N_("Define file sweep time"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct spool, file_sweep_time), - cb_interval }, - { "inotify", NULL, N_("Enable or disable inotify for this spool"), - grecs_type_bool, GRECS_DFLT, - NULL, offsetof(struct spool, inotify_enable), }, - - { "dictionary", N_("ident"), N_("Define data dictionary"), - grecs_type_section, GRECS_DFLT, - NULL, offsetof(struct spool, dictionary), - cb_dictionary, NULL, dictionary_kw }, - { "archive", N_("type: string"), N_("Set up archivation"), - grecs_type_section, GRECS_DFLT, - NULL, offsetof(struct spool, archive), - cb_archive, NULL, archive_kw }, - { "notify-event", NULL, N_("Configure notification"), - grecs_type_section, GRECS_DFLT, - NULL, offsetof(struct spool, notification), - cb_notify_event, NULL, notify_event_kw }, - { "check-script", NULL, N_("A /bin/sh script to verify the tarball"), - grecs_type_string, GRECS_DFLT, - NULL, offsetof(struct spool, check_script) }, - - { NULL } + { "url", N_("arg"), N_("URL corresponding to this spool"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct spool, url) }, + { "alias", N_("arg"), N_("Aliases"), + grecs_type_string, GRECS_LIST, + NULL, offsetof(struct spool, aliases) }, + { "source", N_("dir"), N_("Source directory"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct spool, source_dir) }, + { "destination", N_("dir"), N_("Destination directory"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct spool, dest_url), + cb_url }, + { "file-sweep-time", N_("interval"), N_("Define file sweep time"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct spool, file_sweep_time), + cb_interval }, + { "inotify", NULL, N_("Enable or disable inotify for this spool"), + grecs_type_bool, GRECS_DFLT, + NULL, offsetof(struct spool, inotify_enable), }, + + { "dictionary", N_("ident"), N_("Define data dictionary"), + grecs_type_section, GRECS_DFLT, + NULL, offsetof(struct spool, dictionary), + cb_dictionary, NULL, dictionary_kw }, + { "archive", N_("type: string"), N_("Set up archivation"), + grecs_type_section, GRECS_DFLT, + NULL, offsetof(struct spool, archive), + cb_archive, NULL, archive_kw }, + { "notify-event", NULL, N_("Configure notification"), + grecs_type_section, GRECS_DFLT, + NULL, offsetof(struct spool, notification), + cb_notify_event, NULL, notify_event_kw }, + { "check-script", NULL, N_("A /bin/sh script to verify the tarball"), + grecs_type_string, GRECS_DFLT, + NULL, offsetof(struct spool, check_script) }, + + { NULL } }; static int -cb_spool (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_spool(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - struct spool *spool; - void **pdata = cb_data; - int rc, ec, i; - - switch (cmd) - { - case grecs_callback_section_begin: - if (!value || value->type != GRECS_TYPE_STRING) - { - grecs_error (value ? &value->locus : locus, 0, - _("tag must be a string")); - return 1; - } - spool = grecs_zalloc (sizeof (*spool)); - spool->tag = grecs_strdup (value->v.string); - spool->file_sweep_time = file_sweep_time; - spool->inotify_enable = 1; - for (i = 0; i < NITEMS (spool->dictionary); i++) - spool->dictionary[i] = default_dictionary[i]; - spool->archive = default_archive_descr; - *pdata = spool; - break; - - case grecs_callback_section_end: - rc = 0; - spool = *pdata; - if (!spool->source_dir) - { - grecs_error (locus, 0, _("source is not given")); - rc = 1; - } - else if (test_dir (spool->source_dir, &ec)) - { - if (ec) - grecs_error (locus, ec, _("cannot access %s"), spool->source_dir); - else - grecs_error (locus, 0, _("%s is not a directory"), - spool->source_dir); - rc = 1; - } + struct spool *spool; + void **pdata = cb_data; + int rc, ec, i; + + switch (cmd) { + case grecs_callback_section_begin: + if (!value || value->type != GRECS_TYPE_STRING) { + grecs_error(value ? &value->locus : locus, 0, + _("tag must be a string")); + return 1; + } + spool = grecs_zalloc(sizeof(*spool)); + spool->tag = grecs_strdup(value->v.string); + spool->file_sweep_time = file_sweep_time; + spool->inotify_enable = 1; + for (i = 0; i < NITEMS(spool->dictionary); i++) + spool->dictionary[i] = default_dictionary[i]; + spool->archive = default_archive_descr; + *pdata = spool; + break; + + case grecs_callback_section_end: + rc = 0; + spool = *pdata; + if (!spool->source_dir) { + grecs_error(locus, 0, _("source is not given")); + rc = 1; + } else if (test_dir(spool->source_dir, &ec)) { + if (ec) + grecs_error(locus, ec, _("cannot access %s"), + spool->source_dir); + else + grecs_error(locus, 0, + _("%s is not a directory"), + spool->source_dir); + rc = 1; + } - if (!spool->dest_url) - { - grecs_error (locus, 0, _("destination is not given")); - rc = 1; - } - else if (url_to_vtab (spool->dest_url, &spool->vtab)) - { - grecs_error (locus, 0, _("unsupported url: %s"), - mu_url_to_string (spool->dest_url)); - rc = 1; + if (!spool->dest_url) { + grecs_error(locus, 0, _("destination is not given")); + rc = 1; + } else if (url_to_vtab(spool->dest_url, &spool->vtab)) { + grecs_error(locus, 0, _("unsupported url: %s"), + mu_url_to_string(spool->dest_url)); + rc = 1; + } else if (spool->vtab.test_url + && spool->vtab.test_url(spool->dest_url, locus)) + rc = 1; + + for (i = 0; i < dictionary_count; i++) + if (spool->dictionary[i]->type == + dictionary_external) { + grecs_error(locus, 0, + _("Sorry, the dictionary type " + "`external' is not yet " + "supported")); + rc = 1; + } + + if (rc) + return rc; + + if (!spool->notification) + spool->notification = default_notification; + mu_url_sget_path(spool->dest_url, &spool->dest_dir); + register_spool(spool); + free(spool); + *pdata = NULL; + break; + + case grecs_callback_set_value: + grecs_error(locus, 0, _("invalid use of block statement")); } - else if (spool->vtab.test_url - && spool->vtab.test_url (spool->dest_url, locus)) - rc = 1; - - for (i = 0; i < dictionary_count; i++) - if (spool->dictionary[i]->type == dictionary_external) - { - grecs_error (locus, 0, - _("Sorry, the dictionary type `external' is not yet supported")); - rc = 1; - } - - if (rc) - return rc; - - if (!spool->notification) - spool->notification = default_notification; - mu_url_sget_path (spool->dest_url, &spool->dest_dir); - register_spool (spool); - free (spool); - *pdata = NULL; - break; - - case grecs_callback_set_value: - grecs_error (locus, 0, _("invalid use of block statement")); - } - return 0; + return 0; } - static int -cb_user (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_user(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - struct passwd *pw; - - if (assert_string_arg (locus, cmd, value)) - return 1; - - pw = getpwnam (value->v.string); - if (!pw) - { - grecs_error (&value->locus, 0, - _("no such user: %s"), value->v.string); - return 1; - } - - wydawca_uid = pw->pw_uid; - wydawca_gid = pw->pw_gid; - return 0; + struct passwd *pw; + + if (assert_string_arg(locus, cmd, value)) + return 1; + + pw = getpwnam(value->v.string); + if (!pw) { + grecs_error(&value->locus, 0, + _("no such user: %s"), value->v.string); + return 1; + } + + wydawca_uid = pw->pw_uid; + wydawca_gid = pw->pw_gid; + return 0; } static int -cb_supp_groups (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_supp_groups(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - if (cmd != grecs_callback_set_value) - { - grecs_error (locus, 0, _("Unexpected block statement")); - return 1; - } - if (!value || value->type != GRECS_TYPE_LIST) - { - grecs_error (value ? &value->locus : locus, 0, _("expected list value")); - return 1; - } - - wydawca_supp_groupc = grecs_list_size (value->v.list); - if (wydawca_supp_groupc == 0) - wydawca_supp_groups = NULL; - else - { - int i; - struct grecs_list_entry *ep; - - wydawca_supp_groups = grecs_calloc (wydawca_supp_groupc, - sizeof (wydawca_supp_groups[0])); - - for (i = 0, ep = value->v.list->head; ep; ep = ep->next, i++) - { - const grecs_value_t *vp = ep->data; - struct group *grp; - - if (assert_string_arg (locus, cmd, vp)) - break; - grp = getgrnam (vp->v.string); - if (!grp) - { - grecs_error (&value->locus, 0, - _("no such group: %s"), value->v.string); - break; - } - wydawca_supp_groups[i] = grp->gr_gid; + if (cmd != grecs_callback_set_value) { + grecs_error(locus, 0, _("Unexpected block statement")); + return 1; + } + if (!value || value->type != GRECS_TYPE_LIST) { + grecs_error(value ? &value->locus : locus, 0, + _("expected list value")); + return 1; } - } - return 0; -} + wydawca_supp_groupc = grecs_list_size(value->v.list); + if (wydawca_supp_groupc == 0) + wydawca_supp_groups = NULL; + else { + int i; + struct grecs_list_entry *ep; + + wydawca_supp_groups = + grecs_calloc(wydawca_supp_groupc, + sizeof(wydawca_supp_groups[0])); + + for (i = 0, ep = value->v.list->head; ep; ep = ep->next, i++) { + const grecs_value_t *vp = ep->data; + struct group *grp; + + if (assert_string_arg(locus, cmd, vp)) + break; + grp = getgrnam(vp->v.string); + if (!grp) { + grecs_error(&value->locus, 0, + _("no such group: %s"), + value->v.string); + break; + } + wydawca_supp_groups[i] = grp->gr_gid; + } + } + return 0; +} static struct grecs_keyword locking_kw[] = { - { "enable", NULL, N_("Enable or disable locking"), - grecs_type_bool, GRECS_DFLT, &enable_locking }, - { "directory", N_("dir"), N_("Set directory for lock files"), - grecs_type_string, GRECS_DFLT, &lockdir }, - { "expire-time", N_("interval"), N_("Define lock expiration interval"), - grecs_type_string, GRECS_DFLT, &lock_expire_time, 0, cb_interval }, - { "timeout", N_("interval"), N_("Locking timeout"), - grecs_type_string, GRECS_DFLT, &lock_timeout, 0, cb_interval }, - { NULL } + { "enable", NULL, N_("Enable or disable locking"), + grecs_type_bool, GRECS_DFLT, &enable_locking }, + { "directory", N_("dir"), N_("Set directory for lock files"), + grecs_type_string, GRECS_DFLT, &lockdir }, + { "expire-time", N_("interval"), N_("Define lock expiration interval"), + grecs_type_string, GRECS_DFLT, &lock_expire_time, 0, cb_interval }, + { "timeout", N_("interval"), N_("Locking timeout"), + grecs_type_string, GRECS_DFLT, &lock_timeout, 0, cb_interval }, + { NULL } }; static int -cb_locking (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_locking(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - if (cmd == grecs_callback_set_value) - { - if (!value || value->type != GRECS_TYPE_STRING) - { - grecs_error (value ? &value->locus : locus, 0, - _("expected scalar value as a tag")); - return 1; + if (cmd == grecs_callback_set_value) { + if (!value || value->type != GRECS_TYPE_STRING) { + grecs_error(value ? &value->locus : locus, 0, + _("expected scalar value as a tag")); + return 1; + } + grecs_string_convert(&enable_locking, grecs_type_bool, + value->v.string, locus); } - grecs_string_convert (&enable_locking, grecs_type_bool, value->v.string, - locus); - } - return 0; + return 0; } static int -cb_upload_version (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_upload_version(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - unsigned *pversion = varptr, n; - - if (assert_string_arg (locus, cmd, value)) - return 1; - - if (directive_pack_version (value->v.string, &n)) - { - grecs_error (&value->locus, 0, _("invalid version number")); - return 0; - } - - if (n < MIN_DIRECTIVE_VERSION) - { - grecs_error (&value->locus, 0, _("version number too low")); - return 0; - } - - if (n > MAX_DIRECTIVE_VERSION) - { - grecs_error (&value->locus, 0, _("version number too high")); - return 0; - } - *pversion = n; - return 0; + unsigned *pversion = varptr, n; + + if (assert_string_arg(locus, cmd, value)) + return 1; + + if (directive_pack_version(value->v.string, &n)) { + grecs_error(&value->locus, 0, _("invalid version number")); + return 0; + } + + if (n < MIN_DIRECTIVE_VERSION) { + grecs_error(&value->locus, 0, _("version number too low")); + return 0; + } + + if (n > MAX_DIRECTIVE_VERSION) { + grecs_error(&value->locus, 0, _("version number too high")); + return 0; + } + *pversion = n; + return 0; } - static struct grecs_keyword wydawca_kw[] = { - { "daemon", NULL, N_("Enable daemon mode"), - grecs_type_bool, GRECS_DFLT, &daemon_mode }, - { "foreground", NULL, N_("Start in foreground even in daemon mode"), - grecs_type_bool, GRECS_DFLT, &foreground }, - { "single-process", NULL, N_("Do not spawn subprocesses"), - grecs_type_bool, GRECS_DFLT, &single_process }, - { "wakeup-interval", N_("time"), N_("Set wake-up interval"), - grecs_type_string, GRECS_DFLT, &wakeup_interval, 0, cb_interval }, - { "pidfile", N_("file"), N_("Set pid file name"), - grecs_type_string, GRECS_DFLT, &pidfile }, - - { "inotify", NULL, N_("Enable or disable inotify support"), - grecs_type_bool, GRECS_DFLT, &inotify_enable }, - - { "user", N_("name"), N_("Run with UID and GID of this user"), - grecs_type_string, GRECS_DFLT, NULL, 0, cb_user }, - { "group", NULL, N_("Retain these supplementary groups"), - grecs_type_string, GRECS_LIST, NULL, 0, cb_supp_groups }, - - { "min-version", N_("major.minor"), - N_("Set minimal allowed directive file version"), - grecs_type_string, GRECS_DFLT, - &min_directive_version, 0, cb_upload_version }, - { "max-version", N_("major.minor"), - N_("Set maximal allowed directive file version"), - grecs_type_string, GRECS_DFLT, - &max_directive_version, 0, cb_upload_version }, - - { "locking", NULL, N_("Configure locking"), - grecs_type_section, GRECS_DFLT, NULL, 0, - cb_locking, NULL, locking_kw }, - - { "listen", N_("socket"), N_("Listen on this address"), - grecs_type_sockaddr, GRECS_DFLT, &listen_sockaddr, }, + { "daemon", NULL, N_("Enable daemon mode"), + grecs_type_bool, GRECS_DFLT, &daemon_mode }, + { "foreground", NULL, N_("Start in foreground even in daemon mode"), + grecs_type_bool, GRECS_DFLT, &foreground }, + { "single-process", NULL, N_("Do not spawn subprocesses"), + grecs_type_bool, GRECS_DFLT, &single_process }, + { "wakeup-interval", N_("time"), N_("Set wake-up interval"), + grecs_type_string, GRECS_DFLT, &wakeup_interval, 0, cb_interval }, + { "pidfile", N_("file"), N_("Set pid file name"), + grecs_type_string, GRECS_DFLT, &pidfile }, + + { "inotify", NULL, N_("Enable or disable inotify support"), + grecs_type_bool, GRECS_DFLT, &inotify_enable }, + + { "user", N_("name"), N_("Run with UID and GID of this user"), + grecs_type_string, GRECS_DFLT, NULL, 0, cb_user }, + { "group", NULL, N_("Retain these supplementary groups"), + grecs_type_string, GRECS_LIST, NULL, 0, cb_supp_groups }, + + { "min-version", N_("major.minor"), + N_("Set minimal allowed directive file version"), + grecs_type_string, GRECS_DFLT, + &min_directive_version, 0, cb_upload_version }, + { "max-version", N_("major.minor"), + N_("Set maximal allowed directive file version"), + grecs_type_string, GRECS_DFLT, + &max_directive_version, 0, cb_upload_version }, + + { "locking", NULL, N_("Configure locking"), + grecs_type_section, GRECS_DFLT, NULL, 0, + cb_locking, NULL, locking_kw }, + + { "listen", N_("socket"), N_("Listen on this address"), + grecs_type_sockaddr, GRECS_DFLT, &listen_sockaddr, }, #ifdef WITH_LIBWRAP - { "tcp-wrapper", NULL, N_("Configure TCP wrappers"), - grecs_type_section, GRECS_DFLT, NULL, 0, - NULL, NULL, tcpwrapper_kw }, + { "tcp-wrapper", NULL, N_("Configure TCP wrappers"), + grecs_type_section, GRECS_DFLT, NULL, 0, + NULL, NULL, tcpwrapper_kw }, #endif - { "mailer", N_("url"), N_("Set mailer URL"), - grecs_type_string, GRECS_DFLT, &mailer, 0, cb_mailer }, - { "admin-address", N_("email"), N_("Set admin email address"), - grecs_type_string, GRECS_DFLT, &admin_address, 0, cb_email_address }, - { "from-address", N_("email"), N_("Set sender email address"), - grecs_type_string, GRECS_DFLT, &from_address, 0, cb_email_address }, + { "mailer", N_("url"), N_("Set mailer URL"), + grecs_type_string, GRECS_DFLT, &mailer, 0, cb_mailer }, + { "admin-address", N_("email"), N_("Set admin email address"), + grecs_type_string, GRECS_DFLT, &admin_address, 0, cb_email_address }, + { "from-address", N_("email"), N_("Set sender email address"), + grecs_type_string, GRECS_DFLT, &from_address, 0, cb_email_address }, - /* FIXME: Must be a built-in type? */ - { "file-sweep-time", N_("interval"), N_("Define file sweep time"), - grecs_type_string, GRECS_DFLT, &file_sweep_time, 0, cb_interval }, - { "tar-program", N_("prog"), N_("Set tar invocation command line"), - grecs_type_string, GRECS_DFLT, &tar_command_name, 0, cb_absolute_name }, + /* FIXME: Must be a built-in type? */ + { "file-sweep-time", N_("interval"), N_("Define file sweep time"), + grecs_type_string, GRECS_DFLT, &file_sweep_time, 0, cb_interval }, + { "tar-program", N_("prog"), N_("Set tar invocation command line"), + grecs_type_string, GRECS_DFLT, &tar_command_name, 0, + cb_absolute_name }, - { "umask", N_("mask: octal"), N_("Set umask"), - grecs_type_string, GRECS_DFLT, NULL, 0, cb_set_umask }, + { "umask", N_("mask: octal"), N_("Set umask"), + grecs_type_string, GRECS_DFLT, NULL, 0, cb_set_umask }, - { "archive-signatures", NULL, N_("Control implicit signature archivation"), - grecs_type_bool, GRECS_DFLT, &archive_signatures }, + { "archive-signatures", NULL, + N_("Control implicit signature archivation"), + grecs_type_bool, GRECS_DFLT, &archive_signatures }, - { "statistics", N_("items"), N_("Print these stats at the end of run"), - grecs_type_string, GRECS_DFLT, &print_stats, 0, cb_statistics }, + { "statistics", N_("items"), N_("Print these stats at the end of run"), + grecs_type_string, GRECS_DFLT, &print_stats, 0, cb_statistics }, - { "sql", N_("id: string"), N_("Define SQL database"), - grecs_type_section, GRECS_DFLT, NULL, 0, cb_sql, NULL, sql_kw }, + { "sql", N_("id: string"), N_("Define SQL database"), + grecs_type_section, GRECS_DFLT, NULL, 0, cb_sql, NULL, sql_kw }, - { "syslog", NULL, N_("Configure syslog logging"), - grecs_type_section, GRECS_DFLT, NULL, 0, NULL, NULL, syslog_kw }, + { "syslog", NULL, N_("Configure syslog logging"), + grecs_type_section, GRECS_DFLT, NULL, 0, NULL, NULL, syslog_kw }, - { "define-message", N_("ident: string> <text: string"), - N_("Define message text"), - grecs_type_string, GRECS_DFLT, NULL, 0, cb_define_message }, + { "define-message", N_("ident: string> <text: string"), + N_("Define message text"), + grecs_type_string, GRECS_DFLT, NULL, 0, cb_define_message }, - { "archive", N_("type: string"), N_("Set up archivation"), - grecs_type_section, GRECS_DFLT, &default_archive_descr, 0, - cb_archive, NULL, archive_kw }, + { "archive", N_("type: string"), N_("Set up archivation"), + grecs_type_section, GRECS_DFLT, &default_archive_descr, 0, + cb_archive, NULL, archive_kw }, - { "mail-statistics", NULL, N_("Send statistics"), - grecs_type_section, GRECS_DFLT, NULL, 0, NULL, NULL, mail_statistics_kw }, + { "mail-statistics", NULL, N_("Send statistics"), + grecs_type_section, GRECS_DFLT, NULL, 0, NULL, NULL, + mail_statistics_kw }, - { "notify-event", NULL, N_("Configure notification"), - grecs_type_section, GRECS_DFLT, &default_notification, 0, - cb_notify_event, NULL, notify_event_kw }, + { "notify-event", NULL, N_("Configure notification"), + grecs_type_section, GRECS_DFLT, &default_notification, 0, + cb_notify_event, NULL, notify_event_kw }, - { "dictionary", N_("ident"), N_("Define data dictionary"), - grecs_type_section, GRECS_DFLT, default_dictionary, 0, - cb_dictionary, NULL, dictionary_kw }, + { "dictionary", N_("ident"), N_("Define data dictionary"), + grecs_type_section, GRECS_DFLT, default_dictionary, 0, + cb_dictionary, NULL, dictionary_kw }, - { "check-script", NULL, N_("A /bin/sh script to verify tarballs"), - grecs_type_string, GRECS_DFLT, &default_check_script }, + { "check-script", NULL, N_("A /bin/sh script to verify tarballs"), + grecs_type_string, GRECS_DFLT, &default_check_script }, - { "spool", N_("tag: string"), N_("Define distribution spool"), - grecs_type_section, GRECS_DFLT, NULL, 0, - cb_spool, NULL, spool_kw }, + { "spool", N_("tag: string"), N_("Define distribution spool"), + grecs_type_section, GRECS_DFLT, NULL, 0, + cb_spool, NULL, spool_kw }, - { "all-spools", NULL, N_("Service names that request scanning all spools"), - grecs_type_string, GRECS_LIST, &all_spool_aliases }, + { "all-spools", NULL, + N_("Service names that request scanning all spools"), + grecs_type_string, GRECS_LIST, &all_spool_aliases }, - { "gpg-homedir", NULL, N_("GPG home directory"), - grecs_type_string, GRECS_DFLT, &wydawca_gpg_homedir }, + { "gpg-homedir", NULL, N_("GPG home directory"), + grecs_type_string, GRECS_DFLT, &wydawca_gpg_homedir }, - { NULL } + {NULL} }; void -config_help () +config_help() { - static char docstring[] = - N_("Configuration file structure for wydawca.\n" - "For more information, use `info wydawca configuration'."); - grecs_print_docstring (docstring, 0, stdout); - grecs_print_statement_array (wydawca_kw, 1, 0, stdout); + static char docstring[] = + N_("Configuration file structure for wydawca.\n" + "For more information, use `info wydawca configuration'."); + grecs_print_docstring(docstring, 0, stdout); + grecs_print_statement_array(wydawca_kw, 1, 0, stdout); } void config_init() { - int i; - struct servent *serv; + int i; + struct servent *serv; - grecs_include_path_setup (DEFAULT_VERSION_INCLUDE_DIR, - DEFAULT_INCLUDE_DIR, NULL); - grecs_preprocessor = DEFAULT_PREPROCESSOR; - grecs_log_to_stderr = 1; + grecs_include_path_setup(DEFAULT_VERSION_INCLUDE_DIR, + DEFAULT_INCLUDE_DIR, NULL); + grecs_preprocessor = DEFAULT_PREPROCESSOR; + grecs_log_to_stderr = 1; - serv = getservbyname (PACKAGE, "tcp"); - if (serv != NULL) - grecs_default_port = serv->s_port; + serv = getservbyname(PACKAGE, "tcp"); + if (serv != NULL) + grecs_default_port = serv->s_port; - for (i = 0; i < dictionary_count; i++) - default_dictionary[i] = dictionary_new (i, dictionary_builtin); + for (i = 0; i < dictionary_count; i++) + default_dictionary[i] = dictionary_new(i, dictionary_builtin); } void -config_finish (struct grecs_node *tree) +config_finish(struct grecs_node *tree) { - if (grecs_tree_process (tree, wydawca_kw)) - exit (EX_CONFIG); + if (grecs_tree_process(tree, wydawca_kw)) + exit(EX_CONFIG); } diff --git a/src/dictionary.c b/src/dictionary.c index 11a263b..e36fe7b 100644 --- a/src/dictionary.c +++ b/src/dictionary.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007, 2010-2011 Sergey Poznyakoff + Copyright (C) 2007, 2010-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -18,212 +18,207 @@ #include "sql.h" #include "builtin.h" -struct dictionary_descr -{ - const char *name; +struct dictionary_descr { + const char *name; - int (*init) (struct dictionary *); - int (*done) (struct dictionary *); - int (*free) (struct dictionary *, void *); + int (*init) (struct dictionary *); + int (*done) (struct dictionary *); + int (*free) (struct dictionary *, void *); - void *(*open) (struct dictionary *); - int (*close) (struct dictionary *, void *); + void *(*open) (struct dictionary *); + int (*close) (struct dictionary *, void *); - int (*get) (struct dictionary *, void *, unsigned, unsigned); - int (*lookup) (struct dictionary *, void *, const char *); - int (*quote) (struct dictionary *, void *, const char *, char **, size_t *); + int (*get) (struct dictionary *, void *, unsigned, unsigned); + int (*lookup) (struct dictionary *, void *, const char *); + int (*quote) (struct dictionary *, void *, const char *, char **, + size_t *); }; static struct dictionary_descr dictionary_tab[] = { - { "none", NULL, NULL, NULL, NULL, NULL, NULL, NULL }, - { "sql", sql_init_dictionary, sql_done_dictionary, sql_free_result, - sql_open, NULL, sql_get_dictionary, sql_lookup_dictionary, sql_quote }, - { "builtin", builtin_init, builtin_done, builtin_free_result, - builtin_open, NULL, - builtin_get, - builtin_lookup }, - { "external", NULL, NULL, NULL, NULL, NULL, NULL, NULL } + { "none", NULL, NULL, NULL, NULL, NULL, NULL, NULL}, + { "sql", sql_init_dictionary, sql_done_dictionary, sql_free_result, + sql_open, NULL, sql_get_dictionary, sql_lookup_dictionary, + sql_quote }, + { "builtin", builtin_init, builtin_done, builtin_free_result, + builtin_open, NULL, + builtin_get, + builtin_lookup }, + { "external", NULL, NULL, NULL, NULL, NULL, NULL, NULL } }; struct dictionary * -dictionary_new (enum dictionary_id id, enum dictionary_type type) +dictionary_new(enum dictionary_id id, enum dictionary_type type) { - struct dictionary *mp = grecs_zalloc (sizeof mp[0]); - mp->id = id; - mp->type = type; - return mp; + struct dictionary *mp = grecs_zalloc(sizeof mp[0]); + mp->id = id; + mp->type = type; + return mp; } int -dictionary_init (struct dictionary *dict) +dictionary_init(struct dictionary *dict) { - struct dictionary_descr *mp = dictionary_tab + dict->type; - int rc = 0; - - if (dict->init_passed++) - return 0; - if (debug_level > 1) - { - int i; - logmsg (LOG_DEBUG, _("initializing dictionary: %s \"%s\""), - mp->name, SP (dict->query)); - for (i = 0; i < dict->parmc; i++) - logmsg (LOG_DEBUG, " parmv[%d]=%s", i, dict->parmv[i]); - } - if (mp->init) - rc = mp->init (dict); - if (rc == 0) - dict->init_passed = 1; - return rc; + struct dictionary_descr *mp = dictionary_tab + dict->type; + int rc = 0; + + if (dict->init_passed++) + return 0; + if (debug_level > 1) { + int i; + logmsg(LOG_DEBUG, _("initializing dictionary: %s \"%s\""), + mp->name, SP(dict->query)); + for (i = 0; i < dict->parmc; i++) + logmsg(LOG_DEBUG, " parmv[%d]=%s", i, dict->parmv[i]); + } + if (mp->init) + rc = mp->init(dict); + if (rc == 0) + dict->init_passed = 1; + return rc; } void * -dictionary_open (struct dictionary *dict) +dictionary_open(struct dictionary *dict) { - struct dictionary_descr *mp = dictionary_tab + dict->type; + struct dictionary_descr *mp = dictionary_tab + dict->type; - if (!mp->open) - return NULL; - return mp->open (dict); + if (!mp->open) + return NULL; + return mp->open(dict); } int -dictionary_close (struct dictionary *dict, void *handle) +dictionary_close(struct dictionary *dict, void *handle) { - struct dictionary_descr *mp = dictionary_tab + dict->type; - if (mp->free) - mp->free (dict, handle); - if (!mp->close) - return 0; - return mp->close (dict, handle); + struct dictionary_descr *mp = dictionary_tab + dict->type; + if (mp->free) + mp->free(dict, handle); + if (!mp->close) + return 0; + return mp->close(dict, handle); } int -dictionary_done (struct dictionary *dict) +dictionary_done(struct dictionary *dict) { - struct dictionary_descr *mp = dictionary_tab + dict->type; - int rc = 0; - - if (dict->init_passed == 0) - return 0; - if (--dict->init_passed) - return 0; - if (debug_level > 1) - { - int i; - logmsg (LOG_DEBUG, _("closing dictionary: %s \"%s\""), - mp->name, SP (dict->query)); - for (i = 0; i < dict->parmc; i++) - logmsg (LOG_DEBUG, " parmv[%d]=%s", i, dict->parmv[i]); - } - if (mp->done) - rc = mp->done (dict); - free (dict->result); - dict->result = NULL; - dict->result_size = 0; - return rc; + struct dictionary_descr *mp = dictionary_tab + dict->type; + int rc = 0; + + if (dict->init_passed == 0) + return 0; + if (--dict->init_passed) + return 0; + if (debug_level > 1) { + int i; + logmsg(LOG_DEBUG, _("closing dictionary: %s \"%s\""), + mp->name, SP(dict->query)); + for (i = 0; i < dict->parmc; i++) + logmsg(LOG_DEBUG, " parmv[%d]=%s", i, dict->parmv[i]); + } + if (mp->done) + rc = mp->done(dict); + free(dict->result); + dict->result = NULL; + dict->result_size = 0; + return rc; } int -dictionary_lookup (struct dictionary *dict, void *handle, const char *cmd) +dictionary_lookup(struct dictionary *dict, void *handle, const char *cmd) { - struct dictionary_descr *mp = dictionary_tab + dict->type; - - if (debug_level > 1) - { - if (cmd) - logmsg (LOG_DEBUG, _("dictionary lookup: %s \"%s\""), - mp->name, cmd); - else - logmsg (LOG_DEBUG, _("dictionary lookup: %s"), mp->name); - } - - if (!dict->init_passed) - { - logmsg (LOG_CRIT, - _("INTERNAL ERROR: dictionary %s \"%s\" not initialized"), - mp->name, SP (dict->query)); - return 1; - } - if (!mp->lookup) - { - logmsg (LOG_CRIT, - _("INTERNAL ERROR: no lookup function for dictionary %s \"%s\""), - mp->name, SP (dict->query)); - return 1; - } - if (mp->free) - mp->free (dict, handle); - return mp->lookup (dict, handle, cmd); + struct dictionary_descr *mp = dictionary_tab + dict->type; + + if (debug_level > 1) { + if (cmd) + logmsg(LOG_DEBUG, _("dictionary lookup: %s \"%s\""), + mp->name, cmd); + else + logmsg(LOG_DEBUG, _("dictionary lookup: %s"), + mp->name); + } + + if (!dict->init_passed) { + logmsg(LOG_CRIT, + _("INTERNAL ERROR: " + "dictionary %s \"%s\" not initialized"), + mp->name, SP(dict->query)); + return 1; + } + if (!mp->lookup) { + logmsg(LOG_CRIT, + _("INTERNAL ERROR: " + "no lookup function for dictionary %s \"%s\""), + mp->name, SP(dict->query)); + return 1; + } + if (mp->free) + mp->free(dict, handle); + return mp->lookup(dict, handle, cmd); } unsigned -dictionary_num_rows (struct dictionary *dict) +dictionary_num_rows(struct dictionary *dict) { - return dict->nrow; + return dict->nrow; } unsigned -dictionary_num_cols (struct dictionary *dict) +dictionary_num_cols(struct dictionary *dict) { - return dict->ncol; + return dict->ncol; } const char * -dictionary_result (struct dictionary *dict, void *handle, - unsigned nrow, unsigned ncol) +dictionary_result(struct dictionary *dict, void *handle, + unsigned nrow, unsigned ncol) { - struct dictionary_descr *mp = dictionary_tab + dict->type; + struct dictionary_descr *mp = dictionary_tab + dict->type; - if (nrow >= dict->nrow || ncol >= dict->ncol - || mp->get (dict, handle, nrow, ncol)) - return NULL; - return dict->result; + if (nrow >= dict->nrow || ncol >= dict->ncol + || mp->get(dict, handle, nrow, ncol)) + return NULL; + return dict->result; } void -dictionary_copy_result (struct dictionary *dict, const char *res, size_t size) +dictionary_copy_result(struct dictionary *dict, const char *res, size_t size) { - if (dict->result_size < size + 1) - { - dict->result_size = size + 1; - dict->result = grecs_realloc (dict->result, dict->result_size); - } - memcpy (dict->result, res, size); - dict->result[size] = 0; + if (dict->result_size < size + 1) { + dict->result_size = size + 1; + dict->result = grecs_realloc(dict->result, dict->result_size); + } + memcpy(dict->result, res, size); + dict->result[size] = 0; } /* Quote non-printable characters in INPUT. Point *OUTPUT to the malloc'ed quoted string. Return its length. */ int -dictionary_quote_string (struct dictionary *dict, void *handle, - const char *input, - char **poutput, size_t *psize) +dictionary_quote_string(struct dictionary *dict, void *handle, + const char *input, char **poutput, size_t * psize) { - struct dictionary_descr *mp = dictionary_tab + dict->type; - size_t size; - int quote; - char *output; - - if (!input) - { - *poutput = grecs_malloc (1); - (*poutput)[0] = 0; - *psize = 1; - return 0; - } - - if (mp->quote) - return mp->quote (dict, handle, input, poutput, psize); - - size = wordsplit_c_quoted_length (input, 0, "e); - output = grecs_malloc (size + 1); - wordsplit_c_quote_copy (output, input, 0); - output[size] = 0; - - *poutput = output; - if (psize) - *psize = size; - return 0; + struct dictionary_descr *mp = dictionary_tab + dict->type; + size_t size; + int quote; + char *output; + + if (!input) { + *poutput = grecs_malloc(1); + (*poutput)[0] = 0; + *psize = 1; + return 0; + } + + if (mp->quote) + return mp->quote(dict, handle, input, poutput, psize); + + size = wordsplit_c_quoted_length(input, 0, "e); + output = grecs_malloc(size + 1); + wordsplit_c_quote_copy(output, input, 0); + output[size] = 0; + + *poutput = output; + if (psize) + *psize = size; + return 0; } - diff --git a/src/directive.c b/src/directive.c index cb656e7..ac7c4cc 100644 --- a/src/directive.c +++ b/src/directive.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007-2008, 2010-2012 Sergey Poznyakoff + Copyright (C) 2007-2008, 2010-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -20,70 +20,68 @@ /* Parse directives from TRP->blurb. Fill TRP->directive */ int -directive_parse (struct file_triplet *trp) +directive_parse(struct file_triplet *trp) { - size_t dcount, i, j; - char *p; - - if (debug_level > 2) - logmsg (LOG_DEBUG, _("%s: parsing directive blurb: %s"), - trp->file[file_directive].name, trp->blurb); - - dcount = 0; - for (p = trp->blurb; *p; p++) - if (*p == '\n') - dcount++; - - trp->directive = grecs_calloc (dcount + 1, sizeof trp->directive[0]); - p = trp->blurb; - for (i = j = 0; i < dcount; i++) - { - trp->directive[j] = p; - p = strchr (p, '\n'); - if (p) - *p++ = 0; - if (trim (trp->directive[j]) == 0) /* ignore empty lines */ - continue; - if (strchr (trp->directive[j], ':') == NULL) - { - logmsg (LOG_ERR, _("%s: invalid line: %s"), - trp->file[file_directive].name, trp->directive[j]); - free (trp->directive); - trp->directive = NULL; - return 1; + size_t dcount, i, j; + char *p; + + if (debug_level > 2) + logmsg(LOG_DEBUG, _("%s: parsing directive blurb: %s"), + trp->file[file_directive].name, trp->blurb); + + dcount = 0; + for (p = trp->blurb; *p; p++) + if (*p == '\n') + dcount++; + + trp->directive = grecs_calloc(dcount + 1, sizeof trp->directive[0]); + p = trp->blurb; + for (i = j = 0; i < dcount; i++) { + trp->directive[j] = p; + p = strchr(p, '\n'); + if (p) + *p++ = 0; + if (trim(trp->directive[j]) == 0) /* ignore empty lines */ + continue; + if (strchr(trp->directive[j], ':') == NULL) { + logmsg(LOG_ERR, _("%s: invalid line: %s"), + trp->file[file_directive].name, + trp->directive[j]); + free(trp->directive); + trp->directive = NULL; + return 1; + } + j++; + if (!p) + break; } - j++; - if (!p) - break; - } - trp->directive[j] = NULL; - return 0; + trp->directive[j] = NULL; + return 0; } /* If a directive KEY exists in the triplet TRP, return 0 and point PVAL (unless it is NULL) to its value. Othervise, return 1. */ int -directive_get_value (struct file_triplet *trp, const char *key, - const char **pval) +directive_get_value(struct file_triplet *trp, const char *key, + const char **pval) { - int keylen = strlen (key); - int i; - - for (i = 0; trp->directive[i]; i++) - { - char *str = trp->directive[i]; - int len = strlen (str); - if (len > keylen && memcmp (str, key, keylen) == 0 && str[keylen] == ':') - { - str += keylen + 1; - while (*str && isspace (*str)) - str++; - if (pval) - *pval = str; - return 0; + int keylen = strlen(key); + int i; + + for (i = 0; trp->directive[i]; i++) { + char *str = trp->directive[i]; + int len = strlen(str); + if (len > keylen && memcmp(str, key, keylen) == 0 + && str[keylen] == ':') { + str += keylen + 1; + while (*str && isspace(*str)) + str++; + if (pval) + *pval = str; + return 0; + } } - } - return 1; + return 1; } /* Auxiliary function for sequential access to directories from TRP. @@ -97,622 +95,588 @@ directive_get_value (struct file_triplet *trp, const char *key, If N points past all the directive, the function returns 0. */ static int -_directive_seq_get (int n, struct file_triplet *trp, - const char **pkey, const char **pval) +_directive_seq_get(int n, struct file_triplet *trp, + const char **pkey, const char **pval) { - char *p; - size_t len; - - if (trp->directive[n] == NULL) - return 0; - - p = strchr (trp->directive[n], ':'); - len = p - trp->directive[n]; - if (len + 1 > trp->tmpsize) - { - trp->tmpsize = len + 1; - trp->tmp = grecs_realloc (trp->tmp, trp->tmpsize); - } - memcpy (trp->tmp, trp->directive[n], len); - trp->tmp[len] = 0; - *pkey = trp->tmp; - for (p++; *p && isspace (*p); p++) - ; - if (pval) - *pval = p; - return ++n; + char *p; + size_t len; + + if (trp->directive[n] == NULL) + return 0; + + p = strchr(trp->directive[n], ':'); + len = p - trp->directive[n]; + if (len + 1 > trp->tmpsize) { + trp->tmpsize = len + 1; + trp->tmp = grecs_realloc(trp->tmp, trp->tmpsize); + } + memcpy(trp->tmp, trp->directive[n], len); + trp->tmp[len] = 0; + *pkey = trp->tmp; + for (p++; *p && isspace(*p); p++) ; + if (pval) + *pval = p; + return ++n; } /* Get the first directive from TRP. Point *PKEY to its keyword and *PVAL to its value. Return 1 on success, 0 on failure. */ int -directive_first (struct file_triplet *trp, - const char **pkey, const char **pval) +directive_first(struct file_triplet *trp, const char **pkey, const char **pval) { - int n = 0; - return _directive_seq_get (n, trp, pkey, pval); + int n = 0; + return _directive_seq_get(n, trp, pkey, pval); } /* Get the first directive from TRP. Point *PKEY to its keyword and *PVAL to its value. Return 1 on success, 0 on failure. Return non-0 on success, 0 on failure */ int -directive_next (struct file_triplet *trp, int n, - const char **pkey, const char **pval) +directive_next(struct file_triplet *trp, int n, + const char **pkey, const char **pval) { - return _directive_seq_get (n, trp, pkey, pval); + return _directive_seq_get(n, trp, pkey, pval); } /* Pack a directive string VAL into an unsigned number */ int -directive_pack_version (const char *val, unsigned *pversion) +directive_pack_version(const char *val, unsigned *pversion) { - char *p; - unsigned v; - - v = strtoul (val, &p, 10); - if (*p != '.') - return 1; - p++; - v *= 100; - v += strtoul (p, &p, 10); - if (*p && *p != '.') - return 1; - *pversion = v; - return 0; + char *p; + unsigned v; + + v = strtoul(val, &p, 10); + if (*p != '.') + return 1; + p++; + v *= 100; + v += strtoul(p, &p, 10); + if (*p && *p != '.') + return 1; + *pversion = v; + return 0; } int -directive_unpack_version (unsigned version, char **pbuf, size_t *psize) +directive_unpack_version(unsigned version, char **pbuf, size_t * psize) { - return grecs_asprintf (pbuf, psize, "%u.%u", - version / 100, version % 100); + return grecs_asprintf(pbuf, psize, "%u.%u", + version / 100, version % 100); } - + /* Return true if the directory file version of the triplet TRP is within the inclusive range FROM and TO (packed) */ int -directive_version_in_range_p (struct file_triplet *trp, - unsigned from, unsigned to) +directive_version_in_range_p(struct file_triplet *trp, + unsigned from, unsigned to) { - const char *val; - unsigned version; - - if (directive_get_value (trp, "version", &val)) - { - logmsg (LOG_ERR, _("%s: missing `version' directive"), - trp->file[file_directive].name); - return 0; - } - - if (directive_pack_version (val, &version)) - { - logmsg (LOG_ERR, _("%s: unparsable version: %s"), - trp->file[file_directive].name, val); - return 0; - } - logmsg (LOG_NOTICE, _("%s: VERSION: %s"), - trp->file[file_directive].name, val); - - trp->version = version; - - if (from <= version && version <= to) - return 1; - - logmsg (LOG_ERR, _("%s: version %s is not in the allowed range"), - trp->file[file_directive].name, val); - return 0; + const char *val; + unsigned version; + + if (directive_get_value(trp, "version", &val)) { + logmsg(LOG_ERR, _("%s: missing `version' directive"), + trp->file[file_directive].name); + return 0; + } + + if (directive_pack_version(val, &version)) { + logmsg(LOG_ERR, _("%s: unparsable version: %s"), + trp->file[file_directive].name, val); + return 0; + } + logmsg(LOG_NOTICE, _("%s: VERSION: %s"), + trp->file[file_directive].name, val); + + trp->version = version; + + if (from <= version && version <= to) + return 1; + + logmsg(LOG_ERR, _("%s: version %s is not in the allowed range"), + trp->file[file_directive].name, val); + return 0; } -enum directive - { - unknown_dir, - comment_dir, - directory_dir, - version_dir, - filename_dir, - rmsymlink_dir, - archive_dir, - symlink_dir, - replace_dir - }; - -struct directive_table -{ - const char *name; - enum directive dir; +enum directive { + unknown_dir, + comment_dir, + directory_dir, + version_dir, + filename_dir, + rmsymlink_dir, + archive_dir, + symlink_dir, + replace_dir +}; + +struct directive_table { + const char *name; + enum directive dir; }; static struct directive_table directive_table[] = { - { "comment", comment_dir }, - { "directory", directory_dir }, - { "version", version_dir }, - { "filename", filename_dir }, - { "symlink", symlink_dir }, - { "rmsymlink", rmsymlink_dir }, - { "archive", archive_dir }, - { "replace", replace_dir }, - { NULL } + { "comment", comment_dir }, + { "directory", directory_dir }, + { "version", version_dir }, + { "filename", filename_dir }, + { "symlink", symlink_dir }, + { "rmsymlink", rmsymlink_dir }, + { "archive", archive_dir }, + { "replace", replace_dir }, + { NULL } }; static enum directive -find_directive (const char *key) +find_directive(const char *key) { - int i; + int i; - for (i = 0; directive_table[i].name; i++) - if (strcmp (directive_table[i].name, key) == 0) - return directive_table[i].dir; - return unknown_dir; + for (i = 0; directive_table[i].name; i++) + if (strcmp(directive_table[i].name, key) == 0) + return directive_table[i].dir; + return unknown_dir; } /* Return 0 if the directory file format of the triplet TRP is OK. */ int -verify_directive_format (struct file_triplet *trp) +verify_directive_format(struct file_triplet *trp) { - int n, dnum; - const char *key; - - if (!directive_version_in_range_p (trp, min_directive_version, - max_directive_version)) - return 1; - - dnum = 0; - for (n = directive_first (trp, &key, NULL); n; - n = directive_next (trp, n, &key, NULL)) - { - if (strcmp (key, "comment") == 0) - continue; - dnum++; - switch (dnum) - { - case 1: - if (strcmp (key, "version")) - { - logmsg (LOG_ERR, _("%s:%d: expected `%s' but found `%s'"), - trp->file[file_directive].name, n, "version", key); - return 1; - } - break; - - case 2: - if (strcmp (key, "directory")) - { - logmsg (LOG_ERR, _("%s:%d: expected `%s' but found `%s'"), - trp->file[file_directive].name, n, "directory", key); - return 1; - } - break; - - default: - if (find_directive (key) == unknown_dir) - { - logmsg (LOG_ERR, _("%s:%d: unknown directive `%s'"), - trp->file[file_directive].name, n, key); - return 1; - } - } - } - - if (trp->file[file_dist].name && trp->file[file_signature].name) - { - const char *filename; - if (directive_get_value (trp, "filename", &filename)) - { - logmsg (LOG_ERR, _("%s: missing `filename' directive"), - trp->file[file_directive].name); - return 1; + int n, dnum; + const char *key; + + if (!directive_version_in_range_p(trp, min_directive_version, + max_directive_version)) + return 1; + + dnum = 0; + for (n = directive_first(trp, &key, NULL); n; + n = directive_next(trp, n, &key, NULL)) { + if (strcmp(key, "comment") == 0) + continue; + dnum++; + switch (dnum) { + case 1: + if (strcmp(key, "version")) { + logmsg(LOG_ERR, + _("%s:%d: expected `%s' but found `%s'"), + trp->file[file_directive].name, n, + "version", key); + return 1; + } + break; + + case 2: + if (strcmp(key, "directory")) { + logmsg(LOG_ERR, + _("%s:%d: expected `%s' but found `%s'"), + trp->file[file_directive].name, n, + "directory", key); + return 1; + } + break; + + default: + if (find_directive(key) == unknown_dir) { + logmsg(LOG_ERR, + _("%s:%d: unknown directive `%s'"), + trp->file[file_directive].name, n, key); + return 1; + } + } } - if (strcmp (filename, trp->file[file_dist].name)) - { - logmsg (LOG_ERR, _("%s: filename %s does not match actual name"), - trp->file[file_dist].name, filename); - return 1; + + if (trp->file[file_dist].name && trp->file[file_signature].name) { + const char *filename; + if (directive_get_value(trp, "filename", &filename)) { + logmsg(LOG_ERR, _("%s: missing `filename' directive"), + trp->file[file_directive].name); + return 1; + } + if (strcmp(filename, trp->file[file_dist].name)) { + logmsg(LOG_ERR, + _("%s: filename %s does not match actual name"), + trp->file[file_dist].name, filename); + return 1; + } } - } - return 0; + return 0; } - - static char * -save_script (const char *script) +save_script(const char *script) { - char *file_name; - mode_t old_mask; - int fd; - size_t length; - - file_name = concat_dir (temp_homedir, "chkXXXXXX", NULL); - old_mask = umask (0077); - fd = mkstemp (file_name); - umask (old_mask); - if (fd == -1) - { - logmsg (LOG_CRIT, _("cannot create temporary script file %s: %s"), - file_name, strerror (errno)); - free (file_name); - return NULL; - } - - length = strlen (script); - while (length) - { - ssize_t wrb = write (fd, script, length); - if (wrb == -1) - { - logmsg (LOG_CRIT, _("error writing to temporary script file %s: %s"), - file_name, strerror (errno)); - break; - } - if (wrb == 0) - { - logmsg (LOG_CRIT, _("short write to temporary script file %s"), - file_name); - break; + char *file_name; + mode_t old_mask; + int fd; + size_t length; + + file_name = concat_dir(temp_homedir, "chkXXXXXX", NULL); + old_mask = umask(0077); + fd = mkstemp(file_name); + umask(old_mask); + if (fd == -1) { + logmsg(LOG_CRIT, + _("cannot create temporary script file %s: %s"), + file_name, strerror(errno)); + free(file_name); + return NULL; } - length -= wrb; - script += wrb; - } - close (fd); - if (length) - { - free (file_name); - return NULL; - } - return file_name; + length = strlen(script); + while (length) { + ssize_t wrb = write(fd, script, length); + if (wrb == -1) { + logmsg(LOG_CRIT, + _("error writing to temporary script " + "file %s: %s"), + file_name, strerror(errno)); + break; + } + if (wrb == 0) { + logmsg(LOG_CRIT, + _("short write to temporary script file %s"), + file_name); + break; + } + + length -= wrb; + script += wrb; + } + close(fd); + if (length) { + free(file_name); + return NULL; + } + return file_name; } static int -stderr_redirector (const char *tag) +stderr_redirector(const char *tag) { - int p[2]; - pid_t pid; - - if (pipe (p)) - { - logmsg (LOG_CRIT, "redirector pipe: %s", strerror (errno)); - return -1; - } - - pid = fork (); - if (pid == -1) - { - logmsg (LOG_CRIT, "redirector fork: %s", strerror (errno)); - return -1; - } - - if (pid == 0) - { - FILE *fp; - size_t size = 0; - char *buf = NULL; - - close (p[1]); - fp = fdopen (p[0], "r"); - if (!fp) - _exit (127); - while (grecs_getline (&buf, &size, fp) >= 0) - { - trim_crlf (buf); - logmsg (LOG_NOTICE, "%s: %s", tag, buf); + int p[2]; + pid_t pid; + + if (pipe(p)) { + logmsg(LOG_CRIT, "redirector pipe: %s", strerror(errno)); + return -1; + } + + pid = fork(); + if (pid == -1) { + logmsg(LOG_CRIT, "redirector fork: %s", strerror(errno)); + return -1; + } + + if (pid == 0) { + FILE *fp; + size_t size = 0; + char *buf = NULL; + + close(p[1]); + fp = fdopen(p[0], "r"); + if (!fp) + _exit(127); + while (grecs_getline(&buf, &size, fp) >= 0) { + trim_crlf(buf); + logmsg(LOG_NOTICE, "%s: %s", tag, buf); + } + _exit(0); } - _exit (0); - } - close (p[0]); - return p[1]; + close(p[0]); + return p[1]; } static int -run_check_script (const char *script, struct file_triplet *trp, - const char *descr) +run_check_script(const char *script, struct file_triplet *trp, + const char *descr) { - static char *script_file; - pid_t pid; - int status; - int p[2]; - RETSIGTYPE (*oldsig)(); - FILE *fp; - char *buf; - size_t size, total; - - if (debug_level > 1) - logmsg (LOG_DEBUG, _("prep script: %20.20s%s"), - script, strlen (script) > 20 ? "..." : ""); - script_file = save_script (script); - if (!script_file) - return 1; - if (debug_level > 1) - logmsg (LOG_DEBUG, _("script file: %s"), script_file); - - if (pipe (p)) - { - logmsg (LOG_CRIT, "pipe: %s", strerror (errno)); - return 1; - } - oldsig = signal (SIGCHLD, SIG_DFL); - pid = fork (); - if (pid == -1) - { - logmsg (LOG_CRIT, "fork: %s", strerror (errno)); - free (script_file); - close (p[0]); - close (p[1]); - signal (SIGCHLD, oldsig); - return 1; - } - if (pid == 0) - { - int i; - int efd; - char *argv[4]; - const struct spool *spool = trp->spool; - - signal (SIGHUP, SIG_DFL); - signal (SIGTERM, SIG_DFL); - signal (SIGQUIT, SIG_DFL); - signal (SIGINT, SIG_DFL); - signal (SIGCHLD, SIG_DFL); - signal (SIGALRM, SIG_DFL); - - efd = stderr_redirector (script_file); - if (efd == -1) - _exit (127); - - for (i = getdtablesize (); i >= 0; i--) - { - if (i != p[1] && i != efd) - close (i); + static char *script_file; + pid_t pid; + int status; + int p[2]; + RETSIGTYPE(*oldsig) (); + FILE *fp; + char *buf; + size_t size, total; + + if (debug_level > 1) + logmsg(LOG_DEBUG, _("prep script: %20.20s%s"), + script, strlen(script) > 20 ? "..." : ""); + script_file = save_script(script); + if (!script_file) + return 1; + if (debug_level > 1) + logmsg(LOG_DEBUG, _("script file: %s"), script_file); + + if (pipe(p)) { + logmsg(LOG_CRIT, "pipe: %s", strerror(errno)); + return 1; + } + oldsig = signal(SIGCHLD, SIG_DFL); + pid = fork(); + if (pid == -1) { + logmsg(LOG_CRIT, "fork: %s", strerror(errno)); + free(script_file); + close(p[0]); + close(p[1]); + signal(SIGCHLD, oldsig); + return 1; + } + if (pid == 0) { + int i; + int efd; + char *argv[4]; + const struct spool *spool = trp->spool; + + signal(SIGHUP, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + signal(SIGALRM, SIG_DFL); + + efd = stderr_redirector(script_file); + if (efd == -1) + _exit(127); + + for (i = getdtablesize(); i >= 0; i--) { + if (i != p[1] && i != efd) + close(i); + } + + if (p[1] != 1 && dup2(p[1], 1) != 1) { + logmsg(LOG_CRIT, + "cannot duplicate script's stdout: %s", + strerror(errno)); + _exit(127); + } + + if (efd != 2 && dup2(efd, 2) != 2) { + logmsg(LOG_CRIT, + "cannot duplicate script's stderr: %s", + strerror(errno)); + _exit(127); + } + + setenv("WYDAWCA_SPOOL", spool->tag, 1); + setenv("WYDAWCA_SOURCE", spool->source_dir, 1); + setenv("WYDAWCA_DEST", spool->dest_dir, 1); + setenv("WYDAWCA_URL", spool->url, 1); + setenv("WYDAWCA_TRIPLET_BASE", trp->name, 1); + setenv("WYDAWCA_DIST_FILE", trp->file[file_dist].name, 1); + + if (chdir(temp_homedir)) { + logmsg(LOG_CRIT, "cannot change to %s: %s", + temp_homedir, strerror(errno)); + _exit(127); + } + + argv[0] = "sh"; + argv[1] = script_file; + argv[2] = NULL; + + execv("/bin/sh", argv); + _exit(127); } - if (p[1] != 1 && dup2 (p[1], 1) != 1) - { - logmsg (LOG_CRIT, "cannot duplicate script's stdout: %s", - strerror (errno)); - _exit (127); + /* Master */ + free(script_file); + close(p[1]); + fp = fdopen(p[0], "r"); + buf = NULL; + size = total = 0; + if (debug_level > 2) + logmsg(LOG_DEBUG, _("reading script output...")); + while (grecs_getline(&buf, &size, fp) > 0) { + size_t len = strlen(buf); + if (debug_level > 2) + logmsg(LOG_DEBUG, _("read: %s"), buf); + txtacc_grow(trp->acc, buf, len); + total += size; } - - if (efd != 2 && dup2 (efd, 2) != 2) - { - logmsg (LOG_CRIT, "cannot duplicate script's stderr: %s", - strerror (errno)); - _exit (127); + txtacc_1grow(trp->acc, 0); + if (debug_level > 2) + logmsg(LOG_DEBUG, _("bytes read: %lu"), (unsigned long)total); + + fclose(fp); + + waitpid(pid, &status, 0); + signal(SIGCHLD, oldsig); + + if (total) + trp->check_diag = txtacc_finish(trp->acc, 0); + + trp->check_result = status; + if (WIFEXITED(status)) { + status = WEXITSTATUS(status); + if (status) { + logmsg(LOG_ERR, "%s for %s@%s returned %d", + descr, trp->name, trp->spool->tag, status); + return 1; + } else if (debug_level > 2) + logmsg(LOG_DEBUG, "%s for %s@%s returned %d", + descr, trp->name, trp->spool->tag, status); + } else if (WIFSIGNALED(status)) { + int sig = WTERMSIG(status); + logmsg(LOG_NOTICE, + "%s for %s@%s terminated on signal %d", + descr, trp->name, trp->spool->tag, sig); + return 1; + } else { + logmsg(LOG_NOTICE, + "%s for %s@%s terminated with unhandled status", + descr, trp->name, trp->spool->tag); + return 1; } + return 0; +} - setenv ("WYDAWCA_SPOOL", spool->tag, 1); - setenv ("WYDAWCA_SOURCE", spool->source_dir, 1); - setenv ("WYDAWCA_DEST", spool->dest_dir, 1); - setenv ("WYDAWCA_URL", spool->url, 1); - setenv ("WYDAWCA_TRIPLET_BASE", trp->name, 1); - setenv ("WYDAWCA_DIST_FILE", trp->file[file_dist].name, 1); - - if (chdir (temp_homedir)) - { - logmsg (LOG_CRIT, "cannot change to %s: %s", - temp_homedir, strerror (errno)); - _exit (127); +static int +external_check(struct file_triplet *trp) +{ + int rc; + const struct spool *spool = trp->spool; + char *file; + + if (!trp->file[file_dist].name) + return 0; + if (!spool->check_script && !default_check_script) + return 0; + + file = concat_dir(temp_homedir, trp->file[file_dist].name, NULL); + if (copy_file(trp->file[file_dist].name, file)) { + free(file); + return 1; } - argv[0] = "sh"; - argv[1] = script_file; - argv[2] = NULL; - - execv ("/bin/sh", argv); - _exit (127); - } - - /* Master */ - free (script_file); - close (p[1]); - fp = fdopen (p[0], "r"); - buf = NULL; - size = total = 0; - if (debug_level > 2) - logmsg (LOG_DEBUG, _("reading script output...")); - while (grecs_getline (&buf, &size, fp) > 0) - { - size_t len = strlen (buf); - if (debug_level > 2) - logmsg (LOG_DEBUG, _("read: %s"), buf); - txtacc_grow (trp->acc, buf, len); - total += size; - } - txtacc_1grow (trp->acc, 0); - if (debug_level > 2) - logmsg (LOG_DEBUG, _("bytes read: %lu"), (unsigned long)total); - - fclose (fp); - - waitpid (pid, &status, 0); - signal (SIGCHLD, oldsig); - - if (total) - trp->check_diag = txtacc_finish (trp->acc, 0); - - trp->check_result = status; - if (WIFEXITED (status)) - { - status = WEXITSTATUS (status); - if (status) - { - logmsg (LOG_ERR, "%s for %s@%s returned %d", - descr, trp->name, trp->spool->tag, status); - return 1; + rc = 0; + if (spool->check_script) + rc |= run_check_script(spool->check_script, trp, + _("spool check script")); + + if (rc == 0 && default_check_script) + rc |= run_check_script(default_check_script, trp, + _("default check script")); + + free(file); + + if (rc) { + UPDATE_STATS(STAT_CHECK_FAIL); + notify(spool->notification, trp, ev_check_fail); } - else if (debug_level > 2) - logmsg (LOG_DEBUG, "%s for %s@%s returned %d", - descr, trp->name, trp->spool->tag, status); - } - else if (WIFSIGNALED (status)) - { - int sig = WTERMSIG (status); - logmsg (LOG_NOTICE, - "%s for %s@%s terminated on signal %d", - descr, trp->name, trp->spool->tag, sig); - return 1; - } - else - { - logmsg (LOG_NOTICE, - "%s for %s@%s terminated with unhandled status", - descr, trp->name, trp->spool->tag); - return 1; - } - return 0; + + return rc; } static int -external_check (struct file_triplet *trp) +symlink_filelist(struct file_triplet *trp, const char *key, const char *val) { - int rc; - const struct spool *spool = trp->spool; - char *file; - - if (!trp->file[file_dist].name) - return 0; - if (!spool->check_script && !default_check_script) - return 0; - - file = concat_dir (temp_homedir, trp->file[file_dist].name, NULL); - if (copy_file (trp->file[file_dist].name, file)) - { - free (file); - return 1; - } - - rc = 0; - if (spool->check_script) - rc |= run_check_script (spool->check_script, trp, - _("spool check script")); - - if (rc == 0 && default_check_script) - rc |= run_check_script (default_check_script, trp, - _("default check script")); - - free (file); - - if (rc) - { - UPDATE_STATS (STAT_CHECK_FAIL); - notify (spool->notification, trp, ev_check_fail); - } - - return rc; + int rc = 0; + struct wordsplit ws; + + if (wordsplit(val, &ws, WRDSF_DEFFLAGS)) { + logmsg(LOG_ERR, + _("cannot parse symlink value `%s'"), val); + return 1; + } + + if (ws.ws_wordc != 2) { + rc = 1; + logmsg(LOG_ERR, + _("wrong number of arguments to %s directive: `%s'"), + key, val); + } else + rc = symlink_file(trp, ws.ws_wordv[0], ws.ws_wordv[1]); + + wordsplit_free(&ws); + return rc; } /* Process the directives from TRP */ int -process_directives (struct file_triplet *trp) +process_directives(struct file_triplet *trp) { - int rc, n; - const char *key, *val; - const struct spool *spool; - - ASGN_SPOOL (spool, trp, return 1); - UPDATE_STATS (STAT_COMPLETE_TRIPLETS); - timer_start ("triplet"); - report_init (); - for (n = directive_first (trp, &key, &val); n; - n = directive_next (trp, n, &key, &val)) - { - enum directive d = find_directive (key); - switch (d) - { - case unknown_dir: - /* should not happen */ - abort (); - - case comment_dir: - logmsg (LOG_NOTICE, _("%s: COMMENT: %s"), - trp->file[file_directive].name, val); - break; - - case directory_dir: - /* already processed (see fill_project_name in verify.c */ - break; - - case filename_dir: - rc = verify_detached_signature (trp); - if (rc == 0) - { - if (external_check (trp)) - return 1; - if (move_file (trp, file_dist) - || move_file (trp, file_signature)) - return 1; - } - else - { - logmsg (LOG_ERR, _("invalid detached signature for %s"), - trp->name); - return 1; - } - break; - - case version_dir: - /* Already processed. See directive_version_in_range_p, - called by verify_directive_format */ - break; - - case archive_dir: - if (archive_file (trp, val)) - return 1; - break; - - case symlink_dir: - { - int rc = 0; - struct wordsplit ws; - - if (wordsplit (val, &ws, WRDSF_DEFFLAGS)) - { - logmsg (LOG_ERR, _("cannot parse symlink value `%s'"), - val); - return 1; - } + int rc, n; + const char *key, *val; + const struct spool *spool; + + ASGN_SPOOL(spool, trp, return 1); + UPDATE_STATS(STAT_COMPLETE_TRIPLETS); + timer_start("triplet"); + report_init(); + for (n = directive_first(trp, &key, &val); n; + n = directive_next(trp, n, &key, &val)) { + enum directive d = find_directive(key); + switch (d) { + case unknown_dir: + /* should not happen */ + abort(); + + case comment_dir: + logmsg(LOG_NOTICE, _("%s: COMMENT: %s"), + trp->file[file_directive].name, val); + break; + + case directory_dir: + /* already processed (see fill_project_name in + verify.c */ + break; + + case filename_dir: + rc = verify_detached_signature(trp); + if (rc == 0) { + if (external_check(trp)) + return 1; + if (move_file(trp, file_dist) || + move_file(trp, file_signature)) + return 1; + } else { + logmsg(LOG_ERR, + _("invalid detached signature for %s"), + trp->name); + return 1; + } + break; + + case version_dir: + /* Already processed. See directive_version_in_range_p, + called by verify_directive_format */ + break; + + case archive_dir: + if (archive_file(trp, val)) + return 1; + break; + + case symlink_dir: + if (symlink_filelist(trp, key, val)) + return 1; + break; + + case rmsymlink_dir: + if (rmsymlink_file(trp, val)) + return 1; + + case replace_dir: + if (trp->version < 102) { + rc = 1; + logmsg(LOG_ERR, + _("\"replace\" directive is invalid " + "for version %d"), + trp->version); + } + } + } - if (ws.ws_wordc != 2) - { - rc = 1; - logmsg (LOG_ERR, - _("wrong number of arguments to %s directive: `%s'"), - key, val); - } - else - rc = symlink_file (trp, ws.ws_wordv[0], ws.ws_wordv[1]); - - wordsplit_free (&ws); - if (rc) - return 1; - } - break; - - case rmsymlink_dir: - if (rmsymlink_file (trp, val)) - return 1; - - case replace_dir: - if (trp->version < 102) - { - rc = 1; - logmsg (LOG_ERR, - _("\"replace\" directive is invalid for version %d"), - trp->version); - } + if (!dry_run_mode && unlink(trp->file[file_directive].name)) { + logmsg(LOG_CRIT, _("%s: cannot unlink directive file: %s"), + trp->file[file_directive].name, strerror(errno)); } - } - - if (!dry_run_mode && unlink (trp->file[file_directive].name)) - { - logmsg (LOG_CRIT, _("%s: cannot unlink directive file: %s"), - trp->file[file_directive].name, strerror (errno)); - } - - UPDATE_STATS (STAT_TRIPLET_SUCCESS); - report_finish (); - timer_stop ("triplet"); - notify (spool->notification, trp, ev_success); - return 0; + + UPDATE_STATS(STAT_TRIPLET_SUCCESS); + report_finish(); + timer_stop("triplet"); + notify(spool->notification, trp, ev_success); + return 0; } diff --git a/src/diskio.c b/src/diskio.c index 751d684..209d387 100644 --- a/src/diskio.c +++ b/src/diskio.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007-2012 Sergey Poznyakoff + Copyright (C) 2007-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -18,268 +18,245 @@ /* Return true if ARG is NULL or is a sub-directory of DIR */ int -sub_dir_p (const char *arg, const char *dir) +sub_dir_p(const char *arg, const char *dir) { - int dlen; + int dlen; - if (!arg) - return 0; + if (!arg) + return 0; - dlen = strlen (dir); + dlen = strlen(dir); - return strlen (arg) > dlen - && memcmp (dir, arg, dlen) == 0 - && arg[dlen] == '/'; + return strlen(arg) > dlen + && memcmp(dir, arg, dlen) == 0 && arg[dlen] == '/'; } /* Concatenate BASE directory name, a single directory separator (/) and NAME. Return in PBASELEN the length of BASE, not counting eventual trailing slash. */ char * -concat_dir (const char *base, const char *name, size_t *pbaselen) +concat_dir(const char *base, const char *name, size_t * pbaselen) { - size_t len = strlen (base); - size_t size; - char *dir; - - while (len > 0 && base[len-1] == '/') - len--; - - size = len + 1 + strlen (name); - dir = grecs_malloc (size + 1); - memcpy (dir, base, len); - dir[len++] = '/'; - strcpy (dir + len, name); - - if (pbaselen) - *pbaselen = len; - return dir; + size_t len = strlen(base); + size_t size; + char *dir; + + while (len > 0 && base[len - 1] == '/') + len--; + + size = len + 1 + strlen(name); + dir = grecs_malloc(size + 1); + memcpy(dir, base, len); + dir[len++] = '/'; + strcpy(dir + len, name); + + if (pbaselen) + *pbaselen = len; + return dir; } /* Create the directory DIR, eventually creating all intermediate directories starting from DIR + BASELEN. */ int -create_hierarchy (char *dir, size_t baselen) +create_hierarchy(char *dir, size_t baselen) { - int rc; - struct stat st; - char *p; - - if (stat (dir, &st) == 0) - { - if (!S_ISDIR (st.st_mode)) - { - logmsg (LOG_ERR, _("component %s is not a directory"), dir); - return 1; + int rc; + struct stat st; + char *p; + + if (stat(dir, &st) == 0) { + if (!S_ISDIR(st.st_mode)) { + logmsg(LOG_ERR, _("component %s is not a directory"), + dir); + return 1; + } + return 0; + } else if (errno != ENOENT) { + logmsg(LOG_ERR, _("cannot stat file %s: %s"), dir, + strerror(errno)); + return 1; } - return 0; - } - else if (errno != ENOENT) - { - logmsg (LOG_ERR, _("cannot stat file %s: %s"), dir, strerror (errno)); - return 1; - } - - p = strrchr (dir, '/'); - if (p) - { - if (p - dir + 1 < baselen) - { - logmsg (LOG_ERR, _("base directory %s does not exist"), dir); - return 1; + + p = strrchr(dir, '/'); + if (p) { + if (p - dir + 1 < baselen) { + logmsg(LOG_ERR, _("base directory %s does not exist"), + dir); + return 1; + } + *p = 0; } - *p = 0; - } - - rc = create_hierarchy (dir, baselen); - if (rc == 0) - { - if (p) - *p = '/'; - if (mkdir (dir, MKDIR_PERMISSIONS)) - { - logmsg (LOG_ERR, _("cannot create directory %s: %s"), - dir, strerror (errno)); - rc = 1; + + rc = create_hierarchy(dir, baselen); + if (rc == 0) { + if (p) + *p = '/'; + if (mkdir(dir, MKDIR_PERMISSIONS)) { + logmsg(LOG_ERR, _("cannot create directory %s: %s"), + dir, strerror(errno)); + rc = 1; + } } - } - return rc; + return rc; } /* Create a directory BASE/NAME (with eventual intermediate directories in NAME). Do nothing if dry_run_mode is set. */ char * -create_directory (const char *base, const char *name) +create_directory(const char *base, const char *name) { - size_t baselen; - char *dir = concat_dir (base, name, &baselen); - - if (!dry_run_mode) - { - if (create_hierarchy (dir, baselen)) - { - free (dir); - dir = NULL; + size_t baselen; + char *dir = concat_dir(base, name, &baselen); + + if (!dry_run_mode) { + if (create_hierarchy(dir, baselen)) { + free(dir); + dir = NULL; + } } - } - return dir; + return dir; } - /* Copy FILE to DST_FILE. */ int -copy_file (const char *file, const char *dst_file) +copy_file(const char *file, const char *dst_file) { - int in_fd, out_fd; - struct stat st; - int rc; - char *buf; - size_t bufsize; - size_t fsize; - - in_fd = open (file, O_RDONLY); - - if (in_fd == -1) - { - logmsg (LOG_ERR, _("cannot open source file %s for reading: %s"), - file, strerror (errno)); - return 1; - } - - if (fstat (in_fd, &st)) - { - logmsg (LOG_ERR, _("cannot stat source file %s: %s"), - file, strerror (errno)); - close (in_fd); - return 1; - } - - out_fd = creat (dst_file, CREAT_PERMISSIONS); - if (out_fd == -1) - { - logmsg (LOG_ERR, _("cannot create destination file %s: %s"), - dst_file, strerror (errno)); - close (in_fd); - return 1; - } - - buf = NULL; - fsize = st.st_size; - - for (bufsize = fsize; bufsize > 0 && (buf = malloc (bufsize)) == NULL; - bufsize /= 2) - ; - if (bufsize == 0) - grecs_alloc_die (); - - rc = 0; - while (fsize > 0) - { - size_t rest; - size_t rdbytes; - - rest = fsize > bufsize ? bufsize : fsize; - rdbytes = read (in_fd, buf, rest); - if (rdbytes == -1) - { - logmsg (LOG_ERR, _("unexpected error reading %s: %s"), - file, strerror (errno)); - rc = 1; - break; + int in_fd, out_fd; + struct stat st; + int rc; + char *buf; + size_t bufsize; + size_t fsize; + + in_fd = open(file, O_RDONLY); + + if (in_fd == -1) { + logmsg(LOG_ERR, + _("cannot open source file %s for reading: %s"), + file, strerror(errno)); + return 1; + } + + if (fstat(in_fd, &st)) { + logmsg(LOG_ERR, + _("cannot stat source file %s: %s"), + file, strerror(errno)); + close(in_fd); + return 1; } - rest = write (out_fd, buf, rdbytes); - if (rest == -1) - { - logmsg (LOG_ERR, _("unexpected error writing to %s: %s"), - dst_file, strerror (errno)); - rc = 1; - break; + + out_fd = creat(dst_file, CREAT_PERMISSIONS); + if (out_fd == -1) { + logmsg(LOG_ERR, + _("cannot create destination file %s: %s"), + dst_file, strerror(errno)); + close(in_fd); + return 1; } - else if (rest != rdbytes) - { - logmsg (LOG_ERR, _("short write on %s"), dst_file); - rc = 1; + + buf = NULL; + fsize = st.st_size; + + for (bufsize = fsize; bufsize > 0 && (buf = malloc(bufsize)) == NULL; + bufsize /= 2) ; + if (bufsize == 0) + grecs_alloc_die(); + + rc = 0; + while (fsize > 0) { + size_t rest; + size_t rdbytes; + + rest = fsize > bufsize ? bufsize : fsize; + rdbytes = read(in_fd, buf, rest); + if (rdbytes == -1) { + logmsg(LOG_ERR, _("unexpected error reading %s: %s"), + file, strerror(errno)); + rc = 1; + break; + } + rest = write(out_fd, buf, rdbytes); + if (rest == -1) { + logmsg(LOG_ERR, + _("unexpected error writing to %s: %s"), + dst_file, strerror(errno)); + rc = 1; + break; + } else if (rest != rdbytes) { + logmsg(LOG_ERR, _("short write on %s"), dst_file); + rc = 1; + } + fsize -= rdbytes; } - fsize -= rdbytes; - } - free (buf); - - close (in_fd); - close (out_fd); - if (rc) - unlink (dst_file); - return rc; + free(buf); + + close(in_fd); + close(out_fd); + if (rc) + unlink(dst_file); + return rc; } /* Move FILE to DST_FILE. If they reside on different devices, use copy_file + unlink. */ int -do_move_file (const char *file, const char *dst_file) +do_move_file(const char *file, const char *dst_file) { - int rc = 0; - - if (rename (file, dst_file)) - { - if (errno == EXDEV) - { - if (copy_file (file, dst_file)) - { - logmsg (LOG_CRIT, _("cannot copy %s to %s: %s"), - file, dst_file, strerror (errno)); - rc = 1; - } - else if (unlink (file)) - { - logmsg (LOG_ERR, _("cannot unlink %s: %s"), - file, strerror (errno)); - } - } - else - { - logmsg (LOG_CRIT, _("cannot move %s to %s: %s"), - file, dst_file, strerror (errno)); - rc = 1; + int rc = 0; + + if (rename(file, dst_file)) { + if (errno == EXDEV) { + if (copy_file(file, dst_file)) { + logmsg(LOG_CRIT, _("cannot copy %s to %s: %s"), + file, dst_file, strerror(errno)); + rc = 1; + } else if (unlink(file)) { + logmsg(LOG_ERR, _("cannot unlink %s: %s"), + file, strerror(errno)); + } + } else { + logmsg(LOG_CRIT, _("cannot move %s to %s: %s"), + file, dst_file, strerror(errno)); + rc = 1; + } } - } - return rc; + return rc; } /* Append the FILE to the tar ARCHIVE. Do nothing if dry_run_mode is set. */ int -tar_append_file (const char *archive, const char *file) +tar_append_file(const char *archive, const char *file) { - const char *argv[6]; - - if (debug_level) - logmsg (LOG_DEBUG, _("tarring %s to %s"), file, archive); - if (dry_run_mode) - { - UPDATE_STATS (STAT_ARCHIVES); - return 0; - } - - argv[0] = tar_command_name; - argv[1] = "-f"; - argv[2] = archive; - argv[3] = "-r"; - argv[4] = file; - argv[5] = NULL; - - switch (wydawca_exec (6, argv, NULL)) - { - case exec_success: - UPDATE_STATS (STAT_ARCHIVES); - return 0; - - case exec_fail: - case exec_error: - logmsg (LOG_ERR, _("cannot archive %s"), file); - break; - } - - return 1; + const char *argv[6]; + + if (debug_level) + logmsg(LOG_DEBUG, _("tarring %s to %s"), file, archive); + if (dry_run_mode) { + UPDATE_STATS(STAT_ARCHIVES); + return 0; + } + + argv[0] = tar_command_name; + argv[1] = "-f"; + argv[2] = archive; + argv[3] = "-r"; + argv[4] = file; + argv[5] = NULL; + + switch (wydawca_exec(6, argv, NULL)) { + case exec_success: + UPDATE_STATS(STAT_ARCHIVES); + return 0; + + case exec_fail: + case exec_error: + logmsg(LOG_ERR, _("cannot archive %s"), file); + break; + } + + return 1; } /* Backup a file to a directory. @@ -292,129 +269,126 @@ tar_append_file (const char *archive, const char *file) Do nothing if dry_run_mode is set. */ int -backup_file (const char *dst_file, const char *dst_dir, const char *file, - const struct archive_descr *archive, - const char *reldir) +backup_file(const char *dst_file, const char *dst_dir, const char *file, + const struct archive_descr *archive, const char *reldir) { - int rc = 0; - char *adir; - char *file_name; - - if (archive->name[0] == '/') - adir = create_directory (archive->name, reldir); - else - adir = create_directory (dst_dir, archive->name); - if (!adir) - return 1; - - file_name = concat_dir (adir, file, NULL); - if (access (file_name, F_OK) == 0) - { - if (archive->backup_type == no_backups) - { - if (debug_level) - logmsg (LOG_DEBUG, _("removing previous archive file `%s'"), - file_name); - if (!dry_run_mode && unlink (file_name)) - { - logmsg (LOG_ERR, - _("cannot unlink previous archive file `%s': %s"), - file_name, strerror (errno)); - free (file_name); - free (adir); - return 1; - } - } - else - { - char *archive_file_name = - find_backup_file_name (file_name, archive->backup_type); - if (debug_level) - logmsg (LOG_DEBUG, - _("backing up previous archive file `%s' to `%s'"), - file_name, archive_file_name); - if (!dry_run_mode) - { - rc = do_move_file (file_name, archive_file_name); - if (rc) - { - logmsg (LOG_ERR, _("backing `%s' up as `%s' failed: %s"), - file_name, archive_file_name, strerror (errno)); - free (archive_file_name); - free (file_name); - free (adir); - return 1; + int rc = 0; + char *adir; + char *file_name; + + if (archive->name[0] == '/') + adir = create_directory(archive->name, reldir); + else + adir = create_directory(dst_dir, archive->name); + if (!adir) + return 1; + + file_name = concat_dir(adir, file, NULL); + if (access(file_name, F_OK) == 0) { + if (archive->backup_type == no_backups) { + if (debug_level) + logmsg(LOG_DEBUG, + _("removing previous archive " + "file `%s'"), + file_name); + if (!dry_run_mode && unlink(file_name)) { + logmsg(LOG_ERR, + _("cannot unlink previous archive " + "file `%s': %s"), + file_name, strerror(errno)); + free(file_name); + free(adir); + return 1; + } + } else { + char *archive_file_name = + find_backup_file_name(file_name, + archive->backup_type); + if (debug_level) + logmsg(LOG_DEBUG, + _("backing up previous archive " + "file `%s' to `%s'"), + file_name, archive_file_name); + if (!dry_run_mode) { + rc = do_move_file(file_name, + archive_file_name); + if (rc) { + logmsg(LOG_ERR, + _("backing `%s' up as `%s' failed: %s"), + file_name, archive_file_name, + strerror(errno)); + free(archive_file_name); + free(file_name); + free(adir); + return 1; + } + } + free(archive_file_name); } - } - free (archive_file_name); } - } - - if (debug_level) - logmsg (LOG_DEBUG, _("archiving `%s' to `%s'"), dst_file, file_name); - if (!dry_run_mode) - { - rc = do_move_file (dst_file, file_name); - if (rc) - logmsg (LOG_ERR, _("archiving `%s' as `%s' failed: %s"), - dst_file, file_name, strerror (errno)); - } - free (file_name); - free (adir); - return rc; + + if (debug_level) + logmsg(LOG_DEBUG, _("archiving `%s' to `%s'"), dst_file, + file_name); + if (!dry_run_mode) { + rc = do_move_file(dst_file, file_name); + if (rc) + logmsg(LOG_ERR, _("archiving `%s' as `%s' failed: %s"), + dst_file, file_name, strerror(errno)); + } + free(file_name); + free(adir); + return rc; } /* Select the appropriate backup type and backup a file. See backup_file for the argument description. */ int -do_archive_file (const char *dst_file, const char *dst_dir, const char *file, - const struct archive_descr *archive, - const char *reldir) +do_archive_file(const char *dst_file, const char *dst_dir, const char *file, + const struct archive_descr *archive, const char *reldir) { - switch (archive->type) - { - case archive_none: - break; - - case archive_directory: - if (backup_file (dst_file, dst_dir, file, archive, reldir)) - return 1; - UPDATE_STATS (STAT_ARCHIVES); - break; + switch (archive->type) { + case archive_none: + break; + + case archive_directory: + if (backup_file(dst_file, dst_dir, file, archive, reldir)) + return 1; + UPDATE_STATS(STAT_ARCHIVES); + break; + + case archive_tar: + if (tar_append_file(archive->name, dst_file)) + return 1; + UPDATE_STATS(STAT_ARCHIVES); + break; + } - case archive_tar: - if (tar_append_file (archive->name, dst_file)) - return 1; - UPDATE_STATS (STAT_ARCHIVES); - break; - } - - if (!dry_run_mode && unlink (dst_file) && errno != ENOENT) - { - logmsg (LOG_ERR, _("canot unlink file `%s': %s"), - dst_file, strerror (errno)); - return 1; - } - return 0; + if (!dry_run_mode && unlink(dst_file) && errno != ENOENT) { + logmsg(LOG_ERR, _("canot unlink file `%s': %s"), + dst_file, strerror(errno)); + return 1; + } + return 0; } static int -replace_allowed_p (struct file_triplet *trp) +replace_allowed_p(struct file_triplet *trp) { - const char *val; - - if (trp->version < 102) - return 1; - - if (directive_get_value (trp, "replace", &val)) - return 1; - return strcmp (val, "true") == 0; + const char *val; + + if (trp->version < 102) + return 1; + + if (directive_get_value(trp, "replace", &val)) + return 1; + return strcmp(val, "true") == 0; } const char * -dir_get_path (struct spool *sp) +dir_get_path(struct spool *sp) { - return sp->source_dir; + return sp->source_dir; } /* Move the part FILE_ID of the triplet TRP between the directories in @@ -423,46 +397,46 @@ dir_get_path (struct spool *sp) Do nothing if dry_run_mode is set. */ int -dir_move_file (struct file_triplet *trp, enum file_type file_id) +dir_move_file(struct file_triplet *trp, enum file_type file_id) { - char *dst_file; - int rc = 0; - const struct spool *spool = trp->spool; - char *dst_dir = create_directory (spool->dest_dir, trp->relative_dir); - - if (!dst_dir) - return 1; - dst_file = concat_dir (dst_dir, trp->file[file_id].name, NULL); - - if (debug_level) - logmsg (LOG_DEBUG, _("installing %s to %s"), trp->file[file_id].name, - dst_dir); - - if (access (dst_file, F_OK) == 0) - { - if (replace_allowed_p (trp)) - rc = do_archive_file (dst_file, dst_dir, trp->file[file_id].name, - &spool->archive, trp->relative_dir); - else - { - logmsg (LOG_ERR, - _("refusing to upload %s because it already exists " - "and replace is not allowed"), - trp->file[file_id].name); - free (dst_file); - free (dst_dir); - return 1; + char *dst_file; + int rc = 0; + const struct spool *spool = trp->spool; + char *dst_dir = create_directory(spool->dest_dir, trp->relative_dir); + + if (!dst_dir) + return 1; + dst_file = concat_dir(dst_dir, trp->file[file_id].name, NULL); + + if (debug_level) + logmsg(LOG_DEBUG, _("installing %s to %s"), + trp->file[file_id].name, dst_dir); + + if (access(dst_file, F_OK) == 0) { + if (replace_allowed_p(trp)) + rc = do_archive_file(dst_file, dst_dir, + trp->file[file_id].name, + &spool->archive, + trp->relative_dir); + else { + logmsg(LOG_ERR, + _("refusing to upload %s because it already " + "exists and replace is not allowed"), + trp->file[file_id].name); + free(dst_file); + free(dst_dir); + return 1; + } } - } - if (!dry_run_mode && rc == 0) - rc = do_move_file (trp->file[file_id].name, dst_file); + if (!dry_run_mode && rc == 0) + rc = do_move_file(trp->file[file_id].name, dst_file); - free (dst_file); - free (dst_dir); - if (rc == 0) - UPDATE_STATS (STAT_UPLOADS); - return rc; + free(dst_file); + free(dst_dir); + if (rc == 0) + UPDATE_STATS(STAT_UPLOADS); + return rc; } /* Archive the file FILE_NAME, located in DPAIR->dest_dir, and remove the @@ -470,65 +444,61 @@ dir_move_file (struct file_triplet *trp, enum file_type file_id) Do nothing if dry_run_mode is set. */ int -archive_single_file (struct file_triplet *trp, const char *file_name, - int noentok) +archive_single_file(struct file_triplet *trp, const char *file_name, + int noentok) { - char *dst_file; - int rc = 0; - const struct spool *spool = trp->spool; - char *dst_dir = create_directory (spool->dest_dir, trp->relative_dir); - - if (!dst_dir) - return 1; - - dst_file = safe_file_name (concat_dir (dst_dir, file_name, NULL)); - if (!sub_dir_p (dst_file, spool->dest_dir)) - { - logmsg (LOG_ERR, _("file to be archived `%s' does not lie under `%s'"), - dst_file, spool->dest_dir); - free (dst_file); - free (dst_dir); - return 1; - } - - if (access (dst_file, F_OK) == 0) - { - if (debug_level) - logmsg (LOG_DEBUG, _("archiving file `%s'"), dst_file); - rc = do_archive_file (dst_file, dst_dir, file_name, &spool->archive, - trp->relative_dir); - } - else if (errno == ENOENT) - { - if (!noentok) - logmsg (LOG_NOTICE, _("nothing to archive: file `%s' does not exist"), - dst_file); - } - else - { - logmsg (LOG_ERR, _("canot access file `%s': %s"), - dst_file, strerror (errno)); - rc = 1; - } - - free (dst_file); - free (dst_dir); - return rc; + char *dst_file; + int rc = 0; + const struct spool *spool = trp->spool; + char *dst_dir = create_directory(spool->dest_dir, trp->relative_dir); + + if (!dst_dir) + return 1; + + dst_file = safe_file_name(concat_dir(dst_dir, file_name, NULL)); + if (!sub_dir_p(dst_file, spool->dest_dir)) { + logmsg(LOG_ERR, + _("file to be archived `%s' does not lie under `%s'"), + dst_file, spool->dest_dir); + free(dst_file); + free(dst_dir); + return 1; + } + + if (access(dst_file, F_OK) == 0) { + if (debug_level) + logmsg(LOG_DEBUG, _("archiving file `%s'"), dst_file); + rc = do_archive_file(dst_file, dst_dir, file_name, + &spool->archive, trp->relative_dir); + } else if (errno == ENOENT) { + if (!noentok) + logmsg(LOG_NOTICE, + _("nothing to archive: " + "file `%s' does not exist"), + dst_file); + } else { + logmsg(LOG_ERR, _("canot access file `%s': %s"), + dst_file, strerror(errno)); + rc = 1; + } + + free(dst_file); + free(dst_dir); + return rc; } static char * -make_signame (const char *file_name) +make_signame(const char *file_name) { - size_t len; - - if (((len = strlen (file_name)) > SUF_SIG_LEN - && memcmp (file_name + len - SUF_SIG_LEN, SUF_SIG, SUF_SIG_LEN))) - { - char *signame = grecs_malloc (len + SUF_SIG_LEN + 1); - strcpy (signame, file_name); - return strcat (signame, SUF_SIG); - } - return NULL; + size_t len; + + if (((len = strlen(file_name)) > SUF_SIG_LEN + && memcmp(file_name + len - SUF_SIG_LEN, SUF_SIG, SUF_SIG_LEN))) { + char *signame = grecs_malloc(len + SUF_SIG_LEN + 1); + strcpy(signame, file_name); + return strcat(signame, SUF_SIG); + } + return NULL; } /* Archive the file FILE_NAME, located in DPAIR->dest_dir, and remove the @@ -537,18 +507,18 @@ make_signame (const char *file_name) Do nothing if dry_run_mode is set. */ int -dir_archive_file (struct file_triplet *trp, const char *file_name) +dir_archive_file(struct file_triplet *trp, const char *file_name) { - int rc; - char *signame; - - rc = archive_single_file (trp, file_name, 0); - if (rc == 0 && archive_signatures && (signame = make_signame (file_name))) - { - rc = archive_single_file (trp, signame, 1); - free (signame); - } - return rc; + int rc; + char *signame; + + rc = archive_single_file(trp, file_name, 0); + if (rc == 0 && archive_signatures + && (signame = make_signame(file_name))) { + rc = archive_single_file(trp, signame, 1); + free(signame); + } + return rc; } /* Create a symbolic link from WANTED_SRC to WANTED_DST in the subdirectory @@ -556,207 +526,196 @@ dir_archive_file (struct file_triplet *trp, const char *file_name) Do nothing if dry_run_mode is set. */ int -dir_symlink_file (struct file_triplet *trp, - const char *wanted_src, const char *wanted_dst) +dir_symlink_file(struct file_triplet *trp, + const char *wanted_src, const char *wanted_dst) { - int rc = 0; - const struct spool *spool = trp->spool; - char *dst_dir = create_directory (spool->dest_dir, trp->relative_dir); - char *src, *dst; - - if (!dst_dir) - return 1; - - src = safe_file_name_alloc (wanted_src); - if (!src || src[0] == '/') - { - logmsg (LOG_ERR, _("symlink source `%s' does not lie under `%s'"), - wanted_src, spool->dest_dir); - free (src); - return 1; - } - - dst = safe_file_name_alloc (wanted_dst); - if (!dst || dst[0] == '/') - { - logmsg (LOG_ERR, _("symlink destination `%s' does not lie under `%s'"), - wanted_dst, spool->dest_dir); - free (src); - free (dst); - return 1; - } - - if (debug_level) - logmsg (LOG_DEBUG, _("symlinking %s to %s in directory %s"), - src, dst, dst_dir); - - if (!dry_run_mode) - { - char *p = strrchr (dst, '/'); - if (p > dst) - { - char *dir; - - *p = 0; - dir = create_directory (spool->dest_dir, dst); - if (!dir) - rc = 1; - else - free (dir); - *p = '/'; + int rc = 0; + const struct spool *spool = trp->spool; + char *dst_dir = create_directory(spool->dest_dir, trp->relative_dir); + char *src, *dst; + + if (!dst_dir) + return 1; + + src = safe_file_name_alloc(wanted_src); + if (!src || src[0] == '/') { + logmsg(LOG_ERR, + _("symlink source `%s' does not lie under `%s'"), + wanted_src, spool->dest_dir); + free(src); + return 1; } - if (rc == 0) - { - if (push_dir (dst_dir)) - logmsg (LOG_ERR, _("cannot change to %s: %s"), - dst_dir, strerror (errno)); - else - { - struct stat st; - - if (lstat (dst, &st) == 0) - { - if (!S_ISLNK (st.st_mode)) - { - logmsg (LOG_ERR, - _("file %s exists and is not a symbolic link"), - dst); - rc = 1; - } - else if (unlink (dst)) - { - logmsg (LOG_ERR, - _("cannot unlink %s: %s"), - dst, strerror (errno)); - rc = 1; - } - } - else if (errno != ENOENT) - { - logmsg (LOG_ERR, - _("cannot stat file %s: %s"), - dst, strerror (errno)); - rc = 1; - } + dst = safe_file_name_alloc(wanted_dst); + if (!dst || dst[0] == '/') { + logmsg(LOG_ERR, + _("symlink destination `%s' does not lie under `%s'"), + wanted_dst, spool->dest_dir); + free(src); + free(dst); + return 1; + } - if (rc == 0) - { - rc = symlink (src, dst); - if (rc) - logmsg (LOG_ERR, - _("symlinking %s to %s in directory %s failed: %s"), - src, dst, dst_dir, strerror (errno)); + if (debug_level) + logmsg(LOG_DEBUG, _("symlinking %s to %s in directory %s"), + src, dst, dst_dir); + + if (!dry_run_mode) { + char *p = strrchr(dst, '/'); + if (p > dst) { + char *dir; + + *p = 0; + dir = create_directory(spool->dest_dir, dst); + if (!dir) + rc = 1; + else + free(dir); + *p = '/'; } - if (pop_dir ()) - { - logmsg (LOG_EMERG, _("cannot restore current directory: %s"), - strerror (errno)); - exit (EX_SOFTWARE); + + if (rc == 0) { + if (push_dir(dst_dir)) + logmsg(LOG_ERR, _("cannot change to %s: %s"), + dst_dir, strerror(errno)); + else { + struct stat st; + + if (lstat(dst, &st) == 0) { + if (!S_ISLNK(st.st_mode)) { + logmsg(LOG_ERR, + _("file %s exists and is not a symbolic link"), + dst); + rc = 1; + } else if (unlink(dst)) { + logmsg(LOG_ERR, + _("cannot unlink %s: %s"), + dst, strerror(errno)); + rc = 1; + } + } else if (errno != ENOENT) { + logmsg(LOG_ERR, + _("cannot stat file %s: %s"), + dst, strerror(errno)); + rc = 1; + } + + if (rc == 0) { + rc = symlink(src, dst); + if (rc) + logmsg(LOG_ERR, + _("symlinking %s to %s in directory %s failed: %s"), + src, dst, dst_dir, + strerror(errno)); + } + if (pop_dir()) { + logmsg(LOG_EMERG, + _("cannot restore current directory: %s"), + strerror(errno)); + exit(EX_SOFTWARE); + } + } } - } } - } - - free (src); - free (dst); - free (dst_dir); - if (rc == 0) - UPDATE_STATS (STAT_SYMLINKS); - return rc; + + free(src); + free(dst); + free(dst_dir); + if (rc == 0) + UPDATE_STATS(STAT_SYMLINKS); + return rc; } /* Auxiliary function for rmsymlink_file (see below) */ static int -do_rmsymlink_file (const char *dst_file, int noentok) +do_rmsymlink_file(const char *dst_file, int noentok) { - struct stat st; - - if (debug_level) - logmsg (LOG_DEBUG, _("removing symbolic link %s"), dst_file); - - if (stat (dst_file, &st)) - { - if (errno == ENOENT) - { - if (!noentok) - logmsg (LOG_NOTICE, _("symlink `%s' does not exist"), dst_file); - return 0; + struct stat st; + + if (debug_level) + logmsg(LOG_DEBUG, _("removing symbolic link %s"), dst_file); + + if (stat(dst_file, &st)) { + if (errno == ENOENT) { + if (!noentok) + logmsg(LOG_NOTICE, + _("symlink `%s' does not exist"), + dst_file); + return 0; + } + if (!S_ISLNK(st.st_mode)) { + logmsg(LOG_ERR, + _("refusing to unlink %s: is not a symlink"), + dst_file); + return 1; + } } - if (!S_ISLNK (st.st_mode)) - { - logmsg (LOG_ERR, _("refusing to unlink %s: is not a symlink"), - dst_file); - return 1; + if (!dry_run_mode && unlink(dst_file)) { + logmsg(LOG_ERR, _("cannot unlink %s: %s"), dst_file, + strerror(errno)); + return 1; } - } - if (!dry_run_mode && unlink (dst_file)) - { - logmsg (LOG_ERR, _("cannot unlink %s: %s"), dst_file, strerror (errno)); - return 1; - } - UPDATE_STATS (STAT_RMSYMLINKS); - return 0; + UPDATE_STATS(STAT_RMSYMLINKS); + return 0; } /* Remove the symbolic link TRP->spool->dest_dir/TRP->relative_dir/FILE_NAME Do nothing if dry_run_mode is set. */ int -dir_rmsymlink_file (struct file_triplet *trp, const char *file_name) +dir_rmsymlink_file(struct file_triplet *trp, const char *file_name) { - char *dst_file; - int rc = 0; - char *signame; - const struct spool *spool = trp->spool; - char *dst_dir = create_directory (spool->dest_dir, trp->relative_dir); - - if (!dst_dir) - return 1; - - dst_file = safe_file_name (concat_dir (dst_dir, file_name, NULL)); - if (!sub_dir_p (dst_file, spool->dest_dir)) - { - logmsg (LOG_ERR, _("refusing to remove a symlink `%s' that is not " - "located under `%s'"), - dst_file, spool->dest_dir); - free (dst_file); - free (dst_dir); - return 1; - } - - rc = do_rmsymlink_file (dst_file, 0); - if (rc == 0 && archive_signatures && (signame = make_signame (dst_file))) - { - rc = do_rmsymlink_file (signame, 1); - free (signame); - } - - free (dst_file); - free (dst_dir); - return rc; + char *dst_file; + int rc = 0; + char *signame; + const struct spool *spool = trp->spool; + char *dst_dir = create_directory(spool->dest_dir, trp->relative_dir); + + if (!dst_dir) + return 1; + + dst_file = safe_file_name(concat_dir(dst_dir, file_name, NULL)); + if (!sub_dir_p(dst_file, spool->dest_dir)) { + logmsg(LOG_ERR, + _("refusing to remove a symlink `%s' that is not " + "located under `%s'"), dst_file, spool->dest_dir); + free(dst_file); + free(dst_dir); + return 1; + } + + rc = do_rmsymlink_file(dst_file, 0); + if (rc == 0 && archive_signatures && (signame = make_signame(dst_file))) { + rc = do_rmsymlink_file(signame, 1); + free(signame); + } + + free(dst_file); + free(dst_dir); + return rc; } int -dir_test_url (mu_url_t url, grecs_locus_t *locus) +dir_test_url(mu_url_t url, grecs_locus_t * locus) { - int rc; - const char *dest_dir; - - rc = mu_url_sget_path (url, &dest_dir); - if (rc) - { - grecs_error (locus, 0, _("cannot extract directory part from URL: %s"), - mu_strerror (rc)); - return rc; - } - if (test_dir (dest_dir, &rc)) - { - if (rc) - grecs_error (locus, rc, _("cannot access %s"), dest_dir); - else - grecs_error (locus, 0, _("%s is not a directory"), dest_dir); - return 1; - } - return 0; + int rc; + const char *dest_dir; + + rc = mu_url_sget_path(url, &dest_dir); + if (rc) { + grecs_error(locus, 0, + _("cannot extract directory part from URL: %s"), + mu_strerror(rc)); + return rc; + } + if (test_dir(dest_dir, &rc)) { + if (rc) + grecs_error(locus, rc, _("cannot access %s"), + dest_dir); + else + grecs_error(locus, 0, _("%s is not a directory"), + dest_dir); + return 1; + } + return 0; } @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007, 2009-2011 Sergey Poznyakoff + Copyright (C) 2007, 2009-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -23,150 +23,141 @@ /* Execute a program from ARGC/ARGV. Return PID in PPID. Return FILE connected to the program's stdout and stderr. */ static FILE * -start_prog (int argc, const char **argv, pid_t *ppid) +start_prog(int argc, const char **argv, pid_t * ppid) { - int p[2]; - FILE *fp; - pid_t pid; - int i; - - if (pipe (p)) - { - logmsg (LOG_CRIT, "pipe: %s", strerror (errno)); - return NULL; - } - - switch (pid = fork ()) - { - case 0: - /* Child process */ - - if (p[1] != 1 && dup2 (p[1], 1) == -1) - { - logmsg (LOG_CRIT, "dup2: %s", strerror (errno)); - _exit (EX_UNAVAILABLE); + int p[2]; + FILE *fp; + pid_t pid; + int i; + + if (pipe(p)) { + logmsg(LOG_CRIT, "pipe: %s", strerror(errno)); + return NULL; } - - if (p[1] != 1 && dup2 (p[1], 2) == -1) - { - logmsg (LOG_CRIT, "dup2: %s", strerror (errno)); - _exit (EX_UNAVAILABLE); + + switch (pid = fork()) { + case 0: + /* Child process */ + + if (p[1] != 1 && dup2(p[1], 1) == -1) { + logmsg(LOG_CRIT, "dup2: %s", strerror(errno)); + _exit(EX_UNAVAILABLE); + } + + if (p[1] != 1 && dup2(p[1], 2) == -1) { + logmsg(LOG_CRIT, "dup2: %s", strerror(errno)); + _exit(EX_UNAVAILABLE); + } + + close(p[0]); + + /* Close unneded descripitors */ + for (i = getdtablesize(); i > 2; i--) + close(i); + + execvp(argv[0], (char **)argv); + logmsg(LOG_CRIT, _("cannot run %s: %s"), argv[0], + strerror(errno)); + exit(EX_UNAVAILABLE); + + case -1: + logmsg(LOG_CRIT, _("cannot run `%s': fork failed: %s"), + argv[0], strerror(errno)); + return NULL; + + default: + /* Master process */ + close(p[1]); + fp = fdopen(p[0], "r"); + if (!fp) + logmsg(LOG_ERR, _("cannot fdopen: %s"), + strerror(errno)); + *ppid = pid; } - - close (p[0]); - - /* Close unneded descripitors */ - for (i = getdtablesize (); i > 2; i--) - close (i); - - execvp (argv[0], (char**) argv); - logmsg (LOG_CRIT, _("cannot run %s: %s"), argv[0], strerror (errno)); - exit (EX_UNAVAILABLE); - - case -1: - logmsg (LOG_CRIT, _("cannot run `%s': fork failed: %s"), - argv[0], strerror (errno)); - return NULL; - - default: - /* Master process */ - close (p[1]); - fp = fdopen (p[0], "r"); - if (!fp) - logmsg (LOG_ERR, _("cannot fdopen: %s"), strerror (errno)); - *ppid = pid; - } - return fp; + return fp; } /* Log everything read from FP as the output from the program PROG, using syslog priority PRIO. */ void -log_output (int prio, const char *prog, FILE *fp) +log_output(int prio, const char *prog, FILE * fp) { - size_t size = 0; - char *buf = NULL; - - logmsg (prio, _("%s output follows:"), prog); - while (grecs_getline (&buf, &size, fp) > 0) - logmsg (prio, "%s", buf); - logmsg (prio, _("end of %s output"), prog); - free (buf); + size_t size = 0; + char *buf = NULL; + + logmsg(prio, _("%s output follows:"), prog); + while (grecs_getline(&buf, &size, fp) > 0) + logmsg(prio, "%s", buf); + logmsg(prio, _("end of %s output"), prog); + free(buf); } /* Execute ARGC/ARGV. Return the exit code in RETCODE. */ enum exec_result -wydawca_exec (int argc, const char **argv, int *retcode) +wydawca_exec(int argc, const char **argv, int *retcode) { - FILE *fp; - pid_t pid, npid; - int status; - int i; - enum exec_result res; - - fp = start_prog (5, argv, &pid); - if (!fp) - { - logmsg (LOG_CRIT, _("cannot start %s"), argv[0]); - return exec_error; - } - - for (i = 0; i < 5 && (npid = waitpid (pid, &status, WNOHANG)) == 0; i++) - sleep (1); - - switch (npid) - { - case -1: - logmsg (LOG_CRIT, _("cannot execute %s: waitpid failed: %s"), - argv[0], strerror (errno)); - fclose (fp); - return exec_error; - - case 0: - logmsg (LOG_CRIT, - _("cannot execute %s: the process did not respond " - "within 5 seconds: %s"), - argv[0], strerror (errno)); - kill (pid, SIGKILL); - fclose (fp); - return exec_error; - - default: - break; - } - - if (WIFEXITED (status)) - { - int rc = WEXITSTATUS (status); - if (rc) - { - res = exec_fail; - logmsg (LOG_ERR, _("command %s returned %d"), argv[0], rc); - log_output (LOG_ERR, argv[0], fp); + FILE *fp; + pid_t pid, npid; + int status; + int i; + enum exec_result res; + + fp = start_prog(5, argv, &pid); + if (!fp) { + logmsg(LOG_CRIT, _("cannot start %s"), argv[0]); + return exec_error; } - else - { - res = exec_success; - if (debug_level > 1) - log_output (LOG_DEBUG, argv[0], fp); + + for (i = 0; i < 5 && (npid = waitpid(pid, &status, WNOHANG)) == 0; i++) + sleep(1); + + switch (npid) { + case -1: + logmsg(LOG_CRIT, _("cannot execute %s: waitpid failed: %s"), + argv[0], strerror(errno)); + fclose(fp); + return exec_error; + + case 0: + logmsg(LOG_CRIT, + _("cannot execute %s: the process did not respond " + "within 5 seconds: %s"), argv[0], strerror(errno)); + kill(pid, SIGKILL); + fclose(fp); + return exec_error; + + default: + break; } - if (retcode) - *retcode = rc; - } - else - { - res = exec_error; - if (WIFSIGNALED (status)) - logmsg (LOG_ERR, _("%s terminated on signal %d"), - argv[0], WTERMSIG (status)); - else if (WIFSTOPPED (status)) - logmsg (LOG_ERR, _("%s stopped on signal %d"), - argv[0], WTERMSIG (status)); - else - logmsg (LOG_ERR, _("%s terminated with unrecognized status"), - argv[0]); - } - fclose (fp); - - return res; + + if (WIFEXITED(status)) { + int rc = WEXITSTATUS(status); + if (rc) { + res = exec_fail; + logmsg(LOG_ERR, _("command %s returned %d"), argv[0], + rc); + log_output(LOG_ERR, argv[0], fp); + } else { + res = exec_success; + if (debug_level > 1) + log_output(LOG_DEBUG, argv[0], fp); + } + if (retcode) + *retcode = rc; + } else { + res = exec_error; + if (WIFSIGNALED(status)) + logmsg(LOG_ERR, _("%s terminated on signal %d"), + argv[0], WTERMSIG(status)); + else if (WIFSTOPPED(status)) + logmsg(LOG_ERR, _("%s stopped on signal %d"), + argv[0], WTERMSIG(status)); + else + logmsg(LOG_ERR, + _("%s terminated with unrecognized status"), + argv[0]); + } + fclose(fp); + + return res; } @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007, 2010-2011 Sergey Poznyakoff + Copyright (C) 2007, 2010-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -19,322 +19,305 @@ #include "wydawca.h" #include <gpgme.h> -#define fail_if_err(expr) \ - do \ - { \ - int a = expr; \ - if (a) \ - { \ - logmsg (LOG_ERR, _("%s: GPGME error: %s"), #expr, \ - gpgme_strerror (a)); \ - return 1; \ - } \ - } \ - while (0) +#define fail_if_err(expr) do { \ + int a = expr; \ + if (a) { \ + logmsg(LOG_ERR, _("%s: GPGME error: %s"), #expr, \ + gpgme_strerror(a)); \ + return 1; \ + } \ + } while (0) char *temp_homedir; -static int rmdir_r (const char *name); +static int rmdir_r(const char *name); /* Auxiliary function: change to directory NAME and recursively remove everything under it. */ static int -recursive_rmdir (const char *name) +recursive_rmdir(const char *name) { - int rc; - DIR *dir; - struct dirent *ent; - - if (chdir (name)) - { - logmsg (LOG_ERR, _("cannot change to directory %s: %s"), - name, strerror (errno)); - return 1; - } - - dir = opendir ("."); - if (!dir) - { - logmsg (LOG_ERR, _("cannot open directory %s: %s"), - name, strerror (errno)); - return 1; - } - - for (rc = 0; rc == 0 && (ent = readdir (dir));) - { - struct stat st; - - if (strcmp (ent->d_name, ".") == 0 - || strcmp (ent->d_name, "..") == 0) - continue; - - if (stat (ent->d_name, &st) && errno != ENOENT) - { - logmsg (LOG_ERR, _("cannot stat file `%s': %s"), - name, strerror (errno)); - rc = 1; + int rc; + DIR *dir; + struct dirent *ent; + + if (chdir(name)) { + logmsg(LOG_ERR, _("cannot change to directory %s: %s"), + name, strerror(errno)); + return 1; } - else if (S_ISDIR (st.st_mode)) - rc = rmdir_r (ent->d_name); - else if ((rc = unlink (ent->d_name)) != 0 && errno != ENOENT) - logmsg (LOG_ERR, _("cannot unlink %s: %s"), - ent->d_name, strerror (errno)); - } - closedir (dir); - return rc; + + dir = opendir("."); + if (!dir) { + logmsg(LOG_ERR, _("cannot open directory %s: %s"), + name, strerror(errno)); + return 1; + } + + for (rc = 0; rc == 0 && (ent = readdir(dir));) { + struct stat st; + + if (strcmp(ent->d_name, ".") == 0 + || strcmp(ent->d_name, "..") == 0) + continue; + + if (stat(ent->d_name, &st) && errno != ENOENT) { + logmsg(LOG_ERR, _("cannot stat file `%s': %s"), + name, strerror(errno)); + rc = 1; + } else if (S_ISDIR(st.st_mode)) + rc = rmdir_r(ent->d_name); + else if ((rc = unlink(ent->d_name)) != 0 && errno != ENOENT) + logmsg(LOG_ERR, _("cannot unlink %s: %s"), + ent->d_name, strerror(errno)); + } + closedir(dir); + return rc; } /* Recursively remove the contents of the directory NAME and the directory itself. Do not change CWD. */ static int -rmdir_r (const char *name) +rmdir_r(const char *name) { - int rc; - - if (push_dir (NULL)) - { - logmsg (LOG_ERR, _("cannot save current directory: %s"), - strerror (errno)); - return 1; - } - rc = recursive_rmdir (name); - if (pop_dir ()) - { - logmsg (LOG_ERR, _("cannot restore current directory: %s"), - strerror (errno)); - rc = 1; - } - - if (rc == 0 && rmdir (name)) - { - logmsg (LOG_ERR, _("cannot remove directory %s: %s"), - name, strerror (errno)); - return 1; - } - - return rc; + int rc; + + if (push_dir(NULL)) { + logmsg(LOG_ERR, _("cannot save current directory: %s"), + strerror(errno)); + return 1; + } + rc = recursive_rmdir(name); + if (pop_dir()) { + logmsg(LOG_ERR, _("cannot restore current directory: %s"), + strerror(errno)); + rc = 1; + } + + if (rc == 0 && rmdir(name)) { + logmsg(LOG_ERR, _("cannot remove directory %s: %s"), + name, strerror(errno)); + return 1; + } + + return rc; } /* Remove temporary GPG home directory */ static void -remove_homedir () +remove_homedir() { - if (debug_level > 1) - logmsg (LOG_DEBUG, _("removing GNUPG home directory: %s"), temp_homedir); - if (rmdir_r (temp_homedir)) - logmsg (LOG_CRIT, _("failed to remove GPG directory %s"), temp_homedir); + if (debug_level > 1) + logmsg(LOG_DEBUG, _("removing GNUPG home directory: %s"), + temp_homedir); + if (rmdir_r(temp_homedir)) + logmsg(LOG_CRIT, _("failed to remove GPG directory %s"), + temp_homedir); } /* Create a temporary GPG home directory */ static int -create_gpg_homedir () +create_gpg_homedir() { - if (temp_homedir) - return 0; - - temp_homedir = grecs_strdup ("/tmp/wydawca-XXXXXX"); - if (!mkdtemp (temp_homedir)) - { - logmsg (LOG_CRIT, _("cannot create GPG home directory (%s): %s"), - temp_homedir, strerror (errno)); - return 1; - } - atexit (remove_homedir); - if (debug_level > 1) - logmsg (LOG_DEBUG, _("GNUPG home directory: %s"), temp_homedir); - setenv ("GNUPGHOME", temp_homedir, 1); - return 0; + if (temp_homedir) + return 0; + + temp_homedir = grecs_strdup("/tmp/wydawca-XXXXXX"); + if (!mkdtemp(temp_homedir)) { + logmsg(LOG_CRIT, + _("cannot create GPG home directory (%s): %s"), + temp_homedir, strerror(errno)); + return 1; + } + atexit(remove_homedir); + if (debug_level > 1) + logmsg(LOG_DEBUG, _("GNUPG home directory: %s"), temp_homedir); + setenv("GNUPGHOME", temp_homedir, 1); + return 0; } static int -checksig (gpgme_signature_t sig, const char *uid, struct file_triplet *trp) +checksig(gpgme_signature_t sig, const char *uid, struct file_triplet *trp) { - switch (gpg_err_code (sig->status)) - { - case GPG_ERR_NO_ERROR: - if (debug_level) - logmsg (LOG_NOTICE, _("Good signature from %s"), uid); - trp->uploader = uploader_find_frp (trp->uploader_list, sig->fpr); - if (!trp->uploader) - { - logmsg (LOG_ERR, - _("good signature from %s, " - "but the uploader info for %s not found"), - uid, sig->fpr); - return 1; + switch (gpg_err_code(sig->status)) { + case GPG_ERR_NO_ERROR: + if (debug_level) + logmsg(LOG_NOTICE, _("Good signature from %s"), uid); + trp->uploader = uploader_find_frp(trp->uploader_list, + sig->fpr); + if (!trp->uploader) { + logmsg(LOG_ERR, + _("good signature from %s, " + "but the uploader info for %s not found"), + uid, sig->fpr); + return 1; + } + break; + + case GPG_ERR_BAD_SIGNATURE: + UPDATE_STATS(STAT_BAD_SIGNATURE); + logmsg(LOG_ERR, _("BAD signature from %s"), uid); + return 0; + + case GPG_ERR_NO_PUBKEY: + UPDATE_STATS(STAT_ACCESS_VIOLATIONS); + logmsg(LOG_ERR, _("No public key")); + return 0; + + case GPG_ERR_NO_DATA: + UPDATE_STATS(STAT_BAD_TRIPLETS); + logmsg(LOG_ERR, _("No signature")); + return 0; + + case GPG_ERR_SIG_EXPIRED: + UPDATE_STATS(STAT_BAD_SIGNATURE); + logmsg(LOG_ERR, _("Expired signature from %s"), uid); + return 0; + + case GPG_ERR_KEY_EXPIRED: + UPDATE_STATS(STAT_BAD_SIGNATURE); + logmsg(LOG_ERR, _("Key expired (%s)"), uid); + return 0; + + default: + logmsg(LOG_ERR, _("Unknown signature error")); + return 0; } - break; - - case GPG_ERR_BAD_SIGNATURE: - UPDATE_STATS (STAT_BAD_SIGNATURE); - logmsg (LOG_ERR, _("BAD signature from %s"), uid); - return 0; - - case GPG_ERR_NO_PUBKEY: - UPDATE_STATS (STAT_ACCESS_VIOLATIONS); - logmsg (LOG_ERR, _("No public key")); - return 0; - - case GPG_ERR_NO_DATA: - UPDATE_STATS (STAT_BAD_TRIPLETS); - logmsg (LOG_ERR, _("No signature")); - return 0; - - case GPG_ERR_SIG_EXPIRED: - UPDATE_STATS (STAT_BAD_SIGNATURE); - logmsg (LOG_ERR, _("Expired signature from %s"), uid); - return 0; - - case GPG_ERR_KEY_EXPIRED: - UPDATE_STATS (STAT_BAD_SIGNATURE); - logmsg (LOG_ERR, _("Key expired (%s)"), uid); - return 0; - - default: - logmsg (LOG_ERR, _("Unknown signature error")); - return 0; - } - return -1; + return -1; } static int -gpg_verify_signature (gpgme_ctx_t ctx, gpgme_signature_t sig, - struct file_triplet *trp) +gpg_verify_signature(gpgme_ctx_t ctx, gpgme_signature_t sig, + struct file_triplet *trp) { - if (!sig) - return 0; - - for (; sig; sig = sig->next) - { - const char *uid; - gpgme_key_t key; - int rc; - - if (gpgme_get_key (ctx, sig->fpr, &key, 0) == GPG_ERR_NO_ERROR) - uid = key->uids->uid; - else - uid = sig->fpr; - rc = checksig (sig, uid, trp); - gpgme_key_unref (key); - if (rc != -1) - return rc; - } - return 1; + if (!sig) + return 0; + + for (; sig; sig = sig->next) { + const char *uid; + gpgme_key_t key; + int rc; + + if (gpgme_get_key(ctx, sig->fpr, &key, 0) == GPG_ERR_NO_ERROR) + uid = key->uids->uid; + else + uid = sig->fpr; + rc = checksig(sig, uid, trp); + gpgme_key_unref(key); + if (rc != -1) + return rc; + } + return 1; } /* Verify the directive file from TRP using public key PUBKEY */ int -verify_directive_signature (struct file_triplet *trp) +verify_directive_signature(struct file_triplet *trp) { - gpgme_ctx_t ctx; - gpgme_data_t key_data, directive_data, plain = NULL; - gpgme_error_t ec; - int rc; - struct uploader_info *uptr; - - create_gpg_homedir (); - fail_if_err (gpgme_new (&ctx)); - - for (uptr = trp->uploader_list; uptr; uptr = uptr->next) - { - gpgme_import_result_t res; - gpgme_import_status_t pstat; - - fail_if_err (gpgme_data_new_from_mem (&key_data, - uptr->gpg_key, - strlen (uptr->gpg_key), - 0)); - fail_if_err (gpgme_op_import (ctx, key_data)); - res = gpgme_op_import_result (ctx); - pstat = res->imports; - uptr->fpr = grecs_strdup (pstat->fpr); - if (debug_level > 2) - logmsg (LOG_DEBUG, _("imported key: user = %s, fingerprint = %s"), - uptr->name, uptr->fpr); - } - - fail_if_err (gpgme_data_new_from_file (&directive_data, - trp->file[file_directive].name, 1)); - gpgme_data_new (&plain); - ec = gpgme_op_verify (ctx, directive_data, NULL, plain); - if (ec == GPG_ERR_NO_ERROR) - { - gpgme_verify_result_t result; - - result = gpgme_op_verify_result (ctx); - if (!gpg_verify_signature (ctx, result->signatures, trp)) - { - UPDATE_STATS (STAT_BAD_SIGNATURE); - notify (trp->spool->notification, trp, ev_bad_directive_signature); - rc = 1; + gpgme_ctx_t ctx; + gpgme_data_t key_data, directive_data, plain = NULL; + gpgme_error_t ec; + int rc; + struct uploader_info *uptr; + + create_gpg_homedir(); + fail_if_err(gpgme_new(&ctx)); + + for (uptr = trp->uploader_list; uptr; uptr = uptr->next) { + gpgme_import_result_t res; + gpgme_import_status_t pstat; + + fail_if_err(gpgme_data_new_from_mem(&key_data, + uptr->gpg_key, + strlen(uptr->gpg_key), 0)); + fail_if_err(gpgme_op_import(ctx, key_data)); + res = gpgme_op_import_result(ctx); + pstat = res->imports; + uptr->fpr = grecs_strdup(pstat->fpr); + if (debug_level > 2) + logmsg(LOG_DEBUG, + _("imported key: user = %s, fingerprint = %s"), + uptr->name, uptr->fpr); } - else - rc = 0; - } - else - { - rc = 1; - UPDATE_STATS (STAT_BAD_SIGNATURE); - logmsg (LOG_ERR, _("%s: directive verification failed: %s"), - trp->name, gpgme_strerror (ec)); - } - - gpgme_data_release (plain); - gpgme_data_release (directive_data); - gpgme_data_release (key_data); - gpgme_release (ctx); - - return rc; + + fail_if_err(gpgme_data_new_from_file(&directive_data, + trp->file[file_directive].name, + 1)); + gpgme_data_new(&plain); + ec = gpgme_op_verify(ctx, directive_data, NULL, plain); + if (ec == GPG_ERR_NO_ERROR) { + gpgme_verify_result_t result; + + result = gpgme_op_verify_result(ctx); + if (!gpg_verify_signature(ctx, result->signatures, trp)) { + UPDATE_STATS(STAT_BAD_SIGNATURE); + notify(trp->spool->notification, trp, + ev_bad_directive_signature); + rc = 1; + } else + rc = 0; + } else { + rc = 1; + UPDATE_STATS(STAT_BAD_SIGNATURE); + logmsg(LOG_ERR, _("%s: directive verification failed: %s"), + trp->name, gpgme_strerror(ec)); + } + + gpgme_data_release(plain); + gpgme_data_release(directive_data); + gpgme_data_release(key_data); + gpgme_release(ctx); + + return rc; } /* Verify the detached signature of TRP. NOTE: It is assumed that the public key is already registered (by a previous call to verify_directive_signature). */ int -verify_detached_signature (struct file_triplet *trp) +verify_detached_signature(struct file_triplet *trp) { - gpgme_engine_info_t info; - const char *argv[5]; - const struct spool *spool; - - ASGN_SPOOL (spool, trp, return 1); - - fail_if_err (gpgme_get_engine_info (&info)); - while (info && info->protocol != GPGME_PROTOCOL_OpenPGP) - info = info->next; - if (!info) - { - logmsg (LOG_CRIT, - _("cannot find path to gpg binary (attempting to verify " - "the detached signature for %s"), trp->name); - return 1; - } - - create_gpg_homedir (); - argv[0] = info->file_name; - argv[1] = "--verify"; - argv[2] = trp->file[file_signature].name; - argv[3] = trp->file[file_dist].name; - argv[4] = NULL; - - switch (wydawca_exec (5, argv, NULL)) - { - case exec_success: - if (debug_level) - logmsg (LOG_DEBUG, _("good detached signature for %s"), trp->name); - return 0; - - case exec_fail: - UPDATE_STATS (STAT_BAD_SIGNATURE); - logmsg (LOG_ERR, _("BAD detached signature for %s"), trp->name); - notify (spool->notification, trp, ev_bad_detached_signature); - break; - - case exec_error: - logmsg (LOG_CRIT, _("cannot verify detached signature for %s"), - trp->name); - break; - } - - return 1; + gpgme_engine_info_t info; + const char *argv[5]; + const struct spool *spool; + + ASGN_SPOOL(spool, trp, return 1); + + fail_if_err(gpgme_get_engine_info(&info)); + while (info && info->protocol != GPGME_PROTOCOL_OpenPGP) + info = info->next; + if (!info) { + logmsg(LOG_CRIT, + _("cannot find path to gpg binary (attempting to " + "verify the detached signature for %s"), trp->name); + return 1; + } + + create_gpg_homedir(); + argv[0] = info->file_name; + argv[1] = "--verify"; + argv[2] = trp->file[file_signature].name; + argv[3] = trp->file[file_dist].name; + argv[4] = NULL; + + switch (wydawca_exec(5, argv, NULL)) { + case exec_success: + if (debug_level) + logmsg(LOG_DEBUG, _("good detached signature for %s"), + trp->name); + return 0; + + case exec_fail: + UPDATE_STATS(STAT_BAD_SIGNATURE); + logmsg(LOG_ERR, _("BAD detached signature for %s"), trp->name); + notify(spool->notification, trp, ev_bad_detached_signature); + break; + + case exec_error: + logmsg(LOG_CRIT, _("cannot verify detached signature for %s"), + trp->name); + break; + } + + return 1; } diff --git a/src/interval.c b/src/interval.c index cf46b4c..049091d 100644 --- a/src/interval.c +++ b/src/interval.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007, 2009-2011 Sergey Poznyakoff + Copyright (C) 2007, 2009-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -23,97 +23,86 @@ #include "wydawca.h" static int -time_multiplier (const char *str, unsigned *m, unsigned *plen) +time_multiplier(const char *str, unsigned *m, unsigned *plen) { - static struct timetab - { - char *name; - unsigned mul; - } tab[] = { - { "seconds", 1 }, - { "minutes", 60 }, - { "hours", 60*60 }, - { "days", 24*60*60 }, - { "weeks", 7*24*60*60 }, - { "months", 31*7*24*60*60 }, - { NULL } - }; - struct timetab *p; - int slen; - - for (slen = 0; str[slen]; slen++) - if (isspace (str[slen])) - break; - - for (p = tab; p->name; p++) - { - if (p->name[0] == tolower (str[0])) - { - int nlen = strlen (p->name); - - if (nlen > slen) - nlen = slen; - - if (strncasecmp (p->name, str, nlen) == 0) - { - *m = p->mul; - if (plen) - *plen = nlen; - return 0; - } + static struct timetab { + char *name; + unsigned mul; + } tab[] = { + { "seconds", 1 }, + { "minutes", 60 }, + { "hours", 60 * 60 }, + { "days", 24 * 60 * 60 }, + { "weeks", 7 * 24 * 60 * 60 }, + { "months", 31 * 7 * 24 * 60 * 60 }, + { NULL } + }; + struct timetab *p; + int slen; + + for (slen = 0; str[slen]; slen++) + if (isspace(str[slen])) + break; + + for (p = tab; p->name; p++) { + if (p->name[0] == tolower(str[0])) { + int nlen = strlen(p->name); + + if (nlen > slen) + nlen = slen; + + if (strncasecmp(p->name, str, nlen) == 0) { + *m = p->mul; + if (plen) + *plen = nlen; + return 0; + } + } } - } - return 1; + return 1; } int -parse_time_interval (const char *str, time_t *pint, const char **endp) +parse_time_interval(const char *str, time_t * pint, const char **endp) { - int rc = 0; - time_t interval = 0; - - while (*str) - { - char *p; - unsigned long n; - unsigned mul, len; - - while (*str && isspace (*str)) - str++; - - if (!isdigit (*str) && time_multiplier (str, &mul, &len) == 0) - { - n = 1; - str += len; + int rc = 0; + time_t interval = 0; + + while (*str) { + char *p; + unsigned long n; + unsigned mul, len; + + while (*str && isspace(*str)) + str++; + + if (!isdigit(*str) && time_multiplier(str, &mul, &len) == 0) { + n = 1; + str += len; + } else { + n = strtoul(str, &p, 10); + if (*p && !isspace(*p)) { + str = p; + rc = 1; + break; + } + + while (*p && isspace(*p)) + p++; + + str = p; + if (*str) { + if (rc = time_multiplier(str, &mul, &len)) + break; + str += len; + } else + mul = 1; + } + interval += n * mul; } - else - { - n = strtoul (str, &p, 10); - if (*p && !isspace (*p)) - { - str = p; - rc = 1; - break; - } - - while (*p && isspace (*p)) - p++; - - str = p; - if (*str) - { - if (rc = time_multiplier (str, &mul, &len)) - break; - str += len; - } - else - mul = 1; - } - interval += n * mul; - } - if (rc && endp) - *endp = str; - *pint = interval; - return rc; + if (rc && endp) + *endp = str; + *pint = interval; + return rc; } @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2009-2011 Sergey Poznyakoff + Copyright (C) 2009-2013 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -20,363 +20,335 @@ #define STATE_FINISHED 0x01 #define STATE_QUEUED 0x02 #define STATE_ACTIVE 0x04 - -struct job -{ - struct job *next, *prev; - int state; - struct spool *spool; - uid_t uid; - pid_t pid; - time_t timestamp; - int exit_status; + +struct job { + struct job *next, *prev; + int state; + struct spool *spool; + uid_t uid; + pid_t pid; + time_t timestamp; + int exit_status; }; struct job *queue; size_t jobmax; size_t jobcnt; -struct spool fake_spool = { "all spools" }, - inotify_spool = { "inotify" } ; +struct spool fake_spool = { "all spools" }, inotify_spool = { "inotify"}; static int wakeup; RETSIGTYPE -queue_signal (int sig) +queue_signal(int sig) { - wakeup = 1; - signal (sig, queue_signal); + wakeup = 1; + signal(sig, queue_signal); } void -set_timer (time_t interval) +set_timer(time_t interval) { - wakeup = 0; - if (interval) - alarm (interval); + wakeup = 0; + if (interval) + alarm(interval); } struct job * -job_locate (const struct spool *spool, uid_t uid) +job_locate(const struct spool *spool, uid_t uid) { - struct job *p; - for (p = queue; p; p = p->next) - if (p->spool == spool && p->uid == uid) - break; - return p; + struct job *p; + for (p = queue; p; p = p->next) + if (p->spool == spool && p->uid == uid) + break; + return p; } size_t -job_active_count () +job_active_count() { - struct job *job; - size_t count = 0; - for (job = queue; job; job = job->next) - if (job->state & STATE_ACTIVE) - count++; - return count; + struct job *job; + size_t count = 0; + for (job = queue; job; job = job->next) + if (job->state & STATE_ACTIVE) + count++; + return count; } static int -procspool (struct spool *spool, void *data) +procspool(struct spool *spool, void *data) { - spool_commit_triplets (spool); - return 0; + spool_commit_triplets(spool); + return 0; } int -wydawca_scanner (struct job *job) +wydawca_scanner(struct job *job) { - int rc; - initstats(); - timer_start ("wydawca"); - if (job->spool == &inotify_spool) - rc = for_each_spool (procspool, NULL); - else if (job->spool == &fake_spool) - rc = scan_all_spools (1, &job->uid); - else - { - spool_create_timers (); - rc = scan_spool (job->spool, 1, &job->uid); - } - timer_stop ("wydawca"); - logstats (); - mail_finish (); - return rc; + int rc; + initstats(); + timer_start("wydawca"); + if (job->spool == &inotify_spool) + rc = for_each_spool(procspool, NULL); + else if (job->spool == &fake_spool) + rc = scan_all_spools(1, &job->uid); + else { + spool_create_timers(); + rc = scan_spool(job->spool, 1, &job->uid); + } + timer_stop("wydawca"); + logstats(); + mail_finish(); + return rc; } -int -job_start (struct job *job) +int +job_start(struct job *job) { - pid_t pid; - - if (jobmax && jobcnt == jobmax) - { - logmsg (LOG_NOTICE, "maximum number of processes active"); - return 1; - } - - if (debug_level) - logmsg (LOG_DEBUG, _("starting job: %s, %lu"), - job->spool->tag, (unsigned long)job->uid); - - if (single_process) - { - if (wydawca_scanner (job)) - job->state = STATE_QUEUED; - else - job->state = STATE_FINISHED; - wakeup = 1; - return 0; - } - - pid = fork (); - if (pid == 0) - { - int i; - signal (SIGHUP, SIG_DFL); - signal (SIGTERM, SIG_DFL); - signal (SIGQUIT, SIG_DFL); - signal (SIGINT, SIG_DFL); - signal (SIGCHLD, SIG_DFL); - signal (SIGALRM, SIG_DFL); - alarm (0); - for (i = getdtablesize (); i > 2; i--) - close (i); - exit (wydawca_scanner (job) ? WYDAWCA_EX_AGAIN : 0); - } - else if (pid == -1) - { - logmsg (LOG_CRIT, "fork: %s", strerror (errno)); - return -1; - } - else - { - job->state = STATE_ACTIVE; - job->pid = pid; - jobcnt++; - } - return 0; -} + pid_t pid; + + if (jobmax && jobcnt == jobmax) { + logmsg(LOG_NOTICE, "maximum number of processes active"); + return 1; + } + + if (debug_level) + logmsg(LOG_DEBUG, _("starting job: %s, %lu"), + job->spool->tag, (unsigned long)job->uid); + + if (single_process) { + if (wydawca_scanner(job)) + job->state = STATE_QUEUED; + else + job->state = STATE_FINISHED; + wakeup = 1; + return 0; + } + + pid = fork(); + if (pid == 0) { + int i; + signal(SIGHUP, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + signal(SIGALRM, SIG_DFL); + alarm(0); + for (i = getdtablesize(); i > 2; i--) + close(i); + exit(wydawca_scanner(job) ? WYDAWCA_EX_AGAIN : 0); + } else if (pid == -1) { + logmsg(LOG_CRIT, "fork: %s", strerror(errno)); + return -1; + } else { + job->state = STATE_ACTIVE; + job->pid = pid; + jobcnt++; + } + return 0; +} void -job_remove (struct job *job) +job_remove(struct job *job) { - struct job *p; - - if (debug_level) - logmsg (LOG_DEBUG, _("removing job: %s, %lu"), - job->spool->tag, (unsigned long)job->uid); - p = job->prev; - if (p) - p->next = job->next; - else - queue = job->next; - - p = job->next; - if (p) - p->prev = job->prev; + struct job *p; + + if (debug_level) + logmsg(LOG_DEBUG, _("removing job: %s, %lu"), + job->spool->tag, (unsigned long)job->uid); + p = job->prev; + if (p) + p->next = job->next; + else + queue = job->next; + + p = job->next; + if (p) + p->prev = job->prev; } void -job_insert (struct job *job, struct job *elt) +job_insert(struct job *job, struct job *elt) { - struct job *p; - - job->prev = elt; - if (!elt) - { - if (queue) - queue->prev = job; - job->next = queue; - queue = job; - return; - } - - p = elt->next; - elt->next = job; - - if (p) - p->prev = job; + struct job *p; + + job->prev = elt; + if (!elt) { + if (queue) + queue->prev = job; + job->next = queue; + queue = job; + return; + } + + p = elt->next; + elt->next = job; + + if (p) + p->prev = job; } - + void -schedule_job (struct spool *spool, uid_t uid) +schedule_job(struct spool *spool, uid_t uid) { - struct job *job; - - if (!spool) - spool = &fake_spool; - - if (debug_level) - logmsg (LOG_DEBUG, _("scheduling job: %s, %lu"), - spool->tag, (unsigned long)uid); - - job = job_locate (spool, uid); - if (!job) - { - job = grecs_zalloc (sizeof (*job)); - job->spool = spool; - job->uid = uid; - job->pid = -1; - time (&job->timestamp); - job_insert (job, NULL); - } - - job->state |= STATE_QUEUED; - job_start (job); -} + struct job *job; + + if (!spool) + spool = &fake_spool; + + if (debug_level) + logmsg(LOG_DEBUG, _("scheduling job: %s, %lu"), + spool->tag, (unsigned long)uid); + + job = job_locate(spool, uid); + if (!job) { + job = grecs_zalloc(sizeof(*job)); + job->spool = spool; + job->uid = uid; + job->pid = -1; + time(&job->timestamp); + job_insert(job, NULL); + } + + job->state |= STATE_QUEUED; + job_start(job); +} static void -print_status (struct job *job, int expect_term) +print_status(struct job *job, int expect_term) { - struct passwd *pw = getpwuid (job->uid); - int status = job->exit_status; - - if (WIFEXITED (status)) - { - int exit_code = WEXITSTATUS (status); - if (exit_code == 0) - { - if (debug_level) - logmsg (LOG_DEBUG, - _("%lu (%s, %s) exited successfully"), - (unsigned long) job->pid, job->spool->tag, pw->pw_name); - } - else if (exit_code == WYDAWCA_EX_AGAIN) - { - if (debug_level) - logmsg (LOG_DEBUG, - _("%lu (%s, %s) reported tempfail"), - (unsigned long) job->pid, job->spool->tag, pw->pw_name); - } - else - logmsg (LOG_ERR, - _("%lu (%s, %s) failed with status %d"), - (unsigned long) job->pid, job->spool->tag, pw->pw_name, - exit_code); - } - else if (WIFSIGNALED (status)) - { - int prio; - if (expect_term && WTERMSIG (status) == SIGTERM) - { - if (!debug_level) - return; - prio = LOG_DEBUG; - } - else - prio = LOG_ERR; - - logmsg (prio, - _("%lu (%s, %s) terminated on signal %d"), - (unsigned long)job->pid, job->spool->tag, - pw->pw_name, WTERMSIG (status)); - } - else if (WIFSTOPPED (status)) - logmsg (LOG_NOTICE, - _("%lu (%s, %s) stopped on signal %d"), - (unsigned long)job->pid, job->spool->tag, - pw->pw_name, WSTOPSIG (status)); + struct passwd *pw = getpwuid(job->uid); + int status = job->exit_status; + + if (WIFEXITED(status)) { + int exit_code = WEXITSTATUS(status); + if (exit_code == 0) { + if (debug_level) + logmsg(LOG_DEBUG, + _("%lu (%s, %s) exited successfully"), + (unsigned long)job->pid, + job->spool->tag, + pw->pw_name); + } else if (exit_code == WYDAWCA_EX_AGAIN) { + if (debug_level) + logmsg(LOG_DEBUG, + _("%lu (%s, %s) reported tempfail"), + (unsigned long)job->pid, + job->spool->tag, + pw->pw_name); + } else + logmsg(LOG_ERR, + _("%lu (%s, %s) failed with status %d"), + (unsigned long)job->pid, job->spool->tag, + pw->pw_name, exit_code); + } else if (WIFSIGNALED(status)) { + int prio; + if (expect_term && WTERMSIG(status) == SIGTERM) { + if (!debug_level) + return; + prio = LOG_DEBUG; + } else + prio = LOG_ERR; + + logmsg(prio, + _("%lu (%s, %s) terminated on signal %d"), + (unsigned long)job->pid, job->spool->tag, + pw->pw_name, WTERMSIG(status)); + } else if (WIFSTOPPED(status)) + logmsg(LOG_NOTICE, + _("%lu (%s, %s) stopped on signal %d"), + (unsigned long)job->pid, job->spool->tag, + pw->pw_name, WSTOPSIG(status)); #ifdef WCOREDUMP - else if (WCOREDUMP (status)) - logmsg (LOG_NOTICE, - _("%lu (%s, %s) dumped core"), - (unsigned long)job->pid, job->spool->tag, pw->pw_name); + else if (WCOREDUMP(status)) + logmsg(LOG_NOTICE, + _("%lu (%s, %s) dumped core"), + (unsigned long)job->pid, job->spool->tag, pw->pw_name); #endif - else - logmsg (LOG_ERR, - _("%lu (%s, %s) terminated with unrecognized status"), - (unsigned long)job->pid, job->spool->tag, pw->pw_name); + else + logmsg(LOG_ERR, + _("%lu (%s, %s) terminated with unrecognized status"), + (unsigned long)job->pid, job->spool->tag, pw->pw_name); } void -job_queue_runner (time_t min_interval) +job_queue_runner(time_t min_interval) { - int status; - struct job *job; - time_t now = time (NULL); - - if (wakeup) - { - wakeup = 0; - - for (;;) - { - pid_t pid = waitpid ((pid_t)-1, &status, WNOHANG); - if (pid <= 0) - break; - for (job = queue; job; job = job->next) - { - if ((job->state & STATE_ACTIVE) && job->pid == pid) - { - job->state &= ~STATE_ACTIVE; - job->state |= STATE_FINISHED; - job->exit_status = status; - jobcnt--; - } - } - } - - for (job = queue; job;) - { - struct job *next = job->next; - if (job->state & STATE_FINISHED) - { - print_status (job, 0); - if ((job->state &= ~STATE_FINISHED) == 0) - { - if (WIFEXITED (job->exit_status) - && WEXITSTATUS (job->exit_status) == WYDAWCA_EX_AGAIN) - { - time_t interval = lock_timeout; - if (interval == 0) - interval = lock_expire_time; - /* Re-queue the job */ - job->state = STATE_QUEUED; - job->timestamp = now + interval; - } - else - { - job_remove (job); - free (job); - job = next; - continue; - } - } - } - - if (job->state == STATE_QUEUED) - { - if (job->timestamp >= now) - { - if (job_start (job)) - pause (); /* FIXME */ - now = time (NULL); + int status; + struct job *job; + time_t now = time(NULL); + + if (wakeup) { + wakeup = 0; + + for (;;) { + pid_t pid = waitpid((pid_t) - 1, &status, WNOHANG); + if (pid <= 0) + break; + for (job = queue; job; job = job->next) { + if ((job->state & STATE_ACTIVE) && + job->pid == pid) { + job->state &= ~STATE_ACTIVE; + job->state |= STATE_FINISHED; + job->exit_status = status; + jobcnt--; + } + } } - else - { - time_t interval = job->timestamp - now; - if (min_interval == 0 || interval < min_interval) - min_interval = interval; + + for (job = queue; job;) { + struct job *next = job->next; + if (job->state & STATE_FINISHED) { + print_status(job, 0); + if ((job->state &= ~STATE_FINISHED) == 0) { + if (WIFEXITED(job->exit_status) && + WEXITSTATUS(job->exit_status) == + WYDAWCA_EX_AGAIN) { + time_t interval = lock_timeout; + if (interval == 0) + interval = + lock_expire_time; + /* Re-queue the job */ + job->state = STATE_QUEUED; + job->timestamp = now + interval; + } else { + job_remove(job); + free(job); + job = next; + continue; + } + } + } + + if (job->state == STATE_QUEUED) { + if (job->timestamp >= now) { + if (job_start(job)) + pause(); /* FIXME */ + now = time(NULL); + } else { + time_t interval = job->timestamp - now; + if (min_interval == 0 + || interval < min_interval) + min_interval = interval; + } + } + + job = next; } - } - - job = next; } - } - - if (min_interval) - { - if (debug_level > 1) - logmsg (LOG_DEBUG, _("computed interval: %lu"), min_interval); - set_timer (min_interval); - } + + if (min_interval) { + if (debug_level > 1) + logmsg(LOG_DEBUG, _("computed interval: %lu"), + min_interval); + set_timer(min_interval); + } } void -job_init () +job_init() { - signal (SIGCHLD, queue_signal); - signal (SIGALRM, queue_signal); + signal(SIGCHLD, queue_signal); + signal(SIGALRM, queue_signal); } @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007, 2009-2011 Sergey Poznyakoff + Copyright (C) 2007, 2009-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -18,279 +18,259 @@ int enable_locking = 1; char *lockdir; -time_t lock_expire_time = 5*60; +time_t lock_expire_time = 5 * 60; time_t lock_timeout = 60; #define LOCKFILE_MODE 0644 static int -stat_check (const char *file, int fd, int links) +stat_check(const char *file, int fd, int links) { - struct stat fn_stat; - struct stat fd_stat; - int err = 0; - int localfd = -1; - - if (fd == -1) - { - localfd = open (file, O_RDONLY); - - if (localfd == -1) - return errno; - fd = localfd; - } - - /* We should always be able to stat a valid fd, so this - is an error condition. */ - if (lstat (file, &fn_stat) || fstat (fd, &fd_stat)) - err = errno; - else - { - /* If the link and stat don't report the same info, or the - file is a symlink, fail the locking. */ + struct stat fn_stat; + struct stat fd_stat; + int err = 0; + int localfd = -1; + + if (fd == -1) { + localfd = open(file, O_RDONLY); + + if (localfd == -1) + return errno; + fd = localfd; + } + + /* We should always be able to stat a valid fd, so this + is an error condition. */ + if (lstat(file, &fn_stat) || fstat(fd, &fd_stat)) + err = errno; + else { + /* If the link and stat don't report the same info, or the + file is a symlink, fail the locking. */ #define CHK(X) if(X) err = EINVAL - CHK (!S_ISREG (fn_stat.st_mode)); - CHK (!S_ISREG (fd_stat.st_mode)); - CHK (fn_stat.st_nlink != links); - CHK (fn_stat.st_dev != fd_stat.st_dev); - CHK (fn_stat.st_ino != fd_stat.st_ino); - CHK (fn_stat.st_mode != fd_stat.st_mode); - CHK (fn_stat.st_nlink != fd_stat.st_nlink); - CHK (fn_stat.st_uid != fd_stat.st_uid); - CHK (fn_stat.st_gid != fd_stat.st_gid); - CHK (fn_stat.st_rdev != fd_stat.st_rdev); + CHK(!S_ISREG(fn_stat.st_mode)); + CHK(!S_ISREG(fd_stat.st_mode)); + CHK(fn_stat.st_nlink != links); + CHK(fn_stat.st_dev != fd_stat.st_dev); + CHK(fn_stat.st_ino != fd_stat.st_ino); + CHK(fn_stat.st_mode != fd_stat.st_mode); + CHK(fn_stat.st_nlink != fd_stat.st_nlink); + CHK(fn_stat.st_uid != fd_stat.st_uid); + CHK(fn_stat.st_gid != fd_stat.st_gid); + CHK(fn_stat.st_rdev != fd_stat.st_rdev); #undef CHK - } - if (localfd != -1) - close (localfd); + } + if (localfd != -1) + close(localfd); - return err; + return err; } int -_lock_internal (const char *file, const char *fname) +_lock_internal(const char *file, const char *fname) { - int err = 0; - int fd; - FILE *fp; - - fd = open (fname, O_WRONLY | O_CREAT | O_EXCL, LOCKFILE_MODE); - if (fd == -1) - { - if (errno == EEXIST) - return LOCK_RETRY; - else - { - logmsg (LOG_ERR, _("cannot create lock file %s: %s"), - fname, strerror (errno)); - return LOCK_FAILURE; + int err = 0; + int fd; + FILE *fp; + + fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, LOCKFILE_MODE); + if (fd == -1) { + if (errno == EEXIST) + return LOCK_RETRY; + else { + logmsg(LOG_ERR, _("cannot create lock file %s: %s"), + fname, strerror(errno)); + return LOCK_FAILURE; + } + } + close(fd); + + /* Try to link to the lockfile. */ + if (link(fname, file) == -1) { + unlink(fname); + if (errno == EEXIST) + return LOCK_RETRY; + else { + logmsg(LOG_ERR, _("cannot create lock file %s: %s"), + file, strerror(errno)); + return LOCK_FAILURE; + } } - } - close (fd); - - /* Try to link to the lockfile. */ - if (link (fname, file) == -1) - { - unlink (fname); - if (errno == EEXIST) - return LOCK_RETRY; - else - { - logmsg (LOG_ERR, _("cannot create lock file %s: %s"), - file, strerror (errno)); - return LOCK_FAILURE; + + if ((fd = open(file, O_RDWR)) == -1) { + unlink(fname); + logmsg(LOG_ERR, _("cannot open lock file %s: %s"), + fname, strerror(errno)); + return LOCK_FAILURE; + } + + err = stat_check(fname, fd, 2); + if (err) { + unlink(fname); + logmsg(LOG_ERR, _("lock file check failed: %s"), + strerror(errno)); + return (err == EINVAL) ? LOCK_INVALID : LOCK_FAILURE; } - } - - if ((fd = open (file, O_RDWR)) == -1) - { - unlink (fname); - logmsg (LOG_ERR, _("cannot open lock file %s: %s"), - fname, strerror (errno)); - return LOCK_FAILURE; - } - - err = stat_check (fname, fd, 2); - if (err) - { - unlink (fname); - logmsg (LOG_ERR, _("lock file check failed: %s"), strerror (errno)); - return (err == EINVAL) ? LOCK_INVALID : LOCK_FAILURE; - } - - unlink (fname); - - fp = fdopen (fd, "w"); - fprintf (fp, "%lu", (unsigned long) getpid ()); - fclose (fp); - - return 0; + + unlink(fname); + + fp = fdopen(fd, "w"); + fprintf(fp, "%lu", (unsigned long)getpid()); + fclose(fp); + + return 0; } static void -expire_stale_lock (const char *file) +expire_stale_lock(const char *file) { - int stale = 0; - char buf[80]; - int fd; - int len; - - fd = open (file, O_RDONLY); - if (fd == -1) - return; - - len = read (fd, buf, sizeof (buf) - 1); - if (len > 0) - { - pid_t pid; - - buf[len] = 0; - pid = strtoul (buf, NULL, 10); - if (pid > 0) - { - /* Process is gone so we try to remove the lock. */ - if (kill (pid, 0) == -1) - stale = 1; + int stale = 0; + char buf[80]; + int fd; + int len; + + fd = open(file, O_RDONLY); + if (fd == -1) + return; + + len = read(fd, buf, sizeof(buf) - 1); + if (len > 0) { + pid_t pid; + + buf[len] = 0; + pid = strtoul(buf, NULL, 10); + if (pid > 0) { + /* Process is gone so we try to remove the lock. */ + if (kill(pid, 0) == -1) + stale = 1; + } else + stale = 1; /* Corrupted file, remove the lock. */ + } + + if (!stale && lock_expire_time > 0) { + struct stat stbuf; + fstat(fd, &stbuf); + /* The lock has expired. */ + if ((time(NULL) - stbuf.st_mtime) > lock_expire_time) + stale = 1; } - else - stale = 1; /* Corrupted file, remove the lock. */ - } - - if (!stale && lock_expire_time > 0) - { - struct stat stbuf; - fstat (fd, &stbuf); - /* The lock has expired. */ - if ((time (NULL) - stbuf.st_mtime) > lock_expire_time) - stale = 1; - } - - close (fd); - if (stale) - unlink (file); + + close(fd); + if (stale) + unlink(file); } static char * -host_name () +host_name() { - static char *hostbuf = NULL; - size_t size = 0; - int rc; - - if (hostbuf) - return hostbuf; - - do - { - if (!hostbuf) - { - size = 256; - hostbuf = grecs_malloc (size); - } - else - { - size_t ns = size * 2; - if (size < ns) - grecs_alloc_die (); - size = ns; - hostbuf = grecs_realloc (hostbuf, size); + static char *hostbuf = NULL; + size_t size = 0; + int rc; + + if (hostbuf) + return hostbuf; + + do { + if (!hostbuf) { + size = 256; + hostbuf = grecs_malloc(size); + } else { + size_t ns = size * 2; + if (size < ns) + grecs_alloc_die(); + size = ns; + hostbuf = grecs_realloc(hostbuf, size); + } } - } - while ((rc = gethostname (hostbuf, size )) == -1 && - (errno == EINVAL + while ((rc = gethostname(hostbuf, size)) == -1 && + (errno == EINVAL #ifdef ENAMETOOLONG - || errno == ENAMETOOLONG + || errno == ENAMETOOLONG #endif - )); - if (rc) - { - logmsg (LOG_ERR, _("cannot get hostname: %s"), strerror (rc)); - exit (EX_SOFTWARE); - } - return hostbuf; + )); + if (rc) { + logmsg(LOG_ERR, _("cannot get hostname: %s"), strerror(rc)); + exit(EX_SOFTWARE); + } + return hostbuf; } int -wydawca_lock (const char *lockname) +wydawca_lock(const char *lockname) { - char *tempname = NULL; - size_t size = 0; - int rc; - - if (!enable_locking) - return 0; - expire_stale_lock (lockname); - - /* build the NFS hitching-post to the lock file */ - grecs_asprintf (&tempname, &size, "%s.%lu.%lu.%s", - lockname, - (unsigned long) getpid (), - (unsigned long) time (NULL), host_name ()); - if (!tempname) - return LOCK_FAILURE; - if (lock_timeout) - { - time_t start = time (NULL); - - do - { - rc = _lock_internal (lockname, tempname); - if (rc == LOCK_RETRY) - sleep (1); - else - break; - } - while (time (NULL) - start < lock_timeout); - } - else - rc = _lock_internal (lockname, tempname); + char *tempname = NULL; + size_t size = 0; + int rc; + + if (!enable_locking) + return 0; + expire_stale_lock(lockname); + + /* build the NFS hitching-post to the lock file */ + grecs_asprintf(&tempname, &size, "%s.%lu.%lu.%s", + lockname, + (unsigned long)getpid(), + (unsigned long)time(NULL), host_name()); + if (!tempname) + return LOCK_FAILURE; + if (lock_timeout) { + time_t start = time(NULL); + + do { + rc = _lock_internal(lockname, tempname); + if (rc == LOCK_RETRY) + sleep(1); + else + break; + } + while (time(NULL) - start < lock_timeout); + } else + rc = _lock_internal(lockname, tempname); - free (tempname); - return rc; + free(tempname); + return rc; } void -wydawca_unlock (const char *lockfile) +wydawca_unlock(const char *lockfile) { - if (enable_locking) - unlink (lockfile); + if (enable_locking) + unlink(lockfile); } static char * -fix_tagname (const char *tag) +fix_tagname(const char *tag) { - char *tagname = grecs_strdup (tag); - char *p; - - for (p = tagname; *p; p++) - if (!isalnum (*p) && *p != '_' && *p != '-') - *p = '_'; - return tagname; -} + char *tagname = grecs_strdup(tag); + char *p; + + for (p = tagname; *p; p++) + if (!isalnum(*p) && *p != '_' && *p != '-') + *p = '_'; + return tagname; +} char * -wydawca_lockname (const char *tag) +wydawca_lockname(const char *tag) { - char *lockname = NULL; - size_t size = 0; - char *tagname = fix_tagname (tag); - grecs_asprintf (&lockname, &size, "%s/LCK.%s", lockdir, tagname); - if (!lockname) - grecs_alloc_die (); - free (tagname); - return lockname; + char *lockname = NULL; + size_t size = 0; + char *tagname = fix_tagname(tag); + grecs_asprintf(&lockname, &size, "%s/LCK.%s", lockdir, tagname); + if (!lockname) + grecs_alloc_die(); + free(tagname); + return lockname; } void -wydawca_lock_init () +wydawca_lock_init() { - if (enable_locking) - { - if (!lockdir) - lockdir = grecs_strdup (LOCALSTATEDIR "/lock/" PACKAGE); - if (create_hierarchy (lockdir, 0)) - exit (EX_OSFILE); - } + if (enable_locking) { + if (!lockdir) + lockdir = grecs_strdup(LOCALSTATEDIR "/lock/" PACKAGE); + if (create_hierarchy(lockdir, 0)) + exit(EX_OSFILE); + } } @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007-2011 Sergey Poznyakoff + Copyright (C) 2007-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -30,631 +30,582 @@ char *admin_stat_message; char *admin_stat_sign_key; void -mail_init () +mail_init() { - if (!mailer) - { - int rc; - if ((rc = mu_mailer_create (&mailer, NULL))) - { - const char *url = NULL; - mu_mailer_get_url_default (&url); - logmsg (LOG_ERR, _("cannot create default mailer `%s': %s"), - url, mu_strerror (rc)); - } - } + if (!mailer) { + int rc; + if ((rc = mu_mailer_create(&mailer, NULL))) { + const char *url = NULL; + mu_mailer_get_url_default(&url); + logmsg(LOG_ERR, + _("cannot create default mailer `%s': %s"), url, + mu_strerror(rc)); + } + } } static ssize_t -mu_stream_data_read_cb (void *handle, void *buffer, size_t size) +mu_stream_data_read_cb(void *handle, void *buffer, size_t size) { - mu_stream_t str = handle; - size_t nread; - int rc; - - rc = mu_stream_read (str, buffer, size, &nread); - if (rc) - { - logmsg (LOG_ERR, "mu_stream_read: %s", mu_strerror (rc)); - errno = EIO; - return -1; - } - return nread; + mu_stream_t str = handle; + size_t nread; + int rc; + + rc = mu_stream_read(str, buffer, size, &nread); + if (rc) { + logmsg(LOG_ERR, "mu_stream_read: %s", mu_strerror(rc)); + errno = EIO; + return -1; + } + return nread; } static int -check_sign_result (gpgme_sign_result_t result, gpgme_sig_mode_t type) +check_sign_result(gpgme_sign_result_t result, gpgme_sig_mode_t type) { - gpgme_new_signature_t sign; - - if (result->invalid_signers) - { - logmsg (LOG_ERR, _("GPGME: invalid signer found: %s"), - result->invalid_signers->fpr); - return 1; - } - - if (!result->signatures) - { - logmsg (LOG_ERR, _("GPGME: no signatures created")); - return 1; - } - - for (sign = result->signatures; sign; sign = sign->next) - { - if (sign->type != type) - { - logmsg (LOG_ERR, _("GPGME: wrong type of signature created")); - return 1; - } - } - /* FIXME: fingerprint? */ - return 0; + gpgme_new_signature_t sign; + + if (result->invalid_signers) { + logmsg(LOG_ERR, _("GPGME: invalid signer found: %s"), + result->invalid_signers->fpr); + return 1; + } + + if (!result->signatures) { + logmsg(LOG_ERR, _("GPGME: no signatures created")); + return 1; + } + + for (sign = result->signatures; sign; sign = sign->next) { + if (sign->type != type) { + logmsg(LOG_ERR, + _("GPGME: wrong type of signature created")); + return 1; + } + } + /* FIXME: fingerprint? */ + return 0; } - static int -gpg_sign (gpgme_data_t *output, gpgme_data_t input, const char *sign_keys) +gpg_sign(gpgme_data_t * output, gpgme_data_t input, const char *sign_keys) { - gpgme_ctx_t ctx; - gpgme_error_t err = 0; - gpgme_key_t key; - int ret; - - err = gpgme_new (&ctx); - if (err) - { - logmsg (LOG_ERR, _("GPGME: cannot create context: %s"), - gpgme_strerror (err)); - return 1; - } - - err = gpgme_op_keylist_start (ctx, sign_keys, 0); - if (!err) - { - while ((err = gpgme_op_keylist_next (ctx, &key)) == 0) - { - err = gpgme_signers_add (ctx, key); - gpgme_key_release (key); - } - } - - if (err && gpg_err_code (err) != GPG_ERR_EOF) - { - logmsg (LOG_ERR, _("GPGME: cannot list keys: %s"), - gpgme_strerror (err)); - gpgme_release (ctx); - return 1; - } - - err = gpgme_data_new (output); - if (err) - { - logmsg (LOG_ERR, _("%s: GPGME error: %s"), - "gpgme_data_new", - gpgme_strerror (err)); - gpgme_release (ctx); - return 1; - } - - /* FIXME: Passphrase */ - gpgme_set_textmode (ctx, 1); - gpgme_set_armor (ctx, 1); - - err = gpgme_op_sign (ctx, input, *output, GPGME_SIG_MODE_CLEAR); - if (err) - { - logmsg (LOG_ERR, _("%s: GPGME error: %s"), - "gpgme_op_sign", - gpgme_strerror (err)); - ret = 1; - } - else - { - ret = check_sign_result (gpgme_op_sign_result (ctx), - GPGME_SIG_MODE_CLEAR); + gpgme_ctx_t ctx; + gpgme_error_t err = 0; + gpgme_key_t key; + int ret; + + err = gpgme_new(&ctx); + if (err) { + logmsg(LOG_ERR, _("GPGME: cannot create context: %s"), + gpgme_strerror(err)); + return 1; + } + + err = gpgme_op_keylist_start(ctx, sign_keys, 0); + if (!err) { + while ((err = gpgme_op_keylist_next(ctx, &key)) == 0) { + err = gpgme_signers_add(ctx, key); + gpgme_key_release(key); + } + } + + if (err && gpg_err_code(err) != GPG_ERR_EOF) { + logmsg(LOG_ERR, _("GPGME: cannot list keys: %s"), + gpgme_strerror(err)); + gpgme_release(ctx); + return 1; + } + + err = gpgme_data_new(output); + if (err) { + logmsg(LOG_ERR, _("%s: GPGME error: %s"), + "gpgme_data_new", gpgme_strerror(err)); + gpgme_release(ctx); + return 1; + } + + /* FIXME: Passphrase */ + gpgme_set_textmode(ctx, 1); + gpgme_set_armor(ctx, 1); + + err = gpgme_op_sign(ctx, input, *output, GPGME_SIG_MODE_CLEAR); + if (err) { + logmsg(LOG_ERR, _("%s: GPGME error: %s"), + "gpgme_op_sign", gpgme_strerror(err)); + ret = 1; + } else { + ret = check_sign_result(gpgme_op_sign_result(ctx), + GPGME_SIG_MODE_CLEAR); #if 0 - /* FIXME: */ - if (debug_level > 1) - gpgme_debug_info (ctx); + /* FIXME: */ + if (debug_level > 1) + gpgme_debug_info(ctx); #endif - } - - gpgme_release (ctx); - return ret; + } + + gpgme_release(ctx); + return ret; } static int -sign_message (mu_message_t *pmsg, const char *key) +sign_message(mu_message_t * pmsg, const char *key) { - mu_message_t msg = *pmsg; - mu_message_t newmsg; - mu_body_t body; - mu_header_t hdr; - mu_stream_t istr, ostr, bodystr; - int rc; - struct gpgme_data_cbs cbs; - gpgme_data_t input, output; - gpgme_error_t err; - char *buf = NULL; - size_t size = 0; - size_t nread; - - if (debug_level) - logmsg (LOG_DEBUG, _("signing message as %s"), key); - - if (wydawca_gpg_homedir) - { - if (debug_level > 1) - logmsg (LOG_DEBUG, _("setting GNUPG home directory: %s"), - wydawca_gpg_homedir); - setenv ("GNUPGHOME", wydawca_gpg_homedir, 1); - } - - if ((rc = mu_message_get_body (msg, &body))) - { - logmsg (LOG_ERR, "mu_message_get_body: %s", mu_strerror (rc)); - return 1; - } - - if ((rc = mu_body_get_streamref (body, &bodystr))) - { - logmsg (LOG_ERR, "mu_message_get_stream: %s", mu_strerror (rc)); - return 1; - } - - memset (&cbs, 0, sizeof (cbs)); - cbs.read = mu_stream_data_read_cb; - - err = gpgme_data_new_from_cbs (&input, &cbs, &bodystr); - if (err) - { - logmsg (LOG_ERR, "gpgme_data_new_from_cbs: %s", - gpgme_strerror (rc)); - return 1; - } - - rc = gpg_sign (&output, input, key); - mu_stream_unref (bodystr); - if (rc) - return 1; - - if (gpgme_data_seek (output, 0, SEEK_SET) == -1) - { - logmsg (LOG_ERR, "gpgme_data_seek: %s", strerror (errno)); - return 1; - } - - mu_message_create (&newmsg, NULL); - mu_message_get_streamref (newmsg, &ostr); - - /* Copy headers */ - mu_message_get_header (msg, &hdr); - mu_header_get_streamref (hdr, &istr); - - rc = mu_stream_copy (ostr, istr, 0, NULL); - if (rc) - logmsg (LOG_ERR, "mu_stream_copy: %s", mu_strerror (rc)); - else - { - while ((nread = gpgme_data_read (output, buf, size)) > 0) - { - rc = mu_stream_write (ostr, buf, nread, NULL); - if (rc) - { - logmsg (LOG_ERR, "mu_stream_write: %s", mu_strerror (rc)); - break; - } - } - - if (rc == 0) - { - mu_message_destroy (&msg, mu_message_get_owner (msg)); - *pmsg = newmsg; - } - } - mu_stream_unref (istr); - mu_stream_unref (ostr); - - if (rc) - mu_message_destroy (&newmsg, mu_message_get_owner (msg)); - gpgme_data_release (output); - free (buf); - - return rc; + mu_message_t msg = *pmsg; + mu_message_t newmsg; + mu_body_t body; + mu_header_t hdr; + mu_stream_t istr, ostr, bodystr; + int rc; + struct gpgme_data_cbs cbs; + gpgme_data_t input, output; + gpgme_error_t err; + char *buf = NULL; + size_t size = 0; + size_t nread; + + if (debug_level) + logmsg(LOG_DEBUG, _("signing message as %s"), key); + + if (wydawca_gpg_homedir) { + if (debug_level > 1) + logmsg(LOG_DEBUG, + _("setting GNUPG home directory: %s"), + wydawca_gpg_homedir); + setenv("GNUPGHOME", wydawca_gpg_homedir, 1); + } + + if ((rc = mu_message_get_body(msg, &body))) { + logmsg(LOG_ERR, "mu_message_get_body: %s", mu_strerror(rc)); + return 1; + } + + if ((rc = mu_body_get_streamref(body, &bodystr))) { + logmsg(LOG_ERR, "mu_message_get_stream: %s", mu_strerror(rc)); + return 1; + } + + memset(&cbs, 0, sizeof(cbs)); + cbs.read = mu_stream_data_read_cb; + + err = gpgme_data_new_from_cbs(&input, &cbs, &bodystr); + if (err) { + logmsg(LOG_ERR, "gpgme_data_new_from_cbs: %s", + gpgme_strerror(rc)); + return 1; + } + + rc = gpg_sign(&output, input, key); + mu_stream_unref(bodystr); + if (rc) + return 1; + + if (gpgme_data_seek(output, 0, SEEK_SET) == -1) { + logmsg(LOG_ERR, "gpgme_data_seek: %s", strerror(errno)); + return 1; + } + + mu_message_create(&newmsg, NULL); + mu_message_get_streamref(newmsg, &ostr); + + /* Copy headers */ + mu_message_get_header(msg, &hdr); + mu_header_get_streamref(hdr, &istr); + + rc = mu_stream_copy(ostr, istr, 0, NULL); + if (rc) + logmsg(LOG_ERR, "mu_stream_copy: %s", mu_strerror(rc)); + else { + while ((nread = gpgme_data_read(output, buf, size)) > 0) { + rc = mu_stream_write(ostr, buf, nread, NULL); + if (rc) { + logmsg(LOG_ERR, "mu_stream_write: %s", + mu_strerror(rc)); + break; + } + } + + if (rc == 0) { + mu_message_destroy(&msg, mu_message_get_owner(msg)); + *pmsg = newmsg; + } + } + mu_stream_unref(istr); + mu_stream_unref(ostr); + + if (rc) + mu_message_destroy(&newmsg, mu_message_get_owner(msg)); + gpgme_data_release(output); + free(buf); + + return rc; } void -mail_send_message (mu_address_t rcpt, const char *text, - const char *signer_key) +mail_send_message(mu_address_t rcpt, const char *text, const char *signer_key) { - int rc; - mu_message_t msg; - mu_stream_t stream = NULL; - mu_header_t hdr; - static char *x_mailer = "wydawca (" PACKAGE_STRING ")"; - const char *sval; - - mu_static_memory_stream_create (&stream, text, strlen (text)); - rc = mu_stream_to_message (stream, &msg); - mu_stream_unref (stream); - if (rc) - { - logmsg (LOG_CRIT, _("cannot create message: %s"), mu_strerror (rc)); - return; - } - mu_message_get_header (msg, &hdr); - mu_header_append (hdr, "X-Mailer", x_mailer); - - if (rcpt) - { - const char *s; - - if (mu_address_sget_printable (rcpt, &s) == 0) - mu_header_set_value (hdr, "To", s, 1); - - if (from_address && mu_header_sget_value (hdr, "From", &sval)) - { - if (mu_address_sget_printable (from_address, &s) == 0) - mu_header_set_value (hdr, "From", s, 1); - } - } - - if (debug_level > 1) - { - mu_debug_level_t level; - - mu_debug_get_category_level (MU_DEBCAT_MAILER, &level); - level |= MU_DEBUG_LEVEL_MASK (MU_DEBUG_TRACE0) | - MU_DEBUG_LEVEL_MASK (MU_DEBUG_PROT); - if (debug_level > 2) - level |= MU_DEBUG_LEVEL_MASK (MU_DEBUG_TRACE7); - mu_debug_set_category_level (MU_DEBCAT_MAILER, level); - } - - if (!mailer_opened) - { - if ((rc = mu_mailer_open (mailer, 0))) - { - mu_url_t url = NULL; - mu_mailer_get_url (mailer, &url); - logmsg (LOG_CRIT, _("opening mailer `%s' failed: %s"), - url ? mu_url_to_string (url) : "(unknown URL)", - mu_strerror (rc)); - return; - } - mailer_opened = 1; - } - - if (signer_key) - sign_message (&msg, signer_key); - - if (!dry_run_mode) - { - rc = mu_mailer_send_message (mailer, msg, from_address, rcpt); - if (rc) - logmsg (LOG_CRIT, _("cannot send message: %s"), mu_strerror (rc)); - } - - mu_message_destroy (&msg, mu_message_get_owner (msg)); + int rc; + mu_message_t msg; + mu_stream_t stream = NULL; + mu_header_t hdr; + static char *x_mailer = "wydawca (" PACKAGE_STRING ")"; + const char *sval; + + mu_static_memory_stream_create(&stream, text, strlen(text)); + rc = mu_stream_to_message(stream, &msg); + mu_stream_unref(stream); + if (rc) { + logmsg(LOG_CRIT, _("cannot create message: %s"), + mu_strerror(rc)); + return; + } + mu_message_get_header(msg, &hdr); + mu_header_append(hdr, "X-Mailer", x_mailer); + + if (rcpt) { + const char *s; + + if (mu_address_sget_printable(rcpt, &s) == 0) + mu_header_set_value(hdr, "To", s, 1); + + if (from_address && mu_header_sget_value(hdr, "From", &sval)) { + if (mu_address_sget_printable(from_address, &s) == 0) + mu_header_set_value(hdr, "From", s, 1); + } + } + + if (debug_level > 1) { + mu_debug_level_t level; + + mu_debug_get_category_level(MU_DEBCAT_MAILER, &level); + level |= MU_DEBUG_LEVEL_MASK(MU_DEBUG_TRACE0) | + MU_DEBUG_LEVEL_MASK(MU_DEBUG_PROT); + if (debug_level > 2) + level |= MU_DEBUG_LEVEL_MASK(MU_DEBUG_TRACE7); + mu_debug_set_category_level(MU_DEBCAT_MAILER, level); + } + + if (!mailer_opened) { + if ((rc = mu_mailer_open(mailer, 0))) { + mu_url_t url = NULL; + mu_mailer_get_url(mailer, &url); + logmsg(LOG_CRIT, _("opening mailer `%s' failed: %s"), + url ? mu_url_to_string(url) : "(unknown URL)", + mu_strerror(rc)); + return; + } + mailer_opened = 1; + } + + if (signer_key) + sign_message(&msg, signer_key); + + if (!dry_run_mode) { + rc = mu_mailer_send_message(mailer, msg, from_address, rcpt); + if (rc) + logmsg(LOG_CRIT, _("cannot send message: %s"), + mu_strerror(rc)); + } + + mu_message_destroy(&msg, mu_message_get_owner(msg)); } void -mail_finish () +mail_finish() { - if (mailer_opened) - { - mu_mailer_close (mailer); - mailer_opened = 0; - } + if (mailer_opened) { + mu_mailer_close(mailer); + mailer_opened = 0; + } } - -struct message_template -{ - char *name; - char *text; - /* int mime; for future use */ +struct message_template { + char *name; + char *text; + /* int mime; for future use */ }; static struct grecs_symtab *tmpl_table; /* Register a template. */ void -register_message_template (const char *name, const char *text) +register_message_template(const char *name, const char *text) { - struct message_template key, *tmpl; - int install = 1; - - key.name = (char*) text; - - if (!tmpl_table) - { - tmpl_table = grecs_symtab_create_default (sizeof (key)); - if (!tmpl_table) - grecs_alloc_die (); - } - - tmpl = grecs_symtab_lookup_or_install (tmpl_table, &key, &install); - if (!tmpl) - grecs_alloc_die(); - if (!install) - grecs_warning (NULL, 0, "template %s already registered", text); + struct message_template key, *tmpl; + int install = 1; + + key.name = (char *)text; + + if (!tmpl_table) { + tmpl_table = grecs_symtab_create_default(sizeof(key)); + if (!tmpl_table) + grecs_alloc_die(); + } + + tmpl = grecs_symtab_lookup_or_install(tmpl_table, &key, &install); + if (!tmpl) + grecs_alloc_die(); + if (!install) + grecs_warning(NULL, 0, "template %s already registered", text); } const char * -resolve_message_template (const char *name) +resolve_message_template(const char *name) { - if (name[0] == '@') - { - if (name[1] == '@') - return name + 1; - else if (!tmpl_table) - return NULL; - else - { - struct message_template *p, key; - - key.name = (char*) name + 1; - p = grecs_symtab_lookup_or_install (tmpl_table, &key, NULL); - return p ? p->text : NULL; - } - } - return name; + if (name[0] == '@') { + if (name[1] == '@') + return name + 1; + else if (!tmpl_table) + return NULL; + else { + struct message_template *p, key; + + key.name = (char *)name + 1; + p = grecs_symtab_lookup_or_install(tmpl_table, &key, + NULL); + return p ? p->text : NULL; + } + } + return name; } - void -mail_stats () +mail_stats() { - struct metadef *exp; - time_t t; - const char *tmpl; - char *text; - size_t tc; - - if (!admin_stat_message || !stat_mask_p (mail_admin_mask) || !mailer) - return; - - if (!admin_address) - { - logmsg (LOG_ERR, _("cannot mail statistics: admin-address not defined")); - return; - } - - if (debug_level) - { - const char *s; - - if (mu_address_sget_printable (admin_address, &s) == 0) - logmsg (LOG_DEBUG, _("sending stats to %s"), s); - } - - tc = timer_get_count () * 3; - exp = make_stat_expansion (tc + 1); - time (&t); - exp[0].kw = "date"; - exp[0].value = exp[0].storage = grecs_strdup (ctime (&t)); - exp[0].value [strlen (exp[0].value) - 1] = 0; - timer_fill_meta (exp + 1, tc); - - tmpl = resolve_message_template (admin_stat_message); - if (!tmpl) - { - logmsg (LOG_ERR, _("undefined message reference: %s"), - admin_stat_message); - return; - } - text = meta_expand_string (tmpl, exp, NULL, NULL, NULL); - - mail_send_message (admin_address, text, admin_stat_sign_key); - - free (text); - meta_free (exp); - timer_free_meta (exp + 1, tc); - free (exp); + struct metadef *exp; + time_t t; + const char *tmpl; + char *text; + size_t tc; + + if (!admin_stat_message || !stat_mask_p(mail_admin_mask) || !mailer) + return; + + if (!admin_address) { + logmsg(LOG_ERR, + _("cannot mail statistics: admin-address not defined")); + return; + } + + if (debug_level) { + const char *s; + + if (mu_address_sget_printable(admin_address, &s) == 0) + logmsg(LOG_DEBUG, _("sending stats to %s"), s); + } + + tc = timer_get_count() * 3; + exp = make_stat_expansion(tc + 1); + time(&t); + exp[0].kw = "date"; + exp[0].value = exp[0].storage = grecs_strdup(ctime(&t)); + exp[0].value[strlen(exp[0].value) - 1] = 0; + timer_fill_meta(exp + 1, tc); + + tmpl = resolve_message_template(admin_stat_message); + if (!tmpl) { + logmsg(LOG_ERR, _("undefined message reference: %s"), + admin_stat_message); + return; + } + text = meta_expand_string(tmpl, exp, NULL, NULL, NULL); + + mail_send_message(admin_address, text, admin_stat_sign_key); + + free(text); + meta_free(exp); + timer_free_meta(exp + 1, tc); + free(exp); } mu_address_t -get_uploader_email (struct uploader_info *info, struct file_triplet *trp, - const char **errp) +get_uploader_email(struct uploader_info * info, struct file_triplet * trp, + const char **errp) { - mu_address_t addr; - mu_address_t rcpt = NULL; - int rc; - - if (!info) - return NULL; - rc = mu_address_create (&addr, info->email); - if (rc) - { - *errp = mu_strerror (rc); - return NULL; - } - - mu_address_set_personal (addr, 1, info->realname); - - /* This hack makes sure that mu_address_to_string (rcpt) will - return full email address (with personal part) */ - mu_address_union (&rcpt, addr); - mu_address_destroy (&addr); - - return rcpt; + mu_address_t addr; + mu_address_t rcpt = NULL; + int rc; + + if (!info) + return NULL; + rc = mu_address_create(&addr, info->email); + if (rc) { + *errp = mu_strerror(rc); + return NULL; + } + + mu_address_set_personal(addr, 1, info->realname); + + /* This hack makes sure that mu_address_to_string (rcpt) will + return full email address (with personal part) */ + mu_address_union(&rcpt, addr); + mu_address_destroy(&addr); + + return rcpt; } mu_address_t -get_recipient (struct dictionary *dict, struct file_triplet *trp, - const char **errp) +get_recipient(struct dictionary * dict, struct file_triplet * trp, + const char **errp) { - unsigned nrows, ncols, i; - mu_address_t rcpt = NULL; - char *text; - int rc; - void *md; - - if (dict->type == dictionary_none) - { - *errp = N_("dictionary is not configured"); - return NULL; - } - - md = dictionary_open (dict); - if (!md) - { - *errp = N_("failed to open dictionary"); - return NULL; - } - - text = triplet_expand_dictionary_query (dict, md, trp); - - rc = dictionary_lookup (dict, md, text); - free (text); - if (rc) - { - *errp = N_("cannot obtain recipient emails"); - dictionary_close (dict, md); - return NULL; - } - - nrows = dictionary_num_rows (dict); - ncols = dictionary_num_cols (dict); - - if (nrows == 0) - { - *errp = N_("cannot obtain recipient emails"); - return NULL; - } - - for (i = 0; i < nrows; i++) - { - mu_address_t addr; - const char *str = dictionary_result (dict, md, i, 0); - if (mu_address_create (&addr, str)) - continue; - if (ncols > 0) - { - str = dictionary_result (dict, md, i, 1); - if (str) - mu_address_set_personal (addr, 1, str); - } - mu_address_union (&rcpt, addr); - mu_address_destroy (&addr); - } - dictionary_close (dict, md); - - return rcpt; + unsigned nrows, ncols, i; + mu_address_t rcpt = NULL; + char *text; + int rc; + void *md; + + if (dict->type == dictionary_none) { + *errp = N_("dictionary is not configured"); + return NULL; + } + + md = dictionary_open(dict); + if (!md) { + *errp = N_("failed to open dictionary"); + return NULL; + } + + text = triplet_expand_dictionary_query(dict, md, trp); + + rc = dictionary_lookup(dict, md, text); + free(text); + if (rc) { + *errp = N_("cannot obtain recipient emails"); + dictionary_close(dict, md); + return NULL; + } + + nrows = dictionary_num_rows(dict); + ncols = dictionary_num_cols(dict); + + if (nrows == 0) { + *errp = N_("cannot obtain recipient emails"); + return NULL; + } + + for (i = 0; i < nrows; i++) { + mu_address_t addr; + const char *str = dictionary_result(dict, md, i, 0); + if (mu_address_create(&addr, str)) + continue; + if (ncols > 0) { + str = dictionary_result(dict, md, i, 1); + if (str) + mu_address_set_personal(addr, 1, str); + } + mu_address_union(&rcpt, addr); + mu_address_destroy(&addr); + } + dictionary_close(dict, md); + + return rcpt; } void -do_notify (struct file_triplet *trp, enum notification_event ev, - struct notification *ntf) +do_notify(struct file_triplet *trp, enum notification_event ev, + struct notification *ntf) { - mu_address_t rcpt = NULL; - const char *errp; - const char *msg; - - switch (ntf->tgt) - { - case notify_read: - rcpt = NULL; - break; - - case notify_admin: - rcpt = mu_address_dup (admin_address); - break; - - case notify_user: - rcpt = get_uploader_email (trp->uploader, trp, &errp); - break; - - case notify_owner: - rcpt = get_recipient (trp->spool->dictionary[project_owner_dict], - trp, &errp); - } - - if (!rcpt && ntf->tgt != notify_read) - { - logmsg (LOG_ERR, _("not notifying %s (project %s) about %s: %s"), - notification_target_str (ntf->tgt), - trp->project, - notification_event_str (ev), gettext (errp)); - return; - } - - if (debug_level) - { - if (rcpt) - { - const char *s; - - if (mu_address_sget_printable (rcpt, &s) == 0) - logmsg (LOG_DEBUG, _("notifying %s (project %s) about %s"), - s, trp->project, notification_event_str (ev)); - } - else - logmsg (LOG_DEBUG, - _("notifying message recipients (project %s) about %s"), - trp->project, notification_event_str (ev)); - } - - msg = resolve_message_template (ntf->msg); - if (!msg) - logmsg (LOG_ERR, _("undefined message reference: %s"), ntf->msg); - else - { - char *text = triplet_expand_param (msg, trp); - mail_send_message (rcpt, text, ntf->sign_keys); - free (text); - } - - mu_address_destroy (&rcpt); + mu_address_t rcpt = NULL; + const char *errp; + const char *msg; + + switch (ntf->tgt) { + case notify_read: + rcpt = NULL; + break; + + case notify_admin: + rcpt = mu_address_dup(admin_address); + break; + + case notify_user: + rcpt = get_uploader_email(trp->uploader, trp, &errp); + break; + + case notify_owner: + rcpt = get_recipient(trp->spool->dictionary[project_owner_dict], + trp, &errp); + } + + if (!rcpt && ntf->tgt != notify_read) { + logmsg(LOG_ERR, + _("not notifying %s (project %s) about %s: %s"), + notification_target_str(ntf->tgt), + trp->project, notification_event_str(ev), + gettext(errp)); + return; + } + + if (debug_level) { + if (rcpt) { + const char *s; + + if (mu_address_sget_printable(rcpt, &s) == 0) + logmsg(LOG_DEBUG, + _("notifying %s (project %s) about %s"), + s, trp->project, + notification_event_str(ev)); + } else + logmsg(LOG_DEBUG, + _("notifying message recipients (project %s) " + "about %s"), + trp->project, notification_event_str(ev)); + } + + msg = resolve_message_template(ntf->msg); + if (!msg) + logmsg(LOG_ERR, _("undefined message reference: %s"), + ntf->msg); + else { + char *text = triplet_expand_param(msg, trp); + mail_send_message(rcpt, text, ntf->sign_keys); + free(text); + } + + mu_address_destroy(&rcpt); } void -notify (struct notification *notification_list, - struct file_triplet *trp, enum notification_event ev) +notify(struct notification *notification_list, + struct file_triplet *trp, enum notification_event ev) { - struct notification *p; + struct notification *p; - for (p = notification_list; p; p = p->next) - if (p->ev == ev) - do_notify (trp, ev, p); - /* FIXME */ + for (p = notification_list; p; p = p->next) + if (p->ev == ev) + do_notify(trp, ev, p); + /* FIXME */ } const char * -expand_email_admin (struct metadef *def, void *data) +expand_email_admin(struct metadef *def, void *data) { - if (mu_address_aget_printable (admin_address, &def->storage) == 0) - def->value = def->storage; - else - def->value = ""; - return def->value; + if (mu_address_aget_printable(admin_address, &def->storage) == 0) + def->value = def->storage; + else + def->value = ""; + return def->value; } const char * -expand_email_owner (struct metadef *def, void *data) +expand_email_owner(struct metadef *def, void *data) { - struct file_triplet *trp = data; - mu_address_t addr; - const char *errp; - - addr = get_recipient (trp->spool->dictionary[project_owner_dict], - trp, &errp); - if (!addr) - { - logmsg (LOG_ERR, _("cannot get email of the %s's owner: %s"), - trp->project, gettext (errp)); - def->value = ""; - } - else - { - if (mu_address_aget_printable (addr, &def->storage) == 0) - def->value = def->storage; - else - def->value = ""; - mu_address_destroy (&addr); - } - return def->value; + struct file_triplet *trp = data; + mu_address_t addr; + const char *errp; + + addr = get_recipient(trp->spool->dictionary[project_owner_dict], + trp, &errp); + if (!addr) { + logmsg(LOG_ERR, _("cannot get email of the %s's owner: %s"), + trp->project, gettext(errp)); + def->value = ""; + } else { + if (mu_address_aget_printable(addr, &def->storage) == 0) + def->value = def->storage; + else + def->value = ""; + mu_address_destroy(&addr); + } + return def->value; } - @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007, 2010-2011 Sergey Poznyakoff + Copyright (C) 2007, 2010-2013 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -22,7 +22,6 @@ extern mu_address_t from_address; extern unsigned long mail_admin_mask; extern struct message_template *admin_stat_message_template; -void mail_init (void); -void mail_finish (void); -void mail_stats (void); - +void mail_init(void); +void mail_finish(void); +void mail_stats(void); @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007-2011 Sergey Poznyakoff + Copyright (C) 2007-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -18,136 +18,129 @@ #include "sql.h" static const char * -meta_expand (struct metadef *def, void *data) +meta_expand(struct metadef *def, void *data) { - if (!def->value) - { - if (def->expand) - return def->expand (def, data); - def->value = "INTERNAL ERROR: NONEXPANDABLE DATA"; - } - return def->value; + if (!def->value) { + if (def->expand) + return def->expand(def, data); + def->value = "INTERNAL ERROR: NONEXPANDABLE DATA"; + } + return def->value; } static const char * -find_expansion_char (int c, struct metadef *def, void *data) +find_expansion_char(int c, struct metadef *def, void *data) { - for (; def->kw; def++) - if (def->kw[1] == 0 && def->kw[0] == c) - return meta_expand (def, data); - return NULL; + for (; def->kw; def++) + if (def->kw[1] == 0 && def->kw[0] == c) + return meta_expand(def, data); + return NULL; } static const char * -find_expansion_word (const char *kw, size_t len, - struct metadef *def, void *data) +find_expansion_word(const char *kw, size_t len, struct metadef *def, + void *data) { - for (; def->kw; def++) - if (strlen (def->kw) == len && memcmp (def->kw, kw, len) == 0) - return meta_expand (def, data); - return NULL; + for (; def->kw; def++) + if (strlen(def->kw) == len && memcmp(def->kw, kw, len) == 0) + return meta_expand(def, data); + return NULL; } char * -meta_expand_string (const char *string, struct metadef *def, void *data, - struct dictionary *dict, void *handle) +meta_expand_string(const char *string, struct metadef *def, void *data, + struct dictionary *dict, void *handle) { - const char *p, *s; - char *res; - struct txtacc *acc; - - if (!string) - return NULL; - - acc = txtacc_create (); - - for (p = string; *p;) - { - char *e; - size_t len = strcspn (p, "$"); - - txtacc_grow (acc, p, len); - p += len; - if (*p == '$') - { - switch (*++p) - { - case '$': - txtacc_grow (acc, p, 1); - p++; - break; - - case '-': - if (*++p) - p++; - break; - - case '{': - e = strchr (p + 1, '}'); - if (e && (s = find_expansion_word (p + 1, e - p - 1, def, data))) - { - if (dict) - { - char *newval; - size_t len; - /* FIXME: Return value? */ - dictionary_quote_string (dict, handle, s, &newval, &len); - txtacc_grow (acc, newval, len); - free (newval); - } - else - txtacc_grow (acc, s, strlen (s)); - p = e + 1; - } - else - { - txtacc_grow (acc, p - 1, 2); - p++; - } - break; - - default: - if ((s = find_expansion_char (*p, def, data)) != NULL) - len = strlen (s); - else - { - s = p - 1; - len = 1; - } - - if (dict) - { - char *newval; - size_t len; - /* FIXME: Return value? */ - dictionary_quote_string (dict, handle, s, &newval, &len); - txtacc_grow (acc, newval, len); - free (newval); - } - else - txtacc_grow (acc, s, len); - p++; - } + const char *p, *s; + char *res; + struct txtacc *acc; + + if (!string) + return NULL; + + acc = txtacc_create(); + + for (p = string; *p;) { + char *e; + size_t len = strcspn(p, "$"); + + txtacc_grow(acc, p, len); + p += len; + if (*p == '$') { + switch (*++p) { + case '$': + txtacc_grow(acc, p, 1); + p++; + break; + + case '-': + if (*++p) + p++; + break; + + case '{': + e = strchr(p + 1, '}'); + if (e && + (s = find_expansion_word(p + 1, e - p - 1, + def, data))) { + if (dict) { + char *newval; + size_t len; + /* FIXME: Return value? */ + dictionary_quote_string(dict, + handle, + s, + &newval, + &len); + txtacc_grow(acc, newval, len); + free(newval); + } else + txtacc_grow(acc, s, strlen(s)); + p = e + 1; + } else { + txtacc_grow(acc, p - 1, 2); + p++; + } + break; + + default: + if ((s = find_expansion_char(*p, def, data)) + != NULL) + len = strlen(s); + else { + s = p - 1; + len = 1; + } + + if (dict) { + char *newval; + size_t len; + /* FIXME: Return value? */ + dictionary_quote_string(dict, + handle, s, + &newval, &len); + txtacc_grow(acc, newval, len); + free(newval); + } else + txtacc_grow(acc, s, len); + p++; + } + } else + txtacc_grow(acc, p, 1); } - else - txtacc_grow (acc, p, 1); - } - txtacc_1grow (acc, 0); - res = txtacc_finish (acc, 1); - txtacc_free (acc); - return res; + txtacc_1grow(acc, 0); + res = txtacc_finish(acc, 1); + txtacc_free(acc); + return res; } void -meta_free (struct metadef *def) +meta_free(struct metadef *def) { - for (; def->kw; def++) - { - if (def->storage) - { - free (def->storage); - def->value = def->storage = NULL; + for (; def->kw; def++) { + if (def->storage) { + free(def->storage); + def->value = def->storage = NULL; + } } - } } - @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007, 2009-2011 Sergey Poznyakoff + Copyright (C) 2007, 2009-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -17,254 +17,231 @@ #include "wydawca.h" static int -open_listener () +open_listener() { - int fd; - - if (listen_sockaddr.sa == NULL) - return -1; - - fd = socket (listen_sockaddr.sa->sa_family, SOCK_STREAM, 0); - if (fd == -1) - { - logmsg (LOG_CRIT, _("cannot create socket: %s"), - strerror(errno)); - exit (EX_OSERR); - } - if (listen_sockaddr.sa->sa_family == AF_UNIX) - { - struct stat st; - struct sockaddr_un *s_un = (struct sockaddr_un *) listen_sockaddr.sa; - if (stat (s_un->sun_path, &st)) - { - if (errno != ENOENT) - { - logmsg (LOG_CRIT, _("%s: cannot stat socket: %s"), - s_un->sun_path, strerror (errno)); - exit (errno == EACCES ? EX_NOPERM : EX_OSERR); - } + int fd; + + if (listen_sockaddr.sa == NULL) + return -1; + + fd = socket(listen_sockaddr.sa->sa_family, SOCK_STREAM, 0); + if (fd == -1) { + logmsg(LOG_CRIT, _("cannot create socket: %s"), + strerror(errno)); + exit(EX_OSERR); } - else - { - /* FIXME: Check permissions? */ - if (!S_ISSOCK (st.st_mode)) - { - logmsg (LOG_CRIT, _("%s: not a socket"), s_un->sun_path); - exit (EX_OSFILE); - } - unlink (s_un->sun_path); + if (listen_sockaddr.sa->sa_family == AF_UNIX) { + struct stat st; + struct sockaddr_un *s_un = + (struct sockaddr_un *)listen_sockaddr.sa; + if (stat(s_un->sun_path, &st)) { + if (errno != ENOENT) { + logmsg(LOG_CRIT, + _("%s: cannot stat socket: %s"), + s_un->sun_path, strerror(errno)); + exit(errno == EACCES ? EX_NOPERM : EX_OSERR); + } + } else { + /* FIXME: Check permissions? */ + if (!S_ISSOCK(st.st_mode)) { + logmsg(LOG_CRIT, _("%s: not a socket"), + s_un->sun_path); + exit(EX_OSFILE); + } + unlink(s_un->sun_path); + } + /* FIXME: Setup umask */ + } else { + int yes = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, + sizeof(yes)); + } + + if (bind(fd, listen_sockaddr.sa, listen_sockaddr.len) < 0) { + logmsg(LOG_CRIT, _("cannot bind to local address: %s"), + strerror(errno)); + close(fd); + exit(EX_OSERR); } - /* FIXME: Setup umask */ - } - else - { - int yes = 1; - setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (void *) &yes, sizeof(yes)); - } - - if (bind (fd, listen_sockaddr.sa, listen_sockaddr.len) < 0) - { - logmsg (LOG_CRIT, _("cannot bind to local address: %s"), - strerror (errno)); - close (fd); - exit (EX_OSERR); - } - if (listen (fd, 8) == -1) - { - logmsg (LOG_CRIT, "listen: %s", strerror (errno)); - close (fd); - exit (EX_OSERR); - } - - return fd; + if (listen(fd, 8) == -1) { + logmsg(LOG_CRIT, "listen: %s", strerror(errno)); + close(fd); + exit(EX_OSERR); + } + + return fd; } void -trim_crlf (char *s) +trim_crlf(char *s) { - size_t len = strlen (s); - if (len > 0 && s[len-1] == '\n') - { - s[--len] = 0; - if (len > 0 && s[len-1] == '\r') - s[--len] = 0; - } + size_t len = strlen(s); + if (len > 0 && s[len - 1] == '\n') { + s[--len] = 0; + if (len > 0 && s[len - 1] == '\r') + s[--len] = 0; + } } void -handle_connection (FILE *in, FILE *out) +handle_connection(FILE * in, FILE * out) { - char *buf = NULL; - size_t buflen = 0; - struct spool *spool; - char *p; - struct passwd *pw; - - if (grecs_getline (&buf, &buflen, in) <= 0) - return; - trim_crlf (buf); - if (debug_level) - logmsg (LOG_DEBUG, "recv: %s", buf); - spool = wydawca_find_spool (buf); - if (!spool) - { - if (all_spool_aliases && grecs_list_locate (all_spool_aliases, buf)) - fprintf (out, "+ OK, all spools\r\n"); - else - { - fprintf (out, "- Unknown service name\r\n"); - free (buf); - return; + char *buf = NULL; + size_t buflen = 0; + struct spool *spool; + char *p; + struct passwd *pw; + + if (grecs_getline(&buf, &buflen, in) <= 0) + return; + trim_crlf(buf); + if (debug_level) + logmsg(LOG_DEBUG, "recv: %s", buf); + spool = wydawca_find_spool(buf); + if (!spool) { + if (all_spool_aliases + && grecs_list_locate(all_spool_aliases, buf)) + fprintf(out, "+ OK, all spools\r\n"); + else { + fprintf(out, "- Unknown service name\r\n"); + free(buf); + return; + } + } else if (spool->url) + fprintf(out, "+ OK, URL %s\r\n", spool->url); + else + fprintf(out, "+ OK, spool %s\r\n", spool->tag); + + if (grecs_getline(&buf, &buflen, in) < 0) { + logmsg(LOG_ERR, "protocol error"); + free(buf); + return; } - } - else if (spool->url) - fprintf (out, "+ OK, URL %s\r\n", spool->url); - else - fprintf (out, "+ OK, spool %s\r\n", spool->tag); - - if (grecs_getline (&buf, &buflen, in) < 0) - { - logmsg (LOG_ERR, "protocol error"); - free (buf); - return; - } - - trim_crlf (buf); - if (debug_level) - logmsg (LOG_DEBUG, "recv: %s", buf); - - p = strchr (buf, ' '); - if (p) - { - *p++ = 0; - while (*p && (*p == ' ' || *p == '\t')) - p++; - } - else - p = ""; - - pw = getpwnam (buf); - if (pw) - schedule_job (spool, pw->pw_uid); - else - logmsg (LOG_ERR, "no such user: %s", buf); - free (buf); + + trim_crlf(buf); + if (debug_level) + logmsg(LOG_DEBUG, "recv: %s", buf); + + p = strchr(buf, ' '); + if (p) { + *p++ = 0; + while (*p && (*p == ' ' || *p == '\t')) + p++; + } else + p = ""; + + pw = getpwnam(buf); + if (pw) + schedule_job(spool, pw->pw_uid); + else + logmsg(LOG_ERR, "no such user: %s", buf); + free(buf); } int reconfigure; static int terminate; RETSIGTYPE -sig_hup (int sig) +sig_hup(int sig) { - reconfigure = 1; - terminate = 1; + reconfigure = 1; + terminate = 1; } RETSIGTYPE -sig_term (int sig) +sig_term(int sig) { - terminate = 1; + terminate = 1; } void -wydawca_listener () +wydawca_listener() { - int ctlfd = open_listener (); - int wfd = watcher_init (); - int maxfd = 0; - - if (ctlfd != -1) - maxfd = ctlfd; - - if (wfd != -1 && wfd > maxfd) - maxfd = wfd; - - if (maxfd == 0) - { - logmsg (LOG_CRIT, - _("listener address is not configured and inotify is not available")); - exit (EX_CONFIG); - } - - job_init (); - signal (SIGHUP, sig_hup); - signal (SIGTERM, sig_term); - signal (SIGQUIT, sig_term); - signal (SIGINT, sig_term); - while (!terminate) - { - int rc; - fd_set rset; - struct timeval to, *pto; - - job_queue_runner (triplet_sweep ()); - - FD_ZERO (&rset); - if (ctlfd != -1) - FD_SET (ctlfd, &rset); - if (wfd != -1) - FD_SET (wfd, &rset); - - if (wakeup_interval) - { - to.tv_sec = wakeup_interval; - to.tv_usec = 0; - *pto = to; - } - else - pto = NULL; - - rc = select (maxfd + 1, &rset, NULL, NULL, pto); - if (rc == 0) - continue; - else if (rc < 0) - { - if (errno == EINTR) - continue; - logmsg (LOG_ERR, "select: %s", strerror (errno)); - break; - } + int ctlfd = open_listener(); + int wfd = watcher_init(); + int maxfd = 0; + + if (ctlfd != -1) + maxfd = ctlfd; - if (wfd != -1 && FD_ISSET (wfd, &rset)) - { - watcher_run (wfd); + if (wfd != -1 && wfd > maxfd) + maxfd = wfd; + + if (maxfd == 0) { + logmsg(LOG_CRIT, + _("listener address is not configured and inotify " + "is not available")); + exit(EX_CONFIG); } - - if (ctlfd != -1 && FD_ISSET (ctlfd, &rset)) - { - int fd; - FILE *in, *out; - union - { - struct sockaddr sa; - struct sockaddr_in s_in; - struct sockaddr_un s_un; - } addr; - socklen_t len; - - len = sizeof (addr); - fd = accept (ctlfd, (struct sockaddr*) &addr, &len); - if (fd == -1) - continue; - /* FIXME: Use Mailutils ACLs? */ + + job_init(); + signal(SIGHUP, sig_hup); + signal(SIGTERM, sig_term); + signal(SIGQUIT, sig_term); + signal(SIGINT, sig_term); + while (!terminate) { + int rc; + fd_set rset; + struct timeval to, *pto; + + job_queue_runner(triplet_sweep()); + + FD_ZERO(&rset); + if (ctlfd != -1) + FD_SET(ctlfd, &rset); + if (wfd != -1) + FD_SET(wfd, &rset); + + if (wakeup_interval) { + to.tv_sec = wakeup_interval; + to.tv_usec = 0; + *pto = to; + } else + pto = NULL; + + rc = select(maxfd + 1, &rset, NULL, NULL, pto); + if (rc == 0) + continue; + else if (rc < 0) { + if (errno == EINTR) + continue; + logmsg(LOG_ERR, "select: %s", strerror(errno)); + break; + } + + if (wfd != -1 && FD_ISSET(wfd, &rset)) { + watcher_run(wfd); + } + + if (ctlfd != -1 && FD_ISSET(ctlfd, &rset)) { + int fd; + FILE *in, *out; + union { + struct sockaddr sa; + struct sockaddr_in s_in; + struct sockaddr_un s_un; + } addr; + socklen_t len; + + len = sizeof(addr); + fd = accept(ctlfd, (struct sockaddr *)&addr, &len); + if (fd == -1) + continue; + /* FIXME: Use Mailutils ACLs? */ #ifdef WITH_LIBWRAP - if (!tcpwrap_access(fd)) - { - close(fd); - continue; - } + if (!tcpwrap_access(fd)) { + close(fd); + continue; + } #endif - - in = fdopen (fd, "r"); - setlinebuf (in); - out = fdopen (fd, "w"); - setlinebuf (out); - handle_connection (in, out); - fclose (in); - fclose (out); + + in = fdopen(fd, "r"); + setlinebuf(in); + out = fdopen(fd, "w"); + setlinebuf(out); + handle_connection(in, out); + fclose(in); + fclose(out); + } } - } } - - @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2009-2011 Sergey Poznyakoff + Copyright (C) 2009-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -17,51 +17,49 @@ #include "wydawca.h" int -null_move_file (struct file_triplet *trp, enum file_type file_id) +null_move_file(struct file_triplet *trp, enum file_type file_id) { - const struct spool *spool = trp->spool; - const char *file_name = trp->file[file_id].name; - if (debug_level) - logmsg (LOG_DEBUG, _("spool %s: installing file `%s/%s'"), - spool->tag, trp->relative_dir, file_name); - UPDATE_STATS (STAT_UPLOADS); - if (!dry_run_mode && unlink (file_name)) - { - logmsg (LOG_ERR, _("cannot unlink %s: %s"), - file_name, strerror (errno)); - return 1; - } - return 0; + const struct spool *spool = trp->spool; + const char *file_name = trp->file[file_id].name; + if (debug_level) + logmsg(LOG_DEBUG, _("spool %s: installing file `%s/%s'"), + spool->tag, trp->relative_dir, file_name); + UPDATE_STATS(STAT_UPLOADS); + if (!dry_run_mode && unlink(file_name)) { + logmsg(LOG_ERR, _("cannot unlink %s: %s"), + file_name, strerror(errno)); + return 1; + } + return 0; } int -null_archive_file (struct file_triplet *trp, const char *file_name) +null_archive_file(struct file_triplet *trp, const char *file_name) { - if (debug_level) - logmsg (LOG_DEBUG, _("spool %s: archiving `%s'"), - trp->spool->tag, file_name); - UPDATE_STATS (STAT_ARCHIVES); - return 0; + if (debug_level) + logmsg(LOG_DEBUG, _("spool %s: archiving `%s'"), + trp->spool->tag, file_name); + UPDATE_STATS(STAT_ARCHIVES); + return 0; } int -null_symlink_file (struct file_triplet *trp, - const char *wanted_src, const char *wanted_dst) +null_symlink_file(struct file_triplet *trp, + const char *wanted_src, const char *wanted_dst) { - if (debug_level) - logmsg (LOG_DEBUG, _("spool %s: symlinking `%s' to `%s'"), - trp->spool->tag, wanted_src, wanted_dst); - UPDATE_STATS (STAT_SYMLINKS); - return 0; + if (debug_level) + logmsg(LOG_DEBUG, _("spool %s: symlinking `%s' to `%s'"), + trp->spool->tag, wanted_src, wanted_dst); + UPDATE_STATS(STAT_SYMLINKS); + return 0; } int -null_rmsymlink_file (struct file_triplet *trp, const char *file_name) +null_rmsymlink_file(struct file_triplet *trp, const char *file_name) { - if (debug_level) - logmsg (LOG_DEBUG, _("spool %s: removing symlink `%s/%s'"), - trp->spool->tag, trp->relative_dir, file_name); - UPDATE_STATS (STAT_RMSYMLINKS); - return 0; + if (debug_level) + logmsg(LOG_DEBUG, _("spool %s: removing symlink `%s/%s'"), + trp->spool->tag, trp->relative_dir, file_name); + UPDATE_STATS(STAT_RMSYMLINKS); + return 0; } - diff --git a/src/pidfile.c b/src/pidfile.c index 9990e57..eda5ba9 100644 --- a/src/pidfile.c +++ b/src/pidfile.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007, 2009-2011 Sergey Poznyakoff + Copyright (C) 2007, 2009-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -18,72 +18,58 @@ char *pidfile = LOCALSTATEDIR "/run/wydawca.pid"; int force_startup; - void -remove_pidfile (void) +remove_pidfile(void) { - unlink (pidfile); + unlink(pidfile); } void -check_pidfile () +check_pidfile() { - FILE *fp = fopen (pidfile, "r+"); + FILE *fp = fopen(pidfile, "r+"); - if (fp) - { - unsigned long pid = -1; - if (fscanf (fp, "%lu\n", &pid) != 1) - { - logmsg (LOG_ERR, _("malformed pidfile %s"), pidfile); - if (!force_startup) - exit (EX_UNAVAILABLE); - } - else - { - if (kill (pid, 0)) - { - if (errno != ESRCH) - { - logmsg (LOG_ERR, - _("cannot verify if PID %lu is running: %s"), - pid, strerror (errno)); - if (!force_startup) - exit (EX_UNAVAILABLE); + if (fp) { + unsigned long pid = -1; + if (fscanf(fp, "%lu\n", &pid) != 1) { + logmsg(LOG_ERR, _("malformed pidfile %s"), pidfile); + if (!force_startup) + exit(EX_UNAVAILABLE); + } else { + if (kill(pid, 0)) { + if (errno != ESRCH) { + logmsg(LOG_ERR, + _("cannot verify if PID %lu " + "is running: %s"), + pid, strerror(errno)); + if (!force_startup) + exit(EX_UNAVAILABLE); + } + } else if (!force_startup) { + logmsg(LOG_ERR, + _("another wydawca instance may " + "be running (PID %lu)"), + pid); + exit(EX_UNAVAILABLE); + } + } + logmsg(LOG_NOTICE, _("replacing pidfile %s (PID %lu)"), + pidfile, pid); + fseek(fp, 0, SEEK_SET); + } else if (errno != ENOENT) { + logmsg(LOG_ERR, _("cannot open pidfile %s: %s"), pidfile, + strerror(errno)); + exit(EX_UNAVAILABLE); + } else { + fp = fopen(pidfile, "w"); + if (!fp) { + logmsg(LOG_ERR, + _("cannot open pidfile %s for writing: %s"), + pidfile, strerror(errno)); + exit(EX_UNAVAILABLE); } - } - else if (!force_startup) - { - logmsg (LOG_ERR, - _("another wydawca instance may be running (PID %lu)"), - pid); - exit (EX_UNAVAILABLE); - } - } - logmsg (LOG_NOTICE, _("replacing pidfile %s (PID %lu)"), - pidfile, pid); - fseek (fp, 0, SEEK_SET); - } - else if (errno != ENOENT) - { - logmsg (LOG_ERR, _("cannot open pidfile %s: %s"), pidfile, - strerror (errno)); - exit (EX_UNAVAILABLE); - } - else - { - fp = fopen (pidfile, "w"); - if (!fp) - { - logmsg (LOG_ERR, - _("cannot open pidfile %s for writing: %s"), - pidfile, strerror (errno)); - exit (EX_UNAVAILABLE); } - } - fprintf (fp, "%lu\n", (unsigned long) getpid ()); - fclose (fp); + fprintf(fp, "%lu\n", (unsigned long)getpid()); + fclose(fp); } - - diff --git a/src/process.c b/src/process.c index ec64589..c2d6ed2 100644 --- a/src/process.c +++ b/src/process.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007, 2009-2011 Sergey Poznyakoff + Copyright (C) 2007, 2009-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -16,325 +16,310 @@ #include "wydawca.h" -struct spool_list -{ - struct spool_list *next; - struct spool spool; +struct spool_list { + struct spool_list *next; + struct spool spool; }; static struct spool_list *spool_list; int -for_each_spool (int (*fun) (struct spool *, void *), void *data) +for_each_spool(int (*fun) (struct spool *, void *), void *data) { - struct spool_list *sp; - - for (sp = spool_list; sp; sp = sp->next) - { - int rc = fun (&sp->spool, data); - if (rc) - return rc; - } - return 0; + struct spool_list *sp; + + for (sp = spool_list; sp; sp = sp->next) { + int rc = fun(&sp->spool, data); + if (rc) + return rc; + } + return 0; } void -register_spool (struct spool *spool) +register_spool(struct spool *spool) { - struct spool_list *sp = grecs_malloc (sizeof *sp); - sp->spool = *spool; - sp->next = spool_list; - spool_list = sp; + struct spool_list *sp = grecs_malloc(sizeof *sp); + sp->spool = *spool; + sp->next = spool_list; + spool_list = sp; } static int -spool_check_alias (struct spool *spool, const char *name) +spool_check_alias(struct spool *spool, const char *name) { - if (spool->aliases && grecs_list_locate (spool->aliases, (char*) name)) - return 1; - return 0; + if (spool->aliases && grecs_list_locate(spool->aliases, (char *)name)) + return 1; + return 0; } struct spool * -wydawca_find_spool (const char *name) +wydawca_find_spool(const char *name) { - struct spool_list *sp; - - for (sp = spool_list; sp; sp = sp->next) - { - if (strcmp (sp->spool.tag, name) == 0 - || spool_check_alias (&sp->spool, name)) - return &sp->spool; - } - return NULL; + struct spool_list *sp; + + for (sp = spool_list; sp; sp = sp->next) { + if (strcmp(sp->spool.tag, name) == 0 || + spool_check_alias(&sp->spool, name)) + return &sp->spool; + } + return NULL; } /* Return true if NAME is a directory. If stat fails, return the error code in EC */ int -test_dir (const char *name, int *ec) +test_dir(const char *name, int *ec) { - struct stat st; - - *ec = 0; - if (stat (name, &st)) - { - *ec = errno; - return 1; - } - return S_ISDIR (st.st_mode) == 0; + struct stat st; + + *ec = 0; + if (stat(name, &st)) { + *ec = errno; + return 1; + } + return S_ISDIR(st.st_mode) == 0; } /* Return a textual representation of a file TYPE */ const char * -file_type_str (enum file_type type) +file_type_str(enum file_type type) { - switch (type) - { - case file_dist: - return "distributive"; - - case file_signature: - return "detached signature"; - - case file_directive: - return "signed upload directive"; - } - return "UNKNOWN"; + switch (type) { + case file_dist: + return "distributive"; + + case file_signature: + return "detached signature"; + + case file_directive: + return "signed upload directive"; + } + return "UNKNOWN"; } /* Parse file NAME: determine its type and root name and store this information in FINFO */ void -parse_file_name (const char *name, struct file_info *finfo) +parse_file_name(const char *name, struct file_info *finfo) { - static struct suffix - { - const char *suf; - unsigned len; - enum file_type type; - } suftab[] = { - { SUF_SIG, SUF_SIG_LEN, file_signature }, - { SUF_DIR, SUF_DIR_LEN, file_directive }, - { "", 0, file_dist } - }; - int i; - unsigned len = strlen (name); - - for (i = 0; i < sizeof suftab / sizeof suftab[0]; i++) - { - if (len >= suftab[i].len - && memcmp (name + len - suftab[i].len, - suftab[i].suf, suftab[i].len) == 0) - { - finfo->name = grecs_strdup (name); - finfo->type = suftab[i].type; - finfo->root_len = len - suftab[i].len; - return; + static struct suffix { + const char *suf; + unsigned len; + enum file_type type; + } suftab[] = { + { SUF_SIG, SUF_SIG_LEN, file_signature }, + { SUF_DIR, SUF_DIR_LEN, file_directive}, + { "", 0, file_dist } + }; + int i; + unsigned len = strlen(name); + + for (i = 0; i < sizeof suftab / sizeof suftab[0]; i++) { + if (len >= suftab[i].len + && memcmp(name + len - suftab[i].len, + suftab[i].suf, suftab[i].len) == 0) { + finfo->name = grecs_strdup(name); + finfo->type = suftab[i].type; + finfo->root_len = len - suftab[i].len; + return; + } } - } - abort (); /* should not happen */ + abort(); /* should not happen */ } void -file_info_cleanup (struct file_info *finfo) +file_info_cleanup(struct file_info *finfo) { - free (finfo->name); - memset (finfo, 0, sizeof (*finfo)); + free(finfo->name); + memset(finfo, 0, sizeof(*finfo)); } static int -match_uid_p (uid_t uid, int uc, uid_t *uv) +match_uid_p(uid_t uid, int uc, uid_t * uv) { - int i; - if (!uv) - return 1; - for (i = 0; i < uc; i++) - if (uv[i] == uid) - return 1; - return 0; + int i; + if (!uv) + return 1; + for (i = 0; i < uc; i++) + if (uv[i] == uid) + return 1; + return 0; } int -spool_cwd_add_new_file (const struct spool *spool, const char *name, - int uc, uid_t *uv) +spool_cwd_add_new_file(const struct spool *spool, const char *name, + int uc, uid_t * uv) { - struct stat st; - struct file_info finfo; - - if (stat (name, &st)) - { - logmsg (LOG_ERR, _("cannot stat file %s/%s: %s"), - spool->source_dir, name, strerror (errno)); - return -1; - } - - if (!S_ISREG (st.st_mode)) - { - logmsg (LOG_NOTICE, _("not a regular file: %s/%s"), - spool->source_dir, name); - return -1; - } - - if (!match_uid_p (st.st_uid, uc, uv)) - { - if (debug_level) - logmsg (LOG_DEBUG, _("ignoring file: %s/%s"), - spool->source_dir, name); - return -1; - } - - finfo.sb = st; - parse_file_name (name, &finfo); - - if (debug_level) - logmsg (LOG_DEBUG, _("found file %s: %s, stem: %.*s"), name, - file_type_str (finfo.type), finfo.root_len, finfo.name); - - register_file (&finfo, spool); - return 0; + struct stat st; + struct file_info finfo; + + if (stat(name, &st)) { + logmsg(LOG_ERR, _("cannot stat file %s/%s: %s"), + spool->source_dir, name, strerror(errno)); + return -1; + } + + if (!S_ISREG(st.st_mode)) { + logmsg(LOG_NOTICE, _("not a regular file: %s/%s"), + spool->source_dir, name); + return -1; + } + + if (!match_uid_p(st.st_uid, uc, uv)) { + if (debug_level) + logmsg(LOG_DEBUG, _("ignoring file: %s/%s"), + spool->source_dir, name); + return -1; + } + + finfo.sb = st; + parse_file_name(name, &finfo); + + if (debug_level) + logmsg(LOG_DEBUG, _("found file %s: %s, stem: %.*s"), name, + file_type_str(finfo.type), finfo.root_len, finfo.name); + + register_file(&finfo, spool); + return 0; } int -spool_add_new_file (const struct spool *spool, const char *name, - int uc, uid_t *uv) +spool_add_new_file(const struct spool *spool, const char *name, + int uc, uid_t * uv) { - if (debug_level) - logmsg (LOG_DEBUG, "%s -> %s, adding %s", spool->source_dir, - mu_url_to_string (spool->dest_url), name); - - if (chdir (spool->source_dir)) - { - logmsg (LOG_ERR, _("cannot chdir to %s: %s"), spool->source_dir, - strerror (errno)); - return -1; - } - return spool_cwd_add_new_file (spool, name, uc, uv); + if (debug_level) + logmsg(LOG_DEBUG, "%s -> %s, adding %s", spool->source_dir, + mu_url_to_string(spool->dest_url), name); + + if (chdir(spool->source_dir)) { + logmsg(LOG_ERR, _("cannot chdir to %s: %s"), spool->source_dir, + strerror(errno)); + return -1; + } + return spool_cwd_add_new_file(spool, name, uc, uv); } /* Scan upload directory from the DPAIR and register all files found there, forming triplets when possible */ void -scan_spool_unlocked (struct spool *spool, int uc, uid_t *uv) +scan_spool_unlocked(struct spool *spool, int uc, uid_t * uv) { - DIR *dir; - struct dirent *ent; - - if (debug_level) - logmsg (LOG_DEBUG, "%s -> %s", spool->source_dir, - mu_url_to_string (spool->dest_url)); - - if (chdir (spool->source_dir)) - { - logmsg (LOG_ERR, _("cannot chdir to %s: %s"), spool->source_dir, - strerror (errno)); - return; - } - - dir = opendir ("."); - if (!dir) - { - logmsg (LOG_ERR, _("cannot open directory %s: %s"), spool->source_dir, - strerror (errno)); - return; - } - - timer_start ("spool"); - /* FIXME: prefix spool tag with something */ - timer_start (spool->tag); - while ((ent = readdir (dir))) - { - if (strcmp (ent->d_name, ".") == 0 || strcmp (ent->d_name, "..") == 0) - continue; - spool_cwd_add_new_file (spool, ent->d_name, uc, uv); - } - - closedir (dir); - - if (count_collected_triplets () > 0) - spool_commit_triplets (spool); - - timer_stop (spool->tag); - timer_stop ("spool"); + DIR *dir; + struct dirent *ent; + + if (debug_level) + logmsg(LOG_DEBUG, "%s -> %s", spool->source_dir, + mu_url_to_string(spool->dest_url)); + + if (chdir(spool->source_dir)) { + logmsg(LOG_ERR, _("cannot chdir to %s: %s"), spool->source_dir, + strerror(errno)); + return; + } + + dir = opendir("."); + if (!dir) { + logmsg(LOG_ERR, _("cannot open directory %s: %s"), + spool->source_dir, strerror(errno)); + return; + } + + timer_start("spool"); + /* FIXME: prefix spool tag with something */ + timer_start(spool->tag); + while ((ent = readdir(dir))) { + if (strcmp(ent->d_name, ".") == 0 + || strcmp(ent->d_name, "..") == 0) + continue; + spool_cwd_add_new_file(spool, ent->d_name, uc, uv); + } + + closedir(dir); + + if (count_collected_triplets() > 0) + spool_commit_triplets(spool); + + timer_stop(spool->tag); + timer_stop("spool"); } int -scan_spool (struct spool *spool, int uc, uid_t *uv) +scan_spool(struct spool *spool, int uc, uid_t * uv) { - char *lockfile = wydawca_lockname (spool->tag); - int rc = wydawca_lock (lockfile); - switch (rc) - { - case LOCK_OK: - scan_spool_unlocked (spool, uc, uv); - wydawca_unlock (lockfile); - break; - - case LOCK_FAILURE: - logmsg (LOG_ERR, _("cannot lock spool %s"), spool->tag); - break; - - case LOCK_RETRY: - logmsg (LOG_WARNING, _("timed out while looking spool %s"), spool->tag); - break; - } - free (lockfile); - return rc; + char *lockfile = wydawca_lockname(spool->tag); + int rc = wydawca_lock(lockfile); + switch (rc) { + case LOCK_OK: + scan_spool_unlocked(spool, uc, uv); + wydawca_unlock(lockfile); + break; + + case LOCK_FAILURE: + logmsg(LOG_ERR, _("cannot lock spool %s"), spool->tag); + break; + + case LOCK_RETRY: + logmsg(LOG_WARNING, _("timed out while looking spool %s"), + spool->tag); + break; + } + free(lockfile); + return rc; } int -spool_open_dictionaries (struct spool *spool) +spool_open_dictionaries(struct spool *spool) { - if (!spool->dict_inited) - { - int i; - - for (i = 0; i < dictionary_count; i++) - { - if (dictionary_init (spool->dictionary[i])) - { - logmsg (LOG_ERR, _("failed to initialize dictionary %d"), i); - return -1; - } - } - spool->dict_inited = 1; - } - return 0; + if (!spool->dict_inited) { + int i; + + for (i = 0; i < dictionary_count; i++) { + if (dictionary_init(spool->dictionary[i])) { + logmsg(LOG_ERR, + _("failed to initialize dictionary %d"), + i); + return -1; + } + } + spool->dict_inited = 1; + } + return 0; } void -spool_close_dictionaries (struct spool *spool) +spool_close_dictionaries(struct spool *spool) { - int i; - for (i = 0; i < NITEMS (spool->dictionary); i++) - dictionary_done (spool->dictionary[i]); - spool->dict_inited = 0; + int i; + for (i = 0; i < NITEMS(spool->dictionary); i++) + dictionary_done(spool->dictionary[i]); + spool->dict_inited = 0; } /* Scan all configured update directories */ int -scan_all_spools (int uidc, uid_t *uidv) +scan_all_spools(int uidc, uid_t * uidv) { - struct spool_list *sp; - int rc = 0; - - timer_start ("wydawca"); - for (sp = spool_list; sp; sp = sp->next) - if (enabled_spool_p (&sp->spool)) - if (scan_spool (&sp->spool, uidc, uidv)) - rc++; - - for (sp = spool_list; sp; sp = sp->next) - spool_close_dictionaries (&sp->spool); - timer_stop ("wydawca"); - return rc; + struct spool_list *sp; + int rc = 0; + + timer_start("wydawca"); + for (sp = spool_list; sp; sp = sp->next) + if (enabled_spool_p(&sp->spool)) + if (scan_spool(&sp->spool, uidc, uidv)) + rc++; + + for (sp = spool_list; sp; sp = sp->next) + spool_close_dictionaries(&sp->spool); + timer_stop("wydawca"); + return rc; } void -spool_create_timers () +spool_create_timers() { - struct spool_list *sp; + struct spool_list *sp; - for (sp = spool_list; sp; sp = sp->next) - timer_start (sp->spool.tag); + for (sp = spool_list; sp; sp = sp->next) + timer_start(sp->spool.tag); } diff --git a/src/pushd.c b/src/pushd.c index 6de10a6..61ad5b5 100644 --- a/src/pushd.c +++ b/src/pushd.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2011 Sergey Poznyakoff + Copyright (C) 2011,2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -16,11 +16,10 @@ #include "wydawca.h" -struct saved_dir -{ - struct saved_dir *prev; - int fd; - char *name; +struct saved_dir { + struct saved_dir *prev; + int fd; + char *name; }; struct saved_dir *dir_stack; @@ -30,133 +29,122 @@ struct saved_dir *dir_stack; #endif char * -getcwd_alloc (void) +getcwd_alloc(void) { - size_t size = 0; - char *buf = NULL; - char *p; - - do - { - if (!buf) - { - size = 64; - buf = malloc (size); + size_t size = 0; + char *buf = NULL; + char *p; + + do { + if (!buf) { + size = 64; + buf = malloc(size); + } else { + char *np; + size_t ns = 2 * size; + if (ns < size) { + free(buf); + errno = ENOMEM; + return NULL; + } + size = ns; + np = realloc(buf, size); + if (!np) + free(buf); + buf = np; + } + if (!buf) + return NULL; } - else - { - char *np; - size_t ns = 2 * size; - if (ns < size) - { - free (buf); - errno = ENOMEM; - return NULL; - } - size = ns; - np = realloc (buf, size); - if (!np) - free (buf); - buf = np; + while ((p = getcwd(buf, size)) == NULL && errno == ERANGE); + if (!p) { + int ec = errno; + free(buf); + buf = NULL; + errno = ec; } - if (!buf) - return NULL; - } - while ((p = getcwd (buf, size)) == NULL && errno == ERANGE); - if (!p) - { - int ec = errno; - free (buf); - buf = NULL; - errno = ec; - } - return buf; + return buf; } static int -_save_dir (struct saved_dir *sd) +_save_dir(struct saved_dir *sd) { - int fd; - + int fd; + #ifdef HAVE_FCHDIR - fd = open (".", O_SEARCH); + fd = open(".", O_SEARCH); #else - fd = -1; + fd = -1; #endif - if (fd == -1) - { - sd->name = getcwd_alloc (); - if (!sd->name) - return errno; - } - else - sd->name = NULL; - sd->fd = fd; - return 0; + if (fd == -1) { + sd->name = getcwd_alloc(); + if (!sd->name) + return errno; + } else + sd->name = NULL; + sd->fd = fd; + return 0; } static void -_drop_dir (struct saved_dir *sd) +_drop_dir(struct saved_dir *sd) { - if (sd->fd != -1) - close (sd->fd); - free (sd->name); - free (sd); + if (sd->fd != -1) + close(sd->fd); + free(sd->name); + free(sd); } static int -_push_dir (struct saved_dir *sd, const char *dirname) +_push_dir(struct saved_dir *sd, const char *dirname) { - int rc = _save_dir (sd); - if (rc) - return rc; - if (dirname && chdir (dirname)) - { - rc = errno; - _drop_dir (sd); - return rc; - } - return 0; + int rc = _save_dir(sd); + if (rc) + return rc; + if (dirname && chdir(dirname)) { + rc = errno; + _drop_dir(sd); + return rc; + } + return 0; } int -push_dir (const char *dirname) +push_dir(const char *dirname) { - int rc; - struct saved_dir *sd = malloc (sizeof (*sd)); - - if (!sd) - return errno; - rc = _push_dir (sd, dirname); - if (rc) - { - errno = rc; - return -1; - } - sd->prev = dir_stack; - dir_stack = sd; - return 0; + int rc; + struct saved_dir *sd = malloc(sizeof(*sd)); + + if (!sd) + return errno; + rc = _push_dir(sd, dirname); + if (rc) { + errno = rc; + return -1; + } + sd->prev = dir_stack; + dir_stack = sd; + return 0; } int -pop_dir () +pop_dir() { - struct saved_dir *sd = dir_stack; - int rc; - - if (!sd) - { - errno = ENOENT; - return -1; - } - dir_stack = sd->prev; - if (sd->fd != -1) - rc = fchdir (sd->fd); - else - rc = chdir (sd->name); - if (rc) - rc = errno; - _drop_dir (sd); - errno = rc; - return rc; + struct saved_dir *sd = dir_stack; + int rc; + + if (!sd) { + errno = ENOENT; + return -1; + } + dir_stack = sd->prev; + if (sd->fd != -1) + rc = fchdir(sd->fd); + else + rc = chdir(sd->name); + if (rc) + rc = errno; + _drop_dir(sd); + errno = rc; + return rc; } diff --git a/src/report.c b/src/report.c index 7344dbf..fe40454 100644 --- a/src/report.c +++ b/src/report.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2009-2011 Sergey Poznyakoff + Copyright (C) 2009-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -20,35 +20,34 @@ static struct txtacc *report_acc; char *report_string; void -report_init () +report_init() { - if (!report_acc) - report_acc = txtacc_create (); - else - txtacc_free_string (report_acc, report_string); + if (!report_acc) + report_acc = txtacc_create(); + else + txtacc_free_string(report_acc, report_string); } void -report_add (const char *fmt, ...) +report_add(const char *fmt, ...) { - va_list ap; - char *str = NULL; - size_t size = 0; - - va_start (ap, fmt); - grecs_vasprintf (&str, &size, fmt, ap); - va_end (ap); - if (str) - { - txtacc_grow (report_acc, str, strlen (str)); - txtacc_1grow (report_acc, '\n'); - } - free (str); + va_list ap; + char *str = NULL; + size_t size = 0; + + va_start(ap, fmt); + grecs_vasprintf(&str, &size, fmt, ap); + va_end(ap); + if (str) { + txtacc_grow(report_acc, str, strlen(str)); + txtacc_1grow(report_acc, '\n'); + } + free(str); } void -report_finish () +report_finish() { - txtacc_1grow (report_acc, 0); - report_string = txtacc_finish (report_acc, 0); + txtacc_1grow(report_acc, 0); + report_string = txtacc_finish(report_acc, 0); } @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007, 2010-2011 Sergey Poznyakoff + Copyright (C) 2007, 2010-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -18,190 +18,186 @@ #include "sql.h" /* Singly-linked list of configured MySQL connections. */ -struct sql_list -{ - struct sql_list *next; - struct sqlconn conn; +struct sql_list { + struct sql_list *next; + struct sqlconn conn; }; static struct sql_list *sql_list; /* Append CONN to the end of sql_list */ void -sql_register_conn (struct sqlconn *conn) +sql_register_conn(struct sqlconn *conn) { - struct sql_list *ent = grecs_malloc (sizeof *ent); - ent->conn = *conn; - ent->next = sql_list; - sql_list = ent; + struct sql_list *ent = grecs_malloc(sizeof *ent); + ent->conn = *conn; + ent->next = sql_list; + sql_list = ent; } /* Find a configured connection that has the given IDENT */ struct sqlconn * -sql_find_connection (const char *ident) +sql_find_connection(const char *ident) { - struct sql_list *p; - for (p = sql_list; p; p = p->next) - if (strcmp (p->conn.ident, ident) == 0) - return &p->conn; - return NULL; + struct sql_list *p; + for (p = sql_list; p; p = p->next) + if (strcmp(p->conn.ident, ident) == 0) + return &p->conn; + return NULL; } /* Return true if there exists a connection with the given IDENT */ int -sql_connection_exists_p (const char *ident) +sql_connection_exists_p(const char *ident) { - return sql_find_connection (ident) != NULL; + return sql_find_connection(ident) != NULL; } /* Initialize MySQL dictionary */ int -sql_init_dictionary (struct dictionary *dict) +sql_init_dictionary(struct dictionary *dict) { - struct sqlconn *conn = sql_find_connection (dict->parmv[0]); - - if (!conn) - { - logmsg (LOG_EMERG, _("INTERNAL ERROR: cannot find SQL connection %s"), - dict->parmv[0]); - abort (); - } - - if (conn->initcount++ == 0) - { - mysql_init (&conn->mysql); - - if (conn->config_file) - mysql_options (&conn->mysql, MYSQL_READ_DEFAULT_FILE, - conn->config_file); - if (conn->config_group) - mysql_options (&conn->mysql, MYSQL_READ_DEFAULT_GROUP, - conn->config_group); - - if (conn->cacert) - mysql_ssl_set (&conn->mysql, NULL, NULL, conn->cacert, - NULL, NULL); - if (!mysql_real_connect (&conn->mysql, conn->host, conn->user, - conn->password, conn->database, conn->port, - conn->socket, CLIENT_MULTI_RESULTS)) - { - logmsg (LOG_ERR, _("failed to connect to database %s: error: %s\n"), - dict->parmv[0], mysql_error (&conn->mysql)); - return 1; + struct sqlconn *conn = sql_find_connection(dict->parmv[0]); + + if (!conn) { + logmsg(LOG_EMERG, + _("INTERNAL ERROR: cannot find SQL connection %s"), + dict->parmv[0]); + abort(); + } + + if (conn->initcount++ == 0) { + mysql_init(&conn->mysql); + + if (conn->config_file) + mysql_options(&conn->mysql, MYSQL_READ_DEFAULT_FILE, + conn->config_file); + if (conn->config_group) + mysql_options(&conn->mysql, MYSQL_READ_DEFAULT_GROUP, + conn->config_group); + + if (conn->cacert) + mysql_ssl_set(&conn->mysql, NULL, NULL, conn->cacert, + NULL, NULL); + if (!mysql_real_connect(&conn->mysql, conn->host, conn->user, + conn->password, conn->database, + conn->port, conn->socket, + CLIENT_MULTI_RESULTS)) { + logmsg(LOG_ERR, + _("failed to connect to database %s: " + "error: %s\n"), + dict->parmv[0], mysql_error(&conn->mysql)); + return 1; + } } - } - dict->storage = conn; - return 0; + dict->storage = conn; + return 0; } void * -sql_open (struct dictionary *dict) +sql_open(struct dictionary *dict) { - return dict->storage; + return dict->storage; } int -sql_free_result (struct dictionary *dict, void *handle) +sql_free_result(struct dictionary *dict, void *handle) { - struct sqlconn *conn = handle; - if (conn->result) - { - mysql_free_result (conn->result); - conn->result = NULL; - } - return 0; + struct sqlconn *conn = handle; + if (conn->result) { + mysql_free_result(conn->result); + conn->result = NULL; + } + return 0; } /* Finish the initialized MySQL dictionary */ int -sql_done_dictionary (struct dictionary *dict) +sql_done_dictionary(struct dictionary *dict) { - struct sqlconn *conn = dict->storage; - if (!conn || conn->initcount == 0) - return 0; - if (--conn->initcount) - return 0; - sql_free_result (dict, conn); /* FIXME: Not needed */ - mysql_close (&conn->mysql); - dict->storage = NULL; - return 0; + struct sqlconn *conn = dict->storage; + if (!conn || conn->initcount == 0) + return 0; + if (--conn->initcount) + return 0; + sql_free_result(dict, conn); /* FIXME: Not needed */ + mysql_close(&conn->mysql); + dict->storage = NULL; + return 0; } /* Execute QUERY using the given access METHOD. Return 0 on success. */ int -sql_lookup_dictionary (struct dictionary *dict, void *handle, const char *query) +sql_lookup_dictionary(struct dictionary *dict, void *handle, const char *query) { - struct sqlconn *conn = handle; - MYSQL *mysql = &conn->mysql; - - if (!query) - { - logmsg (LOG_ERR, _("no query supplied for dictionary %s"), "sql"); - return 1; - } - - if (mysql_query (mysql, query)) - { - logmsg (LOG_ERR, _("query failed: %s"), mysql_error (mysql)); - logmsg (LOG_NOTICE, _("the failed query was: %s"), query); - return 1; - } - - conn->result = mysql_store_result (mysql); - if (!conn->result) - { - logmsg (LOG_ERR, _("cannot get result: %s"), mysql_error (mysql)); - logmsg (LOG_NOTICE, _("the failed query was: %s"), query); - return 1; - } - - dict->nrow = mysql_num_rows (conn->result); - dict->ncol = mysql_num_fields (conn->result); - if (debug_level > 1) - { - logmsg (LOG_DEBUG, _("query returned %u columns in %u rows"), - dict->ncol, dict->nrow); - logmsg (LOG_DEBUG, _("the query was: %s"), query); - } - - return 0; + struct sqlconn *conn = handle; + MYSQL *mysql = &conn->mysql; + + if (!query) { + logmsg(LOG_ERR, _("no query supplied for dictionary %s"), + "sql"); + return 1; + } + + if (mysql_query(mysql, query)) { + logmsg(LOG_ERR, _("query failed: %s"), mysql_error(mysql)); + logmsg(LOG_NOTICE, _("the failed query was: %s"), query); + return 1; + } + + conn->result = mysql_store_result(mysql); + if (!conn->result) { + logmsg(LOG_ERR, _("cannot get result: %s"), mysql_error(mysql)); + logmsg(LOG_NOTICE, _("the failed query was: %s"), query); + return 1; + } + + dict->nrow = mysql_num_rows(conn->result); + dict->ncol = mysql_num_fields(conn->result); + if (debug_level > 1) { + logmsg(LOG_DEBUG, _("query returned %u columns in %u rows"), + dict->ncol, dict->nrow); + logmsg(LOG_DEBUG, _("the query was: %s"), query); + } + + return 0; } int -sql_get_dictionary (struct dictionary *dict, void *handle, - unsigned nrow, unsigned ncol) +sql_get_dictionary(struct dictionary *dict, void *handle, + unsigned nrow, unsigned ncol) { - struct sqlconn *conn = handle; - MYSQL_ROW row; - size_t len; - - if (!conn->result) - return 1; - mysql_data_seek (conn->result, nrow); - row = mysql_fetch_row (conn->result); - if (row[ncol] == NULL) - len = 0; - else - len = trim_length (row[ncol]); - - dictionary_copy_result (dict, row[ncol], len); - return 0; + struct sqlconn *conn = handle; + MYSQL_ROW row; + size_t len; + + if (!conn->result) + return 1; + mysql_data_seek(conn->result, nrow); + row = mysql_fetch_row(conn->result); + if (row[ncol] == NULL) + len = 0; + else + len = trim_length(row[ncol]); + + dictionary_copy_result(dict, row[ncol], len); + return 0; } int -sql_quote (struct dictionary *dict, void *handle, const char *input, - char **poutput, size_t *psize) +sql_quote(struct dictionary *dict, void *handle, const char *input, + char **poutput, size_t * psize) { - struct sqlconn *conn = handle; - size_t len, size; - char *output; - - len = strlen (input); - size = 2 * len + 1; - output = grecs_malloc (size); - mysql_real_escape_string (&conn->mysql, output, input, len); - *poutput = output; - if (psize) - *psize = strlen (output); - return 0; + struct sqlconn *conn = handle; + size_t len, size; + char *output; + + len = strlen(input); + size = 2 * len + 1; + output = grecs_malloc(size); + mysql_real_escape_string(&conn->mysql, output, input, len); + *poutput = output; + if (psize) + *psize = strlen(output); + return 0; } @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2009-2011 Sergey Poznyakoff + Copyright (C) 2009-2013 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -16,34 +16,33 @@ #include <mysql/mysql.h> -struct sqlconn -{ - char *ident; - char *config_file; - char *config_group; - char *host; - char *socket; - short port; - char *database; - char *user; - char *password; - char *cacert; - size_t initcount; /* Number of initializations */ - MYSQL mysql; - MYSQL_RES *result; +struct sqlconn { + char *ident; + char *config_file; + char *config_group; + char *host; + char *socket; + short port; + char *database; + char *user; + char *password; + char *cacert; + size_t initcount; /* Number of initializations */ + MYSQL mysql; + MYSQL_RES *result; }; -void sql_register_conn (struct sqlconn *); -int sql_connection_exists_p (const char *); -struct sqlconn *sql_find_connection (const char *ident); +void sql_register_conn(struct sqlconn *); +int sql_connection_exists_p(const char *); +struct sqlconn *sql_find_connection(const char *ident); -int sql_init_dictionary (struct dictionary *dict); -int sql_done_dictionary (struct dictionary *dict); -void *sql_open (struct dictionary *dict); +int sql_init_dictionary(struct dictionary *dict); +int sql_done_dictionary(struct dictionary *dict); +void *sql_open(struct dictionary *dict); -int sql_lookup_dictionary (struct dictionary *dict, void *handle, - const char *cmd); -int sql_get_dictionary (struct dictionary *dict, void *handle, - unsigned nrow, unsigned ncol); -int sql_free_result (struct dictionary *dict, void *handle); -int sql_quote (struct dictionary *, void *, const char *, char **, size_t *); +int sql_lookup_dictionary(struct dictionary *dict, void *handle, + const char *cmd); +int sql_get_dictionary(struct dictionary *dict, void *handle, + unsigned nrow, unsigned ncol); +int sql_free_result(struct dictionary *dict, void *handle); +int sql_quote(struct dictionary *, void *, const char *, char **, size_t *); diff --git a/src/tcpwrap.c b/src/tcpwrap.c index 3c29f31..907bc20 100644 --- a/src/tcpwrap.c +++ b/src/tcpwrap.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007-2011 Sergey Poznyakoff + Copyright (C) 2007-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -26,58 +26,59 @@ int deny_severity = LOG_INFO; int allow_severity = LOG_INFO; static int -cb_syslog_priority (enum grecs_callback_command cmd, - grecs_locus_t *locus, - void *varptr, - grecs_value_t *value, - void *cb_data) +cb_syslog_priority(enum grecs_callback_command cmd, + grecs_locus_t * locus, + void *varptr, grecs_value_t * value, void *cb_data) { - if (assert_string_arg (locus, cmd, value)) - return 1; + if (assert_string_arg(locus, cmd, value)) + return 1; - if (mu_string_to_syslog_priority (value->v.string, varptr)) - grecs_error (locus, 0, _("Unknown syslog priority `%s'"), - value->v.string); - return 0; + if (mu_string_to_syslog_priority(value->v.string, varptr)) + grecs_error(locus, 0, _("Unknown syslog priority `%s'"), + value->v.string); + return 0; } struct grecs_keyword tcpwrapper_kw[] = { - { "enable", NULL, - N_("Enable TCP wrapper access control. Default is \"yes\"."), - grecs_type_bool, GRECS_DFLT, &tcpwrap_enable }, - { "daemon", N_("name"), - N_("Set daemon name for TCP wrapper lookups. Default is program name."), - grecs_type_string, GRECS_DFLT, &tcpwrap_daemon }, - { "allow-table", N_("file"), - N_("Use file for positive client address access control " - "(default: /etc/hosts.allow)."), - grecs_type_string, GRECS_DFLT, &hosts_allow_table }, - { "deny-table", N_("file"), - N_("Use file for negative client address access control " - "(default: /etc/hosts.deny)."), - grecs_type_string, GRECS_DFLT, &hosts_deny_table }, - { "allow-syslog-priority", N_("prio"), - N_("Log host allows at this syslog priority."), - grecs_type_string, GRECS_DFLT, &allow_severity, 0, cb_syslog_priority }, - { "deny-syslog-priority", N_("prio"), - N_("Log host denies at this syslog priority."), - grecs_type_string, GRECS_DFLT, &deny_severity, 0, cb_syslog_priority }, - { NULL } + { "enable", NULL, + N_("Enable TCP wrapper access control. Default is \"yes\"."), + grecs_type_bool, GRECS_DFLT, &tcpwrap_enable }, + { "daemon", N_("name"), + N_("Set daemon name for TCP wrapper lookups. " + "Default is program name."), + grecs_type_string, GRECS_DFLT, &tcpwrap_daemon }, + { "allow-table", N_("file"), + N_("Use file for positive client address access control " + "(default: /etc/hosts.allow)."), + grecs_type_string, GRECS_DFLT, &hosts_allow_table }, + { "deny-table", N_("file"), + N_("Use file for negative client address access control " + "(default: /etc/hosts.deny)."), + grecs_type_string, GRECS_DFLT, &hosts_deny_table }, + { "allow-syslog-priority", N_("prio"), + N_("Log host allows at this syslog priority."), + grecs_type_string, GRECS_DFLT, &allow_severity, 0, + cb_syslog_priority }, + { "deny-syslog-priority", N_("prio"), + N_("Log host denies at this syslog priority."), + grecs_type_string, GRECS_DFLT, &deny_severity, 0, + cb_syslog_priority }, + { NULL } }; int tcpwrap_access(int fd) { - struct request_info req; + struct request_info req; - if (!tcpwrap_enable) - return 1; - request_init(&req, - RQ_DAEMON, - tcpwrap_daemon ? tcpwrap_daemon : program_name, - RQ_FILE, fd, NULL); - fromhost(&req); - return hosts_access(&req); + if (!tcpwrap_enable) + return 1; + request_init(&req, + RQ_DAEMON, + tcpwrap_daemon ? tcpwrap_daemon : program_name, + RQ_FILE, fd, NULL); + fromhost(&req); + return hosts_access(&req); } #endif diff --git a/src/timer.c b/src/timer.c index 8881c9a..1c8d68d 100644 --- a/src/timer.c +++ b/src/timer.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2008-2011 Sergey Poznyakoff + Copyright (C) 2008-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -21,78 +21,73 @@ #include <string.h> #include <ctype.h> -struct timer_slot -{ - char *name; - double real; - double self_user; /* user time in sec */ - double self_system; /* system time in sec */ - double children_user; /* user time in sec */ - double children_system; /* system time in sec */ - struct timeval real_mark; - struct rusage self_mark; - struct rusage children_mark; +struct timer_slot { + char *name; + double real; + double self_user; /* user time in sec */ + double self_system; /* system time in sec */ + double children_user; /* user time in sec */ + double children_system; /* system time in sec */ + struct timeval real_mark; + struct rusage self_mark; + struct rusage children_mark; }; static struct grecs_symtab *timer_table; static size_t _timer_count; static unsigned -hash_string_ci (const char *string, unsigned long n_buckets) +hash_string_ci(const char *string, unsigned long n_buckets) { - size_t value = 0; - unsigned char ch; + size_t value = 0; + unsigned char ch; - for (; (ch = *string); string++) - value = (value * 31 + tolower (ch)) % n_buckets; - return value; + for (; (ch = *string); string++) + value = (value * 31 + tolower(ch)) % n_buckets; + return value; } static unsigned -timer_hasher (void *ptr, unsigned long n_buckets) +timer_hasher(void *ptr, unsigned long n_buckets) { - struct timer_slot *tp = ptr; - return hash_string_ci (tp->name, n_buckets); + struct timer_slot *tp = ptr; + return hash_string_ci(tp->name, n_buckets); } /* Lookup a timer by its name. If it does not exist, create it. */ wydawca_timer_t -timer_get (const char *name) -{ - struct timer_slot key, *ret; - int install = 1; - - key.name = (char*) name; - - if (!timer_table) - { - timer_table = grecs_symtab_create (sizeof (key), - timer_hasher, - NULL, - NULL, - NULL, - NULL); - if (!timer_table) - grecs_alloc_die (); - } - - ret = grecs_symtab_lookup_or_install (timer_table, &key, &install); - if (!ret) - grecs_alloc_die(); - if (install) - _timer_count++; - return ret; +timer_get(const char *name) +{ + struct timer_slot key, *ret; + int install = 1; + + key.name = (char *)name; + + if (!timer_table) { + timer_table = grecs_symtab_create(sizeof(key), + timer_hasher, + NULL, NULL, NULL, NULL); + if (!timer_table) + grecs_alloc_die(); + } + + ret = grecs_symtab_lookup_or_install(timer_table, &key, &install); + if (!ret) + grecs_alloc_die(); + if (install) + _timer_count++; + return ret; } wydawca_timer_t -timer_start (const char *name) +timer_start(const char *name) { - wydawca_timer_t t = timer_get (name); + wydawca_timer_t t = timer_get(name); - gettimeofday (&t->real_mark, NULL); - getrusage (RUSAGE_SELF, &t->self_mark); - getrusage (RUSAGE_CHILDREN, &t->children_mark); - return t; + gettimeofday(&t->real_mark, NULL); + getrusage(RUSAGE_SELF, &t->self_mark); + getrusage(RUSAGE_CHILDREN, &t->children_mark); + return t; } #define DIFFTIME(now,then)\ @@ -100,148 +95,148 @@ timer_start (const char *name) + ((double)((now).tv_usec - (then).tv_usec))/1000000) static void -_timer_compute (wydawca_timer_t t) +_timer_compute(wydawca_timer_t t) { - struct timeval real; - struct rusage rusage; - - gettimeofday (&real, NULL); - t->real = DIFFTIME (real, t->real_mark); - getrusage (RUSAGE_SELF, &rusage); - t->self_user = DIFFTIME (rusage.ru_utime, t->self_mark.ru_utime); - t->self_system = DIFFTIME (rusage.ru_stime, t->self_mark.ru_stime); - - getrusage (RUSAGE_CHILDREN, &rusage); - t->children_user = DIFFTIME (rusage.ru_utime, t->children_mark.ru_utime); - t->children_system = DIFFTIME (rusage.ru_stime, t->children_mark.ru_stime); + struct timeval real; + struct rusage rusage; + + gettimeofday(&real, NULL); + t->real = DIFFTIME(real, t->real_mark); + getrusage(RUSAGE_SELF, &rusage); + t->self_user = DIFFTIME(rusage.ru_utime, t->self_mark.ru_utime); + t->self_system = DIFFTIME(rusage.ru_stime, t->self_mark.ru_stime); + + getrusage(RUSAGE_CHILDREN, &rusage); + t->children_user = DIFFTIME(rusage.ru_utime, t->children_mark.ru_utime); + t->children_system = + DIFFTIME(rusage.ru_stime, t->children_mark.ru_stime); } wydawca_timer_t -timer_stop (const char *name) +timer_stop(const char *name) { - wydawca_timer_t t = timer_get (name); - _timer_compute (t); - return t; + wydawca_timer_t t = timer_get(name); + _timer_compute(t); + return t; } wydawca_timer_t -timer_reset (const char *name) -{ - wydawca_timer_t t = timer_get (name); - t->real = 0.0; - t->self_user = 0.0; - t->self_system = 0.0; - t->children_user = 0.0; - t->children_system = 0.0; - return t; +timer_reset(const char *name) +{ + wydawca_timer_t t = timer_get(name); + t->real = 0.0; + t->self_user = 0.0; + t->self_system = 0.0; + t->children_user = 0.0; + t->children_system = 0.0; + return t; } double -timer_get_real (wydawca_timer_t t) +timer_get_real(wydawca_timer_t t) { - return t->real; + return t->real; } double -timer_get_user (wydawca_timer_t t) +timer_get_user(wydawca_timer_t t) { - return t->self_user + t->children_user; + return t->self_user + t->children_user; } double -timer_get_system (wydawca_timer_t t) +timer_get_system(wydawca_timer_t t) { - return t->self_system + t->children_system; + return t->self_system + t->children_system; } char * -timer_format_time (double t) -{ - char *str = NULL; - size_t size = 0; - if (t < 600) - grecs_asprintf (&str, &size, "%0.3f", t); - else - { - long int s, m, h, d; - - s = (long int) t; - d = s / (3600 * 24); - s -= d * 3600 * 24; - h = s / 3600; - s -= h * 3600; - m = s / 60; - s -= m * 60; - - if (d) - grecs_asprintf (&str, &size, "%ld+%02ld:%02ld:%02ld", d, h, m, s); - else if (h) - grecs_asprintf (&str, &size, "%02ld:%02ld:%02ld", h, m, s); - else - grecs_asprintf (&str, &size, "%02ld:%02ld", m, s); - } - if (!str) - grecs_alloc_die (); - return str; +timer_format_time(double t) +{ + char *str = NULL; + size_t size = 0; + if (t < 600) + grecs_asprintf(&str, &size, "%0.3f", t); + else { + long int s, m, h, d; + + s = (long int)t; + d = s / (3600 * 24); + s -= d * 3600 * 24; + h = s / 3600; + s -= h * 3600; + m = s / 60; + s -= m * 60; + + if (d) + grecs_asprintf(&str, &size, "%ld+%02ld:%02ld:%02ld", d, + h, m, s); + else if (h) + grecs_asprintf(&str, &size, "%02ld:%02ld:%02ld", h, m, + s); + else + grecs_asprintf(&str, &size, "%02ld:%02ld", m, s); + } + if (!str) + grecs_alloc_die(); + return str; } size_t -timer_get_count () +timer_get_count() { - return _timer_count; + return _timer_count; } -struct timer_data -{ - struct metadef *def; - size_t num; +struct timer_data { + struct metadef *def; + size_t num; }; int -_fill_meta (void *sym, void *data) -{ - struct timer_slot *slot = sym; - struct timer_data *tp = data; -#define CREATE_DEF(arg) \ - if (tp->num) \ - { \ - char *buf = NULL; \ - size_t size = 0; \ - grecs_asprintf (&buf, &size, "timer:%s:%s", slot->name, #arg); \ - if (!buf) \ - grecs_alloc_die (); \ - tp->def->kw = buf; \ - tp->def->storage = timer_format_time (__cat2__(timer_get_,arg) (slot)); \ - tp->def->value = tp->def->storage; \ - tp->def->expand = NULL; \ - tp->def++; \ - tp->num--; \ - } - - CREATE_DEF(system); - CREATE_DEF(real); - CREATE_DEF(user); - - return tp->num <= 0; +_fill_meta(void *sym, void *data) +{ + struct timer_slot *slot = sym; + struct timer_data *tp = data; +#define CREATE_DEF(arg) \ + if (tp->num) { \ + char *buf = NULL; \ + size_t size = 0; \ + grecs_asprintf(&buf, &size, "timer:%s:%s", slot->name, #arg); \ + if (!buf) \ + grecs_alloc_die(); \ + tp->def->kw = buf; \ + tp->def->storage = \ + timer_format_time(__cat2__(timer_get_,arg)(slot)); \ + tp->def->value = tp->def->storage; \ + tp->def->expand = NULL; \ + tp->def++; \ + tp->num--; \ + } + + CREATE_DEF(system); + CREATE_DEF(real); + CREATE_DEF(user); + + return tp->num <= 0; } void -timer_fill_meta (struct metadef *def, size_t num) -{ - struct timer_data td; - if (!timer_table) - return; - td.def = def; - td.num = num; - grecs_symtab_enumerate (timer_table, _fill_meta, &td); +timer_fill_meta(struct metadef *def, size_t num) +{ + struct timer_data td; + if (!timer_table) + return; + td.def = def; + td.num = num; + grecs_symtab_enumerate(timer_table, _fill_meta, &td); } void -timer_free_meta (struct metadef *def, size_t num) +timer_free_meta(struct metadef *def, size_t num) { - while (num--) - { - free (def->kw); - def++; - } + while (num--) { + free(def->kw); + def++; + } } diff --git a/src/triplet.c b/src/triplet.c index a327b43..c4dc576 100644 --- a/src/triplet.c +++ b/src/triplet.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007-2011 Sergey Poznyakoff + Copyright (C) 2007-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -28,510 +28,489 @@ static struct file_triplet *triplet_list; /* Functions for building the ordered doubly-linked list of triplets */ static time_t -triplet_timestamp (struct file_triplet *tp) +triplet_timestamp(struct file_triplet *tp) { - int i; - time_t t = 0; + int i; + time_t t = 0; - if (!tp) - return 0; - - for (i = 0; i < FILE_TYPE_COUNT; i++) - { - if (tp->file[i].name && - (t == 0 || t > tp->file[i].sb.st_mtime)) - t = tp->file[i].sb.st_mtime; - } - return t; + if (!tp) + return 0; + + for (i = 0; i < FILE_TYPE_COUNT; i++) { + if (tp->file[i].name && + (t == 0 || t > tp->file[i].sb.st_mtime)) + t = tp->file[i].sb.st_mtime; + } + return t; } static time_t -triplet_ttl (struct file_triplet *tp) +triplet_ttl(struct file_triplet *tp) { - time_t t; + time_t t; - if (!tp) - return 0; - t = time (NULL) - triplet_timestamp (tp); - if (t < tp->spool->file_sweep_time) - return tp->spool->file_sweep_time - t; - return 0; + if (!tp) + return 0; + t = time(NULL) - triplet_timestamp(tp); + if (t < tp->spool->file_sweep_time) + return tp->spool->file_sweep_time - t; + return 0; } void -triplet_list_unlink (struct file_triplet *tp) +triplet_list_unlink(struct file_triplet *tp) { - if (tp->prev) - tp->prev->next = tp->next; - else - triplet_list = tp->next; + if (tp->prev) + tp->prev->next = tp->next; + else + triplet_list = tp->next; - if (tp->next) - tp->next->prev = tp->prev; - - tp->next = tp->prev = NULL; + if (tp->next) + tp->next->prev = tp->prev; + + tp->next = tp->prev = NULL; } static void -triplet_list_insert_before (struct file_triplet *newp, - struct file_triplet *anchor) +triplet_list_insert_before(struct file_triplet *newp, + struct file_triplet *anchor) { - if (!anchor) - { - triplet_list = newp; - return; - } + if (!anchor) { + triplet_list = newp; + return; + } - if (anchor->prev) - anchor->prev->next = newp; - else - triplet_list = newp; - newp->prev = anchor->prev; + if (anchor->prev) + anchor->prev->next = newp; + else + triplet_list = newp; + newp->prev = anchor->prev; - anchor->prev = newp; - newp->next = anchor; + anchor->prev = newp; + newp->next = anchor; } void -triplet_list_ordered_insert (struct file_triplet *tp) -{ - time_t t = triplet_timestamp (tp); - struct file_triplet *p, *prev = NULL; - - for (p = triplet_list; p && triplet_timestamp (p) < t; prev = p, p = p->next) - ; - if (p) - triplet_list_insert_before (tp, p); - else if (prev) - { - prev->next = tp; - tp->prev = prev; - tp->next = NULL; - } - else - { - tp->next = tp->prev = NULL; - triplet_list = tp; - } +triplet_list_ordered_insert(struct file_triplet *tp) +{ + time_t t = triplet_timestamp(tp); + struct file_triplet *p, *prev = NULL; + + for (p = triplet_list; p && triplet_timestamp(p) < t; + prev = p, p = p->next) ; + if (p) + triplet_list_insert_before(tp, p); + else if (prev) { + prev->next = tp; + tp->prev = prev; + tp->next = NULL; + } else { + tp->next = tp->prev = NULL; + triplet_list = tp; + } } - /* Functions for operation on a symtab of triplets. */ static unsigned -hash_triplet_hasher (void *data, unsigned long n_buckets) +hash_triplet_hasher(void *data, unsigned long n_buckets) { - struct file_triplet const *t = data; - return grecs_hash_string (t->name, n_buckets); + struct file_triplet const *t = data; + return grecs_hash_string(t->name, n_buckets); } /* Compare two strings for equality. */ static int -hash_triplet_compare (void const *data1, void const *data2) +hash_triplet_compare(void const *data1, void const *data2) { - struct file_triplet const *t1 = data1; - struct file_triplet const *t2 = data2; - return t1->spool == t2->spool && strcmp (t1->name, t2->name); + struct file_triplet const *t1 = data1; + struct file_triplet const *t2 = data2; + return t1->spool == t2->spool && strcmp(t1->name, t2->name); } /* Reclaim memory storage associated with a table entry */ void -hash_triplet_free (void *data) -{ - int i; - struct file_triplet *tp = data; - struct uploader_info *up; - - free (tp->name); - - for (i = 0; i < FILE_TYPE_COUNT; i++) - { - if (tp->file[i].name) - free (tp->file[i].name); - } - - free (tp->directive); - free (tp->blurb); - free (tp->tmp); - txtacc_free (tp->acc); - - /* Free uploader list */ - for (up = tp->uploader_list; up; ) - { - struct uploader_info *next = up->next; - free (up->fpr); - free (up); - up = next; - } - - free (tp); +hash_triplet_free(void *data) +{ + int i; + struct file_triplet *tp = data; + struct uploader_info *up; + + free(tp->name); + + for (i = 0; i < FILE_TYPE_COUNT; i++) { + if (tp->file[i].name) + free(tp->file[i].name); + } + + free(tp->directive); + free(tp->blurb); + free(tp->tmp); + txtacc_free(tp->acc); + + /* Free uploader list */ + for (up = tp->uploader_list; up;) { + struct uploader_info *next = up->next; + free(up->fpr); + free(up); + up = next; + } + + free(tp); } char * -triplet_strdup (struct file_triplet *tp, const char *str) +triplet_strdup(struct file_triplet *tp, const char *str) { - size_t len = strlen (str); - txtacc_grow (tp->acc, str, len + 1); - return txtacc_finish (tp->acc, 0); + size_t len = strlen(str); + txtacc_grow(tp->acc, str, len + 1); + return txtacc_finish(tp->acc, 0); } /* Register a file in the triplet table */ void -register_file (struct file_info *finfo, const struct spool *spool) -{ - struct file_triplet key, *ret; - int install = 1; - - if (!triplet_table) - { - triplet_table = grecs_symtab_create (sizeof (struct file_triplet), - hash_triplet_hasher, - hash_triplet_compare, - NULL, - NULL, - hash_triplet_free); - if (!triplet_table) - grecs_alloc_die (); - } - - key.name = grecs_malloc (finfo->root_len + 1); - memcpy (key.name, finfo->name, finfo->root_len); - key.name[finfo->root_len] = 0; - key.spool = spool; - - ret = grecs_symtab_lookup_or_install (triplet_table, &key, &install); - if (!ret) - grecs_alloc_die (); - free (key.name); - if (install) - { - ret->spool = spool; - ret->acc = txtacc_create (); - } - ret->file[finfo->type] = *finfo; - triplet_list_unlink (ret); - triplet_list_ordered_insert (ret); +register_file(struct file_info *finfo, const struct spool *spool) +{ + struct file_triplet key, *ret; + int install = 1; + + if (!triplet_table) { + triplet_table = + grecs_symtab_create(sizeof(struct file_triplet), + hash_triplet_hasher, + hash_triplet_compare, + NULL, + NULL, + hash_triplet_free); + if (!triplet_table) + grecs_alloc_die(); + } + + key.name = grecs_malloc(finfo->root_len + 1); + memcpy(key.name, finfo->name, finfo->root_len); + key.name[finfo->root_len] = 0; + key.spool = spool; + + ret = grecs_symtab_lookup_or_install(triplet_table, &key, &install); + if (!ret) + grecs_alloc_die(); + free(key.name); + if (install) { + ret->spool = spool; + ret->acc = txtacc_create(); + } + ret->file[finfo->type] = *finfo; + triplet_list_unlink(ret); + triplet_list_ordered_insert(ret); } struct file_triplet * -triplet_lookup (struct spool *spool, const char *name) +triplet_lookup(struct spool *spool, const char *name) { - struct file_triplet key, *ret; - struct file_info finfo; - - if (!triplet_table) - return NULL; + struct file_triplet key, *ret; + struct file_info finfo; - parse_file_name (name, &finfo); + if (!triplet_table) + return NULL; - key.name = grecs_malloc (finfo.root_len + 1); - memcpy (key.name, finfo.name, finfo.root_len); - key.name[finfo.root_len] = 0; - key.spool = spool; - file_info_cleanup (&finfo); + parse_file_name(name, &finfo); - ret = grecs_symtab_lookup_or_install (triplet_table, &key, NULL); - free (key.name); + key.name = grecs_malloc(finfo.root_len + 1); + memcpy(key.name, finfo.name, finfo.root_len); + key.name[finfo.root_len] = 0; + key.spool = spool; + file_info_cleanup(&finfo); - return ret; + ret = grecs_symtab_lookup_or_install(triplet_table, &key, NULL); + free(key.name); + + return ret; } /* Return true if any part of the triplet TRP was modified more than TTL seconds ago */ static int -triplet_expired_p (struct file_triplet *trp) -{ - int i; - time_t now = time (NULL); - time_t ttl = trp->spool->file_sweep_time; - - if (ttl == 0) - return 0; - - for (i = 0; i < FILE_TYPE_COUNT; i++) - { - if (trp->file[i].name - && (now - trp->file[i].sb.st_mtime) >= ttl) - { - if (debug_level) - logmsg (LOG_DEBUG, _("file %s expired"), trp->file[i].name); - return 1; +triplet_expired_p(struct file_triplet *trp) +{ + int i; + time_t now = time(NULL); + time_t ttl = trp->spool->file_sweep_time; + + if (ttl == 0) + return 0; + + for (i = 0; i < FILE_TYPE_COUNT; i++) { + if (trp->file[i].name + && (now - trp->file[i].sb.st_mtime) >= ttl) { + if (debug_level) + logmsg(LOG_DEBUG, _("file %s expired"), + trp->file[i].name); + return 1; + } } - } - return 0; -} - -enum triplet_state - { - triplet_directive, /* Short triplet: only a directive is present, - but nothing more is required */ - triplet_complete, /* A complete triplet: all three files are present - and have the same owner */ - triplet_incomplete, /* Incomplete triplet: some files are missing */ - triplet_bad, /* Bad triplet. Should be removed immediately. */ - }; - + return 0; +} + +enum triplet_state { + triplet_directive, /* Short triplet: only a directive is present, + but nothing more is required */ + triplet_complete, /* A complete triplet: all three files are + present and have the same owner */ + triplet_incomplete, /* Incomplete triplet: some files are + missing */ + triplet_bad, /* Bad triplet. Should be removed + immediately. */ +}; static enum triplet_state -check_triplet_state (struct file_triplet *trp, int noauth) -{ - if (trp->file[file_directive].name) - { - if (verify_directive_file (trp, noauth)) - return triplet_bad; - - if (trp->file[file_dist].name == 0 - && trp->file[file_signature].name == 0) - { - if (directive_get_value (trp, "filename", NULL)) - return triplet_directive; - } - else if (trp->file[file_dist].name && trp->file[file_signature].name) - { - if (trp->file[file_dist].sb.st_uid == - trp->file[file_signature].sb.st_uid - && trp->file[file_dist].sb.st_uid == - trp->file[file_directive].sb.st_uid) - return triplet_complete; - else - { - if (debug_level) - logmsg (LOG_DEBUG, _("%s: invalid triplet: UIDs differ"), - trp->name); - return triplet_bad; - } +check_triplet_state(struct file_triplet *trp, int noauth) +{ + if (trp->file[file_directive].name) { + if (verify_directive_file(trp, noauth)) + return triplet_bad; + + if (trp->file[file_dist].name == 0 && + trp->file[file_signature].name == 0) { + if (directive_get_value(trp, "filename", NULL)) + return triplet_directive; + } else if (trp->file[file_dist].name && + trp->file[file_signature].name) { + if (trp->file[file_dist].sb.st_uid == + trp->file[file_signature].sb.st_uid && + trp->file[file_dist].sb.st_uid == + trp->file[file_directive].sb.st_uid) + return triplet_complete; + else { + if (debug_level) + logmsg(LOG_DEBUG, + _("%s: invalid triplet: " + "UIDs differ"), + trp->name); + return triplet_bad; + } + } } - } - return triplet_incomplete; + return triplet_incomplete; } /* Unlink all parts of the triplet TRP */ static void -remove_triplet (struct file_triplet *trp) -{ - int i; - - for (i = 0; i < FILE_TYPE_COUNT; i++) - { - if (trp->file[i].name) - { - logmsg (LOG_NOTICE, _("removing %s"), trp->file[i].name); - if (!dry_run_mode && unlink (trp->file[i].name)) - logmsg (LOG_ERR, _("cannot remove %s: %s"), - trp->file[i].name, strerror (errno)); +remove_triplet(struct file_triplet *trp) +{ + int i; + + for (i = 0; i < FILE_TYPE_COUNT; i++) { + if (trp->file[i].name) { + logmsg(LOG_NOTICE, _("removing %s"), + trp->file[i].name); + if (!dry_run_mode && unlink(trp->file[i].name)) + logmsg(LOG_ERR, _("cannot remove %s: %s"), + trp->file[i].name, strerror(errno)); + } } - } - triplet_list_unlink (trp); - grecs_symtab_remove (triplet_table, trp); + triplet_list_unlink(trp); + grecs_symtab_remove(triplet_table, trp); } time_t -triplet_sweep (void) +triplet_sweep(void) { - while (triplet_list && triplet_expired_p (triplet_list)) - remove_triplet (triplet_list); + while (triplet_list && triplet_expired_p(triplet_list)) + remove_triplet(triplet_list); - return triplet_ttl (triplet_list); + return triplet_ttl(triplet_list); } /* Process a single triplet from the table */ static int -triplet_processor (void *data, void *proc_data) -{ - struct file_triplet *trp = data; - - if (debug_level) - logmsg (LOG_DEBUG, "FILE %s, DIST=%s, SIG=%s, DIRECTIVE=%s", - trp->name, - SP (trp->file[file_dist].name), - SP (trp->file[file_signature].name), - SP (trp->file[file_directive].name)); - - switch (check_triplet_state (trp, 0)) - { - case triplet_directive: - case triplet_complete: - if (debug_level) - logmsg (LOG_DEBUG, _("processing triplet `%s'"), trp->name); - if (process_directives (trp)) - remove_triplet (trp); - return 0; - - case triplet_incomplete: - if (debug_level) - logmsg (LOG_DEBUG, _("%s: incomplete triplet"), trp->name); - /* ignore unless expired (see below); */ - UPDATE_STATS (STAT_INCOMPLETE_TRIPLETS); - break; - - case triplet_bad: - UPDATE_STATS (STAT_BAD_TRIPLETS); - remove_triplet (trp); - return 0; - } - - if (triplet_expired_p (trp)) - { - UPDATE_STATS (STAT_EXPIRED_TRIPLETS); - remove_triplet (trp); - } - - return 0; +triplet_processor(void *data, void *proc_data) +{ + struct file_triplet *trp = data; + + if (debug_level) + logmsg(LOG_DEBUG, "FILE %s, DIST=%s, SIG=%s, DIRECTIVE=%s", + trp->name, + SP(trp->file[file_dist].name), + SP(trp->file[file_signature].name), + SP(trp->file[file_directive].name)); + + switch (check_triplet_state(trp, 0)) { + case triplet_directive: + case triplet_complete: + if (debug_level) + logmsg(LOG_DEBUG, _("processing triplet `%s'"), + trp->name); + if (process_directives(trp)) + remove_triplet(trp); + return 0; + + case triplet_incomplete: + if (debug_level) + logmsg(LOG_DEBUG, _("%s: incomplete triplet"), + trp->name); + /* ignore unless expired (see below); */ + UPDATE_STATS(STAT_INCOMPLETE_TRIPLETS); + break; + + case triplet_bad: + UPDATE_STATS(STAT_BAD_TRIPLETS); + remove_triplet(trp); + return 0; + } + + if (triplet_expired_p(trp)) { + UPDATE_STATS(STAT_EXPIRED_TRIPLETS); + remove_triplet(trp); + } + + return 0; } /* Process all triplets from the table according to the SPOOL */ void -spool_commit_triplets (struct spool *spool) -{ - if (debug_level) - logmsg (LOG_DEBUG, _("processing spool %s (%s)"), - spool->tag, mu_url_to_string (spool->dest_url)); - if (spool_open_dictionaries (spool)) - return; - if (triplet_table) - { - grecs_symtab_enumerate (triplet_table, triplet_processor, NULL); - grecs_symtab_clear (triplet_table); - } +spool_commit_triplets(struct spool *spool) +{ + if (debug_level) + logmsg(LOG_DEBUG, _("processing spool %s (%s)"), + spool->tag, mu_url_to_string(spool->dest_url)); + if (spool_open_dictionaries(spool)) + return; + if (triplet_table) { + grecs_symtab_enumerate(triplet_table, triplet_processor, NULL); + grecs_symtab_clear(triplet_table); + } } size_t -count_collected_triplets () +count_collected_triplets() { - return triplet_table ? grecs_symtab_count_entries (triplet_table) : 0; + return triplet_table ? grecs_symtab_count_entries(triplet_table) : 0; } static int -triplet_counter (void *data, void *proc_data) -{ - struct file_triplet *trp = data; - size_t *cp = proc_data; - - if (debug_level) - logmsg (LOG_DEBUG, "FILE %s, DIST=%s, SIG=%s, DIRECTIVE=%s", - trp->name, - SP (trp->file[file_dist].name), - SP (trp->file[file_signature].name), - SP (trp->file[file_directive].name)); - - switch (check_triplet_state (trp, 1)) - { - case triplet_directive: - case triplet_complete: - if (triplet_expired_p (trp)) - remove_triplet (trp); - else - ++*cp; - break; - case triplet_incomplete: - break; - case triplet_bad: - remove_triplet (trp); - } - - return 0; +triplet_counter(void *data, void *proc_data) +{ + struct file_triplet *trp = data; + size_t *cp = proc_data; + + if (debug_level) + logmsg(LOG_DEBUG, "FILE %s, DIST=%s, SIG=%s, DIRECTIVE=%s", + trp->name, + SP(trp->file[file_dist].name), + SP(trp->file[file_signature].name), + SP(trp->file[file_directive].name)); + + switch (check_triplet_state(trp, 1)) { + case triplet_directive: + case triplet_complete: + if (triplet_expired_p(trp)) + remove_triplet(trp); + else + ++*cp; + break; + case triplet_incomplete: + break; + case triplet_bad: + remove_triplet(trp); + } + + return 0; } size_t -count_processable_triplets () +count_processable_triplets() { - size_t count = 0; - if (triplet_table) - grecs_symtab_enumerate (triplet_table, triplet_counter, &count); - return count; + size_t count = 0; + if (triplet_table) + grecs_symtab_enumerate(triplet_table, triplet_counter, &count); + return count; } void -triplet_remove_file (struct spool *spool, const char *name) -{ - struct file_triplet *tp = triplet_lookup (spool, name); - int i, n = 0; - - if (!tp) - return; - - for (i = 0; i < FILE_TYPE_COUNT; i++) - { - if (!tp->file[i].name) - /* nothing */; - else if (strcmp (tp->file[i].name, name) == 0) - file_info_cleanup (&tp->file[i]); - else - n++; - } - - if (!n) - { - if (debug_level > 0) - logmsg (LOG_DEBUG, "deleting empty triplet (%s/%s)", - spool->source_dir, name); - remove_triplet (tp); - } -} +triplet_remove_file(struct spool *spool, const char *name) +{ + struct file_triplet *tp = triplet_lookup(spool, name); + int i, n = 0; + + if (!tp) + return; + + for (i = 0; i < FILE_TYPE_COUNT; i++) { + if (!tp->file[i].name) + /* nothing */ ; + else if (strcmp(tp->file[i].name, name) == 0) + file_info_cleanup(&tp->file[i]); + else + n++; + } + if (!n) { + if (debug_level > 0) + logmsg(LOG_DEBUG, "deleting empty triplet (%s/%s)", + spool->source_dir, name); + remove_triplet(tp); + } +} static const char * -expand_project_base (struct metadef *def, void *data) +expand_project_base(struct metadef *def, void *data) { - struct file_triplet *trp = data; - return trp->project; + struct file_triplet *trp = data; + return trp->project; } static const char * -expand_tag (struct metadef *def, void *data) +expand_tag(struct metadef *def, void *data) { - struct file_triplet *trp = data; - return trp->spool->tag; + struct file_triplet *trp = data; + return trp->spool->tag; } static const char * -expand_url (struct metadef *def, void *data) +expand_url(struct metadef *def, void *data) { - struct file_triplet *trp = data; - return trp->spool->url; + struct file_triplet *trp = data; + return trp->spool->url; } static const char * -expand_relative_dir (struct metadef *def, void *data) +expand_relative_dir(struct metadef *def, void *data) { - struct file_triplet *trp = data; - directive_get_value (trp, "directory", (const char**) &def->value); - return def->value; + struct file_triplet *trp = data; + directive_get_value(trp, "directory", (const char **)&def->value); + return def->value; } static const char * -expand_dest_dir (struct metadef *def, void *data) +expand_dest_dir(struct metadef *def, void *data) { - struct file_triplet *trp = data; - return trp->spool->dest_dir; + struct file_triplet *trp = data; + return trp->spool->dest_dir; } static const char * -expand_source_dir (struct metadef *def, void *data) +expand_source_dir(struct metadef *def, void *data) { - struct file_triplet *trp = data; - return trp->spool->source_dir; + struct file_triplet *trp = data; + return trp->spool->source_dir; } static void -decode_file_mode (mode_t mode, char *string) -{ - *string++ = mode & S_IRUSR ? 'r' : '-'; - *string++ = mode & S_IWUSR ? 'w' : '-'; - *string++ = (mode & S_ISUID - ? (mode & S_IXUSR ? 's' : 'S') - : (mode & S_IXUSR ? 'x' : '-')); - *string++ = mode & S_IRGRP ? 'r' : '-'; - *string++ = mode & S_IWGRP ? 'w' : '-'; - *string++ = (mode & S_ISGID - ? (mode & S_IXGRP ? 's' : 'S') - : (mode & S_IXGRP ? 'x' : '-')); - *string++ = mode & S_IROTH ? 'r' : '-'; - *string++ = mode & S_IWOTH ? 'w' : '-'; - *string++ = (mode & S_ISVTX - ? (mode & S_IXOTH ? 't' : 'T') - : (mode & S_IXOTH ? 'x' : '-')); - *string = '\0'; +decode_file_mode(mode_t mode, char *string) +{ + *string++ = mode & S_IRUSR ? 'r' : '-'; + *string++ = mode & S_IWUSR ? 'w' : '-'; + *string++ = (mode & S_ISUID ? (mode & S_IXUSR ? 's' : 'S') + : (mode & S_IXUSR ? 'x' : '-')); + *string++ = mode & S_IRGRP ? 'r' : '-'; + *string++ = mode & S_IWGRP ? 'w' : '-'; + *string++ = (mode & S_ISGID ? (mode & S_IXGRP ? 's' : 'S') + : (mode & S_IXGRP ? 'x' : '-')); + *string++ = mode & S_IROTH ? 'r' : '-'; + *string++ = mode & S_IWOTH ? 'w' : '-'; + *string++ = (mode & S_ISVTX ? (mode & S_IXOTH ? 't' : 'T') + : (mode & S_IXOTH ? 'x' : '-')); + *string = '\0'; } /* Width of "user/group size", with initial value chosen @@ -542,360 +521,349 @@ decode_file_mode (mode_t mode, char *string) static int ugswidth = 19; static int -format_file_data (struct file_triplet *trp, enum file_type type, char **pret) -{ - char modes[11]; - struct file_info *info = trp->file + type; - char timebuf[sizeof "YYYY-MM-DD HH:MM:SS +0000"]; - struct passwd *pw; - struct group *grp; - char *sptr = NULL; - size_t slen = 0; - int pad; - char *user_name; - char *group_name; - struct tm *tm; - char *buf = NULL; - size_t size = 0; - - if (!info->name) - return 1; - - /* MODE OWNER GROUP SIZE MTIME FILE_NAME MD5SUM? */ - - modes[0] = '-'; /* Only regular files are allowed */ - decode_file_mode (info->sb.st_mode, modes + 1); - - /* File time */ - tm = localtime (&info->sb.st_mtime); - strftime (timebuf, sizeof timebuf, "%Y-%m-%d %H:%M:%S %z", tm); - - pw = getpwuid (TRIPLET_UID (trp)); - if (!pw) - user_name = "unknown"; - else - user_name = pw->pw_name; - - grp = getgrgid (TRIPLET_GID (trp)); - if (!grp) - group_name = "unknown"; /* should not happen */ - else - group_name = grp->gr_name; - - /* Size */ - if (grecs_asprintf (&sptr, &slen, "%lu", (unsigned long) info->sb.st_size)) - grecs_alloc_die (); - - /* Figure out padding and format the buffer */ - slen = strlen (sptr); - pad = strlen (user_name) + 1 + strlen (group_name) + 1 + slen; - if (pad > ugswidth) - ugswidth = pad; - - if (grecs_asprintf (&buf, &size, - "%s %s %s %*s %s %s", - modes, user_name, group_name, ugswidth - pad + slen, - sptr, - timebuf, info->name)) - grecs_alloc_die (); - free (sptr); - *pret = buf; - return 0; +format_file_data(struct file_triplet *trp, enum file_type type, char **pret) +{ + char modes[11]; + struct file_info *info = trp->file + type; + char timebuf[sizeof "YYYY-MM-DD HH:MM:SS +0000"]; + struct passwd *pw; + struct group *grp; + char *sptr = NULL; + size_t slen = 0; + int pad; + char *user_name; + char *group_name; + struct tm *tm; + char *buf = NULL; + size_t size = 0; + + if (!info->name) + return 1; + + /* MODE OWNER GROUP SIZE MTIME FILE_NAME MD5SUM? */ + + modes[0] = '-'; /* Only regular files are allowed */ + decode_file_mode(info->sb.st_mode, modes + 1); + + /* File time */ + tm = localtime(&info->sb.st_mtime); + strftime(timebuf, sizeof timebuf, "%Y-%m-%d %H:%M:%S %z", tm); + + pw = getpwuid(TRIPLET_UID(trp)); + if (!pw) + user_name = "unknown"; + else + user_name = pw->pw_name; + + grp = getgrgid(TRIPLET_GID(trp)); + if (!grp) + group_name = "unknown"; /* should not happen */ + else + group_name = grp->gr_name; + + /* Size */ + if (grecs_asprintf + (&sptr, &slen, "%lu", (unsigned long)info->sb.st_size)) + grecs_alloc_die(); + + /* Figure out padding and format the buffer */ + slen = strlen(sptr); + pad = strlen(user_name) + 1 + strlen(group_name) + 1 + slen; + if (pad > ugswidth) + ugswidth = pad; + + if (grecs_asprintf(&buf, &size, + "%s %s %s %*s %s %s", + modes, user_name, group_name, ugswidth - pad + slen, + sptr, timebuf, info->name)) + grecs_alloc_die(); + free(sptr); + *pret = buf; + return 0; } static const char * -expand_triplet_ls_full (struct metadef *def, void *data) -{ - struct file_triplet *trp = data; - char *buf[FILE_TYPE_COUNT] = { NULL, NULL, NULL }; - size_t size = 0; - - if (format_file_data (trp, file_dist, &buf[file_dist]) == 0) - size += strlen (buf[file_dist]) + 1; - if (format_file_data (trp, file_signature, &buf[file_signature]) == 0) - size += strlen (buf[file_signature]) + 1; - if (format_file_data (trp, file_directive, &buf[file_directive]) == 0) - size += strlen (buf[file_directive]) + 1; - - def->value = def->storage = grecs_malloc (size + 1); - def->value[0] = 0; - if (buf[file_dist]) - { - strcat (def->value, buf[file_dist]); - strcat (def->value, "\n"); - } - if (buf[file_signature]) - { - strcat (def->value, buf[file_signature]); - strcat (def->value, "\n"); - } - if (buf[file_directive]) - { - strcat (def->value, buf[file_directive]); - strcat (def->value, "\n"); - } - free (buf[file_dist]); - free (buf[file_signature]); - free (buf[file_directive]); - return def->value; +expand_triplet_ls_full(struct metadef *def, void *data) +{ + struct file_triplet *trp = data; + char *buf[FILE_TYPE_COUNT] = { NULL, NULL, NULL }; + size_t size = 0; + + if (format_file_data(trp, file_dist, &buf[file_dist]) == 0) + size += strlen(buf[file_dist]) + 1; + if (format_file_data(trp, file_signature, &buf[file_signature]) == 0) + size += strlen(buf[file_signature]) + 1; + if (format_file_data(trp, file_directive, &buf[file_directive]) == 0) + size += strlen(buf[file_directive]) + 1; + + def->value = def->storage = grecs_malloc(size + 1); + def->value[0] = 0; + if (buf[file_dist]) { + strcat(def->value, buf[file_dist]); + strcat(def->value, "\n"); + } + if (buf[file_signature]) { + strcat(def->value, buf[file_signature]); + strcat(def->value, "\n"); + } + if (buf[file_directive]) { + strcat(def->value, buf[file_directive]); + strcat(def->value, "\n"); + } + free(buf[file_dist]); + free(buf[file_signature]); + free(buf[file_directive]); + return def->value; } static const char * -expand_triplet_ls_upload (struct metadef *def, void *data) -{ - struct file_triplet *trp = data; - char *buf[2] = { NULL, NULL }; - size_t size = 0; - - if (format_file_data (trp, file_dist, &buf[file_dist]) == 0) - size += strlen (buf[file_dist]) + 1; - if (format_file_data (trp, file_signature, &buf[file_signature]) == 0) - size += strlen (buf[file_signature]) + 1; - - def->value = def->storage = grecs_malloc (size + 1); - def->value[0] = 0; - if (buf[file_dist]) - { - strcat (def->value, buf[file_dist]); - strcat (def->value, "\n"); - } - if (buf[file_signature]) - { - strcat (def->value, buf[file_signature]); - strcat (def->value, "\n"); - } +expand_triplet_ls_upload(struct metadef *def, void *data) +{ + struct file_triplet *trp = data; + char *buf[2] = { NULL, NULL }; + size_t size = 0; + + if (format_file_data(trp, file_dist, &buf[file_dist]) == 0) + size += strlen(buf[file_dist]) + 1; + if (format_file_data(trp, file_signature, &buf[file_signature]) == 0) + size += strlen(buf[file_signature]) + 1; + + def->value = def->storage = grecs_malloc(size + 1); + def->value[0] = 0; + if (buf[file_dist]) { + strcat(def->value, buf[file_dist]); + strcat(def->value, "\n"); + } + if (buf[file_signature]) { + strcat(def->value, buf[file_signature]); + strcat(def->value, "\n"); + } - free (buf[file_dist]); - free (buf[file_signature]); + free(buf[file_dist]); + free(buf[file_signature]); - return def->value; + return def->value; } static const char * -expand_triplet_dist (struct metadef *def, void *data) +expand_triplet_dist(struct metadef *def, void *data) { - struct file_triplet *trp = data; - return trp->file[file_dist].name; + struct file_triplet *trp = data; + return trp->file[file_dist].name; } static const char * -expand_triplet_sig (struct metadef *def, void *data) +expand_triplet_sig(struct metadef *def, void *data) { - struct file_triplet *trp = data; - return trp->file[file_signature].name; + struct file_triplet *trp = data; + return trp->file[file_signature].name; } static const char * -expand_triplet_dir (struct metadef *def, void *data) +expand_triplet_dir(struct metadef *def, void *data) { - struct file_triplet *trp = data; - return trp->file[file_directive].name; + struct file_triplet *trp = data; + return trp->file[file_directive].name; } static const char * -expand_triplet_ls_dist (struct metadef *def, void *data) +expand_triplet_ls_dist(struct metadef *def, void *data) { - struct file_triplet *trp = data; - format_file_data (trp, file_dist, &def->storage); - def->value = def->storage; - return def->value; + struct file_triplet *trp = data; + format_file_data(trp, file_dist, &def->storage); + def->value = def->storage; + return def->value; } static const char * -expand_triplet_ls_sig (struct metadef *def, void *data) +expand_triplet_ls_sig(struct metadef *def, void *data) { - struct file_triplet *trp = data; - format_file_data (trp, file_signature, &def->storage); - def->value = def->storage; - return def->value; + struct file_triplet *trp = data; + format_file_data(trp, file_signature, &def->storage); + def->value = def->storage; + return def->value; } static const char * -expand_triplet_ls_directive (struct metadef *def, void *data) +expand_triplet_ls_directive(struct metadef *def, void *data) { - struct file_triplet *trp = data; - format_file_data (trp, file_directive, &def->storage); - def->value = def->storage; - return def->value; + struct file_triplet *trp = data; + format_file_data(trp, file_directive, &def->storage); + def->value = def->storage; + return def->value; } static const char * -expand_user_name (struct metadef *def, void *data) +expand_user_name(struct metadef *def, void *data) { - struct file_triplet *trp = data; - if (trp->uploader) - return trp->uploader->name; - def->value = "UNKNOWN"; - return def->value; + struct file_triplet *trp = data; + if (trp->uploader) + return trp->uploader->name; + def->value = "UNKNOWN"; + return def->value; } static const char * -expand_user_real_name (struct metadef *def, void *data) +expand_user_real_name(struct metadef *def, void *data) { - struct file_triplet *trp = data; - if (trp->uploader) - return trp->uploader->realname; - def->value = "UNKNOWN"; - return def->value; + struct file_triplet *trp = data; + if (trp->uploader) + return trp->uploader->realname; + def->value = "UNKNOWN"; + return def->value; } static const char * -expand_user_email (struct metadef *def, void *data) +expand_user_email(struct metadef *def, void *data) { - struct file_triplet *trp = data; - if (trp->uploader) - return trp->uploader->email; - def->value = "UNKNOWN"; - return def->value; + struct file_triplet *trp = data; + if (trp->uploader) + return trp->uploader->email; + def->value = "UNKNOWN"; + return def->value; } static const char * -expand_email_user (struct metadef *def, void *data) -{ - struct file_triplet *trp = data; - if (trp->uploader) - { - size_t size = 0; - if (grecs_asprintf (&def->storage, &size, "\"%s\" <%s>", - trp->uploader->realname, trp->uploader->email)) - grecs_alloc_die (); - def->value = def->storage; - } - return def->value; +expand_email_user(struct metadef *def, void *data) +{ + struct file_triplet *trp = data; + if (trp->uploader) { + size_t size = 0; + if (grecs_asprintf(&def->storage, &size, "\"%s\" <%s>", + trp->uploader->realname, + trp->uploader->email)) + grecs_alloc_die(); + def->value = def->storage; + } + return def->value; } static const char * -expand_report (struct metadef *def, void *data) +expand_report(struct metadef *def, void *data) { - return report_string; + return report_string; } static const char * -expand_comment (struct metadef *def, void *data) +expand_comment(struct metadef *def, void *data) { - struct file_triplet *trp = data; - if (directive_get_value (trp, "comment", (const char**) &def->value)) - def->value = ""; - return def->value; + struct file_triplet *trp = data; + if (directive_get_value(trp, "comment", (const char **)&def->value)) + def->value = ""; + return def->value; } static const char * -expand_check_diagn (struct metadef *def, void *data) +expand_check_diagn(struct metadef *def, void *data) { - struct file_triplet *trp = data; - return trp->check_diag; + struct file_triplet *trp = data; + return trp->check_diag; } static const char * -expand_check_result (struct metadef *def, void *data) -{ - struct file_triplet *trp = data; - int status = trp->check_result; - - if (status == 0) - return def->value = "0"; - else if (WIFEXITED (status)) - { - size_t size = 0; - def->storage = NULL; - if (grecs_asprintf (&def->storage, &size, - "%d", WEXITSTATUS (status))) - grecs_alloc_die (); - } - else if (WIFSIGNALED (status)) - { - size_t size = 0; - def->storage = NULL; - if (grecs_asprintf (&def->storage, &size, "SIG+%d", - WTERMSIG (status))) - grecs_alloc_die (); - } - else - return def->value = "[unrecognized return code]"; - return def->value = def->storage; +expand_check_result(struct metadef *def, void *data) +{ + struct file_triplet *trp = data; + int status = trp->check_result; + + if (status == 0) + return def->value = "0"; + else if (WIFEXITED(status)) { + size_t size = 0; + def->storage = NULL; + if (grecs_asprintf(&def->storage, &size, + "%d", WEXITSTATUS(status))) + grecs_alloc_die(); + } else if (WIFSIGNALED(status)) { + size_t size = 0; + def->storage = NULL; + if (grecs_asprintf(&def->storage, &size, "SIG+%d", + WTERMSIG(status))) + grecs_alloc_die(); + } else + return def->value = "[unrecognized return code]"; + return def->value = def->storage; } #define DECL_EXPAND_TIMER(what) \ static const char * \ __cat2__(expand_timer_,what) (struct metadef *def, void *data) \ { \ - wydawca_timer_t t = timer_stop ((char*)def->data); \ - def->storage = timer_format_time (__cat2__(timer_get_,what) (t)); \ - return def->value = def->storage; \ + wydawca_timer_t t = timer_stop ((char*)def->data); \ + def->storage = timer_format_time (__cat2__(timer_get_,what) (t)); \ + return def->value = def->storage; \ } DECL_EXPAND_TIMER(real) DECL_EXPAND_TIMER(user) DECL_EXPAND_TIMER(system) - #define DECL_TIMER(name,t) \ { "timer:" #name ":" #t, NULL, __cat2__(expand_timer_,t), NULL, #name } #define DECL_FULL_TIMER(name) \ DECL_TIMER(name, real), \ DECL_TIMER(name, user), \ - DECL_TIMER(name, system) - + DECL_TIMER(name, system) struct metadef triplet_default_meta[] = { - { "u", NULL, expand_user_name, NULL }, - { "user", NULL, expand_user_name, NULL }, - { "user:name", NULL, expand_user_name, NULL }, - { "p", NULL, expand_project_base, NULL }, - { "project", NULL, expand_project_base, NULL }, - { "url", NULL, expand_url, NULL }, - { "spool", NULL, expand_tag, NULL }, - { "dir", NULL, expand_relative_dir, NULL }, - { "dest-dir", NULL, expand_dest_dir, NULL }, - { "source-dir", NULL, expand_source_dir, NULL }, - { "comment", NULL, expand_comment, NULL }, - { NULL } + { "u", NULL, expand_user_name, NULL }, + { "user", NULL, expand_user_name, NULL }, + { "user:name", NULL, expand_user_name, NULL }, + { "p", NULL, expand_project_base, NULL }, + { "project", NULL, expand_project_base, NULL }, + { "url", NULL, expand_url, NULL }, + { "spool", NULL, expand_tag, NULL }, + { "dir", NULL, expand_relative_dir, NULL }, + { "dest-dir", NULL, expand_dest_dir, NULL }, + { "source-dir", NULL, expand_source_dir, NULL }, + { "comment", NULL, expand_comment, NULL }, + { NULL } }; char * -triplet_expand_dictionary_query (struct dictionary *dict, void *handle, - struct file_triplet *trp) +triplet_expand_dictionary_query(struct dictionary *dict, void *handle, + struct file_triplet *trp) { - char *p = meta_expand_string (dict->query, triplet_default_meta, trp, - dict, handle); - meta_free (triplet_default_meta); - return p; + char *p = meta_expand_string(dict->query, triplet_default_meta, trp, + dict, handle); + meta_free(triplet_default_meta); + return p; } struct metadef triplet_meta[] = { - { "project", NULL, expand_project_base, NULL }, - { "url", NULL, expand_url, NULL }, - { "spool", NULL, expand_tag, NULL }, - { "dir", NULL, expand_relative_dir, NULL }, - { "dest-dir", NULL, expand_dest_dir, NULL }, - { "source-dir", NULL, expand_source_dir, NULL }, - { "triplet:dist", NULL, expand_triplet_dist, NULL }, - { "triplet:sig", NULL, expand_triplet_sig, NULL }, - { "triplet:dir", NULL, expand_triplet_dir, NULL }, - { "triplet:ls:full", NULL, expand_triplet_ls_full, NULL }, - { "triplet:ls:upload", NULL, expand_triplet_ls_upload, NULL }, - { "triplet:ls:dist", NULL, expand_triplet_ls_dist, NULL }, - { "triplet:ls:sig", NULL, expand_triplet_ls_sig, NULL }, - { "triplet:ls:dir", NULL, expand_triplet_ls_directive, NULL }, - { "check:result", NULL, expand_check_result, NULL }, - { "check:diagn", NULL, expand_check_diagn, NULL }, - { "user", NULL, expand_user_name, NULL }, - { "user:name", NULL, expand_user_name, NULL }, - { "user:real-name", NULL, expand_user_real_name, NULL }, - { "user:email", NULL, expand_user_email, NULL }, - { "email:user", NULL, expand_email_user, NULL }, - { "email:admin", NULL, expand_email_admin, NULL }, - { "email:owner", NULL, expand_email_owner, NULL }, - { "report", NULL, expand_report, NULL }, - { "comment", NULL, expand_comment, NULL }, - DECL_FULL_TIMER(wydawca), - DECL_FULL_TIMER(triplet), - DECL_FULL_TIMER(spool), - { NULL } + { "project", NULL, expand_project_base, NULL }, + { "url", NULL, expand_url, NULL }, + { "spool", NULL, expand_tag, NULL }, + { "dir", NULL, expand_relative_dir, NULL }, + { "dest-dir", NULL, expand_dest_dir, NULL }, + { "source-dir", NULL, expand_source_dir, NULL }, + { "triplet:dist", NULL, expand_triplet_dist, NULL }, + { "triplet:sig", NULL, expand_triplet_sig, NULL }, + { "triplet:dir", NULL, expand_triplet_dir, NULL }, + { "triplet:ls:full", NULL, expand_triplet_ls_full, NULL }, + { "triplet:ls:upload", NULL, expand_triplet_ls_upload, NULL }, + { "triplet:ls:dist", NULL, expand_triplet_ls_dist, NULL }, + { "triplet:ls:sig", NULL, expand_triplet_ls_sig, NULL }, + { "triplet:ls:dir", NULL, expand_triplet_ls_directive, NULL }, + { "check:result", NULL, expand_check_result, NULL }, + { "check:diagn", NULL, expand_check_diagn, NULL }, + { "user", NULL, expand_user_name, NULL }, + { "user:name", NULL, expand_user_name, NULL }, + { "user:real-name", NULL, expand_user_real_name, NULL }, + { "user:email", NULL, expand_user_email, NULL }, + { "email:user", NULL, expand_email_user, NULL }, + { "email:admin", NULL, expand_email_admin, NULL }, + { "email:owner", NULL, expand_email_owner, NULL }, + { "report", NULL, expand_report, NULL }, + { "comment", NULL, expand_comment, NULL }, + DECL_FULL_TIMER(wydawca), + DECL_FULL_TIMER(triplet), + DECL_FULL_TIMER(spool), + { NULL} }; char * -triplet_expand_param (const char *tmpl, struct file_triplet *trp) +triplet_expand_param(const char *tmpl, struct file_triplet *trp) { - char *p = meta_expand_string (tmpl, triplet_meta, trp, NULL, NULL); - meta_free (triplet_meta); - return p; + char *p = meta_expand_string(tmpl, triplet_meta, trp, NULL, NULL); + meta_free(triplet_meta); + return p; } diff --git a/src/txtacc.c b/src/txtacc.c index d5da901..a1b96ed 100644 --- a/src/txtacc.c +++ b/src/txtacc.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007, 2009-2011 Sergey Poznyakoff + Copyright (C) 2007, 2009-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -16,169 +16,157 @@ #include "wydawca.h" -struct txtacc_entry -{ - char *buf; /* Text buffer */ - size_t size; /* Buffer size */ - size_t len; /* Actual number of bytes in buffer */ +struct txtacc_entry { + char *buf; /* Text buffer */ + size_t size; /* Buffer size */ + size_t len; /* Actual number of bytes in buffer */ }; #define TXTACC_BUFSIZE 1024 #define txtacc_entry_freesize(e) ((e)->size - (e)->len) -struct txtacc -{ - struct grecs_list *cur; /* Current build list */ - struct grecs_list *mem; /* List of already allocated elements */ +struct txtacc { + struct grecs_list *cur; /* Current build list */ + struct grecs_list *mem; /* List of already allocated elements */ }; static struct txtacc_entry * -txtacc_alloc_entry (struct grecs_list *list, size_t size) +txtacc_alloc_entry(struct grecs_list *list, size_t size) { - struct txtacc_entry *p = grecs_malloc (sizeof (*p)); - p->buf = grecs_malloc (size); - p->size = size; - p->len = 0; - grecs_list_append (list, p); - return p; + struct txtacc_entry *p = grecs_malloc(sizeof(*p)); + p->buf = grecs_malloc(size); + p->size = size; + p->len = 0; + grecs_list_append(list, p); + return p; } static struct txtacc_entry * -txtacc_cur_entry (struct txtacc *acc) +txtacc_cur_entry(struct txtacc *acc) { - struct txtacc_entry *ent; - - if (grecs_list_size (acc->cur) == 0) - return txtacc_alloc_entry (acc->cur, TXTACC_BUFSIZE); - ent = acc->cur->tail->data; - if (txtacc_entry_freesize (ent) == 0) - ent = txtacc_alloc_entry (acc->cur, TXTACC_BUFSIZE); - return ent; + struct txtacc_entry *ent; + + if (grecs_list_size(acc->cur) == 0) + return txtacc_alloc_entry(acc->cur, TXTACC_BUFSIZE); + ent = acc->cur->tail->data; + if (txtacc_entry_freesize(ent) == 0) + ent = txtacc_alloc_entry(acc->cur, TXTACC_BUFSIZE); + return ent; } static void -txtacc_entry_append (struct txtacc_entry *ent, const char *p, size_t size) +txtacc_entry_append(struct txtacc_entry *ent, const char *p, size_t size) { - memcpy (ent->buf + ent->len, p, size); - ent->len += size; -} + memcpy(ent->buf + ent->len, p, size); + ent->len += size; +} static void -txtacc_entry_tailor (struct txtacc_entry *ent) +txtacc_entry_tailor(struct txtacc_entry *ent) { - if (ent->size > ent->len) - { - char *p = realloc (ent->buf, ent->len); - if (!p) - return; - ent->buf = p; - ent->size = ent->len; - } + if (ent->size > ent->len) { + char *p = realloc(ent->buf, ent->len); + if (!p) + return; + ent->buf = p; + ent->size = ent->len; + } } static void -txtacc_entry_free (void *p) +txtacc_entry_free(void *p) { - if (p) - { - struct txtacc_entry *ent = p; - free (ent->buf); - free (ent); - } + if (p) { + struct txtacc_entry *ent = p; + free(ent->buf); + free(ent); + } } struct txtacc * -txtacc_create () +txtacc_create() { - struct txtacc *acc = grecs_malloc (sizeof (*acc)); - acc->cur = grecs_list_create (); - acc->cur->free_entry = txtacc_entry_free; - acc->mem = grecs_list_create (); - acc->mem->free_entry = txtacc_entry_free; - return acc; + struct txtacc *acc = grecs_malloc(sizeof(*acc)); + acc->cur = grecs_list_create(); + acc->cur->free_entry = txtacc_entry_free; + acc->mem = grecs_list_create(); + acc->mem->free_entry = txtacc_entry_free; + return acc; } void -txtacc_free (struct txtacc *acc) +txtacc_free(struct txtacc *acc) { - grecs_list_free (acc->cur); - grecs_list_free (acc->mem); - free (acc); + grecs_list_free(acc->cur); + grecs_list_free(acc->mem); + free(acc); } void -txtacc_grow (struct txtacc *acc, const char *buf, size_t size) +txtacc_grow(struct txtacc *acc, const char *buf, size_t size) { - while (size) - { - struct txtacc_entry *ent = txtacc_cur_entry (acc); - size_t rest = txtacc_entry_freesize (ent); - if (rest > size) - rest = size; - txtacc_entry_append (ent, buf, rest); - buf += rest; - size -= rest; - } + while (size) { + struct txtacc_entry *ent = txtacc_cur_entry(acc); + size_t rest = txtacc_entry_freesize(ent); + if (rest > size) + rest = size; + txtacc_entry_append(ent, buf, rest); + buf += rest; + size -= rest; + } } char * -txtacc_finish (struct txtacc *acc, int steal) +txtacc_finish(struct txtacc *acc, int steal) { - struct grecs_list_entry *ep; - struct txtacc_entry *txtent; - size_t size; - char *p; - - switch (grecs_list_size (acc->cur)) - { - case 0: - return NULL; - - case 1: - txtent = acc->cur->head->data; - acc->cur->head->data = NULL; - txtacc_entry_tailor (txtent); - grecs_list_append (acc->mem, txtent); - break; - - default: - size = 0; - for (ep = acc->cur->head; ep; ep = ep->next) - { - txtent = ep->data; - size += txtent->len; + struct grecs_list_entry *ep; + struct txtacc_entry *txtent; + size_t size; + char *p; + + switch (grecs_list_size(acc->cur)) { + case 0: + return NULL; + + case 1: + txtent = acc->cur->head->data; + acc->cur->head->data = NULL; + txtacc_entry_tailor(txtent); + grecs_list_append(acc->mem, txtent); + break; + + default: + size = 0; + for (ep = acc->cur->head; ep; ep = ep->next) { + txtent = ep->data; + size += txtent->len; + } + + txtent = txtacc_alloc_entry(acc->mem, size); + for (ep = acc->cur->head; ep; ep = ep->next) { + struct txtacc_entry *tp = ep->data; + txtacc_entry_append(txtent, tp->buf, tp->len); + } } - - txtent = txtacc_alloc_entry (acc->mem, size); - for (ep = acc->cur->head; ep; ep = ep->next) - { - struct txtacc_entry *tp = ep->data; - txtacc_entry_append (txtent, tp->buf, tp->len); + + grecs_list_clear(acc->cur); + p = txtent->buf; + if (steal) { + grecs_list_remove_tail(acc->mem); + free(txtent); } - } - - grecs_list_clear (acc->cur); - p = txtent->buf; - if (steal) - { - grecs_list_remove_tail (acc->mem); - free (txtent); - } - return p; + return p; } void -txtacc_free_string (struct txtacc *acc, char *str) +txtacc_free_string(struct txtacc *acc, char *str) { - struct grecs_list_entry *ep; - for (ep = acc->mem->head; ep; ep = ep->next) - { - struct txtacc_entry *tp = ep->data; - if (tp->buf == str) - { - grecs_list_remove_entry (acc->mem, ep); - free (tp->buf); - return; + struct grecs_list_entry *ep; + for (ep = acc->mem->head; ep; ep = ep->next) { + struct txtacc_entry *tp = ep->data; + if (tp->buf == str) { + grecs_list_remove_entry(acc->mem, ep); + free(tp->buf); + return; + } } - } } - diff --git a/src/userprivs.c b/src/userprivs.c index c511438..11285f1 100644 --- a/src/userprivs.c +++ b/src/userprivs.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007, 2009-2011 Sergey Poznyakoff + Copyright (C) 2007, 2009-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -17,103 +17,95 @@ #include "wydawca.h" int -wydawca_userprivs (uid_t uid, gid_t gid, gid_t *grplist, size_t ngrp) +wydawca_userprivs(uid_t uid, gid_t gid, gid_t * grplist, size_t ngrp) { - int rc = 0; + int rc = 0; - if (uid == 0) - return 0; - - /* Reset group permissions */ - if (geteuid () == 0 && setgroups (ngrp, grplist)) - { - logmsg (LOG_CRIT, "setgroups(%lu, %lu...): %s", - (unsigned long)ngrp, (unsigned long)grplist[0], - strerror (errno)); - return rc; - } - - /* Switch to the user's gid. On some OSes the effective gid must - be reset first */ + if (uid == 0) + return 0; + + /* Reset group permissions */ + if (geteuid() == 0 && setgroups(ngrp, grplist)) { + logmsg(LOG_CRIT, "setgroups(%lu, %lu...): %s", + (unsigned long)ngrp, (unsigned long)grplist[0], + strerror(errno)); + return rc; + } + + /* Switch to the user's gid. On some OSes the effective gid must + be reset first */ #if defined(HAVE_SETEGID) - if ((rc = setegid (gid)) < 0) - logmsg (LOG_CRIT, "setegid(%lu): %s", - (unsigned long) gid, strerror (errno)); + if ((rc = setegid(gid)) < 0) + logmsg(LOG_CRIT, "setegid(%lu): %s", + (unsigned long)gid, strerror(errno)); #elif defined(HAVE_SETREGID) - if ((rc = setregid (gid, gid)) < 0) - logmsg (LOG_CRIT, "setregid(%lu,%lu)d: %s", - (unsigned long) gid, (unsigned long) gid, strerror (errno)); + if ((rc = setregid(gid, gid)) < 0) + logmsg(LOG_CRIT, "setregid(%lu,%lu)d: %s", + (unsigned long)gid, (unsigned long)gid, + strerror(errno)); #elif defined(HAVE_SETRESGID) - if ((rc = setresgid (gid, gid, gid)) < 0) - logmsg (LOG_CRIT, "setresgid(%lu,%lu,%lu): %s", - (unsigned long) gid, (unsigned long) gid, - (unsigned long) gid, - strerror (errno)); + if ((rc = setresgid(gid, gid, gid)) < 0) + logmsg(LOG_CRIT, "setresgid(%lu,%lu,%lu): %s", + (unsigned long)gid, (unsigned long)gid, + (unsigned long)gid, strerror(errno)); #endif - if (rc == 0 && gid != 0) - { - if ((rc = setgid (gid)) < 0 && getegid () != gid) - logmsg (LOG_CRIT, "setgid(%lu): %s", - (unsigned long) gid, strerror (errno)); - if (rc == 0 && getegid () != gid) - { - logmsg (LOG_CRIT, _("cannot set effective gid to %lu"), - (unsigned long) gid); - rc = 1; + if (rc == 0 && gid != 0) { + if ((rc = setgid(gid)) < 0 && getegid() != gid) + logmsg(LOG_CRIT, "setgid(%lu): %s", + (unsigned long)gid, strerror(errno)); + if (rc == 0 && getegid() != gid) { + logmsg(LOG_CRIT, _("cannot set effective gid to %lu"), + (unsigned long)gid); + rc = 1; + } } - } - /* Now reset uid */ - if (rc == 0 && uid != 0) - { - uid_t euid; + /* Now reset uid */ + if (rc == 0 && uid != 0) { + uid_t euid; + + if (setuid(uid) || + geteuid() != uid || + (getuid() != uid && (geteuid() == 0 || getuid() == 0))) { - if (setuid (uid) - || geteuid () != uid - || (getuid () != uid - && (geteuid () == 0 || getuid () == 0))) - { - #if defined(HAVE_SETREUID) - if (geteuid () != uid) - { - if (setreuid (uid, -1) < 0) - { - logmsg (LOG_CRIT, "setreuid(%lu,-1): %s", - (unsigned long) uid, strerror (errno)); - rc = 1; + if (geteuid() != uid) { + if (setreuid(uid, -1) < 0) { + logmsg(LOG_CRIT, + "setreuid(%lu,-1): %s", + (unsigned long)uid, + strerror(errno)); + rc = 1; + } + if (setuid(uid) < 0) { + logmsg(LOG_CRIT, + "setreuid(%lu,-1): %s", + (unsigned long)uid, + strerror(errno)); + rc = 1; + } + } else +#endif + { + logmsg(LOG_CRIT, "setuid(%lu): %s", + (unsigned long)uid, strerror(errno)); + rc = 1; + } } - if (setuid (uid) < 0) - { - logmsg (LOG_CRIT, "setreuid(%lu,-1): %s", - (unsigned long) uid, strerror (errno)); - rc = 1; + + euid = geteuid(); + if (uid != 0 && setuid(0) == 0) { + logmsg(LOG_CRIT, + _("seteuid(0) succeeded when it should not")); + rc = 1; + } else if (uid != euid && setuid(euid) == 0) { + logmsg(LOG_CRIT, + _("cannot drop non-root setuid privileges")); + rc = 1; } - } - else -#endif - { - logmsg (LOG_CRIT, "setuid(%lu): %s", - (unsigned long) uid, strerror (errno)); - rc = 1; - } - } - - euid = geteuid (); - if (uid != 0 && setuid (0) == 0) - { - logmsg (LOG_CRIT, _("seteuid(0) succeeded when it should not")); - rc = 1; - } - else if (uid != euid && setuid (euid) == 0) - { - logmsg (LOG_CRIT, _("cannot drop non-root setuid privileges")); - rc = 1; } - } - - return rc; + return rc; } diff --git a/src/verify.c b/src/verify.c index dee160f..6affda2 100644 --- a/src/verify.c +++ b/src/verify.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007-2011 Sergey Poznyakoff + Copyright (C) 2007-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -19,23 +19,22 @@ /* Return the length of the string without trailing whitespace */ size_t -trim_length (const char *str) +trim_length(const char *str) { - size_t len; + size_t len; - for (len = strlen (str); len > 0 && isspace (str[len-1]); len--) - ; - return len; + for (len = strlen(str); len > 0 && isspace(str[len - 1]); len--) ; + return len; } /* Chop off any trailing whitespace. Return the length of the resulting string. */ size_t -trim (char *str) +trim(char *str) { - size_t len = trim_length (str); - str[len] = 0; - return len; + size_t len = trim_length(str); + str[len] = 0; + return len; } #define MSG_BEGIN_MARKER_STR "-----BEGIN PGP SIGNED MESSAGE-----\n" @@ -45,297 +44,284 @@ trim (char *str) #define SIG_BEGIN_MARKER_LEN (sizeof (SIG_BEGIN_MARKER_STR) - 1) static int -extract_plaintext (char *blurb) +extract_plaintext(char *blurb) { - char *start, *p; - - if (memcmp (blurb, MSG_BEGIN_MARKER_STR, MSG_BEGIN_MARKER_LEN)) - return 1; - - p = blurb + MSG_BEGIN_MARKER_LEN; - while (*p) - { - if (*p == '\n') - { - p++; - break; + char *start, *p; + + if (memcmp(blurb, MSG_BEGIN_MARKER_STR, MSG_BEGIN_MARKER_LEN)) + return 1; + + p = blurb + MSG_BEGIN_MARKER_LEN; + while (*p) { + if (*p == '\n') { + p++; + break; + } + + p = strchr(p, '\n'); + if (!p) + return 1; + p++; } - p = strchr (p, '\n'); - if (!p) - return 1; - p++; - } - - if (!*p) - return 1; - - start = p; - while (*p) - { - if (strncmp (p, SIG_BEGIN_MARKER_STR, SIG_BEGIN_MARKER_LEN) == 0) - { - *p++ = 0; - memmove (blurb, start, p - start); - return 0; + if (!*p) + return 1; + + start = p; + while (*p) { + if (strncmp(p, SIG_BEGIN_MARKER_STR, SIG_BEGIN_MARKER_LEN) + == 0) { + *p++ = 0; + memmove(blurb, start, p - start); + return 0; + } + p = strchr(p, '\n'); + if (!p) + return 1; + p++; } - p = strchr (p, '\n'); - if (!p) return 1; - p++; - } - return 1; } int -fill_project_name (struct file_triplet *trp) +fill_project_name(struct file_triplet *trp) { - char *blurb; - size_t size; - FILE *fp; - char *p; - const char *directory; - int rc; - - if (trp->blurb) - return 0; - - size = trp->file[file_directive].sb.st_size; - if (size <= MSG_BEGIN_MARKER_LEN) - { - logmsg (LOG_ERR, _("too small directive file %s"), - trp->file[file_directive].name); - return 1; - } - - fp = fopen (trp->file[file_directive].name, "r"); - if (!fp) - { - logmsg (LOG_ERR, _("cannot open file %s: %s"), - trp->file[file_directive].name, strerror (errno)); - return 1; - } - - blurb = grecs_malloc (size + 1); - - rc = fread (blurb, size, 1, fp); - fclose (fp); - - if (rc != 1) - { - logmsg (LOG_ERR, _("error reading file %s: %s"), - trp->file[file_directive].name, strerror (errno)); - free (blurb); - return 1; - } - - blurb[size] = 0; - if (extract_plaintext (blurb)) - { - logmsg (LOG_ERR, _("%s: unrecognized format"), - trp->file[file_directive].name); - free (blurb); - return 1; - } - - trp->blurb = blurb; - - if (directive_parse (trp)) - { - free (blurb); - trp->blurb = NULL; - return 1; - } - - if (directive_get_value (trp, "directory", &directory)) - { - logmsg (LOG_ERR, _("%s: missing `directory' directive"), - trp->file[file_directive].name); - return 1; - } - - trp->relative_dir = safe_file_name (triplet_strdup (trp, directory)); - if (!trp->relative_dir || trp->relative_dir[0] == '/') - { - logmsg (LOG_ERR, _("%s: invalid directory: %s"), - trp->file[file_directive].name, directory); - return 1; - } - - p = strchr (trp->relative_dir, '/'); - if (p) - { - size_t len = p - trp->relative_dir; - if (len == 0) - { - logmsg (LOG_ERR, _("%s: empty `directory' directive"), - trp->file[file_directive].name); - return 1; + char *blurb; + size_t size; + FILE *fp; + char *p; + const char *directory; + int rc; + + if (trp->blurb) + return 0; + + size = trp->file[file_directive].sb.st_size; + if (size <= MSG_BEGIN_MARKER_LEN) { + logmsg(LOG_ERR, _("too small directive file %s"), + trp->file[file_directive].name); + return 1; + } + + fp = fopen(trp->file[file_directive].name, "r"); + if (!fp) { + logmsg(LOG_ERR, _("cannot open file %s: %s"), + trp->file[file_directive].name, strerror(errno)); + return 1; + } + + blurb = grecs_malloc(size + 1); + + rc = fread(blurb, size, 1, fp); + fclose(fp); + + if (rc != 1) { + logmsg(LOG_ERR, _("error reading file %s: %s"), + trp->file[file_directive].name, strerror(errno)); + free(blurb); + return 1; } - txtacc_grow (trp->acc, trp->relative_dir, len); - txtacc_1grow (trp->acc, 0); - trp->project = txtacc_finish (trp->acc, 0); - } - else - trp->project = trp->relative_dir; - - return 0; + + blurb[size] = 0; + if (extract_plaintext(blurb)) { + logmsg(LOG_ERR, _("%s: unrecognized format"), + trp->file[file_directive].name); + free(blurb); + return 1; + } + + trp->blurb = blurb; + + if (directive_parse(trp)) { + free(blurb); + trp->blurb = NULL; + return 1; + } + + if (directive_get_value(trp, "directory", &directory)) { + logmsg(LOG_ERR, _("%s: missing `directory' directive"), + trp->file[file_directive].name); + return 1; + } + + trp->relative_dir = safe_file_name(triplet_strdup(trp, directory)); + if (!trp->relative_dir || trp->relative_dir[0] == '/') { + logmsg(LOG_ERR, _("%s: invalid directory: %s"), + trp->file[file_directive].name, directory); + return 1; + } + + p = strchr(trp->relative_dir, '/'); + if (p) { + size_t len = p - trp->relative_dir; + if (len == 0) { + logmsg(LOG_ERR, _("%s: empty `directory' directive"), + trp->file[file_directive].name); + return 1; + } + txtacc_grow(trp->acc, trp->relative_dir, len); + txtacc_1grow(trp->acc, 0); + trp->project = txtacc_finish(trp->acc, 0); + } else + trp->project = trp->relative_dir; + + return 0; } struct uploader_info * -new_uploader_info (struct uploader_info *src) +new_uploader_info(struct uploader_info *src) { - struct uploader_info *p = grecs_malloc (sizeof (*p)); - p->next = NULL; - p->name = src->name; - p->realname = src->realname; - p->gpg_key = src->gpg_key; - p->email = src->email; - p->fpr = NULL; - return p; + struct uploader_info *p = grecs_malloc(sizeof(*p)); + p->next = NULL; + p->name = src->name; + p->realname = src->realname; + p->gpg_key = src->gpg_key; + p->email = src->email; + p->fpr = NULL; + return p; } struct uploader_info * -uploader_find_frp (struct uploader_info *list, const char *fpr) +uploader_find_frp(struct uploader_info *list, const char *fpr) { - for (; list; list = list->next) - if (list->fpr && strcmp (list->fpr, fpr) == 0) - break; - return list; + for (; list; list = list->next) + if (list->fpr && strcmp(list->fpr, fpr) == 0) + break; + return list; } int -verify_directive_file (struct file_triplet *trp, int noath) +verify_directive_file(struct file_triplet *trp, int noath) { - char *command; - int rc; - void *md; - size_t nrows, ncols, i; - struct uploader_info *head, *tail; - const struct spool *spool; - struct dictionary *dict; - - ASGN_SPOOL (spool, trp, return 1); - dict = spool->dictionary[project_uploader_dict]; - - if (!trp->file[file_directive].name) - return 1; - - if (fill_project_name (trp)) - return 1; - - if (!noath) - { - md = dictionary_open (dict); - if (!md) - return 1; - - command = triplet_expand_dictionary_query (dict, md, trp); - - rc = dictionary_lookup (dict, md, command); - free (command); - if (rc) - { - logmsg (LOG_ERR, _("cannot get uploaders for %s"), trp->name); - dictionary_close (dict, md); - return 1; + char *command; + int rc; + void *md; + size_t nrows, ncols, i; + struct uploader_info *head, *tail; + const struct spool *spool; + struct dictionary *dict; + + ASGN_SPOOL(spool, trp, return 1); + dict = spool->dictionary[project_uploader_dict]; + + if (!trp->file[file_directive].name) + return 1; + + if (fill_project_name(trp)) + return 1; + + if (!noath) { + md = dictionary_open(dict); + if (!md) + return 1; + + command = triplet_expand_dictionary_query(dict, md, trp); + + rc = dictionary_lookup(dict, md, command); + free(command); + if (rc) { + logmsg(LOG_ERR, _("cannot get uploaders for %s"), + trp->name); + dictionary_close(dict, md); + return 1; + } + + nrows = dictionary_num_rows(dict); + if (nrows == 0) { + logmsg(LOG_ERR, _("found no uploaders for %s"), + trp->name); + dictionary_close(dict, md); + return 1; + } + + ncols = dictionary_num_cols(dict); + if (ncols < 4) { + logmsg(LOG_ERR, + _ + ("project-uploader dictionary error: too few columns (%lu)"), + (unsigned long)ncols); + dictionary_close(dict, md); + return 1; + } + + head = tail = NULL; + for (i = 0; i < nrows; i++) { + const char *p; + struct uploader_info info, *ptr; + + memset(&info, 0, sizeof(info)); + p = dictionary_result(dict, md, i, 0); + if (p) + info.name = triplet_strdup(trp, p); + p = dictionary_result(dict, md, i, 1); + if (p) + info.realname = triplet_strdup(trp, p); + p = dictionary_result(dict, md, i, 2); + if (p) + info.email = triplet_strdup(trp, p); + p = dictionary_result(dict, md, i, 3); + if (p) + info.gpg_key = triplet_strdup(trp, p); + + if (debug_level > 3) { + logmsg(LOG_DEBUG, _("name: %s"), + SP(info.name)); + logmsg(LOG_DEBUG, _("realname: %s"), + SP(info.realname)); + logmsg(LOG_DEBUG, _("gpg-key: %s"), + SP(info.gpg_key)); + logmsg(LOG_DEBUG, _("email: %s"), + SP(info.email)); + } + + if (!info.name || !info.realname || !info.gpg_key + || !info.email) { + logmsg(LOG_ERR, + _("project-uploader dictionary error: " + "malformed row %lu"), + (unsigned long)i); + /* FIXME: Memory not reclaimed */ + continue; + } + + ptr = new_uploader_info(&info); + if (tail) + tail->next = ptr; + else + head = ptr; + tail = ptr; + } + + dictionary_close(dict, md); + + if (!head) { + logmsg(LOG_ERR, _("no valid uploaders found for %s"), + trp->name); + return 1; + } + + trp->uploader_list = head; + trp->uploader = NULL; + + if (verify_directive_signature(trp)) { + /*FIXME: Update stats */ + logmsg(LOG_ERR, _("invalid signature for %s"), + trp->name ? trp->name : "[unknown]"); + return 1; + } else if (debug_level) + logmsg(LOG_DEBUG, _("%s: directive file signature OK"), + trp->name); } - - nrows = dictionary_num_rows (dict); - if (nrows == 0) - { - logmsg (LOG_ERR, _("found no uploaders for %s"), trp->name); - dictionary_close (dict, md); - return 1; - } - - ncols = dictionary_num_cols (dict); - if (ncols < 4) - { - logmsg (LOG_ERR, - _("project-uploader dictionary error: too few columns (%lu)"), - (unsigned long) ncols); - dictionary_close (dict, md); - return 1; - } - - head = tail = NULL; - for (i = 0; i < nrows; i++) - { - const char *p; - struct uploader_info info, *ptr; - - memset (&info, 0, sizeof (info)); - p = dictionary_result (dict, md, i, 0); - if (p) - info.name = triplet_strdup (trp, p); - p = dictionary_result (dict, md, i, 1); - if (p) - info.realname = triplet_strdup (trp, p); - p = dictionary_result (dict, md, i, 2); - if (p) - info.email = triplet_strdup (trp, p); - p = dictionary_result (dict, md, i, 3); - if (p) - info.gpg_key = triplet_strdup (trp, p); - - if (debug_level > 3) - { - logmsg (LOG_DEBUG, _("name: %s"), SP (info.name)); - logmsg (LOG_DEBUG, _("realname: %s"), SP (info.realname)); - logmsg (LOG_DEBUG, _("gpg-key: %s"), SP (info.gpg_key)); - logmsg (LOG_DEBUG, _("email: %s"), SP (info.email)); - } - - if (!info.name || !info.realname || !info.gpg_key || !info.email) - { - logmsg (LOG_ERR, - _("project-uploader dictionary error: malformed row %lu"), - (unsigned long) i); - /* FIXME: Memory not reclaimed */ - continue; - } - - ptr = new_uploader_info (&info); - if (tail) - tail->next = ptr; - else - head = ptr; - tail = ptr; - } - - dictionary_close (dict, md); - if (!head) - { - logmsg (LOG_ERR, _("no valid uploaders found for %s"), trp->name); - return 1; + if (debug_level > 1) { + int i; + for (i = 0; trp->directive[i]; i++) + logmsg(LOG_DEBUG, "directive[%d] = %s", i, + trp->directive[i]); } - - trp->uploader_list = head; - trp->uploader = NULL; - - if (verify_directive_signature (trp)) - { - /*FIXME: Update stats */ - logmsg (LOG_ERR, _("invalid signature for %s"), - trp->name ? trp->name : "[unknown]"); - return 1; - } - else if (debug_level) - logmsg (LOG_DEBUG, _("%s: directive file signature OK"), trp->name); - } - - if (debug_level > 1) - { - int i; - for (i = 0; trp->directive[i]; i++) - logmsg (LOG_DEBUG, "directive[%d] = %s", i, trp->directive[i]); - } - if (verify_directive_format (trp)) - return 1; + if (verify_directive_format(trp)) + return 1; - return 0; + return 0; } - @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2009-2011 Sergey Poznyakoff + Copyright (C) 2009-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -16,77 +16,74 @@ #include "wydawca.h" -struct virt_tab_reg -{ - char *scheme; - struct virt_tab vtab; +struct virt_tab_reg { + char *scheme; + struct virt_tab vtab; }; static struct virt_tab_reg reg[] = { - { "file", - { dir_test_url, dir_move_file, dir_archive_file, - dir_symlink_file, dir_rmsymlink_file } }, - { "dir", - { dir_test_url, dir_move_file, dir_archive_file, - dir_symlink_file, dir_rmsymlink_file } }, - { "null", - { NULL, null_move_file, null_archive_file, null_symlink_file, - null_rmsymlink_file } }, - { NULL } + { "file", + { dir_test_url, dir_move_file, dir_archive_file, + dir_symlink_file, dir_rmsymlink_file } }, + { "dir", + { dir_test_url, dir_move_file, dir_archive_file, + dir_symlink_file, dir_rmsymlink_file } }, + { "null", + { NULL, null_move_file, null_archive_file, null_symlink_file, + null_rmsymlink_file } }, + { NULL } }; int -url_to_vtab (mu_url_t url, struct virt_tab *vtab) +url_to_vtab(mu_url_t url, struct virt_tab *vtab) { - const char *scheme; - int i; + const char *scheme; + int i; - if (mu_url_sget_scheme (url, &scheme)) - return 1; - for (i = 0; reg[i].scheme; i++) - if (strcmp (reg[i].scheme, scheme) == 0) - { - *vtab = reg[i].vtab; - return 0; - } - return 1; + if (mu_url_sget_scheme(url, &scheme)) + return 1; + for (i = 0; reg[i].scheme; i++) + if (strcmp(reg[i].scheme, scheme) == 0) { + *vtab = reg[i].vtab; + return 0; + } + return 1; } - int -move_file (struct file_triplet *trp, enum file_type file_id) +move_file(struct file_triplet *trp, enum file_type file_id) { - int rc = trp->spool->vtab.move_file (trp, file_id); - report_add ("Move %s to %s: %s", trp->file[file_id].name, trp->relative_dir, - rc == 0 ? "OK" : "FAILED"); - return rc; + int rc = trp->spool->vtab.move_file(trp, file_id); + report_add("Move %s to %s: %s", trp->file[file_id].name, + trp->relative_dir, rc == 0 ? "OK" : "FAILED"); + return rc; } int -archive_file (struct file_triplet *trp, const char *file_name) +archive_file(struct file_triplet *trp, const char *file_name) { - int rc = trp->spool->vtab.archive_file (trp, file_name); - report_add ("Archive and remove %s/%s: %s", trp->relative_dir, file_name, - rc == 0 ? "OK" : "FAILED"); - return rc; + int rc = trp->spool->vtab.archive_file(trp, file_name); + report_add("Archive and remove %s/%s: %s", + trp->relative_dir, file_name, + rc == 0 ? "OK" : "FAILED"); + return rc; } int -symlink_file (struct file_triplet *trp, - const char *wanted_src, const char *wanted_dst) +symlink_file(struct file_triplet *trp, + const char *wanted_src, const char *wanted_dst) { - int rc = trp->spool->vtab.symlink_file (trp, wanted_src, wanted_dst); - report_add ("Symlink %s to %s in %s/: %s", wanted_src, wanted_dst, - trp->relative_dir, - rc == 0 ? "OK" : "FAILED"); - return rc; + int rc = trp->spool->vtab.symlink_file(trp, wanted_src, wanted_dst); + report_add("Symlink %s to %s in %s/: %s", wanted_src, wanted_dst, + trp->relative_dir, rc == 0 ? "OK" : "FAILED"); + return rc; } int -rmsymlink_file (struct file_triplet *trp, const char *file_name) +rmsymlink_file(struct file_triplet *trp, const char *file_name) { - int rc = trp->spool->vtab.rmsymlink_file (trp, file_name); - report_add ("Remove symlink %s/%s: %s", trp->relative_dir, file_name, - rc == 0 ? "OK" : "FAILED"); - return rc; + int rc = trp->spool->vtab.rmsymlink_file(trp, file_name); + report_add("Remove symlink %s/%s: %s", trp->relative_dir, file_name, + rc == 0 ? "OK" : "FAILED"); + return rc; } diff --git a/src/watcher.c b/src/watcher.c index f6245db..0c587f1 100644 --- a/src/watcher.c +++ b/src/watcher.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007, 2009-2012 Sergey Poznyakoff + Copyright (C) 2007, 2009-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -19,13 +19,12 @@ #include <sys/ioctl.h> /* A directory watcher is described by the following structure */ -struct dirwatcher -{ - struct dirwatcher *next, *prev; - struct dirwatcher *parent; /* Points to the parent watcher. - NULL for top-level watchers */ - struct spool *spool; - int wd; /* Watch descriptor */ +struct dirwatcher { + struct dirwatcher *next, *prev; + struct dirwatcher *parent; /* Points to the parent watcher. + NULL for top-level watchers */ + struct spool *spool; + int wd; /* Watch descriptor */ }; static struct dirwatcher *dirwatcher_list; @@ -33,226 +32,216 @@ static struct dirwatcher *dirwatcher_list; struct dirwatcher * dirwatcher_unlink(struct dirwatcher **root, struct dirwatcher *p) { - if (p->prev) - p->prev->next = p->next; - else - *root = p->next; - if (p->next) - p->next->prev = p->prev; - p->next = p->prev = NULL; - return p; + if (p->prev) + p->prev->next = p->next; + else + *root = p->next; + if (p->next) + p->next->prev = p->prev; + p->next = p->prev = NULL; + return p; } struct dirwatcher * dirwatcher_pop(struct dirwatcher **pp) { - if (*pp) - return dirwatcher_unlink(pp, *pp); - return NULL; + if (*pp) + return dirwatcher_unlink(pp, *pp); + return NULL; } static void dirwatcher_push(struct dirwatcher **pp, struct dirwatcher *p) { - p->prev = NULL; - p->next = *pp; - if (*pp) - (*pp)->prev = p; - *pp = p; + p->prev = NULL; + p->next = *pp; + if (*pp) + (*pp)->prev = p; + *pp = p; } /* Find a watcher with the given descriptor */ static struct dirwatcher * -dirwatcher_find_wd (int wd) +dirwatcher_find_wd(int wd) { - struct dirwatcher *dwp; - - for (dwp = dirwatcher_list; dwp; dwp = dwp->next) - if (dwp->wd == wd) - break; - return dwp; + struct dirwatcher *dwp; + + for (dwp = dirwatcher_list; dwp; dwp = dwp->next) + if (dwp->wd == wd) + break; + return dwp; } static int -create_watcher (struct spool *sp, void *data) +create_watcher(struct spool *sp, void *data) { - int ifd = *(int*)data; - struct dirwatcher *dwp; - int wd; - const char *path = sp->source_dir; - - if (!sp) - return 0; - - if (!sp->inotify_enable) - { - if (debug_level > 1) - logmsg (LOG_DEBUG, "disabling inotify support for spool %s", sp->tag); - return 0; - } - - if (debug_level > 1) - logmsg (LOG_DEBUG, "spool %s: creating watcher %s", sp->tag, path); - dwp = malloc (sizeof(*dwp)); - if (!dwp) - { - logmsg (LOG_ERR, "not enough memory"); - return 1; - } - dwp->spool = sp; - dwp->parent = NULL; - - wd = inotify_add_watch (ifd, path, IN_DELETE|IN_CREATE|IN_CLOSE_WRITE| - IN_MOVED_FROM|IN_MOVED_TO); - if (wd == -1) - { - logmsg (LOG_ERR, "cannot set watch on %s: %s", path, strerror (errno)); - free (dwp); - return 1; - } - - dwp->wd = wd; - dirwatcher_push (&dirwatcher_list, dwp); - return 0; + int ifd = *(int *)data; + struct dirwatcher *dwp; + int wd; + const char *path = sp->source_dir; + + if (!sp) + return 0; + + if (!sp->inotify_enable) { + if (debug_level > 1) + logmsg(LOG_DEBUG, + "disabling inotify support for spool %s", + sp->tag); + return 0; + } + + if (debug_level > 1) + logmsg(LOG_DEBUG, "spool %s: creating watcher %s", sp->tag, + path); + dwp = malloc(sizeof(*dwp)); + if (!dwp) { + logmsg(LOG_ERR, "not enough memory"); + return 1; + } + dwp->spool = sp; + dwp->parent = NULL; + + wd = inotify_add_watch(ifd, path, + IN_DELETE | IN_CREATE | IN_CLOSE_WRITE | + IN_MOVED_FROM | IN_MOVED_TO); + if (wd == -1) { + logmsg(LOG_ERR, "cannot set watch on %s: %s", path, + strerror(errno)); + free(dwp); + return 1; + } + + dwp->wd = wd; + dirwatcher_push(&dirwatcher_list, dwp); + return 0; } int -watcher_init () +watcher_init() { - int ifd, rc; - - if (!inotify_enable) - { - if (debug_level > 1) - logmsg (LOG_DEBUG, "disabling inotify support"); - return -1; - } - - if (debug_level > 1) - logmsg (LOG_DEBUG, "setting up inotify"); - ifd = inotify_init (); - if (ifd == -1) - { - logmsg (LOG_ERR, "inotify_init: %s", strerror (errno)); - return -1; - } - - rc = for_each_spool (create_watcher, &ifd); - if (rc) - exit (EX_OSERR); - if (!dirwatcher_list) - { - if (debug_level > 1) - logmsg (LOG_DEBUG, "inotify: nothing to watch"); - close (ifd); - ifd = -1; - } - else if (debug_level > 1) - logmsg (LOG_DEBUG, "inotify initialized successfully"); - - return ifd; + int ifd, rc; + + if (!inotify_enable) { + if (debug_level > 1) + logmsg(LOG_DEBUG, "disabling inotify support"); + return -1; + } + + if (debug_level > 1) + logmsg(LOG_DEBUG, "setting up inotify"); + ifd = inotify_init(); + if (ifd == -1) { + logmsg(LOG_ERR, "inotify_init: %s", strerror(errno)); + return -1; + } + + rc = for_each_spool(create_watcher, &ifd); + if (rc) + exit(EX_OSERR); + if (!dirwatcher_list) { + if (debug_level > 1) + logmsg(LOG_DEBUG, "inotify: nothing to watch"); + close(ifd); + ifd = -1; + } else if (debug_level > 1) + logmsg(LOG_DEBUG, "inotify initialized successfully"); + + return ifd; } static void -process_event (struct inotify_event *ep) +process_event(struct inotify_event *ep) { - static struct dirwatcher *dwp; - dwp = dirwatcher_find_wd (ep->wd); - - if (ep->mask & IN_IGNORED) - /* nothing */; - else if (ep->mask & IN_Q_OVERFLOW) - logmsg (LOG_NOTICE, "event queue overflow"); - else if (ep->mask & IN_UNMOUNT) - /* FIXME: not sure if there's - anything to do. Perhaps we should - deregister the watched dirs that - were located under the mountpoint - */; - else if (!dwp) - { - if (ep->name) - logmsg (LOG_NOTICE, "unrecognized event %x for %s", - ep->mask, ep->name); - else - logmsg (LOG_NOTICE, "unrecognized event %x", ep->mask); - } - else if (ep->mask & IN_CREATE) - { - if (debug_level > 0) - logmsg (LOG_DEBUG, "%s/%s created", dwp->spool->source_dir, ep->name); - } - else if (ep->mask & (IN_DELETE|IN_MOVED_FROM)) - { - if (debug_level > 0) - logmsg (LOG_DEBUG, "%s/%s %s", dwp->spool->source_dir, ep->name, - ep->mask & IN_DELETE ? "deleted" : "moved out"); - triplet_remove_file (dwp->spool, ep->name); - } - else if (ep->mask & (IN_CLOSE_WRITE|IN_MOVED_TO)) - { - if (debug_level > 0) - logmsg (LOG_DEBUG, "%s/%s written", dwp->spool->source_dir, ep->name); - if (spool_add_new_file (dwp->spool, ep->name, 0, NULL) == 0 && - count_processable_triplets ()) - schedule_job (&inotify_spool, getuid ()); - } - else - logmsg (LOG_NOTICE, "%s/%s: unexpected event %x", - dwp->spool->source_dir, ep->name, ep->mask); - + static struct dirwatcher *dwp; + dwp = dirwatcher_find_wd(ep->wd); + + if (ep->mask & IN_IGNORED) + /* nothing */ ; + else if (ep->mask & IN_Q_OVERFLOW) + logmsg(LOG_NOTICE, "event queue overflow"); + else if (ep->mask & IN_UNMOUNT) + /* FIXME: not sure if there's + anything to do. Perhaps we should + deregister the watched dirs that + were located under the mountpoint + */ ; + else if (!dwp) { + if (ep->name) + logmsg(LOG_NOTICE, "unrecognized event %x for %s", + ep->mask, ep->name); + else + logmsg(LOG_NOTICE, "unrecognized event %x", ep->mask); + } else if (ep->mask & IN_CREATE) { + if (debug_level > 0) + logmsg(LOG_DEBUG, "%s/%s created", + dwp->spool->source_dir, ep->name); + } else if (ep->mask & (IN_DELETE | IN_MOVED_FROM)) { + if (debug_level > 0) + logmsg(LOG_DEBUG, "%s/%s %s", dwp->spool->source_dir, + ep->name, + ep->mask & IN_DELETE ? "deleted" : "moved out"); + triplet_remove_file(dwp->spool, ep->name); + } else if (ep->mask & (IN_CLOSE_WRITE | IN_MOVED_TO)) { + if (debug_level > 0) + logmsg(LOG_DEBUG, "%s/%s written", + dwp->spool->source_dir, ep->name); + if (spool_add_new_file(dwp->spool, ep->name, 0, NULL) == 0 + && count_processable_triplets()) + schedule_job(&inotify_spool, getuid()); + } else + logmsg(LOG_NOTICE, "%s/%s: unexpected event %x", + dwp->spool->source_dir, ep->name, ep->mask); + } static char buffer[4096]; static int offset; int -watcher_run (int ifd) +watcher_run(int ifd) { - int n; - int rdbytes; - - if (ioctl (ifd, FIONREAD, &n)) - { - logmsg (LOG_ERR, "ioctl: %s", strerror (errno)); - return -1; - } - if (offset + n > sizeof buffer) - n = sizeof buffer - offset; - if (n) - { - rdbytes = read (ifd, buffer + offset, n); - if (rdbytes == -1) - { - if (errno == EINTR) - { - //FIXME logmsg (LOG_NOTICE, "got signal %d", signo); - return 0; - } - - logmsg (LOG_NOTICE, "read failed: %s", strerror (errno)); - return -1; + int n; + int rdbytes; + + if (ioctl(ifd, FIONREAD, &n)) { + logmsg(LOG_ERR, "ioctl: %s", strerror(errno)); + return -1; + } + if (offset + n > sizeof buffer) + n = sizeof buffer - offset; + if (n) { + rdbytes = read(ifd, buffer + offset, n); + if (rdbytes == -1) { + if (errno == EINTR) { + /*FIXME + logmsg (LOG_NOTICE, "got signal %d", signo); + */ + return 0; + } + + logmsg(LOG_NOTICE, "read failed: %s", strerror(errno)); + return -1; + } + } + offset += n; + + for (n = 0; offset - n >= sizeof(struct inotify_event);) { + struct inotify_event *ep; + size_t size; + + ep = (struct inotify_event *)(buffer + n); + size = sizeof(*ep) + ep->len; + if (offset - n < size) + break; + + process_event(ep); + + n += size; } - } - offset += n; - - for (n = 0; offset - n >= sizeof (struct inotify_event); ) - { - struct inotify_event *ep; - size_t size; - - ep = (struct inotify_event *) (buffer + n); - size = sizeof(*ep) + ep->len; - if (offset - n < size) - break; - - process_event (ep); - - n += size; - } - if (n > 0 && offset - n > 0) - memmove (buffer, buffer + n, offset - n); - offset -= n; - - return 0; + if (n > 0 && offset - n > 0) + memmove(buffer, buffer + n, offset - n); + offset -= n; + + return 0; } diff --git a/src/wydawca.c b/src/wydawca.c index 45a5cff..42fcea9 100644 --- a/src/wydawca.c +++ b/src/wydawca.c @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007, 2009-2012 Sergey Poznyakoff + Copyright (C) 2007, 2009-2013 Sergey Poznyakoff Wydawca is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -22,17 +22,17 @@ uid_t wydawca_uid; gid_t wydawca_gid; size_t wydawca_supp_groupc; gid_t *wydawca_supp_groups; -char *conffile = SYSCONFDIR "/wydawca.rc" ; +char *conffile = SYSCONFDIR "/wydawca.rc"; int debug_level; int dry_run_mode; -int log_to_stderr = -1; /* -1 means autodetect */ +int log_to_stderr = -1; /* -1 means autodetect */ int log_facility = LOG_LOCAL1; char *syslog_tag = "wydawca"; -int syslog_include_prio; /* syslog messages include priority */ -unsigned long print_stats; /* Print final statistics output */ +int syslog_include_prio; /* syslog messages include priority */ +unsigned long print_stats; /* Print final statistics output */ time_t file_sweep_time = 0; char *tar_command_name = "tar"; -int archive_signatures = 1; /* Archive sig files by default */ +int archive_signatures = 1; /* Archive sig files by default */ int lint_mode = 0; int preprocess_only = 0; int cron_option = 0; @@ -56,400 +56,370 @@ unsigned max_directive_version = MAX_DIRECTIVE_VERSION; int inotify_enable = 1; void -initstats () +initstats() { - memset (wydawca_stat, 0, sizeof wydawca_stat); + memset(wydawca_stat, 0, sizeof wydawca_stat); } - /* Logging */ void -syslog_printer (int prio, const char *fmt, va_list ap) +syslog_printer(int prio, const char *fmt, va_list ap) { - if (syslog_include_prio) - { - static char *fmtbuf; - static size_t fmtsize; - const char *p = mu_syslog_priority_to_string (prio); - size_t size = strlen (p) + 3 + strlen (fmt) + 1; - - if (size > fmtsize) - { - fmtsize = size; - fmtbuf = grecs_realloc (fmtbuf, fmtsize); + if (syslog_include_prio) { + static char *fmtbuf; + static size_t fmtsize; + const char *p = mu_syslog_priority_to_string(prio); + size_t size = strlen(p) + 3 + strlen(fmt) + 1; + + if (size > fmtsize) { + fmtsize = size; + fmtbuf = grecs_realloc(fmtbuf, fmtsize); + } + sprintf(fmtbuf, "[%s] %s", p, fmt); + fmt = fmtbuf; } - sprintf (fmtbuf, "[%s] %s", p, fmt); - fmt = fmtbuf; - } - #if HAVE_VSYSLOG - vsyslog (prio, fmt, ap); + vsyslog(prio, fmt, ap); #else - char buf[128]; - vsnprintf (buf, sizeof buf, fmt, ap); - syslog (prio, "%s", buf); + char buf[128]; + vsnprintf(buf, sizeof buf, fmt, ap); + syslog(prio, "%s", buf); #endif } void -stderr_printer (int prio, const char *fmt, va_list ap) +stderr_printer(int prio, const char *fmt, va_list ap) { - const char *p = mu_syslog_priority_to_string (prio); - fprintf (stderr, "%s: ", program_name); + const char *p = mu_syslog_priority_to_string(prio); + fprintf(stderr, "%s: ", program_name); - if (p) - fprintf (stderr, "[%s] ", p); + if (p) + fprintf(stderr, "[%s] ", p); - vfprintf (stderr, fmt, ap); - fputc ('\n', stderr); + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); } - static void (*log_printer) (int prio, const char *fmt, va_list ap) = - stderr_printer; + stderr_printer; void -logmsg (int prio, char *fmt, ...) +logmsg(int prio, char *fmt, ...) { - va_list ap; - - switch (prio) - { - case LOG_EMERG: - case LOG_ALERT: - case LOG_CRIT: - case LOG_ERR: - UPDATE_STATS (STAT_ERRORS); - break; - - case LOG_WARNING: - UPDATE_STATS (STAT_WARNINGS); - } - - va_start (ap, fmt); - log_printer (prio, fmt, ap); - va_end (ap); -} + va_list ap; + + switch (prio) { + case LOG_EMERG: + case LOG_ALERT: + case LOG_CRIT: + case LOG_ERR: + UPDATE_STATS(STAT_ERRORS); + break; + + case LOG_WARNING: + UPDATE_STATS(STAT_WARNINGS); + } + va_start(ap, fmt); + log_printer(prio, fmt, ap); + va_end(ap); +} static char *stat_name[MAX_STAT] = { - N_("errors"), - N_("warnings"), - N_("bad signatures"), - N_("access violation attempts"), - N_("complete triplets"), - N_("incomplete triplets"), - N_("bad triplets"), - N_("expired triplets"), - N_("triplet successes"), - N_("files uploaded"), - N_("files archived"), - N_("symlinks created"), - N_("symlinks removed"), - N_("check failures"), + N_("errors"), + N_("warnings"), + N_("bad signatures"), + N_("access violation attempts"), + N_("complete triplets"), + N_("incomplete triplets"), + N_("bad triplets"), + N_("expired triplets"), + N_("triplet successes"), + N_("files uploaded"), + N_("files archived"), + N_("symlinks created"), + N_("symlinks removed"), + N_("check failures"), }; static char *stat_kwname[MAX_STAT] = { - "stat:errors", - "stat:warnings", - "stat:bad_signatures", - "stat:access_violations", - "stat:complete_triplets", - "stat:incomplete_triplets", - "stat:bad_triplets", - "stat:expired_triplets", - "stat:triplet_success", - "stat:uploads", - "stat:archives", - "stat:symlinks", - "stat:rmsymlinks", - "stat:check-failures" + "stat:errors", + "stat:warnings", + "stat:bad_signatures", + "stat:access_violations", + "stat:complete_triplets", + "stat:incomplete_triplets", + "stat:bad_triplets", + "stat:expired_triplets", + "stat:triplet_success", + "stat:uploads", + "stat:archives", + "stat:symlinks", + "stat:rmsymlinks", + "stat:check-failures" }; int -stat_mask_p (unsigned long mask) +stat_mask_p(unsigned long mask) { - int i; + int i; - for (i = 0; i < MAX_STAT; i++) - if (wydawca_stat[i] != 0 && (mask && STAT_MASK (i))) - return 1; - return 0; + for (i = 0; i < MAX_STAT; i++) + if (wydawca_stat[i] != 0 && (mask && STAT_MASK(i))) + return 1; + return 0; } static const char * -stat_expand (struct metadef *def, void *data) +stat_expand(struct metadef *def, void *data) { - size_t size = 0; - def->storage = NULL; - if (grecs_asprintf (&def->storage, &size, "%u", - wydawca_stat[(int) def->data])) - grecs_alloc_die (); - def->value = def->storage; - return def->value; + size_t size = 0; + def->storage = NULL; + if (grecs_asprintf(&def->storage, &size, "%u", + wydawca_stat[(int)def->data])) + grecs_alloc_die(); + def->value = def->storage; + return def->value; } struct metadef * -make_stat_expansion (size_t count) +make_stat_expansion(size_t count) { - int i; - struct metadef *def, *p; - def = grecs_calloc (MAX_STAT + count + 1, sizeof (def[0])); - p = def + count; - for (i = 0; i < MAX_STAT; i++, p++) - { - p->kw = stat_kwname[i]; - p->value = NULL; - p->storage = NULL; - p->expand = stat_expand; - p->data = (void*) i; - } - p->kw = NULL; - return def; + int i; + struct metadef *def, *p; + def = grecs_calloc(MAX_STAT + count + 1, sizeof(def[0])); + p = def + count; + for (i = 0; i < MAX_STAT; i++, p++) { + p->kw = stat_kwname[i]; + p->value = NULL; + p->storage = NULL; + p->expand = stat_expand; + p->data = (void *)i; + } + p->kw = NULL; + return def; } void -logstats () +logstats() { - int i; + int i; - if (stat_mask_p (print_stats)) - { - for (i = 0; i < MAX_STAT; i++) - if (print_stats & STAT_MASK (i)) - logmsg (LOG_INFO, "%s: %u", gettext (stat_name[i]), wydawca_stat[i]); - } + if (stat_mask_p(print_stats)) { + for (i = 0; i < MAX_STAT; i++) + if (print_stats & STAT_MASK(i)) + logmsg(LOG_INFO, "%s: %u", + gettext(stat_name[i]), wydawca_stat[i]); + } - mail_stats (); + mail_stats(); } - void -grecs_print_diag (grecs_locus_t *locus, int err, int errcode, const char *msg) +grecs_print_diag(grecs_locus_t * locus, int err, int errcode, const char *msg) { - char *locstr = NULL; - - if (locus) - { - size_t size = 0; - - if (locus->beg.col == 0) - grecs_asprintf (&locstr, &size, "%s:%u", - locus->beg.file, - locus->beg.line); - else if (strcmp (locus->beg.file, locus->end.file)) - grecs_asprintf (&locstr, &size, "%s:%u.%u-%s:%u.%u", - locus->beg.file, - locus->beg.line, locus->beg.col, - locus->end.file, - locus->end.line, locus->end.col); - else if (locus->beg.line != locus->end.line) - grecs_asprintf (&locstr, &size, "%s:%u.%u-%u.%u", - locus->beg.file, - locus->beg.line, locus->beg.col, - locus->end.line, locus->end.col); - else - grecs_asprintf (&locstr, &size, "%s:%u.%u-%u", - locus->beg.file, - locus->beg.line, locus->beg.col, - locus->end.col); - } - - if (locstr) - { - if (errcode) - logmsg (err ? LOG_ERR : LOG_WARNING, "%s: %s: %s", - locstr, msg, strerror (errcode)); - else - logmsg (err ? LOG_ERR : LOG_WARNING, "%s: %s", - locstr, msg); - free (locstr); - } - else - { - if (errcode) - logmsg (err ? LOG_ERR : LOG_WARNING, "%s: %s", msg, - strerror (errcode)); - else - logmsg (err ? LOG_ERR : LOG_WARNING, "%s", msg); - } -} + char *locstr = NULL; + + if (locus) { + size_t size = 0; + + if (locus->beg.col == 0) + grecs_asprintf(&locstr, &size, "%s:%u", + locus->beg.file, locus->beg.line); + else if (strcmp(locus->beg.file, locus->end.file)) + grecs_asprintf(&locstr, &size, "%s:%u.%u-%s:%u.%u", + locus->beg.file, + locus->beg.line, locus->beg.col, + locus->end.file, + locus->end.line, locus->end.col); + else if (locus->beg.line != locus->end.line) + grecs_asprintf(&locstr, &size, "%s:%u.%u-%u.%u", + locus->beg.file, + locus->beg.line, locus->beg.col, + locus->end.line, locus->end.col); + else + grecs_asprintf(&locstr, &size, "%s:%u.%u-%u", + locus->beg.file, + locus->beg.line, locus->beg.col, + locus->end.col); + } + if (locstr) { + if (errcode) + logmsg(err ? LOG_ERR : LOG_WARNING, "%s: %s: %s", + locstr, msg, strerror(errcode)); + else + logmsg(err ? LOG_ERR : LOG_WARNING, "%s: %s", + locstr, msg); + free(locstr); + } else { + if (errcode) + logmsg(err ? LOG_ERR : LOG_WARNING, "%s: %s", msg, + strerror(errcode)); + else + logmsg(err ? LOG_ERR : LOG_WARNING, "%s", msg); + } +} static int uidc; static uid_t *uidv; static void -collect_uids (int argc, char **argv) +collect_uids(int argc, char **argv) { - int i; - - uidc = argc; - uidv = grecs_calloc (uidc, sizeof (uidv[0])); - for (i = 0; i < argc; i++) - { - struct passwd *pw = getpwnam (argv[i]); - if (!pw) - { - char *p; - unsigned n = strtoul (argv[i], &p, 10); - if (*p) - { - logmsg (LOG_ERR, _("no such user: %s"), argv[i]); - exit (EX_NOUSER); - } - uidv[i] = n; + int i; + + uidc = argc; + uidv = grecs_calloc(uidc, sizeof(uidv[0])); + for (i = 0; i < argc; i++) { + struct passwd *pw = getpwnam(argv[i]); + if (!pw) { + char *p; + unsigned n = strtoul(argv[i], &p, 10); + if (*p) { + logmsg(LOG_ERR, _("no such user: %s"), + argv[i]); + exit(EX_NOUSER); + } + uidv[i] = n; + } else + uidv[i] = pw->pw_uid; } - else - uidv[i] = pw->pw_uid; - } } - char **x_argv; extern int reconfigure; void -wydawca_daemon () +wydawca_daemon() { - if (!foreground) - { - if (daemon (0, 0)) - { - logmsg (LOG_ERR, "%s", strerror (errno)); - exit (EX_OSERR); + if (!foreground) { + if (daemon(0, 0)) { + logmsg(LOG_ERR, "%s", strerror(errno)); + exit(EX_OSERR); + } + logmsg(LOG_NOTICE, _("daemon launched")); } - logmsg (LOG_NOTICE, _("daemon launched")); - } - check_pidfile (); - wydawca_listener (); - remove_pidfile (); + check_pidfile(); + wydawca_listener(); + remove_pidfile(); } - #include "cmdline.h" void -version_hook (FILE *stream) +version_hook(FILE * stream) { - printf ("Compiled with:"); + printf("Compiled with:"); #ifdef WITH_LIBWRAP - printf (" libwrap"); + printf(" libwrap"); #endif #ifdef WITH_INOTIFY - printf (" inotify"); + printf(" inotify"); #endif - putchar ('\n'); + putchar('\n'); } int -main (int argc, char **argv) +main(int argc, char **argv) { - struct grecs_node *tree; - const char *p; - - program_name = argv[0]; - print_version_hook = version_hook; - mu_register_all_mailer_formats (); - mu_stdstream_setup (MU_STDSTREAM_RESET_NONE); - config_init (); - - x_argv = argv; - parse_options (argc, argv); - - argv += optind; - argc -= optind; - - p = gpgme_check_version ("1.1.0"); - if (!p) - { - logmsg (LOG_CRIT, _("GPGMe version check failed")); - exit (EX_UNAVAILABLE); - } - else if (debug_level > 3) - logmsg (LOG_DEBUG, _("using GPGME version %s"), p); - - if (argc) - collect_uids (argc, argv); - - if (preprocess_only) - exit (grecs_preproc_run (conffile, grecs_preprocessor) ? EX_CONFIG : 0); - - tree = grecs_parse (conffile); - if (!tree) - exit (EX_CONFIG); - - config_finish (tree); - grecs_tree_free (tree); - - if (lint_mode) - exit (0); - - if (dry_run_mode || selected_spools ()) - cron_option = 1; - if (cron_option) - daemon_mode = 0; - if (foreground_option >= 0) - foreground = foreground_option; - if (single_process_option >= 0) - single_process = single_process_option; - - if (log_to_stderr == -1) - log_to_stderr = (!daemon_mode || foreground) && isatty (0); - - grecs_log_to_stderr = log_to_stderr; - mu_log_tag = syslog_tag; - mu_log_facility = log_facility; - if (!log_to_stderr) - { - openlog (syslog_tag, LOG_PID, log_facility); - log_printer = syslog_printer; - } - mu_stdstream_strerr_setup (log_to_stderr ? - MU_STRERR_STDERR : MU_STRERR_SYSLOG); - - if (getgid () == 0) - { - if (wydawca_uid == 0) - { - if (!force_startup) - { - logmsg (LOG_CRIT, _("won't run with root privileges")); - exit (EX_UNAVAILABLE); - } + struct grecs_node *tree; + const char *p; + + program_name = argv[0]; + proginfo.print_version_hook = version_hook; + mu_register_all_mailer_formats(); + mu_stdstream_setup(MU_STDSTREAM_RESET_NONE); + config_init(); + + x_argv = argv; + parse_options(argc, argv); + + argv += optind; + argc -= optind; + + p = gpgme_check_version("1.1.0"); + if (!p) { + logmsg(LOG_CRIT, _("GPGMe version check failed")); + exit(EX_UNAVAILABLE); + } else if (debug_level > 3) + logmsg(LOG_DEBUG, _("using GPGME version %s"), p); + + if (argc) + collect_uids(argc, argv); + + if (preprocess_only) + exit(grecs_preproc_run(conffile, grecs_preprocessor) ? + EX_CONFIG : 0); + + tree = grecs_parse(conffile); + if (!tree) + exit(EX_CONFIG); + + config_finish(tree); + grecs_tree_free(tree); + + if (lint_mode) + exit(0); + + if (dry_run_mode || selected_spools()) + cron_option = 1; + if (cron_option) + daemon_mode = 0; + if (foreground_option >= 0) + foreground = foreground_option; + if (single_process_option >= 0) + single_process = single_process_option; + + if (log_to_stderr == -1) + log_to_stderr = (!daemon_mode || foreground) && isatty(0); + + grecs_log_to_stderr = log_to_stderr; + mu_log_tag = syslog_tag; + mu_log_facility = log_facility; + if (!log_to_stderr) { + openlog(syslog_tag, LOG_PID, log_facility); + log_printer = syslog_printer; + } + mu_stdstream_strerr_setup(log_to_stderr ? + MU_STRERR_STDERR : MU_STRERR_SYSLOG); + + if (getgid() == 0) { + if (wydawca_uid == 0) { + if (!force_startup) { + logmsg(LOG_CRIT, + _("won't run with root privileges")); + exit(EX_UNAVAILABLE); + } + } else if (wydawca_userprivs(wydawca_uid, wydawca_gid, + wydawca_supp_groups, + wydawca_supp_groupc)) + exit(EX_UNAVAILABLE); + } + + mail_init(); + wydawca_lock_init(); + + logmsg(LOG_NOTICE, _("wydawca (%s) started"), PACKAGE_STRING); + + if (!daemon_mode) { + scan_all_spools(uidc, uidv); + logstats(); + } else + wydawca_daemon(); + + logmsg(LOG_NOTICE, _("wydawca (%s) finished"), PACKAGE_STRING); + + mail_finish(); + + if (reconfigure) { + int i; + for (i = getdtablesize(); i > 2; i--) + close(i); + remove_pidfile(); + execv(x_argv[0], x_argv); } - else if (wydawca_userprivs (wydawca_uid, wydawca_gid, - wydawca_supp_groups, - wydawca_supp_groupc)) - exit (EX_UNAVAILABLE); - } - - mail_init (); - wydawca_lock_init (); - - logmsg (LOG_NOTICE, _("wydawca (%s) started"), PACKAGE_STRING); - - if (!daemon_mode) - { - scan_all_spools (uidc, uidv); - logstats (); - } - else - wydawca_daemon (); - - logmsg (LOG_NOTICE, _("wydawca (%s) finished"), PACKAGE_STRING); - - mail_finish (); - - if (reconfigure) - { - int i; - for (i = getdtablesize (); i > 2; i--) - close (i); - remove_pidfile (); - execv (x_argv[0], x_argv); - } - - exit (0); + + exit(0); } diff --git a/src/wydawca.h b/src/wydawca.h index a150595..3a90ea1 100644 --- a/src/wydawca.h +++ b/src/wydawca.h @@ -1,5 +1,5 @@ /* wydawca - automatic release submission daemon - Copyright (C) 2007-2012 Sergey Poznyakoff + Copyright (C) 2007-2013 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -73,127 +73,116 @@ #define NITEMS(a) (sizeof(a)/sizeof((a)[0])) enum dictionary_id { - project_uploader_dict, /* Contains names, gpg-keys, emails and - real names of the project uploaders */ - project_owner_dict, /* Contains names and emails of the project - owners */ - dictionary_count + project_uploader_dict, /* Contains names, gpg-keys, emails and + real names of the project uploaders */ + project_owner_dict, /* Contains names and emails of the project + owners */ + dictionary_count }; -enum dictionary_type - { - dictionary_none, /* Undefined or no dictionary */ - dictionary_sql, /* Use SQL database */ - dictionary_builtin, /* Use built-in facilities */ - dictionary_external /* Invoke an external program */ - }; - -struct dictionary -{ - enum dictionary_id id; - enum dictionary_type type; /* Dictionary type */ - char *query; /* Query template */ - int parmc; /* Number of entries in paramv */ - char **parmv; /* Parameters. The semantics differs - depending on type. For SQL: +enum dictionary_type { + dictionary_none, /* Undefined or no dictionary */ + dictionary_sql, /* Use SQL database */ + dictionary_builtin, /* Use built-in facilities */ + dictionary_external /* Invoke an external program */ +}; + +struct dictionary { + enum dictionary_id id; + enum dictionary_type type; /* Dictionary type */ + char *query; /* Query template */ + int parmc; /* Number of entries in paramv */ + char **parmv; /* Parameters. The semantics differs + depending on type. For SQL: 0 - Identifier of the SQL struct - to use; */ + to use; */ - int init_passed; /* Initialization count */ - char *result; /* Result storage */ - size_t result_size; /* Size of result */ - unsigned ncol; /* Number of columns per row */ - unsigned nrow; /* Number of rows */ + int init_passed; /* Initialization count */ + char *result; /* Result storage */ + size_t result_size; /* Size of result */ + unsigned ncol; /* Number of columns per row */ + unsigned nrow; /* Number of rows */ - void *storage; + void *storage; }; - -enum backup_type - { - no_backups, /* Don't make backups */ - simple_backups, /* Make only simple backups */ - numbered_existing_backups,/* Make numbered backups for files that already - have such backups and simple backups for the - rest */ - numbered_backups, /* Make only numbered backups */ - }; +enum backup_type { + no_backups, /* Don't make backups */ + simple_backups, /* Make only simple backups */ + numbered_existing_backups, /* Make numbered backups for files that + already have such backups and simple + backups for the rest */ + numbered_backups, /* Make only numbered backups */ +}; extern char const *simple_backup_suffix; -char *find_backup_file_name (char const *, enum backup_type); - +char *find_backup_file_name(char const *, enum backup_type); /* Archive types */ -enum archive_type - { - archive_none, /* No archivation requested */ - archive_directory, /* Archive by moving files to a separate directory - hierarchy */ - archive_tar /* Archive by appending to a tar file (tar -r) */ - }; - -struct archive_descr -{ - enum archive_type type; /* Archivation type */ - char *name; /* Directory name if type==archive_directory, - archive file name if type==archive_tar */ - enum backup_type backup_type; /* Requested backup type if - type == archive_directory */ +enum archive_type { + archive_none, /* No archivation requested */ + archive_directory, /* Archive by moving files to a separate + directory hierarchy */ + archive_tar /* Archive by appending to a tar file + (tar -r) */ }; +struct archive_descr { + enum archive_type type; /* Archivation type */ + char *name; /* Directory name if type==archive_directory, + archive file name if type==archive_tar */ + enum backup_type backup_type; /* Requested backup type if + type == archive_directory */ +}; /* Type of file in a triplet */ -enum file_type - { - file_dist, /* Something to be distributed */ - file_signature, /* Detached signature (.sig) */ - file_directive, /* Directive (.directive.asc) */ - }; +enum file_type { + file_dist, /* Something to be distributed */ + file_signature, /* Detached signature (.sig) */ + file_directive, /* Directive (.directive.asc) */ +}; #define FILE_TYPE_COUNT (file_directive+1) /* Part of a triplet */ -struct file_info -{ - enum file_type type; /* Part type */ - char *name; /* File name */ - unsigned root_len; /* Length of root part in name */ - struct stat sb; +struct file_info { + enum file_type type; /* Part type */ + char *name; /* File name */ + unsigned root_len; /* Length of root part in name */ + struct stat sb; }; -struct uploader_info -{ - struct uploader_info *next; - char *name; - char *realname; - char *email; - char *gpg_key; - char *fpr; +struct uploader_info { + struct uploader_info *next; + char *name; + char *realname; + char *email; + char *gpg_key; + char *fpr; }; /* File triplet */ -struct file_triplet -{ - char *name; /* Triplet base name */ - struct file_info file[FILE_TYPE_COUNT]; /* Components */ - unsigned version; /* Protocol version */ - const struct spool *spool; /* Owning spool */ - char *relative_dir; /* Directory relative to spool->dest_dir */ - char **directive; /* Decoded directive pairs (key: value\0) */ - char *blurb; /* Block of directives: directive[i] points here */ - char *tmp; /* Temporary storage */ - size_t tmpsize; /* Size of memory allocated in tmp */ - struct txtacc *acc; /* Text accumulator for string allocation */ - struct file_triplet *prev, *next; - /* User data */ - size_t uploader_count; - struct uploader_info *uploader_list; - struct uploader_info *uploader; - /* Special data for template formatting */ - char *project; /* Triplet project name (if known) */ - int check_result; /* Result of external check */ - char *check_diag; /* External check diagnostics */ +struct file_triplet { + char *name; /* Triplet base name */ + struct file_info file[FILE_TYPE_COUNT]; /* Components */ + unsigned version; /* Protocol version */ + const struct spool *spool; /* Owning spool */ + char *relative_dir; /* Directory relative to spool->dest_dir */ + char **directive; /* Decoded directive pairs (key: value\0) */ + char *blurb; /* Block of directives: directive[i] points here */ + char *tmp; /* Temporary storage */ + size_t tmpsize; /* Size of memory allocated in tmp */ + struct txtacc *acc; /* Text accumulator for string allocation */ + struct file_triplet *prev, *next; + /* User data */ + size_t uploader_count; + struct uploader_info *uploader_list; + struct uploader_info *uploader; + /* Special data for template formatting */ + char *project; /* Triplet project name (if known) */ + int check_result; /* Result of external check */ + char *check_diag; /* External check diagnostics */ }; /* Macros to access owner UID and GID. */ @@ -201,133 +190,117 @@ struct file_triplet #define TRIPLET_UID(t) ((t)->file[file_directive].sb.st_uid) /* GID is filled in after the triplet is finalized and verified */ #define TRIPLET_GID(t) ((t)->file[file_directive].sb.st_gid) - - -struct virt_tab -{ - int (*test_url) (mu_url_t url, grecs_locus_t *loc); - int (*move_file) (struct file_triplet *trp, enum file_type file_id); - int (*archive_file) (struct file_triplet *trp, const char *file_name); - int (*symlink_file) (struct file_triplet *trp, - const char *wanted_src, - const char *wanted_dst); - int (*rmsymlink_file)(struct file_triplet *trp, const char *file_name); +struct virt_tab { + int (*test_url) (mu_url_t url, grecs_locus_t * loc); + int (*move_file) (struct file_triplet * trp, enum file_type file_id); + int (*archive_file) (struct file_triplet * trp, const char *file_name); + int (*symlink_file) (struct file_triplet * trp, + const char *wanted_src, const char *wanted_dst); + int (*rmsymlink_file) (struct file_triplet * trp, + const char *file_name); }; /* An upload spool. This structure contains all data necessary for releasing files from source to destination */ -struct spool -{ - char *tag; - struct grecs_list *aliases; - char *url; /* Download URL */ - char *source_dir; /* Source directory */ - mu_url_t dest_url; /* Destination URL */ - const char *dest_dir; /* Directory part of the above */ - struct virt_tab vtab; /* Virtual method table */ - int inotify_enable; - - time_t file_sweep_time; /* Remove invalid/unprocessed files - after this amount of time */ - struct dictionary *dictionary[dictionary_count]; - int dict_inited; - struct archive_descr archive; /* Archivation data */ - struct notification *notification; - char *check_script; +struct spool { + char *tag; + struct grecs_list *aliases; + char *url; /* Download URL */ + char *source_dir; /* Source directory */ + mu_url_t dest_url; /* Destination URL */ + const char *dest_dir; /* Directory part of the above */ + struct virt_tab vtab; /* Virtual method table */ + int inotify_enable; + + time_t file_sweep_time; /* Remove invalid/unprocessed files + after this amount of time */ + struct dictionary *dictionary[dictionary_count]; + int dict_inited; + struct archive_descr archive; /* Archivation data */ + struct notification *notification; + char *check_script; }; -#define ASGN_SPOOL(spool, trp, faction) \ - do \ - { \ - spool = (trp)->spool; \ - if (!spool) \ - { \ - logmsg (LOG_CRIT, \ - _("INTERNAL ERROR at %s:%d: spool not defined for %s"),\ - __FILE__, __LINE__, (trp)->name); \ - faction; \ - } \ - } \ - while (0) - +#define ASGN_SPOOL(spool, trp, faction) do { \ + spool = (trp)->spool; \ + if (!spool) { \ + logmsg (LOG_CRIT, \ + _("INTERNAL ERROR at %s:%d: " \ + "spool not defined for %s"), \ + __FILE__, __LINE__, (trp)->name); \ + faction; \ + } \ + } while (0) -enum wydawca_stat - { - STAT_ERRORS, - STAT_WARNINGS, - STAT_BAD_SIGNATURE, - STAT_ACCESS_VIOLATIONS, - STAT_COMPLETE_TRIPLETS, - STAT_INCOMPLETE_TRIPLETS, - STAT_BAD_TRIPLETS, - STAT_EXPIRED_TRIPLETS, - STAT_TRIPLET_SUCCESS, - STAT_UPLOADS, - STAT_ARCHIVES, - STAT_SYMLINKS, - STAT_RMSYMLINKS, - STAT_CHECK_FAIL, - MAX_STAT - }; +enum wydawca_stat { + STAT_ERRORS, + STAT_WARNINGS, + STAT_BAD_SIGNATURE, + STAT_ACCESS_VIOLATIONS, + STAT_COMPLETE_TRIPLETS, + STAT_INCOMPLETE_TRIPLETS, + STAT_BAD_TRIPLETS, + STAT_EXPIRED_TRIPLETS, + STAT_TRIPLET_SUCCESS, + STAT_UPLOADS, + STAT_ARCHIVES, + STAT_SYMLINKS, + STAT_RMSYMLINKS, + STAT_CHECK_FAIL, + MAX_STAT +}; #define STAT_MASK(c) (1<<(c)) #define STAT_MASK_NONE 0 #define STAT_MASK_ALL (STAT_MASK(MAX_STAT) - 1) - -enum notification_event - { - ev_success, - ev_bad_ownership, - ev_bad_directive_signature, - ev_bad_detached_signature, - ev_check_fail, - MAX_EVENT - }; - -enum notification_target - { - notify_read, /* Read recipients from the message headers */ - notify_admin, /* System administrator */ - notify_owner, /* Project admin */ - notify_user /* User (uploader) */ - }; - -struct notification -{ - struct notification *next; - enum notification_event ev; - enum notification_target tgt; - const char *sign_keys; - const char *msg; +enum notification_event { + ev_success, + ev_bad_ownership, + ev_bad_directive_signature, + ev_bad_detached_signature, + ev_check_fail, + MAX_EVENT }; -void register_message_template (const char *name, const char *text); +enum notification_target { + notify_read, /* Read recipients from the message headers */ + notify_admin, /* System administrator */ + notify_owner, /* Project admin */ + notify_user /* User (uploader) */ +}; + +struct notification { + struct notification *next; + enum notification_event ev; + enum notification_target tgt; + const char *sign_keys; + const char *msg; +}; -void notify (struct notification *, - struct file_triplet *, enum notification_event); +void register_message_template(const char *name, const char *text); -const char *notification_event_str (enum notification_event evt); -const char *notification_target_str (enum notification_target tgt); +void notify(struct notification *, struct file_triplet *, + enum notification_event); +const char *notification_event_str(enum notification_event evt); +const char *notification_target_str(enum notification_target tgt); -struct metadef -{ - char *kw; - char *value; - const char *(*expand) (struct metadef *, void *); - char *storage; - void *data; +struct metadef { + char *kw; + char *value; + const char *(*expand) (struct metadef *, void *); + char *storage; + void *data; }; -char *meta_expand_string (const char *string, struct metadef *def, void *data, - struct dictionary *dict, void *handle); -void meta_free (struct metadef *def); - -const char *expand_email_admin (struct metadef *def, void *data); -const char *expand_email_owner (struct metadef *def, void *data); +char *meta_expand_string(const char *string, struct metadef *def, void *data, + struct dictionary *dict, void *handle); +void meta_free(struct metadef *def); +const char *expand_email_admin(struct metadef *def, void *data); +const char *expand_email_owner(struct metadef *def, void *data); /* Global variables */ extern char *program_name; @@ -335,16 +308,16 @@ extern uid_t wydawca_uid; extern gid_t wydawca_gid; extern size_t wydawca_supp_groupc; extern gid_t *wydawca_supp_groups; -extern char *conffile; /* Configuration file name */ -extern int debug_level; /* Debugging level */ -extern int dry_run_mode; /* Dry run indicator */ -extern int log_to_stderr; /* Log to stderr instead of the syslog */ -extern int log_facility; /* Syslog facility to use if !log_to_stderr */ -extern char *syslog_tag; /* Syslog tag */ -extern int syslog_include_prio;/* Syslog priority indication */ -extern time_t file_sweep_time; /* Unlink stale file after this amount of time - */ -extern char *tar_command_name; /* Name of the tar command */ +extern char *conffile; /* Configuration file name */ +extern int debug_level; /* Debugging level */ +extern int dry_run_mode; /* Dry run indicator */ +extern int log_to_stderr; /* Log to stderr instead of the syslog */ +extern int log_facility; /* Syslog facility to use if !log_to_stderr */ +extern char *syslog_tag; /* Syslog tag */ +extern int syslog_include_prio; /* Syslog priority indication */ +extern time_t file_sweep_time; /* Unlink stale file after this amount of time + */ +extern char *tar_command_name; /* Name of the tar command */ extern unsigned wydawca_stat[MAX_STAT]; extern unsigned long print_stats; extern int archive_signatures; @@ -380,198 +353,181 @@ extern struct spool inotify_spool; extern int inotify_enable; -#define UPDATE_STATS(what) \ - do \ - { \ - if (what >= MAX_STAT) abort(); \ - wydawca_stat[what]++; \ - } \ - while (0) - -int stat_mask_p (unsigned long mask); -struct metadef *make_stat_expansion (size_t count); -void initstats (void); -void logstats (void); +#define UPDATE_STATS(what) do { \ + if (what >= MAX_STAT) abort(); \ + wydawca_stat[what]++; \ + } while (0) +int stat_mask_p(unsigned long mask); +struct metadef *make_stat_expansion(size_t count); +void initstats(void); +void logstats(void); /* Utility functions */ -char *safe_file_name (char *file_name); -char *safe_file_name_alloc (const char *file_name); -size_t trim_length (const char *str); -size_t trim (char *str); -void logmsg (int prio, char *fmt, ...) GSC_PRINTFLIKE(2,3); -int test_dir (const char *name, int *ec); -char *create_directory (const char *base, const char *name); -int create_hierarchy (char *dir, size_t baselen); -void parse_config (void); -void log_output (int prio, const char *prog, FILE *fp); - -enum exec_result - { - exec_success, /* Command executed and returned 0 */ - exec_fail, /* Command executed and returned not 0 */ - exec_error /* Command failed to execute */ - }; - -enum exec_result wydawca_exec (int argc, const char **argv, int *retcode); +char *safe_file_name(char *file_name); +char *safe_file_name_alloc(const char *file_name); +size_t trim_length(const char *str); +size_t trim(char *str); +void logmsg(int prio, char *fmt, ...) GSC_PRINTFLIKE(2, 3); +int test_dir(const char *name, int *ec); +char *create_directory(const char *base, const char *name); +int create_hierarchy(char *dir, size_t baselen); +void parse_config(void); +void log_output(int prio, const char *prog, FILE * fp); + +enum exec_result { + exec_success, /* Command executed and returned 0 */ + exec_fail, /* Command executed and returned not 0 */ + exec_error /* Command failed to execute */ +}; +enum exec_result wydawca_exec(int argc, const char **argv, int *retcode); /* Directory scanning and registering */ -int scan_spool (struct spool *spool, int uc, uid_t *uv); -int scan_all_spools (int, uid_t *); -void spool_create_timers (void); - -int spool_add_new_file (const struct spool *spool, const char *name, - int uc, uid_t *uv); -int spool_cwd_add_new_file (const struct spool *spool, const char *name, - int uc, uid_t *uv); -int spool_open_dictionaries (struct spool *spool); -void spool_close_dictionaries (struct spool *spool); - -void parse_file_name (const char *name, struct file_info *finfo); -void file_info_cleanup (struct file_info *finfo); -int for_each_spool (int (*fun) (struct spool *, void *), void *data); -void register_spool (struct spool *spool); -struct spool *wydawca_find_spool (const char *name); -void register_file (struct file_info *finfo, const struct spool *spool); -void spool_commit_triplets (struct spool *); -size_t count_collected_triplets (void); -size_t count_processable_triplets (void); - -char *triplet_expand_param (const char *tmpl, struct file_triplet *trp); -char *triplet_expand_dictionary_query (struct dictionary *dict, void *handle, - struct file_triplet *trp); - -void triplet_remove_file (struct spool *spool, const char *name); - -time_t triplet_sweep (void); +int scan_spool(struct spool *spool, int uc, uid_t * uv); +int scan_all_spools(int, uid_t *); +void spool_create_timers(void); + +int spool_add_new_file(const struct spool *spool, const char *name, + int uc, uid_t * uv); +int spool_cwd_add_new_file(const struct spool *spool, const char *name, + int uc, uid_t * uv); +int spool_open_dictionaries(struct spool *spool); +void spool_close_dictionaries(struct spool *spool); + +void parse_file_name(const char *name, struct file_info *finfo); +void file_info_cleanup(struct file_info *finfo); +int for_each_spool(int (*fun) (struct spool *, void *), void *data); +void register_spool(struct spool *spool); +struct spool *wydawca_find_spool(const char *name); +void register_file(struct file_info *finfo, const struct spool *spool); +void spool_commit_triplets(struct spool *); +size_t count_collected_triplets(void); +size_t count_processable_triplets(void); + +char *triplet_expand_param(const char *tmpl, struct file_triplet *trp); +char *triplet_expand_dictionary_query(struct dictionary *dict, void *handle, + struct file_triplet *trp); + +void triplet_remove_file(struct spool *spool, const char *name); + +time_t triplet_sweep(void); /* General-purpose dictionary support */ -struct dictionary *dictionary_new (enum dictionary_id id, +struct dictionary *dictionary_new(enum dictionary_id id, enum dictionary_type type); -int dictionary_init (struct dictionary *dict); -int dictionary_done (struct dictionary *dict); -void *dictionary_open (struct dictionary *dict); -int dictionary_close (struct dictionary *dict, void *handle); -int dictionary_lookup (struct dictionary *dict, void *handle, const char *cmd); -void dictionary_copy_result (struct dictionary *dict, const char *res, - size_t size); -const char *dictionary_result (struct dictionary *dict, void *handle, - unsigned nrow, - unsigned ncol); -int dictionary_quote_string (struct dictionary *dict, void *handle, - const char *input, char **poutput, size_t *psize); - -unsigned dictionary_num_rows (struct dictionary *dict); -unsigned dictionary_num_cols (struct dictionary *dict); +int dictionary_init(struct dictionary *dict); +int dictionary_done(struct dictionary *dict); +void *dictionary_open(struct dictionary *dict); +int dictionary_close(struct dictionary *dict, void *handle); +int dictionary_lookup(struct dictionary *dict, void *handle, const char *cmd); +void dictionary_copy_result(struct dictionary *dict, const char *res, + size_t size); +const char *dictionary_result(struct dictionary *dict, void *handle, + unsigned nrow, unsigned ncol); +int dictionary_quote_string(struct dictionary *dict, void *handle, + const char *input, char **poutput, size_t *psize); + +unsigned dictionary_num_rows(struct dictionary *dict); +unsigned dictionary_num_cols(struct dictionary *dict); /* Verification functions */ -int verify_directive_file (struct file_triplet *trp, int noath); -int verify_directive_signature (struct file_triplet *trp); -int verify_detached_signature (struct file_triplet *trp); -int fill_project_name (struct file_triplet *trp); -struct uploader_info *uploader_find_frp (struct uploader_info *list, - const char *frp); +int verify_directive_file(struct file_triplet *trp, int noath); +int verify_directive_signature(struct file_triplet *trp); +int verify_detached_signature(struct file_triplet *trp); +int fill_project_name(struct file_triplet *trp); +struct uploader_info *uploader_find_frp(struct uploader_info *list, + const char *frp); /* Directive file support */ -int directive_parse (struct file_triplet *trp); -int directive_get_value (struct file_triplet *trp, const char *key, - const char **pval); -int directive_pack_version (const char *val, unsigned *pversion); -int directive_unpack_version (unsigned version, char **pbuf, size_t *psize); - -int directive_version_in_range_p (struct file_triplet *trp, - unsigned from, unsigned to); -int verify_directive_format (struct file_triplet *trp); -int directive_first (struct file_triplet *trp, - const char **pkey, const char **pval); -int directive_next (struct file_triplet *trp, int n, - const char **pkey, const char **pval); -int process_directives (struct file_triplet *trp); - -int enabled_spool_p (const struct spool *spool); -int selected_spools (void); - -char *triplet_strdup (struct file_triplet *tp, const char *str); - +int directive_parse(struct file_triplet *trp); +int directive_get_value(struct file_triplet *trp, const char *key, + const char **pval); +int directive_pack_version(const char *val, unsigned *pversion); +int directive_unpack_version(unsigned version, char **pbuf, size_t * psize); + +int directive_version_in_range_p(struct file_triplet *trp, + unsigned from, unsigned to); +int verify_directive_format(struct file_triplet *trp); +int directive_first(struct file_triplet *trp, const char **pkey, + const char **pval); +int directive_next(struct file_triplet *trp, int n, + const char **pkey, const char **pval); +int process_directives(struct file_triplet *trp); + +int enabled_spool_p(const struct spool *spool); +int selected_spools(void); + +char *triplet_strdup(struct file_triplet *tp, const char *str); -int parse_time_interval (const char *str, time_t *pint, const char **endp); - +int parse_time_interval(const char *str, time_t * pint, const char **endp); /* config.c */ -void config_init (void); -void config_finish (struct grecs_node *); -void config_help (void); -int assert_string_arg (grecs_locus_t *, enum grecs_callback_command, - const grecs_value_t *); - +void config_init(void); +void config_finish(struct grecs_node *); +void config_help(void); +int assert_string_arg(grecs_locus_t *, enum grecs_callback_command, + const grecs_value_t *); /* vtab.c */ -int url_to_vtab (mu_url_t url, struct virt_tab *vtab); - -int move_file (struct file_triplet *trp, enum file_type file_id); -int archive_file (struct file_triplet *trp, const char *file_name); -int symlink_file (struct file_triplet *trp, - const char *wanted_src, const char *wanted_dst); -int rmsymlink_file (struct file_triplet *trp, const char *file_name); +int url_to_vtab(mu_url_t url, struct virt_tab *vtab); +int move_file(struct file_triplet *trp, enum file_type file_id); +int archive_file(struct file_triplet *trp, const char *file_name); +int symlink_file(struct file_triplet *trp, + const char *wanted_src, const char *wanted_dst); +int rmsymlink_file(struct file_triplet *trp, const char *file_name); /* diskio.c */ -char *concat_dir (const char *base, const char *name, size_t *pbaselen); -int copy_file (const char *file, const char *dst_file); +char *concat_dir(const char *base, const char *name, size_t * pbaselen); +int copy_file(const char *file, const char *dst_file); -int dir_test_url (mu_url_t url, grecs_locus_t *locus); -int dir_move_file (struct file_triplet *trp, enum file_type file_id); -int dir_archive_file (struct file_triplet *trp, const char *reldir); -int dir_symlink_file (struct file_triplet *trp, - const char *wanted_src, const char *wanted_dst); -int dir_rmsymlink_file (struct file_triplet *trp, const char *file_name); +int dir_test_url(mu_url_t url, grecs_locus_t * locus); +int dir_move_file(struct file_triplet *trp, enum file_type file_id); +int dir_archive_file(struct file_triplet *trp, const char *reldir); +int dir_symlink_file(struct file_triplet *trp, + const char *wanted_src, const char *wanted_dst); +int dir_rmsymlink_file(struct file_triplet *trp, const char *file_name); /* null.c */ -int null_move_file (struct file_triplet *trp, enum file_type file_id); -int null_archive_file (struct file_triplet *trp, const char *file_name); -int null_symlink_file (struct file_triplet *trp, - const char *wanted_src, const char *wanted_dst); -int null_rmsymlink_file (struct file_triplet *trp, const char *file_name); - +int null_move_file(struct file_triplet *trp, enum file_type file_id); +int null_archive_file(struct file_triplet *trp, const char *file_name); +int null_symlink_file(struct file_triplet *trp, + const char *wanted_src, const char *wanted_dst); +int null_rmsymlink_file(struct file_triplet *trp, const char *file_name); /* timer.c */ typedef struct timer_slot *wydawca_timer_t; -wydawca_timer_t timer_get (const char *name); -wydawca_timer_t timer_start (const char *name); -wydawca_timer_t timer_stop (const char *name); -wydawca_timer_t timer_reset (const char *name); -double timer_get_real (wydawca_timer_t t); -double timer_get_user (wydawca_timer_t t); -double timer_get_system (wydawca_timer_t t); -char *timer_format_time (double t); -size_t timer_get_count (void); -void timer_fill_meta (struct metadef *def, size_t num); -void timer_free_meta (struct metadef *def, size_t num); - +wydawca_timer_t timer_get(const char *name); +wydawca_timer_t timer_start(const char *name); +wydawca_timer_t timer_stop(const char *name); +wydawca_timer_t timer_reset(const char *name); +double timer_get_real(wydawca_timer_t t); +double timer_get_user(wydawca_timer_t t); +double timer_get_system(wydawca_timer_t t); +char *timer_format_time(double t); +size_t timer_get_count(void); +void timer_fill_meta(struct metadef *def, size_t num); +void timer_free_meta(struct metadef *def, size_t num); -void report_init (void); -void report_add (const char *fmt, ...); -void report_finish (void); +void report_init(void); +void report_add(const char *fmt, ...); +void report_finish(void); extern char *report_string; - /* job.c */ -void schedule_job (struct spool *spool, uid_t uid); -void job_init (void); -void job_queue_runner (time_t min_timeout); - +void schedule_job(struct spool *spool, uid_t uid); +void job_init(void); +void job_queue_runner(time_t min_timeout); /* profile.c */ -void check_pidfile (void); -void remove_pidfile (void); - +void check_pidfile(void); +void remove_pidfile(void); /* net.c */ -void wydawca_listener (void); -void trim_crlf (char *s); - +void wydawca_listener(void); +void trim_crlf(char *s); #define LOCK_OK 0 #define LOCK_CONFLICT 1 @@ -579,39 +535,36 @@ void trim_crlf (char *s); #define LOCK_INVALID 3 #define LOCK_FAILURE 4 -char *wydawca_lockname (const char *tag); -int wydawca_lock (const char *lockname); -void wydawca_unlock (const char *lockname); -void wydawca_lock_init (void); - +char *wydawca_lockname(const char *tag); +int wydawca_lock(const char *lockname); +void wydawca_unlock(const char *lockname); +void wydawca_lock_init(void); /* tcpwrap.h */ extern struct grecs_keyword tcpwrapper_kw[]; int tcpwrap_access(int fd); /* userprivs.c */ -int wydawca_userprivs (uid_t uid, gid_t gid, gid_t *grplist, size_t ngrp); +int wydawca_userprivs(uid_t uid, gid_t gid, gid_t * grplist, size_t ngrp); -int push_dir (const char *dirname); -int pop_dir (void); -char *getcwd_alloc (void); +int push_dir(const char *dirname); +int pop_dir(void); +char *getcwd_alloc(void); -struct txtacc *txtacc_create (void); -void txtacc_free (struct txtacc *acc); -void txtacc_free_string (struct txtacc *acc, char *str); -void txtacc_grow (struct txtacc *acc, const char *buf, size_t size); -#define txtacc_1grow(acc, c) \ - do \ - { \ - char __ch = c; \ - txtacc_grow (acc, &__ch, 1); \ - } \ - while (0) -char *txtacc_finish (struct txtacc *acc, int steal); +struct txtacc *txtacc_create(void); +void txtacc_free(struct txtacc *acc); +void txtacc_free_string(struct txtacc *acc, char *str); +void txtacc_grow(struct txtacc *acc, const char *buf, size_t size); +#define txtacc_1grow(acc, c) do { \ + char __ch = c; \ + txtacc_grow (acc, &__ch, 1); \ + } while (0) + +char *txtacc_finish(struct txtacc *acc, int steal); #ifdef WITH_INOTIFY -int watcher_init (void); -int watcher_run (int); +int watcher_init(void); +int watcher_run(int); #else # define watcher_init() -1 # define watcher_run(c) |