diff options
author | Roy Marples <roy@marples.name> | 2007-12-14 12:24:16 +0000 |
---|---|---|
committer | Roy Marples <roy@marples.name> | 2007-12-14 12:24:16 +0000 |
commit | a3db3bac6242ff29871161620d0449125b3262aa (patch) | |
tree | a4b6d7f9cefb59dd5955a88a474d1484d82c2fb6 /src | |
parent | b73bd04cf3f19b47480c85dd58e63eef5900fa3c (diff) |
Allow services to be in /usr/local/etc/init.d, but disallow them being added to the boot runlevel.
Diffstat (limited to 'src')
-rw-r--r-- | src/librc-depend.c | 2 | ||||
-rw-r--r-- | src/librc.c | 51 | ||||
-rw-r--r-- | src/rc-misc.h | 3 | ||||
-rw-r--r-- | src/rc-status.c | 2 | ||||
-rw-r--r-- | src/rc-update.c | 37 |
5 files changed, 66 insertions, 29 deletions
diff --git a/src/librc-depend.c b/src/librc-depend.c index ee6c79b7..e870c73c 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 e429318b..61f91525 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 bb3b33dc..985726d3 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 dc515af7..535f438a 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 ddec0066..d5f2ba92 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; |