chiark / gitweb /
notify: add systemd-notify command line tool
authorLennart Poettering <lennart@poettering.net>
Thu, 17 Jun 2010 20:50:06 +0000 (22:50 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 17 Jun 2010 20:50:06 +0000 (22:50 +0200)
.gitignore
Makefile.am
src/notify.c [new file with mode: 0644]

index 0ad1446777304d08cae467c824427a03748e0513..a0a284f2dfa6cd7e65c606b158312adf05e1e8ac 100644 (file)
@@ -1,3 +1,4 @@
+systemd-notify
 test-daemon
 systemd-install
 org.freedesktop.systemd1.*.xml
 test-daemon
 systemd-install
 org.freedesktop.systemd1.*.xml
index 3e77a4737be34a38d40f4f567e90cf1ccf787bd3..197407cdb05a750f6a453cfae1d0f8383aeea6c1 100644 (file)
@@ -48,7 +48,8 @@ AM_CPPFLAGS = \
 
 rootbin_PROGRAMS = \
        systemd \
 
 rootbin_PROGRAMS = \
        systemd \
-       systemctl
+       systemctl \
+       systemd-notify
 
 bin_PROGRAMS = \
        systemd-install
 
 bin_PROGRAMS = \
        systemd-install
@@ -373,6 +374,11 @@ systemctl_SOURCES = \
 systemctl_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
 systemctl_LDADD = $(DBUS_LIBS)
 
 systemctl_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
 systemctl_LDADD = $(DBUS_LIBS)
 
+systemd_notify_SOURCES = \
+       src/notify.c \
+       src/sd-daemon.c \
+       $(BASIC_SOURCES)
+
 systemd_install_SOURCES = \
        src/install.c \
        src/path-lookup.c \
 systemd_install_SOURCES = \
        src/install.c \
        src/path-lookup.c \
diff --git a/src/notify.c b/src/notify.c
new file mode 100644 (file)
index 0000000..864b7c2
--- /dev/null
@@ -0,0 +1,179 @@
+/*-*- Mode: C; c-basic-offset: 8 -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2010 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdio.h>
+#include <getopt.h>
+#include <error.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "strv.h"
+#include "util.h"
+#include "log.h"
+#include "sd-daemon.h"
+
+static bool arg_ready = false;
+static pid_t arg_pid = 0;
+static const char *arg_status = NULL;
+
+static int help(void) {
+
+        printf("%s [options] [VARIABLE=VALUE...]\n\n"
+               "Notify the init system about service status updates.\n\n"
+               "  -h --help         Show this help\n"
+               "     --ready        Inform the init system about service start-up completion\n"
+               "     --pid[=PID]    Set main pid of daemon\n"
+               "     --status=TEXT  Set status text\n",
+               program_invocation_short_name);
+
+        return 0;
+}
+
+static int parse_argv(int argc, char *argv[]) {
+
+        enum {
+                ARG_READY = 0x100,
+                ARG_PID,
+                ARG_STATUS
+        };
+
+        static const struct option options[] = {
+                { "help",      no_argument,       NULL, 'h'         },
+                { "ready",     no_argument,       NULL, ARG_READY   },
+                { "pid",       optional_argument, NULL, ARG_PID     },
+                { "status",    required_argument, NULL, ARG_STATUS  },
+                { NULL,        0,                 NULL, 0           }
+        };
+
+        int c;
+
+        assert(argc >= 0);
+        assert(argv);
+
+        while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
+
+                switch (c) {
+
+                case 'h':
+                        help();
+                        return 0;
+
+                case ARG_READY:
+                        arg_ready = true;
+                        break;
+
+                case ARG_PID:
+
+                        if (optarg) {
+                                if (parse_pid(optarg, &arg_pid) < 0) {
+                                        log_error("Failed to parse PID %s.", optarg);
+                                        return -EINVAL;
+                                }
+                        } else
+                                arg_pid = getppid();
+
+                        break;
+
+                case ARG_STATUS:
+                        arg_status = optarg;
+                        break;
+
+                case '?':
+                        return -EINVAL;
+
+                default:
+                        log_error("Unknown option code %c", c);
+                        return -EINVAL;
+                }
+        }
+
+        return 1;
+}
+
+int main(int argc, char* argv[]) {
+        char* our_env[4], **final_env = NULL;
+        unsigned i = 0;
+        char *status = NULL, *cpid = NULL, *n = NULL;
+        int r, retval = 1;
+
+        log_parse_environment();
+
+        if ((r = parse_argv(argc, argv)) <= 0) {
+                retval = r < 0;
+                goto finish;
+        }
+
+        if (arg_ready)
+                our_env[i++] = (char*) "READY=1";
+
+        if (arg_status) {
+                if (!(status = strappend("STATUS=", arg_status))) {
+                        log_error("Failed to allocate STATUS string.");
+                        goto finish;
+                }
+
+                our_env[i++] = status;
+        }
+
+        if (arg_pid > 0) {
+                if (asprintf(&cpid, "MAINPID=%lu", (unsigned long) arg_pid) < 0) {
+                        log_error("Failed to allocate MAINPID string.");
+                        goto finish;
+                }
+
+                our_env[i++] = cpid;
+        }
+
+        our_env[i++] = NULL;
+
+        if (!(final_env = strv_env_merge(2, our_env, argv + optind))) {
+                log_error("Failed to merge string sets.");
+                goto finish;
+        }
+
+        if (strv_length(final_env) <= 0) {
+                retval = 0;
+                goto finish;
+        }
+
+        if (!(n = strv_join(final_env, "\n"))) {
+                log_error("Failed to concatenate strings.");
+                goto finish;
+        }
+
+        if ((r = sd_notify(false, n)) < 0) {
+                log_error("Failed to notify init system: %s", strerror(-r));
+                goto finish;
+        }
+
+        retval = r <= 0;
+
+finish:
+        free(status);
+        free(cpid);
+        free(n);
+
+        strv_free(final_env);
+
+        return retval;
+}