From 4cba520a67e615b43dc22994670a904daf8643ae Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Fri, 1 Jan 2016 22:34:34 +0100 Subject: massive simpliciation and small bug fixes (not tested yet) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- src/common.h | 240 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 207 insertions(+), 33 deletions(-) (limited to 'src/common.h') diff --git a/src/common.h b/src/common.h index 187723e..7ee9ae5 100644 --- a/src/common.h +++ b/src/common.h @@ -22,19 +22,28 @@ #ifndef _DEFAULT_SOURCE # define _DEFAULT_SOURCE #endif +#include +#include #include -#include +#include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include -#ifndef t /** * Go to `fail` if a statement evaluates to non-zero. * * @param ... The statement. */ +#ifndef t # ifndef DEBUG # define t(...) do { if (__VA_ARGS__) goto fail; } while (0) # else @@ -45,6 +54,38 @@ static const char *failed__ = NULL; #endif +/** + * Perform some actions without changing `errno`. + * + * You must have `int saved_errno` declared. + * + * @param ... The actions. + * @return The value on `errno`. + */ +#define S(...) (saved_errno = errno, __VA_ARGS__, errno = saved_errno) + + +/** + * The file descriptor for the state file. + */ +#define STATE_FILENO 3 + +/** + * The file descriptor for the CLOCK_BOOTTIME timer. + */ +#define BOOT_FILENO 4 + +/** + * The file descriptor for the CLOCK_REALTIME timer. + */ +#define REAL_FILENO 5 + +/** + * The file descriptor for the lock file. + */ +#define LOCK_FILENO 6 + + /** * A queued job. @@ -83,6 +124,30 @@ struct job { +/** + * `dup2(OLD, NEW)` and, on success, `close(OLD)`. + * + * @param OLD:int The file descriptor to duplicate and close. + * @param NEW:int The new file descriptor. + * @return 0 on success, -1 on error. + */ +#define DUP2_AND_CLOSE(OLD, NEW) (dup2(OLD, NEW) == -1 ? -1 : (close(OLD), 0)) + +/** + * Call `CALL` which returns a file descriptor. + * Than make sure that the file descriptor's + * number is `WANT`. Go to `fail' on error. + * + * @param FD:int variable The variable where the file descriptor shall be stored. + * @param WANT:int The file descriptor the file should have. + * @parma CALL:int call Call to function that creates and returns the file descriptor. + */ +#define GET_FD(FD, WANT, CALL) \ + t (FD = CALL, FD == -1); \ + t (dup2_and_null(FD, WANT) == -1); \ + FD = WANT + + /** * Defines the function `void usage(void)` * that prints usage information. @@ -100,7 +165,6 @@ usage(void) \ exit(2); \ } - /** * Declares `argv0` and its value to * a specified string. @@ -125,49 +189,159 @@ do { \ usage(); \ } while (0) +/** + * Macro to put directly after the variable definitions in `main`. + */ +#define PROLOGUE(USAGE_ASSUMPTION, ACCESS) \ + int state = -1; \ + if (argc > 0) argv0 = argv[0]; \ + if (!(USAGE_ASSUMPTION)) usage(); \ + GET_FD(state, STATE_FILENO, open_state(ACCESS, NULL)) /** - * Construct a message from `argv` - * to send to the daemon. + * Macro to put before the cleanup code in `main`. */ -#define CONSTRUCT_MESSAGE \ - n = measure_array(argv + 1); \ - t (n ? !(msg = malloc(n)) : 0); \ - store_array(msg, argv + 1) +#define CLEANUP_START \ + errno = 0; \ +fail: \ + if (errno) perror(argv[0]); \ + if (state >= 0) close(state) + +/** + * Macro to put after the cleanup code in `main`. + */ +#define CLEANUP_END \ + return !!errno + /** - * Send message to daemon. + * Wrapper for `pread` that reads the required amount of data. * - * @param cmd:enum command Command type. - * @param n:size_t The length of the message, 0 if - * `msg` is `NULL` or NUL-terminated. - * @param msg:char * The message to send. + * @param fildes See pread(3). + * @param buf See pread(3). + * @param nbyte See pread(3). + * @param offset See pread(3). + * @return See pread(3), only short if the file is shorter. */ -#define SEND(type, n, msg) \ -do { \ - if (send_command(type, n, msg)) { \ - t (errno); \ - free(msg); \ - return 3; \ - } \ -} while (0) +ssize_t preadn(int fildes, void *buf, size_t nbyte, size_t offset); +/** + * Wrapper for `pwrite` that writes all specified data. + * + * @param fildes See pwrite(3). + * @param buf See pwrite(3). + * @param nbyte See pwrite(3). + * @param offset See pwrite(3). + * @return See pwrite(3). + */ +ssize_t pwriten(int fildes, const void *buf, size_t nbyte, size_t offset); + +/** + * Unmarshal a `NULL`-terminated string array. + * + * The elements are not actually copied, subpointers + * to `buf` are stored in the returned list. + * + * @param buf The marshalled array. Must end with a NUL byte. + * @param len The length of `buf`. + * @param n Output parameter for the number of elements. May be `NULL` + * @return The list, `NULL` on error. + * + * @throws Any exception specified for realloc(3). + */ +char **restore_array(char *buf, size_t len, size_t *n); + +/** + * Create `NULL`-terminate subcopy of an list, + * + * @param list The list. + * @param n The number of elements in the new sublist. + * @return The sublist, `NULL` on error. + * + * @throws Any exception specified for malloc(3). + */ +char **sublist(char *const *list, size_t n); /** - * Exit the process with status indicating success. + * Create a new open file descriptor for an already + * existing file descriptor. * - * Defined the label `fail`. + * @param fd The file descriptor that shall be promoted + * to a new open file descriptor. + * @param oflag See open(3), `O_CREAT` is not allowed. + * @return 0 on success, -1 on error. + */ +int reopen(int fd, int oflag); + +/** + * Run a job or a hook. * - * @param msg The message send to the daemon. + * @param job The job. + * @param hook The hook, `NULL` to run the job. + * @return 0 on success, -1 on error, 1 if the child failed. */ -#define END(msg) \ - free(msg); \ - return 0; \ -fail: \ - perror(argv0); \ - free(msg); \ - return 1; +int run_job_or_hook(struct job *job, const char *hook); + +/** + * Removes (and optionally runs) a job. + * + * @param jobno The job number, `NULL` for any job. + * @param runjob Shall we run the job too? 2 if its time has expired (not forced). + * @return 0 on success, -1 on error. + * + * @throws 0 The job is not in the queue. + */ +int remove_job(const char *jobno, int runjob); + +/** + * Get a `NULL`-terminated list of all queued jobs. + * + * @return A `NULL`-terminated list of all queued jobs. `NULL` on error. + */ +struct job **get_jobs(void); + +/** + * Duplicate a file descriptor, and + * open /dev/null to the old file descriptor. + * However, if `old` is 3 or greater, it will + * be closed rather than /dev/null. + * + * @param old The old file descriptor. + * @param new The new file descriptor. + * @return `new`, -1 on error. + */ +int dup2_and_null(int old, int new); + +/** + * Create or open the state file. + * + * @param open_flags Flags (the second parameter) for `open`. + * @param state_path Output parameter for the state file's pathname. + * May be `NULL`; + * @return A file descriptor to the state file, -1 on error. + * + * @throws 0 `!(open_flags & O_CREAT)` and the file does not exist. + */ +int open_state(int open_flags, char **state_path); + +/** + * Let the daemon know that it may need to + * update the timers, and perhaps exit. + * + * @param start Start the daemon if it is not running? + * @param name The name of the process. + * @return 0 on success, -1 on error. + */ +int poke_daemon(int start, const char *name); + +/** + * Set SAT_HOOK_PATH. + * + * @return 0 on success, -1 on error. + */ +int set_hookpath(void); + /** -- cgit v1.2.3-70-g09d2