aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Rostovtsev <tetromino@gentoo.org>2012-09-07 06:20:10 -0400
committerAlexandre Rostovtsev <tetromino@gentoo.org>2012-09-07 06:30:04 -0400
commit7951278841a9ee7f2a7092a33d32ed9c81b3e753 (patch)
tree5ac8e7b215f235fbd26e7e4c9469ecede3f40090
parentPrepare for installation and distribution (diff)
downloadopenrc-settingsd-7951278841a9ee7f2a7092a33d32ed9c81b3e753.tar.gz
openrc-settingsd-7951278841a9ee7f2a7092a33d32ed9c81b3e753.tar.bz2
openrc-settingsd-7951278841a9ee7f2a7092a33d32ed9c81b3e753.zip
Add daemonized mode with syslog logging, pid file, and ability to set rc status
The ability to set openrc-settingsd's rc status is useful mainly for dbus activation, so a dbus-activated process can be easily stopped via "/etc/init.d/openrc-settingsd stop".
-rw-r--r--Makefile.am8
-rwxr-xr-xautogen.sh3
-rw-r--r--configure.ac7
-rwxr-xr-xdata/init.d/openrc-settingsd.in7
-rw-r--r--data/org.freedesktop.hostname1.service.in2
-rw-r--r--data/org.freedesktop.locale1.service.in2
-rw-r--r--data/org.freedesktop.timedate1.service.in2
-rw-r--r--src/hostnamed.c12
-rw-r--r--src/localed.c12
-rw-r--r--src/main.c186
-rw-r--r--src/main.h33
-rw-r--r--src/timedated.c12
-rw-r--r--src/utils.c26
-rw-r--r--src/utils.h3
14 files changed, 266 insertions, 49 deletions
diff --git a/Makefile.am b/Makefile.am
index dde27ad..5b7b0c2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -44,11 +44,9 @@ initd_SCRIPTS = data/init.d/openrc-settingsd
confddir = $(sysconfdir)/conf.d
dist_confd_DATA = data/conf.d/openrc-settingsd
-rootsbindir = @rootsbindir@
-
+pidfile = @pidfile@
do_subst = sed -e 's,[@]libexecdir[@],$(libexecdir),g' \
- -e 's,[@]localstatedir[@],$(localstatedir),g' \
- -e 's,[@]rootsbindir[@],$(rootsbindir),g' \
+ -e 's,[@]pidfile[@],$(pidfile),g' \
$(NULL)
data/init.d/openrc-settingsd : data/init.d/openrc-settingsd.in
@@ -63,6 +61,7 @@ AM_CPPFLAGS = \
-DDATADIR=\""$(datadir)"\" \
-DLIBEXECDIR=\""$(libexecdir)"\" \
-DPKGDATADIR=\""$(pkgdatadir)"\" \
+ -DPIDFILE=\""$(pidfile)"\" \
$(OPENRC_SETTINGSD_CFLAGS) \
-I$(top_srcdir)/src \
-I$(top_builddir)/src \
@@ -105,6 +104,7 @@ openrc_settingsd_SOURCES = \
src/timedated.h \
src/utils.c \
src/utils.h \
+ src/main.h \
src/main.c \
$(NULL)
diff --git a/autogen.sh b/autogen.sh
index 6383ac1..4f9c076 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -3,8 +3,7 @@
autoreconf --install --symlink
args="--prefix=/usr \
---sysconfdir=/etc \
---localstatedir=/var"
+--sysconfdir=/etc"
echo
echo "----------------------------------------------------------------"
diff --git a/configure.ac b/configure.ac
index a162912..a7ccb04 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,6 +17,7 @@ PKG_CHECK_MODULES(OPENRC_SETTINGSD,
glib-2.0 >= 2.30
dbus-1
polkit-gobject-1
+ libdaemon
openrc])
AC_SUBST(OPENRC_SETTINGSD_CFLAGS)
AC_SUBST(OPENRC_SETTINGSD_LIBS)
@@ -26,8 +27,8 @@ if test "x$GDBUS_CODEGEN" = x; then
AC_MSG_ERROR([Failed to find gdbus-codegen])
fi
-AC_ARG_WITH([rootsbindir], AS_HELP_STRING([--with-rootsbindir=DIR], [root /sbin directory @<:@default=/sbin@:>@]), [], [with_rootsbindir=/sbin])
-AC_SUBST([rootsbindir], [$with_rootsbindir])
+AC_ARG_WITH([pidfile], AS_HELP_STRING([--with-pidfile=FILENAME], [pid filename @<:@default=/var/run/openrc-settingsd.pid@:>@]), [], [with_pidfile=/var/run/openrc-settingsd.pid])
+AC_SUBST([pidfile], [$with_pidfile])
AC_MSG_CHECKING([dbus interfaces directory])
dbusinterfacesdir=`$PKG_CONFIG --variable=interfaces_dir dbus-1`
@@ -68,7 +69,7 @@ AC_MSG_RESULT([
prefix: ${prefix}
sysconfdir: ${sysconfdir}
- rootsbindir: ${with_rootsbindir}
+ pid file: ${with_pidfile}
compiler: ${CC}
cflags: ${CFLAGS}
diff --git a/data/init.d/openrc-settingsd.in b/data/init.d/openrc-settingsd.in
index dfdcda8..8db56c5 100755
--- a/data/init.d/openrc-settingsd.in
+++ b/data/init.d/openrc-settingsd.in
@@ -12,15 +12,14 @@ start() {
[ -n "${NTP_SERVICE}" ] &&
OPENRC_SETTINGSD_OPTS="--ntp-service=${NTP_SERVICE} ${OPENRC_SETTINGSD_OPTS}"
ebegin "Starting openrc-settingsd"
- start-stop-daemon --start --quiet --pidfile "@localstatedir@/run/openrc-settingsd.pid" \
- --make-pidfile --background "@libexecdir@/openrc-settingsd" -- \
- ${OPENRC_SETTINGSD_OPTS}
+ start-stop-daemon --start --quiet --pidfile "@pidfile@" \
+ "@libexecdir@/openrc-settingsd" -- ${OPENRC_SETTINGSD_OPTS}
eend $?
}
stop() {
ebegin "Stopping openrc-settingsd"
- start-stop-daemon --stop --quiet --pidfile "@localstatedir@/run/openrc-settingsd.pid"
+ start-stop-daemon --stop --quiet --pidfile "@pidfile@"
eend $?
}
diff --git a/data/org.freedesktop.hostname1.service.in b/data/org.freedesktop.hostname1.service.in
index 0d850f5..56f4a80 100644
--- a/data/org.freedesktop.hostname1.service.in
+++ b/data/org.freedesktop.hostname1.service.in
@@ -1,4 +1,4 @@
[D-BUS Service]
Name=org.freedesktop.hostname1
-Exec=@rootsbindir@/rc-service openrc-settingsd start
+Exec=@libexecdir@/openrc-settingsd --update-rc-status
User=root \ No newline at end of file
diff --git a/data/org.freedesktop.locale1.service.in b/data/org.freedesktop.locale1.service.in
index eda463a..1debcbb 100644
--- a/data/org.freedesktop.locale1.service.in
+++ b/data/org.freedesktop.locale1.service.in
@@ -1,4 +1,4 @@
[D-BUS Service]
Name=org.freedesktop.locale1
-Exec=@rootsbindir@/rc-service openrc-settingsd start
+Exec=@libexecdir@/openrc-settingsd --update-rc-status
User=root \ No newline at end of file
diff --git a/data/org.freedesktop.timedate1.service.in b/data/org.freedesktop.timedate1.service.in
index 6138b3b..77dd26d 100644
--- a/data/org.freedesktop.timedate1.service.in
+++ b/data/org.freedesktop.timedate1.service.in
@@ -1,4 +1,4 @@
[D-BUS Service]
Name=org.freedesktop.timedate1
-Exec=@rootsbindir@/rc-service openrc-settingsd start
+Exec=@libexecdir@/openrc-settingsd --update-rc-status
User=root \ No newline at end of file
diff --git a/src/hostnamed.c b/src/hostnamed.c
index b476cdb..dce16cd 100644
--- a/src/hostnamed.c
+++ b/src/hostnamed.c
@@ -30,6 +30,7 @@
#include "hostnamed.h"
#include "hostname1-generated.h"
+#include "main.h"
#include "utils.h"
#include "config.h"
@@ -393,8 +394,8 @@ on_bus_acquired (GDBusConnection *connection,
"/org/freedesktop/hostname1",
&err)) {
if (err != NULL) {
- g_printerr ("Failed to export interface on /org/freedesktop/hostname1: %s\n", err->message);
- g_error_free (err);
+ g_critical ("Failed to export interface on /org/freedesktop/hostname1: %s", err->message);
+ openrc_settingsd_exit (1);
}
}
}
@@ -405,6 +406,7 @@ on_name_acquired (GDBusConnection *connection,
gpointer user_data)
{
g_debug ("Acquired the name %s", bus_name);
+ openrc_settingsd_component_started ();
}
static void
@@ -413,10 +415,10 @@ on_name_lost (GDBusConnection *connection,
gpointer user_data)
{
if (connection == NULL)
- g_printerr ("Failed to acquire a dbus connection\n");
+ g_critical ("Failed to acquire a dbus connection");
else
- g_printerr ("Failed to acquire dbus name %s\n", bus_name);
- exit(-1);
+ g_critical ("Failed to acquire dbus name %s", bus_name);
+ openrc_settingsd_exit (1);
}
/* Public functions */
diff --git a/src/localed.c b/src/localed.c
index 5eb3f65..efc4a8b 100644
--- a/src/localed.c
+++ b/src/localed.c
@@ -26,6 +26,7 @@
#include "localed.h"
#include "locale1-generated.h"
+#include "main.h"
#include "utils.h"
#include "config.h"
@@ -1235,8 +1236,8 @@ on_bus_acquired (GDBusConnection *connection,
"/org/freedesktop/locale1",
&err)) {
if (err != NULL) {
- g_printerr ("Failed to export interface on /org/freedesktop/locale1: %s\n", err->message);
- g_error_free (err);
+ g_critical ("Failed to export interface on /org/freedesktop/locale1: %s", err->message);
+ openrc_settingsd_exit (1);
}
}
}
@@ -1247,6 +1248,7 @@ on_name_acquired (GDBusConnection *connection,
gpointer user_data)
{
g_debug ("Acquired the name %s", bus_name);
+ openrc_settingsd_component_started ();
}
static void
@@ -1255,10 +1257,10 @@ on_name_lost (GDBusConnection *connection,
gpointer user_data)
{
if (connection == NULL)
- g_printerr ("Failed to acquire a dbus connection\n");
+ g_critical ("Failed to acquire a dbus connection");
else
- g_printerr ("Failed to acquire dbus name %s\n", bus_name);
- exit(-1);
+ g_critical ("Failed to acquire dbus name %s", bus_name);
+ openrc_settingsd_exit (1);
}
void
diff --git a/src/main.c b/src/main.c
index 54eb407..8374218 100644
--- a/src/main.c
+++ b/src/main.c
@@ -16,12 +16,18 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <syslog.h>
+
+#include <libdaemon/dfork.h>
#include <glib.h>
#include <gio/gio.h>
+#include <rc.h>
+
#include "hostnamed.h"
#include "localed.h"
#include "timedated.h"
@@ -32,26 +38,157 @@
#define DEFAULT_LEVELS (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE)
static gboolean debug = FALSE;
+static gboolean foreground = FALSE;
+static gboolean use_syslog = FALSE;
static gboolean read_only = FALSE;
+static gboolean update_rc_status = FALSE;
static gchar *ntp_preferred_service = NULL;
+static guint components_started = 0;
+G_LOCK_DEFINE_STATIC (components_started);
+
+static gboolean started = FALSE;
+
static GOptionEntry option_entries[] =
{
{ "debug", 0, 0, G_OPTION_ARG_NONE, &debug, "Enable debugging messages", NULL },
+ { "foreground", 0, 0, G_OPTION_ARG_NONE, &foreground, "Do not daemonize", NULL },
{ "read-only", 0, 0, G_OPTION_ARG_NONE, &read_only, "Run in read-only mode", NULL },
{ "ntp-service", 0, 0, G_OPTION_ARG_STRING, &ntp_preferred_service, "Preferred rc NTP service for timedated", NULL },
+ { "update-rc-status", 0, 0, G_OPTION_ARG_NONE, &update_rc_status, "Force openrc-settingsd rc service to be marked as started", NULL },
{ NULL }
};
-/* Emulates the new behavior of g_log_default_handler introduced in glib-2.31.2 */
+static int
+log_level_to_syslog (GLogLevelFlags log_level)
+{
+ switch (log_level & G_LOG_LEVEL_MASK) {
+ case G_LOG_LEVEL_ERROR:
+ case G_LOG_LEVEL_CRITICAL:
+ return LOG_ERR;
+ case G_LOG_LEVEL_WARNING:
+ return LOG_WARNING;
+ case G_LOG_LEVEL_MESSAGE:
+ return LOG_NOTICE;
+ case G_LOG_LEVEL_INFO:
+ return LOG_INFO;
+ case G_LOG_LEVEL_DEBUG:
+ return LOG_DEBUG;
+ }
+ return LOG_NOTICE;
+}
+
static void
log_handler (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer user_data)
{
- if (debug || log_level & DEFAULT_LEVELS)
- g_log_default_handler (log_domain, log_level, message, user_data);
+ const gchar *debug_domains = NULL;
+ GString *result = NULL;
+ gchar *result_data = NULL;
+
+ debug_domains = g_getenv ("G_MESSAGES_DEBUG");
+ if (!debug && !(log_level & DEFAULT_LEVELS) && g_strcmp0 (debug_domains, "all") && strstr0 (debug_domains, log_domain) == NULL)
+ return;
+
+ result = g_string_new (NULL);
+ if (!use_syslog)
+ g_string_append_printf (result, "openrc-settingsd[%lu]: ", (gulong)getpid ());
+ if (log_domain != NULL)
+ g_string_append_printf (result, "%s: ", log_domain);
+
+ if (!use_syslog)
+ switch (log_level & G_LOG_LEVEL_MASK) {
+ case G_LOG_LEVEL_ERROR:
+ case G_LOG_LEVEL_CRITICAL:
+ g_string_append (result, "ERROR: ");
+ break;
+ case G_LOG_LEVEL_WARNING:
+ g_string_append (result, "WARNING: ");
+ break;
+ case G_LOG_LEVEL_MESSAGE:
+ g_string_append (result, "Notice: ");
+ break;
+ case G_LOG_LEVEL_INFO:
+ g_string_append (result, "Info: ");
+ break;
+ case G_LOG_LEVEL_DEBUG:
+ g_string_append (result, "Debug: ");
+ break;
+ }
+
+ if (message != NULL)
+ g_string_append (result, message);
+ else
+ g_string_append (result, "(NULL)");
+
+ result_data = g_string_free (result, FALSE);
+
+ if (use_syslog) {
+ openlog ("openrc-settingsd", LOG_PID, LOG_DAEMON);
+ syslog (log_level_to_syslog (log_level), "%s", result_data);
+ } else
+ g_printerr ("%s\n", result_data);
+
+ g_free (result_data);
+}
+
+void
+openrc_settingsd_exit (int status)
+{
+ GFile *pidfile = NULL;
+
+ if (!foreground)
+ daemon_retval_send (status);
+
+ pidfile = g_file_new_for_path (PIDFILE);
+ g_file_delete (pidfile, NULL, NULL);
+
+ if (update_rc_status && started) {
+ if (status)
+ rc_service_mark ("openrc-settingsd", RC_SERVICE_FAILED);
+ else
+ rc_service_mark ("openrc-settingsd", RC_SERVICE_STOPPED);
+ }
+
+ g_clear_object (&pidfile);
+ exit (status);
+}
+
+/* This is called each time we successfully grab a bus name when starting up */
+void
+openrc_settingsd_component_started ()
+{
+ gchar *pidstring = NULL;
+ GError *err = NULL;
+ GFile *pidfile = NULL;
+
+ G_LOCK (components_started);
+
+ components_started++;
+ /* We want all 3 names (hostnamed, localed, timedated) to be grabbed */
+ if (components_started < 3)
+ goto out;
+
+ pidfile = g_file_new_for_path (PIDFILE);
+ pidstring = g_strdup_printf ("%lu", (gulong)getpid ());
+ if (!g_file_replace_contents (pidfile, pidstring, strlen(pidstring), NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL, &err)) {
+ g_critical ("Failed to write " PIDFILE ": %s", err->message);
+ openrc_settingsd_exit (1);
+ }
+
+ if (!foreground)
+ daemon_retval_send (0);
+
+ if (update_rc_status)
+ rc_service_mark ("openrc-settingsd", RC_SERVICE_STARTED);
+ started = TRUE;
+
+ out:
+ G_UNLOCK (components_started);
+ g_clear_object (&pidfile);
+ g_free (pidstring);
}
gint
@@ -60,21 +197,45 @@ main (gint argc, gchar *argv[])
GError *error = NULL;
GOptionContext *option_context;
GMainLoop *loop = NULL;
+ pid_t pid;
g_type_init ();
+ g_log_set_default_handler (log_handler, NULL);
option_context = g_option_context_new ("- system settings D-Bus service for OpenRC");
g_option_context_add_main_entries (option_context, option_entries, NULL);
if (!g_option_context_parse (option_context, &argc, &argv, &error)) {
- g_printerr ("Failed to parse options: %s\n", error->message);
- exit (1);
+ g_critical ("Failed to parse options: %s", error->message);
+ return 1;
}
- if (glib_check_version (2, 31, 2) == NULL) {
- if (debug)
- g_setenv("G_MESSAGES_DEBUG", "all", TRUE);
- } else
- g_log_set_default_handler (log_handler, NULL);
+ if (!foreground) {
+ if (daemon_retval_init () < 0) {
+ g_critical ("Failed to create pipe");
+ return 1;
+ }
+ if ((pid = daemon_fork ()) < 0) {
+ /* Fork failed */
+ daemon_retval_done ();
+ return 1;
+ } else if (pid) {
+ /* Parent */
+ int ret;
+
+ /* Wait 20 seconds for daemon_retval_send() in the daemon process */
+ if ((ret = daemon_retval_wait (20)) < 0) {
+ g_critical ("Timed out waiting for daemon process: %s", strerror(errno));
+ return 255;
+ } else if (ret > 0) {
+ g_critical ("Daemon process returned error code %d", ret);
+ return ret;
+ }
+ return 0;
+ }
+ /* Daemon */
+ use_syslog = TRUE;
+ daemon_close_all (-1);
+ }
utils_init ();
hostnamed_init (read_only);
@@ -84,10 +245,13 @@ main (gint argc, gchar *argv[])
g_main_loop_run (loop);
g_main_loop_unref (loop);
+
timedated_destroy ();
localed_destroy ();
hostnamed_destroy ();
utils_destroy ();
+
+ g_clear_error (&error);
g_free (ntp_preferred_service);
- return 0;
+ openrc_settingsd_exit (0);
}
diff --git a/src/main.h b/src/main.h
new file mode 100644
index 0000000..f9a30ea
--- /dev/null
+++ b/src/main.h
@@ -0,0 +1,33 @@
+/*
+ Copyright 2012 Alexandre Rostovtsev
+
+ 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.
+*/
+
+#ifndef _MAIN_H_
+#define _MAIN_H_
+
+void
+openrc_settingsd_component_started ();
+
+void
+openrc_settingsd_exit (int status);
+
+#endif
diff --git a/src/timedated.c b/src/timedated.c
index 32e9171..4e5939e 100644
--- a/src/timedated.c
+++ b/src/timedated.c
@@ -30,6 +30,7 @@
#include "copypaste/hwclock.h"
#include "timedated.h"
#include "timedate1-generated.h"
+#include "main.h"
#include "utils.h"
#include "config.h"
@@ -651,8 +652,8 @@ on_bus_acquired (GDBusConnection *connection,
"/org/freedesktop/timedate1",
&err)) {
if (err != NULL) {
- g_printerr ("Failed to export interface on /org/freedesktop/timedate1: %s\n", err->message);
- g_error_free (err);
+ g_critical ("Failed to export interface on /org/freedesktop/timedate1: %s", err->message);
+ openrc_settingsd_exit (1);
}
}
}
@@ -663,6 +664,7 @@ on_name_acquired (GDBusConnection *connection,
gpointer user_data)
{
g_debug ("Acquired the name %s", bus_name);
+ openrc_settingsd_component_started ();
}
static void
@@ -671,10 +673,10 @@ on_name_lost (GDBusConnection *connection,
gpointer user_data)
{
if (connection == NULL)
- g_printerr ("Failed to acquire a dbus connection\n");
+ g_critical ("Failed to acquire a dbus connection");
else
- g_printerr ("Failed to acquire dbus name %s\n", bus_name);
- exit(-1);
+ g_critical ("Failed to acquire dbus name %s", bus_name);
+ openrc_settingsd_exit (1);
}
void
diff --git a/src/utils.c b/src/utils.c
index ba195e5..f76c335 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -22,7 +22,11 @@
*/
#include <stdarg.h>
+#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
+
+#include <libdaemon/dfork.h>
#include <glib.h>
#include <gio/gio.h>
@@ -32,13 +36,13 @@
#include "config.h"
-GRegex *indent_regex = NULL;
-GRegex *comment_regex = NULL;
-GRegex *separator_regex = NULL;
-GRegex *var_equals_regex = NULL;
-GRegex *single_quoted_regex = NULL;
-GRegex *double_quoted_regex = NULL;
-GRegex *unquoted_regex = NULL;
+static GRegex *indent_regex = NULL;
+static GRegex *comment_regex = NULL;
+static GRegex *separator_regex = NULL;
+static GRegex *var_equals_regex = NULL;
+static GRegex *single_quoted_regex = NULL;
+static GRegex *double_quoted_regex = NULL;
+static GRegex *unquoted_regex = NULL;
/* Always returns TRUE */
gboolean
@@ -51,6 +55,14 @@ _g_match_info_clear (GMatchInfo **match_info)
return TRUE;
}
+gchar *
+strstr0 (const gchar *haystack, const gchar *needle)
+{
+ if (haystack == NULL || needle == NULL)
+ return NULL;
+ return strstr (haystack, needle);
+}
+
struct check_polkit_data {
const gchar *unique_name;
const gchar *action_id;
diff --git a/src/utils.h b/src/utils.h
index d0d36fe..f431387 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -40,6 +40,9 @@ struct _ShellParser
gboolean
_g_match_info_clear (GMatchInfo **match_info);
+gchar *
+strstr0 (const char *haystack, const char *needle);
+
void
check_polkit_async (const gchar *unique_name,
const gchar *action_id,