aboutsummaryrefslogtreecommitdiffstats
path: root/src/common.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/common.h240
1 files changed, 207 insertions, 33 deletions
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 <stddef.h>
+#include <errno.h>
#include <string.h>
-#include <stdio.h>
+#include <time.h>
#include <stdlib.h>
-#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/timerfd.h>
-#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.
@@ -84,6 +125,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);
+
/**