aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/client.c2
-rw-r--r--src/client.h2
-rw-r--r--src/common.h121
-rw-r--r--src/daemonise.c36
-rw-r--r--src/parse_time.c28
-rw-r--r--src/sat.c57
-rw-r--r--src/satd.c60
-rw-r--r--src/satq.c28
-rw-r--r--src/satr.c57
-rw-r--r--src/satrm.c50
10 files changed, 206 insertions, 235 deletions
diff --git a/src/client.c b/src/client.c
index c4f2987..b7a43eb 100644
--- a/src/client.c
+++ b/src/client.c
@@ -45,7 +45,7 @@ extern char *argv0;
int
send_command(enum command cmd, size_t n, const char *restrict msg)
{
- return 0 /* TODO */
+ return 0; /* TODO */
}
diff --git a/src/client.h b/src/client.h
index 6a2b91b..d341df6 100644
--- a/src/client.h
+++ b/src/client.h
@@ -71,7 +71,7 @@ int send_command(enum command cmd, size_t n, const char *restrict msg);
* @param array The string array.
* @return The number of bytes required to store the array.
*/
-size_t measure_array(char *array[])
+size_t measure_array(char *array[]);
/**
* Store a string array.
diff --git a/src/common.h b/src/common.h
new file mode 100644
index 0000000..2f8ac86
--- /dev/null
+++ b/src/common.h
@@ -0,0 +1,121 @@
+/**
+ * Copyright © 2015 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 <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+
+
+/**
+ * Go to `fail` if a statement evaluates to non-zero.
+ *
+ * @param ... The statement.
+ */
+#define t(...) do { if (__VA_ARGS__) goto fail; } while (0)
+
+
+
+/**
+ * Defines the function `void usage(void)`
+ * that prints usage information.
+ *
+ * @param synopsis:const char* The command's synopsis sans command name.
+ * `NULL` if there are not arguments.
+ */
+#define USAGE(synopsis) \
+static void \
+usage(void) \
+{ \
+ fprintf(stderr, "usage: %s%s%s\n", \
+ strrchr(argv0, '/') ? (strrchr(argv0, '/') + 1) : argv0, \
+ (synopsis) ? " " : "", synopsis ? synopsis : ""); \
+ exit(2); \
+}
+
+
+/**
+ * Declares `argv0` and its value to
+ * a specified string.
+ *
+ * @param name:sitrng literal The name of the command.
+ */
+#define COMMAND(name) \
+char *argv0 = name;
+
+
+/**
+ * Print usage and exit if there is any argument
+ * that is an option.
+ */
+#define NO_OPTIONS \
+ int i;
+ if (!strcmp(argv[1], "--")) \
+ argv++, argc--; \
+ for (i = 1; i < argc; i++) \
+ if (strchr("-", argv[i][0])) \
+ usage()
+
+
+/**
+ * Construct a message from `argv`
+ * to send to the daemon.
+ */
+#define CONSTRUCT_MESSAGE \
+ n = measure_array(argv + 1); \
+ t (n ? !(msg = malloc(n)) : 0); \
+ store_array(msg, argv + 1)
+
+
+/**
+ * Send message to daemon.
+ *
+ * @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.
+ */
+#define SEND(type, n, msg) \
+do { \
+ if (send_command(type, n, msg)) { \
+ t (errno); \
+ free(msg); \
+ return 3; \
+ }
+} while (0)
+
+
+/**
+ * Exit the process with status indicating success.
+ *
+ * Defined the label `fail`.
+ *
+ * @param msg The message send to the daemon.
+ */
+#define END(msg) \
+ free(msg); \
+ return 0; \
+fail: \
+ perror(argv0); \
+ free(msg); \
+ return 1;
+
diff --git a/src/daemonise.c b/src/daemonise.c
index 929eca0..fb1546d 100644
--- a/src/daemonise.c
+++ b/src/daemonise.c
@@ -21,12 +21,15 @@
*
* This file is copied from <http://github.com/maandree/slibc>.
*/
+#include "daemonise.h"
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
+#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
+#include <sys/stat.h>
#include <sys/resource.h>
@@ -149,10 +152,11 @@ int daemonise(const char* name, int flags)
struct rlimit rlimit;
int pipe_rw[2] = { -1, -1 };
sigset_t set;
- char* r;
- char* w;
+ char** r;
+ char** w;
char* run;
int i, closeerr, fd = -1;
+ pid_t pid;
int saved_errno;
@@ -217,7 +221,7 @@ int daemonise(const char* name, int flags)
t (pid = fork(), pid == -1);
close(pipe_rw[!!pid]), pipe_rw[!!pid] = 1;
if (pid)
- exit(read(pipe_rw[0], &b, (size_t)1) <= 0);
+ exit(read(pipe_rw[0], &fd, (size_t)1) <= 0);
/* Temporarily become session leader. */
t (setsid() == -1);
@@ -233,26 +237,26 @@ int daemonise(const char* name, int flags)
run = getenv("XDG_RUNTIME_DIR");
if (run && *run)
{
- pidpath = malloc(sizeof("/.pid") + (strlen(run) + strlen(name)) * sizeof(char));
- t (pidfile == NULL);
- stpcpy(stpcpy(stpcpy(stpcpy(pidpath, run), "/"), name), ".pid");
+ __pidfile = malloc(sizeof("/.pid") + (strlen(run) + strlen(name)) * sizeof(char));
+ t (__pidfile == NULL);
+ stpcpy(stpcpy(stpcpy(stpcpy(__pidfile, run), "/"), name), ".pid");
}
else
{
- pidpath = malloc(sizeof("/run/.pid") + strlen(name) * sizeof(char));
- t (pidfile == NULL);
- stpcpy(stpcpy(stpcpy(pidpath, "/run/"), name), ".pid");
+ __pidfile = malloc(sizeof("/run/.pid") + strlen(name) * sizeof(char));
+ t (__pidfile == NULL);
+ stpcpy(stpcpy(stpcpy(__pidfile, "/run/"), name), ".pid");
}
- fd = open(pidpath, O_WRONLY | O_CREAT | O_EXCL, 0644);
+ fd = open(__pidfile, O_WRONLY | O_CREAT | O_EXCL, 0644);
if (fd == -1)
{
saved_errno = errno;
- free(pidpath), pidpath = NULL;
+ free(__pidfile), __pidfile = NULL;
errno = saved_errno;
goto fail;
}
pid = getpid();
- t (dprintf(fd, "%lli\n", (long long int)pid)) < 0;
+ t (dprintf(fd, "%lli\n", (long long int)pid) < 0);
t (close(fd) && (errno != EINTR));
no_pid_file:
@@ -275,7 +279,7 @@ int daemonise(const char* name, int flags)
fd = -1;
/* We are done! Let the original process exit. */
- if ((write(pipe_rw[1], &b, (size_t)1) <= 0) ||
+ if ((write(pipe_rw[1], &fd, (size_t)1) <= 0) ||
(close(pipe_rw[1]) && (errno != EINTR)))
{
if (flags & DAEMONISE_KEEP_STDERR)
@@ -313,11 +317,11 @@ int daemonise(const char* name, int flags)
int undaemonise(void)
{
int r, saved_errno;
- if (pidfile == NULL)
+ if (__pidfile == NULL)
return 0;
- r = unlink(pidfile);
+ r = unlink(__pidfile);
saved_errno = errno;
- free(pidfile), pidfile = NULL;
+ free(__pidfile), __pidfile = NULL;
errno = saved_errno;
return r;
}
diff --git a/src/parse_time.c b/src/parse_time.c
index d86ef43..51e9011 100644
--- a/src/parse_time.c
+++ b/src/parse_time.c
@@ -58,6 +58,11 @@
*/
extern char *argv0;
+/**
+ * The highest value that can be stored in `time_t`.
+ */
+const time_t timemax = (sizeof(time_t) == sizeof(long long int)) ? LLONG_MAX : LONG_MAX;
+
/**
@@ -81,6 +86,7 @@ strtotime(const char *str, const char **end)
time_t rc;
long long int rcll;
long int rcl;
+ char **end_ = (char **)end;
if (!isdigit(*str))
FAIL(EINVAL);
@@ -91,10 +97,10 @@ strtotime(const char *str, const char **end)
errno = 0;
if (sizeof(time_t) == sizeof(long long int)) {
- rcll = strtoll(str, end, 10);
+ rcll = strtoll(str, end_, 10);
rc = (time_t)rcll;
} else {
- rcl = strtol(str, end, 10);
+ rcl = strtol(str, end_, 10);
rc = (time_t)rcl;
}
@@ -117,9 +123,7 @@ strtotime(const char *str, const char **end)
static int
parse_time_time(const char *str, struct timespec *ts, const char **end)
{
- char *end;
time_t t;
- const time_t timemax = (sizeof(time_t) == sizeof(long long int)) ? LLONG_MAX : LONG_MAX;
memset(ts, 0, sizeof(*ts));
@@ -208,9 +212,9 @@ int
parse_time(const char *str, struct timespec *ts, clockid_t *clk)
{
struct timespec now;
- int plus = *str == '+';
- char *start = str;
- char *end;
+ int points, plus = *str == '+';
+ const char *start = str;
+ const char *end;
time_t adj;
/* Get current time and clock. */
@@ -218,7 +222,7 @@ parse_time(const char *str, struct timespec *ts, clockid_t *clk)
*clk = plus ? CLOCK_MONOTONIC : CLOCK_REALTIME;
/* Mañana? */
- if (!strcmp("mañana")) { /* Do not documented. */
+ if (!strcmp(str, "mañana")) { /* Do not documented. */
ts->tv_sec = now.tv_sec + ONE_DAY;
ts->tv_nsec = now.tv_nsec;
return 0;
@@ -228,7 +232,7 @@ parse_time(const char *str, struct timespec *ts, clockid_t *clk)
if (strchr(str, ':')) {
if (parse_time_time(str, ts, &end))
return -1;
- adj = now.sec - (now.sec % ONE_DAY);
+ adj = now.tv_sec - (now.tv_sec % ONE_DAY);
ADD(ts->tv_sec, adj); /* In case the HH is really large. */
} else {
if (parse_time_seconds(str + plus, ts, &end))
@@ -244,7 +248,7 @@ parse_time(const char *str, struct timespec *ts, clockid_t *clk)
}
/* Parse up to nanosecond resolution. */
- for (; isdigit(*str); points++) {
+ for (points = 0; isdigit(*str); points++) {
if (points < 9) {
ts->tv_nsec *= 10;
ts->tv_nsec += *str++ & 15;
@@ -260,10 +264,10 @@ parse_time(const char *str, struct timespec *ts, clockid_t *clk)
/* Check for error at end, and missing explicit UTC. */
if (*str) {
if (*clk == CLOCK_MONOTONIC)
- FAIL(einval);
+ FAIL(EINVAL);
while (*str == ' ') str++;
if (!strcasecmp(str, "Z") && !strcasecmp(str, "UTC"))
- FAIL(einval);
+ FAIL(EINVAL);
} else if (*clk == CLOCK_REALTIME) {
fprintf(stderr,
"%s: warning: parsing as UTC, you can avoid "
diff --git a/src/sat.c b/src/sat.c
index 84140a4..afdd910 100644
--- a/src/sat.c
+++ b/src/sat.c
@@ -19,36 +19,20 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <errno.h>
#include "parse_time.h"
#include "client.h"
+#include "common.h"
-/**
- * The name of the process.
- */
-char *argv0 = "sat";
+COMMAND("sat")
+USAGE("TIME COMMAND...")
/**
- * Print usage information.
- */
-static void
-usage(void)
-{
- fprintf(stderr, "usage: %s TIME COMMAND...\n",
- strrchr(argv0) ? (strrchr(argv0) + 1) : argv0);
- exit(2);
-}
-
-
-/**
* Queue a job for later execution.
*
* @param argc You guess!
@@ -70,14 +54,13 @@ main(int argc, char *argv[], char *envp[])
struct timespec ts;
clockid_t clk;
char *msg = NULL;
- char *w;
- char *r;
+ char **w;
+ char **r;
int removed_empty = 0;
size_t n;
- if ((argc < 3) || (argv[1][0] == '-')) {
+ if ((argc < 3) || (argv[1][0] == '-'))
usage();
- }
argv0 = argv[0];
@@ -87,17 +70,17 @@ main(int argc, char *argv[], char *envp[])
case EINVAL:
fprintf(stderr,
"%s: time parameter cound not be parsed, perhaps you "
- "you need an external parser: %s\n", argv0, str);
+ "you need an external parser: %s\n", argv0, argv[1]);
return 2;
case ERANGE:
fprintf(stderr,
"%s: the specified time is beyond the limit of what "
- "can be represented by `struct timespec`: %s\n", argv0, str);
+ "can be represented by `struct timespec`: %s\n", argv0, argv[1]);
return 2;
case EDOM:
fprintf(stderr,
"%s: the specified time is in past, and more than "
- "a day ago: %s\n", argv0, str);
+ "a day ago: %s\n", argv0, argv[1]);
return 2;
default:
goto fail;
@@ -108,7 +91,7 @@ main(int argc, char *argv[], char *envp[])
argv += 2;
/* Remove empty environment entries */
- for (w = r = envp; *r; *r++) {
+ for (w = r = envp; *r; r++) {
if (**r) {
*w++ = *r;
} else if (removed_empty == 0) {
@@ -121,24 +104,14 @@ main(int argc, char *argv[], char *envp[])
/* Construct message to send to the daemon. */
n = measure_array(argv) + measure_array(envp);
- if (!(msg = malloc(n + sizeof(clk) + sizeof(ts))))
- goto fail;
+ t (!(msg = malloc(n + sizeof(clk) + sizeof(ts))));
store_array(store_array(msg, argv), envp);
- memcpy(msg + n, clk, sizeof(clk)), n += sizeof(clk);
- memcpy(msg + n, ts, sizeof(ts)), n += sizeof(ts);
+ memcpy(msg + n, &clk, sizeof(clk)), n += sizeof(clk);
+ memcpy(msg + n, &ts, sizeof(ts)), n += sizeof(ts);
/* Send job to daemon, start daemon if necessary. */
- if (send_command(SAT_QUEUE, n, msg)) {
- if (errno)
- goto fail;
- free(msg);
- return 3;
- }
- return 0;
+ SEND(SAT_QUEUE, n, msg);
-fail:
- perror(argv0);
- free(msg);
- return 1;
+ END(msg);
}
diff --git a/src/satd.c b/src/satd.c
index c2c1525..ec0d205 100644
--- a/src/satd.c
+++ b/src/satd.c
@@ -19,56 +19,21 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <unistd.h>
#include <errno.h>
-#include <grp.h>
#include <sys/stat.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include "daemonise.h"
+#include "common.h"
-#define t(...) do { if (__VA_ARGS__) goto fail; } while (0)
+COMMAND("satd")
+USAGE("[-f]")
-/**
- * The name of the process.
- */
-char *argv0 = "satd";
-
-
-
-/**
- * Print usage information.
- */
-static void
-usage(void)
-{
- fprintf(stderr, "usage: [-f] %s\n",
- strrchr(argv0) ? (strrchr(argv0) + 1) : argv0);
- exit(2);
-}
-
-
-/**
- * Get the group ID of a group.
- *
- * @param name The name of the group.
- * @param fallback The group ID to return if the group is not found.
- * @return The ID of the group, -1 on error.
- */
-static gid_t
-getgroup(const char* name, gid_t fallback)
-{
- struct group *g;
- if (!(g = getgrnam(name)))
- return errno ? (gid_t)-1 : fallback;
- return g->gr_gid;
-}
-
/**
* Create the socket.
@@ -82,22 +47,19 @@ create_socket(struct sockaddr_un *address)
int fd = -1;
ssize_t len;
char *dir;
- gid_t group;
+ int saved_errno;
- dir = getenv("XDG_RUNTIME_DIR"), dir = (dir ? dir : "/run")
+ dir = getenv("XDG_RUNTIME_DIR"), dir = (dir ? dir : "/run");
t (snprintf(NULL, 0, "%s/satd.socket%zn", dir, &len) == -1);
- if ((len < 0) || (len >= sizeof(address->sun_path))) {
- errno = ENAMETOOLING;
- goto fail;
- }
- sprintf(address->sun_path, "%s/satd.socket", dir)
+ if ((len < 0) || ((size_t)len >= sizeof(address->sun_path)))
+ t ((errno = ENAMETOOLONG));
+ sprintf(address->sun_path, "%s/satd.socket", dir);
address->sun_family = AF_UNIX;
/* TODO test flock */
unlink(address->sun_path);
t ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1);
t (fchmod(fd, S_IRWXU) == -1);
- t ((group = getgroup("nobody", 0)) == -1);
- t (fchown(fd, getuid(), group) == -1);
+ t (fchown(fd, getuid(), getgid()) == -1);
t (bind(fd, (struct sockaddr *)address, sizeof(*address)) == -1);
/* TODO flock */
diff --git a/src/satq.c b/src/satq.c
index 73b61ac..0b110f5 100644
--- a/src/satq.c
+++ b/src/satq.c
@@ -19,31 +19,14 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-
#include "client.h"
+#include "common.h"
-/**
- * The name of the process.
- */
-char *argv0 = "satq";
-
-
+COMMAND("satq")
+USAGE(NULL)
-/**
- * Print usage information.
- */
-static void
-usage(void)
-{
- fprintf(stderr, "usage: %s\n",
- strrchr(argv0) ? (strrchr(argv0) + 1) : argv0);
- exit(2);
-}
/**
@@ -62,8 +45,7 @@ main(int argc, char *argv[])
if (argc > 0) argv0 = argv[0];
if (argc > 1) usage();
- if (send_command(SAT_PRINT, 0, NULL))
- return errno ? (perror(argv0), 1) : 3;
- return 0;
+ SEND(SAT_PRINT, 0, NULL));
+ END(NULL);
}
diff --git a/src/satr.c b/src/satr.c
index ef5da6e..b1a587b 100644
--- a/src/satr.c
+++ b/src/satr.c
@@ -19,35 +19,17 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
#include "client.h"
+#include "common.h"
-/**
- * The name of the process.
- */
-char *argv0 = "satr";
+COMMAND("satr")
+USAGE("[JOB-ID]...")
/**
- * Print usage information.
- */
-static void
-usage(void)
-{
- fprintf(stderr, "usage: %s [JOB-ID]...\n",
- strrchr(argv0) ? (strrchr(argv0) + 1) : argv0);
- exit(2);
-}
-
-
-/**
* Run all queued jobs even if it is not time yet.
*
* @param argc Should be 1 or 0.
@@ -62,35 +44,14 @@ main(int argc, char *argv[])
{
size_t n = 0;
char *msg = NULL;
- int i;
- if (argc > 0)
- argv0 = argv[0];
- if (argc < 2)
- goto run;
- if (!strcmp(argv[1], "--"))
- argv++, argc--;
- for (i = 1; i < argc; i++)
- if (strchr("-", argv[i][0]))
- usage();
-
- n = measure_array(argv + 1);
- if (n ? !(msg = malloc(n)) : 0)
- goto fail;
- store_array(msg, argv + 1);
+ if (argc > 0) argv0 = argv[0];
+ if (argc < 2) goto run;
+ NO_OPTIONS;
+ CONSTRUCT_MESSAGE;
run:
- if (send_command(SAT_RUN, n, msg)) {
- if (errno)
- goto fail;
- free(msg);
- return 3;
- }
- return 0;
-
-fail:
- perror(*argv);
- free(msg);
- return 1;
+ SEND(SAT_RUN, n, msg);
+ END(msg);
}
diff --git a/src/satrm.c b/src/satrm.c
index 28bea0b..0a9eccf 100644
--- a/src/satrm.c
+++ b/src/satrm.c
@@ -19,35 +19,17 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
#include "client.h"
+#include "common.h"
-/**
- * The name of the process.
- */
-char *argv0 = "satrm";
+COMMAND("satrm")
+USAGE("JOB-ID...")
/**
- * Print usage information.
- */
-static void
-usage(void)
-{
- fprintf(stderr, "usage: %s JOB-ID...\n",
- strrchr(argv0) ? (strrchr(argv0) + 1) : argv0);
- exit(2);
-}
-
-
-/**
* Remove a job from the queue of jobs.
*
* @param argc Should be 2.
@@ -63,31 +45,13 @@ main(int argc, char *argv[])
{
size_t n;
char *msg;
- int i;
if (argc > 0) argv0 = argv[0];
if (argc < 2) usage();
- if (!strcmp(argv[1], "--")
- argv++, argc--;
- for (i = 1; i < argc; i++)
- if (strchr("-", argv[i][0]))
- usage();
-
- if (!(msg = malloc(n = measure_array(argv + 1))))
- goto fail;
- store_array(msg, argv + 1);
-
- if (send_command(SAT_REMOVE, n, msg)) {
- if (errno)
- goto fail;
- free(msg);
- return 3;
- }
- return 0;
-fail:
- perror(*argv);
- free(msg);
- return 1;
+ NO_OPTIONS;
+ CONSTRUCT_MESSAGE;
+ SEND(SAT_REMOVE, n, msg));
+ END(msg);
}