init scripts and their extra options can now have descriptions, #184327.

This commit is contained in:
Roy Marples 2007-07-10 19:09:41 +00:00
parent 445918685e
commit 05201b514b
22 changed files with 201 additions and 60 deletions

View File

@ -3,6 +3,7 @@
10 Jul 2007; Roy Marples <uberlord@gentoo.org>: 10 Jul 2007; Roy Marples <uberlord@gentoo.org>:
init scripts and their extra options can now have descriptions, #184327.
We no longer care about numerical runlevels, #184733. We no longer care about numerical runlevels, #184733.
09 Jul 2007; Roy Marples <uberlord@gentoo.org>: 09 Jul 2007; Roy Marples <uberlord@gentoo.org>:

View File

@ -4,6 +4,9 @@
opts="save" opts="save"
description="Sets the local clock to UTC or Local Time."
description_save="Saves the current time in the BIOS."
depend() { depend() {
# BSD adjkerntz needs to be able to write to /etc # BSD adjkerntz needs to be able to write to /etc
if [ "${CLOCK}" = "UTC" -a -e /etc/wall_cmos_clock ] || if [ "${CLOCK}" = "UTC" -a -e /etc/wall_cmos_clock ] ||

View File

@ -4,6 +4,9 @@
opts="save" opts="save"
description="Sets the local clock to UTC or Local Time."
description_save="Saves the current time in the BIOS."
depend() { depend() {
case "${CLOCK_ADJTIME}" in case "${CLOCK_ADJTIME}" in
"") before *;; "") before *;;

View File

@ -2,6 +2,8 @@
# Copyright 1999-2007 Gentoo Foundation # Copyright 1999-2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
description="Sets a font for the consoles."
depend() { depend() {
need localmount need localmount
need keymaps # sets up terminal encoding scheme need keymaps # sets up terminal encoding scheme

View File

@ -2,6 +2,8 @@
# Copyright 1999-2007 Gentoo Foundation # Copyright 1999-2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
description="Applies a keymap for the consoles."
depend() { depend() {
need localmount need localmount
} }

View File

@ -2,6 +2,8 @@
# Copyright 1999-2007 Gentoo Foundation # Copyright 1999-2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
description="Loads a user defined list of kernel modules."
depend() { depend() {
need checkroot need checkroot
use isapnp use isapnp

View File

@ -2,6 +2,8 @@
# Copyright 1999-2007 Gentoo Foundation # Copyright 1999-2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
description="Turns numlock on for the consoles."
depend() { depend() {
need localmount need localmount
} }

View File

@ -2,6 +2,9 @@
# Copyright 1999-2007 Gentoo Foundation # Copyright 1999-2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
description="Check filesystems according to /etc/fstab for errors and \
optionally repair them."
depend() { depend() {
need checkroot need checkroot
after modules after modules

View File

@ -2,6 +2,9 @@
# Copyright 1999-2007 Gentoo Foundation # Copyright 1999-2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
description="Check the root filesystem according to /etc/fstab for errors \
and optionally repair them."
do_mtab() { do_mtab() {
# Don't create mtab if /etc is readonly # Don't create mtab if /etc is readonly
if ! touch /etc/mtab 2> /dev/null ; then if ! touch /etc/mtab 2> /dev/null ; then

View File

@ -2,6 +2,8 @@
# Copyright 1999-2007 Gentoo Foundation # Copyright 1999-2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
description="Sets the hostname of the machine."
depend() { depend() {
need checkroot need checkroot
} }

View File

@ -2,6 +2,9 @@
# Copyright 1999-2007 Gentoo Foundation # Copyright 1999-2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
description="Executes user command in /etc/conf.d/local.start when starting \
and /etc/conf.d/local.stop when stopping."
depend() { depend() {
after * after *
} }

View File

@ -2,6 +2,10 @@
# Copyright 1999-2007 Gentoo Foundation # Copyright 1999-2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
description="Mounts disks and swap according to /etc/fstab."
[ -e /proc/filessystems ] && description="${description} Also mounts various filesystems in /proc."
[ -x /sbin/dumpon ] && description="${description} Also configures saving kernel dumps to swap."
depend() { depend() {
need checkfs need checkfs
} }

View File

@ -2,6 +2,8 @@
# Copyright 1999-2007 Gentoo Foundation # Copyright 1999-2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
description="Mounts network shares according to /etc/fstab."
have_nfs() { have_nfs() {
local IFS=\n x= local IFS=\n x=
set -- $(fstabinfo --fstype nfs,nfs4) set -- $(fstabinfo --fstype nfs,nfs4)

View File

@ -2,6 +2,8 @@
# Copyright 1999-2007 Gentoo Foundation # Copyright 1999-2007 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
description="Removes a file which blocks logins until this service has run."
depend() { depend() {
need localmount need localmount
} }

View File

@ -4,6 +4,8 @@
URANDOM_SEED=${URANDOM_SEED:-/var/run/random-seed} URANDOM_SEED=${URANDOM_SEED:-/var/run/random-seed}
description="Initializes the random number generator."
depend() { depend() {
need localmount need localmount
} }

View File

@ -8,6 +8,8 @@ _config_vars="config routes"
[ -z "${IN_BACKGROUND}" ] && IN_BACKGROUND=false [ -z "${IN_BACKGROUND}" ] && IN_BACKGROUND=false
description="Configures network interfaces."
depend() { depend() {
local IFACE=${SVCNAME#*.} local IFACE=${SVCNAME#*.}
local IFVAR=$(echo -n "${IFACE}" | sed -e 's/[^[:alnum:]]/_/g') local IFVAR=$(echo -n "${IFACE}" | sed -e 's/[^[:alnum:]]/_/g')

View File

@ -32,7 +32,7 @@ else
NL= NL=
fi fi
default_opts="start stop restart pause zap" default_opts="describe start stop restart pause zap"
extra_opts="$(. "${myscript}" 2>/dev/null ; echo "${opts}")" extra_opts="$(. "${myscript}" 2>/dev/null ; echo "${opts}")"
if [ "${BE_VERBOSE}" = "yes" ] ; then if [ "${BE_VERBOSE}" = "yes" ] ; then
@ -48,6 +48,9 @@ ${CYAN}Normal Options:${OFF}"
if [ "${BE_VERBOSE}" = "yes" ] ; then if [ "${BE_VERBOSE}" = "yes" ] ; then
printf " printf "
${GREEN}describe${OFF}
Describe what the service and any extra options do.
${GREEN}start${OFF} ${GREEN}start${OFF}
Start service, as well as the services it depends on (if not already Start service, as well as the services it depends on (if not already
started). started).
@ -68,11 +71,6 @@ printf "
${GREEN}conditionalrestart|condrestart${OFF} ${GREEN}conditionalrestart|condrestart${OFF}
Same as 'restart', but only if the service has already been started. Same as 'restart', but only if the service has already been started.
${GREEN}pause${OFF}
Same as 'stop', but the services that depends on it, will not be
stopped. This is useful for stopping a network interface without
stopping all the network services that depend on 'net'.
${GREEN}zap${OFF} ${GREEN}zap${OFF}
Reset a service that is currently stopped, but still marked as started, Reset a service that is currently stopped, but still marked as started,
to the stopped state. Basically for killing zombie services. to the stopped state. Basically for killing zombie services.

View File

@ -17,6 +17,25 @@ if [ -z "$1" -o -z "$2" ] ; then
exit 1 exit 1
fi fi
# Descript the init script to the user
describe() {
if [ -n "${description}" ] ; then
einfo "${description}"
else
ewarn "No description for ${SVCNAME}"
fi
local svc= desc=
for svc in ${opts} ; do
eval desc=\$description_${svc}
if [ -n "${desc}" ] ; then
einfo "${HILITE}${svc}${NORMAL}: ${desc}"
else
ewarn "${HILITE}${svc}${NORMAL}: no description"
fi
done
}
[ "${RC_DEBUG}" = "yes" ] && set -x [ "${RC_DEBUG}" = "yes" ] && set -x
# If we're net.eth0 or openvpn.work then load net or openvpn config # If we're net.eth0 or openvpn.work then load net or openvpn config
@ -50,7 +69,7 @@ shift
while [ -n "$1" ] ; do while [ -n "$1" ] ; do
# See if we have the required function and run it # See if we have the required function and run it
for rc_x in start stop ${opts} ; do for rc_x in describe start stop ${opts} ; do
if [ "${rc_x}" = "$1" ] ; then if [ "${rc_x}" = "$1" ] ; then
if type "$1" >/dev/null 2>/dev/null ; then if type "$1" >/dev/null 2>/dev/null ; then
unset rc_x unset rc_x

View File

@ -172,6 +172,82 @@ bool rc_service_exists (const char *service)
} }
librc_hidden_def(rc_service_exists) librc_hidden_def(rc_service_exists)
char **rc_service_options (const char *service)
{
char *svc;
char cmd[PATH_MAX];
char buffer[RC_LINEBUFFER];
char **opts = NULL;
char *token;
char *p = buffer;
FILE *fp;
if (! rc_service_exists (service))
return (NULL);
svc = rc_resolve_service (service);
snprintf (cmd, sizeof (cmd), ". '%s'; echo \"${opts}\"", svc);
if (! (fp = popen (cmd, "r"))) {
eerror ("popen `%s': %s", svc, strerror (errno));
free (svc);
return (NULL);
}
if (fgets (buffer, RC_LINEBUFFER, fp)) {
if (buffer[strlen (buffer) - 1] == '\n')
buffer[strlen (buffer) - 1] = '\0';
while ((token = strsep (&p, " ")))
opts = rc_strlist_addsort (opts, token);
}
pclose (fp);
return (opts);
}
librc_hidden_def(rc_service_options)
char *rc_service_description (const char *service, const char *function)
{
char *svc;
char cmd[PATH_MAX];
char buffer[RC_LINEBUFFER];
char *desc = NULL;
FILE *fp;
int i;
if (! rc_service_exists (service))
return (NULL);
svc = rc_resolve_service (service);
if (! function)
function = "";
snprintf (cmd, sizeof (cmd), ". '%s'; echo \"${description%s%s}\"",
svc, function ? "_" : "", function);
if (! (fp = popen (cmd, "r"))) {
eerror ("popen `%s': %s", svc, strerror (errno));
free (svc);
return (NULL);
}
free (svc);
while (fgets (buffer, RC_LINEBUFFER, fp)) {
if (! desc) {
desc = rc_xmalloc (strlen (buffer) + 1);
*desc = '\0';
} else {
desc = rc_xrealloc (desc, strlen (desc) + strlen (buffer) + 1);
}
i = strlen (desc);
memcpy (desc + i, buffer, strlen (buffer));
memset (desc + i + strlen (buffer), 0, 1);
}
pclose (fp);
return (desc);
}
librc_hidden_def(rc_service_description)
bool rc_service_in_runlevel (const char *service, const char *runlevel) bool rc_service_in_runlevel (const char *service, const char *runlevel)
{ {
char *file; char *file;

View File

@ -84,8 +84,10 @@ librc_hidden_proto(rc_schedule_start_service)
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_delete) librc_hidden_proto(rc_service_delete)
librc_hidden_proto(rc_service_description)
librc_hidden_proto(rc_service_exists) librc_hidden_proto(rc_service_exists)
librc_hidden_proto(rc_service_in_runlevel) librc_hidden_proto(rc_service_in_runlevel)
librc_hidden_proto(rc_service_options)
librc_hidden_proto(rc_services_in_runlevel) librc_hidden_proto(rc_services_in_runlevel)
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)

View File

@ -44,6 +44,8 @@ typedef enum
char *rc_resolve_service (const char *service); char *rc_resolve_service (const char *service);
bool rc_service_exists (const char *service); bool rc_service_exists (const char *service);
char **rc_service_options (const char *service);
char *rc_service_description (const char *service, const char *function);
bool rc_service_in_runlevel (const char *service, const char *runlevel); bool rc_service_in_runlevel (const char *service, const char *runlevel);
bool rc_service_state (const char *service, rc_service_state_t state); bool rc_service_state (const char *service, rc_service_state_t state);
bool rc_mark_service (const char *service, rc_service_state_t state); bool rc_mark_service (const char *service, rc_service_state_t state);

View File

@ -1182,8 +1182,6 @@ int main (int argc, char **argv)
if (strcmp (optarg, "status") != 0 && if (strcmp (optarg, "status") != 0 &&
strcmp (optarg, "help") != 0) { strcmp (optarg, "help") != 0) {
/* Only root should be able to run us */ /* Only root should be able to run us */
if (geteuid () != 0)
eerrorx ("%s: root access required", applet);
} }
/* Export the command we're running. /* Export the command we're running.
@ -1194,43 +1192,7 @@ int main (int argc, char **argv)
setenv ("RC_CMD", optarg, 1); setenv ("RC_CMD", optarg, 1);
doneone = true; doneone = true;
if (strcmp (optarg, "conditionalrestart") == 0 || if (strcmp (optarg, "help") == 0) {
strcmp (optarg, "condrestart") == 0)
{
if (rc_service_state (service, rc_service_started))
svc_restart (deps);
}
else if (strcmp (optarg, "restart") == 0)
svc_restart (deps);
else if (strcmp (optarg, "start") == 0)
svc_start (deps);
else if (strcmp (optarg, "status") == 0) {
rc_service_state_t r = svc_status (service);
retval = (int) r;
} else if (strcmp (optarg, "stop") == 0) {
if (in_background)
get_started_services ();
svc_stop (deps);
if (! in_background &&
! rc_runlevel_stopping () &&
rc_service_state (service, rc_service_stopped))
uncoldplug ();
if (in_background &&
rc_service_state (service, rc_service_inactive))
{
int j;
STRLIST_FOREACH (restart_services, svc, j)
if (rc_service_state (svc, rc_service_stopped))
rc_schedule_start_service (service, svc);
}
} else if (strcmp (optarg, "zap") == 0) {
einfo ("Manually resetting %s to stopped state", applet);
rc_mark_service (applet, rc_service_stopped);
uncoldplug ();
} else if (strcmp (optarg, "help") == 0) {
execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, "help", (char *) NULL); execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, "help", (char *) NULL);
eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s", eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
applet, strerror (errno)); applet, strerror (errno));
@ -1239,8 +1201,8 @@ int main (int argc, char **argv)
strcmp (optarg, "needsme") == 0 || strcmp (optarg, "needsme") == 0 ||
strcmp (optarg, "usesme") == 0 || strcmp (optarg, "usesme") == 0 ||
strcmp (optarg, "iafter") == 0 || strcmp (optarg, "iafter") == 0 ||
strcmp (optarg, "ibefore") == 0 strcmp (optarg, "ibefore") == 0 ||
strcmp (optorg, "iprovide") == 0) { strcmp (optarg, "iprovide") == 0) {
if (! deptree && ((deptree = rc_load_deptree ()) == NULL)) if (! deptree && ((deptree = rc_load_deptree ()) == NULL))
eerrorx ("failed to load deptree"); eerrorx ("failed to load deptree");
@ -1253,21 +1215,65 @@ int main (int argc, char **argv)
STRLIST_FOREACH (services, svc, i) STRLIST_FOREACH (services, svc, i)
printf ("%s%s", i == 1 ? "" : " ", svc); printf ("%s%s", i == 1 ? "" : " ", svc);
printf ("\n"); printf ("\n");
}else } else if (strcmp (optarg, "status") == 0) {
svc_exec (optarg, NULL); rc_service_state_t r = svc_status (service);
retval = (int) r;
} else if (strcmp (optarg, "help") == 0) {
execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, "help", (char *) NULL);
eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
applet, strerror (errno));
} else {
if (geteuid () != 0)
eerrorx ("%s: root access required", applet);
/* Flush our buffered output if any */ if (strcmp (optarg, "conditionalrestart") == 0 ||
eflush (); strcmp (optarg, "condrestart") == 0)
{
if (rc_service_state (service, rc_service_started))
svc_restart (deps);
} else if (strcmp (optarg, "restart") == 0) {
svc_restart (deps);
} else if (strcmp (optarg, "start") == 0) {
svc_start (deps);
} else if (strcmp (optarg, "stop") == 0) {
if (in_background)
get_started_services ();
/* We should ensure this list is empty after an action is done */ svc_stop (deps);
rc_strlist_free (restart_services);
restart_services = NULL;
}
if (! doneone) { if (! in_background &&
execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL); ! rc_runlevel_stopping () &&
eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s", rc_service_state (service, rc_service_stopped))
applet, strerror (errno)); uncoldplug ();
if (in_background &&
rc_service_state (service, rc_service_inactive))
{
int j;
STRLIST_FOREACH (restart_services, svc, j)
if (rc_service_state (svc, rc_service_stopped))
rc_schedule_start_service (service, svc);
}
} else if (strcmp (optarg, "zap") == 0) {
einfo ("Manually resetting %s to stopped state", applet);
rc_mark_service (applet, rc_service_stopped);
uncoldplug ();
}else
svc_exec (optarg, NULL);
/* Flush our buffered output if any */
eflush ();
/* We should ensure this list is empty after an action is done */
rc_strlist_free (restart_services);
restart_services = NULL;
}
if (! doneone) {
execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
applet, strerror (errno));
}
} }
return (retval); return (retval);