Allow services to be in /usr/local/etc/init.d, but disallow them being added to the boot runlevel.
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
51
src/librc.c
51
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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user