Compare commits

..

99 Commits

Author SHA1 Message Date
William Hubbs
8d6370d469 version 0.41.1 2019-02-23 18:06:00 -06:00
William Hubbs
75ce3addd2 update ChangeLog 2019-02-23 18:03:28 -06:00
William Hubbs
d818be6e2b librc: fix potential buffer overflow in pid_is_argv
This fixes #299.
2019-02-23 18:00:08 -06:00
William Hubbs
b812524303 Revert "src/librc/librc-daemon.c: fix buffer overrun in pid_is_argv"
This reverts commit 084877eb52.
The mentioned commit caused some systems to have some services reported
as crashed.

This fixes #297.
This fixes #298.
2019-02-23 18:00:08 -06:00
William Hubbs
56c006ebd6 Update ChangeLog 2019-02-22 19:03:41 -06:00
William Hubbs
067088bbff move ci scripts to their own directory
This fixes #296.
2019-02-22 18:50:13 -06:00
William Hubbs
52d4e56674 combine test directories
This fixes #295.
2019-02-22 18:08:19 -06:00
William Hubbs
6e6902c28b remove unused test ignore patterns 2019-02-22 16:27:52 -06:00
William Hubbs
084823182a remove unused test data files 2019-02-22 13:25:51 -06:00
Georgy Yakovlev
7478c104fc librc/librc-depend.c: fix NULL pointer dereference
In some cases deptree or depinfo can be NULL, check
before dereferencing.

Fixes https://github.com/OpenRC/openrc/issues/293
Fixes https://github.com/OpenRC/openrc/pulls/294
X-Gentoo-Bug: 659906
X-Gentoo-Bug-URL: https://bugs.gentoo.org/659906
2019-02-21 17:49:54 -06:00
Georgy Yakovlev
065b7ecc0d use cirrus-ci for FreeBSD builds
This fixes #265.
2019-02-19 13:59:01 -06:00
Sergei Trofimovich
b054aca50b src/test/runtests.sh: drop 'readelf'-based tests
The 'readelf'-based tests cover a few situations:
1. undefined symbols in shared libraries
2. unexpected exports in shared libraries

Bug #575958 shows that [2.] implementation is too simplistic
in assuming that presence of relocation equals to export presence.

It is incorrect for PLT stubs and local symbols.
Let's just drop these tests.

If one needs to cover [1.] it is better to use LDFLAGS=-Wl,--no-undefined.

This closes #292.

X-Reported-by: Benda Xu
X-Gentoo-Bug: https://bugs.gentoo.org/575958
X-Gentoo-Bug-URL: https://bugs.gentoo.org/575958
2019-02-19 11:50:11 -06:00
William Hubbs
f9e7a00ba9 rc-status: style fixes 2019-02-15 20:36:46 -06:00
William Hubbs
f1f48011ac update ChangeLog 2019-02-15 14:37:57 -06:00
William Hubbs
427a1ce299 rc-status: add -f option to allow formatting output
The -f option can be used when showing the status of services in
runlevels to allow making the output more easily parsable.
Currently, the .ini format is the only one supported.
2019-02-15 14:21:43 -06:00
William Hubbs
f43cec34ca rc-status.c: small style changes 2019-02-14 13:14:31 -06:00
William Hubbs
d64c9d2050 add experimental support for an alternate shell for service scripts
This is for #288.
2019-02-13 18:22:25 -06:00
Edan Bedrik
b2b2c57a38 librc: fix realpath() return value check
This fixes #226.
2019-02-12 17:56:17 -06:00
William Hubbs
155b845194 improve shutdown documentation
This fixes #290.
2019-02-12 16:54:12 -06:00
Austin English
9b578808fb travis: try enabling musl-gcc
This fixes #261.
2019-02-11 13:56:55 -06:00
Austin English
03164dd38d fix build with muslc
This fixes #261.
2019-02-11 13:56:33 -06:00
Austin English
2b82766452 test/skel.runtests.sh: remove unused file
git grep shows no usage, and `make test` passes

This fixes #256.
2019-02-11 11:54:10 -06:00
Felix Neumärker
3eef6e9127 zsh-completion: _rc-service support extra actions
- use rc-service <service> describe to get action list

This is for #285.
2019-01-21 17:41:59 -06:00
Felix Neumärker
77f09900a2 zsh-completion: _rc-service fix flag/command combinations
- handle `rc-service -<flag> <service> <action>` correctly

This is for #285.
2019-01-21 17:41:38 -06:00
Kim Jahn
50d77a4e5d man/openrc.8: add openrc-run.8 to see also
This fixes #283.
2019-01-18 13:40:06 -06:00
Mike Frysinger
2d31b0a3f8 man: supervise-daemon: fix various style issues
The .Dt header is supposed to be all caps.  This was mixing case.

The options block was being incorrectly indented due to a missing .El.

Some of the new options were missing the .It block, so add that.

Finally, the -D option was missing capitalization.
2019-01-01 18:36:40 -05:00
William Hubbs
b84d0bac4d travis-ci: add IRC notifications 2018-12-29 11:37:06 -06:00
William Hubbs
1ff3a37c60 start-stop-daemon: fix compiler warning 2018-12-28 09:31:38 -06:00
William Hubbs
7e95d924c9 bash-completions/rc-service: allow tab to be used again
X-Gentoo-Bug: 670290
X-Gentoo-Bug-URL: https://bugs.gentoo.org/670290
2018-12-27 16:31:15 -06:00
a15b532a02 scripts: fix halt, poweroff and reboot wrappers
These are designed to emulate the sysvinit equivalents, so pass "now" as
the time argument if no arguments are given.

This fixes #268.
2018-12-27 13:52:16 -06:00
philhofer
3e00fbc9b0 fix leading whitespace
Clean up code indented with mixed tabs and spaces.
No actual code changes.

This fixes #280.
2018-12-27 13:13:09 -06:00
philhofer
846e460075 fix potential out-of-bounds reads
readlink(3) does not nul-terminate the result it sticks
into the supplied buffer. Consequently, the code

  rc = readlink(path, buf, sizeof(buf));

does not necessarily produce a C string.

The code in rc_find_pid() produces some C strings this way
and passes them to strlen() and strcmp(), which can lead
to an out-of-bounds read.

In this case, since the code already takes care to
zero-initialize the buffers before passing them
to readlink(3), only allow sizeof(buf)-1 bytes to
be returned.

(While fixing this issue, I fixed two other locations that
used the same problematic pattern.)

This fixes #270.
2018-12-27 11:28:27 -06:00
William Hubbs
a32b14bbb4 Do not use UT_LINESIZE or __UT_LINESIZE
These are not standard.
For more information see issue #279.
This fixes #279.
2018-12-25 12:13:23 -06:00
philhofer
084877eb52 src/librc/librc-daemon.c: fix buffer overrun in pid_is_argv
The contents of /proc/<pid>/cmdline are read into
a stack buffer using

  bytes = read(fd, buffer, sizeof(buffer));

followed by appending a null terminator to the buffer with

  buffer[bytes] = '\0';

If bytes == sizeof(buffer), then this write is out-of-bounds.

Refactor the code to use rc_getfile instead, since PATH_MAX
is not the maximum size of /proc/<pid>/cmdline. (I hit this
issue in practice while compiling Linux; it tripped the
stack-smashing protector.)

This is roughly the same buffer overflow condition
that was fixed by commit 0ddee9b7d2
This fixes #269.
2018-12-24 11:55:48 -06:00
philhofer
97e74f9734 src/rc/supervise-daemon.c: formatting fixes
Fix misleading indentation and other erroneous whitespace.
This fixes #273.
2018-12-24 10:36:12 -06:00
William Hubbs
d328de198d remove /run migration script again
This time it was done correctly.
I missed a '\' the last time.
2018-12-23 21:04:00 -06:00
philhofer
a9fc26ac13 src/rc/supervise-daemon.c: do not pass NULL to strcmp
The following will cause a segfault due to NULL being
passed to strcmp(3)

$ RC_SVCNAME=foo supervise-daemon

Fix the bounds check on argc in main. If argc<=1, then
it is not safe to dereference argv[1].
2018-12-23 21:01:39 -05:00
philhofer
40f7046696 src/rc/openrc-run.c: remove duplicate statement
The statement

  ll = strlen(applet);

appears twice in the same block without any
intervening assignment to the variables
'll' or 'applet'

Remove the second (duplicate) statement.
2018-12-23 20:27:06 -05:00
William Hubbs
894995176e Revert "remove /run migration script"
For some reason removing this broke the build.

This reverts commit 5246ea7b6f.
2018-12-23 18:13:06 -06:00
William Hubbs
5246ea7b6f remove /run migration script
We have used /run for some time now and we have had this migration
script for 6 years. Linux users should have upgraded by now to a version
of OpenRC which stores its information in /run.
2018-12-23 17:49:34 -06:00
William Hubbs
ed8b768c4a fix compiler warnings 2018-12-21 12:06:15 -06:00
William Hubbs
825caa14de supervise-daemon: do not use the exec_service() function
In order to run healthcheck() and the unhealthy() function, add an
exec_command call to the supervisor.
Another difference is This function also logs errors instead of
attempting to display them.

This is for #271.
2018-12-20 17:39:31 -06:00
William Hubbs
d5c396cbfc Add debug logging to start-stop-daemon and rc-supervisor
This will make it easier to track down why the supervisor intermittently
hangs after it runs for a long time.
2018-12-18 11:29:26 -06:00
William Hubbs
5427783fdf standardize the default shell
I do not know of a need to have the default shell be a build-time
configurable setting. All *nix systems I am aware of have /bin/sh as a
default posix compatible shell.
If some systems running OpenRC do not make that assumption about
/bin/sh, I will consider bringing this back, so feel free to open an
issue.
2018-12-08 12:06:26 -06:00
William Hubbs
d95425b08a rc-cgroup.sh: remove shebang line
This is not a stand-alone script, so it does not need the shebang line.
This also means it is not necessary to run this through sed.
2018-12-07 15:31:13 -06:00
William Hubbs
76420d9849 init.d/agetty: set default respawn period to 60 seconds
Without a respawn period setting, the supervisor will give up on
respawning agetty after it is respawned respawn_max times. For most
daemons giving up like this is reasonable, but not for agettys. Agettys
should always be respawned unless they are respawning too fafst,.

If an agetty is respawning faster than 10 times in 60 seconds, this
seems to be too fast.
2018-12-06 16:37:40 -06:00
William Hubbs
bebc604438 supervise-daemon: fix busy loop
This fixes #264.
2018-12-06 16:22:15 -06:00
Alexander Zubkov
9dae4f2e38 supervise-daemon: redirect std{in,out,err} to /dev/null after demonizing
This fixes #239.
2018-12-04 16:53:39 -06:00
William Hubbs
d126542dc6 version 0.41 2018-12-03 18:14:34 -06:00
William Hubbs
ab6c8d56f1 Update ChangeLog 2018-12-03 15:56:19 -06:00
Austin English
fb4dd351c7 misc: make checks always fatal
This fixes #263.
2018-12-03 15:26:42 -06:00
Austin English
10dc65cc46 src/rc/supervise-daemon.c: fix style issue
This is for #263.
2018-12-03 15:26:20 -06:00
William Hubbs
9a2115f762 rc-status: show status for supervised services instead of a list 2018-12-03 15:16:17 -06:00
William Hubbs
eeba6df476 Update supervise-daemon man page 2018-12-03 13:08:25 -06:00
William Hubbs
ac42e81a64 supervise-daemon.sh: drop the unused stopsig variable 2018-12-03 12:43:12 -06:00
William Hubbs
af70862a7a supervise-daemon: use a default pid file if one is not specified
Since the pid file is internal to us, start moving toward deprecating it
by not requiring the user to specify it.
In the next release, I plan on working on code to start phasing out the
use of a pid file if this is possible.
2018-12-03 12:41:29 -06:00
William Hubbs
fa6611b5af rc-status: add --supervised option to show supervised services 2018-12-02 18:33:25 -06:00
William Hubbs
db01442580 rc-status: show failed services as failed 2018-12-02 18:33:25 -06:00
William Hubbs
ebf79db79e supervise-daemon: mark a service failed if it respawns too many times 2018-12-02 18:33:25 -06:00
William Hubbs
1b5a3b4ef4 supervise-daemon: make respawn-max and respawn-period independent settings 2018-12-02 18:33:25 -06:00
William Hubbs
77262c359c supervise-daemon: add support for a fifo
This will allow us to signal the daemon we are supervising as well as
send other commands to the supervisor in the future.

This fixes #227.
2018-12-02 18:33:25 -06:00
William Hubbs
7f23e0461d supervise-daemon: rework signal handling and main loop
This is needed in preparation for adding support for a fifo to allow us
to communicate with the supervisor to ask it to signal the child it is
supervising.
2018-12-02 18:33:25 -06:00
William Hubbs
ff4af908a5 Revert "checkpath: use O_PATH when available"
This reverts commit 2af0cedd59.

After speaking with Luis Ressel on the Gentoo selinux team, I am reverting
this commit for the following reasons:

- Luis told me that he feels this is not the solution we need to address
  the concern with checkpath; I will be working with him on another
  solution.

- There are concerns about the way the path variable was handled
  and the assert() call.
  The path variable should be dynamically allocated using xasprintf
  instead of defining a length at compile time. This would eliminate the
  need for the assert() call.

- It introduces the definition of _GNU_SOURCE which makes it
  easier to introduce portability concerns in the future (see #262).
2018-12-02 16:08:42 -06:00
Mike Gilbert
2af0cedd59 checkpath: use O_PATH when available
This avoids opening directories/files with read permission, which is
sometimes rejected by selinux policy.

Bug: https://bugs.gentoo.org/667122
2018-12-01 21:43:18 -08:00
William Hubbs
ee41e444ad rc.conf: typo fix
X-Gentoo-Bug: 670874
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=670874
2018-11-29 08:19:56 -06:00
William Hubbs
b7828651ba supervise-daemon: fix type of exiting flag 2018-11-28 16:06:07 -06:00
Austin English
e96f7d5658 src/tests/runtests.sh: add a FATAL_CHECKS variable to make whitespace/etc. fatal 2018-11-27 21:22:29 -05:00
Austin English
28b73fc524 src/rc/openrc-shutdown.c: fix style 2018-11-27 21:22:29 -05:00
Austin English
7a00c63420 fix misc whitespace issues 2018-11-27 21:22:29 -05:00
Austin English
f4597c546a give TravisCI a try 2018-11-27 21:22:29 -05:00
Austin English
e10afc8e75 sh/functions.sh.in: return a different value for invalid input in yesno() 2018-11-18 13:22:59 -05:00
William Hubbs
0f704402a2 supervise-daemon: make the pidfile an implementation detail
The pidfile of the supervisor doesn't need to be adjustable by the
service script. It is only used so the supervisor can stop itself when
the --stop option is used.
2018-11-15 14:15:15 -06:00
William Hubbs
2504a2c25b Do not complain if interrupted by a signal
In start-stop-daemon and rc-schedules, we were printing out a warning if
the nanosleep call was interrupted by a signal, but we did not treat
this as an error situation other than displaying the message, so there
is no need for the message.
2018-11-15 14:03:06 -06:00
William Hubbs
7eb3975543 Create save-keymaps and save-ktermencoding services
These services represent the parts of the keymaps and termencoding
services which saved the settings back to the root file system so they
can be loaded very early in the boot process.
These are needed to allow keymaps and termencoding to run earlier in the
boot sequence.

X-Gentoo-Bug: 446018
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=446018
2018-11-07 08:55:44 -06:00
William Hubbs
60e60dc9bb supervise-daemon.sh: drop invalid --signal switch
This fixes #230.
2018-11-06 10:54:02 -06:00
William Hubbs
008c9d0036 supervise-daemon: reap zombies
We need to make sure to reap zombies so that we can shut down
successfully.

Fixes #252.
Possibly related to #250.
2018-11-05 21:35:00 -06:00
William Hubbs
025c9693cc rc-service: fix help output 2018-11-05 11:39:39 -06:00
William Hubbs
ee3c4afdb7 openrc-init: add SELinux support
This is for #173.
2018-11-02 18:22:11 -05:00
William Hubbs
e2416d0893 openrc-shutdown: do not require a time for -w switch
X-Gentoo-Bug: 669500
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=669500
2018-10-24 15:24:40 -05:00
William Hubbs
a2bcfeb428 version 0.40 2018-10-24 15:18:10 -05:00
William Hubbs
53f7afd3b3 Update ChangeLog 2018-10-23 17:14:01 -05:00
William Hubbs
75e9b66f6f news.md: add information about the modules service changes 2018-10-23 16:59:20 -05:00
William Hubbs
d70b1c55b6 modules: Add --first-time switch to modprobe commands
On Linux, kernel modules should be loaded once during boot, either in an
initramfs or by this service.

This does not change anything other than printing out messages if a
module is loaded more than once.

X-Gentoo-Bug: 659530
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=659530
2018-10-23 16:47:37 -05:00
William Hubbs
c1e582586d supervise-daemon: add health checks
Health checks are a way to monitor a service and make sure it stays
healthy.

If a service is not healthy, it will be automatically restarted after
running the unhealthy() function to clean up.
2018-10-23 13:38:14 -05:00
William Hubbs
7a75bfb00c news.md: add note about scheduled shutdown 2018-10-23 13:34:08 -05:00
William Hubbs
aacf841de4 supervise-daemon-guide.md: re-format and add more variables 2018-10-22 17:49:25 -05:00
William Hubbs
3f918161aa openrc-shutdown: Add scheduled shutdown and the ability to cancel a shutdown
You can now schedule a shutdown for a certain time or a cpecific number
of minutes into the future.

When a shutdown is running, you can now cancel it with ^c from the
keyboard or by running "openrc-shutdown -c" from another shell.
2018-10-18 17:56:36 -05:00
Zac Medico
710c874e6e supervise-daemon: fix respawn_max off by one
Fix the comparison between respawn_count and respawn_max so that
respawn_max = 1 will allow for one respawn. Since respawn_count is
incremented before the comparison, use a 'greater than' comparison
so that respawn will be triggered when respawn_count is equal to
respawn_max.

Fixes: https://github.com/OpenRC/openrc/issues/247
Fixes: https://github.com/OpenRC/openrc/issues/248
2018-10-15 11:50:42 -05:00
Austin English
07908be090 misc: style fixups 2018-10-13 12:53:54 -04:00
Austin English
02af093043 misc: whitespace fixes 2018-10-13 12:53:54 -04:00
William Hubbs
67e2d6033d Complete implementation of forever timeout value in stop schedules 2018-10-09 11:34:52 -05:00
William Hubbs
eca4357892 supervise-daemon: use nanosleep() instead of sleep()
We will be using sigalrm in this process for health checking, and
sigalrm cannot be used with sleep() safely.
2018-10-06 12:51:04 -05:00
William Hubbs
7ee3e5b2d6 openrc-init: convert sleep() call to nanosleep()
Nanosleep is the safer call to use in case we need to use alarms
eventually.
2018-10-06 12:49:44 -05:00
William Hubbs
7cb8d94323 Stop mounting efivarfs read-only
We do not need to do this any longer since all supported linux kernels
make efivarfs immutable and the tools that manipulate it are aware of
this feature.

This fixes https://github.com/openrc/openrc/issues/238.
2018-08-14 10:21:27 -05:00
Zac Medico
84ed570eae librc: fix EACCES errno false-positive crash
Use errno != EACCES to fix false-positive for non-root users
with grsecurity kernels.

Fixes: 37e2944272 ("librc: Add check for crashed state")
This fixes #237
2018-08-06 17:39:52 -05:00
William Hubbs
2eea73bfd5 rc-functions.sh: Remove addon support
This is an old relic from Gentoo baselayout-1.x which should not be used
any longer.
2018-07-09 19:44:40 -05:00
William Hubbs
a571a42421 modules: remove the ability to rename modules on the fly
Kmod doesn't support the -o switch, so if you have been using this your
module loads have been failing.
2018-06-29 15:29:46 -05:00
Holger Hoffstätte
79648ac1c6 rc-status: initialize uptime pointer to prevent memory corruption
This fixes #231.
2018-06-29 08:49:13 -05:00
William Hubbs
02af762e83 version 0.39 2018-06-28 13:32:19 -05:00
81 changed files with 2210 additions and 1382 deletions

15
.cirrus.yml Normal file
View File

@@ -0,0 +1,15 @@
# Cirrus CI integration
# https://cirrus-ci.org
test_task:
freebsd_instance:
matrix:
image: freebsd-12-0-release-amd64
image: freebsd-11-2-release-amd64
env:
OS: FreeBSD
procfs_script: >
[ -f /proc/curproc ] || mount -t procfs proc /proc
pkg_install_script: pkg install -y bash gawk gmake gsed
gsed_hack_script: rm /usr/bin/sed && ln -s /usr/local/bin/gsed /usr/bin/sed
test_script: bash ci/cirrus.sh

28
.travis.yml Normal file
View File

@@ -0,0 +1,28 @@
# Travis build integration.
# https://docs.travis-ci.com/
language: c
os:
- linux
compiler:
- gcc
- clang
- musl-gcc
addons:
apt:
packages:
- musl-tools
notifications:
irc:
channels:
- "irc.freenode.org#openrc"
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: false # default: false
script:
- ./ci/travis.sh

1584
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@@ -33,8 +33,9 @@ ifeq (${MKZSHCOMP},yes)
SUBDIR+= zsh-completion
endif
# We need to ensure that runlevels is done last
# We need to ensure that runlevels is done last other than test
SUBDIR+= runlevels
SUBDIR+= test
INSTALLAFTER= _installafter

View File

@@ -1,3 +1,3 @@
NAME= openrc
VERSION= 0.38.3
VERSION= 0.41.1
PKG= ${NAME}-${VERSION}

53
NEWS.md
View File

@@ -4,6 +4,59 @@ OpenRC NEWS
This file will contain a list of notable changes for each release. Note
the information in this file is in reverse order.
## OpenRC 0.41.
This version adds the ability to format the output of rc-status when
showing the status of services in a runlevel so that it may be parsed.
Currently, the -f switch only accepts ini as an argument which
causes the output to be in the .ini format.
This version adds an experimental build time switch to allow setting the
default shell to use for service scripts.
By default, this is set to /bin/sh if it is changed, the new shell must
be able to understand posix-compatible syntax.
## OpenRC 0.40
In this version, the keymaps and termencoding services on Linux needed
to be modified so they do not write to the root file system. This was
done so they can run earlier in the boot sequence. AS a result, you will
need to add save-termencoding and save-keymaps to your boot runlevel.
This can be done as follows:
```
# rc-update add save-keymaps boot
# rc-update add save-termencoding boot
```
## OpenRC 0.39
This version removes the support for addons.
The only place I know that this was used was Gentoo Baselayout 1.x, so
it shouldn't affect anyone since baselayout-1 has been dead for a few
years.
Since all supported Linux kernel versions now make efivarfs immutable
and all of the tools that access efivarfs are aware of this, we no
longer mount efivarfs read-only. See the following github issue for more
information:
https://github.com/openrc/openrc/issues/238
This version adds timed shutdown and cancelation of shutdown to
openrc-shutdown. Shutdowns can now be delayed for a certain amount of
time or scheduled for an exact time.
supervise-daemon supports health checks, which are a periodic way to make sure a
service is healthy. For more information on setting this up, please see
supervise-daemon-guide.md.
The --first-time switch has been added to all modprobe commands in the
modules service. This means that, on Linux, you will see failures if a
module was loaded by an initramfs or device manager before this service
runs. These messages are harmless, but to clean them up, you should adjust your
modules autoload configuration.
## OpenRC 0.37
start-stop-daemon now supports logging stdout and stderr of daemons to

View File

@@ -38,6 +38,7 @@ PKG_PREFIX=/usr/pkg
LOCAL_PREFIX=/usr/local
PREFIX=/usr/local
BRANDING=\"Gentoo/$(uname -s)\"
SH=/bin/sh
```
## Notes

View File

@@ -91,11 +91,14 @@ _rc_service()
done))
return 0
elif [[ ${COMP_CWORD} -eq 2 ]] && [[ ${prev} != -* ]]; then # if second word typed and we didn't type in a function
filename=$(rc-service --resolve ${prev})
opts=$(cat ${filename} | grep "^\w*()" | sed "s/().*$//") # Greps the functions included in the init script
if [[ "x${opts}" == "x" ]] ; then # if no options found loosen the grep algorhythm
opts=$(cat ${filename} | grep "\w*()" | sed "s/().*$//")
fi
rc-service --exists "$prev" || return
shopt -s extglob
while read -r _ line; do
if [[ $line == +([[:alnum:]_]):* ]]; then
opts+="${line%%:*} "
fi
done < <(rc-service "$prev" describe 2>&1)
shopt -u extglob
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi

21
ci/cirrus.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/bash
# Copyright (c) 2007-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.
set -e
set -u
set -x
# These are steps to run on Cirrus CI under a jailed FreeBSD system.
# See $TOP/.cirrus.yml for more info about the Cirrus CI setup.
cpus=$(getconf NPROCESSORS_CONF || echo 1)
gmake -j"${cpus}" -O
gmake test

23
ci/travis.sh Executable file
View File

@@ -0,0 +1,23 @@
#!/bin/bash
# Copyright (c) 2007-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.
set -e
set -u
set -x
# These are steps to run on TravisCI under a containerized Ubuntu system.
# See $TOP/.travis.yml for more info about the TravisCI setup.
cpus=$(getconf _NPROCESSORS_CONF || echo 1)
# make on TravisCI doesn't support -O yet
make -j"${cpus}"
make test

View File

@@ -8,11 +8,6 @@
#modules_2="ipv6"
#modules="ohci1394"
# Linux users can give modules a different name when they load - the new name
# will also be used to pick arguments below.
# This is not supported on FreeBSD.
#modules="dummy:dummy1"
# Linux users can give the modules some arguments if needed, per version
# if necessary.
# Again, the most specific versioned variable will take precedence.

View File

@@ -230,7 +230,7 @@ rc_tty_number=12
# The following setting turns on the memory.use_hierarchy setting in the
# root memory cgroup for cgroups v1.
# It must be set to yes in this file if you want this functionality.
#rc_cggroup_memory_use_hierarchy="NO"
#rc_cgroup_memory_use_hierarchy="NO"
# The following settings allow you to set up values for the cgroups version 1
# controllers for your services.

View File

@@ -1,4 +1,4 @@
#!@SHELL@
#!/bin/sh
# Copyright (c) 2007-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS

View File

@@ -1,4 +1,4 @@
#!@SHELL@
#!/bin/sh
# Copyright (c) 2007-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS

2
init.d/.gitignore vendored
View File

@@ -41,6 +41,8 @@ rc-enabled
rpcbind
runsvdir
savecore
save-keymaps
save-termencoding
swap-blk
swclock
syslogd

View File

@@ -23,8 +23,8 @@ SRCS-FreeBSD+= adjkerntz.in devd.in dumpon.in encswap.in ipfw.in \
SRCS-Linux= agetty.in binfmt.in devfs.in cgroups.in dmesg.in hwclock.in \
consolefont.in keymaps.in killprocs.in modules.in \
mount-ro.in mtab.in numlock.in procfs.in net-online.in sysfs.in \
termencoding.in
mount-ro.in mtab.in numlock.in procfs.in net-online.in save-keymaps.in \
save-termencoding.in sysfs.in termencoding.in
# Generic BSD scripts
SRCS-NetBSD= hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \

View File

@@ -12,6 +12,7 @@
description="start agetty on a terminal line"
supervisor=supervise-daemon
port="${RC_SVCNAME#*.}"
respawn_period="${respawn_period:-60}"
term_type="${term_type:-linux}"
command=/sbin/agetty
command_args_foreground="${agetty_options} ${port} ${baud} ${term_type}"

View File

@@ -14,7 +14,7 @@ description="Applies a keymap for the consoles."
depend()
{
need termencoding
after bootmisc clock
after devfs
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
}
@@ -68,10 +68,5 @@ start()
echo "altgr keycode 18 = U+20AC" | loadkeys -q -
eend $?
fi
# Save the keymapping for use immediately at boot
if checkpath -W "$RC_LIBEXECDIR"; then
mkdir -p "$RC_LIBEXECDIR"/console
dumpkeys >"$RC_LIBEXECDIR"/console/keymap
fi
return 0
}

View File

@@ -56,11 +56,12 @@ load_modules()
ebegin "Loading module $x"
case "$RC_UNAME" in
FreeBSD) kldload "$x"; rc=$? ;;
Linux) modprobe --use-blacklist -q "$x"; rc=$? ;;
Linux) modprobe --first-time -q --use-blacklist "$x"; rc=$? ;;
*) ;;
esac
eend $rc "Failed to load $x"
done
return 0
}
modules_load_d()
@@ -103,7 +104,7 @@ Linux_modules()
x=${x%.*}
done
local list= x= xx= y= args= mpargs= a=
local list= x= xx= y= args=
for x in $kv_variant_list ; do
eval list=\$modules_$(shell_var "$x")
[ -n "$list" ] && break
@@ -112,24 +113,13 @@ Linux_modules()
[ -n "$list" ] && ebegin "Loading kernel modules"
for x in $list; do
a=${x#*:}
if [ "$a" = "$x" ]; then
unset mpargs
else
x=${x%%:*}
mpargs="-o $a"
fi
aa=$(shell_var "$a")
xx=$(shell_var "$x")
for y in $kv_variant_list ; do
eval args=\$module_${aa}_args_$(shell_var "$y")
[ -n "${args}" ] && break
eval args=\$module_${xx}_args_$(shell_var "$y")
[ -n "${args}" ] && break
done
[ -z "$args" ] && eval args=\$module_${aa}_args
[ -z "$args" ] && eval args=\$module_${xx}_args
eval modprobe --use-blacklist --verbose "$mpargs" "$x" "$args"
eval modprobe --first-time --use-blacklist --verbose "$x" "$args"
done
[ -n "$list" ] && eend
}
@@ -137,7 +127,7 @@ Linux_modules()
start()
{
case "$RC_UNAME" in
FreeBSD|Linux)
FreeBSD|Linux)
modules_load_d
${RC_UNAME}_modules
;;

28
init.d/save-keymaps.in Normal file
View File

@@ -0,0 +1,28 @@
#!@SBINDIR@/openrc-run
# Copyright (c) 2018 Sony Interactive Entertainment, Inc.
#
# 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="Save the keymap for use as early as possible"
depend()
{
need termencoding
after bootmisc clock keymaps
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
}
start()
{
# Save the keymapping for use immediately at boot
ebegin "Saving key mapping"
if checkpath -W "$RC_LIBEXECDIR"; then
mkdir -p "$RC_LIBEXECDIR"/console
dumpkeys >"$RC_LIBEXECDIR"/console/keymap
fi
eend $? "Unable to save keymapping"
}

View File

@@ -0,0 +1,35 @@
#!@SBINDIR@/openrc-run
# Copyright (c) 2018 Sony Interactive Entertainment, Inc.
#
# 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="Configures terminal encoding."
ttyn=${rc_tty_number:-${RC_TTY_NUMBER:-12}}
: ${unicode:=${UNICODE}}
depend()
{
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
use root
after bootmisc clock termencoding
}
start()
{
ebegin "Saving terminal encoding"
# Save the encoding for use immediately at boot
if checkpath -W "$RC_LIBEXECDIR"; then
mkdir -p "$RC_LIBEXECDIR"/console
if yesno ${unicode:-${UNICODE}}; then
echo "" > "$RC_LIBEXECDIR"/console/unicode
else
rm -f "$RC_LIBEXECDIR"/console/unicode
fi
fi
eend 0
}

View File

@@ -101,7 +101,7 @@ mount_misc()
if [ -d /sys/firmware/efi/efivars ] &&
! mountinfo -q /sys/firmware/efi/efivars; then
ebegin "Mounting efivarfs filesystem"
mount -n -t efivarfs -o ro \
mount -n -t efivarfs -o ${sysfs_opts} \
efivarfs /sys/firmware/efi/efivars 2> /dev/null
eend 0
fi

View File

@@ -17,8 +17,7 @@ ttyn=${rc_tty_number:-${RC_TTY_NUMBER:-12}}
depend()
{
keyword -docker -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
use root
after bootmisc clock
after devfs
}
start()

View File

@@ -16,15 +16,36 @@
.Nd bring the system down
.Sh SYNOPSIS
.Nm
.Op Fl c , -cancel
.Nm
.Op Fl R , -reexec
.Nm
.Op Fl w , -write-only
.Nm
.Op Fl d , -no-write
.Op Fl D , -dry-run
.Op Fl H , -halt
time
.Nm
.Op Fl d , -no-write
.Op Fl D , -dry-run
.Op Fl k , -kexec
time
.Nm
.Op Fl d , -no-write
.Op Fl D , -dry-run
.Op Fl p , -poweroff
.Op Fl R , -reexec
time
.Nm
.Op Fl d , -no-write
.Op Fl D , -dry-run
.Op Fl r , -reboot
time
.Nm
.Op Fl d , -no-write
.Op Fl D , -dry-run
.Op Fl s , -single
.Op Fl w , -write-only
time
.Sh DESCRIPTION
.Nm
is the utility that communicates with
@@ -32,6 +53,8 @@ is the utility that communicates with
to bring down the system or instruct openrc-init to re-execute itself.
It supports the following options:
.Bl -tag -width "poweroff"
.It Fl c , -cancel
Cancel a pending shutdown.
.It Fl d , -no-write
Do not write the wtmp boot record.
.It Fl D , -dry-run
@@ -53,7 +76,7 @@ Stop all services, kill all processes and reboot the system.
.It Fl s , -single
Stop all services, kill all processes and move to single user mode.
.It Fl w , -write-only
Stop all services, kill all processes and move to single user mode.
Wrrite a wtmp shutdown record and do nothing else.
.El
.Sh SEE ALSO
.Xr openrc-init 8 ,

View File

@@ -66,6 +66,7 @@ and
.Xr shutdown 8
and let them call these special runlevels.
.Sh SEE ALSO
.Xr openrc-run 8 ,
.Xr rc-status 8 ,
.Xr rc-update 8 ,
.Xr init 8 ,

View File

@@ -17,6 +17,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl aclsuC
.Op Fl f Ar ini
.Op Ar runlevel
.Sh DESCRIPTION
.Nm
@@ -37,12 +38,17 @@ The options are as follows:
Show all runlevels and their services.
.It Fl c , -crashed
List all services that have crashed.
.It Fl f , -format
Select a format for the output. Currently, the only one that can be
specified is ini, which outputs in *.ini format.
.It Fl l , -list
List all defined runlevels.
.It Fl m , -manual
Show all manually started services.
.It Fl r , -runlevel
Print the current runlevel name.
.It Fl S , -supervised
Show all supervised services.
.It Fl s , -servicelist
Show all services.
.It Fl u , -unused

View File

@@ -9,13 +9,18 @@
.\" except according to the terms contained in the LICENSE file.
.\"
.Dd April 27, 2016
.Dt supervise-DAEMON 8 SMM
.Dt SUPERVISE-DAEMON 8 SMM
.Os OpenRC
.Sh NAME
.Nm supervise-daemon
.Nd starts a daemon and restarts it if it crashes
.Sh SYNOPSIS
.Nm
servicename
.Fl a , -healthcheck-timer
.Ar seconds
.Fl A , -healthcheck-delay
.Ar seconds
.Fl D , -respawn-delay
.Ar seconds
.Fl d , -chdir
@@ -32,8 +37,6 @@
.Ar count
.Fl N , -nicelevel
.Ar level
.Fl p , -pidfile
.Ar pidfile
.Fl P , -respawn-period
.Ar seconds
.Fl R , -retry
@@ -51,10 +54,15 @@
.Op Fl -
.Op Ar arguments
.Nm
servicename
.Fl K , -stop
.Ar daemon
.Fl p , -pidfile
.Ar pidfile
.Fl r , -chroot
.Ar chrootpath
.Nm
servicename
.Fl s , -signal
.Ar signal
.Fl r , -chroot
.Ar chrootpath
.Sh DESCRIPTION
@@ -62,22 +70,15 @@
provides a consistent method of starting, stopping and restarting
daemons. If
.Fl K , -stop
or
.Fl s , -signal
is not provided, then we assume we are starting the daemon.
.Nm
only works with daemons which do not fork. Also, it uses its own pid
file, so the daemon should not write a pid file, or the pid file passed
to
.Nm
should not be the one the daemon writes.
only works with daemons which do not fork. If your daemon has options to
tell it not to fork, it should be configured to not fork.
.Pp
Here are the options to specify the daemon and how it should start or stop:
.Bl -tag -width indent
.It Fl p , -pidfile Ar pidfile
When starting, we write a
.Ar pidfile
so we know which supervisor to stop. When stopping we only stop the pid(s)
listed in the
.Ar pidfile .
.It Fl u , -user Ar user Ns Op : Ns Ar group
Start the daemon as the
.Ar user
@@ -87,11 +88,17 @@ owned by the user. You can optionally append a
name here also.
.It Fl v , -verbose
Print the action(s) that are taken just before doing them.
.El
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl a , -healthcheck-timer Ar seconds
Run the healthcheck() command, possibly followed by the unhealthy()
command every time this number of seconds passes.
.It Fl A , -healthcheck-delay Ar seconds
Wait this long before the first health check.
.It Fl D , -respawn-delay Ar seconds
wait this number of seconds before restarting a daemon after it crashes.
Wait this number of seconds before restarting a daemon after it crashes.
The default is 0.
.It Fl d , -chdir Ar path
chdir to this directory before starting the daemon.
@@ -106,16 +113,19 @@ Data can be from 0 to 7 inclusive.
.It Fl k , -umask Ar mode
Set the umask of the daemon.
.It Fl m , -respawn-max Ar count
Sets the maximum number of times a daemon will be respawned during a
respawn period. If a daemon dies more than this number of times during a
respawn period,
Sets the maximum number of times a daemon will be respawned. If a daemon
crashes more than this number of times,
.Nm
will give up trying to respawn it and exit. The default is 10, and 0
means unlimited.
will give up and exit. The default is 10 and 0 means unlimited.
.Pp
If respawn-period is also set, more than respawn-max crashes must occur
during respawn-period seconds to cause
.Nm
to give up and exit.
.It Fl N , -nicelevel Ar level
Modifies the scheduling priority of the daemon.
.It Fl P , -respawn-period Ar seconds
Sets the length of a respawn period. The default is 10 seconds. See the
Sets the length of a respawn period. See the
description of --respawn-max for more information.
.It Fl R , -retry Ar timeout | Ar signal Ns / Ns Ar timeout
The retry specification can be either a timeout in seconds or multiple
@@ -123,7 +133,11 @@ signal/timeout pairs (like SIGTERM/5).
If this option is not given, the default is SIGTERM/5.
.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.
as the path to the daemon and chdir should be relative to the chroot.
.It Fl , -signal Ar signal
Instruct a supervisor to signal the process it is supervising. The
process to communicate with is determined by the name of the service
taken from the RC_SVCNAME environment variable.
.It Fl u , -user Ar user
Start the daemon as the specified user.
.It Fl 1 , -stdout Ar logfile
@@ -136,7 +150,6 @@ The same thing as
.Fl 1 , -stdout
but with the standard error output.
.El
.El
.Sh ENVIRONMENT
.Va SSD_NICELEVEL
can also set the scheduling priority of the daemon, but the command line
@@ -158,15 +171,16 @@ make sure the settings mmake sense. For example, a respawn period of 5
seconds with a respawn max of 10 and a respawn delay of 1 second leads
to infinite respawning since there can never be 10 respawns within 5
seconds.
.Sh NOTE
Invoking supervise-daemon requires both the RC_SVCNAME environment
variable to be set and the name of the service as the first argument on
the command line, so it is best to invoke it inside a service script
rather than manually.
.Sh SEE ALSO
.Xr chdir 2 ,
.Xr chroot 2 ,
.Xr getopt 3 ,
.Xr nice 2 ,
.Xr rc_find_pids 3
.Sh BUGS
.Nm
cannot stop an interpreted daemon that no longer exists without a pidfile.
.Sh HISTORY
.Nm
first appeared in Debian.

View File

@@ -11,7 +11,7 @@
SFX= .Linux.in
PKG_PREFIX?= /usr
CPPFLAGS+= -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L
CPPFLAGS+= -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L -D_BSD_SOURCE -D_XOPEN_SOURCE
LIBDL= -Wl,-Bdynamic -ldl
ifeq (${MKSELINUX},yes)

View File

@@ -19,7 +19,7 @@ _PKG_SED:= $(shell ${_PKG_SED_SH})
_LCL_SED_SH= if test "${PREFIX}" = "${LOCAL_PREFIX}"; then echo "-e 's:@LOCAL_PREFIX@::g'"; else echo "-e 's:@LOCAL_PREFIX@:${LOCAL_PREFIX}:g'"; fi
_LCL_SED:= $(shell ${_LCL_SED_SH})
SED_REPLACE= -e 's:@SHELL@:${SH}:g' -e 's:@LIB@:${LIBNAME}:g' -e 's:@SYSCONFDIR@:${SYSCONFDIR}:g' -e 's:@LIBEXECDIR@:${LIBEXECDIR}:g' -e 's:@PREFIX@:${PREFIX}:g' -e 's:@BINDIR@:${BINDIR}:g' -e 's:@SBINDIR@:${SBINDIR}:g' ${_PKG_SED} ${_LCL_SED}
SED_REPLACE= -e 's:@SHELL@:${SH}:' -e 's:@LIB@:${LIBNAME}:g' -e 's:@SYSCONFDIR@:${SYSCONFDIR}:g' -e 's:@LIBEXECDIR@:${LIBEXECDIR}:g' -e 's:@PREFIX@:${PREFIX}:g' -e 's:@BINDIR@:${BINDIR}:g' -e 's:@SBINDIR@:${SBINDIR}:g' ${_PKG_SED} ${_LCL_SED}
# Tweak our shell scripts
%.sh: %.sh.in
@@ -53,7 +53,6 @@ realinstall: ${BIN} ${CONF} ${INC}
install: all realinstall ${INSTALLAFTER}
check test::
@if test -e runtests.sh ; then ./runtests.sh || exit $$? ; fi
# A lot of scripts don't have anything to clean
# Also, some rm implentation require a file argument regardless of error

View File

@@ -36,7 +36,8 @@ BOOT-FreeBSD+= hostid modules newsyslog savecore syslogd
# FreeBSD specific stuff
BOOT-FreeBSD+= adjkerntz dumpon syscons
BOOT-Linux+= binfmt hwclock keymaps modules mtab procfs termencoding
BOOT-Linux+= binfmt hwclock keymaps modules mtab procfs save-keymaps \
save-termencoding termencoding
SHUTDOWN-Linux= killprocs mount-ro
SYSINIT-Linux= devfs cgroups dmesg sysfs

View File

@@ -1,4 +1,4 @@
#!@SHELL@
#!/bin/sh
option_arg=
poweroff_arg=
@@ -21,4 +21,9 @@ if [ -z "${poweroff_arg}" ]; then
poweroff_arg=--poweroff
fi
exec @SBINDIR@/openrc-shutdown ${option_arg} ${poweroff_arg} "$@"
script_args="$@"
if [ -z "${script_args}" ]; then
script_args=now
fi
exec @SBINDIR@/openrc-shutdown ${option_arg} ${poweroff_arg} "${script_args}"

View File

@@ -1,4 +1,4 @@
#!@SHELL@
#!/bin/sh
option_arg=
poweroff_arg=
@@ -20,4 +20,9 @@ if [ -z "${poweroff_arg}" ]; then
poweroff_arg=--poweroff
fi
exec @SBINDIR@/openrc-shutdown ${option_arg} ${poweroff_arg} "$@"
script_args="$@"
if [ -z "${script_args}" ]; then
script_args=now
fi
exec @SBINDIR@/openrc-shutdown ${option_arg} ${poweroff_arg} "${script_args}"

View File

@@ -1,4 +1,4 @@
#!@SHELL@
#!/bin/sh
# Copyright (c) 2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS

View File

@@ -1,4 +1,4 @@
#!@SHELL@
#!/bin/sh
option_arg=
poweroff_arg=
@@ -22,4 +22,9 @@ if [ -z "${poweroff_arg}" ]; then
poweroff_arg=--reboot
fi
exec @SBINDIR@/openrc-shutdown ${option_arg} ${poweroff_arg} "$@"
script_args="$@"
if [ -z "${script_args}" ]; then
script_args=now
fi
exec @SBINDIR@/openrc-shutdown ${option_arg} ${poweroff_arg} "${script_args}"

View File

@@ -1,4 +1,4 @@
#!@SHELL@
#!/bin/sh
shutdown_arg=
while getopts :akrhPHfFnct: opt; do

3
sh/.gitignore vendored
View File

@@ -1,10 +1,7 @@
functions.sh
gendepends.sh
rc-functions.sh
openrc-run.sh
cgroup-release-agent.sh
init.sh
init-early.sh
rc-cgroup.sh
migrate-to-run.sh
binfmt.sh

View File

@@ -1,8 +1,8 @@
DIR= ${LIBEXECDIR}/sh
SRCS= init.sh.in functions.sh.in gendepends.sh.in \
openrc-run.sh.in rc-functions.sh.in ${SRCS-${OS}}
openrc-run.sh.in ${SRCS-${OS}}
INC= rc-mount.sh functions.sh rc-functions.sh runit.sh s6.sh \
start-stop-daemon.sh supervise-daemon.sh
start-stop-daemon.sh supervise-daemon.sh ${INC-${OS}}
BIN= gendepends.sh init.sh openrc-run.sh ${BIN-${OS}}
INSTALLAFTER= _installafter
@@ -13,10 +13,9 @@ include ${MK}/os.mk
SRCS-FreeBSD=
BIN-FreeBSD=
SRCS-Linux= binfmt.sh.in cgroup-release-agent.sh.in init-early.sh.in \
migrate-to-run.sh.in rc-cgroup.sh.in
BIN-Linux= binfmt.sh cgroup-release-agent.sh init-early.sh migrate-to-run.sh \
rc-cgroup.sh
SRCS-Linux= binfmt.sh.in cgroup-release-agent.sh.in init-early.sh.in
BIN-Linux= binfmt.sh cgroup-release-agent.sh init-early.sh
INC-Linux= rc-cgroup.sh
SRCS-NetBSD=
BIN-NetBSD=
@@ -32,4 +31,3 @@ _installafter:
ln -snf ${LIBEXECDIR}/sh/functions.sh ${DESTDIR}/${INITDIR} || exit $$?
check test::
./runtests.sh

View File

@@ -1,4 +1,4 @@
#!@SHELL@
#!/bin/sh
# This is a reimplementation of the systemd binfmt.d code to register
# misc binary formats with the kernel.
#

View File

@@ -1,4 +1,4 @@
#!@SHELL@
#!/bin/sh
# This is run by the kernel after the last task is removed from a
# control group in the openrc hierarchy.

View File

@@ -46,7 +46,7 @@ yesno()
case "$value" in
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) return 0;;
[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) return 1;;
*) vewarn "\$$1 is not set properly"; return 1;;
*) vewarn "\$$1 is not set properly"; return 2;;
esac
}

View File

@@ -1,4 +1,4 @@
#!@SHELL@
#!/bin/sh
# Copyright (c) 2007-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS

View File

@@ -1,4 +1,4 @@
#!@SHELL@
#!/bin/sh
# Copyright (c) 2007-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS

View File

@@ -1,4 +1,4 @@
#!@SHELL@
#!/bin/sh
# Copyright (c) 2007-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS

View File

@@ -1,4 +1,4 @@
#!@SHELL@
#!/bin/sh
# Copyright (c) 2007-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS

View File

@@ -1,4 +1,4 @@
#!@SHELL@
#!/bin/sh
# Copyright (c) 1999-2007 Gentoo Foundation
# Copyright (c) 2007-2009 Roy Marples <roy@marples.name>
# Released under the 2-clause BSD license.

View File

@@ -1,36 +0,0 @@
#!@SHELL@
# Copyright (c) 2012-2015 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.
. "@LIBEXECDIR@/sh/functions.sh"
if [ -e /run/openrc/softlevel ]; then
einfo "The OpenRC dependency data has already been migrated."
exit 0
fi
if [ ! -d /run ]; then
eerror "/run is not a directory."
eerror "moving /run to /run.pre-openrc"
mv /run /run.pre-openrc
mkdir /run
fi
rm -rf /run/openrc
if ! mountinfo -q -f tmpfs /run; then
ln -s "@LIBEXECDIR@"/init.d /run/openrc
else
cp -a "@LIBEXECDIR@/init.d" /run/openrc
rc-update -u
fi
einfo "The OpenRC dependency data was migrated successfully."
exit 0

View File

@@ -1,4 +1,3 @@
#!@SHELL@
# Copyright (c) 2012-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS
@@ -62,7 +61,7 @@ cgroup_set_values()
while [ -n "$1" ] && [ "$controller" != "cpuacct" ]; do
case "$1" in
$controller.*)
if [ -n "${name}" ] && [ -w "${cgroup}/${name}" ] &&
if [ -n "${name}" ] && [ -w "${cgroup}/${name}" ] &&
[ -n "${val}" ]; then
veinfo "$RC_SVCNAME: Setting $cgroup/$name to $val"
printf "%s" "$val" > "$cgroup/$name"

View File

@@ -2,42 +2,6 @@
# Copyright (c) 2007-2009 Roy Marples <roy@marples.name>
# Released under the 2-clause BSD license.
has_addon()
{
[ -e /@LIB@/rc/addons/"$1".sh -o -e /@LIB@/rcscripts/addons/"$1".sh ]
}
_addon_warn()
{
eindent
ewarn "$RC_SVCNAME uses addon code which is deprecated"
ewarn "and may not be available in the future."
eoutdent
}
import_addon()
{
if [ -e /@LIB@/rc/addons/"$1".sh ]; then
_addon_warn
. /@LIB@/rc/addons/"$1".sh
elif [ -e /@LIB@/rcscripts/addons/"$1".sh ]; then
_addon_warn
. /@LIB@/rcscripts/addons/"$1".sh
else
return 1
fi
}
start_addon()
{
( import_addon "$1-start" )
}
stop_addon()
{
( import_addon "$1-stop" )
}
net_fs_list="afs ceph cifs coda davfs fuse fuse.sshfs gfs glusterfs lustre
ncpfs nfs nfs4 ocfs2 shfs smbfs"
is_net_fs()

View File

@@ -57,7 +57,7 @@ s6_stop()
ebegin "Stopping ${name:-$RC_SVCNAME}"
s6-svc -d -wD -T ${s6_service_timeout_stop:-60000} "${s6_service_link}"
set -- $(s6-svstat "${s6_service_link}")
[ "$1" = "up" ] &&
[ "$1" = "up" ] &&
yesno "${s6_force_kill:-yes}" &&
_s6_force_kill "$@"
set -- $(s6-svstat "${s6_service_link}")

View File

@@ -38,9 +38,9 @@ ssd_start()
service_inactive && _inactive=true
mark_service_inactive
fi
[ -n "$output_logger" ] &&
[ -n "$output_logger" ] &&
output_logger_arg="--stdout-logger \"$output_logger\""
[ -n "$error_logger" ] &&
[ -n "$error_logger" ] &&
error_logger_arg="--stderr-logger \"$error_logger\""
#the eval call is necessary for cases like:
# command_args="this \"is a\" test"

View File

@@ -10,6 +10,8 @@
# This file may not be copied, modified, propagated, or distributed
# except according to the terms contained in the LICENSE file.
extra_commands="healthcheck unhealthy ${extra_commands}"
supervise_start()
{
if [ -z "$command" ]; then
@@ -32,6 +34,8 @@ supervise_start()
${respawn_delay:+--respawn-delay} $respawn_delay \
${respawn_max:+--respawn-max} $respawn_max \
${respawn_period:+--respawn-period} $respawn_period \
${healthcheck_delay:+--healthcheck-delay} $healthcheck_delay \
${healthcheck_timer:+--healthcheck-timer} $healthcheck_timer \
${command_user+--user} $command_user \
${umask+--umask} $umask \
${supervise_daemon_args:-${start_stop_daemon_args}} \
@@ -51,11 +55,9 @@ supervise_stop()
local startpidfile="$(service_get_value "pidfile")"
chroot="${startchroot:-$chroot}"
pidfile="${startpidfile:-$pidfile}"
[ -n "$pidfile" ] || return 0
ebegin "Stopping ${name:-$RC_SVCNAME}"
supervise-daemon "${RC_SVCNAME}" --stop \
${pidfile:+--pidfile} $chroot$pidfile \
${stopsig:+--signal} $stopsig
${pidfile:+--pidfile} $chroot$pidfile
eend $? "Failed to stop ${name:-$RC_SVCNAME}"
}
@@ -98,3 +100,13 @@ supervise_status()
return 3
fi
}
healthcheck()
{
return 0
}
unhealthy()
{
return 0
}

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2007-2008 Roy Marples <roy@marples.name>
# Released under the 2-clause BSD license.
SUBDIR= test libeinfo librc rc
SUBDIR= libeinfo librc rc
MK= ../mk
include ${MK}/subdir.mk

View File

@@ -59,7 +59,7 @@ pid_is_argv(pid_t pid, const char *const *argv)
free(cmdline);
return false;
}
bytes = read(fd, buffer, sizeof(buffer));
bytes = read(fd, buffer, sizeof(buffer) - 1);
close(fd);
free(cmdline);
if (bytes == -1)
@@ -141,7 +141,7 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
memset(my_ns, 0, sizeof(my_ns));
memset(proc_ns, 0, sizeof(proc_ns));
if (exists("/proc/self/ns/pid")) {
rc = readlink("/proc/self/ns/pid", my_ns, sizeof(my_ns));
rc = readlink("/proc/self/ns/pid", my_ns, sizeof(my_ns)-1);
if (rc <= 0)
my_ns[0] = '\0';
}
@@ -155,7 +155,7 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
continue;
xasprintf(&buffer, "/proc/%d/ns/pid", p);
if (exists(buffer)) {
rc = readlink(buffer, proc_ns, sizeof(proc_ns));
rc = readlink(buffer, proc_ns, sizeof(proc_ns)-1);
if (rc <= 0)
proc_ns[0] = '\0';
}

View File

@@ -84,10 +84,11 @@ static RC_DEPINFO *
get_depinfo(const RC_DEPTREE *deptree, const char *service)
{
RC_DEPINFO *di;
TAILQ_FOREACH(di, deptree, entries)
if (strcmp(di->service, service) == 0)
return di;
if (deptree) {
TAILQ_FOREACH(di, deptree, entries)
if (strcmp(di->service, service) == 0)
return di;
}
return NULL;
}
@@ -96,9 +97,11 @@ get_deptype(const RC_DEPINFO *depinfo, const char *type)
{
RC_DEPTYPE *dt;
TAILQ_FOREACH(dt, &depinfo->depends, entries)
if (strcmp(dt->type, type) == 0)
return dt;
if (depinfo) {
TAILQ_FOREACH(dt, &depinfo->depends, entries)
if (strcmp(dt->type, type) == 0)
return dt;
}
return NULL;
}
@@ -616,11 +619,11 @@ mtime_check(const char *source, const char *target, bool newer,
return false;
mtime = buf.st_mtime;
retval = deep_mtime_check(target,newer,&mtime,file);
if (rel) {
*rel = mtime;
}
return retval;
retval = deep_mtime_check(target,newer,&mtime,file);
if (rel) {
*rel = mtime;
}
return retval;
}
bool

View File

@@ -277,7 +277,6 @@ static RC_STRINGLIST *rc_config_kcl(RC_STRINGLIST *config)
char *tmp = NULL;
char *value = NULL;
size_t varlen = 0;
size_t len = 0;
overrides = rc_stringlist_new();
@@ -295,7 +294,6 @@ static RC_STRINGLIST *rc_config_kcl(RC_STRINGLIST *config)
}
if (value != NULL) {
len = varlen + strlen(value) + 2;
xasprintf(&tmp, "%s=%s", override->value, value);
}
@@ -425,7 +423,7 @@ rc_conf_value(const char *setting)
}
rc_conf = rc_config_directory(rc_conf);
rc_conf = rc_config_kcl(rc_conf);
rc_conf = rc_config_kcl(rc_conf);
/* Convert old uppercase to lowercase */
TAILQ_FOREACH(s, rc_conf, entries) {

View File

@@ -558,7 +558,7 @@ rc_service_resolve(const char *service)
if (*file) {
memset(buffer, 0, sizeof(buffer));
r = readlink(file, buffer, sizeof(buffer));
r = readlink(file, buffer, sizeof(buffer)-1);
if (r > 0)
return xstrdup(buffer);
}
@@ -1047,7 +1047,6 @@ rc_service_add(const char *runlevel, const char *service)
char *init;
char file[PATH_MAX];
char path[MAXPATHLEN] = { '\0' };
char *p = NULL;
char binit[PATH_MAX];
char *i;
@@ -1068,8 +1067,7 @@ rc_service_add(const char *runlevel, const char *service)
/* We need to ensure that only things in /etc/init.d are added
* to the boot runlevel */
if (strcmp(runlevel, RC_LEVEL_BOOT) == 0) {
p = realpath(dirname(init), path);
if (!*p) {
if (realpath(dirname(init), path) == NULL) {
free(init);
return false;
}

View File

@@ -14,7 +14,7 @@ SRCS+= rc-selinux.c
endif
ifeq (${OS},Linux)
SRCS+= kill_all.c openrc-init.c openrc-shutdown.c rc-wtmp.c
SRCS+= kill_all.c openrc-init.c openrc-shutdown.c broadcast.c rc-wtmp.c
endif
CLEANFILES= version.h rc-selinux.o
@@ -134,7 +134,7 @@ mountinfo: mountinfo.o _usage.o rc-misc.o
openrc rc: rc.o rc-logger.o rc-misc.o rc-plugin.o _usage.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
openrc-shutdown: openrc-shutdown.o _usage.o rc-wtmp.o
openrc-shutdown: openrc-shutdown.o rc-misc.o _usage.o broadcast.o rc-wtmp.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
openrc-run runscript: openrc-run.o _usage.o rc-misc.o rc-plugin.o
@@ -161,7 +161,7 @@ rc-update: rc-update.o _usage.o rc-misc.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}
supervise-daemon: supervise-daemon.o _usage.o rc-misc.o rc-schedules.o
supervise-daemon: supervise-daemon.o _usage.o rc-misc.o rc-plugin.o rc-schedules.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
service_get_value service_set_value get_options save_options: do_value.o rc-misc.o

204
src/rc/broadcast.c Normal file
View File

@@ -0,0 +1,204 @@
/*
* broadcast.c
* broadcast a message to every logged in user
*/
/*
* Copyright 2018 Sony Interactive Entertainment Inc.
*
* 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 <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <stdio.h>
#include <utmpx.h>
#include <pwd.h>
#include <fcntl.h>
#include <signal.h>
#include <setjmp.h>
#include <paths.h>
#include <sys/utsname.h>
#include "broadcast.h"
#include "helpers.h"
#ifndef _PATH_DEV
# define _PATH_DEV "/dev/"
#endif
static sigjmp_buf jbuf;
/*
* Alarm handler
*/
/*ARGSUSED*/
# ifdef __GNUC__
static void handler(int arg __attribute__((unused)))
# else
static void handler(int arg)
# endif
{
siglongjmp(jbuf, 1);
}
static void getuidtty(char **userp, char **ttyp)
{
struct passwd *pwd;
uid_t uid;
char *tty;
static char uidbuf[32];
char *ttynm = NULL;
uid = getuid();
if ((pwd = getpwuid(uid)) != NULL) {
uidbuf[0] = 0;
strncat(uidbuf, pwd->pw_name, sizeof(uidbuf) - 1);
} else {
if (uid)
sprintf(uidbuf, "uid %d", (int) uid);
else
sprintf(uidbuf, "root");
}
if ((tty = ttyname(0)) != NULL) {
const size_t plen = strlen(_PATH_DEV);
if (strncmp(tty, _PATH_DEV, plen) == 0) {
tty += plen;
if (tty[0] == '/')
tty++;
}
xasprintf(&ttynm, "(%s) ", tty);
}
*userp = uidbuf;
*ttyp = ttynm;
}
/*
* Check whether the given filename looks like a tty device.
*/
static int file_isatty(const char *fname)
{
struct stat st;
int major;
if (stat(fname, &st) < 0)
return 0;
if (st.st_nlink != 1 || !S_ISCHR(st.st_mode))
return 0;
/*
* It would be an impossible task to list all major/minors
* of tty devices here, so we just exclude the obvious
* majors of which just opening has side-effects:
* printers and tapes.
*/
major = major(st.st_dev);
if (major == 1 || major == 2 || major == 6 || major == 9 ||
major == 12 || major == 16 || major == 21 || major == 27 ||
major == 37 || major == 96 || major == 97 || major == 206 ||
major == 230)
return 0;
return 1;
}
/*
* broadcast function.
*/
void broadcast(char *text)
{
char *tty;
char *user;
struct utsname name;
time_t t;
char *date;
char *p;
char *line = NULL;
struct sigaction sa;
volatile int fd;
FILE *tp;
int flags;
char *term = NULL;
struct utmpx *utmp;
getuidtty(&user, &tty);
/*
* Get and report current hostname, to make it easier to find out
* which machine is being shut down.
*/
uname(&name);
/* Get the time */
time(&t);
date = ctime(&t);
p = strchr(date, '\n');
if (p)
*p = 0;
xasprintf(&line, "\007\r\nBroadcast message from %s@%s %s(%s):\r\n\r\n",
user, name.nodename, tty, date);
free(tty);
/*
* Fork to avoid hanging in a write()
*/
if (fork() != 0)
return;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sigaction(SIGALRM, &sa, NULL);
setutxent();
while ((utmp = getutxent()) != NULL) {
if (utmp->ut_type != USER_PROCESS || utmp->ut_user[0] == 0)
continue;
if (strncmp(utmp->ut_line, _PATH_DEV, strlen(_PATH_DEV)) == 0)
xasprintf(&term, "%s", utmp->ut_line);
else
xasprintf(&term, "%s%s", _PATH_DEV, utmp->ut_line);
if (strstr(term, "/../")) {
free(term);
continue;
}
/*
* Open it non-delay
*/
if (sigsetjmp(jbuf, 1) == 0) {
alarm(2);
flags = O_WRONLY|O_NDELAY|O_NOCTTY;
if (file_isatty(term) && (fd = open(term, flags)) >= 0) {
if (isatty(fd) && (tp = fdopen(fd, "w")) != NULL) {
fputs(line, tp);
fputs(text, tp);
fflush(tp);
}
}
}
alarm(0);
if (fd >= 0)
close(fd);
if (tp != NULL)
fclose(tp);
free(term);
}
endutxent();
free(line);
exit(0);
}

16
src/rc/broadcast.h Normal file
View File

@@ -0,0 +1,16 @@
/*
* Copyright 2018 Sony Interactive Entertainment Inc.
*
* 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 BROADCAST_H
#define BROADCAST_H
void broadcast(char *text);
#endif

View File

@@ -58,7 +58,7 @@ static int mount_proc(void)
if (exists("/proc/version"))
return 0;
pid = fork();
switch(pid) {
switch (pid) {
case -1:
syslog(LOG_ERR, "Unable to fork");
return -1;
@@ -248,7 +248,7 @@ int main(int argc, char **argv)
usage(EXIT_FAILURE);
}
}
openlog(applet, LOG_CONS|LOG_PID, LOG_DAEMON);
if (mount_proc() != 0) {
rc_stringlist_free(omits);

View File

@@ -24,12 +24,17 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/reboot.h>
#include <sys/wait.h>
#ifdef HAVE_SELINUX
# include <selinux/selinux.h>
#endif
#include "helpers.h"
#include "rc.h"
#include "rc-wtmp.h"
@@ -44,7 +49,7 @@ static pid_t do_openrc(const char *runlevel)
sigset_t signals;
pid = fork();
switch(pid) {
switch (pid) {
case -1:
perror("fork");
break;
@@ -96,12 +101,15 @@ static void handle_reexec(char *my_name)
static void handle_shutdown(const char *runlevel, int cmd)
{
pid_t pid;
struct timespec ts;
pid = do_openrc(runlevel);
while (waitpid(pid, NULL, 0) != pid);
printf("Sending the final term signal\n");
kill(-1, SIGTERM);
sleep(3);
ts.tv_sec = 3;
ts.tv_nsec = 0;
nanosleep(&ts, NULL);
printf("Sending the final kill signal\n");
kill(-1, SIGKILL);
sync();
@@ -135,7 +143,7 @@ static void reap_zombies(void)
static void signal_handler(int sig)
{
switch(sig) {
switch (sig) {
case SIGINT:
handle_shutdown("reboot", RB_AUTOBOOT);
break;
@@ -157,10 +165,36 @@ int main(int argc, char **argv)
bool reexec = false;
sigset_t signals;
struct sigaction sa;
#ifdef HAVE_SELINUX
int enforce = 0;
#endif
if (getpid() != 1)
return 1;
#ifdef HAVE_SELINUX
if (getenv("SELINUX_INIT") == NULL) {
if (is_selinux_enabled() != 1) {
if (selinux_init_load_policy(&enforce) == 0) {
putenv("SELINUX_INIT=YES");
execv(argv[0], argv);
} else {
if (enforce > 0) {
/*
* SELinux in enforcing mode but load_policy failed
* At this point, we probably can't open /dev/console,
* so log() won't work
*/
fprintf(stderr,"Unable to load SELinux Policy.\n");
fprintf(stderr,"Machine is in enforcing mode.\n");
fprintf(stderr,"Halting now.\n");
exit(1);
}
}
}
}
#endif
printf("OpenRC init version %s starting\n", VERSION);
if (argc > 1)

View File

@@ -1120,7 +1120,7 @@ int main(int argc, char **argv)
char *dir, *save = NULL, *saveLnk = NULL;
char *pidstr = NULL;
size_t l = 0, ll;
const char *file;
const char *file;
struct stat stbuf;
/* Show help if insufficient args */
@@ -1152,7 +1152,7 @@ int main(int argc, char **argv)
}
lnk = xmalloc(4096);
memset(lnk, 0, 4096);
if (readlink(argv[1], lnk, 4096)) {
if (readlink(argv[1], lnk, 4096-1)) {
dir = dirname(path);
if (strchr(lnk, '/')) {
save = xstrdup(dir);
@@ -1223,7 +1223,6 @@ int main(int argc, char **argv)
/* Make our prefix string */
prefix = xmalloc(sizeof(char) * l + 1);
ll = strlen(applet);
memcpy(prefix, applet, ll);
memset(prefix + ll, ' ', l - ll);
memset(prefix + l, 0, 1);

View File

@@ -25,20 +25,24 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include "broadcast.h"
#include "einfo.h"
#include "rc.h"
#include "helpers.h"
#include "rc-misc.h"
#include "_usage.h"
#include "rc-wtmp.h"
const char *applet = NULL;
const char *extraopts = NULL;
const char *getoptstring = "dDHKpRrsw" getoptstring_COMMON;
const char *getoptstring = "cdDfFHKpRrsw" getoptstring_COMMON;
const struct option longopts[] = {
{ "cancel", no_argument, NULL, 'c'},
{ "no-write", no_argument, NULL, 'd'},
{ "dry-run", no_argument, NULL, 'D'},
{ "halt", no_argument, NULL, 'H'},
@@ -51,6 +55,7 @@ const struct option longopts[] = {
longopts_COMMON
};
const char * const longopts_help[] = {
"cancel a pending shutdown",
"do not write wtmp record",
"print actions instead of executing them",
"halt the system",
@@ -62,10 +67,22 @@ const char * const longopts_help[] = {
"write wtmp boot record and exit",
longopts_help_COMMON
};
const char *usagestring = NULL;
const char *usagestring = "" \
"Usage: openrc-shutdown -c | --cancel\n" \
" or: openrc-shutdown -R | --reexec\n" \
" or: openrc-shutdown -w | --write-only\n" \
" or: openmrc-shutdown -H | --halt time\n" \
" or: openrc-shutdown -K | --kexec time\n" \
" or: openrc-shutdown -p | --poweroff time\n" \
" or: openrc-shutdown -r | --reboot time\n" \
" or: openrc-shutdown -s | --single time";
const char *exclusive = "Select one of "
"--halt, --kexec, --poweroff, --reexec, --reboot, --single or --write-only";
"--cancel, --halt, --kexec, --poweroff, --reexec, --reboot, --single or \n"
"--write-only";
const char *nologin_file = RC_SYSCONFDIR"/nologin";
const char *shutdown_pid = "/run/openrc-shutdown.pid";
static bool do_cancel = false;
static bool do_dryrun = false;
static bool do_halt = false;
static bool do_kexec = false;
@@ -76,10 +93,44 @@ static bool do_single = false;
static bool do_wtmp = true;
static bool do_wtmp_only = false;
static void cancel_shutdown(void)
{
pid_t pid;
pid = get_pid(applet, shutdown_pid);
if (pid <= 0)
eerrorx("%s: Unable to cancel shutdown", applet);
if (kill(pid, SIGTERM) != -1)
einfo("%s: shutdown canceled", applet);
else
eerrorx("%s: Unable to cancel shutdown", applet);
}
/*
* Create the nologin file.
*/
static void create_nologin(int mins)
{
FILE *fp;
time_t t;
time(&t);
t += 60 * mins;
if ((fp = fopen(nologin_file, "w")) != NULL) {
fprintf(fp, "\rThe system is going down on %s\r\n", ctime(&t));
fclose(fp);
}
}
/*
* Send a command to our init
*/
static void send_cmd(const char *cmd)
{
FILE *fifo;
size_t ignored;
size_t ignored;
if (do_dryrun) {
einfo("Would send %s to init", cmd);
@@ -99,16 +150,57 @@ static void send_cmd(const char *cmd)
fclose(fifo);
}
/*
* sleep without being interrupted.
* The idea for this code came from sysvinit.
*/
static void sleep_no_interrupt(int seconds)
{
struct timespec duration;
struct timespec remaining;
duration.tv_sec = seconds;
duration.tv_nsec = 0;
while (nanosleep(&duration, &remaining) < 0 && errno == EINTR)
duration = remaining;
}
static void stop_shutdown(int sig)
{
(void) sig;
unlink(nologin_file);
unlink(shutdown_pid);
einfo("Shutdown canceled");
exit(0);
}
int main(int argc, char **argv)
{
char *ch = NULL;
int opt;
int cmd_count = 0;
int hour = 0;
int min = 0;
int shutdown_delay = 0;
struct sigaction sa;
struct tm *lt;
time_t tv;
bool need_warning = false;
char *msg = NULL;
char *state = NULL;
char *time_arg = NULL;
FILE *fp;
applet = basename_c(argv[0]);
while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *) 0)) != -1)
{
switch (opt) {
case 'c':
do_cancel = true;
cmd_count++;
break;
case 'd':
do_wtmp = false;
break;
@@ -117,14 +209,17 @@ int main(int argc, char **argv)
break;
case 'H':
do_halt = true;
xasprintf(&state, "%s", "halt");
cmd_count++;
break;
case 'K':
do_kexec = true;
xasprintf(&state, "%s", "reboot");
cmd_count++;
break;
case 'p':
do_poweroff = true;
xasprintf(&state, "%s", "power off");
cmd_count++;
break;
case 'R':
@@ -133,10 +228,12 @@ int main(int argc, char **argv)
break;
case 'r':
do_reboot = true;
xasprintf(&state, "%s", "reboot");
cmd_count++;
break;
case 's':
do_single = true;
xasprintf(&state, "%s", "go down for maintenance");
cmd_count++;
break;
case 'w':
@@ -146,12 +243,91 @@ int main(int argc, char **argv)
case_RC_COMMON_GETOPT
}
}
if (geteuid() != 0 && ! do_dryrun)
if (geteuid() != 0)
eerrorx("%s: you must be root\n", applet);
if (cmd_count != 1) {
eerror("%s: %s\n", applet, exclusive);
usage(EXIT_FAILURE);
}
if (do_cancel) {
cancel_shutdown();
exit(EXIT_SUCCESS);
} else if (do_reexec) {
send_cmd("reexec");
exit(EXIT_SUCCESS);
} else if (do_wtmp_only) {
log_wtmp("shutdown", "~~", 0, RUN_LVL, "~~");
exit(EXIT_SUCCESS);
}
if (optind >= argc) {
eerror("%s: No shutdown time specified", applet);
usage(EXIT_FAILURE);
}
time_arg = argv[optind];
if (*time_arg == '+')
time_arg++;
if (strcasecmp(time_arg, "now") == 0)
strcpy(time_arg, "0");
for (ch=time_arg; *ch; ch++)
if ((*ch < '0' || *ch > '9') && *ch != ':') {
eerror("%s: invalid time %s", applet, time_arg);
usage(EXIT_FAILURE);
}
if (strchr(time_arg, ':')) {
if ((sscanf(time_arg, "%2d:%2d", &hour, &min) != 2) ||
(hour > 23) || (min > 59)) {
eerror("%s: invalid time %s", applet, time_arg);
usage(EXIT_FAILURE);
}
time(&tv);
lt = localtime(&tv);
shutdown_delay = (hour * 60 + min) - (lt->tm_hour * 60 + lt->tm_min);
if (shutdown_delay < 0)
shutdown_delay += 1440;
} else {
shutdown_delay = atoi(time_arg);
}
fp = fopen(shutdown_pid, "w");
if (!fp)
eerrorx("%s: fopen `%s': %s", applet, shutdown_pid, strerror(errno));
fprintf(fp, "%d\n", getpid());
fclose(fp);
openlog(applet, LOG_PID, LOG_DAEMON);
memset(&sa, 0, sizeof(sa));
sa.sa_handler = stop_shutdown;
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
while (shutdown_delay > 0) {
need_warning = false;
if (shutdown_delay > 180)
need_warning = (shutdown_delay % 60 == 0);
else if (shutdown_delay > 60)
need_warning = (shutdown_delay % 30 == 0);
else if (shutdown_delay > 10)
need_warning = (shutdown_delay % 15 == 0);
else
need_warning = true;
if (shutdown_delay <= 5)
create_nologin(shutdown_delay);
if (need_warning) {
xasprintf(&msg, "\rThe system will %s in %d minutes\r\n",
state, shutdown_delay);
broadcast(msg);
free(msg);
}
sleep_no_interrupt(60);
shutdown_delay--;
}
xasprintf(&msg, "\rThe system will %s now\r\n", state);
broadcast(msg);
syslog(LOG_NOTICE, "The system will %s now", state);
unlink(nologin_file);
unlink(shutdown_pid);
if (do_halt)
send_cmd("halt");
else if (do_kexec)
@@ -160,10 +336,6 @@ int main(int argc, char **argv)
send_cmd("poweroff");
else if (do_reboot)
send_cmd("reboot");
else if (do_reexec)
send_cmd("reexec");
else if (do_wtmp_only)
log_wtmp("shutdown", "~~", 0, RUN_LVL, "~~");
else if (do_single)
send_cmd("single");
return 0;

View File

@@ -28,6 +28,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
@@ -270,8 +271,11 @@ int do_stop(const char *applet, const char *exec, const char *const *argv,
einfo("Would send signal %d to PID %d", sig, pi->pid);
nkilled++;
} else {
if (!quiet)
ebeginv("Sending signal %d to PID %d", sig, pi->pid);
if (sig) {
syslog(LOG_DEBUG, "Sending signal %d to PID %d", sig, pi->pid);
if (!quiet)
ebeginv("Sending signal %d to PID %d", sig, pi->pid);
}
errno = 0;
killed = (kill(pi->pid, sig) == 0 ||
errno == ESRCH ? true : false);
@@ -279,6 +283,9 @@ int do_stop(const char *applet, const char *exec, const char *const *argv,
eendv(killed ? 0 : 1,
"%s: failed to send signal %d to PID %d: %s",
applet, sig, pi->pid, strerror(errno));
else if (!killed)
syslog(LOG_ERR, "Failed to send signal %d to PID %d: %s",
sig, pi->pid, strerror(errno));
if (!killed) {
nkilled = -1;
} else {
@@ -310,12 +317,18 @@ int run_stop_schedule(const char *applet,
if (!(pid > 0 || exec || uid || (argv && *argv)))
return 0;
if (exec)
if (exec) {
einfov("Will stop %s", exec);
if (pid > 0)
syslog(LOG_DEBUG, "Will stop %s", exec);
}
if (pid > 0) {
einfov("Will stop PID %d", pid);
if (uid)
syslog(LOG_DEBUG, "Will stop PID %d", pid);
}
if (uid) {
einfov("Will stop processes owned by UID %d", uid);
syslog(LOG_DEBUG, "Will stop processes owned by UID %d", uid);
}
if (argv && *argv) {
einfovn("Will stop processes of `");
if (rc_yesno(getenv("EINFO_VERBOSE"))) {
@@ -351,8 +364,9 @@ int run_stop_schedule(const char *applet,
tkilled += nkilled;
break;
case SC_FOREVER:
case SC_TIMEOUT:
if (item->value < 1) {
if (item->type == SC_TIMEOUT && item->value < 1) {
item = NULL;
break;
}
@@ -360,7 +374,7 @@ int run_stop_schedule(const char *applet,
ts.tv_sec = 0;
ts.tv_nsec = POLL_INTERVAL;
for (nsecs = 0; nsecs < item->value; nsecs++) {
for (nsecs = 0; item->type == SC_FOREVER || nsecs < item->value; nsecs++) {
for (nloops = 0;
nloops < ONE_SECOND / POLL_INTERVAL;
nloops++)
@@ -375,10 +389,7 @@ int run_stop_schedule(const char *applet,
printf("\n");
progressed = false;
}
if (errno == EINTR)
eerror("%s: caught an"
" interrupt", applet);
else {
if (errno != EINTR) {
eerror("%s: nanosleep: %s",
applet, strerror(errno));
return 0;

View File

@@ -49,10 +49,12 @@ const char * const longopts_help[] = {
"set xtrace when running the command",
"ignore dependencies",
"tests if the service exists or not",
"if the service is crashed then run the command",
"if the service exists then run the command",
"if the service is inactive then run the command",
"if the service is not started then run the command",
"if the service is crashed run the command",
"if the service exists run the command",
"if the service is inactive run the command",
"if the service is not started run the command",
"if the service is started run the command",
"if the service is stopped run the command",
"list all available services",
"resolve the service name to an init script",
"dry run (show what would happen)",

View File

@@ -27,31 +27,40 @@
#include "rc-misc.h"
#include "_usage.h"
enum format_t {
FORMAT_DEFAULT,
FORMAT_INI,
};
const char *applet = NULL;
const char *extraopts = NULL;
const char *getoptstring = "aclmrsu" getoptstring_COMMON;
const char *getoptstring = "acf:lmrsSu" getoptstring_COMMON;
const struct option longopts[] = {
{"all", 0, NULL, 'a'},
{"crashed", 0, NULL, 'c'},
{"format", 1, NULL, 'f'},
{"list", 0, NULL, 'l'},
{"manual", 0, NULL, 'm'},
{"runlevel", 0, NULL, 'r'},
{"servicelist", 0, NULL, 's'},
{"supervised", 0, NULL, 'S'},
{"unused", 0, NULL, 'u'},
longopts_COMMON
};
const char * const longopts_help[] = {
"Show services from all run levels",
"Show crashed services",
"format status to be parsable (currently arg must be ini)",
"Show list of run levels",
"Show manually started services",
"Show the name of the current runlevel",
"Show service list",
"show supervised services",
"Show services not assigned to any runlevel",
longopts_help_COMMON
};
const char *usagestring = "" \
"Usage: rc-status [options] <runlevel>...\n" \
"Usage: rc-status [options] -f ini <runlevel>...\n" \
" or: rc-status [options] [-a | -c | -l | -m | -r | -s | -u]";
static RC_DEPTREE *deptree;
@@ -60,19 +69,27 @@ static RC_STRINGLIST *types;
static RC_STRINGLIST *levels, *services, *tmp, *alist;
static RC_STRINGLIST *sservices, *nservices, *needsme;
static void
print_level(const char *prefix, const char *level)
static void print_level(const char *prefix, const char *level,
enum format_t format)
{
if (prefix)
printf("%s ", prefix);
printf ("Runlevel: ");
if (isatty(fileno(stdout)))
printf("%s%s%s\n",
ecolor(ECOLOR_HILITE),
level,
ecolor(ECOLOR_NORMAL));
else
printf("%s\n", level);
switch (format) {
case FORMAT_DEFAULT:
if (prefix)
printf("%s ", prefix);
printf ("Runlevel: ");
if (isatty(fileno(stdout)))
printf("%s%s%s\n",
ecolor(ECOLOR_HILITE), level, ecolor(ECOLOR_NORMAL));
else
printf("%s\n", level);
break;
case FORMAT_INI:
printf("%s", "[");
if (prefix)
printf("%s ", prefix);
printf("%s]\n", level);
break;
}
}
static char *get_uptime(const char *service)
@@ -123,14 +140,13 @@ static char *get_uptime(const char *service)
return uptime;
}
static void
print_service(const char *service)
static void print_service(const char *service, enum format_t format)
{
char *status = NULL;
char *uptime = NULL;
char *child_pid = NULL;
char *start_time = NULL;
int cols = printf(" %s", service);
int cols;
const char *c = ecolor(ECOLOR_GOOD);
RC_SERVICE state = rc_service_state(service);
ECOLOR color = ECOLOR_BAD;
@@ -167,18 +183,29 @@ print_service(const char *service)
} else if (state & RC_SERVICE_SCHEDULED) {
xasprintf(&status, "scheduled");
color = ECOLOR_WARN;
} else if (state & RC_SERVICE_FAILED) {
xasprintf(&status, "failed");
color = ECOLOR_WARN;
} else
xasprintf(&status, " stopped ");
errno = 0;
if (c && *c && isatty(fileno(stdout)))
printf("\n");
ebracket(cols, color, status);
switch (format) {
case FORMAT_DEFAULT:
cols = printf(" %s", service);
if (c && *c && isatty(fileno(stdout)))
printf("\n");
ebracket(cols, color, status);
break;
case FORMAT_INI:
printf("%s = %s\n", service, status);
break;
}
free(status);
}
static void
print_services(const char *runlevel, RC_STRINGLIST *svcs)
static void print_services(const char *runlevel, RC_STRINGLIST *svcs,
enum format_t format)
{
RC_STRINGLIST *l = NULL;
RC_STRING *s;
@@ -192,7 +219,7 @@ print_services(const char *runlevel, RC_STRINGLIST *svcs)
TAILQ_FOREACH(s, svcs, entries)
if (!runlevel ||
rc_service_in_runlevel(s->value, runlevel))
print_service(s->value);
print_service(s->value, format);
return;
}
if (!types) {
@@ -212,13 +239,12 @@ print_services(const char *runlevel, RC_STRINGLIST *svcs)
if (!rc_stringlist_find(svcs, s->value))
continue;
if (!runlevel || rc_service_in_runlevel(s->value, runlevel))
print_service(s->value);
print_service(s->value, format);
}
rc_stringlist_free(l);
}
static void
print_stacked_services(const char *runlevel)
static void print_stacked_services(const char *runlevel, enum format_t format)
{
RC_STRINGLIST *stackedlevels, *servicelist;
RC_STRING *stackedlevel;
@@ -227,9 +253,9 @@ print_stacked_services(const char *runlevel)
TAILQ_FOREACH(stackedlevel, stackedlevels, entries) {
if (rc_stringlist_find(levels, stackedlevel->value) != NULL)
continue;
print_level("Stacked", stackedlevel->value);
print_level("Stacked", stackedlevel->value, format);
servicelist = rc_services_in_runlevel(stackedlevel->value);
print_services(stackedlevel->value, servicelist);
print_services(stackedlevel->value, servicelist, format);
rc_stringlist_free(servicelist);
}
rc_stringlist_free(stackedlevels);
@@ -238,7 +264,10 @@ print_stacked_services(const char *runlevel)
int main(int argc, char **argv)
{
RC_STRING *s, *l, *t, *level;
RC_SERVICE state;
RC_STRING *s, *l, *t, *level;
enum format_t format = FORMAT_DEFAULT;
bool levels_given = false;
bool show_all = false;
char *p, *runlevel = NULL;
int opt, retval = 0;
@@ -261,6 +290,12 @@ int main(int argc, char **argv)
}
goto exit;
/* NOTREACHED */
case 'f':
if (strcasecmp(optarg, "ini") == 0)
format = FORMAT_INI;
else
eerrorx("%s: invalid argument to --format switch\n", applet);
break;
case 'l':
levels = rc_runlevel_list();
TAILQ_FOREACH(l, levels, entries)
@@ -285,16 +320,24 @@ int main(int argc, char **argv)
free(s->value);
free(s);
}
print_services(NULL, services);
print_services(NULL, services, FORMAT_DEFAULT);
goto exit;
case 'r':
runlevel = rc_runlevel_get();
printf("%s\n", runlevel);
goto exit;
/* NOTREACHED */
case 'S':
services = rc_services_in_state(RC_SERVICE_STARTED);
TAILQ_FOREACH_SAFE(s, services, entries, t)
if (!rc_service_value_get(s->value, "child_pid"))
TAILQ_REMOVE(services, s, entries);
print_services(NULL, services, FORMAT_DEFAULT);
goto exit;
/* NOTREACHED */
case 's':
services = rc_services_in_runlevel(NULL);
print_services(NULL, services);
print_services(NULL, services, FORMAT_DEFAULT);
goto exit;
/* NOTREACHED */
case 'u':
@@ -309,7 +352,7 @@ int main(int argc, char **argv)
break;
}
}
print_services(NULL, services);
print_services(NULL, services, FORMAT_DEFAULT);
goto exit;
/* NOTREACHED */
@@ -321,6 +364,7 @@ int main(int argc, char **argv)
opt = (optind < argc) ? 0 : 1;
while (optind < argc) {
if (rc_runlevel_exists(argv[optind])) {
levels_given = true;
rc_stringlist_add(levels, argv[optind++]);
opt++;
} else
@@ -337,21 +381,21 @@ int main(int argc, char **argv)
deptree = _rc_deptree_load(0, NULL);
TAILQ_FOREACH(l, levels, entries) {
print_level(NULL, l->value);
print_level(NULL, l->value, format);
services = rc_services_in_runlevel(l->value);
print_services(l->value, services);
print_stacked_services(l->value);
print_services(l->value, services, format);
print_stacked_services(l->value, format);
rc_stringlist_free(nservices);
nservices = NULL;
rc_stringlist_free(services);
services = NULL;
}
if (show_all || argc < 2) {
if (show_all || !levels_given) {
/* Show hotplugged services */
print_level("Dynamic", "hotplugged");
print_level("Dynamic", "hotplugged", format);
services = rc_services_in_state(RC_SERVICE_HOTPLUGGED);
print_services(NULL, services);
print_services(NULL, services, format);
rc_stringlist_free(services);
services = NULL;
@@ -373,11 +417,14 @@ int main(int argc, char **argv)
free(nservices);
}
TAILQ_FOREACH_SAFE(s, services, entries, t) {
state = rc_service_state(s->value);
if ((rc_stringlist_find(sservices, s->value) ||
(rc_service_state(s->value) & ( RC_SERVICE_STOPPED | RC_SERVICE_HOTPLUGGED)))) {
TAILQ_REMOVE(services, s, entries);
free(s->value);
free(s);
(state & ( RC_SERVICE_STOPPED | RC_SERVICE_HOTPLUGGED)))) {
if (! (state & RC_SERVICE_FAILED)) {
TAILQ_REMOVE(services, s, entries);
free(s->value);
free(s);
}
}
}
needsme = rc_stringlist_new();
@@ -405,10 +452,10 @@ int main(int argc, char **argv)
* be added to the list
*/
unsetenv("RC_SVCNAME");
print_level("Dynamic", "needed/wanted");
print_services(NULL, nservices);
print_level("Dynamic", "manual");
print_services(NULL, services);
print_level("Dynamic", "needed/wanted", format);
print_services(NULL, nservices, format);
print_level("Dynamic", "manual", format);
print_services(NULL, services, format);
}
exit:

View File

@@ -42,9 +42,9 @@ void log_wtmp(const char *user, const char *id, pid_t pid, int type,
strncpy(utmp.ut_name, user, sizeof(utmp.ut_name));
strncpy(utmp.ut_id , id , sizeof(utmp.ut_id ));
strncpy(utmp.ut_line, line, sizeof(utmp.ut_line));
/* Put the OS version in place of the hostname */
if (uname(&uname_buf) == 0)
/* Put the OS version in place of the hostname */
if (uname(&uname_buf) == 0)
strncpy(utmp.ut_host, uname_buf.release, sizeof(utmp.ut_host));
updwtmp(WTMP_FILE, &utmp);

View File

@@ -492,7 +492,7 @@ int main(int argc, char **argv)
startas = optarg;
break;
case 'w':
if (sscanf(optarg, "%d", &start_wait) != 1)
if (sscanf(optarg, "%u", &start_wait) != 1)
eerrorx("%s: `%s' not a number",
applet, optarg);
break;
@@ -547,7 +547,7 @@ int main(int argc, char **argv)
} else if (name) {
*--argv = name;
++argc;
} else if (exec) {
} else if (exec) {
*--argv = exec;
++argc;
};
@@ -996,9 +996,7 @@ int main(int argc, char **argv)
ts.tv_sec = start_wait / 1000;
ts.tv_nsec = (start_wait % 1000) * ONE_MS;
if (nanosleep(&ts, NULL) == -1) {
if (errno == EINTR)
eerror("%s: caught an interrupt", applet);
else {
if (errno != EINTR) {
eerror("%s: nanosleep: %s",
applet, strerror(errno));
return 0;

View File

@@ -61,15 +61,18 @@ static struct pam_conv conv = { NULL, NULL};
#include "queue.h"
#include "rc.h"
#include "rc-misc.h"
#include "rc-plugin.h"
#include "rc-schedules.h"
#include "_usage.h"
#include "helpers.h"
const char *applet = NULL;
const char *extraopts = NULL;
const char *getoptstring = "D:d:e:g:I:Kk:m:N:p:R:r:Su:1:2:3" \
const char *getoptstring = "A:a:D:d:e:g:H:I:Kk:m:N:p:R:r:s:Su:1:2:3" \
getoptstring_COMMON;
const struct option longopts[] = {
{ "healthcheck-timer", 1, NULL, 'a'},
{ "healthcheck-delay", 1, NULL, 'A'},
{ "respawn-delay", 1, NULL, 'D'},
{ "chdir", 1, NULL, 'd'},
{ "env", 1, NULL, 'e'},
@@ -83,6 +86,7 @@ const struct option longopts[] = {
{ "respawn-period", 1, NULL, 'P'},
{ "retry", 1, NULL, 'R'},
{ "chroot", 1, NULL, 'r'},
{ "signal", 1, NULL, 's'},
{ "start", 0, NULL, 'S'},
{ "user", 1, NULL, 'u'},
{ "stdout", 1, NULL, '1'},
@@ -91,6 +95,8 @@ const struct option longopts[] = {
longopts_COMMON
};
const char * const longopts_help[] = {
"set an initial health check delay",
"set a health check timer",
"Set a respawn delay",
"Change the PWD",
"Set an environment string",
@@ -104,6 +110,7 @@ const char * const longopts_help[] = {
"Set respawn time period",
"Retry schedule to use when stopping",
"Chroot to this directory",
"Send a signal to the daemon",
"Start daemon",
"Change the process user",
"Redirect stdout to file",
@@ -113,6 +120,10 @@ const char * const longopts_help[] = {
};
const char *usagestring = NULL;
static int healthcheckdelay = 0;
static int healthchecktimer = 0;
static volatile sig_atomic_t do_healthcheck = 0;
static volatile sig_atomic_t exiting = 0;
static int nicelevel = 0;
static int ionicec = -1;
static int ioniced = 0;
@@ -125,7 +136,6 @@ static int stdout_fd;
static int stderr_fd;
static char *redirect_stderr = NULL;
static char *redirect_stdout = NULL;
static bool exiting = false;
#ifdef TIOCNOTTY
static int tty_fd = -1;
#endif
@@ -133,7 +143,9 @@ static pid_t child_pid;
static int respawn_count = 0;
static int respawn_delay = 0;
static int respawn_max = 10;
static int respawn_period = 5;
static int respawn_period = 0;
static char *fifopath = NULL;
static int fifo_fd = 0;
static char *pidfile = NULL;
static char *svcname = NULL;
@@ -172,15 +184,32 @@ static void re_exec_supervisor(void)
static void handle_signal(int sig)
{
int serrno = errno;
pid_t pid;
syslog(LOG_WARNING, "caught signal %d", sig);
if (sig == SIGTERM)
exiting = true;
switch (sig) {
case SIGALRM:
do_healthcheck = 1;
break;
case SIGCHLD:
if (exiting)
while (waitpid((pid_t)(-1), NULL, WNOHANG) > 0) {}
else {
while ((pid = waitpid((pid_t)(-1), NULL, WNOHANG|WNOWAIT)) > 0) {
if (pid == child_pid)
break;
pid = waitpid(pid, NULL, WNOHANG);
}
}
break;
case SIGTERM:
exiting = 1;
break;
default:
syslog(LOG_WARNING, "caught signal %d", sig);
re_exec_supervisor();
}
/* Restore errno */
errno = serrno;
if (! exiting)
re_exec_supervisor();
}
static char * expand_home(const char *home, const char *path)
@@ -208,7 +237,7 @@ static char * expand_home(const char *home, const char *path)
ppath++;
if (!home) {
free(opath);
free(opath);
return xstrdup(path);
}
if (!ppath) {
@@ -238,6 +267,56 @@ static char *make_cmdline(char **argv)
return cmdline;
}
static pid_t exec_command(const char *cmd)
{
char *file;
pid_t pid = -1;
sigset_t full;
sigset_t old;
struct sigaction sa;
file = rc_service_resolve(svcname);
if (!exists(file)) {
free(file);
return 0;
}
/* We need to block signals until we have forked */
memset(&sa, 0, sizeof (sa));
sa.sa_handler = SIG_DFL;
sigemptyset(&sa.sa_mask);
sigfillset(&full);
sigprocmask(SIG_SETMASK, &full, &old);
pid = fork();
if (pid == 0) {
/* Restore default handlers */
sigaction(SIGCHLD, &sa, NULL);
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGQUIT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGUSR1, &sa, NULL);
sigaction(SIGWINCH, &sa, NULL);
/* Unmask signals */
sigprocmask(SIG_SETMASK, &old, NULL);
/* Safe to run now */
execl(file, file, cmd, (char *) NULL);
syslog(LOG_ERR, "unable to exec `%s': %s\n",
file, strerror(errno));
_exit(EXIT_FAILURE);
}
if (pid == -1)
syslog(LOG_ERR, "fork: %s\n",strerror (errno));
sigprocmask(SIG_SETMASK, &old, NULL);
free(file);
return pid;
}
static void child_process(char *exec, char **argv)
{
RC_STRINGLIST *env_list;
@@ -423,52 +502,40 @@ static void child_process(char *exec, char **argv)
static void supervisor(char *exec, char **argv)
{
FILE *fp;
char buf[2048];
char cmd[2048];
int count;
int failing;
int health_status;
int healthcheck_respawn;
int i;
int nkilled;
int sig_send;
pid_t health_pid;
pid_t wait_pid;
sigset_t old_signals;
sigset_t signals;
struct sigaction sa;
struct timespec ts;
time_t respawn_now= 0;
time_t first_spawn= 0;
#ifndef RC_DEBUG
signal_setup_restart(SIGHUP, handle_signal);
signal_setup_restart(SIGINT, handle_signal);
signal_setup_restart(SIGQUIT, handle_signal);
signal_setup_restart(SIGILL, handle_signal);
signal_setup_restart(SIGABRT, handle_signal);
signal_setup_restart(SIGFPE, handle_signal);
signal_setup_restart(SIGSEGV, handle_signal);
signal_setup_restart(SIGPIPE, handle_signal);
signal_setup_restart(SIGALRM, handle_signal);
signal_setup(SIGTERM, handle_signal);
signal_setup_restart(SIGUSR1, handle_signal);
signal_setup_restart(SIGUSR2, handle_signal);
signal_setup_restart(SIGBUS, handle_signal);
#ifdef SIGPOLL
signal_setup_restart(SIGPOLL, handle_signal);
#endif
signal_setup_restart(SIGPROF, handle_signal);
signal_setup_restart(SIGSYS, handle_signal);
signal_setup_restart(SIGTRAP, handle_signal);
signal_setup_restart(SIGVTALRM, handle_signal);
signal_setup_restart(SIGXCPU, handle_signal);
signal_setup_restart(SIGXFSZ, handle_signal);
#ifdef SIGEMT
signal_setup_restart(SIGEMT, handle_signal);
#endif
signal_setup_restart(SIGIO, handle_signal);
#ifdef SIGPWR
signal_setup_restart(SIGPWR, handle_signal);
#endif
#ifdef SIGUNUSED
signal_setup_restart(SIGUNUSED, handle_signal);
#endif
#ifdef SIGRTMIN
for (i = SIGRTMIN; i <= SIGRTMAX; i++)
signal_setup_restart(i, handle_signal);
#endif
#endif
/* block all signals we do not handle */
sigfillset(&signals);
sigdelset(&signals, SIGALRM);
sigdelset(&signals, SIGCHLD);
sigdelset(&signals, SIGTERM);
sigprocmask(SIG_SETMASK, &signals, &old_signals);
/* install signal handler */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = handle_signal;
sigaction(SIGALRM, &sa, NULL);
sigaction(SIGCHLD, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
fp = fopen(pidfile, "w");
if (! fp)
if (!fp)
eerrorx("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
fprintf(fp, "%d\n", getpid());
fclose(fp);
@@ -486,56 +553,131 @@ static void supervisor(char *exec, char **argv)
/*
* Supervisor main loop
*/
i = 0;
if (healthcheckdelay)
alarm(healthcheckdelay);
else if (healthchecktimer)
alarm(healthchecktimer);
failing = 0;
while (!exiting) {
wait(&i);
healthcheck_respawn = 0;
fifo_fd = open(fifopath, O_RDONLY);
if (fifo_fd > 0) {
memset(buf, 0, sizeof(buf));
count = read(fifo_fd, buf, sizeof(buf) - 1);
close(fifo_fd);
if (count != -1)
buf[count] = 0;
if (count == 0)
continue;
syslog(LOG_DEBUG, "Received %s from fifo", buf);
if (strncasecmp(buf, "sig", 3) == 0) {
if ((sscanf(buf, "%s %d", cmd, &sig_send) == 2)
&& (sig_send >= 0 && sig_send < NSIG)) {
syslog(LOG_INFO, "Sending signal %d to %d", sig_send,
child_pid);
if (kill(child_pid, sig_send) == -1)
syslog(LOG_ERR, "Unable to send signal %d to %d",
sig_send, child_pid);
}
}
continue;
}
if (do_healthcheck) {
do_healthcheck = 0;
alarm(0);
syslog(LOG_DEBUG, "running health check for %s", svcname);
health_pid = exec_command("healthcheck");
health_status = rc_waitpid(health_pid);
if (WIFEXITED(health_status) && WEXITSTATUS(health_status) == 0)
alarm(healthchecktimer);
else {
syslog(LOG_WARNING, "health check for %s failed", svcname);
health_pid = exec_command("unhealthy");
rc_waitpid(health_pid);
syslog(LOG_INFO, "stopping %s, pid %d", exec, child_pid);
nkilled = run_stop_schedule(applet, NULL, NULL, child_pid, 0,
false, false, true);
if (nkilled < 0)
syslog(LOG_INFO, "Unable to kill %d: %s",
child_pid, strerror(errno));
else
healthcheck_respawn = 1;
}
}
if (exiting) {
signal_setup(SIGCHLD, SIG_IGN);
alarm(0);
syslog(LOG_INFO, "stopping %s, pid %d", exec, child_pid);
nkilled = run_stop_schedule(applet, exec, NULL, child_pid, 0,
nkilled = run_stop_schedule(applet, NULL, NULL, child_pid, 0,
false, false, true);
if (nkilled > 0)
syslog(LOG_INFO, "killed %d processes", nkilled);
} else {
sleep(respawn_delay);
if (respawn_max > 0 && respawn_period > 0) {
respawn_now = time(NULL);
if (first_spawn == 0)
first_spawn = respawn_now;
if (respawn_now - first_spawn > respawn_period) {
respawn_count = 0;
first_spawn = 0;
} else
respawn_count++;
if (respawn_count > respawn_max) {
syslog(LOG_WARNING,
"respawned \"%s\" too many times, exiting", exec);
exiting = true;
continue;
}
}
continue;
}
wait_pid = waitpid(child_pid, &i, WNOHANG);
if (wait_pid == child_pid) {
if (WIFEXITED(i))
syslog(LOG_WARNING, "%s, pid %d, exited with return code %d",
exec, child_pid, WEXITSTATUS(i));
else if (WIFSIGNALED(i))
syslog(LOG_WARNING, "%s, pid %d, terminated by signal %d",
exec, child_pid, WTERMSIG(i));
}
if (wait_pid == child_pid || healthcheck_respawn) {
do_healthcheck = 0;
healthcheck_respawn = 0;
alarm(0);
respawn_now = time(NULL);
if (first_spawn == 0)
first_spawn = respawn_now;
if ((respawn_period > 0)
&& (respawn_now - first_spawn > respawn_period)) {
respawn_count = 0;
first_spawn = 0;
} else
respawn_count++;
if (respawn_max > 0 && respawn_count > respawn_max) {
syslog(LOG_WARNING, "respawned \"%s\" too many times, exiting",
exec);
exiting = 1;
failing = 1;
continue;
}
ts.tv_sec = respawn_delay;
ts.tv_nsec = 0;
nanosleep(&ts, NULL);
child_pid = fork();
if (child_pid == -1)
eerrorx("%s: fork: %s", applet, strerror(errno));
if (child_pid == 0)
if (child_pid == -1) {
syslog(LOG_ERR, "%s: fork: %s", applet, strerror(errno));
exit(EXIT_FAILURE);
}
if (child_pid == 0) {
sigprocmask(SIG_SETMASK, &old_signals, NULL);
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
sigaction(SIGALRM, &sa, NULL);
sigaction(SIGCHLD, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
child_process(exec, argv);
}
if (healthcheckdelay)
alarm(healthcheckdelay);
else if (healthchecktimer)
alarm(healthchecktimer);
}
}
if (pidfile && exists(pidfile))
unlink(pidfile);
if (svcname) {
rc_service_daemon_set(svcname, exec, (const char *const *)argv,
pidfile, false);
rc_service_mark(svcname, RC_SERVICE_STOPPED);
rc_service_value_set(svcname, "child_pid", NULL);
rc_service_mark(svcname, RC_SERVICE_STOPPED);
if (failing)
rc_service_mark(svcname, RC_SERVICE_FAILED);
}
if (pidfile && exists(pidfile))
unlink(pidfile);
if (fifopath && exists(fifopath))
unlink(fifopath);
exit(EXIT_SUCCESS);
}
@@ -547,6 +689,7 @@ int main(int argc, char **argv)
bool start = false;
bool stop = false;
bool reexec = false;
bool sendsig = false;
char *exec = NULL;
char *retry = NULL;
int sig = SIGTERM;
@@ -577,7 +720,7 @@ int main(int argc, char **argv)
eerrorx("%s: The RC_SVCNAME environment variable is not set", applet);
openlog(applet, LOG_PID, LOG_DAEMON);
if (argc >= 1 && svcname && strcmp(argv[1], svcname))
if (argc <= 1 || strcmp(argv[1], svcname))
eerrorx("%s: the first argument is %s and must be %s",
applet, argv[1], svcname);
@@ -609,6 +752,16 @@ int main(int argc, char **argv)
while ((opt = getopt_long(argc, argv, getoptstring, longopts,
(int *) 0)) != -1)
switch (opt) {
case 'a': /* --healthcheck-timer <time> */
if (sscanf(optarg, "%d", &healthchecktimer) != 1 || healthchecktimer < 1)
eerrorx("%s: invalid health check timer %s", applet, optarg);
break;
case 'A': /* --healthcheck-delay <time> */
if (sscanf(optarg, "%d", &healthcheckdelay) != 1 || healthcheckdelay < 1)
eerrorx("%s: invalid health check delay %s", applet, optarg);
break;
case 'D': /* --respawn-delay time */
n = sscanf(optarg, "%d", &respawn_delay);
if (n != 1 || respawn_delay < 1)
@@ -642,6 +795,10 @@ int main(int argc, char **argv)
eerrorx("Invalid respawn-period value '%s'", optarg);
break;
case 's': /* --signal */
sig = parse_signal(applet, optarg);
sendsig = true;
break;
case 'S': /* --start */
start = true;
break;
@@ -665,6 +822,11 @@ int main(int argc, char **argv)
gid = gr->gr_gid;
break;
case 'H': /* --healthcheck-timer <minutes> */
if (sscanf(optarg, "%d", &healthchecktimer) != 1 || healthchecktimer < 1)
eerrorx("%s: invalid health check timer %s", applet, optarg);
break;
case 'k':
if (parse_mode(&numask, optarg))
eerrorx("%s: invalid mode `%s'",
@@ -742,8 +904,6 @@ int main(int argc, char **argv)
case_RC_COMMON_GETOPT
}
if (!pidfile && !reexec)
eerrorx("%s: --pidfile must be specified", applet);
endpwent();
argc -= optind;
argv += optind;
@@ -756,6 +916,12 @@ int main(int argc, char **argv)
ch_root = expand_home(home, ch_root);
umask(numask);
if (!pidfile)
xasprintf(&pidfile, "/var/run/supervise-%s.pid", svcname);
xasprintf(&fifopath, "%s/supervise-%s.ctl", RC_SVCDIR, svcname);
if (mkfifo(fifopath, 0600) == -1 && errno != EEXIST)
eerrorx("%s: unable to create control fifo: %s",
applet, strerror(errno));
if (reexec) {
str = rc_service_value_get(svcname, "argc");
@@ -830,9 +996,9 @@ int main(int argc, char **argv)
0, false, true) > 0)
eerrorx("%s: %s is already running", applet, exec);
if (respawn_delay * respawn_max > respawn_period)
if (respawn_period > 0 && respawn_delay * respawn_max > respawn_period)
ewarn("%s: Please increase the value of --respawn-period to more "
"than %d to avoid infinite respawning", applet,
"than %d to avoid infinite respawning", applet,
respawn_delay * respawn_max);
if (retry) {
@@ -877,6 +1043,9 @@ int main(int argc, char **argv)
tty_fd = open("/dev/tty", O_RDWR);
#endif
devnull_fd = open("/dev/null", O_RDWR);
dup2(devnull_fd, STDIN_FILENO);
dup2(devnull_fd, STDOUT_FILENO);
dup2(devnull_fd, STDERR_FILENO);
child_pid = fork();
if (child_pid == -1)
eerrorx("%s: fork: %s", applet, strerror(errno));
@@ -893,8 +1062,8 @@ int main(int argc, char **argv)
c++;
}
xasprintf(&varbuf, "%d", x);
rc_service_value_set(svcname, "argc", varbuf);
free(varbuf);
rc_service_value_set(svcname, "argc", varbuf);
free(varbuf);
rc_service_value_set(svcname, "exec", exec);
supervisor(exec, argv);
} else
@@ -929,5 +1098,18 @@ int main(int argc, char **argv)
rc_service_mark(svcname, RC_SERVICE_STOPPED);
}
exit(EXIT_SUCCESS);
} else if (sendsig) {
fifo_fd = open(fifopath, O_WRONLY |O_NONBLOCK);
if (fifo_fd < 0)
eerrorx("%s: unable to open control fifo %s", applet, strerror(errno));
xasprintf(&str, "sig %d", sig);
x = write(fifo_fd, str, strlen(str));
if (x == -1) {
free(tmp);
eerrorx("%s: error writing to control fifo: %s", applet,
strerror(errno));
}
free(tmp);
exit(EXIT_SUCCESS);
}
}

6
src/test/.gitignore vendored
View File

@@ -1,6 +0,0 @@
einfo.data.out
einfo.funcs.out
librc.funcs.hidden.out
librc.funcs.hidden.list
rc.data.out
rc.funcs.out

View File

@@ -1 +0,0 @@
EINFO_1.0

View File

@@ -1,52 +0,0 @@
ebegin
ebegin@@EINFO_1.0
ebeginv
ebeginv@@EINFO_1.0
ebracket
ebracket@@EINFO_1.0
ecolor
ecolor@@EINFO_1.0
eend
eend@@EINFO_1.0
eendv
eendv@@EINFO_1.0
eerror
eerror@@EINFO_1.0
eerrorn
eerrorn@@EINFO_1.0
eerrorx
eerrorx@@EINFO_1.0
eindent
eindent@@EINFO_1.0
eindentv
eindentv@@EINFO_1.0
einfo
einfo@@EINFO_1.0
einfon
einfon@@EINFO_1.0
einfov
einfov@@EINFO_1.0
einfovn
einfovn@@EINFO_1.0
elog
elog@@EINFO_1.0
eoutdent
eoutdent@@EINFO_1.0
eoutdentv
eoutdentv@@EINFO_1.0
eprefix
eprefix@@EINFO_1.0
ewarn
ewarn@@EINFO_1.0
ewarnn
ewarnn@@EINFO_1.0
ewarnv
ewarnv@@EINFO_1.0
ewarnvn
ewarnvn@@EINFO_1.0
ewarnx
ewarnx@@EINFO_1.0
ewend
ewend@@EINFO_1.0
ewendv
ewendv@@EINFO_1.0

View File

@@ -1,3 +0,0 @@
RC_1.0
rc_environ_fd
rc_environ_fd@@RC_1.0

View File

@@ -1,116 +0,0 @@
rc_conf_value
rc_conf_value@@RC_1.0
rc_config_list
rc_config_list@@RC_1.0
rc_config_load
rc_config_load@@RC_1.0
rc_config_value
rc_config_value@@RC_1.0
rc_deptree_depend
rc_deptree_depend@@RC_1.0
rc_deptree_depends
rc_deptree_depends@@RC_1.0
rc_deptree_free
rc_deptree_free@@RC_1.0
rc_deptree_load
rc_deptree_load@@RC_1.0
rc_deptree_load_file
rc_deptree_load_file@@RC_1.0
rc_deptree_order
rc_deptree_order@@RC_1.0
rc_deptree_update
rc_deptree_update@@RC_1.0
rc_deptree_update_needed
rc_deptree_update_needed@@RC_1.0
rc_find_pids
rc_find_pids@@RC_1.0
rc_getfile
rc_getfile@@RC_1.0
rc_getline
rc_getline@@RC_1.0
rc_newer_than
rc_newer_than@@RC_1.0
rc_older_than
rc_older_than@@RC_1.0
rc_proc_getent
rc_proc_getent@@RC_1.0
rc_runlevel_exists
rc_runlevel_exists@@RC_1.0
rc_runlevel_get
rc_runlevel_get@@RC_1.0
rc_runlevel_list
rc_runlevel_list@@RC_1.0
rc_runlevel_set
rc_runlevel_set@@RC_1.0
rc_runlevel_stack
rc_runlevel_stack@@RC_1.0
rc_runlevel_stacks
rc_runlevel_stacks@@RC_1.0
rc_runlevel_starting
rc_runlevel_starting@@RC_1.0
rc_runlevel_stopping
rc_runlevel_stopping@@RC_1.0
rc_runlevel_unstack
rc_runlevel_unstack@@RC_1.0
rc_service_add
rc_service_add@@RC_1.0
rc_service_daemon_set
rc_service_daemon_set@@RC_1.0
rc_service_daemons_crashed
rc_service_daemons_crashed@@RC_1.0
rc_service_delete
rc_service_delete@@RC_1.0
rc_service_description
rc_service_description@@RC_1.0
rc_service_exists
rc_service_exists@@RC_1.0
rc_service_extra_commands
rc_service_extra_commands@@RC_1.0
rc_service_in_runlevel
rc_service_in_runlevel@@RC_1.0
rc_service_mark
rc_service_mark@@RC_1.0
rc_service_resolve
rc_service_resolve@@RC_1.0
rc_service_schedule_clear
rc_service_schedule_clear@@RC_1.0
rc_service_schedule_start
rc_service_schedule_start@@RC_1.0
rc_service_started_daemon
rc_service_started_daemon@@RC_1.0
rc_service_state
rc_service_state@@RC_1.0
rc_service_value_get
rc_service_value_get@@RC_1.0
rc_service_value_set
rc_service_value_set@@RC_1.0
rc_services_in_runlevel
rc_services_in_runlevel@@RC_1.0
rc_services_in_runlevel_stacked
rc_services_in_runlevel_stacked@@RC_1.0
rc_services_in_state
rc_services_in_state@@RC_1.0
rc_services_scheduled
rc_services_scheduled@@RC_1.0
rc_services_scheduled_by
rc_services_scheduled_by@@RC_1.0
rc_stringlist_add
rc_stringlist_add@@RC_1.0
rc_stringlist_addu
rc_stringlist_addu@@RC_1.0
rc_stringlist_delete
rc_stringlist_delete@@RC_1.0
rc_stringlist_find
rc_stringlist_find@@RC_1.0
rc_stringlist_free
rc_stringlist_free@@RC_1.0
rc_stringlist_new
rc_stringlist_new@@RC_1.0
rc_stringlist_sort
rc_stringlist_sort@@RC_1.0
rc_stringlist_split
rc_stringlist_split@@RC_1.0
rc_sys
rc_sys@@RC_1.0
rc_yesno
rc_yesno@@RC_1.0

View File

@@ -7,44 +7,100 @@ terminates unexpectedly.
The following is a brief guide on using this capability.
## Use Default start, stop and status functions
* Use Default start, stop and status functions
If you write your own start, stop and status functions in your service
script, none of this will work. You must allow OpenRC to use the default
functions.
If you write your own start, stop and status functions in your service
script, none of this will work. You must allow OpenRC to use the default
functions.
* Daemons must not fork
Any deamon that you would like to have monitored by supervise-daemon
must not fork. Instead, it must stay in the foreground. If the daemon
forks, the supervisor will be unable to monitor it.
## Daemons must not fork
If the daemon can be configured to not fork, this should be done in the
daemon's configuration file, or by adding a command line option that
instructs it not to fork to the command_args_foreground variable shown
below.
Any deamon that you would like to have monitored by supervise-daemon
must not fork. Instead, it must stay in the foreground. If the daemon
itself forks, the supervisor will be unable to monitor it.
# Health Checks
If the daemon can be configured to not fork, this should be done in the
daemon's configuration file, or by adding a command line option that
instructs it not to fork to the command_args_foreground variable shown
below.
Health checks are a way to make sure a service monitored by
supervise-daemon stays healthy. To configure a health check for a
service, you need to write a healthcheck() function, and optionally an
unhealthy() function in the service script. Also, you will need to set
the healthcheck_timer and optionally healthcheck_delay variables.
## Variable Settings
## healthcheck() function
The healthcheck() function is run repeatedly based on the settings of
the healthcheck_* variables. This function should return zero if the
service is currently healthy or non-zero otherwise.
## unhealthy() function
If the healthcheck() function returns non-zero, the unhealthy() function
is run, then the service is restarted. Since the service will be
restarted by the supervisor, the unhealthy function should not try to
restart it; the purpose of the function is to allow any cleanup tasks
other than restarting the service to be run.
# Variable Settings
The most important setting is the supervisor variable. At the top of
your service script, you should set this variable as follows:
``` sh
supervisor=supervise-daemon
```
Several other variables affect the way services behave under
supervise-daemon. They are documented on the openrc-run man page, but I
will list them here for convenience:
pidfile=/pid/of/supervisor.pid
``` sh
command_args_foreground="arguments"
```
If you are using start-stop-daemon to monitor your scripts, the pidfile
is the path to the pidfile the daemon creates. If, on the other hand,
you are using supervise-daemon, this is the path to the pidfile the
supervisor creates.
command_args_foreground should be used if the daemon you want to monitor
This should be used if the daemon you want to monitor
forks and goes to the background by default. This should be set to the
command line option that instructs the daemon to stay in the foreground.
This is very early support, so feel free to file bugs if you have
issues.
``` sh
healthcheck_delay=seconds
```
This is the delay, in seconds, before the first health check is run.
If it is not set, we use the value of healthcheck_timer.
``` sh
healthcheck_timer=seconds
```
This is the number of seconds between health checks. If it is not set,
no health checks will be run.
``` sh
respawn_delay
```
This is the number of seconds to delay before attempting to respawn a
supervised process after it dies unexpectedly.
The default is to respawn immediately.
``` sh
respawn_max=x
```
This is the maximum number of times to respawn a supervised process
during the given respawn period. The default is unlimited.
``` sh
respawn_period=seconds
```
This works in conjunction with respawn_max and respawn_delay above to
decide if a process should not be respawned for some reason.
For example, if respawn_period is 60, respawn_max is 2 and respawn_delay
is 3 and a process dies more than 4 times, the process will not be
respawned and the supervisor will terminate.

View File

@@ -1,6 +1,6 @@
#!/bin/sh
top_srcdir=${top_srcdir:-../..}
top_srcdir=${top_srcdir:-..}
. ${top_srcdir}/test/setup_env.sh
libeinfo_srcdir="${srcdir}/../libeinfo"
@@ -20,52 +20,12 @@ checkit() {
ret=0
ebegin "Checking exported symbols in libeinfo.so (data)"
checkit einfo.data $(
readelf -Ws ${libeinfo_builddir}/libeinfo.so \
| awk '$4 == "OBJECT" && $5 == "GLOBAL" && $7 != "UND" {print $NF}' \
| LC_ALL=C sort -u
)
ebegin "Checking exported symbols in libeinfo.so (functions)"
checkit einfo.funcs $(
readelf -Ws ${libeinfo_builddir}/libeinfo.so \
| awk '$4 == "FUNC" && $5 == "GLOBAL" && $7 != "UND" {print $NF}' \
| LC_ALL=C sort -u \
| egrep -v \
-e '^_(init|fini)$'
)
ebegin "Checking exported symbols in librc.so (data)"
checkit rc.data $(
readelf -Ws ${librc_builddir}/librc.so \
| awk '$4 == "OBJECT" && $5 == "GLOBAL" && $7 != "UND" {print $NF}' \
| LC_ALL=C sort -u
)
ebegin "Checking exported symbols in librc.so (functions)"
checkit rc.funcs $(
readelf -Ws ${librc_builddir}/librc.so \
| awk '$4 == "FUNC" && $5 == "GLOBAL" && $7 != "UND" {print $NF}' \
| LC_ALL=C sort -u \
| egrep -v \
-e '^_(init|fini)$'
)
ebegin "Checking hidden functions in librc.so"
sed -n '/^librc_hidden_proto/s:.*(\(.*\))$:\1:p' ${librc_srcdir}/librc.h \
| LC_ALL=C sort -u \
> librc.funcs.hidden.list
readelf -Wr $(grep -l '#include[[:space:]]"librc\.h"' ${librc_srcdir}/*.c | sed 's:\.c$:.o:') \
| egrep -v -e 'R_PARISC_(DP|SEG)REL' \
| awk '$5 ~ /^rc_/ {print $5}' \
| LC_ALL=C sort -u \
| egrep -v '^rc_environ_fd$' \
> librc.funcs.hidden.out
syms=$(diff -u librc.funcs.hidden.list librc.funcs.hidden.out | sed -n '/^+[^+]/s:^+::p')
[ -z "${syms}" ]
eend $? "Missing hidden defs:"$'\n'"${syms}"
: $(( ret += $? ))
fail_on_out() {
if [ -n "${out}" ]; then
eerror "Last command failed; failing"
exit 1
fi
}
ebegin "Checking trailing whitespace in code"
# XXX: Should we check man pages too ?
@@ -74,6 +34,7 @@ out=$(cd ${top_srcdir}; find */ \
-exec grep -n -E '[[:space:]]+$' {} +)
[ -z "${out}" ]
eend $? "Trailing whitespace needs to be deleted:"$'\n'"${out}"
fail_on_out
ebegin "Checking trailing newlines in code"
out=$(cd ${top_srcdir};
@@ -82,6 +43,7 @@ out=$(cd ${top_srcdir};
done)
[ -z "${out}" ]
eend $? "Trailing newlines need to be deleted:"$'\n'"${out}"
fail_on_out
ebegin "Checking for obsolete functions"
out=$(cd ${top_srcdir}; find src -name '*.[ch]' \
@@ -89,6 +51,7 @@ out=$(cd ${top_srcdir}; find src -name '*.[ch]' \
-exec grep -n -E '\<(malloc|memory|sys/(errno|fcntl|signal|stropts|termios|unistd))\.h\>' {} +)
[ -z "${out}" ]
eend $? "Avoid these obsolete functions:"$'\n'"${out}"
fail_on_out
ebegin "Checking for x* func usage"
out=$(cd ${top_srcdir}; find src -name '*.[ch]' \
@@ -99,6 +62,7 @@ out=$(cd ${top_srcdir}; find src -name '*.[ch]' \
-e src/libeinfo/libeinfo.c)
[ -z "${out}" ]
eend $? "These need to be using the x* variant:"$'\n'"${out}"
fail_on_out
ebegin "Checking spacing style"
out=$(cd ${top_srcdir}; find src -name '*.[ch]' \
@@ -113,6 +77,7 @@ out=$(cd ${top_srcdir}; find src -name '*.[ch]' \
{} +)
[ -z "${out}" ]
eend $? "These lines violate style rules:"$'\n'"${out}"
fail_on_out
einfo "Running unit tests"
eindent

View File

@@ -1,5 +0,0 @@
#!/bin/sh
# top_srcdir=${top_srcdir:-SET/THIS/PATH/OK!?}
. ${top_srcdir}/test/setup_env.sh

View File

@@ -15,7 +15,6 @@
ret=0
tret=0
ebegin "Testing yesno()"
for f in yes YES Yes true TRUE True 1 ; do
if ! yesno $f; then
: $(( tret += 1 ))
@@ -28,7 +27,7 @@ for f in no NO No false FALSE False 0 ; do
echo "!$f!"
fi
done
eend $tret
: $(( ret += $tret ))
eend $ret
exit $ret

View File

@@ -1,27 +1,37 @@
#compdef rc-service
if (( CURRENT == 2 )); then
_arguments -s \
'(-e --exists)'{-e,--exists}"[tests if the service exists or not]" \
'(-l --list)'{-l,--list}'[list all available services]' \
'(-r --resolve)'{-r,--resolve}'[resolve the service name to an init script]' \
'(-C --nocolor)'{-C,--nocolor}'[Disable color output]' \
'(-v --verbose)'{-v,--verbose}'[Run verbosely]' \
'(-q --quiet)'{-q,--quiet}'[Run quietly]'
_values "service" $(rc-service --list)
else
case $words[2] in
-e|--exists|-r|--resolve)
(( CURRENT > 3 )) && return 0
_values "service" $(rc-service --list)
;;
-*)
return 0
;;
*)
_values "action" stop start restart describe zap
;;
esac
fi
_rc_services() {
if [[ -n "${opt_args[(i)-l|--list]}" ]]; then
_nothing
else
_values 'service' $(rc-service -l)
fi
}
_rc_actions() {
local service="${line[1]}"
if [[ -n "${opt_args[(i)-e|--exists|-r|--resolve]}" ]] || ! $(rc-service -e $service) ; then
_nothing
else
local -a actions=(${(f)"$(rc-service -C $service describe 2>&1)"})
shift actions
actions=(${actions# \* })
actions=(${actions/:*})
actions=(stop start restart describe zap ${actions[@]})
_describe -V 'action' actions
fi
}
_arguments -C -s \
'(-e --exists)'{-e,--exists}'[tests if the service exists or not]' \
'(-l --list)'{-l,--list}'[list all available services]' \
'(-r --resolve)'{-r,--resolve}'[resolve the service name to an init script]' \
'(-C --nocolor)'{-C,--nocolor}'[Disable color output]' \
'(-v --verbose)'{-v,--verbose}'[Run verbosely]' \
'(-q --quiet)'{-q,--quiet}'[Run quietly]' \
'1:service:_rc_services' \
'2:action:_rc_actions'
# vim: set et sw=2 ts=2 ft=zsh: