Compare commits

..

7 Commits

Author SHA1 Message Date
William Hubbs
ac76b24b85 Update ChangeLog 2018-12-06 17:40:06 -06:00
William Hubbs
b8e57c693a 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:56:20 -06:00
William Hubbs
5df12e2414 supervise-daemon: fix busy loop
This fixes #264.
2018-12-06 16:56:20 -06:00
William Hubbs
461df0c78b version 0.40.2 2018-12-06 16:55:51 -06:00
William Hubbs
cefae65392 Update ChangeLog 2018-12-04 17:27:46 -06:00
Alexander Zubkov
69fbd12993 supervise-daemon: redirect std{in,out,err} to /dev/null after demonizing
This fixes #239.
2018-12-04 17:23:27 -06:00
William Hubbs
4aa5686d90 version 0.40.1 2018-12-04 17:21:55 -06:00
76 changed files with 1734 additions and 1359 deletions

View File

@@ -1,15 +0,0 @@
# 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

View File

@@ -9,20 +9,6 @@ os:
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
- ./test/travis.sh

View File

@@ -82,7 +82,6 @@ Semen Maryasin <marsoft@ya.ru>
Sergei Trofimovich <slyfox@gentoo.org>
Seth Robertson <in-gentoo@baka.org>
S. Gilles <sgilles@umd.edu>
Sony Interactive Entertainment, llc.
Stefan Knoblich <s.knoblich@axsentis.de>
Stef Simoens <stef.simoens@scarlet.be>
Steve L <slong@rathaus.eclipse.co.uk>

1639
ChangeLog

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -1,3 +1,3 @@
NAME= openrc
VERSION= 0.42.1
VERSION= 0.40.2
PKG= ${NAME}-${VERSION}

19
NEWS.md
View File

@@ -4,25 +4,6 @@ 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.42
openrc-shutdown now has the ability to shut down sysvinit-based systems.
A guide has been added for migrating systems using another init system
to openrc-init.
## 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

View File

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

View File

@@ -91,14 +91,11 @@ _rc_service()
done))
return 0
elif [[ ${COMP_CWORD} -eq 2 ]] && [[ ${prev} != -* ]]; then # if second word typed and we didn't type in a function
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
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
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi

View File

@@ -1,21 +0,0 @@
#!/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

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!@SHELL@
# 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 @@
#!/bin/sh
#!@SHELL@
# 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,50 +0,0 @@
# OpenRC init process guide
OpenRC now includes an init process which can be used on Linux systems
in place of sysvinit.
## migrating a live system to openrc-init
Configuring a live system to use this init process is very
straight-forward, but the steps must be completed in this order.
* have your boot loader add "init=/sbin/openrc-init" to the kernel command line
The details of how to do this will vary from distro to distro, so they are
out of scope for this document.
* Install gettys into the runlevels where you need them.
If you are using the provided /etc/init.d/agetty script,, you should
first create symlinks in /etc/init.d to it for the ports where you
want gettys to run, e.g. the following will work if you want gettys on
tty1-tty6.
```
# cd /etc/init.d
# for x in tty1 tty2 tty3 tty4 tty5 tty6; do
ln -snf agetty agetty.$x
done
```
Once this is done, use ```rc-update``` as normal to install the agetty
services in the appropriate runlevels.
* Reboot your system.
At this point you are running under openrc-init, and you should use
openrc-shutdown to handle shutting down, powering off, rebooting etc.
## optional sysvinit compatibility
If you build and install OpenRC with MKSYSVINIT=yes, you will build and install
wrappers that make openrc-init compatible with sysvinit -- you will have
commands like "halt" "shutdown" "reboot" and "poweroff".
If you want this functionality on a live system, you should first
migrate the system to openrc-init, remove sysvinit, then rebuild and
install this package with MKSYSVINIT=yes.
package.
migrating your system to openrc-init.

View File

@@ -21,7 +21,6 @@ pidfile="/run/${RC_SVCNAME}.pid"
depend() {
after local
keyword -prefix
provide getty
}
start_pre() {

View File

@@ -17,35 +17,15 @@
.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
time
.Nm
.Op Fl d , -no-write
.Op Fl D , -dry-run
.Op Fl R , -reexec
.Op Fl r , -reboot
time
.Nm
.Op Fl d , -no-write
.Op Fl D , -dry-run
.Op Fl s , -single
time
.Op Fl w , -write-only
.Sh DESCRIPTION
.Nm
is the utility that communicates with
@@ -76,7 +56,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
Wrrite a wtmp shutdown record and do nothing else.
Stop all services, kill all processes and move to single user mode.
.El
.Sh SEE ALSO
.Xr openrc-init 8 ,

View File

@@ -66,7 +66,6 @@ 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,7 +17,6 @@
.Sh SYNOPSIS
.Nm
.Op Fl aclsuC
.Op Fl f Ar ini
.Op Ar runlevel
.Sh DESCRIPTION
.Nm
@@ -38,9 +37,6 @@ 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

View File

@@ -9,7 +9,7 @@
.\" 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
@@ -88,17 +88,16 @@ 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
.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
.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.

View File

@@ -11,7 +11,7 @@
SFX= .Linux.in
PKG_PREFIX?= /usr
CPPFLAGS+= -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L -D_BSD_SOURCE -D_XOPEN_SOURCE
CPPFLAGS+= -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L
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}:' -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}: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}
# Tweak our shell scripts
%.sh: %.sh.in
@@ -53,6 +53,7 @@ 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

@@ -90,12 +90,6 @@ install:
fi; \
ln -snf ${INITDIR}/"$$x" ${SHUTDOWNDIR}/"$$x" || exit $$?; done \
fi
if test "${MKSYSVINIT}" = yes && test "${OS}" = Linux; then \
for x in tty1 tty2 tty3 tty4 tty5 tty6; do \
ln -snf ${INITDIR}/agetty ${DESTDIR}/${INITDIR}/"agetty.$$x" || exit $$?; \
ln -snf ${INITDIR}/agetty.$$x ${DEFAULTDIR}/"agetty.$$x" || exit $$?; \
done; \
fi
check test::

View File

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

View File

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

View File

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

View File

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

2
sh/.gitignore vendored
View File

@@ -4,4 +4,6 @@ openrc-run.sh
cgroup-release-agent.sh
init.sh
init-early.sh
rc-cgroup.sh
migrate-to-run.sh
binfmt.sh

View File

@@ -2,7 +2,7 @@ DIR= ${LIBEXECDIR}/sh
SRCS= init.sh.in functions.sh.in gendepends.sh.in \
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 ${INC-${OS}}
start-stop-daemon.sh supervise-daemon.sh
BIN= gendepends.sh init.sh openrc-run.sh ${BIN-${OS}}
INSTALLAFTER= _installafter
@@ -13,9 +13,10 @@ include ${MK}/os.mk
SRCS-FreeBSD=
BIN-FreeBSD=
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-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-NetBSD=
BIN-NetBSD=
@@ -31,3 +32,4 @@ _installafter:
ln -snf ${LIBEXECDIR}/sh/functions.sh ${DESTDIR}/${INITDIR} || exit $$?
check test::
./runtests.sh

View File

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

View File

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

View File

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

36
sh/migrate-to-run.sh.in Normal file
View File

@@ -0,0 +1,36 @@
#!@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,3 +1,4 @@
#!@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

View File

@@ -15,6 +15,7 @@
ret=0
tret=0
ebegin "Testing yesno()"
for f in yes YES Yes true TRUE True 1 ; do
if ! yesno $f; then
: $(( tret += 1 ))
@@ -27,7 +28,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,7 +1,7 @@
# Copyright (c) 2007-2008 Roy Marples <roy@marples.name>
# Released under the 2-clause BSD license.
SUBDIR= libeinfo librc rc
SUBDIR= test libeinfo librc rc
MK= ../mk
include ${MK}/subdir.mk

View File

@@ -0,0 +1,26 @@
/*
* Written by Mike Frysinger
* Placed in the Public Domain
*/
#ifndef _HIDDEN_VISIBILITY_H_
#define _HIDDEN_VISIBILITY_H_
#if defined(__ELF__) && defined(__GNUC__)
# define __hidden_asmname(name) __hidden_asmname1 (__USER_LABEL_PREFIX__, name)
# define __hidden_asmname1(prefix, name) __hidden_asmname2(prefix, name)
# define __hidden_asmname2(prefix, name) #prefix name
# define __hidden_proto(name, internal) \
extern __typeof (name) name __asm__ (__hidden_asmname (#internal)) \
__attribute__ ((visibility ("hidden")));
# define __hidden_ver(local, internal, name) \
extern __typeof (name) __EI_##name __asm__(__hidden_asmname (#internal)); \
extern __typeof (name) __EI_##name __attribute__((alias (__hidden_asmname1 (,#local))))
# define hidden_proto(name) __hidden_proto(name, __RC_##name)
# define hidden_def(name) __hidden_ver(__RC_##name, name, name);
#else
# define hidden_proto(name)
# define hidden_def(name)
#endif
#endif

View File

@@ -15,7 +15,7 @@
* except according to the terms contained in the LICENSE file.
*/
static const char libeinfo_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
const char libeinfo_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#include <sys/types.h>
#include <sys/ioctl.h>
@@ -39,6 +39,34 @@ static const char libeinfo_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#include "einfo.h"
#include "helpers.h"
#include "hidden-visibility.h"
hidden_proto(ecolor)
hidden_proto(ebegin)
hidden_proto(ebeginv)
hidden_proto(ebracket)
hidden_proto(eend)
hidden_proto(eendv)
hidden_proto(eerror)
hidden_proto(eerrorn)
hidden_proto(eerrorx)
hidden_proto(eindent)
hidden_proto(eindentv)
hidden_proto(einfo)
hidden_proto(einfon)
hidden_proto(einfov)
hidden_proto(einfovn)
hidden_proto(elog)
hidden_proto(eoutdent)
hidden_proto(eoutdentv)
hidden_proto(eprefix)
hidden_proto(ewarn)
hidden_proto(ewarnn)
hidden_proto(ewarnv)
hidden_proto(ewarnvn)
hidden_proto(ewarnx)
hidden_proto(ewend)
hidden_proto(ewendv)
/* Incase we cannot work out how many columns from ioctl, supply a default */
#define DEFAULT_COLS 80
@@ -482,6 +510,7 @@ eprefix(const char *EINFO_RESTRICT prefix)
{
_eprefix = prefix;
}
hidden_def(eprefix)
static void EINFO_PRINTF(2, 0)
elogv(int level, const char *EINFO_RESTRICT fmt, va_list ap)
@@ -508,6 +537,7 @@ elog(int level, const char *EINFO_RESTRICT fmt, ...)
elogv(level, fmt, ap);
va_end(ap);
}
hidden_def(elog)
static int
_eindent(FILE * EINFO_RESTRICT stream)
@@ -546,6 +576,7 @@ _ecolor(FILE * EINFO_RESTRICT f, ECOLOR color)
return ecolors_str[i];
return "";
}
hidden_def(ecolor)
const char *
ecolor(ECOLOR color)
@@ -612,6 +643,7 @@ einfon(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("einfon");
return retval;
}
hidden_def(einfon)
int
ewarnn(const char *EINFO_RESTRICT fmt, ...)
@@ -627,6 +659,7 @@ ewarnn(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("ewarnn");
return retval;
}
hidden_def(ewarnn)
int
eerrorn(const char *EINFO_RESTRICT fmt, ...)
@@ -642,6 +675,7 @@ eerrorn(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("errorn");
return retval;
}
hidden_def(eerrorn)
int
einfo(const char *EINFO_RESTRICT fmt, ...)
@@ -658,6 +692,7 @@ einfo(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("einfo");
return retval;
}
hidden_def(einfo)
int
ewarn(const char *EINFO_RESTRICT fmt, ...)
@@ -675,6 +710,7 @@ ewarn(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("ewarn");
return retval;
}
hidden_def(ewarn)
void
ewarnx(const char *EINFO_RESTRICT fmt, ...)
@@ -691,6 +727,7 @@ ewarnx(const char *EINFO_RESTRICT fmt, ...)
}
exit(EXIT_FAILURE);
}
hidden_def(ewarnx)
int
eerror(const char *EINFO_RESTRICT fmt, ...)
@@ -708,6 +745,7 @@ eerror(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("eerror");
return retval;
}
hidden_def(eerror)
void
eerrorx(const char *EINFO_RESTRICT fmt, ...)
@@ -723,6 +761,7 @@ eerrorx(const char *EINFO_RESTRICT fmt, ...)
}
exit(EXIT_FAILURE);
}
hidden_def(eerrorx)
int
ebegin(const char *EINFO_RESTRICT fmt, ...)
@@ -741,6 +780,7 @@ ebegin(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("ebegin");
return retval;
}
hidden_def(ebegin)
static void
_eend(FILE * EINFO_RESTRICT fp, int col, ECOLOR color, const char *msg)
@@ -814,6 +854,7 @@ eend(int retval, const char *EINFO_RESTRICT fmt, ...)
LASTCMD("eend");
return retval;
}
hidden_def(eend)
int
ewend(int retval, const char *EINFO_RESTRICT fmt, ...)
@@ -828,12 +869,14 @@ ewend(int retval, const char *EINFO_RESTRICT fmt, ...)
LASTCMD("ewend");
return retval;
}
hidden_def(ewend)
void
ebracket(int col, ECOLOR color, const char *msg)
{
_eend(stdout, col, color, msg);
}
hidden_def(ebracket)
void
eindent(void)
@@ -855,6 +898,7 @@ eindent(void)
setenv("EINFO_INDENT", num, 1);
free(num);
}
hidden_def(eindent)
void eoutdent(void)
{
@@ -880,6 +924,7 @@ void eoutdent(void)
}
errno = serrno;
}
hidden_def(eoutdent)
int
einfovn(const char *EINFO_RESTRICT fmt, ...)
@@ -895,6 +940,7 @@ einfovn(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("einfovn");
return retval;
}
hidden_def(einfovn)
int
ewarnvn(const char *EINFO_RESTRICT fmt, ...)
@@ -910,6 +956,7 @@ ewarnvn(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("ewarnvn");
return retval;
}
hidden_def(ewarnvn)
int
einfov(const char *EINFO_RESTRICT fmt, ...)
@@ -926,6 +973,7 @@ einfov(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("einfov");
return retval;
}
hidden_def(einfov)
int
ewarnv(const char *EINFO_RESTRICT fmt, ...)
@@ -942,6 +990,7 @@ ewarnv(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("ewarnv");
return retval;
}
hidden_def(ewarnv)
int
ebeginv(const char *EINFO_RESTRICT fmt, ...)
@@ -961,6 +1010,7 @@ ebeginv(const char *EINFO_RESTRICT fmt, ...)
LASTCMD("ebeginv");
return retval;
}
hidden_def(ebeginv)
int
eendv(int retval, const char *EINFO_RESTRICT fmt, ...)
@@ -975,6 +1025,7 @@ eendv(int retval, const char *EINFO_RESTRICT fmt, ...)
LASTCMD("eendv");
return retval;
}
hidden_def(eendv)
int
ewendv(int retval, const char *EINFO_RESTRICT fmt, ...)
@@ -989,6 +1040,7 @@ ewendv(int retval, const char *EINFO_RESTRICT fmt, ...)
LASTCMD("ewendv");
return retval;
}
hidden_def(ewendv)
void
eindentv(void)
@@ -996,6 +1048,7 @@ eindentv(void)
if (is_verbose())
eindent();
}
hidden_def(eindentv)
void
eoutdentv(void)
@@ -1003,3 +1056,4 @@ eoutdentv(void)
if (is_verbose())
eoutdent();
}
hidden_def(eoutdentv)

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) - 1);
bytes = read(fd, buffer, sizeof(buffer));
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)-1);
rc = readlink("/proc/self/ns/pid", my_ns, sizeof(my_ns));
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)-1);
rc = readlink(buffer, proc_ns, sizeof(proc_ns));
if (rc <= 0)
proc_ns[0] = '\0';
}
@@ -208,6 +208,7 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
closedir(procdir);
return pids;
}
librc_hidden_def(rc_find_pids)
#elif BSD
@@ -312,6 +313,7 @@ rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
return pids;
}
librc_hidden_def(rc_find_pids)
#else
# error "Platform not supported!"
@@ -453,6 +455,7 @@ rc_service_daemon_set(const char *service, const char *exec,
free(dirpath);
return retval;
}
librc_hidden_def(rc_service_daemon_set)
bool
rc_service_started_daemon(const char *service,
@@ -492,6 +495,7 @@ rc_service_started_daemon(const char *service,
free(dirpath);
return retval;
}
librc_hidden_def(rc_service_started_daemon)
bool
rc_service_daemons_crashed(const char *service)
@@ -611,7 +615,7 @@ rc_service_daemons_crashed(const char *service)
i = 0;
TAILQ_FOREACH(s, list, entries)
argv[i++] = s->value;
argv[i] = NULL;
argv[i] = '\0';
}
}
@@ -649,3 +653,4 @@ rc_service_daemons_crashed(const char *service)
return retval;
}
librc_hidden_def(rc_service_daemons_crashed)

View File

@@ -78,16 +78,16 @@ rc_deptree_free(RC_DEPTREE *deptree)
}
free(deptree);
}
librc_hidden_def(rc_deptree_free)
static RC_DEPINFO *
get_depinfo(const RC_DEPTREE *deptree, const char *service)
{
RC_DEPINFO *di;
if (deptree) {
TAILQ_FOREACH(di, deptree, entries)
if (strcmp(di->service, service) == 0)
return di;
}
TAILQ_FOREACH(di, deptree, entries)
if (strcmp(di->service, service) == 0)
return di;
return NULL;
}
@@ -96,11 +96,9 @@ get_deptype(const RC_DEPINFO *depinfo, const char *type)
{
RC_DEPTYPE *dt;
if (depinfo) {
TAILQ_FOREACH(dt, &depinfo->depends, entries)
if (strcmp(dt->type, type) == 0)
return dt;
}
TAILQ_FOREACH(dt, &depinfo->depends, entries)
if (strcmp(dt->type, type) == 0)
return dt;
return NULL;
}
@@ -108,6 +106,7 @@ RC_DEPTREE *
rc_deptree_load(void) {
return rc_deptree_load_file(RC_DEPTREE_CACHE);
}
librc_hidden_def(rc_deptree_load)
RC_DEPTREE *
rc_deptree_load_file(const char *deptree_file)
@@ -171,6 +170,7 @@ rc_deptree_load_file(const char *deptree_file)
return deptree;
}
librc_hidden_def(rc_deptree_load_file)
static bool
valid_service(const char *runlevel, const char *service, const char *type)
@@ -456,6 +456,7 @@ rc_deptree_depend(const RC_DEPTREE *deptree,
rc_stringlist_add(svcs, svc->value);
return svcs;
}
librc_hidden_def(rc_deptree_depend)
RC_STRINGLIST *
rc_deptree_depends(const RC_DEPTREE *deptree,
@@ -483,6 +484,7 @@ rc_deptree_depends(const RC_DEPTREE *deptree,
rc_stringlist_free(visited);
return sorted;
}
librc_hidden_def(rc_deptree_depends)
RC_STRINGLIST *
rc_deptree_order(const RC_DEPTREE *deptree, const char *runlevel, int options)
@@ -538,6 +540,7 @@ rc_deptree_order(const RC_DEPTREE *deptree, const char *runlevel, int options)
rc_stringlist_free(types);
return services;
}
librc_hidden_def(rc_deptree_order)
/* Given a time, recurse the target path to find out if there are
@@ -613,11 +616,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
@@ -627,6 +630,7 @@ rc_newer_than(const char *source, const char *target,
return mtime_check(source, target, true, newest, file);
}
librc_hidden_def(rc_newer_than)
bool
rc_older_than(const char *source, const char *target,
@@ -634,6 +638,7 @@ rc_older_than(const char *source, const char *target,
{
return mtime_check(source, target, false, oldest, file);
}
librc_hidden_def(rc_older_than)
typedef struct deppair
{
@@ -729,6 +734,7 @@ rc_deptree_update_needed(time_t *newest, char *file)
return newer;
}
librc_hidden_def(rc_deptree_update_needed)
/* This is a 7 phase operation
Phase 1 is a shell script which loads each init script and config in turn
@@ -1075,3 +1081,4 @@ rc_deptree_update(void)
rc_deptree_free(deptree);
return retval;
}
librc_hidden_def(rc_deptree_update)

View File

@@ -43,6 +43,7 @@ rc_yesno(const char *value)
return false;
}
librc_hidden_def(rc_yesno)
/**
@@ -90,6 +91,7 @@ rc_getfile(const char *file, char **buffer, size_t *len)
fclose(fp);
return ret;
}
librc_hidden_def(rc_getfile)
ssize_t
rc_getline(char **line, size_t *len, FILE *fp)
@@ -114,6 +116,7 @@ rc_getline(char **line, size_t *len, FILE *fp)
}
return last;
}
librc_hidden_def(rc_getline)
char *
rc_proc_getent(const char *ent _unused)
@@ -160,6 +163,7 @@ rc_proc_getent(const char *ent _unused)
return NULL;
#endif
}
librc_hidden_def(rc_proc_getent)
RC_STRINGLIST *
rc_config_list(const char *file)
@@ -198,6 +202,7 @@ rc_config_list(const char *file)
return list;
}
librc_hidden_def(rc_config_list)
static void rc_config_set_value(RC_STRINGLIST *config, char *value)
{
@@ -272,6 +277,7 @@ 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();
@@ -289,6 +295,7 @@ static RC_STRINGLIST *rc_config_kcl(RC_STRINGLIST *config)
}
if (value != NULL) {
len = varlen + strlen(value) + 2;
xasprintf(&tmp, "%s=%s", override->value, value);
}
@@ -368,6 +375,7 @@ rc_config_load(const char *file)
return config;
}
librc_hidden_def(rc_config_load)
char *
rc_config_value(RC_STRINGLIST *list, const char *entry)
@@ -386,6 +394,7 @@ rc_config_value(RC_STRINGLIST *list, const char *entry)
}
return NULL;
}
librc_hidden_def(rc_config_value)
/* Global for caching the strings loaded from rc.conf to avoid reparsing for
* each rc_conf_value call */
@@ -416,7 +425,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) {
@@ -431,3 +440,4 @@ rc_conf_value(const char *setting)
return rc_config_value(rc_conf, setting);
}
librc_hidden_def(rc_conf_value)

View File

@@ -25,6 +25,7 @@ rc_stringlist_new(void)
TAILQ_INIT(l);
return l;
}
librc_hidden_def(rc_stringlist_new)
RC_STRING *
rc_stringlist_add(RC_STRINGLIST *list, const char *value)
@@ -35,6 +36,7 @@ rc_stringlist_add(RC_STRINGLIST *list, const char *value)
TAILQ_INSERT_TAIL(list, s, entries);
return s;
}
librc_hidden_def(rc_stringlist_add)
RC_STRING *
rc_stringlist_addu(RC_STRINGLIST *list, const char *value)
@@ -49,6 +51,7 @@ rc_stringlist_addu(RC_STRINGLIST *list, const char *value)
return rc_stringlist_add(list, value);
}
librc_hidden_def(rc_stringlist_addu)
bool
rc_stringlist_delete(RC_STRINGLIST *list, const char *value)
@@ -66,6 +69,7 @@ rc_stringlist_delete(RC_STRINGLIST *list, const char *value)
errno = EEXIST;
return false;
}
librc_hidden_def(rc_stringlist_delete)
RC_STRING *
rc_stringlist_find(RC_STRINGLIST *list, const char *value)
@@ -79,6 +83,7 @@ rc_stringlist_find(RC_STRINGLIST *list, const char *value)
}
return NULL;
}
librc_hidden_def(rc_stringlist_find)
RC_STRINGLIST *
rc_stringlist_split(const char *value, const char *sep)
@@ -93,6 +98,7 @@ rc_stringlist_split(const char *value, const char *sep)
return list;
}
librc_hidden_def(rc_stringlist_split)
void
rc_stringlist_sort(RC_STRINGLIST **list)
@@ -122,6 +128,7 @@ rc_stringlist_sort(RC_STRINGLIST **list)
free(l);
*list = new;
}
librc_hidden_def(rc_stringlist_sort)
void
rc_stringlist_free(RC_STRINGLIST *list)
@@ -141,3 +148,4 @@ rc_stringlist_free(RC_STRINGLIST *list)
}
free(list);
}
librc_hidden_def(rc_stringlist_free)

View File

@@ -15,7 +15,7 @@
* except according to the terms contained in the LICENSE file.
*/
static const char librc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
const char librc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#include "queue.h"
#include "librc.h"
@@ -351,6 +351,7 @@ rc_sys(void)
return sys;
}
librc_hidden_def(rc_sys)
static const char *
rc_parse_service_state(RC_SERVICE state)
@@ -425,17 +426,20 @@ rc_runlevel_starting(void)
{
return exists(RC_STARTING);
}
librc_hidden_def(rc_runlevel_starting)
bool
rc_runlevel_stopping(void)
{
return exists(RC_STOPPING);
}
librc_hidden_def(rc_runlevel_stopping)
RC_STRINGLIST *rc_runlevel_list(void)
{
return ls_dir(RC_RUNLEVELDIR, LS_DIR);
}
librc_hidden_def(rc_runlevel_list)
char *
rc_runlevel_get(void)
@@ -462,6 +466,7 @@ rc_runlevel_get(void)
return runlevel;
}
librc_hidden_def(rc_runlevel_get)
bool
rc_runlevel_set(const char *runlevel)
@@ -474,6 +479,7 @@ rc_runlevel_set(const char *runlevel)
fclose(fp);
return true;
}
librc_hidden_def(rc_runlevel_set)
bool
rc_runlevel_exists(const char *runlevel)
@@ -488,6 +494,7 @@ rc_runlevel_exists(const char *runlevel)
return true;
return false;
}
librc_hidden_def(rc_runlevel_exists)
bool
rc_runlevel_stack(const char *dst, const char *src)
@@ -500,6 +507,7 @@ rc_runlevel_stack(const char *dst, const char *src)
snprintf(d, sizeof(s), "%s/%s/%s", RC_RUNLEVELDIR, dst, src);
return (symlink(s, d) == 0 ? true : false);
}
librc_hidden_def(rc_runlevel_stack)
bool
rc_runlevel_unstack(const char *dst, const char *src)
@@ -509,6 +517,7 @@ rc_runlevel_unstack(const char *dst, const char *src)
snprintf(path, sizeof(path), "%s/%s/%s", RC_RUNLEVELDIR, dst, src);
return (unlink(path) == 0 ? true : false);
}
librc_hidden_def(rc_runlevel_unstack)
RC_STRINGLIST *
rc_runlevel_stacks(const char *runlevel)
@@ -521,6 +530,7 @@ rc_runlevel_stacks(const char *runlevel)
rc_stringlist_free(ancestor_list);
return stack;
}
librc_hidden_def(rc_runlevel_stacks)
/* Resolve a service name to its full path */
char *
@@ -548,7 +558,7 @@ rc_service_resolve(const char *service)
if (*file) {
memset(buffer, 0, sizeof(buffer));
r = readlink(file, buffer, sizeof(buffer)-1);
r = readlink(file, buffer, sizeof(buffer));
if (r > 0)
return xstrdup(buffer);
}
@@ -574,6 +584,7 @@ rc_service_resolve(const char *service)
return NULL;
}
librc_hidden_def(rc_service_resolve)
bool
rc_service_exists(const char *service)
@@ -612,6 +623,7 @@ rc_service_exists(const char *service)
free(file);
return retval;
}
librc_hidden_def(rc_service_exists)
#define OPTSTR \
". '%s'; echo $extra_commands $extra_started_commands $extra_stopped_commands"
@@ -653,6 +665,7 @@ rc_service_extra_commands(const char *service)
free(cmd);
return commands;
}
librc_hidden_def(rc_service_extra_commands)
#define DESCSTR ". '%s'; echo \"${description%s%s}\""
char *
@@ -682,6 +695,7 @@ rc_service_description(const char *service, const char *option)
free(cmd);
return desc;
}
librc_hidden_def(rc_service_description)
bool
rc_service_in_runlevel(const char *service, const char *runlevel)
@@ -692,6 +706,7 @@ rc_service_in_runlevel(const char *service, const char *runlevel)
runlevel, basename_c(service));
return exists(file);
}
librc_hidden_def(rc_service_in_runlevel)
bool
rc_service_mark(const char *service, const RC_SERVICE state)
@@ -811,6 +826,7 @@ rc_service_mark(const char *service, const RC_SERVICE state)
free(init);
return true;
}
librc_hidden_def(rc_service_mark)
RC_SERVICE
rc_service_state(const char *service)
@@ -853,6 +869,7 @@ rc_service_state(const char *service)
return state;
}
librc_hidden_def(rc_service_state)
char *
rc_service_value_get(const char *service, const char *option)
@@ -867,6 +884,7 @@ rc_service_value_get(const char *service, const char *option)
return buffer;
}
librc_hidden_def(rc_service_value_get)
bool
rc_service_value_set(const char *service, const char *option,
@@ -891,6 +909,7 @@ rc_service_value_set(const char *service, const char *option,
}
return true;
}
librc_hidden_def(rc_service_value_set)
bool
@@ -917,6 +936,7 @@ rc_service_schedule_start(const char *service, const char *service_to_start)
free(init);
return retval;
}
librc_hidden_def(rc_service_schedule_start)
bool
rc_service_schedule_clear(const char *service)
@@ -929,6 +949,7 @@ rc_service_schedule_clear(const char *service)
return true;
return false;
}
librc_hidden_def(rc_service_schedule_clear)
RC_STRINGLIST *
rc_services_in_runlevel(const char *runlevel)
@@ -966,6 +987,7 @@ rc_services_in_runlevel(const char *runlevel)
list = rc_stringlist_new();
return list;
}
librc_hidden_def(rc_services_in_runlevel)
RC_STRINGLIST *
rc_services_in_runlevel_stacked(const char *runlevel)
@@ -982,6 +1004,7 @@ rc_services_in_runlevel_stacked(const char *runlevel)
}
return list;
}
librc_hidden_def(rc_services_in_runlevel_stacked)
RC_STRINGLIST *
rc_services_in_state(RC_SERVICE state)
@@ -1015,6 +1038,7 @@ rc_services_in_state(RC_SERVICE state)
rc_stringlist_free(dirs);
return list;
}
librc_hidden_def(rc_services_in_state)
bool
rc_service_add(const char *runlevel, const char *service)
@@ -1023,6 +1047,7 @@ 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;
@@ -1043,7 +1068,8 @@ 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) {
if (realpath(dirname(init), path) == NULL) {
p = realpath(dirname(init), path);
if (!*p) {
free(init);
return false;
}
@@ -1060,6 +1086,7 @@ rc_service_add(const char *runlevel, const char *service)
free(init);
return retval;
}
librc_hidden_def(rc_service_add)
bool
rc_service_delete(const char *runlevel, const char *service)
@@ -1072,6 +1099,7 @@ rc_service_delete(const char *runlevel, const char *service)
return true;
return false;
}
librc_hidden_def(rc_service_delete)
RC_STRINGLIST *
rc_services_scheduled_by(const char *service)
@@ -1090,6 +1118,7 @@ rc_services_scheduled_by(const char *service)
rc_stringlist_free(dirs);
return list;
}
librc_hidden_def(rc_services_scheduled_by)
RC_STRINGLIST *
rc_services_scheduled(const char *service)
@@ -1100,3 +1129,4 @@ rc_services_scheduled(const char *service)
basename_c(service));
return ls_dir(dir, LS_INITD);
}
librc_hidden_def(rc_services_scheduled)

View File

@@ -56,4 +56,67 @@
#include "rc.h"
#include "rc-misc.h"
#include "hidden-visibility.h"
#define librc_hidden_proto(x) hidden_proto(x)
#define librc_hidden_def(x) hidden_def(x)
librc_hidden_proto(rc_conf_value)
librc_hidden_proto(rc_config_list)
librc_hidden_proto(rc_config_load)
librc_hidden_proto(rc_config_value)
librc_hidden_proto(rc_deptree_depend)
librc_hidden_proto(rc_deptree_depends)
librc_hidden_proto(rc_deptree_free)
librc_hidden_proto(rc_deptree_load)
librc_hidden_proto(rc_deptree_load_file)
librc_hidden_proto(rc_deptree_order)
librc_hidden_proto(rc_deptree_update)
librc_hidden_proto(rc_deptree_update_needed)
librc_hidden_proto(rc_find_pids)
librc_hidden_proto(rc_getfile)
librc_hidden_proto(rc_getline)
librc_hidden_proto(rc_newer_than)
librc_hidden_proto(rc_proc_getent)
librc_hidden_proto(rc_older_than)
librc_hidden_proto(rc_runlevel_exists)
librc_hidden_proto(rc_runlevel_get)
librc_hidden_proto(rc_runlevel_list)
librc_hidden_proto(rc_runlevel_set)
librc_hidden_proto(rc_runlevel_stack)
librc_hidden_proto(rc_runlevel_stacks)
librc_hidden_proto(rc_runlevel_starting)
librc_hidden_proto(rc_runlevel_stopping)
librc_hidden_proto(rc_runlevel_unstack)
librc_hidden_proto(rc_service_add)
librc_hidden_proto(rc_service_daemons_crashed)
librc_hidden_proto(rc_service_daemon_set)
librc_hidden_proto(rc_service_delete)
librc_hidden_proto(rc_service_description)
librc_hidden_proto(rc_service_exists)
librc_hidden_proto(rc_service_extra_commands)
librc_hidden_proto(rc_service_in_runlevel)
librc_hidden_proto(rc_service_mark)
librc_hidden_proto(rc_service_resolve)
librc_hidden_proto(rc_service_schedule_clear)
librc_hidden_proto(rc_service_schedule_start)
librc_hidden_proto(rc_services_in_runlevel)
librc_hidden_proto(rc_services_in_runlevel_stacked)
librc_hidden_proto(rc_services_in_state)
librc_hidden_proto(rc_services_scheduled)
librc_hidden_proto(rc_services_scheduled_by)
librc_hidden_proto(rc_service_started_daemon)
librc_hidden_proto(rc_service_state)
librc_hidden_proto(rc_service_value_get)
librc_hidden_proto(rc_service_value_set)
librc_hidden_proto(rc_stringlist_add)
librc_hidden_proto(rc_stringlist_addu)
librc_hidden_proto(rc_stringlist_delete)
librc_hidden_proto(rc_stringlist_find)
librc_hidden_proto(rc_stringlist_free)
librc_hidden_proto(rc_stringlist_new)
librc_hidden_proto(rc_stringlist_split)
librc_hidden_proto(rc_stringlist_sort)
librc_hidden_proto(rc_sys)
librc_hidden_proto(rc_yesno)
#endif

View File

@@ -14,8 +14,7 @@ SRCS+= rc-selinux.c
endif
ifeq (${OS},Linux)
SRCS+= kill_all.c openrc-init.c openrc-shutdown.c rc-sysvinit.c broadcast.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
@@ -113,7 +112,7 @@ veinfo vewarn vebegin veend vewend veindent veoutdent: do_e.o rc-misc.o
fstabinfo: fstabinfo.o _usage.o rc-misc.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
openrc-init: openrc-init.o rc-plugin.o rc-wtmp.o
openrc-init: openrc-init.o rc-wtmp.o
${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LDADD}
is_newer_than: is_newer_than.o rc-misc.o
@@ -135,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 rc-misc.o _usage.o broadcast.o rc-wtmp.o rc-sysvinit.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

View File

@@ -37,6 +37,10 @@
# define _PATH_DEV "/dev/"
#endif
#ifndef UT_LINESIZE
#define UT_LINESIZE __UT_LINESIZE
#endif
static sigjmp_buf jbuf;
/*
@@ -58,7 +62,7 @@ static void getuidtty(char **userp, char **ttyp)
uid_t uid;
char *tty;
static char uidbuf[32];
char *ttynm = NULL;
static char ttynm[UT_LINESIZE + 4];
uid = getuid();
if ((pwd = getpwuid(uid)) != NULL) {
@@ -78,8 +82,10 @@ static void getuidtty(char **userp, char **ttyp)
if (tty[0] == '/')
tty++;
}
xasprintf(&ttynm, "(%s) ", tty);
}
snprintf(ttynm, sizeof(ttynm), "(%.*s) ",
UT_LINESIZE, tty);
} else
ttynm[0] = 0;
*userp = uidbuf;
*ttyp = ttynm;
@@ -127,7 +133,7 @@ void broadcast(char *text)
char *p;
char *line = NULL;
struct sigaction sa;
volatile int fd;
int fd;
FILE *tp;
int flags;
char *term = NULL;
@@ -150,7 +156,6 @@ void broadcast(char *text)
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()

View File

@@ -35,9 +35,9 @@
const char *applet = NULL;
static int syslog_decode(char *name, const CODE *codetab)
static int syslog_decode(char *name, CODE *codetab)
{
const CODE *c;
CODE *c;
if (isdigit((unsigned char)*name))
return atoi(name);

View File

@@ -19,7 +19,6 @@
*/
#include <errno.h>
#include <pwd.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
@@ -38,52 +37,46 @@
#include "helpers.h"
#include "rc.h"
#include "rc-plugin.h"
#include "rc-wtmp.h"
#include "version.h"
static const char *path_default = "/sbin:/usr/sbin:/bin:/usr/bin";
static const char *rc_default_runlevel = "default";
static void do_openrc(const char *runlevel)
static pid_t do_openrc(const char *runlevel)
{
pid_t pid;
sigset_t all_signals;
sigset_t our_signals;
sigset_t signals;
sigfillset(&all_signals);
/* block all signals */
sigprocmask(SIG_BLOCK, &all_signals, &our_signals);
pid = fork();
switch (pid) {
case -1:
perror("fork");
exit(1);
break;
case 0:
setsid();
/* unblock all signals */
sigprocmask(SIG_UNBLOCK, &all_signals, NULL);
sigemptyset(&signals);
sigprocmask(SIG_SETMASK, &signals, NULL);
printf("Starting %s runlevel\n", runlevel);
execlp("openrc", "openrc", runlevel, NULL);
perror("exec");
exit(1);
break;
default:
/* restore our signal mask */
sigprocmask(SIG_SETMASK, &our_signals, NULL);
while (waitpid(pid, NULL, 0) != pid)
if (errno == ECHILD)
break;
break;
}
return pid;
}
static void init(const char *default_runlevel)
{
const char *runlevel = NULL;
do_openrc("sysinit");
do_openrc("boot");
pid_t pid;
pid = do_openrc("sysinit");
waitpid(pid, NULL, 0);
pid = do_openrc("boot");
waitpid(pid, NULL, 0);
if (default_runlevel)
runlevel = default_runlevel;
else
@@ -94,7 +87,8 @@ static void init(const char *default_runlevel)
printf("%s is an invalid runlevel\n", runlevel);
runlevel = rc_default_runlevel;
}
do_openrc(runlevel);
pid = do_openrc(runlevel);
waitpid(pid, NULL, 0);
log_wtmp("reboot", "~~", 0, RUN_LVL, "~~");
}
@@ -106,9 +100,11 @@ static void handle_reexec(char *my_name)
static void handle_shutdown(const char *runlevel, int cmd)
{
pid_t pid;
struct timespec ts;
do_openrc(runlevel);
pid = do_openrc(runlevel);
while (waitpid(pid, NULL, 0) != pid);
printf("Sending the final term signal\n");
kill(-1, SIGTERM);
ts.tv_sec = 3;
@@ -120,68 +116,12 @@ static void handle_shutdown(const char *runlevel, int cmd)
reboot(cmd);
}
static void run_program(const char *prog)
{
sigset_t full;
sigset_t old;
pid_t pid;
/* We need to block signals until we have forked */
sigfillset(&full);
sigprocmask(SIG_SETMASK, &full, &old);
pid = fork();
if (pid == -1) {
perror("init");
return;
}
if (pid == 0) {
/* Unmask signals */
sigprocmask(SIG_SETMASK, &old, NULL);
execl(prog, prog, (char *)NULL);
perror("init");
exit(1);
}
/* Unmask signals and wait for child */
sigprocmask(SIG_SETMASK, &old, NULL);
if (rc_waitpid(pid) == -1)
perror("init");
}
static void open_shell(void)
{
const char *shell;
struct passwd *pw;
#ifdef __linux__
const char *sys = rc_sys();
/* VSERVER systems cannot really drop to shells */
if (sys && strcmp(sys, RC_SYS_VSERVER) == 0)
{
execlp("halt", "halt", "-f", (char *) NULL);
perror("init");
return;
}
#endif
shell = rc_conf_value("rc_shell");
/* No shell set, so obey env, then passwd, then default to /bin/sh */
if (!shell) {
shell = getenv("SHELL");
if (!shell) {
pw = getpwuid(getuid());
if (pw)
shell = pw->pw_shell;
if (!shell)
shell = "/bin/sh";
}
}
run_program(shell);
}
static void handle_single(void)
{
do_openrc("single");
pid_t pid;
pid = do_openrc("single");
while (waitpid(pid, NULL, 0) != pid);
}
static void reap_zombies(void)
@@ -309,11 +249,8 @@ int main(int argc, char **argv)
handle_shutdown("reboot", RB_AUTOBOOT);
else if (strcmp(buf, "reexec") == 0)
handle_reexec(argv[0]);
else if (strcmp(buf, "single") == 0) {
else if (strcmp(buf, "single") == 0)
handle_single();
open_shell();
init(default_runlevel);
}
}
return 0;
}

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-1)) {
if (readlink(argv[1], lnk, 4096)) {
dir = dirname(path);
if (strchr(lnk, '/')) {
save = xstrdup(dir);
@@ -1223,6 +1223,7 @@ 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

@@ -35,9 +35,8 @@
#include "rc.h"
#include "helpers.h"
#include "rc-misc.h"
#include "rc-sysvinit.h"
#include "rc-wtmp.h"
#include "_usage.h"
#include "rc-wtmp.h"
const char *applet = NULL;
const char *extraopts = NULL;
@@ -68,15 +67,7 @@ const char * const longopts_help[] = {
"write wtmp boot record and exit",
longopts_help_COMMON
};
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 *usagestring = NULL;
const char *exclusive = "Select one of "
"--cancel, --halt, --kexec, --poweroff, --reexec, --reboot, --single or \n"
"--write-only";
@@ -120,8 +111,8 @@ static void create_nologin(int mins)
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);
fprintf(fp, "\rThe system is going down on %s\r\n", ctime(&t));
fclose(fp);
}
}
@@ -131,7 +122,7 @@ static void create_nologin(int mins)
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);
@@ -169,7 +160,9 @@ static void sleep_no_interrupt(int seconds)
static void stop_shutdown(int sig)
{
(void) sig;
/* use the sig parameter so the compiler will not complain */
if (sig == SIGINT)
;
unlink(nologin_file);
unlink(shutdown_pid);
einfo("Shutdown canceled");
@@ -329,30 +322,15 @@ int main(int argc, char **argv)
syslog(LOG_NOTICE, "The system will %s now", state);
unlink(nologin_file);
unlink(shutdown_pid);
if (do_halt) {
if (exists("/run/initctl")) {
sysvinit_setenv("INIT_HALT", "HALT");
sysvinit_runlevel('0');
} else
send_cmd("halt");
} else if (do_kexec)
if (do_halt)
send_cmd("halt");
else if (do_kexec)
send_cmd("kexec");
else if (do_poweroff) {
if (exists("/run/initctl")) {
sysvinit_setenv("INIT_HALT", "POWEROFF");
sysvinit_runlevel('0');
} else
send_cmd("poweroff");
} else if (do_reboot) {
if (exists("/run/initctl"))
sysvinit_runlevel('6');
else
send_cmd("reboot");
} else if (do_single) {
if (exists("/run/initctl"))
sysvinit_runlevel('S');
else
send_cmd("single");
}
else if (do_poweroff)
send_cmd("poweroff");
else if (do_reboot)
send_cmd("reboot");
else if (do_single)
send_cmd("single");
return 0;
}

View File

@@ -28,7 +28,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
@@ -271,11 +270,8 @@ 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 (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);
}
if (!quiet)
ebeginv("Sending signal %d to PID %d", sig, pi->pid);
errno = 0;
killed = (kill(pi->pid, sig) == 0 ||
errno == ESRCH ? true : false);
@@ -283,9 +279,6 @@ 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 {
@@ -317,18 +310,12 @@ 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);
syslog(LOG_DEBUG, "Will stop %s", exec);
}
if (pid > 0) {
if (pid > 0)
einfov("Will stop PID %d", pid);
syslog(LOG_DEBUG, "Will stop PID %d", pid);
}
if (uid) {
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"))) {

View File

@@ -27,18 +27,12 @@
#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 = "acf:lmrsSu" getoptstring_COMMON;
const char *getoptstring = "aclmrsSu" 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'},
@@ -50,7 +44,6 @@ const struct option longopts[] = {
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",
@@ -60,7 +53,7 @@ const char * const longopts_help[] = {
longopts_help_COMMON
};
const char *usagestring = "" \
"Usage: rc-status [options] -f ini <runlevel>...\n" \
"Usage: rc-status [options] <runlevel>...\n" \
" or: rc-status [options] [-a | -c | -l | -m | -r | -s | -u]";
static RC_DEPTREE *deptree;
@@ -69,27 +62,19 @@ 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,
enum format_t format)
static void
print_level(const char *prefix, const char *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;
}
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);
}
static char *get_uptime(const char *service)
@@ -140,13 +125,14 @@ static char *get_uptime(const char *service)
return uptime;
}
static void print_service(const char *service, enum format_t format)
static void
print_service(const char *service)
{
char *status = NULL;
char *uptime = NULL;
char *child_pid = NULL;
char *start_time = NULL;
int cols;
int cols = printf(" %s", service);
const char *c = ecolor(ECOLOR_GOOD);
RC_SERVICE state = rc_service_state(service);
ECOLOR color = ECOLOR_BAD;
@@ -190,22 +176,14 @@ static void print_service(const char *service, enum format_t format)
xasprintf(&status, " stopped ");
errno = 0;
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;
}
if (c && *c && isatty(fileno(stdout)))
printf("\n");
ebracket(cols, color, status);
free(status);
}
static void print_services(const char *runlevel, RC_STRINGLIST *svcs,
enum format_t format)
static void
print_services(const char *runlevel, RC_STRINGLIST *svcs)
{
RC_STRINGLIST *l = NULL;
RC_STRING *s;
@@ -219,7 +197,7 @@ static void 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, format);
print_service(s->value);
return;
}
if (!types) {
@@ -239,12 +217,13 @@ static void 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, format);
print_service(s->value);
}
rc_stringlist_free(l);
}
static void print_stacked_services(const char *runlevel, enum format_t format)
static void
print_stacked_services(const char *runlevel)
{
RC_STRINGLIST *stackedlevels, *servicelist;
RC_STRING *stackedlevel;
@@ -253,9 +232,9 @@ static void print_stacked_services(const char *runlevel, enum format_t format)
TAILQ_FOREACH(stackedlevel, stackedlevels, entries) {
if (rc_stringlist_find(levels, stackedlevel->value) != NULL)
continue;
print_level("Stacked", stackedlevel->value, format);
print_level("Stacked", stackedlevel->value);
servicelist = rc_services_in_runlevel(stackedlevel->value);
print_services(stackedlevel->value, servicelist, format);
print_services(stackedlevel->value, servicelist);
rc_stringlist_free(servicelist);
}
rc_stringlist_free(stackedlevels);
@@ -265,9 +244,7 @@ static void print_stacked_services(const char *runlevel, enum format_t format)
int main(int argc, char **argv)
{
RC_SERVICE state;
RC_STRING *s, *l, *t, *level;
enum format_t format = FORMAT_DEFAULT;
bool levels_given = false;
RC_STRING *s, *l, *t, *level;
bool show_all = false;
char *p, *runlevel = NULL;
int opt, retval = 0;
@@ -290,12 +267,6 @@ 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)
@@ -320,7 +291,7 @@ int main(int argc, char **argv)
free(s->value);
free(s);
}
print_services(NULL, services, FORMAT_DEFAULT);
print_services(NULL, services);
goto exit;
case 'r':
runlevel = rc_runlevel_get();
@@ -332,12 +303,12 @@ int main(int argc, char **argv)
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);
print_services(NULL, services);
goto exit;
/* NOTREACHED */
case 's':
services = rc_services_in_runlevel(NULL);
print_services(NULL, services, FORMAT_DEFAULT);
print_services(NULL, services);
goto exit;
/* NOTREACHED */
case 'u':
@@ -352,7 +323,7 @@ int main(int argc, char **argv)
break;
}
}
print_services(NULL, services, FORMAT_DEFAULT);
print_services(NULL, services);
goto exit;
/* NOTREACHED */
@@ -364,7 +335,6 @@ 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
@@ -381,21 +351,21 @@ int main(int argc, char **argv)
deptree = _rc_deptree_load(0, NULL);
TAILQ_FOREACH(l, levels, entries) {
print_level(NULL, l->value, format);
print_level(NULL, l->value);
services = rc_services_in_runlevel(l->value);
print_services(l->value, services, format);
print_stacked_services(l->value, format);
print_services(l->value, services);
print_stacked_services(l->value);
rc_stringlist_free(nservices);
nservices = NULL;
rc_stringlist_free(services);
services = NULL;
}
if (show_all || !levels_given) {
if (show_all || argc < 2) {
/* Show hotplugged services */
print_level("Dynamic", "hotplugged", format);
print_level("Dynamic", "hotplugged");
services = rc_services_in_state(RC_SERVICE_HOTPLUGGED);
print_services(NULL, services, format);
print_services(NULL, services);
rc_stringlist_free(services);
services = NULL;
@@ -452,10 +422,10 @@ int main(int argc, char **argv)
* be added to the list
*/
unsetenv("RC_SVCNAME");
print_level("Dynamic", "needed/wanted", format);
print_services(NULL, nservices, format);
print_level("Dynamic", "manual", format);
print_services(NULL, services, format);
print_level("Dynamic", "needed/wanted");
print_services(NULL, nservices);
print_level("Dynamic", "manual");
print_services(NULL, services);
}
exit:

View File

@@ -1,102 +0,0 @@
/*
* rc-sysvinit.c
* Helper to send a runlevel change to sysvinit
*/
/*
* Copyright (c) 2019 The OpenRC Authors.
* See the Authors file at the top-level directory of this distribution and
* https://github.com/OpenRC/openrc/blob/master/AUTHORS
*
* This file is part of OpenRC. It is subject to the license terms in
* the LICENSE file found in the top-level directory of this
* distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
* This file may not be copied, modified, propagated, or distributed
* except according to the terms contained in the LICENSE file.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "einfo.h"
#include "rc-sysvinit.h"
static void sysvinit_send_cmd(struct init_request *request)
{
int fd;
char *p;
size_t bytes;
ssize_t r;
fd = open("/run/initctl", O_WRONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY);
if (fd < 0) {
if (errno != ENOENT)
eerror("Failed to open initctl fifo: %s", strerror(errno));
return;
}
p = (char *) request;
bytes = sizeof(*request);
do {
r = write(fd, p, bytes);
if (r < 0) {
if ((errno == EAGAIN) || (errno == EINTR))
continue;
eerror("Failed to write to /run/initctl: %s", strerror(errno));
return;
}
p += r;
bytes -= r;
} while (bytes > 0);
}
void sysvinit_runlevel(char rl)
{
struct init_request request;
if (!rl)
return;
request = (struct init_request) {
.magic = INIT_MAGIC,
.sleeptime = 0,
.cmd = INIT_CMD_RUNLVL,
.runlevel = rl,
};
sysvinit_send_cmd(&request);
return;
}
/*
* Set environment variables in the init process.
*/
void sysvinit_setenv(const char *name, const char *value)
{
struct init_request request;
size_t nl;
size_t vl;
memset(&request, 0, sizeof(request));
request.magic = INIT_MAGIC;
request.cmd = INIT_CMD_SETENV;
nl = strlen(name);
if (value)
vl = strlen(value);
else
vl = 0;
if (nl + vl + 3 >= (int)sizeof(request.i.data))
return;
memcpy(request.i.data, name, nl);
if (value) {
request.i.data[nl] = '=';
memcpy(request.i.data + nl + 1, value, vl);
}
sysvinit_send_cmd(&request);
return;
}

View File

@@ -1,72 +0,0 @@
/*
* rc-sysvinit.h - Interface to communicate with sysvinit via /run/initctl.
*/
/*
* Copyright (c) 2019 The OpenRC Authors.
* See the Authors file at the top-level directory of this distribution and
* https://github.com/OpenRC/openrc/blob/master/AUTHORS
*
* This file is part of OpenRC. It is subject to the license terms in
* the LICENSE file found in the top-level directory of this
* distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
* This file may not be copied, modified, propagated, or distributed
* except according to the terms contained in the LICENSE file.
*/
#ifndef _RC_SYSVINIT_H
#define _RC_SYSVINIT_H
/*
* The #defines and structures below are taken from initreq.h in
* sysvinit and must be used by any program wishing to communicate with
* it.
*/
#define INIT_MAGIC 0x03091969
#define INIT_CMD_START 0
#define INIT_CMD_RUNLVL 1
#define INIT_CMD_POWERFAIL 2
#define INIT_CMD_POWERFAILNOW 3
#define INIT_CMD_POWEROK 4
#define INIT_CMD_BSD 5
#define INIT_CMD_SETENV 6
#define INIT_CMD_UNSETENV 7
/*
* This is what BSD 4.4 uses when talking to init.
* Linux doesn't use this right now.
*/
struct init_request_bsd {
char gen_id[8]; /* Beats me.. telnetd uses "fe" */
char tty_id[16]; /* Tty name minus /dev/tty */
char host[64]; /* Hostname */
char term_type[16]; /* Terminal type */
int signal; /* Signal to send */
int pid; /* Process to send to */
char exec_name[128]; /* Program to execute */
char reserved[128]; /* For future expansion. */
};
/*
* Because of legacy interfaces, "runlevel" and "sleeptime"
* aren't in a seperate struct in the union.
*
* The weird sizes are because init expects the whole
* struct to be 384 bytes.
*/
struct init_request {
int magic; /* Magic number */
int cmd; /* What kind of request */
int runlevel; /* Runlevel to change to */
int sleeptime; /* Time between TERM and KILL */
union {
struct init_request_bsd bsd;
char data[368];
} i;
};
void sysvinit_runlevel(char rl);
void sysvinit_setenv(const char *name, const char *value);
#endif

View File

@@ -43,8 +43,8 @@ void log_wtmp(const char *user, const char *id, pid_t pid, int type,
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

@@ -20,7 +20,7 @@
* except according to the terms contained in the LICENSE file.
*/
static const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#include <sys/types.h>
#include <sys/ioctl.h>

View File

@@ -492,7 +492,7 @@ int main(int argc, char **argv)
startas = optarg;
break;
case 'w':
if (sscanf(optarg, "%u", &start_wait) != 1)
if (sscanf(optarg, "%d", &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;
};
@@ -669,7 +669,7 @@ int main(int argc, char **argv)
nav[len++] = p;
for (i = 0; i < opt; i++)
nav[i + len] = argv[i];
nav[i + len] = NULL;
nav[i + len] = '\0';
}
}
}

View File

@@ -237,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) {
@@ -267,56 +267,6 @@ 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;
@@ -510,6 +460,7 @@ static void supervisor(char *exec, char **argv)
int healthcheck_respawn;
int i;
int nkilled;
int ready;
int sig_send;
pid_t health_pid;
pid_t wait_pid;
@@ -535,7 +486,7 @@ static void supervisor(char *exec, char **argv)
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);
@@ -557,10 +508,10 @@ static void supervisor(char *exec, char **argv)
alarm(healthcheckdelay);
else if (healthchecktimer)
alarm(healthchecktimer);
failing = 0;
failing = 0;
while (!exiting) {
healthcheck_respawn = 0;
fifo_fd = open(fifopath, O_RDONLY);
fifo_fd = open(fifopath, O_RDONLY);
if (fifo_fd > 0) {
memset(buf, 0, sizeof(buf));
count = read(fifo_fd, buf, sizeof(buf) - 1);
@@ -586,13 +537,13 @@ static void supervisor(char *exec, char **argv)
do_healthcheck = 0;
alarm(0);
syslog(LOG_DEBUG, "running health check for %s", svcname);
health_pid = exec_command("healthcheck");
health_pid = exec_service(svcname, "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");
health_pid = exec_service(svcname, "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,
@@ -604,7 +555,7 @@ static void supervisor(char *exec, char **argv)
healthcheck_respawn = 1;
}
}
if (exiting) {
if (exiting ) {
alarm(0);
syslog(LOG_INFO, "stopping %s, pid %d", exec, child_pid);
nkilled = run_stop_schedule(applet, NULL, NULL, child_pid, 0,
@@ -720,7 +671,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 || strcmp(argv[1], svcname))
if (argc >= 1 && svcname && strcmp(argv[1], svcname))
eerrorx("%s: the first argument is %s and must be %s",
applet, argv[1], svcname);
@@ -835,7 +786,7 @@ int main(int argc, char **argv)
case 'm': /* --respawn-max count */
n = sscanf(optarg, "%d", &respawn_max);
if (n != 1 || respawn_max < 0)
if (n != 1 || respawn_max < 1)
eerrorx("Invalid respawn-max value '%s'", optarg);
break;
@@ -1062,8 +1013,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

6
src/test/.gitignore vendored Normal file
View File

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

1
src/test/einfo.data.list Normal file
View File

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

52
src/test/einfo.funcs.list Normal file
View File

@@ -0,0 +1,52 @@
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

3
src/test/rc.data.list Normal file
View File

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

116
src/test/rc.funcs.list Normal file
View File

@@ -0,0 +1,116 @@
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

@@ -1,6 +1,6 @@
#!/bin/sh
top_srcdir=${top_srcdir:-..}
top_srcdir=${top_srcdir:-../..}
. ${top_srcdir}/test/setup_env.sh
libeinfo_srcdir="${srcdir}/../libeinfo"
@@ -27,6 +27,53 @@ fail_on_out() {
fi
}
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 += $? ))
ebegin "Checking trailing whitespace in code"
# XXX: Should we check man pages too ?
out=$(cd ${top_srcdir}; find */ \

View File

@@ -92,8 +92,7 @@ respawn_max=x
```
This is the maximum number of times to respawn a supervised process
during the given respawn period.
The default is 10. 0 means unlimited.
during the given respawn period. The default is unlimited.
``` sh
respawn_period=seconds
@@ -102,10 +101,6 @@ 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 10 and respawn_max is 2, the process
would need to die 3 times within 10 seconds to no longer be respawned.
Note that respawn_delay will delay all of this, so in the above scenario
a respawn_delay of greater than 5 will cause infinite respawns.
By default, this is unset and respawn_max applies to the entire lifetime
of the service.
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

@@ -2,7 +2,7 @@ MK= ../../mk
include ${MK}/os.mk
DIR= ${DATADIR}/support/sysvinit
INC= halt.sh inittab README.md
INC= inittab README.md
include ${MK}/scripts.mk

View File

@@ -1,6 +0,0 @@
#!/bin/sh
if [ "$INIT_HALT" = HALT ]; then
exec /sbin/halt -dhn
else
exec /sbin/poweroff -dhn
fi

View File

@@ -10,15 +10,13 @@ si::sysinit:/sbin/openrc sysinit
# Further system initialization, brings up the boot runlevel.
rc::bootwait:/sbin/openrc boot
l0u:0:wait:/sbin/telinit u
l0:0:wait:/sbin/openrc shutdown
l0s:0:wait:/sbin/halt.sh
l0s:0:wait:/sbin/halt -dhip
l1:S1:wait:/sbin/openrc single
l2:2:wait:/sbin/openrc nonetwork
l3:3:wait:/sbin/openrc default
l4:4:wait:/sbin/openrc default
l5:5:wait:/sbin/openrc default
l6u:6:wait:/sbin/telinit u
l6:6:wait:/sbin/openrc reboot
l6r:6:wait:/sbin/reboot -d
#z6:6:respawn:/sbin/sulogin
@@ -36,8 +34,8 @@ c5:2345:respawn:/sbin/agetty 38400 tty5 linux
c6:2345:respawn:/sbin/agetty 38400 tty6 linux
# SERIAL CONSOLES
#s0:12345:respawn:/sbin/agetty -L 9600 ttyS0 vt100
#s1:12345:respawn:/sbin/agetty -L 9600 ttyS1 vt100
#s0:12345:respawn:/sbin/agetty 9600 ttyS0 vt100
#s1:12345:respawn:/sbin/agetty 9600 ttyS1 vt100
# What to do at the "Three Finger Salute".
ca:12345:ctrlaltdel:/sbin/shutdown -r now

5
test/skel.runtests.sh Executable file
View File

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

View File

@@ -1,37 +1,27 @@
#compdef rc-service
_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'
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
# vim: set et sw=2 ts=2 ft=zsh: