From 75eab72cf3e5d70f55af52c62ea5adc11294dc26 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Fri, 1 Jan 2016 09:34:28 +0100 Subject: further improvement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- src/README | 3 +- src/client.c | 1 - src/client.h | 1 + src/common.h | 83 +++++++++++++++++++++++++++++++++++++++++++++ src/daemon.c | 4 ++- src/daemon.h | 104 ++------------------------------------------------------- src/sat.c | 27 ++++++--------- src/satd-add.c | 43 ++++++++++-------------- src/satd.c | 1 - src/satq.c | 1 - src/satr.c | 1 - src/satrm.c | 1 - 12 files changed, 120 insertions(+), 150 deletions(-) diff --git a/src/README b/src/README index c77d17e..51fa80c 100644 --- a/src/README +++ b/src/README @@ -23,5 +23,6 @@ client.[ch] Used by sat{,q,r,rm}.c, code for communicating daemon.[ch] Used by satd*.c, some shared code for daemons objects. -common.h Used by sat{,q,r,rm,d}.c, some shared code. +common.h Used by sat{,q,r,rm,d'}.c, some shared code. + Included via client.h and daemon.h. diff --git a/src/client.c b/src/client.c index 3573f46..80cd527 100644 --- a/src/client.c +++ b/src/client.c @@ -20,7 +20,6 @@ * DEALINGS IN THE SOFTWARE. */ #include "client.h" -#include "common.h" #include #include #include diff --git a/src/client.h b/src/client.h index a7640e7..8f27d73 100644 --- a/src/client.h +++ b/src/client.h @@ -22,6 +22,7 @@ #ifndef _DEFAULT_SOURCE # define _DEFAULT_SOURCE #endif +#include "common.h" #include diff --git a/src/common.h b/src/common.h index 68d465e..187723e 100644 --- a/src/common.h +++ b/src/common.h @@ -46,6 +46,43 @@ static const char *failed__ = NULL; +/** + * A queued job. + */ +struct job { + /** + * The job number. + */ + size_t no; + + /** + * The number of “argv” elements in `payload`. + */ + int argc; + + /** + * The clock in which `ts` is measured. + */ + clockid_t clk; + + /** + * The time when the job shall be executed. + */ + struct timespec ts; + + /** + * The number of bytes in `payload`. + */ + size_t n; + + /** + * “argv” followed by “envp”. + */ + char payload[]; +}; + + + /** * Defines the function `void usage(void)` * that prints usage information. @@ -132,3 +169,49 @@ fail: \ free(msg); \ return 1; + +/** + * This block of code allows us to compile with DEBUG=valgrind + * or DEBUG=strace and have all exec:s be wrapped in + * valgrind --leak-check=full --show-leak-kinds=all or + * strace, respectively. Very useful for debugging. However, + * children do not inherit strace, so between forking and + * exec:ing we do not have strace. + */ +#if 1 && defined(DEBUG) +# if ((DEBUG == 2) || (DEBUG == 3)) +# ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" +__attribute__((__used__)) +# endif +# if DEBUG == 2 +# define DEBUGPROG "strace" +# else +# define DEBUGPROG "valgrind" +# endif +# define execl(path, _, ...) (execl)("/usr/bin/" DEBUGPROG, "/usr/bin/" DEBUGPROG, path, __VA_ARGS__) +# define execve(...) execve_(__VA_ARGS__) +static int +execve_(const char *path, char *const argv[], char *const envp[]) +{ + size_t n = 0; + char **new_argv = NULL; + int x = (DEBUG - 2) * 2, saved_errno; + while (argv[n++]); + t (!(new_argv = malloc((n + 1 + (size_t)x) * sizeof(char *)))); + new_argv[x] = "--show-leak-kinds=all"; + new_argv[1] = "--leak-check=full"; + new_argv[0] = "/usr/bin/" DEBUGPROG; + new_argv[1 + x] = path; + memcpy(new_argv + 2 + x, argv + 1, (n - 1) * sizeof(char *)); + (execve)(*new_argv, new_argv, envp); +fail: + return saved_errno = errno, free(new_argv), errno = saved_errno, -1; +} +# ifdef __GNUC__ +# pragma GCC diagnostic pop +# endif +# endif +#endif + diff --git a/src/daemon.c b/src/daemon.c index e4c444e..ee05cf7 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -103,6 +103,8 @@ pwriten(int fildes, const void *buf, size_t nbyte, size_t offset) /** * Wrapper for `read` that reads all available data. * + * `errno` is set to `EBADMSG` on success. + * * @param fd The file descriptor from which to to read. * @param buf Output parameter for the data. * @param n Output parameter for the number of read bytes. @@ -131,7 +133,7 @@ readall(int fd, char **buf, size_t *n) new = realloc(buffer, *n = ptr); *buf = ptr ? (new ? new : buffer) : NULL; shutdown(SOCK_FILENO, SHUT_RD); - return 0; + return errno = EBADMSG, 0; fail: saved_errno = errno; diff --git a/src/daemon.h b/src/daemon.h index d860d1f..cb6736a 100644 --- a/src/daemon.h +++ b/src/daemon.h @@ -22,6 +22,7 @@ #ifndef _DEFAULT_SOURCE # define _DEFAULT_SOURCE #endif +#include "common.h" #include #include #include @@ -83,23 +84,6 @@ -#ifndef t -/** - * Go to `fail` if a statement evaluates to non-zero. - * - * @param ... The statement. - */ -# ifndef DEBUG -# define t(...) do { if (__VA_ARGS__) goto fail; } while (0) -# else -# define t(...) do { if ((__VA_ARGS__) ? (failed__ = #__VA_ARGS__) : 0) { (perror)(failed__); goto fail; } } while (0) -static const char *failed__ = NULL; -# define perror(_) ((void)(_)) -# endif -#endif - - - /** * `dup2(OLD, NEW)` and, on success, `close(OLD)`. * @@ -143,43 +127,6 @@ fail: \ -/** - * A queued job. - */ -struct job { - /** - * The job number. - */ - size_t no; - - /** - * The number of “argv” elements in `payload`. - */ - int argc; - - /** - * The clock in which `ts` is measured. - */ - clockid_t clk; - - /** - * The time when the job shall be executed. - */ - struct timespec ts; - - /** - * The number of bytes in `payload`. - */ - size_t n; - - /** - * “argv” followed by “envp”. - */ - char payload[]; -}; - - - /** * Wrapper for `pread` that reads the required amount of data. * @@ -205,6 +152,8 @@ ssize_t pwriten(int fildes, const void *buf, size_t nbyte, size_t offset); /** * Wrapper for `read` that reads all available data. * + * `errno` is set to `EBADMSG` on success. + * * @param fd The file descriptor from which to to read. * @param buf Output parameter for the data. * @param n Output parameter for the number of read bytes. @@ -289,50 +238,3 @@ int remove_job(const char *jobno, int runjob); */ struct job **get_jobs(void); - - -/** - * This block of code allows us to compile with DEBUG=valgrind - * or DEBUG=strace and have all exec:s be wrapped in - * valgrind --leak-check=full --show-leak-kinds=all or - * strace, respectively. Very useful for debugging. However, - * children do not inherit strace, so between forking and - * exec:ing we do not have strace. - */ -#if 1 && defined(DEBUG) -# if ((DEBUG == 2) || (DEBUG == 3)) -# ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" -__attribute__((__used__)) -# endif -# if DEBUG == 2 -# define DEBUGPROG "strace" -# else -# define DEBUGPROG "valgrind" -# endif -# define execl(path, _, ...) (execl)("/usr/bin/" DEBUGPROG, "/usr/bin/" DEBUGPROG, path, __VA_ARGS__) -# define execve(...) execve_(__VA_ARGS__) -static int -execve_(const char *path, char *const argv[], char *const envp[]) -{ - size_t n = 0; - char **new_argv = NULL; - int x = (DEBUG - 2) * 2, saved_errno; - while (argv[n++]); - t (!(new_argv = malloc((n + 1 + (size_t)x) * sizeof(char *)))); - new_argv[x] = "--show-leak-kinds=all"; - new_argv[1] = "--leak-check=full"; - new_argv[0] = "/usr/bin/" DEBUGPROG; - new_argv[1 + x] = path; - memcpy(new_argv + 2 + x, argv + 1, (n - 1) * sizeof(char *)); - (execve)(*new_argv, new_argv, envp); -fail: - return saved_errno = errno, free(new_argv), errno = saved_errno, -1; -} -# ifdef __GNUC__ -# pragma GCC diagnostic pop -# endif -# endif -#endif - diff --git a/src/sat.c b/src/sat.c index 5431208..147c327 100644 --- a/src/sat.c +++ b/src/sat.c @@ -21,7 +21,6 @@ */ #include "parse_time.h" #include "client.h" -#include "common.h" #include #include @@ -53,19 +52,20 @@ main(int argc, char *argv[], char *envp[]) { #define E(CASE, DESC) case CASE: return fprintf(stderr, "%s: %s: %s\n", argv0, DESC, argv[1]), 2 - struct timespec ts; - clockid_t clk; char *msg = NULL; + char *timearg; void *new; - size_t n, size = 64; + size_t size = 64; + struct job job = { .no = 0 }; if ((argc < 3) || (argv[1][0] == '-')) usage(); - argv0 = argv[0]; + argv0 = argv[0], timearg = argv[1]; + job.argc = argc -= 2, argv += 2; /* Parse the time argument. */ - if (parse_time(argv[1], &ts, &clk)) { + if (parse_time(timearg, &(job.ts), &(job.clk))) { switch (errno) { E (EINVAL, "time parameter cound not be parsed, perhaps you need an external parser"); E (ERANGE, "the specified time is beyond the limit of what can be stored"); @@ -74,9 +74,6 @@ main(int argc, char *argv[], char *envp[]) } } - argc -= 2; - argv += 2; - retry: /* Get the size of the current working directory's pathname. */ t (!(new = realloc(msg, size <<= 1))); @@ -87,15 +84,13 @@ retry: size = strlen(getcwd(msg, size)) + 1, free(msg); /* Construct message to send to the daemon. */ - n = measure_array(argv) + size + measure_array(envp); - t (!(msg = malloc(n + sizeof(argc) + sizeof(clk) + sizeof(ts)))); - store_array(getcwd(store_array(msg, argv), size) + size, envp); - memcpy(msg + n, &argc, sizeof(argc)), n += sizeof(argc); - memcpy(msg + n, &clk, sizeof(clk)), n += sizeof(clk); - memcpy(msg + n, &ts, sizeof(ts)), n += sizeof(ts); + job.n = measure_array(argv) + size + measure_array(envp); + t (!(msg = malloc(sizeof(job) + job.n))); + memcpy(msg, &job, sizeof(job)); + store_array(getcwd(store_array(msg + sizeof(job), argv), size) + size, envp); /* Send job to daemon, start daemon if necessary. */ - SEND(SAT_QUEUE, n, msg); + SEND(SAT_QUEUE, sizeof(job) + job.n, msg); END(msg); } diff --git a/src/satd-add.c b/src/satd-add.c index fba4465..c550072 100644 --- a/src/satd-add.c +++ b/src/satd-add.c @@ -37,49 +37,40 @@ int main(int argc, char *argv[]) { +#define M ((struct job *)message) + size_t n = 0, elements = 0, i; ssize_t r; char *message = NULL; - int msg_argc; - struct job *job = NULL; struct stat attr; DAEMON_PROLOGUE; /* Receive and validate message. */ - t (readall(SOCK_FILENO, &message, &n)); - t (n < sizeof(int) + sizeof(clockid_t) + sizeof(struct timespec)); - n -= sizeof(int) + sizeof(clockid_t) + sizeof(struct timespec); - msg_argc = *(int *)(message + n); - t ((msg_argc < 1) || !n || message[n - 1]); - for (i = n; i--; elements += !message[i]); - t (elements < (size_t)msg_argc); - - /* Parse message. */ - t (!(job = malloc(sizeof(*job) + n))); - job->argc = msg_argc;/* *(int *)(message + n); "See a few lines above."; */ - job->clk = *(clockid_t *)(message + n + sizeof(int)); - job->ts = *(struct timespec *)(message + n + sizeof(int) + sizeof(clockid_t)); - memcpy(job->payload, message, job->n = n); + t (readall(SOCK_FILENO, &message, &n) || (n < sizeof(struct job))); + t (M->n != (n -= sizeof(struct job))); + t ((M->argc < 1) || !n || message[sizeof(struct job) - 1 + n]); + for (i = n; i--; elements += !message[sizeof(struct job) + i]); + t (elements < (size_t)(M->argc)); /* Update state file and run hook. */ t (flock(STATE_FILENO, LOCK_EX)); t (fstat(STATE_FILENO, &attr)); - t (r = preadn(STATE_FILENO, &(job->no), sizeof(job->no), (size_t)0), r < 0); - if (r < (ssize_t)sizeof(job->no)) - job->no = 0; + t (r = preadn(STATE_FILENO, &(M->no), sizeof(M->no), (size_t)0), r < 0); + if (r < (ssize_t)sizeof(M->no)) + M->no = 0; else - job->no += 1; - t (pwriten(STATE_FILENO, &(job->no), sizeof(job->no), (size_t)0) < (ssize_t)sizeof(job->no)); - if (attr.st_size < (off_t)sizeof(job->no)) - attr.st_size = (off_t)sizeof(job->no); - t (pwriten(STATE_FILENO, job, sizeof(*job) + n, (size_t)(attr.st_size)) < (ssize_t)n); + M->no += 1; + t (pwriten(STATE_FILENO, &(M->no), sizeof(M->no), (size_t)0) < (ssize_t)sizeof(M->no)); + if (attr.st_size < (off_t)sizeof(M->no)) + attr.st_size = (off_t)sizeof(M->no); + n += sizeof(struct job); + t (pwriten(STATE_FILENO, message, n, (size_t)(attr.st_size)) < (ssize_t)n); fsync(STATE_FILENO); - run_job_or_hook(job, "queued"); + run_job_or_hook(M, "queued"); t (flock(STATE_FILENO, LOCK_UN)); DAEMON_CLEANUP_START; free(message); - free(job); DAEMON_CLEANUP_END; } diff --git a/src/satd.c b/src/satd.c index 8865c51..d9745ef 100644 --- a/src/satd.c +++ b/src/satd.c @@ -19,7 +19,6 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#include "common.h" #include "daemon.h" #include "daemonise.h" #include diff --git a/src/satq.c b/src/satq.c index e851c1b..7f92878 100644 --- a/src/satq.c +++ b/src/satq.c @@ -20,7 +20,6 @@ * DEALINGS IN THE SOFTWARE. */ #include "client.h" -#include "common.h" diff --git a/src/satr.c b/src/satr.c index 0543d58..42bfda4 100644 --- a/src/satr.c +++ b/src/satr.c @@ -20,7 +20,6 @@ * DEALINGS IN THE SOFTWARE. */ #include "client.h" -#include "common.h" diff --git a/src/satrm.c b/src/satrm.c index 45f4bc2..fda6288 100644 --- a/src/satrm.c +++ b/src/satrm.c @@ -20,7 +20,6 @@ * DEALINGS IN THE SOFTWARE. */ #include "client.h" -#include "common.h" -- cgit v1.2.3-70-g09d2