Compare commits

...

40 Commits

Author SHA1 Message Date
Roy Marples
3fc17f5966 Store the file skewed against. 2009-02-10 15:25:28 +00:00
Roy Marples
522ab21fbf Only create the reboot file if rebooting. 2009-02-10 15:16:25 +00:00
Roy Marples
3d7b56f2e2 Create /reboot if running inside OpenVZ, #138.
This should be fine as vpsreboot should only restart a stopped container.
2009-02-10 15:06:48 +00:00
Roy Marples
6bb44be2a3 We should always mount $RC_SVCDIR unless in a vserver or it's already mounted. 2009-01-29 13:38:15 +00:00
Roy Marples
415fe87d8c Clean up some compiler warnings. 2009-01-29 13:29:04 +00:00
Roy Marples
4f163f9b9a Allow wpa_cli_$IFACE to too send args to wpa_cli. 2009-01-21 09:25:34 +00:00
Roy Marples
417a817d25 noinit makes more sense than noinitd 2009-01-18 20:02:50 +00:00
Roy Marples
30a7a3a9bf Fix locale with svnversion, #140 thanks to Matthias Schwarzott. 2009-01-14 14:32:56 +00:00
Roy Marples
5208a1de29 yes should be YES 2009-01-13 11:04:37 +00:00
Roy Marples
abcc4c5c72 Don't allow SYSVINIT parameters through anymore.
RC_REBOOT is now yes when rebooting.
Document the special reboot runlevel.
2009-01-13 11:02:00 +00:00
Roy Marples
fcf1cce549 rc_newer/older_than only report file if time_t is a pointer, so it
should take precedence in the argument list.
2009-01-13 09:11:31 +00:00
Roy Marples
3d37005a3d We now warn about clock skews
rc-update -u will force a regen of the dep tree
rc_newer_than and rc_olderthan now take another two parameters for newest/oldest file and mtime
2009-01-12 23:53:13 +00:00
Roy Marples
2243c01390 Add snapshot and snap targets 2009-01-12 23:12:06 +00:00
Roy Marples
a52472c3c3 Fix ordering, #139 thanks to Matthias. 2009-01-12 10:24:47 +00:00
Roy Marples
f23822e082 Copyright 2009-01-12 10:24:00 +00:00
Roy Marples
8a9a2d5fe9 Use snprintf instead of strlcpy to save on size if not available. 2009-01-12 08:31:03 +00:00
Roy Marples
a33554ab18 Copyright 2009-01-11 17:17:04 +00:00
Roy Marples
baf0ce64f5 Ensure that $HOME and $USER are always set, #139 2009-01-11 17:09:13 +00:00
Roy Marples
26f70a5277 Style 2009-01-10 12:18:00 +00:00
Roy Marples
36c53e7551 Keyword novserver, #137. 2009-01-06 16:25:33 +00:00
Roy Marples
5ca3345534 Release openrc-0.4.2 2009-01-05 20:16:50 +00:00
Roy Marples
0298e4ffa0 Remove leading and trailing space on the ctrl_interface line. 2009-01-05 09:37:38 +00:00
Roy Marples
a063035b37 Make _SVNVER_SH more readable. 2009-01-02 22:51:47 +00:00
Roy Marples
213cef1739 Fix version for releases. 2009-01-02 16:48:42 +00:00
Roy Marples
386ee57432 Fix compile, #136 2009-01-02 15:11:15 +00:00
Roy Marples
631acff7aa Document the --chuid option. 2009-01-01 14:32:09 +00:00
Roy Marples
877a328179 dmesg and sysfs won't work in a vserver, #137 thanks to Hollow. 2009-01-01 14:27:29 +00:00
Roy Marples
1efa64cae8 Typo. 2008-12-30 19:08:51 +00:00
Roy Marples
22959c3963 Fix working on zsh 2008-12-30 00:05:17 +00:00
Roy Marples
2464f9e93b Add parens, #134 thanks to Matthias Schwarzott. 2008-12-29 23:06:22 +00:00
Roy Marples
d91201cb94 Skip all forcefsck checking when stopping, #134. 2008-12-28 15:25:40 +00:00
Roy Marples
1c5ec9d161 Fake get_bootparam function so that we don't check for kernel options forcefsck when doing an fsck on shutdown. 2008-12-28 14:49:07 +00:00
Roy Marples
f4b8366942 Parse retry schedule correctly, #129. Thanks to vaeth. 2008-12-28 14:05:33 +00:00
Roy Marples
438665357b Release 0.4.1 2008-12-23 10:45:16 +00:00
Roy Marples
7ad40abf64 Our error messages don't have full stops at the end 2008-12-23 10:42:25 +00:00
Roy Marples
7e12abe035 Typo. 2008-12-23 10:41:33 +00:00
Roy Marples
4dba5b1ff1 Disallow hotplug to run during sysinit, but allow elsewhere. Fixes #131. 2008-12-23 10:40:27 +00:00
Roy Marples
1ff289e305 Whitespace. 2008-12-23 10:39:45 +00:00
Roy Marples
53e2bec385 We should match on the correct args for stopping daemons when pidfiles
are not being used.
2008-12-23 10:15:41 +00:00
Roy Marples
9d9f17aa52 Allow working with the new ctrl_iface=DIR=foo directive. 2008-12-23 10:13:58 +00:00
40 changed files with 403 additions and 280 deletions

View File

@@ -3,7 +3,7 @@
# All rights reserved. Released under the 2-clause BSD license.
NAME= openrc
VERSION= 0.4.0
VERSION= 0.4.2
PKG= ${NAME}-${VERSION}
SUBDIR= conf.d doc etc init.d man net sh src

View File

@@ -29,7 +29,7 @@ cleanup_tmp_dir()
if yesno ${wipe_tmp:-${WIPE_TMP:-yes}}; then
ebegin "Wiping ${dir} directory"
local startopts="-x . -depth"
[ "${RC_UNAME}" = "Linux" ] && startopts=". -xdev -depth"
[ "${RC_UNAME}" = Linux ] && startopts=". -xdev -depth"
# Faster than find
rm -rf -- [b-ikm-pr-zA-Z0-9\.]*
@@ -131,7 +131,7 @@ start()
if ${logw} || dir_writeable /var/log; then
# Create an 'after-boot' dmesg log
if [ "${RC_SYS}" != "VSERVER" -a "${RC_SYS}" != "OPENVZ" ]; then
if [ "${RC_SYS}" != VSERVER -a "${RC_SYS}" != OPENVZ ]; then
dmesg > /var/log/dmesg
chmod 640 /var/log/dmesg
fi
@@ -144,9 +144,12 @@ start()
stop()
{
# Write a halt record if we're shutting down
case "${RC_RUNLEVEL}" in
reboot|shutdown) [ "${RC_UNAME}" = "Linux" ] && halt -w;;
esac
if [ "${RC_RUNLEVEL}" = shutdown ]; then
[ "${RC_UNAME}" = Linux ] && halt -w
if [ "${RC_SYS}" = OPENVZ ]; then
yesno ${RC_REBOOT} && printf "" >/reboot
fi
fi
return 0
}

View File

@@ -6,7 +6,7 @@ description="Mount system critical filesystems in /dev."
depend() {
use dev
keyword noprefix
keyword noprefix novserver
}
start() {

View File

@@ -7,6 +7,7 @@ description="Set the dmesg level for a cleaner boot"
depend()
{
before dev modules
keyword novserver
}
start()

View File

@@ -25,6 +25,11 @@ _reboot() {
fi
}
_forcefsck()
{
[ -e /forcefsck ] || get_bootparam forcefsck
}
start()
{
local fsck_opts= p= check_extra=
@@ -33,7 +38,7 @@ start()
ewarn "Skipping fsck due to /fastboot"
return 0
fi
if [ -e /forcefsck ] || get_bootparam forcefsck; then
if _forcefsck; then
fsck_opts="${fsck_opts} -f"
check_extra="(check forced)"
fi
@@ -92,6 +97,7 @@ stop()
# Fake function so we always shutdown correctly.
_abort() { return 0; }
_reboot() { return 0; }
_forcefsck() { return 1; }
yesno "${fsck_shutdown}" && start
return 0

View File

@@ -595,7 +595,7 @@ ${routes}"
fi
fi
local OIFS="${IFS}" SIFS=${IFS-y}
local OIFS="${IFS}" SIFS="${IFS-y}"
local IFS="$__IFS"
for cmd in ${routes}; do
unset IFS

View File

@@ -1,11 +1,18 @@
#!@PREFIX@/sbin/runscript
# Copyright 2007-2008 Roy Marples <roy@marples.name>
# Copyright 2007-2009 Roy Marples <roy@marples.name>
# All rights reserved. Released under the 2-clause BSD license.
description="Saves the caches OpenRC uses to non volatile storage"
start()
{
if [ -e "${RC_SVCDIR}"/clock-skewed ]; then
ewarn "WARNING: clock skew detected!"
if ! yesno "savecache_skewed"; then
eerror "Not saving deptree cache"
return 1
fi
fi
ebegin "Saving dependency cache"
if [ ! -d "${RC_LIBDIR}"/cache ]; then
rm -rf "${RC_LIBDIR}"/cache

View File

@@ -6,7 +6,7 @@ description="Mount the sys filesystem."
depend()
{
keyword noprefix
keyword noprefix novserver
}
mount_sys()

View File

@@ -61,4 +61,4 @@ does the same and also prints the full path of the service to stdout.
.Xr rc 8 ,
.Xr stdout 3
.Sh AUTHORS
.An Roy Marples" <roy@marples.name>
.An Roy Marples <roy@marples.name>

View File

@@ -61,4 +61,4 @@ Show information only for the named
.Xr rc 8 ,
.Xr rc-update 8
.Sh AUTHORS
.An Roy Marples" <roy@marples.name>
.An Roy Marples <roy@marples.name>

View File

@@ -1,4 +1,4 @@
.\" Copyright 2007-2008 Roy Marples
.\" Copyright 2007-2009 Roy Marples
.\" All rights reserved
.\"
.\" 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
.\" SUCH DAMAGE.
.\"
.Dd Jan 15, 2008
.Dd Jan 10, 2009
.Dt RC-UPDATE 8 SMM
.Os OpenRC
.Sh NAME
@@ -38,6 +38,7 @@
.Ar service
.Op Ar runlevel ...
.Nm
.Op Fl u , -update
.Op Fl v , -verbose
.Ar show
.Op Ar runlevel ...
@@ -53,7 +54,7 @@ or
directories. They must also conform to the OpenRC runscript standard.
.Pp
.Bl -tag -width "Fl a , -delete service"
.It Fl a , -add Ar service
.It Ar add Ar service
Add the
.Ar service
to the
@@ -72,9 +73,13 @@ Show all enabled services and the runlevels they belong to. If you specify
runlevels to show, then only those will be included in the output.
.It Fl v , -verbose
Show all services.
.It Fl u , -update
Forces an update of the dependency tree cache.
This may be needed in the even of clock skew (a file in /etc is newer than the
system clock).
.El
.Sh SEE ALSO
.Xr rc 8 ,
.Xr rc-status 8
.Sh AUTHORS
.An Roy Marples" <roy@marples.name>
.An Roy Marples <roy@marples.name>

View File

@@ -1,4 +1,4 @@
.\" Copyright 2007-2008 Roy Marples
.\" Copyright 2007-2009 Roy Marples
.\" All rights reserved
.\"
.\" 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
.\" SUCH DAMAGE.
.\"
.Dd November 03, 2008
.Dd January 13, 2009
.Dt RC 8 SMM
.Os OpenRC
.Sh NAME
@@ -65,8 +65,10 @@ All services in the boot and sysinit runlevels are automatically included
in all other runlevels except for those listed here.
.It Ar single
Stops all services except for those in the sysinit runlevel.
.It Ar reboot
Changes to the shutdown runlevel and then reboots the host.
.It Ar shutdown
Changes to the single runlevel and then halts the host.
Changes to the shutdown runlevel and then halts the host.
.El
.Pp
You should not call any of these runlevels yourself.
@@ -81,4 +83,4 @@ and let them call these special runlevels.
.Xr init 8 ,
.Xr shutdown 8
.Sh AUTHORS
.An Roy Marples <roy@marples.name>
.An Roy Marples Aq roy@marples.name

View File

@@ -70,4 +70,4 @@ is set to
.Xr rc_stringlist_free 3 ,
.Xr sh 1
.Sh AUTHORS
.An Roy Marples" <roy@marples.name>
.An Roy Marples <roy@marples.name>

View File

@@ -110,4 +110,4 @@ when done.
.Xr rc_stringlist_free 3 ,
.Xr runscript 8
.Sh AUTHORS
.An Roy Marples" <roy@marples.name>
.An Roy Marples <roy@marples.name>

View File

@@ -67,4 +67,4 @@ Each RC_PID should be freed in the list as well as the list itself when done.
.Xr free 3 ,
.Xr queue 3
.Sh AUTHORS
.An Roy Marples" <roy@marples.name>
.An Roy Marples <roy@marples.name>

View File

@@ -48,4 +48,4 @@ Plugins can affect the parent environemnt by writing NULL separated strings to
.Xr rc 8 ,
.Xr runscript 8
.Sh AUTHORS
.An Roy Marples" <roy@marples.name>
.An Roy Marples <roy@marples.name>

View File

@@ -63,4 +63,4 @@ Rinse and repeat for the other verbose functions.
.Xr free 3
.Xr rc_stringlist_free 3
.Sh AUTHORS
.An Roy Marples" <roy@marples.name>
.An Roy Marples <roy@marples.name>

View File

@@ -227,4 +227,4 @@ normally holds the volatile state data for services on a RAM backed disk.
.Xr rc_stringlist_free 3 ,
.Xr start-stop-daemon 8
.Sh AUTHORS
.An Roy Marples" <roy@marples.name>
.An Roy Marples <roy@marples.name>

View File

@@ -85,4 +85,4 @@ itself.
.Xr queue 3 ,
.Xr strcmp 3
.Sh AUTHORS
.An Roy Marples" <roy@marples.name>
.An Roy Marples <roy@marples.name>

View File

@@ -461,4 +461,4 @@ Users are encouraged to use the is_newer_than function which returns correctly.
.Xr start-stop-daemon 8 ,
.Xr uname 1
.Sh AUTHORS
.An Roy Marples" <roy@marples.name>
.An Roy Marples <roy@marples.name>

View File

@@ -1,4 +1,4 @@
.\" Copyright 2007-2008 Roy Marples
.\" Copyright 2007-2009 Roy Marples
.\" All rights reserved
.\"
.\" 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
.\" SUCH DAMAGE.
.\"
.Dd September 27, 2008
.Dd January 1, 2009
.Dt START-STOP-DAEMON 8 SMM
.Os OpenRC
.Sh NAME
@@ -116,6 +116,10 @@ chdir to this directory before starting the daemon.
.It Fl r , -chroot Ar path
chroot to this directory before starting the daemon. All other paths, such
as the path to the daemon, chdir and pidfile, should be relative to the chroot.
.It Fl c , -chuid Ar user
Same as the
.Fl u , -user
option.
.It Fl e , -env Ar VAR=VALUE
Set the environment variable VAR to VALUE.
.It Fl g , -group Ar group
@@ -185,4 +189,4 @@ first appeared in Debian.
This is a complete re-implementation with the process finding code in the
OpenRC library (librc, -lrc) so other programs can make use of it.
.Sh AUTHORS
.An Roy Marples" <roy@marples.name>
.An Roy Marples <roy@marples.name>

View File

@@ -5,9 +5,28 @@
DISTPREFIX?= ${NAME}-${VERSION}
DISTFILE?= ${DISTPREFIX}.tar.bz2
CLEANFILES+= ${DISTFILE}
CLEANFILES+= ${NAME}-*.tar.bz2
_SNAP_SH= date -u +%Y%m%d%H%M
_SNAP!= ${_SNAP_SH}
SNAP= ${_SNAP}$(shell ${_SNAP_SH})
SNAPDIR= ${DISTPREFIX}-${SNAP}
SNAPFILE= ${SNAPDIR}.tar.bz2
dist:
svn export . ${DISTPREFIX}
tar cjpf ${DISTFILE} ${DISTPREFIX}
rm -rf ${DISTPREFIX}
snapshot:
rm -rf /tmp/${SNAPDIR}
mkdir /tmp/${SNAPDIR}
cp -RPp * /tmp/${SNAPDIR}
(cd /tmp/${SNAPDIR}; make clean)
find /tmp/${SNAPDIR} -name .svn -exec rm -rf -- {} \; 2>/dev/null || true
tar -cvjpf ${SNAPFILE} -C /tmp ${SNAPDIR}
rm -rf /tmp/${SNAPDIR}
ls -l ${SNAPFILE}
snap: snapshot

View File

@@ -1,4 +1,4 @@
# Copyright 2007-2008 Roy Marples <roy@marples.name>
# Copyright 2007-2009 Roy Marples <roy@marples.name>
# All rights reserved. Released under the 2-clause BSD license.
wpa_supplicant_depend()
@@ -45,7 +45,7 @@ fi
wpa_supplicant_pre_start()
{
local opts= cfgfile= ctrl_dir= wireless=true
local opts= cliopts= cfgfile= ctrl_dir= wireless=true
local wpas=/usr/sbin/wpa_supplicant wpac=/usr/bin/wpa_cli
local actfile=/etc/wpa_supplicant/wpa_cli.sh
@@ -57,6 +57,8 @@ wpa_supplicant_pre_start()
[ -e "${actfile}" ] || unset wpac
eval opts=\$wpa_supplicant_${IFVAR}
eval cliopts=\$wpa_cli_${IFVAR}
[ -z "${cliopts}" ] && cliopts=${wpa_cli}
case " ${opts} " in
*" -Dwired "*) wireless=false;;
*) _is_wireless || return 0;;
@@ -105,7 +107,15 @@ wpa_supplicant_pre_start()
fi
# Work out where the ctrl_interface dir is if it's not specified
local ctrl_dir=$(sed -n -e 's/[[:space:]]*#.*//g;s/[[:space:]]*$//g;s/^ctrl_interface=//p' "${cfgfile}")
local ctrl_dir=$(sed -e 's/^ *//' \
-e '/^ctrl_interface=/!d' \
-e 's/^ctrl_interface=//' \
-e 's/^ *//' \
-e 's/^DIR=//' \
-e 's/^ *//' \
-e 's/GROUP=.*//' \
-e 's/ *$//' \
"${cfgfile}")
if [ -z "${ctrl_dir}" ]; then
ctrl_dir=${opts##* -C}
if [ -n "${ctrl_dir}" -a "${ctrl_dir}" != "${opts}" ]; then
@@ -120,7 +130,6 @@ wpa_supplicant_pre_start()
fi
service_set_value ctrl_dir "${ctrl_dir}"
if [ -n "${wpac}" ]; then
opts="${opts} -W"
elif service_started devd; then
@@ -150,7 +159,7 @@ wpa_supplicant_pre_start()
ebegin "Starting wpa_cli on" "${IFACE}"
start-stop-daemon --start --exec "${wpac}" \
--pidfile "/var/run/wpa_cli-${IFACE}.pid" \
-- -a "${actfile}" -p "${ctrl_dir}" -i "${IFACE}" \
-- ${cliopts} -a "${actfile}" -p "${ctrl_dir}" -i "${IFACE}" \
-P "/var/run/wpa_cli-${IFACE}.pid" -B
if eend $?; then
ebegin "Backgrounding ..."

View File

@@ -1,19 +1,20 @@
# Copyright 2007-2008 Roy Marples <roy@marples.name>
# All rights reserved. Released under the 2-clause BSD license.
retval=0
# mount $svcdir as something we can write to if it's not rw
# mount $RC_SVCDIR as something we can write to if it's not rw
# On vservers, / is always rw at this point, so we need to clean out
# the old service state data
RC_SVCDIR=${RC_SVCDIR:-/@LIB@/rc/init.d}
if [ "${RC_SVCDIR}" != "/" ] && mkdir "${RC_SVCDIR}/.test.$$" 2>/dev/null; then
rmdir "${RC_SVCDIR}/.test.$$"
rm -rf "${RC_SVCDIR}"/*
else
mount_svcdir
retval=$?
fi
case "$(rc --sys)" in
OPENVZ|VSERVER) rm -rf "${RC_SVCDIR}"/*;;
*) if mountinfo --quiet "${RC_SVCDIR}"; then
rm -rf "${RC_SVCDIR}"/*
else
mount_svcdir
fi
;;
esac
retval=$?
if [ -e "${RC_LIBDIR}"/cache/deptree ]; then
cp -p "${RC_LIBDIR}"/cache/* "${RC_SVCDIR}" 2>/dev/null

View File

@@ -4,7 +4,7 @@
*/
/*
* Copyright 2007-2008 Roy Marples <roy@marples.name>
* Copyright 2007-2009 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,7 @@
#define RC_LEVEL_DEFAULT "default"
#define RC_DEPTREE_CACHE RC_SVCDIR "/deptree"
#define RC_DEPTREE_SKEWED RC_SVCDIR "/clock-skewed"
#define RC_KRUNLEVEL RC_SVCDIR "/krunlevel"
#define RC_STARTING RC_SVCDIR "/rc.starting"
#define RC_STOPPING RC_SVCDIR "/rc.stopping"
@@ -84,6 +85,11 @@
(var) = (tvar))
#endif
#ifdef __GLIBC__
# if ! defined (__UCLIBC__) && ! defined (__dietlibc__)
# define strlcpy(dst, src, size) snprintf(dst, size, "%s", src)
# endif
#endif
_unused static void *xmalloc (size_t size)
{

View File

@@ -4,7 +4,7 @@
*/
/*
* Copyright 2007-2008 Roy Marples <roy@marples.name>
* Copyright 2007-2009 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -31,32 +31,7 @@
#include "librc.h"
#ifdef __GLIBC__
# if ! defined (__UCLIBC__) && ! defined (__dietlibc__)
static size_t strlcpy(char *dst, const char *src, size_t size)
{
const char *s = src;
size_t n = size;
if (n && --n)
do {
if (!(*dst++ = *src++))
break;
} while (--n);
if (!n) {
if (size)
*dst = '\0';
while (*src++);
}
return src - s - 1;
}
# endif
#endif
#if defined(__linux__)
static bool pid_is_exec(pid_t pid, const char *exec)
{
char buffer[32];

View File

@@ -4,7 +4,7 @@
*/
/*
* Copyright 2007-2008 Roy Marples <roy@marples.name>
* Copyright 2007-2009 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -544,7 +544,8 @@ rc_deptree_order(const RC_DEPTREE *deptree, const char *runlevel, int options)
librc_hidden_def(rc_deptree_order)
static bool
mtime_check(const char *source, const char *target, bool newer)
mtime_check(const char *source, const char *target, bool newer,
time_t *rel, char *file)
{
struct stat buf;
time_t mtime;
@@ -565,16 +566,32 @@ mtime_check(const char *source, const char *target, bool newer)
if (newer) {
if (mtime < buf.st_mtime)
return false;
retval = false;
if (rel != NULL) {
if (*rel < buf.st_mtime) {
if (file)
strlcpy(file, target, PATH_MAX);
*rel = buf.st_mtime;
}
} else
return retval;
} else {
if (mtime > buf.st_mtime)
return false;
retval = false;
if (rel != NULL) {
if (*rel > buf.st_mtime) {
if (file)
strlcpy(file, target, PATH_MAX);
*rel = buf.st_mtime;
}
} else
return retval;
}
/* If not a dir then reset errno */
if (!(dp = opendir(target))) {
errno = serrno;
return true;
return retval;
}
/* Check all the entries in the dir */
@@ -582,26 +599,30 @@ mtime_check(const char *source, const char *target, bool newer)
if (d->d_name[0] == '.')
continue;
snprintf(path, sizeof(path), "%s/%s", target, d->d_name);
retval = mtime_check(source, path, newer);
if (!retval)
break;
if (!mtime_check(source, path, newer, rel, file)) {
retval = false;
if (rel == NULL)
break;
}
}
closedir(dp);
return retval;
}
bool
rc_newer_than(const char *source, const char *target)
rc_newer_than(const char *source, const char *target,
time_t *newest, char *file)
{
return mtime_check(source, target, true);
return mtime_check(source, target, true, newest, file);
}
librc_hidden_def(rc_newer_than)
bool
rc_older_than(const char *source, const char *target)
rc_older_than(const char *source, const char *target,
time_t *oldest, char *file)
{
return mtime_check(source, target, false);
return mtime_check(source, target, false, oldest, file);
}
librc_hidden_def(rc_older_than)
@@ -638,7 +659,7 @@ static const char *const depdirs[] =
};
bool
rc_deptree_update_needed(void)
rc_deptree_update_needed(time_t *newest, char *file)
{
bool newer = false;
RC_STRINGLIST *config;
@@ -652,31 +673,39 @@ rc_deptree_update_needed(void)
/* Quick test to see if anything we use has changed and we have
* data in our deptree */
if (!existss(RC_DEPTREE_CACHE) ||
!rc_newer_than(RC_DEPTREE_CACHE, RC_INITDIR) ||
!rc_newer_than(RC_DEPTREE_CACHE, RC_CONFDIR) ||
if (!existss(RC_DEPTREE_CACHE))
return true;
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_INITDIR, newest, file))
newer = true;
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_CONFDIR, newest, file))
newer = true;
#ifdef RC_PKG_INITDIR
!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_INITDIR) ||
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_INITDIR, newest, file))
newer = true;
#endif
#ifdef RC_PKG_CONFDIR
!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_CONFDIR) ||
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_CONFDIR, newest, file))
newer = true;
#endif
#ifdef RC_LOCAL_INITDIR
!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_INITDIR) ||
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_INITDIR, newest, file))
newer = true;
#endif
#ifdef RC_LOCAL_CONFDIR
!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_CONFDIR) ||
if (!rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_CONFDIR, newest, file))
newer = true;
#endif
!rc_newer_than(RC_DEPTREE_CACHE, "/etc/rc.conf"))
return true;
if (!rc_newer_than(RC_DEPTREE_CACHE, "/etc/rc.conf", newest, file))
newer = true;
/* Some init scripts dependencies change depending on config files
* outside of baselayout, like syslog-ng, so we check those too. */
config = rc_config_list(RC_DEPCONFIG);
TAILQ_FOREACH(s, config, entries) {
if (!rc_newer_than(RC_DEPTREE_CACHE, s->value)) {
if (!rc_newer_than(RC_DEPTREE_CACHE, s->value, newest, file)) {
newer = true;
break;
if (newest == NULL)
break;
}
}
rc_stringlist_free(config);

View File

@@ -66,7 +66,8 @@ ssize_t rc_getline(char **line, size_t *len, FILE *fp)
}
p = *line + last;
memset(p, 0, BUFSIZ);
fgets(p, BUFSIZ, fp);
if (fgets(p, BUFSIZ, fp) == NULL)
break;
last += strlen(p);
if (last && (*line)[last - 1] == '\n') {
(*line)[last - 1] = '\0';

View File

@@ -555,7 +555,8 @@ rc_service_mark(const char *service, const RC_SERVICE state)
RC_SVCDIR "/%s/%s",
rc_parse_service_state(RC_SERVICE_WASINACTIVE),
base);
symlink(init, was);
if (symlink(init, was) == -1)
return false;
skip_wasinactive = true;
}
if (unlink(file) == -1) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2007-2008 Roy Marples <roy@marples.name>
* Copyright 2007-2009 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -304,25 +304,37 @@ typedef void *RC_DEPTREE;
/*! Check to see if source is newer than target.
* If target is a directory then we traverse it and it's children.
* @return true if source is newer than target, otherwise false */
bool rc_newer_than(const char *, const char *);
* @param source
* @param target
* @param mtime of newest target
* @param filename of the newest target (needs mtime param)
* @return true if source is newer than target, otherwise false */
bool rc_newer_than(const char *, const char *, time_t *, char *);
/*! Check to see if source is newer than target.
/*! Check to see if source is older than target.
* If target is a directory then we traverse it and it's children.
* @return true if source is newer than target, otherwise false */
bool rc_older_than(const char *, const char *);
* @param source
* @param target
* @param mtime of oldest target
* @param filename of the oldest target (needs mtime param)
* @return true if source is older than target, otherwise false */
bool rc_older_than(const char *, const char *, time_t *, char *);
/*! Update the cached dependency tree if it's older than any init script,
* its configuration file or an external configuration file the init script
* has specified.
* time_t returns the time of the newest file that the dependency tree
* will be checked against.
* @return true if successful, otherwise false */
bool rc_deptree_update(void);
/*! Check if the cached dependency tree is older than any init script,
* its configuration file or an external configuration file the init script
* has specified.
* @param mtime of newest file
* @param buffer of PATH_MAX to store newest file
* @return true if it needs updating, otherwise false */
bool rc_deptree_update_needed(void);
bool rc_deptree_update_needed(time_t *, char *);
/*! Load the cached dependency tree and return a pointer to it.
* This pointer should be freed with rc_deptree_free when done.

View File

@@ -43,11 +43,12 @@ include ${MK}/${MKTERMCAP}.mk
LDADD+= ${LIBDL} ${LIBKVM}
include ${MK}/${MKPAM}.mk
_SVNVER_SH= if type svnversion >/dev/null 2>&1; then \
echo "-svn-$$(svnversion)"; \
else \
echo ""; \
fi
_SVNVER_SH= ret=""; \
if type svnversion >/dev/null 2>&1; then \
svnver="$$(LC_ALL=C svnversion)"; \
[ "$${svnver}" != exported ] && ret="-svn-$${svnver}"; \
fi; \
echo "$${ret}";
_SVNVER!= ${_SVNVER_SH}
SVNVER= ${_SVNVER}$(shell ${_SVNVER_SH})

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2007-2008 Roy Marples <roy@marples.name>
* Copyright 2007-2009 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -39,7 +39,7 @@ int start_stop_daemon(int, char **);
void run_applets(int, char **);
/* Handy function so we can wrap einfo around our deptree */
RC_DEPTREE *_rc_deptree_load (int *);
RC_DEPTREE *_rc_deptree_load (int, int *);
/* Test to see if we can see pid 1 or not */
bool _rc_can_find_pids(void);

View File

@@ -7,7 +7,7 @@
*/
/*
* Copyright 2007-2008 Roy Marples <roy@marples.name>
* Copyright 2007-2009 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -451,7 +451,7 @@ void run_applets(int argc, char **argv)
if (argc < 3)
exit (EXIT_FAILURE);
while (i < argc) {
if (!rc_newer_than(argv[1], argv[i++]))
if (!rc_newer_than(argv[1], argv[i++], NULL, NULL))
exit(EXIT_SUCCESS);
}
exit(EXIT_FAILURE);
@@ -461,7 +461,7 @@ void run_applets(int argc, char **argv)
if (argc < 3)
exit (EXIT_FAILURE);
while (i < argc) {
if (!rc_newer_than(argv[1], argv[i++]))
if (!rc_newer_than(argv[1], argv[i++], NULL, NULL))
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);

View File

@@ -4,7 +4,7 @@
*/
/*
* Copyright 2007-2008 Roy Marples <roy@marples.name>
* Copyright 2007-2009 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -29,17 +29,21 @@
* SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <getopt.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <utime.h>
#include "builtins.h"
#include "einfo.h"
@@ -49,13 +53,19 @@
extern const char *applet;
RC_DEPTREE *
_rc_deptree_load(int *regen) {
_rc_deptree_load(int force, int *regen) {
int fd;
int retval;
int serrno = errno;
int merrno;
time_t t;
char file[PATH_MAX];
struct stat st;
struct utimbuf ut;
FILE *fp;
if (rc_deptree_update_needed()) {
t = 0;
if (rc_deptree_update_needed(&t, file) || force != 0) {
/* Test if we have permission to update the deptree */
fd = open(RC_DEPTREE_CACHE, O_WRONLY);
merrno = errno;
@@ -67,8 +77,30 @@ _rc_deptree_load(int *regen) {
if (regen)
*regen = 1;
ebegin("Caching service dependencies");
retval = rc_deptree_update();
eend (retval ? 0 : -1, "Failed to update the dependency tree");
retval = rc_deptree_update() ? 0 : -1;
eend (retval, "Failed to update the dependency tree");
if (retval == 0) {
stat(RC_DEPTREE_CACHE, &st);
if (st.st_mtime < t) {
eerror("Clock skew detected with `%s'", file);
eerrorn("Adjusting mtime of `" RC_DEPTREE_CACHE
"' to %s", ctime(&t));
fp = fopen(RC_DEPTREE_SKEWED, "w");
if (fp != NULL) {
fprintf(fp, "%s\n", file);
fclose(fp);
}
ut.actime = t;
ut.modtime = t;
utime(RC_DEPTREE_CACHE, &ut);
} else {
if (exists(RC_DEPTREE_SKEWED))
unlink(RC_DEPTREE_SKEWED);
}
}
if (force == -1 && regen != NULL)
*regen = retval;
}
return rc_deptree_load();
}
@@ -104,9 +136,8 @@ rc_depend(int argc, char **argv)
RC_STRINGLIST *depends;
RC_STRING *s;
RC_DEPTREE *deptree = NULL;
int options = RC_DEP_TRACE;
int options = RC_DEP_TRACE, update = 0;
bool first = true;
bool update = false;
char *runlevel = xstrdup(getenv("RC_RUNLEVEL"));
int opt;
char *token;
@@ -130,7 +161,7 @@ rc_depend(int argc, char **argv)
rc_stringlist_add(types, token);
break;
case 'u':
update = true;
update = 1;
break;
case 'T':
options &= RC_DEP_TRACE;
@@ -140,15 +171,7 @@ rc_depend(int argc, char **argv)
}
}
if (update) {
ebegin("Caching service dependencies");
update = rc_deptree_update();
eend(update ? 0 : -1, "%s: %s", applet, strerror(errno));
if (!update)
eerrorx("Failed to update the dependency tree");
}
if (!(deptree = _rc_deptree_load(NULL)))
if (!(deptree = _rc_deptree_load(update, NULL)))
eerrorx("failed to load deptree");
if (!runlevel)

View File

@@ -112,11 +112,10 @@ rc_conf_yesno(const char *setting)
}
static const char *const env_whitelist[] = {
"PATH", "SHELL", "USER", "HOME", "TERM",
"CONSOLE", "PATH", "SHELL", "USER", "HOME", "TERM",
"LANG", "LC_CTYPE", "LC_NUMERIC", "LC_TIME", "LC_COLLATE",
"LC_MONETARY", "LC_MESSAGES", "LC_PAPER", "LC_NAME", "LC_ADDRESS",
"LC_TELEPHONE", "LC_MEASUREMENT", "LC_IDENTIFICATION", "LC_ALL",
"INIT_HALT", "INIT_VERSION", "RUNLEVEL", "PREVLEVEL", "CONSOLE",
"IN_HOTPLUG", "IN_BACKGROUND", "RC_INTERFACE_KEEP_CONFIG",
NULL
};

View File

@@ -4,7 +4,7 @@
*/
/*
* Copyright 2007-2008 Roy Marples <roy@marples.name>
* Copyright 2007-2009 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -140,7 +140,7 @@ print_services(const char *runlevel, RC_STRINGLIST *svcs)
if (!svcs)
return;
if (!deptree)
deptree = _rc_deptree_load(NULL);
deptree = _rc_deptree_load(0, NULL);
if (!deptree) {
TAILQ_FOREACH(s, svcs, entries)
if (!runlevel ||
@@ -260,7 +260,7 @@ rc_status(int argc, char **argv)
}
/* Output the services in the order in which they would start */
deptree = _rc_deptree_load(NULL);
deptree = _rc_deptree_load(0, NULL);
TAILQ_FOREACH(l, levels, entries) {
print_level(l->value);

View File

@@ -4,7 +4,7 @@
*/
/*
* Copyright 2007-2008 Roy Marples <roy@marples.name>
* Copyright 2007-2009 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -50,7 +50,8 @@ extern const char *applet;
* 0 = no changes (nothing to do)
* 1+ = number of runlevels updated
*/
static int add (const char *runlevel, const char *service)
static int
add(const char *runlevel, const char *service)
{
int retval = -1;
@@ -70,7 +71,8 @@ static int add (const char *runlevel, const char *service)
return retval;
}
static int delete (const char *runlevel, const char *service)
static int
delete(const char *runlevel, const char *service)
{
int retval = -1;
@@ -90,7 +92,8 @@ static int delete (const char *runlevel, const char *service)
return retval;
}
static void show (RC_STRINGLIST *runlevels, bool verbose)
static void
show(RC_STRINGLIST *runlevels, bool verbose)
{
RC_STRINGLIST *services = rc_services_in_runlevel(NULL);
RC_STRING *service;
@@ -135,11 +138,13 @@ static void show (RC_STRINGLIST *runlevels, bool verbose)
"Usage: rc-update [options] add service <runlevel>\n" \
" rc-update [options] del service <runlevel>\n" \
" rc-update [options] show"
#define getoptstring getoptstring_COMMON
#define getoptstring "u" getoptstring_COMMON
static const struct option longopts[] = {
{ "update", 0, NULL, 'u' },
longopts_COMMON
};
static const char * const longopts_help[] = {
"Force an update of the dependency tree",
longopts_help_COMMON
};
#include "_usage.c"
@@ -148,7 +153,8 @@ static const char * const longopts_help[] = {
#define DODELETE (1 << 2)
#define DOSHOW (1 << 3)
int rc_update(int argc, char **argv)
int
rc_update(int argc, char **argv)
{
RC_STRINGLIST *runlevels;
RC_STRING *runlevel;
@@ -163,8 +169,11 @@ int rc_update(int argc, char **argv)
int ret;
while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *) 0)) != -1)
longopts, (int *)0)) != -1)
switch (opt) {
case 'u':
_rc_deptree_load(-1, &ret);
return ret;
case_RC_COMMON_GETOPT
}
@@ -189,7 +198,7 @@ int rc_update(int argc, char **argv)
else
eerrorx("%s: invalid command `%s'", applet, argv[optind]);
}
if (! action)
if (!action)
action = DOSHOW;
runlevels = rc_stringlist_new();
@@ -215,14 +224,14 @@ int rc_update(int argc, char **argv)
if (action & DOSHOW) {
if (service)
rc_stringlist_add(runlevels, service);
if (! TAILQ_FIRST(runlevels)) {
if (!TAILQ_FIRST(runlevels)) {
free(runlevels);
runlevels = rc_runlevel_list();
}
show (runlevels, verbose);
} else {
if (! service)
if (!service)
eerror ("%s: no service specified", applet);
else {
if (action & DOADD) {
@@ -231,22 +240,22 @@ int rc_update(int argc, char **argv)
actfunc = delete;
} else {
rc_stringlist_free(runlevels);
eerrorx ("%s: invalid action", applet);
eerrorx("%s: invalid action", applet);
}
if (! TAILQ_FIRST(runlevels)) {
if (!TAILQ_FIRST(runlevels)) {
p = rc_runlevel_get();
rc_stringlist_add(runlevels, p);
free(p);
}
if (! TAILQ_FIRST(runlevels)) {
if (!TAILQ_FIRST(runlevels)) {
free(runlevels);
eerrorx ("%s: no runlevels found", applet);
}
TAILQ_FOREACH (runlevel, runlevels, entries) {
if (! rc_runlevel_exists(runlevel->value)) {
TAILQ_FOREACH(runlevel, runlevels, entries) {
if (!rc_runlevel_exists(runlevel->value)) {
eerror ("%s: runlevel `%s' does not exist",
applet, runlevel->value);
continue;

View File

@@ -9,7 +9,7 @@
*/
/*
* Copyright 2007-2008 Roy Marples <roy@marples.name>
* Copyright 2007-2009 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -842,10 +842,14 @@ main(int argc, char **argv)
}
newlevel = argv[optind++];
/* For compat with old system */
/* To make life easier, we only have the shutdown runlevel as
* nothing really needs to know that we're rebooting.
* But for those that do, you can test against RC_REBOOT. */
if (newlevel) {
if (strcmp(newlevel, "reboot") == 0)
if (strcmp(newlevel, "reboot") == 0) {
newlevel = UNCONST(RC_LEVEL_SHUTDOWN);
setenv("RC_REBOOT", "YES", 1);
}
}
/* Enable logging */
@@ -918,8 +922,8 @@ main(int argc, char **argv)
free(p);
}
}
}
#endif
}
}
if (going_down) {
@@ -944,8 +948,10 @@ main(int argc, char **argv)
}
/* Load our deptree */
if ((deptree = _rc_deptree_load(&regen)) == NULL)
if ((deptree = _rc_deptree_load(0, &regen)) == NULL)
eerrorx("failed to load deptree");
if (exists(RC_DEPTREE_SKEWED))
ewarn("WARNING: clock skew detected!");
/* Clean the failed services state dir */
clean_failed();
@@ -1062,7 +1068,7 @@ main(int argc, char **argv)
#ifdef __linux__
/* mark any services skipped as started */
proc = p = proc_getent("noinitd");
proc = p = proc_getent("noinit");
if (proc) {
while ((token = strsep(&p, ",")))
rc_service_mark(token, RC_SERVICE_STARTED);
@@ -1083,7 +1089,7 @@ main(int argc, char **argv)
#ifdef __linux__
/* mark any services skipped as stopped */
proc = p = proc_getent("noinitd");
proc = p = proc_getent("noinit");
if (proc) {
while ((token = strsep(&p, ",")))
rc_service_mark(token, RC_SERVICE_STOPPED);

View File

@@ -4,7 +4,7 @@
*/
/*
* Copyright 2007-2008 Roy Marples <roy@marples.name>
* Copyright 2007-2009 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -717,9 +717,9 @@ svc_start(bool deps)
exit(EXIT_FAILURE);
background = true;
rc_service_mark(service, RC_SERVICE_HOTPLUGGED);
if (rc_runlevel_starting())
ewarnx("WARNING: %s will be started when the runlevel"
" has finished.", applet);
if (strcmp(runlevel, RC_LEVEL_SYSINIT) == 0)
ewarnx("WARNING: %s will be started in the"
" next runlevel", applet);
}
if (state & RC_SERVICE_STARTED) {
@@ -748,7 +748,7 @@ svc_start(bool deps)
depoptions |= RC_DEP_STRICT;
if (deps) {
if (!deptree && ((deptree = _rc_deptree_load(NULL)) == NULL))
if (!deptree && ((deptree = _rc_deptree_load(0, NULL)) == NULL))
eerrorx("failed to load deptree");
if (!types_b)
setup_types();
@@ -977,7 +977,7 @@ svc_stop(bool deps)
if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT)
depoptions |= RC_DEP_STRICT;
if (!deptree && ((deptree = _rc_deptree_load(NULL)) == NULL))
if (!deptree && ((deptree = _rc_deptree_load(0, NULL)) == NULL))
eerrorx("failed to load deptree");
if (!types_m)
@@ -1236,7 +1236,7 @@ runscript(int argc, char **argv)
/* Change dir to / to ensure all init scripts don't use stuff in pwd */
chdir("/");
if ((runlevel = xstrdup (getenv ("RC_RUNLEVEL"))) == NULL) {
if ((runlevel = xstrdup(getenv("RC_RUNLEVEL"))) == NULL) {
env_filter();
env_config();
runlevel = rc_runlevel_get();
@@ -1289,7 +1289,7 @@ runscript(int argc, char **argv)
longopts, (int *)0)) != -1)
switch (opt) {
case 'd':
setenv("RC_DEBUG", "yes", 1);
setenv("RC_DEBUG", "YES", 1);
break;
case 's':
if (!(rc_service_state(service) & RC_SERVICE_STARTED))
@@ -1368,7 +1368,7 @@ runscript(int argc, char **argv)
depoptions |= RC_DEP_STRICT;
if (!deptree &&
((deptree = _rc_deptree_load(NULL)) == NULL))
((deptree = _rc_deptree_load(0, NULL)) == NULL))
eerrorx("failed to load deptree");
tmplist = rc_stringlist_new();

View File

@@ -8,7 +8,7 @@
*/
/*
* Copyright 2007-2008 Roy Marples <roy@marples.name>
* Copyright 2007-2009 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
@@ -368,6 +368,7 @@ static int run_stop_schedule(const char *exec, const char *const *argv,
long nloops;
struct timespec ts;
pid_t pid = 0;
const char *const *p;
if (verbose) {
if (exec)
@@ -376,8 +377,15 @@ static int run_stop_schedule(const char *exec, const char *const *argv,
einfo("Will stop PID in pidfile `%s'", pidfile);
if (uid)
einfo("Will stop processes owned by UID %d", uid);
if (argv && *argv)
einfo("Will stop processes of `%s'", *argv);
if (argv && *argv) {
einfon("Will stop processes of `");
for (p = argv; p && *p; p++) {
if (p != argv)
printf(" ");
printf("%s", *p);
}
printf("'\n");
}
}
if (pidfile) {
@@ -618,6 +626,7 @@ int start_stop_daemon(int argc, char **argv)
char *startas = NULL;
char *name = NULL;
char *pidfile = NULL;
char *retry = NULL;
int sig = 0;
int nicelevel = 0;
bool background = false;
@@ -636,8 +645,6 @@ int start_stop_daemon(int argc, char **argv)
RC_STRINGLIST *env_list;
RC_STRING *env;
char *tmp, *newpath, *np;
bool sethome = false;
bool setuser = false;
char *p;
char *token;
char exec_file[PATH_MAX];
@@ -665,12 +672,19 @@ int start_stop_daemon(int argc, char **argv)
eerror("%s: invalid nice level `%s' (SSD_NICELEVEL)",
applet, tmp);
/* Get our initial dir */
/* Get our user name and initial dir */
p = getenv("USER");
home = getenv("HOME");
if (!home) {
if (home == NULL || p == NULL) {
pw = getpwuid(getuid());
if (pw)
home = pw->pw_dir;
if (pw != NULL) {
if (p == NULL)
setenv("USER", pw->pw_name, 1);
if (home == NULL) {
setenv("HOME", pw->pw_dir, 1);
home = pw->pw_dir;
}
}
}
while ((opt = getopt_long(argc, argv, getoptstring, longopts,
@@ -686,7 +700,7 @@ int start_stop_daemon(int argc, char **argv)
break;
case 'R': /* --retry <schedule>|<timeout> */
parse_schedule(optarg, sig);
retry = optarg;
break;
case 'S': /* --start */
@@ -706,14 +720,20 @@ int start_stop_daemon(int argc, char **argv)
if (sscanf(tmp, "%d", &tid) != 1)
pw = getpwnam(tmp);
else
pw = getpwuid((uid_t) tid);
pw = getpwuid((uid_t)tid);
if (!pw)
if (pw == NULL)
eerrorx("%s: user `%s' not found",
applet, tmp);
uid = pw->pw_uid;
home = pw->pw_dir;
if (!gid)
unsetenv("HOME");
if (pw->pw_dir)
setenv("HOME", pw->pw_dir, 1);
unsetenv("USER");
if (pw->pw_name)
setenv("USER", pw->pw_name, 1);
if (gid == 0)
gid = pw->pw_gid;
if (p) {
@@ -723,7 +743,7 @@ int start_stop_daemon(int argc, char **argv)
else
gr = getgrgid((gid_t) tid);
if (!gr)
if (gr == NULL)
eerrorx("%s: group `%s'"
" not found",
applet, tmp);
@@ -737,27 +757,18 @@ int start_stop_daemon(int argc, char **argv)
break;
case 'e': /* --env */
if (putenv(optarg) == 0) {
if (strncmp("HOME=", optarg, 5) == 0) {
sethome = true;
home = strchr(optarg, '=') + 1;
} else if (strncmp("USER=", optarg, 5) == 0)
setuser = true;
}
putenv(optarg);
break;
case 'g': /* --group <group>|<gid> */
{
if (sscanf(optarg, "%d", &tid) != 1)
gr = getgrnam(optarg);
else
gr = getgrgid((gid_t) tid);
if (!gr)
eerrorx("%s: group `%s' not found",
applet, optarg);
gid = gr->gr_gid;
}
if (sscanf(optarg, "%d", &tid) != 1)
gr = getgrnam(optarg);
else
gr = getgrgid((gid_t)tid);
if (gr == NULL)
eerrorx("%s: group `%s' not found",
applet, optarg);
gid = gr->gr_gid;
break;
case 'k':
@@ -840,13 +851,15 @@ int start_stop_daemon(int argc, char **argv)
exec = name;
if (name && start)
*argv = name;
} else if (name && (start || **argv))
} else if (name)
*--argv = name;
else
else if (exec)
*--argv = exec;
if (stop || sig) {
if ( !*argv && !pidfile && !name && !uid)
if (stop || sig != 0) {
if (sig == 0)
sig = SIGTERM;
if (!*argv && !pidfile && !name && !uid)
eerrorx("%s: --stop needs --exec, --pidfile,"
" --name or --user", applet);
if (background)
@@ -869,70 +882,44 @@ int start_stop_daemon(int argc, char **argv)
" with --background", applet);
}
if (stop || sig) {
if (!sig)
sig = SIGTERM;
if (!stop)
oknodo = true;
if (!TAILQ_FIRST(&schedule)) {
if (test || oknodo)
parse_schedule("0", sig);
else
parse_schedule(NULL, sig);
}
i = run_stop_schedule(exec, (const char *const *)argv,
pidfile, uid, quiet, verbose, test);
if (i < 0)
/* We failed to stop something */
exit(EXIT_FAILURE);
if (test || oknodo)
return i > 0 ? EXIT_SUCCESS : EXIT_FAILURE;
/* Even if we have not actually killed anything, we should
* remove information about it as it may have unexpectedly
* crashed out. We should also return success as the end
* result would be the same. */
if (pidfile && exists(pidfile))
unlink(pidfile);
if (svcname)
rc_service_daemon_set(svcname, exec,
(const char *const *)argv,
pidfile, false);
exit(EXIT_SUCCESS);
}
/* Expand ~ */
if (ch_dir && *ch_dir == '~')
ch_dir = expand_home(home, ch_dir);
if (ch_root && *ch_root == '~')
ch_root = expand_home(home, ch_root);
if (*exec == '~')
exec = expand_home(home, exec);
if (exec) {
if (*exec == '~')
exec = expand_home(home, exec);
/* Validate that the binary exists if we are starting */
if (*exec == '/' || *exec == '.') {
/* Full or relative path */
if (ch_root)
snprintf(exec_file, sizeof(exec_file), "%s/%s", ch_root, exec);
else
snprintf(exec_file, sizeof(exec_file), "%s", exec);
} else {
/* Something in $PATH */
p = tmp = xstrdup(getenv("PATH"));
*exec_file = '\0';
while ((token = strsep(&p, ":"))) {
/* Validate that the binary exists if we are starting */
if (*exec == '/' || *exec == '.') {
/* Full or relative path */
if (ch_root)
snprintf(exec_file, sizeof(exec_file), "%s/%s/%s", ch_root, token, exec);
snprintf(exec_file, sizeof(exec_file),
"%s/%s", ch_root, exec);
else
snprintf(exec_file, sizeof(exec_file), "%s/%s", token, exec);
if (exists(exec_file))
break;
snprintf(exec_file, sizeof(exec_file),
"%s", exec);
} else {
/* Something in $PATH */
p = tmp = xstrdup(getenv("PATH"));
*exec_file = '\0';
while ((token = strsep(&p, ":"))) {
if (ch_root)
snprintf(exec_file, sizeof(exec_file),
"%s/%s/%s",
ch_root, token, exec);
else
snprintf(exec_file, sizeof(exec_file),
"%s/%s", token, exec);
if (exists(exec_file))
break;
*exec_file = '\0';
}
free(tmp);
}
free(tmp);
}
if (!exists(exec_file)) {
if (start && !exists(exec_file)) {
eerror("%s: %s does not exist", applet,
*exec_file ? exec_file : exec);
exit(EXIT_FAILURE);
@@ -971,9 +958,41 @@ int start_stop_daemon(int argc, char **argv)
}
}
}
margv = nav ? nav : argv;
if (stop || sig) {
if (sig == 0)
sig = SIGTERM;
if (!stop)
oknodo = true;
if (retry)
parse_schedule(retry, sig);
else if (test || oknodo)
parse_schedule("0", sig);
else
parse_schedule(NULL, sig);
i = run_stop_schedule(exec, (const char *const *)margv,
pidfile, uid, quiet, verbose, test);
if (i < 0)
/* We failed to stop something */
exit(EXIT_FAILURE);
if (test || oknodo)
return i > 0 ? EXIT_SUCCESS : EXIT_FAILURE;
/* Even if we have not actually killed anything, we should
* remove information about it as it may have unexpectedly
* crashed out. We should also return success as the end
* result would be the same. */
if (pidfile && exists(pidfile))
unlink(pidfile);
if (svcname)
rc_service_daemon_set(svcname, exec,
(const char *const *)argv,
pidfile, false);
exit(EXIT_SUCCESS);
}
if (pidfile)
pid = get_pid(pidfile, true);
else
@@ -1072,23 +1091,8 @@ int start_stop_daemon(int argc, char **argv)
eerrorx("%s: unable to set groupid to %d", applet, gid);
if (changeuser && initgroups(changeuser, gid))
eerrorx("%s: initgroups (%s, %d)", applet, changeuser, gid);
if (uid) {
if (setuid(uid))
eerrorx ("%s: unable to set userid to %d", applet, uid);
pw = getpwuid(uid);
if (pw) {
if (!sethome) {
unsetenv("HOME");
if (pw->pw_dir)
setenv("HOME", pw->pw_dir, 1);
}
if (!setuser) {
unsetenv("USER");
if (pw->pw_name)
setenv("USER", pw->pw_name, 1);
}
}
}
if (uid && setuid(uid))
eerrorx ("%s: unable to set userid to %d", applet, uid);
/* Close any fd's to the passwd database */
endpwent();