aboutsummaryrefslogtreecommitdiffstats
path: root/src/daemon.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@member.fsf.org>2016-01-01 22:34:34 +0100
committerMattias Andrée <maandree@member.fsf.org>2016-01-01 22:34:34 +0100
commit4cba520a67e615b43dc22994670a904daf8643ae (patch)
tree6649c99fa94d8b7842a8ca7df7478ccf722d4c67 /src/daemon.c
parentremove satd-rm and satd-r and let satrm and satr do everything (not done yet) (diff)
downloadsat-4cba520a67e615b43dc22994670a904daf8643ae.tar.gz
sat-4cba520a67e615b43dc22994670a904daf8643ae.tar.bz2
sat-4cba520a67e615b43dc22994670a904daf8643ae.tar.xz
massive simpliciation and small bug fixes (not tested yet)
Signed-off-by: Mattias Andrée <maandree@member.fsf.org>
Diffstat (limited to 'src/daemon.c')
-rw-r--r--src/daemon.c488
1 files changed, 0 insertions, 488 deletions
diff --git a/src/daemon.c b/src/daemon.c
deleted file mode 100644
index a39b0e3..0000000
--- a/src/daemon.c
+++ /dev/null
@@ -1,488 +0,0 @@
-/**
- * Copyright © 2015, 2016 Mattias Andrée <maandree@member.fsf.org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-#include "daemon.h"
-#include <ctype.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <sys/wait.h>
-
-
-
-/**
- * The environment.
- */
-extern char **environ;
-
-
-
-/**
- * Common code for `preadn` and `pwriten`.
- *
- * @param FUN `pread` or `pwrite`.
- */
-#define PIO(FUN) \
- ssize_t r, n = 0; \
- int saved_errno = 0; \
- sigset_t mask, oldmask; \
- sigfillset(&mask); \
- sigprocmask(SIG_BLOCK, &mask, &oldmask); \
- while (nbyte) { \
- t (r = FUN(fildes, buffer, nbyte, (off_t)offset), r < 0); \
- if (r == 0) \
- break; \
- n += r; \
- buffer += r; \
- offset += (size_t)r; \
- nbyte -= (size_t)r; \
- } \
-done: \
- sigprocmask(SIG_SETMASK, &oldmask, NULL); \
- errno = saved_errno; \
- return n; \
-fail: \
- saved_errno = errno; \
- n = -1; \
- goto done
-
-
-/**
- * Wrapper for `pread` that reads the required amount of data.
- *
- * @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.
- */
-ssize_t
-preadn(int fildes, void *buf, size_t nbyte, size_t offset)
-{
- char *buffer = buf;
- PIO(pread);
-}
-
-
-/**
- * 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)
-{
- const char *buffer = buf;
- PIO(pwrite);
-}
-
-
-/**
- * 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.
- * @return 0 on success, -1 on error.
- *
- * @throws Any exception specified for read(3).
- * @throws Any exception specified for realloc(3).
- */
-int
-readall(int fd, char **buf, size_t *n)
-{
- char *buffer = NULL;
- size_t ptr = 0, size = 128;
- ssize_t got;
- char *new;
- int saved_errno;
-
- do {
- if ((buffer == NULL) || (ptr == size)) {
- t (!(new = realloc(buffer, size <<= 1)));
- buffer = new;
- }
- t (got = read(fd, buffer + ptr, size - ptr), got < 0);
- } while (ptr += (size_t)got, got);
-
- new = realloc(buffer, *n = ptr);
- *buf = ptr ? (new ? new : buffer) : NULL;
- shutdown(SOCK_FILENO, SHUT_RD);
- return errno = EBADMSG, 0;
-
-fail:
- saved_errno = errno;
- free(buffer);
- shutdown(SOCK_FILENO, SHUT_RD);
- errno = saved_errno;
- return -1;
-}
-
-
-/**
- * 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)
-{
- char **rc = malloc((len + 1) * sizeof(char*));
- char **new = NULL;
- size_t i = 0, e = 0;
-
- t (!rc);
- while (i < len) i += strlen(rc[e++] = buf + i) + 1;
- if (n) *n = e;
- rc[e++] = NULL;
- new = realloc(rc, e * sizeof(char*));
-fail:
- return new ? new : rc;
-}
-
-
-/**
- * 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)
-{
- char **rc = malloc((n + 1) * sizeof(char*));
- t (!rc);
- for (rc[n] = NULL; n--; rc[n] = list[n]);
-fail:
- return rc;
-}
-
-
-/**
- * Create a new open file descriptor for an already
- * existing file descriptor.
- *
- * @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)
-{
- char path[sizeof("/dev/fd/") + 3 * sizeof(int)];
- int r, saved_errno;
-
- sprintf(path, "/dev/fd/%i", fd);
- if (r = open(path, oflag), r < 0)
- return -1;
- if (DUP2_AND_CLOSE(r, fd) == -1)
- return saved_errno = errno, close(r), errno = saved_errno, -1;
- return 0;
-}
-
-
-/**
- * Send a string to a client.
- *
- * @param sockfd The file descriptor of the socket.
- * @param outfd The file descriptor to which the client shall output the message.
- * @param ... `NULL`-terminated list of string to concatenate.
- * @return 0 on success, -1 on error.
- */
-int
-send_string(int sockfd, int outfd, ...)
-{
- va_list args;
- size_t i, n = 0;
- ssize_t r;
- char out = (char)outfd;
- const char *s;
-
- va_start(args, outfd);
- while ((s = va_arg(args, const char *)))
- n += strlen(s);
- va_end(args);
-
- t (write(sockfd, &out, sizeof(out)) < (ssize_t)sizeof(out));
- t (write(sockfd, &n, sizeof(n)) < (ssize_t)sizeof(n));
-
- va_start(args, outfd);
- while ((s = va_arg(args, const char *)))
- for (i = 0, n = strlen(s); i < n; i += (size_t)r)
- t (r = write(sockfd, s + i, n - i), r <= 0);
- va_end(args);
-
- return 0;
-fail:
- return -1;
-}
-
-
-/**
- * Run a job or a hook.
- *
- * @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.
- */
-int
-run_job_or_hook(struct job *job, const char *hook)
-{
- pid_t pid;
- char **args = NULL;
- char **argv = NULL;
- char **envp = NULL;
- size_t argsn;
- void *new;
- int status = 0, saved_errno;
-
- t (!(args = restore_array(job->payload, job->n, &argsn)));
- t (!(argv = sublist(args, (size_t)(job->argc))));
- t (!(envp = sublist(args + job->argc, argsn - (size_t)(job->argc)))); /* Includes wdir. */
- free(args), args = NULL;
-
- if (hook) {
- t (!(new = realloc(argv, ((size_t)(job->argc) + 3) * sizeof(*argv))));
- argv = new;
- memmove(argv + 2, argv, ((size_t)(job->argc) + 1) * sizeof(*argv));
- argv[0] = getenv("SAT_HOOK_PATH");
- argv[1] = (strstr)(hook, hook); /* strstr: just to remove a warning */
- }
-
- if (!(pid = fork())) {
- close(SOCK_FILENO), close(STATE_FILENO);
- close(BOOT_FILENO), close(REAL_FILENO);
- (void)(status = chdir(envp[0]));
- environ = envp + 1;
- execvp(*argv, argv);
- exit(1);
- }
-
- t ((pid < 0) || (waitpid(pid, &status, 0) != pid));
-fail:
- saved_errno = errno;
- free(args), free(argv), free(envp);
- errno = saved_errno;
- return status ? 1 : -!!saved_errno;
-}
-
-
-/**
- * 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)
-{
- char *end;
- char *buf = NULL;
- size_t no = 0, off = sizeof(size_t), n;
- ssize_t r;
- struct stat attr;
- struct job job;
- struct job *job_full = NULL;
- int rc = 0, saved_errno = 0;
-
- if (jobno) {
- no = (errno = 0, strtoul)(jobno, &end, 10);
- if (errno || *end || !isdigit(*jobno))
- return 0;
- }
-
- t (flock(STATE_FILENO, LOCK_EX));
- t (fstat(STATE_FILENO, &attr));
- for (n = (size_t)(attr.st_size); off < n; off += sizeof(job) + job.n) {
- t (preadn(STATE_FILENO, &job, sizeof(job), off) < (ssize_t)sizeof(job));
- if (!jobno || (job.no == no))
- goto found_it;
- }
- flock(STATE_FILENO, LOCK_UN); /* Failure isn't fatal. */
- return errno = 0, -1;
-
-found_it:
- t (!(job_full = malloc(sizeof(job) + job.n)));
- *job_full = job;
- t (preadn(STATE_FILENO, job_full->payload, job.n, off + sizeof(job)) < (ssize_t)(job.n));
- n -= off + sizeof(job) + job.n;
- t (!(buf = malloc(n)));
- t (r = preadn(STATE_FILENO, buf, n, off + sizeof(job) + job.n), r < 0);
- t (pwriten(STATE_FILENO, buf, (size_t)r, off) < 0);
- t (ftruncate(STATE_FILENO, (off_t)r + (off_t)off));
- free(buf), buf = NULL;
- fsync(STATE_FILENO);
-
- if (runjob) {
- run_job_or_hook(job_full, runjob == 2 ? "expired" : "forced");
- rc = run_job_or_hook(job_full, NULL);
- saved_errno = errno;
- run_job_or_hook(job_full, rc ? "failure" : "success");
- rc = rc == 1 ? 0 : rc;
- } else {
- run_job_or_hook(job_full, "removed");
- }
-
- free(job_full);
- flock(STATE_FILENO, LOCK_UN); /* Unlock late so that hooks are synchronised. Failure isn't fatal. */
- errno = saved_errno;
- return rc;
-
-fail:
- saved_errno = errno;
- flock(STATE_FILENO, LOCK_UN);
- free(buf), free(job_full);
- errno = saved_errno;
- return -1;
-}
-
-
-/**
- * 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)
-{
- size_t off = sizeof(size_t), n, j = 0;
- struct stat attr;
- struct job **js = NULL;
- struct job job;
- int saved_errno;
-
- t (flock(STATE_FILENO, LOCK_SH));
- t (fstat(STATE_FILENO, &attr));
- n = (size_t)(attr.st_size);
- t (!(js = malloc((n / sizeof(**js) + 1) * sizeof(*js))));
- while (off < n) {
- t (preadn(STATE_FILENO, &job, sizeof(job), off) < (ssize_t)sizeof(job));
- off += sizeof(job);
- t (!(js[j] = malloc(sizeof(job) + job.n)));
- *(js[j]) = job;
- t (preadn(STATE_FILENO, js[j++]->payload, job.n, off) < (ssize_t)(job.n));
- off += job.n;
- }
- t (flock(STATE_FILENO, LOCK_UN));
- return js[j] = NULL, js;
-
-fail:
- saved_errno = errno;
- flock(STATE_FILENO, LOCK_UN);
- while (j--) free(js[j]);
- free(js);
- errno = saved_errno;
- return NULL;
-}
-
-
-/**
- * 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)
-{
- int fd = -1, saved_errno;
-
- if (old == new) return new; t (DUP2_AND_CLOSE(old, new));
- if (old >= 3) return new; t (fd = open("/dev/null", O_RDWR), fd == -1);
- if (fd == old) return new; t (DUP2_AND_CLOSE(fd, old));
- return new;
-fail:
- saved_errno = errno, close(fd), errno = saved_errno;
- return -1;
-}
-
-
-/**
- * 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)
-{
- const char *dir;
- char *path;
- int fd = -1, saved_errno;
-
- /* Create directory. */
- dir = getenv("XDG_RUNTIME_DIR"), dir = (dir ? dir : "/run");
- t (!(path = malloc(strlen(dir) * sizeof(char) + sizeof("/" PACKAGE "/state"))));
- stpcpy(stpcpy(path, dir), "/" PACKAGE "/state");
- t (fd = open(path, open_flags, S_IRUSR | S_IWUSR), fd == -1);
-
- if (state_path) *state_path = path, path = NULL;
- else free(path), path = NULL;
-fail:
- saved_errno = errno, free(path), errno = saved_errno;
- if (!(open_flags & O_CREAT) && ((errno == ENOENT) || (errno == ENOTDIR)))
- errno = 0;
- return fd;
-}
-
-
-/**
- * Let the daemon know that it may need to
- * update the timers, and perhaps exit.
- *
- * @return 0 on success, -1 on error.
- */
-int
-poke_daemon(void)
-{
- return 0; /* TODO poke_daemon */
-}
-