summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2007-12-14 12:24:16 +0000
committerRoy Marples <roy@marples.name>2007-12-14 12:24:16 +0000
commita3db3bac6242ff29871161620d0449125b3262aa (patch)
treea4b6d7f9cefb59dd5955a88a474d1484d82c2fb6
parentb73bd04cf3f19b47480c85dd58e63eef5900fa3c (diff)
downloadopenrc-a3db3bac6242ff29871161620d0449125b3262aa.tar.gz
openrc-a3db3bac6242ff29871161620d0449125b3262aa.tar.bz2
openrc-a3db3bac6242ff29871161620d0449125b3262aa.tar.xz
Allow services to be in /usr/local/etc/init.d, but disallow them being added to the boot runlevel.
-rwxr-xr-xsh/gendepends.sh63
-rw-r--r--src/librc-depend.c2
-rw-r--r--src/librc.c51
-rw-r--r--src/rc-misc.h3
-rw-r--r--src/rc-status.c2
-rw-r--r--src/rc-update.c37
6 files changed, 99 insertions, 59 deletions
diff --git a/sh/gendepends.sh b/sh/gendepends.sh
index 4fb2c8e..f6c6edb 100755
--- a/sh/gendepends.sh
+++ b/sh/gendepends.sh
@@ -53,42 +53,45 @@ depend() {
:
}
-cd /etc/init.d
-for SVCNAME in *; do
- [ -x "${SVCNAME}" ] || continue
+for _dir in /etc/init.d /usr/local/etc/init.d; do
+ [ -d "${_dir}" ] || continue
+ cd "${_dir}"
+ for SVCNAME in *; do
+ [ -x "${SVCNAME}" ] || continue
- # Only generate dependencies for runscripts
- read one two < "${SVCNAME}"
- [ "${one}" = "#!/sbin/runscript" ] || continue
- unset one two
+ # Only generate dependencies for runscripts
+ read one two < "${SVCNAME}"
+ [ "${one}" = "#!/sbin/runscript" ] || continue
+ unset one two
- SVCNAME=${SVCNAME##*/}
- (
- # Save stdout in fd3, then remap it to stderr
- exec 3>&1 1>&2
+ SVCNAME=${SVCNAME##*/}
+ (
+ # Save stdout in fd3, then remap it to stderr
+ exec 3>&1 1>&2
- rc_c=${SVCNAME%%.*}
- if [ -n "${rc_c}" -a "${rc_c}" != "${SVCNAME}" ]; then
- [ -e /etc/conf.d/"${rc_c}" ] && . /etc/conf.d/"${rc_c}"
- fi
- unset rc_c
+ _rc_c=${SVCNAME%%.*}
+ if [ -n "${_rc_c}" -a "${_rc_c}" != "${SVCNAME}" ]; then
+ [ -e "${_dir}/../conf.d/${_rc_c}" ] && . "${_dir}/../conf.d/${_rc_c}"
+ fi
+ unset _rc_c
- [ -e /etc/conf.d/"${SVCNAME}" ] && . /etc/conf.d/"${SVCNAME}"
+ [ -e "${_dir}/../conf.d/${SVCNAME}" ] && . "${_dir}/../conf.d/${SVCNAME}"
- if . /etc/init.d/"${SVCNAME}"; then
- echo "${SVCNAME}" >&3
- depend
+ if . "${_dir}/${SVCNAME}"; then
+ echo "${SVCNAME}" >&3
+ depend
- # Add any user defined depends
- config ${rc_config} ${RC_CONFIG}
- need ${rc_need} ${RC_NEED}
- use ${rc_use} ${RC_USE}
- before ${rc_before} ${RC_BEFORE}
- after ${rc_after} ${RC_AFTER}
- provide ${rc_provide} ${RC_PROVIDE}
- keywords ${rc_keywords} ${RC_KEYWORDS}
- fi
- )
+ # Add any user defined depends
+ config ${rc_config} ${RC_CONFIG}
+ need ${rc_need} ${RC_NEED}
+ use ${rc_use} ${RC_USE}
+ before ${rc_before} ${RC_BEFORE}
+ after ${rc_after} ${RC_AFTER}
+ provide ${rc_provide} ${RC_PROVIDE}
+ keywords ${rc_keywords} ${RC_KEYWORDS}
+ fi
+ )
+ done
done
# vim: set ts=4 :
diff --git a/src/librc-depend.c b/src/librc-depend.c
index ee6c79b..e870c73 100644
--- a/src/librc-depend.c
+++ b/src/librc-depend.c
@@ -673,6 +673,8 @@ bool rc_deptree_update_needed (void)
/* Quick test to see if anything we use has changed */
if (! is_newer_than (RC_DEPTREE, RC_INITDIR) ||
! is_newer_than (RC_DEPTREE, RC_CONFDIR) ||
+ ! is_newer_than (RC_DEPTREE, RC_INITDIR_LOCAL) ||
+ ! is_newer_than (RC_DEPTREE, RC_CONFDIR_LOCAL) ||
! is_newer_than (RC_DEPTREE, "/etc/rc.conf"))
return (true);
diff --git a/src/librc.c b/src/librc.c
index e429318..61f9152 100644
--- a/src/librc.c
+++ b/src/librc.c
@@ -71,6 +71,7 @@ static char **ls_dir (const char *dir, int options)
DIR *dp;
struct dirent *d;
char **list = NULL;
+ struct stat buf;
if ((dp = opendir (dir)) == NULL)
return (NULL);
@@ -79,11 +80,14 @@ static char **ls_dir (const char *dir, int options)
if (d->d_name[0] != '.') {
if (options & LS_INITD) {
int l = strlen (d->d_name);
- char *init = rc_strcatpaths (RC_INITDIR, d->d_name,
- (char *) NULL);
- bool ok = exists (init);
- free (init);
- if (! ok)
+
+ /* Check that our file really exists.
+ * This is important as a service maybe in a runlevel, but
+ * could also have been removed. */
+ char *file = rc_strcatpaths (dir, d->d_name, NULL);
+ int ok = stat (file, &buf);
+ free (file);
+ if (ok != 0)
continue;
/* .sh files are not init scripts */
@@ -93,8 +97,6 @@ static char **ls_dir (const char *dir, int options)
continue;
}
if (options & LS_DIR) {
- struct stat buf;
-
if (stat (d->d_name, &buf) == 0 && ! S_ISDIR (buf.st_mode))
continue;
}
@@ -258,8 +260,15 @@ char *rc_service_resolve (const char *service)
if (r > 0)
return (xstrdup (buffer));
}
-
snprintf (buffer, sizeof (buffer), RC_INITDIR "/%s", service);
+
+ /* So we don't exist in /etc/init.d - check /usr/local/etc/init.d */
+ if (stat (buffer, &buf) != 0) {
+ snprintf (buffer, sizeof (buffer), RC_INITDIR_LOCAL "/%s", service);
+ if (stat (buffer, &buf) != 0)
+ return (NULL);
+ }
+
return (xstrdup (buffer));
}
librc_hidden_def(rc_service_resolve)
@@ -717,8 +726,16 @@ char **rc_services_in_runlevel (const char *runlevel)
char *dir;
char **list = NULL;
- if (! runlevel)
- return (ls_dir (RC_INITDIR, LS_INITD));
+ if (! runlevel) {
+ int i;
+ char **local = ls_dir (RC_INITDIR_LOCAL, LS_INITD);
+
+ list = ls_dir (RC_INITDIR, LS_INITD);
+ STRLIST_FOREACH (local, dir, i)
+ rc_strlist_addsortu (&list, dir);
+ rc_strlist_free (local);
+ return (list);
+ }
/* These special levels never contain any services */
if (strcmp (runlevel, RC_LEVEL_SYSINIT) == 0 ||
@@ -785,6 +802,20 @@ bool rc_service_add (const char *runlevel, const char *service)
}
init = rc_service_resolve (service);
+
+ /* We need to ensure that only things in /etc/init.d are added
+ * to the boot runlevel */
+ if (strcmp (runlevel, RC_LEVEL_BOOT) == 0) {
+ char *tmp = xstrdup (init);
+ retval = (strcmp (dirname (tmp), RC_INITDIR) == 0);
+ free (tmp);
+ if (! retval) {
+ free (init);
+ errno = EPERM;
+ return (false);
+ }
+ }
+
svc = xstrdup (service);
file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (svc),
(char *) NULL);
diff --git a/src/rc-misc.h b/src/rc-misc.h
index bb3b33d..985726d 100644
--- a/src/rc-misc.h
+++ b/src/rc-misc.h
@@ -51,6 +51,9 @@
#define RC_INITDIR "/etc/init.d"
#define RC_CONFDIR "/etc/conf.d"
+#define RC_INITDIR_LOCAL "/usr/local/etc/init.d"
+#define RC_CONFDIR_LOCAL "/usr/local/etc/conf.d"
+
#define RC_KSOFTLEVEL RC_SVCDIR "/ksoftlevel"
#define RC_STARTING RC_SVCDIR "/rc.starting"
#define RC_STOPPING RC_SVCDIR "/rc.stopping"
diff --git a/src/rc-status.c b/src/rc-status.c
index dc515af..535f438 100644
--- a/src/rc-status.c
+++ b/src/rc-status.c
@@ -170,7 +170,7 @@ int rc_status (int argc, char **argv)
/* Output the services in the order in which they would start */
if (geteuid () == 0)
- deptree = _rc_deptree_load ();
+ deptree = _rc_deptree_load (NULL);
else
deptree = rc_deptree_load ();
diff --git a/src/rc-update.c b/src/rc-update.c
index ddec006..d5f2ba9 100644
--- a/src/rc-update.c
+++ b/src/rc-update.c
@@ -60,8 +60,6 @@ static ssize_t add (const char *runlevel, const char *service)
if (! rc_service_exists (service))
eerror ("%s: service `%s' does not exist", applet, service);
- else if (! rc_runlevel_exists (runlevel))
- eerror ("%s: runlevel `%s' does not exist", applet, runlevel);
else if (rc_service_in_runlevel (service, runlevel)) {
ewarn ("%s: %s already installed in runlevel `%s'; skipping",
applet, service, runlevel);
@@ -80,19 +78,18 @@ static ssize_t delete (const char *runlevel, const char *service)
{
ssize_t retval = -1;
- if (rc_service_in_runlevel (service, runlevel)) {
- if (rc_service_delete (runlevel, service)) {
- einfo ("%s removed from runlevel %s", service, runlevel);
- retval = 1;
- } else
- eerror ("%s: failed to remove service `%s' from runlevel `%s': %s",
- applet, service, runlevel, strerror (errno));
- } else if (! rc_service_exists (service))
- eerror ("%s: service `%s' does not exist", applet, service);
- else if (! rc_runlevel_exists (runlevel))
- eerror ("%s: runlevel `%s' does not exist", applet, runlevel);
- else
- retval = 0;
+ errno = 0;
+ if (rc_service_delete (runlevel, service)) {
+ einfo ("%s removed from runlevel %s", service, runlevel);
+ return 1;
+ }
+
+ if (errno == ENOENT)
+ eerror ("%s: service `%s' is not in the runlevel `%s'",
+ applet, service, runlevel);
+ else
+ eerror ("%s: failed to remove service `%s' from runlevel `%s': %s",
+ applet, service, runlevel, strerror (errno));
return (retval);
}
@@ -238,11 +235,10 @@ int rc_update (int argc, char **argv)
} else {
if (! service)
eerror ("%s: no service specified", applet);
- else if (! rc_service_exists (service))
- eerror ("%s: service `%s' does not exist", applet, service);
else {
ssize_t num_updated = 0;
ssize_t (*actfunc)(const char *, const char *);
+ size_t ret;
if (action & DOADD) {
actfunc = add;
@@ -259,7 +255,12 @@ int rc_update (int argc, char **argv)
eerrorx ("%s: no runlevels found", applet);
STRLIST_FOREACH (runlevels, runlevel, i) {
- ssize_t ret = actfunc (runlevel, service);
+ if (! rc_runlevel_exists (runlevel)) {
+ eerror ("%s: runlevel `%s' does not exist", applet, runlevel);
+ continue;
+ }
+
+ ret = actfunc (runlevel, service);
if (ret < 0)
retval = EXIT_FAILURE;
num_updated += ret;