Compare commits

...

19 Commits

Author SHA1 Message Date
Daniel Robbins
6eace7dc5a remove trailing whitespace in sysctl.Linux.in, which produces a warning during build 2013-09-26 19:21:25 +00:00
Daniel Robbins
11e1f4d30d FL-786: sysctl.Linux.in: set System V SHM to 25% of RAM 2013-09-26 18:07:59 +00:00
Daniel Robbins
c30a8d2c3c FL-786: localmount: support filesystem mounting on openvz 2013-09-26 18:05:40 +00:00
Daniel Robbins
419af8f0aa FL-786: funtoo hostname changes 2013-09-26 18:04:42 +00:00
William Hubbs
9e989227ab start-stop-daemon: remove the verbose variable
Along the same lines as the quiet variable, this is controlled by an
environment variable for the einfo code, so we do not need a separate
boolean flag.
2013-09-24 01:47:17 -05:00
William Hubbs
d6436bed09 start-stop-daemon: remove the quiet variable
The suppression of output is controlled in the e* functions themselves,
so there is no need for a variable to test in start-stop-daemon.

X-Gentoo-Bug: 482396
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=482396
2013-09-23 17:28:39 -05:00
William Hubbs
4480f1f395 rc: add service to ignore patterns 2013-09-23 13:37:21 -05:00
William Hubbs
0ba14ae720 style fixes 2013-09-23 12:40:26 -05:00
Alexander V Vershilov
7716bf31de Fix stacked runlevel support
Patch was provided by  Max Hacking <max.gentoo.bugzilla@hacking.co.uk>
and slightly fixed by Alexander Vershilov <qnikst@gentoo.org> and
William Hubbs <williamh@gentoo.org>.

Fixes:
1). Rebase to newest OpenRC version.
2). Remove code style fixes. Port to currect code style.
3). Fix rc_runlevel_stack instead of introducing new function.
4). Make get_runlevel_chain a private function.

X-Gentoo-Bug: 467368
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=467368
2013-09-20 14:27:31 -05:00
William Hubbs
445b297360 rc: add support for suppressing error messages
Add support for suppressing error messages with --quiet specified twice
on the command line.

X-Gentoo-Bug: 482396
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=482396
2013-09-03 19:05:13 -05:00
William Hubbs
2590bf7a2b libeinfo: add separate variable to suppress eerror messages
Add an EERROR_QUIET environment variable which works like EINFO_QUIET
but for the eerror functions. This will allow library consumers to
choose whether to suppress eerror messages separately from einfo and
ewarn messages.

X-Gentoo-Bug: 482396
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=482396
2013-09-03 13:03:55 -05:00
William Hubbs
4ce3cb90a0 init.d: update ignore patterns
Remove net.lo* from the ignore pattern since these scripts are no longer
part of OpenRC and add loopback and tmpfiles.dev.
2013-09-01 16:30:18 -05:00
William Hubbs
a78b18e291 libeinfo: suppress output for eerror* functions
This makes the eerror* functions honor the EINFO_QUIET environment
variable like the einfo* and ewarn* functions.

X-Gentoo-Bug: 482396
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=482396
2013-08-28 14:23:46 -05:00
William Hubbs
72b58b9e6b Revert "Libeinfo: do not suppress ewarn() messages"
This reverts commit 4ee62c7903.

The previously referenced commit broke consistency because ewarnx() was
respecting the EINFO_QUIET environment setting, but after this commit,
ewarn() was not.
Also, due to discussion on the below referenced bugs, I think we do
want to suppress warnings when EINFO_QUIET=yes.

X-Gentoo-Bug: 482396
X-Gentoo-Bug: 439174
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=482396
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=439174
2013-08-27 10:26:48 -05:00
William Hubbs
5c3e5d801b start-stop-daemon: remove redundant test of the quiet value
The einfo() function tests for the EINFO_QUIET environment variable
directly, and this is the variable that is set by the --quiet flag, so
there was no reason for this test to exist.
2013-08-26 17:09:18 -05:00
William Hubbs
bb8a9c087d start-stop-daemon: fix --quiet switch
The --quiet switch wasn't really quiet, because we changed it to report
errors. I am changing it back due to discussions on the listed bugs.

X-Gentoo-Bug: 482396
X-Gentoo-Bug: 439174
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=482396
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=439174
2013-08-26 15:51:11 -05:00
William Hubbs
d1b183a2f9 increment version 2013-08-24 17:59:19 -05:00
William Hubbs
7296379f3f man/runscript.8: minor grammar fixes 2013-08-24 11:57:22 -05:00
William Hubbs
1f5d447eda fix typo on runscript man page
The example code had an invalid checkpath option (--dir instead of
--directory) and a mode that does not make sense for directories (664
instead of 775).

X-Gentoo-Bug: 481034
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=481034
2013-08-15 10:14:42 -05:00
16 changed files with 265 additions and 157 deletions

View File

@@ -1,3 +1,3 @@
NAME= openrc NAME= openrc
VERSION= 0.12 VERSION= 0.13
PKG= ${NAME}-${VERSION} PKG= ${NAME}-${VERSION}

View File

@@ -1,2 +1,2 @@
# Set to the hostname of this machine # Set to the fully-qualified hostname of this machine
hostname="localhost" hostname="localhost"

4
init.d/.gitignore vendored
View File

@@ -3,9 +3,8 @@ fsck
hostname hostname
local local
localmount localmount
loopback
moused moused
net.lo
net.lo0
netmount netmount
network network
root root
@@ -41,4 +40,5 @@ syslogd
termencoding termencoding
ttys ttys
wscons wscons
tmpfiles.dev
tmpfiles.setup tmpfiles.setup

View File

@@ -1,18 +1,42 @@
#!@SBINDIR@/runscript #!@PREFIX@/sbin/runscript
# Copyright (c) 2007-2009 Roy Marples <roy@marples.name> # Copyright (c) 2007-2009 Roy Marples <roy@marples.name>
# Released under the 2-clause BSD license. # Released under the 2-clause BSD license.
description="Sets the hostname of the machine." description="Sets the hostname of the machine."
depend() { depend() {
keyword -prefix -lxc need root
} }
start() start()
{ {
# HOSTNAME variable used to be defined in caps in conf.d/hostname. hostname=${hostname-${HOSTNAME-localhost}}
# It is also a magic variable in bash. out=$hostname
hostname=${hostname-${HOSTNAME-localhost}} # checkbashisms: false positive short=${hostname%%.*}
if [ "$short" != "$hostname" ]; then
out="$out $short"
fi
if [ "$nisdomainname" != "" ]; then
ebegin "Setting NIS domain name to $nisdomainname"
nisdomainname $nisdomainname
eend $? "Failed to set the NIS domain name"
fi
if [ "$short" != "localhost" ]; then
out="$out localhost"
fi
if [ "$hostname" != "localhost.localdomain" ]; then
out="$out localhost.localdomain"
fi
[ -n "$aliases" ] && out="$out $aliases"
ebegin "Configuring /etc/hosts"
[ -e /etc/hosts ] && sed -i -e '/[[:space:]]*127.0.0.1[[:space:]]/d' -e '/[[:space:]]*::1[[:space:]]/d' /etc/hosts
cat <<END >> /etc/hosts
127.0.0.1 $out
::1 $out
END
chmod 0644 /etc/hosts
eend $?
[ "$RC_SYS" = "LXC" ] && return 0
ebegin "Setting hostname to $hostname" ebegin "Setting hostname to $hostname"
hostname "$hostname" hostname "$hostname"
eend $? "Failed to set the hostname" eend $? "Failed to set the hostname"

View File

@@ -9,7 +9,7 @@ depend()
need fsck need fsck
use lvm modules mtab use lvm modules mtab
after lvm modules after lvm modules
keyword -jail -openvz -prefix -vserver -lxc keyword -jail -prefix -vserver -lxc
} }
start() start()

View File

@@ -1,11 +1,11 @@
#!@SBINDIR@/runscript #!@PREFIX@/sbin/runscript
# Copyright (c) 2007-2008 Roy Marples <roy@marples.name> # Copyright (c) 2007-2008 Roy Marples <roy@marples.name>
# Released under the 2-clause BSD license. # Released under the 2-clause BSD license.
depend() depend()
{ {
before bootmisc logger before bootmisc logger
keyword -lxc -prefix -vserver keyword -lxc -vserver
} }
start() start()
@@ -15,6 +15,14 @@ start()
ebegin "Configuring kernel parameters" ebegin "Configuring kernel parameters"
eindent eindent
# default sysctl System V max shared memory to 1/4 of RAM:
mem_bytes=`awk '/MemTotal:/ { printf "%0.f",$2 * 1024}' /proc/meminfo`
mem_max=`expr $mem_bytes / 4`
page_size=`getconf PAGE_SIZE`
shmall=`expr $mem_bytes / $page_size`
sysctl kernel.shmmax=$mem_max > /dev/null
sysctl kernel.shmall=$shmall > /dev/null
for conf in @SYSCONFDIR@/sysctl.conf @SYSCONFDIR@/sysctl.d/*.conf; do for conf in @SYSCONFDIR@/sysctl.conf @SYSCONFDIR@/sysctl.d/*.conf; do
if [ -r "$conf" ]; then if [ -r "$conf" ]; then
vebegin "applying $conf" vebegin "applying $conf"

View File

@@ -105,7 +105,8 @@ and
respectively, but only work when respectively, but only work when
.Va EINFO_VERBOSE .Va EINFO_VERBOSE
is true. You can also make the is true. You can also make the
.Fn einfo .Fn einfo ,
.Fn ewarn ,
and and
.Fn ebegin .Fn ebegin
functions silent by setting functions silent by setting
@@ -184,6 +185,12 @@ when set to true makes the
and and
.Fn einfon .Fn einfon
family of functions quiet, so nothing is printed. family of functions quiet, so nothing is printed.
.Va EERROR_QUIET
when set to true makes the
.Fn eerror
and
.Fn eerrorn
family of functions quiet, so nothing is printed.
.Pp .Pp
.Va EINFO_VERBOSE .Va EINFO_VERBOSE
when set to true makes the when set to true makes the

View File

@@ -60,12 +60,12 @@ First we ensure that any services that depend on us are stopped. If any
services that need us fail to stop then we exit with a suitable error, services that need us fail to stop then we exit with a suitable error,
otherwise call the supplied stop function if it exists. otherwise call the supplied stop function if it exists.
.It Ar restart .It Ar restart
Stop and start the service, including dependencies. This cannot be Stops and starts the service, including dependencies. This cannot be
overridden. See the description of the RC_CMD variable below for the overridden. See the description of the RC_CMD variable below for the
method to make your service behave differently when restart is being method to make your service behave differently when restart is being
executed. executed.
.It Ar status .It Ar status
Show the status of the service. The return code matches the status, with the Shows the status of the service. The return code matches the status, with the
exception of "started" returning 0 to match standard command behaviour. exception of "started" returning 0 to match standard command behaviour.
.It Ar zap .It Ar zap
Resets the service state to stopped and removes all saved data about the Resets the service state to stopped and removes all saved data about the
@@ -88,8 +88,8 @@ Output from any non OpenRC commands is not affected.
.It Fl v , -verbose .It Fl v , -verbose
Turns on any extra informational output the service generates. Turns on any extra informational output the service generates.
.It Fl Z , -dry-run .It Fl Z , -dry-run
Shows what services would be stopped and/or started without actually starting Shows which services would be stopped and/or started without actually stopping
or stopping them. or starting them.
.El .El
.Pp .Pp
The following variables affect the service script: The following variables affect the service script:
@@ -471,7 +471,7 @@ start_pre()
# stop_post. # stop_post.
fi fi
# Ensure that our dirs are correct # Ensure that our dirs are correct
checkpath --dir --owner foo:foo --mode 0664 \\ checkpath --directory --owner foo:foo --mode 0775 \\
/var/run/foo /var/cache/foo /var/run/foo /var/cache/foo
} }

View File

@@ -273,6 +273,12 @@ is_quiet(void)
return yesno(getenv("EINFO_QUIET")); return yesno(getenv("EINFO_QUIET"));
} }
static bool
is_really_quiet(void)
{
return yesno(getenv("EERROR_QUIET"));
}
static bool static bool
is_verbose(void) is_verbose(void)
{ {
@@ -674,6 +680,8 @@ eerrorn(const char *EINFO_RESTRICT fmt, ...)
int retval; int retval;
va_list ap; va_list ap;
if (!fmt || is_really_quiet())
return 0;
va_start(ap, fmt); va_start(ap, fmt);
retval = _eerrorvn(fmt, ap); retval = _eerrorvn(fmt, ap);
va_end(ap); va_end(ap);
@@ -705,7 +713,7 @@ ewarn(const char *EINFO_RESTRICT fmt, ...)
int retval; int retval;
va_list ap; va_list ap;
if (!fmt) if (!fmt || is_quiet())
return 0; return 0;
va_start(ap, fmt); va_start(ap, fmt);
elogv(LOG_WARNING, fmt, ap); elogv(LOG_WARNING, fmt, ap);
@@ -740,7 +748,7 @@ eerror(const char *EINFO_RESTRICT fmt, ...)
int retval; int retval;
va_list ap; va_list ap;
if (!fmt) if (!fmt || is_really_quiet())
return 0; return 0;
va_start(ap, fmt); va_start(ap, fmt);
elogv(LOG_ERR, fmt, ap); elogv(LOG_ERR, fmt, ap);
@@ -757,7 +765,7 @@ eerrorx(const char *EINFO_RESTRICT fmt, ...)
{ {
va_list ap; va_list ap;
if (fmt) { if (fmt && !is_really_quiet()) {
va_start(ap, fmt); va_start(ap, fmt);
elogv(LOG_ERR, fmt, ap); elogv(LOG_ERR, fmt, ap);
_eerrorvn(fmt, ap); _eerrorvn(fmt, ap);

View File

@@ -323,6 +323,42 @@ rc_parse_service_state(RC_SERVICE state)
return NULL; return NULL;
} }
/* Returns a list of all the chained runlevels used by the
* specified runlevel in dependency order, including the
* specified runlevel. */
static void
get_runlevel_chain(const char *runlevel, RC_STRINGLIST *level_list)
{
char path[PATH_MAX];
RC_STRINGLIST *dirs;
RC_STRING *d, *dn;
/*
* If we haven't been passed a runlevel or a level list, or
* if the passed runlevel doesn't exist then we're done already!
*/
if (!runlevel || !level_list || !rc_runlevel_exists(runlevel))
return;
/*
* We want to add this runlevel to the list but if
* it is already in the list it needs to go at the
* end again.
*/
if (rc_stringlist_find(level_list, runlevel))
rc_stringlist_delete(level_list, runlevel);
rc_stringlist_add(level_list, runlevel);
/*
* We can now do exactly the above procedure for our chained
* runlevels.
*/
snprintf(path, sizeof(path), "%s/%s", RC_RUNLEVELDIR, runlevel);
dirs = ls_dir(path, LS_DIR);
TAILQ_FOREACH_SAFE(d, dirs, entries, dn)
get_runlevel_chain(d->value, level_list);
}
bool bool
rc_runlevel_starting(void) rc_runlevel_starting(void)
{ {
@@ -424,22 +460,10 @@ librc_hidden_def(rc_runlevel_unstack)
RC_STRINGLIST * RC_STRINGLIST *
rc_runlevel_stacks(const char *runlevel) rc_runlevel_stacks(const char *runlevel)
{ {
char path[PATH_MAX]; RC_STRINGLIST *stack;
RC_STRINGLIST *dirs; stack = rc_stringlist_new();
RC_STRING *d, *dn; get_runlevel_chain(runlevel, stack);
return stack;
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) librc_hidden_def(rc_runlevel_stacks)
@@ -903,17 +927,13 @@ rc_services_in_runlevel_stacked(const char *runlevel)
stacks = rc_runlevel_stacks(runlevel); stacks = rc_runlevel_stacks(runlevel);
TAILQ_FOREACH(stack, stacks, entries) { TAILQ_FOREACH(stack, stacks, entries) {
sl = rc_services_in_runlevel(stack->value); sl = rc_services_in_runlevel(stack->value);
if (list != NULL) { TAILQ_CONCAT(list, sl, entries);
TAILQ_CONCAT(list, sl, entries); free(sl);
free(sl);
} else
list = sl;
} }
return list; return list;
} }
librc_hidden_def(rc_services_in_runlevel_stacked) 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)
{ {

1
src/rc/.gitignore vendored
View File

@@ -3,6 +3,7 @@ rc-status
rc-service rc-service
rc-update rc-update
runscript runscript
service
start-stop-daemon start-stop-daemon
einfon einfon
einfo einfo

View File

@@ -35,6 +35,21 @@
# define _noreturn # define _noreturn
#endif #endif
static void set_quiet_options(void)
{
static int qcount = 0;
qcount ++;
switch (qcount) {
case 1:
setenv ("EINFO_QUIET", "YES", 1);
break;
case 2:
setenv ("EERROR_QUIET", "YES", 1);
break;
}
}
_noreturn static void _noreturn static void
show_version(void) show_version(void)
{ {

View File

@@ -38,13 +38,13 @@
"Disable color output", \ "Disable color output", \
"Display software version", \ "Display software version", \
"Run verbosely", \ "Run verbosely", \
"Run quietly (Does not affect errors)" "Run quietly (repeat to suppress errors)"
#define case_RC_COMMON_getopt_case_C setenv ("EINFO_COLOR", "NO", 1); #define case_RC_COMMON_getopt_case_C setenv ("EINFO_COLOR", "NO", 1);
#define case_RC_COMMON_getopt_case_h usage (EXIT_SUCCESS); #define case_RC_COMMON_getopt_case_h usage (EXIT_SUCCESS);
#define case_RC_COMMON_getopt_case_V if (argc == 2) show_version(); #define case_RC_COMMON_getopt_case_V if (argc == 2) show_version();
#define case_RC_COMMON_getopt_case_v setenv ("EINFO_VERBOSE", "YES", 1); #define case_RC_COMMON_getopt_case_v setenv ("EINFO_VERBOSE", "YES", 1);
#define case_RC_COMMON_getopt_case_q setenv ("EINFO_QUIET", "YES", 1); #define case_RC_COMMON_getopt_case_q set_quiet_options();
#define case_RC_COMMON_getopt_default usage (EXIT_FAILURE); #define case_RC_COMMON_getopt_default usage (EXIT_FAILURE);
#define case_RC_COMMON_GETOPT \ #define case_RC_COMMON_GETOPT \

View File

@@ -171,6 +171,26 @@ print_services(const char *runlevel, RC_STRINGLIST *svcs)
rc_stringlist_free(l); rc_stringlist_free(l);
} }
static void
print_stacked_services(const char *runlevel)
{
RC_STRINGLIST *stackedlevels, *servicelist;
RC_STRING *stackedlevel;
stackedlevels = rc_runlevel_stacks(runlevel);
TAILQ_FOREACH(stackedlevel, stackedlevels, entries) {
if (rc_stringlist_find(levels, stackedlevel->value) != NULL)
continue;
print_level("Stacked", stackedlevel->value);
servicelist = rc_services_in_runlevel(stackedlevel->value);
print_services(stackedlevel->value, servicelist);
rc_stringlist_free(servicelist);
print_stacked_services(stackedlevel->value);
}
rc_stringlist_free(stackedlevels);
stackedlevels = NULL;
}
#include "_usage.h" #include "_usage.h"
#define usagestring "" \ #define usagestring "" \
"Usage: rc-status [options] <runlevel>...\n" \ "Usage: rc-status [options] <runlevel>...\n" \
@@ -199,7 +219,8 @@ static const char * const longopts_help[] = {
int int
rc_status(int argc, char **argv) rc_status(int argc, char **argv)
{ {
RC_STRING *s, *l, *t; RC_STRING *s, *l, *t, *level;
char *p, *runlevel = NULL; char *p, *runlevel = NULL;
int opt, aflag = 0, retval = 0; int opt, aflag = 0, retval = 0;
@@ -280,16 +301,7 @@ rc_status(int argc, char **argv)
print_level(NULL, 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); print_stacked_services(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); rc_stringlist_free(nservices);
nservices = NULL; nservices = NULL;
rc_stringlist_free(services); rc_stringlist_free(services);
@@ -317,16 +329,14 @@ rc_status(int argc, char **argv)
services = rc_services_in_runlevel(NULL); services = rc_services_in_runlevel(NULL);
sservices = rc_stringlist_new(); sservices = rc_stringlist_new();
TAILQ_FOREACH(l, levels, entries) { TAILQ_FOREACH(l, levels, entries) {
nservices = rc_services_in_runlevel(l->value); nservices = rc_services_in_runlevel_stacked(l->value);
TAILQ_CONCAT(sservices, nservices, entries); TAILQ_CONCAT(sservices, nservices, entries);
free(nservices); free(nservices);
} }
TAILQ_FOREACH_SAFE(s, services, entries, t) { TAILQ_FOREACH_SAFE(s, services, entries, t) {
if (rc_stringlist_find(sservices, s->value) || if ((rc_stringlist_find(sservices, s->value) ||
rc_service_state(s->value) & (rc_service_state(s->value) & ( RC_SERVICE_STOPPED | RC_SERVICE_HOTPLUGGED)))) {
(RC_SERVICE_STOPPED | RC_SERVICE_HOTPLUGGED)) TAILQ_REMOVE(services, s, entries);
{
TAILQ_REMOVE(services, s, entries);
free(s->value); free(s->value);
free(s); free(s);
} }
@@ -337,22 +347,23 @@ rc_status(int argc, char **argv)
alist = rc_stringlist_new(); alist = rc_stringlist_new();
l = rc_stringlist_add(alist, ""); l = rc_stringlist_add(alist, "");
p = l->value; p = l->value;
if (!runlevel) TAILQ_FOREACH(level, levels, entries) {
runlevel = rc_runlevel_get(); TAILQ_FOREACH_SAFE(s, services, entries, t) {
TAILQ_FOREACH_SAFE(s, services, entries, t) { l->value = s->value;
l->value = s->value; setenv("RC_SVCNAME", l->value, 1);
unsetenv("RC_SVCNAME"); tmp = rc_deptree_depends(deptree, needsme, alist, level->value, RC_DEP_TRACE);
setenv("RC_SVCNAME", l->value, 1); if (TAILQ_FIRST(tmp)) {
tmp = rc_deptree_depends(deptree, needsme, alist, runlevel, RC_DEP_TRACE); TAILQ_REMOVE(services, s, entries);
if (TAILQ_FIRST(tmp)) { TAILQ_INSERT_TAIL(nservices, s, entries);
TAILQ_REMOVE(services, s, entries); }
TAILQ_INSERT_TAIL(nservices, s, entries); rc_stringlist_free(tmp);
} }
rc_stringlist_free(tmp);
} }
l->value = p; l->value = p;
/* we are unsetting RC_SVCNAME because last loaded service /*
wount be added to list */ * we are unsetting RC_SVCNAME because last loaded service will not
* be added to the list
*/
unsetenv("RC_SVCNAME"); unsetenv("RC_SVCNAME");
print_level("Dynamic", "needed"); print_level("Dynamic", "needed");
print_services(NULL, nservices); print_services(NULL, nservices);

View File

@@ -79,12 +79,6 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
const char *applet = NULL; const char *applet = NULL;
static char *runlevel; static char *runlevel;
static RC_STRINGLIST *hotplugged_services;
static RC_STRINGLIST *stop_services;
static RC_STRINGLIST *start_services;
static RC_STRINGLIST *types_n;
static RC_STRINGLIST *types_nua;
static RC_DEPTREE *deptree;
static RC_HOOK hook_out; static RC_HOOK hook_out;
struct termios *termios_orig = NULL; struct termios *termios_orig = NULL;
@@ -524,7 +518,9 @@ runlevel_config(const char *service, const char *level)
} }
static void static void
do_stop_services(const char *newlevel, bool parallel, bool going_down) do_stop_services(const RC_STRINGLIST *types_n, const RC_STRINGLIST *start_services,
const RC_STRINGLIST *stop_services, const RC_DEPTREE *deptree,
const char *newlevel, bool parallel, bool going_down)
{ {
pid_t pid; pid_t pid;
RC_STRING *service, *svc1, *svc2; RC_STRING *service, *svc1, *svc2;
@@ -627,7 +623,7 @@ stop:
} }
static void static void
do_start_services(bool parallel) do_start_services(const RC_STRINGLIST *start_services, bool parallel)
{ {
RC_STRING *service; RC_STRING *service;
pid_t pid; pid_t pid;
@@ -754,6 +750,12 @@ main(int argc, char **argv)
{ {
const char *bootlevel = NULL; const char *bootlevel = NULL;
char *newlevel = NULL; char *newlevel = NULL;
static RC_STRINGLIST *hotplugged_services;
static RC_STRINGLIST *stop_services;
static RC_STRINGLIST *start_services;
static RC_STRINGLIST *types_n;
static RC_STRINGLIST *types_nua;
static RC_DEPTREE *deptree;
RC_STRINGLIST *deporder = NULL; RC_STRINGLIST *deporder = NULL;
RC_STRINGLIST *tmplist; RC_STRINGLIST *tmplist;
RC_STRING *service; RC_STRING *service;
@@ -868,7 +870,11 @@ main(int argc, char **argv)
snprintf(pidstr, sizeof(pidstr), "%d", getpid()); snprintf(pidstr, sizeof(pidstr), "%d", getpid());
setenv("RC_PID", pidstr, 1); setenv("RC_PID", pidstr, 1);
/* Load current runlevel */ /* Create a list of all services which should be started for the new or
* current runlevel including those in boot, sysinit and hotplugged
* runlevels. Clearly, some of these will already be started so we
* won't actually be starting them all.
*/
bootlevel = getenv("RC_BOOTLEVEL"); bootlevel = getenv("RC_BOOTLEVEL");
runlevel = rc_runlevel_get(); runlevel = rc_runlevel_get();
@@ -972,8 +978,13 @@ main(int argc, char **argv)
applet, RC_STOPPING, strerror(errno)); applet, RC_STOPPING, strerror(errno));
} }
/* Build a list of all services to stop and then work out the /* Create a list of all services which we could stop (assuming
* correct order for stopping them */ * they won't be active in the new or current runlevel) including
* all those services which have been started, are inactive or
* are currently starting. Clearly, some of these will be listed
* in the new or current runlevel so we won't actually be stopping
* them all.
*/
stop_services = rc_services_in_state(RC_SERVICE_STARTED); stop_services = rc_services_in_state(RC_SERVICE_STARTED);
tmplist = rc_services_in_state(RC_SERVICE_INACTIVE); tmplist = rc_services_in_state(RC_SERVICE_INACTIVE);
TAILQ_CONCAT(stop_services, tmplist, entries); TAILQ_CONCAT(stop_services, tmplist, entries);
@@ -996,7 +1007,11 @@ main(int argc, char **argv)
stop_services = tmplist; stop_services = tmplist;
} }
/* Load our list of start services */ /* Create a list of all services which should be started for the new or
* current runlevel including those in boot, sysinit and hotplugged
* runlevels. Clearly, some of these will already be started so we
* won't actually be starting them all.
*/
hotplugged_services = rc_services_in_state(RC_SERVICE_HOTPLUGGED); hotplugged_services = rc_services_in_state(RC_SERVICE_HOTPLUGGED);
start_services = rc_services_in_runlevel_stacked(newlevel ? start_services = rc_services_in_runlevel_stacked(newlevel ?
newlevel : runlevel); newlevel : runlevel);
@@ -1006,9 +1021,11 @@ main(int argc, char **argv)
tmplist = rc_services_in_runlevel(RC_LEVEL_SYSINIT); tmplist = rc_services_in_runlevel(RC_LEVEL_SYSINIT);
TAILQ_CONCAT(start_services, tmplist, entries); TAILQ_CONCAT(start_services, tmplist, entries);
free(tmplist); free(tmplist);
/* If we are NOT headed for the single-user runlevel... */
if (strcmp(newlevel ? newlevel : runlevel, if (strcmp(newlevel ? newlevel : runlevel,
RC_LEVEL_SINGLE) != 0) RC_LEVEL_SINGLE) != 0)
{ {
/* If we are NOT headed for the boot runlevel... */
if (strcmp(newlevel ? newlevel : runlevel, if (strcmp(newlevel ? newlevel : runlevel,
bootlevel) != 0) bootlevel) != 0)
{ {
@@ -1029,7 +1046,7 @@ main(int argc, char **argv)
/* Now stop the services that shouldn't be running */ /* Now stop the services that shouldn't be running */
if (stop_services && !nostop) if (stop_services && !nostop)
do_stop_services(newlevel, parallel, going_down); do_stop_services(types_n, start_services, stop_services, deptree, newlevel, parallel, going_down);
/* Wait for our services to finish */ /* Wait for our services to finish */
wait_for_services(); wait_for_services();
@@ -1065,18 +1082,10 @@ main(int argc, char **argv)
TAILQ_FOREACH(service, hotplugged_services, entries) TAILQ_FOREACH(service, hotplugged_services, entries)
rc_service_mark(service->value, RC_SERVICE_HOTPLUGGED); rc_service_mark(service->value, RC_SERVICE_HOTPLUGGED);
/* Order the services to start */
if (start_services) {
rc_stringlist_sort(&start_services);
deporder = rc_deptree_depends(deptree, types_nua,
start_services, runlevel,
depoptions | RC_DEP_START);
rc_stringlist_free(start_services);
start_services = deporder;
}
#ifdef __linux__ #ifdef __linux__
/* mark any services skipped as started */ /* If the "noinit" parameter was passed on the kernel command line then
* mark the specified services as started so they will not be started
* by us. */
proc = p = rc_proc_getent("noinit"); proc = p = rc_proc_getent("noinit");
if (proc) { if (proc) {
while ((token = strsep(&p, ","))) while ((token = strsep(&p, ",")))
@@ -1085,19 +1094,38 @@ main(int argc, char **argv)
} }
#endif #endif
/* If we have a list of services to start then... */
if (start_services) { if (start_services) {
do_start_services(parallel); /* Get a list of the chained runlevels which compose the target runlevel */
/* FIXME: If we skip the boot runlevel and go straight RC_STRINGLIST *runlevel_chain = rc_runlevel_stacks(runlevel);
* to default from sysinit, we should now re-evaluate our
* start services + hotplugged services and call
* do_start_services a second time. */
/* Wait for our services to finish */ /* Loop through them in reverse order. */
wait_for_services(); RC_STRING *rlevel;
TAILQ_FOREACH_REVERSE(rlevel, runlevel_chain, rc_stringlist, entries)
{
/* Get a list of all the services in that runlevel */
RC_STRINGLIST *run_services = rc_services_in_runlevel(rlevel->value);
/* Start those services. */
rc_stringlist_sort(&run_services);
deporder = rc_deptree_depends(deptree, types_nua, run_services, rlevel->value, depoptions | RC_DEP_START);
rc_stringlist_free(run_services);
run_services = deporder;
do_start_services(run_services, parallel);
/* Wait for our services to finish */
wait_for_services();
/* Free the list of services, we're done with it. */
rc_stringlist_free(run_services);
}
rc_stringlist_free(runlevel_chain);
} }
#ifdef __linux__ #ifdef __linux__
/* mark any services skipped as stopped */ /* If the "noinit" parameter was passed on the kernel command line then
* mark the specified services as stopped so that our records reflect
* reality. */
proc = p = rc_proc_getent("noinit"); proc = p = rc_proc_getent("noinit");
if (proc) { if (proc) {
while ((token = strsep(&p, ","))) while ((token = strsep(&p, ",")))

View File

@@ -307,7 +307,7 @@ parse_schedule(const char *string, int timeout)
} }
static pid_t static pid_t
get_pid(const char *pidfile, bool quiet) get_pid(const char *pidfile)
{ {
FILE *fp; FILE *fp;
pid_t pid; pid_t pid;
@@ -316,14 +316,12 @@ get_pid(const char *pidfile, bool quiet)
return -1; return -1;
if ((fp = fopen(pidfile, "r")) == NULL) { if ((fp = fopen(pidfile, "r")) == NULL) {
if (!quiet) eerror("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
eerror("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
return -1; return -1;
} }
if (fscanf(fp, "%d", &pid) != 1) { if (fscanf(fp, "%d", &pid) != 1) {
if (!quiet) eerror("%s: no pid found in `%s'", applet, pidfile);
eerror("%s: no pid found in `%s'", applet, pidfile);
fclose(fp); fclose(fp);
return -1; return -1;
} }
@@ -336,8 +334,7 @@ get_pid(const char *pidfile, bool quiet)
/* return number of processed killed, -1 on error */ /* return number of processed killed, -1 on error */
static int static int
do_stop(const char *exec, const char *const *argv, do_stop(const char *exec, const char *const *argv,
pid_t pid, uid_t uid,int sig, pid_t pid, uid_t uid,int sig, bool test)
bool quiet, bool verbose, bool test)
{ {
RC_PIDLIST *pids; RC_PIDLIST *pids;
RC_PID *pi; RC_PID *pi;
@@ -355,20 +352,16 @@ do_stop(const char *exec, const char *const *argv,
LIST_FOREACH_SAFE(pi, pids, entries, np) { LIST_FOREACH_SAFE(pi, pids, entries, np) {
if (test) { if (test) {
if (!quiet) einfo("Would send signal %d to PID %d", sig, pi->pid);
einfo("Would send signal %d to PID %d", sig, pi->pid);
nkilled++; nkilled++;
} else { } else {
if (verbose) ebeginv("Sending signal %d to PID %d", sig, pi->pid);
ebegin("Sending signal %d to PID %d",
sig, pi->pid);
errno = 0; errno = 0;
killed = (kill(pi->pid, sig) == 0 || killed = (kill(pi->pid, sig) == 0 ||
errno == ESRCH ? true : false); errno == ESRCH ? true : false);
if (verbose) eendv(killed ? 0 : 1,
eend(killed ? 0 : 1, "%s: failed to send signal %d to PID %d: %s",
"%s: failed to send signal %d to PID %d: %s", applet, sig, pi->pid, strerror(errno));
applet, sig, pi->pid, strerror(errno));
if (!killed) { if (!killed) {
nkilled = -1; nkilled = -1;
} else { } else {
@@ -386,7 +379,7 @@ do_stop(const char *exec, const char *const *argv,
static int static int
run_stop_schedule(const char *exec, const char *const *argv, run_stop_schedule(const char *exec, const char *const *argv,
const char *pidfile, uid_t uid, const char *pidfile, uid_t uid,
bool quiet, bool verbose, bool test, bool progress) bool test, bool progress)
{ {
SCHEDULEITEM *item = TAILQ_FIRST(&schedule); SCHEDULEITEM *item = TAILQ_FIRST(&schedule);
int nkilled = 0; int nkilled = 0;
@@ -398,15 +391,15 @@ run_stop_schedule(const char *exec, const char *const *argv,
const char *const *p; const char *const *p;
bool progressed = false; bool progressed = false;
if (verbose) { if (exec)
if (exec) einfov("Will stop %s", exec);
einfo ("Will stop %s", exec); if (pidfile)
if (pidfile) einfov("Will stop PID in pidfile `%s'", pidfile);
einfo("Will stop PID in pidfile `%s'", pidfile); if (uid)
if (uid) einfov("Will stop processes owned by UID %d", uid);
einfo("Will stop processes owned by UID %d", uid); if (argv && *argv) {
if (argv && *argv) { einfovn("Will stop processes of `");
einfon("Will stop processes of `"); if (rc_yesno(getenv("EINFO_VERBOSE"))) {
for (p = argv; p && *p; p++) { for (p = argv; p && *p; p++) {
if (p != argv) if (p != argv)
printf(" "); printf(" ");
@@ -417,7 +410,7 @@ run_stop_schedule(const char *exec, const char *const *argv,
} }
if (pidfile) { if (pidfile) {
pid = get_pid(pidfile, false); pid = get_pid(pidfile);
if (pid == -1) if (pid == -1)
return 0; return 0;
} }
@@ -430,8 +423,7 @@ run_stop_schedule(const char *exec, const char *const *argv,
case SC_SIGNAL: case SC_SIGNAL:
nrunning = 0; nrunning = 0;
nkilled = do_stop(exec, argv, pid, uid, item->value, nkilled = do_stop(exec, argv, pid, uid, item->value, test);
quiet, verbose, test);
if (nkilled == 0) { if (nkilled == 0) {
if (tkilled == 0) { if (tkilled == 0) {
if (progressed) if (progressed)
@@ -460,8 +452,7 @@ run_stop_schedule(const char *exec, const char *const *argv,
nloops++) nloops++)
{ {
if ((nrunning = do_stop(exec, argv, if ((nrunning = do_stop(exec, argv,
pid, uid, 0, true, false, pid, uid, 0, true)) == 0)
true)) == 0)
return 0; return 0;
@@ -678,8 +669,6 @@ start_stop_daemon(int argc, char **argv)
bool stop = false; bool stop = false;
bool oknodo = false; bool oknodo = false;
bool test = false; bool test = false;
bool quiet;
bool verbose = false;
char *exec = NULL; char *exec = NULL;
char *startas = NULL; char *startas = NULL;
char *name = NULL; char *name = NULL;
@@ -916,8 +905,6 @@ start_stop_daemon(int argc, char **argv)
endpwent(); endpwent();
argc -= optind; argc -= optind;
argv += optind; argv += optind;
quiet = rc_yesno(getenv("EINFO_QUIET"));
verbose = rc_yesno(getenv("EINFO_VERBOSE"));
/* Allow start-stop-daemon --signal HUP --exec /usr/sbin/dnsmasq /* Allow start-stop-daemon --signal HUP --exec /usr/sbin/dnsmasq
* instead of forcing --stop --oknodo as well */ * instead of forcing --stop --oknodo as well */
@@ -1061,7 +1048,7 @@ start_stop_daemon(int argc, char **argv)
else else
parse_schedule(NULL, sig); parse_schedule(NULL, sig);
i = run_stop_schedule(exec, (const char *const *)margv, i = run_stop_schedule(exec, (const char *const *)margv,
pidfile, uid, quiet, verbose, test, progress); pidfile, uid, test, progress);
if (i < 0) if (i < 0)
/* We failed to stop something */ /* We failed to stop something */
@@ -1083,16 +1070,16 @@ start_stop_daemon(int argc, char **argv)
} }
if (pidfile) if (pidfile)
pid = get_pid(pidfile, true); pid = get_pid(pidfile);
else else
pid = 0; pid = 0;
if (do_stop(exec, (const char * const *)margv, pid, uid, if (do_stop(exec, (const char * const *)margv, pid, uid,
0, true, false, true) > 0) 0, true) > 0)
eerrorx("%s: %s is already running", applet, exec); eerrorx("%s: %s is already running", applet, exec);
if (test) { if (test) {
if (quiet) if (rc_yesno(getenv("EINFO_QUIET")))
exit (EXIT_SUCCESS); exit (EXIT_SUCCESS);
einfon("Would start"); einfon("Would start");
@@ -1116,10 +1103,8 @@ start_stop_daemon(int argc, char **argv)
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
if (verbose) { ebeginv("Detaching to start `%s'", exec);
ebegin("Detaching to start `%s'", exec); eindentv();
eindent();
}
/* Remove existing pidfile */ /* Remove existing pidfile */
if (pidfile) if (pidfile)
@@ -1287,9 +1272,9 @@ start_stop_daemon(int argc, char **argv)
} }
/* We don't redirect stdin as some daemons may need it */ /* We don't redirect stdin as some daemons may need it */
if (background || quiet || redirect_stdout) if (background || redirect_stdout || rc_yesno(getenv("EINFO_QUIET")))
dup2(stdout_fd, STDOUT_FILENO); dup2(stdout_fd, STDOUT_FILENO);
if (background || redirect_stderr) if (background || redirect_stderr || rc_yesno(getenv("EINFO_QUIET")))
dup2(stderr_fd, STDERR_FILENO); dup2(stderr_fd, STDERR_FILENO);
for (i = getdtablesize() - 1; i >= 3; --i) for (i = getdtablesize() - 1; i >= 3; --i)
@@ -1320,9 +1305,10 @@ start_stop_daemon(int argc, char **argv)
return -1; return -1;
} }
} while (!WIFEXITED(i) && !WIFSIGNALED(i)); } while (!WIFEXITED(i) && !WIFSIGNALED(i));
if (!WIFEXITED(i) || WEXITSTATUS(i) != 0) if (!WIFEXITED(i) || WEXITSTATUS(i) != 0) {
eerrorx("%s: failed to start `%s'", applet, exec); eerror("%s: failed to start `%s'", applet, exec);
exit(EXIT_FAILURE);
}
pid = spid; pid = spid;
} }
@@ -1356,7 +1342,7 @@ start_stop_daemon(int argc, char **argv)
alive = true; alive = true;
} else { } else {
if (pidfile) { if (pidfile) {
pid = get_pid(pidfile, false); pid = get_pid(pidfile);
if (pid == -1) { if (pid == -1) {
eerrorx("%s: did not " eerrorx("%s: did not "
"create a valid" "create a valid"
@@ -1366,7 +1352,7 @@ start_stop_daemon(int argc, char **argv)
} else } else
pid = 0; pid = 0;
if (do_stop(exec, (const char *const *)margv, if (do_stop(exec, (const char *const *)margv,
pid, uid, 0, true, false, true) > 0) pid, uid, 0, true) > 0)
alive = true; alive = true;
} }