aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sh/gendepends.sh.in180
-rw-r--r--src/librc/librc-depend.c66
2 files changed, 155 insertions, 91 deletions
diff --git a/sh/gendepends.sh.in b/sh/gendepends.sh.in
index 8ce1c87f..85fb48c1 100644
--- a/sh/gendepends.sh.in
+++ b/sh/gendepends.sh.in
@@ -53,88 +53,112 @@ depend() {
:
}
-_dirs="
- @SYSCONFDIR@/init.d
- @PKG_PREFIX@/etc/init.d
- @LOCAL_PREFIX@/etc/init.d
-"
+gendepend() {
+ RC_SERVICE="$1"
+ [ -x "$RC_SERVICE" -a -f "$RC_SERVICE" ] || continue
+
+ # Only generate dependencies for OpenRC scripts
+ read one two three <"$RC_SERVICE"
+ case "$one" in
+ \#*/openrc-run) ;;
+ \#*/runscript) ;;
+ \#!)
+ case "$two" in
+ */openrc-run) ;;
+ */runscript) ;;
+ *)
+ continue
+ ;;
+ esac
+ ;;
+ *)
+ continue
+ ;;
+ esac
+ unset one two three
+
+ RC_SVCNAME=${RC_SERVICE##*/}; export RC_SVCNAME
+
+ # Compat
+ SVCNAME=$RC_SVCNAME; export SVCNAME
+
+ (
+ # Save stdout in fd3, then remap it to stderr
+ exec 3>&1 1>&2
+
+ _rc_c=${RC_SVCNAME%%.*}
+ _conf_d="${RC_SYSCONF_DIR}/conf.d"
+ if [ -n "$_rc_c" -a "$_rc_c" != "$RC_SVCNAME" ]; then
+ if [ -e "$_conf_d/$_rc_c" ]; then
+ . "$_conf_d/$_rc_c"
+ fi
+ fi
+ unset _rc_c
+
+ if [ -e "$_conf_d/$RC_SVCNAME" ]; then
+ . "$_conf_d/$RC_SVCNAME"
+ fi
+
+ [ -e @SYSCONFDIR@/rc.conf ] && . @SYSCONFDIR@/rc.conf
+ if [ -d "@SYSCONFDIR@/rc.conf.d" ]; then
+ for _f in "@SYSCONFDIR@"/rc.conf.d/*.conf; do
+ [ -e "$_f" ] && . "$_f"
+ done
+ fi
+
+ if . "$RC_SERVICE"; then
+ echo "$RC_SVCNAME" >&3
+ _depend
+ fi
+ )
+}
-if yesno "$RC_USER_SERVICES"; then
+do_all() {
_dirs="
- @SYSCONFDIR@/user.d/init.d
- ${XDG_CONFIG_HOME:-${HOME}/.config}/openrc/init.d
+ @SYSCONFDIR@/init.d
+ @PKG_PREFIX@/etc/init.d
+ @LOCAL_PREFIX@/etc/init.d
"
-fi
-_done_dirs=
-for _dir in ${_dirs}
-do
- [ -d "$_dir" ] || continue
-
- # Don't do the same dir twice
- for _d in $_done_dirs; do
- [ "$_d" = "$_dir" ] && continue 2
+ if yesno "$RC_USER_SERVICES"; then
+ _dirs="
+ @SYSCONFDIR@/user.d/init.d
+ ${XDG_CONFIG_HOME:-${HOME}/.config}/openrc/init.d
+ "
+ fi
+
+ _done_dirs=
+ for _dir in ${_dirs}
+ do
+ [ -d "$_dir" ] || continue
+
+ # Don't do the same dir twice
+ for _d in $_done_dirs; do
+ [ "$_d" = "$_dir" ] && continue 2
+ done
+ unset _d
+ _done_dirs="$_done_dirs $_dir"
+
+ cd "$_dir"
+ RC_SYSCONF_DIR="$_dir"
+ for _service in *; do
+ gendepend "$_dir/$_service"
+ done
done
- unset _d
- _done_dirs="$_done_dirs $_dir"
-
- cd "$_dir"
- for RC_SERVICE in *; do
- [ -x "$RC_SERVICE" -a -f "$RC_SERVICE" ] || continue
-
- # Only generate dependencies for OpenRC scripts
- read one two three <"$RC_SERVICE"
- case "$one" in
- \#*/openrc-run) ;;
- \#*/runscript) ;;
- \#!)
- case "$two" in
- */openrc-run) ;;
- */runscript) ;;
- *)
- continue
- ;;
- esac
- ;;
- *)
- continue
- ;;
- esac
- unset one two three
-
- RC_SVCNAME=${RC_SERVICE##*/} ; export RC_SVCNAME
-
- # Compat
- SVCNAME=$RC_SVCNAME ; export SVCNAME
-
- (
- # Save stdout in fd3, then remap it to stderr
- exec 3>&1 1>&2
-
- _rc_c=${RC_SVCNAME%%.*}
- if [ -n "$_rc_c" -a "$_rc_c" != "$RC_SVCNAME" ]; then
- if [ -e "$_dir/../conf.d/$_rc_c" ]; then
- . "$_dir/../conf.d/$_rc_c"
- fi
- fi
- unset _rc_c
-
- if [ -e "$_dir/../conf.d/$RC_SVCNAME" ]; then
- . "$_dir/../conf.d/$RC_SVCNAME"
- fi
-
- [ -e @SYSCONFDIR@/rc.conf ] && . @SYSCONFDIR@/rc.conf
- if [ -d "@SYSCONFDIR@/rc.conf.d" ]; then
- for _f in "@SYSCONFDIR@"/rc.conf.d/*.conf; do
- [ -e "$_f" ] && . "$_f"
- done
- fi
+ unset _dirs
+}
- if . "$_dir/$RC_SVCNAME"; then
- echo "$RC_SVCNAME" >&3
- _depend
- fi
- )
+do_svcs() {
+ for _service in $@; do
+ RC_SYSCONF_DIR="$(dirname $(realpath "$_service"))/.."
+ [ -d "${RC_SYSCONF_DIR}" ] || return 1
+ cd "${RC_SYSCONF_DIR}" || return 1
+ gendepend "$_service"
done
-done
-unset _dirs
+}
+
+if [ $# -gt 0 ]; then
+ do_svcs $@
+else
+ do_all
+fi
diff --git a/src/librc/librc-depend.c b/src/librc/librc-depend.c
index cb38f190..4f72f2df 100644
--- a/src/librc/librc-depend.c
+++ b/src/librc/librc-depend.c
@@ -833,7 +833,7 @@ filter_sys(RC_DEPTREE *deptree, const char *sys)
}
static bool
-deptree_generate(RC_DEPTREE *deptree, RC_STRINGLIST **config)
+deptree_generate(const char *target, RC_DEPTREE *deptree, RC_STRINGLIST **config)
{
FILE *fp;
RC_DEPTREE *providers;
@@ -854,10 +854,21 @@ deptree_generate(RC_DEPTREE *deptree, RC_STRINGLIST **config)
if (uname(&uts) == 0)
setenv("RC_UNAME", uts.sysname, 1);
/* Phase 1 - source all init scripts and print dependencies */
- if (!(fp = popen(GENDEP, "r")))
+
+ if (target) {
+ char *cmd;
+ xasprintf(&cmd, GENDEP " %s", target);
+ fp = popen(cmd, "r");
+ free(cmd);
+ } else {
+ fp = popen(GENDEP, "r");
+ }
+
+ if (!fp)
return false;
- *config = rc_stringlist_new();
+ if (config)
+ *config = rc_stringlist_new();
while ((size = getline(&line, &len, fp)) != -1) {
line[size - 1] = '\0';
@@ -895,7 +906,8 @@ deptree_generate(RC_DEPTREE *deptree, RC_STRINGLIST **config)
continue;
if (strcmp(type, "config") == 0) {
- rc_stringlist_addu(*config, depend);
+ if (config)
+ rc_stringlist_addu(*config, depend);
continue;
}
@@ -928,9 +940,9 @@ deptree_generate(RC_DEPTREE *deptree, RC_STRINGLIST **config)
}
/* If we're after something, remove us from the before list */
if (strcmp(type, "iafter") == 0 ||
- strcmp(type, "ineed") == 0 ||
- strcmp(type, "iwant") == 0 ||
- strcmp(type, "iuse") == 0) {
+ strcmp(type, "ineed") == 0 ||
+ strcmp(type, "iwant") == 0 ||
+ strcmp(type, "iuse") == 0) {
if ((dt = get_deptype(depinfo, "ibefore")))
rc_stringlist_delete(dt->services, depend);
}
@@ -964,15 +976,42 @@ deptree_generate(RC_DEPTREE *deptree, RC_STRINGLIST **config)
return true;
}
+static RC_DEPINFO *
+make_dylink_depinfo(RC_DEPTREE *deptree, const char *service)
+{
+ RC_DEPINFO *di = NULL;
+ char *target_file = NULL;
+ char *base = rc_service_base(service);
+ if (!base)
+ return NULL;
+ target_file = rc_service_dylink(base, service);
+ if (!target_file)
+ goto out;
+ /* TODO: integrate configuration checking for dynamic services */
+ if (!deptree_generate(target_file, deptree, NULL))
+ goto out;
+
+ di = get_depinfo(deptree, service);
+
+out:
+ free(base);
+ free(target_file);
+ return di;
+}
+
/* This is a 7 phase operation
Phase 1 is a shell script which loads each init script and config in turn
- and echos their dependency info to stdout
- Phase 2 takes that and populates a depinfo object with that data
+ and echos their dependency info to stdout and populates a depinfo object
+ with that data
+ Phase 2 filters services for system compatibility (i.e. keyword -container)
Phase 3 adds any provided services to the depinfo object
- Phase 4 scans that depinfo object and puts in backlinks
+
+ Phase 4 scans that depinfo object and puts in backlinks, and dynamically
+ links services on the <base>.<service> format that are missing.
Phase 5 removes broken before dependencies
Phase 6 looks for duplicate services indicating a real and virtual service
with the same names
+
Phase 7 saves the depinfo object to disk
*/
bool
@@ -992,12 +1031,13 @@ rc_deptree_update(void)
deptree = xmalloc(sizeof(*deptree));
TAILQ_INIT(deptree);
- if (!deptree_generate(deptree, &config)) {
+ /* Phases 1..3 - generate intial deptree */
+ if (!deptree_generate(NULL, deptree, &config)) {
free(deptree);
return false;
}
- /* Phase 4 - backreference our depends */
+ /* Phase 4 - backreference our depends and dylink services */
TAILQ_FOREACH(depinfo, deptree, entries) {
for (size_t i = 0; deppairs[i].depend; i++) {
deptype = get_deptype(depinfo, deppairs[i].depend);
@@ -1005,7 +1045,7 @@ rc_deptree_update(void)
continue;
TAILQ_FOREACH(s, deptype->services, entries) {
di = get_depinfo(deptree, s->value);
- if (!di) {
+ if (!di && !(di = make_dylink_depinfo(deptree, s->value))) {
if (strcmp(deptype->type, "ineed") == 0) {
fprintf(stderr, "Service '%s' needs non existent service '%s'\n",
depinfo->service, s->value);