Allow services to be in /usr/local/etc/init.d, but disallow them being added to the boot runlevel.

This commit is contained in:
Roy Marples 2007-12-14 12:24:16 +00:00
parent b73bd04cf3
commit a3db3bac62
6 changed files with 99 additions and 59 deletions

View File

@ -53,42 +53,45 @@ depend() {
: :
} }
cd /etc/init.d for _dir in /etc/init.d /usr/local/etc/init.d; do
for SVCNAME in *; do [ -d "${_dir}" ] || continue
[ -x "${SVCNAME}" ] || continue cd "${_dir}"
for SVCNAME in *; do
[ -x "${SVCNAME}" ] || continue
# Only generate dependencies for runscripts # Only generate dependencies for runscripts
read one two < "${SVCNAME}" read one two < "${SVCNAME}"
[ "${one}" = "#!/sbin/runscript" ] || continue [ "${one}" = "#!/sbin/runscript" ] || continue
unset one two unset one two
SVCNAME=${SVCNAME##*/} SVCNAME=${SVCNAME##*/}
( (
# Save stdout in fd3, then remap it to stderr # Save stdout in fd3, then remap it to stderr
exec 3>&1 1>&2 exec 3>&1 1>&2
rc_c=${SVCNAME%%.*} _rc_c=${SVCNAME%%.*}
if [ -n "${rc_c}" -a "${rc_c}" != "${SVCNAME}" ]; then if [ -n "${_rc_c}" -a "${_rc_c}" != "${SVCNAME}" ]; then
[ -e /etc/conf.d/"${rc_c}" ] && . /etc/conf.d/"${rc_c}" [ -e "${_dir}/../conf.d/${_rc_c}" ] && . "${_dir}/../conf.d/${_rc_c}"
fi fi
unset rc_c 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 if . "${_dir}/${SVCNAME}"; then
echo "${SVCNAME}" >&3 echo "${SVCNAME}" >&3
depend depend
# Add any user defined depends # Add any user defined depends
config ${rc_config} ${RC_CONFIG} config ${rc_config} ${RC_CONFIG}
need ${rc_need} ${RC_NEED} need ${rc_need} ${RC_NEED}
use ${rc_use} ${RC_USE} use ${rc_use} ${RC_USE}
before ${rc_before} ${RC_BEFORE} before ${rc_before} ${RC_BEFORE}
after ${rc_after} ${RC_AFTER} after ${rc_after} ${RC_AFTER}
provide ${rc_provide} ${RC_PROVIDE} provide ${rc_provide} ${RC_PROVIDE}
keywords ${rc_keywords} ${RC_KEYWORDS} keywords ${rc_keywords} ${RC_KEYWORDS}
fi fi
) )
done
done done
# vim: set ts=4 : # vim: set ts=4 :

View File

@ -673,6 +673,8 @@ bool rc_deptree_update_needed (void)
/* Quick test to see if anything we use has changed */ /* Quick test to see if anything we use has changed */
if (! is_newer_than (RC_DEPTREE, RC_INITDIR) || if (! is_newer_than (RC_DEPTREE, RC_INITDIR) ||
! is_newer_than (RC_DEPTREE, RC_CONFDIR) || ! 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")) ! is_newer_than (RC_DEPTREE, "/etc/rc.conf"))
return (true); return (true);

View File

@ -71,6 +71,7 @@ static char **ls_dir (const char *dir, int options)
DIR *dp; DIR *dp;
struct dirent *d; struct dirent *d;
char **list = NULL; char **list = NULL;
struct stat buf;
if ((dp = opendir (dir)) == NULL) if ((dp = opendir (dir)) == NULL)
return (NULL); return (NULL);
@ -79,11 +80,14 @@ static char **ls_dir (const char *dir, int options)
if (d->d_name[0] != '.') { if (d->d_name[0] != '.') {
if (options & LS_INITD) { if (options & LS_INITD) {
int l = strlen (d->d_name); int l = strlen (d->d_name);
char *init = rc_strcatpaths (RC_INITDIR, d->d_name,
(char *) NULL); /* Check that our file really exists.
bool ok = exists (init); * This is important as a service maybe in a runlevel, but
free (init); * could also have been removed. */
if (! ok) char *file = rc_strcatpaths (dir, d->d_name, NULL);
int ok = stat (file, &buf);
free (file);
if (ok != 0)
continue; continue;
/* .sh files are not init scripts */ /* .sh files are not init scripts */
@ -93,8 +97,6 @@ static char **ls_dir (const char *dir, int options)
continue; continue;
} }
if (options & LS_DIR) { if (options & LS_DIR) {
struct stat buf;
if (stat (d->d_name, &buf) == 0 && ! S_ISDIR (buf.st_mode)) if (stat (d->d_name, &buf) == 0 && ! S_ISDIR (buf.st_mode))
continue; continue;
} }
@ -258,8 +260,15 @@ char *rc_service_resolve (const char *service)
if (r > 0) if (r > 0)
return (xstrdup (buffer)); return (xstrdup (buffer));
} }
snprintf (buffer, sizeof (buffer), RC_INITDIR "/%s", service); 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)); return (xstrdup (buffer));
} }
librc_hidden_def(rc_service_resolve) librc_hidden_def(rc_service_resolve)
@ -717,8 +726,16 @@ char **rc_services_in_runlevel (const char *runlevel)
char *dir; char *dir;
char **list = NULL; char **list = NULL;
if (! runlevel) if (! runlevel) {
return (ls_dir (RC_INITDIR, LS_INITD)); 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 */ /* These special levels never contain any services */
if (strcmp (runlevel, RC_LEVEL_SYSINIT) == 0 || 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); 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); svc = xstrdup (service);
file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (svc), file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (svc),
(char *) NULL); (char *) NULL);

View File

@ -51,6 +51,9 @@
#define RC_INITDIR "/etc/init.d" #define RC_INITDIR "/etc/init.d"
#define RC_CONFDIR "/etc/conf.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_KSOFTLEVEL RC_SVCDIR "/ksoftlevel"
#define RC_STARTING RC_SVCDIR "/rc.starting" #define RC_STARTING RC_SVCDIR "/rc.starting"
#define RC_STOPPING RC_SVCDIR "/rc.stopping" #define RC_STOPPING RC_SVCDIR "/rc.stopping"

View File

@ -170,7 +170,7 @@ int rc_status (int argc, char **argv)
/* Output the services in the order in which they would start */ /* Output the services in the order in which they would start */
if (geteuid () == 0) if (geteuid () == 0)
deptree = _rc_deptree_load (); deptree = _rc_deptree_load (NULL);
else else
deptree = rc_deptree_load (); deptree = rc_deptree_load ();

View File

@ -60,8 +60,6 @@ static ssize_t add (const char *runlevel, const char *service)
if (! rc_service_exists (service)) if (! rc_service_exists (service))
eerror ("%s: service `%s' does not exist", applet, 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)) { else if (rc_service_in_runlevel (service, runlevel)) {
ewarn ("%s: %s already installed in runlevel `%s'; skipping", ewarn ("%s: %s already installed in runlevel `%s'; skipping",
applet, service, runlevel); applet, service, runlevel);
@ -80,19 +78,18 @@ static ssize_t delete (const char *runlevel, const char *service)
{ {
ssize_t retval = -1; ssize_t retval = -1;
if (rc_service_in_runlevel (service, runlevel)) { errno = 0;
if (rc_service_delete (runlevel, service)) { if (rc_service_delete (runlevel, service)) {
einfo ("%s removed from runlevel %s", service, runlevel); einfo ("%s removed from runlevel %s", service, runlevel);
retval = 1; return 1;
} else }
eerror ("%s: failed to remove service `%s' from runlevel `%s': %s",
applet, service, runlevel, strerror (errno)); if (errno == ENOENT)
} else if (! rc_service_exists (service)) eerror ("%s: service `%s' is not in the runlevel `%s'",
eerror ("%s: service `%s' does not exist", applet, service); applet, service, runlevel);
else if (! rc_runlevel_exists (runlevel)) else
eerror ("%s: runlevel `%s' does not exist", applet, runlevel); eerror ("%s: failed to remove service `%s' from runlevel `%s': %s",
else applet, service, runlevel, strerror (errno));
retval = 0;
return (retval); return (retval);
} }
@ -238,11 +235,10 @@ int rc_update (int argc, char **argv)
} else { } else {
if (! service) if (! service)
eerror ("%s: no service specified", applet); eerror ("%s: no service specified", applet);
else if (! rc_service_exists (service))
eerror ("%s: service `%s' does not exist", applet, service);
else { else {
ssize_t num_updated = 0; ssize_t num_updated = 0;
ssize_t (*actfunc)(const char *, const char *); ssize_t (*actfunc)(const char *, const char *);
size_t ret;
if (action & DOADD) { if (action & DOADD) {
actfunc = add; actfunc = add;
@ -259,7 +255,12 @@ int rc_update (int argc, char **argv)
eerrorx ("%s: no runlevels found", applet); eerrorx ("%s: no runlevels found", applet);
STRLIST_FOREACH (runlevels, runlevel, i) { 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) if (ret < 0)
retval = EXIT_FAILURE; retval = EXIT_FAILURE;
num_updated += ret; num_updated += ret;