Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01c34c28e6 | ||
|
|
56ddda54b5 | ||
|
|
3a803b3135 | ||
|
|
72df51e17b | ||
|
|
b2f5531194 | ||
|
|
19bf49a710 | ||
|
|
64354831da | ||
|
|
e14edd765f | ||
|
|
f9d41243d8 | ||
|
|
be7ad06d4a | ||
|
|
a616516895 | ||
|
|
04721ece03 | ||
|
|
c7e8f1133a | ||
|
|
47e4bfae57 | ||
|
|
8a945194af | ||
|
|
aa4a004c29 | ||
|
|
9ec5d36bdd | ||
|
|
a097933eda | ||
|
|
a6f5b1bb63 | ||
|
|
e6d01471fe | ||
|
|
d4501a9f06 | ||
|
|
ec8abea460 | ||
|
|
e4ddfa38e0 | ||
|
|
21d30bc6d9 | ||
|
|
2a1ff6e49c | ||
|
|
6762cb875c | ||
|
|
6edf516a1f | ||
|
|
7e56a49e23 | ||
|
|
fa5aea80c5 | ||
|
|
0f4fa41574 | ||
|
|
5d6dd97bba | ||
|
|
37e2944272 | ||
|
|
4e0eace837 | ||
|
|
faa8318b3b | ||
|
|
08da36149c | ||
|
|
56870d0db1 | ||
|
|
4d47ce440c | ||
|
|
958f57d895 | ||
|
|
04886efd85 | ||
|
|
d980798d64 | ||
|
|
414a9aae6c | ||
|
|
a7f475ca04 | ||
|
|
3c53680018 | ||
|
|
f0ad647303 | ||
|
|
b35e03b6b1 | ||
|
|
2b1392af2f | ||
|
|
a3d0e293ee | ||
|
|
0200002b8c | ||
|
|
f4e2142089 | ||
|
|
49a90f27a8 | ||
|
|
2ae60ca041 | ||
|
|
6b475ab269 | ||
|
|
b302b0c094 | ||
|
|
40aa69cf3a | ||
|
|
5346fbf2c9 | ||
|
|
92e6bdee12 | ||
|
|
71f275b2aa | ||
|
|
6dc0d0af33 | ||
|
|
59a9e53378 | ||
|
|
122768d339 | ||
|
|
fa3c60c0d8 | ||
|
|
61905bfcf5 | ||
|
|
3e68013631 | ||
|
|
b46123f2e1 | ||
|
|
109869641f | ||
|
|
e8a2305de0 |
@@ -1,3 +1,3 @@
|
|||||||
NAME= openrc
|
NAME= openrc
|
||||||
VERSION= 0.35
|
VERSION= 0.38
|
||||||
PKG= ${NAME}-${VERSION}
|
PKG= ${NAME}-${VERSION}
|
||||||
|
|||||||
23
NEWS.md
23
NEWS.md
@@ -4,6 +4,29 @@ OpenRC NEWS
|
|||||||
This file will contain a list of notable changes for each release. Note
|
This file will contain a list of notable changes for each release. Note
|
||||||
the information in this file is in reverse order.
|
the information in this file is in reverse order.
|
||||||
|
|
||||||
|
## OpenRC 0.37
|
||||||
|
|
||||||
|
start-stop-daemon now supports logging stdout and stderr of daemons to
|
||||||
|
processes instead of files. These processes are defined by the
|
||||||
|
output_logger and error_logger variables in standard service scripts, or
|
||||||
|
by the -3/--output-logger or -4/--error-logger switches if you use
|
||||||
|
start-stop-daemon directly. For more information on this, see the
|
||||||
|
start-stop-daemon man page.
|
||||||
|
|
||||||
|
## OpenRC 0.36
|
||||||
|
|
||||||
|
In this release, the modules-load service has been combined into the
|
||||||
|
modules service since there is no reason I know of to keep them
|
||||||
|
separate. However, modules also provides modules-load in case you were
|
||||||
|
using modules-load in your dependencies.
|
||||||
|
|
||||||
|
The consolefont, keymaps, numlock and procfs service scripts no longer
|
||||||
|
have a dependency on localmount.
|
||||||
|
If you are a linux user and are still separaating / from /usr,
|
||||||
|
you will need to add the following line to the appropriate conf.d files:
|
||||||
|
|
||||||
|
rc_need="localmount"
|
||||||
|
|
||||||
## OpenRC 0.35
|
## OpenRC 0.35
|
||||||
|
|
||||||
In this version, the cgroups mounting logic has been moved from the
|
In this version, the cgroups mounting logic has been moved from the
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ SRCS-FreeBSD= hostid.in modules.in moused.in newsyslog.in pf.in rarpd.in \
|
|||||||
rc-enabled.in rpcbind.in savecore.in syslogd.in
|
rc-enabled.in rpcbind.in savecore.in syslogd.in
|
||||||
# These are FreeBSD specific
|
# These are FreeBSD specific
|
||||||
SRCS-FreeBSD+= adjkerntz.in devd.in dumpon.in encswap.in ipfw.in \
|
SRCS-FreeBSD+= adjkerntz.in devd.in dumpon.in encswap.in ipfw.in \
|
||||||
modules-load.in mixer.in nscd.in powerd.in syscons.in
|
mixer.in nscd.in powerd.in syscons.in
|
||||||
|
|
||||||
SRCS-Linux= agetty.in binfmt.in devfs.in cgroups.in dmesg.in hwclock.in \
|
SRCS-Linux= agetty.in binfmt.in devfs.in cgroups.in dmesg.in hwclock.in \
|
||||||
consolefont.in keymaps.in killprocs.in modules.in modules-load.in \
|
consolefont.in keymaps.in killprocs.in modules.in \
|
||||||
mount-ro.in mtab.in numlock.in procfs.in net-online.in sysfs.in \
|
mount-ro.in mtab.in numlock.in procfs.in net-online.in sysfs.in \
|
||||||
termencoding.in
|
termencoding.in
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ term_type="${term_type:-linux}"
|
|||||||
command=/sbin/agetty
|
command=/sbin/agetty
|
||||||
command_args_foreground="${agetty_options} ${port} ${baud} ${term_type}"
|
command_args_foreground="${agetty_options} ${port} ${baud} ${term_type}"
|
||||||
pidfile="/run/${RC_SVCNAME}.pid"
|
pidfile="/run/${RC_SVCNAME}.pid"
|
||||||
export EINFO_QUIET="${quiet:-yes}"
|
|
||||||
|
|
||||||
depend() {
|
depend() {
|
||||||
after local
|
after local
|
||||||
@@ -29,5 +28,12 @@ start_pre() {
|
|||||||
eerror "symbolic links to it for the ports you want to start"
|
eerror "symbolic links to it for the ports you want to start"
|
||||||
eerror "agetty on and add those to the appropriate runlevels."
|
eerror "agetty on and add those to the appropriate runlevels."
|
||||||
return 1
|
return 1
|
||||||
|
else
|
||||||
|
export EINFO_QUIET="${quiet:-yes}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stop_pre()
|
||||||
|
{
|
||||||
|
export EINFO_QUIET="${quiet:-yes}"
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ description="Sets a font for the consoles."
|
|||||||
|
|
||||||
depend()
|
depend()
|
||||||
{
|
{
|
||||||
need localmount termencoding
|
need termencoding
|
||||||
after hotplug bootmisc modules
|
after hotplug bootmisc modules
|
||||||
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
|
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ description="Applies a keymap for the consoles."
|
|||||||
|
|
||||||
depend()
|
depend()
|
||||||
{
|
{
|
||||||
need localmount termencoding
|
need termencoding
|
||||||
after bootmisc clock
|
after bootmisc clock
|
||||||
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
|
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
#!@SBINDIR@/openrc-run
|
|
||||||
# Copyright (c) 2016 The OpenRC Authors.
|
|
||||||
# See the Authors file at the top-level directory of this distribution and
|
|
||||||
# https://github.com/OpenRC/openrc/blob/master/AUTHORS
|
|
||||||
#
|
|
||||||
# This file is part of OpenRC. It is subject to the license terms in
|
|
||||||
# the LICENSE file found in the top-level directory of this
|
|
||||||
# distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
|
|
||||||
# This file may not be copied, modified, propagated, or distributed
|
|
||||||
# except according to the terms contained in the LICENSE file.
|
|
||||||
|
|
||||||
description="Loads a list of modules from systemd-compatible locations."
|
|
||||||
|
|
||||||
depend()
|
|
||||||
{
|
|
||||||
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
|
|
||||||
}
|
|
||||||
|
|
||||||
find_modfiles()
|
|
||||||
{
|
|
||||||
local dirs="/usr/lib/modules-load.d /run/modules-load.d /etc/modules-load.d"
|
|
||||||
local basenames files fn x y
|
|
||||||
for x in $dirs; do
|
|
||||||
[ ! -d $x ] && continue
|
|
||||||
for y in $x/*.conf; do
|
|
||||||
[ -f $y ] && basenames="${basenames}\n${y##*/}"
|
|
||||||
done
|
|
||||||
done
|
|
||||||
basenames=$(printf "$basenames" | sort -u)
|
|
||||||
for x in $basenames; do
|
|
||||||
for y in $dirs; do
|
|
||||||
[ -r $y/$x ] &&
|
|
||||||
fn=$y/$x
|
|
||||||
done
|
|
||||||
files="$files $fn"
|
|
||||||
done
|
|
||||||
echo $files
|
|
||||||
}
|
|
||||||
|
|
||||||
load_modules()
|
|
||||||
{
|
|
||||||
local file m modules rc x
|
|
||||||
file=$1
|
|
||||||
[ -z "$file" ] && return 0
|
|
||||||
while read m x; do
|
|
||||||
case $m in
|
|
||||||
\;*) continue ;;
|
|
||||||
\#*) continue ;;
|
|
||||||
*) modules="$modules $m"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done < $file
|
|
||||||
for x in $modules; do
|
|
||||||
ebegin "Loading module $x"
|
|
||||||
case "$RC_UNAME" in
|
|
||||||
FreeBSD) kldload "$x"; rc=$? ;;
|
|
||||||
Linux) modprobe --use-blacklist -q "$x"; rc=$? ;;
|
|
||||||
*) ;;
|
|
||||||
esac
|
|
||||||
eend $rc "Failed to load $x"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
start()
|
|
||||||
{
|
|
||||||
local x
|
|
||||||
files=$(find_modfiles)
|
|
||||||
for x in $files; do
|
|
||||||
load_modules $x
|
|
||||||
done
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
@@ -14,10 +14,65 @@ description="Loads a user defined list of kernel modules."
|
|||||||
depend()
|
depend()
|
||||||
{
|
{
|
||||||
use isapnp
|
use isapnp
|
||||||
want modules-load
|
provide modules-load
|
||||||
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
|
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
find_modfiles()
|
||||||
|
{
|
||||||
|
local dirs="/usr/lib/modules-load.d /run/modules-load.d /etc/modules-load.d"
|
||||||
|
local basenames files fn x y
|
||||||
|
for x in $dirs; do
|
||||||
|
[ ! -d $x ] && continue
|
||||||
|
for y in $x/*.conf; do
|
||||||
|
[ -f $y ] && basenames="${basenames}\n${y##*/}"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
basenames=$(printf "$basenames" | sort -u)
|
||||||
|
for x in $basenames; do
|
||||||
|
for y in $dirs; do
|
||||||
|
[ -r $y/$x ] &&
|
||||||
|
fn=$y/$x
|
||||||
|
done
|
||||||
|
files="$files $fn"
|
||||||
|
done
|
||||||
|
echo $files
|
||||||
|
}
|
||||||
|
|
||||||
|
load_modules()
|
||||||
|
{
|
||||||
|
local file m modules rc x
|
||||||
|
file=$1
|
||||||
|
[ -z "$file" ] && return 0
|
||||||
|
while read m x; do
|
||||||
|
case $m in
|
||||||
|
\;*) continue ;;
|
||||||
|
\#*) continue ;;
|
||||||
|
*) modules="$modules $m"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done < $file
|
||||||
|
for x in $modules; do
|
||||||
|
ebegin "Loading module $x"
|
||||||
|
case "$RC_UNAME" in
|
||||||
|
FreeBSD) kldload "$x"; rc=$? ;;
|
||||||
|
Linux) modprobe --use-blacklist -q "$x"; rc=$? ;;
|
||||||
|
*) ;;
|
||||||
|
esac
|
||||||
|
eend $rc "Failed to load $x"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
modules_load_d()
|
||||||
|
{
|
||||||
|
local x
|
||||||
|
files=$(find_modfiles)
|
||||||
|
for x in $files; do
|
||||||
|
load_modules $x
|
||||||
|
done
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
FreeBSD_modules()
|
FreeBSD_modules()
|
||||||
{
|
{
|
||||||
local cnt=0 x
|
local cnt=0 x
|
||||||
@@ -82,7 +137,10 @@ Linux_modules()
|
|||||||
start()
|
start()
|
||||||
{
|
{
|
||||||
case "$RC_UNAME" in
|
case "$RC_UNAME" in
|
||||||
FreeBSD|Linux) ${RC_UNAME}_modules ;;
|
FreeBSD|Linux)
|
||||||
|
modules_load_d
|
||||||
|
${RC_UNAME}_modules
|
||||||
|
;;
|
||||||
*) ;;
|
*) ;;
|
||||||
esac
|
esac
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ description="Delays until the network is online or a specific timeout"
|
|||||||
|
|
||||||
depend()
|
depend()
|
||||||
{
|
{
|
||||||
after modules
|
after modules net
|
||||||
need sysfs
|
need sysfs
|
||||||
provide network-online
|
provide network-online
|
||||||
keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -uml -vserver
|
keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -uml -vserver
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ ttyn=${rc_tty_number:-${RC_TTY_NUMBER:-12}}
|
|||||||
|
|
||||||
depend()
|
depend()
|
||||||
{
|
{
|
||||||
need localmount
|
|
||||||
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
|
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ depend()
|
|||||||
after clock
|
after clock
|
||||||
use devfs
|
use devfs
|
||||||
want modules
|
want modules
|
||||||
need localmount
|
|
||||||
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
|
keyword -docker -lxc -openvz -prefix -systemd-nspawn -vserver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ start()
|
|||||||
fi
|
fi
|
||||||
ebegin "Saving dependency cache"
|
ebegin "Saving dependency cache"
|
||||||
local rc=0 save=
|
local rc=0 save=
|
||||||
for x in shutdowntime softlevel rc.log; do
|
for x in depconfig deptree rc.log shutdowntime softlevel; do
|
||||||
[ -e "$RC_SVCDIR/$x" ] && save="$save $RC_SVCDIR/$x"
|
[ -e "$RC_SVCDIR/$x" ] && save="$save $RC_SVCDIR/$x"
|
||||||
done
|
done
|
||||||
if [ -n "$save" ]; then
|
if [ -n "$save" ]; then
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
depend()
|
depend()
|
||||||
{
|
{
|
||||||
after clock
|
after clock root
|
||||||
before localmount
|
before localmount
|
||||||
keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -vserver
|
keyword -docker -jail -lxc -openvz -prefix -systemd-nspawn -vserver
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,6 +119,9 @@ The amount of time, in milliseconds, s6-svc should wait for the service
|
|||||||
to go down when stopping the service. The default is 60000.
|
to go down when stopping the service. The default is 60000.
|
||||||
.It Ar start_stop_daemon_args
|
.It Ar start_stop_daemon_args
|
||||||
List of arguments passed to start-stop-daemon when starting the daemon.
|
List of arguments passed to start-stop-daemon when starting the daemon.
|
||||||
|
.It Ar supervise_daemon_args
|
||||||
|
List of arguments passed to supervise-daemon when starting the daemon.
|
||||||
|
If undefined, start_stop_daemon_args is used as a fallback.
|
||||||
.It Ar command
|
.It Ar command
|
||||||
Daemon to start or stop via
|
Daemon to start or stop via
|
||||||
.Nm start-stop-daemon
|
.Nm start-stop-daemon
|
||||||
@@ -170,6 +173,23 @@ variable is set.
|
|||||||
The same thing as
|
The same thing as
|
||||||
.Pa output_log
|
.Pa output_log
|
||||||
but for the standard error output.
|
but for the standard error output.
|
||||||
|
.It Ar output_logger
|
||||||
|
This is a process which will be used to log the standard output from the
|
||||||
|
service. If you are starting this service with
|
||||||
|
.Xr start-stop-daemon 8 ,
|
||||||
|
, you must set
|
||||||
|
.Pa command_background
|
||||||
|
to true. Keep in mind that this command must be executable as a shell
|
||||||
|
command inside the chroot if the
|
||||||
|
.Pa chroot
|
||||||
|
variable is set. Keep in mind also that this command works by accepting
|
||||||
|
the stdout of the service on stdin.
|
||||||
|
An example of a command that can be run this way is logger if you want
|
||||||
|
your service output to go to syslog.
|
||||||
|
.It Ar error_logger
|
||||||
|
The same thing as
|
||||||
|
.Pa output_logger
|
||||||
|
but for the standard error output.
|
||||||
.It Ar directory
|
.It Ar directory
|
||||||
.Xr start-stop-daemon 8
|
.Xr start-stop-daemon 8
|
||||||
and
|
and
|
||||||
@@ -594,7 +614,7 @@ rc_net_tap1_provide="!net"
|
|||||||
# It's also possible to negate keywords. This is mainly useful for prefix
|
# It's also possible to negate keywords. This is mainly useful for prefix
|
||||||
# users testing OpenRC.
|
# users testing OpenRC.
|
||||||
rc_keyword="!-prefix"
|
rc_keyword="!-prefix"
|
||||||
# This can also be used to block a script from runining in all
|
# This can also be used to block a script from running in all
|
||||||
# containers except one or two
|
# containers except one or two
|
||||||
rc_keyword="!-containers !-docker"
|
rc_keyword="!-containers !-docker"
|
||||||
.Ed
|
.Ed
|
||||||
|
|||||||
@@ -20,6 +20,14 @@
|
|||||||
.Ar service cmd
|
.Ar service cmd
|
||||||
.Op Ar ...
|
.Op Ar ...
|
||||||
.Nm
|
.Nm
|
||||||
|
.Fl d , -debug
|
||||||
|
.Ar service cmd
|
||||||
|
.Op Ar ...
|
||||||
|
.Nm
|
||||||
|
.Fl D , -nodeps
|
||||||
|
.Ar service cmd
|
||||||
|
.Op Ar ...
|
||||||
|
.Nm
|
||||||
.Op Fl i , -ifexists
|
.Op Fl i , -ifexists
|
||||||
.Ar service cmd
|
.Ar service cmd
|
||||||
.Op Ar ...
|
.Op Ar ...
|
||||||
@@ -32,9 +40,21 @@
|
|||||||
.Ar service cmd
|
.Ar service cmd
|
||||||
.Op Ar ...
|
.Op Ar ...
|
||||||
.Nm
|
.Nm
|
||||||
|
.Op Fl s , -ifstarted
|
||||||
|
.Ar service cmd
|
||||||
|
.Op Ar ...
|
||||||
|
.Nm
|
||||||
|
.Op Fl S , -ifstopped
|
||||||
|
.Ar service cmd
|
||||||
|
.Op Ar ...
|
||||||
|
.Nm
|
||||||
.Fl e , -exists
|
.Fl e , -exists
|
||||||
.Ar service
|
.Ar service
|
||||||
.Nm
|
.Nm
|
||||||
|
.Fl Z , -dry-run
|
||||||
|
.Ar service cmd
|
||||||
|
.Op Ar ...
|
||||||
|
.Nm
|
||||||
.Fl l , -list
|
.Fl l , -list
|
||||||
.Nm
|
.Nm
|
||||||
.Fl r , -resolve
|
.Fl r , -resolve
|
||||||
@@ -68,6 +88,15 @@ return 0 if it can find
|
|||||||
otherwise -1.
|
otherwise -1.
|
||||||
.Fl r , -resolve
|
.Fl r , -resolve
|
||||||
does the same and also prints the full path of the service to stdout.
|
does the same and also prints the full path of the service to stdout.
|
||||||
|
.Pp
|
||||||
|
.Fl d , -debug
|
||||||
|
sets -x when running the service script(s).
|
||||||
|
.Pp
|
||||||
|
.Fl D , -nodeps
|
||||||
|
ignores dependencies when running the service.
|
||||||
|
.Pp
|
||||||
|
.Fl Z , -dry-run
|
||||||
|
displays commands rather than executing them.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr openrc 8 ,
|
.Xr openrc 8 ,
|
||||||
.Xr stdout 3
|
.Xr stdout 3
|
||||||
|
|||||||
@@ -131,9 +131,34 @@ Modifies the scheduling priority of the daemon.
|
|||||||
.It Fl 1 , -stdout Ar logfile
|
.It Fl 1 , -stdout Ar logfile
|
||||||
Redirect the standard output of the process to logfile when started with
|
Redirect the standard output of the process to logfile when started with
|
||||||
.Fl background .
|
.Fl background .
|
||||||
Must be an absolute pathname, but relative to the path optionally given with
|
The logfile Must be an absolute pathname, but relative to the path
|
||||||
|
optionally given with
|
||||||
.Fl r , -chroot .
|
.Fl r , -chroot .
|
||||||
The logfile can also be a named pipe.
|
The logfile can also be a named pipe.
|
||||||
|
.It Fl 2 , -stderr Ar logfile
|
||||||
|
Redirect the standard error of the process to logfile when started with
|
||||||
|
.Fl background .
|
||||||
|
The logfile must be an absolute pathname, but relative to the path
|
||||||
|
optionally given with
|
||||||
|
.Fl r , -chroot .
|
||||||
|
The logfile can also be a named pipe.
|
||||||
|
.It Fl 3 , -stdout-logger Ar cmd
|
||||||
|
Run cmd as a child process redirecting the standard output to the
|
||||||
|
standard input of cmd when started with
|
||||||
|
.Fl background .
|
||||||
|
Cmd must be an absolute pathname, but relative to the path optionally given with
|
||||||
|
.Fl r , -chroot .
|
||||||
|
This process must be prepared to accept input on stdin and be able to
|
||||||
|
log it or send it to another location.
|
||||||
|
.It Fl 4 , -stderr-logger Ar cmd
|
||||||
|
Run cmd as a child process and
|
||||||
|
Redirect the standard error of the process to the standard input of cmd
|
||||||
|
when started with
|
||||||
|
.Fl background .
|
||||||
|
Cmd must be an absolute pathname, but relative to the path optionally given with
|
||||||
|
.Fl r , -chroot .
|
||||||
|
This process must be prepared to accept input on stdin and be able to
|
||||||
|
log it or send it to another location.
|
||||||
.It Fl w , -wait Ar milliseconds
|
.It Fl w , -wait Ar milliseconds
|
||||||
Wait
|
Wait
|
||||||
.Ar milliseconds
|
.Ar milliseconds
|
||||||
@@ -151,6 +176,7 @@ These options are only used for stopping daemons:
|
|||||||
.It Fl R , -retry Ar timeout | Ar signal Ns / Ns Ar timeout
|
.It Fl R , -retry Ar timeout | Ar signal Ns / Ns Ar timeout
|
||||||
The retry specification can be either a timeout in seconds or multiple
|
The retry specification can be either a timeout in seconds or multiple
|
||||||
signal/timeout pairs (like SIGTERM/5).
|
signal/timeout pairs (like SIGTERM/5).
|
||||||
|
If this option is not given, the default is SIGTERM/5.
|
||||||
.El
|
.El
|
||||||
.Sh ENVIRONMENT
|
.Sh ENVIRONMENT
|
||||||
.Va SSD_IONICELEVEL
|
.Va SSD_IONICELEVEL
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ description of --respawn-max for more information.
|
|||||||
.It Fl R , -retry Ar timeout | Ar signal Ns / Ns Ar timeout
|
.It Fl R , -retry Ar timeout | Ar signal Ns / Ns Ar timeout
|
||||||
The retry specification can be either a timeout in seconds or multiple
|
The retry specification can be either a timeout in seconds or multiple
|
||||||
signal/timeout pairs (like SIGTERM/5).
|
signal/timeout pairs (like SIGTERM/5).
|
||||||
|
If this option is not given, the default is SIGTERM/5.
|
||||||
.It Fl r , -chroot Ar path
|
.It Fl r , -chroot Ar path
|
||||||
chroot to this directory before starting the daemon. All other paths, such
|
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.
|
as the path to the daemon, chdir and pidfile, should be relative to the chroot.
|
||||||
|
|||||||
@@ -11,3 +11,5 @@
|
|||||||
# Generic definitions
|
# Generic definitions
|
||||||
|
|
||||||
include ${MK}/os-BSD.mk
|
include ${MK}/os-BSD.mk
|
||||||
|
|
||||||
|
CPPFLAGS+= -D_BSD_SOURCE
|
||||||
|
|||||||
@@ -13,6 +13,6 @@
|
|||||||
SFX= .GNU-kFreeBSD.in
|
SFX= .GNU-kFreeBSD.in
|
||||||
PKG_PREFIX?= /usr
|
PKG_PREFIX?= /usr
|
||||||
|
|
||||||
CPPFLAGS+= -D_BSD_SOURCE -D_XOPEN_SOURCE=700
|
CPPFLAGS+= -D_BSD_SOURCE
|
||||||
LIBDL= -Wl,-Bdynamic -ldl
|
LIBDL= -Wl,-Bdynamic -ldl
|
||||||
LIBKVM?=
|
LIBKVM?=
|
||||||
|
|||||||
@@ -11,5 +11,5 @@
|
|||||||
SFX= .GNU.in
|
SFX= .GNU.in
|
||||||
PKG_PREFIX?= /usr
|
PKG_PREFIX?= /usr
|
||||||
|
|
||||||
CPPFLAGS+= -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700 -DMAXPATHLEN=4096 -DPATH_MAX=4096
|
CPPFLAGS+= -D_DEFAULT_SOURCE -DMAXPATHLEN=4096 -DPATH_MAX=4096
|
||||||
LIBDL= -Wl,-Bdynamic -ldl
|
LIBDL= -Wl,-Bdynamic -ldl
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
SFX= .Linux.in
|
SFX= .Linux.in
|
||||||
PKG_PREFIX?= /usr
|
PKG_PREFIX?= /usr
|
||||||
|
|
||||||
CPPFLAGS+= -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700
|
CPPFLAGS+= -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L
|
||||||
LIBDL= -Wl,-Bdynamic -ldl
|
LIBDL= -Wl,-Bdynamic -ldl
|
||||||
|
|
||||||
ifeq (${MKSELINUX},yes)
|
ifeq (${MKSELINUX},yes)
|
||||||
|
|||||||
@@ -45,20 +45,20 @@ SBINDIR?= ${PREFIX}/sbin
|
|||||||
SBINMODE?= 0755
|
SBINMODE?= 0755
|
||||||
|
|
||||||
INCDIR?= ${UPREFIX}/include
|
INCDIR?= ${UPREFIX}/include
|
||||||
INCMODE?= 0444
|
INCMODE?= 0644
|
||||||
|
|
||||||
_LIBNAME_SH= case `readlink /lib` in /lib64|lib64) echo "lib64";; *) echo "lib";; esac
|
_LIBNAME_SH= case `readlink /lib` in /lib64|lib64) echo "lib64";; *) echo "lib";; esac
|
||||||
_LIBNAME:= $(shell ${_LIBNAME_SH})
|
_LIBNAME:= $(shell ${_LIBNAME_SH})
|
||||||
LIBNAME?= ${_LIBNAME}
|
LIBNAME?= ${_LIBNAME}
|
||||||
LIBDIR?= ${UPREFIX}/${LIBNAME}
|
LIBDIR?= ${UPREFIX}/${LIBNAME}
|
||||||
LIBMODE?= 0444
|
LIBMODE?= 0644
|
||||||
SHLIBDIR?= ${PREFIX}/${LIBNAME}
|
SHLIBDIR?= ${PREFIX}/${LIBNAME}
|
||||||
|
|
||||||
LIBEXECDIR?= ${PREFIX}/libexec/rc
|
LIBEXECDIR?= ${PREFIX}/libexec/rc
|
||||||
|
|
||||||
MANPREFIX?= ${UPREFIX}/share
|
MANPREFIX?= ${UPREFIX}/share
|
||||||
MANDIR?= ${MANPREFIX}/man
|
MANDIR?= ${MANPREFIX}/man
|
||||||
MANMODE?= 0444
|
MANMODE?= 0644
|
||||||
|
|
||||||
BASHCOMPDIR?= ${UPREFIX}/share/bash-completion/completions
|
BASHCOMPDIR?= ${UPREFIX}/share/bash-completion/completions
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,9 @@ Not using this interpreter will break the use of dependencies and is not
|
|||||||
supported. (iow: if you insist on using `#!/bin/sh` you're on your own)
|
supported. (iow: if you insist on using `#!/bin/sh` you're on your own)
|
||||||
|
|
||||||
A `depend` function declares the dependencies of this service script.
|
A `depend` function declares the dependencies of this service script.
|
||||||
All scripts must have start/stop/status functions, but defaults are provided and should be used unless you have a very strong reason not to use them.
|
All scripts must have start/stop/status functions, but defaults are
|
||||||
|
provided and should be used unless you have a very strong reason not to
|
||||||
|
use them.
|
||||||
|
|
||||||
Extra functions can be added easily:
|
Extra functions can be added easily:
|
||||||
|
|
||||||
|
|||||||
@@ -133,11 +133,10 @@ _status()
|
|||||||
elif service_inactive; then
|
elif service_inactive; then
|
||||||
ewarn "status: inactive"
|
ewarn "status: inactive"
|
||||||
return 16
|
return 16
|
||||||
|
elif service_crashed; then
|
||||||
|
eerror "status: crashed"
|
||||||
|
return 32
|
||||||
elif service_started; then
|
elif service_started; then
|
||||||
if service_crashed; then
|
|
||||||
eerror "status: crashed"
|
|
||||||
return 32
|
|
||||||
fi
|
|
||||||
einfo "status: started"
|
einfo "status: started"
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -184,18 +184,17 @@ cgroup2_set_limits()
|
|||||||
cgroup_path="$(cgroup2_find_path)"
|
cgroup_path="$(cgroup2_find_path)"
|
||||||
[ -d "${cgroup_path}" ] || return 0
|
[ -d "${cgroup_path}" ] || return 0
|
||||||
rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}"
|
rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}"
|
||||||
local OIFS="$IFS"
|
|
||||||
IFS="
|
|
||||||
"
|
|
||||||
[ ! -d "${rc_cgroup_path}" ] && mkdir "${rc_cgroup_path}"
|
[ ! -d "${rc_cgroup_path}" ] && mkdir "${rc_cgroup_path}"
|
||||||
printf "%d" 0 > "${rc_cgroup_path}/cgroup.procs"
|
[ -f "${rc_cgroup_path}"/cgroup.procs ] &&
|
||||||
echo "${rc_cgroup_settings}" | while IFS="$OIFS" read -r key value; do
|
printf 0 > "${rc_cgroup_path}"/cgroup.procs
|
||||||
[ -z "${key}" ] || [ -z "${value}" ] && continue
|
[ -z "${rc_cgroup_settings}" ] && return 0
|
||||||
[ ! -e "${rc_cgroup_path}/${key}" ] && continue
|
echo "${rc_cgroup_settings}" | while read -r key value; do
|
||||||
veinfo "${RC_SVCNAME}: cgroups: ${key} ${value}"
|
[ -z "${key}" ] && continue
|
||||||
printf "%s" "${value}" > "${rc_cgroup_path}/${key}"
|
[ -z "${value}" ] && continue
|
||||||
|
[ ! -f "${rc_cgroup_path}/${key}" ] && continue
|
||||||
|
veinfo "${RC_SVCNAME}: cgroups: setting ${key} to ${value}"
|
||||||
|
printf "%s\n" "${value}" > "${rc_cgroup_path}/${key}"
|
||||||
done
|
done
|
||||||
IFS="$OIFS"
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ ssd_start()
|
|||||||
service_inactive && _inactive=true
|
service_inactive && _inactive=true
|
||||||
mark_service_inactive
|
mark_service_inactive
|
||||||
fi
|
fi
|
||||||
|
[ -n "$output_logger" ] &&
|
||||||
|
output_logger_arg="--stdout-logger \"$output_logger\""
|
||||||
|
[ -n "$error_logger" ] &&
|
||||||
|
error_logger_arg="--stderr-logger \"$error_logger\""
|
||||||
#the eval call is necessary for cases like:
|
#the eval call is necessary for cases like:
|
||||||
# command_args="this \"is a\" test"
|
# command_args="this \"is a\" test"
|
||||||
# to work properly.
|
# to work properly.
|
||||||
@@ -47,6 +51,8 @@ ssd_start()
|
|||||||
${directory:+--chdir} $directory \
|
${directory:+--chdir} $directory \
|
||||||
${output_log+--stdout} $output_log \
|
${output_log+--stdout} $output_log \
|
||||||
${error_log+--stderr} $error_log \
|
${error_log+--stderr} $error_log \
|
||||||
|
${output_logger_arg} \
|
||||||
|
${error_logger_arg} \
|
||||||
${procname:+--name} $procname \
|
${procname:+--name} $procname \
|
||||||
${pidfile:+--pidfile} $pidfile \
|
${pidfile:+--pidfile} $pidfile \
|
||||||
${command_user+--user} $command_user \
|
${command_user+--user} $command_user \
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ supervise_start()
|
|||||||
${respawn_period:+--respawn-period} $respawn_period \
|
${respawn_period:+--respawn-period} $respawn_period \
|
||||||
${command_user+--user} $command_user \
|
${command_user+--user} $command_user \
|
||||||
${umask+--umask} $umask \
|
${umask+--umask} $umask \
|
||||||
$supervise_daemon_args \
|
${supervise_daemon_args:-${start_stop_daemon_args}} \
|
||||||
$command \
|
$command \
|
||||||
-- $command_args $command_args_foreground
|
-- $command_args $command_args_foreground
|
||||||
rc=$?
|
rc=$?
|
||||||
|
|||||||
@@ -66,9 +66,6 @@ int parse_mode(mode_t *, char *);
|
|||||||
/* Handy function so we can wrap einfo around our deptree */
|
/* Handy function so we can wrap einfo around our deptree */
|
||||||
RC_DEPTREE *_rc_deptree_load (int, 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);
|
|
||||||
|
|
||||||
RC_SERVICE lookup_service_state(const char *service);
|
RC_SERVICE lookup_service_state(const char *service);
|
||||||
void from_time_t(char *time_string, time_t tv);
|
void from_time_t(char *time_string, time_t tv);
|
||||||
time_t to_time_t(char *timestring);
|
time_t to_time_t(char *timestring);
|
||||||
|
|||||||
@@ -883,7 +883,7 @@ eindent(void)
|
|||||||
{
|
{
|
||||||
char *env = getenv("EINFO_INDENT");
|
char *env = getenv("EINFO_INDENT");
|
||||||
int amount = 0;
|
int amount = 0;
|
||||||
char num[10];
|
char *num;
|
||||||
|
|
||||||
if (env) {
|
if (env) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
@@ -894,8 +894,9 @@ eindent(void)
|
|||||||
amount += INDENT_WIDTH;
|
amount += INDENT_WIDTH;
|
||||||
if (amount > INDENT_MAX)
|
if (amount > INDENT_MAX)
|
||||||
amount = INDENT_MAX;
|
amount = INDENT_MAX;
|
||||||
snprintf(num, 10, "%08d", amount);
|
xasprintf(&num, "%08d", amount);
|
||||||
setenv("EINFO_INDENT", num, 1);
|
setenv("EINFO_INDENT", num, 1);
|
||||||
|
free(num);
|
||||||
}
|
}
|
||||||
hidden_def(eindent)
|
hidden_def(eindent)
|
||||||
|
|
||||||
@@ -903,7 +904,7 @@ void eoutdent(void)
|
|||||||
{
|
{
|
||||||
char *env = getenv("EINFO_INDENT");
|
char *env = getenv("EINFO_INDENT");
|
||||||
int amount = 0;
|
int amount = 0;
|
||||||
char num[10];
|
char *num = NULL;
|
||||||
int serrno = errno;
|
int serrno = errno;
|
||||||
|
|
||||||
if (!env)
|
if (!env)
|
||||||
@@ -917,8 +918,9 @@ void eoutdent(void)
|
|||||||
if (amount <= 0)
|
if (amount <= 0)
|
||||||
unsetenv("EINFO_INDENT");
|
unsetenv("EINFO_INDENT");
|
||||||
else {
|
else {
|
||||||
snprintf(num, 10, "%08d", amount);
|
xasprintf(&num, "%08d", amount);
|
||||||
setenv("EINFO_INDENT", num, 1);
|
setenv("EINFO_INDENT", num, 1);
|
||||||
|
free(num);
|
||||||
}
|
}
|
||||||
errno = serrno;
|
errno = serrno;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,13 +23,13 @@
|
|||||||
static bool
|
static bool
|
||||||
pid_is_exec(pid_t pid, const char *exec)
|
pid_is_exec(pid_t pid, const char *exec)
|
||||||
{
|
{
|
||||||
char buffer[32];
|
char *buffer = NULL;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int c;
|
int c;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
exec = basename_c(exec);
|
exec = basename_c(exec);
|
||||||
snprintf(buffer, sizeof(buffer), "/proc/%d/stat", pid);
|
xasprintf(&buffer, "/proc/%d/stat", pid);
|
||||||
if ((fp = fopen(buffer, "r"))) {
|
if ((fp = fopen(buffer, "r"))) {
|
||||||
while ((c = getc(fp)) != EOF && c != '(')
|
while ((c = getc(fp)) != EOF && c != '(')
|
||||||
;
|
;
|
||||||
@@ -41,23 +41,27 @@ pid_is_exec(pid_t pid, const char *exec)
|
|||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
free(buffer);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
pid_is_argv(pid_t pid, const char *const *argv)
|
pid_is_argv(pid_t pid, const char *const *argv)
|
||||||
{
|
{
|
||||||
char cmdline[32];
|
char *cmdline = NULL;
|
||||||
int fd;
|
int fd;
|
||||||
char buffer[PATH_MAX];
|
char buffer[PATH_MAX];
|
||||||
char *p;
|
char *p;
|
||||||
ssize_t bytes;
|
ssize_t bytes;
|
||||||
|
|
||||||
snprintf(cmdline, sizeof(cmdline), "/proc/%u/cmdline", pid);
|
xasprintf(&cmdline, "/proc/%u/cmdline", pid);
|
||||||
if ((fd = open(cmdline, O_RDONLY)) < 0)
|
if ((fd = open(cmdline, O_RDONLY)) < 0) {
|
||||||
|
free(cmdline);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
bytes = read(fd, buffer, sizeof(buffer));
|
bytes = read(fd, buffer, sizeof(buffer));
|
||||||
close(fd);
|
close(fd);
|
||||||
|
free(cmdline);
|
||||||
if (bytes == -1)
|
if (bytes == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -88,7 +92,7 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
|
|||||||
char proc_ns[30];
|
char proc_ns[30];
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
pid_t p;
|
pid_t p;
|
||||||
char buffer[PATH_MAX];
|
char *buffer = NULL;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
pid_t openrc_pid = 0;
|
pid_t openrc_pid = 0;
|
||||||
char *pp;
|
char *pp;
|
||||||
@@ -149,18 +153,22 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
|
|||||||
continue;
|
continue;
|
||||||
if (pid != 0 && pid != p)
|
if (pid != 0 && pid != p)
|
||||||
continue;
|
continue;
|
||||||
snprintf(buffer, sizeof(buffer), "/proc/%d/ns/pid", p);
|
xasprintf(&buffer, "/proc/%d/ns/pid", p);
|
||||||
if (exists(buffer)) {
|
if (exists(buffer)) {
|
||||||
rc = readlink(buffer, proc_ns, sizeof(proc_ns));
|
rc = readlink(buffer, proc_ns, sizeof(proc_ns));
|
||||||
if (rc <= 0)
|
if (rc <= 0)
|
||||||
proc_ns[0] = '\0';
|
proc_ns[0] = '\0';
|
||||||
}
|
}
|
||||||
|
free(buffer);
|
||||||
if (strlen(my_ns) && strlen (proc_ns) && strcmp(my_ns, proc_ns))
|
if (strlen(my_ns) && strlen (proc_ns) && strcmp(my_ns, proc_ns))
|
||||||
continue;
|
continue;
|
||||||
if (uid) {
|
if (uid) {
|
||||||
snprintf(buffer, sizeof(buffer), "/proc/%d", p);
|
xasprintf(&buffer, "/proc/%d", p);
|
||||||
if (stat(buffer, &sb) != 0 || sb.st_uid != uid)
|
if (stat(buffer, &sb) != 0 || sb.st_uid != uid) {
|
||||||
|
free(buffer);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
free(buffer);
|
||||||
}
|
}
|
||||||
if (exec && !pid_is_exec(p, exec))
|
if (exec && !pid_is_exec(p, exec))
|
||||||
continue;
|
continue;
|
||||||
@@ -169,9 +177,10 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
|
|||||||
continue;
|
continue;
|
||||||
/* If this is an OpenVZ host, filter out container processes */
|
/* If this is an OpenVZ host, filter out container processes */
|
||||||
if (openvz_host) {
|
if (openvz_host) {
|
||||||
snprintf(buffer, sizeof(buffer), "/proc/%d/status", p);
|
xasprintf(&buffer, "/proc/%d/status", p);
|
||||||
if (exists(buffer)) {
|
if (exists(buffer)) {
|
||||||
fp = fopen(buffer, "r");
|
fp = fopen(buffer, "r");
|
||||||
|
free(buffer);
|
||||||
if (! fp)
|
if (! fp)
|
||||||
continue;
|
continue;
|
||||||
while (! feof(fp)) {
|
while (! feof(fp)) {
|
||||||
@@ -315,12 +324,13 @@ _match_daemon(const char *path, const char *file, RC_STRINGLIST *match)
|
|||||||
{
|
{
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
char ffile[PATH_MAX];
|
char *ffile = NULL;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
RC_STRING *m;
|
RC_STRING *m;
|
||||||
|
|
||||||
snprintf(ffile, sizeof(ffile), "%s/%s", path, file);
|
xasprintf(&ffile, "%s/%s", path, file);
|
||||||
fp = fopen(ffile, "r");
|
fp = fopen(ffile, "r");
|
||||||
|
free(ffile);
|
||||||
|
|
||||||
if (!fp)
|
if (!fp)
|
||||||
return false;
|
return false;
|
||||||
@@ -346,29 +356,22 @@ _match_list(const char *exec, const char *const *argv, const char *pidfile)
|
|||||||
{
|
{
|
||||||
RC_STRINGLIST *match = rc_stringlist_new();
|
RC_STRINGLIST *match = rc_stringlist_new();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
size_t l;
|
|
||||||
char *m;
|
char *m;
|
||||||
|
|
||||||
if (exec) {
|
if (exec) {
|
||||||
l = strlen(exec) + 6;
|
xasprintf(&m, "exec=%s", exec);
|
||||||
m = xmalloc(sizeof(char) * l);
|
|
||||||
snprintf(m, l, "exec=%s", exec);
|
|
||||||
rc_stringlist_add(match, m);
|
rc_stringlist_add(match, m);
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (argv && argv[i]) {
|
while (argv && argv[i]) {
|
||||||
l = strlen(*argv) + strlen("argv_=") + 16;
|
xasprintf(&m, "argv_0=%s", argv[i++]);
|
||||||
m = xmalloc(sizeof(char) * l);
|
|
||||||
snprintf(m, l, "argv_0=%s", argv[i++]);
|
|
||||||
rc_stringlist_add(match, m);
|
rc_stringlist_add(match, m);
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pidfile) {
|
if (pidfile) {
|
||||||
l = strlen(pidfile) + 9;
|
xasprintf(&m, "pidfile=%s", pidfile);
|
||||||
m = xmalloc(sizeof(char) * l);
|
|
||||||
snprintf(m, l, "pidfile=%s", pidfile);
|
|
||||||
rc_stringlist_add(match, m);
|
rc_stringlist_add(match, m);
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
@@ -381,8 +384,8 @@ rc_service_daemon_set(const char *service, const char *exec,
|
|||||||
const char *const *argv,
|
const char *const *argv,
|
||||||
const char *pidfile, bool started)
|
const char *pidfile, bool started)
|
||||||
{
|
{
|
||||||
char dirpath[PATH_MAX];
|
char *dirpath = NULL;
|
||||||
char file[PATH_MAX];
|
char *file = NULL;
|
||||||
int nfiles = 0;
|
int nfiles = 0;
|
||||||
char oldfile[PATH_MAX] = { '\0' };
|
char oldfile[PATH_MAX] = { '\0' };
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
@@ -397,8 +400,7 @@ rc_service_daemon_set(const char *service, const char *exec,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
xasprintf(&dirpath, RC_SVCDIR "/daemons/%s", basename_c(service));
|
||||||
basename_c(service));
|
|
||||||
|
|
||||||
/* Regardless, erase any existing daemon info */
|
/* Regardless, erase any existing daemon info */
|
||||||
if ((dp = opendir(dirpath))) {
|
if ((dp = opendir(dirpath))) {
|
||||||
@@ -407,8 +409,7 @@ rc_service_daemon_set(const char *service, const char *exec,
|
|||||||
if (d->d_name[0] == '.')
|
if (d->d_name[0] == '.')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
snprintf(file, sizeof(file), "%s/%s",
|
xasprintf(&file, "%s/%s", dirpath, d->d_name);
|
||||||
dirpath, d->d_name);
|
|
||||||
nfiles++;
|
nfiles++;
|
||||||
|
|
||||||
if (!*oldfile) {
|
if (!*oldfile) {
|
||||||
@@ -421,6 +422,7 @@ rc_service_daemon_set(const char *service, const char *exec,
|
|||||||
rename(file, oldfile);
|
rename(file, oldfile);
|
||||||
strlcpy(oldfile, file, sizeof(oldfile));
|
strlcpy(oldfile, file, sizeof(oldfile));
|
||||||
}
|
}
|
||||||
|
free(file);
|
||||||
}
|
}
|
||||||
closedir(dp);
|
closedir(dp);
|
||||||
rc_stringlist_free(match);
|
rc_stringlist_free(match);
|
||||||
@@ -429,8 +431,7 @@ rc_service_daemon_set(const char *service, const char *exec,
|
|||||||
/* Now store our daemon info */
|
/* Now store our daemon info */
|
||||||
if (started) {
|
if (started) {
|
||||||
if (mkdir(dirpath, 0755) == 0 || errno == EEXIST) {
|
if (mkdir(dirpath, 0755) == 0 || errno == EEXIST) {
|
||||||
snprintf(file, sizeof(file), "%s/%03d",
|
xasprintf(&file, "%s/%03d", dirpath, nfiles + 1);
|
||||||
dirpath, nfiles + 1);
|
|
||||||
if ((fp = fopen(file, "w"))) {
|
if ((fp = fopen(file, "w"))) {
|
||||||
fprintf(fp, "exec=");
|
fprintf(fp, "exec=");
|
||||||
if (exec)
|
if (exec)
|
||||||
@@ -446,10 +447,12 @@ rc_service_daemon_set(const char *service, const char *exec,
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
retval = true;
|
retval = true;
|
||||||
}
|
}
|
||||||
|
free(file);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
|
free(dirpath);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_daemon_set)
|
librc_hidden_def(rc_service_daemon_set)
|
||||||
@@ -458,8 +461,8 @@ bool
|
|||||||
rc_service_started_daemon(const char *service,
|
rc_service_started_daemon(const char *service,
|
||||||
const char *exec, const char *const *argv, int indx)
|
const char *exec, const char *const *argv, int indx)
|
||||||
{
|
{
|
||||||
char dirpath[PATH_MAX];
|
char *dirpath = NULL;
|
||||||
char file[16];
|
char *file = NULL;
|
||||||
RC_STRINGLIST *match;
|
RC_STRINGLIST *match;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
DIR *dp;
|
DIR *dp;
|
||||||
@@ -468,13 +471,13 @@ rc_service_started_daemon(const char *service,
|
|||||||
if (!service || !exec)
|
if (!service || !exec)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
xasprintf(&dirpath, RC_SVCDIR "/daemons/%s", basename_c(service));
|
||||||
basename_c(service));
|
|
||||||
match = _match_list(exec, argv, NULL);
|
match = _match_list(exec, argv, NULL);
|
||||||
|
|
||||||
if (indx > 0) {
|
if (indx > 0) {
|
||||||
snprintf(file, sizeof(file), "%03d", indx);
|
xasprintf(&file, "%03d", indx);
|
||||||
retval = _match_daemon(dirpath, file, match);
|
retval = _match_daemon(dirpath, file, match);
|
||||||
|
free(file);
|
||||||
} else {
|
} else {
|
||||||
if ((dp = opendir(dirpath))) {
|
if ((dp = opendir(dirpath))) {
|
||||||
while ((d = readdir(dp))) {
|
while ((d = readdir(dp))) {
|
||||||
@@ -489,6 +492,7 @@ rc_service_started_daemon(const char *service,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rc_stringlist_free(match);
|
rc_stringlist_free(match);
|
||||||
|
free(dirpath);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_started_daemon)
|
librc_hidden_def(rc_service_started_daemon)
|
||||||
|
|||||||
@@ -237,13 +237,9 @@ static void rc_config_set_value(RC_STRINGLIST *config, char *value)
|
|||||||
if (token[i] == '\n')
|
if (token[i] == '\n')
|
||||||
token[i] = 0;
|
token[i] = 0;
|
||||||
|
|
||||||
i = strlen(entry) + strlen(token) + 2;
|
xasprintf(&newline, "%s=%s", entry, token);
|
||||||
newline = xmalloc(sizeof(char) * i);
|
|
||||||
snprintf(newline, i, "%s=%s", entry, token);
|
|
||||||
} else {
|
} else {
|
||||||
i = strlen(entry) + 2;
|
xasprintf(&newline, "%s=", entry);
|
||||||
newline = xmalloc(sizeof(char) * i);
|
|
||||||
snprintf(newline, i, "%s=", entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
replaced = false;
|
replaced = false;
|
||||||
@@ -300,8 +296,7 @@ static RC_STRINGLIST *rc_config_kcl(RC_STRINGLIST *config)
|
|||||||
|
|
||||||
if (value != NULL) {
|
if (value != NULL) {
|
||||||
len = varlen + strlen(value) + 2;
|
len = varlen + strlen(value) + 2;
|
||||||
tmp = xmalloc(sizeof(char) * len);
|
xasprintf(&tmp, "%s=%s", override->value, value);
|
||||||
snprintf(tmp, len, "%s=%s", override->value, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ static const rc_service_state_name_t rc_service_state_names[] = {
|
|||||||
{ RC_SERVICE_HOTPLUGGED, "hotplugged" },
|
{ RC_SERVICE_HOTPLUGGED, "hotplugged" },
|
||||||
{ RC_SERVICE_FAILED, "failed" },
|
{ RC_SERVICE_FAILED, "failed" },
|
||||||
{ RC_SERVICE_SCHEDULED, "scheduled"},
|
{ RC_SERVICE_SCHEDULED, "scheduled"},
|
||||||
|
{ RC_SERVICE_CRASHED, "crashed"},
|
||||||
{ 0, NULL}
|
{ 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -848,6 +849,10 @@ rc_service_state(const char *service)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state & RC_SERVICE_STARTED) {
|
||||||
|
if (rc_service_daemons_crashed(service))
|
||||||
|
state |= RC_SERVICE_CRASHED;
|
||||||
|
}
|
||||||
if (state & RC_SERVICE_STOPPED) {
|
if (state & RC_SERVICE_STOPPED) {
|
||||||
dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
|
dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
|
||||||
TAILQ_FOREACH(dir, dirs, entries) {
|
TAILQ_FOREACH(dir, dirs, entries) {
|
||||||
|
|||||||
@@ -188,7 +188,8 @@ typedef enum
|
|||||||
/* Optional states service could also be in */
|
/* Optional states service could also be in */
|
||||||
RC_SERVICE_FAILED = 0x0200,
|
RC_SERVICE_FAILED = 0x0200,
|
||||||
RC_SERVICE_SCHEDULED = 0x0400,
|
RC_SERVICE_SCHEDULED = 0x0400,
|
||||||
RC_SERVICE_WASINACTIVE = 0x0800
|
RC_SERVICE_WASINACTIVE = 0x0800,
|
||||||
|
RC_SERVICE_CRASHED = 0x1000,
|
||||||
} RC_SERVICE;
|
} RC_SERVICE;
|
||||||
|
|
||||||
/*! Add the service to the runlevel
|
/*! Add the service to the runlevel
|
||||||
|
|||||||
1
src/rc/.gitignore
vendored
1
src/rc/.gitignore
vendored
@@ -56,6 +56,7 @@ mark_service_inactive
|
|||||||
mark_service_wasinactive
|
mark_service_wasinactive
|
||||||
mark_service_hotplugged
|
mark_service_hotplugged
|
||||||
mark_service_failed
|
mark_service_failed
|
||||||
|
mark_service_crashed
|
||||||
rc-abort
|
rc-abort
|
||||||
rc
|
rc
|
||||||
openrc
|
openrc
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ include ${MK}/os.mk
|
|||||||
SRCS= checkpath.c do_e.c do_mark_service.c do_service.c \
|
SRCS= checkpath.c do_e.c do_mark_service.c do_service.c \
|
||||||
do_value.c fstabinfo.c is_newer_than.c is_older_than.c \
|
do_value.c fstabinfo.c is_newer_than.c is_older_than.c \
|
||||||
mountinfo.c openrc-run.c rc-abort.c rc.c \
|
mountinfo.c openrc-run.c rc-abort.c rc.c \
|
||||||
rc-depend.c rc-logger.c rc-misc.c rc-plugin.c \
|
rc-depend.c rc-logger.c rc-misc.c rc-pipes.c \
|
||||||
rc-service.c rc-status.c rc-update.c \
|
rc-plugin.c rc-service.c rc-status.c rc-update.c \
|
||||||
shell_var.c start-stop-daemon.c supervise-daemon.c swclock.c _usage.c
|
shell_var.c start-stop-daemon.c supervise-daemon.c swclock.c _usage.c
|
||||||
|
|
||||||
ifeq (${MKSELINUX},yes)
|
ifeq (${MKSELINUX},yes)
|
||||||
@@ -41,6 +41,7 @@ RC_SBINPROGS= mark_service_starting mark_service_started \
|
|||||||
mark_service_stopping mark_service_stopped \
|
mark_service_stopping mark_service_stopped \
|
||||||
mark_service_inactive mark_service_wasinactive \
|
mark_service_inactive mark_service_wasinactive \
|
||||||
mark_service_hotplugged mark_service_failed \
|
mark_service_hotplugged mark_service_failed \
|
||||||
|
mark_service_crashed \
|
||||||
rc-abort swclock
|
rc-abort swclock
|
||||||
|
|
||||||
ifeq (${OS},Linux)
|
ifeq (${OS},Linux)
|
||||||
@@ -123,7 +124,8 @@ is_older_than: is_older_than.o rc-misc.o
|
|||||||
mark_service_starting mark_service_started \
|
mark_service_starting mark_service_started \
|
||||||
mark_service_stopping mark_service_stopped \
|
mark_service_stopping mark_service_stopped \
|
||||||
mark_service_inactive mark_service_wasinactive \
|
mark_service_inactive mark_service_wasinactive \
|
||||||
mark_service_hotplugged mark_service_failed: do_mark_service.o rc-misc.o
|
mark_service_hotplugged mark_service_failed \
|
||||||
|
mark_service_crashed: do_mark_service.o rc-misc.o
|
||||||
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
||||||
|
|
||||||
mountinfo: mountinfo.o _usage.o rc-misc.o
|
mountinfo: mountinfo.o _usage.o rc-misc.o
|
||||||
@@ -156,7 +158,7 @@ rc-service: rc-service.o _usage.o rc-misc.o
|
|||||||
rc-update: rc-update.o _usage.o rc-misc.o
|
rc-update: rc-update.o _usage.o rc-misc.o
|
||||||
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
||||||
|
|
||||||
start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o rc-schedules.o
|
start-stop-daemon: start-stop-daemon.o _usage.o rc-misc.o rc-pipes.o rc-schedules.o
|
||||||
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
|
||||||
|
|
||||||
supervise-daemon: supervise-daemon.o _usage.o rc-misc.o rc-schedules.o
|
supervise-daemon: supervise-daemon.o _usage.o rc-misc.o rc-schedules.o
|
||||||
|
|||||||
@@ -269,11 +269,13 @@ int main(int argc, char **argv)
|
|||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'D':
|
case 'D':
|
||||||
trunc = true;
|
trunc = true;
|
||||||
|
/* falls through */
|
||||||
case 'd':
|
case 'd':
|
||||||
type = inode_dir;
|
type = inode_dir;
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
trunc = true;
|
trunc = true;
|
||||||
|
/* falls through */
|
||||||
case 'f':
|
case 'f':
|
||||||
type = inode_file;
|
type = inode_file;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -68,9 +68,7 @@ int main(int argc, char **argv)
|
|||||||
ok = rc_service_started_daemon(service, exec, NULL, idx);
|
ok = rc_service_started_daemon(service, exec, NULL, idx);
|
||||||
|
|
||||||
} else if (strcmp(applet, "service_crashed") == 0) {
|
} else if (strcmp(applet, "service_crashed") == 0) {
|
||||||
ok = (_rc_can_find_pids() &&
|
ok = ( rc_service_daemons_crashed(service) && errno != EACCES);
|
||||||
rc_service_daemons_crashed(service) &&
|
|
||||||
errno != EACCES);
|
|
||||||
} else
|
} else
|
||||||
eerrorx("%s: unknown applet", applet);
|
eerrorx("%s: unknown applet", applet);
|
||||||
|
|
||||||
|
|||||||
@@ -1152,7 +1152,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
lnk = xmalloc(4096);
|
lnk = xmalloc(4096);
|
||||||
memset(lnk, 0, 4096);
|
memset(lnk, 0, 4096);
|
||||||
if (readlink(argv[1], lnk, sizeof(lnk)-1)) {
|
if (readlink(argv[1], lnk, 4096)) {
|
||||||
dir = dirname(path);
|
dir = dirname(path);
|
||||||
if (strchr(lnk, '/')) {
|
if (strchr(lnk, '/')) {
|
||||||
save = xstrdup(dir);
|
save = xstrdup(dir);
|
||||||
@@ -1268,6 +1268,9 @@ int main(int argc, char **argv)
|
|||||||
case_RC_COMMON_GETOPT
|
case_RC_COMMON_GETOPT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rc_yesno(getenv("RC_NODEPS")))
|
||||||
|
deps = false;
|
||||||
|
|
||||||
/* If we're changing runlevels and not called by rc then we cannot
|
/* If we're changing runlevels and not called by rc then we cannot
|
||||||
work with any dependencies */
|
work with any dependencies */
|
||||||
if (deps && getenv("RC_PID") == NULL &&
|
if (deps && getenv("RC_PID") == NULL &&
|
||||||
@@ -1282,6 +1285,8 @@ int main(int argc, char **argv)
|
|||||||
unsetenv("IN_BACKGROUND");
|
unsetenv("IN_BACKGROUND");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rc_yesno(getenv("IN_DRYRUN")))
|
||||||
|
dry_run = true;
|
||||||
if (rc_yesno(getenv("IN_HOTPLUG"))) {
|
if (rc_yesno(getenv("IN_HOTPLUG"))) {
|
||||||
if (!service_plugable())
|
if (!service_plugable())
|
||||||
eerrorx("%s: not allowed to be hotplugged", applet);
|
eerrorx("%s: not allowed to be hotplugged", applet);
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ write_log(int logfd, const char *buffer, size_t bytes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!in_escape) {
|
if (!in_escape) {
|
||||||
|
if (!isprint((int) *p) && *p != '\n')
|
||||||
|
goto cont;
|
||||||
if (write(logfd, p++, 1) == -1)
|
if (write(logfd, p++, 1) == -1)
|
||||||
eerror("write: %s", strerror(errno));
|
eerror("write: %s", strerror(errno));
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ rc_conf_yesno(const char *setting)
|
|||||||
|
|
||||||
static const char *const env_whitelist[] = {
|
static const char *const env_whitelist[] = {
|
||||||
"EERROR_QUIET", "EINFO_QUIET",
|
"EERROR_QUIET", "EINFO_QUIET",
|
||||||
"IN_BACKGROUND", "IN_HOTPLUG",
|
"IN_BACKGROUND", "IN_DRYRUN", "IN_HOTPLUG",
|
||||||
|
"RC_DEBUG", "RC_NODEPS",
|
||||||
"LANG", "LC_MESSAGES", "TERM",
|
"LANG", "LC_MESSAGES", "TERM",
|
||||||
"EINFO_COLOR", "EINFO_VERBOSE",
|
"EINFO_COLOR", "EINFO_VERBOSE",
|
||||||
NULL
|
NULL
|
||||||
@@ -410,34 +411,6 @@ RC_DEPTREE * _rc_deptree_load(int force, int *regen)
|
|||||||
return rc_deptree_load();
|
return rc_deptree_load();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _rc_can_find_pids(void)
|
|
||||||
{
|
|
||||||
RC_PIDLIST *pids;
|
|
||||||
RC_PID *pid;
|
|
||||||
RC_PID *pid2;
|
|
||||||
bool retval = false;
|
|
||||||
|
|
||||||
if (geteuid() == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
/* If we cannot see process 1, then we don't test to see if
|
|
||||||
* services crashed or not */
|
|
||||||
pids = rc_find_pids(NULL, NULL, 0, 1);
|
|
||||||
if (pids) {
|
|
||||||
pid = LIST_FIRST(pids);
|
|
||||||
if (pid) {
|
|
||||||
retval = true;
|
|
||||||
while (pid) {
|
|
||||||
pid2 = LIST_NEXT(pid, entries);
|
|
||||||
free(pid);
|
|
||||||
pid = pid2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(pids);
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
const char * const name;
|
const char * const name;
|
||||||
RC_SERVICE bit;
|
RC_SERVICE bit;
|
||||||
@@ -450,6 +423,7 @@ static const struct {
|
|||||||
{ "service_hotplugged", RC_SERVICE_HOTPLUGGED, },
|
{ "service_hotplugged", RC_SERVICE_HOTPLUGGED, },
|
||||||
{ "service_wasinactive", RC_SERVICE_WASINACTIVE, },
|
{ "service_wasinactive", RC_SERVICE_WASINACTIVE, },
|
||||||
{ "service_failed", RC_SERVICE_FAILED, },
|
{ "service_failed", RC_SERVICE_FAILED, },
|
||||||
|
{ "service_crashed", RC_SERVICE_CRASHED, },
|
||||||
};
|
};
|
||||||
|
|
||||||
RC_SERVICE lookup_service_state(const char *service)
|
RC_SERVICE lookup_service_state(const char *service)
|
||||||
|
|||||||
56
src/rc/rc-pipes.c
Normal file
56
src/rc/rc-pipes.c
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* rc-pipes.c
|
||||||
|
* Helper to handle spawning processes and connecting them to pipes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 The OpenRC Authors.
|
||||||
|
* See the Authors file at the top-level directory of this distribution and
|
||||||
|
* https://github.com/OpenRC/openrc/blob/master/AUTHORS
|
||||||
|
*
|
||||||
|
* This file is part of OpenRC. It is subject to the license terms in
|
||||||
|
* the LICENSE file found in the top-level directory of this
|
||||||
|
* distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
|
||||||
|
* This file may not be copied, modified, propagated, or distributed
|
||||||
|
* except according to the terms contained in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "rc-pipes.h"
|
||||||
|
|
||||||
|
static const int pipe_read_end = 0;
|
||||||
|
static const int pipe_write_end = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Starts a command with stdin redirected from a pipe
|
||||||
|
* Returns the write end of the pipe or -1
|
||||||
|
*/
|
||||||
|
int rc_pipe_command(char *cmd)
|
||||||
|
{
|
||||||
|
int pfd[2];
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
if (pipe(pfd) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid > 0) {
|
||||||
|
/* parent */
|
||||||
|
close(pfd[pipe_read_end]);
|
||||||
|
return pfd[pipe_write_end];
|
||||||
|
} else if (pid == 0) {
|
||||||
|
/* child */
|
||||||
|
close(pfd[pipe_write_end]);
|
||||||
|
if (pfd[pipe_read_end] != STDIN_FILENO) {
|
||||||
|
if (dup2(pfd[pipe_read_end], STDIN_FILENO) < 0)
|
||||||
|
exit(1);
|
||||||
|
close(pfd[pipe_read_end]);
|
||||||
|
}
|
||||||
|
execl("/bin/sh", "sh", "-c", cmd, NULL);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
18
src/rc/rc-pipes.h
Normal file
18
src/rc/rc-pipes.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 The OpenRC Authors.
|
||||||
|
* See the Authors file at the top-level directory of this distribution and
|
||||||
|
* https://github.com/OpenRC/openrc/blob/master/AUTHORS
|
||||||
|
*
|
||||||
|
* This file is part of OpenRC. It is subject to the license terms in
|
||||||
|
* the LICENSE file found in the top-level directory of this
|
||||||
|
* distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
|
||||||
|
* This file may not be copied, modified, propagated, or distributed
|
||||||
|
* except according to the terms contained in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RC_PIPES_H
|
||||||
|
#define RC_PIPES_H
|
||||||
|
|
||||||
|
int rc_pipe_command(char *cmd);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -29,18 +29,25 @@
|
|||||||
|
|
||||||
const char *applet = NULL;
|
const char *applet = NULL;
|
||||||
const char *extraopts = NULL;
|
const char *extraopts = NULL;
|
||||||
const char *getoptstring = "ce:ilr:IN" getoptstring_COMMON;
|
const char *getoptstring = "cdDe:ilr:INsSZ" getoptstring_COMMON;
|
||||||
const struct option longopts[] = {
|
const struct option longopts[] = {
|
||||||
|
{ "debug", 0, NULL, 'd' },
|
||||||
|
{ "nodeps", 0, NULL, 'D' },
|
||||||
{ "exists", 1, NULL, 'e' },
|
{ "exists", 1, NULL, 'e' },
|
||||||
{ "ifcrashed", 0, NULL, 'c' },
|
{ "ifcrashed", 0, NULL, 'c' },
|
||||||
{ "ifexists", 0, NULL, 'i' },
|
{ "ifexists", 0, NULL, 'i' },
|
||||||
{ "ifinactive", 0, NULL, 'I' },
|
{ "ifinactive", 0, NULL, 'I' },
|
||||||
{ "ifnotstarted", 0, NULL, 'N' },
|
{ "ifnotstarted", 0, NULL, 'N' },
|
||||||
|
{ "ifstarted", 0, NULL, 's' },
|
||||||
|
{ "ifstopped", 0, NULL, 'S' },
|
||||||
{ "list", 0, NULL, 'l' },
|
{ "list", 0, NULL, 'l' },
|
||||||
{ "resolve", 1, NULL, 'r' },
|
{ "resolve", 1, NULL, 'r' },
|
||||||
|
{ "dry-run", 0, NULL, 'Z' },
|
||||||
longopts_COMMON
|
longopts_COMMON
|
||||||
};
|
};
|
||||||
const char * const longopts_help[] = {
|
const char * const longopts_help[] = {
|
||||||
|
"set xtrace when running the command",
|
||||||
|
"ignore dependencies",
|
||||||
"tests if the service exists or not",
|
"tests if the service exists or not",
|
||||||
"if the service is crashed then run the command",
|
"if the service is crashed then run the command",
|
||||||
"if the service exists then run the command",
|
"if the service exists then run the command",
|
||||||
@@ -48,6 +55,7 @@ const char * const longopts_help[] = {
|
|||||||
"if the service is not started then run the command",
|
"if the service is not started then run the command",
|
||||||
"list all available services",
|
"list all available services",
|
||||||
"resolve the service name to an init script",
|
"resolve the service name to an init script",
|
||||||
|
"dry run (show what would happen)",
|
||||||
longopts_help_COMMON
|
longopts_help_COMMON
|
||||||
};
|
};
|
||||||
const char *usagestring = "" \
|
const char *usagestring = "" \
|
||||||
@@ -67,6 +75,8 @@ int main(int argc, char **argv)
|
|||||||
bool if_exists = false;
|
bool if_exists = false;
|
||||||
bool if_inactive = false;
|
bool if_inactive = false;
|
||||||
bool if_notstarted = false;
|
bool if_notstarted = false;
|
||||||
|
bool if_started = false;
|
||||||
|
bool if_stopped = false;
|
||||||
|
|
||||||
applet = basename_c(argv[0]);
|
applet = basename_c(argv[0]);
|
||||||
/* Ensure that we are only quiet when explicitly told to be */
|
/* Ensure that we are only quiet when explicitly told to be */
|
||||||
@@ -76,6 +86,12 @@ int main(int argc, char **argv)
|
|||||||
longopts, (int *) 0)) != -1)
|
longopts, (int *) 0)) != -1)
|
||||||
{
|
{
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
case 'd':
|
||||||
|
setenv("RC_DEBUG", "yes", 1);
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
setenv("RC_NODEPS", "yes", 1);
|
||||||
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
service = rc_service_resolve(optarg);
|
service = rc_service_resolve(optarg);
|
||||||
opt = service ? EXIT_SUCCESS : EXIT_FAILURE;
|
opt = service ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
@@ -112,6 +128,15 @@ int main(int argc, char **argv)
|
|||||||
free(service);
|
free(service);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
|
case 's':
|
||||||
|
if_started = true;
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
if_stopped = true;
|
||||||
|
break;
|
||||||
|
case 'Z':
|
||||||
|
setenv("IN_DRYRUN", "yes", 1);
|
||||||
|
break;
|
||||||
|
|
||||||
case_RC_COMMON_GETOPT
|
case_RC_COMMON_GETOPT
|
||||||
}
|
}
|
||||||
@@ -133,6 +158,10 @@ int main(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
if (if_notstarted && (state & RC_SERVICE_STARTED))
|
if (if_notstarted && (state & RC_SERVICE_STARTED))
|
||||||
return 0;
|
return 0;
|
||||||
|
if (if_started && ! (state & RC_SERVICE_STARTED))
|
||||||
|
return 0;
|
||||||
|
if (if_stopped && ! (state & RC_SERVICE_STOPPED))
|
||||||
|
return 0;
|
||||||
*argv = service;
|
*argv = service;
|
||||||
execv(*argv, argv);
|
execv(*argv, argv);
|
||||||
eerrorx("%s: %s", applet, strerror(errno));
|
eerrorx("%s: %s", applet, strerror(errno));
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ const char *usagestring = "" \
|
|||||||
"Usage: rc-status [options] <runlevel>...\n" \
|
"Usage: rc-status [options] <runlevel>...\n" \
|
||||||
" or: rc-status [options] [-a | -c | -l | -m | -r | -s | -u]";
|
" or: rc-status [options] [-a | -c | -l | -m | -r | -s | -u]";
|
||||||
|
|
||||||
static bool test_crashed = false;
|
|
||||||
static RC_DEPTREE *deptree;
|
static RC_DEPTREE *deptree;
|
||||||
static RC_STRINGLIST *types;
|
static RC_STRINGLIST *types;
|
||||||
|
|
||||||
@@ -76,7 +75,7 @@ print_level(const char *prefix, const char *level)
|
|||||||
printf("%s\n", level);
|
printf("%s\n", level);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_uptime(const char *service, char *uptime, int uptime_size)
|
static char *get_uptime(const char *service)
|
||||||
{
|
{
|
||||||
RC_SERVICE state = rc_service_state(service);
|
RC_SERVICE state = rc_service_state(service);
|
||||||
char *start_count;
|
char *start_count;
|
||||||
@@ -88,8 +87,8 @@ static void get_uptime(const char *service, char *uptime, int uptime_size)
|
|||||||
time_t diff_hours = (time_t) 0;
|
time_t diff_hours = (time_t) 0;
|
||||||
time_t diff_mins = (time_t) 0;
|
time_t diff_mins = (time_t) 0;
|
||||||
time_t diff_secs = (time_t) 0;
|
time_t diff_secs = (time_t) 0;
|
||||||
|
char *uptime;
|
||||||
|
|
||||||
uptime[0] = '\0';
|
|
||||||
if (state & RC_SERVICE_STARTED) {
|
if (state & RC_SERVICE_STARTED) {
|
||||||
start_count = rc_service_value_get(service, "start_count");
|
start_count = rc_service_value_get(service, "start_count");
|
||||||
start_time_string = rc_service_value_get(service, "start_time");
|
start_time_string = rc_service_value_get(service, "start_time");
|
||||||
@@ -111,23 +110,24 @@ static void get_uptime(const char *service, char *uptime, int uptime_size)
|
|||||||
diff_secs %= diff_mins * (time_t) 60;
|
diff_secs %= diff_mins * (time_t) 60;
|
||||||
}
|
}
|
||||||
if (diff_days > 0)
|
if (diff_days > 0)
|
||||||
snprintf(uptime, uptime_size,
|
xasprintf(&uptime,
|
||||||
"%ld day(s) %02ld:%02ld:%02ld (%s)",
|
"%ld day(s) %02ld:%02ld:%02ld (%s)",
|
||||||
diff_days, diff_hours, diff_mins, diff_secs,
|
diff_days, diff_hours, diff_mins, diff_secs,
|
||||||
start_count);
|
start_count);
|
||||||
else
|
else
|
||||||
snprintf(uptime, uptime_size,
|
xasprintf(&uptime,
|
||||||
"%02ld:%02ld:%02ld (%s)",
|
"%02ld:%02ld:%02ld (%s)",
|
||||||
diff_hours, diff_mins, diff_secs, start_count);
|
diff_hours, diff_mins, diff_secs, start_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return uptime;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_service(const char *service)
|
print_service(const char *service)
|
||||||
{
|
{
|
||||||
char status[60];
|
char *status = NULL;
|
||||||
char uptime [40];
|
char *uptime = NULL;
|
||||||
char *child_pid = NULL;
|
char *child_pid = NULL;
|
||||||
char *start_time = NULL;
|
char *start_time = NULL;
|
||||||
int cols = printf(" %s", service);
|
int cols = printf(" %s", service);
|
||||||
@@ -136,42 +136,45 @@ print_service(const char *service)
|
|||||||
ECOLOR color = ECOLOR_BAD;
|
ECOLOR color = ECOLOR_BAD;
|
||||||
|
|
||||||
if (state & RC_SERVICE_STOPPING)
|
if (state & RC_SERVICE_STOPPING)
|
||||||
snprintf(status, sizeof(status), "stopping ");
|
xasprintf(&status, "stopping ");
|
||||||
else if (state & RC_SERVICE_STARTING) {
|
else if (state & RC_SERVICE_STARTING) {
|
||||||
snprintf(status, sizeof(status), "starting ");
|
xasprintf(&status, "starting ");
|
||||||
color = ECOLOR_WARN;
|
color = ECOLOR_WARN;
|
||||||
} else if (state & RC_SERVICE_INACTIVE) {
|
} else if (state & RC_SERVICE_INACTIVE) {
|
||||||
snprintf(status, sizeof(status), "inactive ");
|
xasprintf(&status, "inactive ");
|
||||||
color = ECOLOR_WARN;
|
color = ECOLOR_WARN;
|
||||||
} else if (state & RC_SERVICE_STARTED) {
|
} else if (state & RC_SERVICE_STARTED) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (test_crashed &&
|
if (rc_service_daemons_crashed(service) && errno != EACCES)
|
||||||
rc_service_daemons_crashed(service) &&
|
|
||||||
errno != EACCES)
|
|
||||||
{
|
{
|
||||||
child_pid = rc_service_value_get(service, "child_pid");
|
child_pid = rc_service_value_get(service, "child_pid");
|
||||||
start_time = rc_service_value_get(service, "start_time");
|
start_time = rc_service_value_get(service, "start_time");
|
||||||
if (start_time && child_pid)
|
if (start_time && child_pid)
|
||||||
snprintf(status, sizeof(status), " unsupervised ");
|
xasprintf(&status, " unsupervised ");
|
||||||
else
|
else
|
||||||
snprintf(status, sizeof(status), " crashed ");
|
xasprintf(&status, " crashed ");
|
||||||
free(child_pid);
|
free(child_pid);
|
||||||
free(start_time);
|
free(start_time);
|
||||||
} else {
|
} else {
|
||||||
get_uptime(service, uptime, 40);
|
uptime = get_uptime(service);
|
||||||
snprintf(status, sizeof(status), " started %s", uptime);
|
if (uptime) {
|
||||||
|
xasprintf(&status, " started %s", uptime);
|
||||||
|
free(uptime);
|
||||||
|
} else
|
||||||
|
xasprintf(&status, " started ");
|
||||||
color = ECOLOR_GOOD;
|
color = ECOLOR_GOOD;
|
||||||
}
|
}
|
||||||
} else if (state & RC_SERVICE_SCHEDULED) {
|
} else if (state & RC_SERVICE_SCHEDULED) {
|
||||||
snprintf(status, sizeof(status), "scheduled");
|
xasprintf(&status, "scheduled");
|
||||||
color = ECOLOR_WARN;
|
color = ECOLOR_WARN;
|
||||||
} else
|
} else
|
||||||
snprintf(status, sizeof(status), " stopped ");
|
xasprintf(&status, " stopped ");
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (c && *c && isatty(fileno(stdout)))
|
if (c && *c && isatty(fileno(stdout)))
|
||||||
printf("\n");
|
printf("\n");
|
||||||
ebracket(cols, color, status);
|
ebracket(cols, color, status);
|
||||||
|
free(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -240,8 +243,6 @@ int main(int argc, char **argv)
|
|||||||
char *p, *runlevel = NULL;
|
char *p, *runlevel = NULL;
|
||||||
int opt, retval = 0;
|
int opt, retval = 0;
|
||||||
|
|
||||||
test_crashed = _rc_can_find_pids();
|
|
||||||
|
|
||||||
applet = basename_c(argv[0]);
|
applet = basename_c(argv[0]);
|
||||||
while ((opt = getopt_long(argc, argv, getoptstring, longopts,
|
while ((opt = getopt_long(argc, argv, getoptstring, longopts,
|
||||||
(int *) 0)) != -1)
|
(int *) 0)) != -1)
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ add(const char *runlevel, const char *service)
|
|||||||
|
|
||||||
if (!rc_service_exists(service)) {
|
if (!rc_service_exists(service)) {
|
||||||
if (errno == ENOEXEC)
|
if (errno == ENOEXEC)
|
||||||
eerror("%s: service `%s' is not executeable",
|
eerror("%s: service `%s' is not executable",
|
||||||
applet, service);
|
applet, service);
|
||||||
else
|
else
|
||||||
eerror("%s: service `%s' does not exist",
|
eerror("%s: service `%s' does not exist",
|
||||||
|
|||||||
40
src/rc/rc.c
40
src/rc/rc.c
@@ -101,7 +101,6 @@ clean_failed(void)
|
|||||||
{
|
{
|
||||||
DIR *dp;
|
DIR *dp;
|
||||||
struct dirent *d;
|
struct dirent *d;
|
||||||
size_t l;
|
|
||||||
char *path;
|
char *path;
|
||||||
|
|
||||||
/* Clean the failed services state dir now */
|
/* Clean the failed services state dir now */
|
||||||
@@ -112,16 +111,11 @@ clean_failed(void)
|
|||||||
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
|
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
l = strlen(RC_SVCDIR "/failed/") +
|
xasprintf(&path, RC_SVCDIR "/failed/%s", d->d_name);
|
||||||
strlen(d->d_name) + 1;
|
if (unlink(path))
|
||||||
path = xmalloc(sizeof(char) * l);
|
eerror("%s: unlink `%s': %s",
|
||||||
snprintf(path, l, RC_SVCDIR "/failed/%s", d->d_name);
|
applet, path, strerror(errno));
|
||||||
if (path) {
|
free(path);
|
||||||
if (unlink(path))
|
|
||||||
eerror("%s: unlink `%s': %s",
|
|
||||||
applet, path, strerror(errno));
|
|
||||||
free(path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
closedir(dp);
|
closedir(dp);
|
||||||
}
|
}
|
||||||
@@ -391,7 +385,7 @@ static void
|
|||||||
handle_signal(int sig)
|
handle_signal(int sig)
|
||||||
{
|
{
|
||||||
int serrno = errno;
|
int serrno = errno;
|
||||||
char signame[10] = { '\0' };
|
char *signame = NULL;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
RC_PID *pi;
|
RC_PID *pi;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
@@ -422,16 +416,16 @@ handle_signal(int sig)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
if (!signame[0])
|
if (!signame)
|
||||||
snprintf(signame, sizeof(signame), "SIGINT");
|
xasprintf(&signame, "SIGINT");
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
if (!signame[0])
|
if (!signame)
|
||||||
snprintf(signame, sizeof(signame), "SIGTERM");
|
xasprintf(&signame, "SIGTERM");
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case SIGQUIT:
|
case SIGQUIT:
|
||||||
if (!signame[0])
|
if (!signame)
|
||||||
snprintf(signame, sizeof(signame), "SIGQUIT");
|
xasprintf(&signame, "SIGQUIT");
|
||||||
eerrorx("%s: caught %s, aborting", applet, signame);
|
eerrorx("%s: caught %s, aborting", applet, signame);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
case SIGUSR1:
|
case SIGUSR1:
|
||||||
@@ -512,14 +506,11 @@ runlevel_config(const char *service, const char *level)
|
|||||||
{
|
{
|
||||||
char *init = rc_service_resolve(service);
|
char *init = rc_service_resolve(service);
|
||||||
char *conf, *dir;
|
char *conf, *dir;
|
||||||
size_t l;
|
|
||||||
bool retval;
|
bool retval;
|
||||||
|
|
||||||
dir = dirname(init);
|
dir = dirname(init);
|
||||||
dir = dirname(init);
|
dir = dirname(init);
|
||||||
l = strlen(dir) + strlen(level) + strlen(service) + 10;
|
xasprintf(&conf, "%s/conf.d/%s.%s", dir, service, level);
|
||||||
conf = xmalloc(sizeof(char) * l);
|
|
||||||
snprintf(conf, l, "%s/conf.d/%s.%s", dir, service, level);
|
|
||||||
retval = exists(conf);
|
retval = exists(conf);
|
||||||
free(conf);
|
free(conf);
|
||||||
free(init);
|
free(init);
|
||||||
@@ -744,7 +735,7 @@ int main(int argc, char **argv)
|
|||||||
bool going_down = false;
|
bool going_down = false;
|
||||||
int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
|
int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
|
||||||
char *krunlevel = NULL;
|
char *krunlevel = NULL;
|
||||||
char pidstr[10];
|
char *pidstr = NULL;
|
||||||
int opt;
|
int opt;
|
||||||
bool parallel;
|
bool parallel;
|
||||||
int regen = 0;
|
int regen = 0;
|
||||||
@@ -844,8 +835,9 @@ int main(int argc, char **argv)
|
|||||||
setenv("EINFO_LOG", "openrc", 1);
|
setenv("EINFO_LOG", "openrc", 1);
|
||||||
|
|
||||||
/* Export our PID */
|
/* Export our PID */
|
||||||
snprintf(pidstr, sizeof(pidstr), "%d", getpid());
|
xasprintf(&pidstr, "%d", getpid());
|
||||||
setenv("RC_PID", pidstr, 1);
|
setenv("RC_PID", pidstr, 1);
|
||||||
|
free(pidstr);
|
||||||
|
|
||||||
/* Create a list of all services which should be started for the new or
|
/* Create a list of all services which should be started for the new or
|
||||||
* current runlevel including those in boot, sysinit and hotplugged
|
* current runlevel including those in boot, sysinit and hotplugged
|
||||||
|
|||||||
@@ -59,13 +59,14 @@ static struct pam_conv conv = { NULL, NULL};
|
|||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "rc-misc.h"
|
#include "rc-misc.h"
|
||||||
|
#include "rc-pipes.h"
|
||||||
#include "rc-schedules.h"
|
#include "rc-schedules.h"
|
||||||
#include "_usage.h"
|
#include "_usage.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
const char *applet = NULL;
|
const char *applet = NULL;
|
||||||
const char *extraopts = NULL;
|
const char *extraopts = NULL;
|
||||||
const char *getoptstring = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:" \
|
const char *getoptstring = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:3:4:" \
|
||||||
getoptstring_COMMON;
|
getoptstring_COMMON;
|
||||||
const struct option longopts[] = {
|
const struct option longopts[] = {
|
||||||
{ "ionice", 1, NULL, 'I'},
|
{ "ionice", 1, NULL, 'I'},
|
||||||
@@ -93,6 +94,8 @@ const struct option longopts[] = {
|
|||||||
{ "exec", 1, NULL, 'x'},
|
{ "exec", 1, NULL, 'x'},
|
||||||
{ "stdout", 1, NULL, '1'},
|
{ "stdout", 1, NULL, '1'},
|
||||||
{ "stderr", 1, NULL, '2'},
|
{ "stderr", 1, NULL, '2'},
|
||||||
|
{ "stdout-logger",1, NULL, '3'},
|
||||||
|
{ "stderr-logger",1, NULL, '4'},
|
||||||
{ "progress", 0, NULL, 'P'},
|
{ "progress", 0, NULL, 'P'},
|
||||||
longopts_COMMON
|
longopts_COMMON
|
||||||
};
|
};
|
||||||
@@ -122,6 +125,8 @@ const char * const longopts_help[] = {
|
|||||||
"Binary to start/stop",
|
"Binary to start/stop",
|
||||||
"Redirect stdout to file",
|
"Redirect stdout to file",
|
||||||
"Redirect stderr to file",
|
"Redirect stderr to file",
|
||||||
|
"Redirect stdout to process",
|
||||||
|
"Redirect stderr to process",
|
||||||
"Print dots each second while waiting",
|
"Print dots each second while waiting",
|
||||||
longopts_help_COMMON
|
longopts_help_COMMON
|
||||||
};
|
};
|
||||||
@@ -162,20 +167,20 @@ handle_signal(int sig)
|
|||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
int serrno = errno;
|
int serrno = errno;
|
||||||
char signame[10] = { '\0' };
|
char *signame = NULL;
|
||||||
|
|
||||||
switch (sig) {
|
switch (sig) {
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
if (!signame[0])
|
if (!signame)
|
||||||
snprintf(signame, sizeof(signame), "SIGINT");
|
xasprintf(&signame, "SIGINT");
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
if (!signame[0])
|
if (!signame)
|
||||||
snprintf(signame, sizeof(signame), "SIGTERM");
|
xasprintf(&signame, "SIGTERM");
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case SIGQUIT:
|
case SIGQUIT:
|
||||||
if (!signame[0])
|
if (!signame)
|
||||||
snprintf(signame, sizeof(signame), "SIGQUIT");
|
xasprintf(&signame, "SIGQUIT");
|
||||||
eerrorx("%s: caught %s, aborting", applet, signame);
|
eerrorx("%s: caught %s, aborting", applet, signame);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
|
|
||||||
@@ -194,6 +199,9 @@ handle_signal(int sig)
|
|||||||
eerror("%s: caught unknown signal %d", applet, sig);
|
eerror("%s: caught unknown signal %d", applet, sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* free signame */
|
||||||
|
free(signame);
|
||||||
|
|
||||||
/* Restore errno */
|
/* Restore errno */
|
||||||
errno = serrno;
|
errno = serrno;
|
||||||
}
|
}
|
||||||
@@ -202,7 +210,6 @@ static char *
|
|||||||
expand_home(const char *home, const char *path)
|
expand_home(const char *home, const char *path)
|
||||||
{
|
{
|
||||||
char *opath, *ppath, *p, *nh;
|
char *opath, *ppath, *p, *nh;
|
||||||
size_t len;
|
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
|
||||||
if (!path || *path != '~')
|
if (!path || *path != '~')
|
||||||
@@ -233,9 +240,7 @@ expand_home(const char *home, const char *path)
|
|||||||
return xstrdup(home);
|
return xstrdup(home);
|
||||||
}
|
}
|
||||||
|
|
||||||
len = strlen(ppath) + strlen(home) + 1;
|
xasprintf(&nh, "%s%s", home, ppath);
|
||||||
nh = xmalloc(len);
|
|
||||||
snprintf(nh, len, "%s%s", home, ppath);
|
|
||||||
free(opath);
|
free(opath);
|
||||||
return nh;
|
return nh;
|
||||||
}
|
}
|
||||||
@@ -276,6 +281,8 @@ int main(int argc, char **argv)
|
|||||||
int tid = 0;
|
int tid = 0;
|
||||||
char *redirect_stderr = NULL;
|
char *redirect_stderr = NULL;
|
||||||
char *redirect_stdout = NULL;
|
char *redirect_stdout = NULL;
|
||||||
|
char *stderr_process = NULL;
|
||||||
|
char *stdout_process = NULL;
|
||||||
int stdin_fd;
|
int stdin_fd;
|
||||||
int stdout_fd;
|
int stdout_fd;
|
||||||
int stderr_fd;
|
int stderr_fd;
|
||||||
@@ -379,6 +386,7 @@ int main(int argc, char **argv)
|
|||||||
case 'c': /* --chuid <username>|<uid> */
|
case 'c': /* --chuid <username>|<uid> */
|
||||||
/* DEPRECATED */
|
/* DEPRECATED */
|
||||||
ewarn("WARNING: -c/--chuid is deprecated and will be removed in the future, please use -u/--user instead");
|
ewarn("WARNING: -c/--chuid is deprecated and will be removed in the future, please use -u/--user instead");
|
||||||
|
/* falls through */
|
||||||
case 'u': /* --user <username>|<uid> */
|
case 'u': /* --user <username>|<uid> */
|
||||||
{
|
{
|
||||||
p = optarg;
|
p = optarg;
|
||||||
@@ -500,6 +508,14 @@ int main(int argc, char **argv)
|
|||||||
redirect_stderr = optarg;
|
redirect_stderr = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '3': /* --stdout-logger "command to run for stdout logging" */
|
||||||
|
stdout_process = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '4': /* --stderr-logger "command to run for stderr logging" */
|
||||||
|
stderr_process = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
case_RC_COMMON_GETOPT
|
case_RC_COMMON_GETOPT
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,6 +567,9 @@ int main(int argc, char **argv)
|
|||||||
if (redirect_stdout || redirect_stderr)
|
if (redirect_stdout || redirect_stderr)
|
||||||
eerrorx("%s: --stdout and --stderr are only relevant"
|
eerrorx("%s: --stdout and --stderr are only relevant"
|
||||||
" with --start", applet);
|
" with --start", applet);
|
||||||
|
if (stdout_process || stderr_process)
|
||||||
|
eerrorx("%s: --stdout-logger and --stderr-logger are only relevant"
|
||||||
|
" with --start", applet);
|
||||||
if (start_wait)
|
if (start_wait)
|
||||||
ewarn("using --wait with --stop has no effect,"
|
ewarn("using --wait with --stop has no effect,"
|
||||||
" use --retry instead");
|
" use --retry instead");
|
||||||
@@ -563,6 +582,15 @@ int main(int argc, char **argv)
|
|||||||
if ((redirect_stdout || redirect_stderr) && !background)
|
if ((redirect_stdout || redirect_stderr) && !background)
|
||||||
eerrorx("%s: --stdout and --stderr are only relevant"
|
eerrorx("%s: --stdout and --stderr are only relevant"
|
||||||
" with --background", applet);
|
" with --background", applet);
|
||||||
|
if ((stdout_process || stderr_process) && !background)
|
||||||
|
eerrorx("%s: --stdout-logger and --stderr-logger are only relevant"
|
||||||
|
" with --background", applet);
|
||||||
|
if (redirect_stdout && stdout_process)
|
||||||
|
eerrorx("%s: do not use --stdout and --stdout-logger together",
|
||||||
|
applet);
|
||||||
|
if (redirect_stderr && stderr_process)
|
||||||
|
eerrorx("%s: do not use --stderr and --stderr-logger together",
|
||||||
|
applet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expand ~ */
|
/* Expand ~ */
|
||||||
@@ -603,7 +631,6 @@ int main(int argc, char **argv)
|
|||||||
*exec_file ? exec_file : exec);
|
*exec_file ? exec_file : exec);
|
||||||
free(exec_file);
|
free(exec_file);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (start && retry)
|
if (start && retry)
|
||||||
ewarn("using --retry with --start has no effect,"
|
ewarn("using --retry with --start has no effect,"
|
||||||
@@ -661,7 +688,7 @@ int main(int argc, char **argv)
|
|||||||
parse_schedule(applet, NULL, sig);
|
parse_schedule(applet, NULL, sig);
|
||||||
if (pidfile) {
|
if (pidfile) {
|
||||||
pid = get_pid(applet, pidfile);
|
pid = get_pid(applet, pidfile);
|
||||||
if (pid == -1)
|
if (pid == -1 && errno != ENOENT)
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
} else {
|
} else {
|
||||||
pid = 0;
|
pid = 0;
|
||||||
@@ -886,6 +913,12 @@ int main(int argc, char **argv)
|
|||||||
eerrorx("%s: unable to open the logfile"
|
eerrorx("%s: unable to open the logfile"
|
||||||
" for stdout `%s': %s",
|
" for stdout `%s': %s",
|
||||||
applet, redirect_stdout, strerror(errno));
|
applet, redirect_stdout, strerror(errno));
|
||||||
|
}else if (stdout_process) {
|
||||||
|
stdout_fd = rc_pipe_command(stdout_process);
|
||||||
|
if (stdout_fd == -1)
|
||||||
|
eerrorx("%s: unable to open the logging process"
|
||||||
|
" for stdout `%s': %s",
|
||||||
|
applet, stdout_process, strerror(errno));
|
||||||
}
|
}
|
||||||
if (redirect_stderr) {
|
if (redirect_stderr) {
|
||||||
if ((stderr_fd = open(redirect_stderr,
|
if ((stderr_fd = open(redirect_stderr,
|
||||||
@@ -894,13 +927,21 @@ int main(int argc, char **argv)
|
|||||||
eerrorx("%s: unable to open the logfile"
|
eerrorx("%s: unable to open the logfile"
|
||||||
" for stderr `%s': %s",
|
" for stderr `%s': %s",
|
||||||
applet, redirect_stderr, strerror(errno));
|
applet, redirect_stderr, strerror(errno));
|
||||||
|
}else if (stderr_process) {
|
||||||
|
stderr_fd = rc_pipe_command(stderr_process);
|
||||||
|
if (stderr_fd == -1)
|
||||||
|
eerrorx("%s: unable to open the logging process"
|
||||||
|
" for stderr `%s': %s",
|
||||||
|
applet, stderr_process, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (background)
|
if (background)
|
||||||
dup2(stdin_fd, STDIN_FILENO);
|
dup2(stdin_fd, STDIN_FILENO);
|
||||||
if (background || redirect_stdout || rc_yesno(getenv("EINFO_QUIET")))
|
if (background || redirect_stdout || stdout_process
|
||||||
|
|| rc_yesno(getenv("EINFO_QUIET")))
|
||||||
dup2(stdout_fd, STDOUT_FILENO);
|
dup2(stdout_fd, STDOUT_FILENO);
|
||||||
if (background || redirect_stderr || rc_yesno(getenv("EINFO_QUIET")))
|
if (background || redirect_stderr || stderr_process
|
||||||
|
|| 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)
|
||||||
|
|||||||
@@ -186,7 +186,6 @@ static void handle_signal(int sig)
|
|||||||
static char * expand_home(const char *home, const char *path)
|
static char * expand_home(const char *home, const char *path)
|
||||||
{
|
{
|
||||||
char *opath, *ppath, *p, *nh;
|
char *opath, *ppath, *p, *nh;
|
||||||
size_t len;
|
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
|
||||||
if (!path || *path != '~')
|
if (!path || *path != '~')
|
||||||
@@ -217,9 +216,7 @@ static char * expand_home(const char *home, const char *path)
|
|||||||
return xstrdup(home);
|
return xstrdup(home);
|
||||||
}
|
}
|
||||||
|
|
||||||
len = strlen(ppath) + strlen(home) + 1;
|
xasprintf(&nh, "%s%s", home, ppath);
|
||||||
nh = xmalloc(len);
|
|
||||||
snprintf(nh, len, "%s%s", home, ppath);
|
|
||||||
free(opath);
|
free(opath);
|
||||||
return nh;
|
return nh;
|
||||||
}
|
}
|
||||||
@@ -232,8 +229,8 @@ static char *make_cmdline(char **argv)
|
|||||||
|
|
||||||
for (c = argv; c && *c; c++)
|
for (c = argv; c && *c; c++)
|
||||||
len += (strlen(*c) + 1);
|
len += (strlen(*c) + 1);
|
||||||
cmdline = xmalloc(len);
|
cmdline = xmalloc(len+1);
|
||||||
memset(cmdline, 0, len);
|
memset(cmdline, 0, len+1);
|
||||||
for (c = argv; c && *c; c++) {
|
for (c = argv; c && *c; c++) {
|
||||||
strcat(cmdline, *c);
|
strcat(cmdline, *c);
|
||||||
strcat(cmdline, " ");
|
strcat(cmdline, " ");
|
||||||
@@ -863,10 +860,13 @@ int main(int argc, char **argv)
|
|||||||
varbuf = NULL;
|
varbuf = NULL;
|
||||||
xasprintf(&varbuf, "%i", respawn_delay);
|
xasprintf(&varbuf, "%i", respawn_delay);
|
||||||
rc_service_value_set(svcname, "respawn_delay", varbuf);
|
rc_service_value_set(svcname, "respawn_delay", varbuf);
|
||||||
|
free(varbuf);
|
||||||
xasprintf(&varbuf, "%i", respawn_max);
|
xasprintf(&varbuf, "%i", respawn_max);
|
||||||
rc_service_value_set(svcname, "respawn_max", varbuf);
|
rc_service_value_set(svcname, "respawn_max", varbuf);
|
||||||
|
free(varbuf);
|
||||||
xasprintf(&varbuf, "%i", respawn_period);
|
xasprintf(&varbuf, "%i", respawn_period);
|
||||||
rc_service_value_set(svcname, "respawn_period", varbuf);
|
rc_service_value_set(svcname, "respawn_period", varbuf);
|
||||||
|
free(varbuf);
|
||||||
child_pid = fork();
|
child_pid = fork();
|
||||||
if (child_pid == -1)
|
if (child_pid == -1)
|
||||||
eerrorx("%s: fork: %s", applet, strerror(errno));
|
eerrorx("%s: fork: %s", applet, strerror(errno));
|
||||||
@@ -894,6 +894,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
xasprintf(&varbuf, "%d", x);
|
xasprintf(&varbuf, "%d", x);
|
||||||
rc_service_value_set(svcname, "argc", varbuf);
|
rc_service_value_set(svcname, "argc", varbuf);
|
||||||
|
free(varbuf);
|
||||||
rc_service_value_set(svcname, "exec", exec);
|
rc_service_value_set(svcname, "exec", exec);
|
||||||
supervisor(exec, argv);
|
supervisor(exec, argv);
|
||||||
} else
|
} else
|
||||||
|
|||||||
@@ -90,8 +90,8 @@ the service script by hand.
|
|||||||
|
|
||||||
FIXME: Document stacked runlevels
|
FIXME: Document stacked runlevels
|
||||||
|
|
||||||
The default startup uses the runlevels `boot`, `sysinit` and `default`, in that
|
The default startup uses the runlevels `sysinit`, `boot`, and `default`,
|
||||||
order. Shutdown uses the `shutdown` runlevel.
|
in that order. Shutdown uses the `shutdown` runlevel.
|
||||||
|
|
||||||
# The Magic of `conf.d`
|
# The Magic of `conf.d`
|
||||||
|
|
||||||
@@ -162,7 +162,6 @@ stopped, by using:
|
|||||||
The `rc_cgroup_cleanup` setting can be changed to yes to make this
|
The `rc_cgroup_cleanup` setting can be changed to yes to make this
|
||||||
happen automatically when the service is stopped.
|
happen automatically when the service is stopped.
|
||||||
|
|
||||||
|
|
||||||
# Caching
|
# Caching
|
||||||
|
|
||||||
For performance reasons OpenRC keeps a cache of pre-parsed service metadata
|
For performance reasons OpenRC keeps a cache of pre-parsed service metadata
|
||||||
|
|||||||
Reference in New Issue
Block a user