Add runlevel stacking, #88
This implementation has the limitation that you cannot have a stacked runlevel and service of the same name in a runlevel.
This commit is contained in:
parent
e040bd77e9
commit
6615eb4b68
@ -1,4 +1,4 @@
|
|||||||
.\" Copyright (c) 2007-2009 Roy Marples
|
4.\" Copyright (c) 2007-2009 Roy Marples
|
||||||
.\" All rights reserved
|
.\" All rights reserved
|
||||||
.\"
|
.\"
|
||||||
.\" Redistribution and use in source and binary forms, with or without
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
@ -22,7 +22,7 @@
|
|||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd Jan 10, 2009
|
.Dd May 2, 2009
|
||||||
.Dt RC-UPDATE 8 SMM
|
.Dt RC-UPDATE 8 SMM
|
||||||
.Os OpenRC
|
.Os OpenRC
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -30,10 +30,12 @@
|
|||||||
.Nd add and remove services to and from a runlevel
|
.Nd add and remove services to and from a runlevel
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
|
.Op Fl s , -stack
|
||||||
.Ar add
|
.Ar add
|
||||||
.Ar service
|
.Ar service
|
||||||
.Op Ar runlevel ...
|
.Op Ar runlevel ...
|
||||||
.Nm
|
.Nm
|
||||||
|
.Op Fl s , -stack
|
||||||
.Ar delete
|
.Ar delete
|
||||||
.Ar service
|
.Ar service
|
||||||
.Op Ar runlevel ...
|
.Op Ar runlevel ...
|
||||||
@ -51,7 +53,8 @@ All services must reside in the
|
|||||||
.Pa /etc/init.d
|
.Pa /etc/init.d
|
||||||
or
|
or
|
||||||
.Pa /usr/local/etc/init.d
|
.Pa /usr/local/etc/init.d
|
||||||
directories. They must also conform to the OpenRC runscript standard.
|
directories.
|
||||||
|
They must also conform to the OpenRC runscript standard.
|
||||||
.Pp
|
.Pp
|
||||||
.Bl -tag -width "Fl a , -delete service"
|
.Bl -tag -width "Fl a , -delete service"
|
||||||
.It Ar add Ar service
|
.It Ar add Ar service
|
||||||
@ -78,6 +81,11 @@ Forces an update of the dependency tree cache.
|
|||||||
This may be needed in the event of clock skew (a file in /etc is newer than the
|
This may be needed in the event of clock skew (a file in /etc is newer than the
|
||||||
system clock).
|
system clock).
|
||||||
.El
|
.El
|
||||||
|
.Pp
|
||||||
|
If the
|
||||||
|
.Fl s , -stack
|
||||||
|
option is given then we either add or remove the runlevel from the runlevel.
|
||||||
|
This allows inheritance of runlevels.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr rc 8 ,
|
.Xr rc 8 ,
|
||||||
.Xr rc-status 8
|
.Xr rc-status 8
|
||||||
|
9
man/rc.8
9
man/rc.8
@ -22,7 +22,7 @@
|
|||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd January 13, 2009
|
.Dd May 2, 2009
|
||||||
.Dt RC 8 SMM
|
.Dt RC 8 SMM
|
||||||
.Os OpenRC
|
.Os OpenRC
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -35,10 +35,11 @@
|
|||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
first stops any services that are not for the runlevel and then starts any
|
first stops any services that are not for the runlevel and then starts any
|
||||||
services added by
|
services in the runlevel and from stacked runlevels added by
|
||||||
.Nm rc-update
|
.Nm rc-update
|
||||||
that are not currently started. If no runlevel is specified then we use the
|
that are not currently started.
|
||||||
current runlevel the system is currently in.
|
If no runlevel is specified then we use the current runlevel the system
|
||||||
|
is currently in.
|
||||||
.Pp
|
.Pp
|
||||||
There are some special runlevels that you should be aware of:
|
There are some special runlevels that you should be aware of:
|
||||||
.Bl -tag -width "shutdown"
|
.Bl -tag -width "shutdown"
|
||||||
|
@ -102,7 +102,7 @@ ls_dir(const char *dir, int options)
|
|||||||
}
|
}
|
||||||
if (options & LS_DIR) {
|
if (options & LS_DIR) {
|
||||||
if (stat(d->d_name, &buf) == 0 &&
|
if (stat(d->d_name, &buf) == 0 &&
|
||||||
! S_ISDIR(buf.st_mode))
|
!S_ISDIR(buf.st_mode))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
rc_stringlist_add(list, d->d_name);
|
rc_stringlist_add(list, d->d_name);
|
||||||
@ -330,6 +330,51 @@ rc_runlevel_exists(const char *runlevel)
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_runlevel_exists)
|
librc_hidden_def(rc_runlevel_exists)
|
||||||
|
|
||||||
|
bool
|
||||||
|
rc_runlevel_stack(const char *dst, const char *src)
|
||||||
|
{
|
||||||
|
char d[PATH_MAX], s[PATH_MAX];
|
||||||
|
|
||||||
|
if (!rc_runlevel_exists(dst) || !rc_runlevel_exists(src))
|
||||||
|
return false;
|
||||||
|
snprintf(s, sizeof(s), "../%s", src);
|
||||||
|
snprintf(d, sizeof(s), "%s/%s/%s", RC_RUNLEVELDIR, dst, src);
|
||||||
|
return (symlink(s, d) == 0 ? true : false);
|
||||||
|
}
|
||||||
|
librc_hidden_def(rc_runlevel_stack)
|
||||||
|
|
||||||
|
bool
|
||||||
|
rc_runlevel_unstack(const char *dst, const char *src)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "%s/%s/%s", RC_RUNLEVELDIR, dst, src);
|
||||||
|
return (unlink(path) == 0 ? true : false);
|
||||||
|
}
|
||||||
|
librc_hidden_def(rc_runlevel_unstack)
|
||||||
|
|
||||||
|
RC_STRINGLIST *
|
||||||
|
rc_runlevel_stacks(const char *runlevel)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
RC_STRINGLIST *dirs;
|
||||||
|
RC_STRING *d, *dn;
|
||||||
|
|
||||||
|
if (!runlevel)
|
||||||
|
return false;
|
||||||
|
snprintf(path, sizeof(path), "%s/%s", RC_RUNLEVELDIR, runlevel);
|
||||||
|
dirs = ls_dir(path, LS_DIR);
|
||||||
|
TAILQ_FOREACH_SAFE(d, dirs, entries, dn) {
|
||||||
|
if (!rc_runlevel_exists(d->value)) {
|
||||||
|
TAILQ_REMOVE(dirs, d, entries);
|
||||||
|
free(d->value);
|
||||||
|
free(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dirs;
|
||||||
|
}
|
||||||
|
librc_hidden_def(rc_runlevel_stacks)
|
||||||
|
|
||||||
/* Resolve a service name to it's full path */
|
/* Resolve a service name to it's full path */
|
||||||
char *
|
char *
|
||||||
rc_service_resolve(const char *service)
|
rc_service_resolve(const char *service)
|
||||||
@ -780,6 +825,27 @@ rc_services_in_runlevel(const char *runlevel)
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_services_in_runlevel)
|
librc_hidden_def(rc_services_in_runlevel)
|
||||||
|
|
||||||
|
RC_STRINGLIST *
|
||||||
|
rc_services_in_runlevel_stacked(const char *runlevel)
|
||||||
|
{
|
||||||
|
RC_STRINGLIST *list, *stacks, *sl;
|
||||||
|
RC_STRING *stack;
|
||||||
|
|
||||||
|
list = rc_services_in_runlevel(runlevel);
|
||||||
|
stacks = rc_runlevel_stacks(runlevel);
|
||||||
|
TAILQ_FOREACH (stack, stacks, entries) {
|
||||||
|
sl = rc_services_in_runlevel(stack->value);
|
||||||
|
if (list != NULL) {
|
||||||
|
TAILQ_CONCAT(list, sl, entries);
|
||||||
|
free(sl);
|
||||||
|
} else
|
||||||
|
list = sl;
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
librc_hidden_def(rc_services_in_runlevel_stacked)
|
||||||
|
|
||||||
|
|
||||||
RC_STRINGLIST *
|
RC_STRINGLIST *
|
||||||
rc_services_in_state(RC_SERVICE state)
|
rc_services_in_state(RC_SERVICE state)
|
||||||
{
|
{
|
||||||
|
@ -91,8 +91,11 @@ librc_hidden_proto(rc_runlevel_exists)
|
|||||||
librc_hidden_proto(rc_runlevel_get)
|
librc_hidden_proto(rc_runlevel_get)
|
||||||
librc_hidden_proto(rc_runlevel_list)
|
librc_hidden_proto(rc_runlevel_list)
|
||||||
librc_hidden_proto(rc_runlevel_set)
|
librc_hidden_proto(rc_runlevel_set)
|
||||||
|
librc_hidden_proto(rc_runlevel_stack)
|
||||||
|
librc_hidden_proto(rc_runlevel_stacks)
|
||||||
librc_hidden_proto(rc_runlevel_starting)
|
librc_hidden_proto(rc_runlevel_starting)
|
||||||
librc_hidden_proto(rc_runlevel_stopping)
|
librc_hidden_proto(rc_runlevel_stopping)
|
||||||
|
librc_hidden_proto(rc_runlevel_unstack)
|
||||||
librc_hidden_proto(rc_service_add)
|
librc_hidden_proto(rc_service_add)
|
||||||
librc_hidden_proto(rc_service_daemons_crashed)
|
librc_hidden_proto(rc_service_daemons_crashed)
|
||||||
librc_hidden_proto(rc_service_daemon_set)
|
librc_hidden_proto(rc_service_daemon_set)
|
||||||
@ -106,6 +109,7 @@ librc_hidden_proto(rc_service_resolve)
|
|||||||
librc_hidden_proto(rc_service_schedule_clear)
|
librc_hidden_proto(rc_service_schedule_clear)
|
||||||
librc_hidden_proto(rc_service_schedule_start)
|
librc_hidden_proto(rc_service_schedule_start)
|
||||||
librc_hidden_proto(rc_services_in_runlevel)
|
librc_hidden_proto(rc_services_in_runlevel)
|
||||||
|
librc_hidden_proto(rc_services_in_runlevel_stacked)
|
||||||
librc_hidden_proto(rc_services_in_state)
|
librc_hidden_proto(rc_services_in_state)
|
||||||
librc_hidden_proto(rc_services_scheduled)
|
librc_hidden_proto(rc_services_scheduled)
|
||||||
librc_hidden_proto(rc_services_scheduled_by)
|
librc_hidden_proto(rc_services_scheduled_by)
|
||||||
|
@ -80,6 +80,22 @@ char *rc_runlevel_get(void);
|
|||||||
* @return true if the runlevel exists, otherwise false */
|
* @return true if the runlevel exists, otherwise false */
|
||||||
bool rc_runlevel_exists(const char *);
|
bool rc_runlevel_exists(const char *);
|
||||||
|
|
||||||
|
/*! Stack a runlevel onto another
|
||||||
|
* @param runlevel to stack onto
|
||||||
|
* @param runlevel being stacked
|
||||||
|
* @return true if successful, otherwise false */
|
||||||
|
bool rc_runlevel_stack(const char *, const char *);
|
||||||
|
|
||||||
|
/*! Unstack a runlevel from another
|
||||||
|
* @param runlevel to unstack from
|
||||||
|
* @param runlevel being unstacked
|
||||||
|
* @return true if successful, otherwise false */
|
||||||
|
bool rc_runlevel_unstack(const char *, const char *);
|
||||||
|
|
||||||
|
/*! Return a NULL terminated list of runlevel stacks in the runlevels
|
||||||
|
* @return a NULL terminated list of runlevels */
|
||||||
|
RC_STRINGLIST *rc_runlevel_stacks(const char *);
|
||||||
|
|
||||||
/*! Return a NULL terminated list of runlevels
|
/*! Return a NULL terminated list of runlevels
|
||||||
* @return a NULL terminated list of runlevels */
|
* @return a NULL terminated list of runlevels */
|
||||||
RC_STRINGLIST *rc_runlevel_list(void);
|
RC_STRINGLIST *rc_runlevel_list(void);
|
||||||
@ -225,6 +241,11 @@ bool rc_service_value_set(const char *, const char *, const char *);
|
|||||||
* @return NULL terminated list of services */
|
* @return NULL terminated list of services */
|
||||||
RC_STRINGLIST *rc_services_in_runlevel(const char *);
|
RC_STRINGLIST *rc_services_in_runlevel(const char *);
|
||||||
|
|
||||||
|
/*! List the stacked services in a runlevel
|
||||||
|
* @param runlevel to list
|
||||||
|
* @return NULL terminated list of services */
|
||||||
|
RC_STRINGLIST *rc_services_in_runlevel_stacked(const char *);
|
||||||
|
|
||||||
/*! List the services in a state
|
/*! List the services in a state
|
||||||
* @param state to list
|
* @param state to list
|
||||||
* @return NULL terminated list of services */
|
* @return NULL terminated list of services */
|
||||||
|
@ -18,8 +18,11 @@ global:
|
|||||||
rc_runlevel_get;
|
rc_runlevel_get;
|
||||||
rc_runlevel_list;
|
rc_runlevel_list;
|
||||||
rc_runlevel_set;
|
rc_runlevel_set;
|
||||||
|
rc_runlevel_stack;
|
||||||
|
rc_runlevel_stacks;
|
||||||
rc_runlevel_starting;
|
rc_runlevel_starting;
|
||||||
rc_runlevel_stopping;
|
rc_runlevel_stopping;
|
||||||
|
rc_runlevel_unstack;
|
||||||
rc_service_add;
|
rc_service_add;
|
||||||
rc_service_daemons_crashed;
|
rc_service_daemons_crashed;
|
||||||
rc_service_daemon_set;
|
rc_service_daemon_set;
|
||||||
@ -34,6 +37,7 @@ global:
|
|||||||
rc_service_schedule_clear;
|
rc_service_schedule_clear;
|
||||||
rc_service_schedule_start;
|
rc_service_schedule_start;
|
||||||
rc_services_in_runlevel;
|
rc_services_in_runlevel;
|
||||||
|
rc_services_in_runlevel_stacked;
|
||||||
rc_services_in_state;
|
rc_services_in_state;
|
||||||
rc_services_scheduled;
|
rc_services_scheduled;
|
||||||
rc_services_scheduled_by;
|
rc_services_scheduled_by;
|
||||||
|
@ -78,8 +78,10 @@ _rc_can_find_pids(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_level(const char *level)
|
print_level(const char *prefix, const char *level)
|
||||||
{
|
{
|
||||||
|
if (prefix)
|
||||||
|
printf("%s ", prefix);
|
||||||
printf ("Runlevel: ");
|
printf ("Runlevel: ");
|
||||||
if (isatty(fileno(stdout)))
|
if (isatty(fileno(stdout)))
|
||||||
printf("%s%s%s\n",
|
printf("%s%s%s\n",
|
||||||
@ -274,16 +276,28 @@ rc_status(int argc, char **argv)
|
|||||||
deptree = _rc_deptree_load(0, NULL);
|
deptree = _rc_deptree_load(0, NULL);
|
||||||
|
|
||||||
TAILQ_FOREACH(l, levels, entries) {
|
TAILQ_FOREACH(l, levels, entries) {
|
||||||
print_level(l->value);
|
print_level(NULL, l->value);
|
||||||
services = rc_services_in_runlevel(l->value);
|
services = rc_services_in_runlevel(l->value);
|
||||||
print_services(l->value, services);
|
print_services(l->value, services);
|
||||||
|
nservices = rc_runlevel_stacks(l->value);
|
||||||
|
TAILQ_FOREACH(s, nservices, entries) {
|
||||||
|
if (rc_stringlist_find(levels, s->value) != NULL)
|
||||||
|
continue;
|
||||||
|
print_level("Stacked", s->value);
|
||||||
|
sservices = rc_services_in_runlevel(s->value);
|
||||||
|
print_services(s->value, sservices);
|
||||||
|
rc_stringlist_free(sservices);
|
||||||
|
}
|
||||||
|
sservices = NULL;
|
||||||
|
rc_stringlist_free(nservices);
|
||||||
|
nservices = NULL;
|
||||||
rc_stringlist_free(services);
|
rc_stringlist_free(services);
|
||||||
services = NULL;
|
services = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aflag || argc < 2) {
|
if (aflag || argc < 2) {
|
||||||
/* Show hotplugged services */
|
/* Show hotplugged services */
|
||||||
print_level("hotplugged");
|
print_level("Dynamic", "hotplugged");
|
||||||
services = rc_services_in_state(RC_SERVICE_HOTPLUGGED);
|
services = rc_services_in_state(RC_SERVICE_HOTPLUGGED);
|
||||||
print_services(NULL, services);
|
print_services(NULL, services);
|
||||||
rc_stringlist_free(services);
|
rc_stringlist_free(services);
|
||||||
@ -336,9 +350,9 @@ rc_status(int argc, char **argv)
|
|||||||
rc_stringlist_free(tmp);
|
rc_stringlist_free(tmp);
|
||||||
}
|
}
|
||||||
l->value = p;
|
l->value = p;
|
||||||
print_level("needed");
|
print_level("Dynamic", "needed");
|
||||||
print_services(NULL, nservices);
|
print_services(NULL, nservices);
|
||||||
print_level("manual");
|
print_level("Dynamic", "manual");
|
||||||
print_services(NULL, services);
|
print_services(NULL, services);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,11 +63,11 @@ add(const char *runlevel, const char *service)
|
|||||||
eerror("%s: service `%s' does not exist",
|
eerror("%s: service `%s' does not exist",
|
||||||
applet, service);
|
applet, service);
|
||||||
} 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);
|
||||||
retval = 0;
|
retval = 0;
|
||||||
} else if (rc_service_add(runlevel, service)) {
|
} else if (rc_service_add(runlevel, service)) {
|
||||||
einfo ("%s added to runlevel %s", service, runlevel);
|
einfo("service %s added to runlevel %s", service, runlevel);
|
||||||
retval = 1;
|
retval = 1;
|
||||||
} else
|
} else
|
||||||
eerror("%s: failed to add service `%s' to runlevel `%s': %s",
|
eerror("%s: failed to add service `%s' to runlevel `%s': %s",
|
||||||
@ -83,20 +83,76 @@ delete(const char *runlevel, const char *service)
|
|||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (rc_service_delete(runlevel, service)) {
|
if (rc_service_delete(runlevel, service)) {
|
||||||
einfo("%s removed from runlevel %s", service, runlevel);
|
einfo("service %s removed from runlevel %s",
|
||||||
|
service, runlevel);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT)
|
||||||
eerror ("%s: service `%s' is not in the runlevel `%s'",
|
eerror("%s: service `%s' is not in the runlevel `%s'",
|
||||||
applet, service, runlevel);
|
applet, service, runlevel);
|
||||||
else
|
else
|
||||||
eerror ("%s: failed to remove service `%s' from runlevel `%s': %s",
|
eerror("%s: failed to remove service `%s' from runlevel `%s': %s",
|
||||||
applet, service, runlevel, strerror (errno));
|
applet, service, runlevel, strerror (errno));
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
addstack(const char *runlevel, const char *stack)
|
||||||
|
{
|
||||||
|
if (!rc_runlevel_exists(runlevel)) {
|
||||||
|
eerror("%s: runlevel `%s' does not exist", applet, runlevel);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!rc_runlevel_exists(stack)) {
|
||||||
|
eerror("%s: runlevel `%s' does not exist", applet, stack);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (strcmp(runlevel, stack) == 0) {
|
||||||
|
eerror("%s: cannot stack `%s' onto itself", applet, stack);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (strcmp(runlevel, RC_LEVEL_SYSINIT) == 0 ||
|
||||||
|
strcmp(stack, RC_LEVEL_SYSINIT) == 0 ||
|
||||||
|
strcmp(runlevel, RC_LEVEL_BOOT) == 0 ||
|
||||||
|
strcmp(stack, RC_LEVEL_BOOT) == 0 ||
|
||||||
|
strcmp(runlevel, RC_LEVEL_SINGLE) == 0 ||
|
||||||
|
strcmp(stack, RC_LEVEL_SINGLE) == 0 ||
|
||||||
|
strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
|
||||||
|
strcmp(stack, RC_LEVEL_SHUTDOWN) == 0)
|
||||||
|
{
|
||||||
|
eerror("%s: cannot stack the %s runlevel",
|
||||||
|
applet, RC_LEVEL_SYSINIT);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!rc_runlevel_stack(runlevel, stack)) {
|
||||||
|
eerror("%s: failed to stack `%s' to `%s': %s",
|
||||||
|
applet, stack, runlevel, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
einfo("runlevel %s added to runlevel %s", stack, runlevel);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
delstack(const char *runlevel, const char *stack)
|
||||||
|
{
|
||||||
|
if (rc_runlevel_unstack(runlevel, stack)) {
|
||||||
|
einfo("runlevel %s removed from runlevel %s", stack, runlevel);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errno == ENOENT)
|
||||||
|
eerror("%s: runlevel `%s' is not in the runlevel `%s'",
|
||||||
|
applet, stack, runlevel);
|
||||||
|
else
|
||||||
|
eerror("%s: failed to remove runlevel `%s' from runlevel `%s': %s",
|
||||||
|
applet, stack, runlevel, strerror (errno));
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
show(RC_STRINGLIST *runlevels, bool verbose)
|
show(RC_STRINGLIST *runlevels, bool verbose)
|
||||||
{
|
{
|
||||||
@ -143,12 +199,14 @@ show(RC_STRINGLIST *runlevels, bool verbose)
|
|||||||
"Usage: rc-update [options] add service <runlevel>\n" \
|
"Usage: rc-update [options] add service <runlevel>\n" \
|
||||||
" rc-update [options] del service <runlevel>\n" \
|
" rc-update [options] del service <runlevel>\n" \
|
||||||
" rc-update [options] show"
|
" rc-update [options] show"
|
||||||
#define getoptstring "u" getoptstring_COMMON
|
#define getoptstring "su" getoptstring_COMMON
|
||||||
static const struct option longopts[] = {
|
static const struct option longopts[] = {
|
||||||
|
{ "stack", 0, NULL, 's' },
|
||||||
{ "update", 0, NULL, 'u' },
|
{ "update", 0, NULL, 'u' },
|
||||||
longopts_COMMON
|
longopts_COMMON
|
||||||
};
|
};
|
||||||
static const char * const longopts_help[] = {
|
static const char * const longopts_help[] = {
|
||||||
|
"Stack a runlevel instead of a service",
|
||||||
"Force an update of the dependency tree",
|
"Force an update of the dependency tree",
|
||||||
longopts_help_COMMON
|
longopts_help_COMMON
|
||||||
};
|
};
|
||||||
@ -166,7 +224,7 @@ rc_update(int argc, char **argv)
|
|||||||
char *service = NULL;
|
char *service = NULL;
|
||||||
char *p;
|
char *p;
|
||||||
int action = 0;
|
int action = 0;
|
||||||
bool verbose = false;
|
bool verbose = false, stack = false;
|
||||||
int opt;
|
int opt;
|
||||||
int retval = EXIT_FAILURE;
|
int retval = EXIT_FAILURE;
|
||||||
int num_updated = 0;
|
int num_updated = 0;
|
||||||
@ -176,10 +234,13 @@ rc_update(int argc, char **argv)
|
|||||||
while ((opt = getopt_long(argc, argv, getoptstring,
|
while ((opt = getopt_long(argc, argv, getoptstring,
|
||||||
longopts, (int *)0)) != -1)
|
longopts, (int *)0)) != -1)
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
case 's':
|
||||||
|
stack = true;
|
||||||
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
_rc_deptree_load(-1, &ret);
|
_rc_deptree_load(-1, &ret);
|
||||||
return ret;
|
return ret;
|
||||||
case_RC_COMMON_GETOPT
|
case_RC_COMMON_GETOPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
verbose = rc_yesno(getenv ("EINFO_VERBOSE"));
|
verbose = rc_yesno(getenv ("EINFO_VERBOSE"));
|
||||||
@ -241,9 +302,9 @@ rc_update(int argc, char **argv)
|
|||||||
eerror ("%s: no service specified", applet);
|
eerror ("%s: no service specified", applet);
|
||||||
else {
|
else {
|
||||||
if (action & DOADD) {
|
if (action & DOADD) {
|
||||||
actfunc = add;
|
actfunc = stack ? addstack : add;
|
||||||
} else if (action & DODELETE) {
|
} else if (action & DODELETE) {
|
||||||
actfunc = delete;
|
actfunc = stack ? delstack : delete;
|
||||||
} else {
|
} else {
|
||||||
rc_stringlist_free(runlevels);
|
rc_stringlist_free(runlevels);
|
||||||
eerrorx("%s: invalid action", applet);
|
eerrorx("%s: invalid action", applet);
|
||||||
|
@ -1037,7 +1037,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
/* Load our list of start services */
|
/* Load our list of start services */
|
||||||
hotplugged_services = rc_services_in_state(RC_SERVICE_HOTPLUGGED);
|
hotplugged_services = rc_services_in_state(RC_SERVICE_HOTPLUGGED);
|
||||||
start_services = rc_services_in_runlevel(newlevel ?
|
start_services = rc_services_in_runlevel_stacked(newlevel ?
|
||||||
newlevel : runlevel);
|
newlevel : runlevel);
|
||||||
if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
|
if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
|
||||||
strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SYSINIT) != 0)
|
strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SYSINIT) != 0)
|
||||||
|
@ -16,8 +16,11 @@ rc_runlevel_exists
|
|||||||
rc_runlevel_get
|
rc_runlevel_get
|
||||||
rc_runlevel_list
|
rc_runlevel_list
|
||||||
rc_runlevel_set
|
rc_runlevel_set
|
||||||
|
rc_runlevel_stack
|
||||||
|
rc_runlevel_stacks
|
||||||
rc_runlevel_starting
|
rc_runlevel_starting
|
||||||
rc_runlevel_stopping
|
rc_runlevel_stopping
|
||||||
|
rc_runlevel_unstack
|
||||||
rc_service_add
|
rc_service_add
|
||||||
rc_service_daemon_set
|
rc_service_daemon_set
|
||||||
rc_service_daemons_crashed
|
rc_service_daemons_crashed
|
||||||
@ -35,6 +38,7 @@ rc_service_state
|
|||||||
rc_service_value_get
|
rc_service_value_get
|
||||||
rc_service_value_set
|
rc_service_value_set
|
||||||
rc_services_in_runlevel
|
rc_services_in_runlevel
|
||||||
|
rc_services_in_runlevel_stacked
|
||||||
rc_services_in_state
|
rc_services_in_state
|
||||||
rc_services_scheduled
|
rc_services_scheduled
|
||||||
rc_services_scheduled_by
|
rc_services_scheduled_by
|
||||||
|
@ -32,10 +32,16 @@ rc_runlevel_list
|
|||||||
rc_runlevel_list@@RC_1.0
|
rc_runlevel_list@@RC_1.0
|
||||||
rc_runlevel_set
|
rc_runlevel_set
|
||||||
rc_runlevel_set@@RC_1.0
|
rc_runlevel_set@@RC_1.0
|
||||||
|
rc_runlevel_stack
|
||||||
|
rc_runlevel_stack@@RC_1.0
|
||||||
|
rc_runlevel_stacks
|
||||||
|
rc_runlevel_stacks@@RC_1.0
|
||||||
rc_runlevel_starting
|
rc_runlevel_starting
|
||||||
rc_runlevel_starting@@RC_1.0
|
rc_runlevel_starting@@RC_1.0
|
||||||
rc_runlevel_stopping
|
rc_runlevel_stopping
|
||||||
rc_runlevel_stopping@@RC_1.0
|
rc_runlevel_stopping@@RC_1.0
|
||||||
|
rc_runlevel_unstack
|
||||||
|
rc_runlevel_unstack@@RC_1.0
|
||||||
rc_service_add
|
rc_service_add
|
||||||
rc_service_add@@RC_1.0
|
rc_service_add@@RC_1.0
|
||||||
rc_service_daemon_set
|
rc_service_daemon_set
|
||||||
@ -70,6 +76,8 @@ rc_service_value_set
|
|||||||
rc_service_value_set@@RC_1.0
|
rc_service_value_set@@RC_1.0
|
||||||
rc_services_in_runlevel
|
rc_services_in_runlevel
|
||||||
rc_services_in_runlevel@@RC_1.0
|
rc_services_in_runlevel@@RC_1.0
|
||||||
|
rc_services_in_runlevel_stacked
|
||||||
|
rc_services_in_runlevel_stacked@@RC_1.0
|
||||||
rc_services_in_state
|
rc_services_in_state
|
||||||
rc_services_in_state@@RC_1.0
|
rc_services_in_state@@RC_1.0
|
||||||
rc_services_scheduled
|
rc_services_scheduled
|
||||||
|
Loading…
Reference in New Issue
Block a user