summaryrefslogtreecommitdiffstats
path: root/src/analyze
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2017-11-17 10:33:22 +0100
committerLennart Poettering <lennart@poettering.net>2017-11-20 10:57:41 +0100
commit6d86f4bd11c2cfaadc924a8a1ac04b0b463b8036 (patch)
tree5e877a0aa0c51ee2ce22ddd243d81fe06f709fd6 /src/analyze
parentutil: add new helper in_utc_timezone() (diff)
downloadsystemd-6d86f4bd11c2cfaadc924a8a1ac04b0b463b8036.tar.xz
systemd-6d86f4bd11c2cfaadc924a8a1ac04b0b463b8036.zip
analyze: add new "calendar" command
This little new command can parse, validate, normalize calendar events, and calculate when they will elapse next. This should be useful for anyone writing calendar events and who'd like to validate the expression before running them as timer units.
Diffstat (limited to 'src/analyze')
-rw-r--r--src/analyze/analyze.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c
index 913aa35016..5229b3a082 100644
--- a/src/analyze/analyze.c
+++ b/src/analyze/analyze.c
@@ -31,6 +31,7 @@
#include "bus-error.h"
#include "bus-unit-util.h"
#include "bus-util.h"
+#include "calendarspec.h"
#include "glob-util.h"
#include "hashmap.h"
#include "locale-util.h"
@@ -1395,6 +1396,70 @@ static int dump_syscall_filters(char** names) {
}
#endif
+static int test_calendar(char **args) {
+ int ret = 0, r;
+ char **p;
+ usec_t n;
+
+ if (strv_isempty(args)) {
+ log_error("Expected at least one calendar specification string as argument.");
+ return -EINVAL;
+ }
+
+ n = now(CLOCK_REALTIME);
+
+ STRV_FOREACH(p, args) {
+ _cleanup_(calendar_spec_freep) CalendarSpec *spec = NULL;
+ _cleanup_free_ char *t = NULL;
+ usec_t next;
+
+ r = calendar_spec_from_string(*p, &spec);
+ if (r < 0) {
+ ret = log_error_errno(r, "Failed to parse calendar specification '%s': %m", *p);
+ continue;
+ }
+
+ r = calendar_spec_normalize(spec);
+ if (r < 0) {
+ ret = log_error_errno(r, "Failed to normalize calendar specification '%s': %m", *p);
+ continue;
+ }
+
+ r = calendar_spec_to_string(spec, &t);
+ if (r < 0) {
+ ret = log_error_errno(r, "Failed to fomat calendar specification '%s': %m", *p);
+ continue;
+ }
+
+ if (!streq(t, *p))
+ printf(" Original form: %s\n", *p);
+
+ printf("Normalized form: %s\n", t);
+
+ r = calendar_spec_next_usec(spec, n, &next);
+ if (r == -ENOENT)
+ printf(" Next elapse: never\n");
+ else if (r < 0) {
+ ret = log_error_errno(r, "Failed to determine next elapse for '%s': %m", *p);
+ continue;
+ } else {
+ char buffer[CONST_MAX(FORMAT_TIMESTAMP_MAX, FORMAT_TIMESTAMP_RELATIVE_MAX)];
+
+ printf(" Next elapse: %s\n", format_timestamp(buffer, sizeof(buffer), next));
+
+ if (!in_utc_timezone())
+ printf(" (in UTC): %s\n", format_timestamp_utc(buffer, sizeof(buffer), next));
+
+ printf(" From now: %s\n", format_timestamp_relative(buffer, sizeof(buffer), next));
+ }
+
+ if (*(p+1))
+ putchar('\n');
+ }
+
+ return ret;
+}
+
static void help(void) {
pager_open(arg_no_pager, false);
@@ -1429,6 +1494,7 @@ static void help(void) {
" dump Output state serialization of service manager\n"
" syscall-filter [NAME...] Print list of syscalls in seccomp filter\n"
" verify FILE... Check unit files for correctness\n"
+ " calendar SPEC... Validate repetitive calendar time events\n"
, program_invocation_short_name);
/* When updating this list, including descriptions, apply
@@ -1618,6 +1684,8 @@ int main(int argc, char *argv[]) {
r = get_log_target(bus, argv+optind+1);
else if (streq(argv[optind], "syscall-filter"))
r = dump_syscall_filters(argv+optind+1);
+ else if (streq(argv[optind], "calendar"))
+ r = test_calendar(argv+optind+1);
else
log_error("Unknown operation '%s'.", argv[optind]);
}