Remove null terminated char ** lists in favour of RC_STRINGLIST, using TAILQ from queue(3). Refactor code style around the BSD KNF.
This commit is contained in:
parent
40e12f6ba0
commit
cb9da6a262
@ -1,6 +1,6 @@
|
|||||||
MAN3= einfo.3 \
|
MAN3= einfo.3 \
|
||||||
rc_config.3 rc_deptree.3 rc_find_pids.3 rc_plugin_hook.3 \
|
rc_config.3 rc_deptree.3 rc_find_pids.3 rc_plugin_hook.3 \
|
||||||
rc_runlevel.3 rc_service.3 rc_strcatpaths.3 rc_strlist.3
|
rc_runlevel.3 rc_service.3 rc_strcatpaths.3 rc_stringlist.3
|
||||||
MAN8= rc-status.8 rc-update.8 rc.8 runscript.8 start-stop-daemon.8
|
MAN8= rc-status.8 rc-update.8 rc.8 runscript.8 start-stop-daemon.8
|
||||||
|
|
||||||
# Handy macro to create symlinks
|
# Handy macro to create symlinks
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd Feb 22, 2008
|
.Dd Mar 16, 2008
|
||||||
.Dt EINFO 3 SMM
|
.Dt EINFO 3 SMM
|
||||||
.Os OpenRC
|
.Os OpenRC
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -62,7 +62,7 @@ Enhanced Informatation output library (libeinfo, -leinfo)
|
|||||||
.Ft int Fn ewend "int retval" "const char * restrict format" ...
|
.Ft int Fn ewend "int retval" "const char * restrict format" ...
|
||||||
.Ft int Fn eendv "int retval" "const char * restrict format" ...
|
.Ft int Fn eendv "int retval" "const char * restrict format" ...
|
||||||
.Ft int Fn ewendv "int retval" "const char * restrict format" ...
|
.Ft int Fn ewendv "int retval" "const char * restrict format" ...
|
||||||
.Ft void Fn ebracket "int col" "einfo_color_t color" "const char * restrict msg"
|
.Ft void Fn ebracket "int col" "ECOLOR color" "const char * restrict msg"
|
||||||
.Ft void Fn eindent void
|
.Ft void Fn eindent void
|
||||||
.Ft void Fn eoutdent void
|
.Ft void Fn eoutdent void
|
||||||
.Ft void Fn eindentv void
|
.Ft void Fn eindentv void
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd Jan 08, 2008
|
.Dd Mar 16, 2008
|
||||||
.Dt RC_CONFIG 3 SMM
|
.Dt RC_CONFIG 3 SMM
|
||||||
.Os OpenRC
|
.Os OpenRC
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -33,8 +33,8 @@ Run Command library (librc, -lrc)
|
|||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.In rc.h
|
.In rc.h
|
||||||
.Ft "char *" Fn rc_getline "FILE *fp"
|
.Ft "char *" Fn rc_getline "FILE *fp"
|
||||||
.Ft "char **" Fn rc_config_list "const char *file"
|
.Ft "RC_STRINGLIST *" Fn rc_config_list "const char *file"
|
||||||
.Ft "char **" Fn rc_config_load "const char *file"
|
.Ft "RC_STRINGLIST *" Fn rc_config_load "const char *file"
|
||||||
.Ft "char *" Fn rc_config_value "const char *const *list" "const char *entry"
|
.Ft "char *" Fn rc_config_value "const char *const *list" "const char *entry"
|
||||||
.Ft bool Fn rc_yesno "const char *value"
|
.Ft bool Fn rc_yesno "const char *value"
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
@ -61,7 +61,7 @@ found in
|
|||||||
.Fa list .
|
.Fa list .
|
||||||
.Pp
|
.Pp
|
||||||
Each list should be freed using
|
Each list should be freed using
|
||||||
.Fn rc_strlist_free
|
.Fn rc_stringlist_free
|
||||||
when done.
|
when done.
|
||||||
.Pp
|
.Pp
|
||||||
.Fn rc_yesno
|
.Fn rc_yesno
|
||||||
@ -76,7 +76,7 @@ is set to
|
|||||||
.Va EINVAL .
|
.Va EINVAL .
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr malloc 3 ,
|
.Xr malloc 3 ,
|
||||||
.Xr rc_strlist_free 3 ,
|
.Xr rc_stringlist_free 3 ,
|
||||||
.Xr sh 1
|
.Xr sh 1
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An "Roy Marples" Aq roy@marples.name
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd Feb 22, 2008
|
.Dd Mar 16, 2008
|
||||||
.Dt RC_DEPTREE 3 SMM
|
.Dt RC_DEPTREE 3 SMM
|
||||||
.Os OpenRC
|
.Os OpenRC
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -36,25 +36,25 @@ Run Command library (librc, -lrc)
|
|||||||
.In rc.h
|
.In rc.h
|
||||||
.Ft bool Fn rc_deptree_update void
|
.Ft bool Fn rc_deptree_update void
|
||||||
.Ft bool Fn rc_deptree_update_needed void
|
.Ft bool Fn rc_deptree_update_needed void
|
||||||
.Ft rc_depinfo_t Fn rc_deptree_load void
|
.Ft RC_DEPTREE Fn rc_deptree_load void
|
||||||
.Ft "char **" Fo rc_deptree_depend
|
.Ft "RC_STRINGLIST *" Fo rc_deptree_depend
|
||||||
.Fa "const rc_depinfo_t *deptree"
|
.Fa "const RC_DEPTREE *deptree"
|
||||||
.Fa "const char *type"
|
.Fa "const char *type"
|
||||||
.Fa "const char *service"
|
.Fa "const char *service"
|
||||||
.Fc
|
.Fc
|
||||||
.Ft bool Fo rc_deptree_depends
|
.Ft bool Fo rc_deptree_depends
|
||||||
.Fa "const rc_depinfo_t *deptree"
|
.Fa "const RC_DEPTREE *deptree"
|
||||||
.Fa "const char *const *types"
|
.Fa "const char *const *types"
|
||||||
.Fa "const char *const *services"
|
.Fa "const char *const *services"
|
||||||
.Fa "const char *runlevel"
|
.Fa "const char *runlevel"
|
||||||
.Fa "int options"
|
.Fa "int options"
|
||||||
.Fc
|
.Fc
|
||||||
.Ft "char **" Fo rc_deptree_order
|
.Ft "RC_STRINGLIST *" Fo rc_deptree_order
|
||||||
.Fa "const rc_depinfo_t *deptree"
|
.Fa "const RC_DEPTREE *deptree"
|
||||||
.Fa "const char *runlevel"
|
.Fa "const char *runlevel"
|
||||||
.Fa "int options"
|
.Fa "int options"
|
||||||
.Fc
|
.Fc
|
||||||
.Ft void Fn rc_deptree_free "rc_depinfo_t *deptree"
|
.Ft void Fn rc_deptree_free "RC_DEPTREE *deptree"
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
These functions provide a means of querying the dependencies of OpenRC
|
These functions provide a means of querying the dependencies of OpenRC
|
||||||
services.
|
services.
|
||||||
@ -100,15 +100,14 @@ only lists services actually needed or in the
|
|||||||
.Va runlevel .
|
.Va runlevel .
|
||||||
.Sh IMPLEMENTATION NOTES
|
.Sh IMPLEMENTATION NOTES
|
||||||
Each function that returns
|
Each function that returns
|
||||||
.Fr "char **"
|
.Fr "RC_STRINGLIST *"
|
||||||
returns a malloced NULL terminated array of malloced NULL terminated strings,
|
should be freed by calling
|
||||||
all of which need to be freed using
|
.Fn rc_stringlist_free
|
||||||
.Fn rc_strlist_free
|
|
||||||
when done.
|
when done.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr malloc 3 ,
|
.Xr malloc 3 ,
|
||||||
.Xr free 3 ,
|
.Xr free 3 ,
|
||||||
.Xr rc_strlist_free 3 ,
|
.Xr rc_stringlist_free 3 ,
|
||||||
.Xr runscript 8
|
.Xr runscript 8
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An "Roy Marples" Aq roy@marples.name
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd Feb 22, 2008
|
.Dd Mar 16, 2008
|
||||||
.Dt RC_PLUGIN_HOOK 3 SMM
|
.Dt RC_PLUGIN_HOOK 3 SMM
|
||||||
.Os OpenRC
|
.Os OpenRC
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -32,7 +32,7 @@
|
|||||||
Run Command library (librc, -lrc)
|
Run Command library (librc, -lrc)
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.In rc.h
|
.In rc.h
|
||||||
.Ft int Fn rc_plugin_hook "rc_hook_t hook" "const char *name"
|
.Ft int Fn rc_plugin_hook "RC_HOOK hook" "const char *name"
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Fn rc_plugin_hook
|
.Fn rc_plugin_hook
|
||||||
is called for each shareable object found in
|
is called for each shareable object found in
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd Feb 22, 2008
|
.Dd Mar 16, 2008
|
||||||
.Dt RC_RUNLEVEL 3 SMM
|
.Dt RC_RUNLEVEL 3 SMM
|
||||||
.Os OpenRC
|
.Os OpenRC
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -35,7 +35,7 @@ Run Command library (librc, -lrc)
|
|||||||
.In rc.h
|
.In rc.h
|
||||||
.Ft "char *" Fn rc_runlevel_get void
|
.Ft "char *" Fn rc_runlevel_get void
|
||||||
.Ft bool Fn rc_runlevel_exists
|
.Ft bool Fn rc_runlevel_exists
|
||||||
.Ft "char **" Fn rc_runlevel_list void
|
.Ft "RC_STRINGLIST *" Fn rc_runlevel_list void
|
||||||
.Ft bool Fn rc_runlevel_set "const char *runlevel"
|
.Ft bool Fn rc_runlevel_set "const char *runlevel"
|
||||||
.Ft bool Fn rc_runlevel_starting void
|
.Ft bool Fn rc_runlevel_starting void
|
||||||
.Ft bool Fn rc_runlevel_stopping void
|
.Ft bool Fn rc_runlevel_stopping void
|
||||||
@ -48,10 +48,9 @@ Each function that returns
|
|||||||
returns a malloced NULL terminated string that should be freed when done.
|
returns a malloced NULL terminated string that should be freed when done.
|
||||||
.Pp
|
.Pp
|
||||||
Each function that returns
|
Each function that returns
|
||||||
.Fr "char **"
|
.Fr "RC_STRINGLIST *"
|
||||||
returns a malloced NULL terminated array of malloced NULL terminated strings,
|
should by freed by calling
|
||||||
all of which need to be freed using
|
.Fn rc_stringlist_free
|
||||||
.Fn rc_strlist_free
|
|
||||||
when done.
|
when done.
|
||||||
.Sh FILES
|
.Sh FILES
|
||||||
.Pa /etc/init.d/functions.sh
|
.Pa /etc/init.d/functions.sh
|
||||||
@ -62,6 +61,6 @@ Rinse and repeat for the other verbose functions.
|
|||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr malloc 3 ,
|
.Xr malloc 3 ,
|
||||||
.Xr free 3
|
.Xr free 3
|
||||||
.Xr rc_strlist_free 3
|
.Xr rc_stringlist_free 3
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An "Roy Marples" Aq roy@marples.name
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd Feb 22, 2008
|
.Dd Mar 16, 2008
|
||||||
.Dt RC_SERVICE 3 SMM
|
.Dt RC_SERVICE 3 SMM
|
||||||
.Os OpenRC
|
.Os OpenRC
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -55,17 +55,17 @@ Run Command library (librc, -lrc)
|
|||||||
.Fc
|
.Fc
|
||||||
.Ft bool Fn rc_service_exists "const char *service"
|
.Ft bool Fn rc_service_exists "const char *service"
|
||||||
.Ft bool Fn rc_service_in_runlevel "const char *service" "const char *runlevel"
|
.Ft bool Fn rc_service_in_runlevel "const char *service" "const char *runlevel"
|
||||||
.Ft bool Fn rc_service_mark "const char *service" "rc_service_state_t state"
|
.Ft bool Fn rc_service_mark "const char *service" "RC_SERVICE state"
|
||||||
.Ft "char **" Fn rc_service_extra_commands "const char *service"
|
.Ft "RC_STRINGLIST *" Fn rc_service_extra_commands "const char *service"
|
||||||
.Ft bool Fn rc_service_plugable "const char *service"
|
.Ft bool Fn rc_service_plugable "const char *service"
|
||||||
.Ft "char *" rc_service_resolve "const char *service"
|
.Ft "char *" rc_service_resolve "const char *service"
|
||||||
.Ft bool Fo rc_service_schedule_start
|
.Ft bool Fo rc_service_schedule_start
|
||||||
.Fa "const char *service"
|
.Fa "const char *service"
|
||||||
.Fa "const char *service_to_start"
|
.Fa "const char *service_to_start"
|
||||||
.Fc
|
.Fc
|
||||||
.Ft "char **" Fn rc_services_scheduled_by "const char *service"
|
.Ft "RC_STRINGLIST *" Fn rc_services_scheduled_by "const char *service"
|
||||||
.Ft bool Fn rc_service_schedule_clear "const char *service"
|
.Ft bool Fn rc_service_schedule_clear "const char *service"
|
||||||
.Ft rc_service_state_t Fn rc_service_state "const char *service"
|
.Ft RC_SERVICE Fn rc_service_state "const char *service"
|
||||||
.Ft pid_t Fn rc_service_start "const char *service"
|
.Ft pid_t Fn rc_service_start "const char *service"
|
||||||
.Ft pid_t Fn rc_service_stop "const char *service"
|
.Ft pid_t Fn rc_service_stop "const char *service"
|
||||||
.Ft bool Fo rc_service_started_daemon
|
.Ft bool Fo rc_service_started_daemon
|
||||||
@ -79,9 +79,9 @@ Run Command library (librc, -lrc)
|
|||||||
.Fa "const char *option"
|
.Fa "const char *option"
|
||||||
.Fa "const char *value"
|
.Fa "const char *value"
|
||||||
.Fc
|
.Fc
|
||||||
.Ft "char **" Fn rc_services_in_runlevel "const char *runlevel"
|
.Ft "RC_STRINGLIST *" Fn rc_services_in_runlevel "const char *runlevel"
|
||||||
.Ft "char **" Fn rc_services_in_state "rc_service_state_t state"
|
.Ft "RC_STRINGLIST *" Fn rc_services_in_state "RC_SERVICE state"
|
||||||
.Ft "char **" Fn rc_services_scheduled "const char *service"
|
.Ft "RC_STRINGLIST *" Fn rc_services_scheduled "const char *service"
|
||||||
.Ft bool Fn rc_service_daemons_crashed "const char *service"
|
.Ft bool Fn rc_service_daemons_crashed "const char *service"
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
These functions provide a means of querying OpenRC services to find out the
|
These functions provide a means of querying OpenRC services to find out the
|
||||||
@ -222,10 +222,9 @@ Each function that returns
|
|||||||
returns a malloced NULL terminated string that should be freed when done.
|
returns a malloced NULL terminated string that should be freed when done.
|
||||||
.Pp
|
.Pp
|
||||||
Each function that returns
|
Each function that returns
|
||||||
.Fr "char **"
|
.Fr "RC_STRINGLIST *"
|
||||||
returns a malloced NULL terminated array of malloced NULL terminated strings,
|
should be freed using
|
||||||
all of which need to be freed using
|
.Fn rc_stringlist_free
|
||||||
.Fn rc_strlist_free
|
|
||||||
when done.
|
when done.
|
||||||
.Pp
|
.Pp
|
||||||
When a function fails it should either return false or NULL and set
|
When a function fails it should either return false or NULL and set
|
||||||
@ -238,7 +237,7 @@ normally holds the volatile state data for services on a RAM backed disk.
|
|||||||
.Xr errno 3 ,
|
.Xr errno 3 ,
|
||||||
.Xr malloc 3 ,
|
.Xr malloc 3 ,
|
||||||
.Xr free 3
|
.Xr free 3
|
||||||
.Xr rc_strlist_free 3 ,
|
.Xr rc_stringlist_free 3 ,
|
||||||
.Xr start-stop-daemon 8
|
.Xr start-stop-daemon 8
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
.An "Roy Marples" Aq roy@marples.name
|
||||||
|
104
man/rc_strlist.3
104
man/rc_strlist.3
@ -1,104 +0,0 @@
|
|||||||
.\" Copyright 2007-2008 Roy Marples
|
|
||||||
.\" All rights reserved
|
|
||||||
.\"
|
|
||||||
.\" Redistribution and use in source and binary forms, with or without
|
|
||||||
.\" modification, are permitted provided that the following conditions
|
|
||||||
.\" are met:
|
|
||||||
.\" 1. Redistributions of source code must retain the above copyright
|
|
||||||
.\" notice, this list of conditions and the following disclaimer.
|
|
||||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
.\" notice, this list of conditions and the following disclaimer in the
|
|
||||||
.\" documentation and/or other materials provided with the distribution.
|
|
||||||
.\"
|
|
||||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
||||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
.\" SUCH DAMAGE.
|
|
||||||
.\"
|
|
||||||
.Dd Feb 22, 2008
|
|
||||||
.Dt RC_STRLIST 3 SMM
|
|
||||||
.Os OpenRC
|
|
||||||
.Sh NAME
|
|
||||||
.Nm rc_strlist_add , rc_strlist_addu , rc_strlist_addsort ,
|
|
||||||
.Nm rc_strlist_addsortc , rc_strlist_addsortu , rc_strlist_delete ,
|
|
||||||
.Nm rc_strlist_join , rc_strlist_reverse , rc_strlist_free
|
|
||||||
.Nd RC string list functions
|
|
||||||
.Sh LIBRARY
|
|
||||||
Run Command library (librc, -lrc)
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.In rc.h
|
|
||||||
.Ft "char *" Fn rc_strlist_add "char ***list" "const char *item"
|
|
||||||
.Ft "char *" Fn rc_strlist_addu "char ***list" "const char *item"
|
|
||||||
.Ft "char *" Fn rc_strlist_addsort "char ***list" "const char *item"
|
|
||||||
.Ft "char *" Fn rc_strlist_addsortc "char ***list" "const char *item"
|
|
||||||
.Ft "char *" Fn rc_strlist_addsortu "char ***list" "const char *item"
|
|
||||||
.Ft bool Fn rc_strlist_delete "char ***list" "const char *item"
|
|
||||||
.Ft "char *" Fn rc_strlist_join "char ***list1" "const char **list2"
|
|
||||||
.Ft void Fn rc_strlist_reverse "char **list"
|
|
||||||
.Ft void Fn rc_strlist_free "char **list"
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
These functions provide an easy means of manipulating string lists without
|
|
||||||
the need for custom structures or non standard macros.
|
|
||||||
.Pp
|
|
||||||
.Fn rc_strlist_add
|
|
||||||
adds a malloced copy of
|
|
||||||
.Fa item
|
|
||||||
to
|
|
||||||
.Fa list ,
|
|
||||||
realloced to accomodate the new item. It returns a pointer to the new item on
|
|
||||||
success, or NULL on failure and sets
|
|
||||||
.Va errno
|
|
||||||
accordingly.
|
|
||||||
.Fn rc_strlist_addu
|
|
||||||
and
|
|
||||||
.Fn rc_strlist_addsortu
|
|
||||||
only work if
|
|
||||||
.Fa list
|
|
||||||
does not already contain
|
|
||||||
.Fa item .
|
|
||||||
.Fn rc_strlist_addsort
|
|
||||||
adds the item to the list in a lexically sorted position, using
|
|
||||||
.Nm strcoll ,
|
|
||||||
whereas
|
|
||||||
.Fn rc_strlist_addsortc
|
|
||||||
uses
|
|
||||||
.Nm strcmp .
|
|
||||||
.Pp
|
|
||||||
.Fn rc_strlist_delete
|
|
||||||
removes and frees
|
|
||||||
.Fa item
|
|
||||||
from
|
|
||||||
.Fa list ,
|
|
||||||
retuning true on success, otherwise false.
|
|
||||||
.Pp
|
|
||||||
.Fn rc_strlist_join
|
|
||||||
appends
|
|
||||||
.Fa list2
|
|
||||||
to the end of
|
|
||||||
.Fa list1
|
|
||||||
and returns a pointer to the last item on the new list.
|
|
||||||
.Pp
|
|
||||||
.Fn rc_strlist_reverse
|
|
||||||
reverses the items on
|
|
||||||
.Fa list .
|
|
||||||
.Pp
|
|
||||||
.Fn rc_strlist_free
|
|
||||||
frees each item on
|
|
||||||
.Fa list
|
|
||||||
and the
|
|
||||||
.Fa list
|
|
||||||
itself.
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr malloc 3 ,
|
|
||||||
.Xr free 3 ,
|
|
||||||
.Xr strcmp 3 ,
|
|
||||||
.Xr strcoll 3
|
|
||||||
.Sh AUTHORS
|
|
||||||
.An "Roy Marples" Aq roy@marples.name
|
|
@ -56,7 +56,7 @@
|
|||||||
|
|
||||||
#define RC_LIBDIR RC_PREFIX "/" LIB "/rc"
|
#define RC_LIBDIR RC_PREFIX "/" LIB "/rc"
|
||||||
#define RC_SVCDIR RC_LIBDIR "/init.d"
|
#define RC_SVCDIR RC_LIBDIR "/init.d"
|
||||||
#define RC_DEPTREE RC_SVCDIR "/deptree"
|
#define RC_DEPTREE_CACHE RC_SVCDIR "/deptree"
|
||||||
#define RC_RUNLEVELDIR RC_PREFIX SYSCONFDIR "/runlevels"
|
#define RC_RUNLEVELDIR RC_PREFIX SYSCONFDIR "/runlevels"
|
||||||
#define RC_INITDIR RC_PREFIX SYSCONFDIR "/init.d"
|
#define RC_INITDIR RC_PREFIX SYSCONFDIR "/init.d"
|
||||||
#define RC_CONFDIR RC_PREFIX SYSCONFDIR "/conf.d"
|
#define RC_CONFDIR RC_PREFIX SYSCONFDIR "/conf.d"
|
||||||
@ -98,9 +98,46 @@
|
|||||||
# define _unused
|
# define _unused
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Some libc implemntations don't have these */
|
||||||
|
#ifndef STAILQ_CONCAT
|
||||||
|
#define STAILQ_CONCAT(head1, head2) do { \
|
||||||
|
if (!STAILQ_EMPTY((head2))) { \
|
||||||
|
*(head1)->stqh_last = (head2)->stqh_first; \
|
||||||
|
(head1)->stqh_last = (head2)->stqh_last; \
|
||||||
|
STAILQ_INIT((head2)); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TAILQ_CONCAT
|
||||||
|
#define TAILQ_CONCAT(head1, head2) do { \
|
||||||
|
if (!TAILQ_EMPTY((head2))) { \
|
||||||
|
*(head1)->tqh_last = (head2)->tqh_first; \
|
||||||
|
(head1)->tqh_last = (head2)->tqh_last; \
|
||||||
|
TAILQ_INIT((head2)); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef STAILQ_FOREACH_SAFE
|
||||||
|
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||||
|
for ((var) = STAILQ_FIRST((head)); \
|
||||||
|
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
|
||||||
|
(var) = (tvar))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TAILQ_FOREACH_SAFE
|
||||||
|
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||||
|
for ((var) = TAILQ_FIRST((head)); \
|
||||||
|
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
|
||||||
|
(var) = (tvar))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
_unused static void *xmalloc (size_t size)
|
_unused static void *xmalloc (size_t size)
|
||||||
{
|
{
|
||||||
void *value = malloc (size);
|
void *value = malloc(size);
|
||||||
|
|
||||||
if (value)
|
if (value)
|
||||||
return (value);
|
return (value);
|
||||||
@ -109,9 +146,9 @@ _unused static void *xmalloc (size_t size)
|
|||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
_unused static void *xrealloc (void *ptr, size_t size)
|
_unused static void *xrealloc(void *ptr, size_t size)
|
||||||
{
|
{
|
||||||
void *value = realloc (ptr, size);
|
void *value = realloc(ptr, size);
|
||||||
|
|
||||||
if (value)
|
if (value)
|
||||||
return (value);
|
return (value);
|
||||||
@ -120,14 +157,14 @@ _unused static void *xrealloc (void *ptr, size_t size)
|
|||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
_unused static char *xstrdup (const char *str)
|
_unused static char *xstrdup(const char *str)
|
||||||
{
|
{
|
||||||
char *value;
|
char *value;
|
||||||
|
|
||||||
if (! str)
|
if (! str)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
value = strdup (str);
|
value = strdup(str);
|
||||||
|
|
||||||
if (value)
|
if (value)
|
||||||
return (value);
|
return (value);
|
||||||
@ -138,32 +175,32 @@ _unused static char *xstrdup (const char *str)
|
|||||||
|
|
||||||
#undef ERRX
|
#undef ERRX
|
||||||
|
|
||||||
_unused static bool exists (const char *pathname)
|
_unused static bool exists(const char *pathname)
|
||||||
{
|
{
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
|
|
||||||
return (stat (pathname, &buf) == 0);
|
return (stat(pathname, &buf) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
_unused static bool existss (const char *pathname)
|
_unused static bool existss(const char *pathname)
|
||||||
{
|
{
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
|
|
||||||
return (stat (pathname, &buf) == 0 && buf.st_size != 0);
|
return (stat(pathname, &buf) == 0 && buf.st_size != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *rc_conf_value (const char *var);
|
char *rc_conf_value(const char *var);
|
||||||
bool rc_conf_yesno (const char *var);
|
bool rc_conf_yesno(const char *var);
|
||||||
char **env_filter (void);
|
void env_filter(void);
|
||||||
char **env_config (void);
|
void env_config(void);
|
||||||
bool service_plugable (const char *service);
|
bool service_plugable(const char *service);
|
||||||
int signal_setup (int sig, void (*handler)(int));
|
int signal_setup(int sig, void (*handler)(int));
|
||||||
|
|
||||||
/* basename_c never modifies the argument. As such, if there is a trailing
|
/* basename_c never modifies the argument. As such, if there is a trailing
|
||||||
* slash then an empty string is returned. */
|
* slash then an empty string is returned. */
|
||||||
_unused static const char *basename_c (const char *path)
|
_unused static const char *basename_c(const char *path)
|
||||||
{
|
{
|
||||||
const char *slash = strrchr (path, '/');
|
const char *slash = strrchr(path, '/');
|
||||||
|
|
||||||
if (slash)
|
if (slash)
|
||||||
return (++slash);
|
return (++slash);
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
strlist.h
|
|
||||||
String list macros for making char ** arrays
|
|
||||||
Based on a previous implementation by Martin Schlemmer
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2007-2008 Roy Marples
|
|
||||||
* All rights reserved
|
|
||||||
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __STRLIST_H__
|
|
||||||
#define __STRLIST_H__
|
|
||||||
|
|
||||||
/* FIXME: We should replace the macro with an rc_strlist_foreach
|
|
||||||
function, but I'm unsure how to go about this. */
|
|
||||||
|
|
||||||
/* Step through each entry in the string list, setting '_pos' to the
|
|
||||||
beginning of the entry. '_counter' is used by the macro as index,
|
|
||||||
but should not be used by code as index (or if really needed, then
|
|
||||||
it should usually by +1 from what you expect, and should only be
|
|
||||||
used in the scope of the macro) */
|
|
||||||
#define STRLIST_FOREACH(_list, _pos, _counter) \
|
|
||||||
if ((_list) && _list[0] && ! (_counter = 0)) \
|
|
||||||
while ((_pos = _list[_counter++]))
|
|
||||||
|
|
||||||
#endif /* __STRLIST_H__ */
|
|
@ -54,19 +54,19 @@
|
|||||||
/*! @brief Color types to use */
|
/*! @brief Color types to use */
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
ECOLOR_NORMAL = 1,
|
ECOLOR_NORMAL = 1,
|
||||||
ECOLOR_GOOD = 2,
|
ECOLOR_GOOD = 2,
|
||||||
ECOLOR_WARN = 3,
|
ECOLOR_WARN = 3,
|
||||||
ECOLOR_BAD = 4,
|
ECOLOR_BAD = 4,
|
||||||
ECOLOR_HILITE = 5,
|
ECOLOR_HILITE = 5,
|
||||||
ECOLOR_BRACKET = 6
|
ECOLOR_BRACKET = 6
|
||||||
} einfo_color_t;
|
} ECOLOR;
|
||||||
|
|
||||||
/*! @brief Returns the ASCII code for the color */
|
/*! @brief Returns the ASCII code for the color */
|
||||||
const char *ecolor (einfo_color_t);
|
const char *ecolor(ECOLOR);
|
||||||
|
|
||||||
/*! @brief Writes to syslog. */
|
/*! @brief Writes to syslog. */
|
||||||
void elog (int __level, const char * __EINFO_RESTRICT __fmt, ...) __EEND_PRINTF;
|
void elog(int, const char * __EINFO_RESTRICT, ...) __EEND_PRINTF;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Display informational messages.
|
* @brief Display informational messages.
|
||||||
@ -84,22 +84,22 @@ void elog (int __level, const char * __EINFO_RESTRICT __fmt, ...) __EEND_PRINTF;
|
|||||||
* The v suffix means only print if EINFO_VERBOSE is yes.
|
* The v suffix means only print if EINFO_VERBOSE is yes.
|
||||||
*/
|
*/
|
||||||
/*@{*/
|
/*@{*/
|
||||||
int einfon (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF;
|
int einfon(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF;
|
||||||
int ewarnn (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF;
|
int ewarnn(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF;
|
||||||
int eerrorn (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF;
|
int eerrorn(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF;
|
||||||
int einfo (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF;
|
int einfo(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF;
|
||||||
int ewarn (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF;
|
int ewarn(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF;
|
||||||
void ewarnx (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_XPRINTF;
|
void ewarnx(const char * __EINFO_RESTRICT, ...) __EINFO_XPRINTF;
|
||||||
int eerror (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF;
|
int eerror(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF;
|
||||||
void eerrorx (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_XPRINTF;
|
void eerrorx(const char * __EINFO_RESTRICT, ...) __EINFO_XPRINTF;
|
||||||
|
|
||||||
int einfovn (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF;
|
int einfovn(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF;
|
||||||
int ewarnvn (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF;
|
int ewarnvn(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF;
|
||||||
int ebeginvn (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF;
|
int ebeginvn(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF;
|
||||||
int eendvn (int __retval, const char * __EINFO_RESTRICT __fmt, ...) __EEND_PRINTF;
|
int eendvn(int, const char * __EINFO_RESTRICT, ...) __EEND_PRINTF;
|
||||||
int ewendvn (int __retval, const char * __EINFO_RESTRICT __fmt, ...) __EEND_PRINTF;
|
int ewendvn(int, const char * __EINFO_RESTRICT, ...) __EEND_PRINTF;
|
||||||
int einfov (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF;
|
int einfov(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF;
|
||||||
int ewarnv (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF;
|
int ewarnv(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF;
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
/*! @ingroup ebegin
|
/*! @ingroup ebegin
|
||||||
@ -107,8 +107,8 @@ int ewarnv (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF;
|
|||||||
*
|
*
|
||||||
* Similar to einfo, but we add ... to the end of the message */
|
* Similar to einfo, but we add ... to the end of the message */
|
||||||
/*@{*/
|
/*@{*/
|
||||||
int ebeginv (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF;
|
int ebeginv(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF;
|
||||||
int ebegin (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF;
|
int ebegin(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF;
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
/*! @ingroup eend
|
/*! @ingroup eend
|
||||||
@ -120,12 +120,12 @@ int ebegin (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF;
|
|||||||
*
|
*
|
||||||
* ebracket allows you to specifiy the position, color and message */
|
* ebracket allows you to specifiy the position, color and message */
|
||||||
/*@{*/
|
/*@{*/
|
||||||
int eend (int __retval, const char * __EINFO_RESTRICT __fmt, ...) __EEND_PRINTF;
|
int eend(int, const char * __EINFO_RESTRICT, ...) __EEND_PRINTF;
|
||||||
int ewend (int __retval, const char * __EINFO_RESTRICT __fmt, ...) __EEND_PRINTF;
|
int ewend(int, const char * __EINFO_RESTRICT, ...) __EEND_PRINTF;
|
||||||
void ebracket (int __col, einfo_color_t __color, const char * __EINFO_RESTRICT __msg);
|
void ebracket(int, ECOLOR, const char * __EINFO_RESTRICT);
|
||||||
|
|
||||||
int eendv (int __retval, const char * __EINFO_RESTRICT __fmt, ...) __EEND_PRINTF;
|
int eendv(int, const char * __EINFO_RESTRICT, ...) __EEND_PRINTF;
|
||||||
int ewendv (int __retval, const char * __EINFO_RESTRICT __fmt, ...) __EEND_PRINTF;
|
int ewendv(int, const char * __EINFO_RESTRICT, ...) __EEND_PRINTF;
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
/*! @ingroup eindent
|
/*! @ingroup eindent
|
||||||
@ -133,12 +133,12 @@ int ewendv (int __retval, const char * __EINFO_RESTRICT __fmt, ...) __EEND_PRINT
|
|||||||
*
|
*
|
||||||
* For each indent you should outdent when done */
|
* For each indent you should outdent when done */
|
||||||
/*@{*/
|
/*@{*/
|
||||||
void eindent (void);
|
void eindent(void);
|
||||||
void eoutdent (void);
|
void eoutdent(void);
|
||||||
void eindentv (void);
|
void eindentv(void);
|
||||||
void eoutdentv (void);
|
void eoutdentv(void);
|
||||||
|
|
||||||
/*! @brief Prefix each einfo line with something */
|
/*! @brief Prefix each einfo line with something */
|
||||||
void eprefix (const char * __EINFO_RESTRICT __prefix);
|
void eprefix(const char * __EINFO_RESTRICT);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
File diff suppressed because it is too large
Load Diff
4
src/librc/.gitignore
vendored
4
src/librc/.gitignore
vendored
@ -3,12 +3,12 @@ librc.o
|
|||||||
librc-daemon.o
|
librc-daemon.o
|
||||||
librc-depend.o
|
librc-depend.o
|
||||||
librc-misc.o
|
librc-misc.o
|
||||||
librc-strlist.o
|
librc-stringlist.o
|
||||||
librc.So
|
librc.So
|
||||||
librc-daemon.So
|
librc-daemon.So
|
||||||
librc-depend.So
|
librc-depend.So
|
||||||
librc-misc.So
|
librc-misc.So
|
||||||
librc-strlist.So
|
librc-stringlist.So
|
||||||
librc.a
|
librc.a
|
||||||
librc.so.1
|
librc.so.1
|
||||||
librc.so
|
librc.so
|
||||||
|
@ -4,7 +4,7 @@ include ${MK}/os.mk
|
|||||||
LIB= rc
|
LIB= rc
|
||||||
SHLIB_MAJOR= 1
|
SHLIB_MAJOR= 1
|
||||||
SRCS= librc.c librc-daemon.c librc-depend.c librc-misc.c \
|
SRCS= librc.c librc-daemon.c librc-depend.c librc-misc.c \
|
||||||
librc-strlist.c
|
librc-stringlist.c
|
||||||
INCS= rc.h
|
INCS= rc.h
|
||||||
VERSION_MAP= rc.map
|
VERSION_MAP= rc.map
|
||||||
|
|
||||||
|
@ -32,33 +32,33 @@
|
|||||||
#include "librc.h"
|
#include "librc.h"
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
static bool pid_is_cmd (pid_t pid, const char *cmd)
|
static bool pid_is_cmd(pid_t pid, const char *cmd)
|
||||||
{
|
{
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
snprintf(buffer, sizeof (buffer), "/proc/%d/stat", pid);
|
snprintf(buffer, sizeof(buffer), "/proc/%d/stat", pid);
|
||||||
if ((fp = fopen (buffer, "r")) == NULL)
|
if ((fp = fopen(buffer, "r")) == NULL)
|
||||||
return (false);
|
return false;
|
||||||
|
|
||||||
while ((c = getc (fp)) != EOF && c != '(')
|
while ((c = getc(fp)) != EOF && c != '(')
|
||||||
;
|
;
|
||||||
|
|
||||||
if (c != '(') {
|
if (c != '(') {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return (false);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((c = getc (fp)) != EOF && c == *cmd)
|
while ((c = getc(fp)) != EOF && c == *cmd)
|
||||||
cmd++;
|
cmd++;
|
||||||
|
|
||||||
fclose (fp);
|
fclose(fp);
|
||||||
|
|
||||||
return ((c == ')' && *cmd == '\0') ? true : false);
|
return (c == ')' && *cmd == '\0') ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool pid_is_exec (pid_t pid, const char *const *argv)
|
static bool pid_is_exec(pid_t pid, const char *const *argv)
|
||||||
{
|
{
|
||||||
char cmdline[32];
|
char cmdline[32];
|
||||||
char buffer[PATH_MAX];
|
char buffer[PATH_MAX];
|
||||||
@ -66,31 +66,30 @@ static bool pid_is_exec (pid_t pid, const char *const *argv)
|
|||||||
int fd = -1;
|
int fd = -1;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
/* Check it's the right binary */
|
||||||
snprintf (cmdline, sizeof (cmdline), "/proc/%u/exe", pid);
|
snprintf (cmdline, sizeof (cmdline), "/proc/%u/exe", pid);
|
||||||
memset (buffer, 0, sizeof (buffer));
|
memset (buffer, 0, sizeof (buffer));
|
||||||
#if 0
|
if (readlink(cmdline, buffer, sizeof(buffer)) != -1) {
|
||||||
if (readlink (cmdline, buffer, sizeof (buffer)) != -1) {
|
if (strcmp(*argv, buffer) == 0)
|
||||||
if (strcmp (exec, buffer) == 0)
|
return true;
|
||||||
return (true);
|
|
||||||
|
|
||||||
/* We should cater for deleted binaries too */
|
/* We should cater for deleted binaries too */
|
||||||
if (strlen (buffer) > 10) {
|
if (strlen(buffer) > 10) {
|
||||||
p = buffer + (strlen (buffer) - 10);
|
p = buffer + (strlen(buffer) - 10);
|
||||||
if (strcmp (p, " (deleted)") == 0) {
|
if (strcmp(p, " (deleted)") == 0) {
|
||||||
*p = 0;
|
*p = 0;
|
||||||
if (strcmp (buffer, exec) == 0)
|
if (strcmp(buffer, *argv) == 0)
|
||||||
return (true);
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
snprintf (cmdline, sizeof (cmdline), "/proc/%u/cmdline", pid);
|
snprintf(cmdline, sizeof(cmdline), "/proc/%u/cmdline", pid);
|
||||||
if ((fd = open (cmdline, O_RDONLY)) < 0)
|
if ((fd = open(cmdline, O_RDONLY)) < 0)
|
||||||
return (false);
|
return false;
|
||||||
|
|
||||||
r = read (fd, buffer, sizeof (buffer));
|
r = read(fd, buffer, sizeof(buffer));
|
||||||
close (fd);
|
close(fd);
|
||||||
|
|
||||||
if (r == -1)
|
if (r == -1)
|
||||||
return 0;
|
return 0;
|
||||||
@ -98,18 +97,18 @@ static bool pid_is_exec (pid_t pid, const char *const *argv)
|
|||||||
buffer[r] = 0;
|
buffer[r] = 0;
|
||||||
p = buffer;
|
p = buffer;
|
||||||
while (*argv) {
|
while (*argv) {
|
||||||
if (strcmp (*argv, p) != 0)
|
if (strcmp(*argv, p) != 0)
|
||||||
return (false);
|
return false;
|
||||||
argv++;
|
argv++;
|
||||||
p += strlen (p) + 1;
|
p += strlen(p) + 1;
|
||||||
if ((unsigned) (p - buffer) > sizeof (buffer))
|
if ((unsigned) (p - buffer) > sizeof (buffer))
|
||||||
return (false);
|
return false;
|
||||||
}
|
}
|
||||||
return (true);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t *rc_find_pids (const char *const *argv, const char *cmd,
|
pid_t *rc_find_pids(const char *const *argv, const char *cmd,
|
||||||
uid_t uid, pid_t pid)
|
uid_t uid, pid_t pid)
|
||||||
{
|
{
|
||||||
DIR *procdir;
|
DIR *procdir;
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
@ -122,8 +121,8 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
|
|||||||
pid_t runscript_pid = 0;
|
pid_t runscript_pid = 0;
|
||||||
char *pp;
|
char *pp;
|
||||||
|
|
||||||
if ((procdir = opendir ("/proc")) == NULL)
|
if ((procdir = opendir("/proc")) == NULL)
|
||||||
return (NULL);
|
return NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We never match RC_RUNSCRIPT_PID if present so we avoid the below
|
We never match RC_RUNSCRIPT_PID if present so we avoid the below
|
||||||
@ -136,13 +135,13 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
|
|||||||
nasty
|
nasty
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((pp = getenv ("RC_RUNSCRIPT_PID"))) {
|
if ((pp = getenv("RC_RUNSCRIPT_PID"))) {
|
||||||
if (sscanf (pp, "%d", &runscript_pid) != 1)
|
if (sscanf(pp, "%d", &runscript_pid) != 1)
|
||||||
runscript_pid = 0;
|
runscript_pid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((entry = readdir (procdir)) != NULL) {
|
while ((entry = readdir(procdir)) != NULL) {
|
||||||
if (sscanf (entry->d_name, "%d", &p) != 1)
|
if (sscanf(entry->d_name, "%d", &p) != 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (runscript_pid != 0 && runscript_pid == p)
|
if (runscript_pid != 0 && runscript_pid == p)
|
||||||
@ -152,23 +151,23 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (uid) {
|
if (uid) {
|
||||||
snprintf (buffer, sizeof (buffer), "/proc/%d", p);
|
snprintf(buffer, sizeof(buffer), "/proc/%d", p);
|
||||||
if (stat (buffer, &sb) != 0 || sb.st_uid != uid)
|
if (stat(buffer, &sb) != 0 || sb.st_uid != uid)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd && ! pid_is_cmd (p, cmd))
|
if (cmd && ! pid_is_cmd(p, cmd))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (argv && ! cmd && ! pid_is_exec (p, (const char *const *)argv))
|
if (argv && ! cmd && ! pid_is_exec(p, (const char *const *)argv))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
tmp = realloc (pids, sizeof (pid_t) * (npids + 2));
|
tmp = realloc(pids, sizeof (pid_t) * (npids + 2));
|
||||||
if (! tmp) {
|
if (! tmp) {
|
||||||
free (pids);
|
free(pids);
|
||||||
closedir (procdir);
|
closedir(procdir);
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return (NULL);
|
return NULL;
|
||||||
}
|
}
|
||||||
pids = tmp;
|
pids = tmp;
|
||||||
|
|
||||||
@ -176,9 +175,9 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
|
|||||||
pids[npids + 1] = 0;
|
pids[npids + 1] = 0;
|
||||||
npids++;
|
npids++;
|
||||||
}
|
}
|
||||||
closedir (procdir);
|
closedir(procdir);
|
||||||
|
|
||||||
return (pids);
|
return pids;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_find_pids)
|
librc_hidden_def(rc_find_pids)
|
||||||
|
|
||||||
@ -206,8 +205,8 @@ librc_hidden_def(rc_find_pids)
|
|||||||
# define _KVM_FLAGS O_RDONLY
|
# define _KVM_FLAGS O_RDONLY
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
pid_t *rc_find_pids (const char *const *argv, const char *cmd,
|
pid_t *rc_find_pids(const char *const *argv, const char *cmd,
|
||||||
uid_t uid, pid_t pid)
|
uid_t uid, pid_t pid)
|
||||||
{
|
{
|
||||||
static kvm_t *kd = NULL;
|
static kvm_t *kd = NULL;
|
||||||
char errbuf[_POSIX2_LINE_MAX];
|
char errbuf[_POSIX2_LINE_MAX];
|
||||||
@ -218,44 +217,45 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
|
|||||||
char **pargv;
|
char **pargv;
|
||||||
pid_t *pids = NULL;
|
pid_t *pids = NULL;
|
||||||
pid_t *tmp;
|
pid_t *tmp;
|
||||||
|
pid_t p;
|
||||||
const char *const *arg;
|
const char *const *arg;
|
||||||
int npids = 0;
|
int npids = 0;
|
||||||
int match;
|
int match;
|
||||||
|
|
||||||
if ((kd = kvm_openfiles (_KVM_PATH, _KVM_PATH,
|
if ((kd = kvm_openfiles(_KVM_PATH, _KVM_PATH,
|
||||||
NULL, _KVM_FLAGS, errbuf)) == NULL)
|
NULL, _KVM_FLAGS, errbuf)) == NULL)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "kvm_open: %s\n", errbuf);
|
fprintf(stderr, "kvm_open: %s\n", errbuf);
|
||||||
return (NULL);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _KVM_GETPROC2
|
#ifdef _KVM_GETPROC2
|
||||||
kp = kvm_getproc2 (kd, KERN_PROC_ALL, 0, sizeof(*kp), &processes);
|
kp = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(*kp), &processes);
|
||||||
#else
|
#else
|
||||||
kp = kvm_getprocs (kd, KERN_PROC_PROC, 0, &processes);
|
kp = kvm_getprocs(kd, KERN_PROC_PROC, 0, &processes);
|
||||||
#endif
|
#endif
|
||||||
if ((kp == NULL && processes > 0) || (kp != NULL && processes < 0)) {
|
if ((kp == NULL && processes > 0) || (kp != NULL && processes < 0)) {
|
||||||
fprintf (stderr, "kvm_getprocs: %s\n", kvm_geterr (kd));
|
fprintf(stderr, "kvm_getprocs: %s\n", kvm_geterr(kd));
|
||||||
kvm_close (kd);
|
kvm_close(kd);
|
||||||
return (NULL);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < processes; i++) {
|
for (i = 0; i < processes; i++) {
|
||||||
pid_t p = _GET_KINFO_PID (kp[i]);
|
p = _GET_KINFO_PID(kp[i]);
|
||||||
if (pid != 0 && pid != p)
|
if (pid != 0 && pid != p)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (uid != 0 && uid != _GET_KINFO_UID (kp[i]))
|
if (uid != 0 && uid != _GET_KINFO_UID(kp[i]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (cmd) {
|
if (cmd) {
|
||||||
if (! _GET_KINFO_COMM (kp[i]) ||
|
if (! _GET_KINFO_COMM(kp[i]) ||
|
||||||
strcmp (cmd, _GET_KINFO_COMM (kp[i])) != 0)
|
strcmp(cmd, _GET_KINFO_COMM(kp[i])) != 0)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argv && *argv && ! cmd) {
|
if (argv && *argv && ! cmd) {
|
||||||
pargv = _KVM_GETARGV (kd, &kp[i], pargc);
|
pargv = _KVM_GETARGV(kd, &kp[i], pargc);
|
||||||
if (! pargv || ! *pargv)
|
if (! pargv || ! *pargv)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -263,7 +263,7 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
|
|||||||
match = 1;
|
match = 1;
|
||||||
|
|
||||||
while (*arg && *pargv)
|
while (*arg && *pargv)
|
||||||
if (strcmp (*arg++, *pargv++) != 0) {
|
if (strcmp(*arg++, *pargv++) != 0) {
|
||||||
match = 0;
|
match = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -272,12 +272,12 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = realloc (pids, sizeof (pid_t) * (npids + 2));
|
tmp = realloc(pids, sizeof(pid_t) * (npids + 2));
|
||||||
if (! tmp) {
|
if (! tmp) {
|
||||||
free (pids);
|
free(pids);
|
||||||
kvm_close (kd);
|
kvm_close(kd);
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return (NULL);
|
return NULL;
|
||||||
}
|
}
|
||||||
pids = tmp;
|
pids = tmp;
|
||||||
|
|
||||||
@ -285,9 +285,9 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd,
|
|||||||
pids[npids + 1] = 0;
|
pids[npids + 1] = 0;
|
||||||
npids++;
|
npids++;
|
||||||
}
|
}
|
||||||
kvm_close (kd);
|
kvm_close(kd);
|
||||||
|
|
||||||
return (pids);
|
return pids;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_find_pids)
|
librc_hidden_def(rc_find_pids)
|
||||||
|
|
||||||
@ -295,67 +295,72 @@ librc_hidden_def(rc_find_pids)
|
|||||||
# error "Platform not supported!"
|
# error "Platform not supported!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool _match_daemon (const char *path, const char *file, char **match)
|
static bool _match_daemon(const char *path, const char *file,
|
||||||
|
RC_STRINGLIST *match)
|
||||||
{
|
{
|
||||||
char *line;
|
char *line;
|
||||||
char *ffile = rc_strcatpaths (path, file, (char *) NULL);
|
char *ffile = rc_strcatpaths(path, file, (char *) NULL);
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
RC_STRING *m;
|
||||||
|
|
||||||
fp = fopen (ffile, "r");
|
fp = fopen(ffile, "r");
|
||||||
free (ffile);
|
free(ffile);
|
||||||
|
|
||||||
if (! fp)
|
if (! fp)
|
||||||
return (false);
|
return false;
|
||||||
|
|
||||||
while ((line = rc_getline (fp))) {
|
while ((line = rc_getline(fp))) {
|
||||||
rc_strlist_delete (&match, line);
|
TAILQ_FOREACH(m, match, entries)
|
||||||
if (! match || !*match)
|
if (strcmp(line, m->value) == 0) {
|
||||||
|
TAILQ_REMOVE(match, m, entries);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (! TAILQ_FIRST(match))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fclose (fp);
|
fclose(fp);
|
||||||
if (match && *match)
|
if (TAILQ_FIRST(match))
|
||||||
return (false);
|
return false;
|
||||||
return (true);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char **_match_list (const char* const* argv,
|
static RC_STRINGLIST *_match_list(const char* const* argv,
|
||||||
const char *name, const char *pidfile)
|
const char *name, const char *pidfile)
|
||||||
{
|
{
|
||||||
char **match = NULL;
|
RC_STRINGLIST *match = rc_stringlist_new();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
size_t l;
|
size_t l;
|
||||||
char *m;
|
char *m;
|
||||||
|
|
||||||
while (argv && argv[i]) {
|
while (argv && argv[i]) {
|
||||||
l = strlen (*argv) + strlen ("argv_=") + 16;
|
l = strlen(*argv) + strlen("argv_=") + 16;
|
||||||
m = xmalloc (sizeof (char) * l);
|
m = xmalloc(sizeof(char) * l);
|
||||||
snprintf (m, l, "argv_0=%s", argv[i++]);
|
snprintf(m, l, "argv_0=%s", argv[i++]);
|
||||||
rc_strlist_add (&match, m);
|
rc_stringlist_add(match, m);
|
||||||
free (m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
l = strlen (name) + 6;
|
l = strlen(name) + 6;
|
||||||
m = xmalloc (sizeof (char) * l);
|
m = xmalloc(sizeof (char) * l);
|
||||||
snprintf (m, l, "name=%s", name);
|
snprintf(m, l, "name=%s", name);
|
||||||
rc_strlist_add (&match, m);
|
rc_stringlist_add(match, m);
|
||||||
free (m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pidfile) {
|
if (pidfile) {
|
||||||
l = strlen (pidfile) + 9;
|
l = strlen(pidfile) + 9;
|
||||||
m = xmalloc (sizeof (char) * l);
|
m = xmalloc(sizeof (char) * l);
|
||||||
snprintf (m, l, "pidfile=%s", pidfile);
|
snprintf(m, l, "pidfile=%s", pidfile);
|
||||||
rc_strlist_add (&match, m);
|
rc_stringlist_add(match, m);
|
||||||
free (m);
|
free (m);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (match);
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rc_service_daemon_set (const char *service, const char *const *argv,
|
bool rc_service_daemon_set(const char *service, const char *const *argv,
|
||||||
const char *name, const char *pidfile,
|
const char *name, const char *pidfile, bool started)
|
||||||
bool started)
|
|
||||||
{
|
{
|
||||||
char *dirpath;
|
char *dirpath;
|
||||||
char *file = NULL;
|
char *file = NULL;
|
||||||
@ -364,123 +369,123 @@ bool rc_service_daemon_set (const char *service, const char *const *argv,
|
|||||||
bool retval = false;
|
bool retval = false;
|
||||||
DIR *dp;
|
DIR *dp;
|
||||||
struct dirent *d;
|
struct dirent *d;
|
||||||
char **match = NULL;
|
RC_STRINGLIST *match;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
char buffer[10];
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
if (! (argv && *argv) && ! name && ! pidfile) {
|
if (!(argv && *argv) && ! name && ! pidfile) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return (false);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dirpath = rc_strcatpaths (RC_SVCDIR, "daemons",
|
dirpath = rc_strcatpaths(RC_SVCDIR, "daemons",
|
||||||
basename_c (service), (char *) NULL);
|
basename_c(service), (char *) NULL);
|
||||||
|
|
||||||
match = _match_list (argv, name, pidfile);
|
match = _match_list(argv, name, pidfile);
|
||||||
|
|
||||||
/* Regardless, erase any existing daemon info */
|
/* Regardless, erase any existing daemon info */
|
||||||
if ((dp = opendir (dirpath))) {
|
if ((dp = opendir(dirpath))) {
|
||||||
while ((d = readdir (dp))) {
|
while ((d = readdir(dp))) {
|
||||||
if (d->d_name[0] == '.')
|
if (d->d_name[0] == '.')
|
||||||
continue;
|
continue;
|
||||||
file = rc_strcatpaths (dirpath, d->d_name, (char *) NULL);
|
file = rc_strcatpaths(dirpath, d->d_name, (char *) NULL);
|
||||||
nfiles++;
|
nfiles++;
|
||||||
|
|
||||||
if (! oldfile) {
|
if (! oldfile) {
|
||||||
if (_match_daemon (dirpath, d->d_name, match)) {
|
if (_match_daemon(dirpath, d->d_name, match)) {
|
||||||
unlink (file);
|
unlink (file);
|
||||||
oldfile = file;
|
oldfile = file;
|
||||||
nfiles--;
|
nfiles--;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rename (file, oldfile);
|
rename(file, oldfile);
|
||||||
free (oldfile);
|
free(oldfile);
|
||||||
oldfile = file;
|
oldfile = file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free (file);
|
free(file);
|
||||||
closedir (dp);
|
closedir(dp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now store our daemon info */
|
/* Now store our daemon info */
|
||||||
if (started) {
|
if (started) {
|
||||||
char buffer[10];
|
if (mkdir(dirpath, 0755) == 0 || errno == EEXIST) {
|
||||||
FILE *fp;
|
snprintf(buffer, sizeof(buffer), "%03d", nfiles + 1);
|
||||||
|
file = rc_strcatpaths(dirpath, buffer, (char *) NULL);
|
||||||
if (mkdir (dirpath, 0755) == 0 || errno == EEXIST) {
|
if ((fp = fopen(file, "w"))) {
|
||||||
snprintf (buffer, sizeof (buffer), "%03d", nfiles + 1);
|
|
||||||
file = rc_strcatpaths (dirpath, buffer, (char *) NULL);
|
|
||||||
if ((fp = fopen (file, "w"))) {
|
|
||||||
while (argv && argv[i]) {
|
while (argv && argv[i]) {
|
||||||
fprintf (fp, "argv_%d=%s\n", i, argv[i]);
|
fprintf(fp, "argv_%d=%s\n", i, argv[i]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
fprintf (fp, "name=");
|
fprintf(fp, "name=");
|
||||||
if (name)
|
if (name)
|
||||||
fprintf (fp, "%s", name);
|
fprintf(fp, "%s", name);
|
||||||
fprintf (fp, "\npidfile=");
|
fprintf(fp, "\npidfile=");
|
||||||
if (pidfile)
|
if (pidfile)
|
||||||
fprintf (fp, "%s", pidfile);
|
fprintf(fp, "%s", pidfile);
|
||||||
fprintf (fp, "\n");
|
fprintf(fp, "\n");
|
||||||
fclose (fp);
|
fclose(fp);
|
||||||
retval = true;
|
retval = true;
|
||||||
}
|
}
|
||||||
free (file);
|
free(file);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
rc_strlist_free (match);
|
rc_stringlist_free(match);
|
||||||
free (dirpath);
|
free(dirpath);
|
||||||
|
|
||||||
return (retval);
|
return retval;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_daemon_set)
|
librc_hidden_def(rc_service_daemon_set)
|
||||||
|
|
||||||
bool rc_service_started_daemon (const char *service, const char *const *argv,
|
bool
|
||||||
int indx)
|
rc_service_started_daemon (const char *service, const char *const *argv,
|
||||||
|
int indx)
|
||||||
{
|
{
|
||||||
char *dirpath;
|
char *dirpath;
|
||||||
char *file;
|
char *file;
|
||||||
size_t l;
|
size_t l;
|
||||||
char **match;
|
RC_STRINGLIST *match;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
DIR *dp;
|
DIR *dp;
|
||||||
struct dirent *d;
|
struct dirent *d;
|
||||||
|
|
||||||
if (! service || ! (argv && *argv))
|
if (!service || !(argv && *argv))
|
||||||
return (false);
|
return false;
|
||||||
|
|
||||||
dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename_c (service),
|
dirpath = rc_strcatpaths(RC_SVCDIR, "daemons", basename_c(service),
|
||||||
(char *) NULL);
|
(char *) NULL);
|
||||||
|
|
||||||
match = _match_list (argv, NULL, NULL);
|
match = _match_list(argv, NULL, NULL);
|
||||||
|
|
||||||
if (indx > 0) {
|
if (indx > 0) {
|
||||||
l = sizeof (char) * 10;
|
l = sizeof (char) * 10;
|
||||||
file = xmalloc (l);
|
file = xmalloc(l);
|
||||||
snprintf (file, l, "%03d", indx);
|
snprintf(file, l, "%03d", indx);
|
||||||
retval = _match_daemon (dirpath, file, match);
|
retval = _match_daemon(dirpath, file, match);
|
||||||
free (file);
|
free(file);
|
||||||
} else {
|
} else {
|
||||||
if ((dp = opendir (dirpath))) {
|
if ((dp = opendir(dirpath))) {
|
||||||
while ((d = readdir (dp))) {
|
while ((d = readdir(dp))) {
|
||||||
if (d->d_name[0] == '.')
|
if (d->d_name[0] == '.')
|
||||||
continue;
|
continue;
|
||||||
retval = _match_daemon (dirpath, d->d_name, match);
|
retval = _match_daemon(dirpath, d->d_name, match);
|
||||||
if (retval)
|
if (retval)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
closedir (dp);
|
closedir(dp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free (dirpath);
|
free(dirpath);
|
||||||
rc_strlist_free (match);
|
rc_stringlist_free(match);
|
||||||
return (retval);
|
return retval;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_started_daemon)
|
librc_hidden_def(rc_service_started_daemon)
|
||||||
|
|
||||||
bool rc_service_daemons_crashed (const char *service)
|
bool rc_service_daemons_crashed(const char *service)
|
||||||
{
|
{
|
||||||
char *dirpath;
|
char *dirpath;
|
||||||
DIR *dp;
|
DIR *dp;
|
||||||
@ -497,116 +502,123 @@ bool rc_service_daemons_crashed (const char *service)
|
|||||||
char *p;
|
char *p;
|
||||||
char *token;
|
char *token;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
RC_STRINGLIST *list;
|
||||||
|
RC_STRING *s;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
if (! service)
|
dirpath = rc_strcatpaths(RC_SVCDIR, "daemons", basename_c(service),
|
||||||
return (false);
|
(char *) NULL);
|
||||||
|
|
||||||
dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename_c (service),
|
if (! (dp = opendir(dirpath))) {
|
||||||
(char *) NULL);
|
free(dirpath);
|
||||||
|
return false;
|
||||||
if (! (dp = opendir (dirpath))) {
|
|
||||||
free (dirpath);
|
|
||||||
return (false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((d = readdir (dp))) {
|
while ((d = readdir(dp))) {
|
||||||
if (d->d_name[0] == '.')
|
if (d->d_name[0] == '.')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
path = rc_strcatpaths (dirpath, d->d_name, (char *) NULL);
|
path = rc_strcatpaths(dirpath, d->d_name, (char *) NULL);
|
||||||
fp = fopen (path, "r");
|
fp = fopen(path, "r");
|
||||||
free (path);
|
free(path);
|
||||||
if (! fp)
|
if (! fp)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
while ((line = rc_getline (fp))) {
|
list = rc_stringlist_new();
|
||||||
|
|
||||||
|
while ((line = rc_getline(fp))) {
|
||||||
p = line;
|
p = line;
|
||||||
if ((token = strsep (&p, "=")) == NULL || ! p) {
|
if ((token = strsep(&p, "=")) == NULL || ! p) {
|
||||||
free (line);
|
free(line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen (p) == 0) {
|
if (! *p) {
|
||||||
free (line);
|
free(line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp (token, "argv_", 5) == 0) {
|
if (strncmp(token, "argv_", 5) == 0) {
|
||||||
rc_strlist_add (&argv, p);
|
rc_stringlist_add(list, p);
|
||||||
} else if (strcmp (token, "exec") == 0) {
|
} else if (strcmp(token, "exec") == 0) {
|
||||||
if (exec)
|
if (exec)
|
||||||
free (exec);
|
free(exec);
|
||||||
exec = xstrdup (p);
|
exec = xstrdup(p);
|
||||||
} else if (strcmp (token, "name") == 0) {
|
} else if (strcmp(token, "name") == 0) {
|
||||||
if (name)
|
if (name)
|
||||||
free (name);
|
free(name);
|
||||||
name = xstrdup (p);
|
name = xstrdup(p);
|
||||||
} else if (strcmp (token, "pidfile") == 0) {
|
} else if (strcmp(token, "pidfile") == 0) {
|
||||||
if (pidfile)
|
if (pidfile)
|
||||||
free (pidfile);
|
free(pidfile);
|
||||||
pidfile = xstrdup (p);
|
pidfile = xstrdup(p);
|
||||||
}
|
}
|
||||||
free (line);
|
free(line);
|
||||||
}
|
}
|
||||||
fclose (fp);
|
fclose(fp);
|
||||||
|
|
||||||
pid = 0;
|
pid = 0;
|
||||||
if (pidfile) {
|
if (pidfile) {
|
||||||
if (! exists (pidfile)) {
|
if (! exists(pidfile)) {
|
||||||
retval = true;
|
retval = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fp = fopen (pidfile, "r")) == NULL) {
|
if ((fp = fopen(pidfile, "r")) == NULL) {
|
||||||
retval = true;
|
retval = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fscanf (fp, "%d", &pid) != 1) {
|
if (fscanf(fp, "%d", &pid) != 1) {
|
||||||
fclose (fp);
|
fclose (fp);
|
||||||
retval = true;
|
retval = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose (fp);
|
fclose(fp);
|
||||||
free (pidfile);
|
free(pidfile);
|
||||||
pidfile = NULL;
|
pidfile = NULL;
|
||||||
|
|
||||||
/* We have the pid, so no need to match on name */
|
/* We have the pid, so no need to match on name */
|
||||||
rc_strlist_free (argv);
|
rc_stringlist_free(list);
|
||||||
argv = NULL;
|
list = NULL;
|
||||||
free (exec);
|
free (exec);
|
||||||
exec = NULL;
|
exec = NULL;
|
||||||
free (name);
|
free (name);
|
||||||
name = NULL;
|
name = NULL;
|
||||||
}
|
} else {
|
||||||
|
if (exec && ! TAILQ_FIRST(list)) {
|
||||||
if (exec && ! argv) {
|
rc_stringlist_add(list, exec);
|
||||||
rc_strlist_add (&argv, exec);
|
}
|
||||||
free (exec);
|
free(exec);
|
||||||
exec = NULL;
|
exec = NULL;
|
||||||
|
|
||||||
|
/* We need to flatten our linked list into an array */
|
||||||
|
i = 0;
|
||||||
|
TAILQ_FOREACH(s, list, entries)
|
||||||
|
i++;
|
||||||
|
argv = xmalloc(sizeof(char *) * (i + 1));
|
||||||
|
i = 0;
|
||||||
|
TAILQ_FOREACH(s, list, entries)
|
||||||
|
argv[i++] = s->value;
|
||||||
|
argv[i] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pids = rc_find_pids ((const char *const *)argv, name, 0, pid)) == NULL) {
|
if ((pids = rc_find_pids((const char *const *)argv, name, 0, pid)) == NULL)
|
||||||
retval = true;
|
retval = true;
|
||||||
break;
|
free(pids);
|
||||||
}
|
free(argv);
|
||||||
free (pids);
|
|
||||||
|
|
||||||
rc_strlist_free (argv);
|
|
||||||
argv = NULL;
|
argv = NULL;
|
||||||
free (exec);
|
rc_stringlist_free(list);
|
||||||
exec = NULL;
|
free(name);
|
||||||
free (name);
|
|
||||||
name = NULL;
|
name = NULL;
|
||||||
|
if (retval)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_strlist_free (argv);
|
free(dirpath);
|
||||||
free (exec);
|
closedir(dp);
|
||||||
free (name);
|
|
||||||
free (dirpath);
|
|
||||||
closedir (dp);
|
|
||||||
|
|
||||||
return (retval);
|
return retval;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_daemons_crashed)
|
librc_hidden_def(rc_service_daemons_crashed)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* librc-depend.h
|
|
||||||
* Internal header file for dependency structures
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2007-2008 Roy Marples
|
|
||||||
* All rights reserved
|
|
||||||
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _LIBRC_DEPEND_H
|
|
||||||
#define _LIBRC_DEPEND_H
|
|
||||||
|
|
||||||
/*! @name Dependency structures
|
|
||||||
* private to librc - rc.h exposes them just a pointers */
|
|
||||||
|
|
||||||
/*! Singly linked list of dependency types that list the services the
|
|
||||||
* type is for */
|
|
||||||
typedef struct rc_deptype
|
|
||||||
{
|
|
||||||
/*! ineed, iuse, iafter, etc */
|
|
||||||
char *type;
|
|
||||||
/*! NULL terminated list of services */
|
|
||||||
char **services;
|
|
||||||
/*! Next dependency type */
|
|
||||||
struct rc_deptype *next;
|
|
||||||
} rc_deptype_t;
|
|
||||||
|
|
||||||
/*! Singly linked list of services and their dependencies */
|
|
||||||
typedef struct rc_depinfo
|
|
||||||
{
|
|
||||||
/*! Name of service */
|
|
||||||
char *service;
|
|
||||||
/*! Dependencies */
|
|
||||||
rc_deptype_t *depends;
|
|
||||||
/*! Next service dependency type */
|
|
||||||
struct rc_depinfo *next;
|
|
||||||
} rc_depinfo_t;
|
|
||||||
|
|
||||||
#endif
|
|
@ -35,14 +35,14 @@ bool rc_yesno (const char *value)
|
|||||||
{
|
{
|
||||||
if (! value) {
|
if (! value) {
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
return (false);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcasecmp (value, "yes") == 0 ||
|
if (strcasecmp (value, "yes") == 0 ||
|
||||||
strcasecmp (value, "y") == 0 ||
|
strcasecmp (value, "y") == 0 ||
|
||||||
strcasecmp (value, "true") == 0 ||
|
strcasecmp (value, "true") == 0 ||
|
||||||
strcasecmp (value, "1") == 0)
|
strcasecmp (value, "1") == 0)
|
||||||
return (true);
|
return true;
|
||||||
|
|
||||||
if (strcasecmp (value, "no") != 0 &&
|
if (strcasecmp (value, "no") != 0 &&
|
||||||
strcasecmp (value, "n") != 0 &&
|
strcasecmp (value, "n") != 0 &&
|
||||||
@ -50,7 +50,7 @@ bool rc_yesno (const char *value)
|
|||||||
strcasecmp (value, "0") != 0)
|
strcasecmp (value, "0") != 0)
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
|
|
||||||
return (false);
|
return false;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_yesno)
|
librc_hidden_def(rc_yesno)
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ char *rc_strcatpaths (const char *path1, const char *paths, ...)
|
|||||||
char *pathp;
|
char *pathp;
|
||||||
|
|
||||||
if (! path1 || ! paths)
|
if (! path1 || ! paths)
|
||||||
return (NULL);
|
return NULL;
|
||||||
|
|
||||||
length = strlen (path1) + strlen (paths) + 1;
|
length = strlen (path1) + strlen (paths) + 1;
|
||||||
if (*paths != '/')
|
if (*paths != '/')
|
||||||
@ -101,7 +101,7 @@ char *rc_strcatpaths (const char *path1, const char *paths, ...)
|
|||||||
|
|
||||||
*pathp++ = 0;
|
*pathp++ = 0;
|
||||||
|
|
||||||
return (path);
|
return path;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_strcatpaths)
|
librc_hidden_def(rc_strcatpaths)
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ char *rc_getline (FILE *fp)
|
|||||||
size_t last = 0;
|
size_t last = 0;
|
||||||
|
|
||||||
if (feof (fp))
|
if (feof (fp))
|
||||||
return (NULL);
|
return NULL;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
len += BUFSIZ;
|
len += BUFSIZ;
|
||||||
@ -128,74 +128,78 @@ char *rc_getline (FILE *fp)
|
|||||||
if (*line && line[--last] == '\n')
|
if (*line && line[--last] == '\n')
|
||||||
line[last] = '\0';
|
line[last] = '\0';
|
||||||
|
|
||||||
return (line);
|
return line;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_getline)
|
librc_hidden_def(rc_getline)
|
||||||
|
|
||||||
char **rc_config_list (const char *file)
|
RC_STRINGLIST *rc_config_list(const char *file)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
char *p;
|
char *p;
|
||||||
char *token;
|
char *token;
|
||||||
char **list = NULL;
|
RC_STRINGLIST *list;
|
||||||
|
|
||||||
if (! (fp = fopen (file, "r")))
|
if (!(fp = fopen(file, "r")))
|
||||||
return (NULL);
|
return NULL;
|
||||||
|
|
||||||
while ((p = buffer = rc_getline (fp))) {
|
list = rc_stringlist_new();
|
||||||
|
|
||||||
|
while ((p = buffer = rc_getline(fp))) {
|
||||||
/* Strip leading spaces/tabs */
|
/* Strip leading spaces/tabs */
|
||||||
while ((*p == ' ') || (*p == '\t'))
|
while ((*p == ' ') || (*p == '\t'))
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
/* Get entry - we do not want comments */
|
/* Get entry - we do not want comments */
|
||||||
token = strsep (&p, "#");
|
token = strsep(&p, "#");
|
||||||
if (token && (strlen (token) > 1)) {
|
if (token && (strlen(token) > 1)) {
|
||||||
/* If not variable assignment then skip */
|
/* If not variable assignment then skip */
|
||||||
if (strchr (token, '=')) {
|
if (strchr(token, '=')) {
|
||||||
/* Stip the newline if present */
|
/* Stip the newline if present */
|
||||||
if (token[strlen (token) - 1] == '\n')
|
if (token[strlen(token) - 1] == '\n')
|
||||||
token[strlen (token) - 1] = 0;
|
token[strlen(token) - 1] = 0;
|
||||||
|
|
||||||
rc_strlist_add (&list, token);
|
rc_stringlist_add(list, token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free (buffer);
|
free(buffer);
|
||||||
}
|
}
|
||||||
fclose (fp);
|
fclose(fp);
|
||||||
|
|
||||||
return (list);
|
return list;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_config_list)
|
librc_hidden_def(rc_config_list)
|
||||||
|
|
||||||
char **rc_config_load (const char *file)
|
RC_STRINGLIST *rc_config_load(const char *file)
|
||||||
{
|
{
|
||||||
char **list = NULL;
|
RC_STRINGLIST *list = NULL;
|
||||||
char **config = NULL;
|
RC_STRINGLIST *config = NULL;
|
||||||
char *token;
|
char *token;
|
||||||
char *line;
|
RC_STRING *line;
|
||||||
char *linep;
|
RC_STRING *cline;
|
||||||
char *linetok;
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
int j;
|
|
||||||
bool replaced;
|
bool replaced;
|
||||||
char *entry;
|
char *entry;
|
||||||
char *newline;
|
char *newline;
|
||||||
|
char *p;
|
||||||
|
|
||||||
list = rc_config_list (file);
|
config = rc_stringlist_new();
|
||||||
STRLIST_FOREACH (list, line, j) {
|
|
||||||
|
list = rc_config_list(file);
|
||||||
|
TAILQ_FOREACH(line, list, entries) {
|
||||||
/* Get entry */
|
/* Get entry */
|
||||||
if (! (token = strsep (&line, "=")))
|
p = line->value;
|
||||||
|
if (! (token = strsep(&p, "=")))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
entry = xstrdup (token);
|
entry = xstrdup (token);
|
||||||
/* Preserve shell coloring */
|
/* Preserve shell coloring */
|
||||||
if (*line == '$')
|
if (*p == '$')
|
||||||
token = line;
|
token = line->value;
|
||||||
else
|
else
|
||||||
do {
|
do {
|
||||||
/* Bash variables are usually quoted */
|
/* Bash variables are usually quoted */
|
||||||
token = strsep (&line, "\"\'");
|
token = strsep(&p, "\"\'");
|
||||||
} while (token && *token == '\0');
|
} while (token && *token == '\0');
|
||||||
|
|
||||||
/* Drop a newline if that's all we have */
|
/* Drop a newline if that's all we have */
|
||||||
@ -205,57 +209,54 @@ char **rc_config_load (const char *file)
|
|||||||
token[i] = 0;
|
token[i] = 0;
|
||||||
|
|
||||||
i = strlen (entry) + strlen (token) + 2;
|
i = strlen (entry) + strlen (token) + 2;
|
||||||
newline = xmalloc (sizeof (char) * i);
|
newline = xmalloc(sizeof(char) * i);
|
||||||
snprintf (newline, i, "%s=%s", entry, token);
|
snprintf(newline, i, "%s=%s", entry, token);
|
||||||
} else {
|
} else {
|
||||||
i = strlen (entry) + 2;
|
i = strlen (entry) + 2;
|
||||||
newline = xmalloc (sizeof (char) * i);
|
newline = xmalloc(sizeof(char) * i);
|
||||||
snprintf (newline, i, "%s=", entry);
|
snprintf(newline, i, "%s=", entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
replaced = false;
|
replaced = false;
|
||||||
/* In shells the last item takes precedence, so we need to remove
|
/* In shells the last item takes precedence, so we need to remove
|
||||||
any prior values we may already have */
|
any prior values we may already have */
|
||||||
STRLIST_FOREACH (config, line, i) {
|
TAILQ_FOREACH(cline, config, entries) {
|
||||||
char *tmp = xstrdup (line);
|
p = strchr(cline->value, '=');
|
||||||
linep = tmp;
|
if (p && strncmp(entry, cline->value,
|
||||||
linetok = strsep (&linep, "=");
|
(size_t) (p - cline->value)) == 0)
|
||||||
if (strcmp (linetok, entry) == 0) {
|
{
|
||||||
/* We have a match now - to save time we directly replace it */
|
/* We have a match now - to save time we directly replace it */
|
||||||
free (config[i - 1]);
|
free(cline->value);
|
||||||
config[i - 1] = newline;
|
cline->value = newline;
|
||||||
replaced = true;
|
replaced = true;
|
||||||
free (tmp);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
free (tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! replaced) {
|
if (! replaced) {
|
||||||
rc_strlist_addsort (&config, newline);
|
rc_stringlist_add(config, newline);
|
||||||
free (newline);
|
free(newline);
|
||||||
}
|
}
|
||||||
free (entry);
|
free(entry);
|
||||||
}
|
}
|
||||||
rc_strlist_free (list);
|
rc_stringlist_free(list);
|
||||||
|
|
||||||
return (config);
|
return config;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_config_load)
|
librc_hidden_def(rc_config_load)
|
||||||
|
|
||||||
char *rc_config_value (const char *const *list, const char *entry)
|
char *rc_config_value(RC_STRINGLIST *list, const char *entry)
|
||||||
{
|
{
|
||||||
const char *line;
|
RC_STRING *line;
|
||||||
int i;
|
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
STRLIST_FOREACH (list, line, i) {
|
TAILQ_FOREACH(line, list, entries) {
|
||||||
p = strchr (line, '=');
|
p = strchr(line->value, '=');
|
||||||
if (p && strncmp (entry, line, (size_t) (p - line)) == 0)
|
if (p &&
|
||||||
return (p += 1);
|
strncmp(entry, line->value, (size_t)(p - line->value)) == 0)
|
||||||
|
return p += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (NULL);
|
return NULL;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_config_value)
|
librc_hidden_def(rc_config_value)
|
||||||
|
|
||||||
|
@ -1,230 +0,0 @@
|
|||||||
/*
|
|
||||||
librc-strlist.h
|
|
||||||
String list functions for using char ** arrays
|
|
||||||
|
|
||||||
Based on a previous implementation by Martin Schlemmer
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2007-2008 Roy Marples
|
|
||||||
* All rights reserved
|
|
||||||
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "librc.h"
|
|
||||||
|
|
||||||
static char *_rc_strlist_add (char ***list, const char *item, bool uniq)
|
|
||||||
{
|
|
||||||
char **newlist;
|
|
||||||
char **lst = *list;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if (! item)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
while (lst && lst[i]) {
|
|
||||||
if (uniq && strcmp (lst[i], item) == 0) {
|
|
||||||
errno = EEXIST;
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
newlist = xrealloc (lst, sizeof (char *) * (i + 2));
|
|
||||||
newlist[i] = xstrdup (item);
|
|
||||||
newlist[i + 1] = NULL;
|
|
||||||
|
|
||||||
*list = newlist;
|
|
||||||
return (newlist[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *rc_strlist_add (char ***list, const char *item)
|
|
||||||
{
|
|
||||||
return (_rc_strlist_add (list, item, false));
|
|
||||||
}
|
|
||||||
librc_hidden_def(rc_strlist_add)
|
|
||||||
|
|
||||||
char *rc_strlist_addu (char ***list, const char *item)
|
|
||||||
{
|
|
||||||
return (_rc_strlist_add (list, item, true));
|
|
||||||
}
|
|
||||||
librc_hidden_def(rc_strlist_addu)
|
|
||||||
|
|
||||||
static char *_rc_strlist_addsort (char ***list, const char *item,
|
|
||||||
int (*sortfunc) (const char *s1,
|
|
||||||
const char *s2),
|
|
||||||
bool uniq)
|
|
||||||
{
|
|
||||||
char **newlist;
|
|
||||||
char **lst = *list;
|
|
||||||
int i = 0;
|
|
||||||
char *tmp1;
|
|
||||||
char *tmp2;
|
|
||||||
char *retval;
|
|
||||||
|
|
||||||
if (! item)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
while (lst && lst[i]) {
|
|
||||||
if (uniq && strcmp (lst[i], item) == 0) {
|
|
||||||
errno = EEXIST;
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
newlist = xrealloc (lst, sizeof (char *) * (i + 2));
|
|
||||||
|
|
||||||
if (! i)
|
|
||||||
newlist[i] = NULL;
|
|
||||||
newlist[i + 1] = NULL;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
while (newlist[i] && sortfunc (newlist[i], item) < 0)
|
|
||||||
i++;
|
|
||||||
|
|
||||||
tmp1 = newlist[i];
|
|
||||||
retval = newlist[i] = xstrdup (item);
|
|
||||||
do {
|
|
||||||
i++;
|
|
||||||
tmp2 = newlist[i];
|
|
||||||
newlist[i] = tmp1;
|
|
||||||
tmp1 = tmp2;
|
|
||||||
} while (tmp1);
|
|
||||||
|
|
||||||
*list = newlist;
|
|
||||||
return (retval);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *rc_strlist_addsort (char ***list, const char *item)
|
|
||||||
{
|
|
||||||
return (_rc_strlist_addsort (list, item, strcoll, false));
|
|
||||||
}
|
|
||||||
librc_hidden_def(rc_strlist_addsort)
|
|
||||||
|
|
||||||
char *rc_strlist_addsortc (char ***list, const char *item)
|
|
||||||
{
|
|
||||||
return (_rc_strlist_addsort (list, item, strcmp, false));
|
|
||||||
}
|
|
||||||
librc_hidden_def(rc_strlist_addsortc)
|
|
||||||
|
|
||||||
char *rc_strlist_addsortu (char ***list, const char *item)
|
|
||||||
{
|
|
||||||
return (_rc_strlist_addsort (list, item, strcmp, true));
|
|
||||||
}
|
|
||||||
librc_hidden_def(rc_strlist_addsortu)
|
|
||||||
|
|
||||||
bool rc_strlist_delete (char ***list, const char *item)
|
|
||||||
{
|
|
||||||
char **lst = *list;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if (!lst || ! item)
|
|
||||||
return (false);
|
|
||||||
|
|
||||||
while (lst[i]) {
|
|
||||||
if (strcmp (lst[i], item) == 0) {
|
|
||||||
free (lst[i]);
|
|
||||||
do {
|
|
||||||
lst[i] = lst[i + 1];
|
|
||||||
i++;
|
|
||||||
} while (lst[i]);
|
|
||||||
return (true);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
errno = ENOENT;
|
|
||||||
return (false);
|
|
||||||
}
|
|
||||||
librc_hidden_def(rc_strlist_delete)
|
|
||||||
|
|
||||||
char *rc_strlist_join (char ***list1, char **list2)
|
|
||||||
{
|
|
||||||
char **lst1 = *list1;
|
|
||||||
char **newlist;
|
|
||||||
int i = 0;
|
|
||||||
int j = 0;
|
|
||||||
|
|
||||||
if (! list2)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
while (lst1 && lst1[i])
|
|
||||||
i++;
|
|
||||||
|
|
||||||
while (list2[j])
|
|
||||||
j++;
|
|
||||||
|
|
||||||
newlist = xrealloc (lst1, sizeof (char *) * (i + j + 1));
|
|
||||||
|
|
||||||
j = 0;
|
|
||||||
while (list2[j]) {
|
|
||||||
newlist[i] = list2[j];
|
|
||||||
/* Take the item off the 2nd list as it's only a shallow copy */
|
|
||||||
list2[j] = NULL;
|
|
||||||
i++;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
newlist[i] = NULL;
|
|
||||||
|
|
||||||
*list1 = newlist;
|
|
||||||
return (newlist[i == 0 ? 0 : i - 1]);
|
|
||||||
}
|
|
||||||
librc_hidden_def(rc_strlist_join)
|
|
||||||
|
|
||||||
void rc_strlist_reverse (char **list)
|
|
||||||
{
|
|
||||||
char *item;
|
|
||||||
int i = 0;
|
|
||||||
int j = 0;
|
|
||||||
|
|
||||||
if (! list)
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (list[j])
|
|
||||||
j++;
|
|
||||||
j--;
|
|
||||||
|
|
||||||
while (i < j && list[i] && list[j]) {
|
|
||||||
item = list[i];
|
|
||||||
list[i] = list[j];
|
|
||||||
list[j] = item;
|
|
||||||
i++;
|
|
||||||
j--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
librc_hidden_def(rc_strlist_reverse)
|
|
||||||
|
|
||||||
void rc_strlist_free (char **list)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if (! list)
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (list[i])
|
|
||||||
free (list[i++]);
|
|
||||||
|
|
||||||
free (list);
|
|
||||||
}
|
|
||||||
librc_hidden_def(rc_strlist_free)
|
|
File diff suppressed because it is too large
Load Diff
@ -64,10 +64,8 @@
|
|||||||
#include <kvm.h>
|
#include <kvm.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "librc-depend.h"
|
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "rc-misc.h"
|
#include "rc-misc.h"
|
||||||
#include "strlist.h"
|
|
||||||
|
|
||||||
#include "hidden-visibility.h"
|
#include "hidden-visibility.h"
|
||||||
#define librc_hidden_proto(x) hidden_proto(x)
|
#define librc_hidden_proto(x) hidden_proto(x)
|
||||||
@ -115,15 +113,11 @@ librc_hidden_proto(rc_service_state)
|
|||||||
librc_hidden_proto(rc_service_value_get)
|
librc_hidden_proto(rc_service_value_get)
|
||||||
librc_hidden_proto(rc_service_value_set)
|
librc_hidden_proto(rc_service_value_set)
|
||||||
librc_hidden_proto(rc_strcatpaths)
|
librc_hidden_proto(rc_strcatpaths)
|
||||||
librc_hidden_proto(rc_strlist_add)
|
librc_hidden_proto(rc_stringlist_add)
|
||||||
librc_hidden_proto(rc_strlist_addu)
|
librc_hidden_proto(rc_stringlist_addu)
|
||||||
librc_hidden_proto(rc_strlist_addsort)
|
librc_hidden_proto(rc_stringlist_delete)
|
||||||
librc_hidden_proto(rc_strlist_addsortc)
|
librc_hidden_proto(rc_stringlist_free)
|
||||||
librc_hidden_proto(rc_strlist_addsortu)
|
librc_hidden_proto(rc_stringlist_sort)
|
||||||
librc_hidden_proto(rc_strlist_delete)
|
|
||||||
librc_hidden_proto(rc_strlist_free)
|
|
||||||
librc_hidden_proto(rc_strlist_join)
|
|
||||||
librc_hidden_proto(rc_strlist_reverse)
|
|
||||||
librc_hidden_proto(rc_yesno)
|
librc_hidden_proto(rc_yesno)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
200
src/librc/rc.h
200
src/librc/rc.h
@ -32,15 +32,24 @@
|
|||||||
# if (GCC_VERSION >= 3005)
|
# if (GCC_VERSION >= 3005)
|
||||||
# define SENTINEL __attribute__ ((__sentinel__))
|
# define SENTINEL __attribute__ ((__sentinel__))
|
||||||
# endif
|
# endif
|
||||||
|
# define DEPRECATED __attribute__ ((deprecated))
|
||||||
#endif
|
#endif
|
||||||
#ifndef SENTINEL
|
#ifndef SENTINEL
|
||||||
# define SENTINEL
|
# define SENTINEL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/queue.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* A doubly linked list using queue(3) for ease of use */
|
||||||
|
typedef struct rc_string {
|
||||||
|
char *value;
|
||||||
|
TAILQ_ENTRY(rc_string) entries;
|
||||||
|
} RC_STRING;
|
||||||
|
typedef TAILQ_HEAD(rc_stringlist, rc_string) RC_STRINGLIST;
|
||||||
|
|
||||||
/*! @name Reserved runlevel names */
|
/*! @name Reserved runlevel names */
|
||||||
#define RC_LEVEL_SYSINIT "sysinit"
|
#define RC_LEVEL_SYSINIT "sysinit"
|
||||||
#define RC_LEVEL_SINGLE "single"
|
#define RC_LEVEL_SINGLE "single"
|
||||||
@ -49,30 +58,30 @@
|
|||||||
|
|
||||||
/*! Return the current runlevel.
|
/*! Return the current runlevel.
|
||||||
* @return the current runlevel */
|
* @return the current runlevel */
|
||||||
char *rc_runlevel_get (void);
|
char *rc_runlevel_get(void);
|
||||||
|
|
||||||
/*! Checks if the runlevel exists or not
|
/*! Checks if the runlevel exists or not
|
||||||
* @param runlevel to check
|
* @param runlevel to check
|
||||||
* @return true if the runlevel exists, otherwise false */
|
* @return true if the runlevel exists, otherwise false */
|
||||||
bool rc_runlevel_exists (const char *runlevel);
|
bool rc_runlevel_exists(const char *);
|
||||||
|
|
||||||
/*! Return a NULL terminated list of runlevels
|
/*! Return a NULL terminated list of runlevels
|
||||||
* @return a NULL terminated list of runlevels */
|
* @return a NULL terminated list of runlevels */
|
||||||
char **rc_runlevel_list (void);
|
RC_STRINGLIST *rc_runlevel_list(void);
|
||||||
|
|
||||||
/*! Set the runlevel.
|
/*! Set the runlevel.
|
||||||
* This just changes the stored runlevel and does not start or stop any
|
* This just changes the stored runlevel and does not start or stop any
|
||||||
* services.
|
* services.
|
||||||
* @param runlevel to store */
|
* @param runlevel to store */
|
||||||
bool rc_runlevel_set (const char *runlevel);
|
bool rc_runlevel_set(const char *);
|
||||||
|
|
||||||
/*! Is the runlevel starting?
|
/*! Is the runlevel starting?
|
||||||
* @return true if yes, otherwise false */
|
* @return true if yes, otherwise false */
|
||||||
bool rc_runlevel_starting (void);
|
bool rc_runlevel_starting(void);
|
||||||
|
|
||||||
/*! Is the runlevel stopping?
|
/*! Is the runlevel stopping?
|
||||||
* @return true if yes, otherwise false */
|
* @return true if yes, otherwise false */
|
||||||
bool rc_runlevel_stopping (void);
|
bool rc_runlevel_stopping(void);
|
||||||
|
|
||||||
/*! @name RC
|
/*! @name RC
|
||||||
* A service can be given as a full path or just its name.
|
* A service can be given as a full path or just its name.
|
||||||
@ -97,19 +106,19 @@ typedef enum
|
|||||||
RC_SERVICE_FAILED = 0x0200,
|
RC_SERVICE_FAILED = 0x0200,
|
||||||
RC_SERVICE_SCHEDULED = 0x0400,
|
RC_SERVICE_SCHEDULED = 0x0400,
|
||||||
RC_SERVICE_WASINACTIVE = 0x0800
|
RC_SERVICE_WASINACTIVE = 0x0800
|
||||||
} rc_service_state_t;
|
} RC_SERVICE;
|
||||||
|
|
||||||
/*! Add the service to the runlevel
|
/*! Add the service to the runlevel
|
||||||
* @param runlevel to add to
|
* @param runlevel to add to
|
||||||
* @param service to add
|
* @param service to add
|
||||||
* @return true if successful, otherwise false */
|
* @return true if successful, otherwise false */
|
||||||
bool rc_service_add (const char *runlevel, const char *service);
|
bool rc_service_add(const char *, const char *);
|
||||||
|
|
||||||
/*! Remove the service from the runlevel
|
/*! Remove the service from the runlevel
|
||||||
* @param runlevel to remove from
|
* @param runlevel to remove from
|
||||||
* @param service to remove
|
* @param service to remove
|
||||||
* @return true if sucessful, otherwise false */
|
* @return true if sucessful, otherwise false */
|
||||||
bool rc_service_delete (const char *runlevel, const char *service);
|
bool rc_service_delete(const char *, const char *);
|
||||||
|
|
||||||
/*! Save the arguments to find a running daemon
|
/*! Save the arguments to find a running daemon
|
||||||
* @param service to save arguments for
|
* @param service to save arguments for
|
||||||
@ -117,116 +126,113 @@ bool rc_service_delete (const char *runlevel, const char *service);
|
|||||||
* @param name of the process (optional)
|
* @param name of the process (optional)
|
||||||
* @param pidfile of the process (optional)
|
* @param pidfile of the process (optional)
|
||||||
* @param started if true, add the arguments otherwise remove existing matching arguments */
|
* @param started if true, add the arguments otherwise remove existing matching arguments */
|
||||||
bool rc_service_daemon_set (const char *service, const char *const *argv,
|
bool rc_service_daemon_set(const char *, const char *const *, const char *, const char *,
|
||||||
const char *name, const char *pidfile,
|
bool);
|
||||||
bool started);
|
|
||||||
|
|
||||||
/*! Returns a description of what the service and/or option does.
|
/*! Returns a description of what the service and/or option does.
|
||||||
* @param service to check
|
* @param service to check
|
||||||
* @param option to check (if NULL, service description)
|
* @param option to check (if NULL, service description)
|
||||||
* @return a newly allocated pointer to the description */
|
* @return a newly allocated pointer to the description */
|
||||||
char *rc_service_description (const char *service, const char *option);
|
char *rc_service_description(const char *, const char *);
|
||||||
|
|
||||||
/*! Checks if a service exists or not.
|
/*! Checks if a service exists or not.
|
||||||
* @param service to check
|
* @param service to check
|
||||||
* @return true if service exists, otherwise false */
|
* @return true if service exists, otherwise false */
|
||||||
bool rc_service_exists (const char *service);
|
bool rc_service_exists(const char *);
|
||||||
|
|
||||||
/*! Checks if a service is in a runlevel
|
/*! Checks if a service is in a runlevel
|
||||||
* @param service to check
|
* @param service to check
|
||||||
* @param runlevel it should be in
|
* @param runlevel it should be in
|
||||||
* @return true if service is in the runlevel, otherwise false */
|
* @return true if service is in the runlevel, otherwise false */
|
||||||
bool rc_service_in_runlevel (const char *service, const char *runlevel);
|
bool rc_service_in_runlevel(const char *, const char *);
|
||||||
|
|
||||||
/*! Marks the service state
|
/*! Marks the service state
|
||||||
* @param service to mark
|
* @param service to mark
|
||||||
* @param state service should be in
|
* @param state service should be in
|
||||||
* @return true if service state change was successful, otherwise false */
|
* @return true if service state change was successful, otherwise false */
|
||||||
bool rc_service_mark (const char *service, rc_service_state_t state);
|
bool rc_service_mark(const char *, RC_SERVICE);
|
||||||
|
|
||||||
/*! Lists the extra commands a service has
|
/*! Lists the extra commands a service has
|
||||||
* @param service to load the commands from
|
* @param service to load the commands from
|
||||||
* @return NULL terminated string list of commands */
|
* @return NULL terminated string list of commands */
|
||||||
char **rc_service_extra_commands (const char *service);
|
RC_STRINGLIST *rc_service_extra_commands(const char *);
|
||||||
|
|
||||||
/*! Resolves a service name to its full path.
|
/*! Resolves a service name to its full path.
|
||||||
* @param service to check
|
* @param service to check
|
||||||
* @return pointer to full path of service */
|
* @return pointer to full path of service */
|
||||||
char *rc_service_resolve (const char *service);
|
char *rc_service_resolve(const char *);
|
||||||
|
|
||||||
/*! Schedule a service to be started when another service starts
|
/*! Schedule a service to be started when another service starts
|
||||||
* @param service that starts the scheduled service when started
|
* @param service that starts the scheduled service when started
|
||||||
* @param service_to_start service that will be started */
|
* @param service_to_start service that will be started */
|
||||||
bool rc_service_schedule_start (const char *service,
|
bool rc_service_schedule_start(const char *, const char *);
|
||||||
const char *service_to_start);
|
|
||||||
/*! Return a NULL terminated list of services that are scheduled to start
|
/*! Return a NULL terminated list of services that are scheduled to start
|
||||||
* when the given service has started
|
* when the given service has started
|
||||||
* @param service to check
|
* @param service to check
|
||||||
* @return NULL terminated list of services scheduled to start */
|
* @return NULL terminated list of services scheduled to start */
|
||||||
char **rc_services_scheduled_by (const char *service);
|
RC_STRINGLIST *rc_services_scheduled_by(const char *);
|
||||||
|
|
||||||
/*! Clear the list of services scheduled to be started by this service
|
/*! Clear the list of services scheduled to be started by this service
|
||||||
* @param service to clear
|
* @param service to clear
|
||||||
* @return true if no errors, otherwise false */
|
* @return true if no errors, otherwise false */
|
||||||
bool rc_service_schedule_clear (const char *service);
|
bool rc_service_schedule_clear(const char *);
|
||||||
|
|
||||||
/*! Checks if a service in in a state
|
/*! Checks if a service in in a state
|
||||||
* @param service to check
|
* @param service to check
|
||||||
* @return state of the service */
|
* @return state of the service */
|
||||||
rc_service_state_t rc_service_state (const char *service);
|
RC_SERVICE rc_service_state(const char *);
|
||||||
|
|
||||||
/*! Start a service
|
/*! Start a service
|
||||||
* @param service to start
|
* @param service to start
|
||||||
* @return pid of the service starting process */
|
* @return pid of the service starting process */
|
||||||
pid_t rc_service_start (const char *service);
|
pid_t rc_service_start(const char *);
|
||||||
|
|
||||||
/*! Stop a service
|
/*! Stop a service
|
||||||
* @param service to stop
|
* @param service to stop
|
||||||
* @return pid of service stopping process */
|
* @return pid of service stopping process */
|
||||||
pid_t rc_service_stop (const char *service);
|
pid_t rc_service_stop(const char *);
|
||||||
|
|
||||||
/*! Check if the service started the daemon
|
/*! Check if the service started the daemon
|
||||||
* @param service to check
|
* @param service to check
|
||||||
* @param exec to check
|
* @param exec to check
|
||||||
* @param indx of the daemon (optional - 1st daemon, 2nd daemon, etc)
|
* @param indx of the daemon (optional - 1st daemon, 2nd daemon, etc)
|
||||||
* @return true if started by this service, otherwise false */
|
* @return true if started by this service, otherwise false */
|
||||||
bool rc_service_started_daemon (const char *service, const char *const *argv,
|
bool rc_service_started_daemon(const char *, const char *const *, int);
|
||||||
int indx);
|
|
||||||
|
|
||||||
/*! Return a saved value for a service
|
/*! Return a saved value for a service
|
||||||
* @param service to check
|
* @param service to check
|
||||||
* @param option to load
|
* @param option to load
|
||||||
* @return saved value */
|
* @return saved value */
|
||||||
char *rc_service_value_get (const char *service, const char *option);
|
char *rc_service_value_get(const char *, const char *);
|
||||||
|
|
||||||
/*! Save a persistent value for a service
|
/*! Save a persistent value for a service
|
||||||
* @param service to save for
|
* @param service to save for
|
||||||
* @param option to save
|
* @param option to save
|
||||||
* @param value of the option
|
* @param value of the option
|
||||||
* @return true if saved, otherwise false */
|
* @return true if saved, otherwise false */
|
||||||
bool rc_service_value_set (const char *service, const char *option,
|
bool rc_service_value_set(const char *, const char *, const char *);
|
||||||
const char *value);
|
|
||||||
|
|
||||||
/*! List the services in a runlevel
|
/*! List the services in a runlevel
|
||||||
* @param runlevel to list
|
* @param runlevel to list
|
||||||
* @return NULL terminated list of services */
|
* @return NULL terminated list of services */
|
||||||
char **rc_services_in_runlevel (const char *runlevel);
|
RC_STRINGLIST *rc_services_in_runlevel(const char *);
|
||||||
|
|
||||||
/*! List the services in a state
|
/*! List the services in a state
|
||||||
* @param state to list
|
* @param state to list
|
||||||
* @return NULL terminated list of services */
|
* @return NULL terminated list of services */
|
||||||
char **rc_services_in_state (rc_service_state_t state);
|
RC_STRINGLIST *rc_services_in_state(RC_SERVICE);
|
||||||
|
|
||||||
/*! List the services shceduled to start when this one does
|
/*! List the services shceduled to start when this one does
|
||||||
* @param service to check
|
* @param service to check
|
||||||
* @return NULL terminated list of services */
|
* @return NULL terminated list of services */
|
||||||
char **rc_services_scheduled (const char *service);
|
RC_STRINGLIST *rc_services_scheduled(const char *);
|
||||||
|
|
||||||
/*! Checks that all daemons started with start-stop-daemon by the service
|
/*! Checks that all daemons started with start-stop-daemon by the service
|
||||||
* are still running.
|
* are still running.
|
||||||
* @param service to check
|
* @param service to check
|
||||||
* @return true if all daemons started are still running, otherwise false */
|
* @return true if all daemons started are still running, otherwise false */
|
||||||
bool rc_service_daemons_crashed (const char *service);
|
bool rc_service_daemons_crashed(const char *);
|
||||||
|
|
||||||
/*! @name System types
|
/*! @name System types
|
||||||
* OpenRC can support some special sub system types, normally virtualization.
|
* OpenRC can support some special sub system types, normally virtualization.
|
||||||
@ -238,7 +244,7 @@ bool rc_service_daemons_crashed (const char *service);
|
|||||||
#define RC_SYS_VSERVER "VSERVER"
|
#define RC_SYS_VSERVER "VSERVER"
|
||||||
#define RC_SYS_XEN0 "XEN0"
|
#define RC_SYS_XEN0 "XEN0"
|
||||||
#define RC_SYS_XENU "XENU"
|
#define RC_SYS_XENU "XENU"
|
||||||
const char *rc_sys (void);
|
const char *rc_sys(void);
|
||||||
|
|
||||||
/*! @name Dependency options
|
/*! @name Dependency options
|
||||||
* These options can change the services found by the rc_get_depinfo and
|
* These options can change the services found by the rc_get_depinfo and
|
||||||
@ -256,40 +262,67 @@ const char *rc_sys (void);
|
|||||||
* We analyse each init script and cache the resultant dependency tree.
|
* We analyse each init script and cache the resultant dependency tree.
|
||||||
* This tree can be accessed using the below functions. */
|
* This tree can be accessed using the below functions. */
|
||||||
|
|
||||||
#ifndef _IN_LIBRC
|
#ifdef _IN_LIBRC
|
||||||
|
/*! @name Dependency structures
|
||||||
|
* private to librc */
|
||||||
|
|
||||||
|
/*! Singly linked list of dependency types that list the services the
|
||||||
|
* type is for */
|
||||||
|
typedef struct rc_deptype
|
||||||
|
{
|
||||||
|
/*! ineed, iuse, iafter, etc */
|
||||||
|
char *type;
|
||||||
|
/*! list of services */
|
||||||
|
RC_STRINGLIST *services;
|
||||||
|
/*! list of types */
|
||||||
|
STAILQ_ENTRY(rc_deptype) entries;
|
||||||
|
} RC_DEPTYPE;
|
||||||
|
|
||||||
|
/*! Singly linked list of services and their dependencies */
|
||||||
|
typedef struct rc_depinfo
|
||||||
|
{
|
||||||
|
/*! Name of service */
|
||||||
|
char *service;
|
||||||
|
/*! Dependencies */
|
||||||
|
STAILQ_HEAD(, rc_deptype) depends;
|
||||||
|
/*! List of entries */
|
||||||
|
STAILQ_ENTRY(rc_depinfo) entries;
|
||||||
|
} RC_DEPINFO;
|
||||||
|
|
||||||
|
typedef STAILQ_HEAD(,rc_depinfo) RC_DEPTREE;
|
||||||
|
#else
|
||||||
/* Handles to internal structures */
|
/* Handles to internal structures */
|
||||||
typedef void *rc_depinfo_t;
|
typedef void *RC_DEPTREE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*! Check to see if source is newer than target.
|
/*! Check to see if source is newer than target.
|
||||||
* If target is a directory then we traverse it and it's children.
|
* If target is a directory then we traverse it and it's children.
|
||||||
* @return true if source is newer than target, otherwise false */
|
* @return true if source is newer than target, otherwise false */
|
||||||
bool rc_newer_than (const char *source, const char *target);
|
bool rc_newer_than(const char *, const char *);
|
||||||
|
|
||||||
/*! Update the cached dependency tree if it's older than any init script,
|
/*! Update the cached dependency tree if it's older than any init script,
|
||||||
* its configuration file or an external configuration file the init script
|
* its configuration file or an external configuration file the init script
|
||||||
* has specified.
|
* has specified.
|
||||||
* @return true if successful, otherwise false */
|
* @return true if successful, otherwise false */
|
||||||
bool rc_deptree_update (void);
|
bool rc_deptree_update(void);
|
||||||
|
|
||||||
/*! Check if the cached dependency tree is older than any init script,
|
/*! Check if the cached dependency tree is older than any init script,
|
||||||
* its configuration file or an external configuration file the init script
|
* its configuration file or an external configuration file the init script
|
||||||
* has specified.
|
* has specified.
|
||||||
* @return true if it needs updating, otherwise false */
|
* @return true if it needs updating, otherwise false */
|
||||||
bool rc_deptree_update_needed (void);
|
bool rc_deptree_update_needed(void);
|
||||||
|
|
||||||
/*! Load the cached dependency tree and return a pointer to it.
|
/*! Load the cached dependency tree and return a pointer to it.
|
||||||
* This pointer should be freed with rc_deptree_free when done.
|
* This pointer should be freed with rc_deptree_free when done.
|
||||||
* @return pointer to the dependency tree */
|
* @return pointer to the dependency tree */
|
||||||
rc_depinfo_t *rc_deptree_load (void);
|
RC_DEPTREE *rc_deptree_load(void);
|
||||||
|
|
||||||
/*! List the depend for the type of service
|
/*! List the depend for the type of service
|
||||||
* @param deptree to search
|
* @param deptree to search
|
||||||
* @param type to use (keywords, etc)
|
* @param type to use (keywords, etc)
|
||||||
* @param service to check
|
* @param service to check
|
||||||
* @return NULL terminated list of services in order */
|
* @return NULL terminated list of services in order */
|
||||||
char **rc_deptree_depend (const rc_depinfo_t *deptree,
|
RC_STRINGLIST *rc_deptree_depend(const RC_DEPTREE *, const char *, const char *);
|
||||||
const char *type, const char *service);
|
|
||||||
|
|
||||||
/*! List all the services in order that the given services have
|
/*! List all the services in order that the given services have
|
||||||
* for the given types and options.
|
* for the given types and options.
|
||||||
@ -298,10 +331,8 @@ char **rc_deptree_depend (const rc_depinfo_t *deptree,
|
|||||||
* @param services to check
|
* @param services to check
|
||||||
* @param options to pass
|
* @param options to pass
|
||||||
* @return NULL terminated list of services in order */
|
* @return NULL terminated list of services in order */
|
||||||
char **rc_deptree_depends (const rc_depinfo_t *deptree,
|
RC_STRINGLIST *rc_deptree_depends(const RC_DEPTREE *, const RC_STRINGLIST *,
|
||||||
const char *const *types,
|
const RC_STRINGLIST *, const char *, int);
|
||||||
const char *const *services, const char *runlevel,
|
|
||||||
int options);
|
|
||||||
|
|
||||||
/*! List all the services that should be stoppned and then started, in order,
|
/*! List all the services that should be stoppned and then started, in order,
|
||||||
* for the given runlevel, including sysinit and boot services where
|
* for the given runlevel, including sysinit and boot services where
|
||||||
@ -310,12 +341,11 @@ char **rc_deptree_depends (const rc_depinfo_t *deptree,
|
|||||||
* @param runlevel to change into
|
* @param runlevel to change into
|
||||||
* @param options to pass
|
* @param options to pass
|
||||||
* @return NULL terminated list of services in order */
|
* @return NULL terminated list of services in order */
|
||||||
char **rc_deptree_order (const rc_depinfo_t *deptree, const char *runlevel,
|
RC_STRINGLIST *rc_deptree_order(const RC_DEPTREE *, const char *, int);
|
||||||
int options);
|
|
||||||
|
|
||||||
/*! Free a deptree and its information
|
/*! Free a deptree and its information
|
||||||
* @param deptree to free */
|
* @param deptree to free */
|
||||||
void rc_deptree_free (rc_depinfo_t *deptree);
|
void rc_deptree_free(RC_DEPTREE *);
|
||||||
|
|
||||||
/*! @name Plugins
|
/*! @name Plugins
|
||||||
* For each plugin loaded we will call rc_plugin_hook with the below
|
* For each plugin loaded we will call rc_plugin_hook with the below
|
||||||
@ -347,13 +377,13 @@ typedef enum
|
|||||||
RC_HOOK_SERVICE_START_NOW = 106,
|
RC_HOOK_SERVICE_START_NOW = 106,
|
||||||
RC_HOOK_SERVICE_START_DONE = 107,
|
RC_HOOK_SERVICE_START_DONE = 107,
|
||||||
RC_HOOK_SERVICE_START_OUT = 108
|
RC_HOOK_SERVICE_START_OUT = 108
|
||||||
} rc_hook_t;
|
} RC_HOOK;
|
||||||
|
|
||||||
/*! Plugin entry point
|
/*! Plugin entry point
|
||||||
* @param hook point
|
* @param hook point
|
||||||
* @param name of runlevel or service
|
* @param name of runlevel or service
|
||||||
* @return 0 for success otherwise -1 */
|
* @return 0 for success otherwise -1 */
|
||||||
int rc_plugin_hook (rc_hook_t hook, const char *name);
|
int rc_plugin_hook(RC_HOOK, const char *);
|
||||||
|
|
||||||
/*! Plugins should write FOO=BAR to this fd to set any environment
|
/*! Plugins should write FOO=BAR to this fd to set any environment
|
||||||
* variables they wish. Variables should be separated by NULLs. */
|
* variables they wish. Variables should be separated by NULLs. */
|
||||||
@ -362,91 +392,64 @@ extern FILE *rc_environ_fd;
|
|||||||
/*! @name Configuration
|
/*! @name Configuration
|
||||||
* These functions help to deal with shell based configuration files */
|
* These functions help to deal with shell based configuration files */
|
||||||
/*! Return a line from a file, stripping the trailing newline. */
|
/*! Return a line from a file, stripping the trailing newline. */
|
||||||
char *rc_getline (FILE *fp);
|
char *rc_getline(FILE *);
|
||||||
|
|
||||||
/*! Return a NULL terminated list of non comment lines from a file. */
|
/*! Return a NULL terminated list of non comment lines from a file. */
|
||||||
char **rc_config_list (const char *file);
|
RC_STRINGLIST *rc_config_list(const char *);
|
||||||
|
|
||||||
/*! Return a NULL terminated list of key=value lines from a file. */
|
/*! Return a NULL terminated list of key=value lines from a file. */
|
||||||
char **rc_config_load (const char *file);
|
RC_STRINGLIST *rc_config_load(const char *);
|
||||||
|
|
||||||
/*! Return the value of the entry from a key=value list. */
|
/*! Return the value of the entry from a key=value list. */
|
||||||
char *rc_config_value (const char *const *list, const char *entry);
|
char *rc_config_value(RC_STRINGLIST *, const char *);
|
||||||
|
|
||||||
/*! Check if a variable is a boolean and return it's value.
|
/*! Check if a variable is a boolean and return it's value.
|
||||||
* If variable is not a boolean then we set errno to be ENOENT when it does
|
* If variable is not a boolean then we set errno to be ENOENT when it does
|
||||||
* not exist or EINVAL if it's not a boolean.
|
* not exist or EINVAL if it's not a boolean.
|
||||||
* @param variable to check
|
* @param variable to check
|
||||||
* @return true if it matches true, yes or 1, false if otherwise. */
|
* @return true if it matches true, yes or 1, false if otherwise. */
|
||||||
bool rc_yesno (const char *variable);
|
bool rc_yesno(const char *);
|
||||||
|
|
||||||
/*! @name String List functions
|
/*! @name String List functions
|
||||||
* Handy functions for dealing with string arrays of char **.
|
* Every string list should be released with a call to rc_stringlist_free. */
|
||||||
* It's safe to assume that any function here that uses char ** is a string
|
|
||||||
* list that can be manipulated with the below functions. Every string list
|
/*! Create a new stringlinst
|
||||||
* should be released with a call to rc_strlist_free. */
|
* @return pointer to new list */
|
||||||
|
RC_STRINGLIST *rc_stringlist_new(void);
|
||||||
|
|
||||||
/*! Duplicate the item, add it to end of the list and return a pointer to it.
|
/*! Duplicate the item, add it to end of the list and return a pointer to it.
|
||||||
* @param list to add the item too
|
* @param list to add the item too
|
||||||
* @param item to add.
|
* @param item to add.
|
||||||
* @return pointer to newly added item */
|
* @return pointer to newly added item */
|
||||||
char *rc_strlist_add (char ***list, const char *item);
|
RC_STRING *rc_stringlist_add(RC_STRINGLIST *, const char *);
|
||||||
|
|
||||||
/*! If the item does not exist in the list, duplicate it, add it to the
|
/*! If the item does not exist in the list, duplicate it, add it to the
|
||||||
* list and then return a pointer to it.
|
* list and then return a pointer to it.
|
||||||
* @param list to add the item too
|
* @param list to add the item too
|
||||||
* @param item to add.
|
* @param item to add.
|
||||||
* @return pointer to newly added item */
|
* @return pointer to newly added item */
|
||||||
char *rc_strlist_addu (char ***list, const char *item);
|
RC_STRING *rc_stringlist_addu(RC_STRINGLIST *, const char *);
|
||||||
|
|
||||||
/*! Duplicate the item, add it to the list at the point based on locale and
|
|
||||||
* then return a pointer to it.
|
|
||||||
* @param list to add the item too
|
|
||||||
* @param item to add.
|
|
||||||
* @return pointer to newly added item */
|
|
||||||
char *rc_strlist_addsort (char ***list, const char *item);
|
|
||||||
|
|
||||||
/*! Duplicate the item, add it to the list at the point based on C locale and
|
|
||||||
* then return a pointer to it.
|
|
||||||
* @param list to add the item too
|
|
||||||
* @param item to add.
|
|
||||||
* @return pointer to newly added item */
|
|
||||||
char *rc_strlist_addsortc (char ***list, const char *item);
|
|
||||||
|
|
||||||
/*! If the item does not exist in the list, duplicate it, add it to the
|
|
||||||
* list based on locale and then return a pointer to it.
|
|
||||||
* @param list to add the item too
|
|
||||||
* @param item to add.
|
|
||||||
* @return pointer to newly added item */
|
|
||||||
char *rc_strlist_addsortu (char ***list, const char *item);
|
|
||||||
|
|
||||||
/*! Free the item and remove it from the list. Return 0 on success otherwise -1.
|
/*! Free the item and remove it from the list. Return 0 on success otherwise -1.
|
||||||
* @param list to add the item too
|
* @param list to add the item too
|
||||||
* @param item to add.
|
* @param item to add.
|
||||||
* @return true on success, otherwise false */
|
* @return true on success, otherwise false */
|
||||||
bool rc_strlist_delete (char ***list, const char *item);
|
bool rc_stringlist_delete(RC_STRINGLIST *, const char *);
|
||||||
|
|
||||||
/*! Moves the contents of list2 onto list1, so list2 is effectively emptied.
|
/*! Sort the list according to C locale
|
||||||
* Returns a pointer to the last item on the new list.
|
* @param list to sort */
|
||||||
* @param list1 to append to
|
void rc_stringlist_sort(RC_STRINGLIST **);
|
||||||
* @param list2 to move from
|
|
||||||
* @return pointer to the last item on the list */
|
|
||||||
char *rc_strlist_join (char ***list1, char **list2);
|
|
||||||
|
|
||||||
/*! Reverses the contents of the list.
|
|
||||||
* @param list to reverse */
|
|
||||||
void rc_strlist_reverse (char **list);
|
|
||||||
|
|
||||||
/*! Frees each item on the list and the list itself.
|
/*! Frees each item on the list and the list itself.
|
||||||
* @param list to free */
|
* @param list to free */
|
||||||
void rc_strlist_free (char **list);
|
void rc_stringlist_free(RC_STRINGLIST *);
|
||||||
|
|
||||||
/*! Concatenate paths adding '/' if needed. The resultant pointer should be
|
/*! Concatenate paths adding '/' if needed. The resultant pointer should be
|
||||||
* freed when finished with.
|
* freed when finished with.
|
||||||
* @param path1 starting path
|
* @param path1 starting path
|
||||||
* @param paths NULL terminated list of paths to add
|
* @param paths NULL terminated list of paths to add
|
||||||
* @return pointer to the new path */
|
* @return pointer to the new path */
|
||||||
char *rc_strcatpaths (const char *path1, const char *paths, ...) SENTINEL;
|
char *rc_strcatpaths(const char *, const char *, ...) SENTINEL;
|
||||||
|
|
||||||
/*! Find processes based on criteria.
|
/*! Find processes based on criteria.
|
||||||
* All of these are optional.
|
* All of these are optional.
|
||||||
@ -457,7 +460,6 @@ char *rc_strcatpaths (const char *path1, const char *paths, ...) SENTINEL;
|
|||||||
* @param uid to check for
|
* @param uid to check for
|
||||||
* @param pid to check for
|
* @param pid to check for
|
||||||
* @return NULL terminated list of pids */
|
* @return NULL terminated list of pids */
|
||||||
pid_t *rc_find_pids (const char *const *argv, const char *cmd,
|
pid_t *rc_find_pids(const char *const *, const char *, uid_t, pid_t);
|
||||||
uid_t uid, pid_t pid);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,15 +43,12 @@ global:
|
|||||||
rc_service_value_get;
|
rc_service_value_get;
|
||||||
rc_service_value_set;
|
rc_service_value_set;
|
||||||
rc_strcatpaths;
|
rc_strcatpaths;
|
||||||
rc_strlist_add;
|
rc_stringlist_add;
|
||||||
rc_strlist_addu;
|
rc_stringlist_addu;
|
||||||
rc_strlist_addsort;
|
rc_stringlist_delete;
|
||||||
rc_strlist_addsortc;
|
rc_stringlist_new;
|
||||||
rc_strlist_addsortu;
|
rc_stringlist_sort;
|
||||||
rc_strlist_delete;
|
rc_stringlist_free;
|
||||||
rc_strlist_free;
|
|
||||||
rc_strlist_join;
|
|
||||||
rc_strlist_reverse;
|
|
||||||
rc_sys;
|
rc_sys;
|
||||||
rc_yesno;
|
rc_yesno;
|
||||||
|
|
||||||
|
4
src/rc/.gitignore
vendored
4
src/rc/.gitignore
vendored
@ -55,6 +55,7 @@ rc-abort
|
|||||||
checkpath.o
|
checkpath.o
|
||||||
fstabinfo.o
|
fstabinfo.o
|
||||||
mountinfo.o
|
mountinfo.o
|
||||||
|
start-stop-daemon.o
|
||||||
rc-applets.o
|
rc-applets.o
|
||||||
rc-depend.o
|
rc-depend.o
|
||||||
rc-logger.o
|
rc-logger.o
|
||||||
@ -62,8 +63,7 @@ rc-misc.o
|
|||||||
rc-plugin.o
|
rc-plugin.o
|
||||||
rc-status.o
|
rc-status.o
|
||||||
rc-update.o
|
rc-update.o
|
||||||
rc.o
|
|
||||||
runscript.o
|
runscript.o
|
||||||
start-stop-daemon.o
|
rc.o
|
||||||
rc
|
rc
|
||||||
.depend
|
.depend
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
PROG= rc
|
PROG= rc
|
||||||
SRCS= checkpath.c fstabinfo.c mountinfo.c \
|
SRCS= checkpath.c fstabinfo.c mountinfo.c start-stop-daemon.c \
|
||||||
rc-applets.c rc-depend.c rc-logger.c \
|
rc-applets.c rc-depend.c rc-logger.c \
|
||||||
rc-misc.c rc-plugin.c rc-status.c rc-update.c rc.c \
|
rc-misc.c rc-plugin.c rc-status.c rc-update.c \
|
||||||
runscript.c start-stop-daemon.c
|
runscript.c rc.c
|
||||||
|
|
||||||
CLEANFILES= version.h
|
CLEANFILES= version.h
|
||||||
|
|
||||||
@ -31,8 +31,9 @@ ALL_LINKS= ${BINLINKS} ${SBINLINKS} ${RC_BINLINKS} ${RC_SBINLINKS}
|
|||||||
CLEANFILES+= ${ALL_LINKS}
|
CLEANFILES+= ${ALL_LINKS}
|
||||||
|
|
||||||
LDFLAGS+= -L../librc -L../libeinfo
|
LDFLAGS+= -L../librc -L../libeinfo
|
||||||
#LDFLAGS+= -Wl,--rpath=../librc -Wl,--rpath=../libeinfo
|
|
||||||
LDADD+= -lutil -lrc -leinfo
|
LDADD+= -lutil -lrc -leinfo
|
||||||
|
#CFLAGS+= -ggdb
|
||||||
|
#LDFLAGS+= -Wl,--rpath=../librc -Wl,--rpath=../libeinfo
|
||||||
|
|
||||||
MK= ../../mk
|
MK= ../../mk
|
||||||
include ${MK}/cc.mk
|
include ${MK}/cc.mk
|
||||||
|
@ -33,35 +33,36 @@
|
|||||||
# define _noreturn
|
# define _noreturn
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_noreturn static void usage (int exit_status)
|
_noreturn static void usage(int exit_status)
|
||||||
{
|
{
|
||||||
const char * const has_arg[] = { "", "<arg>", "[arg]" };
|
const char * const has_arg[] = { "", "<arg>", "[arg]" };
|
||||||
int i;
|
int i;
|
||||||
|
int len;
|
||||||
|
char *lo;
|
||||||
|
char *p;
|
||||||
|
char *token;
|
||||||
|
|
||||||
#ifdef usagestring
|
#ifdef usagestring
|
||||||
printf (usagestring);
|
printf(usagestring);
|
||||||
#else
|
#else
|
||||||
printf ("Usage: %s [options] ", applet);
|
printf("Usage: %s [options] ", applet);
|
||||||
#endif
|
#endif
|
||||||
#ifdef extraopts
|
#ifdef extraopts
|
||||||
printf (extraopts);
|
printf(extraopts);
|
||||||
#endif
|
#endif
|
||||||
printf ("\n\nOptions: [" getoptstring "]\n");
|
printf("\n\nOptions: [" getoptstring "]\n");
|
||||||
for (i = 0; longopts[i].name; ++i) {
|
for (i = 0; longopts[i].name; ++i) {
|
||||||
int len = printf (" -%c, --%s %s", longopts[i].val, longopts[i].name,
|
len = printf(" -%c, --%s %s", longopts[i].val, longopts[i].name,
|
||||||
has_arg[longopts[i].has_arg]);
|
has_arg[longopts[i].has_arg]);
|
||||||
|
|
||||||
char *lo = xstrdup (longopts_help[i]);
|
lo = p = xstrdup(longopts_help[i]);
|
||||||
char *p = lo;
|
while ((token = strsep(&p, "\n"))) {
|
||||||
char *token;
|
|
||||||
|
|
||||||
while ((token = strsep (&p, "\n"))) {
|
|
||||||
while (++len < 37)
|
while (++len < 37)
|
||||||
printf (" ");
|
printf(" ");
|
||||||
puts (token);
|
puts(token);
|
||||||
len = 0;
|
len = 0;
|
||||||
}
|
}
|
||||||
free (lo);
|
free(lo);
|
||||||
}
|
}
|
||||||
exit (exit_status);
|
exit(exit_status);
|
||||||
}
|
}
|
||||||
|
@ -38,4 +38,4 @@ int start_stop_daemon (int argc, char **argv);
|
|||||||
void run_applets (int argc, char **argv);
|
void run_applets (int argc, char **argv);
|
||||||
|
|
||||||
/* Handy function so we can wrap einfo around our deptree */
|
/* Handy function so we can wrap einfo around our deptree */
|
||||||
rc_depinfo_t *_rc_deptree_load (int *regen);
|
RC_DEPTREE *_rc_deptree_load (int *regen);
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
@ -48,84 +49,84 @@
|
|||||||
|
|
||||||
extern const char *applet;
|
extern const char *applet;
|
||||||
|
|
||||||
static int do_check (char *path, uid_t uid, gid_t gid, mode_t mode, int file)
|
static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode, int file)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
int fd;
|
||||||
|
|
||||||
memset (&st, 0, sizeof (st));
|
if (stat(path, &st)) {
|
||||||
|
|
||||||
if (stat (path, &st)) {
|
|
||||||
if (file) {
|
if (file) {
|
||||||
int fd;
|
einfo("%s: creating file", path);
|
||||||
einfo ("%s: creating file", path);
|
if ((fd = open(path, O_CREAT)) == -1) {
|
||||||
if ((fd = open (path, O_CREAT)) == -1) {
|
eerror("%s: open: %s", applet, strerror(errno));
|
||||||
eerror ("%s: open: %s", applet, strerror (errno));
|
return -1;
|
||||||
return (-1);
|
|
||||||
}
|
}
|
||||||
close (fd);
|
close (fd);
|
||||||
} else {
|
} else {
|
||||||
einfo ("%s: creating directory", path);
|
einfo("%s: creating directory", path);
|
||||||
if (! mode)
|
if (! mode)
|
||||||
mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
|
mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
|
||||||
if (mkdir (path, mode)) {
|
if (mkdir(path, mode)) {
|
||||||
eerror ("%s: mkdir: %s", applet, strerror (errno));
|
eerror("%s: mkdir: %s", applet, strerror (errno));
|
||||||
return (-1);
|
return -1;
|
||||||
}
|
}
|
||||||
mode = 0;
|
mode = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((file && S_ISDIR (st.st_mode)) ||
|
if ((file && S_ISDIR(st.st_mode)) ||
|
||||||
(! file && ! S_ISDIR (st.st_mode)))
|
(! file && ! S_ISDIR(st.st_mode)))
|
||||||
{
|
{
|
||||||
if (file)
|
if (file)
|
||||||
eerror ("%s: is a directory", path);
|
eerror("%s: is a directory", path);
|
||||||
else
|
else
|
||||||
eerror ("%s: is a file", path);
|
eerror("%s: is a file", path);
|
||||||
return (-1);
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode && (st.st_mode & 0777) != mode) {
|
if (mode && (st.st_mode & 0777) != mode) {
|
||||||
einfo ("%s: correcting mode", applet);
|
einfo("%s: correcting mode", applet);
|
||||||
if (chmod (path, mode)) {
|
if (chmod(path, mode)) {
|
||||||
eerror ("%s: chmod: %s", applet, strerror (errno));
|
eerror("%s: chmod: %s", applet, strerror(errno));
|
||||||
return (-1);
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (st.st_uid != uid || st.st_gid != gid) {
|
if (st.st_uid != uid || st.st_gid != gid) {
|
||||||
if (st.st_dev || st.st_ino)
|
if (st.st_dev || st.st_ino)
|
||||||
einfo ("%s: correcting owner", path);
|
einfo("%s: correcting owner", path);
|
||||||
if (chown (path, uid, gid)) {
|
if (chown(path, uid, gid)) {
|
||||||
eerror ("%s: chown: %s", applet, strerror (errno));
|
eerror("%s: chown: %s", applet, strerror(errno));
|
||||||
return (-1);
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Based on busybox */
|
/* Based on busybox */
|
||||||
static int parse_mode (mode_t *mode, char *text)
|
static int parse_mode (mode_t *mode, char *text)
|
||||||
{
|
{
|
||||||
|
char *p;
|
||||||
|
unsigned long l;
|
||||||
|
|
||||||
/* Check for a numeric mode */
|
/* Check for a numeric mode */
|
||||||
if ((*text - '0') < 8) {
|
if ((*text - '0') < 8) {
|
||||||
char *p;
|
l = strtoul(text, &p, 8);
|
||||||
unsigned long l = strtoul (text, &p, 8);
|
|
||||||
if (*p || l > 07777U) {
|
if (*p || l > 07777U) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return (-1);
|
return -1;
|
||||||
}
|
}
|
||||||
*mode = (mode_t) l;
|
*mode = (mode_t) l;
|
||||||
return (0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We currently don't check g+w type stuff */
|
/* We currently don't check g+w type stuff */
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return (-1);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_owner (struct passwd **user, struct group **group,
|
static int parse_owner(struct passwd **user, struct group **group,
|
||||||
const char *owner)
|
const char *owner)
|
||||||
{
|
{
|
||||||
char *u = xstrdup (owner);
|
char *u = xstrdup (owner);
|
||||||
@ -137,25 +138,25 @@ static int parse_owner (struct passwd **user, struct group **group,
|
|||||||
*g++ = '\0';
|
*g++ = '\0';
|
||||||
|
|
||||||
if (user && *u) {
|
if (user && *u) {
|
||||||
if (sscanf (u, "%d", &id) == 1)
|
if (sscanf(u, "%d", &id) == 1)
|
||||||
*user = getpwuid ((uid_t) id);
|
*user = getpwuid((uid_t) id);
|
||||||
else
|
else
|
||||||
*user = getpwnam (u);
|
*user = getpwnam(u);
|
||||||
if (! *user)
|
if (! *user)
|
||||||
retval = -1;
|
retval = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (group && g && *g) {
|
if (group && g && *g) {
|
||||||
if (sscanf (g, "%d", &id) == 1)
|
if (sscanf(g, "%d", &id) == 1)
|
||||||
*group = getgrgid ((gid_t) id);
|
*group = getgrgid((gid_t) id);
|
||||||
else
|
else
|
||||||
*group = getgrnam (g);
|
*group = getgrnam(g);
|
||||||
if (! *group)
|
if (! *group)
|
||||||
retval = -1;
|
retval = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
free (u);
|
free(u);
|
||||||
return (retval);
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "_usage.h"
|
#include "_usage.h"
|
||||||
@ -177,7 +178,7 @@ static const char * const longopts_help[] = {
|
|||||||
};
|
};
|
||||||
#include "_usage.c"
|
#include "_usage.c"
|
||||||
|
|
||||||
int checkpath (int argc, char **argv)
|
int checkpath(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int opt;
|
int opt;
|
||||||
uid_t uid = geteuid();
|
uid_t uid = geteuid();
|
||||||
@ -188,33 +189,31 @@ int checkpath (int argc, char **argv)
|
|||||||
bool file = 0;
|
bool file = 0;
|
||||||
int retval = EXIT_SUCCESS;
|
int retval = EXIT_SUCCESS;
|
||||||
|
|
||||||
while ((opt = getopt_long (argc, argv, getoptstring,
|
while ((opt = getopt_long(argc, argv, getoptstring,
|
||||||
longopts, (int *) 0)) != -1)
|
longopts, (int *) 0)) != -1)
|
||||||
{
|
{
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'd':
|
case 'd':
|
||||||
file = 0;
|
file = 0;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
file = 1;
|
file = 1;
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
if (parse_mode (&mode, optarg) != 0)
|
if (parse_mode(&mode, optarg) != 0)
|
||||||
eerrorx ("%s: invalid mode `%s'",
|
eerrorx("%s: invalid mode `%s'", applet, optarg);
|
||||||
applet, optarg);
|
break;
|
||||||
break;
|
case 'o':
|
||||||
case 'o':
|
if (parse_owner(&pw, &gr, optarg) != 0)
|
||||||
if (parse_owner (&pw, &gr, optarg) != 0)
|
eerrorx("%s: owner `%s' not found", applet, optarg);
|
||||||
eerrorx ("%s: owner `%s' not found",
|
break;
|
||||||
applet, optarg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case_RC_COMMON_GETOPT
|
case_RC_COMMON_GETOPT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optind >= argc)
|
if (optind >= argc)
|
||||||
usage (EXIT_FAILURE);
|
usage(EXIT_FAILURE);
|
||||||
|
|
||||||
if (pw) {
|
if (pw) {
|
||||||
uid = pw->pw_uid;
|
uid = pw->pw_uid;
|
||||||
@ -224,11 +223,11 @@ int checkpath (int argc, char **argv)
|
|||||||
gid = gr->gr_gid;
|
gid = gr->gr_gid;
|
||||||
|
|
||||||
while (optind < argc) {
|
while (optind < argc) {
|
||||||
if (do_check (argv[optind], uid, gid, mode, file))
|
if (do_check(argv[optind], uid, gid, mode, file))
|
||||||
retval = EXIT_FAILURE;
|
retval = EXIT_FAILURE;
|
||||||
optind++;
|
optind++;
|
||||||
}
|
}
|
||||||
|
|
||||||
exit (retval);
|
exit(retval);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -72,27 +73,26 @@
|
|||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "rc-misc.h"
|
#include "rc-misc.h"
|
||||||
#include "strlist.h"
|
|
||||||
|
|
||||||
#ifdef HAVE_GETMNTENT
|
#ifdef HAVE_GETMNTENT
|
||||||
static struct mntent *getmntfile (const char *file)
|
static struct mntent *getmntfile(const char *file)
|
||||||
{
|
{
|
||||||
struct mntent *ent = NULL;
|
struct mntent *ent;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
START_ENT;
|
START_ENT;
|
||||||
while ((ent = getmntent (fp)))
|
while ((ent = getmntent(fp)))
|
||||||
if (strcmp (file, ent->mnt_dir) == 0)
|
if (strcmp(file, ent->mnt_dir) == 0)
|
||||||
break;
|
break;
|
||||||
END_ENT;
|
END_ENT;
|
||||||
|
|
||||||
return (ent);
|
return ent;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const char *applet;
|
extern const char *applet;
|
||||||
|
|
||||||
static int do_mount (struct ENT *ent)
|
static int do_mount(struct ENT *ent)
|
||||||
{
|
{
|
||||||
char *argv[8];
|
char *argv[8];
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
@ -100,29 +100,27 @@ static int do_mount (struct ENT *ent)
|
|||||||
|
|
||||||
argv[0] = (char *) "mount";
|
argv[0] = (char *) "mount";
|
||||||
argv[1] = (char *) "-o";
|
argv[1] = (char *) "-o";
|
||||||
argv[2] = ENT_OPTS (*ent);
|
argv[2] = ENT_OPTS(*ent);
|
||||||
argv[3] = (char *) "-t";
|
argv[3] = (char *) "-t";
|
||||||
argv[4] = ENT_TYPE (*ent);
|
argv[4] = ENT_TYPE(*ent);
|
||||||
argv[5] = ENT_BLOCKDEVICE (*ent);
|
argv[5] = ENT_BLOCKDEVICE(*ent);
|
||||||
argv[6] = ENT_FILE (*ent);
|
argv[6] = ENT_FILE(*ent);
|
||||||
argv[7] = NULL;
|
argv[7] = NULL;
|
||||||
switch (pid = vfork()) {
|
switch (pid = vfork()) {
|
||||||
case -1:
|
case -1:
|
||||||
eerrorx ("%s: vfork: %s", applet,
|
eerrorx("%s: vfork: %s", applet, strerror(errno));
|
||||||
strerror (errno));
|
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
case 0:
|
case 0:
|
||||||
execvp (argv[0], argv);
|
execvp(argv[0], argv);
|
||||||
eerror ("%s: execv: %s", applet,
|
eerror("%s: execv: %s", applet, strerror(errno));
|
||||||
strerror (errno));
|
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
default:
|
default:
|
||||||
waitpid (pid, &status, 0);
|
waitpid(pid, &status, 0);
|
||||||
if (WIFEXITED (status))
|
if (WIFEXITED(status))
|
||||||
return (WEXITSTATUS(status));
|
return WEXITSTATUS(status);
|
||||||
else
|
else
|
||||||
return (-1);
|
return -1;
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -155,7 +153,7 @@ static const char * const longopts_help[] = {
|
|||||||
#define OUTPUT_BLOCKDEV (1 << 5)
|
#define OUTPUT_BLOCKDEV (1 << 5)
|
||||||
#define OUTPUT_MOUNT (1 << 6)
|
#define OUTPUT_MOUNT (1 << 6)
|
||||||
|
|
||||||
int fstabinfo (int argc, char **argv)
|
int fstabinfo(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct ENT *ent;
|
struct ENT *ent;
|
||||||
int result = EXIT_SUCCESS;
|
int result = EXIT_SUCCESS;
|
||||||
@ -163,8 +161,8 @@ int fstabinfo (int argc, char **argv)
|
|||||||
int i;
|
int i;
|
||||||
int opt;
|
int opt;
|
||||||
int output = OUTPUT_FILE;
|
int output = OUTPUT_FILE;
|
||||||
char **files = NULL;
|
RC_STRINGLIST *files = rc_stringlist_new();
|
||||||
char *file;
|
RC_STRING *file;
|
||||||
bool filtered = false;
|
bool filtered = false;
|
||||||
|
|
||||||
#ifdef HAVE_GETMNTENT
|
#ifdef HAVE_GETMNTENT
|
||||||
@ -172,125 +170,126 @@ int fstabinfo (int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Ensure that we are only quiet when explicitly told to be */
|
/* Ensure that we are only quiet when explicitly told to be */
|
||||||
unsetenv ("EINFO_QUIET");
|
unsetenv("EINFO_QUIET");
|
||||||
|
|
||||||
while ((opt = getopt_long (argc, argv, getoptstring,
|
while ((opt = getopt_long(argc, argv, getoptstring,
|
||||||
longopts, (int *) 0)) != -1)
|
longopts, (int *) 0)) != -1)
|
||||||
{
|
{
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'M':
|
case 'M':
|
||||||
output = OUTPUT_MOUNT;
|
output = OUTPUT_MOUNT;
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
output = OUTPUT_BLOCKDEV;
|
output = OUTPUT_BLOCKDEV;
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
output = OUTPUT_OPTIONS;
|
output = OUTPUT_OPTIONS;
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
output = OUTPUT_MOUNTARGS;
|
output = OUTPUT_MOUNTARGS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
switch (optarg[0]) {
|
switch (optarg[0]) {
|
||||||
case '=':
|
case '=':
|
||||||
case '<':
|
case '<':
|
||||||
case '>':
|
case '>':
|
||||||
if (sscanf (optarg + 1, "%d", &i) != 1)
|
if (sscanf(optarg + 1, "%d", &i) != 1)
|
||||||
eerrorx ("%s: invalid passno %s", argv[0], optarg + 1);
|
eerrorx("%s: invalid passno %s",
|
||||||
|
argv[0], optarg + 1);
|
||||||
|
|
||||||
filtered = true;
|
|
||||||
START_ENT;
|
|
||||||
while ((ent = GET_ENT)) {
|
|
||||||
if (((optarg[0] == '=' && i == ENT_PASS (ent)) ||
|
|
||||||
(optarg[0] == '<' && i > ENT_PASS (ent)) ||
|
|
||||||
(optarg[0] == '>' && i < ENT_PASS (ent))) &&
|
|
||||||
strcmp (ENT_FILE (ent), "none") != 0)
|
|
||||||
rc_strlist_add (&files, ENT_FILE (ent));
|
|
||||||
}
|
|
||||||
END_ENT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
rc_strlist_add (&files, optarg);
|
|
||||||
output = OUTPUT_PASSNO;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 't':
|
|
||||||
filtered = true;
|
filtered = true;
|
||||||
while ((token = strsep (&optarg, ","))) {
|
START_ENT;
|
||||||
START_ENT;
|
while ((ent = GET_ENT)) {
|
||||||
while ((ent = GET_ENT))
|
if (((optarg[0] == '=' && i == ENT_PASS(ent)) ||
|
||||||
if (strcmp (token, ENT_TYPE (ent)) == 0)
|
(optarg[0] == '<' && i > ENT_PASS(ent)) ||
|
||||||
rc_strlist_add (&files, ENT_FILE (ent));
|
(optarg[0] == '>' && i < ENT_PASS(ent))) &&
|
||||||
END_ENT;
|
strcmp(ENT_FILE(ent), "none") != 0)
|
||||||
|
rc_stringlist_add(files, ENT_FILE(ent));
|
||||||
}
|
}
|
||||||
|
END_ENT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case_RC_COMMON_GETOPT
|
default:
|
||||||
|
rc_stringlist_add(files, optarg);
|
||||||
|
output = OUTPUT_PASSNO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 't':
|
||||||
|
filtered = true;
|
||||||
|
while ((token = strsep(&optarg, ","))) {
|
||||||
|
START_ENT;
|
||||||
|
while ((ent = GET_ENT))
|
||||||
|
if (strcmp(token, ENT_TYPE(ent)) == 0)
|
||||||
|
rc_stringlist_add(files, ENT_FILE(ent));
|
||||||
|
END_ENT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case_RC_COMMON_GETOPT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (optind < argc)
|
if (optind < argc) {
|
||||||
rc_strlist_add (&files, argv[optind++]);
|
while (optind < argc)
|
||||||
|
rc_stringlist_add(files, argv[optind++]);
|
||||||
if (! files && ! filtered) {
|
} else if (! filtered) {
|
||||||
START_ENT;
|
START_ENT;
|
||||||
while ((ent = GET_ENT))
|
while ((ent = GET_ENT))
|
||||||
rc_strlist_add (&files, ENT_FILE (ent));
|
rc_stringlist_add(files, ENT_FILE(ent));
|
||||||
END_ENT;
|
END_ENT;
|
||||||
|
|
||||||
if (! files)
|
if (! TAILQ_FIRST(files))
|
||||||
eerrorx ("%s: emtpy fstab", argv[0]);
|
eerrorx("%s: emtpy fstab", argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure we always display something */
|
/* Ensure we always display something */
|
||||||
START_ENT;
|
START_ENT;
|
||||||
STRLIST_FOREACH (files, file, i) {
|
TAILQ_FOREACH(file, files, entries) {
|
||||||
if (! (ent = GET_ENT_FILE (file))) {
|
if (! (ent = GET_ENT_FILE(file->value))) {
|
||||||
result = EXIT_FAILURE;
|
result = EXIT_FAILURE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No point in outputting if quiet */
|
/* No point in outputting if quiet */
|
||||||
if (rc_yesno (getenv ("EINFO_QUIET")))
|
if (rc_yesno(getenv("EINFO_QUIET")))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (output) {
|
switch (output) {
|
||||||
case OUTPUT_BLOCKDEV:
|
case OUTPUT_BLOCKDEV:
|
||||||
printf ("%s\n", ENT_BLOCKDEVICE (ent));
|
printf("%s\n", ENT_BLOCKDEVICE(ent));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OUTPUT_MOUNT:
|
case OUTPUT_MOUNT:
|
||||||
result += do_mount (ent);
|
result += do_mount(ent);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OUTPUT_MOUNTARGS:
|
case OUTPUT_MOUNTARGS:
|
||||||
printf ("-o %s -t %s %s %s\n",
|
printf("-o %s -t %s %s %s\n",
|
||||||
ENT_OPTS (ent),
|
ENT_OPTS(ent),
|
||||||
ENT_TYPE (ent),
|
ENT_TYPE(ent),
|
||||||
ENT_BLOCKDEVICE (ent),
|
ENT_BLOCKDEVICE(ent),
|
||||||
file);
|
file->value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OUTPUT_OPTIONS:
|
case OUTPUT_OPTIONS:
|
||||||
printf ("%s\n", ENT_OPTS (ent));
|
printf("%s\n", ENT_OPTS(ent));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OUTPUT_FILE:
|
case OUTPUT_FILE:
|
||||||
printf ("%s\n", file);
|
printf("%s\n", file->value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OUTPUT_PASSNO:
|
case OUTPUT_PASSNO:
|
||||||
printf ("%d\n", ENT_PASS (ent));
|
printf("%d\n", ENT_PASS(ent));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_ENT;
|
END_ENT;
|
||||||
|
|
||||||
rc_strlist_free (files);
|
rc_stringlist_free(files);
|
||||||
exit (result);
|
exit(result);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
@ -47,16 +47,15 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <regex.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <regex.h>
|
|
||||||
|
|
||||||
#include "builtins.h"
|
#include "builtins.h"
|
||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "rc-misc.h"
|
#include "rc-misc.h"
|
||||||
#include "strlist.h"
|
|
||||||
|
|
||||||
extern const char *applet;
|
extern const char *applet;
|
||||||
|
|
||||||
@ -80,93 +79,93 @@ struct args {
|
|||||||
regex_t *skip_fstype_regex;
|
regex_t *skip_fstype_regex;
|
||||||
regex_t *options_regex;
|
regex_t *options_regex;
|
||||||
regex_t *skip_options_regex;
|
regex_t *skip_options_regex;
|
||||||
char **mounts;
|
RC_STRINGLIST *mounts;
|
||||||
mount_type mount_type;
|
mount_type mount_type;
|
||||||
net_opts netdev;
|
net_opts netdev;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int process_mount (char ***list, struct args *args,
|
static int process_mount(RC_STRINGLIST *list, struct args *args,
|
||||||
char *from, char *to, char *fstype, char *options,
|
char *from, char *to, char *fstype, char *options,
|
||||||
int netdev)
|
int netdev)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
RC_STRING *s;
|
||||||
|
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
/* Skip the really silly rootfs */
|
/* Skip the really silly rootfs */
|
||||||
if (strcmp (fstype, "rootfs") == 0)
|
if (strcmp(fstype, "rootfs") == 0)
|
||||||
return (-1);
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (args->netdev == net_yes && (netdev != -1 || args->mounts)) {
|
if (args->netdev == net_yes &&
|
||||||
|
(netdev != -1 || TAILQ_FIRST(args->mounts)))
|
||||||
|
{
|
||||||
if (netdev != 0)
|
if (netdev != 0)
|
||||||
return (1);
|
return 1;
|
||||||
} else if (args->netdev == net_no && (netdev != -1 || args->mounts)) {
|
} else if (args->netdev == net_no &&
|
||||||
|
(netdev != -1 || TAILQ_FIRST(args->mounts)))
|
||||||
|
{
|
||||||
if (netdev != 1)
|
if (netdev != 1)
|
||||||
return (1);
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
if (args->node_regex &&
|
if (args->node_regex &&
|
||||||
regexec (args->node_regex, from, 0, NULL, 0) != 0)
|
regexec(args->node_regex, from, 0, NULL, 0) != 0)
|
||||||
return (1);
|
return 1;
|
||||||
if (args->skip_node_regex &&
|
if (args->skip_node_regex &&
|
||||||
regexec (args->skip_node_regex, from, 0, NULL, 0) == 0)
|
regexec(args->skip_node_regex, from, 0, NULL, 0) == 0)
|
||||||
return (1);
|
return 1;
|
||||||
|
|
||||||
if (args->fstype_regex &&
|
if (args->fstype_regex &&
|
||||||
regexec (args->fstype_regex, fstype, 0, NULL, 0) != 0)
|
regexec(args->fstype_regex, fstype, 0, NULL, 0) != 0)
|
||||||
return (-1);
|
return -1;
|
||||||
if (args->skip_fstype_regex &&
|
if (args->skip_fstype_regex &&
|
||||||
regexec (args->skip_fstype_regex, fstype, 0, NULL, 0) == 0)
|
regexec(args->skip_fstype_regex, fstype, 0, NULL, 0) == 0)
|
||||||
return (-1);
|
return -1;
|
||||||
|
|
||||||
if (args->options_regex &&
|
if (args->options_regex &&
|
||||||
regexec (args->options_regex, options, 0, NULL, 0) != 0)
|
regexec(args->options_regex, options, 0, NULL, 0) != 0)
|
||||||
return (-1);
|
return -1;
|
||||||
if (args->skip_options_regex &&
|
if (args->skip_options_regex &&
|
||||||
regexec (args->skip_options_regex, options, 0, NULL, 0) == 0)
|
regexec(args->skip_options_regex, options, 0, NULL, 0) == 0)
|
||||||
return (-1);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args->mounts) {
|
if (TAILQ_FIRST(args->mounts)) {
|
||||||
bool found = false;
|
TAILQ_FOREACH(s, args->mounts, entries)
|
||||||
int j;
|
if (strcmp(s->value, to) == 0)
|
||||||
char *mnt;
|
|
||||||
STRLIST_FOREACH (args->mounts, mnt, j)
|
|
||||||
if (strcmp (mnt, to) == 0) {
|
|
||||||
found = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
if (! s)
|
||||||
if (! found)
|
return -1;
|
||||||
return (-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (args->mount_type) {
|
switch (args->mount_type) {
|
||||||
case mount_from:
|
case mount_from:
|
||||||
p = from;
|
p = from;
|
||||||
break;
|
break;
|
||||||
case mount_to:
|
case mount_to:
|
||||||
p = to;
|
p = to;
|
||||||
break;
|
break;
|
||||||
case mount_fstype:
|
case mount_fstype:
|
||||||
p = fstype;
|
p = fstype;
|
||||||
break;
|
break;
|
||||||
case mount_options:
|
case mount_options:
|
||||||
p = options;
|
p = options;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
p = NULL;
|
p = NULL;
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
rc_strlist_addsortc (list, p);
|
rc_stringlist_add(list, p);
|
||||||
return (0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (-1);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BSD
|
#ifdef BSD
|
||||||
@ -212,70 +211,73 @@ static struct opt {
|
|||||||
{ 0, NULL }
|
{ 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static char **find_mounts (struct args *args)
|
static RC_STRINGLIST *find_mounts(struct args *args)
|
||||||
{
|
{
|
||||||
struct statfs *mnts;
|
struct statfs *mnts;
|
||||||
int nmnts;
|
int nmnts;
|
||||||
int i;
|
int i;
|
||||||
char **list = NULL;
|
RC_STRINGLIST *list;
|
||||||
char *options = NULL;
|
char *options = NULL;
|
||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
struct opt *o;
|
struct opt *o;
|
||||||
|
int netdev;
|
||||||
|
char *tmp;
|
||||||
|
size_t l;
|
||||||
|
|
||||||
if ((nmnts = getmntinfo (&mnts, MNT_NOWAIT)) == 0)
|
if ((nmnts = getmntinfo(&mnts, MNT_NOWAIT)) == 0)
|
||||||
eerrorx ("getmntinfo: %s", strerror (errno));
|
eerrorx("getmntinfo: %s", strerror (errno));
|
||||||
|
|
||||||
|
list = rc_stringlist_new();
|
||||||
for (i = 0; i < nmnts; i++) {
|
for (i = 0; i < nmnts; i++) {
|
||||||
int netdev = 0;
|
netdev = 0;
|
||||||
flags = mnts[i].F_FLAGS & MNT_VISFLAGMASK;
|
flags = mnts[i].F_FLAGS & MNT_VISFLAGMASK;
|
||||||
for (o = optnames; flags && o->o_opt; o++) {
|
for (o = optnames; flags && o->o_opt; o++) {
|
||||||
if (flags & o->o_opt) {
|
if (flags & o->o_opt) {
|
||||||
if (o->o_opt == MNT_LOCAL)
|
if (o->o_opt == MNT_LOCAL)
|
||||||
netdev = 1;
|
netdev = 1;
|
||||||
if (! options)
|
if (! options)
|
||||||
options = xstrdup (o->o_name);
|
options = xstrdup(o->o_name);
|
||||||
else {
|
else {
|
||||||
char *tmp = NULL;
|
l = strlen(options) + strlen(o->o_name) + 2;
|
||||||
size_t l = strlen (options) + strlen (o->o_name) + 2;
|
tmp = xmalloc(sizeof (char) * l);
|
||||||
tmp = xmalloc (sizeof (char) * l);
|
snprintf(tmp, l, "%s,%s", options, o->o_name);
|
||||||
snprintf (tmp, l, "%s,%s", options, o->o_name);
|
free(options);
|
||||||
free (options);
|
|
||||||
options = tmp;
|
options = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
flags &= ~o->o_opt;
|
flags &= ~o->o_opt;
|
||||||
}
|
}
|
||||||
|
|
||||||
process_mount (&list, args,
|
process_mount(list, args,
|
||||||
mnts[i].f_mntfromname,
|
mnts[i].f_mntfromname,
|
||||||
mnts[i].f_mntonname,
|
mnts[i].f_mntonname,
|
||||||
mnts[i].f_fstypename,
|
mnts[i].f_fstypename,
|
||||||
options,
|
options,
|
||||||
netdev);
|
netdev);
|
||||||
|
|
||||||
free (options);
|
free(options);
|
||||||
options = NULL;
|
options = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (list);
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined (__linux__)
|
#elif defined (__linux__)
|
||||||
static struct mntent *getmntfile (const char *file)
|
static struct mntent *getmntfile(const char *file)
|
||||||
{
|
{
|
||||||
struct mntent *ent = NULL;
|
struct mntent *ent = NULL;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
fp = setmntent ("/etc/fstab", "r");
|
fp = setmntent("/etc/fstab", "r");
|
||||||
while ((ent = getmntent (fp)))
|
while ((ent = getmntent(fp)))
|
||||||
if (strcmp (file, ent->mnt_dir) == 0)
|
if (strcmp(file, ent->mnt_dir) == 0)
|
||||||
break;
|
break;
|
||||||
endmntent (fp);
|
endmntent(fp);
|
||||||
|
|
||||||
return (ent);
|
return ent;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char **find_mounts (struct args *args)
|
static RC_STRINGLIST *find_mounts(struct args *args)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
@ -284,52 +286,54 @@ static char **find_mounts (struct args *args)
|
|||||||
char *to;
|
char *to;
|
||||||
char *fst;
|
char *fst;
|
||||||
char *opts;
|
char *opts;
|
||||||
char **list = NULL;
|
|
||||||
struct mntent *ent;
|
struct mntent *ent;
|
||||||
int netdev;
|
int netdev;
|
||||||
|
RC_STRINGLIST *list;
|
||||||
|
|
||||||
if ((fp = fopen ("/proc/mounts", "r")) == NULL)
|
if ((fp = fopen("/proc/mounts", "r")) == NULL)
|
||||||
eerrorx ("getmntinfo: %s", strerror (errno));
|
eerrorx("getmntinfo: %s", strerror(errno));
|
||||||
|
|
||||||
buffer = xmalloc (sizeof (char) * PATH_MAX * 3);
|
list = rc_stringlist_new();
|
||||||
while (fgets (buffer, PATH_MAX * 3, fp)) {
|
|
||||||
|
buffer = xmalloc(sizeof(char) * PATH_MAX * 3);
|
||||||
|
while (fgets(buffer, PATH_MAX * 3, fp)) {
|
||||||
netdev = -1;
|
netdev = -1;
|
||||||
p = buffer;
|
p = buffer;
|
||||||
from = strsep (&p, " ");
|
from = strsep(&p, " ");
|
||||||
to = strsep (&p, " ");
|
to = strsep(&p, " ");
|
||||||
fst = strsep (&p, " ");
|
fst = strsep(&p, " ");
|
||||||
opts = strsep (&p, " ");
|
opts = strsep(&p, " ");
|
||||||
|
|
||||||
if ((ent = getmntfile (to))) {
|
if ((ent = getmntfile(to))) {
|
||||||
if (strstr (ent->mnt_opts, "_netdev"))
|
if (strstr(ent->mnt_opts, "_netdev"))
|
||||||
netdev = 0;
|
netdev = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
process_mount (&list, args, from, to, fst, opts, netdev);
|
process_mount(list, args, from, to, fst, opts, netdev);
|
||||||
}
|
}
|
||||||
free (buffer);
|
free(buffer);
|
||||||
fclose (fp);
|
fclose(fp);
|
||||||
|
|
||||||
return (list);
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# error "Operating system not supported!"
|
# error "Operating system not supported!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static regex_t *get_regex (const char *string)
|
static regex_t *get_regex(const char *string)
|
||||||
{
|
{
|
||||||
regex_t *reg = xmalloc (sizeof (*reg));
|
regex_t *reg = xmalloc(sizeof (*reg));
|
||||||
int result;
|
int result;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
|
|
||||||
if ((result = regcomp (reg, string, REG_EXTENDED | REG_NOSUB)) != 0)
|
if ((result = regcomp(reg, string, REG_EXTENDED | REG_NOSUB)) != 0)
|
||||||
{
|
{
|
||||||
regerror (result, reg, buffer, sizeof (buffer));
|
regerror(result, reg, buffer, sizeof(buffer));
|
||||||
eerrorx ("%s: invalid regex `%s'", applet, buffer);
|
eerrorx("%s: invalid regex `%s'", applet, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (reg);
|
return reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "_usage.h"
|
#include "_usage.h"
|
||||||
@ -347,7 +351,7 @@ static const struct option longopts[] = {
|
|||||||
{ "options", 0, NULL, 'i'},
|
{ "options", 0, NULL, 'i'},
|
||||||
{ "fstype", 0, NULL, 's'},
|
{ "fstype", 0, NULL, 's'},
|
||||||
{ "node", 0, NULL, 't'},
|
{ "node", 0, NULL, 't'},
|
||||||
{ "netdev", 0, NULL, 'e'},
|
{ "netdev", 0, NULL, 'e'},
|
||||||
{ "nonetdev", 0, NULL, 'E'},
|
{ "nonetdev", 0, NULL, 'E'},
|
||||||
longopts_COMMON
|
longopts_COMMON
|
||||||
};
|
};
|
||||||
@ -369,112 +373,113 @@ static const char * const longopts_help[] = {
|
|||||||
};
|
};
|
||||||
#include "_usage.c"
|
#include "_usage.c"
|
||||||
|
|
||||||
int mountinfo (int argc, char **argv)
|
int mountinfo(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
struct args args;
|
struct args args;
|
||||||
regex_t *point_regex = NULL;
|
regex_t *point_regex = NULL;
|
||||||
regex_t *skip_point_regex = NULL;
|
regex_t *skip_point_regex = NULL;
|
||||||
char **nodes = NULL;
|
RC_STRINGLIST *nodes;
|
||||||
char *n;
|
RC_STRING *s;
|
||||||
int opt;
|
int opt;
|
||||||
int result;
|
int result;
|
||||||
bool quiet;
|
bool quiet;
|
||||||
|
|
||||||
/* Ensure that we are only quiet when explicitly told to be */
|
/* Ensure that we are only quiet when explicitly told to be */
|
||||||
unsetenv ("EINFO_QUIET");
|
unsetenv("EINFO_QUIET");
|
||||||
|
|
||||||
#define DO_REG(_var) \
|
#define DO_REG(_var) \
|
||||||
if (_var) free (_var); \
|
if (_var) free(_var); \
|
||||||
_var = get_regex (optarg);
|
_var = get_regex(optarg);
|
||||||
#define REG_FREE(_var) \
|
#define REG_FREE(_var) \
|
||||||
if (_var) { regfree (_var); free (_var); }
|
if (_var) { regfree(_var); free(_var); }
|
||||||
|
|
||||||
memset (&args, 0, sizeof (args));
|
memset (&args, 0, sizeof(args));
|
||||||
args.mount_type = mount_to;
|
args.mount_type = mount_to;
|
||||||
args.netdev = net_ignore;
|
args.netdev = net_ignore;
|
||||||
|
args.mounts = rc_stringlist_new();
|
||||||
|
|
||||||
while ((opt = getopt_long (argc, argv, getoptstring,
|
while ((opt = getopt_long(argc, argv, getoptstring,
|
||||||
longopts, (int *) 0)) != -1)
|
longopts, (int *) 0)) != -1)
|
||||||
{
|
{
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'e':
|
case 'e':
|
||||||
args.netdev = net_yes;
|
args.netdev = net_yes;
|
||||||
break;
|
break;
|
||||||
case 'E':
|
case 'E':
|
||||||
args.netdev = net_no;
|
args.netdev = net_no;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
DO_REG (args.fstype_regex);
|
DO_REG(args.fstype_regex);
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
DO_REG (args.skip_fstype_regex);
|
DO_REG(args.skip_fstype_regex);
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
DO_REG (args.node_regex);
|
DO_REG(args.node_regex);
|
||||||
break;
|
break;
|
||||||
case 'N':
|
case 'N':
|
||||||
DO_REG (args.skip_node_regex);
|
DO_REG(args.skip_node_regex);
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
DO_REG (args.options_regex);
|
DO_REG(args.options_regex);
|
||||||
break;
|
break;
|
||||||
case 'O':
|
case 'O':
|
||||||
DO_REG (args.skip_options_regex);
|
DO_REG(args.skip_options_regex);
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
DO_REG (point_regex);
|
DO_REG(point_regex);
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
DO_REG (skip_point_regex);
|
DO_REG(skip_point_regex);
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
args.mount_type = mount_options;
|
args.mount_type = mount_options;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
args.mount_type = mount_fstype;
|
args.mount_type = mount_fstype;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
args.mount_type = mount_from;
|
args.mount_type = mount_from;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case_RC_COMMON_GETOPT
|
case_RC_COMMON_GETOPT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (optind < argc) {
|
while (optind < argc) {
|
||||||
if (argv[optind][0] != '/')
|
if (argv[optind][0] != '/')
|
||||||
eerrorx ("%s: `%s' is not a mount point", argv[0], argv[optind]);
|
eerrorx("%s: `%s' is not a mount point", argv[0], argv[optind]);
|
||||||
rc_strlist_add (&args.mounts, argv[optind++]);
|
rc_stringlist_add(args.mounts, argv[optind++]);
|
||||||
}
|
}
|
||||||
|
nodes = find_mounts(&args);
|
||||||
|
rc_stringlist_free(args.mounts);
|
||||||
|
rc_stringlist_sort(&nodes);
|
||||||
|
|
||||||
nodes = find_mounts (&args);
|
REG_FREE(args.fstype_regex);
|
||||||
|
REG_FREE(args.skip_fstype_regex);
|
||||||
REG_FREE (args.fstype_regex);
|
REG_FREE(args.node_regex);
|
||||||
REG_FREE (args.skip_fstype_regex);
|
REG_FREE(args.skip_node_regex);
|
||||||
REG_FREE (args.node_regex);
|
REG_FREE(args.options_regex);
|
||||||
REG_FREE (args.skip_node_regex);
|
REG_FREE(args.skip_options_regex);
|
||||||
REG_FREE (args.options_regex);
|
|
||||||
REG_FREE (args.skip_options_regex);
|
|
||||||
|
|
||||||
rc_strlist_reverse (nodes);
|
|
||||||
|
|
||||||
result = EXIT_FAILURE;
|
result = EXIT_FAILURE;
|
||||||
quiet = rc_yesno (getenv ("EINFO_QUIET"));
|
quiet = rc_yesno(getenv("EINFO_QUIET"));
|
||||||
STRLIST_FOREACH (nodes, n, i) {
|
TAILQ_FOREACH_REVERSE(s, nodes, rc_stringlist, entries) {
|
||||||
if (point_regex && regexec (point_regex, n, 0, NULL, 0) != 0)
|
if (point_regex &&
|
||||||
|
regexec(point_regex, s->value, 0, NULL, 0) != 0)
|
||||||
continue;
|
continue;
|
||||||
if (skip_point_regex && regexec (skip_point_regex, n, 0, NULL, 0) == 0)
|
if (skip_point_regex &&
|
||||||
|
regexec(skip_point_regex, s->value, 0, NULL, 0) == 0)
|
||||||
continue;
|
continue;
|
||||||
if (! quiet)
|
if (! quiet)
|
||||||
printf ("%s\n", n);
|
printf("%s\n", s->value);
|
||||||
result = EXIT_SUCCESS;
|
result = EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
rc_strlist_free (nodes);
|
rc_stringlist_free(nodes);
|
||||||
|
|
||||||
REG_FREE (point_regex);
|
REG_FREE(point_regex);
|
||||||
REG_FREE (skip_point_regex);
|
REG_FREE(skip_point_regex);
|
||||||
|
|
||||||
exit (result);
|
exit(result);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#define SYSLOG_NAMES
|
#define SYSLOG_NAMES
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
@ -49,26 +50,25 @@
|
|||||||
#include "builtins.h"
|
#include "builtins.h"
|
||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "rc-misc.h"
|
#include "rc-misc.h"
|
||||||
#include "strlist.h"
|
|
||||||
|
|
||||||
/* Applet is first parsed in rc.c - no point in doing it again */
|
/* Applet is first parsed in rc.c - no point in doing it again */
|
||||||
extern const char *applet;
|
extern const char *applet;
|
||||||
|
|
||||||
static int syslog_decode (char *name, CODE *codetab)
|
static int syslog_decode(char *name, CODE *codetab)
|
||||||
{
|
{
|
||||||
CODE *c;
|
CODE *c;
|
||||||
|
|
||||||
if (isdigit ((int) *name))
|
if (isdigit((int) *name))
|
||||||
return (atoi (name));
|
return atoi(name);
|
||||||
|
|
||||||
for (c = codetab; c->c_name; c++)
|
for (c = codetab; c->c_name; c++)
|
||||||
if (! strcasecmp (name, c->c_name))
|
if (! strcasecmp(name, c->c_name))
|
||||||
return (c->c_val);
|
return c->c_val;
|
||||||
|
|
||||||
return (-1);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_e (int argc, char **argv)
|
static int do_e(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int retval = EXIT_SUCCESS;
|
int retval = EXIT_SUCCESS;
|
||||||
int i;
|
int i;
|
||||||
@ -82,42 +82,42 @@ static int do_e (int argc, char **argv)
|
|||||||
argc--;
|
argc--;
|
||||||
argv++;
|
argv++;
|
||||||
|
|
||||||
if (strcmp (applet, "eval_ecolors") == 0) {
|
if (strcmp(applet, "eval_ecolors") == 0) {
|
||||||
printf ("GOOD='%s'\nWARN='%s'\nBAD='%s'\nHILITE='%s'\nBRACKET='%s'\nNORMAL='%s'\n",
|
printf("GOOD='%s'\nWARN='%s'\nBAD='%s'\nHILITE='%s'\nBRACKET='%s'\nNORMAL='%s'\n",
|
||||||
ecolor (ECOLOR_GOOD),
|
ecolor(ECOLOR_GOOD),
|
||||||
ecolor (ECOLOR_WARN),
|
ecolor(ECOLOR_WARN),
|
||||||
ecolor (ECOLOR_BAD),
|
ecolor(ECOLOR_BAD),
|
||||||
ecolor (ECOLOR_HILITE),
|
ecolor(ECOLOR_HILITE),
|
||||||
ecolor (ECOLOR_BRACKET),
|
ecolor(ECOLOR_BRACKET),
|
||||||
ecolor (ECOLOR_NORMAL));
|
ecolor(ECOLOR_NORMAL));
|
||||||
exit (EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc > 0) {
|
if (argc > 0) {
|
||||||
if (strcmp (applet, "eend") == 0 ||
|
if (strcmp(applet, "eend") == 0 ||
|
||||||
strcmp (applet, "ewend") == 0 ||
|
strcmp(applet, "ewend") == 0 ||
|
||||||
strcmp (applet, "veend") == 0 ||
|
strcmp(applet, "veend") == 0 ||
|
||||||
strcmp (applet, "vweend") == 0)
|
strcmp(applet, "vweend") == 0)
|
||||||
{
|
{
|
||||||
errno = 0;
|
errno = 0;
|
||||||
retval = (int) strtoimax (argv[0], NULL, 0);
|
retval = (int) strtoimax(argv[0], NULL, 0);
|
||||||
if (errno != 0)
|
if (errno != 0)
|
||||||
retval = EXIT_FAILURE;
|
retval = EXIT_FAILURE;
|
||||||
else {
|
else {
|
||||||
argc--;
|
argc--;
|
||||||
argv++;
|
argv++;
|
||||||
}
|
}
|
||||||
} else if (strcmp (applet, "esyslog") == 0 ||
|
} else if (strcmp(applet, "esyslog") == 0 ||
|
||||||
strcmp (applet, "elog") == 0) {
|
strcmp(applet, "elog") == 0) {
|
||||||
char *dot = strchr (argv[0], '.');
|
p = strchr(argv[0], '.');
|
||||||
if ((level = syslog_decode (dot + 1, prioritynames)) == -1)
|
if ((level = syslog_decode(p + 1, prioritynames)) == -1)
|
||||||
eerrorx ("%s: invalid log level `%s'", applet, argv[0]);
|
eerrorx("%s: invalid log level `%s'", applet, argv[0]);
|
||||||
|
|
||||||
if (argc < 3)
|
if (argc < 3)
|
||||||
eerrorx ("%s: not enough arguments", applet);
|
eerrorx("%s: not enough arguments", applet);
|
||||||
|
|
||||||
unsetenv ("EINFO_LOG");
|
unsetenv("EINFO_LOG");
|
||||||
setenv ("EINFO_LOG", argv[1], 1);
|
setenv("EINFO_LOG", argv[1], 1);
|
||||||
|
|
||||||
argc -= 2;
|
argc -= 2;
|
||||||
argv += 2;
|
argv += 2;
|
||||||
@ -126,16 +126,17 @@ static int do_e (int argc, char **argv)
|
|||||||
|
|
||||||
if (argc > 0) {
|
if (argc > 0) {
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++)
|
||||||
l += strlen (argv[i]) + 1;
|
l += strlen(argv[i]) + 1;
|
||||||
|
|
||||||
message = xmalloc (l);
|
message = xmalloc(l);
|
||||||
p = message;
|
p = message;
|
||||||
|
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
*p++ = ' ';
|
*p++ = ' ';
|
||||||
memcpy (p, argv[i], strlen (argv[i]));
|
l = strlen(argv[i]);
|
||||||
p += strlen (argv[i]);
|
memcpy(p, argv[i], l);
|
||||||
|
p += l;
|
||||||
}
|
}
|
||||||
*p = 0;
|
*p = 0;
|
||||||
}
|
}
|
||||||
@ -143,300 +144,302 @@ static int do_e (int argc, char **argv)
|
|||||||
if (! message)
|
if (! message)
|
||||||
fmt = "";
|
fmt = "";
|
||||||
|
|
||||||
if (strcmp (applet, "einfo") == 0)
|
if (strcmp(applet, "einfo") == 0)
|
||||||
einfo (fmt, message);
|
einfo(fmt, message);
|
||||||
else if (strcmp (applet, "einfon") == 0)
|
else if (strcmp(applet, "einfon") == 0)
|
||||||
einfon (fmt, message);
|
einfon(fmt, message);
|
||||||
else if (strcmp (applet, "ewarn") == 0)
|
else if (strcmp(applet, "ewarn") == 0)
|
||||||
ewarn (fmt, message);
|
ewarn(fmt, message);
|
||||||
else if (strcmp (applet, "ewarnn") == 0)
|
else if (strcmp(applet, "ewarnn") == 0)
|
||||||
ewarnn (fmt, message);
|
ewarnn(fmt, message);
|
||||||
else if (strcmp (applet, "eerror") == 0) {
|
else if (strcmp(applet, "eerror") == 0) {
|
||||||
eerror (fmt, message);
|
eerror(fmt, message);
|
||||||
retval = 1;
|
retval = 1;
|
||||||
} else if (strcmp (applet, "eerrorn") == 0) {
|
} else if (strcmp(applet, "eerrorn") == 0) {
|
||||||
eerrorn (fmt, message);
|
eerrorn(fmt, message);
|
||||||
retval = 1;
|
retval = 1;
|
||||||
} else if (strcmp (applet, "ebegin") == 0)
|
} else if (strcmp(applet, "ebegin") == 0)
|
||||||
ebegin (fmt, message);
|
ebegin(fmt, message);
|
||||||
else if (strcmp (applet, "eend") == 0)
|
else if (strcmp(applet, "eend") == 0)
|
||||||
eend (retval, fmt, message);
|
eend(retval, fmt, message);
|
||||||
else if (strcmp (applet, "ewend") == 0)
|
else if (strcmp(applet, "ewend") == 0)
|
||||||
ewend (retval, fmt, message);
|
ewend(retval, fmt, message);
|
||||||
else if (strcmp (applet, "esyslog") == 0)
|
else if (strcmp(applet, "esyslog") == 0)
|
||||||
elog (level, fmt, message);
|
elog(level, fmt, message);
|
||||||
else if (strcmp (applet, "veinfo") == 0)
|
else if (strcmp(applet, "veinfo") == 0)
|
||||||
einfov (fmt, message);
|
einfov(fmt, message);
|
||||||
else if (strcmp (applet, "veinfon") == 0)
|
else if (strcmp(applet, "veinfon") == 0)
|
||||||
einfovn (fmt, message);
|
einfovn(fmt, message);
|
||||||
else if (strcmp (applet, "vewarn") == 0)
|
else if (strcmp(applet, "vewarn") == 0)
|
||||||
ewarnv (fmt, message);
|
ewarnv(fmt, message);
|
||||||
else if (strcmp (applet, "vewarnn") == 0)
|
else if (strcmp(applet, "vewarnn") == 0)
|
||||||
ewarnvn (fmt, message);
|
ewarnvn(fmt, message);
|
||||||
else if (strcmp (applet, "vebegin") == 0)
|
else if (strcmp(applet, "vebegin") == 0)
|
||||||
ebeginv (fmt, message);
|
ebeginv(fmt, message);
|
||||||
else if (strcmp (applet, "veend") == 0)
|
else if (strcmp(applet, "veend") == 0)
|
||||||
eendv (retval, fmt, message);
|
eendv(retval, fmt, message);
|
||||||
else if (strcmp (applet, "vewend") == 0)
|
else if (strcmp(applet, "vewend") == 0)
|
||||||
ewendv (retval, fmt, message);
|
ewendv(retval, fmt, message);
|
||||||
else if (strcmp (applet, "eindent") == 0)
|
else if (strcmp(applet, "eindent") == 0)
|
||||||
eindent ();
|
eindent();
|
||||||
else if (strcmp (applet, "eoutdent") == 0)
|
else if (strcmp(applet, "eoutdent") == 0)
|
||||||
eoutdent ();
|
eoutdent();
|
||||||
else if (strcmp (applet, "veindent") == 0)
|
else if (strcmp(applet, "veindent") == 0)
|
||||||
eindentv ();
|
eindentv();
|
||||||
else if (strcmp (applet, "veoutdent") == 0)
|
else if (strcmp(applet, "veoutdent") == 0)
|
||||||
eoutdentv ();
|
eoutdentv();
|
||||||
else {
|
else {
|
||||||
eerror ("%s: unknown applet", applet);
|
eerror("%s: unknown applet", applet);
|
||||||
retval = EXIT_FAILURE;
|
retval = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
free (message);
|
free(message);
|
||||||
return (retval);
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_service (int argc, char **argv)
|
static int do_service(int argc, char **argv)
|
||||||
{
|
{
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
char *service = NULL;
|
char *service = NULL;
|
||||||
|
int idx = 0;
|
||||||
|
char *d[] = { NULL, NULL };
|
||||||
|
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
service = argv[1];
|
service = argv[1];
|
||||||
else
|
else
|
||||||
service = getenv ("SVCNAME");
|
service = getenv("SVCNAME");
|
||||||
|
|
||||||
if (! service || *service == '\0')
|
if (! service || *service == '\0')
|
||||||
eerrorx ("%s: no service specified", applet);
|
eerrorx("%s: no service specified", applet);
|
||||||
|
|
||||||
if (strcmp (applet, "service_started") == 0)
|
if (strcmp(applet, "service_started") == 0)
|
||||||
ok = (rc_service_state (service) & RC_SERVICE_STARTED);
|
ok = (rc_service_state(service) & RC_SERVICE_STARTED);
|
||||||
else if (strcmp (applet, "service_stopped") == 0)
|
else if (strcmp(applet, "service_stopped") == 0)
|
||||||
ok = (rc_service_state (service) & RC_SERVICE_STOPPED);
|
ok = (rc_service_state(service) & RC_SERVICE_STOPPED);
|
||||||
else if (strcmp (applet, "service_inactive") == 0)
|
else if (strcmp(applet, "service_inactive") == 0)
|
||||||
ok = (rc_service_state (service) & RC_SERVICE_INACTIVE);
|
ok = (rc_service_state(service) & RC_SERVICE_INACTIVE);
|
||||||
else if (strcmp (applet, "service_starting") == 0)
|
else if (strcmp(applet, "service_starting") == 0)
|
||||||
ok = (rc_service_state (service) & RC_SERVICE_STARTING);
|
ok = (rc_service_state(service) & RC_SERVICE_STARTING);
|
||||||
else if (strcmp (applet, "service_stopping") == 0)
|
else if (strcmp(applet, "service_stopping") == 0)
|
||||||
ok = (rc_service_state (service) & RC_SERVICE_STOPPING);
|
ok = (rc_service_state(service) & RC_SERVICE_STOPPING);
|
||||||
else if (strcmp (applet, "service_coldplugged") == 0)
|
else if (strcmp(applet, "service_coldplugged") == 0)
|
||||||
ok = (rc_service_state (service) & RC_SERVICE_COLDPLUGGED);
|
ok = (rc_service_state(service) & RC_SERVICE_COLDPLUGGED);
|
||||||
else if (strcmp (applet, "service_wasinactive") == 0)
|
else if (strcmp(applet, "service_wasinactive") == 0)
|
||||||
ok = (rc_service_state (service) & RC_SERVICE_WASINACTIVE);
|
ok = (rc_service_state(service) & RC_SERVICE_WASINACTIVE);
|
||||||
else if (strcmp (applet, "service_started_daemon") == 0) {
|
else if (strcmp(applet, "service_started_daemon") == 0) {
|
||||||
int idx = 0;
|
d[0] = argv[1];
|
||||||
char *d[] = { argv[1], NULL };
|
|
||||||
|
|
||||||
service = getenv ("SVCNAME");
|
service = getenv("SVCNAME");
|
||||||
if (argc > 3) {
|
if (argc > 3) {
|
||||||
service = argv[1];
|
service = argv[1];
|
||||||
d[0] = argv[2];
|
d[0] = argv[2];
|
||||||
sscanf (argv[3], "%d", &idx);
|
sscanf(argv[3], "%d", &idx);
|
||||||
} else if (argc == 3) {
|
} else if (argc == 3) {
|
||||||
if (sscanf (argv[2], "%d", &idx) != 1) {
|
if (sscanf(argv[2], "%d", &idx) != 1) {
|
||||||
service = argv[1];
|
service = argv[1];
|
||||||
*d = argv[2];
|
d[0] = argv[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ok = rc_service_started_daemon (service,
|
ok = rc_service_started_daemon(service,
|
||||||
(const char * const *)d, idx);
|
(const char * const *)d, idx);
|
||||||
|
|
||||||
} else
|
} else
|
||||||
eerrorx ("%s: unknown applet", applet);
|
eerrorx("%s: unknown applet", applet);
|
||||||
|
|
||||||
return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
|
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_mark_service (int argc, char **argv)
|
static int do_mark_service(int argc, char **argv)
|
||||||
{
|
{
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
char *svcname = getenv ("SVCNAME");
|
char *svcname = getenv("SVCNAME");
|
||||||
char *service = NULL;
|
char *service = NULL;
|
||||||
|
char *runscript_pid;
|
||||||
|
char *mtime;
|
||||||
|
pid_t pid;
|
||||||
|
size_t l;
|
||||||
|
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
service = argv[1];
|
service = argv[1];
|
||||||
else
|
else
|
||||||
service = getenv ("SVCNAME");
|
service = getenv("SVCNAME");
|
||||||
|
|
||||||
if (! service || *service == '\0')
|
if (! service || *service == '\0')
|
||||||
eerrorx ("%s: no service specified", applet);
|
eerrorx("%s: no service specified", applet);
|
||||||
|
|
||||||
if (strcmp (applet, "mark_service_started") == 0)
|
if (strcmp(applet, "mark_service_started") == 0)
|
||||||
ok = rc_service_mark (service, RC_SERVICE_STARTED);
|
ok = rc_service_mark(service, RC_SERVICE_STARTED);
|
||||||
else if (strcmp (applet, "mark_service_stopped") == 0)
|
else if (strcmp(applet, "mark_service_stopped") == 0)
|
||||||
ok = rc_service_mark (service, RC_SERVICE_STOPPED);
|
ok = rc_service_mark(service, RC_SERVICE_STOPPED);
|
||||||
else if (strcmp (applet, "mark_service_inactive") == 0)
|
else if (strcmp(applet, "mark_service_inactive") == 0)
|
||||||
ok = rc_service_mark (service, RC_SERVICE_INACTIVE);
|
ok = rc_service_mark(service, RC_SERVICE_INACTIVE);
|
||||||
else if (strcmp (applet, "mark_service_starting") == 0)
|
else if (strcmp(applet, "mark_service_starting") == 0)
|
||||||
ok = rc_service_mark (service, RC_SERVICE_STARTING);
|
ok = rc_service_mark(service, RC_SERVICE_STARTING);
|
||||||
else if (strcmp (applet, "mark_service_stopping") == 0)
|
else if (strcmp(applet, "mark_service_stopping") == 0)
|
||||||
ok = rc_service_mark (service, RC_SERVICE_STOPPING);
|
ok = rc_service_mark(service, RC_SERVICE_STOPPING);
|
||||||
else if (strcmp (applet, "mark_service_coldplugged") == 0)
|
else if (strcmp(applet, "mark_service_coldplugged") == 0)
|
||||||
ok = rc_service_mark (service, RC_SERVICE_COLDPLUGGED);
|
ok = rc_service_mark(service, RC_SERVICE_COLDPLUGGED);
|
||||||
else if (strcmp (applet, "mark_service_failed") == 0)
|
else if (strcmp(applet, "mark_service_failed") == 0)
|
||||||
ok = rc_service_mark (service, RC_SERVICE_FAILED);
|
ok = rc_service_mark(service, RC_SERVICE_FAILED);
|
||||||
else
|
else
|
||||||
eerrorx ("%s: unknown applet", applet);
|
eerrorx("%s: unknown applet", applet);
|
||||||
|
|
||||||
/* If we're marking ourselves then we need to inform our parent runscript
|
/* If we're marking ourselves then we need to inform our parent runscript
|
||||||
process so they do not mark us based on our exit code */
|
process so they do not mark us based on our exit code */
|
||||||
if (ok && svcname && strcmp (svcname, service) == 0) {
|
if (ok && svcname && strcmp(svcname, service) == 0) {
|
||||||
char *runscript_pid = getenv ("RC_RUNSCRIPT_PID");
|
runscript_pid = getenv("RC_RUNSCRIPT_PID");
|
||||||
char *mtime;
|
if (runscript_pid && sscanf(runscript_pid, "%d", &pid) == 1)
|
||||||
pid_t pid = 0;
|
if (kill(pid, SIGHUP) != 0)
|
||||||
size_t l;
|
eerror("%s: failed to signal parent %d: %s",
|
||||||
|
applet, pid, strerror(errno));
|
||||||
if (runscript_pid && sscanf (runscript_pid, "%d", &pid) == 1)
|
|
||||||
if (kill (pid, SIGHUP) != 0)
|
|
||||||
eerror ("%s: failed to signal parent %d: %s",
|
|
||||||
applet, pid, strerror (errno));
|
|
||||||
|
|
||||||
/* Remove the exclusive time test. This ensures that it's not
|
/* Remove the exclusive time test. This ensures that it's not
|
||||||
in control as well */
|
in control as well */
|
||||||
l = strlen (RC_SVCDIR "exclusive") +
|
l = strlen(RC_SVCDIR "exclusive") + strlen(svcname) +
|
||||||
strlen (svcname) +
|
strlen(runscript_pid) + 4;
|
||||||
strlen (runscript_pid) +
|
mtime = xmalloc(l);
|
||||||
4;
|
snprintf(mtime, l, RC_SVCDIR "exclusive/%s.%s",
|
||||||
mtime = xmalloc (l);
|
svcname, runscript_pid);
|
||||||
snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s",
|
if (exists(mtime) && unlink(mtime) != 0)
|
||||||
svcname, runscript_pid);
|
eerror("%s: unlink: %s", applet, strerror(errno));
|
||||||
if (exists (mtime) && unlink (mtime) != 0)
|
free(mtime);
|
||||||
eerror ("%s: unlink: %s", applet, strerror (errno));
|
|
||||||
free (mtime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
|
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_value (int argc, char **argv)
|
static int do_value(int argc, char **argv)
|
||||||
{
|
{
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
char *service = getenv ("SVCNAME");
|
char *service = getenv("SVCNAME");
|
||||||
|
char *option;
|
||||||
|
|
||||||
if (! service)
|
if (! service)
|
||||||
eerrorx ("%s: no service specified", applet);
|
eerrorx("%s: no service specified", applet);
|
||||||
|
|
||||||
if (argc < 2 || ! argv[1] || *argv[1] == '\0')
|
if (argc < 2 || ! argv[1] || *argv[1] == '\0')
|
||||||
eerrorx ("%s: no option specified", applet);
|
eerrorx("%s: no option specified", applet);
|
||||||
|
|
||||||
if (strcmp (applet, "service_get_value") == 0 ||
|
if (strcmp(applet, "service_get_value") == 0 ||
|
||||||
strcmp (applet, "get_options") == 0)
|
strcmp(applet, "get_options") == 0)
|
||||||
{
|
{
|
||||||
char *option = rc_service_value_get (service, argv[1]);
|
option = rc_service_value_get(service, argv[1]);
|
||||||
if (option) {
|
if (option) {
|
||||||
printf ("%s", option);
|
printf("%s", option);
|
||||||
free (option);
|
free(option);
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
} else if (strcmp (applet, "service_set_value") == 0 ||
|
} else if (strcmp(applet, "service_set_value") == 0 ||
|
||||||
strcmp (applet, "save_options") == 0)
|
strcmp(applet, "save_options") == 0)
|
||||||
ok = rc_service_value_set (service, argv[1], argv[2]);
|
ok = rc_service_value_set(service, argv[1], argv[2]);
|
||||||
else
|
else
|
||||||
eerrorx ("%s: unknown applet", applet);
|
eerrorx("%s: unknown applet", applet);
|
||||||
|
|
||||||
return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
|
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_shell_var (int argc, char **argv)
|
static int do_shell_var(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
char *p;
|
||||||
|
int c;
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
char *p = argv[i];
|
p = argv[i];
|
||||||
|
|
||||||
if (i != 1)
|
if (i != 1)
|
||||||
putchar (' ');
|
putchar(' ');
|
||||||
|
|
||||||
while (*p) {
|
while (*p) {
|
||||||
char c = *p++;
|
c = *p++;
|
||||||
if (! isalnum ((int) c))
|
if (! isalnum(c))
|
||||||
c = '_';
|
c = '_';
|
||||||
putchar (c);
|
putchar(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
putchar ('\n');
|
putchar('\n');
|
||||||
|
|
||||||
return (EXIT_SUCCESS);
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void run_applets (int argc, char **argv)
|
void run_applets(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
int i = 2;
|
||||||
|
bool match = false;
|
||||||
|
char *p;
|
||||||
|
pid_t pid = 0;
|
||||||
|
|
||||||
/* These are designed to be applications in their own right */
|
/* These are designed to be applications in their own right */
|
||||||
if (strcmp (applet, "fstabinfo") == 0)
|
if (strcmp(applet, "fstabinfo") == 0)
|
||||||
exit (fstabinfo (argc, argv));
|
exit(fstabinfo(argc, argv));
|
||||||
else if (strcmp (applet, "mountinfo") == 0)
|
else if (strcmp(applet, "mountinfo") == 0)
|
||||||
exit (mountinfo (argc, argv));
|
exit(mountinfo(argc, argv));
|
||||||
else if (strcmp (applet, "rc-depend") == 0)
|
else if (strcmp(applet, "rc-depend") == 0)
|
||||||
exit (rc_depend (argc, argv));
|
exit(rc_depend(argc, argv));
|
||||||
else if (strcmp (applet, "rc-status") == 0)
|
else if (strcmp(applet, "rc-status") == 0)
|
||||||
exit (rc_status (argc, argv));
|
exit(rc_status(argc, argv));
|
||||||
else if (strcmp (applet, "rc-update") == 0 ||
|
else if (strcmp(applet, "rc-update") == 0 ||
|
||||||
strcmp (applet, "update-rc") == 0)
|
strcmp(applet, "update-rc") == 0)
|
||||||
exit (rc_update (argc, argv));
|
exit(rc_update(argc, argv));
|
||||||
else if (strcmp (applet, "runscript") == 0)
|
else if (strcmp(applet, "runscript") == 0)
|
||||||
exit (runscript (argc, argv));
|
exit(runscript(argc, argv));
|
||||||
else if (strcmp (applet, "start-stop-daemon") == 0)
|
else if (strcmp(applet, "start-stop-daemon") == 0)
|
||||||
exit (start_stop_daemon (argc, argv));
|
exit(start_stop_daemon(argc, argv));
|
||||||
else if (strcmp (applet, "checkpath") == 0)
|
else if (strcmp (applet, "checkpath") == 0)
|
||||||
exit (checkpath (argc, argv));
|
exit(checkpath(argc, argv));
|
||||||
|
|
||||||
/* These could also be applications in their own right */
|
/* These could also be applications in their own right */
|
||||||
if (strcmp (applet, "shell_var") == 0)
|
if (strcmp(applet, "shell_var") == 0)
|
||||||
exit (do_shell_var (argc, argv));
|
exit(do_shell_var(argc, argv));
|
||||||
|
|
||||||
if (strcmp (applet, "is_newer_than") == 0 ||
|
if (strcmp(applet, "is_newer_than") == 0 ||
|
||||||
strcmp (applet, "is_older_than") == 0)
|
strcmp(applet, "is_older_than") == 0)
|
||||||
{
|
{
|
||||||
bool match = false;
|
|
||||||
int i = 2;
|
|
||||||
|
|
||||||
if (argc < 3)
|
if (argc < 3)
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
if (strcmp (applet, "is_newer_than") == 0)
|
if (strcmp(applet, "is_newer_than") == 0)
|
||||||
match = true;
|
match = true;
|
||||||
while (i < argc) {
|
while (i < argc) {
|
||||||
if (rc_newer_than (argv[1], argv[i++]) != match)
|
if (rc_newer_than(argv[1], argv[i++]) != match)
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
exit (EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (applet[0] == 'e' || (applet[0] == 'v' && applet[1] == 'e'))
|
if (applet[0] == 'e' || (applet[0] == 'v' && applet[1] == 'e'))
|
||||||
exit (do_e (argc, argv));
|
exit(do_e(argc, argv));
|
||||||
|
|
||||||
/* These are purely for init scripts and do not make sense as
|
/* These are purely for init scripts and do not make sense as
|
||||||
* anything else */
|
* anything else */
|
||||||
if (strcmp (applet, "service_get_value") == 0 ||
|
if (strcmp(applet, "service_get_value") == 0 ||
|
||||||
strcmp (applet, "service_set_value") == 0 ||
|
strcmp(applet, "service_set_value") == 0 ||
|
||||||
strcmp (applet, "get_options") == 0 ||
|
strcmp(applet, "get_options") == 0 ||
|
||||||
strcmp (applet, "save_options") == 0)
|
strcmp(applet, "save_options") == 0)
|
||||||
exit (do_value (argc, argv));
|
exit(do_value(argc, argv));
|
||||||
|
|
||||||
if (strncmp (applet, "service_", strlen ("service_")) == 0)
|
if (strncmp(applet, "service_", strlen("service_")) == 0)
|
||||||
exit (do_service (argc, argv));
|
exit(do_service(argc, argv));
|
||||||
|
|
||||||
if (strncmp (applet, "mark_service_", strlen ("mark_service_")) == 0)
|
if (strncmp(applet, "mark_service_", strlen("mark_service_")) == 0)
|
||||||
exit (do_mark_service (argc, argv));
|
exit(do_mark_service(argc, argv));
|
||||||
|
|
||||||
if (strcmp (applet, "is_runlevel_start") == 0)
|
if (strcmp(applet, "is_runlevel_start") == 0)
|
||||||
exit (rc_runlevel_starting () ? 0 : 1);
|
exit(rc_runlevel_starting() ? 0 : 1);
|
||||||
else if (strcmp (applet, "is_runlevel_stop") == 0)
|
else if (strcmp (applet, "is_runlevel_stop") == 0)
|
||||||
exit (rc_runlevel_stopping () ? 0 : 1);
|
exit(rc_runlevel_stopping() ? 0 : 1);
|
||||||
|
|
||||||
if (strcmp (applet, "rc-abort") == 0) {
|
if (strcmp(applet, "rc-abort") == 0) {
|
||||||
char *p = getenv ("RC_PID");
|
p = getenv("RC_PID");
|
||||||
pid_t pid = 0;
|
if (p && sscanf(p, "%d", &pid) == 1) {
|
||||||
|
if (kill(pid, SIGUSR1) != 0)
|
||||||
if (p && sscanf (p, "%d", &pid) == 1) {
|
eerrorx("rc-abort: failed to signal parent %d: %s",
|
||||||
if (kill (pid, SIGUSR1) != 0)
|
pid, strerror(errno));
|
||||||
eerrorx ("rc-abort: failed to signal parent %d: %s",
|
exit(EXIT_SUCCESS);
|
||||||
pid, strerror (errno));
|
|
||||||
exit (EXIT_SUCCESS);
|
|
||||||
}
|
}
|
||||||
exit (EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp (applet, "rc" ) != 0)
|
if (strcmp(applet, "rc") != 0)
|
||||||
eerrorx ("%s: unknown applet", applet);
|
eerrorx("%s: unknown applet", applet);
|
||||||
}
|
}
|
||||||
|
@ -45,34 +45,33 @@
|
|||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "rc-misc.h"
|
#include "rc-misc.h"
|
||||||
#include "strlist.h"
|
|
||||||
|
|
||||||
extern const char *applet;
|
extern const char *applet;
|
||||||
|
|
||||||
rc_depinfo_t *_rc_deptree_load (int *regen) {
|
RC_DEPTREE *_rc_deptree_load(int *regen) {
|
||||||
if (rc_deptree_update_needed ()) {
|
int fd;
|
||||||
int fd;
|
int retval;
|
||||||
int retval;
|
int serrno = errno;
|
||||||
int serrno = errno;
|
int merrno;
|
||||||
int merrno;
|
|
||||||
|
|
||||||
|
if (rc_deptree_update_needed()) {
|
||||||
/* Test if we have permission to update the deptree */
|
/* Test if we have permission to update the deptree */
|
||||||
fd = open (RC_DEPTREE, O_WRONLY);
|
fd = open(RC_DEPTREE_CACHE, O_WRONLY);
|
||||||
merrno = errno;
|
merrno = errno;
|
||||||
errno = serrno;
|
errno = serrno;
|
||||||
if (fd == -1 && merrno == EACCES)
|
if (fd == -1 && merrno == EACCES)
|
||||||
return (rc_deptree_load ());
|
return rc_deptree_load();
|
||||||
close (fd);
|
close(fd);
|
||||||
|
|
||||||
if (regen)
|
if (regen)
|
||||||
*regen = 1;
|
*regen = 1;
|
||||||
|
|
||||||
ebegin ("Caching service dependencies");
|
ebegin("Caching service dependencies");
|
||||||
retval = rc_deptree_update ();
|
retval = rc_deptree_update();
|
||||||
eend (retval ? 0 : -1, "Failed to update the dependency tree");
|
eend (retval ? 0 : -1, "Failed to update the dependency tree");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (rc_deptree_load ());
|
return rc_deptree_load();
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "_usage.h"
|
#include "_usage.h"
|
||||||
@ -97,117 +96,114 @@ static const char * const longopts_help[] = {
|
|||||||
};
|
};
|
||||||
#include "_usage.c"
|
#include "_usage.c"
|
||||||
|
|
||||||
int rc_depend (int argc, char **argv)
|
int rc_depend(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char **types = NULL;
|
RC_STRINGLIST *list;
|
||||||
char **services = NULL;
|
RC_STRINGLIST *types;
|
||||||
char **depends = NULL;
|
RC_STRINGLIST *services;
|
||||||
char **list;
|
RC_STRINGLIST *depends;
|
||||||
rc_depinfo_t *deptree = NULL;
|
RC_STRING *s;
|
||||||
char *service;
|
RC_DEPTREE *deptree = NULL;
|
||||||
int options = RC_DEP_TRACE;
|
int options = RC_DEP_TRACE;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
int i;
|
|
||||||
bool update = false;
|
bool update = false;
|
||||||
char *runlevel = xstrdup( getenv ("RC_SOFTLEVEL"));
|
char *runlevel = xstrdup(getenv("RC_SOFTLEVEL"));
|
||||||
int opt;
|
int opt;
|
||||||
char *token;
|
char *token;
|
||||||
|
|
||||||
while ((opt = getopt_long (argc, argv, getoptstring,
|
types = rc_stringlist_new();
|
||||||
longopts, (int *) 0)) != -1)
|
|
||||||
|
while ((opt = getopt_long(argc, argv, getoptstring,
|
||||||
|
longopts, (int *) 0)) != -1)
|
||||||
{
|
{
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'a':
|
case 'a':
|
||||||
options |= RC_DEP_START;
|
options |= RC_DEP_START;
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
options |= RC_DEP_STOP;
|
options |= RC_DEP_STOP;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
options |= RC_DEP_STRICT;
|
options |= RC_DEP_STRICT;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
while ((token = strsep (&optarg, ",")))
|
while ((token = strsep(&optarg, ",")))
|
||||||
rc_strlist_addu (&types, token);
|
rc_stringlist_add(types, token);
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
update = true;
|
update = true;
|
||||||
break;
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
options &= RC_DEP_TRACE;
|
options &= RC_DEP_TRACE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case_RC_COMMON_GETOPT
|
case_RC_COMMON_GETOPT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update) {
|
if (update) {
|
||||||
bool u = false;
|
ebegin("Caching service dependencies");
|
||||||
ebegin ("Caching service dependencies");
|
update = rc_deptree_update();
|
||||||
u = rc_deptree_update ();
|
eend(update ? 0 : -1, "%s: %s", applet, strerror(errno));
|
||||||
eend (u ? 0 : -1, "%s: %s", applet, strerror (errno));
|
if (! update)
|
||||||
if (! u)
|
eerrorx("Failed to update the dependency tree");
|
||||||
eerrorx ("Failed to update the dependency tree");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! (deptree = _rc_deptree_load (NULL)))
|
if (! (deptree = _rc_deptree_load(NULL)))
|
||||||
eerrorx ("failed to load deptree");
|
eerrorx("failed to load deptree");
|
||||||
|
|
||||||
if (! runlevel)
|
if (! runlevel)
|
||||||
runlevel = rc_runlevel_get ();
|
runlevel = rc_runlevel_get();
|
||||||
|
|
||||||
|
services = rc_stringlist_new();
|
||||||
while (optind < argc) {
|
while (optind < argc) {
|
||||||
list = NULL;
|
list = rc_stringlist_new();
|
||||||
rc_strlist_add (&list, argv[optind]);
|
rc_stringlist_add(list, argv[optind]);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
depends = rc_deptree_depends (deptree, NULL, (const char **) list,
|
depends = rc_deptree_depends(deptree, NULL, list, runlevel, 0);
|
||||||
runlevel, 0);
|
|
||||||
if (! depends && errno == ENOENT)
|
if (! depends && errno == ENOENT)
|
||||||
eerror ("no dependency info for service `%s'", argv[optind]);
|
eerror("no dependency info for service `%s'", argv[optind]);
|
||||||
else
|
else
|
||||||
rc_strlist_add (&services, argv[optind]);
|
rc_stringlist_add(services, argv[optind]);
|
||||||
|
|
||||||
rc_strlist_free (depends);
|
rc_stringlist_free(depends);
|
||||||
rc_strlist_free (list);
|
rc_stringlist_free(list);
|
||||||
optind++;
|
optind++;
|
||||||
}
|
}
|
||||||
|
if (! TAILQ_FIRST(services)) {
|
||||||
if (! services) {
|
rc_stringlist_free(services);
|
||||||
rc_strlist_free (types);
|
rc_stringlist_free(types);
|
||||||
rc_deptree_free (deptree);
|
rc_deptree_free(deptree);
|
||||||
free (runlevel);
|
free(runlevel);
|
||||||
if (update)
|
if (update)
|
||||||
return (EXIT_SUCCESS);
|
return EXIT_SUCCESS;
|
||||||
eerrorx ("no services specified");
|
eerrorx("no services specified");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we don't have any types, then supply some defaults */
|
/* If we don't have any types, then supply some defaults */
|
||||||
if (! types) {
|
if (! TAILQ_FIRST(types)) {
|
||||||
rc_strlist_add (&types, "ineed");
|
rc_stringlist_add(types, "ineed");
|
||||||
rc_strlist_add (&types, "iuse");
|
rc_stringlist_add(types, "iuse");
|
||||||
}
|
}
|
||||||
|
|
||||||
depends = rc_deptree_depends (deptree, (const char **) types,
|
depends = rc_deptree_depends(deptree, types, services, runlevel, options);
|
||||||
(const char **) services, runlevel, options);
|
|
||||||
|
|
||||||
if (depends) {
|
if (TAILQ_FIRST(depends)) {
|
||||||
STRLIST_FOREACH (depends, service, i) {
|
TAILQ_FOREACH(s, depends, entries) {
|
||||||
if (first)
|
if (first)
|
||||||
first = false;
|
first = false;
|
||||||
else
|
else
|
||||||
printf (" ");
|
printf (" ");
|
||||||
|
printf ("%s", s->value);
|
||||||
if (service)
|
|
||||||
printf ("%s", service);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_strlist_free (types);
|
rc_stringlist_free(types);
|
||||||
rc_strlist_free (services);
|
rc_stringlist_free(services);
|
||||||
rc_strlist_free (depends);
|
rc_stringlist_free(depends);
|
||||||
rc_deptree_free (deptree);
|
rc_deptree_free(deptree);
|
||||||
free (runlevel);
|
free(runlevel);
|
||||||
return (EXIT_SUCCESS);
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@ -76,67 +77,67 @@ pid_t rc_logger_pid = -1;
|
|||||||
int rc_logger_tty = -1;
|
int rc_logger_tty = -1;
|
||||||
bool rc_in_logger = false;
|
bool rc_in_logger = false;
|
||||||
|
|
||||||
static void write_log (int logfd, const char *buffer, size_t bytes)
|
static void write_log(int logfd, const char *buffer, size_t bytes)
|
||||||
{
|
{
|
||||||
const char *p = buffer;
|
const char *p = buffer;
|
||||||
|
|
||||||
while ((size_t) (p - buffer) < bytes) {
|
while ((size_t) (p - buffer) < bytes) {
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case '\r':
|
case '\r':
|
||||||
goto cont;
|
goto cont;
|
||||||
case '\033':
|
case '\033':
|
||||||
in_escape = true;
|
in_escape = true;
|
||||||
in_term = false;
|
in_term = false;
|
||||||
goto cont;
|
goto cont;
|
||||||
case '\n':
|
case '\n':
|
||||||
in_escape = in_term = false;
|
in_escape = in_term = false;
|
||||||
break;
|
break;
|
||||||
case '[':
|
case '[':
|
||||||
if (in_escape)
|
if (in_escape)
|
||||||
in_term = true;
|
in_term = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! in_escape) {
|
if (! in_escape) {
|
||||||
write (logfd, p++, 1);
|
write(logfd, p++, 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! in_term || isalpha ((int) *p))
|
if (! in_term || isalpha((int) *p))
|
||||||
in_escape = in_term = false;
|
in_escape = in_term = false;
|
||||||
cont:
|
cont:
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static void write_time(FILE *f, const char *s)
|
||||||
static void write_time (FILE *f, const char *s)
|
|
||||||
{
|
{
|
||||||
time_t now = time (NULL);
|
time_t now = time(NULL);
|
||||||
struct tm *tm = localtime (&now);
|
struct tm *tm = localtime(&now);
|
||||||
|
|
||||||
fprintf (f, "\nrc %s logging %s at %s\n", runlevel, s, asctime (tm));
|
fprintf(f, "\nrc %s logging %s at %s\n", runlevel, s, asctime(tm));
|
||||||
fflush (f);
|
fflush(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rc_logger_close ()
|
void rc_logger_close(void)
|
||||||
{
|
{
|
||||||
|
int sig = SIGTERM;
|
||||||
|
|
||||||
if (signal_pipe[1] > -1) {
|
if (signal_pipe[1] > -1) {
|
||||||
int sig = SIGTERM;
|
write(signal_pipe[1], &sig, sizeof(sig));
|
||||||
write (signal_pipe[1], &sig, sizeof (sig));
|
close(signal_pipe[1]);
|
||||||
close (signal_pipe[1]);
|
|
||||||
signal_pipe[1] = -1;
|
signal_pipe[1] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc_logger_pid > 0)
|
if (rc_logger_pid > 0)
|
||||||
waitpid (rc_logger_pid, 0, 0);
|
waitpid(rc_logger_pid, 0, 0);
|
||||||
|
|
||||||
if (fd_stdout > -1)
|
if (fd_stdout > -1)
|
||||||
dup2 (fd_stdout, STDOUT_FILENO);
|
dup2(fd_stdout, STDOUT_FILENO);
|
||||||
if (fd_stderr > -1)
|
if (fd_stderr > -1)
|
||||||
dup2 (fd_stderr, STDERR_FILENO);
|
dup2(fd_stderr, STDERR_FILENO);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rc_logger_open (const char *level)
|
void rc_logger_open(const char *level)
|
||||||
{
|
{
|
||||||
int slave_tty;
|
int slave_tty;
|
||||||
struct termios tt;
|
struct termios tt;
|
||||||
@ -149,125 +150,127 @@ void rc_logger_open (const char *level)
|
|||||||
int i;
|
int i;
|
||||||
FILE *log = NULL;
|
FILE *log = NULL;
|
||||||
|
|
||||||
if (! isatty (STDOUT_FILENO))
|
if (! isatty(STDOUT_FILENO))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (! rc_conf_yesno ("rc_logger"))
|
if (! rc_conf_yesno("rc_logger"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (pipe (signal_pipe) == -1)
|
if (pipe(signal_pipe) == -1)
|
||||||
eerrorx ("pipe: %s", strerror (errno));
|
eerrorx("pipe: %s", strerror(errno));
|
||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++)
|
||||||
if ((s = fcntl (signal_pipe[i], F_GETFD, 0) == -1 ||
|
if ((s = fcntl (signal_pipe[i], F_GETFD, 0) == -1 ||
|
||||||
fcntl (signal_pipe[i], F_SETFD, s | FD_CLOEXEC) == -1))
|
fcntl (signal_pipe[i], F_SETFD, s | FD_CLOEXEC) == -1))
|
||||||
eerrorx ("fcntl: %s", strerror (errno));
|
eerrorx("fcntl: %s", strerror (errno));
|
||||||
|
|
||||||
tcgetattr (STDOUT_FILENO, &tt);
|
tcgetattr(STDOUT_FILENO, &tt);
|
||||||
ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws);
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
|
||||||
|
|
||||||
/* /dev/pts may not be available yet */
|
/* /dev/pts may not be available yet */
|
||||||
if (openpty (&rc_logger_tty, &slave_tty, NULL, &tt, &ws))
|
if (openpty(&rc_logger_tty, &slave_tty, NULL, &tt, &ws))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((s = fcntl (rc_logger_tty, F_GETFD, 0)) == 0)
|
if ((s = fcntl(rc_logger_tty, F_GETFD, 0)) == 0)
|
||||||
fcntl (rc_logger_tty, F_SETFD, s | FD_CLOEXEC);
|
fcntl(rc_logger_tty, F_SETFD, s | FD_CLOEXEC);
|
||||||
|
|
||||||
if ((s = fcntl (slave_tty, F_GETFD, 0)) == 0)
|
if ((s = fcntl(slave_tty, F_GETFD, 0)) == 0)
|
||||||
fcntl (slave_tty, F_SETFD, s | FD_CLOEXEC);
|
fcntl(slave_tty, F_SETFD, s | FD_CLOEXEC);
|
||||||
|
|
||||||
rc_logger_pid = fork ();
|
rc_logger_pid = fork();
|
||||||
switch (rc_logger_pid) {
|
switch (rc_logger_pid) {
|
||||||
case -1:
|
case -1:
|
||||||
eerror ("forkpty: %s", strerror (errno));
|
eerror("fork: %s", strerror(errno));
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
rc_in_logger = true;
|
rc_in_logger = true;
|
||||||
close (signal_pipe[1]);
|
close(signal_pipe[1]);
|
||||||
signal_pipe[1] = -1;
|
signal_pipe[1] = -1;
|
||||||
|
|
||||||
runlevel = level;
|
runlevel = level;
|
||||||
if ((log = fopen (LOGFILE, "a")))
|
if ((log = fopen(LOGFILE, "a")))
|
||||||
write_time (log, "started");
|
write_time(log, "started");
|
||||||
else {
|
else {
|
||||||
free (logbuf);
|
free(logbuf);
|
||||||
logbuf_size = BUFSIZ * 10;
|
logbuf_size = BUFSIZ * 10;
|
||||||
logbuf = xmalloc (sizeof (char) * logbuf_size);
|
logbuf = xmalloc(sizeof (char) * logbuf_size);
|
||||||
logbuf_len = 0;
|
logbuf_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = xmalloc(sizeof (char) * BUFSIZ);
|
||||||
|
selfd = rc_logger_tty > signal_pipe[0] ? rc_logger_tty : signal_pipe[0];
|
||||||
|
for (;;) {
|
||||||
|
FD_ZERO(&rset);
|
||||||
|
FD_SET(rc_logger_tty, &rset);
|
||||||
|
FD_SET(signal_pipe[0], &rset);
|
||||||
|
|
||||||
|
if ((s = select(selfd + 1, &rset, NULL, NULL, NULL)) == -1) {
|
||||||
|
eerror("select: %s", strerror(errno));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = xmalloc (sizeof (char) * BUFSIZ);
|
if (s > 0) {
|
||||||
selfd = rc_logger_tty > signal_pipe[0] ? rc_logger_tty : signal_pipe[0];
|
if (FD_ISSET(rc_logger_tty, &rset)) {
|
||||||
for (;;) {
|
memset(buffer, 0, BUFSIZ);
|
||||||
FD_ZERO (&rset);
|
bytes = read(rc_logger_tty, buffer, BUFSIZ);
|
||||||
FD_SET (rc_logger_tty, &rset);
|
write(STDOUT_FILENO, buffer, bytes);
|
||||||
FD_SET (signal_pipe[0], &rset);
|
|
||||||
|
|
||||||
if ((s = select (selfd + 1, &rset, NULL, NULL, NULL)) == -1) {
|
if (log)
|
||||||
eerror ("select: %s", strerror (errno));
|
write_log(fileno (log), buffer, bytes);
|
||||||
break;
|
else {
|
||||||
}
|
if (logbuf_size - logbuf_len < bytes) {
|
||||||
|
logbuf_size += BUFSIZ * 10;
|
||||||
if (s > 0) {
|
logbuf = xrealloc(logbuf,
|
||||||
if (FD_ISSET (rc_logger_tty, &rset)) {
|
sizeof(char ) *
|
||||||
memset (buffer, 0, BUFSIZ);
|
logbuf_size);
|
||||||
bytes = read (rc_logger_tty, buffer, BUFSIZ);
|
|
||||||
write (STDOUT_FILENO, buffer, bytes);
|
|
||||||
|
|
||||||
if (log)
|
|
||||||
write_log (fileno (log), buffer, bytes);
|
|
||||||
else {
|
|
||||||
if (logbuf_size - logbuf_len < bytes) {
|
|
||||||
logbuf_size += BUFSIZ * 10;
|
|
||||||
logbuf = xrealloc (logbuf, sizeof (char ) *
|
|
||||||
logbuf_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy (logbuf + logbuf_len, buffer, bytes);
|
|
||||||
logbuf_len += bytes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(logbuf + logbuf_len, buffer, bytes);
|
||||||
|
logbuf_len += bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only SIGTERMS signals come down this pipe */
|
|
||||||
if (FD_ISSET (signal_pipe[0], &rset))
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
free (buffer);
|
|
||||||
if (logbuf) {
|
|
||||||
if ((log = fopen (LOGFILE, "a"))) {
|
|
||||||
write_time (log, "started");
|
|
||||||
write_log (fileno (log), logbuf, logbuf_len);
|
|
||||||
}
|
|
||||||
free (logbuf);
|
|
||||||
}
|
|
||||||
if (log) {
|
|
||||||
write_time (log, "stopped");
|
|
||||||
fclose (log);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try and cat our new logfile to a more permament location and then
|
/* Only SIGTERMS signals come down this pipe */
|
||||||
* punt it */
|
if (FD_ISSET(signal_pipe[0], &rset))
|
||||||
system (MOVELOG);
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(buffer);
|
||||||
|
if (logbuf) {
|
||||||
|
if ((log = fopen(LOGFILE, "a"))) {
|
||||||
|
write_time(log, "started");
|
||||||
|
write_log(fileno(log), logbuf, logbuf_len);
|
||||||
|
}
|
||||||
|
free(logbuf);
|
||||||
|
}
|
||||||
|
if (log) {
|
||||||
|
write_time(log, "stopped");
|
||||||
|
fclose(log);
|
||||||
|
}
|
||||||
|
|
||||||
exit (0);
|
/* Try and cat our new logfile to a more permament location and then
|
||||||
/* NOTREACHED */
|
* punt it */
|
||||||
default:
|
system(MOVELOG);
|
||||||
setpgid (rc_logger_pid, 0);
|
|
||||||
fd_stdout = dup (STDOUT_FILENO);
|
|
||||||
fd_stderr = dup (STDERR_FILENO);
|
|
||||||
if ((s = fcntl (fd_stdout, F_GETFD, 0)) == 0)
|
|
||||||
fcntl (fd_stdout, F_SETFD, s | FD_CLOEXEC);
|
|
||||||
|
|
||||||
if ((s = fcntl (fd_stderr, F_GETFD, 0)) == 0)
|
exit(0);
|
||||||
fcntl (fd_stderr, F_SETFD, s | FD_CLOEXEC);
|
/* NOTREACHED */
|
||||||
dup2 (slave_tty, STDOUT_FILENO);
|
|
||||||
dup2 (slave_tty, STDERR_FILENO);
|
default:
|
||||||
if (slave_tty != STDIN_FILENO &&
|
setpgid(rc_logger_pid, 0);
|
||||||
slave_tty != STDOUT_FILENO &&
|
fd_stdout = dup(STDOUT_FILENO);
|
||||||
slave_tty != STDERR_FILENO)
|
fd_stderr = dup(STDERR_FILENO);
|
||||||
close (slave_tty);
|
if ((s = fcntl(fd_stdout, F_GETFD, 0)) == 0)
|
||||||
close (signal_pipe[0]);
|
fcntl(fd_stdout, F_SETFD, s | FD_CLOEXEC);
|
||||||
signal_pipe[0] = -1;
|
|
||||||
break;
|
if ((s = fcntl(fd_stderr, F_GETFD, 0)) == 0)
|
||||||
|
fcntl(fd_stderr, F_SETFD, s | FD_CLOEXEC);
|
||||||
|
dup2(slave_tty, STDOUT_FILENO);
|
||||||
|
dup2(slave_tty, STDERR_FILENO);
|
||||||
|
if (slave_tty != STDIN_FILENO &&
|
||||||
|
slave_tty != STDOUT_FILENO &&
|
||||||
|
slave_tty != STDERR_FILENO)
|
||||||
|
close(slave_tty);
|
||||||
|
close(signal_pipe[0]);
|
||||||
|
signal_pipe[0] = -1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
370
src/rc/rc-misc.c
370
src/rc/rc-misc.c
@ -30,13 +30,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include <sys/sysinfo.h>
|
#include <sys/sysinfo.h>
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@ -47,7 +47,6 @@
|
|||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "rc-misc.h"
|
#include "rc-misc.h"
|
||||||
#include "strlist.h"
|
|
||||||
|
|
||||||
#define PROFILE_ENV SYSCONFDIR "/profile.env"
|
#define PROFILE_ENV SYSCONFDIR "/profile.env"
|
||||||
#define SYS_WHITELIST RC_LIBDIR "/conf.d/env_whitelist"
|
#define SYS_WHITELIST RC_LIBDIR "/conf.d/env_whitelist"
|
||||||
@ -57,314 +56,253 @@
|
|||||||
|
|
||||||
#define PATH_PREFIX RC_LIBDIR "/bin:/bin:/sbin:/usr/bin:/usr/sbin"
|
#define PATH_PREFIX RC_LIBDIR "/bin:/bin:/sbin:/usr/bin:/usr/sbin"
|
||||||
|
|
||||||
static char **rc_conf = NULL;
|
static RC_STRINGLIST *rc_conf = NULL;
|
||||||
|
|
||||||
static void _free_rc_conf (void)
|
extern char** environ;
|
||||||
|
|
||||||
|
static void _free_rc_conf(void)
|
||||||
{
|
{
|
||||||
rc_strlist_free (rc_conf);
|
rc_stringlist_free(rc_conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *rc_conf_value (const char *setting)
|
char *rc_conf_value(const char *setting)
|
||||||
{
|
{
|
||||||
if (! rc_conf) {
|
RC_STRINGLIST *old;
|
||||||
char *line;
|
RC_STRING *s;
|
||||||
int i;
|
char *p;
|
||||||
|
|
||||||
rc_conf = rc_config_load (RC_CONF);
|
if (! rc_conf) {
|
||||||
atexit (_free_rc_conf);
|
rc_conf = rc_config_load(RC_CONF);
|
||||||
|
atexit(_free_rc_conf);
|
||||||
|
|
||||||
/* Support old configs */
|
/* Support old configs */
|
||||||
if (exists (RC_CONF_OLD)) {
|
if (exists(RC_CONF_OLD)) {
|
||||||
char **old = rc_config_load (RC_CONF_OLD);
|
old = rc_config_load(RC_CONF_OLD);
|
||||||
rc_strlist_join (&rc_conf, old);
|
if (old) {
|
||||||
rc_strlist_free (old);
|
TAILQ_CONCAT(rc_conf, old);
|
||||||
|
free(old);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert old uppercase to lowercase */
|
/* Convert old uppercase to lowercase */
|
||||||
STRLIST_FOREACH (rc_conf, line, i) {
|
TAILQ_FOREACH(s, rc_conf, entries) {
|
||||||
char *p = line;
|
p = s->value;
|
||||||
while (p && *p && *p != '=') {
|
while (p && *p && *p != '=') {
|
||||||
if (isupper ((int) *p))
|
if (isupper((int) *p))
|
||||||
*p = tolower ((int) *p);
|
*p = tolower((int) *p);
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (rc_config_value ((const char *const *)rc_conf, setting));
|
return rc_config_value(rc_conf, setting);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rc_conf_yesno (const char *setting)
|
bool rc_conf_yesno(const char *setting)
|
||||||
{
|
{
|
||||||
return (rc_yesno (rc_conf_value (setting)));
|
return rc_yesno(rc_conf_value (setting));
|
||||||
}
|
}
|
||||||
|
|
||||||
char **env_filter (void)
|
static const char *const env_whitelist[] = {
|
||||||
|
"PATH", "SHELL", "USER", "HOME", "TERM",
|
||||||
|
"LANG", "LC_CTYPE", "LC_NUMERIC", "LC_TIME", "LC_COLLATE",
|
||||||
|
"LC_MONETARY", "LC_MESSAGES", "LC_PAPER", "LC_NAME", "LC_ADDRESS",
|
||||||
|
"LC_TELEPHONE", "LC_MEASUREMENT", "LC_IDENTIFICATION", "LC_ALL",
|
||||||
|
"INIT_HALT", "INIT_VERSION", "RUNLEVEL", "PREVLEVEL", "CONSOLE",
|
||||||
|
"IN_HOTPLUG", "IN_BACKGROUND", "RC_INTERFACE_KEEP_CONFIG",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
void env_filter(void)
|
||||||
{
|
{
|
||||||
char **env = NULL;
|
RC_STRINGLIST *env_allow;
|
||||||
char **whitelist = NULL;
|
RC_STRINGLIST *profile = NULL;
|
||||||
char *env_name = NULL;
|
RC_STRINGLIST *env_list;
|
||||||
char **profile = NULL;
|
RC_STRING *env;
|
||||||
int count = 0;
|
RC_STRING *s;
|
||||||
bool got_path = false;
|
char *env_name;
|
||||||
char *env_var;
|
|
||||||
size_t env_len;
|
|
||||||
char *token;
|
|
||||||
char *sep;
|
|
||||||
char *e;
|
char *e;
|
||||||
char *p;
|
char *token;
|
||||||
size_t pplen = strlen (PATH_PREFIX);
|
size_t i = 0;
|
||||||
|
|
||||||
/* Init a system whitelist, start with shell vars we need */
|
|
||||||
rc_strlist_add (&whitelist, "PATH");
|
|
||||||
rc_strlist_add (&whitelist, "SHELL");
|
|
||||||
rc_strlist_add (&whitelist, "USER");
|
|
||||||
rc_strlist_add (&whitelist, "HOME");
|
|
||||||
rc_strlist_add (&whitelist, "TERM");
|
|
||||||
|
|
||||||
/* Add Language vars */
|
|
||||||
rc_strlist_add (&whitelist, "LANG");
|
|
||||||
rc_strlist_add (&whitelist, "LC_CTYPE");
|
|
||||||
rc_strlist_add (&whitelist, "LC_NUMERIC");
|
|
||||||
rc_strlist_add (&whitelist, "LC_TIME");
|
|
||||||
rc_strlist_add (&whitelist, "LC_COLLATE");
|
|
||||||
rc_strlist_add (&whitelist, "LC_MONETARY");
|
|
||||||
rc_strlist_add (&whitelist, "LC_MESSAGES");
|
|
||||||
rc_strlist_add (&whitelist, "LC_PAPER");
|
|
||||||
rc_strlist_add (&whitelist, "LC_NAME");
|
|
||||||
rc_strlist_add (&whitelist, "LC_ADDRESS");
|
|
||||||
rc_strlist_add (&whitelist, "LC_TELEPHONE");
|
|
||||||
rc_strlist_add (&whitelist, "LC_MEASUREMENT");
|
|
||||||
rc_strlist_add (&whitelist, "LC_IDENTIFICATION");
|
|
||||||
rc_strlist_add (&whitelist, "LC_ALL");
|
|
||||||
|
|
||||||
/* Allow rc to override library path */
|
|
||||||
rc_strlist_add (&whitelist, "LD_LIBRARY_PATH");
|
|
||||||
|
|
||||||
/* We need to know sysvinit stuff - we emulate this for BSD too */
|
|
||||||
rc_strlist_add (&whitelist, "INIT_HALT");
|
|
||||||
rc_strlist_add (&whitelist, "INIT_VERSION");
|
|
||||||
rc_strlist_add (&whitelist, "RUNLEVEL");
|
|
||||||
rc_strlist_add (&whitelist, "PREVLEVEL");
|
|
||||||
rc_strlist_add (&whitelist, "CONSOLE");
|
|
||||||
|
|
||||||
/* Hotplug and daemon vars */
|
|
||||||
rc_strlist_add (&whitelist, "IN_HOTPLUG");
|
|
||||||
rc_strlist_add (&whitelist, "IN_BACKGROUND");
|
|
||||||
rc_strlist_add (&whitelist, "RC_INTERFACE_KEEP_CONFIG");
|
|
||||||
|
|
||||||
/* Add the user defined list of vars */
|
/* Add the user defined list of vars */
|
||||||
e = env_name = xstrdup (rc_conf_value ("rc_env_allow"));
|
env_allow = rc_stringlist_new();
|
||||||
while ((token = strsep (&e, " "))) {
|
e = env_name = xstrdup(rc_conf_value ("rc_env_allow"));
|
||||||
|
while ((token = strsep(&e, " "))) {
|
||||||
if (token[0] == '*') {
|
if (token[0] == '*') {
|
||||||
free (env_name);
|
free(env_name);
|
||||||
return (NULL);
|
rc_stringlist_free(env_allow);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
rc_strlist_add (&whitelist, token);
|
rc_stringlist_add(env_allow, token);
|
||||||
}
|
}
|
||||||
free (env_name);
|
free(env_name);
|
||||||
|
|
||||||
if (exists (PROFILE_ENV))
|
if (exists(PROFILE_ENV))
|
||||||
profile = rc_config_load (PROFILE_ENV);
|
profile = rc_config_load(PROFILE_ENV);
|
||||||
|
|
||||||
STRLIST_FOREACH (whitelist, env_name, count) {
|
/* Copy the env and work from this so we can remove safely */
|
||||||
char *space = strchr (env_name, ' ');
|
env_list = rc_stringlist_new();
|
||||||
if (space)
|
while (environ[i])
|
||||||
*space = 0;
|
rc_stringlist_add(env_list, environ[i++]);
|
||||||
|
|
||||||
env_var = getenv (env_name);
|
TAILQ_FOREACH(env, env_list, entries) {
|
||||||
|
/* Check the whitelist */
|
||||||
if (! env_var && profile) {
|
i = 0;
|
||||||
env_len = strlen (env_name) + strlen ("export ") + 1;
|
while (env_whitelist[i]) {
|
||||||
p = xmalloc (sizeof (char) * env_len);
|
if (strcmp(env_whitelist[i++], env->value))
|
||||||
snprintf (p, env_len, "export %s", env_name);
|
break;
|
||||||
env_var = rc_config_value ((const char *const *) profile, p);
|
|
||||||
free (p);
|
|
||||||
}
|
}
|
||||||
|
if (env_whitelist[i])
|
||||||
if (! env_var)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Ensure our PATH is prefixed with the system locations first
|
/* Check our user defined list */
|
||||||
for a little extra security */
|
TAILQ_FOREACH(s, env_allow, entries)
|
||||||
if (strcmp (env_name, "PATH") == 0 &&
|
if (strcmp(s->value, env->value) == 0)
|
||||||
strncmp (PATH_PREFIX, env_var, pplen) != 0)
|
break;
|
||||||
{
|
if (s)
|
||||||
got_path = true;
|
continue;
|
||||||
env_len = strlen (env_name) + strlen (env_var) + pplen + 3;
|
|
||||||
e = p = xmalloc (sizeof (char) * env_len);
|
|
||||||
p += snprintf (e, env_len, "%s=%s", env_name, PATH_PREFIX);
|
|
||||||
|
|
||||||
/* Now go through the env var and only add bits not in our PREFIX */
|
/* Now check our profile */
|
||||||
sep = env_var;
|
|
||||||
while ((token = strsep (&sep, ":"))) {
|
|
||||||
char *np = xstrdup (PATH_PREFIX);
|
|
||||||
char *npp = np;
|
|
||||||
char *tok = NULL;
|
|
||||||
while ((tok = strsep (&npp, ":")))
|
|
||||||
if (strcmp (tok, token) == 0)
|
|
||||||
break;
|
|
||||||
if (! tok)
|
|
||||||
p += snprintf (p, env_len - (p - e), ":%s", token);
|
|
||||||
free (np);
|
|
||||||
}
|
|
||||||
*p++ = 0;
|
|
||||||
} else {
|
|
||||||
env_len = strlen (env_name) + strlen (env_var) + 2;
|
|
||||||
e = xmalloc (sizeof (char) * env_len);
|
|
||||||
snprintf (e, env_len, "%s=%s", env_name, env_var);
|
|
||||||
}
|
|
||||||
|
|
||||||
rc_strlist_add (&env, e);
|
/* OK, not allowed! */
|
||||||
free (e);
|
e = strchr(env->value, '=');
|
||||||
|
*e = '\0';
|
||||||
|
unsetenv(env->value);
|
||||||
}
|
}
|
||||||
|
rc_stringlist_free(env_list);
|
||||||
/* We filtered the env but didn't get a PATH? Very odd.
|
rc_stringlist_free(env_allow);
|
||||||
However, we do need a path, so use a default. */
|
rc_stringlist_free(profile);
|
||||||
if (! got_path) {
|
|
||||||
env_len = strlen ("PATH=") + strlen (PATH_PREFIX) + 1;
|
|
||||||
e = xmalloc (sizeof (char) * env_len);
|
|
||||||
snprintf (e, env_len, "PATH=%s", PATH_PREFIX);
|
|
||||||
rc_strlist_add (&env, e);
|
|
||||||
free (e);
|
|
||||||
}
|
|
||||||
|
|
||||||
rc_strlist_free (whitelist);
|
|
||||||
rc_strlist_free (profile);
|
|
||||||
|
|
||||||
return (env);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char **env_config (void)
|
void env_config(void)
|
||||||
{
|
{
|
||||||
char **env = NULL;
|
size_t pplen = strlen(PATH_PREFIX);
|
||||||
char *line;
|
char *path;
|
||||||
|
char *p;
|
||||||
|
char *e;
|
||||||
size_t l;
|
size_t l;
|
||||||
const char *sys = rc_sys ();
|
|
||||||
struct utsname uts;
|
struct utsname uts;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
char *token;
|
||||||
|
char *np;
|
||||||
|
char *npp;
|
||||||
|
char *tok;
|
||||||
|
const char *sys = rc_sys();
|
||||||
char buffer[PATH_MAX];
|
char buffer[PATH_MAX];
|
||||||
char *runlevel = rc_runlevel_get ();
|
|
||||||
|
|
||||||
/* One char less to drop the trailing / */
|
/* Ensure our PATH is prefixed with the system locations first
|
||||||
l = strlen ("RC_LIBDIR=") + strlen (RC_LIBDIR) + 1;
|
for a little extra security */
|
||||||
line = xmalloc (sizeof (char) * l);
|
path = getenv("PATH");
|
||||||
snprintf (line, l, "RC_LIBDIR=" RC_LIBDIR);
|
if (! path)
|
||||||
rc_strlist_add (&env, line);
|
setenv("PATH", PATH_PREFIX, 1);
|
||||||
free (line);
|
else if (strncmp (PATH_PREFIX, path, pplen) != 0) {
|
||||||
|
l = strlen(path) + pplen + 3;
|
||||||
|
e = p = xmalloc(sizeof(char) * l);
|
||||||
|
p += snprintf(p, l, "%s", PATH_PREFIX);
|
||||||
|
|
||||||
/* One char less to drop the trailing / */
|
/* Now go through the env var and only add bits not in our PREFIX */
|
||||||
l = strlen ("RC_SVCDIR=") + strlen (RC_SVCDIR) + 1;
|
while ((token = strsep(&path, ":"))) {
|
||||||
line = xmalloc (sizeof (char) * l);
|
np = npp = xstrdup(PATH_PREFIX);
|
||||||
snprintf (line, l, "RC_SVCDIR=" RC_SVCDIR);
|
while ((tok = strsep(&npp, ":")))
|
||||||
rc_strlist_add (&env, line);
|
if (strcmp(tok, token) == 0)
|
||||||
free (line);
|
break;
|
||||||
|
if (! tok)
|
||||||
|
p += snprintf(p, l - (p - e), ":%s", token);
|
||||||
|
free (np);
|
||||||
|
}
|
||||||
|
*p++ = '\0';
|
||||||
|
unsetenv("PATH");
|
||||||
|
setenv("PATH", e, 1);
|
||||||
|
free(e);
|
||||||
|
}
|
||||||
|
|
||||||
rc_strlist_add (&env, "RC_BOOTLEVEL=" RC_LEVEL_BOOT);
|
setenv("RC_LIBDIR", RC_LIBDIR, 1);
|
||||||
|
setenv("RC_SVCDIR", RC_SVCDIR, 1);
|
||||||
|
setenv("RC_BOOTLEVEL", RC_LEVEL_BOOT, 1);
|
||||||
|
e = rc_runlevel_get();
|
||||||
|
setenv("RC_RUNLEVEL", e, 1);
|
||||||
|
free(e);
|
||||||
|
|
||||||
l = strlen ("RC_SOFTLEVEL=") + strlen (runlevel) + 1;
|
if ((fp = fopen(RC_KSOFTLEVEL, "r"))) {
|
||||||
line = xmalloc (sizeof (char) * l);
|
memset(buffer, 0, sizeof (buffer));
|
||||||
snprintf (line, l, "RC_SOFTLEVEL=%s", runlevel);
|
if (fgets(buffer, sizeof (buffer), fp)) {
|
||||||
rc_strlist_add (&env, line);
|
|
||||||
free (line);
|
|
||||||
|
|
||||||
if ((fp = fopen (RC_KSOFTLEVEL, "r"))) {
|
|
||||||
memset (buffer, 0, sizeof (buffer));
|
|
||||||
if (fgets (buffer, sizeof (buffer), fp)) {
|
|
||||||
l = strlen (buffer) - 1;
|
l = strlen (buffer) - 1;
|
||||||
if (buffer[l] == '\n')
|
if (buffer[l] == '\n')
|
||||||
buffer[l] = 0;
|
buffer[l] = 0;
|
||||||
l += strlen ("RC_DEFAULTLEVEL=") + 2;
|
setenv("RC_DEFAULTLEVEL", buffer, 1);
|
||||||
line = xmalloc (sizeof (char) * l);
|
|
||||||
snprintf (line, l, "RC_DEFAULTLEVEL=%s", buffer);
|
|
||||||
rc_strlist_add (&env, line);
|
|
||||||
free (line);
|
|
||||||
}
|
}
|
||||||
fclose (fp);
|
fclose(fp);
|
||||||
} else
|
} else
|
||||||
rc_strlist_add (&env, "RC_DEFAULTLEVEL=" RC_LEVEL_DEFAULT);
|
setenv("RC_DEFAULTLEVEL", RC_LEVEL_DEFAULT, 1);
|
||||||
|
|
||||||
if (sys) {
|
if (sys)
|
||||||
l = strlen ("RC_SYS=") + strlen (sys) + 2;
|
setenv("RC_SYS", sys, 1);
|
||||||
line = xmalloc (sizeof (char) * l);
|
|
||||||
snprintf (line, l, "RC_SYS=%s", sys);
|
|
||||||
rc_strlist_add (&env, line);
|
|
||||||
free (line);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Some scripts may need to take a different code path if Linux/FreeBSD, etc
|
/* Some scripts may need to take a different code path if Linux/FreeBSD, etc
|
||||||
To save on calling uname, we store it in an environment variable */
|
To save on calling uname, we store it in an environment variable */
|
||||||
if (uname (&uts) == 0) {
|
if (uname(&uts) == 0)
|
||||||
l = strlen ("RC_UNAME=") + strlen (uts.sysname) + 2;
|
setenv("RC_UNAME", uts.sysname, 1);
|
||||||
line = xmalloc (sizeof (char) * l);
|
|
||||||
snprintf (line, l, "RC_UNAME=%s", uts.sysname);
|
|
||||||
rc_strlist_add (&env, line);
|
|
||||||
free (line);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Be quiet or verbose as necessary */
|
/* Be quiet or verbose as necessary */
|
||||||
if (rc_conf_yesno ("rc_quiet"))
|
if (rc_conf_yesno("rc_quiet"))
|
||||||
rc_strlist_add (&env, "EINFO_QUIET=YES");
|
setenv("EINFO_QUIET", "YES", 1);
|
||||||
if (rc_conf_yesno ("rc_verbose"))
|
if (rc_conf_yesno("rc_verbose"))
|
||||||
rc_strlist_add (&env, "EINFO_VERBOSE=YES");
|
setenv("EINFO_VERBOSE", "YES", 1);
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if ((! rc_conf_yesno ("rc_color") && errno == 0) ||
|
if ((! rc_conf_yesno("rc_color") && errno == 0) ||
|
||||||
rc_conf_yesno ("rc_nocolor"))
|
rc_conf_yesno("rc_nocolor"))
|
||||||
rc_strlist_add (&env, "EINFO_COLOR=NO");
|
setenv("EINFO_COLOR", "NO", 1);
|
||||||
|
|
||||||
free (runlevel);
|
|
||||||
return (env);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool service_plugable (const char *service)
|
bool service_plugable(const char *service)
|
||||||
{
|
{
|
||||||
char *list;
|
char *list;
|
||||||
char *p;
|
char *p;
|
||||||
char *star;
|
char *star;
|
||||||
char *token;
|
char *token;
|
||||||
bool allow = true;
|
bool allow = true;
|
||||||
char *match = rc_conf_value ("rc_plug_services");
|
char *match = rc_conf_value("rc_plug_services");
|
||||||
|
bool truefalse;
|
||||||
|
|
||||||
if (! match)
|
if (! match)
|
||||||
return (true);
|
return true;
|
||||||
|
|
||||||
list = xstrdup (match);
|
list = xstrdup(match);
|
||||||
p = list;
|
p = list;
|
||||||
while ((token = strsep (&p, " "))) {
|
while ((token = strsep(&p, " "))) {
|
||||||
bool truefalse = true;
|
|
||||||
|
|
||||||
if (token[0] == '!') {
|
if (token[0] == '!') {
|
||||||
truefalse = false;
|
truefalse = false;
|
||||||
token++;
|
token++;
|
||||||
}
|
} else
|
||||||
|
truefalse = true;
|
||||||
|
|
||||||
star = strchr (token, '*');
|
star = strchr(token, '*');
|
||||||
if (star) {
|
if (star) {
|
||||||
if (strncmp (service, token, (size_t) (star - token))
|
if (strncmp(service, token, (size_t)(star - token)) == 0)
|
||||||
== 0)
|
|
||||||
{
|
{
|
||||||
allow = truefalse;
|
allow = truefalse;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (strcmp (service, token) == 0) {
|
if (strcmp(service, token) == 0) {
|
||||||
allow = truefalse;
|
allow = truefalse;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free (list);
|
free(list);
|
||||||
return (allow);
|
return allow;
|
||||||
}
|
}
|
||||||
|
|
||||||
int signal_setup (int sig, void (*handler)(int))
|
int signal_setup(int sig, void (*handler)(int))
|
||||||
{
|
{
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
|
||||||
memset (&sa, 0, sizeof (sa));
|
memset(&sa, 0, sizeof (sa));
|
||||||
sigemptyset (&sa.sa_mask);
|
sigemptyset(&sa.sa_mask);
|
||||||
sa.sa_handler = handler;
|
sa.sa_handler = handler;
|
||||||
return (sigaction (sig, &sa, NULL));
|
return sigaction(sig, &sa, NULL);
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -46,7 +47,6 @@
|
|||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "rc-misc.h"
|
#include "rc-misc.h"
|
||||||
#include "rc-plugin.h"
|
#include "rc-plugin.h"
|
||||||
#include "strlist.h"
|
|
||||||
|
|
||||||
#define RC_PLUGIN_HOOK "rc_plugin_hook"
|
#define RC_PLUGIN_HOOK "rc_plugin_hook"
|
||||||
|
|
||||||
@ -56,129 +56,117 @@ typedef struct plugin
|
|||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
void *handle;
|
void *handle;
|
||||||
int (*hook) (rc_hook_t, const char *);
|
int (*hook)(RC_HOOK, const char *);
|
||||||
struct plugin *next;
|
STAILQ_ENTRY(plugin) entries;
|
||||||
} plugin_t;
|
} PLUGIN;
|
||||||
|
STAILQ_HEAD(, plugin) plugins;
|
||||||
static plugin_t *plugins = NULL;
|
|
||||||
|
|
||||||
#ifndef __FreeBSD__
|
#ifndef __FreeBSD__
|
||||||
dlfunc_t dlfunc (void * __restrict handle, const char * __restrict symbol)
|
dlfunc_t dlfunc(void * __restrict handle, const char * __restrict symbol)
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
void *d;
|
void *d;
|
||||||
dlfunc_t f;
|
dlfunc_t f;
|
||||||
} rv;
|
} rv;
|
||||||
|
|
||||||
rv.d = dlsym (handle, symbol);
|
rv.d = dlsym(handle, symbol);
|
||||||
return (rv.f);
|
return rv.f;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void rc_plugin_load (void)
|
void rc_plugin_load(void)
|
||||||
{
|
{
|
||||||
DIR *dp;
|
DIR *dp;
|
||||||
struct dirent *d;
|
struct dirent *d;
|
||||||
plugin_t *plugin = plugins;
|
PLUGIN *plugin;
|
||||||
char *p;
|
char *p;
|
||||||
void *h;
|
void *h;
|
||||||
int (*fptr) (rc_hook_t, const char *);
|
int (*fptr)(RC_HOOK, const char *);
|
||||||
|
|
||||||
/* Don't load plugins if we're in one */
|
/* Don't load plugins if we're in one */
|
||||||
if (rc_in_plugin)
|
if (rc_in_plugin)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Ensure some sanity here */
|
STAILQ_INIT(&plugins);
|
||||||
rc_plugin_unload ();
|
|
||||||
|
|
||||||
if (! (dp = opendir (RC_PLUGINDIR)))
|
if (! (dp = opendir(RC_PLUGINDIR)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while ((d = readdir (dp))) {
|
while ((d = readdir(dp))) {
|
||||||
if (d->d_name[0] == '.')
|
if (d->d_name[0] == '.')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
p = rc_strcatpaths (RC_PLUGINDIR, d->d_name, NULL);
|
p = rc_strcatpaths(RC_PLUGINDIR, d->d_name, NULL);
|
||||||
h = dlopen (p, RTLD_LAZY);
|
h = dlopen(p, RTLD_LAZY);
|
||||||
free (p);
|
free(p);
|
||||||
if (! h) {
|
if (! h) {
|
||||||
eerror ("dlopen: %s", dlerror ());
|
eerror("dlopen: %s", dlerror());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
fptr = (int (*)(rc_hook_t, const char*)) dlfunc (h, RC_PLUGIN_HOOK);
|
fptr = (int (*)(RC_HOOK, const char*))dlfunc(h, RC_PLUGIN_HOOK);
|
||||||
if (! fptr) {
|
if (! fptr) {
|
||||||
eerror ("%s: cannot find symbol `%s'", d->d_name, RC_PLUGIN_HOOK);
|
eerror("%s: cannot find symbol `%s'", d->d_name, RC_PLUGIN_HOOK);
|
||||||
dlclose (h);
|
dlclose(h);
|
||||||
} else {
|
} else {
|
||||||
if (plugin) {
|
plugin = xmalloc(sizeof(*plugin));
|
||||||
plugin->next = xmalloc (sizeof (*plugin->next));
|
plugin->name = xstrdup(d->d_name);
|
||||||
plugin = plugin->next;
|
|
||||||
} else
|
|
||||||
plugin = plugins = xmalloc (sizeof (*plugin));
|
|
||||||
|
|
||||||
plugin->name = xstrdup (d->d_name);
|
|
||||||
plugin->handle = h;
|
plugin->handle = h;
|
||||||
plugin->hook = fptr;
|
plugin->hook = fptr;
|
||||||
plugin->next = NULL;
|
STAILQ_INSERT_TAIL(&plugins, plugin, entries);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closedir (dp);
|
closedir(dp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc_waitpid (pid_t pid)
|
int rc_waitpid(pid_t pid)
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0;
|
||||||
pid_t savedpid = pid;
|
pid_t savedpid = pid;
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
while ((pid = waitpid (savedpid, &status, 0)) > 0) {
|
while ((pid = waitpid(savedpid, &status, 0)) > 0) {
|
||||||
if (pid == savedpid)
|
if (pid == savedpid)
|
||||||
retval = WIFEXITED (status) ? WEXITSTATUS (status) : EXIT_FAILURE;
|
retval = WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (retval);
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rc_plugin_run (rc_hook_t hook, const char *value)
|
void rc_plugin_run(RC_HOOK hook, const char *value)
|
||||||
{
|
{
|
||||||
plugin_t *plugin = plugins;
|
PLUGIN *plugin;
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
sigset_t empty;
|
sigset_t empty;
|
||||||
sigset_t full;
|
sigset_t full;
|
||||||
sigset_t old;
|
sigset_t old;
|
||||||
|
int i;
|
||||||
|
int flags;
|
||||||
|
int pfd[2];
|
||||||
|
pid_t pid;
|
||||||
|
char *buffer;
|
||||||
|
char *token;
|
||||||
|
char *p;
|
||||||
|
ssize_t nr;
|
||||||
|
int retval;
|
||||||
|
|
||||||
/* Don't run plugins if we're in one */
|
/* Don't run plugins if we're in one */
|
||||||
if (rc_in_plugin)
|
if (rc_in_plugin)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* We need to block signals until we have forked */
|
/* We need to block signals until we have forked */
|
||||||
memset (&sa, 0, sizeof (sa));
|
memset(&sa, 0, sizeof(sa));
|
||||||
sa.sa_handler = SIG_DFL;
|
sa.sa_handler = SIG_DFL;
|
||||||
sigemptyset (&sa.sa_mask);
|
sigemptyset(&sa.sa_mask);
|
||||||
sigemptyset (&empty);
|
sigemptyset(&empty);
|
||||||
sigfillset (&full);
|
sigfillset(&full);
|
||||||
|
|
||||||
while (plugin) {
|
|
||||||
int i;
|
|
||||||
int flags;
|
|
||||||
int pfd[2];
|
|
||||||
pid_t pid;
|
|
||||||
char *buffer;
|
|
||||||
char *token;
|
|
||||||
char *p;
|
|
||||||
ssize_t nr;
|
|
||||||
|
|
||||||
if (! plugin->hook) {
|
|
||||||
plugin = plugin->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
STAILQ_FOREACH(plugin, &plugins, entries) {
|
||||||
/* We create a pipe so that plugins can affect our environment
|
/* We create a pipe so that plugins can affect our environment
|
||||||
* vars, which in turn influence our scripts. */
|
* vars, which in turn influence our scripts. */
|
||||||
if (pipe (pfd) == -1) {
|
if (pipe(pfd) == -1) {
|
||||||
eerror ("pipe: %s", strerror (errno));
|
eerror("pipe: %s", strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,81 +176,78 @@ void rc_plugin_run (rc_hook_t hook, const char *value)
|
|||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++)
|
||||||
if ((flags = fcntl (pfd[i], F_GETFD, 0)) < 0 ||
|
if ((flags = fcntl (pfd[i], F_GETFD, 0)) < 0 ||
|
||||||
fcntl (pfd[i], F_SETFD, flags | FD_CLOEXEC) < 0)
|
fcntl (pfd[i], F_SETFD, flags | FD_CLOEXEC) < 0)
|
||||||
eerror ("fcntl: %s", strerror (errno));
|
eerror("fcntl: %s", strerror(errno));
|
||||||
|
|
||||||
sigprocmask (SIG_SETMASK, &full, &old);
|
sigprocmask(SIG_SETMASK, &full, &old);
|
||||||
|
|
||||||
/* We run the plugin in a new process so we never crash
|
/* We run the plugin in a new process so we never crash
|
||||||
* or otherwise affected by it */
|
* or otherwise affected by it */
|
||||||
if ((pid = fork ()) == -1) {
|
if ((pid = fork()) == -1) {
|
||||||
eerror ("fork: %s", strerror (errno));
|
eerror("fork: %s", strerror(errno));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
int retval;
|
|
||||||
|
|
||||||
/* Restore default handlers */
|
/* Restore default handlers */
|
||||||
sigaction (SIGCHLD, &sa, NULL);
|
sigaction(SIGCHLD, &sa, NULL);
|
||||||
sigaction (SIGHUP, &sa, NULL);
|
sigaction(SIGHUP, &sa, NULL);
|
||||||
sigaction (SIGINT, &sa, NULL);
|
sigaction(SIGINT, &sa, NULL);
|
||||||
sigaction (SIGQUIT, &sa, NULL);
|
sigaction(SIGQUIT, &sa, NULL);
|
||||||
sigaction (SIGTERM, &sa, NULL);
|
sigaction(SIGTERM, &sa, NULL);
|
||||||
sigaction (SIGUSR1, &sa, NULL);
|
sigaction(SIGUSR1, &sa, NULL);
|
||||||
sigaction (SIGWINCH, &sa, NULL);
|
sigaction(SIGWINCH, &sa, NULL);
|
||||||
sigprocmask (SIG_SETMASK, &old, NULL);
|
sigprocmask(SIG_SETMASK, &old, NULL);
|
||||||
|
|
||||||
rc_in_plugin = true;
|
rc_in_plugin = true;
|
||||||
close (pfd[0]);
|
close(pfd[0]);
|
||||||
rc_environ_fd = fdopen (pfd[1], "w");
|
rc_environ_fd = fdopen(pfd[1], "w");
|
||||||
retval = plugin->hook (hook, value);
|
retval = plugin->hook(hook, value);
|
||||||
fclose (rc_environ_fd);
|
fclose(rc_environ_fd);
|
||||||
rc_environ_fd = NULL;
|
rc_environ_fd = NULL;
|
||||||
|
|
||||||
/* Just in case the plugin sets this to false */
|
/* Just in case the plugin sets this to false */
|
||||||
rc_in_plugin = true;
|
rc_in_plugin = true;
|
||||||
exit (retval);
|
exit(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
sigprocmask (SIG_SETMASK, &old, NULL);
|
sigprocmask(SIG_SETMASK, &old, NULL);
|
||||||
close (pfd[1]);
|
close(pfd[1]);
|
||||||
buffer = xmalloc (sizeof (char) * BUFSIZ);
|
buffer = xmalloc(sizeof(char) * BUFSIZ);
|
||||||
memset (buffer, 0, BUFSIZ);
|
memset(buffer, 0, BUFSIZ);
|
||||||
|
|
||||||
while ((nr = read (pfd[0], buffer, BUFSIZ)) > 0) {
|
while ((nr = read(pfd[0], buffer, BUFSIZ)) > 0) {
|
||||||
p = buffer;
|
p = buffer;
|
||||||
while (*p && p - buffer < nr) {
|
while (*p && p - buffer < nr) {
|
||||||
token = strsep (&p, "=");
|
token = strsep(&p, "=");
|
||||||
if (token) {
|
if (token) {
|
||||||
unsetenv (token);
|
unsetenv(token);
|
||||||
if (*p) {
|
if (*p) {
|
||||||
setenv (token, p, 1);
|
setenv(token, p, 1);
|
||||||
p += strlen (p) + 1;
|
p += strlen(p) + 1;
|
||||||
} else
|
} else
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free (buffer);
|
free(buffer);
|
||||||
close (pfd[0]);
|
close(pfd[0]);
|
||||||
|
|
||||||
rc_waitpid (pid);
|
rc_waitpid(pid);
|
||||||
plugin = plugin->next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rc_plugin_unload (void)
|
void rc_plugin_unload(void)
|
||||||
{
|
{
|
||||||
plugin_t *plugin = plugins;
|
PLUGIN *plugin = STAILQ_FIRST(&plugins);
|
||||||
plugin_t *next;
|
PLUGIN *next;
|
||||||
|
|
||||||
while (plugin) {
|
while (plugin) {
|
||||||
next = plugin->next;
|
next = STAILQ_NEXT(plugin, entries);
|
||||||
dlclose (plugin->handle);
|
dlclose(plugin->handle);
|
||||||
free (plugin->name);
|
free(plugin->name);
|
||||||
free (plugin);
|
free(plugin);
|
||||||
plugin = next;
|
plugin = next;
|
||||||
}
|
}
|
||||||
plugins = NULL;
|
STAILQ_INIT(&plugins);
|
||||||
}
|
}
|
||||||
|
@ -36,10 +36,10 @@
|
|||||||
* Mainly used in atexit code. */
|
* Mainly used in atexit code. */
|
||||||
extern bool rc_in_plugin;
|
extern bool rc_in_plugin;
|
||||||
|
|
||||||
int rc_waitpid (pid_t pid);
|
int rc_waitpid(pid_t pid);
|
||||||
void rc_plugin_load ();
|
void rc_plugin_load(void);
|
||||||
void rc_plugin_unload ();
|
void rc_plugin_unload(void);
|
||||||
void rc_plugin_run (rc_hook_t, const char *value);
|
void rc_plugin_run(RC_HOOK, const char *value);
|
||||||
|
|
||||||
/* dlfunc defines needed to avoid ISO errors. FreeBSD has this right :) */
|
/* dlfunc defines needed to avoid ISO errors. FreeBSD has this right :) */
|
||||||
#ifndef __FreeBSD__
|
#ifndef __FreeBSD__
|
||||||
@ -47,7 +47,7 @@ struct __dlfunc_arg {
|
|||||||
int __dlfunc_dummy;
|
int __dlfunc_dummy;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*dlfunc_t) (struct __dlfunc_arg);
|
typedef void (*dlfunc_t)(struct __dlfunc_arg);
|
||||||
|
|
||||||
dlfunc_t dlfunc (void * __restrict handle, const char * __restrict symbol);
|
dlfunc_t dlfunc (void * __restrict handle, const char * __restrict symbol);
|
||||||
#endif
|
#endif
|
||||||
|
@ -39,57 +39,56 @@
|
|||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "rc-misc.h"
|
#include "rc-misc.h"
|
||||||
#include "strlist.h"
|
|
||||||
|
|
||||||
extern const char *applet;
|
extern const char *applet;
|
||||||
|
|
||||||
static const char *const types_nua[] = { "ineed", "iuse", "iafter", NULL };
|
static const char *const types_nua[] = { "ineed", "iuse", "iafter", NULL };
|
||||||
|
|
||||||
static void print_level (char *level)
|
static void print_level(char *level)
|
||||||
{
|
{
|
||||||
printf ("Runlevel: ");
|
printf ("Runlevel: ");
|
||||||
if (isatty (fileno (stdout)))
|
if (isatty(fileno(stdout)))
|
||||||
printf ("%s%s%s\n",
|
printf("%s%s%s\n",
|
||||||
ecolor (ECOLOR_HILITE),
|
ecolor(ECOLOR_HILITE),
|
||||||
level,
|
level,
|
||||||
ecolor (ECOLOR_NORMAL));
|
ecolor(ECOLOR_NORMAL));
|
||||||
else
|
else
|
||||||
printf ("%s\n", level);
|
printf("%s\n", level);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_service (char *service)
|
static void print_service(char *service)
|
||||||
{
|
{
|
||||||
char status[10];
|
char status[10];
|
||||||
int cols = printf (" %s", service);
|
int cols = printf(" %s", service);
|
||||||
const char *c = ecolor (ECOLOR_GOOD);
|
const char *c = ecolor(ECOLOR_GOOD);
|
||||||
rc_service_state_t state = rc_service_state (service);
|
RC_SERVICE state = rc_service_state(service);
|
||||||
einfo_color_t color = ECOLOR_BAD;
|
ECOLOR color = ECOLOR_BAD;
|
||||||
|
|
||||||
if (state & RC_SERVICE_STOPPING)
|
if (state & RC_SERVICE_STOPPING)
|
||||||
snprintf (status, sizeof (status), "stopping ");
|
snprintf(status, sizeof(status), "stopping ");
|
||||||
else if (state & RC_SERVICE_STARTING) {
|
else if (state & RC_SERVICE_STARTING) {
|
||||||
snprintf (status, sizeof (status), "starting ");
|
snprintf(status, sizeof(status), "starting ");
|
||||||
color = ECOLOR_WARN;
|
color = ECOLOR_WARN;
|
||||||
} else if (state & RC_SERVICE_INACTIVE) {
|
} else if (state & RC_SERVICE_INACTIVE) {
|
||||||
snprintf (status, sizeof (status), "inactive ");
|
snprintf(status, sizeof(status), "inactive ");
|
||||||
color = ECOLOR_WARN;
|
color = ECOLOR_WARN;
|
||||||
} else if (state & RC_SERVICE_STARTED) {
|
} else if (state & RC_SERVICE_STARTED) {
|
||||||
if (geteuid () == 0 && rc_service_daemons_crashed (service))
|
if (rc_service_daemons_crashed(service))
|
||||||
snprintf (status, sizeof (status), " crashed ");
|
snprintf(status, sizeof(status), " crashed ");
|
||||||
else {
|
else {
|
||||||
snprintf (status, sizeof (status), " started ");
|
snprintf(status, sizeof(status), " started ");
|
||||||
color = ECOLOR_GOOD;
|
color = ECOLOR_GOOD;
|
||||||
}
|
}
|
||||||
} else if (state & RC_SERVICE_SCHEDULED) {
|
} else if (state & RC_SERVICE_SCHEDULED) {
|
||||||
snprintf (status, sizeof (status), "scheduled");
|
snprintf(status, sizeof(status), "scheduled");
|
||||||
color = ECOLOR_WARN;
|
color = ECOLOR_WARN;
|
||||||
} else
|
} else
|
||||||
snprintf (status, sizeof (status), " stopped ");
|
snprintf(status, sizeof(status), " stopped ");
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if (c && *c && isatty (fileno (stdout)))
|
if (c && *c && isatty(fileno(stdout)))
|
||||||
printf ("\n");
|
printf("\n");
|
||||||
ebracket (cols, color, status);
|
ebracket(cols, color, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "_usage.h"
|
#include "_usage.h"
|
||||||
@ -115,99 +114,100 @@ static const char * const longopts_help[] = {
|
|||||||
|
|
||||||
int rc_status (int argc, char **argv)
|
int rc_status (int argc, char **argv)
|
||||||
{
|
{
|
||||||
rc_depinfo_t *deptree = NULL;
|
RC_DEPTREE *deptree = NULL;
|
||||||
char **levels = NULL;
|
RC_STRINGLIST *levels = NULL;
|
||||||
char **services = NULL;
|
RC_STRINGLIST *services;
|
||||||
char **ordered = NULL;
|
RC_STRINGLIST *types = NULL;
|
||||||
char *level;
|
RC_STRINGLIST *ordered;
|
||||||
char *service;
|
RC_STRING *s;
|
||||||
|
RC_STRING *l;
|
||||||
|
char *p;
|
||||||
int opt;
|
int opt;
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
int depopts = RC_DEP_STRICT | RC_DEP_START | RC_DEP_TRACE;
|
int depopts = RC_DEP_STRICT | RC_DEP_START | RC_DEP_TRACE;
|
||||||
|
|
||||||
while ((opt = getopt_long (argc, argv, getoptstring, longopts,
|
while ((opt = getopt_long(argc, argv, getoptstring, longopts,
|
||||||
(int *) 0)) != -1)
|
(int *) 0)) != -1)
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'a':
|
case 'a':
|
||||||
levels = rc_runlevel_list ();
|
levels = rc_runlevel_list();
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
levels = rc_runlevel_list ();
|
levels = rc_runlevel_list();
|
||||||
STRLIST_FOREACH (levels, level, i)
|
TAILQ_FOREACH (l, levels, entries)
|
||||||
printf ("%s\n", level);
|
printf("%s\n", l->value);
|
||||||
rc_strlist_free (levels);
|
rc_stringlist_free(levels);
|
||||||
exit (EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
case 'r':
|
case 'r':
|
||||||
level = rc_runlevel_get ();
|
p = rc_runlevel_get ();
|
||||||
printf ("%s\n", level);
|
printf("%s\n", p);
|
||||||
free (level);
|
free(p);
|
||||||
exit (EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
case 's':
|
case 's':
|
||||||
services = rc_services_in_runlevel (NULL);
|
services = rc_services_in_runlevel(NULL);
|
||||||
STRLIST_FOREACH (services, service, i)
|
TAILQ_FOREACH(s, services, entries)
|
||||||
print_service (service);
|
print_service(s->value);
|
||||||
rc_strlist_free (services);
|
rc_stringlist_free(services);
|
||||||
exit (EXIT_SUCCESS);
|
exit (EXIT_SUCCESS);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
case 'u':
|
case 'u':
|
||||||
services = rc_services_in_runlevel (NULL);
|
services = rc_services_in_runlevel(NULL);
|
||||||
levels = rc_runlevel_list ();
|
levels = rc_runlevel_list();
|
||||||
STRLIST_FOREACH (services, service, i) {
|
TAILQ_FOREACH(s, services, entries) {
|
||||||
bool found = false;
|
TAILQ_FOREACH(l, levels, entries)
|
||||||
STRLIST_FOREACH (levels, level, j)
|
if (rc_service_in_runlevel(s->value, l->value))
|
||||||
if (rc_service_in_runlevel (service, level)) {
|
break;
|
||||||
found = true;
|
if (! l)
|
||||||
break;
|
print_service(s->value);
|
||||||
}
|
}
|
||||||
if (! found)
|
rc_stringlist_free(levels);
|
||||||
print_service (service);
|
rc_stringlist_free(services);
|
||||||
}
|
exit (EXIT_SUCCESS);
|
||||||
rc_strlist_free (levels);
|
/* NOTREACHED */
|
||||||
rc_strlist_free (services);
|
|
||||||
exit (EXIT_SUCCESS);
|
|
||||||
/* NOTREACHED */
|
|
||||||
|
|
||||||
case_RC_COMMON_GETOPT
|
case_RC_COMMON_GETOPT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! levels)
|
||||||
|
levels = rc_stringlist_new();
|
||||||
while (optind < argc)
|
while (optind < argc)
|
||||||
rc_strlist_add (&levels, argv[optind++]);
|
rc_stringlist_add(levels, argv[optind++]);
|
||||||
|
if (! TAILQ_FIRST(levels)) {
|
||||||
if (! levels) {
|
p = rc_runlevel_get();
|
||||||
level = rc_runlevel_get ();
|
rc_stringlist_add(levels, p);
|
||||||
rc_strlist_add (&levels, level);
|
free(p);
|
||||||
free (level);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output the services in the order in which they would start */
|
/* Output the services in the order in which they would start */
|
||||||
if (geteuid () == 0)
|
deptree = _rc_deptree_load(NULL);
|
||||||
deptree = _rc_deptree_load (NULL);
|
|
||||||
else
|
|
||||||
deptree = rc_deptree_load ();
|
|
||||||
|
|
||||||
STRLIST_FOREACH (levels, level, i) {
|
TAILQ_FOREACH(l, levels, entries) {
|
||||||
print_level (level);
|
print_level(l->value);
|
||||||
services = rc_services_in_runlevel (level);
|
services = rc_services_in_runlevel(l->value);
|
||||||
if (deptree) {
|
if (deptree) {
|
||||||
ordered = rc_deptree_depends (deptree, types_nua,
|
if (! types) {
|
||||||
(const char **) services,
|
types = rc_stringlist_new();
|
||||||
level, depopts);
|
rc_stringlist_add(types, "ineed");
|
||||||
rc_strlist_free (services);
|
rc_stringlist_add(types, "iuse");
|
||||||
|
rc_stringlist_add(types, "iafter");
|
||||||
|
}
|
||||||
|
ordered = rc_deptree_depends(deptree, types, services,
|
||||||
|
l->value, depopts);
|
||||||
|
rc_stringlist_free(services);
|
||||||
services = ordered;
|
services = ordered;
|
||||||
ordered = NULL;
|
ordered = NULL;
|
||||||
}
|
}
|
||||||
STRLIST_FOREACH (services, service, j)
|
TAILQ_FOREACH(s, services, entries)
|
||||||
if (rc_service_in_runlevel (service, level))
|
if (rc_service_in_runlevel(s->value, l->value))
|
||||||
print_service (service);
|
print_service(s->value);
|
||||||
rc_strlist_free (services);
|
rc_stringlist_free(services);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_strlist_free (levels);
|
rc_stringlist_free(types);
|
||||||
rc_deptree_free (deptree);
|
rc_stringlist_free(levels);
|
||||||
|
rc_deptree_free(deptree);
|
||||||
|
|
||||||
exit (EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,6 @@
|
|||||||
#include "einfo.h"
|
#include "einfo.h"
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "rc-misc.h"
|
#include "rc-misc.h"
|
||||||
#include "strlist.h"
|
|
||||||
|
|
||||||
extern const char *applet;
|
extern const char *applet;
|
||||||
|
|
||||||
@ -68,7 +67,7 @@ static int add (const char *runlevel, const char *service)
|
|||||||
eerror ("%s: failed to add service `%s' to runlevel `%s': %s",
|
eerror ("%s: failed to add service `%s' to runlevel `%s': %s",
|
||||||
applet, service, runlevel, strerror (errno));
|
applet, service, runlevel, strerror (errno));
|
||||||
|
|
||||||
return (retval);
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int delete (const char *runlevel, const char *service)
|
static int delete (const char *runlevel, const char *service)
|
||||||
@ -88,44 +87,47 @@ static int delete (const char *runlevel, const char *service)
|
|||||||
eerror ("%s: failed to remove service `%s' from runlevel `%s': %s",
|
eerror ("%s: failed to remove service `%s' from runlevel `%s': %s",
|
||||||
applet, service, runlevel, strerror (errno));
|
applet, service, runlevel, strerror (errno));
|
||||||
|
|
||||||
return (retval);
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show (char **runlevels, bool verbose)
|
static void show (RC_STRINGLIST *runlevels, bool verbose)
|
||||||
{
|
{
|
||||||
char *service;
|
RC_STRINGLIST *services = rc_services_in_runlevel(NULL);
|
||||||
char **services = rc_services_in_runlevel (NULL);
|
RC_STRING *service;
|
||||||
char *runlevel;
|
RC_STRING *runlevel;
|
||||||
int i;
|
RC_STRINGLIST *in;
|
||||||
int j;
|
bool inone;
|
||||||
|
char buffer[PATH_MAX];
|
||||||
|
size_t l;
|
||||||
|
|
||||||
STRLIST_FOREACH (services, service, i) {
|
TAILQ_FOREACH(service, services, entries) {
|
||||||
char **in = NULL;
|
in = rc_stringlist_new();
|
||||||
bool inone = false;
|
inone = false;
|
||||||
|
|
||||||
STRLIST_FOREACH (runlevels, runlevel, j) {
|
TAILQ_FOREACH(runlevel, runlevels, entries) {
|
||||||
if (rc_service_in_runlevel (service, runlevel)) {
|
if (rc_service_in_runlevel(service->value,
|
||||||
rc_strlist_add (&in, runlevel);
|
runlevel->value))
|
||||||
|
{
|
||||||
|
rc_stringlist_add(in, runlevel->value);
|
||||||
inone = true;
|
inone = true;
|
||||||
} else {
|
} else {
|
||||||
char buffer[PATH_MAX];
|
l = strlen(runlevel->value);
|
||||||
memset (buffer, ' ', strlen (runlevel));
|
memset (buffer, ' ', l);
|
||||||
buffer[strlen (runlevel)] = 0;
|
buffer[l] = 0;
|
||||||
rc_strlist_add (&in, buffer);
|
rc_stringlist_add (in, buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! inone && ! verbose)
|
if (inone || verbose) {
|
||||||
continue;
|
printf(" %20s |", service->value);
|
||||||
|
TAILQ_FOREACH(runlevel, in, entries)
|
||||||
printf (" %20s |", service);
|
printf (" %s", runlevel->value);
|
||||||
STRLIST_FOREACH (in, runlevel, j)
|
printf ("\n");
|
||||||
printf (" %s", runlevel);
|
}
|
||||||
printf ("\n");
|
rc_stringlist_free(in);
|
||||||
rc_strlist_free (in);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_strlist_free (services);
|
rc_stringlist_free (services);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "_usage.h"
|
#include "_usage.h"
|
||||||
@ -146,111 +148,124 @@ static const char * const longopts_help[] = {
|
|||||||
#define DODELETE (1 << 2)
|
#define DODELETE (1 << 2)
|
||||||
#define DOSHOW (1 << 3)
|
#define DOSHOW (1 << 3)
|
||||||
|
|
||||||
int rc_update (int argc, char **argv)
|
int rc_update(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i;
|
RC_STRINGLIST *runlevels;
|
||||||
|
RC_STRING *runlevel;
|
||||||
char *service = NULL;
|
char *service = NULL;
|
||||||
char **runlevels = NULL;
|
char *p;
|
||||||
char *runlevel;
|
|
||||||
int action = 0;
|
int action = 0;
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
int opt;
|
int opt;
|
||||||
int retval = EXIT_FAILURE;
|
int retval = EXIT_FAILURE;
|
||||||
|
int num_updated = 0;
|
||||||
|
int (*actfunc)(const char *, const char *);
|
||||||
|
int ret;
|
||||||
|
|
||||||
while ((opt = getopt_long (argc, argv, getoptstring,
|
while ((opt = getopt_long(argc, argv, getoptstring,
|
||||||
longopts, (int *) 0)) != -1)
|
longopts, (int *) 0)) != -1)
|
||||||
{
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case_RC_COMMON_GETOPT
|
case_RC_COMMON_GETOPT
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
verbose = rc_yesno (getenv ("EINFO_VERBOSE"));
|
verbose = rc_yesno(getenv ("EINFO_VERBOSE"));
|
||||||
|
|
||||||
if ((action & DOSHOW && action != DOSHOW) ||
|
if ((action & DOSHOW && action != DOSHOW) ||
|
||||||
(action & DOADD && action != DOADD) ||
|
(action & DOADD && action != DOADD) ||
|
||||||
(action & DODELETE && action != DODELETE))
|
(action & DODELETE && action != DODELETE))
|
||||||
eerrorx ("%s: cannot mix commands", applet);
|
eerrorx("%s: cannot mix commands", applet);
|
||||||
|
|
||||||
/* We need to be backwards compatible */
|
/* We need to be backwards compatible */
|
||||||
if (optind < argc) {
|
if (optind < argc) {
|
||||||
if (strcmp (argv[optind], "add") == 0)
|
if (strcmp(argv[optind], "add") == 0)
|
||||||
action = DOADD;
|
action = DOADD;
|
||||||
else if (strcmp (argv[optind], "delete") == 0 ||
|
else if (strcmp(argv[optind], "delete") == 0 ||
|
||||||
strcmp (argv[optind], "del") == 0)
|
strcmp(argv[optind], "del") == 0)
|
||||||
action = DODELETE;
|
action = DODELETE;
|
||||||
else if (strcmp (argv[optind], "show") == 0)
|
else if (strcmp(argv[optind], "show") == 0)
|
||||||
action = DOSHOW;
|
action = DOSHOW;
|
||||||
if (action)
|
if (action)
|
||||||
optind++;
|
optind++;
|
||||||
else
|
else
|
||||||
eerrorx ("%s: invalid command `%s'", applet, argv[optind]);
|
eerrorx("%s: invalid command `%s'", applet, argv[optind]);
|
||||||
}
|
}
|
||||||
if (! action)
|
if (! action)
|
||||||
action = DOSHOW;
|
action = DOSHOW;
|
||||||
|
|
||||||
|
runlevels = rc_stringlist_new();
|
||||||
|
|
||||||
if (optind >= argc) {
|
if (optind >= argc) {
|
||||||
if (! action & DOSHOW)
|
if (! action & DOSHOW)
|
||||||
eerrorx ("%s: no service specified", applet);
|
eerrorx("%s: no service specified", applet);
|
||||||
} else {
|
} else {
|
||||||
service = argv[optind];
|
service = argv[optind];
|
||||||
optind++;
|
optind++;
|
||||||
|
|
||||||
while (optind < argc)
|
while (optind < argc)
|
||||||
if (rc_runlevel_exists (argv[optind]))
|
if (rc_runlevel_exists(argv[optind]))
|
||||||
rc_strlist_add (&runlevels, argv[optind++]);
|
rc_stringlist_add(runlevels, argv[optind++]);
|
||||||
else {
|
else {
|
||||||
rc_strlist_free (runlevels);
|
rc_stringlist_free(runlevels);
|
||||||
eerrorx ("%s: `%s' is not a valid runlevel", applet, argv[optind]);
|
eerrorx ("%s: `%s' is not a valid runlevel",
|
||||||
|
applet, argv[optind]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = EXIT_SUCCESS;
|
retval = EXIT_SUCCESS;
|
||||||
if (action & DOSHOW) {
|
if (action & DOSHOW) {
|
||||||
if (service)
|
if (service)
|
||||||
rc_strlist_add (&runlevels, service);
|
rc_stringlist_add(runlevels, service);
|
||||||
if (! runlevels)
|
if (! TAILQ_FIRST(runlevels)) {
|
||||||
runlevels = rc_runlevel_list ();
|
free(runlevels);
|
||||||
|
runlevels = rc_runlevel_list();
|
||||||
|
}
|
||||||
|
|
||||||
show (runlevels, verbose);
|
show (runlevels, verbose);
|
||||||
} else {
|
} else {
|
||||||
if (! service)
|
if (! service)
|
||||||
eerror ("%s: no service specified", applet);
|
eerror ("%s: no service specified", applet);
|
||||||
else {
|
else {
|
||||||
int num_updated = 0;
|
|
||||||
int (*actfunc)(const char *, const char *);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (action & DOADD) {
|
if (action & DOADD) {
|
||||||
actfunc = add;
|
actfunc = add;
|
||||||
} else if (action & DODELETE) {
|
} else if (action & DODELETE) {
|
||||||
actfunc = delete;
|
actfunc = delete;
|
||||||
} else
|
} else {
|
||||||
|
rc_stringlist_free(runlevels);
|
||||||
eerrorx ("%s: invalid action", applet);
|
eerrorx ("%s: invalid action", applet);
|
||||||
|
}
|
||||||
|
|
||||||
if (! runlevels)
|
if (! TAILQ_FIRST(runlevels)) {
|
||||||
rc_strlist_add (&runlevels, rc_runlevel_get ());
|
p = rc_runlevel_get();
|
||||||
|
rc_stringlist_add(runlevels, p);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
if (! runlevels)
|
if (! TAILQ_FIRST(runlevels)) {
|
||||||
|
free(runlevels);
|
||||||
eerrorx ("%s: no runlevels found", applet);
|
eerrorx ("%s: no runlevels found", applet);
|
||||||
|
}
|
||||||
|
|
||||||
STRLIST_FOREACH (runlevels, runlevel, i) {
|
TAILQ_FOREACH (runlevel, runlevels, entries) {
|
||||||
if (! rc_runlevel_exists (runlevel)) {
|
if (! rc_runlevel_exists(runlevel->value)) {
|
||||||
eerror ("%s: runlevel `%s' does not exist", applet, runlevel);
|
eerror ("%s: runlevel `%s' does not exist",
|
||||||
|
applet, runlevel->value);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = actfunc (runlevel, service);
|
ret = actfunc(runlevel->value, service);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
retval = EXIT_FAILURE;
|
retval = EXIT_FAILURE;
|
||||||
num_updated += ret;
|
num_updated += ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retval == EXIT_SUCCESS && num_updated == 0 && action & DODELETE)
|
if (retval == EXIT_SUCCESS &&
|
||||||
ewarnx ("%s: service `%s' not found in any of the specified runlevels", applet, service);
|
num_updated == 0 && action & DODELETE)
|
||||||
|
ewarnx("%s: service `%s' not found in any"
|
||||||
|
" of the specified runlevels",
|
||||||
|
applet, service);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_strlist_free (runlevels);
|
rc_stringlist_free(runlevels);
|
||||||
return (retval);
|
return retval;
|
||||||
}
|
}
|
||||||
|
1220
src/rc/rc.c
1220
src/rc/rc.c
File diff suppressed because it is too large
Load Diff
1279
src/rc/runscript.c
1279
src/rc/runscript.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user