[Initscripts-ng-commits] r1088 - in /trunk/src/insserv: CHANGES Makefile insserv.8.in insserv.c listing.c listing.h systemd.c systemd.h
pere at users.alioth.debian.org
pere at users.alioth.debian.org
Sat Feb 8 21:29:44 UTC 2014
Author: pere
Date: Sat Feb 8 21:29:44 2014
New Revision: 1088
URL: http://svn.debian.org/wsvn/initscripts-ng/?sc=1&rev=1088
Log:
New upstream version 1.16.0.
Added:
trunk/src/insserv/systemd.c
trunk/src/insserv/systemd.h
Modified:
trunk/src/insserv/CHANGES
trunk/src/insserv/Makefile
trunk/src/insserv/insserv.8.in
trunk/src/insserv/insserv.c
trunk/src/insserv/listing.c
trunk/src/insserv/listing.h
Modified: trunk/src/insserv/CHANGES
URL: http://svn.debian.org/wsvn/initscripts-ng/trunk/src/insserv/CHANGES?rev=1088&op=diff
==============================================================================
--- trunk/src/insserv/CHANGES (original)
+++ trunk/src/insserv/CHANGES Sat Feb 8 21:29:44 2014
@@ -1,3 +1,94 @@
+-------------------------------------------------------------------
+Wed Nov 14 12:12:15 CET 2012 - werner at suse.de
+
+- Add systemd support
+ * Talk with systemd over dbus connection to get all services and
+ targets known by systemd
+ * Implement missing garbage collector for system facilities as
+ the systemd targets are used as system facilities
+ + Side efect is that we detect loops in the systemd units
+
+-------------------------------------------------------------------
+Fri Oct 26 11:14:05 UTC 2012 - werner at suse.de
+
+- Add showall patch from Debian developer Kel Modderman
+
+-------------------------------------------------------------------
+Mon Sep 24 14:05:44 UTC 2012 - werner at suse.de
+
+- Avoid warnings if there exsists LSB tags for a script in the
+ override locations (fate #314069)
+
+-------------------------------------------------------------------
+Fri Nov 18 14:40:21 UTC 2011 - werner at suse.de
+
+- Do not enforce service reload in case of an other root files
+ system no in case of not having systemd running (bnc#728947)
+
+-------------------------------------------------------------------
+Fri Aug 19 13:57:29 UTC 2011 - werner at suse.de
+
+- We should forward to systemctl when running under rpm (this is
+ supposed to be handled outside insserv) (from Frederic Crozat)
+- When insserv is called with full path of initscript
+ ("insserv /etc/init.d/acpid") , systemctl was called with a "null"
+ alternative root (from Frederic Crozat).
+
+-------------------------------------------------------------------
+Tue Aug 2 12:18:51 UTC 2011 - werner at suse.de
+
+- Enable insserv to support systemd services if shadowed by systemd
+
+-------------------------------------------------------------------
+Fri Feb 25 17:39:37 CET 2011 - werner at suse.de
+
+- Skip `FATAL' key word from messages currently nonfatal
+
+-------------------------------------------------------------------
+Thu Feb 10 12:49:14 CET 2011 - werner at suse.de
+
+- Linked lists: support prefetch of next pointer address for all
+ architectures
+
+-------------------------------------------------------------------
+Tue Nov 30 11:03:21 CET 2010 - werner at suse.de
+
+- Make temporary the new dependency checks nonfatal
+
+-------------------------------------------------------------------
+Fri Nov 26 15:50:35 CET 2010 - werner at suse.de
+
+- Warn if dependencies are not done in all runlevel
+- Ignore real boot scripts for runlevel services as those
+ are already enabled.
+
+-------------------------------------------------------------------
+Fri Jun 18 18:08:54 CEST 2010 - werner at suse.de
+
+- Remove redundant dependencies in the .depend.* makefiles
+
+-------------------------------------------------------------------
+Tue Jun 15 14:05:31 CEST 2010 - werner at suse.de
+
+- Do not forget the aliases in the makefiles
+
+-------------------------------------------------------------------
+Thu Jun 10 17:19:26 CEST 2010 - werner at suse.de
+
+- Sort dependency lists of the services that is the highest
+ dependencies first
+
+-------------------------------------------------------------------
+Fri May 7 17:15:02 CEST 2010 - werner at suse.de
+
+- Get the value instead the ``X-'' from interactive tag
+ this fix debian bug #580564
+
+-------------------------------------------------------------------
+Fri Apr 30 18:27:29 CEST 2010 - werner at suse.de
+
+- Add the option of recursive enabling all required services
+
-------------------------------------------------------------------
Wed Apr 28 15:29:23 CEST 2010 - werner at suse.de
Modified: trunk/src/insserv/Makefile
URL: http://svn.debian.org/wsvn/initscripts-ng/trunk/src/insserv/Makefile?rev=1088&op=diff
==============================================================================
--- trunk/src/insserv/Makefile (original)
+++ trunk/src/insserv/Makefile Sat Feb 8 21:29:44 2014
@@ -12,8 +12,9 @@
DEBUG =
ISSUSE = -DSUSE
DESTDIR =
-VERSION = 1.14.0
+VERSION = 1.16.0
DATE = $(shell date +'%d%b%y' | tr '[:lower:]' '[:upper:]')
+CFLDBUS = $(shell pkg-config --cflags dbus-1)
#
# Architecture
@@ -38,6 +39,7 @@
LDFLAGS += -Wl,--as-needed
LIBS += -lrpm
endif
+ LIBS += $(shell pkg-config --libs dbus-1)
CC = gcc
RM = rm -f
MKDIR = mkdir -p
@@ -74,14 +76,17 @@
all: $(TODO)
-insserv: insserv.o listing.o
+insserv: insserv.o listing.o systemd.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
listing.o: listing.c listing.h config.h .system
$(CC) $(CFLAGS) $(CLOOP) -c $<
-insserv.o: insserv.c listing.h config.h .system
- $(CC) $(CFLAGS) $(CLOOP) -c $<
+insserv.o: insserv.c listing.h systemd.h config.h .system
+ $(CC) $(CFLAGS) $(CLOOP) $(CFLDBUS) -c $<
+
+systemd.o: systemd.c listing.h systemd.h config.h .system
+ $(CC) $(CFLAGS) $(CLOOP) $(CFLDBUS) -c $<
listing.h: .system
@@ -161,6 +166,8 @@
Makefile \
listing.c \
listing.h \
+ systemd.c \
+ systemd.h \
insserv.8.in \
insserv.c \
insserv.conf \
@@ -172,6 +179,7 @@
insserv-$(VERSION).lsm
SVLOGIN=$(shell svn info | sed -rn '/Repository Root:/{ s|.*//(.*)\@.*|\1|p }')
+ifeq ($(MAKECMDGOALS),upload)
override TMP:=$(shell mktemp -d $(PACKAGE)-$(VERSION).XXXXXXXX)
override TARBALL:=$(TMP)/$(PACKAGE)-$(VERSION).tar.bz2
override SFTPBATCH:=$(TMP)/$(VERSION)-sftpbatch
@@ -224,4 +232,4 @@
svn export . $@
@chmod -R a+r,u+w,og-w $@
@find $@ -type d | xargs -r chmod a+rx,u+w,og-w
-
+endif
Modified: trunk/src/insserv/insserv.8.in
URL: http://svn.debian.org/wsvn/initscripts-ng/trunk/src/insserv/insserv.8.in?rev=1088&op=diff
==============================================================================
--- trunk/src/insserv/insserv.8.in (original)
+++ trunk/src/insserv/insserv.8.in Sat Feb 8 21:29:44 2014
@@ -269,6 +269,9 @@
.TP
.BR \-n ,\ \-\-dryrun
Do not update symlinks.
+.TP
+.BR \-s ,\ \-\-showall
+Output runlevel and sequence information. Do not update symlinks.
.TP
.BR \-r ,\ \-\-remove
Remove the listed scripts from all runlevels.
Modified: trunk/src/insserv/insserv.c
URL: http://svn.debian.org/wsvn/initscripts-ng/trunk/src/insserv/insserv.c?rev=1088&op=diff
==============================================================================
--- trunk/src/insserv/insserv.c (original)
+++ trunk/src/insserv/insserv.c Sat Feb 8 21:29:44 2014
@@ -23,9 +23,16 @@
*
*/
+/*
+ * Systemd integration
+ */
+#define SYSTEMD_SERVICE_PATH "/lib/systemd/system"
+#define SYSTEMD_BINARY_PATH "/bin/systemd"
+
#define MINIMAL_MAKE 1 /* Remove disabled scripts from .depend.boot,
* .depend.start, .depend.halt, and .depend.stop */
#define MINIMAL_RULES 1 /* ditto */
+#define MINIMAL_DEPEND 1 /* Remove redundant dependencies */
#include <pwd.h>
#include <string.h>
@@ -36,6 +43,7 @@
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
+#include <sys/statfs.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/syscall.h>
@@ -44,6 +52,12 @@
#include <errno.h>
#include <limits.h>
#include <getopt.h>
+#if defined(__linux__)
+# include <linux/magic.h>
+#endif
+#if !defined(CGROUP_SUPER_MAGIC)
+# define CGROUP_SUPER_MAGIC 0x27e0eb
+#endif
#if defined(USE_RPMLIB) && (USE_RPMLIB > 0)
# include <rpm/rpmlib.h>
# include <rpm/rpmmacro.h>
@@ -52,6 +66,7 @@
# include <sys/mount.h>
#endif /* SUSE */
#include "listing.h"
+#include "systemd.h"
#if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) >= 600
# ifndef POSIX_FADV_SEQUENTIAL
@@ -97,7 +112,11 @@
# define INSCONF "/etc/insserv.conf"
#endif
-const char *upstartjob_path = "/lib/init/upstart-job";
+/* Upstart suport */
+static const char *upstartjob_path = "/lib/init/upstart-job";
+
+/* Systemd support */
+static DBusConnection *sbus;
/*
* For a description of regular expressions see regex(7).
@@ -151,6 +170,10 @@
static boolean set_override = false;
static boolean set_insconf = false;
+/* Wether systemd is active or not */
+static boolean systemd = false;
+static boolean is_overridden_by_systemd(const char *);
+
/* Search results points here */
typedef struct lsb_struct {
char *provides;
@@ -242,13 +265,18 @@
* Linked list of system facilities services and their replacment
*/
typedef struct string {
- int *restrict ref;
+ list_t s_list;
+ int ref;
char *name;
} __align string_t;
+#define getfstr(arg) list_entry((arg), struct string, s_list)
typedef struct repl {
list_t r_list;
- string_t r[1];
+ struct {
+ string_t *addr;
+ const char *name;
+ };
ushort flags;
} __align repl_t;
#define getrepl(arg) list_entry((arg), struct repl, r_list)
@@ -260,6 +288,7 @@
} __align faci_t;
#define getfaci(arg) list_entry((arg), struct faci, list)
+static list_t facistr = { &facistr, &facistr }, *facistr_start = &facistr;
static list_t sysfaci = { &sysfaci, &sysfaci }, *sysfaci_start = &sysfaci;
/*
@@ -337,7 +366,7 @@
if (!strcmp(token, getfaci(ptr)->name)) {
list_t * lst;
np_list_for_each(lst, &getfaci(ptr)->replace)
- rememberreq(serv, bit, getrepl(lst)->r[0].name);
+ rememberreq(serv, bit, getrepl(lst)->name);
break;
}
}
@@ -377,7 +406,7 @@
if (!strcmp(token, getfaci(ptr)->name)) {
list_t * lst;
np_list_for_each(lst, &getfaci(ptr)->replace)
- reversereq(serv, bit, getrepl(lst)->r[0].name);
+ reversereq(serv, bit, getrepl(lst)->name);
break;
}
}
@@ -389,8 +418,8 @@
/*
* Check required services for name
*/
-static boolean chkrequired(service_t *restrict serv) attribute((nonnull(1)));
-static boolean chkrequired(service_t *restrict serv)
+static boolean chkrequired(service_t *restrict serv, const boolean recursive) attribute((nonnull(1)));
+static boolean chkrequired(service_t *restrict serv, const boolean recursive)
{
boolean ret = true;
list_t * pos;
@@ -409,12 +438,23 @@
must = getorig(must);
if ((must->attr.flags & (SERV_CMDLINE|SERV_ENABLED)) == 0) {
- warn("Service %s has to be enabled to start service %s\n",
- req->serv->name, serv->name);
+ if (recursive) {
+ must->attr.flags |= SERV_ENFORCE;
+ continue; /* Enabled this later even if not on command line */
+ }
+ if ((must->attr.flags & SERV_WARNED) == 0) {
+ warn("FATAL: service %s has to be enabled to use service %s\n",
+ req->serv->name, serv->name);
+ must->attr.flags |= SERV_WARNED;
+ }
ret = false;
}
}
#if 0
+ /*
+ * Once we may use REQ_MUST for X-Start-Before and/or
+ * X-Stop-After we may enable this, see reversereq()
+ */
if (serv->attr.flags & (SERV_CMDLINE|SERV_ENABLED))
goto out;
np_list_for_each(pos, &serv->sort.rev) {
@@ -425,9 +465,8 @@
continue;
must = rev->serv;
must = getorig(must);
-
if (must->attr.flags & (SERV_CMDLINE|SERV_ENABLED)) {
- warn("Service %s has to be enabled to stop service %s\n",
+ warn("FATAL: service %s has to be enabled to use service %s\n",
serv->name, rev->serv->name);
ret = false;
}
@@ -476,7 +515,7 @@
if ((cur->attr.flags & SERV_CMDLINE) && (flags & SERV_CMDLINE))
continue;
- warn("Service %s has to be enabled to start service %s\n",
+ warn("FATAL: service %s has to be enabled to use service %s\n",
name, cur->name);
ret = false;
}
@@ -738,7 +777,7 @@
FILE *halt;
#endif /* USE_KILL_IN_BOOT */
const char *target;
- service_t *serv;
+ const service_t *serv;
if (dryrun) {
#ifdef USE_KILL_IN_BOOT
@@ -818,6 +857,10 @@
target = (char*)0;
while ((serv = listscripts(&target, 'S', LVL_BOOT|LVL_ALL))) {
+#if defined(MINIMAL_DEPEND) && (MINIMAL_DEPEND != 0)
+ const service_t * lserv[100] = {0};
+ unsigned long lcnt = 0;
+#endif /* not MINIMAL_DEPEND */
boolean mark;
list_t * pos;
@@ -841,6 +884,10 @@
np_list_for_each(pos, &serv->sort.req) {
req_t * req = getreq(pos);
service_t * dep = req->serv;
+#if defined(MINIMAL_DEPEND) && (MINIMAL_DEPEND != 0)
+ boolean shadow = false;
+ unsigned long n;
+#endif /* not MINIMAL_DEPEND */
const char * name;
if (!dep)
@@ -870,7 +917,36 @@
fprintf(out, "%s:", target);
mark = true;
}
+#if defined(MINIMAL_DEPEND) && (MINIMAL_DEPEND != 0)
+ for (n = 0; n < lcnt && lserv[n] ; n++) {
+ list_t * red;
+ if (lserv[n]->attr.sorder <= dep->attr.sorder)
+ break;
+ np_list_for_each(red, &(lserv[n])->sort.req) {
+ req_t * other = getreq(red);
+ if (other->serv->attr.flags & SERV_DUPLET)
+ continue;
+ if (other->serv->attr.ref <= 0)
+ continue;
+ if ((serv->start->lvl & other->serv->start->lvl) == 0)
+ continue;
+ if (!other->serv->attr.script)
+ continue;
+ if (other->serv != dep)
+ continue;
+ shadow = true;
+ }
+ }
+ if (shadow)
+ continue;
+#endif /* not MINIMAL_DEPEND */
fprintf(out, " %s", name);
+
+#if defined(MINIMAL_DEPEND) && (MINIMAL_DEPEND != 0)
+ if (lcnt >= sizeof(lserv)/sizeof(lserv[0]))
+ continue;
+ lserv[lcnt++] = dep;
+#endif /* not MINIMAL_DEPEND */
}
if (mark) fputc('\n', out);
@@ -927,6 +1003,10 @@
target = (char*)0;
while ((serv = listscripts(&target, 'K', (LVL_NORM|LVL_BOOT)))) {
+#if defined(MINIMAL_DEPEND) && (MINIMAL_DEPEND != 0)
+ const service_t * lserv[100] = {0};
+ unsigned long lcnt = 0;
+#endif /* not MINIMAL_DEPEND */
boolean mark;
list_t * pos;
@@ -953,6 +1033,10 @@
np_list_for_each(pos, &serv->sort.rev) {
req_t * rev = getreq(pos);
service_t * dep = rev->serv;
+#if defined(MINIMAL_DEPEND) && (MINIMAL_DEPEND != 0)
+ boolean shadow = false;
+ unsigned long n;
+#endif /* not MINIMAL_DEPEND */
const char * name;
if (!dep)
@@ -976,7 +1060,36 @@
fprintf(out, "%s:", target);
mark = true;
}
+#if defined(MINIMAL_DEPEND) && (MINIMAL_DEPEND != 0)
+ for (n = 0; n < lcnt && lserv[n]; n++) {
+ list_t * red;
+ if (lserv[n]->attr.korder <= dep->attr.korder)
+ break;
+ np_list_for_each(red, &(lserv[n])->sort.rev) {
+ req_t * other = getreq(red);
+ if (other->serv->attr.flags & SERV_DUPLET)
+ continue;
+ if (other->serv->attr.ref <= 0)
+ continue;
+ if ((serv->start->lvl & other->serv->start->lvl) == 0)
+ continue;
+ if (!other->serv->attr.script)
+ continue;
+ if (other->serv != dep)
+ continue;
+ shadow = true;
+ }
+ }
+ if (shadow)
+ continue;
+#endif /* not MINIMAL_DEPEND */
fprintf(out, " %s", name);
+
+#if defined(MINIMAL_DEPEND) && (MINIMAL_DEPEND != 0)
+ if (lcnt >= sizeof(lserv)/sizeof(lserv[0]))
+ continue;
+ lserv[lcnt++] = dep;
+#endif /* not MINIMAL_DEPEND */
}
if (mark) fputc('\n', out);
}
@@ -1244,6 +1357,7 @@
#define FOUND_LSB_DEFAULT 0x02
#define FOUND_LSB_OVERRIDE 0x04
#define FOUND_LSB_UPSTART 0x08
+#define FOUND_LSB_SYSTEMD 0x10
static int o_flags = O_RDONLY;
@@ -1378,10 +1492,10 @@
description = empty;
}
- if (!interactive && regexecutor(®.interact, COMMON_ARGS) == true) {
- if (val->rm_so < val->rm_eo) {
- *(pbuf+val->rm_eo) = '\0';
- interactive = xstrdup(pbuf+val->rm_so);
+ if (!interactive && regexecutor(®.interact, COMMON_SHD_ARGS) == true) {
+ if (shl->rm_so < shl->rm_eo) {
+ *(pbuf+shl->rm_eo) = '\0';
+ interactive = xstrdup(pbuf+shl->rm_so);
} else
interactive = empty;
}
@@ -1416,7 +1530,7 @@
char *name = basename(path);
if (*name == 'S' || *name == 'K')
name += 3;
- warn("Script %s is broken: missing end of LSB comment.\n", name);
+ warn("%sscript %s is broken: missing end of LSB comment.\n", ignore ? "" : "FATAL: ", name);
if (!ignore)
error("exiting now!\n");
}
@@ -1432,7 +1546,7 @@
char *name = basename(path);
if (*name == 'S' || *name == 'K')
name += 3;
- warn("Script %s is broken: incomplete LSB comment.\n", name);
+ warn("script %s is broken: incomplete LSB comment.\n", name);
if (!provides)
warn("missing `Provides:' entry: please add.\n");
if (provides == empty)
@@ -1478,7 +1592,7 @@
linkbuf[PATH_MAX] = '\0';
do {
- struct stat st;
+ struct stat st;
int linklen;
if (deep++ > MAXSYMLINKS) {
@@ -1544,7 +1658,7 @@
error("snprintf(): %s\n", strerror(errno));
if (stat(fullpath, &statbuf) == 0 && S_ISREG(statbuf.st_mode))
- ret = scan_lsb_headers(-1, fullpath, cache, ignore);
+ ret = scan_lsb_headers(-1, fullpath, cache, ignore);
if (ret & FOUND_LSB_HEADER)
ret |= FOUND_LSB_OVERRIDE;
return ret;
@@ -1588,27 +1702,48 @@
}
#endif /* SUSE */
- /* Replace with headers from the script itself */
- ret |= scan_lsb_headers(dfd, path, cache, ignore);
-
- /* Do not override the upstarts defaults, if we allow this
- * we have to change name to the link name otherwise the
- * name is always "upstart-job" */
- if (ret & FOUND_LSB_UPSTART)
- goto out;
-
- /* Load values if the override file exist */
- if ((ret & FOUND_LSB_HEADER) == 0)
- ret |= load_overrides("/usr/share/insserv/overrides", name, cache, ignore);
- else
- ret |= FOUND_LSB_DEFAULT;
+ if (systemd) {
+ const char *serv;
+ serv = path;
+ if (strncmp("boot.", serv, 5) == 0)
+ serv += 5;
+ if (is_overridden_by_systemd(serv)) {
+ ret |= FOUND_LSB_SYSTEMD;
+ }
+ }
+
+ if (is_upstart_job(path) != (char*)0) {
+ /*
+ * Do not override the upstarts defaults, if we allow this
+ * we have to change name to the link name otherwise the
+ * name is always "upstart-job"
+ */
+ ret |= scan_lsb_headers(dfd, path, cache, ignore);
+ if (ret & FOUND_LSB_UPSTART)
+ goto out;
+ }
/*
* Allow host-specific overrides to replace the content in the
* init.d scripts
*/
ret |= load_overrides(override_path, name, cache, ignore);
+ if (ret & FOUND_LSB_OVERRIDE)
+ goto out;
+
+ /*
+ * Load third-party-specific values if the override file exist
+ */
+ ret |= load_overrides("/usr/share/insserv/overrides", name, cache, ignore);
+ if (ret & FOUND_LSB_OVERRIDE)
+ goto out;
+
+ /*
+ * Replace with headers from the script itself
+ */
+ ret |= scan_lsb_headers(dfd, path, cache, ignore);
out:
+ ret |= FOUND_LSB_DEFAULT;
free(name);
return ret;
}
@@ -1723,7 +1858,7 @@
if (!strpbrk(token, "0123456sSbB"))
continue;
- ret |= map_key_to_lvl(*token);
+ ret |= map_key_to_lvl(*token);
}
return ret;
@@ -1967,57 +2102,51 @@
real = pbuf+val->rm_so;
}
if (virt) {
- list_t * ptr;
- boolean found = false;
+ list_t *ptr;
+ list_t *r_list = (list_t*)0;
list_for_each(ptr, sysfaci_start) {
if (!strcmp(getfaci(ptr)->name, virt)) {
- found = true;
- if(real) {
- list_t * r_list = &getfaci(ptr)->replace;
- char * token;
- while ((token = strsep(&real, delimeter))) {
- repl_t *restrict subst;
- string_t * r;
- if (posix_memalign((void*)&subst, sizeof(void*), alignof(repl_t)) != 0)
- error("%s", strerror(errno));
- insert(&subst->r_list, r_list->prev);
- subst->flags = 0;
- r = &subst->r[0];
- if (posix_memalign((void*)&r->ref, sizeof(void*), alignof(typeof(r->ref))+strsize(token)) != 0)
- error("%s", strerror(errno));
- *r->ref = 1;
- r->name = ((char*)(r->ref))+alignof(typeof(r->ref));
- strcpy(r->name, token);
- }
- }
+ r_list = &getfaci(ptr)->replace;
break;
}
}
- if (!found) {
+ if (!r_list) {
faci_t *restrict this;
if (posix_memalign((void*)&this, sizeof(void*), alignof(faci_t)) != 0)
error("%s", strerror(errno));
else {
- list_t * r_list = &this->replace;
- char * token;
- r_list->next = r_list;
- r_list->prev = r_list;
+ r_list = &this->replace;
+ initial(r_list);
insert(&this->list, sysfaci_start->prev);
this->name = xstrdup(virt);
- while ((token = strsep(&real, delimeter))) {
- repl_t *restrict subst;
- string_t * r;
- if (posix_memalign((void*)&subst, sizeof(void*), alignof(repl_t)) != 0)
+ }
+ }
+ if(real) {
+ char *token;
+ while ((token = strsep(&real, delimeter))) {
+ repl_t *restrict subst;
+ string_t *r = (string_t*)0;
+ if (posix_memalign((void*)&subst, sizeof(void*), alignof(repl_t)) != 0)
+ error("%s", strerror(errno));
+ insert(&subst->r_list, r_list->prev);
+ subst->flags = 0;
+ list_for_each(ptr, facistr_start) {
+ if (strcmp(getfstr(ptr)->name, token) == 0) {
+ r = getfstr(ptr);
+ break;
+ }
+ }
+ if (!r) {
+ if (posix_memalign((void*)&r, sizeof(void*), alignof(string_t)+strsize(token)) != 0)
error("%s", strerror(errno));
- insert(&subst->r_list, r_list->prev);
- subst->flags = 0;
- r = &subst->r[0];
- if (posix_memalign((void*)&r->ref, sizeof(void*), alignof(typeof(r->ref))+strsize(token)) != 0)
- error("%s", strerror(errno));
- *r->ref = 1;
- r->name = ((char*)(r->ref))+alignof(typeof(r->ref));
+ r->ref = 1;
+ insert(&r->s_list, facistr_start);
+ r->name = ((char*)r)+alignof(string_t);
strcpy(r->name, token);
- }
+ } else
+ r->ref++;
+ subst->addr = r;
+ subst->name = r->name;
}
}
}
@@ -2140,69 +2269,218 @@
regfree(&creg.isactive);
}
+/*
+ * Maps between systemd and SystemV
+ */
+static const char* sdmap[] = {
+ "$local-fs", "$local_fs",
+ "$remote-fs", "$remote_fs",
+ "cryptsetup", "boot.crypto-early",
+ "udev", "boot.udev",
+ "multipathd", "boot.multipath",
+ "loadmodules", "boot.loadmodules",
+ "device-mapper", "boot.device-mapper",
+ "sysctl", "boot.sysctl",
+ "fsck-root", "boot.rootfsck",
+ "localfs", "boot.localfs"
+};
+
+/*
+ * Here the systemd targets are imported as system facilities
+ */
+static void import_systemd_facilities(void)
+{
+ list_t *ptr;
+ list_for_each(ptr, &sdservs) {
+ sdserv_t *sdserv = list_entry(ptr, sdserv_t, s_list);
+ const char *facilitiy;
+ list_t *r_list;
+ list_t *iptr;
+ int n;
+
+ if (*sdserv->name != '$')
+ continue;
+
+ facilitiy = sdserv->name;
+ for (n = 0; n < (int)(sizeof(sdmap)/sizeof(sdmap[0])); n += 2) {
+ if (strcmp(sdmap[n], facilitiy) == 0) {
+ facilitiy = sdmap[n+1];
+ break;
+ }
+ }
+
+ r_list = (list_t*)0;
+ np_list_for_each(iptr, sysfaci_start) {
+ if (strcmp(getfaci(iptr)->name, facilitiy) == 0) {
+ r_list = &getfaci(iptr)->replace;
+ break;
+ }
+ }
+ if (!r_list) {
+ faci_t *restrict this;
+ if (posix_memalign((void*)&this, sizeof(void*), alignof(faci_t)) != 0)
+ error("%s", strerror(errno));
+ else {
+ r_list = &this->replace;
+ initial(r_list);
+ insert(&this->list, sysfaci_start->prev);
+ this->name = xstrdup(facilitiy);
+ }
+ }
+
+ np_list_for_each(iptr, &sdserv->a_list) {
+ ally_t *ally = list_entry(iptr, ally_t, a_list);
+ repl_t *restrict subst;
+ string_t *r = (string_t*)0;
+ const char *token;
+ list_t *fptr;
+
+ if (ally->flags & SDREL_CONFLICTS)
+ continue;
+ if (ally->flags & SDREL_BEFORE)
+ continue;
+
+ token = ally->serv->name;
+ for (n = 0; n < (int)(sizeof(sdmap)/sizeof(sdmap[0])); n += 2) {
+ if (strcmp(sdmap[n], token) == 0) {
+ token = sdmap[n+1];
+ break;
+ }
+ }
+
+ if (posix_memalign((void*)&subst, sizeof(void*), alignof(repl_t)) != 0)
+ error("%s", strerror(errno));
+ insert(&subst->r_list, r_list->prev);
+ subst->flags = 0;
+ np_list_for_each(fptr, facistr_start) {
+ if (strcmp(getfstr(fptr)->name, token) == 0) {
+ r = getfstr(fptr);
+ break;
+ }
+ }
+ if (!r) {
+ if (posix_memalign((void*)&r, sizeof(void*), alignof(string_t)+strsize(token)) != 0)
+ error("%s", strerror(errno));
+ r->ref = 1;
+ insert(&r->s_list, facistr_start);
+ r->name = ((char*)r)+alignof(string_t);
+ strcpy(r->name, token);
+ } else
+ r->ref++;
+ subst->addr = r;
+ subst->name = r->name;
+ }
+ }
+}
+
+/*
+ * Here the systemd servies are imported as services
+ */
+static void import_systemd_services(void)
+{
+ list_t *ptr;
+ list_for_each(ptr, &sdservs) {
+ sdserv_t *sdserv = list_entry(ptr, sdserv_t, s_list);
+ const char *this;
+ list_t *aptr;
+ int n;
+
+ if (*sdserv->name == '$')
+ continue;
+
+ this = sdserv->name;
+ for (n = 0; n < (int)(sizeof(sdmap)/sizeof(sdmap[0])); n += 2) {
+ if (strcmp(sdmap[n], this) == 0) {
+ this = sdmap[n+1];
+ break;
+ }
+ }
+
+ np_list_for_each(aptr, &sdserv->a_list) {
+ ally_t *ally = list_entry(aptr, ally_t, a_list);
+ service_t * service;
+ const char *token;
+
+ if (ally->flags & SDREL_CONFLICTS)
+ continue;
+ if (ally->flags & SDREL_BEFORE)
+ continue;
+
+ token = ally->serv->name;
+ for (n = 0; n < (int)(sizeof(sdmap)/sizeof(sdmap[0])); n += 2) {
+ if (strcmp(sdmap[n], token) == 0) {
+ token = sdmap[n+1];
+ break;
+ }
+ }
+ service = addservice(this);
+ rememberreq(service, (ally->flags & SDREL_WANTS) ? REQ_SHLD : REQ_MUST, token);
+ service->attr.flags |= SERV_SYSTEMD;
+ }
+ }
+}
+
static void expand_faci(list_t *restrict rlist, list_t *restrict head,
int *restrict deep) attribute((noinline,nonnull(1,2,3)));
static void expand_faci(list_t *restrict rlist, list_t *restrict head, int *restrict deep)
{
- repl_t * rent = getrepl(rlist);
- list_t * tmp, * safe, * ptr = (list_t*)0;
-
- list_for_each(tmp, sysfaci_start) {
- if (!strcmp(getfaci(tmp)->name, rent->r[0].name)) {
- ptr = &getfaci(tmp)->replace;
- break;
- }
- }
-
- if (!ptr || list_empty(ptr)) {
- delete(rlist);
- if (--(*rent->r[0].ref) <= 0)
- free(rent->r[0].ref);
- free(rent);
- goto out;
- }
-
- list_for_each_safe(tmp, safe, ptr) {
- repl_t * rnxt = getrepl(tmp);
- if (rnxt->flags & 0x0001) {
- error("Loop detected during expanding system facilities in the insserv.conf file(s): %s\n",
- rnxt->r[0].name);
- }
- if (*rnxt->r[0].name == '$') {
- if (*deep > 10) {
- warn("The nested level of the system facilities in the insserv.conf file(s) is to large\n");
- goto out;
- }
- (*deep)++;
- rnxt->flags |= 0x0001;
- expand_faci(tmp, head, deep);
- rnxt->flags &= ~0x0001;
- (*deep)--;
- } else if (*deep > 0) {
- repl_t *restrict subst;
- if (posix_memalign((void*)&subst, sizeof(void*), alignof(repl_t)) != 0)
- error("%s", strerror(errno));
- insert(&subst->r_list, head->prev);
- subst->r[0] = rnxt->r[0];
- (*subst->r[0].ref) = 1;
- }
- }
+ repl_t *rent = getrepl(rlist);
+ list_t *tmp, *safe, *ptr = (list_t*)0;
+
+ list_for_each(tmp, sysfaci_start) {
+ if (!strcmp(getfaci(tmp)->name, rent->name)) {
+ ptr = &getfaci(tmp)->replace;
+ break;
+ }
+ }
+
+ if (!ptr || list_empty(ptr))
+ goto out;
+
+ list_for_each_safe(tmp, safe, ptr) {
+ repl_t *rnxt = getrepl(tmp);
+ if (rnxt->flags & 0x0001) {
+ error("Loop detected during expanding system facilities in the insserv.conf file(s): %s %s\n",
+ rnxt->name, getrepl(head->prev)->name);
+ }
+ if (*rnxt->name == '$') {
+ if (*deep > 10) {
+ warn("The nested level of the system facilities in the insserv.conf file(s) is to large\n");
+ goto out;
+ }
+ (*deep)++;
+ rnxt->flags |= 0x0001;
+ expand_faci(tmp, head, deep);
+ rnxt->flags &= ~0x0001;
+ (*deep)--;
+ } else if (*deep >= 0) {
+ repl_t *restrict subst;
+ if (posix_memalign((void*)&subst, sizeof(void*), alignof(repl_t)) != 0)
+ error("%s", strerror(errno));
+ insert(&subst->r_list, head->prev);
+ subst->addr = rnxt->addr;
+ subst->name = rnxt->name;
+ subst->addr->ref++;
+ }
+ }
out:
- return;
+ return;
}
static inline void expand_conf(void)
{
list_t *ptr;
list_for_each(ptr, sysfaci_start) {
- list_t * rlist, * safe, * head = &getfaci(ptr)->replace;
+ list_t *rlist, *safe, *head = &getfaci(ptr)->replace;
list_for_each_safe(rlist, safe, head) {
- repl_t * tmp = getrepl(rlist);
- if (*tmp->r[0].name == '$') {
+ repl_t *tmp = getrepl(rlist);
+ if (*tmp->name == '$') {
int deep = 0;
- tmp->flags |= 0x0001;
- expand_faci(rlist, rlist, &deep);
- tmp->flags &= ~0x0001;
+ expand_faci(rlist, head, &deep);
+ delete(rlist);
+ if (--(tmp->addr->ref) <= 0)
+ free(tmp->addr);
+ free(tmp);
}
}
}
@@ -2336,19 +2614,77 @@
}
#endif /* SUSE */
+/*
+ * Systemd integration
+ */
+static boolean is_overridden_by_systemd(const char *service) {
+ char *p;
+ boolean ret = false;
+
+ if (asprintf(&p, SYSTEMD_SERVICE_PATH "/%s.service", service) < 0)
+ error("asprintf(): %s\n", strerror(errno));
+
+ if (access(p, F_OK) >= 0)
+ ret = true;
+ free(p);
+ return ret;
+}
+
+static void forward_to_systemd (const char *initscript, const char *verb, boolean alternative_root) {
+ const char *name;
+
+ if (initscript == NULL)
+ return;
+
+ if (strncmp("boot.",initscript,5) == 0)
+ name = initscript+5;
+ else
+ name = initscript;
+
+ if (is_overridden_by_systemd (name)) {
+ char *p;
+ int err = 0;
+
+ if (alternative_root && root)
+ err = asprintf (&p, "/bin/systemctl --quiet --no-reload --root %s %s %s.service", root, verb, name);
+ else {
+ struct statfs stfs;
+ if (statfs("/sys/fs/cgroup/systemd", &stfs) < 0 && errno != ENOENT)
+ error("statfs(): %s\n", strerror(errno));
+ if (errno == 0 && stfs.f_type == CGROUP_SUPER_MAGIC)
+ err = asprintf (&p, "/bin/systemctl --quiet %s %s.service", verb, name);
+ else
+ err = asprintf (&p, "/bin/systemctl --quiet --no-reload %s %s.service", verb, name);
+ }
+ if (err < 0)
+ error("asprintf(): %s\n", strerror(errno));
+
+ warn("Note: sysvinit service %s is shadowed by systemd %s.service,\nForwarding request to '%s'.\n", initscript, name, p);
+ if (!dryrun)
+ err = system(p);
+ if (err < 0)
+ warn("Failed to forward service request to systemctl: %m\n");
+ else if (err > 0)
+ warn("Forward service request to systemctl returned error status : %d\n",err);
+ free (p);
+ }
+}
+
static struct option long_options[] =
{
- {"verbose", 0, (int*)0, 'v'},
- {"config", 1, (int*)0, 'c'},
- {"dryrun", 0, (int*)0, 'n'},
- {"default", 0, (int*)0, 'd'},
- {"remove", 0, (int*)0, 'r'},
- {"force", 0, (int*)0, 'f'},
- {"path", 1, (int*)0, 'p'},
- {"override",1, (int*)0, 'o'},
- {"upstart-job",1, (int*)0, 'u'},
- {"help", 0, (int*)0, 'h'},
- { 0, 0, (int*)0, 0 },
+ {"verbose", 0, (int*)0, 'v'},
+ {"config", 1, (int*)0, 'c'},
+ {"dryrun", 0, (int*)0, 'n'},
+ {"default", 0, (int*)0, 'd'},
+ {"remove", 0, (int*)0, 'r'},
+ {"force", 0, (int*)0, 'f'},
+ {"path", 1, (int*)0, 'p'},
+ {"override", 1, (int*)0, 'o'},
+ {"upstart-job", 1, (int*)0, 'u'},
+ {"recursive", 0, (int*)0, 'e'},
+ {"showall", 0, (int*)0, 's'},
+ {"help", 0, (int*)0, 'h'},
+ { 0, 0, (int*)0, 0 },
};
static void help(const char *restrict const name) attribute((nonnull(1)));
@@ -2364,6 +2700,9 @@
printf(" -o <path>, --override <path> Path to replace " OVERRIDEDIR ".\n");
printf(" -c <config>, --config <config> Path to config file.\n");
printf(" -n, --dryrun Do not change the system, only talk about it.\n");
+ printf(" -s, --showall Output runlevel and sequence information.\n");
+ printf(" -u <path>, --upstart-job <path> Path to replace existing upstart job path.\n");
+ printf(" -e, --recursive Expand and enable all required services.\n");
printf(" -d, --default Use default runlevels a defined in the scripts\n");
}
@@ -2386,6 +2725,9 @@
boolean defaults = false;
boolean ignore = false;
boolean loadarg = false;
+ boolean recursive = false;
+ boolean showall = false;
+ boolean waserr = false;
myname = basename(*argv);
@@ -2400,7 +2742,7 @@
for (c = 0; c < argc; c++)
argr[c] = (char*)0;
- while ((c = getopt_long(argc, argv, "c:dfrhvno:p:u:", long_options, (int *)0)) != -1) {
+ while ((c = getopt_long(argc, argv, "c:dfrhvno:p:u:es", long_options, (int *)0)) != -1) {
size_t l;
switch (c) {
case 'c':
@@ -2425,6 +2767,10 @@
verbose ++;
dryrun = true;
break;
+ case 's':
+ showall = true;
+ dryrun = true;
+ break;
case 'p':
if (optarg == (char*)0 || *optarg == '\0')
goto err;
@@ -2445,6 +2791,9 @@
goto err;
upstartjob_path = optarg;
break;
+ case 'e':
+ recursive = true;
+ break;
case '?':
err:
error("For help use: %s -h\n", myname);
@@ -2566,15 +2915,67 @@
printf("Overwrite argument for %s is %s\n", argv[c], argr[c]);
#endif /* DEBUG */
+#ifdef SUSE
+ if (!underrpm())
+#endif
+ /*
+ * Systemd support
+ */
+ if (access(SYSTEMD_BINARY_PATH, F_OK) == 0 && (sbus = systemd_open_conn())) {
+
+ for (c = 0; c < argc; c++)
+ forward_to_systemd (argv[c], del ? "disable": "enable", path != ipath);
+
+ (void)systemd_get_tree(sbus);
+ systemd_close_conn(sbus);
+ systemd = true;
+ }
+
/*
* Scan and set our configuration for virtual services.
*/
scan_conf(insconf);
/*
+ * Handle Systemd target as system facilities (<name>.target -> $<name>)
+ */
+ if (systemd)
+ import_systemd_facilities();
+
+ {
+ list_t *ptr;
+ list_for_each(ptr, sysfaci_start) {
+ list_t *iptr, *head = &getfaci(ptr)->replace;
+ printf("%s : ", getfaci(ptr)->name);
+ np_list_for_each(iptr, head)
+ printf("%s ", getrepl(iptr)->name);
+ printf("\n");
+ }
+ }
+
+ /*
* Expand system facilities to real services
*/
expand_conf();
+
+ {
+ list_t *ptr;
+ list_for_each(ptr, sysfaci_start) {
+ list_t *iptr, *head = &getfaci(ptr)->replace;
+ printf("%s : ", getfaci(ptr)->name);
+ np_list_for_each(iptr, head)
+ printf("%s ", getrepl(iptr)->name);
+ printf("\n");
+ }
+ }
+
+ /*
+ * Handle Systemd services (<name>.service -> <name>)
+ */
+ if (systemd) {
+ import_systemd_services();
+ systemd_free(); /* Not used anymore */
+ }
/*
* Initialize the regular scanner for the scripts.
@@ -2612,7 +3013,7 @@
* Scan scripts found in the command line to be able to resolve
* all dependcies given within those scripts.
*/
- if (argc > 1) for (c = 0; c < argc; c++) {
+ for (c = 0; c < argc; c++) {
const char *const name = argv[c];
service_t * first = (service_t*)0;
char * provides, * begin, * token;
@@ -3000,8 +3401,10 @@
if (!del || (del && !isarg))
warn("script %s: service %s already provided!\n", d->d_name, token);
- if (!del && !ignore && isarg)
- error("exiting now!\n");
+ if (!del && !ignore && isarg) {
+ waserr = true;
+ continue;
+ }
if (!del || (del && !ignore && !isarg))
continue;
@@ -3064,9 +3467,9 @@
if (del)
ok = chkdependencies(service);
else
- ok = chkrequired(service);
+ ok = chkrequired(service, recursive);
if (!ok && !ignore)
- error("exiting now!\n");
+ waserr = true;
}
if (script_inf.default_start && script_inf.default_start != empty) {
@@ -3357,10 +3760,136 @@
active_script();
/*
+ * Check if runlevels of required scripts are a real subset
+ * of the services handled here.
+ */
+ if (!del && !ignore) {
+ list_t * ptr;
+ list_for_each(ptr, s_start) {
+ service_t * cur = getservice(ptr);
+ ushort clvl = cur->start->lvl & ~LVL_SINGLE;
+ list_t * pos;
+
+ cur = getorig(cur);
+ if (list_empty(&cur->sort.req))
+ continue;
+
+ if (cur->attr.flags & SERV_SYSTEMD)
+ continue;
+
+ np_list_for_each(pos, &cur->sort.req) {
+ req_t *req = getreq(pos);
+ service_t * must;
+
+ if ((req->flags & REQ_MUST) == 0)
+ continue;
+ must = req->serv;
+ must = getorig(must);
+
+ if (must->attr.flags & SERV_SYSTEMD)
+ continue;
+
+ /*
+ * Check for recursive mode the existence of the required services
+ */
+ if (cur->attr.flags & SERV_CMDLINE) {
+
+ if (must->attr.flags & SERV_ENABLED) {
+ ushort mlvl = must->start->lvl & ~LVL_SINGLE;
+
+ if ((mlvl & LVL_BOOT) && (clvl & LVL_BOOT) == 0)
+ continue;
+
+ if ((mlvl & clvl) == clvl)
+ continue;
+ if (recursive) {
+ must->start->lvl |= clvl;
+ must->stopp->lvl |= clvl;
+ continue;
+ }
+ clvl &= ~mlvl;
+ if ((must->attr.flags & SERV_WARNED) == 0)
+#ifdef OSCBUILD
+ warn("Service %s is missed in the runlevels %s to use service %s\n",
+ must->name, lvl2str(clvl), cur->name);
+#else
+ warn("FATAL: service %s is missed in the runlevels %s to use service %s\n",
+ must->name, lvl2str(clvl), cur->name);
+ waserr = true;
+#endif
+ must->attr.flags |= SERV_WARNED;
+ continue;
+ }
+ if ((must->attr.flags & (SERV_ENFORCE|SERV_KNOWN)) == SERV_ENFORCE) {
+ if ((must->attr.flags & SERV_WARNED) == 0)
+#ifdef OSCBUILD
+ warn("Service %s has to exists for service %s\n",
+ must->name, cur->name);
+#else
+ warn("FATAL: service %s has to exists for service %s\n",
+ must->name, cur->name);
+ waserr = true;
+#endif
+ must->attr.flags |= SERV_WARNED;
+ continue;
+ }
+ if (recursive) {
+ must->start->lvl |= clvl;
+ must->stopp->lvl |= clvl;
+ continue;
+ }
+ continue;
+ }
+ if ((cur->attr.flags & SERV_ENABLED) == 0)
+ continue;
+ if ((must->attr.flags & (SERV_CMDLINE|SERV_KNOWN)) == 0) {
+ if ((must->attr.flags & SERV_WARNED) == 0)
+#ifdef OSCBUILD
+ warn("Service %s has to exists for service %s\n",
+ must->name, cur->name);
+#else
+ warn("FATAL: service %s has to exists for service %s\n",
+ must->name, cur->name);
+ waserr = true;
+#endif
+ must->attr.flags |= SERV_WARNED;
+ continue;
+ }
+ if (must->attr.flags & SERV_ENABLED) {
+ ushort mlvl = must->start->lvl & ~LVL_SINGLE;
+
+ if ((mlvl & LVL_BOOT) && (clvl & LVL_BOOT) == 0)
+ continue;
+
+ if ((mlvl & clvl) == clvl)
+ continue;
+ clvl &= ~mlvl;
+ if ((must->attr.flags & SERV_WARNED) == 0)
+#ifdef OSCBUILD
+ warn("Service %s is missed in the runlevels %s to use service %s\n",
+ must->name, lvl2str(clvl), cur->name);
+#else
+ warn("FATAL: service %s is missed in the runlevels %s to use service %s\n",
+ must->name, lvl2str(clvl), cur->name);
+ waserr = true;
+#endif
+ must->attr.flags |= SERV_WARNED;
+ }
+ }
+ }
+ }
+
+ if (waserr)
+ error("exiting now!\n");
+
+ /*
* Sorry but we support only [KS][0-9][0-9]<name>
*/
if (maxstart > MAX_DEEP || maxstop > MAX_DEEP)
error("Maximum of %u in ordering reached\n", MAX_DEEP);
+
+ if (showall)
+ show_all();
#if defined(DEBUG) && (DEBUG > 0)
printf("Maxorder %d/%d\n", maxstart, maxstop);
@@ -3435,12 +3964,15 @@
script = (char*)0;
while ((serv = listscripts(&script, 'X', lvl))) {
- const boolean this = chkfor(script, argv, argc);
+ boolean this = chkfor(script, argv, argc);
boolean found, slink;
char * clink;
if (*script == '$') /* Do not link in virtual dependencies */
continue;
+
+ if ((serv->attr.flags & (SERV_ENFORCE|SERV_ENABLED)) == SERV_ENFORCE)
+ this = true;
slink = false;
if ((serv->start->lvl & lvl) == 0)
@@ -3616,13 +4148,16 @@
script = (char*)0;
while ((serv = listscripts(&script, 'X', seek))) {
- const boolean this = chkfor(script, argv, argc);
+ boolean this = chkfor(script, argv, argc);
boolean found;
char * clink;
char mode;
if (*script == '$') /* Do not link in virtual dependencies */
continue;
+
+ if ((serv->attr.flags & (SERV_ENFORCE|SERV_ENABLED)) == SERV_ENFORCE)
+ this = true;
sprintf(olink, "../init.d/%s", script);
if (serv->stopp->lvl & lvl) {
Modified: trunk/src/insserv/listing.c
URL: http://svn.debian.org/wsvn/initscripts-ng/trunk/src/insserv/listing.c?rev=1088&op=diff
==============================================================================
--- trunk/src/insserv/listing.c (original)
+++ trunk/src/insserv/listing.c Sat Feb 8 21:29:44 2014
@@ -86,6 +86,7 @@
#define DIR_LOOP 0x0002
#define DIR_LOOPREPORT 0x0004
#define DIR_MAXDEEP 0x0008
+#define DIR_SYSTEMD 0x0010
/*
* The linked list off all services, note that the d_list
@@ -534,19 +535,16 @@
* Sort linked list of provides into start or stop order
* during this set new start or stop order of the serives.
*/
-#undef SORT_REQUESTS
+#define getdep(req) ((dir_t*)(req)->serv->dir)
void lsort(const char type)
{
list_t sort = { &sort, &sort };
-#ifdef SORT_REQUESTS
- list_t * this;
-#endif /* SORT_REQUESTS */
+ list_t * ptr, * safe, * this;
int order;
switch (type) {
case 'K':
for (order = 0; order <= maxstop; order++) {
- list_t * ptr, * safe;
list_for_each_safe(ptr, safe, d_start) {
dir_t * dir = getdir(ptr);
if (dir->stopp.deep == order)
@@ -554,28 +552,54 @@
}
}
join(&sort, d_start);
-#ifdef SORT_REQUESTS
list_for_each(this, s_start) {
service_t * serv = getservice(this);
if (serv->attr.flags & SERV_DUPLET)
continue;
initial(&sort);
- for (order = 0; order <= maxstop; order++) {
- list_t * ptr, * safe;
+ for (order = maxstop; order >= 0; order--) {
list_for_each_safe(ptr, safe, &serv->sort.rev) {
req_t * rev = getreq(ptr);
- dir_t * dir = (dir_t*)rev->serv->dir;
- if (dir->stopp.deep == order)
- move_tail(ptr, &sort);
+ dir_t * dir = getdep(rev);
+ if (dir->stopp.deep == order) {
+ service_t *const orig = getorig(rev->serv);
+ list_t * chk;
+ boolean found = false;
+
+ list_for_each_prev(chk, &sort) { /* check if service was already resorted */
+ req_t * this = getreq(chk);
+ if (getdep(this)->stopp.deep != order)
+ break; /* added on tail always with same order */
+ if (getdep(this) == orig->dir) {
+ found = true;
+ }
+ }
+
+ if (!found) {
+ if (rev->serv != orig) { /* replace alias with its original */
+ req_t *restrict this;
+ if (posix_memalign((void*)&this, sizeof(void*), alignof(req_t)) != 0)
+ error("%s", strerror(errno));
+ memset(this, 0, alignof(req_t));
+ this->flags = rev->flags;
+ this->serv = orig;
+ replace(ptr, &this->list);
+ ptr = &this->list;
+ free(rev);
+ }
+ move_tail(ptr, &sort);
+ } else { /* already included */
+ delete(ptr);
+ free(rev);
+ }
+ }
}
}
join(&sort, &serv->sort.rev);
}
-#endif /* SORT_REQUESTS */
break;
default:
for (order = 0; order <= maxstart; order++) {
- list_t * ptr, * safe;
list_for_each_safe(ptr, safe, d_start) {
dir_t * dir = getdir(ptr);
if (dir->start.deep == order)
@@ -583,28 +607,54 @@
}
}
join(&sort, d_start);
-#ifdef SORT_REQUESTS
list_for_each(this, s_start) {
service_t * serv = getservice(this);
if (serv->attr.flags & SERV_DUPLET)
continue;
initial(&sort);
- for (order = 0; order <= maxstart; order++) {
- list_t * ptr, * safe;
+ for (order = maxstart; order >= 0; order--) {
list_for_each_safe(ptr, safe, &serv->sort.req) {
req_t * req = getreq(ptr);
- dir_t * dir = (dir_t*)req->serv->dir;
- if (dir->start.deep == order)
- move_tail(ptr, &sort);
+ dir_t * dir = getdep(req);
+ if (dir->start.deep == order) {
+ service_t * orig = getorig(req->serv);
+ list_t * chk;
+ boolean found = false;
+
+ list_for_each_prev(chk, &sort) { /* check if service was already resorted */
+ req_t * this = getreq(chk);
+ if (getdep(this)->start.deep != order)
+ break; /* added on tail always with same order */
+ if (getdep(this) == orig->dir) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ if (req->serv != orig) { /* replace alias with its original */
+ req_t *restrict this;
+ if (posix_memalign((void*)&this, sizeof(void*), alignof(req_t)) != 0)
+ error("%s", strerror(errno));
+ memset(this, 0, alignof(req_t));
+ this->flags = req->flags;
+ this->serv = orig;
+ replace(ptr, &this->list);
+ ptr = &this->list;
+ free(req);
+ }
+ move_tail(ptr, &sort);
+ } else { /* already included */
+ delete(ptr);
+ free(req);
+ }
+ }
}
}
join(&sort, &serv->sort.req);
}
-#endif /* SORT_REQUESTS */
break;
}
-
-
}
/*
@@ -889,56 +939,80 @@
/*
* For debuging: show all services
*/
-#if defined(DEBUG) && (DEBUG > 0)
void show_all()
{
list_t *tmp;
if (maxstop > 0) list_for_each(tmp, d_start) {
- char * script, *name, *lvlstr;
+ char * script, *lvlstr;
+#if defined(DEBUG) && (DEBUG > 0)
+ char *name;
+#endif
dir_t * dir = getdir(tmp);
handle_t * peg;
uchar deep;
ushort lvl;
if (!dir)
continue;
+#if defined(DEBUG) && (DEBUG > 0)
name = dir->name;
+#endif
peg = &dir->stopp;
lvl = peg->run.lvl;
+ lvlstr = lvl2str(lvl);
deep = peg->deep;
if (attof(dir)->script)
script = attof(dir)->script;
+#if defined(DEBUG) && (DEBUG > 0)
else if (*name == '$')
script = "%system";
else
script = "%guessed";
- lvlstr = lvl2str(lvl);
- info("K%.2d %s 0x%.2x '%s' (%s)\n", deep, name, lvl, lvlstr, script);
+ info(1, "K%.2d %s 0x%.2x '%s' (%s)\n", deep, name, lvl, lvlstr,
+ script);
+#else
+ else
+ script = NULL;
+ if (script && lvlstr)
+ fprintf(stdout, "K:%.2d:%s:%s\n", deep, lvlstr, script);
+#endif
xreset(lvlstr);
}
if (maxstart > 0) list_for_each(tmp, d_start) {
- char * script, *name, *lvlstr;
+ char * script, *lvlstr;
+#if defined(DEBUG) && (DEBUG > 0)
+ char *name;
+#endif
dir_t * dir = getdir(tmp);
handle_t * peg;
uchar deep;
ushort lvl;
if (!dir)
continue;
+#if defined(DEBUG) && (DEBUG > 0)
name = dir->name;
+#endif
peg = &dir->start;
lvl = peg->run.lvl;
+ lvlstr = lvl2str(lvl);
deep = peg->deep;
if (attof(dir)->script)
script = attof(dir)->script;
+#if defined(DEBUG) && (DEBUG > 0)
else if (*name == '$')
script = "%system";
else
script = "%guessed";
- lvlstr = lvl2str(lvl);
- info("S%.2d %s 0x%.2x '%s' (%s)\n", deep, name, lvl, lvlstr, script);
+ info(1, "S%.2d %s 0x%.2x '%s' (%s)\n", deep, name, lvl, lvlstr,
+ script);
+#else
+ else
+ script = NULL;
+ if (script && lvlstr)
+ fprintf(stdout, "S:%.2d:%s:%s\n", deep, lvlstr, script);
+#endif
xreset(lvlstr);
}
}
-#endif
/*
* Used within loops to get scripts not included in this runlevel
@@ -989,8 +1063,8 @@
prefetch(tmp->next);
dir = getdir(tmp);
- attof(dir)->korder = dir->stopp.deep;
- attof(dir)->sorder = dir->start.deep;
+ attof(dir)->korder = dir->stopp.deep;
+ attof(dir)->sorder = dir->start.deep;
serv = dir->serv;
*script = serv->attr.script;
@@ -1020,6 +1094,20 @@
void requires(service_t *restrict this, service_t *restrict dep, const char mode)
{
ln_sf((dir_t*)this->dir, (dir_t*)dep->dir, mode);
+ if (this->attr.flags & SERV_SYSTEMD) {
+ dir_t *dir = (dir_t*)this->dir;
+ handle_t *peg = &dir->stopp;
+ peg->flags |= DIR_SYSTEMD;
+ peg = &dir->start;
+ peg->flags |= DIR_SYSTEMD;
+ }
+ if (dep->attr.flags & SERV_SYSTEMD) {
+ dir_t *dir = (dir_t*)dep->dir;
+ handle_t *peg = &dir->stopp;
+ peg->flags |= DIR_SYSTEMD;
+ peg = &dir->start;
+ peg->flags |= DIR_SYSTEMD;
+ }
}
/*
@@ -1027,7 +1115,7 @@
*/
void runlevels(service_t *restrict serv, const char mode, const char *restrict lvl)
{
- dir_t * dir = (dir_t *)serv->dir;
+ dir_t *dir = (dir_t *)serv->dir;
handle_t * peg = (mode == 'K') ? &dir->stopp : &dir->start;
peg->run.lvl |= str2lvl(lvl);
}
Modified: trunk/src/insserv/listing.h
URL: http://svn.debian.org/wsvn/initscripts-ng/trunk/src/insserv/listing.h?rev=1088&op=diff
==============================================================================
--- trunk/src/insserv/listing.h (original)
+++ trunk/src/insserv/listing.h Sat Feb 8 21:29:44 2014
@@ -54,6 +54,9 @@
#ifndef attribute
# define attribute(attr) __attribute__(attr)
#endif
+#ifndef offsetof
+# define offsetof(type,memb) __builtin_offsetof(type,memb)
+#endif
/*
* This is lent from the kernel by e.g. using
@@ -64,8 +67,7 @@
*
* on the appropiate architecture (here on i686 for i586).
*/
-static inline void prefetch(const void *restrict x) attribute((used,always_inline));
-static inline void prefetch(const void *restrict x)
+extern inline void attribute((used,__gnu_inline__,always_inline,__artificial__)) prefetch(const void *restrict x)
{
#if defined(__x86_64__)
asm volatile ("prefetcht0 %0" :: "m" (*(unsigned long *)x))
@@ -91,6 +93,8 @@
" \n664:\n"
".previous"
:: "i" ((0*32+25)), "r" (x))
+#else
+ __builtin_prefetch ((x), 0, 1);
#endif
;
}
@@ -158,6 +162,18 @@
initial(entry);
}
+/*
+ * Replace an entry by a new one.
+ */
+static inline void replace(list_t *restrict old, list_t *restrict new) attribute((always_inline,nonnull(1,2)));
+static inline void replace(list_t *restrict old, list_t *restrict new)
+{
+ new->next = old->next;
+ new->next->prev = new;
+ new->prev = old->prev;
+ new->prev->next = new;
+}
+
static inline void join(list_t *restrict list, list_t *restrict head) attribute((always_inline,nonnull(1,2)));
static inline void join(list_t *restrict list, list_t *restrict head)
{
@@ -165,20 +181,38 @@
if (first != list) {
list_t * last = list->prev;
- list_t * at = head->next;
-
- first->prev = head;
- head->next = first;
-
- last->next = at;
- at->prev = last;
+ list_t * at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
}
}
-static inline boolean list_empty(list_t *restrict head) attribute((always_inline,nonnull(1)));
-static inline boolean list_empty(list_t *restrict head)
+static inline boolean list_empty(const list_t *restrict const head) attribute((always_inline,nonnull(1)));
+static inline boolean list_empty(const list_t *restrict const head)
{
return head->next == head;
+}
+
+static inline void move_head(list_t *restrict entry, list_t *restrict head) attribute((always_inline,nonnull(1,2)));
+static inline void move_head(list_t *restrict entry, list_t *restrict head)
+{
+ list_t * prev = entry->prev;
+ list_t * next = entry->next;
+
+ next->prev = prev; /* remove enty from old list */
+ prev->next = next;
+
+ prev = head;
+ next = head->next;
+
+ next->prev = entry; /* and add it at head of new list */
+ entry->next = next;
+ entry->prev = prev;
+ prev->next = entry;
}
static inline void move_tail(list_t *restrict entry, list_t *restrict head) attribute((always_inline,nonnull(1,2)));
@@ -379,6 +413,9 @@
#define SERV_NOSTOP 0x0100
#define SERV_CMDLINE 0x0200
#define SERV_FIRST 0x0400
+#define SERV_ENFORCE 0x0800
+#define SERV_WARNED 0x1000
+#define SERV_SYSTEMD 0x2000
/*
* Bits of the runlevels
Added: trunk/src/insserv/systemd.c
URL: http://svn.debian.org/wsvn/initscripts-ng/trunk/src/insserv/systemd.c?rev=1088&op=file
==============================================================================
--- trunk/src/insserv/systemd.c (added)
+++ trunk/src/insserv/systemd.c Sat Feb 8 21:29:44 2014
@@ -0,0 +1,459 @@
+/*
+ * systemd.c Use dbus API of systemd to import dependencies from.
+ *
+ * Copyright 2012 Werner Fink, 2012 SUSE LINUX Products GmbH, Germany.
+ *
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdio.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include "listing.h"
+#include "systemd.h"
+
+/*
+ * Linked list of services, targets and their allies.
+ */
+list_t sdservs = { &sdservs, &sdservs }, *sdservs_start = &sdservs;
+
+static sdserv_t * addsysd(const char *const name) attribute((malloc,nonnull(1)));
+static sdserv_t * addsysd(const char *const name)
+{
+ sdserv_t *restrict this;
+ const char *dot;
+ boolean target;
+ list_t *ptr;
+ size_t len;
+
+ list_for_each_prev(ptr, sdservs_start) {
+ this = list_entry(ptr, sdserv_t, s_list);
+ if (!strcmp(this->unit, name))
+ goto out;
+ }
+
+ target = false;
+ len = strsize(name);
+ if ((dot = strrchr(name, '.'))) {
+ dot++;
+ if (*dot == 't') {
+ target = true;
+ len++;
+ }
+ }
+ if (posix_memalign((void*)&this, sizeof(void*), alignof(sdserv_t)+len) != 0)
+ error ("addsysd() can not alloc memory for %s: %m\n", name);
+ memset(this, 0, alignof(sdserv_t)+len);
+ insert(&this->s_list, sdservs_start->prev);
+ this->name = ((char*)this)+alignof(sdserv_t);
+ if (target) {
+ *this->name = '$';
+ strcpy(this->name+1, name);
+ this->unit = this->name+1;
+ } else {
+ strcpy(this->name, name);
+ this->unit = this->name;
+ }
+ initial(&this->a_list);
+out:
+ return this;
+}
+
+static void addally(sdserv_t *restrict serv, sdserv_t *restrict ally, const ushort flags)
+{
+ ally_t *restrict this;
+ list_t *ptr, *allies;
+
+ allies = &serv->a_list;
+ list_for_each_prev(ptr, allies) {
+ this = list_entry(ptr, ally_t, a_list);
+ if (this->serv == ally) {
+ this->flags |= flags;
+ if (this->flags & SDREL_WANTS) {
+ if (this->flags & (SDREL_REQUIRES|SDREL_REQUISITE))
+ warn("bogus systemd dependcy: %s %s\n", serv->unit, this->serv->unit);
+ }
+ return;
+ }
+ }
+ if (posix_memalign((void*)&this, sizeof(void*), alignof(ally_t)) != 0)
+ error ("addally() can not alloc memory for %s: %m\n", ally->unit);
+ memset(this, 0, alignof(ally_t));
+ insert(&this->a_list, allies->prev);
+ this->serv = ally;
+ this->flags = flags;
+}
+
+static void systemd_strip_dot(void)
+{
+ list_t *ptr;
+
+ list_for_each_prev(ptr, &sdservs) {
+ sdserv_t *sdserv = list_entry(ptr, sdserv_t, s_list);
+ char *dot = strrchr(sdserv->unit, '.');
+ const char *tag;
+ if (dot == (char*)0 || *dot == '\0')
+ continue;
+ tag = dot+1;
+ if (strcmp(tag, "target") == 0 || strcmp(tag, "service") == 0)
+ *dot = '\0';
+ else
+ *dot = '_';
+ }
+}
+
+static int iter_get_and_next(DBusMessageIter *iter, int type, void *data)
+{
+ if (dbus_message_iter_get_arg_type(iter) != type)
+ goto err;
+ dbus_message_iter_get_basic(iter, data);
+ if (!dbus_message_iter_next(iter))
+ goto err;
+ return 1;
+err:
+ return 0;
+}
+
+typedef struct {
+ const char *const tag;
+ ushort flag;
+} relation_t;
+
+static int handle_one_property(sdserv_t *one, const char *prop, DBusMessageIter *iter)
+{
+ static relation_t relations[] = {
+ { "Requires", SDREL_REQUIRES },
+ { "RequiresOverridable", SDREL_REQUIRES },
+ { "Requisite", SDREL_REQUISITE },
+ { "RequisiteOverridable", SDREL_REQUISITE },
+ { "Wants", SDREL_WANTS },
+ { "Conflicts", SDREL_CONFLICTS },
+ { "Before", SDREL_BEFORE },
+ { "After", SDREL_AFTER },
+ { (const char*)0, 0 }
+ };
+ const relation_t *relation = (relation_t*)0;
+ int i;
+
+ for (i = 0; relations[i].tag; i++) {
+ if (strcmp(relations[i].tag, prop) == 0) {
+ relation = &relations[i];
+ break;
+ }
+ }
+
+ if (!relation)
+ return 1;
+
+ switch (dbus_message_iter_get_arg_type(iter)) {
+ case DBUS_TYPE_ARRAY:
+ if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
+ DBusMessageIter isub;
+
+ dbus_message_iter_recurse(iter, &isub);
+
+ do {
+ const char *ally;
+ const char *dot;
+ int type;
+
+ type = dbus_message_iter_get_arg_type(&isub);
+ if (type == DBUS_TYPE_INVALID)
+ break;
+ if (type != DBUS_TYPE_STRING)
+ goto failed;
+ dbus_message_iter_get_basic(&isub, &ally);
+
+ // Here we go to parse the dependcies
+ // targets are somehow like `$'
+ // services are somehow scripts
+ // Wants -> Optional
+ // Requires/Requisite -> Requires
+ // After -> ??
+
+ if ((dot = strrchr(ally, '.'))) {
+ dot++;
+ if (strcmp(dot, "target") == 0 || strcmp(dot, "service") == 0) {
+ sdserv_t * serv;
+#if 0
+ printf("\tdependcy (%s)\t: \"%s\" -> \"%s\"\n", relation->tag, one->unit, ally);
+#endif
+ serv = addsysd(ally);
+ addally(one, serv, relation->flag);
+ }
+ }
+
+ dbus_message_iter_next(&isub);
+
+ } while (TRUE);
+ }
+ }
+ return 1;
+failed:
+ warn ("failed to parse reply from systemd\n");
+ return 0;
+}
+
+static int handle_one_id(DBusConnection *bus, sdserv_t * serv, const char *path)
+{
+ DBusError error;
+ const char *device = "org.freedesktop.systemd1.Unit";
+ DBusMessage *reply, *send;
+ DBusMessageIter iter, isub;
+ int ret = 0;
+
+ dbus_error_init(&error);
+ send = dbus_message_new_method_call("org.freedesktop.systemd1",
+ path,
+ "org.freedesktop.DBus.Properties",
+ "GetAll");
+ if (!send)
+ goto err;
+ dbus_message_set_auto_start(send, TRUE);
+ if (!dbus_message_set_destination(send, "org.freedesktop.systemd1"))
+ goto err;
+
+ dbus_message_iter_init_append(send, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &device);
+
+ reply = dbus_connection_send_with_reply_and_block(bus, send, -1, &error);
+ dbus_message_unref(send);
+
+ if (dbus_error_is_set(&error)) {
+ warn ("can not connect system dbus: %s\n", error.message);
+ dbus_error_free(&error);
+ goto err;
+ }
+ if (!reply)
+ goto err;
+ if (dbus_message_get_type(reply) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
+ goto unref;
+
+ if (!dbus_message_iter_init(reply, &iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY)
+ goto failed;
+ dbus_message_iter_recurse(&iter, &isub);
+
+ do {
+ DBusMessageIter iisub, iiisub;
+ const char *prop;
+ int type;
+
+ type = dbus_message_iter_get_arg_type(&isub);
+ if (type == DBUS_TYPE_INVALID)
+ break;
+ if (type != DBUS_TYPE_DICT_ENTRY)
+ goto failed;
+
+ dbus_message_iter_recurse(&isub, &iisub);
+ if (!iter_get_and_next(&iisub, DBUS_TYPE_STRING, &prop))
+ goto failed;
+ if (dbus_message_iter_get_arg_type(&iisub) != DBUS_TYPE_VARIANT)
+ goto failed;
+
+ dbus_message_iter_recurse(&iisub, &iiisub);
+
+ handle_one_property(serv, prop, &iiisub);
+
+ dbus_message_iter_next(&isub);
+
+ } while (TRUE);
+
+ ret = 1;
+ goto unref;
+failed:
+ warn ("failed to parse reply from systemd\n");
+unref:
+ dbus_message_unref(reply);
+err:
+ return ret;
+}
+
+int systemd_get_tree(DBusConnection *bus)
+{
+ DBusError error;
+ DBusMessage *reply, *send;
+ DBusMessageIter iter, isub;
+ int ret = 0;
+
+ dbus_error_init(&error);
+ send = dbus_message_new_method_call("org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "ListUnits");
+ if (!send)
+ goto err;
+ dbus_message_set_auto_start(send, TRUE);
+ if (!dbus_message_set_destination(send, "org.freedesktop.systemd1"))
+ goto err;
+
+ reply = dbus_connection_send_with_reply_and_block(bus, send, -1, &error);
+ dbus_message_unref(send);
+
+ if (dbus_error_is_set(&error)) {
+ warn ("can not connect system dbus: %s\n", error.message);
+ dbus_error_free(&error);
+ goto err;
+ }
+ if (!reply)
+ goto err;
+ if (dbus_message_get_type(reply) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
+ goto unref;
+
+ if (!dbus_message_iter_init(reply, &iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT)
+ goto failed;
+ dbus_message_iter_recurse(&iter, &isub);
+
+ do {
+ const char *id, *description, *load_state, *active_state,
+ *sub_state, *following, *unit_path;
+ DBusMessageIter iisub;
+ const char *dot;
+ int type;
+
+ type = dbus_message_iter_get_arg_type(&isub);
+ if (type == DBUS_TYPE_INVALID)
+ break;
+ if (type != DBUS_TYPE_STRUCT)
+ goto failed;
+ dbus_message_iter_recurse(&isub, &iisub);
+
+ if (!iter_get_and_next(&iisub, DBUS_TYPE_STRING, &id) ||
+ !iter_get_and_next(&iisub, DBUS_TYPE_STRING, &description) ||
+ !iter_get_and_next(&iisub, DBUS_TYPE_STRING, &load_state) ||
+ !iter_get_and_next(&iisub, DBUS_TYPE_STRING, &active_state) ||
+ !iter_get_and_next(&iisub, DBUS_TYPE_STRING, &sub_state) ||
+ !iter_get_and_next(&iisub, DBUS_TYPE_STRING, &following) ||
+ !iter_get_and_next(&iisub, DBUS_TYPE_OBJECT_PATH, &unit_path))
+ goto failed;
+
+#if 0
+uint job_id;
+const char *sjob_type;
+const char *j_path;
+
+ iter_get_and_next(&iisub, DBUS_TYPE_UINT32, &job_id);
+ iter_get_and_next(&iisub, DBUS_TYPE_STRING, &sjob_type);
+ iter_get_and_next(&iisub, DBUS_TYPE_OBJECT_PATH, &j_path);
+
+printf("id=%s ls=%s as=%s subs=%s fl=%s %s ID=%u jt=%s jp=%s\n",
+ id, load_state, active_state, sub_state, following, unit_path,
+ job_id, sjob_type, j_path);
+#endif
+ if ((dot = strrchr(id, '.'))) {
+ dot++;
+ if (strcmp(dot, "target") == 0 || strcmp(dot, "service") == 0) {
+ sdserv_t * serv;
+ serv = addsysd(id);
+ handle_one_id(bus, serv, unit_path);
+ }
+ }
+
+ dbus_message_iter_next(&isub);
+
+ } while (TRUE);
+
+ systemd_strip_dot();
+
+ ret = 1;
+ goto unref;
+failed:
+ warn ("failed to parse reply from systemd\n");
+unref:
+ dbus_message_unref(reply);
+err:
+ return ret;
+}
+
+DBusConnection * systemd_open_conn(void)
+{
+ DBusConnection *bus;
+ DBusError error;
+ struct ucred cred;
+ socklen_t len;
+ int oerrno;
+ int DBfd;
+
+ dbus_error_init(&error);
+ if (geteuid() == 0) /* for root use unix socket for speed */
+ bus = dbus_connection_open_private("unix:path=/run/systemd/private", &error);
+ else
+ bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
+
+ if (!bus) {
+ warn ("can not connect systemd: %s\n", error.message);
+ goto err;
+ }
+ dbus_connection_set_exit_on_disconnect(bus, FALSE);
+
+ if (!dbus_connection_get_unix_fd(bus, &DBfd))
+ goto perm;
+ len = sizeof(cred);
+ if (getsockopt(DBfd, SOL_SOCKET, SO_PEERCRED, &cred, &len) < 0)
+ goto perm;
+ oerrno = errno;
+ errno = E2BIG;
+ if (len != sizeof(cred))
+ goto perm;
+ errno = EPERM;
+ if (cred.uid != 0 && cred.uid != geteuid())
+ goto perm;
+ errno = oerrno;
+ return bus;
+perm:
+ warn ("can not connect to systemd: %m\n");
+err:
+ dbus_connection_close(bus);
+ dbus_connection_unref(bus);
+ if (dbus_error_is_set(&error))
+ dbus_error_free(&error);
+ return (DBusConnection*)0;
+}
+
+void systemd_close_conn(DBusConnection *bus)
+{
+ if (bus) {
+ dbus_connection_flush(bus);
+ dbus_connection_close(bus);
+ dbus_connection_unref(bus);
+ }
+}
+
+void systemd_free(void)
+{
+ list_t *ptr, *safe;
+ list_for_each_safe(ptr, safe, sdservs_start) {
+ sdserv_t *serv = list_entry(ptr, sdserv_t, s_list);
+ list_t *aptr, *asafe;
+ list_for_each_safe(aptr, asafe, &serv->a_list) {
+ ally_t *ally = list_entry(aptr, ally_t, a_list);
+ delete(aptr);
+ free(ally);
+ }
+ delete(ptr);
+ free(serv);
+ }
+}
Added: trunk/src/insserv/systemd.h
URL: http://svn.debian.org/wsvn/initscripts-ng/trunk/src/insserv/systemd.h?rev=1088&op=file
==============================================================================
--- trunk/src/insserv/systemd.h (added)
+++ trunk/src/insserv/systemd.h Sat Feb 8 21:29:44 2014
@@ -0,0 +1,54 @@
+/*
+ * systemd.h
+ *
+ * Copyright 2012 Werner Fink, 2012 SuSE Linux Products GmbH Nuernberg, Germany
+ *
+ * This source 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <dbus/dbus.h>
+extern int systemd_get_tree(DBusConnection *bus);
+extern DBusConnection * systemd_open_conn(void);
+extern void systemd_close_conn(DBusConnection *bus);
+extern void systemd_free(void);
+
+/*
+ * Linked lists of services, targets and their allies.
+ */
+
+typedef struct sdserv __align sdserv_t;
+typedef struct {
+ list_t a_list;
+ ushort flags;
+ sdserv_t *serv;
+} __align ally_t;
+
+struct sdserv {
+ list_t s_list;
+ list_t a_list;
+ char *unit;
+ char *name;
+};
+
+extern list_t sdservs;
+
+#define SDREL_REQUIRES (1<<0) /* Requires/RequiresOverridable */
+#define SDREL_REQUISITE (1<<1) /* Requisite/RequisiteOverridable */
+#define SDREL_WANTS (1<<2) /* Wants */
+#define SDREL_CONFLICTS (1<<3) /* Conflicts */
+#define SDREL_BEFORE (1<<4) /* Before */
+#define SDREL_AFTER (1<<5) /* After */
+
More information about the Initscripts-ng-commits
mailing list