diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-01-01 13:25:55 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-01-01 13:33:04 +0200 |
commit | 24e6dfa7cffceea0cac0f3cc349192788f040939 (patch) | |
tree | c2bd53e9bc58873c8187e6bd622ae152b35d1d51 /src/directive.c | |
parent | 2bdd70d698c63d32f25b4f1142e09f5eaef4812a (diff) | |
download | wydawca-24e6dfa7cffceea0cac0f3cc349192788f040939.tar.gz wydawca-24e6dfa7cffceea0cac0f3cc349192788f040939.tar.bz2 |
Update copyright years. Switch to a familiar style.
Diffstat (limited to 'src/directive.c')
-rw-r--r-- | src/directive.c | 1152 |
1 files changed, 558 insertions, 594 deletions
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; + + UPD |