diff options
41 files changed, 4667 insertions, 5314 deletions
diff --git a/man/Makefile b/man/Makefile index f6ffd699..f8c8dedb 100644 --- a/man/Makefile +++ b/man/Makefile @@ -1,6 +1,6 @@ MAN3= einfo.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 # Handy macro to create symlinks diff --git a/man/einfo.3 b/man/einfo.3 index 327ae355..5f1b96bd 100644 --- a/man/einfo.3 +++ b/man/einfo.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd Feb 22, 2008 +.Dd Mar 16, 2008 .Dt EINFO 3 SMM .Os OpenRC .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 eendv "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 eoutdent void .Ft void Fn eindentv void diff --git a/man/rc_config.3 b/man/rc_config.3 index 9a5bfcd4..f420d43b 100644 --- a/man/rc_config.3 +++ b/man/rc_config.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd Jan 08, 2008 +.Dd Mar 16, 2008 .Dt RC_CONFIG 3 SMM .Os OpenRC .Sh NAME @@ -33,8 +33,8 @@ Run Command library (librc, -lrc) .Sh SYNOPSIS .In rc.h .Ft "char *" Fn rc_getline "FILE *fp" -.Ft "char **" Fn rc_config_list "const char *file" -.Ft "char **" Fn rc_config_load "const char *file" +.Ft "RC_STRINGLIST *" Fn rc_config_list "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 bool Fn rc_yesno "const char *value" .Sh DESCRIPTION @@ -61,7 +61,7 @@ found in .Fa list . .Pp Each list should be freed using -.Fn rc_strlist_free +.Fn rc_stringlist_free when done. .Pp .Fn rc_yesno @@ -76,7 +76,7 @@ is set to .Va EINVAL . .Sh SEE ALSO .Xr malloc 3 , -.Xr rc_strlist_free 3 , +.Xr rc_stringlist_free 3 , .Xr sh 1 .Sh AUTHORS .An "Roy Marples" Aq roy@marples.name diff --git a/man/rc_deptree.3 b/man/rc_deptree.3 index 0ee1ad26..8ca2a7d7 100644 --- a/man/rc_deptree.3 +++ b/man/rc_deptree.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd Feb 22, 2008 +.Dd Mar 16, 2008 .Dt RC_DEPTREE 3 SMM .Os OpenRC .Sh NAME @@ -36,25 +36,25 @@ Run Command library (librc, -lrc) .In rc.h .Ft bool Fn rc_deptree_update void .Ft bool Fn rc_deptree_update_needed void -.Ft rc_depinfo_t Fn rc_deptree_load void -.Ft "char **" Fo rc_deptree_depend -.Fa "const rc_depinfo_t *deptree" +.Ft RC_DEPTREE Fn rc_deptree_load void +.Ft "RC_STRINGLIST *" Fo rc_deptree_depend +.Fa "const RC_DEPTREE *deptree" .Fa "const char *type" .Fa "const char *service" .Fc .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 *services" .Fa "const char *runlevel" .Fa "int options" .Fc -.Ft "char **" Fo rc_deptree_order -.Fa "const rc_depinfo_t *deptree" +.Ft "RC_STRINGLIST *" Fo rc_deptree_order +.Fa "const RC_DEPTREE *deptree" .Fa "const char *runlevel" .Fa "int options" .Fc -.Ft void Fn rc_deptree_free "rc_depinfo_t *deptree" +.Ft void Fn rc_deptree_free "RC_DEPTREE *deptree" .Sh DESCRIPTION These functions provide a means of querying the dependencies of OpenRC services. @@ -100,15 +100,14 @@ only lists services actually needed or in the .Va runlevel . .Sh IMPLEMENTATION NOTES Each function that returns -.Fr "char **" -returns a malloced NULL terminated array of malloced NULL terminated strings, -all of which need to be freed using -.Fn rc_strlist_free +.Fr "RC_STRINGLIST *" +should be freed by calling +.Fn rc_stringlist_free when done. .Sh SEE ALSO .Xr malloc 3 , .Xr free 3 , -.Xr rc_strlist_free 3 , +.Xr rc_stringlist_free 3 , .Xr runscript 8 .Sh AUTHORS .An "Roy Marples" Aq roy@marples.name diff --git a/man/rc_plugin_hook.3 b/man/rc_plugin_hook.3 index 7a6e8908..f433a940 100644 --- a/man/rc_plugin_hook.3 +++ b/man/rc_plugin_hook.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd Feb 22, 2008 +.Dd Mar 16, 2008 .Dt RC_PLUGIN_HOOK 3 SMM .Os OpenRC .Sh NAME @@ -32,7 +32,7 @@ Run Command library (librc, -lrc) .Sh SYNOPSIS .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 .Fn rc_plugin_hook is called for each shareable object found in diff --git a/man/rc_runlevel.3 b/man/rc_runlevel.3 index 1a806c8c..2ee7977f 100644 --- a/man/rc_runlevel.3 +++ b/man/rc_runlevel.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd Feb 22, 2008 +.Dd Mar 16, 2008 .Dt RC_RUNLEVEL 3 SMM .Os OpenRC .Sh NAME @@ -35,7 +35,7 @@ Run Command library (librc, -lrc) .In rc.h .Ft "char *" Fn rc_runlevel_get void .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_starting 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. .Pp Each function that returns -.Fr "char **" -returns a malloced NULL terminated array of malloced NULL terminated strings, -all of which need to be freed using -.Fn rc_strlist_free +.Fr "RC_STRINGLIST *" +should by freed by calling +.Fn rc_stringlist_free when done. .Sh FILES .Pa /etc/init.d/functions.sh @@ -62,6 +61,6 @@ Rinse and repeat for the other verbose functions. .Sh SEE ALSO .Xr malloc 3 , .Xr free 3 -.Xr rc_strlist_free 3 +.Xr rc_stringlist_free 3 .Sh AUTHORS .An "Roy Marples" Aq roy@marples.name diff --git a/man/rc_service.3 b/man/rc_service.3 index 9faecb61..a716857f 100644 --- a/man/rc_service.3 +++ b/man/rc_service.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd Feb 22, 2008 +.Dd Mar 16, 2008 .Dt RC_SERVICE 3 SMM .Os OpenRC .Sh NAME @@ -55,17 +55,17 @@ Run Command library (librc, -lrc) .Fc .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_mark "const char *service" "rc_service_state_t state" -.Ft "char **" Fn rc_service_extra_commands "const char *service" +.Ft bool Fn rc_service_mark "const char *service" "RC_SERVICE state" +.Ft "RC_STRINGLIST *" Fn rc_service_extra_commands "const char *service" .Ft bool Fn rc_service_plugable "const char *service" .Ft "char *" rc_service_resolve "const char *service" .Ft bool Fo rc_service_schedule_start .Fa "const char *service" .Fa "const char *service_to_start" .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 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_stop "const char *service" .Ft bool Fo rc_service_started_daemon @@ -79,9 +79,9 @@ Run Command library (librc, -lrc) .Fa "const char *option" .Fa "const char *value" .Fc -.Ft "char **" Fn rc_services_in_runlevel "const char *runlevel" -.Ft "char **" Fn rc_services_in_state "rc_service_state_t state" -.Ft "char **" Fn rc_services_scheduled "const char *service" +.Ft "RC_STRINGLIST *" Fn rc_services_in_runlevel "const char *runlevel" +.Ft "RC_STRINGLIST *" Fn rc_services_in_state "RC_SERVICE state" +.Ft "RC_STRINGLIST *" Fn rc_services_scheduled "const char *service" .Ft bool Fn rc_service_daemons_crashed "const char *service" .Sh DESCRIPTION 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. .Pp Each function that returns -.Fr "char **" -returns a malloced NULL terminated array of malloced NULL terminated strings, -all of which need to be freed using -.Fn rc_strlist_free +.Fr "RC_STRINGLIST *" +should be freed using +.Fn rc_stringlist_free when done. .Pp 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 malloc 3 , .Xr free 3 -.Xr rc_strlist_free 3 , +.Xr rc_stringlist_free 3 , .Xr start-stop-daemon 8 .Sh AUTHORS .An "Roy Marples" Aq roy@marples.name diff --git a/man/rc_strlist.3 b/man/rc_strlist.3 deleted file mode 100644 index 9d082c55..00000000 --- a/man/rc_strlist.3 +++ /dev/null @@ -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 diff --git a/src/includes/rc-misc.h b/src/includes/rc-misc.h index fafbc49c..0b33c997 100644 --- a/src/includes/rc-misc.h +++ b/src/includes/rc-misc.h @@ -56,7 +56,7 @@ #define RC_LIBDIR RC_PREFIX "/" LIB "/rc" #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_INITDIR RC_PREFIX SYSCONFDIR "/init.d" #define RC_CONFDIR RC_PREFIX SYSCONFDIR "/conf.d" @@ -98,9 +98,46 @@ # define _unused #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) { - void *value = malloc (size); + void *value = malloc(size); if (value) return (value); @@ -109,9 +146,9 @@ _unused static void *xmalloc (size_t size) /* 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) return (value); @@ -120,14 +157,14 @@ _unused static void *xrealloc (void *ptr, size_t size) /* NOTREACHED */ } -_unused static char *xstrdup (const char *str) +_unused static char *xstrdup(const char *str) { char *value; if (! str) return (NULL); - value = strdup (str); + value = strdup(str); if (value) return (value); @@ -138,32 +175,32 @@ _unused static char *xstrdup (const char *str) #undef ERRX -_unused static bool exists (const char *pathname) +_unused static bool exists(const char *pathname) { 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; - 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); -bool rc_conf_yesno (const char *var); -char **env_filter (void); -char **env_config (void); -bool service_plugable (const char *service); -int signal_setup (int sig, void (*handler)(int)); +char *rc_conf_value(const char *var); +bool rc_conf_yesno(const char *var); +void env_filter(void); +void env_config(void); +bool service_plugable(const char *service); +int signal_setup(int sig, void (*handler)(int)); /* basename_c never modifies the argument. As such, if there is a trailing * 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) return (++slash); diff --git a/src/includes/strlist.h b/src/includes/strlist.h deleted file mode 100644 index ff4c4edc..00000000 --- a/src/includes/strlist.h +++ /dev/null @@ -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__ */ diff --git a/src/libeinfo/einfo.h b/src/libeinfo/einfo.h index 06fd3aa8..6d39c364 100644 --- a/src/libeinfo/einfo.h +++ b/src/libeinfo/einfo.h @@ -54,19 +54,19 @@ /*! @brief Color types to use */ typedef enum { - ECOLOR_NORMAL = 1, - ECOLOR_GOOD = 2, - ECOLOR_WARN = 3, - ECOLOR_BAD = 4, - ECOLOR_HILITE = 5, - ECOLOR_BRACKET = 6 -} einfo_color_t; + ECOLOR_NORMAL = 1, + ECOLOR_GOOD = 2, + ECOLOR_WARN = 3, + ECOLOR_BAD = 4, + ECOLOR_HILITE = 5, + ECOLOR_BRACKET = 6 +} ECOLOR; /*! @brief Returns the ASCII code for the color */ -const char *ecolor (einfo_color_t); +const char *ecolor(ECOLOR); /*! @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. @@ -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. */ /*@{*/ -int einfon (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF; -int ewarnn (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF; -int eerrorn (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF; -int einfo (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF; -int ewarn (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF; -void ewarnx (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_XPRINTF; -int eerror (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF; -void eerrorx (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_XPRINTF; - -int einfovn (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF; -int ewarnvn (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF; -int ebeginvn (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF; -int eendvn (int __retval, const char * __EINFO_RESTRICT __fmt, ...) __EEND_PRINTF; -int ewendvn (int __retval, const char * __EINFO_RESTRICT __fmt, ...) __EEND_PRINTF; -int einfov (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF; -int ewarnv (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF; +int einfon(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF; +int ewarnn(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF; +int eerrorn(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF; +int einfo(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF; +int ewarn(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF; +void ewarnx(const char * __EINFO_RESTRICT, ...) __EINFO_XPRINTF; +int eerror(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF; +void eerrorx(const char * __EINFO_RESTRICT, ...) __EINFO_XPRINTF; + +int einfovn(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF; +int ewarnvn(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF; +int ebeginvn(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF; +int eendvn(int, const char * __EINFO_RESTRICT, ...) __EEND_PRINTF; +int ewendvn(int, const char * __EINFO_RESTRICT, ...) __EEND_PRINTF; +int einfov(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF; +int ewarnv(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF; /*@}*/ /*! @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 */ /*@{*/ -int ebeginv (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF; -int ebegin (const char * __EINFO_RESTRICT __fmt, ...) __EINFO_PRINTF; +int ebeginv(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF; +int ebegin(const char * __EINFO_RESTRICT, ...) __EINFO_PRINTF; /*@}*/ /*! @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 */ /*@{*/ -int eend (int __retval, const char * __EINFO_RESTRICT __fmt, ...) __EEND_PRINTF; -int ewend (int __retval, const char * __EINFO_RESTRICT __fmt, ...) __EEND_PRINTF; -void ebracket (int __col, einfo_color_t __color, const char * __EINFO_RESTRICT __msg); +int eend(int, const char * __EINFO_RESTRICT, ...) __EEND_PRINTF; +int ewend(int, const char * __EINFO_RESTRICT, ...) __EEND_PRINTF; +void ebracket(int, ECOLOR, const char * __EINFO_RESTRICT); -int eendv (int __retval, const char * __EINFO_RESTRICT __fmt, ...) __EEND_PRINTF; -int ewendv (int __retval, const char * __EINFO_RESTRICT __fmt, ...) __EEND_PRINTF; +int eendv(int, const char * __EINFO_RESTRICT, ...) __EEND_PRINTF; +int ewendv(int, const char * __EINFO_RESTRICT, ...) __EEND_PRINTF; /*@}*/ /*! @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 */ /*@{*/ -void eindent (void); -void eoutdent (void); -void eindentv (void); -void eoutdentv (void); +void eindent(void); +void eoutdent(void); +void eindentv(void); +void eoutdentv(void); /*! @brief Prefix each einfo line with something */ -void eprefix (const char * __EINFO_RESTRICT __prefix); +void eprefix(const char * __EINFO_RESTRICT); #endif diff --git a/src/libeinfo/libeinfo.c b/src/libeinfo/libeinfo.c index ee5b8a68..41969964 100644 --- a/src/libeinfo/libeinfo.c +++ b/src/libeinfo/libeinfo.c @@ -34,6 +34,7 @@ const char libeinfo_copyright[] = "Copyright (c) 2007-2008 Roy Marples"; #include <sys/types.h> #include <sys/ioctl.h> #include <sys/stat.h> + #include <errno.h> #include <fcntl.h> #include <inttypes.h> @@ -52,6 +53,7 @@ const char libeinfo_copyright[] = "Copyright (c) 2007-2008 Roy Marples"; #include "einfo.h" #include "hidden-visibility.h" + hidden_proto(ecolor) hidden_proto(ebegin) hidden_proto(ebeginv) @@ -107,10 +109,10 @@ hidden_proto(ewendv) #define ME "\033[m" #define UP "\033[A" -#define _GET_CAP(_d, _c) strlcpy (_d, tgoto (_c, 0, 0), sizeof (_d)); +#define _GET_CAP(_d, _c) strlcpy(_d, tgoto(_c, 0, 0), sizeof(_d)); #define _ASSIGN_CAP(_v) { \ _v = p; \ - p += strlcpy (p, tmp, sizeof (ebuffer) - (p - ebuffer)) + 1; \ + p += strlcpy(p, tmp, sizeof(ebuffer) - (p - ebuffer)) + 1; \ } /* A pointer to a string to prefix to einfo/ewarn/eerror messages */ @@ -119,7 +121,7 @@ static const char *_eprefix = NULL; /* Buffers and structures to hold the final colours */ static char ebuffer[100]; struct ecolor { - einfo_color_t color; + ECOLOR color; int def; const char *name; }; @@ -197,7 +199,7 @@ static const char *const color_terms[] = { /* strlcat and strlcpy are nice, shame glibc does not define them */ #ifdef __GLIBC__ # if ! defined (__UCLIBC__) && ! defined (__dietlibc__) -static size_t strlcat (char *dst, const char *src, size_t size) +static size_t strlcat(char *dst, const char *src, size_t size) { char *d = dst; const char *s = src; @@ -210,7 +212,7 @@ static size_t strlcat (char *dst, const char *src, size_t size) src_n = size - dst_n; if (src_n == 0) - return (dst_n + strlen (src)); + return dst_n + strlen(src); while (*s != '\0') { if (src_n != 1) { @@ -221,10 +223,10 @@ static size_t strlcat (char *dst, const char *src, size_t size) } *d = '\0'; - return (dst_n + (s - src)); + return dst_n + (s - src); } -static size_t strlcpy (char *dst, const char *src, size_t size) +static size_t strlcpy(char *dst, const char *src, size_t size) { const char *s = src; size_t n = size; @@ -241,72 +243,72 @@ static size_t strlcpy (char *dst, const char *src, size_t size) while (*src++); } - return (src - s - 1); + return src - s - 1; } # endif #endif -static bool yesno (const char *value) +static bool yesno(const char *value) { if (! value) { errno = ENOENT; - return (false); + return false; } - if (strcasecmp (value, "yes") == 0 || - strcasecmp (value, "y") == 0 || - strcasecmp (value, "true") == 0 || - strcasecmp (value, "on") == 0 || - strcasecmp (value, "1") == 0) - return (true); - - if (strcasecmp (value, "no") != 0 && - strcasecmp (value, "n") != 0 && - strcasecmp (value, "false") != 0 && - strcasecmp (value, "off") != 0 && - strcasecmp (value, "0") != 0) + if (strcasecmp(value, "yes") == 0 || + strcasecmp(value, "y") == 0 || + strcasecmp(value, "true") == 0 || + strcasecmp(value, "on") == 0 || + strcasecmp(value, "1") == 0) + return true; + + if (strcasecmp(value, "no") != 0 && + strcasecmp(value, "n") != 0 && + strcasecmp(value, "false") != 0 && + strcasecmp(value, "off") != 0 && + strcasecmp(value, "0") != 0) errno = EINVAL; - return (false); + return false; } -static bool noyes (const char *value) +static bool noyes(const char *value) { int serrno = errno; bool retval; errno = 0; - retval = yesno (value); + retval = yesno(value); if (errno == 0) { retval = ! retval; errno = serrno; } - return (retval); + return retval; } -static bool is_quiet() +static bool is_quiet(void) { - return (yesno (getenv ("EINFO_QUIET"))); + return yesno(getenv("EINFO_QUIET")); } -static bool is_verbose() +static bool is_verbose(void) { - return (yesno (getenv ("EINFO_VERBOSE"))); + return yesno(getenv ("EINFO_VERBOSE")); } /* Fake tgoto call - very crapy, but works for our needs */ #ifndef HAVE_TERMCAP -static char *tgoto (const char *cap, int a, int b) +static char *tgoto(const char *cap, int a, int b) { static char buf[20]; - snprintf (buf, sizeof (buf), cap, b, a); - return (buf); + snprintf(buf, sizeof(buf), cap, b, a); + return buf; } #endif -static bool colour_terminal (FILE * __EINFO_RESTRICT f) +static bool colour_terminal(FILE * __EINFO_RESTRICT f) { static int in_colour = -1; char *e; @@ -321,50 +323,50 @@ static bool colour_terminal (FILE * __EINFO_RESTRICT f) char *p; unsigned int i = 0; - if (f && ! isatty (fileno (f))) - return (false); + if (f && ! isatty(fileno(f))) + return false; - if (noyes (getenv ("EINFO_COLOR"))) - return (false); + if (noyes(getenv("EINFO_COLOR"))) + return false; if (in_colour == 0) - return (false); + return false; if (in_colour == 1) - return (true); + return true; term_is_cons25 = false; if (! term) { - term = getenv ("TERM"); + term = getenv("TERM"); if (! term) - return (false); + return false; } - if (strcmp (term, "cons25") == 0) + if (strcmp(term, "cons25") == 0) term_is_cons25 = true; #ifdef HAVE_TERMCAP /* Check termcap to see if we can do colour or not */ - if (tgetent (termcapbuf, term) == 1) { + if (tgetent(termcapbuf, term) == 1) { char *bp = tcapbuf; - _af = tgetstr ("AF", &bp); - _ce = tgetstr ("ce", &bp); - _ch = tgetstr ("ch", &bp); + _af = tgetstr("AF", &bp); + _ce = tgetstr("ce", &bp); + _ch = tgetstr("ch", &bp); /* Our ch use also works with RI .... for now */ if (! _ch) - _ch = tgetstr ("RI", &bp); - _md = tgetstr ("md", &bp); - _me = tgetstr ("me", &bp); - _up = tgetstr ("up", &bp); + _ch = tgetstr("RI", &bp); + _md = tgetstr("md", &bp); + _me = tgetstr("me", &bp); + _up = tgetstr("up", &bp); } /* Cheat here as vanilla BSD has the whole termcap info in /usr * which is not available to us when we boot */ - if (term_is_cons25 || strcmp (term, "wsvt25") == 0) { + if (term_is_cons25 || strcmp(term, "wsvt25") == 0) { #else while (color_terms[i]) { - if (strcmp (color_terms[i], term) == 0) { + if (strcmp(color_terms[i], term) == 0) { in_colour = 1; } i++; @@ -372,7 +374,7 @@ static bool colour_terminal (FILE * __EINFO_RESTRICT f) if (in_colour != 1) { in_colour = 0; - return (false); + return false; } #endif if (! _af) @@ -392,7 +394,7 @@ static bool colour_terminal (FILE * __EINFO_RESTRICT f) if (! _af || ! _ce || ! _me || !_md || ! _up) { in_colour = 0; - return (false); + return false; } /* Many termcap databases don't have ch or RI even though they @@ -403,7 +405,7 @@ static bool colour_terminal (FILE * __EINFO_RESTRICT f) /* Now setup our colours */ p = ebuffer; - for (i = 0; i < sizeof (ecolors) / sizeof (ecolors[0]); i++) { + for (i = 0; i < sizeof(ecolors) / sizeof(ecolors[0]); i++) { tmp[0] = '\0'; if (ecolors[i].name) { @@ -414,370 +416,370 @@ static bool colour_terminal (FILE * __EINFO_RESTRICT f) * We use a :col;bold: format like 2;1: for bold green * and 1;0: for a normal red */ if ((e = getenv("EINFO_COLOR"))) { - char *ee = strstr (e, ecolors[i].name); + char *ee = strstr(e, ecolors[i].name); if (ee) - ee += strlen (ecolors[i].name); + ee += strlen(ecolors[i].name); if (ee && *ee == '=') { - char *d = strdup (ee + 1); + char *d = strdup(ee + 1); if (d) { - char *end = strchr (d, ':'); + char *end = strchr(d, ':'); if (end) *end = '\0'; c = atoi(d); - end = strchr (d, ';'); + end = strchr(d, ';'); if (end && *++end == '0') bold = _me; - free (d); + free(d); } } } - strlcpy (tmp, tgoto (bold, 0, 0), sizeof (tmp)); - strlcat (tmp, tgoto (_af, 0, c & 0x07), sizeof (tmp)); + strlcpy(tmp, tgoto(bold, 0, 0), sizeof(tmp)); + strlcat(tmp, tgoto(_af, 0, c & 0x07), sizeof(tmp)); } else - _GET_CAP (tmp, _me); + _GET_CAP(tmp, _me); if (tmp[0]) - _ASSIGN_CAP (ecolors_str[i]) + _ASSIGN_CAP(ecolors_str[i]) else ecolors_str[i] = &nullstr; } - _GET_CAP (tmp, _ce) - _ASSIGN_CAP (flush) - _GET_CAP (tmp, _up); - _ASSIGN_CAP (up); - strlcpy (tmp, _ch, sizeof (tmp)); - _ASSIGN_CAP (goto_column); + _GET_CAP(tmp, _ce); + _ASSIGN_CAP(flush); + _GET_CAP(tmp, _up); + _ASSIGN_CAP(up); + strlcpy(tmp, _ch, sizeof(tmp)); + _ASSIGN_CAP(goto_column); in_colour = 1; - return (true); + return true; } -static int get_term_columns (FILE * __EINFO_RESTRICT stream) +static int get_term_columns(FILE * __EINFO_RESTRICT stream) { struct winsize ws; - char *env = getenv ("COLUMNS"); + char *env = getenv("COLUMNS"); char *p; int i; if (env) { - i = strtoimax (env, &p, 10); + i = strtoimax(env, &p, 10); if (! *p) - return (i); + return i; } - if (ioctl (fileno (stream), TIOCGWINSZ, &ws) == 0) - return (ws.ws_col); + if (ioctl(fileno(stream), TIOCGWINSZ, &ws) == 0) + return ws.ws_col; - return (DEFAULT_COLS); + return DEFAULT_COLS; } -void eprefix (const char *__EINFO_RESTRICT prefix) +void eprefix(const char *__EINFO_RESTRICT prefix) { _eprefix = prefix; } hidden_def(eprefix) -static void elogv (int level, const char *__EINFO_RESTRICT fmt, va_list ap) +static void elogv(int level, const char *__EINFO_RESTRICT fmt, va_list ap) { - char *e = getenv ("EINFO_LOG"); + char *e = getenv("EINFO_LOG"); va_list apc; if (fmt && e) { - closelog (); - openlog (e, LOG_PID, LOG_DAEMON); - va_copy (apc, ap); - vsyslog (level, fmt, apc); - va_end (apc); - closelog (); + closelog(); + openlog(e, LOG_PID, LOG_DAEMON); + va_copy(apc, ap); + vsyslog(level, fmt, apc); + va_end(apc); + closelog(); } } -void elog (int level, const char *__EINFO_RESTRICT fmt, ...) +void elog(int level, const char *__EINFO_RESTRICT fmt, ...) { va_list ap; - va_start (ap, fmt); - elogv (level, fmt, ap); - va_end (ap); + va_start(ap, fmt); + elogv(level, fmt, ap); + va_end(ap); } hidden_def(elog) -static int _eindent (FILE * __EINFO_RESTRICT stream) +static int _eindent(FILE * __EINFO_RESTRICT stream) { - char *env = getenv ("EINFO_INDENT"); + char *env = getenv("EINFO_INDENT"); int amount = 0; char indent[INDENT_MAX]; if (env) { errno = 0; - amount = strtoimax (env, NULL, 0); + amount = strtoimax(env, NULL, 0); if (errno != 0 || amount < 0) amount = 0; else if (amount > INDENT_MAX) amount = INDENT_MAX; if (amount > 0) - memset (indent, ' ', (size_t) amount); + memset(indent, ' ', (size_t) amount); } /* Terminate it */ - memset (indent + amount, 0, 1); - return (fprintf (stream, "%s", indent)); + memset(indent + amount, 0, 1); + return fprintf(stream, "%s", indent); } -static const char *_ecolor (FILE * __EINFO_RESTRICT f, einfo_color_t color) +static const char *_ecolor(FILE * __EINFO_RESTRICT f, ECOLOR color) { unsigned int i; - if (! colour_terminal (f)) - return (""); + if (! colour_terminal(f)) + return ""; - for (i = 0; i < sizeof (ecolors) / sizeof (ecolors[0]); i++) { + for (i = 0; i < sizeof(ecolors) / sizeof(ecolors[0]); i++) { if (ecolors[i].color == color) - return (ecolors_str[i]); + return ecolors_str[i]; } - return (""); + return ""; } hidden_def(ecolor) -const char *ecolor (einfo_color_t color) +const char *ecolor(ECOLOR color) { FILE *f = stdout; /* Try and guess a valid tty */ - if (! isatty (fileno (f))) { + if (! isatty(fileno(f))) { f = stderr; - if (! isatty (fileno (f))) { + if (! isatty(fileno(f))) { f = stdin; - if (! isatty (fileno (f))) + if (! isatty(fileno(f))) f = NULL; } } - return (_ecolor (f, color)); + return _ecolor(f, color); } #define LASTCMD(_cmd) { \ - unsetenv ("EINFO_LASTCMD"); \ - setenv ("EINFO_LASTCMD", _cmd, 1); \ + unsetenv("EINFO_LASTCMD"); \ + setenv("EINFO_LASTCMD", _cmd, 1); \ } #define EINFOVN(_file, _color) \ { \ - char *_e = getenv ("EINFO_LASTCMD"); \ - if (_e && ! colour_terminal (_file) && strcmp (_e, "ewarn") != 0 && \ + char *_e = getenv("EINFO_LASTCMD"); \ + if (_e && ! colour_terminal(_file) && strcmp(_e, "ewarn") != 0 && \ _e[strlen (_e) - 1] == 'n') \ - fprintf (_file, "\n"); \ + fprintf(_file, "\n"); \ if (_eprefix) \ - fprintf (_file, "%s%s%s|", _ecolor (_file, _color), _eprefix, _ecolor (_file, ECOLOR_NORMAL)); \ - fprintf (_file, " %s*%s ", _ecolor (_file, _color), _ecolor (_file, ECOLOR_NORMAL)); \ - retval += _eindent (_file); \ + fprintf(_file, "%s%s%s|", _ecolor(_file, _color), _eprefix, _ecolor(_file, ECOLOR_NORMAL)); \ + fprintf(_file, " %s*%s ", _ecolor(_file, _color), _ecolor(_file, ECOLOR_NORMAL)); \ + retval += _eindent(_file); \ { \ va_list _ap; \ - va_copy (_ap, ap); \ - retval += vfprintf (_file, fmt, _ap) + 3; \ - va_end (_ap); \ + va_copy(_ap, ap); \ + retval += vfprintf(_file, fmt, _ap) + 3; \ + va_end(_ap); \ } \ - if (colour_terminal (_file)) \ - fprintf (_file, "%s", flush); \ + if (colour_terminal(_file)) \ + fprintf(_file, "%s", flush); \ } -static int _einfovn (const char *__EINFO_RESTRICT fmt, va_list ap) +static int _einfovn(const char *__EINFO_RESTRICT fmt, va_list ap) { int retval = 0; - EINFOVN (stdout, ECOLOR_GOOD); - return (retval); + EINFOVN(stdout, ECOLOR_GOOD); + return retval; } -static int _ewarnvn (const char *__EINFO_RESTRICT fmt, va_list ap) +static int _ewarnvn(const char *__EINFO_RESTRICT fmt, va_list ap) { int retval = 0; - EINFOVN (stderr, ECOLOR_WARN); - return (retval); + EINFOVN(stderr, ECOLOR_WARN); + return retval; } -static int _eerrorvn (const char *__EINFO_RESTRICT fmt, va_list ap) +static int _eerrorvn(const char *__EINFO_RESTRICT fmt, va_list ap) { int retval = 0; - EINFOVN (stderr, ECOLOR_BAD); - return (retval); + EINFOVN(stderr, ECOLOR_BAD); + return retval; } -int einfon (const char *__EINFO_RESTRICT fmt, ...) +int einfon(const char *__EINFO_RESTRICT fmt, ...) { int retval; va_list ap; - if (! fmt || is_quiet ()) - return (0); + if (! fmt || is_quiet()) + return 0; - va_start (ap, fmt); - retval = _einfovn (fmt, ap); - va_end (ap); + va_start(ap, fmt); + retval = _einfovn(fmt, ap); + va_end(ap); - LASTCMD ("einfon"); + LASTCMD("einfon"); - return (retval); + return retval; } hidden_def(einfon) -int ewarnn (const char *__EINFO_RESTRICT fmt, ...) +int ewarnn(const char *__EINFO_RESTRICT fmt, ...) { int retval; va_list ap; - if (! fmt || is_quiet ()) - return (0); + if (! fmt || is_quiet()) + return 0; - va_start (ap, fmt); - retval = _ewarnvn (fmt, ap); - va_end (ap); + va_start(ap, fmt); + retval = _ewarnvn(fmt, ap); + va_end(ap); - LASTCMD ("ewarnn"); + LASTCMD("ewarnn"); - return (retval); + return retval; } hidden_def(ewarnn) -int eerrorn (const char *__EINFO_RESTRICT fmt, ...) +int eerrorn(const char *__EINFO_RESTRICT fmt, ...) { int retval; va_list ap; - va_start (ap, fmt); - retval = _eerrorvn (fmt, ap); - va_end (ap); + va_start(ap, fmt); + retval = _eerrorvn(fmt, ap); + va_end(ap); - LASTCMD ("errorn"); + LASTCMD("errorn"); - return (retval); + return retval; } hidden_def(eerrorn) -int einfo (const char *__EINFO_RESTRICT fmt, ...) +int einfo(const char *__EINFO_RESTRICT fmt, ...) { int retval; va_list ap; if (! fmt || is_quiet()) - return (0); + return 0; - va_start (ap, fmt); - retval = _einfovn (fmt, ap); - retval += printf ("\n"); - va_end (ap); + va_start(ap, fmt); + retval = _einfovn(fmt, ap); + retval += printf("\n"); + va_end(ap); - LASTCMD ("einfo"); + LASTCMD("einfo"); - return (retval); + return retval; } hidden_def(einfo) -int ewarn (const char *__EINFO_RESTRICT fmt, ...) +int ewarn(const char *__EINFO_RESTRICT fmt, ...) { int retval; va_list ap; - if (! fmt || is_quiet ()) - return (0); + if (! fmt || is_quiet()) + return 0; - va_start (ap, fmt); - elogv (LOG_WARNING, fmt, ap); - retval = _ewarnvn (fmt, ap); - retval += fprintf (stderr, "\n"); - va_end (ap); + va_start(ap, fmt); + elogv(LOG_WARNING, fmt, ap); + retval = _ewarnvn(fmt, ap); + retval += fprintf(stderr, "\n"); + va_end(ap); - LASTCMD ("ewarn"); + LASTCMD("ewarn"); - return (retval); + return retval; } hidden_def(ewarn) -void ewarnx (const char *__EINFO_RESTRICT fmt, ...) +void ewarnx(const char *__EINFO_RESTRICT fmt, ...) { int retval; va_list ap; - if (fmt && ! is_quiet ()) { - va_start (ap, fmt); - elogv (LOG_WARNING, fmt, ap); - retval = _ewarnvn (fmt, ap); - va_end (ap); - retval += fprintf (stderr, "\n"); + if (fmt && ! is_quiet()) { + va_start(ap, fmt); + elogv(LOG_WARNING, fmt, ap); + retval = _ewarnvn(fmt, ap); + va_end(ap); + retval += fprintf(stderr, "\n"); } - exit (EXIT_FAILURE); + exit(EXIT_FAILURE); } hidden_def(ewarnx) -int eerror (const char *__EINFO_RESTRICT fmt, ...) +int eerror(const char *__EINFO_RESTRICT fmt, ...) { int retval; va_list ap; if (! fmt) - return (0); + return 0; - va_start (ap, fmt); - elogv (LOG_ERR, fmt, ap); - retval = _eerrorvn (fmt, ap); - va_end (ap); - retval += fprintf (stderr, "\n"); + va_start(ap, fmt); + elogv(LOG_ERR, fmt, ap); + retval = _eerrorvn(fmt, ap); + va_end(ap); + retval += fprintf(stderr, "\n"); - LASTCMD ("eerror"); + LASTCMD("eerror"); - return (retval); + return retval; } hidden_def(eerror) -void eerrorx (const char *__EINFO_RESTRICT fmt, ...) +void eerrorx(const char *__EINFO_RESTRICT fmt, ...) { va_list ap; if (fmt) { - va_start (ap, fmt); - elogv (LOG_ERR, fmt, ap); - _eerrorvn (fmt, ap); - va_end (ap); - fprintf (stderr, "\n"); + va_start(ap, fmt); + elogv(LOG_ERR, fmt, ap); + _eerrorvn(fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); } - exit (EXIT_FAILURE); + exit(EXIT_FAILURE); } hidden_def(eerrorx) -int ebegin (const char *__EINFO_RESTRICT fmt, ...) +int ebegin(const char *__EINFO_RESTRICT fmt, ...) { int retval; va_list ap; - if (! fmt || is_quiet ()) - return (0); + if (! fmt || is_quiet()) + return 0; - va_start (ap, fmt); - retval = _einfovn (fmt, ap); - va_end (ap); - retval += printf (" ..."); - if (colour_terminal (stdout)) - retval += printf ("\n"); + va_start(ap, fmt); + retval = _einfovn(fmt, ap); + va_end(ap); + retval += printf(" ..."); + if (colour_terminal(stdout)) + retval += printf("\n"); - LASTCMD ("ebegin"); + LASTCMD("ebegin"); - return (retval); + return retval; } hidden_def(ebegin) -static void _eend (FILE * __EINFO_RESTRICT fp, int col, einfo_color_t color, - const char *msg) +static void _eend(FILE * __EINFO_RESTRICT fp, int col, ECOLOR color, + const char *msg) { int i; int cols; @@ -785,13 +787,13 @@ static void _eend (FILE * __EINFO_RESTRICT fp, int col, einfo_color_t color, if (! msg) return; - cols = get_term_columns (fp) - (strlen (msg) + 3); + cols = get_term_columns(fp) - (strlen(msg) + 3); /* cons25 is special - we need to remove one char, otherwise things * do not align properly at all. */ if (! term) { - term = getenv ("TERM"); - if (term && strcmp (term, "cons25") == 0) + term = getenv("TERM"); + if (term && strcmp(term, "cons25") == 0) term_is_cons25 = true; else term_is_cons25 = false; @@ -799,19 +801,19 @@ static void _eend (FILE * __EINFO_RESTRICT fp, int col, einfo_color_t color, if (term_is_cons25) cols--; - if (cols > 0 && colour_terminal (fp)) { - fprintf (fp, "%s%s %s[%s%s%s]%s\n", up, tgoto (goto_column, 0, cols), - ecolor (ECOLOR_BRACKET), ecolor (color), msg, - ecolor (ECOLOR_BRACKET), ecolor (ECOLOR_NORMAL)); + if (cols > 0 && colour_terminal(fp)) { + fprintf(fp, "%s%s %s[%s%s%s]%s\n", up, tgoto(goto_column, 0, cols), + ecolor(ECOLOR_BRACKET), ecolor(color), msg, + ecolor(ECOLOR_BRACKET), ecolor(ECOLOR_NORMAL)); } else { if (col > 0) for (i = 0; i < cols - col; i++) - fprintf (fp, " "); - fprintf (fp, " [%s]\n", msg); + fprintf(fp, " "); + fprintf(fp, " [%s]\n", msg); } } -static int _do_eend (const char *cmd, int retval, const char *__EINFO_RESTRICT fmt, va_list ap) +static int _do_eend(const char *cmd, int retval, const char *__EINFO_RESTRICT fmt, va_list ap) { int col = 0; FILE *fp = stdout; @@ -819,70 +821,70 @@ static int _do_eend (const char *cmd, int retval, const char *__EINFO_RESTRICT f if (fmt && *fmt != '\0' && retval != 0) { fp = stderr; - va_copy (apc, ap); - if (strcmp (cmd, "ewend") == 0) - col = _ewarnvn (fmt, apc); + va_copy(apc, ap); + if (strcmp(cmd, "ewend") == 0) + col = _ewarnvn(fmt, apc); else - col = _eerrorvn (fmt, apc); - col += fprintf (fp, "\n"); - va_end (apc); + col = _eerrorvn(fmt, apc); + col += fprintf(fp, "\n"); + va_end(apc); } - _eend (fp, col, - retval == 0 ? ECOLOR_GOOD : ECOLOR_BAD, - retval == 0 ? OK : NOT_OK); - return (retval); + _eend(fp, col, + retval == 0 ? ECOLOR_GOOD : ECOLOR_BAD, + retval == 0 ? OK : NOT_OK); + return retval; } -int eend (int retval, const char *__EINFO_RESTRICT fmt, ...) +int eend(int retval, const char *__EINFO_RESTRICT fmt, ...) { va_list ap; - if (is_quiet ()) - return (retval); + if (is_quiet()) + return retval; - va_start (ap, fmt); - _do_eend ("eend", retval, fmt, ap); - va_end (ap); + va_start(ap, fmt); + _do_eend("eend", retval, fmt, ap); + va_end(ap); - LASTCMD ("eend"); + LASTCMD("eend"); - return (retval); + return retval; } hidden_def(eend) -int ewend (int retval, const char *__EINFO_RESTRICT fmt, ...) +int ewend(int retval, const char *__EINFO_RESTRICT fmt, ...) { va_list ap; - if (is_quiet ()) - return (retval); + if (is_quiet()) + return retval; - va_start (ap, fmt); - _do_eend ("ewend", retval, fmt, ap); - va_end (ap); + va_start(ap, fmt); + _do_eend("ewend", retval, fmt, ap); + va_end(ap); - LASTCMD ("ewend"); + LASTCMD("ewend"); - return (retval); + return retval; } hidden_def(ewend) -void ebracket (int col, einfo_color_t color, const char *msg) +void ebracket(int col, ECOLOR color, const char *msg) { - _eend (stdout, col, color, msg); + _eend(stdout, col, color, msg); } hidden_def(ebracket) -void eindent (void) +void eindent(void) { - char *env = getenv ("EINFO_INDENT"); + char *env = getenv("EINFO_INDENT"); int amount = 0; char num[10]; if (env) { errno = 0; - amount = strtoimax (env, NULL, 0); + amount = strtoimax(env, NULL, 0); if (errno != 0) amount = 0; } @@ -891,14 +893,14 @@ void eindent (void) if (amount > INDENT_MAX) amount = INDENT_MAX; - snprintf (num, 10, "%08d", amount); - setenv ("EINFO_INDENT", num, 1); + snprintf(num, 10, "%08d", amount); + setenv("EINFO_INDENT", num, 1); } hidden_def(eindent) -void eoutdent (void) +void eoutdent(void) { - char *env = getenv ("EINFO_INDENT"); + char *env = getenv("EINFO_INDENT"); int amount = 0; char num[10]; int serrno = errno; @@ -907,161 +909,161 @@ void eoutdent (void) return; errno = 0; - amount = strtoimax (env, NULL, 0); + amount = strtoimax(env, NULL, 0); if (errno != 0) amount = 0; else amount -= INDENT_WIDTH; if (amount <= 0) - unsetenv ("EINFO_INDENT"); + unsetenv("EINFO_INDENT"); else { - snprintf (num, 10, "%08d", amount); - setenv ("EINFO_INDENT", num, 1); + snprintf(num, 10, "%08d", amount); + setenv("EINFO_INDENT", num, 1); } errno = serrno; } hidden_def(eoutdent) -int einfovn (const char *__EINFO_RESTRICT fmt, ...) +int einfovn(const char *__EINFO_RESTRICT fmt, ...) { int retval; va_list ap; - if (! fmt || ! is_verbose ()) - return (0); + if (! fmt || ! is_verbose()) + return 0; - va_start (ap, fmt); - retval = _einfovn (fmt, ap); - va_end (ap); + va_start(ap, fmt); + retval = _einfovn(fmt, ap); + va_end(ap); - LASTCMD ("einfovn"); + LASTCMD("einfovn"); - return (retval); + return retval; } hidden_def(einfovn) -int ewarnvn (const char *__EINFO_RESTRICT fmt, ...) +int ewarnvn(const char *__EINFO_RESTRICT fmt, ...) { int retval; va_list ap; - if (! fmt || ! is_verbose ()) - return (0); + if (! fmt || ! is_verbose()) + return 0; - va_start (ap, fmt); - retval = _ewarnvn (fmt, ap); - va_end (ap); + va_start(ap, fmt); + retval = _ewarnvn(fmt, ap); + va_end(ap); - LASTCMD ("ewarnvn"); + LASTCMD("ewarnvn"); - return (retval); + return retval; } hidden_def(ewarnvn) -int einfov (const char *__EINFO_RESTRICT fmt, ...) +int einfov(const char *__EINFO_RESTRICT fmt, ...) { int retval; va_list ap; - if (! fmt || ! is_verbose ()) - return (0); + if (! fmt || ! is_verbose()) + return 0; - va_start (ap, fmt); - retval = _einfovn (fmt, ap); - retval += printf ("\n"); - va_end (ap); + va_start(ap, fmt); + retval = _einfovn(fmt, ap); + retval += printf("\n"); + va_end(ap); - LASTCMD ("einfov"); + LASTCMD("einfov"); - return (retval); + return retval; } hidden_def(einfov) -int ewarnv (const char *__EINFO_RESTRICT fmt, ...) +int ewarnv(const char *__EINFO_RESTRICT fmt, ...) { int retval; va_list ap; - if (! fmt || ! is_verbose ()) - return (0); + if (! fmt || ! is_verbose()) + return 0; - va_start (ap, fmt); - retval = _ewarnvn (fmt, ap); - retval += printf ("\n"); - va_end (ap); + va_start(ap, fmt); + retval = _ewarnvn(fmt, ap); + retval += printf("\n"); + va_end(ap); - LASTCMD ("ewarnv"); + LASTCMD("ewarnv"); - return (retval); + return retval; } hidden_def(ewarnv) -int ebeginv (const char *__EINFO_RESTRICT fmt, ...) +int ebeginv(const char *__EINFO_RESTRICT fmt, ...) { int retval; va_list ap; - if (! fmt || ! is_verbose ()) - return (0); + if (! fmt || ! is_verbose()) + return 0; - va_start (ap, fmt); - retval = _einfovn (fmt, ap); - retval += printf (" ..."); - if (colour_terminal (stdout)) - retval += printf ("\n"); - va_end (ap); + va_start(ap, fmt); + retval = _einfovn(fmt, ap); + retval += printf(" ..."); + if (colour_terminal(stdout)) + retval += printf("\n"); + va_end(ap); - LASTCMD ("ebeginv"); + LASTCMD("ebeginv"); - return (retval); + return retval; } hidden_def(ebeginv) -int eendv (int retval, const char *__EINFO_RESTRICT fmt, ...) +int eendv(int retval, const char *__EINFO_RESTRICT fmt, ...) { va_list ap; - if (! is_verbose ()) - return (0); + if (! is_verbose()) + return 0; - va_start (ap, fmt); - _do_eend ("eendv", retval, fmt, ap); - va_end (ap); + va_start(ap, fmt); + _do_eend("eendv", retval, fmt, ap); + va_end(ap); - LASTCMD ("eendv"); + LASTCMD("eendv"); - return (retval); + return retval; } hidden_def(eendv) -int ewendv (int retval, const char *__EINFO_RESTRICT fmt, ...) +int ewendv(int retval, const char *__EINFO_RESTRICT fmt, ...) { va_list ap; - if (! is_verbose ()) - return (0); + if (! is_verbose()) + return 0; - va_start (ap, fmt); - _do_eend ("ewendv", retval, fmt, ap); - va_end (ap); + va_start(ap, fmt); + _do_eend("ewendv", retval, fmt, ap); + va_end(ap); - LASTCMD ("ewendv"); + LASTCMD("ewendv"); - return (retval); + return retval; } hidden_def(ewendv) -void eindentv (void) +void eindentv(void) { - if (is_verbose ()) + if (is_verbose()) eindent (); } hidden_def(eindentv) -void eoutdentv (void) +void eoutdentv(void) { - if (is_verbose ()) - eoutdent (); + if (is_verbose()) + eoutdent(); } hidden_def(eoutdentv) diff --git a/src/librc/.gitignore b/src/librc/.gitignore index 5f6e3ee2..eab6c70e 100644 --- a/src/librc/.gitignore +++ b/src/librc/.gitignore @@ -3,12 +3,12 @@ librc.o librc-daemon.o librc-depend.o librc-misc.o -librc-strlist.o +librc-stringlist.o librc.So librc-daemon.So librc-depend.So librc-misc.So -librc-strlist.So +librc-stringlist.So librc.a librc.so.1 librc.so diff --git a/src/librc/Makefile b/src/librc/Makefile index 78c97ce8..15c396b3 100644 --- a/src/librc/Makefile +++ b/src/librc/Makefile @@ -4,7 +4,7 @@ include ${MK}/os.mk LIB= rc SHLIB_MAJOR= 1 SRCS= librc.c librc-daemon.c librc-depend.c librc-misc.c \ - librc-strlist.c + librc-stringlist.c INCS= rc.h VERSION_MAP= rc.map diff --git a/src/librc/librc-daemon.c b/src/librc/librc-daemon.c index ca23ed27..9ae4ac26 100644 --- a/src/librc/librc-daemon.c +++ b/src/librc/librc-daemon.c @@ -32,33 +32,33 @@ #include "librc.h" #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]; FILE *fp; int c; - snprintf(buffer, sizeof (buffer), "/proc/%d/stat", pid); - if ((fp = fopen (buffer, "r")) == NULL) - return (false); + snprintf(buffer, sizeof(buffer), "/proc/%d/stat", pid); + if ((fp = fopen(buffer, "r")) == NULL) + return false; - while ((c = getc (fp)) != EOF && c != '(') + while ((c = getc(fp)) != EOF && c != '(') ; if (c != '(') { fclose(fp); - return (false); + return false; } - while ((c = getc (fp)) != EOF && c == *cmd) + while ((c = getc(fp)) != EOF && c == *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 buffer[PATH_MAX]; @@ -66,31 +66,30 @@ static bool pid_is_exec (pid_t pid, const char *const *argv) int fd = -1; int r; + /* Check it's the right binary */ snprintf (cmdline, sizeof (cmdline), "/proc/%u/exe", pid); memset (buffer, 0, sizeof (buffer)); -#if 0 - if (readlink (cmdline, buffer, sizeof (buffer)) != -1) { - if (strcmp (exec, buffer) == 0) - return (true); + if (readlink(cmdline, buffer, sizeof(buffer)) != -1) { + if (strcmp(*argv, buffer) == 0) + return true; /* We should cater for deleted binaries too */ - if (strlen (buffer) > 10) { - p = buffer + (strlen (buffer) - 10); - if (strcmp (p, " (deleted)") == 0) { + if (strlen(buffer) > 10) { + p = buffer + (strlen(buffer) - 10); + if (strcmp(p, " (deleted)") == 0) { *p = 0; - if (strcmp (buffer, exec) == 0) - return (true); + if (strcmp(buffer, *argv) == 0) + return true; } } } -#endif - snprintf (cmdline, sizeof (cmdline), "/proc/%u/cmdline", pid); - if ((fd = open (cmdline, O_RDONLY)) < 0) - return (false); + snprintf(cmdline, sizeof(cmdline), "/proc/%u/cmdline", pid); + if ((fd = open(cmdline, O_RDONLY)) < 0) + return false; - r = read (fd, buffer, sizeof (buffer)); - close (fd); + r = read(fd, buffer, sizeof(buffer)); + close(fd); if (r == -1) return 0; @@ -98,18 +97,18 @@ static bool pid_is_exec (pid_t pid, const char *const *argv) buffer[r] = 0; p = buffer; while (*argv) { - if (strcmp (*argv, p) != 0) - return (false); + if (strcmp(*argv, p) != 0) + return false; argv++; - p += strlen (p) + 1; + p += strlen(p) + 1; 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, - uid_t uid, pid_t pid) +pid_t *rc_find_pids(const char *const *argv, const char *cmd, + uid_t uid, pid_t pid) { DIR *procdir; struct dirent *entry; @@ -122,8 +121,8 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd, pid_t runscript_pid = 0; char *pp; - if ((procdir = opendir ("/proc")) == NULL) - return (NULL); + if ((procdir = opendir("/proc")) == NULL) + return NULL; /* 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 */ - if ((pp = getenv ("RC_RUNSCRIPT_PID"))) { - if (sscanf (pp, "%d", &runscript_pid) != 1) + if ((pp = getenv("RC_RUNSCRIPT_PID"))) { + if (sscanf(pp, "%d", &runscript_pid) != 1) runscript_pid = 0; } - while ((entry = readdir (procdir)) != NULL) { - if (sscanf (entry->d_name, "%d", &p) != 1) + while ((entry = readdir(procdir)) != NULL) { + if (sscanf(entry->d_name, "%d", &p) != 1) continue; if (runscript_pid != 0 && runscript_pid == p) @@ -152,23 +151,23 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd, continue; if (uid) { - snprintf (buffer, sizeof (buffer), "/proc/%d", p); - if (stat (buffer, &sb) != 0 || sb.st_uid != uid) + snprintf(buffer, sizeof(buffer), "/proc/%d", p); + if (stat(buffer, &sb) != 0 || sb.st_uid != uid) continue; } - if (cmd && ! pid_is_cmd (p, cmd)) + if (cmd && ! pid_is_cmd(p, cmd)) continue; - if (argv && ! cmd && ! pid_is_exec (p, (const char *const *)argv)) + if (argv && ! cmd && ! pid_is_exec(p, (const char *const *)argv)) continue; - tmp = realloc (pids, sizeof (pid_t) * (npids + 2)); + tmp = realloc(pids, sizeof (pid_t) * (npids + 2)); if (! tmp) { - free (pids); - closedir (procdir); + free(pids); + closedir(procdir); errno = ENOMEM; - return (NULL); + return NULL; } pids = tmp; @@ -176,9 +175,9 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd, pids[npids + 1] = 0; npids++; } - closedir (procdir); + closedir(procdir); - return (pids); + return pids; } librc_hidden_def(rc_find_pids) @@ -206,8 +205,8 @@ librc_hidden_def(rc_find_pids) # define _KVM_FLAGS O_RDONLY # endif -pid_t *rc_find_pids (const char *const *argv, const char *cmd, - uid_t uid, pid_t pid) +pid_t *rc_find_pids(const char *const *argv, const char *cmd, + uid_t uid, pid_t pid) { static kvm_t *kd = NULL; char errbuf[_POSIX2_LINE_MAX]; @@ -218,44 +217,45 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd, char **pargv; pid_t *pids = NULL; pid_t *tmp; + pid_t p; const char *const *arg; int npids = 0; int match; - if ((kd = kvm_openfiles (_KVM_PATH, _KVM_PATH, - NULL, _KVM_FLAGS, errbuf)) == NULL) + if ((kd = kvm_openfiles(_KVM_PATH, _KVM_PATH, + NULL, _KVM_FLAGS, errbuf)) == NULL) { - fprintf (stderr, "kvm_open: %s\n", errbuf); - return (NULL); + fprintf(stderr, "kvm_open: %s\n", errbuf); + return NULL; } #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 - kp = kvm_getprocs (kd, KERN_PROC_PROC, 0, &processes); + kp = kvm_getprocs(kd, KERN_PROC_PROC, 0, &processes); #endif if ((kp == NULL && processes > 0) || (kp != NULL && processes < 0)) { - fprintf (stderr, "kvm_getprocs: %s\n", kvm_geterr (kd)); - kvm_close (kd); - return (NULL); + fprintf(stderr, "kvm_getprocs: %s\n", kvm_geterr(kd)); + kvm_close(kd); + return NULL; } 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) continue; - if (uid != 0 && uid != _GET_KINFO_UID (kp[i])) + if (uid != 0 && uid != _GET_KINFO_UID(kp[i])) continue; if (cmd) { - if (! _GET_KINFO_COMM (kp[i]) || - strcmp (cmd, _GET_KINFO_COMM (kp[i])) != 0) + if (! _GET_KINFO_COMM(kp[i]) || + strcmp(cmd, _GET_KINFO_COMM(kp[i])) != 0) continue; } if (argv && *argv && ! cmd) { - pargv = _KVM_GETARGV (kd, &kp[i], pargc); + pargv = _KVM_GETARGV(kd, &kp[i], pargc); if (! pargv || ! *pargv) continue; @@ -263,7 +263,7 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd, match = 1; while (*arg && *pargv) - if (strcmp (*arg++, *pargv++) != 0) { + if (strcmp(*arg++, *pargv++) != 0) { match = 0; break; } @@ -272,12 +272,12 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd, continue; } - tmp = realloc (pids, sizeof (pid_t) * (npids + 2)); + tmp = realloc(pids, sizeof(pid_t) * (npids + 2)); if (! tmp) { - free (pids); - kvm_close (kd); + free(pids); + kvm_close(kd); errno = ENOMEM; - return (NULL); + return NULL; } pids = tmp; @@ -285,9 +285,9 @@ pid_t *rc_find_pids (const char *const *argv, const char *cmd, pids[npids + 1] = 0; npids++; } - kvm_close (kd); + kvm_close(kd); - return (pids); + return pids; } librc_hidden_def(rc_find_pids) @@ -295,67 +295,72 @@ librc_hidden_def(rc_find_pids) # error "Platform not supported!" #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 *ffile = rc_strcatpaths (path, file, (char *) NULL); + char *ffile = rc_strcatpaths(path, file, (char *) NULL); FILE *fp; + RC_STRING *m; - fp = fopen (ffile, "r"); - free (ffile); + fp = fopen(ffile, "r"); + free(ffile); if (! fp) - return (false); + return false; - while ((line = rc_getline (fp))) { - rc_strlist_delete (&match, line); - if (! match || !*match) + while ((line = rc_getline(fp))) { + TAILQ_FOREACH(m, match, entries) + if (strcmp(line, m->value) == 0) { + TAILQ_REMOVE(match, m, entries); + break; + } + if (! TAILQ_FIRST(match)) break; } - fclose (fp); - if (match && *match) - return (false); - return (true); + fclose(fp); + if (TAILQ_FIRST(match)) + return false; + return true; } -static char **_match_list (const char* const* argv, - const char *name, const char *pidfile) +static RC_STRINGLIST *_match_list(const char* const* argv, + const char *name, const char *pidfile) { - char **match = NULL; + RC_STRINGLIST *match = rc_stringlist_new(); int i = 0; size_t l; char *m; while (argv && argv[i]) { - l = strlen (*argv) + strlen ("argv_=") + 16; - m = xmalloc (sizeof (char) * l); - snprintf (m, l, "argv_0=%s", argv[i++]); - rc_strlist_add (&match, m); - free (m); + l = strlen(*argv) + strlen("argv_=") + 16; + m = xmalloc(sizeof(char) * l); + snprintf(m, l, "argv_0=%s", argv[i++]); + rc_stringlist_add(match, m); + free(m); } if (name) { - l = strlen (name) + 6; - m = xmalloc (sizeof (char) * l); - snprintf (m, l, "name=%s", name); - rc_strlist_add (&match, m); - free (m); + l = strlen(name) + 6; + m = xmalloc(sizeof (char) * l); + snprintf(m, l, "name=%s", name); + rc_stringlist_add(match, m); + free(m); } if (pidfile) { - l = strlen (pidfile) + 9; - m = xmalloc (sizeof (char) * l); - snprintf (m, l, "pidfile=%s", pidfile); - rc_strlist_add (&match, m); + l = strlen(pidfile) + 9; + m = xmalloc(sizeof (char) * l); + snprintf(m, l, "pidfile=%s", pidfile); + rc_stringlist_add(match, m); free (m); } - return (match); + return match; } -bool rc_service_daemon_set (const char *service, const char *const *argv, - const char *name, const char *pidfile, - bool started) +bool rc_service_daemon_set(const char *service, const char *const *argv, + const char *name, const char *pidfile, bool started) { char *dirpath; char *file = NULL; @@ -364,123 +369,123 @@ bool rc_service_daemon_set (const char *service, const char *const *argv, bool retval = false; DIR *dp; struct dirent *d; - char **match = NULL; + RC_STRINGLIST *match; int i = 0; + char buffer[10]; + FILE *fp; - if (! (argv && *argv) && ! name && ! pidfile) { + if (!(argv && *argv) && ! name && ! pidfile) { errno = EINVAL; - return (false); + return false; } - dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", - basename_c (service), (char *) NULL); + dirpath = rc_strcatpaths(RC_SVCDIR, "daemons", + basename_c(service), (char *) NULL); - match = _match_list (argv, name, pidfile); + match = _match_list(argv, name, pidfile); /* Regardless, erase any existing daemon info */ - if ((dp = opendir (dirpath))) { - while ((d = readdir (dp))) { + if ((dp = opendir(dirpath))) { + while ((d = readdir(dp))) { if (d->d_name[0] == '.') continue; - file = rc_strcatpaths (dirpath, d->d_name, (char *) NULL); + file = rc_strcatpaths(dirpath, d->d_name, (char *) NULL); nfiles++; if (! oldfile) { - if (_match_daemon (dirpath, d->d_name, match)) { + if (_match_daemon(dirpath, d->d_name, match)) { unlink (file); oldfile = file; nfiles--; } } else { - rename (file, oldfile); - free (oldfile); + rename(file, oldfile); + free(oldfile); oldfile = file; } } - free (file); - closedir (dp); + free(file); + closedir(dp); } /* Now store our daemon info */ if (started) { - char buffer[10]; - FILE *fp; - - if (mkdir (dirpath, 0755) == 0 || errno == EEXIST) { - snprintf (buffer, sizeof (buffer), "%03d", nfiles + 1); - file = rc_strcatpaths (dirpath, buffer, (char *) NULL); - if ((fp = fopen (file, "w"))) { + if (mkdir(dirpath, 0755) == 0 || errno == EEXIST) { + snprintf(buffer, sizeof(buffer), "%03d", nfiles + 1); + file = rc_strcatpaths(dirpath, buffer, (char *) NULL); + if ((fp = fopen(file, "w"))) { while (argv && argv[i]) { - fprintf (fp, "argv_%d=%s\n", i, argv[i]); + fprintf(fp, "argv_%d=%s\n", i, argv[i]); i++; } - fprintf (fp, "name="); + fprintf(fp, "name="); if (name) - fprintf (fp, "%s", name); - fprintf (fp, "\npidfile="); + fprintf(fp, "%s", name); + fprintf(fp, "\npidfile="); if (pidfile) - fprintf (fp, "%s", pidfile); - fprintf (fp, "\n"); - fclose (fp); + fprintf(fp, "%s", pidfile); + fprintf(fp, "\n"); + fclose(fp); retval = true; } - free (file); + free(file); } } else retval = true; - rc_strlist_free (match); - free (dirpath); + rc_stringlist_free(match); + free(dirpath); - return (retval); + return retval; } librc_hidden_def(rc_service_daemon_set) -bool rc_service_started_daemon (const char *service, const char *const *argv, - int indx) +bool +rc_service_started_daemon (const char *service, const char *const *argv, + int indx) { char *dirpath; char *file; size_t l; - char **match; + RC_STRINGLIST *match; bool retval = false; DIR *dp; struct dirent *d; - if (! service || ! (argv && *argv)) - return (false); + if (!service || !(argv && *argv)) + return false; - dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename_c (service), - (char *) NULL); + dirpath = rc_strcatpaths(RC_SVCDIR, "daemons", basename_c(service), + (char *) NULL); - match = _match_list (argv, NULL, NULL); + match = _match_list(argv, NULL, NULL); if (indx > 0) { l = sizeof (char) * 10; - file = xmalloc (l); - snprintf (file, l, "%03d", indx); - retval = _match_daemon (dirpath, file, match); - free (file); + file = xmalloc(l); + snprintf(file, l, "%03d", indx); + retval = _match_daemon(dirpath, file, match); + free(file); } else { - if ((dp = opendir (dirpath))) { - while ((d = readdir (dp))) { + if ((dp = opendir(dirpath))) { + while ((d = readdir(dp))) { if (d->d_name[0] == '.') continue; - retval = _match_daemon (dirpath, d->d_name, match); + retval = _match_daemon(dirpath, d->d_name, match); if (retval) break; } - closedir (dp); + closedir(dp); } } - free (dirpath); - rc_strlist_free (match); - return (retval); + free(dirpath); + rc_stringlist_free(match); + return retval; } 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; DIR *dp; @@ -497,116 +502,123 @@ bool rc_service_daemons_crashed (const char *service) char *p; char *token; bool retval = false; + RC_STRINGLIST *list; + RC_STRING *s; + size_t i; - if (! service) - return (false); + dirpath = rc_strcatpaths(RC_SVCDIR, "daemons", basename_c(service), + (char *) NULL); - dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", basename_c (service), - (char *) NULL); - - if (! (dp = opendir (dirpath))) { - 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] == '.') continue; - path = rc_strcatpaths (dirpath, d->d_name, (char *) NULL); - fp = fopen (path, "r"); - free (path); + path = rc_strcatpaths(dirpath, d->d_name, (char *) NULL); + fp = fopen(path, "r"); + free(path); if (! fp) break; - while ((line = rc_getline (fp))) { + list = rc_stringlist_new(); + + while ((line = rc_getline(fp))) { p = line; - if ((token = strsep (&p, "=")) == NULL || ! p) { - free (line); + if ((token = strsep(&p, "=")) == NULL || ! p) { + free(line); continue; } - if (strlen (p) == 0) { - free (line); + if (! *p) { + free(line); continue; } - if (strncmp (token, "argv_", 5) == 0) { - rc_strlist_add (&argv, p); - } else if (strcmp (token, "exec") == 0) { + if (strncmp(token, "argv_", 5) == 0) { + rc_stringlist_add(list, p); + } else if (strcmp(token, "exec") == 0) { if (exec) - free (exec); - exec = xstrdup (p); - } else if (strcmp (token, "name") == 0) { + free(exec); + exec = xstrdup(p); + } else if (strcmp(token, "name") == 0) { if (name) - free (name); - name = xstrdup (p); - } else if (strcmp (token, "pidfile") == 0) { + free(name); + name = xstrdup(p); + } else if (strcmp(token, "pidfile") == 0) { if (pidfile) - free (pidfile); - pidfile = xstrdup (p); + free(pidfile); + pidfile = xstrdup(p); } - free (line); + free(line); } - fclose (fp); + fclose(fp); pid = 0; if (pidfile) { - if (! exists (pidfile)) { + if (! exists(pidfile)) { retval = true; break; } - if ((fp = fopen (pidfile, "r")) == NULL) { + if ((fp = fopen(pidfile, "r")) == NULL) { retval = true; break; } - if (fscanf (fp, "%d", &pid) != 1) { + if (fscanf(fp, "%d", &pid) != 1) { fclose (fp); retval = true; break; } - fclose (fp); - free (pidfile); + fclose(fp); + free(pidfile); pidfile = NULL; /* We have the pid, so no need to match on name */ - rc_strlist_free (argv); - argv = NULL; + rc_stringlist_free(list); + list = NULL; free (exec); exec = NULL; free (name); name = NULL; - } - - if (exec && ! argv) { - rc_strlist_add (&argv, exec); - free (exec); + } else { + if (exec && ! TAILQ_FIRST(list)) { + rc_stringlist_add(list, exec); + } + free(exec); exec = NULL; - } - if ((pids = rc_find_pids ((const char *const *)argv, name, 0, pid)) == NULL) { - retval = true; - break; + /* 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'; } - free (pids); - rc_strlist_free (argv); + if ((pids = rc_find_pids((const char *const *)argv, name, 0, pid)) == NULL) + retval = true; + free(pids); + free(argv); argv = NULL; - free (exec); - exec = NULL; - free (name); + rc_stringlist_free(list); + free(name); name = NULL; + if (retval) + break; } - rc_strlist_free (argv); - free (exec); - free (name); - free (dirpath); - closedir (dp); + free(dirpath); + closedir(dp); - return (retval); + return retval; } librc_hidden_def(rc_service_daemons_crashed) diff --git a/src/librc/librc-depend.c b/src/librc/librc-depend.c index 22470368..8617d753 100644 --- a/src/librc/librc-depend.c +++ b/src/librc/librc-depend.c @@ -37,31 +37,18 @@ static const char *bootlevel = NULL; -/* We use this so we can pass our char array through many functions */ -struct lhead -{ - char **list; -}; - -static void *xzalloc (size_t size) -{ - void *value = xmalloc (size); - memset (value, 0, size); - return (value); -} - -static char *get_shell_value (char *string) +static char *get_shell_value(char *string) { char *p = string; char *e; if (! string) - return (NULL); + return NULL; if (*p == '\'') p++; - e = p + strlen (p) - 1; + e = p + strlen(p) - 1; if (*e == '\n') *e-- = 0; if (*e == '\'') @@ -70,191 +57,184 @@ static char *get_shell_value (char *string) if (*p != 0) return p; - return (NULL); + return NULL; } -void rc_deptree_free (rc_depinfo_t *deptree) +void rc_deptree_free(RC_DEPTREE *deptree) { - rc_depinfo_t *di = deptree; + RC_DEPINFO *di; + RC_DEPINFO *di2; + RC_DEPTYPE *dt; + RC_DEPTYPE *dt2; + + if (! deptree) + return; + + di = STAILQ_FIRST(deptree); while (di) { - rc_depinfo_t *dip = di->next; - rc_deptype_t *dt = di->depends; - free (di->service); + di2 = STAILQ_NEXT(di, entries); + dt = STAILQ_FIRST(&di->depends); while (dt) { - rc_deptype_t *dtp = dt->next; - free (dt->type); - rc_strlist_free (dt->services); - free (dt); - dt = dtp; + dt2 = STAILQ_NEXT(dt, entries); + rc_stringlist_free(dt->services); + free(dt->type); + free(dt); + dt = dt2; } - free (di); - di = dip; + free(di->service); + free(di); + di = di2; } + free(deptree); } librc_hidden_def(rc_deptree_free) -static rc_depinfo_t *get_depinfo (const rc_depinfo_t *deptree, - const char *service) +static RC_DEPINFO *get_depinfo(const RC_DEPTREE *deptree, + const char *service) { - const rc_depinfo_t *di; - - if (! deptree || ! service) - return (NULL); + RC_DEPINFO *di; - for (di = deptree; di; di = di->next) - if (strcmp (di->service, service) == 0) - return ((rc_depinfo_t *)di); + STAILQ_FOREACH(di, deptree, entries) + if (strcmp(di->service, service) == 0) + return di; - return (NULL); + return NULL; } -static rc_deptype_t *get_deptype (const rc_depinfo_t *depinfo, - const char *type) +static RC_DEPTYPE *get_deptype(const RC_DEPINFO *depinfo, + const char *type) { - rc_deptype_t *dt; + RC_DEPTYPE *dt; - if (! depinfo || !type) - return (NULL); + STAILQ_FOREACH(dt, &depinfo->depends, entries) + if (strcmp(dt->type, type) == 0) + return dt; - for (dt = depinfo->depends; dt; dt = dt->next) - if (strcmp (dt->type, type) == 0) - return (dt); - - return (NULL); + return NULL; } -rc_depinfo_t *rc_deptree_load (void) +RC_DEPTREE *rc_deptree_load(void) { FILE *fp; - rc_depinfo_t *deptree = NULL; - rc_depinfo_t *depinfo = NULL; - rc_deptype_t *deptype = NULL; + RC_DEPTREE *deptree; + RC_DEPINFO *depinfo = NULL; + RC_DEPTYPE *deptype = NULL; char *line; char *type; char *p; char *e; int i; - if (! (fp = fopen (RC_DEPTREE, "r"))) - return (NULL); + if (!(fp = fopen(RC_DEPTREE_CACHE, "r"))) + return NULL; + + deptree = xmalloc(sizeof(*deptree)); + STAILQ_INIT(deptree); - while ((line = rc_getline (fp))) + while ((line = rc_getline(fp))) { p = line; - e = strsep (&p, "_"); - if (! e || strcmp (e, "depinfo") != 0) + e = strsep(&p, "_"); + if (! e || strcmp(e, "depinfo") != 0) goto next; e = strsep (&p, "_"); - if (! e || sscanf (e, "%d", &i) != 1) + if (! e || sscanf(e, "%d", &i) != 1) goto next; - if (! (type = strsep (&p, "_="))) + if (! (type = strsep(&p, "_="))) goto next; - if (strcmp (type, "service") == 0) + if (strcmp(type, "service") == 0) { /* Sanity */ - e = get_shell_value (p); + e = get_shell_value(p); if (! e || *e == '\0') goto next; - if (! deptree) - { - deptree = xzalloc (sizeof (*deptree)); - depinfo = deptree; - } - else - { - depinfo->next = xzalloc (sizeof (*depinfo->next)); - depinfo = depinfo->next; - } - depinfo->service = xstrdup (e); + depinfo = xmalloc(sizeof(*depinfo)); + STAILQ_INIT(&depinfo->depends); + depinfo->service = xstrdup(e); + STAILQ_INSERT_TAIL(deptree, depinfo, entries); deptype = NULL; goto next; } - e = strsep (&p, "="); - if (! e || sscanf (e, "%d", &i) != 1) + e = strsep(&p, "="); + if (! e || sscanf(e, "%d", &i) != 1) goto next; /* Sanity */ - e = get_shell_value (p); + e = get_shell_value(p); if (! e || *e == '\0') goto next; - if (! deptype) - { - depinfo->depends = xzalloc (sizeof (*depinfo->depends)); - deptype = depinfo->depends; - } - else - if (strcmp (deptype->type, type) != 0) - { - deptype->next = xzalloc (sizeof (*deptype->next)); - deptype = deptype->next; - } - - if (! deptype->type) + if (! deptype || strcmp(deptype->type, type) != 0) { + deptype = xmalloc(sizeof(*deptype)); + deptype->services = rc_stringlist_new(); deptype->type = xstrdup (type); + STAILQ_INSERT_TAIL(&depinfo->depends, deptype, entries); + } - rc_strlist_addsort (&deptype->services, e); - + rc_stringlist_add(deptype->services, e); next: - free (line); + free(line); } - fclose (fp); - - return (deptree); + fclose(fp); + + return deptree; } librc_hidden_def(rc_deptree_load) -static bool valid_service (const char *runlevel, const char *service) +static bool valid_service(const char *runlevel, const char *service) { - rc_service_state_t state = rc_service_state (service); + RC_SERVICE state = rc_service_state(service); return ((strcmp (runlevel, bootlevel) != 0 && - rc_service_in_runlevel (service, bootlevel)) || - rc_service_in_runlevel (service, runlevel) || + rc_service_in_runlevel(service, bootlevel)) || + rc_service_in_runlevel(service, runlevel) || state & RC_SERVICE_COLDPLUGGED || state & RC_SERVICE_STARTED); } -static bool get_provided1 (const char *runlevel, struct lhead *providers, - rc_deptype_t *deptype, - const char *level, bool coldplugged, - rc_service_state_t state) +static bool get_provided1(const char *runlevel, RC_STRINGLIST *providers, + RC_DEPTYPE *deptype, + const char *level, bool coldplugged, + RC_SERVICE state) { - char *service; - int i; + RC_STRING *service; + RC_SERVICE st; bool retval = false; + bool ok; + const char *svc; + + TAILQ_FOREACH(service, deptype->services, entries) { + ok = true; + svc = service->value; + st = rc_service_state(svc); - STRLIST_FOREACH (deptype->services, service, i) - { - bool ok = true; - rc_service_state_t s = rc_service_state (service); if (level) - ok = rc_service_in_runlevel (service, level); + ok = rc_service_in_runlevel(svc, level); else if (coldplugged) - ok = (s & RC_SERVICE_COLDPLUGGED && - ! rc_service_in_runlevel (service, runlevel) && - ! rc_service_in_runlevel (service, bootlevel)); + ok = (st & RC_SERVICE_COLDPLUGGED && + ! rc_service_in_runlevel(svc, runlevel) && + ! rc_service_in_runlevel(svc, bootlevel)); if (! ok) continue; switch (state) { case RC_SERVICE_STARTED: - ok = (s & RC_SERVICE_STARTED); + ok = (st & RC_SERVICE_STARTED); break; case RC_SERVICE_INACTIVE: case RC_SERVICE_STARTING: case RC_SERVICE_STOPPING: - ok = (s & RC_SERVICE_STARTING || - s & RC_SERVICE_STOPPING || - s & RC_SERVICE_INACTIVE); + ok = (st & RC_SERVICE_STARTING || + st & RC_SERVICE_STOPPING || + st & RC_SERVICE_INACTIVE); break; default: break; @@ -264,10 +244,10 @@ static bool get_provided1 (const char *runlevel, struct lhead *providers, continue; retval = true; - rc_strlist_add (&providers->list, service); + rc_stringlist_add(providers, svc); } - return (retval); + return retval; } /* Work out if a service is provided by another service. @@ -279,50 +259,41 @@ static bool get_provided1 (const char *runlevel, struct lhead *providers, If there are any bugs in rc-depend, they will probably be here as provided dependancy can change depending on runlevel state. */ -static char **get_provided (const rc_depinfo_t *deptree, - const rc_depinfo_t *depinfo, - const char *runlevel, int options) +static RC_STRINGLIST *get_provided (const RC_DEPINFO *depinfo, + const char *runlevel, int options) { - rc_deptype_t *dt; - struct lhead providers; - char *service; - int i; + RC_DEPTYPE *dt; + RC_STRINGLIST *providers = rc_stringlist_new(); + RC_STRING *service; - if (! deptree || ! depinfo) - return (NULL); - - if (rc_service_exists (depinfo->service)) - return (NULL); - - dt = get_deptype (depinfo, "providedby"); + dt = get_deptype(depinfo, "providedby"); if (! dt) - return (NULL); + return providers; - memset (&providers, 0, sizeof (providers)); /* If we are stopping then all depends are true, regardless of state. This is especially true for net services as they could force a restart of the local dns resolver which may depend on net. */ if (options & RC_DEP_STOP) { - STRLIST_FOREACH (dt->services, service, i) - rc_strlist_add (&providers.list, service); - - return (providers.list); + TAILQ_FOREACH(service, dt->services, entries) + rc_stringlist_add(providers, service->value); + return providers; } /* If we're strict or startng, then only use what we have in our * runlevel and bootlevel. If we starting then check cold-plugged too. */ if (options & RC_DEP_STRICT || options & RC_DEP_START) { - STRLIST_FOREACH (dt->services, service, i) - if (rc_service_in_runlevel (service, runlevel) || - rc_service_in_runlevel (service, bootlevel) || + + TAILQ_FOREACH(service, dt->services, entries) + if (rc_service_in_runlevel(service->value, runlevel) || + rc_service_in_runlevel(service->value, bootlevel) || (options & RC_DEP_START && - rc_service_state (service) & RC_SERVICE_COLDPLUGGED)) - rc_strlist_add (&providers.list, service); + rc_service_state(service->value) & RC_SERVICE_COLDPLUGGED)) + rc_stringlist_add(providers, service->value); - if (providers.list) - return (providers.list); + if (TAILQ_FIRST(providers)) + return providers; } /* OK, we're not strict or there were no services in our runlevel. @@ -333,225 +304,211 @@ static char **get_provided (const rc_depinfo_t *deptree, We apply this to our runlevel, coldplugged services, then bootlevel and finally any running.*/ #define DO \ - if (providers.list && providers.list[0] && providers.list[1]) \ - { \ - rc_strlist_free (providers.list); \ - return (NULL); \ - } \ - else if (providers.list) \ - return providers.list; \ + if (TAILQ_FIRST(providers)) { \ + if (TAILQ_NEXT(TAILQ_FIRST(providers), entries)) { \ + rc_stringlist_free(providers); \ + providers = rc_stringlist_new(); \ + } \ + return providers; \ + } /* Anything in the runlevel has to come first */ - if (get_provided1 (runlevel, &providers, dt, runlevel, false, RC_SERVICE_STARTED)) + if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STARTED)) { DO } - if (get_provided1 (runlevel, &providers, dt, runlevel, false, RC_SERVICE_STARTING)) - return (providers.list); - if (get_provided1 (runlevel, &providers, dt, runlevel, false, RC_SERVICE_STOPPED)) - return (providers.list); + if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STARTING)) + return providers; + if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STOPPED)) + return providers; /* Check coldplugged services */ - if (get_provided1 (runlevel, &providers, dt, NULL, true, RC_SERVICE_STARTED)) + if (get_provided1 (runlevel, providers, dt, NULL, true, RC_SERVICE_STARTED)) { DO } - if (get_provided1 (runlevel, &providers, dt, NULL, true, RC_SERVICE_STARTING)) - return (providers.list); + if (get_provided1 (runlevel, providers, dt, NULL, true, RC_SERVICE_STARTING)) + return providers; /* Check bootlevel if we're not in it */ if (bootlevel && strcmp (runlevel, bootlevel) != 0) { - if (get_provided1 (runlevel, &providers, dt, bootlevel, false, RC_SERVICE_STARTED)) + if (get_provided1 (runlevel, providers, dt, bootlevel, false, RC_SERVICE_STARTED)) { DO } - if (get_provided1 (runlevel, &providers, dt, bootlevel, false, RC_SERVICE_STARTING)) - return (providers.list); + if (get_provided1 (runlevel, providers, dt, bootlevel, false, RC_SERVICE_STARTING)) + return providers; } /* Check coldplugged services */ - if (get_provided1 (runlevel, &providers, dt, NULL, true, RC_SERVICE_STOPPED)) + if (get_provided1 (runlevel, providers, dt, NULL, true, RC_SERVICE_STOPPED)) { DO } /* Check manually started */ - if (get_provided1 (runlevel, &providers, dt, NULL, false, RC_SERVICE_STARTED)) + if (get_provided1 (runlevel, providers, dt, NULL, false, RC_SERVICE_STARTED)) { DO } - if (get_provided1 (runlevel, &providers, dt, NULL, false, RC_SERVICE_STARTING)) - return (providers.list); + if (get_provided1 (runlevel, providers, dt, NULL, false, RC_SERVICE_STARTING)) + return providers; /* Nothing started then. OK, lets get the stopped services */ - if (get_provided1 (runlevel, &providers, dt, runlevel, false, RC_SERVICE_STOPPED)) - return (providers.list); + if (get_provided1 (runlevel, providers, dt, runlevel, false, RC_SERVICE_STOPPED)) + return providers; if (bootlevel && (strcmp (runlevel, bootlevel) != 0) - && (get_provided1 (runlevel, &providers, dt, bootlevel, false, RC_SERVICE_STOPPED))) - return (providers.list); + && (get_provided1 (runlevel, providers, dt, bootlevel, false, RC_SERVICE_STOPPED))) + return providers; /* Still nothing? OK, list all services */ - STRLIST_FOREACH (dt->services, service, i) - rc_strlist_add (&providers.list, service); + TAILQ_FOREACH(service, dt->services, entries) + rc_stringlist_add(providers, service->value); - return (providers.list); + return providers; } -static void visit_service (const rc_depinfo_t *deptree, - const char * const *types, - struct lhead *sorted, struct lhead *visited, - const rc_depinfo_t *depinfo, +static void visit_service (const RC_DEPTREE *deptree, + const RC_STRINGLIST *types, + RC_STRINGLIST *sorted, + RC_STRINGLIST *visited, + const RC_DEPINFO *depinfo, const char *runlevel, int options) { - int i, j, k; - char *lp; - const char *item; - char *service; - rc_depinfo_t *di; - rc_deptype_t *dt; - char **provides; - char *svcname; - - if (! deptree || !sorted || !visited || !depinfo) - return; + RC_STRING *type; + RC_STRING *service; + RC_DEPTYPE *dt; + RC_DEPINFO *di; + RC_STRINGLIST *provided; + RC_STRING *p; + const char *svcname; /* Check if we have already visited this service or not */ - STRLIST_FOREACH (visited->list, item, i) - if (strcmp (item, depinfo->service) == 0) + TAILQ_FOREACH(type, visited, entries) + if (strcmp(type->value, depinfo->service) == 0) return; /* Add ourselves as a visited service */ - rc_strlist_add (&visited->list, depinfo->service); + rc_stringlist_add(visited, depinfo->service); - STRLIST_FOREACH (types, item, i) + TAILQ_FOREACH(type, types, entries) { - if ((dt = get_deptype (depinfo, item))) - { - STRLIST_FOREACH (dt->services, service, j) + if (!(dt = get_deptype(depinfo, type->value))) + continue; + + TAILQ_FOREACH(service, dt->services, entries) { + if (! options & RC_DEP_TRACE || + strcmp(type->value, "iprovide") == 0) { - if (! options & RC_DEP_TRACE || strcmp (item, "iprovide") == 0) - { - rc_strlist_add (&sorted->list, service); - continue; - } + rc_stringlist_add(sorted, service->value); + continue; + } - di = get_depinfo (deptree, service); - if ((provides = get_provided (deptree, di, runlevel, options))) - { - STRLIST_FOREACH (provides, lp, k) - { - di = get_depinfo (deptree, lp); - if (di && (strcmp (item, "ineed") == 0 || - strcmp (item, "needsme") == 0 || - valid_service (runlevel, di->service))) - visit_service (deptree, types, sorted, visited, di, - runlevel, options | RC_DEP_TRACE); - } - rc_strlist_free (provides); + if (!(di = get_depinfo(deptree, service->value))) + continue; + provided = get_provided(di, runlevel, options); + + if (TAILQ_FIRST(provided)) { + TAILQ_FOREACH(p, provided, entries) { + di = get_depinfo(deptree, p->value); + if (di && + (strcmp(type->value, "ineed") == 0 || + strcmp(type->value, "needsme") == 0 || + valid_service(runlevel, di->service))) + visit_service(deptree, types, sorted, visited, di, + runlevel, options | RC_DEP_TRACE); } - else - if (di && (strcmp (item, "ineed") == 0 || - strcmp (item, "needsme") == 0 || - valid_service (runlevel, service))) - visit_service (deptree, types, sorted, visited, di, - runlevel, options | RC_DEP_TRACE); } + else if (di && + (strcmp(type->value, "ineed") == 0 || + strcmp(type->value, "needsme") == 0 || + valid_service(runlevel, service->value))) + visit_service(deptree, types, sorted, visited, di, + runlevel, options | RC_DEP_TRACE); + + rc_stringlist_free(provided); } } /* Now visit the stuff we provide for */ if (options & RC_DEP_TRACE && - (dt = get_deptype (depinfo, "iprovide"))) + (dt = get_deptype(depinfo, "iprovide"))) { - STRLIST_FOREACH (dt->services, service, i) - { - if ((di = get_depinfo (deptree, service))) - if ((provides = get_provided (deptree, di, runlevel, options))) - { - STRLIST_FOREACH (provides, lp, j) - if (strcmp (lp, depinfo->service) == 0) - { - visit_service (deptree, types, sorted, visited, di, - runlevel, options | RC_DEP_TRACE); - break; - } - rc_strlist_free (provides); + TAILQ_FOREACH(service, dt->services, entries) { + if (!(di = get_depinfo(deptree, service->value))) + continue; + + provided = get_provided(di, runlevel, options); + TAILQ_FOREACH(p, provided, entries) + if (strcmp (p->value, depinfo->service) == 0) { + //visit_service (deptree, types, sorted, visited, di, + // runlevel, options | RC_DEP_TRACE); + break; } + rc_stringlist_free(provided); } } /* We've visited everything we need, so add ourselves unless we are also the service calling us or we are provided by something */ svcname = getenv("SVCNAME"); - if (! svcname || strcmp (svcname, depinfo->service) != 0) - if (! get_deptype (depinfo, "providedby")) - rc_strlist_add (&sorted->list, depinfo->service); + if (! svcname || strcmp(svcname, depinfo->service) != 0) + if (! get_deptype(depinfo, "providedby")) + rc_stringlist_add(sorted, depinfo->service); } -char **rc_deptree_depend (const rc_depinfo_t *deptree, - const char *service, const char *type) +RC_STRINGLIST *rc_deptree_depend(const RC_DEPTREE *deptree, + const char *service, const char *type) { - rc_depinfo_t *di; - rc_deptype_t *dt; - char **svcs = NULL; - int i; - char *svc; + RC_DEPINFO *di; + RC_DEPTYPE *dt; + RC_STRINGLIST *svcs; + RC_STRING *svc; - if (! (di = get_depinfo (deptree, service)) || - ! (dt = get_deptype (di, type))) + if (!(di = get_depinfo(deptree, service)) || + ! (dt = get_deptype(di, type))) { errno = ENOENT; - return (NULL); + return NULL; } /* For consistency, we copy the array */ - STRLIST_FOREACH (dt->services, svc, i) - rc_strlist_add (&svcs, svc); + svcs = rc_stringlist_new(); + TAILQ_FOREACH(svc, dt->services, entries) + rc_stringlist_add(svcs, svc->value); - return (svcs); + return svcs; } librc_hidden_def(rc_deptree_depend) -char **rc_deptree_depends (const rc_depinfo_t *deptree, - const char *const *types, - const char *const *services, - const char *runlevel, int options) +RC_STRINGLIST *rc_deptree_depends (const RC_DEPTREE *deptree, + const RC_STRINGLIST *types, + const RC_STRINGLIST *services, + const char *runlevel, int options) { - struct lhead sorted; - struct lhead visited; - rc_depinfo_t *di; - const char *service; - int i; - - if (! deptree || ! services) - return (NULL); - - memset (&sorted, 0, sizeof (sorted)); - memset (&visited, 0, sizeof (visited)); + RC_STRINGLIST *sorted = rc_stringlist_new(); + RC_STRINGLIST *visited = rc_stringlist_new(); + RC_DEPINFO *di; + const RC_STRING *service; bootlevel = getenv ("RC_BOOTLEVEL"); if (! bootlevel) bootlevel = RC_LEVEL_BOOT; - STRLIST_FOREACH (services, service, i) - { - if (! (di = get_depinfo (deptree, service))) { + TAILQ_FOREACH(service, services, entries) { + if (! (di = get_depinfo(deptree, service->value))) { errno = ENOENT; continue; } if (types) - visit_service (deptree, types, &sorted, &visited, + visit_service (deptree, types, sorted, visited, di, runlevel, options); } - rc_strlist_free (visited.list); - return (sorted.list); + rc_stringlist_free (visited); + return sorted; } librc_hidden_def(rc_deptree_depends) - static const char * const order_types[] = { "ineed", "iuse", "iafter", NULL }; -char **rc_deptree_order (const rc_depinfo_t *deptree, const char *runlevel, - int options) +RC_STRINGLIST *rc_deptree_order(const RC_DEPTREE *deptree, + const char *runlevel, int options) { - char **list = NULL; - char **services = NULL; - bool reverse = false; - char **tmp = NULL; - - if (! runlevel) - return (NULL); + RC_STRINGLIST *list; + RC_STRINGLIST *list2; + RC_STRINGLIST *types; + RC_STRINGLIST *services; bootlevel = getenv ("RC_BOOTLEVEL"); if (! bootlevel) @@ -562,47 +519,48 @@ char **rc_deptree_order (const rc_depinfo_t *deptree, const char *runlevel, strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 || strcmp (runlevel, RC_LEVEL_REBOOT) == 0) { - list = rc_services_in_state (RC_SERVICE_STARTED); + list = rc_services_in_state(RC_SERVICE_STARTED); - tmp = rc_services_in_state (RC_SERVICE_INACTIVE); - rc_strlist_join (&list, tmp); - rc_strlist_free (tmp); + list2 = rc_services_in_state (RC_SERVICE_INACTIVE); + TAILQ_CONCAT(list, list2); + free(list2); - tmp = rc_services_in_state (RC_SERVICE_STARTING); - rc_strlist_join (&list, tmp); - rc_strlist_free (tmp); - reverse = true; + list2 = rc_services_in_state (RC_SERVICE_STARTING); + TAILQ_CONCAT(list, list2); + free(list2); } else { list = rc_services_in_runlevel (runlevel); /* Add coldplugged services */ - tmp = rc_services_in_state (RC_SERVICE_COLDPLUGGED); - rc_strlist_join (&list, tmp); - rc_strlist_free (tmp); + list2 = rc_services_in_state (RC_SERVICE_COLDPLUGGED); + TAILQ_CONCAT(list, list2); + free(list2); /* If we're not the boot runlevel then add that too */ if (strcmp (runlevel, bootlevel) != 0) { - tmp = rc_services_in_runlevel (bootlevel); - rc_strlist_join (&list, tmp); - rc_strlist_free (tmp); + list2 = rc_services_in_runlevel (bootlevel); + TAILQ_CONCAT(list, list2); + free(list2); } } /* Now we have our lists, we need to pull in any dependencies and order them */ - services = rc_deptree_depends (deptree, order_types, (const char **) list, - runlevel, - RC_DEP_STRICT | RC_DEP_TRACE | options); - rc_strlist_free (list); + types = rc_stringlist_new(); + rc_stringlist_add(types, "ineed"); + rc_stringlist_add(types, "iuse"); + rc_stringlist_add(types, "iafter"); - if (reverse) - rc_strlist_reverse (services); + services = rc_deptree_depends(deptree, types, list, runlevel, + RC_DEP_STRICT | RC_DEP_TRACE | options); + rc_stringlist_free (list); + rc_stringlist_free (types); - return (services); + return services; } librc_hidden_def(rc_deptree_order) -bool rc_newer_than (const char *source, const char *target) +bool rc_newer_than(const char *source, const char *target) { struct stat buf; time_t mtime; @@ -613,38 +571,38 @@ bool rc_newer_than (const char *source, const char *target) int serrno = errno; /* We have to exist */ - if (stat (source, &buf) != 0) - return (false); + if (stat(source, &buf) != 0) + return false; mtime = buf.st_mtime; /* Of course we are newer than targets that don't exist such as broken symlinks */ - if (stat (target, &buf) != 0) - return (true); + if (stat(target, &buf) != 0) + return true; if (mtime < buf.st_mtime) - return (false); + return false; /* If not a dir then reset errno */ - if (! (dp = opendir (target))) { + if (! (dp = opendir(target))) { errno = serrno; - return (true); + return true; } /* Check if we're newer than all the entries in the dir */ - while ((d = readdir (dp))) { + while ((d = readdir(dp))) { if (d->d_name[0] == '.') continue; - path = rc_strcatpaths (target, d->d_name, (char *) NULL); - newer = rc_newer_than (source, path); - free (path); + path = rc_strcatpaths(target, d->d_name, (char *) NULL); + newer = rc_newer_than(source, path); + free(path); if (! newer) break; } - closedir (dp); + closedir(dp); - return (newer); + return newer; } librc_hidden_def(rc_newer_than) @@ -652,12 +610,12 @@ typedef struct deppair { const char *depend; const char *addto; -} deppair_t; +} DEPPAIR; -static const deppair_t deppairs[] = { - { "ineed", "needsme" }, - { "iuse", "usesme" }, - { "iafter", "ibefore" }, +static const DEPPAIR deppairs[] = { + { "ineed", "needsme" }, + { "iuse", "usesme" }, + { "iafter", "ibefore" }, { "ibefore", "iafter" }, { "iprovide", "providedby" }, { NULL, NULL } @@ -679,168 +637,151 @@ static const char *const depdirs[] = NULL }; -bool rc_deptree_update_needed (void) +bool rc_deptree_update_needed(void) { bool newer = false; - char **config; - char *service; + RC_STRINGLIST *config; + RC_STRING *s; int i; /* Create base directories if needed */ for (i = 0; depdirs[i]; i++) - if (mkdir (depdirs[i], 0755) != 0 && errno != EEXIST) - fprintf (stderr, "mkdir `%s': %s\n", depdirs[i], strerror (errno)); + if (mkdir(depdirs[i], 0755) != 0 && errno != EEXIST) + fprintf(stderr, "mkdir `%s': %s\n", depdirs[i], strerror (errno)); /* Quick test to see if anything we use has changed and we have * data in our deptree */ - if (! existss (RC_DEPTREE) || - ! rc_newer_than (RC_DEPTREE, RC_INITDIR) || - ! rc_newer_than (RC_DEPTREE, RC_CONFDIR) || + if (! existss(RC_DEPTREE_CACHE) || + ! rc_newer_than(RC_DEPTREE_CACHE, RC_INITDIR) || + ! rc_newer_than(RC_DEPTREE_CACHE, RC_CONFDIR) || #ifdef RC_PKG_INITDIR - ! rc_newer_than (RC_DEPTREE, RC_PKG_INITDIR) || + ! rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_INITDIR) || #endif #ifdef RC_PKG_CONFDIR - ! rc_newer_than (RC_DEPTREE, RC_PKG_CONFDIR) || + ! rc_newer_than(RC_DEPTREE_CACHE, RC_PKG_CONFDIR) || #endif #ifdef RC_LOCAL_INITDIR - ! rc_newer_than (RC_DEPTREE, RC_LOCAL_INITDIR) || + ! rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_INITDIR) || #endif #ifdef RC_LOCAL_CONFDIR - ! rc_newer_than (RC_DEPTREE, RC_LOCAL_CONFDIR) || + ! rc_newer_than(RC_DEPTREE_CACHE, RC_LOCAL_CONFDIR) || #endif - ! rc_newer_than (RC_DEPTREE, "/etc/rc.conf")) - return (true); + ! rc_newer_than(RC_DEPTREE_CACHE, "/etc/rc.conf")) + return true; /* Some init scripts dependencies change depending on config files * outside of baselayout, like syslog-ng, so we check those too. */ config = rc_config_list (RC_DEPCONFIG); - STRLIST_FOREACH (config, service, i) { - if (! rc_newer_than (RC_DEPTREE, service)) { + TAILQ_FOREACH(s, config, entries) { + if (! rc_newer_than(RC_DEPTREE_CACHE, s->value)) { newer = true; break; } } - rc_strlist_free (config); + rc_stringlist_free(config); - return (newer); + return newer; } librc_hidden_def(rc_deptree_update_needed) - /* This is a 5 phase operation - Phase 1 is a shell script which loads each init script and config in turn - and echos their dependency info to stdout - Phase 2 takes that and populates a depinfo object with that data - Phase 3 adds any provided services to the depinfo object - Phase 4 scans that depinfo object and puts in backlinks - Phase 5 saves the depinfo object to disk - */ -bool rc_deptree_update (void) +/* This is a 5 phase operation + Phase 1 is a shell script which loads each init script and config in turn + and echos their dependency info to stdout + Phase 2 takes that and populates a depinfo object with that data + Phase 3 adds any provided services to the depinfo object + Phase 4 scans that depinfo object and puts in backlinks + Phase 5 saves the depinfo object to disk + */ +bool rc_deptree_update(void) { + FILE *fp; + RC_DEPTREE *deptree; + RC_DEPTREE *providers; + RC_DEPINFO *depinfo = NULL; + RC_DEPINFO *depinfo_np; + RC_DEPINFO *di; + RC_DEPTYPE *deptype = NULL; + RC_DEPTYPE *dt; + RC_DEPTYPE *dt_np; + RC_STRINGLIST *config; + RC_STRING *s; + RC_STRING *s2; + RC_DEPTYPE *provide; + char *line; + char *depend; char *depends; char *service; char *type; - char *depend; - char **config = NULL; - int retval = true; - FILE *fp; - rc_depinfo_t *deptree = NULL; - rc_depinfo_t *depinfo; - rc_depinfo_t *di; - rc_depinfo_t *last_depinfo = NULL; - rc_deptype_t *deptype = NULL; - rc_deptype_t *dt; - rc_deptype_t *last_deptype = NULL; - char **removedp = NULL; - char *line; - size_t len; size_t i; - size_t j; size_t k; - bool already_added; - const char *sys = rc_sys (); + size_t len; + int retval = true; + const char *sys = rc_sys(); + char *nosys; /* Some init scripts need RC_LIBDIR to source stuff Ideally we should be setting our full env instead */ - if (! getenv ("RC_LIBDIR")) - setenv ("RC_LIBDIR", RC_LIBDIR, 0); + if (! getenv("RC_LIBDIR")) + setenv("RC_LIBDIR", RC_LIBDIR, 0); /* Phase 1 - source all init scripts and print dependencies */ - if (! (fp = popen (GENDEP, "r"))) - return (false); + if (! (fp = popen(GENDEP, "r"))) + return false; + + deptree = xmalloc(sizeof(*deptree)); + STAILQ_INIT(deptree); - while ((line = rc_getline (fp))) + config = rc_stringlist_new(); + + while ((line = rc_getline(fp))) { depends = line; - service = strsep (&depends, " "); + service = strsep(&depends, " "); if (! service || ! *service) goto next; - type = strsep (&depends, " "); + type = strsep(&depends, " "); - for (depinfo = deptree; depinfo; depinfo = depinfo->next) - { - last_depinfo = depinfo; - if (depinfo->service && strcmp (depinfo->service, service) == 0) - break; - } - - if (! depinfo) - { - if (! last_depinfo) - deptree = depinfo = xzalloc (sizeof (*depinfo)); - else if (! last_depinfo->service) - depinfo = last_depinfo; - else - { - last_depinfo->next = xzalloc (sizeof (*last_depinfo->next)); - depinfo = last_depinfo->next; + if (! depinfo || strcmp(depinfo->service, service) != 0) { + deptype = NULL; + depinfo = get_depinfo(deptree, service); + if (! depinfo) { + depinfo = xmalloc(sizeof(*depinfo)); + STAILQ_INIT(&depinfo->depends); + depinfo->service = xstrdup(service); + STAILQ_INSERT_TAIL(deptree, depinfo, entries); } - depinfo->service = xstrdup (service); } - + /* We may not have any depends */ if (! type || ! depends) goto next; /* Get the type */ - if (strcmp (type, "config") != 0) { - last_deptype = NULL; - for (deptype = depinfo->depends; deptype; deptype = deptype->next) - { - last_deptype = deptype; - if (strcmp (deptype->type, type) == 0) - break; - } - - if (! deptype) - { - if (! last_deptype) - { - depinfo->depends = xzalloc (sizeof (*depinfo->depends)); - deptype = depinfo->depends; - } - else - { - last_deptype->next = xzalloc (sizeof (*last_deptype->next)); - deptype = last_deptype->next; - } - deptype->type = xstrdup (type); + if (strcmp(type, "config") != 0) { + if (! deptype || strcmp (deptype->type, type) != 0) + deptype = get_deptype(depinfo, type); + if (! deptype) { + deptype = xmalloc(sizeof(*deptype)); + deptype->type = xstrdup(type); + deptype->services = rc_stringlist_new(); + STAILQ_INSERT_TAIL(&depinfo->depends, deptype, entries); } } /* Now add each depend to our type. We do this individually so we handle multiple spaces gracefully */ - while ((depend = strsep (&depends, " "))) + while ((depend = strsep(&depends, " "))) { if (depend[0] == 0) continue; - if (strcmp (type, "config") == 0) { - rc_strlist_addsort (&config, depend); + if (strcmp(type, "config") == 0) { + rc_stringlist_add(config, depend); continue; } /* .sh files are not init scripts */ - len = strlen (depend); + len = strlen(depend); if (len > 2 && depend[len - 3] == '.' && depend[len - 2] == 's' && @@ -849,171 +790,114 @@ bool rc_deptree_update (void) /* Remove our dependency if instructed */ if (depend[0] == '!') { - rc_strlist_delete (&deptype->services, depend + 1); + rc_stringlist_delete(deptype->services, depend + 1); continue; } - rc_strlist_addsort (&deptype->services, depend); + rc_stringlist_add(deptype->services, depend); /* We need to allow `after *; before local;` to work. * Conversely, we need to allow 'before *; after modules' also */ /* If we're before something, remove us from the after list */ - if (strcmp (type, "ibefore") == 0) { - if ((dt = get_deptype (depinfo, "iafter"))) - rc_strlist_delete (&dt->services, depend); + if (strcmp(type, "ibefore") == 0) { + if ((dt = get_deptype(depinfo, "iafter"))) + rc_stringlist_delete(dt->services, depend); } /* If we're after something, remove us from the before list */ if (strcmp (type, "iafter") == 0 || strcmp (type, "ineed") == 0 || strcmp (type, "iuse") == 0) { - if ((dt = get_deptype (depinfo, "ibefore"))) - rc_strlist_delete (&dt->services, depend); + if ((dt = get_deptype(depinfo, "ibefore"))) + rc_stringlist_delete(dt->services, depend); } } next: - free (line); + free(line); } - pclose (fp); + pclose(fp); /* Phase 2 - if we're a special system, remove services that don't * work for them. This doesn't stop them from being run directly. */ if (sys) { - char *nosys; - - len = strlen (sys); - nosys = xmalloc (len + 3); + len = strlen(sys); + nosys = xmalloc(len + 3); nosys[0] = 'n'; nosys[1] = 'o'; for (i = 0; i < len; i++) - nosys[i + 2] = (char) tolower ((int) sys[i]); + nosys[i + 2] = (char) tolower((int) sys[i]); nosys[i + 2] = '\0'; - last_depinfo = NULL; - depinfo = deptree; - while (depinfo) { - bool removed = false; - if ((deptype = get_deptype (depinfo, "keyword"))) { - STRLIST_FOREACH (deptype->services, service, i) - if (strcmp (service, nosys) == 0) { - if (last_depinfo) - last_depinfo->next = depinfo->next; - else - deptree = depinfo->next; - removed = true; - break; + STAILQ_FOREACH_SAFE(depinfo, deptree, entries, depinfo_np) + if ((deptype = get_deptype(depinfo, "keyword"))) + TAILQ_FOREACH(s, deptype->services, entries) + if (strcmp (s->value, nosys) == 0) { + provide = get_deptype(depinfo, "iprovide"); + STAILQ_REMOVE(deptree, depinfo, rc_depinfo, entries); + STAILQ_FOREACH(di, deptree, entries) { + STAILQ_FOREACH_SAFE(dt, &di->depends, entries, dt_np) { + rc_stringlist_delete(dt->services, depinfo->service); + if (provide) + TAILQ_FOREACH(s2, provide->services, entries) + rc_stringlist_delete(dt->services, s2->value); + if (! TAILQ_FIRST(dt->services)) { + STAILQ_REMOVE(&di->depends, dt, rc_deptype, entries); + free(dt->type); + free(dt->services); + free(dt); + } + } + } } - } - if (removed) { - dt = get_deptype (depinfo, "iprovide"); - if (dt) - STRLIST_FOREACH (dt->services, service, i) - rc_strlist_addu (&removedp, service); - for (di = deptree; di; di = di->next) { - for (dt = di->depends; dt; dt = dt->next) - rc_strlist_delete (&dt->services, depinfo->service); - } - di = depinfo->next; - depinfo->next = NULL; - rc_deptree_free (depinfo); - depinfo = di; - } else { - last_depinfo = depinfo; - depinfo = depinfo->next; - } - } - free (nosys); } - /* Phase 3 - add our providors to the tree */ - for (depinfo = deptree; depinfo; depinfo = depinfo->next) - { - if ((deptype = get_deptype (depinfo, "iprovide"))) - STRLIST_FOREACH (deptype->services, service, i) - { - for (di = deptree; di; di = di->next) - { - last_depinfo = di; - if (strcmp (di->service, service) == 0) + /* Phase 3 - add our providers to the tree */ + providers = xmalloc(sizeof(*providers)); + STAILQ_INIT(providers); + STAILQ_FOREACH(depinfo, deptree, entries) + if ((deptype = get_deptype(depinfo, "iprovide"))) + TAILQ_FOREACH(s, deptype->services, entries) { + STAILQ_FOREACH(di, providers, entries) + if (strcmp(di->service, s->value) == 0) break; - } - if (! di) - { - last_depinfo->next = xzalloc (sizeof (*last_depinfo->next)); - di = last_depinfo->next; - di->service = xstrdup (service); + if (! di) { + di = xmalloc(sizeof(*di)); + STAILQ_INIT(&di->depends); + di->service = xstrdup(s->value); + STAILQ_INSERT_TAIL(providers, di, entries); } } - } + STAILQ_CONCAT(deptree, providers); + free(providers); /* Phase 4 - backreference our depends */ - for (depinfo = deptree; depinfo; depinfo = depinfo->next) - { - for (i = 0; deppairs[i].depend; i++) - { - deptype = get_deptype (depinfo, deppairs[i].depend); + STAILQ_FOREACH(depinfo, deptree, entries) + for (i = 0; deppairs[i].depend; i++) { + deptype = get_deptype(depinfo, deppairs[i].depend); if (! deptype) continue; - - STRLIST_FOREACH (deptype->services, service, j) - { - di = get_depinfo (deptree, service); - if (! di) - { + TAILQ_FOREACH(s, deptype->services, entries) { + di = get_depinfo(deptree, s->value); + if (! di) { if (strcmp (deptype->type, "ineed") == 0) - { - bool removed = false; - STRLIST_FOREACH (removedp, line, k) { - if (strcmp (line, service) == 0) { - removed = true; - break; - } - } - if (! removed) - fprintf (stderr, - "Service `%s' needs non existant service `%s'\n", - depinfo->service, service); - } + fprintf (stderr, + "Service `%s' needs non" + " existant service `%s'\n", + depinfo->service, s->value); continue; } - /* Add our deptype now */ - last_deptype = NULL; - for (dt = di->depends; dt; dt = dt->next) - { - last_deptype = dt; - if (strcmp (dt->type, deppairs[i].addto) == 0) - break; + dt = get_deptype(di, deppairs[i].addto); + if (! dt) { + dt = xmalloc(sizeof(*dt)); + dt->type = xstrdup(deppairs[i].addto); + dt->services = rc_stringlist_new(); + STAILQ_INSERT_TAIL(&di->depends, dt, entries); } - if (! dt) - { - if (! last_deptype) - { - di->depends = xzalloc (sizeof (*di->depends)); - dt = di->depends; - } - else - { - last_deptype->next = xzalloc (sizeof (*last_deptype->next)); - dt = last_deptype->next; - } - dt->type = xstrdup (deppairs[i].addto); - } - - already_added = false; - STRLIST_FOREACH (dt->services, service, k) - if (strcmp (service, depinfo->service) == 0) - { - already_added = true; - break; - } - - if (! already_added) - rc_strlist_addsort (&dt->services, depinfo->service); + rc_stringlist_add(dt->services, depinfo->service); } } - } /* Phase 5 - save to disk Now that we're purely in C, do we need to keep a shell parseable file? @@ -1021,49 +905,47 @@ next: This works and should be entirely shell parseable provided that depend names don't have any non shell variable characters in */ - if ((fp = fopen (RC_DEPTREE, "w"))) { + if ((fp = fopen (RC_DEPTREE_CACHE, "w"))) { i = 0; - for (depinfo = deptree; depinfo; depinfo = depinfo->next) - { - fprintf (fp, "depinfo_%zu_service='%s'\n", - i, depinfo->service); - for (deptype = depinfo->depends; deptype; deptype = deptype->next) - { + STAILQ_FOREACH(depinfo, deptree, entries) { + fprintf(fp, "depinfo_%zu_service='%s'\n", + i, depinfo->service); + STAILQ_FOREACH(deptype, &depinfo->depends, entries) { k = 0; - STRLIST_FOREACH (deptype->services, service, j) - { - fprintf (fp, - "depinfo_%zu_%s_%zu='%s'\n", - i, - deptype->type, - k, service); + TAILQ_FOREACH(s, deptype->services, entries) { + fprintf(fp, + "depinfo_%zu_%s_%zu='%s'\n", + i, deptype->type, k, s->value); k++; } } i++; } - fclose (fp); + fclose(fp); } else { - fprintf (stderr, "fopen `%s': %s\n", RC_DEPTREE, strerror (errno)); + fprintf(stderr, "fopen `%s': %s\n", + RC_DEPTREE_CACHE, strerror(errno)); retval = false; } /* Save our external config files to disk */ - if (config) { - if ((fp = fopen (RC_DEPCONFIG, "w"))) { - STRLIST_FOREACH (config, service, i) - fprintf (fp, "%s\n", service); - fclose (fp); + if (TAILQ_FIRST(config)) { + if ((fp = fopen(RC_DEPCONFIG, "w"))) { + TAILQ_FOREACH(s, config, entries) + fprintf (fp, "%s\n", s->value); + fclose(fp); } else { - fprintf (stderr, "fopen `%s': %s\n", RC_DEPCONFIG, strerror (errno)); + fprintf(stderr, "fopen `%s': %s\n", + RC_DEPCONFIG, strerror(errno)); retval = false; } - rc_strlist_free (config); + rc_stringlist_free (config); + } else { + unlink(RC_DEPCONFIG); } - rc_strlist_free (removedp); - rc_deptree_free (deptree); + rc_deptree_free(deptree); - return (retval); + return retval; } librc_hidden_def(rc_deptree_update) diff --git a/src/librc/librc-depend.h b/src/librc/librc-depend.h deleted file mode 100644 index 737920e3..00000000 --- a/src/librc/librc-depend.h +++ /dev/null @@ -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 diff --git a/src/librc/librc-misc.c b/src/librc/librc-misc.c index f08a7622..fac78e2a 100644 --- a/src/librc/librc-misc.c +++ b/src/librc/librc-misc.c @@ -35,14 +35,14 @@ bool rc_yesno (const char *value) { if (! value) { errno = ENOENT; - return (false); + return false; } if (strcasecmp (value, "yes") == 0 || strcasecmp (value, "y") == 0 || strcasecmp (value, "true") == 0 || strcasecmp (value, "1") == 0) - return (true); + return true; if (strcasecmp (value, "no") != 0 && strcasecmp (value, "n") != 0 && @@ -50,7 +50,7 @@ bool rc_yesno (const char *value) strcasecmp (value, "0") != 0) errno = EINVAL; - return (false); + return false; } librc_hidden_def(rc_yesno) @@ -64,7 +64,7 @@ char *rc_strcatpaths (const char *path1, const char *paths, ...) char *pathp; if (! path1 || ! paths) - return (NULL); + return NULL; length = strlen (path1) + strlen (paths) + 1; if (*paths != '/') @@ -101,7 +101,7 @@ char *rc_strcatpaths (const char *path1, const char *paths, ...) *pathp++ = 0; - return (path); + return path; } librc_hidden_def(rc_strcatpaths) @@ -113,7 +113,7 @@ char *rc_getline (FILE *fp) size_t last = 0; if (feof (fp)) - return (NULL); + return NULL; do { len += BUFSIZ; @@ -128,74 +128,78 @@ char *rc_getline (FILE *fp) if (*line && line[--last] == '\n') line[last] = '\0'; - return (line); + return line; } librc_hidden_def(rc_getline) -char **rc_config_list (const char *file) +RC_STRINGLIST *rc_config_list(const char *file) { FILE *fp; char *buffer; char *p; char *token; - char **list = NULL; + RC_STRINGLIST *list; - if (! (fp = fopen (file, "r"))) - return (NULL); + if (!(fp = fopen(file, "r"))) + return NULL; - while ((p = buffer = rc_getline (fp))) { + list = rc_stringlist_new(); + + while ((p = buffer = rc_getline(fp))) { /* Strip leading spaces/tabs */ while ((*p == ' ') || (*p == '\t')) p++; /* Get entry - we do not want comments */ - token = strsep (&p, "#"); - if (token && (strlen (token) > 1)) { + token = strsep(&p, "#"); + if (token && (strlen(token) > 1)) { /* If not variable assignment then skip */ - if (strchr (token, '=')) { + if (strchr(token, '=')) { /* Stip the newline if present */ - if (token[strlen (token) - 1] == '\n') - token[strlen (token) - 1] = 0; + if (token[strlen(token) - 1] == '\n') + 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) -char **rc_config_load (const char *file) +RC_STRINGLIST *rc_config_load(const char *file) { - char **list = NULL; - char **config = NULL; + RC_STRINGLIST *list = NULL; + RC_STRINGLIST *config = NULL; char *token; - char *line; - char *linep; - char *linetok; + RC_STRING *line; + RC_STRING *cline; size_t i = 0; - int j; bool replaced; char *entry; char *newline; + char *p; - list = rc_config_list (file); - STRLIST_FOREACH (list, line, j) { + config = rc_stringlist_new(); + + list = rc_config_list(file); + TAILQ_FOREACH(line, list, entries) { /* Get entry */ - if (! (token = strsep (&line, "="))) + p = line->value; + if (! (token = strsep(&p, "="))) continue; entry = xstrdup (token); /* Preserve shell coloring */ - if (*line == '$') - token = line; + if (*p == '$') + token = line->value; else do { /* Bash variables are usually quoted */ - token = strsep (&line, "\"\'"); + token = strsep(&p, "\"\'"); } while (token && *token == '\0'); /* Drop a newline if that's all we have */ @@ -205,57 +209,54 @@ char **rc_config_load (const char *file) token[i] = 0; i = strlen (entry) + strlen (token) + 2; - newline = xmalloc (sizeof (char) * i); - snprintf (newline, i, "%s=%s", entry, token); + newline = xmalloc(sizeof(char) * i); + snprintf(newline, i, "%s=%s", entry, token); } else { i = strlen (entry) + 2; - newline = xmalloc (sizeof (char) * i); - snprintf (newline, i, "%s=", entry); + newline = xmalloc(sizeof(char) * i); + snprintf(newline, i, "%s=", entry); } replaced = false; /* In shells the last item takes precedence, so we need to remove any prior values we may already have */ - STRLIST_FOREACH (config, line, i) { - char *tmp = xstrdup (line); - linep = tmp; - linetok = strsep (&linep, "="); - if (strcmp (linetok, entry) == 0) { + TAILQ_FOREACH(cline, config, entries) { + p = strchr(cline->value, '='); + if (p && strncmp(entry, cline->value, + (size_t) (p - cline->value)) == 0) + { /* We have a match now - to save time we directly replace it */ - free (config[i - 1]); - config[i - 1] = newline; + free(cline->value); + cline->value = newline; replaced = true; - free (tmp); break; } - free (tmp); } if (! replaced) { - rc_strlist_addsort (&config, newline); - free (newline); + rc_stringlist_add(config, 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) -char *rc_config_value (const char *const *list, const char *entry) +char *rc_config_value(RC_STRINGLIST *list, const char *entry) { - const char *line; - int i; + RC_STRING *line; char *p; - STRLIST_FOREACH (list, line, i) { - p = strchr (line, '='); - if (p && strncmp (entry, line, (size_t) (p - line)) == 0) - return (p += 1); + TAILQ_FOREACH(line, list, entries) { + p = strchr(line->value, '='); + if (p && + strncmp(entry, line->value, (size_t)(p - line->value)) == 0) + return p += 1; } - return (NULL); + return NULL; } librc_hidden_def(rc_config_value) - diff --git a/src/librc/librc-strlist.c b/src/librc/librc-strlist.c deleted file mode 100644 index 9b622695..00000000 --- a/src/librc/librc-strlist.c +++ /dev/null @@ -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) diff --git a/src/librc/librc.c b/src/librc/librc.c index 7344e375..301a388a 100644 --- a/src/librc/librc.c +++ b/src/librc/librc.c @@ -47,7 +47,7 @@ const char librc_copyright[] = "Copyright (c) 2007-2008 Roy Marples"; FILE *rc_environ_fd = NULL; typedef struct rc_service_state_name { - rc_service_state_t state; + RC_SERVICE state; const char *name; } rc_service_state_name_t; @@ -68,49 +68,53 @@ static const rc_service_state_name_t rc_service_state_names[] = { #define LS_INITD 0x01 #define LS_DIR 0x02 -static char **ls_dir (const char *dir, int options) +static RC_STRINGLIST *ls_dir(const char *dir, int options) { DIR *dp; struct dirent *d; - char **list = NULL; + RC_STRINGLIST *list; struct stat buf; + size_t l; + char *file; + int r; - if ((dp = opendir (dir)) == NULL) - return (NULL); + if ((dp = opendir(dir)) == NULL) + return NULL; - while (((d = readdir (dp)) != NULL)) { + list = rc_stringlist_new(); + while (((d = readdir(dp)) != NULL)) { if (d->d_name[0] != '.') { if (options & LS_INITD) { - int l = strlen (d->d_name); - /* Check that our file really exists. * This is important as a service maybe in a runlevel, but * could also have been removed. */ - char *file = rc_strcatpaths (dir, d->d_name, NULL); - int ok = stat (file, &buf); - free (file); - if (ok != 0) + file = rc_strcatpaths(dir, d->d_name, NULL); + r = stat(file, &buf); + free(file); + if (r != 0) continue; /* .sh files are not init scripts */ + l = strlen(d->d_name); if (l > 2 && d->d_name[l - 3] == '.' && d->d_name[l - 2] == 's' && d->d_name[l - 1] == 'h') continue; } if (options & LS_DIR) { - if (stat (d->d_name, &buf) == 0 && ! S_ISDIR (buf.st_mode)) + if (stat(d->d_name, &buf) == 0 && + ! S_ISDIR(buf.st_mode)) continue; } - rc_strlist_addsort (&list, d->d_name); + rc_stringlist_add(list, d->d_name); } } - closedir (dp); + closedir(dp); - return (list); + return list; } -static bool rm_dir (const char *pathname, bool top) +static bool rm_dir(const char *pathname, bool top) { DIR *dp; struct dirent *d; @@ -118,49 +122,49 @@ static bool rm_dir (const char *pathname, bool top) struct stat s; bool retval = true; - if ((dp = opendir (pathname)) == NULL) - return (false); + if ((dp = opendir(pathname)) == NULL) + return false; errno = 0; - while (((d = readdir (dp)) != NULL) && errno == 0) { - if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0) { - free (tmp); - tmp = rc_strcatpaths (pathname, d->d_name, (char *) NULL); + while (((d = readdir(dp)) != NULL) && errno == 0) { + if (strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0) { + free(tmp); + tmp = rc_strcatpaths(pathname, d->d_name, (char *) NULL); - if (stat (tmp, &s) != 0) { + if (stat(tmp, &s) != 0) { retval = false; break; } - if (S_ISDIR (s.st_mode)) { - if (! rm_dir (tmp, true)) + if (S_ISDIR(s.st_mode)) { + if (! rm_dir(tmp, true)) { retval = false; break; } } else { - if (unlink (tmp)) { + if (unlink(tmp)) { retval = false; break; } } } } - closedir (dp); - free (tmp); + closedir(dp); + free(tmp); if (! retval) - return (false); + return false; - if (top && rmdir (pathname) != 0) - return (false); + if (top && rmdir(pathname) != 0) + return false; - return (true); + return true; } /* Other systems may need this at some point, but for now it's Linux only */ #ifdef __linux__ -static bool file_regex (const char *file, const char *regex) +static bool file_regex(const char *file, const char *regex) { FILE *fp; char *line; @@ -168,153 +172,153 @@ static bool file_regex (const char *file, const char *regex) bool retval = false; int result; - if (! (fp = fopen (file, "r"))) - return (false); + if (! (fp = fopen(file, "r"))) + return false; - if ((result = regcomp (&re, regex, REG_EXTENDED | REG_NOSUB)) != 0) { - fclose (fp); - line = xmalloc (sizeof (char) * BUFSIZ); - regerror (result, &re, line, BUFSIZ); - fprintf (stderr, "file_regex: %s", line); - free (line); - return (false); + if ((result = regcomp(&re, regex, REG_EXTENDED | REG_NOSUB)) != 0) { + fclose(fp); + line = xmalloc(sizeof (char) * BUFSIZ); + regerror(result, &re, line, BUFSIZ); + fprintf(stderr, "file_regex: %s", line); + free(line); + return false; } - while ((line = rc_getline (fp))) { - if (regexec (&re, line, 0, NULL, 0) == 0) + while ((line = rc_getline(fp))) { + if (regexec(&re, line, 0, NULL, 0) == 0) retval = true; - free (line); + free(line); if (retval) break; } - fclose (fp); - regfree (&re); + fclose(fp); + regfree(&re); - return (retval); + return retval; } #endif -const char *rc_sys (void) +const char *rc_sys(void) { #ifdef PREFIX - return (RC_SYS_PREFIX); + return RC_SYS_PREFIX; #else #ifdef __FreeBSD__ int jailed = 0; - size_t len = sizeof (jailed); + size_t len = sizeof(jailed); - if (sysctlbyname ("security.jail.jailed", &jailed, &len, NULL, 0) == 0) + if (sysctlbyname("security.jail.jailed", &jailed, &len, NULL, 0) == 0) if (jailed == 1) - return (RC_SYS_JAIL); + return RC_SYS_JAIL; #endif #ifdef __linux__ - if (exists ("/proc/xen")) { - if (file_regex ("/proc/xen/capabilities", "control_d")) - return (RC_SYS_XEN0); - return (RC_SYS_XENU); - } else if (file_regex ("/proc/cpuinfo", "UML")) - return (RC_SYS_UML); - else if (file_regex ("/proc/self/status", - "(s_context|VxID):[[:space:]]*[1-9]")) - return (RC_SYS_VSERVER); - else if (file_regex ("/proc/self/status", - "envID:[[:space:]]*[1-9]")) - return (RC_SYS_OPENVZ); + if (exists("/proc/xen")) { + if (file_regex("/proc/xen/capabilities", "control_d")) + return RC_SYS_XEN0; + return RC_SYS_XENU; + } else if (file_regex("/proc/cpuinfo", "UML")) + return RC_SYS_UML; + else if (file_regex("/proc/self/status", + "(s_context|VxID):[[:space:]]*[1-9]")) + return RC_SYS_VSERVER; + else if (file_regex("/proc/self/status", + "envID:[[:space:]]*[1-9]")) + return RC_SYS_OPENVZ; #endif - return (NULL); + return NULL; #endif /* PREFIX */ } -static const char *rc_parse_service_state (rc_service_state_t state) +static const char *rc_parse_service_state(RC_SERVICE state) { int i; for (i = 0; rc_service_state_names[i].name; i++) { if (rc_service_state_names[i].state == state) - return (rc_service_state_names[i].name); + return rc_service_state_names[i].name; } - return (NULL); + return NULL; } -bool rc_runlevel_starting (void) +bool rc_runlevel_starting(void) { - return (exists (RC_STARTING)); + return exists(RC_STARTING); } librc_hidden_def(rc_runlevel_starting) -bool rc_runlevel_stopping (void) +bool rc_runlevel_stopping(void) { - return (exists (RC_STOPPING)); + return exists(RC_STOPPING); } librc_hidden_def(rc_runlevel_stopping) -char **rc_runlevel_list (void) +RC_STRINGLIST *rc_runlevel_list(void) { - return (ls_dir (RC_RUNLEVELDIR, LS_DIR)); + return ls_dir(RC_RUNLEVELDIR, LS_DIR); } librc_hidden_def(rc_runlevel_list) -char *rc_runlevel_get (void) +char *rc_runlevel_get(void) { FILE *fp; char *runlevel = NULL; - if ((fp = fopen (SOFTLEVEL, "r"))) { - runlevel = xmalloc (sizeof (char) * PATH_MAX); - if (fgets (runlevel, PATH_MAX, fp)) { - int i = strlen (runlevel) - 1; + if ((fp = fopen(SOFTLEVEL, "r"))) { + runlevel = xmalloc(sizeof(char) * PATH_MAX); + if (fgets(runlevel, PATH_MAX, fp)) { + int i = strlen(runlevel) - 1; if (runlevel[i] == '\n') runlevel[i] = 0; } else *runlevel = '\0'; - fclose (fp); + fclose(fp); } if (! runlevel || ! *runlevel) { - free (runlevel); - runlevel = xstrdup (RC_LEVEL_SYSINIT); + free(runlevel); + runlevel = xstrdup(RC_LEVEL_SYSINIT); } - return (runlevel); + return runlevel; } librc_hidden_def(rc_runlevel_get) -bool rc_runlevel_set (const char *runlevel) +bool rc_runlevel_set(const char *runlevel) { - FILE *fp = fopen (SOFTLEVEL, "w"); + FILE *fp = fopen(SOFTLEVEL, "w"); if (! fp) - return (false); - fprintf (fp, "%s", runlevel); - fclose (fp); - return (true); + return false; + fprintf(fp, "%s", runlevel); + fclose(fp); + return true; } librc_hidden_def(rc_runlevel_set) -bool rc_runlevel_exists (const char *runlevel) +bool rc_runlevel_exists(const char *runlevel) { char *path; struct stat buf; bool retval = false; if (! runlevel) - return (false); + return false; - path = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL); - if (stat (path, &buf) == 0 && S_ISDIR (buf.st_mode)) + path = rc_strcatpaths(RC_RUNLEVELDIR, runlevel, (char *) NULL); + if (stat(path, &buf) == 0 && S_ISDIR(buf.st_mode)) retval = true; - free (path); - return (retval); + free(path); + return retval; } librc_hidden_def(rc_runlevel_exists) - /* Resolve a service name to it's full path */ -char *rc_service_resolve (const char *service) +/* Resolve a service name to it's full path */ +char *rc_service_resolve(const char *service) { char buffer[PATH_MAX]; char *file; @@ -322,53 +326,53 @@ char *rc_service_resolve (const char *service) struct stat buf; if (! service) - return (NULL); + return NULL; if (service[0] == '/') - return (xstrdup (service)); + return xstrdup(service); /* First check started services */ - file = rc_strcatpaths (RC_SVCDIR, "started", service, (char *) NULL); - if (lstat (file, &buf) || ! S_ISLNK (buf.st_mode)) { - free (file); - file = rc_strcatpaths (RC_SVCDIR, "inactive", service, (char *) NULL); - if (lstat (file, &buf) || ! S_ISLNK (buf.st_mode)) { - free (file); + file = rc_strcatpaths(RC_SVCDIR, "started", service, (char *) NULL); + if (lstat(file, &buf) || ! S_ISLNK(buf.st_mode)) { + free(file); + file = rc_strcatpaths(RC_SVCDIR, "inactive", service, (char *) NULL); + if (lstat(file, &buf) || ! S_ISLNK(buf.st_mode)) { + free(file); file = NULL; } } - memset (buffer, 0, sizeof (buffer)); + memset(buffer, 0, sizeof(buffer)); /* Nope, so lets see if the user has written it */ #ifdef RC_LOCAL_INITDIR - snprintf (buffer, sizeof (buffer), RC_LOCAL_INITDIR "/%s", service); - if (stat (buffer, &buf) == 0) - return (xstrdup (buffer)); + snprintf(buffer, sizeof(buffer), RC_LOCAL_INITDIR "/%s", service); + if (stat(buffer, &buf) == 0) + return xstrdup(buffer); #endif if (file) { - r = readlink (file, buffer, sizeof (buffer)); - free (file); + r = readlink(file, buffer, sizeof(buffer)); + free(file); if (r > 0) - return (xstrdup (buffer)); + return xstrdup(buffer); } - snprintf (buffer, sizeof (buffer), RC_INITDIR "/%s", service); + snprintf(buffer, sizeof(buffer), RC_INITDIR "/%s", service); /* So we don't exist in /etc/init.d - check RC_PKG_INITDIR */ #ifdef RC_PKG_INITDIR - if (stat (buffer, &buf) != 0) { - snprintf (buffer, sizeof (buffer), RC_PKG_INITDIR "/%s", service); - if (stat (buffer, &buf) != 0) - return (NULL); + if (stat(buffer, &buf) != 0) { + snprintf(buffer, sizeof(buffer), RC_PKG_INITDIR "/%s", service); + if (stat(buffer, &buf) != 0) + return NULL; } #endif - return (xstrdup (buffer)); + return xstrdup(buffer); } librc_hidden_def(rc_service_resolve) -bool rc_service_exists (const char *service) +bool rc_service_exists(const char *service) { char *file; bool retval = false; @@ -376,59 +380,62 @@ bool rc_service_exists (const char *service) struct stat buf; if (! service) - return (false); + return false; - len = strlen (service); + len = strlen(service); /* .sh files are not init scripts */ if (len > 2 && service[len - 3] == '.' && service[len - 2] == 's' && service[len - 1] == 'h') - return (false); + return false; - if (! (file = rc_service_resolve (service))) - return (false); + if (! (file = rc_service_resolve(service))) + return false; - if (stat (file, &buf) == 0 && buf.st_mode & S_IXUGO) + if (stat(file, &buf) == 0 && buf.st_mode & S_IXUGO) retval = true; - free (file); - return (retval); + free(file); + return retval; } librc_hidden_def(rc_service_exists) #define OPTSTR ". '%s'; echo \"${opts}\"" -char **rc_service_extra_commands (const char *service) +RC_STRINGLIST *rc_service_extra_commands(const char *service) { char *svc; char *cmd = NULL; char *buffer = NULL; - char **commands = NULL; + RC_STRINGLIST *commands; char *token; char *p; FILE *fp; size_t l; - if (! (svc = rc_service_resolve (service))) - return (NULL); - - l = strlen (OPTSTR) + strlen (svc) + 1; - cmd = xmalloc (sizeof (char) * l); - snprintf (cmd, l, OPTSTR, svc); - free (svc); - if ((fp = popen (cmd, "r"))) { - p = buffer = rc_getline (fp); - while ((token = strsep (&p, " "))) - rc_strlist_addsort (&commands, token); - pclose (fp); - free (buffer); - } - free (cmd); - return (commands); + if (! (svc = rc_service_resolve(service))) + return NULL; + + commands = rc_stringlist_new(); + + l = strlen(OPTSTR) + strlen(svc) + 1; + cmd = xmalloc(sizeof(char) * l); + snprintf(cmd, l, OPTSTR, svc); + free(svc); + + if ((fp = popen(cmd, "r"))) { + p = buffer = rc_getline(fp); + while ((token = strsep(&p, " "))) + rc_stringlist_add(commands, token); + pclose(fp); + free(buffer); + } + free(cmd); + return commands; } librc_hidden_def(rc_service_extra_commands) #define DESCSTR ". '%s'; echo \"${description%s%s}\"" -char *rc_service_description (const char *service, const char *option) +char *rc_service_description(const char *service, const char *option) { char *svc; char *cmd; @@ -436,85 +443,90 @@ char *rc_service_description (const char *service, const char *option) FILE *fp; size_t l; - if (! (svc = rc_service_resolve (service))) - return (NULL); + if (! (svc = rc_service_resolve(service))) + return NULL; if (! option) option = ""; - l = strlen (DESCSTR) + strlen (svc) + strlen (option) + 2; - cmd = xmalloc (sizeof (char) * l); - snprintf (cmd, l, DESCSTR, svc, option ? "_" : "", option); - free (svc); - if ((fp = popen (cmd, "r"))) { - desc = rc_getline (fp); - pclose (fp); + l = strlen(DESCSTR) + strlen(svc) + strlen(option) + 2; + cmd = xmalloc(sizeof(char) * l); + snprintf(cmd, l, DESCSTR, svc, option ? "_" : "", option); + free(svc); + if ((fp = popen(cmd, "r"))) { + desc = rc_getline(fp); + pclose(fp); } - free (cmd); - return (desc); + free(cmd); + return desc; } librc_hidden_def(rc_service_description) -bool rc_service_in_runlevel (const char *service, const char *runlevel) +bool rc_service_in_runlevel(const char *service, const char *runlevel) { char *file; bool retval; if (! runlevel || ! service) - return (false); + return false; - file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename_c (service), - (char *) NULL); - retval = exists (file); - free (file); + file = rc_strcatpaths(RC_RUNLEVELDIR, runlevel, basename_c(service), + (char *) NULL); + retval = exists(file); + free(file); - return (retval); + return retval; } librc_hidden_def(rc_service_in_runlevel) -bool rc_service_mark (const char *service, const rc_service_state_t state) +bool rc_service_mark(const char *service, const RC_SERVICE state) { char *file; int i = 0; int skip_state = -1; const char *base; - char *init = rc_service_resolve (service); + char *init = rc_service_resolve(service); bool skip_wasinactive = false; + int s; + char *was; + RC_STRINGLIST *dirs; + RC_STRING *dir; + int serrno; if (! init) - return (false); + return false; - base = basename_c (service); + base = basename_c(service); if (state != RC_SERVICE_STOPPED) { - if (! exists (init)) { - free (init); - return (false); + if (! exists(init)) { + free(init); + return false; } - file = rc_strcatpaths (RC_SVCDIR, rc_parse_service_state (state), base, - (char *) NULL); - if (exists (file)) - unlink (file); - i = symlink (init, file); - if (i != 0) { - free (file); - free (init); - return (false); + file = rc_strcatpaths(RC_SVCDIR, rc_parse_service_state (state), base, + (char *) NULL); + if (exists(file)) + unlink(file); + i = symlink(init, file); + if (i != 0) { + free(file); + free(init); + return false; } - free (file); + free(file); skip_state = state; } if (state == RC_SERVICE_COLDPLUGGED || state == RC_SERVICE_FAILED) { - free (init); - return (true); + free(init); + return true; } /* Remove any old states now */ for (i = 0; rc_service_state_names[i].name; i++) { - int s = rc_service_state_names[i].state; + s = rc_service_state_names[i].state; if ((s != skip_state && s != RC_SERVICE_STOPPED && @@ -522,24 +534,24 @@ bool rc_service_mark (const char *service, const rc_service_state_t state) s != RC_SERVICE_SCHEDULED) && (! skip_wasinactive || s != RC_SERVICE_WASINACTIVE)) { - file = rc_strcatpaths (RC_SVCDIR, rc_parse_service_state (s), base, - (char *) NULL); - if (exists (file)) { + file = rc_strcatpaths(RC_SVCDIR, rc_parse_service_state(s), base, + (char *) NULL); + if (exists(file)) { if ((state == RC_SERVICE_STARTING || state == RC_SERVICE_STOPPING) && s == RC_SERVICE_INACTIVE) { - char *wasfile = rc_strcatpaths (RC_SVCDIR, - rc_parse_service_state (RC_SERVICE_WASINACTIVE), - base, (char *) NULL); + was = rc_strcatpaths(RC_SVCDIR, + rc_parse_service_state(RC_SERVICE_WASINACTIVE), + base, (char *) NULL); - symlink (init, wasfile); + symlink(init, was); skip_wasinactive = true; - free (wasfile); + free(was); } - unlink (file); + unlink(file); } - free (file); + free(file); } } @@ -548,126 +560,133 @@ bool rc_service_mark (const char *service, const rc_service_state_t state) state == RC_SERVICE_STOPPED || state == RC_SERVICE_INACTIVE) { - file = rc_strcatpaths (RC_SVCDIR, "exclusive", base, (char *) NULL); - unlink (file); - free (file); + file = rc_strcatpaths(RC_SVCDIR, "exclusive", base, (char *) NULL); + unlink(file); + free(file); } /* Remove any options and daemons the service may have stored */ if (state == RC_SERVICE_STOPPED) { - char *dir = rc_strcatpaths (RC_SVCDIR, "options", base, (char *) NULL); - rm_dir (dir, true); - free (dir); + file = rc_strcatpaths(RC_SVCDIR, "options", base, (char *) NULL); + rm_dir(file, true); + free(file); - dir = rc_strcatpaths (RC_SVCDIR, "daemons", base, (char *) NULL); - rm_dir (dir, true); - free (dir); + file = rc_strcatpaths(RC_SVCDIR, "daemons", base, (char *) NULL); + rm_dir(file, true); + free(file); - rc_service_schedule_clear (service); + rc_service_schedule_clear(service); } /* These are final states, so remove us from scheduled */ if (state == RC_SERVICE_STARTED || state == RC_SERVICE_STOPPED) { - char *sdir = rc_strcatpaths (RC_SVCDIR, "scheduled", (char *) NULL); - char **dirs = ls_dir (sdir, 0); - char *dir; - int serrno; + file = rc_strcatpaths(RC_SVCDIR, "scheduled", (char *) NULL); + dirs = ls_dir(file, 0); - STRLIST_FOREACH (dirs, dir, i) { - char *bdir = rc_strcatpaths (sdir, dir, (char *) NULL); - file = rc_strcatpaths (bdir, base, (char *) NULL); - unlink (file); - free (file); + TAILQ_FOREACH(dir, dirs, entries) { + was = rc_strcatpaths(file, dir->value, base, (char *) NULL); + unlink(was); + free(was); /* Try and remove the dir - we don't care about errors */ + was = rc_strcatpaths(file, dir->value, (char *) NULL); serrno = errno; - rmdir (bdir); + rmdir(was); errno = serrno; - free (bdir); + free(was); } - rc_strlist_free (dirs); - free (sdir); + rc_stringlist_free(dirs); } - free (init); - return (true); + free(init); + return true; } librc_hidden_def(rc_service_mark) -rc_service_state_t rc_service_state (const char *service) +RC_SERVICE rc_service_state(const char *service) { int i; int state = RC_SERVICE_STOPPED; + char *file; + RC_STRINGLIST *dirs; + RC_STRING *dir; for (i = 0; rc_service_state_names[i].name; i++) { - char *file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[i].name, - basename_c (service), (char*) NULL); - if (exists (file)) { + file = rc_strcatpaths(RC_SVCDIR, rc_service_state_names[i].name, + basename_c(service), (char*) NULL); + if (exists(file)) { if (rc_service_state_names[i].state <= 0x10) state = rc_service_state_names[i].state; else state |= rc_service_state_names[i].state; } - free (file); + free(file); } if (state & RC_SERVICE_STOPPED) { - char **services = rc_services_scheduled_by (service); - if (services) { - state |= RC_SERVICE_SCHEDULED; - free (services); + dirs = ls_dir(RC_SVCDIR "/scheduled", 0); + TAILQ_FOREACH (dir, dirs, entries) { + file = rc_strcatpaths(RC_SVCDIR, "scheduled", + dir->value, + service, (char *) NULL); + if (exists(file)) + state |= RC_SERVICE_SCHEDULED; + free(file); + if (state & RC_SERVICE_SCHEDULED) + break; } + rc_stringlist_free(dirs); } - return (state); + return state; } librc_hidden_def(rc_service_state) -char *rc_service_value_get (const char *service, const char *option) +char *rc_service_value_get(const char *service, const char *option) { FILE *fp; char *line = NULL; - char *file = rc_strcatpaths (RC_SVCDIR, "options", service, option, - (char *) NULL); + char *file = rc_strcatpaths(RC_SVCDIR, "options", service, option, + (char *) NULL); - if ((fp = fopen (file, "r"))) { - line = rc_getline (fp); - fclose (fp); + if ((fp = fopen(file, "r"))) { + line = rc_getline(fp); + fclose(fp); } - free (file); + free(file); - return (line); + return line; } librc_hidden_def(rc_service_value_get) -bool rc_service_value_set (const char *service, const char *option, - const char *value) +bool rc_service_value_set(const char *service, const char *option, + const char *value) { FILE *fp; - char *path = rc_strcatpaths (RC_SVCDIR, "options", service, (char *) NULL); - char *file = rc_strcatpaths (path, option, (char *) NULL); + char *path = rc_strcatpaths(RC_SVCDIR, "options", service, (char *) NULL); + char *file = rc_strcatpaths(path, option, (char *) NULL); bool retval = false; - if (mkdir (path, 0755) != 0 && errno != EEXIST) { - free (path); - free (file); - return (false); + if (mkdir(path, 0755) != 0 && errno != EEXIST) { + free(path); + free(file); + return false; } - if ((fp = fopen (file, "w"))) { + if ((fp = fopen(file, "w"))) { if (value) - fprintf (fp, "%s", value); - fclose (fp); + fprintf(fp, "%s", value); + fclose(fp); retval = true; } - free (path); - free (file); - return (retval); + free(path); + free(file); + return retval; } librc_hidden_def(rc_service_value_set) -static pid_t _exec_service (const char *service, const char *arg) +static pid_t _exec_service(const char *service, const char *arg) { char *file; char *fifo; @@ -676,92 +695,92 @@ static pid_t _exec_service (const char *service, const char *arg) sigset_t old; struct sigaction sa; - file = rc_service_resolve (service); - if (! exists (file)) { - rc_service_mark (service, RC_SERVICE_STOPPED); - free (file); - return (0); + file = rc_service_resolve(service); + if (! exists(file)) { + rc_service_mark(service, RC_SERVICE_STOPPED); + free(file); + return 0; } /* We create a fifo so that other services can wait until we complete */ - fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename_c (service), - (char *) NULL); + fifo = rc_strcatpaths(RC_SVCDIR, "exclusive", basename_c(service), + (char *) NULL); - if (mkfifo (fifo, 0600) != 0 && errno != EEXIST) { - free (fifo); - free (file); - return (-1); + if (mkfifo(fifo, 0600) != 0 && errno != EEXIST) { + free(fifo); + free(file); + return -1; } /* We need to block signals until we have forked */ - memset (&sa, 0, sizeof (sa)); + memset(&sa, 0, sizeof (sa)); sa.sa_handler = SIG_DFL; - sigemptyset (&sa.sa_mask); - sigfillset (&full); - sigprocmask (SIG_SETMASK, &full, &old); + sigemptyset(&sa.sa_mask); + sigfillset(&full); + sigprocmask(SIG_SETMASK, &full, &old); - if ((pid = fork ()) == 0) { + if ((pid = fork()) == 0) { /* Restore default handlers */ - sigaction (SIGCHLD, &sa, NULL); - sigaction (SIGHUP, &sa, NULL); - sigaction (SIGINT, &sa, NULL); - sigaction (SIGQUIT, &sa, NULL); - sigaction (SIGTERM, &sa, NULL); - sigaction (SIGUSR1, &sa, NULL); - sigaction (SIGWINCH, &sa, NULL); + sigaction(SIGCHLD, &sa, NULL); + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGQUIT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGUSR1, &sa, NULL); + sigaction(SIGWINCH, &sa, NULL); /* Unmask signals */ - sigprocmask (SIG_SETMASK, &old, NULL); + sigprocmask(SIG_SETMASK, &old, NULL); /* Safe to run now */ - execl (file, file, arg, (char *) NULL); - fprintf (stderr, "unable to exec `%s': %s\n", - file, strerror (errno)); - unlink (fifo); - _exit (EXIT_FAILURE); + execl(file, file, arg, (char *) NULL); + fprintf(stderr, "unable to exec `%s': %s\n", + file, strerror(errno)); + unlink(fifo); + _exit(EXIT_FAILURE); } if (pid == -1) - fprintf (stderr, "fork: %s\n", strerror (errno)); + fprintf(stderr, "fork: %s\n",strerror (errno)); - sigprocmask (SIG_SETMASK, &old, NULL); + sigprocmask(SIG_SETMASK, &old, NULL); - free (fifo); - free (file); + free(fifo); + free(file); - return (pid); + return pid; } -pid_t rc_service_stop (const char *service) +pid_t rc_service_stop(const char *service) { - rc_service_state_t state = rc_service_state (service); + RC_SERVICE state = rc_service_state(service); if (state & RC_SERVICE_FAILED) - return (-1); + return -1; if (state & RC_SERVICE_STOPPED) - return (0); + return 0; - return (_exec_service (service, "stop")); + return _exec_service(service, "stop"); } librc_hidden_def(rc_service_stop) -pid_t rc_service_start (const char *service) +pid_t rc_service_start(const char *service) { - rc_service_state_t state = rc_service_state (service); + RC_SERVICE state = rc_service_state(service); if (state & RC_SERVICE_FAILED) - return (-1); + return -1; if (! state & RC_SERVICE_STOPPED) - return (0); + return 0; - return (_exec_service (service, "start")); + return _exec_service(service, "start"); } librc_hidden_def(rc_service_start) -bool rc_service_schedule_start (const char *service, - const char *service_to_start) +bool rc_service_schedule_start(const char *service, + const char *service_to_start) { char *dir; char *init; @@ -769,162 +788,156 @@ bool rc_service_schedule_start (const char *service, bool retval; /* service may be a provided service, like net */ - if (! service || ! rc_service_exists (service_to_start)) - return (false); + if (! service || ! rc_service_exists(service_to_start)) + return false; - dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename_c (service), - (char *) NULL); - if (mkdir (dir, 0755) != 0 && errno != EEXIST) { - free (dir); - return (false); + dir = rc_strcatpaths(RC_SVCDIR, "scheduled", basename_c(service), + (char *) NULL); + if (mkdir(dir, 0755) != 0 && errno != EEXIST) { + free(dir); + return false; } - init = rc_service_resolve (service_to_start); - file = rc_strcatpaths (dir, basename_c (service_to_start), (char *) NULL); - retval = (exists (file) || symlink (init, file) == 0); - free (init); - free (file); - free (dir); + init = rc_service_resolve(service_to_start); + file = rc_strcatpaths(dir, basename_c(service_to_start), (char *) NULL); + retval = (exists(file) || symlink(init, file) == 0); + free(init); + free(file); + free(dir); - return (retval); + return retval; } librc_hidden_def(rc_service_schedule_start) -bool rc_service_schedule_clear (const char *service) +bool rc_service_schedule_clear(const char *service) { - char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename_c (service), - (char *) NULL); + char *dir = rc_strcatpaths(RC_SVCDIR, "scheduled", basename_c(service), + (char *) NULL); bool retval; - if (! (retval = rm_dir (dir, true)) && errno == ENOENT) + if (! (retval = rm_dir(dir, true)) && errno == ENOENT) retval = true; - free (dir); - return (retval); + free(dir); + return retval; } librc_hidden_def(rc_service_schedule_clear) - -char **rc_services_in_runlevel (const char *runlevel) +RC_STRINGLIST *rc_services_in_runlevel(const char *runlevel) { char *dir; - char **list = NULL; + RC_STRINGLIST *list; if (! runlevel) { -#if defined(RC_PKG_INITDIR) || defined(RC_LOCAL_INITDIR) - int i; -#endif #ifdef RC_PKG_INITDIR - char **pkg = ls_dir (RC_PKG_INITDIR, LS_INITD); + RC_STRINGLIST *pkg = ls_dir(RC_PKG_INITDIR, LS_INITD); #endif #ifdef RC_LOCAL_INITDIR - char **local = ls_dir (RC_LOCAL_INITDIR, LS_INITD); + RC_STRINGLIST *local = ls_dir(RC_LOCAL_INITDIR, LS_INITD); #endif - list = ls_dir (RC_INITDIR, LS_INITD); + list = ls_dir(RC_INITDIR, LS_INITD); #ifdef RC_PKG_INITDIR - STRLIST_FOREACH (pkg, dir, i) - rc_strlist_addsortu (&list, dir); - rc_strlist_free (pkg); + if (pkg) { + TAILQ_CONCAT(list, pkg); + free(pkg); + } #endif #ifdef RC_LOCAL_DIR - STRLIST_FOREACH (local, dir, i) - rc_strlist_addsortu (&list, dir); - rc_strlist_free (local); + if (local) { + TAILQ_CONCAT(list, local); + free(local); + } #endif - return (list); + return list; } /* These special levels never contain any services */ - if (strcmp (runlevel, RC_LEVEL_SYSINIT) == 0 || - strcmp (runlevel, RC_LEVEL_SINGLE) == 0) - return (NULL); - - dir = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL); - list = ls_dir (dir, LS_INITD); - free (dir); - return (list); + if (strcmp(runlevel, RC_LEVEL_SYSINIT) == 0 || + strcmp(runlevel, RC_LEVEL_SINGLE) == 0) { + list = rc_stringlist_new(); + return list; + } + + dir = rc_strcatpaths(RC_RUNLEVELDIR, runlevel, (char *) NULL); + list = ls_dir(dir, LS_INITD); + free(dir); + return list; } librc_hidden_def(rc_services_in_runlevel) -char **rc_services_in_state (rc_service_state_t state) +RC_STRINGLIST *rc_services_in_state(RC_SERVICE state) { - char *dir = rc_strcatpaths (RC_SVCDIR, rc_parse_service_state (state), - (char *) NULL); - char **list = NULL; + char *dir = rc_strcatpaths(RC_SVCDIR, rc_parse_service_state(state), + (char *) NULL); + RC_STRINGLIST *services; + RC_STRINGLIST *list; + RC_STRINGLIST *dirs; + RC_STRING *d; + char *p; if (state == RC_SERVICE_SCHEDULED) { - char **dirs = ls_dir (dir, 0); - char *d; - int i; - - STRLIST_FOREACH (dirs, d, i) { - char *p = rc_strcatpaths (dir, d, (char *) NULL); - char **entries = ls_dir (p, LS_INITD); - char *e; - int j; - - STRLIST_FOREACH (entries, e, j) - rc_strlist_addsortu (&list, e); - - if (entries) - free (entries); + dirs = ls_dir(dir, 0); + list = rc_stringlist_new(); + TAILQ_FOREACH(d, dirs, entries) { + p = rc_strcatpaths(dir, d->value, (char *) NULL); + services = ls_dir(p, LS_INITD); + free(p); + TAILQ_CONCAT(list, services); + free(services); } - - if (dirs) - free (dirs); + rc_stringlist_free(dirs); } else { - list = ls_dir (dir, LS_INITD); + list = ls_dir(dir, LS_INITD); } - free (dir); - return (list); + free(dir); + return list; } librc_hidden_def(rc_services_in_state) -bool rc_service_add (const char *runlevel, const char *service) +bool rc_service_add(const char *runlevel, const char *service) { bool retval; char *init; char *file; + char path[MAXPATHLEN] = { '\0' }; + char *p; - if (! rc_runlevel_exists (runlevel)) { + if (! rc_runlevel_exists(runlevel)) { errno = ENOENT; - return (false); + return false; } - if (rc_service_in_runlevel (service, runlevel)) { + if (rc_service_in_runlevel(service, runlevel)) { errno = EEXIST; - return (false); + return false; } - init = rc_service_resolve (service); + init = rc_service_resolve(service); /* We need to ensure that only things in /etc/init.d are added * to the boot runlevel */ if (strcmp (runlevel, RC_LEVEL_BOOT) == 0) { - char tmp[MAXPATHLEN] = { '\0' }; - char *p; - - p = realpath (dirname (init), tmp); - free (init); + p = realpath(dirname (init), path); + free(init); if (! *p) - return (false); + return false; - retval = (strcmp (tmp, RC_INITDIR) == 0); + retval = (strcmp(path, RC_INITDIR) == 0); if (! retval) { errno = EPERM; - return (false); + return false; } - init = rc_strcatpaths (RC_INITDIR, service, (char *) NULL); + init = rc_strcatpaths(RC_INITDIR, service, (char *) NULL); } - file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename_c (service), - (char *) NULL); - retval = (symlink (init, file) == 0); - free (init); - free (file); - return (retval); + file = rc_strcatpaths(RC_RUNLEVELDIR, runlevel, basename_c(service), + (char *) NULL); + retval = (symlink(init, file) == 0); + free(init); + free(file); + return retval; } librc_hidden_def(rc_service_add) @@ -934,46 +947,46 @@ bool rc_service_delete (const char *runlevel, const char *service) bool retval = false; if (! runlevel || ! service) - return (false); + return false; - file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename_c (service), + file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename_c(service), (char *) NULL); - if (unlink (file) == 0) + if (unlink(file) == 0) retval = true; - free (file); - return (retval); + free(file); + return retval; } librc_hidden_def(rc_service_delete) -char **rc_services_scheduled_by (const char *service) +RC_STRINGLIST *rc_services_scheduled_by(const char *service) { - char **dirs = ls_dir (RC_SVCDIR "/scheduled", 0); - char **list = NULL; - char *dir; - int i; + RC_STRINGLIST *dirs = ls_dir(RC_SVCDIR "/scheduled", 0); + RC_STRINGLIST *list; + RC_STRING *dir; + char *file; - STRLIST_FOREACH (dirs, dir, i) { - char *file = rc_strcatpaths (RC_SVCDIR, "scheduled", dir, service, - (char *) NULL); - if (exists (file)) - rc_strlist_add (&list, file); - free (file); + list = rc_stringlist_new(); + TAILQ_FOREACH (dir, dirs, entries) { + file = rc_strcatpaths(RC_SVCDIR, "scheduled", dir->value, + service, (char *) NULL); + if (exists(file)) + rc_stringlist_add(list, file); + free(file); } - rc_strlist_free (dirs); + rc_stringlist_free(dirs); - return (list); + return list; } librc_hidden_def(rc_services_scheduled_by) -char **rc_services_scheduled (const char *service) +RC_STRINGLIST *rc_services_scheduled(const char *service) { - char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename_c (service), - (char *) NULL); - char **list = NULL; + char *dir = rc_strcatpaths(RC_SVCDIR, "scheduled", basename_c(service), + (char *) NULL); + RC_STRINGLIST *list = ls_dir(dir, LS_INITD); - list = ls_dir (dir, LS_INITD); - free (dir); - return (list); + free(dir); + return list; } librc_hidden_def(rc_services_scheduled) diff --git a/src/librc/librc.h b/src/librc/librc.h index edbebafb..aaad7ccd 100644 --- a/src/librc/librc.h +++ b/src/librc/librc.h @@ -64,10 +64,8 @@ #include <kvm.h> #endif -#include "librc-depend.h" #include "rc.h" #include "rc-misc.h" -#include "strlist.h" #include "hidden-visibility.h" #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_set) librc_hidden_proto(rc_strcatpaths) -librc_hidden_proto(rc_strlist_add) -librc_hidden_proto(rc_strlist_addu) -librc_hidden_proto(rc_strlist_addsort) -librc_hidden_proto(rc_strlist_addsortc) -librc_hidden_proto(rc_strlist_addsortu) -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_stringlist_add) +librc_hidden_proto(rc_stringlist_addu) +librc_hidden_proto(rc_stringlist_delete) +librc_hidden_proto(rc_stringlist_free) +librc_hidden_proto(rc_stringlist_sort) librc_hidden_proto(rc_yesno) #endif diff --git a/src/librc/rc.h b/src/librc/rc.h index 0b811f46..061959e7 100644 --- a/src/librc/rc.h +++ b/src/librc/rc.h @@ -32,15 +32,24 @@ # if (GCC_VERSION >= 3005) # define SENTINEL __attribute__ ((__sentinel__)) # endif +# define DEPRECATED __attribute__ ((deprecated)) #endif #ifndef SENTINEL # define SENTINEL #endif #include <sys/types.h> +#include <sys/queue.h> #include <stdbool.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 */ #define RC_LEVEL_SYSINIT "sysinit" #define RC_LEVEL_SINGLE "single" @@ -49,30 +58,30 @@ /*! 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 * @param runlevel to check * @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 */ -char **rc_runlevel_list (void); +RC_STRINGLIST *rc_runlevel_list(void); /*! Set the runlevel. * This just changes the stored runlevel and does not start or stop any * services. * @param runlevel to store */ -bool rc_runlevel_set (const char *runlevel); +bool rc_runlevel_set(const char *); /*! Is the runlevel starting? * @return true if yes, otherwise false */ -bool rc_runlevel_starting (void); +bool rc_runlevel_starting(void); /*! Is the runlevel stopping? * @return true if yes, otherwise false */ -bool rc_runlevel_stopping (void); +bool rc_runlevel_stopping(void); /*! @name RC * 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_SCHEDULED = 0x0400, RC_SERVICE_WASINACTIVE = 0x0800 -} rc_service_state_t; +} RC_SERVICE; /*! Add the service to the runlevel * @param runlevel to add to * @param service to add * @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 * @param runlevel to remove from * @param service to remove * @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 * @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 pidfile of the process (optional) * @param started if true, add the arguments otherwise remove existing matching arguments */ -bool rc_service_daemon_set (const char *service, const char *const *argv, - const char *name, const char *pidfile, - bool started); +bool rc_service_daemon_set(const char *, const char *const *, const char *, const char *, + bool); /*! Returns a description of what the service and/or option does. * @param service to check * @param option to check (if NULL, service 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. * @param service to check * @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 * @param service to check * @param runlevel it should be in * @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 * @param service to mark * @param state service should be in * @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 * @param service to load the commands from * @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. * @param service to check * @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 * @param service that starts the scheduled service when started * @param service_to_start service that will be started */ -bool rc_service_schedule_start (const char *service, - const char *service_to_start); +bool rc_service_schedule_start(const char *, const char *); + /*! Return a NULL terminated list of services that are scheduled to start * when the given service has started * @param service to check * @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 * @param service to clear * @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 * @param service to check * @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 * @param service to start * @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 * @param service to stop * @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 * @param service to check * @param exec to check * @param indx of the daemon (optional - 1st daemon, 2nd daemon, etc) * @return true if started by this service, otherwise false */ -bool rc_service_started_daemon (const char *service, const char *const *argv, - int indx); +bool rc_service_started_daemon(const char *, const char *const *, int); /*! Return a saved value for a service * @param service to check * @param option to load * @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 * @param service to save for * @param option to save * @param value of the option * @return true if saved, otherwise false */ -bool rc_service_value_set (const char *service, const char *option, - const char *value); +bool rc_service_value_set(const char *, const char *, const char *); /*! List the services in a runlevel * @param runlevel to list * @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 * @param state to list * @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 * @param service to check * @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 * are still running. * @param service to check * @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 * 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_XEN0 "XEN0" #define RC_SYS_XENU "XENU" -const char *rc_sys (void); +const char *rc_sys(void); /*! @name Dependency options * 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. * 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 */ -typedef void *rc_depinfo_t; +typedef void *RC_DEPTREE; #endif /*! Check to see if source is newer than target. * If target is a directory then we traverse it and it's children. * @return true if source is newer than target, otherwise false */ -bool rc_newer_than (const char *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, * its configuration file or an external configuration file the init script * has specified. * @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, * its configuration file or an external configuration file the init script * has specified. * @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. * This pointer should be freed with rc_deptree_free when done. * @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 * @param deptree to search * @param type to use (keywords, etc) * @param service to check * @return NULL terminated list of services in order */ -char **rc_deptree_depend (const rc_depinfo_t *deptree, - const char *type, const char *service); +RC_STRINGLIST *rc_deptree_depend(const RC_DEPTREE *, const char *, const char *); /*! List all the services in order that the given services have * for the given types and options. @@ -298,10 +331,8 @@ char **rc_deptree_depend (const rc_depinfo_t *deptree, * @param services to check * @param options to pass * @return NULL terminated list of services in order */ -char **rc_deptree_depends (const rc_depinfo_t *deptree, - const char *const *types, - const char *const *services, const char *runlevel, - int options); +RC_STRINGLIST *rc_deptree_depends(const RC_DEPTREE *, const RC_STRINGLIST *, + const RC_STRINGLIST *, const char *, int); /*! List all the services that should be stoppned and then started, in order, * 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 options to pass * @return NULL terminated list of services in order */ -char **rc_deptree_order (const rc_depinfo_t *deptree, const char *runlevel, - int options); +RC_STRINGLIST *rc_deptree_order(const RC_DEPTREE *, const char *, int); /*! Free a deptree and its information * @param deptree to free */ -void rc_deptree_free (rc_depinfo_t *deptree); +void rc_deptree_free(RC_DEPTREE *); /*! @name Plugins * 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_DONE = 107, RC_HOOK_SERVICE_START_OUT = 108 -} rc_hook_t; +} RC_HOOK; /*! Plugin entry point * @param hook point * @param name of runlevel or service * @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 * variables they wish. Variables should be separated by NULLs. */ @@ -362,91 +392,64 @@ extern FILE *rc_environ_fd; /*! @name Configuration * These functions help to deal with shell based configuration files */ /*! 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. */ -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. */ -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. */ -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. * 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. * @param variable to check * @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 - * Handy functions for dealing with string arrays of char **. - * 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 - * should be released with a call to rc_strlist_free. */ + * Every string list should be released with a call to rc_stringlist_free. */ + +/*! Create a new stringlinst + * @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. * @param list to add the item too * @param item to add. * @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 * list 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_addu (char ***list, const char *item); - -/*! 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); +RC_STRING *rc_stringlist_addu(RC_STRINGLIST *, const char *); /*! Free the item and remove it from the list. Return 0 on success otherwise -1. * @param list to add the item too * @param item to add. * @return true on success, otherwise false */ -bool rc_strlist_delete (char ***list, const char *item); - -/*! Moves the contents of list2 onto list1, so list2 is effectively emptied. - * Returns a pointer to the last item on the new list. - * @param list1 to append to - * @param list2 to move from - * @return pointer to the last item on the list */ -char *rc_strlist_join (char ***list1, char **list2); +bool rc_stringlist_delete(RC_STRINGLIST *, const char *); -/*! Reverses the contents of the list. - * @param list to reverse */ -void rc_strlist_reverse (char **list); +/*! Sort the list according to C locale + * @param list to sort */ +void rc_stringlist_sort(RC_STRINGLIST **); /*! Frees each item on the list and the list itself. * @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 * freed when finished with. * @param path1 starting path * @param paths NULL terminated list of paths to add * @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. * 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 pid to check for * @return NULL terminated list of pids */ -pid_t *rc_find_pids (const char *const *argv, const char *cmd, - uid_t uid, pid_t pid); +pid_t *rc_find_pids(const char *const *, const char *, uid_t, pid_t); #endif diff --git a/src/librc/rc.map b/src/librc/rc.map index e5fd350b..8ad4e187 100644 --- a/src/librc/rc.map +++ b/src/librc/rc.map @@ -43,15 +43,12 @@ global: rc_service_value_get; rc_service_value_set; rc_strcatpaths; - rc_strlist_add; - rc_strlist_addu; - rc_strlist_addsort; - rc_strlist_addsortc; - rc_strlist_addsortu; - rc_strlist_delete; - rc_strlist_free; - rc_strlist_join; - rc_strlist_reverse; + rc_stringlist_add; + rc_stringlist_addu; + rc_stringlist_delete; + rc_stringlist_new; + rc_stringlist_sort; + rc_stringlist_free; rc_sys; rc_yesno; diff --git a/src/rc/.gitignore b/src/rc/.gitignore index eaa7de9e..d2499761 100644 --- a/src/rc/.gitignore +++ b/src/rc/.gitignore @@ -55,6 +55,7 @@ rc-abort checkpath.o fstabinfo.o mountinfo.o +start-stop-daemon.o rc-applets.o rc-depend.o rc-logger.o @@ -62,8 +63,7 @@ rc-misc.o rc-plugin.o rc-status.o rc-update.o -rc.o runscript.o -start-stop-daemon.o +rc.o rc .depend diff --git a/src/rc/Makefile b/src/rc/Makefile index df185d69..469ac984 100644 --- a/src/rc/Makefile +++ b/src/rc/Makefile @@ -1,8 +1,8 @@ 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-misc.c rc-plugin.c rc-status.c rc-update.c rc.c \ - runscript.c start-stop-daemon.c + rc-misc.c rc-plugin.c rc-status.c rc-update.c \ + runscript.c rc.c CLEANFILES= version.h @@ -31,8 +31,9 @@ ALL_LINKS= ${BINLINKS} ${SBINLINKS} ${RC_BINLINKS} ${RC_SBINLINKS} CLEANFILES+= ${ALL_LINKS} LDFLAGS+= -L../librc -L../libeinfo -#LDFLAGS+= -Wl,--rpath=../librc -Wl,--rpath=../libeinfo LDADD+= -lutil -lrc -leinfo +#CFLAGS+= -ggdb +#LDFLAGS+= -Wl,--rpath=../librc -Wl,--rpath=../libeinfo MK= ../../mk include ${MK}/cc.mk diff --git a/src/rc/_usage.c b/src/rc/_usage.c index 7ad925d0..afe517f1 100644 --- a/src/rc/_usage.c +++ b/src/rc/_usage.c @@ -33,35 +33,36 @@ # define _noreturn #endif -_noreturn static void usage (int exit_status) +_noreturn static void usage(int exit_status) { const char * const has_arg[] = { "", "<arg>", "[arg]" }; int i; + int len; + char *lo; + char *p; + char *token; #ifdef usagestring - printf (usagestring); + printf(usagestring); #else - printf ("Usage: %s [options] ", applet); + printf("Usage: %s [options] ", applet); #endif #ifdef extraopts - printf (extraopts); + printf(extraopts); #endif - printf ("\n\nOptions: [" getoptstring "]\n"); + printf("\n\nOptions: [" getoptstring "]\n"); for (i = 0; longopts[i].name; ++i) { - int len = printf (" -%c, --%s %s", longopts[i].val, longopts[i].name, - has_arg[longopts[i].has_arg]); + len = printf(" -%c, --%s %s", longopts[i].val, longopts[i].name, + has_arg[longopts[i].has_arg]); - char *lo = xstrdup (longopts_help[i]); - char *p = lo; - char *token; - - while ((token = strsep (&p, "\n"))) { + lo = p = xstrdup(longopts_help[i]); + while ((token = strsep(&p, "\n"))) { while (++len < 37) - printf (" "); - puts (token); + printf(" "); + puts(token); len = 0; } - free (lo); + free(lo); } - exit (exit_status); + exit(exit_status); } diff --git a/src/rc/builtins.h b/src/rc/builtins.h index 6d180bab..81325847 100644 --- a/src/rc/builtins.h +++ b/src/rc/builtins.h @@ -38,4 +38,4 @@ int start_stop_daemon (int argc, char **argv); void run_applets (int argc, char **argv); /* 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); diff --git a/src/rc/checkpath.c b/src/rc/checkpath.c index 7b16aee5..4bf0c46a 100644 --- a/src/rc/checkpath.c +++ b/src/rc/checkpath.c @@ -32,6 +32,7 @@ #include <sys/types.h> #include <sys/stat.h> + #include <errno.h> #include <fcntl.h> #include <getopt.h> @@ -48,84 +49,84 @@ 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; + int fd; - memset (&st, 0, sizeof (st)); - - if (stat (path, &st)) { + if (stat(path, &st)) { if (file) { - int fd; - einfo ("%s: creating file", path); - if ((fd = open (path, O_CREAT)) == -1) { - eerror ("%s: open: %s", applet, strerror (errno)); - return (-1); + einfo("%s: creating file", path); + if ((fd = open(path, O_CREAT)) == -1) { + eerror("%s: open: %s", applet, strerror(errno)); + return -1; } close (fd); } else { - einfo ("%s: creating directory", path); + einfo("%s: creating directory", path); if (! mode) mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; - if (mkdir (path, mode)) { - eerror ("%s: mkdir: %s", applet, strerror (errno)); - return (-1); + if (mkdir(path, mode)) { + eerror("%s: mkdir: %s", applet, strerror (errno)); + return -1; } mode = 0; } } else { - if ((file && S_ISDIR (st.st_mode)) || - (! file && ! S_ISDIR (st.st_mode))) + if ((file && S_ISDIR(st.st_mode)) || + (! file && ! S_ISDIR(st.st_mode))) { if (file) - eerror ("%s: is a directory", path); + eerror("%s: is a directory", path); else - eerror ("%s: is a file", path); - return (-1); + eerror("%s: is a file", path); + return -1; } } if (mode && (st.st_mode & 0777) != mode) { - einfo ("%s: correcting mode", applet); - if (chmod (path, mode)) { - eerror ("%s: chmod: %s", applet, strerror (errno)); - return (-1); + einfo("%s: correcting mode", applet); + if (chmod(path, mode)) { + eerror("%s: chmod: %s", applet, strerror(errno)); + return -1; } } if (st.st_uid != uid || st.st_gid != gid) { if (st.st_dev || st.st_ino) - einfo ("%s: correcting owner", path); - if (chown (path, uid, gid)) { - eerror ("%s: chown: %s", applet, strerror (errno)); - return (-1); + einfo("%s: correcting owner", path); + if (chown(path, uid, gid)) { + eerror("%s: chown: %s", applet, strerror(errno)); + return -1; } } - return (0); + return 0; } /* Based on busybox */ static int parse_mode (mode_t *mode, char *text) { + char *p; + unsigned long l; + /* Check for a numeric mode */ if ((*text - '0') < 8) { - char *p; - unsigned long l = strtoul (text, &p, 8); + l = strtoul(text, &p, 8); if (*p || l > 07777U) { errno = EINVAL; - return (-1); + return -1; } *mode = (mode_t) l; - return (0); + return 0; } /* We currently don't check g+w type stuff */ 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) { char *u = xstrdup (owner); @@ -137,25 +138,25 @@ static int parse_owner (struct passwd **user, struct group **group, *g++ = '\0'; if (user && *u) { - if (sscanf (u, "%d", &id) == 1) - *user = getpwuid ((uid_t) id); + if (sscanf(u, "%d", &id) == 1) + *user = getpwuid((uid_t) id); else - *user = getpwnam (u); + *user = getpwnam(u); if (! *user) retval = -1; } if (group && g && *g) { - if (sscanf (g, "%d", &id) == 1) - *group = getgrgid ((gid_t) id); + if (sscanf(g, "%d", &id) == 1) + *group = getgrgid((gid_t) id); else - *group = getgrnam (g); + *group = getgrnam(g); if (! *group) retval = -1; } - free (u); - return (retval); + free(u); + return retval; } #include "_usage.h" @@ -177,7 +178,7 @@ static const char * const longopts_help[] = { }; #include "_usage.c" -int checkpath (int argc, char **argv) +int checkpath(int argc, char **argv) { int opt; uid_t uid = geteuid(); @@ -188,33 +189,31 @@ int checkpath (int argc, char **argv) bool file = 0; int retval = EXIT_SUCCESS; - while ((opt = getopt_long (argc, argv, getoptstring, - longopts, (int *) 0)) != -1) + while ((opt = getopt_long(argc, argv, getoptstring, + longopts, (int *) 0)) != -1) { switch (opt) { - case 'd': - file = 0; - break; - case 'f': - file = 1; - break; - case 'm': - if (parse_mode (&mode, optarg) != 0) - eerrorx ("%s: invalid mode `%s'", - applet, optarg); - break; - case 'o': - if (parse_owner (&pw, &gr, optarg) != 0) - eerrorx ("%s: owner `%s' not found", - applet, optarg); - break; - - case_RC_COMMON_GETOPT + case 'd': + file = 0; + break; + case 'f': + file = 1; + break; + case 'm': + if (parse_mode(&mode, optarg) != 0) + eerrorx("%s: invalid mode `%s'", applet, optarg); + break; + case 'o': + if (parse_owner(&pw, &gr, optarg) != 0) + eerrorx("%s: owner `%s' not found", applet, optarg); + break; + + case_RC_COMMON_GETOPT } } if (optind >= argc) - usage (EXIT_FAILURE); + usage(EXIT_FAILURE); if (pw) { uid = pw->pw_uid; @@ -224,11 +223,11 @@ int checkpath (int argc, char **argv) gid = gr->gr_gid; while (optind < argc) { - if (do_check (argv[optind], uid, gid, mode, file)) + if (do_check(argv[optind], uid, gid, mode, file)) retval = EXIT_FAILURE; optind++; } - exit (retval); + exit(retval); /* NOTREACHED */ } diff --git a/src/rc/fstabinfo.c b/src/rc/fstabinfo.c index 309c6842..54812bfe 100644 --- a/src/rc/fstabinfo.c +++ b/src/rc/fstabinfo.c @@ -30,6 +30,7 @@ */ #include <sys/wait.h> + #include <errno.h> #include <getopt.h> #include <stdio.h> @@ -72,27 +73,26 @@ #include "einfo.h" #include "rc.h" #include "rc-misc.h" -#include "strlist.h" #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; START_ENT; - while ((ent = getmntent (fp))) - if (strcmp (file, ent->mnt_dir) == 0) + while ((ent = getmntent(fp))) + if (strcmp(file, ent->mnt_dir) == 0) break; END_ENT; - return (ent); + return ent; } #endif extern const char *applet; -static int do_mount (struct ENT *ent) +static int do_mount(struct ENT *ent) { char *argv[8]; pid_t pid; @@ -100,29 +100,27 @@ static int do_mount (struct ENT *ent) argv[0] = (char *) "mount"; argv[1] = (char *) "-o"; - argv[2] = ENT_OPTS (*ent); + argv[2] = ENT_OPTS(*ent); argv[3] = (char *) "-t"; - argv[4] = ENT_TYPE (*ent); - argv[5] = ENT_BLOCKDEVICE (*ent); - argv[6] = ENT_FILE (*ent); + argv[4] = ENT_TYPE(*ent); + argv[5] = ENT_BLOCKDEVICE(*ent); + argv[6] = ENT_FILE(*ent); argv[7] = NULL; switch (pid = vfork()) { case -1: - eerrorx ("%s: vfork: %s", applet, - strerror (errno)); + eerrorx("%s: vfork: %s", applet, strerror(errno)); /* NOTREACHED */ case 0: - execvp (argv[0], argv); - eerror ("%s: execv: %s", applet, - strerror (errno)); + execvp(argv[0], argv); + eerror("%s: execv: %s", applet, strerror(errno)); _exit(EXIT_FAILURE); /* NOTREACHED */ default: - waitpid (pid, &status, 0); - if (WIFEXITED (status)) - return (WEXITSTATUS(status)); + waitpid(pid, &status, 0); + if (WIFEXITED(status)) + return WEXITSTATUS(status); else - return (-1); + return -1; /* NOTREACHED */ } } @@ -155,7 +153,7 @@ static const char * const longopts_help[] = { #define OUTPUT_BLOCKDEV (1 << 5) #define OUTPUT_MOUNT (1 << 6) -int fstabinfo (int argc, char **argv) +int fstabinfo(int argc, char **argv) { struct ENT *ent; int result = EXIT_SUCCESS; @@ -163,8 +161,8 @@ int fstabinfo (int argc, char **argv) int i; int opt; int output = OUTPUT_FILE; - char **files = NULL; - char *file; + RC_STRINGLIST *files = rc_stringlist_new(); + RC_STRING *file; bool filtered = false; #ifdef HAVE_GETMNTENT @@ -172,125 +170,126 @@ int fstabinfo (int argc, char **argv) #endif /* Ensure that we are only quiet when explicitly told to be */ - unsetenv ("EINFO_QUIET"); + unsetenv("EINFO_QUIET"); - while ((opt = getopt_long (argc, argv, getoptstring, - longopts, (int *) 0)) != -1) + while ((opt = getopt_long(argc, argv, getoptstring, + longopts, (int *) 0)) != -1) { switch (opt) { - case 'M': - output = OUTPUT_MOUNT; - break; - case 'b': - output = OUTPUT_BLOCKDEV; - break; - case 'o': - output = OUTPUT_OPTIONS; - break; - case 'm': - output = OUTPUT_MOUNTARGS; - break; + case 'M': + output = OUTPUT_MOUNT; + break; + case 'b': + output = OUTPUT_BLOCKDEV; + break; + case 'o': + output = OUTPUT_OPTIONS; + break; + case 'm': + output = OUTPUT_MOUNTARGS; + break; - case 'p': - switch (optarg[0]) { - case '=': - case '<': - case '>': - if (sscanf (optarg + 1, "%d", &i) != 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 'p': + switch (optarg[0]) { + case '=': + case '<': + case '>': + if (sscanf(optarg + 1, "%d", &i) != 1) + eerrorx("%s: invalid passno %s", + argv[0], optarg + 1); - case 't': filtered = true; - while ((token = strsep (&optarg, ","))) { - START_ENT; - while ((ent = GET_ENT)) - if (strcmp (token, ENT_TYPE (ent)) == 0) - rc_strlist_add (&files, ENT_FILE (ent)); - END_ENT; + 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_stringlist_add(files, ENT_FILE(ent)); } + END_ENT; 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) - rc_strlist_add (&files, argv[optind++]); - - if (! files && ! filtered) { + if (optind < argc) { + while (optind < argc) + rc_stringlist_add(files, argv[optind++]); + } else if (! filtered) { START_ENT; while ((ent = GET_ENT)) - rc_strlist_add (&files, ENT_FILE (ent)); + rc_stringlist_add(files, ENT_FILE(ent)); END_ENT; - if (! files) - eerrorx ("%s: emtpy fstab", argv[0]); + if (! TAILQ_FIRST(files)) + eerrorx("%s: emtpy fstab", argv[0]); } /* Ensure we always display something */ START_ENT; - STRLIST_FOREACH (files, file, i) { - if (! (ent = GET_ENT_FILE (file))) { + TAILQ_FOREACH(file, files, entries) { + if (! (ent = GET_ENT_FILE(file->value))) { result = EXIT_FAILURE; continue; } /* No point in outputting if quiet */ - if (rc_yesno (getenv ("EINFO_QUIET"))) + if (rc_yesno(getenv("EINFO_QUIET"))) continue; switch (output) { - case OUTPUT_BLOCKDEV: - printf ("%s\n", ENT_BLOCKDEVICE (ent)); - break; + case OUTPUT_BLOCKDEV: + printf("%s\n", ENT_BLOCKDEVICE(ent)); + break; - case OUTPUT_MOUNT: - result += do_mount (ent); - break; + case OUTPUT_MOUNT: + result += do_mount(ent); + break; - case OUTPUT_MOUNTARGS: - printf ("-o %s -t %s %s %s\n", - ENT_OPTS (ent), - ENT_TYPE (ent), - ENT_BLOCKDEVICE (ent), - file); - break; + case OUTPUT_MOUNTARGS: + printf("-o %s -t %s %s %s\n", + ENT_OPTS(ent), + ENT_TYPE(ent), + ENT_BLOCKDEVICE(ent), + file->value); + break; - case OUTPUT_OPTIONS: - printf ("%s\n", ENT_OPTS (ent)); - break; + case OUTPUT_OPTIONS: + printf("%s\n", ENT_OPTS(ent)); + break; - case OUTPUT_FILE: - printf ("%s\n", file); - break; + case OUTPUT_FILE: + printf("%s\n", file->value); + break; - case OUTPUT_PASSNO: - printf ("%d\n", ENT_PASS (ent)); - break; + case OUTPUT_PASSNO: + printf("%d\n", ENT_PASS(ent)); + break; } } END_ENT; - rc_strlist_free (files); - exit (result); + rc_stringlist_free(files); + exit(result); /* NOTREACHED */ } diff --git a/src/rc/mountinfo.c b/src/rc/mountinfo.c index a05c3929..3adff5de 100644 --- a/src/rc/mountinfo.c +++ b/src/rc/mountinfo.c @@ -47,16 +47,15 @@ #include <errno.h> #include <getopt.h> #include <limits.h> +#include <regex.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <regex.h> #include "builtins.h" #include "einfo.h" #include "rc.h" #include "rc-misc.h" -#include "strlist.h" extern const char *applet; @@ -80,93 +79,93 @@ struct args { regex_t *skip_fstype_regex; regex_t *options_regex; regex_t *skip_options_regex; - char **mounts; + RC_STRINGLIST *mounts; mount_type mount_type; net_opts netdev; }; -static int process_mount (char ***list, struct args *args, - char *from, char *to, char *fstype, char *options, - int netdev) +static int process_mount(RC_STRINGLIST *list, struct args *args, + char *from, char *to, char *fstype, char *options, + int netdev) { char *p; + RC_STRING *s; errno = ENOENT; #ifdef __linux__ /* Skip the really silly rootfs */ - if (strcmp (fstype, "rootfs") == 0) - return (-1); + if (strcmp(fstype, "rootfs") == 0) + return -1; #endif - if (args->netdev == net_yes && (netdev != -1 || args->mounts)) { + if (args->netdev == net_yes && + (netdev != -1 || TAILQ_FIRST(args->mounts))) + { if (netdev != 0) - return (1); - } else if (args->netdev == net_no && (netdev != -1 || args->mounts)) { + return 1; + } else if (args->netdev == net_no && + (netdev != -1 || TAILQ_FIRST(args->mounts))) + { if (netdev != 1) - return (1); + return 1; } else { if (args->node_regex && - regexec (args->node_regex, from, 0, NULL, 0) != 0) - return (1); + regexec(args->node_regex, from, 0, NULL, 0) != 0) + return 1; if (args->skip_node_regex && - regexec (args->skip_node_regex, from, 0, NULL, 0) == 0) - return (1); + regexec(args->skip_node_regex, from, 0, NULL, 0) == 0) + return 1; if (args->fstype_regex && - regexec (args->fstype_regex, fstype, 0, NULL, 0) != 0) - return (-1); + regexec(args->fstype_regex, fstype, 0, NULL, 0) != 0) + return -1; if (args->skip_fstype_regex && - regexec (args->skip_fstype_regex, fstype, 0, NULL, 0) == 0) - return (-1); + regexec(args->skip_fstype_regex, fstype, 0, NULL, 0) == 0) + return -1; if (args->options_regex && - regexec (args->options_regex, options, 0, NULL, 0) != 0) - return (-1); + regexec(args->options_regex, options, 0, NULL, 0) != 0) + return -1; if (args->skip_options_regex && - regexec (args->skip_options_regex, options, 0, NULL, 0) == 0) - return (-1); + regexec(args->skip_options_regex, options, 0, NULL, 0) == 0) + return -1; } - if (args->mounts) { - bool found = false; - int j; - char *mnt; - STRLIST_FOREACH (args->mounts, mnt, j) - if (strcmp (mnt, to) == 0) { - found = true; + if (TAILQ_FIRST(args->mounts)) { + TAILQ_FOREACH(s, args->mounts, entries) + if (strcmp(s->value, to) == 0) break; - } - if (! found) - return (-1); + if (! s) + return -1; } switch (args->mount_type) { - case mount_from: - p = from; - break; - case mount_to: - p = to; - break; - case mount_fstype: - p = fstype; - break; - case mount_options: - p = options; - break; - default: - p = NULL; - errno = EINVAL; - break; + case mount_from: + p = from; + break; + case mount_to: + p = to; + break; + case mount_fstype: + p = fstype; + break; + case mount_options: + p = options; + break; + default: + p = NULL; + errno = EINVAL; + break; } if (p) { errno = 0; - rc_strlist_addsortc (list, p); - return (0); + rc_stringlist_add(list, p); + return 0; } - return (-1); + return -1; } #ifdef BSD @@ -212,70 +211,73 @@ static struct opt { { 0, NULL } }; -static char **find_mounts (struct args *args) +static RC_STRINGLIST *find_mounts(struct args *args) { struct statfs *mnts; int nmnts; int i; - char **list = NULL; + RC_STRINGLIST *list; char *options = NULL; uint64_t flags; struct opt *o; + int netdev; + char *tmp; + size_t l; - if ((nmnts = getmntinfo (&mnts, MNT_NOWAIT)) == 0) - eerrorx ("getmntinfo: %s", strerror (errno)); + if ((nmnts = getmntinfo(&mnts, MNT_NOWAIT)) == 0) + eerrorx("getmntinfo: %s", strerror (errno)); + list = rc_stringlist_new(); for (i = 0; i < nmnts; i++) { - int netdev = 0; + netdev = 0; flags = mnts[i].F_FLAGS & MNT_VISFLAGMASK; for (o = optnames; flags && o->o_opt; o++) { if (flags & o->o_opt) { if (o->o_opt == MNT_LOCAL) netdev = 1; if (! options) - options = xstrdup (o->o_name); + options = xstrdup(o->o_name); else { - char *tmp = NULL; - size_t l = strlen (options) + strlen (o->o_name) + 2; - tmp = xmalloc (sizeof (char) * l); - snprintf (tmp, l, "%s,%s", options, o->o_name); - free (options); + l = strlen(options) + strlen(o->o_name) + 2; + tmp = xmalloc(sizeof (char) * l); + snprintf(tmp, l, "%s,%s", options, o->o_name); + free(options); options = tmp; } } flags &= ~o->o_opt; } - process_mount (&list, args, - mnts[i].f_mntfromname, - mnts[i].f_mntonname, - mnts[i].f_fstypename, - options, - netdev); + process_mount(list, args, + mnts[i].f_mntfromname, + mnts[i].f_mntonname, + mnts[i].f_fstypename, + options, + netdev); - free (options); + free(options); options = NULL; } - return (list); + return list; } #elif defined (__linux__) -static struct mntent *getmntfile (const char *file) +static struct mntent *getmntfile(const char *file) { struct mntent *ent = NULL; FILE *fp; - fp = setmntent ("/etc/fstab", "r"); - while ((ent = getmntent (fp))) - if (strcmp (file, ent->mnt_dir) == 0) + fp = setmntent("/etc/fstab", "r"); + while ((ent = getmntent(fp))) + if (strcmp(file, ent->mnt_dir) == 0) 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; char *buffer; @@ -284,52 +286,54 @@ static char **find_mounts (struct args *args) char *to; char *fst; char *opts; - char **list = NULL; struct mntent *ent; int netdev; + RC_STRINGLIST *list; - if ((fp = fopen ("/proc/mounts", "r")) == NULL) - eerrorx ("getmntinfo: %s", strerror (errno)); + if ((fp = fopen("/proc/mounts", "r")) == NULL) + eerrorx("getmntinfo: %s", strerror(errno)); - buffer = xmalloc (sizeof (char) * PATH_MAX * 3); - while (fgets (buffer, PATH_MAX * 3, fp)) { + list = rc_stringlist_new(); + + buffer = xmalloc(sizeof(char) * PATH_MAX * 3); + while (fgets(buffer, PATH_MAX * 3, fp)) { netdev = -1; p = buffer; - from = strsep (&p, " "); - to = strsep (&p, " "); - fst = strsep (&p, " "); - opts = strsep (&p, " "); + from = strsep(&p, " "); + to = strsep(&p, " "); + fst = strsep(&p, " "); + opts = strsep(&p, " "); - if ((ent = getmntfile (to))) { - if (strstr (ent->mnt_opts, "_netdev")) + if ((ent = getmntfile(to))) { + if (strstr(ent->mnt_opts, "_netdev")) netdev = 0; } - process_mount (&list, args, from, to, fst, opts, netdev); + process_mount(list, args, from, to, fst, opts, netdev); } - free (buffer); - fclose (fp); + free(buffer); + fclose(fp); - return (list); + return list; } #else # error "Operating system not supported!" #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; 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)); - eerrorx ("%s: invalid regex `%s'", applet, buffer); + regerror(result, reg, buffer, sizeof(buffer)); + eerrorx("%s: invalid regex `%s'", applet, buffer); } - return (reg); + return reg; } #include "_usage.h" @@ -347,7 +351,7 @@ static const struct option longopts[] = { { "options", 0, NULL, 'i'}, { "fstype", 0, NULL, 's'}, { "node", 0, NULL, 't'}, - { "netdev", 0, NULL, 'e'}, + { "netdev", 0, NULL, 'e'}, { "nonetdev", 0, NULL, 'E'}, longopts_COMMON }; @@ -369,112 +373,113 @@ static const char * const longopts_help[] = { }; #include "_usage.c" -int mountinfo (int argc, char **argv) +int mountinfo(int argc, char **argv) { - int i; struct args args; regex_t *point_regex = NULL; regex_t *skip_point_regex = NULL; - char **nodes = NULL; - char *n; + RC_STRINGLIST *nodes; + RC_STRING *s; int opt; int result; bool quiet; /* Ensure that we are only quiet when explicitly told to be */ - unsetenv ("EINFO_QUIET"); + unsetenv("EINFO_QUIET"); #define DO_REG(_var) \ - if (_var) free (_var); \ - _var = get_regex (optarg); + if (_var) free(_var); \ + _var = get_regex(optarg); #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.netdev = net_ignore; + args.mounts = rc_stringlist_new(); - while ((opt = getopt_long (argc, argv, getoptstring, - longopts, (int *) 0)) != -1) + while ((opt = getopt_long(argc, argv, getoptstring, + longopts, (int *) 0)) != -1) { switch (opt) { - case 'e': - args.netdev = net_yes; - break; - case 'E': - args.netdev = net_no; - break; - case 'f': - DO_REG (args.fstype_regex); - break; - case 'F': - DO_REG (args.skip_fstype_regex); - break; - case 'n': - DO_REG (args.node_regex); - break; - case 'N': - DO_REG (args.skip_node_regex); - break; - case 'o': - DO_REG (args.options_regex); - break; - case 'O': - DO_REG (args.skip_options_regex); - break; - case 'p': - DO_REG (point_regex); - break; - case 'P': - DO_REG (skip_point_regex); - break; - case 'i': - args.mount_type = mount_options; - break; - case 's': - args.mount_type = mount_fstype; - break; - case 't': - args.mount_type = mount_from; - break; + case 'e': + args.netdev = net_yes; + break; + case 'E': + args.netdev = net_no; + break; + case 'f': + DO_REG(args.fstype_regex); + break; + case 'F': + DO_REG(args.skip_fstype_regex); + break; + case 'n': + DO_REG(args.node_regex); + break; + case 'N': + DO_REG(args.skip_node_regex); + break; + case 'o': + DO_REG(args.options_regex); + break; + case 'O': + DO_REG(args.skip_options_regex); + break; + case 'p': + DO_REG(point_regex); + break; + case 'P': + DO_REG(skip_point_regex); + break; + case 'i': + args.mount_type = mount_options; + break; + case 's': + args.mount_type = mount_fstype; + break; + case 't': + args.mount_type = mount_from; + break; - case_RC_COMMON_GETOPT + case_RC_COMMON_GETOPT } } while (optind < argc) { if (argv[optind][0] != '/') - eerrorx ("%s: `%s' is not a mount point", argv[0], argv[optind]); - rc_strlist_add (&args.mounts, argv[optind++]); + eerrorx("%s: `%s' is not a mount point", argv[0], 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.node_regex); - REG_FREE (args.skip_node_regex); - REG_FREE (args.options_regex); - REG_FREE (args.skip_options_regex); - - rc_strlist_reverse (nodes); + REG_FREE(args.fstype_regex); + REG_FREE(args.skip_fstype_regex); + REG_FREE(args.node_regex); + REG_FREE(args.skip_node_regex); + REG_FREE(args.options_regex); + REG_FREE(args.skip_options_regex); result = EXIT_FAILURE; - quiet = rc_yesno (getenv ("EINFO_QUIET")); - STRLIST_FOREACH (nodes, n, i) { - if (point_regex && regexec (point_regex, n, 0, NULL, 0) != 0) + quiet = rc_yesno(getenv("EINFO_QUIET")); + TAILQ_FOREACH_REVERSE(s, nodes, rc_stringlist, entries) { + if (point_regex && + regexec(point_regex, s->value, 0, NULL, 0) != 0) 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; if (! quiet) - printf ("%s\n", n); + printf("%s\n", s->value); result = EXIT_SUCCESS; } - rc_strlist_free (nodes); + rc_stringlist_free(nodes); - REG_FREE (point_regex); - REG_FREE (skip_point_regex); + REG_FREE(point_regex); + REG_FREE(skip_point_regex); - exit (result); + exit(result); /* NOTREACHED */ } diff --git a/src/rc/rc-applets.c b/src/rc/rc-applets.c index 5f242f70..96b392d8 100644 --- a/src/rc/rc-applets.c +++ b/src/rc/rc-applets.c @@ -35,6 +35,7 @@ #define SYSLOG_NAMES #include <sys/types.h> + #include <errno.h> #include <ctype.h> #include <inttypes.h> @@ -49,26 +50,25 @@ #include "builtins.h" #include "einfo.h" #include "rc-misc.h" -#include "strlist.h" /* Applet is first parsed in rc.c - no point in doing it again */ extern const char *applet; -static int syslog_decode (char *name, CODE *codetab) +static int syslog_decode(char *name, CODE *codetab) { CODE *c; - if (isdigit ((int) *name)) - return (atoi (name)); + if (isdigit((int) *name)) + return atoi(name); for (c = codetab; c->c_name; c++) - if (! strcasecmp (name, c->c_name)) - return (c->c_val); + if (! strcasecmp(name, c->c_name)) + 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 i; @@ -82,42 +82,42 @@ static int do_e (int argc, char **argv) argc--; argv++; - if (strcmp (applet, "eval_ecolors") == 0) { - printf ("GOOD='%s'\nWARN='%s'\nBAD='%s'\nHILITE='%s'\nBRACKET='%s'\nNORMAL='%s'\n", - ecolor (ECOLOR_GOOD), - ecolor (ECOLOR_WARN), - ecolor (ECOLOR_BAD), - ecolor (ECOLOR_HILITE), - ecolor (ECOLOR_BRACKET), - ecolor (ECOLOR_NORMAL)); - exit (EXIT_SUCCESS); + if (strcmp(applet, "eval_ecolors") == 0) { + printf("GOOD='%s'\nWARN='%s'\nBAD='%s'\nHILITE='%s'\nBRACKET='%s'\nNORMAL='%s'\n", + ecolor(ECOLOR_GOOD), + ecolor(ECOLOR_WARN), + ecolor(ECOLOR_BAD), + ecolor(ECOLOR_HILITE), + ecolor(ECOLOR_BRACKET), + ecolor(ECOLOR_NORMAL)); + exit(EXIT_SUCCESS); } if (argc > 0) { - if (strcmp (applet, "eend") == 0 || - strcmp (applet, "ewend") == 0 || - strcmp (applet, "veend") == 0 || - strcmp (applet, "vweend") == 0) + if (strcmp(applet, "eend") == 0 || + strcmp(applet, "ewend") == 0 || + strcmp(applet, "veend") == 0 || + strcmp(applet, "vweend") == 0) { errno = 0; - retval = (int) strtoimax (argv[0], NULL, 0); + retval = (int) strtoimax(argv[0], NULL, 0); if (errno != 0) retval = EXIT_FAILURE; else { argc--; argv++; } - } else if (strcmp (applet, "esyslog") == 0 || - strcmp (applet, "elog") == 0) { - char *dot = strchr (argv[0], '.'); - if ((level = syslog_decode (dot + 1, prioritynames)) == -1) - eerrorx ("%s: invalid log level `%s'", applet, argv[0]); + } else if (strcmp(applet, "esyslog") == 0 || + strcmp(applet, "elog") == 0) { + p = strchr(argv[0], '.'); + if ((level = syslog_decode(p + 1, prioritynames)) == -1) + eerrorx("%s: invalid log level `%s'", applet, argv[0]); if (argc < 3) - eerrorx ("%s: not enough arguments", applet); + eerrorx("%s: not enough arguments", applet); - unsetenv ("EINFO_LOG"); - setenv ("EINFO_LOG", argv[1], 1); + unsetenv("EINFO_LOG"); + setenv("EINFO_LOG", argv[1], 1); argc -= 2; argv += 2; @@ -126,16 +126,17 @@ static int do_e (int argc, char **argv) if (argc > 0) { for (i = 0; i < argc; i++) - l += strlen (argv[i]) + 1; + l += strlen(argv[i]) + 1; - message = xmalloc (l); + message = xmalloc(l); p = message; for (i = 0; i < argc; i++) { if (i > 0) *p++ = ' '; - memcpy (p, argv[i], strlen (argv[i])); - p += strlen (argv[i]); + l = strlen(argv[i]); + memcpy(p, argv[i], l); + p += l; } *p = 0; } @@ -143,300 +144,302 @@ static int do_e (int argc, char **argv) if (! message) fmt = ""; - if (strcmp (applet, "einfo") == 0) - einfo (fmt, message); - else if (strcmp (applet, "einfon") == 0) - einfon (fmt, message); - else if (strcmp (applet, "ewarn") == 0) - ewarn (fmt, message); - else if (strcmp (applet, "ewarnn") == 0) - ewarnn (fmt, message); - else if (strcmp (applet, "eerror") == 0) { - eerror (fmt, message); + if (strcmp(applet, "einfo") == 0) + einfo(fmt, message); + else if (strcmp(applet, "einfon") == 0) + einfon(fmt, message); + else if (strcmp(applet, "ewarn") == 0) + ewarn(fmt, message); + else if (strcmp(applet, "ewarnn") == 0) + ewarnn(fmt, message); + else if (strcmp(applet, "eerror") == 0) { + eerror(fmt, message); retval = 1; - } else if (strcmp (applet, "eerrorn") == 0) { - eerrorn (fmt, message); + } else if (strcmp(applet, "eerrorn") == 0) { + eerrorn(fmt, message); retval = 1; - } else if (strcmp (applet, "ebegin") == 0) - ebegin (fmt, message); - else if (strcmp (applet, "eend") == 0) - eend (retval, fmt, message); - else if (strcmp (applet, "ewend") == 0) - ewend (retval, fmt, message); - else if (strcmp (applet, "esyslog") == 0) - elog (level, fmt, message); - else if (strcmp (applet, "veinfo") == 0) - einfov (fmt, message); - else if (strcmp (applet, "veinfon") == 0) - einfovn (fmt, message); - else if (strcmp (applet, "vewarn") == 0) - ewarnv (fmt, message); - else if (strcmp (applet, "vewarnn") == 0) - ewarnvn (fmt, message); - else if (strcmp (applet, "vebegin") == 0) - ebeginv (fmt, message); - else if (strcmp (applet, "veend") == 0) - eendv (retval, fmt, message); - else if (strcmp (applet, "vewend") == 0) - ewendv (retval, fmt, message); - else if (strcmp (applet, "eindent") == 0) - eindent (); - else if (strcmp (applet, "eoutdent") == 0) - eoutdent (); - else if (strcmp (applet, "veindent") == 0) - eindentv (); - else if (strcmp (applet, "veoutdent") == 0) - eoutdentv (); + } else if (strcmp(applet, "ebegin") == 0) + ebegin(fmt, message); + else if (strcmp(applet, "eend") == 0) + eend(retval, fmt, message); + else if (strcmp(applet, "ewend") == 0) + ewend(retval, fmt, message); + else if (strcmp(applet, "esyslog") == 0) + elog(level, fmt, message); + else if (strcmp(applet, "veinfo") == 0) + einfov(fmt, message); + else if (strcmp(applet, "veinfon") == 0) + einfovn(fmt, message); + else if (strcmp(applet, "vewarn") == 0) + ewarnv(fmt, message); + else if (strcmp(applet, "vewarnn") == 0) + ewarnvn(fmt, message); + else if (strcmp(applet, "vebegin") == 0) + ebeginv(fmt, message); + else if (strcmp(applet, "veend") == 0) + eendv(retval, fmt, message); + else if (strcmp(applet, "vewend") == 0) + ewendv(retval, fmt, message); + else if (strcmp(applet, "eindent") == 0) + eindent(); + else if (strcmp(applet, "eoutdent") == 0) + eoutdent(); + else if (strcmp(applet, "veindent") == 0) + eindentv(); + else if (strcmp(applet, "veoutdent") == 0) + eoutdentv(); else { - eerror ("%s: unknown applet", applet); + eerror("%s: unknown applet", applet); retval = EXIT_FAILURE; } - free (message); - return (retval); + free(message); + return retval; } -static int do_service (int argc, char **argv) +static int do_service(int argc, char **argv) { bool ok = false; char *service = NULL; + int idx = 0; + char *d[] = { NULL, NULL }; if (argc > 1) service = argv[1]; else - service = getenv ("SVCNAME"); + service = getenv("SVCNAME"); if (! service || *service == '\0') - eerrorx ("%s: no service specified", applet); - - if (strcmp (applet, "service_started") == 0) - ok = (rc_service_state (service) & RC_SERVICE_STARTED); - else if (strcmp (applet, "service_stopped") == 0) - ok = (rc_service_state (service) & RC_SERVICE_STOPPED); - else if (strcmp (applet, "service_inactive") == 0) - ok = (rc_service_state (service) & RC_SERVICE_INACTIVE); - else if (strcmp (applet, "service_starting") == 0) - ok = (rc_service_state (service) & RC_SERVICE_STARTING); - else if (strcmp (applet, "service_stopping") == 0) - ok = (rc_service_state (service) & RC_SERVICE_STOPPING); - else if (strcmp (applet, "service_coldplugged") == 0) - ok = (rc_service_state (service) & RC_SERVICE_COLDPLUGGED); - else if (strcmp (applet, "service_wasinactive") == 0) - ok = (rc_service_state (service) & RC_SERVICE_WASINACTIVE); - else if (strcmp (applet, "service_started_daemon") == 0) { - int idx = 0; - char *d[] = { argv[1], NULL }; - - service = getenv ("SVCNAME"); + eerrorx("%s: no service specified", applet); + + if (strcmp(applet, "service_started") == 0) + ok = (rc_service_state(service) & RC_SERVICE_STARTED); + else if (strcmp(applet, "service_stopped") == 0) + ok = (rc_service_state(service) & RC_SERVICE_STOPPED); + else if (strcmp(applet, "service_inactive") == 0) + ok = (rc_service_state(service) & RC_SERVICE_INACTIVE); + else if (strcmp(applet, "service_starting") == 0) + ok = (rc_service_state(service) & RC_SERVICE_STARTING); + else if (strcmp(applet, "service_stopping") == 0) + ok = (rc_service_state(service) & RC_SERVICE_STOPPING); + else if (strcmp(applet, "service_coldplugged") == 0) + ok = (rc_service_state(service) & RC_SERVICE_COLDPLUGGED); + else if (strcmp(applet, "service_wasinactive") == 0) + ok = (rc_service_state(service) & RC_SERVICE_WASINACTIVE); + else if (strcmp(applet, "service_started_daemon") == 0) { + d[0] = argv[1]; + + service = getenv("SVCNAME"); if (argc > 3) { service = argv[1]; d[0] = argv[2]; - sscanf (argv[3], "%d", &idx); + sscanf(argv[3], "%d", &idx); } else if (argc == 3) { - if (sscanf (argv[2], "%d", &idx) != 1) { + if (sscanf(argv[2], "%d", &idx) != 1) { service = argv[1]; - *d = argv[2]; + d[0] = argv[2]; } } - ok = rc_service_started_daemon (service, - (const char * const *)d, idx); + ok = rc_service_started_daemon(service, + (const char * const *)d, idx); } 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; - char *svcname = getenv ("SVCNAME"); + char *svcname = getenv("SVCNAME"); char *service = NULL; + char *runscript_pid; + char *mtime; + pid_t pid; + size_t l; if (argc > 1) service = argv[1]; else - service = getenv ("SVCNAME"); + service = getenv("SVCNAME"); if (! service || *service == '\0') - eerrorx ("%s: no service specified", applet); - - if (strcmp (applet, "mark_service_started") == 0) - ok = rc_service_mark (service, RC_SERVICE_STARTED); - else if (strcmp (applet, "mark_service_stopped") == 0) - ok = rc_service_mark (service, RC_SERVICE_STOPPED); - else if (strcmp (applet, "mark_service_inactive") == 0) - ok = rc_service_mark (service, RC_SERVICE_INACTIVE); - else if (strcmp (applet, "mark_service_starting") == 0) - ok = rc_service_mark (service, RC_SERVICE_STARTING); - else if (strcmp (applet, "mark_service_stopping") == 0) - ok = rc_service_mark (service, RC_SERVICE_STOPPING); - else if (strcmp (applet, "mark_service_coldplugged") == 0) - ok = rc_service_mark (service, RC_SERVICE_COLDPLUGGED); - else if (strcmp (applet, "mark_service_failed") == 0) - ok = rc_service_mark (service, RC_SERVICE_FAILED); + eerrorx("%s: no service specified", applet); + + if (strcmp(applet, "mark_service_started") == 0) + ok = rc_service_mark(service, RC_SERVICE_STARTED); + else if (strcmp(applet, "mark_service_stopped") == 0) + ok = rc_service_mark(service, RC_SERVICE_STOPPED); + else if (strcmp(applet, "mark_service_inactive") == 0) + ok = rc_service_mark(service, RC_SERVICE_INACTIVE); + else if (strcmp(applet, "mark_service_starting") == 0) + ok = rc_service_mark(service, RC_SERVICE_STARTING); + else if (strcmp(applet, "mark_service_stopping") == 0) + ok = rc_service_mark(service, RC_SERVICE_STOPPING); + else if (strcmp(applet, "mark_service_coldplugged") == 0) + ok = rc_service_mark(service, RC_SERVICE_COLDPLUGGED); + else if (strcmp(applet, "mark_service_failed") == 0) + ok = rc_service_mark(service, RC_SERVICE_FAILED); else - eerrorx ("%s: unknown applet", applet); + eerrorx("%s: unknown applet", applet); /* 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 */ - if (ok && svcname && strcmp (svcname, service) == 0) { - char *runscript_pid = getenv ("RC_RUNSCRIPT_PID"); - char *mtime; - pid_t pid = 0; - size_t l; - - 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)); + if (ok && svcname && strcmp(svcname, service) == 0) { + runscript_pid = getenv("RC_RUNSCRIPT_PID"); + 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 in control as well */ - l = strlen (RC_SVCDIR "exclusive") + - strlen (svcname) + - strlen (runscript_pid) + - 4; - mtime = xmalloc (l); - snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s", - svcname, runscript_pid); - if (exists (mtime) && unlink (mtime) != 0) - eerror ("%s: unlink: %s", applet, strerror (errno)); - free (mtime); + l = strlen(RC_SVCDIR "exclusive") + strlen(svcname) + + strlen(runscript_pid) + 4; + mtime = xmalloc(l); + snprintf(mtime, l, RC_SVCDIR "exclusive/%s.%s", + svcname, runscript_pid); + if (exists(mtime) && unlink(mtime) != 0) + 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; - char *service = getenv ("SVCNAME"); + char *service = getenv("SVCNAME"); + char *option; if (! service) - eerrorx ("%s: no service specified", applet); + eerrorx("%s: no service specified", applet); 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 || - strcmp (applet, "get_options") == 0) + if (strcmp(applet, "service_get_value") == 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) { - printf ("%s", option); - free (option); + printf("%s", option); + free(option); ok = true; } - } else if (strcmp (applet, "service_set_value") == 0 || - strcmp (applet, "save_options") == 0) - ok = rc_service_value_set (service, argv[1], argv[2]); + } else if (strcmp(applet, "service_set_value") == 0 || + strcmp(applet, "save_options") == 0) + ok = rc_service_value_set(service, argv[1], argv[2]); 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; + char *p; + int c; for (i = 1; i < argc; i++) { - char *p = argv[i]; + p = argv[i]; if (i != 1) - putchar (' '); + putchar(' '); while (*p) { - char c = *p++; - if (! isalnum ((int) c)) + c = *p++; + if (! isalnum(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 */ - if (strcmp (applet, "fstabinfo") == 0) - exit (fstabinfo (argc, argv)); - else if (strcmp (applet, "mountinfo") == 0) - exit (mountinfo (argc, argv)); - else if (strcmp (applet, "rc-depend") == 0) - exit (rc_depend (argc, argv)); - else if (strcmp (applet, "rc-status") == 0) - exit (rc_status (argc, argv)); - else if (strcmp (applet, "rc-update") == 0 || - strcmp (applet, "update-rc") == 0) - exit (rc_update (argc, argv)); - else if (strcmp (applet, "runscript") == 0) - exit (runscript (argc, argv)); - else if (strcmp (applet, "start-stop-daemon") == 0) - exit (start_stop_daemon (argc, argv)); + if (strcmp(applet, "fstabinfo") == 0) + exit(fstabinfo(argc, argv)); + else if (strcmp(applet, "mountinfo") == 0) + exit(mountinfo(argc, argv)); + else if (strcmp(applet, "rc-depend") == 0) + exit(rc_depend(argc, argv)); + else if (strcmp(applet, "rc-status") == 0) + exit(rc_status(argc, argv)); + else if (strcmp(applet, "rc-update") == 0 || + strcmp(applet, "update-rc") == 0) + exit(rc_update(argc, argv)); + else if (strcmp(applet, "runscript") == 0) + exit(runscript(argc, argv)); + else if (strcmp(applet, "start-stop-daemon") == 0) + exit(start_stop_daemon(argc, argv)); else if (strcmp (applet, "checkpath") == 0) - exit (checkpath (argc, argv)); + exit(checkpath(argc, argv)); /* These could also be applications in their own right */ - if (strcmp (applet, "shell_var") == 0) - exit (do_shell_var (argc, argv)); + if (strcmp(applet, "shell_var") == 0) + exit(do_shell_var(argc, argv)); - if (strcmp (applet, "is_newer_than") == 0 || - strcmp (applet, "is_older_than") == 0) + if (strcmp(applet, "is_newer_than") == 0 || + strcmp(applet, "is_older_than") == 0) { - bool match = false; - int i = 2; - if (argc < 3) exit (EXIT_FAILURE); - if (strcmp (applet, "is_newer_than") == 0) + if (strcmp(applet, "is_newer_than") == 0) match = true; 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_SUCCESS); + exit(EXIT_SUCCESS); }; 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 * anything else */ - if (strcmp (applet, "service_get_value") == 0 || - strcmp (applet, "service_set_value") == 0 || - strcmp (applet, "get_options") == 0 || - strcmp (applet, "save_options") == 0) - exit (do_value (argc, argv)); + if (strcmp(applet, "service_get_value") == 0 || + strcmp(applet, "service_set_value") == 0 || + strcmp(applet, "get_options") == 0 || + strcmp(applet, "save_options") == 0) + exit(do_value(argc, argv)); - if (strncmp (applet, "service_", strlen ("service_")) == 0) - exit (do_service (argc, argv)); + if (strncmp(applet, "service_", strlen("service_")) == 0) + exit(do_service(argc, argv)); - if (strncmp (applet, "mark_service_", strlen ("mark_service_")) == 0) - exit (do_mark_service (argc, argv)); + if (strncmp(applet, "mark_service_", strlen("mark_service_")) == 0) + exit(do_mark_service(argc, argv)); - if (strcmp (applet, "is_runlevel_start") == 0) - exit (rc_runlevel_starting () ? 0 : 1); + if (strcmp(applet, "is_runlevel_start") == 0) + exit(rc_runlevel_starting() ? 0 : 1); else if (strcmp (applet, "is_runlevel_stop") == 0) - exit (rc_runlevel_stopping () ? 0 : 1); - - if (strcmp (applet, "rc-abort") == 0) { - char *p = getenv ("RC_PID"); - pid_t pid = 0; - - if (p && sscanf (p, "%d", &pid) == 1) { - if (kill (pid, SIGUSR1) != 0) - eerrorx ("rc-abort: failed to signal parent %d: %s", - pid, strerror (errno)); - exit (EXIT_SUCCESS); + exit(rc_runlevel_stopping() ? 0 : 1); + + if (strcmp(applet, "rc-abort") == 0) { + p = getenv("RC_PID"); + if (p && sscanf(p, "%d", &pid) == 1) { + if (kill(pid, SIGUSR1) != 0) + eerrorx("rc-abort: failed to signal parent %d: %s", + pid, strerror(errno)); + exit(EXIT_SUCCESS); } - exit (EXIT_FAILURE); + exit(EXIT_FAILURE); } - if (strcmp (applet, "rc" ) != 0) - eerrorx ("%s: unknown applet", applet); + if (strcmp(applet, "rc") != 0) + eerrorx("%s: unknown applet", applet); } diff --git a/src/rc/rc-depend.c b/src/rc/rc-depend.c index 0eda7f0f..33a50f06 100644 --- a/src/rc/rc-depend.c +++ b/src/rc/rc-depend.c @@ -45,34 +45,33 @@ #include "einfo.h" #include "rc.h" #include "rc-misc.h" -#include "strlist.h" extern const char *applet; -rc_depinfo_t *_rc_deptree_load (int *regen) { - if (rc_deptree_update_needed ()) { - int fd; - int retval; - int serrno = errno; - int merrno; +RC_DEPTREE *_rc_deptree_load(int *regen) { + int fd; + int retval; + int serrno = errno; + int merrno; + if (rc_deptree_update_needed()) { /* Test if we have permission to update the deptree */ - fd = open (RC_DEPTREE, O_WRONLY); + fd = open(RC_DEPTREE_CACHE, O_WRONLY); merrno = errno; errno = serrno; if (fd == -1 && merrno == EACCES) - return (rc_deptree_load ()); - close (fd); + return rc_deptree_load(); + close(fd); if (regen) *regen = 1; - ebegin ("Caching service dependencies"); - retval = rc_deptree_update (); + ebegin("Caching service dependencies"); + retval = rc_deptree_update(); eend (retval ? 0 : -1, "Failed to update the dependency tree"); } - return (rc_deptree_load ()); + return rc_deptree_load(); } #include "_usage.h" @@ -97,117 +96,114 @@ static const char * const longopts_help[] = { }; #include "_usage.c" -int rc_depend (int argc, char **argv) +int rc_depend(int argc, char **argv) { - char **types = NULL; - char **services = NULL; - char **depends = NULL; - char **list; - rc_depinfo_t *deptree = NULL; - char *service; + RC_STRINGLIST *list; + RC_STRINGLIST *types; + RC_STRINGLIST *services; + RC_STRINGLIST *depends; + RC_STRING *s; + RC_DEPTREE *deptree = NULL; int options = RC_DEP_TRACE; bool first = true; - int i; bool update = false; - char *runlevel = xstrdup( getenv ("RC_SOFTLEVEL")); + char *runlevel = xstrdup(getenv("RC_SOFTLEVEL")); int opt; char *token; - while ((opt = getopt_long (argc, argv, getoptstring, - longopts, (int *) 0)) != -1) + types = rc_stringlist_new(); + + while ((opt = getopt_long(argc, argv, getoptstring, + longopts, (int *) 0)) != -1) { switch (opt) { - case 'a': - options |= RC_DEP_START; - break; - case 'o': - options |= RC_DEP_STOP; - break; - case 's': - options |= RC_DEP_STRICT; - break; - case 't': - while ((token = strsep (&optarg, ","))) - rc_strlist_addu (&types, token); - break; - case 'u': - update = true; - break; - case 'T': - options &= RC_DEP_TRACE; - break; - - case_RC_COMMON_GETOPT + case 'a': + options |= RC_DEP_START; + break; + case 'o': + options |= RC_DEP_STOP; + break; + case 's': + options |= RC_DEP_STRICT; + break; + case 't': + while ((token = strsep(&optarg, ","))) + rc_stringlist_add(types, token); + break; + case 'u': + update = true; + break; + case 'T': + options &= RC_DEP_TRACE; + break; + + case_RC_COMMON_GETOPT } } if (update) { - bool u = false; - ebegin ("Caching service dependencies"); - u = rc_deptree_update (); - eend (u ? 0 : -1, "%s: %s", applet, strerror (errno)); - if (! u) - eerrorx ("Failed to update the dependency tree"); + ebegin("Caching service dependencies"); + update = rc_deptree_update(); + eend(update ? 0 : -1, "%s: %s", applet, strerror(errno)); + if (! update) + eerrorx("Failed to update the dependency tree"); } - if (! (deptree = _rc_deptree_load (NULL))) - eerrorx ("failed to load deptree"); + if (! (deptree = _rc_deptree_load(NULL))) + eerrorx("failed to load deptree"); if (! runlevel) - runlevel = rc_runlevel_get (); + runlevel = rc_runlevel_get(); + services = rc_stringlist_new(); while (optind < argc) { - list = NULL; - rc_strlist_add (&list, argv[optind]); + list = rc_stringlist_new(); + rc_stringlist_add(list, argv[optind]); errno = 0; - depends = rc_deptree_depends (deptree, NULL, (const char **) list, - runlevel, 0); + depends = rc_deptree_depends(deptree, NULL, list, runlevel, 0); if (! depends && errno == ENOENT) - eerror ("no dependency info for service `%s'", argv[optind]); + eerror("no dependency info for service `%s'", argv[optind]); else - rc_strlist_add (&services, argv[optind]); + rc_stringlist_add(services, argv[optind]); - rc_strlist_free (depends); - rc_strlist_free (list); + rc_stringlist_free(depends); + rc_stringlist_free(list); optind++; } - - if (! services) { - rc_strlist_free (types); - rc_deptree_free (deptree); - free (runlevel); + if (! TAILQ_FIRST(services)) { + rc_stringlist_free(services); + rc_stringlist_free(types); + rc_deptree_free(deptree); + free(runlevel); if (update) - return (EXIT_SUCCESS); - eerrorx ("no services specified"); + return EXIT_SUCCESS; + eerrorx("no services specified"); } /* If we don't have any types, then supply some defaults */ - if (! types) { - rc_strlist_add (&types, "ineed"); - rc_strlist_add (&types, "iuse"); + if (! TAILQ_FIRST(types)) { + rc_stringlist_add(types, "ineed"); + rc_stringlist_add(types, "iuse"); } - depends = rc_deptree_depends (deptree, (const char **) types, - (const char **) services, runlevel, options); + depends = rc_deptree_depends(deptree, types, services, runlevel, options); - if (depends) { - STRLIST_FOREACH (depends, service, i) { + if (TAILQ_FIRST(depends)) { + TAILQ_FOREACH(s, depends, entries) { if (first) first = false; else printf (" "); - - if (service) - printf ("%s", service); + printf ("%s", s->value); } printf ("\n"); } - rc_strlist_free (types); - rc_strlist_free (services); - rc_strlist_free (depends); - rc_deptree_free (deptree); - free (runlevel); - return (EXIT_SUCCESS); + rc_stringlist_free(types); + rc_stringlist_free(services); + rc_stringlist_free(depends); + rc_deptree_free(deptree); + free(runlevel); + return EXIT_SUCCESS; } diff --git a/src/rc/rc-logger.c b/src/rc/rc-logger.c index 3e02a1aa..b4e4e352 100644 --- a/src/rc/rc-logger.c +++ b/src/rc/rc-logger.c @@ -33,6 +33,7 @@ #include <sys/types.h> #include <sys/ioctl.h> #include <sys/wait.h> + #include <ctype.h> #include <fcntl.h> #include <signal.h> @@ -76,67 +77,67 @@ pid_t rc_logger_pid = -1; int rc_logger_tty = -1; 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; while ((size_t) (p - buffer) < bytes) { switch (*p) { - case '\r': - goto cont; - case '\033': - in_escape = true; - in_term = false; - goto cont; - case '\n': - in_escape = in_term = false; - break; - case '[': - if (in_escape) - in_term = true; - break; + case '\r': + goto cont; + case '\033': + in_escape = true; + in_term = false; + goto cont; + case '\n': + in_escape = in_term = false; + break; + case '[': + if (in_escape) + in_term = true; + break; } if (! in_escape) { - write (logfd, p++, 1); + write(logfd, p++, 1); continue; } - if (! in_term || isalpha ((int) *p)) + if (! in_term || isalpha((int) *p)) in_escape = in_term = false; cont: p++; } } - -static void write_time (FILE *f, const char *s) +static void write_time(FILE *f, const char *s) { - time_t now = time (NULL); - struct tm *tm = localtime (&now); + time_t now = time(NULL); + struct tm *tm = localtime(&now); - fprintf (f, "\nrc %s logging %s at %s\n", runlevel, s, asctime (tm)); - fflush (f); + fprintf(f, "\nrc %s logging %s at %s\n", runlevel, s, asctime(tm)); + fflush(f); } -void rc_logger_close () +void rc_logger_close(void) { + int sig = SIGTERM; + if (signal_pipe[1] > -1) { - int sig = SIGTERM; - write (signal_pipe[1], &sig, sizeof (sig)); - close (signal_pipe[1]); + write(signal_pipe[1], &sig, sizeof(sig)); + close(signal_pipe[1]); signal_pipe[1] = -1; } if (rc_logger_pid > 0) - waitpid (rc_logger_pid, 0, 0); + waitpid(rc_logger_pid, 0, 0); if (fd_stdout > -1) - dup2 (fd_stdout, STDOUT_FILENO); + dup2(fd_stdout, STDOUT_FILENO); 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; struct termios tt; @@ -149,125 +150,127 @@ void rc_logger_open (const char *level) int i; FILE *log = NULL; - if (! isatty (STDOUT_FILENO)) + if (! isatty(STDOUT_FILENO)) return; - if (! rc_conf_yesno ("rc_logger")) + if (! rc_conf_yesno("rc_logger")) return; - if (pipe (signal_pipe) == -1) - eerrorx ("pipe: %s", strerror (errno)); + if (pipe(signal_pipe) == -1) + eerrorx("pipe: %s", strerror(errno)); for (i = 0; i < 2; i++) if ((s = fcntl (signal_pipe[i], F_GETFD, 0) == -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); - ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws); + tcgetattr(STDOUT_FILENO, &tt); + ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws); /* /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; - if ((s = fcntl (rc_logger_tty, F_GETFD, 0)) == 0) - fcntl (rc_logger_tty, F_SETFD, s | FD_CLOEXEC); + if ((s = fcntl(rc_logger_tty, F_GETFD, 0)) == 0) + fcntl(rc_logger_tty, F_SETFD, s | FD_CLOEXEC); - if ((s = fcntl (slave_tty, F_GETFD, 0)) == 0) - fcntl (slave_tty, F_SETFD, s | FD_CLOEXEC); + if ((s = fcntl(slave_tty, F_GETFD, 0)) == 0) + fcntl(slave_tty, F_SETFD, s | FD_CLOEXEC); - rc_logger_pid = fork (); + rc_logger_pid = fork(); switch (rc_logger_pid) { - case -1: - eerror ("forkpty: %s", strerror (errno)); - break; - case 0: - rc_in_logger = true; - close (signal_pipe[1]); - signal_pipe[1] = -1; - - runlevel = level; - if ((log = fopen (LOGFILE, "a"))) - write_time (log, "started"); - else { - free (logbuf); - logbuf_size = BUFSIZ * 10; - logbuf = xmalloc (sizeof (char) * logbuf_size); - logbuf_len = 0; - } + case -1: + eerror("fork: %s", strerror(errno)); + break; + case 0: + rc_in_logger = true; + close(signal_pipe[1]); + signal_pipe[1] = -1; - 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); + runlevel = level; + if ((log = fopen(LOGFILE, "a"))) + write_time(log, "started"); + else { + free(logbuf); + logbuf_size = BUFSIZ * 10; + logbuf = xmalloc(sizeof (char) * logbuf_size); + logbuf_len = 0; + } - if ((s = select (selfd + 1, &rset, NULL, NULL, NULL)) == -1) { - eerror ("select: %s", strerror (errno)); - break; - } + 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 > 0) { - if (FD_ISSET (rc_logger_tty, &rset)) { - memset (buffer, 0, BUFSIZ); - 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; + if ((s = select(selfd + 1, &rset, NULL, NULL, NULL)) == -1) { + eerror("select: %s", strerror(errno)); + break; + } + + if (s > 0) { + if (FD_ISSET(rc_logger_tty, &rset)) { + memset(buffer, 0, BUFSIZ); + 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); } - } - /* 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); + memcpy(logbuf + logbuf_len, buffer, bytes); + logbuf_len += bytes; + } } - free (logbuf); + + /* Only SIGTERMS signals come down this pipe */ + if (FD_ISSET(signal_pipe[0], &rset)) + break; } - if (log) { - write_time (log, "stopped"); - fclose (log); + } + 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 - * punt it */ - system (MOVELOG); - - exit (0); - /* NOTREACHED */ - default: - 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) - 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; + /* Try and cat our new logfile to a more permament location and then + * punt it */ + system(MOVELOG); + + exit(0); + /* NOTREACHED */ + + default: + 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) + 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; } } diff --git a/src/rc/rc-misc.c b/src/rc/rc-misc.c index 343a1534..3167f26b 100644 --- a/src/rc/rc-misc.c +++ b/src/rc/rc-misc.c @@ -30,13 +30,13 @@ */ #include <sys/types.h> +#include <sys/utsname.h> #ifdef __linux__ #include <sys/sysinfo.h> #include <regex.h> #endif -#include <sys/utsname.h> #include <ctype.h> #include <limits.h> #include <signal.h> @@ -47,7 +47,6 @@ #include "einfo.h" #include "rc.h" #include "rc-misc.h" -#include "strlist.h" #define PROFILE_ENV SYSCONFDIR "/profile.env" #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" -static char **rc_conf = NULL; +static RC_STRINGLIST *rc_conf = NULL; + +extern char** environ; -static void _free_rc_conf (void) +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) { - char *line; - int i; + RC_STRINGLIST *old; + RC_STRING *s; + char *p; - rc_conf = rc_config_load (RC_CONF); - atexit (_free_rc_conf); + if (! rc_conf) { + rc_conf = rc_config_load(RC_CONF); + atexit(_free_rc_conf); /* Support old configs */ - if (exists (RC_CONF_OLD)) { - char **old = rc_config_load (RC_CONF_OLD); - rc_strlist_join (&rc_conf, old); - rc_strlist_free (old); + if (exists(RC_CONF_OLD)) { + old = rc_config_load(RC_CONF_OLD); + if (old) { + TAILQ_CONCAT(rc_conf, old); + free(old); + } } /* Convert old uppercase to lowercase */ - STRLIST_FOREACH (rc_conf, line, i) { - char *p = line; + TAILQ_FOREACH(s, rc_conf, entries) { + p = s->value; while (p && *p && *p != '=') { - if (isupper ((int) *p)) - *p = tolower ((int) *p); + if (isupper((int) *p)) + *p = tolower((int) *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; - char **whitelist = NULL; - char *env_name = NULL; - char **profile = NULL; - int count = 0; - bool got_path = false; - char *env_var; - size_t env_len; - char *token; - char *sep; + RC_STRINGLIST *env_allow; + RC_STRINGLIST *profile = NULL; + RC_STRINGLIST *env_list; + RC_STRING *env; + RC_STRING *s; + char *env_name; char *e; - char *p; - size_t pplen = strlen (PATH_PREFIX); - - /* 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"); + char *token; + size_t i = 0; /* Add the user defined list of vars */ - e = env_name = xstrdup (rc_conf_value ("rc_env_allow")); - while ((token = strsep (&e, " "))) { + env_allow = rc_stringlist_new(); + e = env_name = xstrdup(rc_conf_value ("rc_env_allow")); + while ((token = strsep(&e, " "))) { if (token[0] == '*') { - free (env_name); - return (NULL); + free(env_name); + rc_stringlist_free(env_allow); + return; } - rc_strlist_add (&whitelist, token); + rc_stringlist_add(env_allow, token); } - free (env_name); - - if (exists (PROFILE_ENV)) - profile = rc_config_load (PROFILE_ENV); + free(env_name); - STRLIST_FOREACH (whitelist, env_name, count) { - char *space = strchr (env_name, ' '); - if (space) - *space = 0; + if (exists(PROFILE_ENV)) + profile = rc_config_load(PROFILE_ENV); - env_var = getenv (env_name); + /* Copy the env and work from this so we can remove safely */ + env_list = rc_stringlist_new(); + while (environ[i]) + rc_stringlist_add(env_list, environ[i++]); - if (! env_var && profile) { - env_len = strlen (env_name) + strlen ("export ") + 1; - p = xmalloc (sizeof (char) * env_len); - snprintf (p, env_len, "export %s", env_name); - env_var = rc_config_value ((const char *const *) profile, p); - free (p); + TAILQ_FOREACH(env, env_list, entries) { + /* Check the whitelist */ + i = 0; + while (env_whitelist[i]) { + if (strcmp(env_whitelist[i++], env->value)) + break; } + if (env_whitelist[i]) + continue; - if (! env_var) + /* Check our user defined list */ + TAILQ_FOREACH(s, env_allow, entries) + if (strcmp(s->value, env->value) == 0) + break; + if (s) continue; - /* Ensure our PATH is prefixed with the system locations first - for a little extra security */ - if (strcmp (env_name, "PATH") == 0 && - strncmp (PATH_PREFIX, env_var, pplen) != 0) - { - got_path = true; - 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 */ - 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); - } + /* Now check our profile */ - rc_strlist_add (&env, e); - free (e); + /* OK, not allowed! */ + e = strchr(env->value, '='); + *e = '\0'; + unsetenv(env->value); } - - /* We filtered the env but didn't get a PATH? Very odd. - However, we do need a path, so use a default. */ - 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); + rc_stringlist_free(env_list); + rc_stringlist_free(env_allow); + rc_stringlist_free(profile); } -char **env_config (void) +void env_config(void) { - char **env = NULL; - char *line; + size_t pplen = strlen(PATH_PREFIX); + char *path; + char *p; + char *e; size_t l; - const char *sys = rc_sys (); struct utsname uts; FILE *fp; + char *token; + char *np; + char *npp; + char *tok; + const char *sys = rc_sys(); char buffer[PATH_MAX]; - char *runlevel = rc_runlevel_get (); - - /* One char less to drop the trailing / */ - l = strlen ("RC_LIBDIR=") + strlen (RC_LIBDIR) + 1; - line = xmalloc (sizeof (char) * l); - snprintf (line, l, "RC_LIBDIR=" RC_LIBDIR); - rc_strlist_add (&env, line); - free (line); - - /* One char less to drop the trailing / */ - l = strlen ("RC_SVCDIR=") + strlen (RC_SVCDIR) + 1; - line = xmalloc (sizeof (char) * l); - snprintf (line, l, "RC_SVCDIR=" RC_SVCDIR); - rc_strlist_add (&env, line); - free (line); - - rc_strlist_add (&env, "RC_BOOTLEVEL=" RC_LEVEL_BOOT); - - l = strlen ("RC_SOFTLEVEL=") + strlen (runlevel) + 1; - line = xmalloc (sizeof (char) * l); - snprintf (line, l, "RC_SOFTLEVEL=%s", runlevel); - rc_strlist_add (&env, line); - free (line); - - if ((fp = fopen (RC_KSOFTLEVEL, "r"))) { - memset (buffer, 0, sizeof (buffer)); - if (fgets (buffer, sizeof (buffer), fp)) { + + /* Ensure our PATH is prefixed with the system locations first + for a little extra security */ + path = getenv("PATH"); + if (! path) + setenv("PATH", PATH_PREFIX, 1); + 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); + + /* Now go through the env var and only add bits not in our PREFIX */ + while ((token = strsep(&path, ":"))) { + np = npp = xstrdup(PATH_PREFIX); + while ((tok = strsep(&npp, ":"))) + if (strcmp(tok, token) == 0) + break; + if (! tok) + p += snprintf(p, l - (p - e), ":%s", token); + free (np); + } + *p++ = '\0'; + unsetenv("PATH"); + setenv("PATH", e, 1); + free(e); + } + + 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); + + if ((fp = fopen(RC_KSOFTLEVEL, "r"))) { + memset(buffer, 0, sizeof (buffer)); + if (fgets(buffer, sizeof (buffer), fp)) { l = strlen (buffer) - 1; if (buffer[l] == '\n') buffer[l] = 0; - l += strlen ("RC_DEFAULTLEVEL=") + 2; - line = xmalloc (sizeof (char) * l); - snprintf (line, l, "RC_DEFAULTLEVEL=%s", buffer); - rc_strlist_add (&env, line); - free (line); + setenv("RC_DEFAULTLEVEL", buffer, 1); } - fclose (fp); + fclose(fp); } else - rc_strlist_add (&env, "RC_DEFAULTLEVEL=" RC_LEVEL_DEFAULT); - - if (sys) { - l = strlen ("RC_SYS=") + strlen (sys) + 2; - line = xmalloc (sizeof (char) * l); - snprintf (line, l, "RC_SYS=%s", sys); - rc_strlist_add (&env, line); - free (line); - } + setenv("RC_DEFAULTLEVEL", RC_LEVEL_DEFAULT, 1); + + if (sys) + setenv("RC_SYS", sys, 1); /* 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 */ - if (uname (&uts) == 0) { - l = strlen ("RC_UNAME=") + strlen (uts.sysname) + 2; - line = xmalloc (sizeof (char) * l); - snprintf (line, l, "RC_UNAME=%s", uts.sysname); - rc_strlist_add (&env, line); - free (line); - } + if (uname(&uts) == 0) + setenv("RC_UNAME", uts.sysname, 1); /* Be quiet or verbose as necessary */ - if (rc_conf_yesno ("rc_quiet")) - rc_strlist_add (&env, "EINFO_QUIET=YES"); - if (rc_conf_yesno ("rc_verbose")) - rc_strlist_add (&env, "EINFO_VERBOSE=YES"); + if (rc_conf_yesno("rc_quiet")) + setenv("EINFO_QUIET", "YES", 1); + if (rc_conf_yesno("rc_verbose")) + setenv("EINFO_VERBOSE", "YES", 1); errno = 0; - if ((! rc_conf_yesno ("rc_color") && errno == 0) || - rc_conf_yesno ("rc_nocolor")) - rc_strlist_add (&env, "EINFO_COLOR=NO"); - - free (runlevel); - return (env); + if ((! rc_conf_yesno("rc_color") && errno == 0) || + rc_conf_yesno("rc_nocolor")) + setenv("EINFO_COLOR", "NO", 1); } -bool service_plugable (const char *service) +bool service_plugable(const char *service) { char *list; char *p; char *star; char *token; bool allow = true; - char *match = rc_conf_value ("rc_plug_services"); + char *match = rc_conf_value("rc_plug_services"); + bool truefalse; if (! match) - return (true); + return true; - list = xstrdup (match); + list = xstrdup(match); p = list; - while ((token = strsep (&p, " "))) { - bool truefalse = true; - + while ((token = strsep(&p, " "))) { if (token[0] == '!') { truefalse = false; token++; - } + } else + truefalse = true; - star = strchr (token, '*'); + star = strchr(token, '*'); if (star) { - if (strncmp (service, token, (size_t) (star - token)) - == 0) + if (strncmp(service, token, (size_t)(star - token)) == 0) { allow = truefalse; break; } } else { - if (strcmp (service, token) == 0) { + if (strcmp(service, token) == 0) { allow = truefalse; break; } } } - free (list); - return (allow); + free(list); + return allow; } -int signal_setup (int sig, void (*handler)(int)) +int signal_setup(int sig, void (*handler)(int)) { struct sigaction sa; - memset (&sa, 0, sizeof (sa)); - sigemptyset (&sa.sa_mask); + memset(&sa, 0, sizeof (sa)); + sigemptyset(&sa.sa_mask); sa.sa_handler = handler; - return (sigaction (sig, &sa, NULL)); + return sigaction(sig, &sa, NULL); } diff --git a/src/rc/rc-plugin.c b/src/rc/rc-plugin.c index e3184a34..f0ee5a61 100644 --- a/src/rc/rc-plugin.c +++ b/src/rc/rc-plugin.c @@ -31,6 +31,7 @@ #include <sys/types.h> #include <sys/wait.h> + #include <dirent.h> #include <dlfcn.h> #include <errno.h> @@ -46,7 +47,6 @@ #include "rc.h" #include "rc-misc.h" #include "rc-plugin.h" -#include "strlist.h" #define RC_PLUGIN_HOOK "rc_plugin_hook" @@ -56,129 +56,117 @@ typedef struct plugin { char *name; void *handle; - int (*hook) (rc_hook_t, const char *); - struct plugin *next; -} plugin_t; - -static plugin_t *plugins = NULL; + int (*hook)(RC_HOOK, const char *); + STAILQ_ENTRY(plugin) entries; +} PLUGIN; +STAILQ_HEAD(, plugin) plugins; #ifndef __FreeBSD__ -dlfunc_t dlfunc (void * __restrict handle, const char * __restrict symbol) +dlfunc_t dlfunc(void * __restrict handle, const char * __restrict symbol) { union { void *d; dlfunc_t f; } rv; - rv.d = dlsym (handle, symbol); - return (rv.f); + rv.d = dlsym(handle, symbol); + return rv.f; } #endif -void rc_plugin_load (void) +void rc_plugin_load(void) { DIR *dp; struct dirent *d; - plugin_t *plugin = plugins; + PLUGIN *plugin; char *p; void *h; - int (*fptr) (rc_hook_t, const char *); + int (*fptr)(RC_HOOK, const char *); /* Don't load plugins if we're in one */ if (rc_in_plugin) return; - /* Ensure some sanity here */ - rc_plugin_unload (); + STAILQ_INIT(&plugins); - if (! (dp = opendir (RC_PLUGINDIR))) + if (! (dp = opendir(RC_PLUGINDIR))) return; - while ((d = readdir (dp))) { + while ((d = readdir(dp))) { if (d->d_name[0] == '.') continue; - p = rc_strcatpaths (RC_PLUGINDIR, d->d_name, NULL); - h = dlopen (p, RTLD_LAZY); - free (p); + p = rc_strcatpaths(RC_PLUGINDIR, d->d_name, NULL); + h = dlopen(p, RTLD_LAZY); + free(p); if (! h) { - eerror ("dlopen: %s", dlerror ()); + eerror("dlopen: %s", dlerror()); 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) { - eerror ("%s: cannot find symbol `%s'", d->d_name, RC_PLUGIN_HOOK); - dlclose (h); + eerror("%s: cannot find symbol `%s'", d->d_name, RC_PLUGIN_HOOK); + dlclose(h); } else { - if (plugin) { - plugin->next = xmalloc (sizeof (*plugin->next)); - plugin = plugin->next; - } else - plugin = plugins = xmalloc (sizeof (*plugin)); - - plugin->name = xstrdup (d->d_name); + plugin = xmalloc(sizeof(*plugin)); + plugin->name = xstrdup(d->d_name); plugin->handle = h; 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; pid_t savedpid = pid; int retval = -1; errno = 0; - while ((pid = waitpid (savedpid, &status, 0)) > 0) { + while ((pid = waitpid(savedpid, &status, 0)) > 0) { 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; sigset_t empty; sigset_t full; 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 */ if (rc_in_plugin) return; /* We need to block signals until we have forked */ - memset (&sa, 0, sizeof (sa)); + memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_DFL; - sigemptyset (&sa.sa_mask); - sigemptyset (&empty); - 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; - } + sigemptyset(&sa.sa_mask); + sigemptyset(&empty); + sigfillset(&full); + STAILQ_FOREACH(plugin, &plugins, entries) { /* We create a pipe so that plugins can affect our environment * vars, which in turn influence our scripts. */ - if (pipe (pfd) == -1) { - eerror ("pipe: %s", strerror (errno)); + if (pipe(pfd) == -1) { + eerror("pipe: %s", strerror(errno)); return; } @@ -188,81 +176,78 @@ void rc_plugin_run (rc_hook_t hook, const char *value) for (i = 0; i < 2; i++) if ((flags = fcntl (pfd[i], F_GETFD, 0)) < 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 * or otherwise affected by it */ - if ((pid = fork ()) == -1) { - eerror ("fork: %s", strerror (errno)); + if ((pid = fork()) == -1) { + eerror("fork: %s", strerror(errno)); break; } if (pid == 0) { - int retval; - /* Restore default handlers */ - sigaction (SIGCHLD, &sa, NULL); - sigaction (SIGHUP, &sa, NULL); - sigaction (SIGINT, &sa, NULL); - sigaction (SIGQUIT, &sa, NULL); - sigaction (SIGTERM, &sa, NULL); - sigaction (SIGUSR1, &sa, NULL); - sigaction (SIGWINCH, &sa, NULL); - sigprocmask (SIG_SETMASK, &old, NULL); + sigaction(SIGCHLD, &sa, NULL); + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGQUIT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGUSR1, &sa, NULL); + sigaction(SIGWINCH, &sa, NULL); + sigprocmask(SIG_SETMASK, &old, NULL); rc_in_plugin = true; - close (pfd[0]); - rc_environ_fd = fdopen (pfd[1], "w"); - retval = plugin->hook (hook, value); - fclose (rc_environ_fd); + close(pfd[0]); + rc_environ_fd = fdopen(pfd[1], "w"); + retval = plugin->hook(hook, value); + fclose(rc_environ_fd); rc_environ_fd = NULL; /* Just in case the plugin sets this to false */ rc_in_plugin = true; - exit (retval); + exit(retval); } - sigprocmask (SIG_SETMASK, &old, NULL); - close (pfd[1]); - buffer = xmalloc (sizeof (char) * BUFSIZ); - memset (buffer, 0, BUFSIZ); + sigprocmask(SIG_SETMASK, &old, NULL); + close(pfd[1]); + buffer = xmalloc(sizeof(char) * BUFSIZ); + memset(buffer, 0, BUFSIZ); - while ((nr = read (pfd[0], buffer, BUFSIZ)) > 0) { + while ((nr = read(pfd[0], buffer, BUFSIZ)) > 0) { p = buffer; while (*p && p - buffer < nr) { - token = strsep (&p, "="); + token = strsep(&p, "="); if (token) { - unsetenv (token); + unsetenv(token); if (*p) { - setenv (token, p, 1); - p += strlen (p) + 1; + setenv(token, p, 1); + p += strlen(p) + 1; } else p++; } } } - free (buffer); - close (pfd[0]); + free(buffer); + close(pfd[0]); - rc_waitpid (pid); - plugin = plugin->next; + rc_waitpid(pid); } } -void rc_plugin_unload (void) +void rc_plugin_unload(void) { - plugin_t *plugin = plugins; - plugin_t *next; + PLUGIN *plugin = STAILQ_FIRST(&plugins); + PLUGIN *next; while (plugin) { - next = plugin->next; - dlclose (plugin->handle); - free (plugin->name); - free (plugin); + next = STAILQ_NEXT(plugin, entries); + dlclose(plugin->handle); + free(plugin->name); + free(plugin); plugin = next; } - plugins = NULL; + STAILQ_INIT(&plugins); } diff --git a/src/rc/rc-plugin.h b/src/rc/rc-plugin.h index 91ba5619..0b8ab090 100644 --- a/src/rc/rc-plugin.h +++ b/src/rc/rc-plugin.h @@ -36,10 +36,10 @@ * Mainly used in atexit code. */ extern bool rc_in_plugin; -int rc_waitpid (pid_t pid); -void rc_plugin_load (); -void rc_plugin_unload (); -void rc_plugin_run (rc_hook_t, const char *value); +int rc_waitpid(pid_t pid); +void rc_plugin_load(void); +void rc_plugin_unload(void); +void rc_plugin_run(RC_HOOK, const char *value); /* dlfunc defines needed to avoid ISO errors. FreeBSD has this right :) */ #ifndef __FreeBSD__ @@ -47,7 +47,7 @@ struct __dlfunc_arg { 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); #endif diff --git a/src/rc/rc-status.c b/src/rc/rc-status.c index 579c416b..9f7167f6 100644 --- a/src/rc/rc-status.c +++ b/src/rc/rc-status.c @@ -39,57 +39,56 @@ #include "einfo.h" #include "rc.h" #include "rc-misc.h" -#include "strlist.h" extern const char *applet; static const char *const types_nua[] = { "ineed", "iuse", "iafter", NULL }; -static void print_level (char *level) +static void print_level(char *level) { printf ("Runlevel: "); - if (isatty (fileno (stdout))) - printf ("%s%s%s\n", - ecolor (ECOLOR_HILITE), - level, - ecolor (ECOLOR_NORMAL)); + if (isatty(fileno(stdout))) + printf("%s%s%s\n", + ecolor(ECOLOR_HILITE), + level, + ecolor(ECOLOR_NORMAL)); else - printf ("%s\n", level); + printf("%s\n", level); } -static void print_service (char *service) +static void print_service(char *service) { char status[10]; - int cols = printf (" %s", service); - const char *c = ecolor (ECOLOR_GOOD); - rc_service_state_t state = rc_service_state (service); - einfo_color_t color = ECOLOR_BAD; + int cols = printf(" %s", service); + const char *c = ecolor(ECOLOR_GOOD); + RC_SERVICE state = rc_service_state(service); + ECOLOR color = ECOLOR_BAD; if (state & RC_SERVICE_STOPPING) - snprintf (status, sizeof (status), "stopping "); + snprintf(status, sizeof(status), "stopping "); else if (state & RC_SERVICE_STARTING) { - snprintf (status, sizeof (status), "starting "); + snprintf(status, sizeof(status), "starting "); color = ECOLOR_WARN; } else if (state & RC_SERVICE_INACTIVE) { - snprintf (status, sizeof (status), "inactive "); + snprintf(status, sizeof(status), "inactive "); color = ECOLOR_WARN; } else if (state & RC_SERVICE_STARTED) { - if (geteuid () == 0 && rc_service_daemons_crashed (service)) - snprintf (status, sizeof (status), " crashed "); + if (rc_service_daemons_crashed(service)) + snprintf(status, sizeof(status), " crashed "); else { - snprintf (status, sizeof (status), " started "); + snprintf(status, sizeof(status), " started "); color = ECOLOR_GOOD; } } else if (state & RC_SERVICE_SCHEDULED) { - snprintf (status, sizeof (status), "scheduled"); + snprintf(status, sizeof(status), "scheduled"); color = ECOLOR_WARN; } else - snprintf (status, sizeof (status), " stopped "); + snprintf(status, sizeof(status), " stopped "); errno = 0; - if (c && *c && isatty (fileno (stdout))) - printf ("\n"); - ebracket (cols, color, status); + if (c && *c && isatty(fileno(stdout))) + printf("\n"); + ebracket(cols, color, status); } #include "_usage.h" @@ -115,99 +114,100 @@ static const char * const longopts_help[] = { int rc_status (int argc, char **argv) { - rc_depinfo_t *deptree = NULL; - char **levels = NULL; - char **services = NULL; - char **ordered = NULL; - char *level; - char *service; + RC_DEPTREE *deptree = NULL; + RC_STRINGLIST *levels = NULL; + RC_STRINGLIST *services; + RC_STRINGLIST *types = NULL; + RC_STRINGLIST *ordered; + RC_STRING *s; + RC_STRING *l; + char *p; int opt; - int i; - int j; int depopts = RC_DEP_STRICT | RC_DEP_START | RC_DEP_TRACE; - while ((opt = getopt_long (argc, argv, getoptstring, longopts, - (int *) 0)) != -1) + while ((opt = getopt_long(argc, argv, getoptstring, longopts, + (int *) 0)) != -1) switch (opt) { - case 'a': - levels = rc_runlevel_list (); - break; - case 'l': - levels = rc_runlevel_list (); - STRLIST_FOREACH (levels, level, i) - printf ("%s\n", level); - rc_strlist_free (levels); - exit (EXIT_SUCCESS); - /* NOTREACHED */ - case 'r': - level = rc_runlevel_get (); - printf ("%s\n", level); - free (level); - exit (EXIT_SUCCESS); - /* NOTREACHED */ - case 's': - services = rc_services_in_runlevel (NULL); - STRLIST_FOREACH (services, service, i) - print_service (service); - rc_strlist_free (services); - exit (EXIT_SUCCESS); - /* NOTREACHED */ - case 'u': - services = rc_services_in_runlevel (NULL); - levels = rc_runlevel_list (); - STRLIST_FOREACH (services, service, i) { - bool found = false; - STRLIST_FOREACH (levels, level, j) - if (rc_service_in_runlevel (service, level)) { - found = true; - break; - } - if (! found) - print_service (service); - } - rc_strlist_free (levels); - rc_strlist_free (services); - exit (EXIT_SUCCESS); - /* NOTREACHED */ - - case_RC_COMMON_GETOPT + case 'a': + levels = rc_runlevel_list(); + break; + case 'l': + levels = rc_runlevel_list(); + TAILQ_FOREACH (l, levels, entries) + printf("%s\n", l->value); + rc_stringlist_free(levels); + exit(EXIT_SUCCESS); + /* NOTREACHED */ + case 'r': + p = rc_runlevel_get (); + printf("%s\n", p); + free(p); + exit(EXIT_SUCCESS); + /* NOTREACHED */ + case 's': + services = rc_services_in_runlevel(NULL); + TAILQ_FOREACH(s, services, entries) + print_service(s->value); + rc_stringlist_free(services); + exit (EXIT_SUCCESS); + /* NOTREACHED */ + case 'u': + services = rc_services_in_runlevel(NULL); + levels = rc_runlevel_list(); + TAILQ_FOREACH(s, services, entries) { + TAILQ_FOREACH(l, levels, entries) + if (rc_service_in_runlevel(s->value, l->value)) + break; + if (! l) + print_service(s->value); + } + rc_stringlist_free(levels); + rc_stringlist_free(services); + exit (EXIT_SUCCESS); + /* NOTREACHED */ + + case_RC_COMMON_GETOPT } + if (! levels) + levels = rc_stringlist_new(); while (optind < argc) - rc_strlist_add (&levels, argv[optind++]); - - if (! levels) { - level = rc_runlevel_get (); - rc_strlist_add (&levels, level); - free (level); + rc_stringlist_add(levels, argv[optind++]); + if (! TAILQ_FIRST(levels)) { + p = rc_runlevel_get(); + rc_stringlist_add(levels, p); + free(p); } /* Output the services in the order in which they would start */ - if (geteuid () == 0) - deptree = _rc_deptree_load (NULL); - else - deptree = rc_deptree_load (); + deptree = _rc_deptree_load(NULL); - STRLIST_FOREACH (levels, level, i) { - print_level (level); - services = rc_services_in_runlevel (level); + TAILQ_FOREACH(l, levels, entries) { + print_level(l->value); + services = rc_services_in_runlevel(l->value); if (deptree) { - ordered = rc_deptree_depends (deptree, types_nua, - (const char **) services, - level, depopts); - rc_strlist_free (services); + if (! types) { + types = rc_stringlist_new(); + rc_stringlist_add(types, "ineed"); + 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; ordered = NULL; } - STRLIST_FOREACH (services, service, j) - if (rc_service_in_runlevel (service, level)) - print_service (service); - rc_strlist_free (services); + TAILQ_FOREACH(s, services, entries) + if (rc_service_in_runlevel(s->value, l->value)) + print_service(s->value); + rc_stringlist_free(services); } - rc_strlist_free (levels); - rc_deptree_free (deptree); + rc_stringlist_free(types); + rc_stringlist_free(levels); + rc_deptree_free(deptree); - exit (EXIT_SUCCESS); + exit(EXIT_SUCCESS); /* NOTREACHED */ } diff --git a/src/rc/rc-update.c b/src/rc/rc-update.c index fdd1417c..e09f521c 100644 --- a/src/rc/rc-update.c +++ b/src/rc/rc-update.c @@ -42,7 +42,6 @@ #include "einfo.h" #include "rc.h" #include "rc-misc.h" -#include "strlist.h" 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", applet, service, runlevel, strerror (errno)); - return (retval); + return retval; } 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", 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; - char **services = rc_services_in_runlevel (NULL); - char *runlevel; - int i; - int j; - - STRLIST_FOREACH (services, service, i) { - char **in = NULL; - bool inone = false; - - STRLIST_FOREACH (runlevels, runlevel, j) { - if (rc_service_in_runlevel (service, runlevel)) { - rc_strlist_add (&in, runlevel); + RC_STRINGLIST *services = rc_services_in_runlevel(NULL); + RC_STRING *service; + RC_STRING *runlevel; + RC_STRINGLIST *in; + bool inone; + char buffer[PATH_MAX]; + size_t l; + + TAILQ_FOREACH(service, services, entries) { + in = rc_stringlist_new(); + inone = false; + + TAILQ_FOREACH(runlevel, runlevels, entries) { + if (rc_service_in_runlevel(service->value, + runlevel->value)) + { + rc_stringlist_add(in, runlevel->value); inone = true; } else { - char buffer[PATH_MAX]; - memset (buffer, ' ', strlen (runlevel)); - buffer[strlen (runlevel)] = 0; - rc_strlist_add (&in, buffer); + l = strlen(runlevel->value); + memset (buffer, ' ', l); + buffer[l] = 0; + rc_stringlist_add (in, buffer); } } - if (! inone && ! verbose) - continue; - - printf (" %20s |", service); - STRLIST_FOREACH (in, runlevel, j) - printf (" %s", runlevel); - printf ("\n"); - rc_strlist_free (in); + if (inone || verbose) { + printf(" %20s |", service->value); + TAILQ_FOREACH(runlevel, in, entries) + printf (" %s", runlevel->value); + printf ("\n"); + } + rc_stringlist_free(in); } - rc_strlist_free (services); + rc_stringlist_free (services); } #include "_usage.h" @@ -146,111 +148,124 @@ static const char * const longopts_help[] = { #define DODELETE (1 << 2) #define DOSHOW (1 << 3) -int rc_update (int argc, char **argv) +int rc_update(int argc, char **argv) { - int i; + RC_STRINGLIST *runlevels; + RC_STRING *runlevel; char *service = NULL; - char **runlevels = NULL; - char *runlevel; + char *p; int action = 0; bool verbose = false; int opt; 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) - { 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) || (action & DOADD && action != DOADD) || (action & DODELETE && action != DODELETE)) - eerrorx ("%s: cannot mix commands", applet); + eerrorx("%s: cannot mix commands", applet); /* We need to be backwards compatible */ if (optind < argc) { - if (strcmp (argv[optind], "add") == 0) + if (strcmp(argv[optind], "add") == 0) action = DOADD; - else if (strcmp (argv[optind], "delete") == 0 || - strcmp (argv[optind], "del") == 0) + else if (strcmp(argv[optind], "delete") == 0 || + strcmp(argv[optind], "del") == 0) action = DODELETE; - else if (strcmp (argv[optind], "show") == 0) + else if (strcmp(argv[optind], "show") == 0) action = DOSHOW; if (action) optind++; else - eerrorx ("%s: invalid command `%s'", applet, argv[optind]); + eerrorx("%s: invalid command `%s'", applet, argv[optind]); } if (! action) action = DOSHOW; + runlevels = rc_stringlist_new(); + if (optind >= argc) { if (! action & DOSHOW) - eerrorx ("%s: no service specified", applet); + eerrorx("%s: no service specified", applet); } else { service = argv[optind]; optind++; while (optind < argc) - if (rc_runlevel_exists (argv[optind])) - rc_strlist_add (&runlevels, argv[optind++]); + if (rc_runlevel_exists(argv[optind])) + rc_stringlist_add(runlevels, argv[optind++]); else { - rc_strlist_free (runlevels); - eerrorx ("%s: `%s' is not a valid runlevel", applet, argv[optind]); + rc_stringlist_free(runlevels); + eerrorx ("%s: `%s' is not a valid runlevel", + applet, argv[optind]); } } retval = EXIT_SUCCESS; if (action & DOSHOW) { if (service) - rc_strlist_add (&runlevels, service); - if (! runlevels) - runlevels = rc_runlevel_list (); + rc_stringlist_add(runlevels, service); + if (! TAILQ_FIRST(runlevels)) { + free(runlevels); + runlevels = rc_runlevel_list(); + } show (runlevels, verbose); } else { if (! service) eerror ("%s: no service specified", applet); else { - int num_updated = 0; - int (*actfunc)(const char *, const char *); - int ret; - if (action & DOADD) { actfunc = add; } else if (action & DODELETE) { actfunc = delete; - } else + } else { + rc_stringlist_free(runlevels); eerrorx ("%s: invalid action", applet); + } - if (! runlevels) - rc_strlist_add (&runlevels, rc_runlevel_get ()); + if (! TAILQ_FIRST(runlevels)) { + 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); + } - STRLIST_FOREACH (runlevels, runlevel, i) { - if (! rc_runlevel_exists (runlevel)) { - eerror ("%s: runlevel `%s' does not exist", applet, runlevel); + TAILQ_FOREACH (runlevel, runlevels, entries) { + if (! rc_runlevel_exists(runlevel->value)) { + eerror ("%s: runlevel `%s' does not exist", + applet, runlevel->value); continue; } - ret = actfunc (runlevel, service); + ret = actfunc(runlevel->value, service); if (ret < 0) retval = EXIT_FAILURE; num_updated += ret; } - if (retval == EXIT_SUCCESS && num_updated == 0 && action & DODELETE) - ewarnx ("%s: service `%s' not found in any of the specified runlevels", applet, service); + if (retval == EXIT_SUCCESS && + num_updated == 0 && action & DODELETE) + ewarnx("%s: service `%s' not found in any" + " of the specified runlevels", + applet, service); } } - rc_strlist_free (runlevels); - return (retval); + rc_stringlist_free(runlevels); + return retval; } diff --git a/src/rc/rc.c b/src/rc/rc.c index 98b44cc8..6a6aa0a4 100644 --- a/src/rc/rc.c +++ b/src/rc/rc.c @@ -42,10 +42,18 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples"; #include <sys/stat.h> #include <sys/utsname.h> #include <sys/wait.h> + +/* So we can coldplug net devices */ +#ifdef BSD +# include <sys/socket.h> +# include <ifaddrs.h> +#endif + #include <errno.h> #include <dirent.h> #include <ctype.h> #include <getopt.h> +#include <libgen.h> #include <limits.h> #include <stdbool.h> #include <stdio.h> @@ -56,19 +64,12 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples"; #include <termios.h> #include <unistd.h> -/* So we can coldplug net devices */ -#ifdef BSD -# include <sys/socket.h> -# include <ifaddrs.h> -#endif - #include "builtins.h" #include "einfo.h" #include "rc.h" #include "rc-logger.h" #include "rc-misc.h" #include "rc-plugin.h" -#include "strlist.h" #include "version.h" @@ -81,43 +82,31 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples"; #define INTERACTIVE RC_SVCDIR "/interactive" -#define DEVBOOT "/dev/.rcboot" - -/* Cleanup anything in main */ -#define CHAR_FREE(_item) if (_item) { \ - free (_item); \ - _item = NULL; \ -} - -extern char **environ; +#define DEVBOOT "/dev/.rcboot" static char *RUNLEVEL = NULL; static char *PREVLEVEL = NULL; const char *applet = NULL; static char *runlevel = NULL; -static char **env = NULL; -static char **newenv = NULL; -static char **coldplugged_services = NULL; -static char **stop_services = NULL; -static char **start_services = NULL; -static rc_depinfo_t *deptree = NULL; -static rc_hook_t hook_out = 0; -static char *tmp = NULL; +static RC_STRINGLIST *coldplugged_services = NULL; +static RC_STRINGLIST *stop_services = NULL; +static RC_STRINGLIST *start_services = NULL; +static RC_STRINGLIST *types_n = NULL; +static RC_STRINGLIST *types_nua = NULL; +static RC_DEPTREE *deptree = NULL; +static RC_HOOK hook_out = 0; struct termios *termios_orig = NULL; -typedef struct pidlist +typedef struct piditem { pid_t pid; - struct pidlist *next; -} pidlist_t; -static pidlist_t *service_pids = NULL; - -static const char *const types_n[] = { "needsme", NULL }; -static const char *const types_nua[] = { "ineed", "iuse", "iafter", NULL }; + LIST_ENTRY(piditem) entries; +} PIDITEM; +LIST_HEAD(, piditem) service_pids; -static void clean_failed (void) +static void clean_failed(void) { DIR *dp; struct dirent *d; @@ -125,70 +114,71 @@ static void clean_failed (void) char *path; /* Clean the failed services state dir now */ - if ((dp = opendir (RC_SVCDIR "/failed"))) { - while ((d = readdir (dp))) { + if ((dp = opendir(RC_SVCDIR "/failed"))) { + while ((d = readdir(dp))) { if (d->d_name[0] == '.' && (d->d_name[1] == '\0' || (d->d_name[1] == '.' && d->d_name[2] == '\0'))) continue; - l = strlen (RC_SVCDIR "/failed/") + strlen (d->d_name) + 1; - path = xmalloc (sizeof (char) * l); - snprintf (path, l, RC_SVCDIR "/failed/%s", d->d_name); + l = strlen(RC_SVCDIR "/failed/") + strlen(d->d_name) + 1; + path = xmalloc(sizeof(char) * l); + snprintf(path, l, RC_SVCDIR "/failed/%s", d->d_name); if (path) { - if (unlink (path)) - eerror ("%s: unlink `%s': %s", applet, path, - strerror (errno)); - free (path); + if (unlink(path)) + eerror("%s: unlink `%s': %s", applet, path, + strerror(errno)); + free(path); } } - closedir (dp); + closedir(dp); } } -static void cleanup (void) +static void cleanup(void) { - if (applet && strcmp (applet, "rc") == 0) { - pidlist_t *pl = service_pids; + if (applet && strcmp(applet, "rc") == 0) { + PIDITEM *p1 = LIST_FIRST(&service_pids); + PIDITEM *p2; if (hook_out) - rc_plugin_run (hook_out, runlevel); + rc_plugin_run(hook_out, runlevel); - rc_plugin_unload (); + rc_plugin_unload(); if (! rc_in_plugin && termios_orig) { - tcsetattr (fileno (stdin), TCSANOW, termios_orig); - free (termios_orig); + tcsetattr(fileno(stdin), TCSANOW, termios_orig); + free(termios_orig); } - while (pl) { - pidlist_t *p = pl->next; - free (pl); - pl = p; + while (p1) { + p2 = LIST_NEXT(p1, entries); + free(p1); + p1 = p2; } - rc_strlist_free (env); - rc_strlist_free (newenv); - rc_strlist_free (coldplugged_services); - rc_strlist_free (stop_services); - rc_strlist_free (start_services); - rc_deptree_free (deptree); + rc_stringlist_free(coldplugged_services); + rc_stringlist_free(stop_services); + rc_stringlist_free(start_services); + rc_stringlist_free(types_n); + rc_stringlist_free(types_nua); + rc_deptree_free(deptree); /* Clean runlevel start, stop markers */ if (! rc_in_plugin && ! rc_in_logger) { - rmdir (RC_STARTING); - rmdir (RC_STOPPING); - clean_failed (); + rmdir(RC_STARTING); + rmdir(RC_STOPPING); + clean_failed(); - rc_logger_close (); + rc_logger_close(); } - free (runlevel); + free(runlevel); } } #ifdef __linux__ -static char *proc_getent (const char *ent) +static char *proc_getent(const char *ent) { FILE *fp; char *proc; @@ -196,50 +186,50 @@ static char *proc_getent (const char *ent) char *value = NULL; int i; - if (! exists ("/proc/cmdline")) - return (NULL); + if (! exists("/proc/cmdline")) + return NULL; - if (! (fp = fopen ("/proc/cmdline", "r"))) { - eerror ("failed to open `/proc/cmdline': %s", strerror (errno)); - return (NULL); + if (! (fp = fopen("/proc/cmdline", "r"))) { + eerror("failed to open `/proc/cmdline': %s", strerror(errno)); + return NULL; } - if ((proc = rc_getline (fp)) && - (p = strstr (proc, ent))) + if ((proc = rc_getline(fp)) && + (p = strstr(proc, ent))) { i = p - proc; if (i == '\0' || proc[i - 1] == ' ') { - p += strlen (ent); + p += strlen(ent); if (*p == '=') p++; - value = xstrdup (strsep (&p, " ")); + value = xstrdup(strsep(&p, " ")); } } else errno = ENOENT; - free (proc); - fclose (fp); + free(proc); + fclose(fp); - return (value); + return value; } #endif -static char read_key (bool block) +static char read_key(bool block) { struct termios termios; char c = 0; - int fd = fileno (stdin); + int fd = fileno(stdin); - if (! isatty (fd)) - return (false); + if (! isatty(fd)) + return false; /* Now save our terminal settings. We need to restore them at exit as we * will be changing it for non-blocking reads for Interactive */ if (! termios_orig) { - termios_orig = xmalloc (sizeof (*termios_orig)); - tcgetattr (fd, termios_orig); + termios_orig = xmalloc(sizeof(*termios_orig)); + tcgetattr(fd, termios_orig); } - tcgetattr (fd, &termios); + tcgetattr(fd, &termios); termios.c_lflag &= ~(ICANON | ECHO); if (block) termios.c_cc[VMIN] = 1; @@ -247,49 +237,49 @@ static char read_key (bool block) termios.c_cc[VMIN] = 0; termios.c_cc[VTIME] = 0; } - tcsetattr (fd, TCSANOW, &termios); + tcsetattr(fd, TCSANOW, &termios); - read (fd, &c, 1); + read(fd, &c, 1); - tcsetattr (fd, TCSANOW, termios_orig); + tcsetattr(fd, TCSANOW, termios_orig); - return (c); + return c; } -static bool want_interactive (void) +static bool want_interactive(void) { char c; static bool gotinteractive; static bool interactive; - if (rc_yesno (getenv ("EINFO_QUIET"))) - return (false); + if (rc_yesno(getenv("EINFO_QUIET"))) + return false; if (PREVLEVEL && - strcmp (PREVLEVEL, "N") != 0 && - strcmp (PREVLEVEL, "S") != 0 && - strcmp (PREVLEVEL, "1") != 0) - return (false); + strcmp(PREVLEVEL, "N") != 0 && + strcmp(PREVLEVEL, "S") != 0 && + strcmp(PREVLEVEL, "1") != 0) + return false; if (! gotinteractive) { gotinteractive = true; - interactive = rc_conf_yesno ("rc_interactive"); + interactive = rc_conf_yesno("rc_interactive"); } if (! interactive) - return (false); + return false; - c = read_key (false); - return ((c == 'I' || c == 'i') ? true : false); + c = read_key(false); + return (c == 'I' || c == 'i') ? true : false; } -static void mark_interactive (void) +static void mark_interactive(void) { - FILE *fp = fopen (INTERACTIVE, "w"); + FILE *fp = fopen(INTERACTIVE, "w"); if (fp) - fclose (fp); + fclose(fp); } -static void sulogin (bool cont) +static void sulogin(bool cont) { int status = 0; struct sigaction sa; @@ -297,287 +287,276 @@ static void sulogin (bool cont) sigset_t old; pid_t pid; #ifdef __linux__ - const char *sys = rc_sys (); + const char *sys = rc_sys(); /* VSERVER and OPENVZ systems cannot do a sulogin */ - if (sys && (strcmp (sys, "VSERVER") == 0 || strcmp (sys, "OPENVZ") == 0)) { - execl ("/sbin/halt", "/sbin/halt", "-f", (char *) NULL); - eerrorx ("%s: unable to exec `/sbin/halt': %s", applet, strerror (errno)); + if (sys && (strcmp(sys, "VSERVER") == 0 || strcmp(sys, "OPENVZ") == 0)) { + execl("/sbin/halt", "/sbin/halt", "-f", (char *) NULL); + eerrorx("%s: unable to exec `/sbin/halt': %s", + applet, strerror(errno)); } #endif - newenv = env_filter (); - if (! cont) { - rc_logger_close (); + rc_logger_close(); #ifdef __linux__ - execle ("/sbin/sulogin", "/sbin/sulogin", (char *) NULL, newenv); - eerrorx ("%s: unable to exec `/sbin/sulogin': %s", applet, strerror (errno)); + execl("/sbin/sulogin", "/sbin/sulogin", (char *) NULL); + eerrorx("%s: unable to exec `/sbin/sulogin': %s", + applet, strerror(errno)); #else - exit (EXIT_SUCCESS); + exit(EXIT_SUCCESS); #endif } /* We need to block signals until we have forked */ - memset (&sa, 0, sizeof (sa)); + memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_DFL; - sigemptyset (&sa.sa_mask); - sigfillset (&full); - sigprocmask (SIG_SETMASK, &full, &old); - pid = vfork (); + sigemptyset(&sa.sa_mask); + sigfillset(&full); + sigprocmask(SIG_SETMASK, &full, &old); + pid = vfork(); if (pid == -1) - eerrorx ("%s: fork: %s", applet, strerror (errno)); + eerrorx("%s: fork: %s", applet, strerror(errno)); if (pid == 0) { /* Restore default handlers */ - sigaction (SIGCHLD, &sa, NULL); - sigaction (SIGHUP, &sa, NULL); - sigaction (SIGINT, &sa, NULL); - sigaction (SIGQUIT, &sa, NULL); - sigaction (SIGTERM, &sa, NULL); - sigaction (SIGUSR1, &sa, NULL); - sigaction (SIGWINCH, &sa, NULL); + sigaction(SIGCHLD, &sa, NULL); + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGQUIT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGUSR1, &sa, NULL); + sigaction(SIGWINCH, &sa, NULL); /* Unmask signals */ - sigprocmask (SIG_SETMASK, &old, NULL); + sigprocmask(SIG_SETMASK, &old, NULL); if (termios_orig) - tcsetattr (fileno (stdin), TCSANOW, termios_orig); + tcsetattr(fileno(stdin), TCSANOW, termios_orig); #ifdef __linux__ - execle (SULOGIN, SULOGIN, (char *) NULL, newenv); - eerror ("%s: unable to exec `%s': %s", applet, SULOGIN, - strerror (errno)); + execl(SULOGIN, SULOGIN, (char *) NULL); + eerror("%s: unable to exec `%s': %s", applet, SULOGIN, + strerror(errno)); #else - execle ("/bin/sh", "/bin/sh", (char *) NULL, newenv); - eerror ("%s: unable to exec `/bin/sh': %s", applet, - strerror (errno)); + execl("/bin/sh", "/bin/sh", (char *) NULL); + eerror("%s: unable to exec `/bin/sh': %s", applet, + strerror(errno)); #endif - _exit (EXIT_FAILURE); + _exit(EXIT_FAILURE); } /* Unmask signals and wait for child */ - sigprocmask (SIG_SETMASK, &old, NULL); - waitpid (pid, &status, 0); + sigprocmask(SIG_SETMASK, &old, NULL); + waitpid(pid, &status, 0); } -static void single_user (void) +static void single_user(void) { - rc_logger_close (); + rc_logger_close(); - execl (SHUTDOWN, SHUTDOWN, "now", (char *) NULL); - eerrorx ("%s: unable to exec `" SHUTDOWN "': %s", - applet, strerror (errno)); + execl(SHUTDOWN, SHUTDOWN, "now", (char *) NULL); + eerrorx("%s: unable to exec `" SHUTDOWN "': %s", + applet, strerror(errno)); } -static bool set_ksoftlevel (const char *level) +static bool set_ksoftlevel(const char *level) { FILE *fp; if (! level || - strcmp (level, getenv ("RC_BOOTLEVEL")) == 0 || - strcmp (level, RC_LEVEL_SINGLE) == 0 || - strcmp (level, RC_LEVEL_SYSINIT) == 0) + strcmp(level, getenv ("RC_BOOTLEVEL")) == 0 || + strcmp(level, RC_LEVEL_SINGLE) == 0 || + strcmp(level, RC_LEVEL_SYSINIT) == 0) { - if (exists (RC_KSOFTLEVEL) && - unlink (RC_KSOFTLEVEL) != 0) - eerror ("unlink `%s': %s", RC_KSOFTLEVEL, strerror (errno)); - return (false); + if (exists(RC_KSOFTLEVEL) && + unlink(RC_KSOFTLEVEL) != 0) + eerror("unlink `%s': %s", RC_KSOFTLEVEL, strerror(errno)); + return false; } - if (! (fp = fopen (RC_KSOFTLEVEL, "w"))) { - eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno)); - return (false); + if (! (fp = fopen(RC_KSOFTLEVEL, "w"))) { + eerror("fopen `%s': %s", RC_KSOFTLEVEL, strerror(errno)); + return false; } - fprintf (fp, "%s", level); - fclose (fp); - return (true); + fprintf(fp, "%s", level); + fclose(fp); + return true; } -static int get_ksoftlevel (char *buffer, int buffer_len) +static int get_ksoftlevel(char *buffer, int buffer_len) { FILE *fp; int i = 0; - if (! exists (RC_KSOFTLEVEL)) - return (0); + if (! exists(RC_KSOFTLEVEL)) + return 0; - if (! (fp = fopen (RC_KSOFTLEVEL, "r"))) { - eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno)); - return (-1); + if (! (fp = fopen(RC_KSOFTLEVEL, "r"))) { + eerror("fopen `%s': %s", RC_KSOFTLEVEL, strerror(errno)); + return -1; } - if (fgets (buffer, buffer_len, fp)) { - i = strlen (buffer) - 1; + if (fgets(buffer, buffer_len, fp)) { + i = strlen(buffer) - 1; if (buffer[i] == '\n') buffer[i] = 0; } - fclose (fp); - return (i); + fclose(fp); + return i; } -static void add_pid (pid_t pid) +static void add_pid(pid_t pid) { - pidlist_t *sp = service_pids; - if (sp) { - while (sp->next) - sp = sp->next; - sp->next = xmalloc (sizeof (*sp->next)); - sp = sp->next; - } else - sp = service_pids = xmalloc (sizeof (*sp)); - memset (sp, 0, sizeof (*sp)); - sp->pid = pid; + PIDITEM *p = xmalloc(sizeof(*p)); + p->pid = pid; + LIST_INSERT_HEAD(&service_pids, p, entries); } -static void remove_pid (pid_t pid) +static void remove_pid(pid_t pid) { - pidlist_t *last = NULL; - pidlist_t *pl; + PIDITEM *p; - for (pl = service_pids; pl; pl = pl->next) { - if (pl->pid == pid) { - if (last) - last->next = pl->next; - else - service_pids = pl->next; - free (pl); - break; + LIST_FOREACH(p, &service_pids, entries) + if (p->pid == pid) { + LIST_REMOVE(p, entries); + free(p); + return; } - last = pl; - } } -static void wait_for_services () +static void wait_for_services(void) { - while (waitpid (0, 0, 0) != -1); + while (waitpid(0, 0, 0) != -1); } -static void handle_signal (int sig) +static void handle_signal(int sig) { int serrno = errno; char signame[10] = { '\0' }; - pidlist_t *pl; pid_t pid; + PIDITEM *pi; int status = 0; struct winsize ws; sigset_t sset; switch (sig) { - case SIGCHLD: - do { - pid = waitpid (-1, &status, WNOHANG); - if (pid < 0) { - if (errno != ECHILD) - eerror ("waitpid: %s", strerror (errno)); - return; - } - } while (! WIFEXITED (status) && ! WIFSIGNALED (status)); - - /* Remove that pid from our list */ - if (pid > 0) - remove_pid (pid); - break; - - case SIGWINCH: - if (rc_logger_tty >= 0) { - ioctl (STDIN_FILENO, TIOCGWINSZ, &ws); - ioctl (rc_logger_tty, TIOCSWINSZ, &ws); + case SIGCHLD: + do { + pid = waitpid(-1, &status, WNOHANG); + if (pid < 0) { + if (errno != ECHILD) + eerror("waitpid: %s", strerror(errno)); + return; } - break; - - case SIGINT: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGINT"); - /* FALLTHROUGH */ - case SIGTERM: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGTERM"); - /* FALLTHROUGH */ - case SIGQUIT: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGQUIT"); - eerrorx ("%s: caught %s, aborting", applet, signame); - /* NOTREACHED */ - case SIGUSR1: - eerror ("rc: Aborting!"); - - /* Block child signals */ - sigemptyset (&sset); - sigaddset (&sset, SIGCHLD); - sigprocmask (SIG_BLOCK, &sset, NULL); - - /* Kill any running services we have started */ - for (pl = service_pids; pl; pl = pl->next) - kill (pl->pid, SIGTERM); - - /* Notify plugins we are aborting */ - rc_plugin_run (RC_HOOK_ABORT, NULL); - - /* Only drop into single user mode if we're booting */ - if ((PREVLEVEL && - (strcmp (PREVLEVEL, "S") == 0 || - strcmp (PREVLEVEL, "1") == 0)) || - (RUNLEVEL && - (strcmp (RUNLEVEL, "S") == 0 || - strcmp (RUNLEVEL, "1") == 0))) - single_user (); - - exit (EXIT_FAILURE); - /* NOTREACHED */ + } while (! WIFEXITED(status) && ! WIFSIGNALED(status)); - default: - eerror ("%s: caught unknown signal %d", applet, sig); + /* Remove that pid from our list */ + if (pid > 0) + remove_pid(pid); + break; + + case SIGWINCH: + if (rc_logger_tty >= 0) { + ioctl(STDIN_FILENO, TIOCGWINSZ, &ws); + ioctl(rc_logger_tty, TIOCSWINSZ, &ws); + } + break; + + case SIGINT: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGINT"); + /* FALLTHROUGH */ + case SIGTERM: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGTERM"); + /* FALLTHROUGH */ + case SIGQUIT: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGQUIT"); + eerrorx("%s: caught %s, aborting", applet, signame); + /* NOTREACHED */ + case SIGUSR1: + eerror("rc: Aborting!"); + + /* Block child signals */ + sigemptyset(&sset); + sigaddset(&sset, SIGCHLD); + sigprocmask(SIG_BLOCK, &sset, NULL); + + /* Kill any running services we have started */ + LIST_FOREACH(pi, &service_pids, entries) + kill(pi->pid, SIGTERM); + + /* Notify plugins we are aborting */ + rc_plugin_run(RC_HOOK_ABORT, NULL); + + /* Only drop into single user mode if we're booting */ + if ((PREVLEVEL && + (strcmp(PREVLEVEL, "S") == 0 || + strcmp(PREVLEVEL, "1") == 0)) || + (RUNLEVEL && + (strcmp(RUNLEVEL, "S") == 0 || + strcmp(RUNLEVEL, "1") == 0))) + single_user(); + + exit(EXIT_FAILURE); + /* NOTREACHED */ + + default: + eerror("%s: caught unknown signal %d", applet, sig); } /* Restore errno */ errno = serrno; } -static void run_script (const char *script) +static void run_script(const char *script) { int status = 0; - pid_t pid = vfork (); + pid_t pid = vfork(); + pid_t wpid; if (pid < 0) - eerrorx ("%s: vfork: %s", applet, strerror (errno)); + eerrorx("%s: vfork: %s", applet, strerror(errno)); else if (pid == 0) { - execl (script, script, (char *) NULL); - eerror ("%s: unable to exec `%s': %s", - script, applet, strerror (errno)); - _exit (EXIT_FAILURE); + execl(script, script, (char *) NULL); + eerror("%s: unable to exec `%s': %s", + script, applet, strerror(errno)); + _exit(EXIT_FAILURE); } do { - pid_t wpid = waitpid (pid, &status, 0); + wpid = waitpid(pid, &status, 0); if (wpid < 1) - eerror ("waitpid: %s", strerror (errno)); - } while (! WIFEXITED (status) && ! WIFSIGNALED (status)); + eerror("waitpid: %s", strerror(errno)); + } while (! WIFEXITED(status) && ! WIFSIGNALED(status)); - if (! WIFEXITED (status) || ! WEXITSTATUS (status) == 0) - eerrorx ("%s: failed to exec `%s'", applet, script); + if (! WIFEXITED(status) || ! WEXITSTATUS(status) == 0) + eerrorx("%s: failed to exec `%s'", applet, script); } -static void do_coldplug (void) +static void do_coldplug(void) { - size_t s; - int i; + size_t l; DIR *dp; struct dirent *d; char *service; + RC_STRING *s; #ifdef BSD struct ifaddrs *ifap; struct ifaddrs *ifa; + char *p; #endif - if (! rc_conf_yesno ("rc_coldplug") && errno != ENOENT) + if (! rc_conf_yesno("rc_coldplug") && errno != ENOENT) return; /* We need to ensure our state dirs exist. * We should have a better call than this, but oh well. */ - rc_deptree_update_needed (); + rc_deptree_update_needed(); #ifdef BSD if (getifaddrs(&ifap) == 0) { @@ -585,33 +564,33 @@ static void do_coldplug (void) if (ifa->ifa_addr->sa_family != AF_LINK) continue; - s = strlen ("net.") + strlen (ifa->ifa_name) + 1; - tmp = xmalloc (sizeof (char) * s); - snprintf (tmp, s, "net.%s", ifa->ifa_name); - if (rc_service_exists (tmp) && - service_plugable (tmp)) - rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED); - CHAR_FREE (tmp); + l = strlen("net.") + strlen(ifa->ifa_name) + 1; + service = xmalloc(sizeof (char) * l); + snprintf(service, l, "net.%s", ifa->ifa_name); + if (rc_service_exists(service) && + service_plugable(service)) + rc_service_mark(service, RC_SERVICE_COLDPLUGGED); + free(service); } freeifaddrs (ifap); } /* The mice are a little more tricky. * If we coldplug anything else, we'll probably do it here. */ - if ((dp = opendir ("/dev"))) { - while ((d = readdir (dp))) { - if (strncmp (d->d_name, "psm", 3) == 0 || - strncmp (d->d_name, "ums", 3) == 0) + if ((dp = opendir("/dev"))) { + while ((d = readdir(dp))) { + if (strncmp(d->d_name, "psm", 3) == 0 || + strncmp(d->d_name, "ums", 3) == 0) { - char *p = d->d_name + 3; - if (p && isdigit ((int) *p)) { - s = strlen ("moused.") + strlen (d->d_name) + 1; - tmp = xmalloc (sizeof (char) * s); - snprintf (tmp, s, "moused.%s", d->d_name); - if (rc_service_exists (tmp) && - service_plugable (tmp)) - rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED); - CHAR_FREE (tmp); + p = d->d_name + 3; + if (p && isdigit((int) *p)) { + l = strlen("moused.") + strlen(d->d_name) + 1; + service = xmalloc(sizeof(char) * l); + snprintf (service, l, "moused.%s", d->d_name); + if (rc_service_exists (service) && + service_plugable (service)) + rc_service_mark (service, RC_SERVICE_COLDPLUGGED); + free(service); } } } @@ -624,41 +603,57 @@ static void do_coldplug (void) * its coldplugging thing. runscript knows when we're not ready so it * stores a list of coldplugged services in DEVBOOT for us to pick up * here when we are ready for them */ - if ((dp = opendir (DEVBOOT))) { - while ((d = readdir (dp))) { + if ((dp = opendir(DEVBOOT))) { + while ((d = readdir(dp))) { if (d->d_name[0] == '.' && (d->d_name[1] == '\0' || (d->d_name[1] == '.' && d->d_name[2] == '\0'))) continue; - if (rc_service_exists (d->d_name) && - service_plugable (d->d_name)) - rc_service_mark (d->d_name, RC_SERVICE_COLDPLUGGED); - - s = strlen (DEVBOOT "/") + strlen (d->d_name) + 1; - tmp = xmalloc (sizeof (char) * s); - snprintf (tmp, s, DEVBOOT "/%s", d->d_name); - if (tmp) { - if (unlink (tmp)) - eerror ("%s: unlink `%s': %s", applet, tmp, - strerror (errno)); - free (tmp); - } + if (rc_service_exists(d->d_name) && + service_plugable(d->d_name)) + rc_service_mark(d->d_name, RC_SERVICE_COLDPLUGGED); + + l = strlen(DEVBOOT "/") + strlen(d->d_name) + 1; + service = xmalloc(sizeof (char) * l); + snprintf(service, l, DEVBOOT "/%s", d->d_name); + if (unlink(service)) + eerror("%s: unlink `%s': %s", applet, service, + strerror(errno)); + free(service); } - closedir (dp); - rmdir (DEVBOOT); + closedir(dp); + rmdir(DEVBOOT); } #endif - if (rc_yesno (getenv ("EINFO_QUIET"))) + if (rc_yesno(getenv("EINFO_QUIET"))) return; /* Load our list of coldplugged services and display them */ - einfon ("Device initiated services:%s", ecolor (ECOLOR_HILITE)); - coldplugged_services = rc_services_in_state (RC_SERVICE_COLDPLUGGED); - STRLIST_FOREACH (coldplugged_services, service, i) - printf (" %s", service); - printf ("%s\n", ecolor (ECOLOR_NORMAL)); + einfon("Device initiated services:%s", ecolor(ECOLOR_HILITE)); + coldplugged_services = rc_services_in_state(RC_SERVICE_COLDPLUGGED); + TAILQ_FOREACH(s, coldplugged_services, entries) + printf(" %s", s->value); + printf ("%s\n", ecolor(ECOLOR_NORMAL)); +} + +static bool runlevel_config(const char *service, const char *level) +{ + char *init = rc_service_resolve(service); + char *conf; + size_t l; + bool retval; + + init = dirname(init); + init = dirname(init); + l = strlen(init) + strlen(level) + strlen(service) + 10; + conf = xmalloc(sizeof(char) * l); + snprintf(conf, l, "%s/conf.d/%s.%s", init, service, level); + retval = exists(conf); + free(conf); + + return retval; } #include "_usage.h" @@ -673,16 +668,14 @@ static const char * const longopts_help[] = { }; #include "_usage.c" -int main (int argc, char **argv) +int main(int argc, char **argv) { const char *bootlevel = NULL; - const char *sys = rc_sys (); + const char *sys = rc_sys(); char *newlevel = NULL; - char *service = NULL; - char **deporder = NULL; - char **tmplist; - int i = 0; - int j = 0; + RC_STRINGLIST *deporder = NULL; + RC_STRINGLIST *tmplist; + RC_STRING *service; bool going_down = false; bool interactive = false; int depoptions = RC_DEP_STRICT | RC_DEP_TRACE; @@ -692,116 +685,94 @@ int main (int argc, char **argv) bool parallel; int regen = 0; pid_t pid; + RC_STRING *svc1; + RC_STRING *svc2 = NULL; + struct utsname uts; +#ifdef __linux__ + char *cmd; + char *proc; + char *p; + char *token; +#endif - applet = basename_c (argv[0]); - atexit (cleanup); + applet = basename_c(argv[0]); + LIST_INIT(&service_pids); + atexit(cleanup); if (! applet) - eerrorx ("arguments required"); + eerrorx("arguments required"); - if (argc > 1 && (strcmp (argv[1], "--version") == 0)) { - printf ("%s (OpenRC", applet); + if (argc > 1 && (strcmp(argv[1], "--version") == 0)) { + printf("%s (OpenRC", applet); if (sys) - printf (" [%s]", sys); - printf (") " VERSION + printf(" [%s]", sys); + printf(") " VERSION #ifdef BRANDING - " (" BRANDING ")" + " (" BRANDING ")" #endif - "\n"); - exit (EXIT_SUCCESS); + "\n"); + exit(EXIT_SUCCESS); } /* Run our built in applets. If we ran one, we don't return. */ - run_applets (argc, argv); + run_applets(argc, argv); argc--; argv++; /* Change dir to / to ensure all scripts don't use stuff in pwd */ - chdir ("/"); + chdir("/"); /* RUNLEVEL is set by sysvinit as is a magic number * RC_SOFTLEVEL is set by us and is the name for this magic number * even though all our userland documentation refers to runlevel */ - RUNLEVEL = getenv ("RUNLEVEL"); - PREVLEVEL = getenv ("PREVLEVEL"); + RUNLEVEL = getenv("RUNLEVEL"); + PREVLEVEL = getenv("PREVLEVEL"); /* Ensure our environment is pure * Also, add our configuration to it */ - env = env_filter (); - tmplist = env_config (); - rc_strlist_join (&env, tmplist); - rc_strlist_free (tmplist); - - if (env) { - char *p; - -#ifdef __linux__ - /* clearenv isn't portable, but there's no harm in using it - * if we have it */ - clearenv (); -#else - char *var; - /* No clearenv present here then. - * We could manipulate environ directly ourselves, but it seems that - * some kernels bitch about this according to the environ man pages - * so we walk though environ and call unsetenv for each value. */ - while (environ[0]) { - tmp = xstrdup (environ[0]); - p = tmp; - var = strsep (&p, "="); - unsetenv (var); - free (tmp); - } - tmp = NULL; -#endif - - STRLIST_FOREACH (env, p, i) - if (strcmp (p, "RC_SOFTLEVEL") != 0 && strcmp (p, "SOFTLEVEL") != 0) - putenv (p); - - /* We don't free our list as that would be null in environ */ - } + env_filter(); + env_config(); argc++; argv--; - while ((opt = getopt_long (argc, argv, getoptstring, - longopts, (int *) 0)) != -1) + while ((opt = getopt_long(argc, argv, getoptstring, + longopts, (int *) 0)) != -1) { switch (opt) { - case 'o': - if (*optarg == '\0') - optarg = NULL; - exit (set_ksoftlevel (optarg) ? EXIT_SUCCESS : EXIT_FAILURE); - /* NOTREACHED */ - case_RC_COMMON_GETOPT + case 'o': + if (*optarg == '\0') + optarg = NULL; + exit(set_ksoftlevel(optarg) ? EXIT_SUCCESS : EXIT_FAILURE); + /* NOTREACHED */ + case_RC_COMMON_GETOPT } } newlevel = argv[optind++]; /* Enable logging */ - setenv ("EINFO_LOG", "rc", 1); + setenv("EINFO_LOG", "rc", 1); /* Export our PID */ - snprintf (pidstr, sizeof (pidstr), "%d", getpid ()); - setenv ("RC_PID", pidstr, 1); + snprintf(pidstr, sizeof(pidstr), "%d", getpid()); + setenv("RC_PID", pidstr, 1); /* Load current softlevel */ - bootlevel = getenv ("RC_BOOTLEVEL"); - runlevel = rc_runlevel_get (); + bootlevel = getenv("RC_BOOTLEVEL"); + runlevel = rc_runlevel_get(); - rc_logger_open (newlevel ? newlevel : runlevel); + rc_logger_open(newlevel ? newlevel : runlevel); /* Setup a signal handler */ - signal_setup (SIGINT, handle_signal); - signal_setup (SIGQUIT, handle_signal); - signal_setup (SIGTERM, handle_signal); - signal_setup (SIGUSR1, handle_signal); - signal_setup (SIGWINCH, handle_signal); - - if (! rc_yesno (getenv ("EINFO_QUIET"))) - interactive = exists (INTERACTIVE); - rc_plugin_load (); + signal_setup(SIGINT, handle_signal); + signal_setup(SIGQUIT, handle_signal); + signal_setup(SIGTERM, handle_signal); + signal_setup(SIGUSR1, handle_signal); + signal_setup(SIGWINCH, handle_signal); + + if (! rc_yesno(getenv("EINFO_QUIET"))) + interactive = exists(INTERACTIVE); + rc_plugin_load(); /* Check we're in the runlevel requested, ie from * rc single @@ -809,450 +780,417 @@ int main (int argc, char **argv) * rc reboot */ if (newlevel) { - if (strcmp (newlevel, RC_LEVEL_SYSINIT) == 0 + if (strcmp(newlevel, RC_LEVEL_SYSINIT) == 0 #ifndef PREFIX && RUNLEVEL && - (strcmp (RUNLEVEL, "S") == 0 || - strcmp (RUNLEVEL, "1") == 0) + (strcmp(RUNLEVEL, "S") == 0 || + strcmp(RUNLEVEL, "1") == 0) #endif - ) + ) { - - struct utsname uts; /* OK, we're either in runlevel 1 or single user mode */ -#ifdef __linux__ - char *cmd; -#endif /* exec init-early.sh if it exists * This should just setup the console to use the correct * font. Maybe it should setup the keyboard too? */ - if (exists (INITEARLYSH)) - run_script (INITEARLYSH); + if (exists(INITEARLYSH)) + run_script(INITEARLYSH); - uname (&uts); - printf ("\n %sOpenRC %s" VERSION "%s is starting up %s", - ecolor (ECOLOR_GOOD), ecolor (ECOLOR_HILITE), - ecolor (ECOLOR_NORMAL), ecolor (ECOLOR_BRACKET)); + uname(&uts); + printf("\n %sOpenRC %s" VERSION "%s is starting up %s", + ecolor(ECOLOR_GOOD), ecolor(ECOLOR_HILITE), + ecolor(ECOLOR_NORMAL), ecolor(ECOLOR_BRACKET)); #ifdef BRANDING - printf (BRANDING " (%s)", uts.machine); + printf(BRANDING " (%s)", uts.machine); #else - printf ("%s %s (%s)", - uts.sysname, - uts.release, - uts.machine); + printf("%s %s (%s)", + uts.sysname, + uts.release, + uts.machine); #endif if (sys) - printf (" [%s]", sys); + printf(" [%s]", sys); - printf ("%s\n\n", ecolor (ECOLOR_NORMAL)); + printf("%s\n\n", ecolor(ECOLOR_NORMAL)); - if (! rc_yesno (getenv ("EINFO_QUIET")) && - rc_conf_yesno ("rc_interactive")) - printf ("Press %sI%s to enter interactive boot mode\n\n", - ecolor (ECOLOR_GOOD), ecolor (ECOLOR_NORMAL)); + if (! rc_yesno(getenv ("EINFO_QUIET")) && + rc_conf_yesno("rc_interactive")) + printf("Press %sI%s to enter interactive boot mode\n\n", + ecolor(ECOLOR_GOOD), ecolor(ECOLOR_NORMAL)); - setenv ("RC_SOFTLEVEL", newlevel, 1); - rc_plugin_run (RC_HOOK_RUNLEVEL_START_IN, newlevel); + setenv("RC_SOFTLEVEL", newlevel, 1); + rc_plugin_run(RC_HOOK_RUNLEVEL_START_IN, newlevel); hook_out = RC_HOOK_RUNLEVEL_START_OUT; - run_script (INITSH); + run_script(INITSH); #ifdef __linux__ /* If we requested a softlevel, save it now */ - set_ksoftlevel (NULL); - if ((cmd = proc_getent ("softlevel"))) { - set_ksoftlevel (cmd); - free (cmd); + set_ksoftlevel(NULL); + if ((cmd = proc_getent("softlevel"))) { + set_ksoftlevel(cmd); + free(cmd); } #endif /* Setup our coldplugged services now */ - do_coldplug (); + do_coldplug(); - rc_plugin_run (RC_HOOK_RUNLEVEL_START_OUT, newlevel); + rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, newlevel); hook_out = 0; - if (want_interactive ()) - mark_interactive (); + if (want_interactive()) + mark_interactive(); - exit (EXIT_SUCCESS); - } else if (strcmp (newlevel, RC_LEVEL_SINGLE) == 0) { + exit(EXIT_SUCCESS); + } else if (strcmp(newlevel, RC_LEVEL_SINGLE) == 0) { #ifndef PREFIX if (! RUNLEVEL || - (strcmp (RUNLEVEL, "S") != 0 && - strcmp (RUNLEVEL, "1") != 0)) + (strcmp(RUNLEVEL, "S") != 0 && + strcmp(RUNLEVEL, "1") != 0)) { /* Remember the current runlevel for when we come back */ - set_ksoftlevel (runlevel); - single_user (); + set_ksoftlevel(runlevel); + single_user(); } #endif - } else if (strcmp (newlevel, RC_LEVEL_REBOOT) == 0) { + } else if (strcmp(newlevel, RC_LEVEL_REBOOT) == 0) { if (! RUNLEVEL || - strcmp (RUNLEVEL, "6") != 0) + strcmp(RUNLEVEL, "6") != 0) { - rc_logger_close (); - execl (SHUTDOWN, SHUTDOWN, "-r", "now", (char *) NULL); - eerrorx ("%s: unable to exec `" SHUTDOWN "': %s", - applet, strerror (errno)); + rc_logger_close(); + execl(SHUTDOWN, SHUTDOWN, "-r", "now", (char *) NULL); + eerrorx("%s: unable to exec `" SHUTDOWN "': %s", + applet, strerror(errno)); } - } else if (strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0) { + } else if (strcmp(newlevel, RC_LEVEL_SHUTDOWN) == 0) { if (! RUNLEVEL || - strcmp (RUNLEVEL, "0") != 0) + strcmp(RUNLEVEL, "0") != 0) { - rc_logger_close (); - execl (SHUTDOWN, SHUTDOWN, + rc_logger_close(); + execl(SHUTDOWN, SHUTDOWN, #ifdef __linux__ - "-h", + "-h", #else - "-p", + "-p", #endif - "now", (char *) NULL); - eerrorx ("%s: unable to exec `" SHUTDOWN "': %s", - applet, strerror (errno)); + "now", (char *) NULL); + eerrorx("%s: unable to exec `" SHUTDOWN "': %s", + applet, strerror(errno)); } } } /* Now we start handling our children */ - signal_setup (SIGCHLD, handle_signal); + signal_setup(SIGCHLD, handle_signal); /* We should only use ksoftlevel if we were in single user mode * If not, we need to erase ksoftlevel now. */ if (PREVLEVEL && - (strcmp (PREVLEVEL, "1") == 0 || - strcmp (PREVLEVEL, "S") == 0 || - strcmp (PREVLEVEL, "N") == 0)) + (strcmp(PREVLEVEL, "1") == 0 || + strcmp(PREVLEVEL, "S") == 0 || + strcmp(PREVLEVEL, "N") == 0)) { /* Try not to join boot and ksoftlevels together */ if (! newlevel || - strcmp (newlevel, getenv ("RC_BOOTLEVEL")) != 0) - if (get_ksoftlevel (ksoftbuffer, sizeof (ksoftbuffer))) + strcmp(newlevel, getenv("RC_BOOTLEVEL")) != 0) + if (get_ksoftlevel(ksoftbuffer, sizeof(ksoftbuffer))) newlevel = ksoftbuffer; } else if (! RUNLEVEL || - (strcmp (RUNLEVEL, "1") != 0 && - strcmp (RUNLEVEL, "S") != 0 && - strcmp (RUNLEVEL, "N") != 0)) + (strcmp(RUNLEVEL, "1") != 0 && + strcmp(RUNLEVEL, "S") != 0 && + strcmp(RUNLEVEL, "N") != 0)) { - set_ksoftlevel (NULL); + set_ksoftlevel(NULL); } if (newlevel && - (strcmp (newlevel, RC_LEVEL_REBOOT) == 0 || - strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0 || - strcmp (newlevel, RC_LEVEL_SINGLE) == 0)) + (strcmp(newlevel, RC_LEVEL_REBOOT) == 0 || + strcmp(newlevel, RC_LEVEL_SHUTDOWN) == 0 || + strcmp(newlevel, RC_LEVEL_SINGLE) == 0)) { going_down = true; - rc_runlevel_set (newlevel); - setenv ("RC_SOFTLEVEL", newlevel, 1); + rc_runlevel_set(newlevel); + setenv("RC_RUNLEVEL", newlevel, 1); #ifdef __FreeBSD__ /* FIXME: we shouldn't have todo this */ /* For some reason, wait_for_services waits for the logger proccess * to finish as well, but only on FreeBSD. We cannot allow this so * we stop logging now. */ - rc_logger_close (); + rc_logger_close(); #endif - rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_IN, newlevel); + rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_IN, newlevel); } else { - rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_IN, runlevel); + rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_IN, runlevel); } hook_out = RC_HOOK_RUNLEVEL_STOP_OUT; /* Check if runlevel is valid if we're changing */ - if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down) { - if (! rc_runlevel_exists (newlevel)) + if (newlevel && strcmp(runlevel, newlevel) != 0 && ! going_down) { + if (! rc_runlevel_exists(newlevel)) eerrorx ("%s: is not a valid runlevel", newlevel); } /* Load our deptree */ - if ((deptree = _rc_deptree_load (®en)) == NULL) - eerrorx ("failed to load deptree"); + if ((deptree = _rc_deptree_load(®en)) == NULL) + eerrorx("failed to load deptree"); /* Clean the failed services state dir */ - clean_failed (); + clean_failed(); - if (mkdir (RC_STOPPING, 0755) != 0) { + if (mkdir(RC_STOPPING, 0755) != 0) { if (errno == EACCES) - eerrorx ("%s: superuser access required", applet); - eerrorx ("%s: failed to create stopping dir: %s", - applet, strerror (errno)); + eerrorx("%s: superuser access required", applet); + eerrorx("%s: failed to create stopping dir `%s': %s", + applet, RC_STOPPING, strerror(errno)); } /* Build a list of all services to stop and then work out the * correct order for stopping them */ - stop_services = rc_services_in_state (RC_SERVICE_STARTING); - - tmplist = rc_services_in_state (RC_SERVICE_INACTIVE); - rc_strlist_join (&stop_services, tmplist); - rc_strlist_free (tmplist); - - tmplist = rc_services_in_state (RC_SERVICE_STARTED); - rc_strlist_join (&stop_services, tmplist); - rc_strlist_free (tmplist); - - deporder = rc_deptree_depends (deptree, types_nua, - (const char **) stop_services, - runlevel, depoptions | RC_DEP_STOP); - - rc_strlist_free (stop_services); - stop_services = deporder; - deporder = NULL; - rc_strlist_reverse (stop_services); + stop_services = rc_services_in_state(RC_SERVICE_STARTED); + tmplist = rc_services_in_state(RC_SERVICE_INACTIVE); + TAILQ_CONCAT(stop_services, tmplist); + free(tmplist); + tmplist = rc_services_in_state(RC_SERVICE_STARTING); + TAILQ_CONCAT(stop_services, tmplist); + free(tmplist); + rc_stringlist_sort(&stop_services); + + types_n = rc_stringlist_new(); + rc_stringlist_add(types_n, "needsme"); + + types_nua = rc_stringlist_new(); + rc_stringlist_add(types_nua, "ineed"); + rc_stringlist_add(types_nua, "iuse"); + rc_stringlist_add(types_nua, "iafter"); + + tmplist = rc_deptree_depends(deptree, types_nua, stop_services, + runlevel, depoptions | RC_DEP_STOP); + rc_stringlist_free(stop_services); + stop_services = tmplist; /* Load our list of coldplugged services */ - coldplugged_services = rc_services_in_state (RC_SERVICE_COLDPLUGGED); - if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 && - strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && - strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0) + coldplugged_services = rc_services_in_state(RC_SERVICE_COLDPLUGGED); + if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 && + strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && + strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0) { /* We need to include the boot runlevel services if we're not in it */ - start_services = rc_services_in_runlevel (bootlevel); + start_services = rc_services_in_runlevel(bootlevel); if (strcmp (newlevel ? newlevel : runlevel, bootlevel) != 0) { - tmplist = rc_services_in_runlevel (newlevel ? newlevel : runlevel); - rc_strlist_join (&start_services, tmplist); - rc_strlist_free (tmplist); + tmplist = rc_services_in_runlevel(newlevel ? newlevel : runlevel); + TAILQ_CONCAT(start_services, tmplist); + free(tmplist); } - STRLIST_FOREACH (coldplugged_services, service, i) - rc_strlist_add (&start_services, service); + TAILQ_FOREACH(service, coldplugged_services, entries) + rc_stringlist_addu(start_services, service->value); } /* Save our softlevel now */ if (going_down) - rc_runlevel_set (newlevel); + rc_runlevel_set(newlevel); - parallel = rc_conf_yesno ("rc_parallel"); + parallel = rc_conf_yesno("rc_parallel"); /* Now stop the services that shouldn't be running */ - STRLIST_FOREACH (stop_services, service, i) { - bool found = false; - char *conf = NULL; - char **stopdeps = NULL; - char *svc1 = NULL; - char *svc2 = NULL; - int k; - - if (rc_service_state (service) & RC_SERVICE_STOPPED) + TAILQ_FOREACH_REVERSE(service, stop_services, rc_stringlist, entries) { + if (rc_service_state(service->value) & RC_SERVICE_STOPPED) continue; /* We always stop the service when in these runlevels */ if (going_down) { - pid = rc_service_stop (service); + pid = rc_service_stop(service->value); if (pid > 0 && ! parallel) - rc_waitpid (pid); + rc_waitpid(pid); continue; } /* If we're in the start list then don't bother stopping us */ - STRLIST_FOREACH (start_services, svc1, j) - if (strcmp (svc1, service) == 0) { - found = true; + TAILQ_FOREACH(svc1, start_services, entries) + if (strcmp (svc1->value, service->value) == 0) break; - } - /* Unless we would use a different config file */ - if (found) { - size_t len; - if (! newlevel) - continue; - - len = strlen (service) + strlen (runlevel) + 2; - tmp = xmalloc (sizeof (char) * len); - snprintf (tmp, len, "%s.%s", service, runlevel); - conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL); - found = exists (conf); - CHAR_FREE (conf); - CHAR_FREE (tmp); - if (! found) { - len = strlen (service) + strlen (newlevel) + 2; - tmp = xmalloc (sizeof (char) * len); - snprintf (tmp, len, "%s.%s", service, newlevel); - conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL); - found = exists (conf); - CHAR_FREE (conf); - CHAR_FREE (tmp); - if (!found) + if (svc1) { + if (newlevel && strcmp(runlevel, newlevel) != 0) { + /* So we're in the start list. But we should + * be stopped if we have a runlevel + * configuration file for either the current + * or next so we use the correct one. */ + if (! runlevel_config(service->value, runlevel) && + ! runlevel_config(service->value, newlevel)) continue; } - } else { - /* Allow coldplugged services not to be in the runlevels list */ - if (rc_service_state (service) & RC_SERVICE_COLDPLUGGED) + else continue; } - /* We got this far! Or last check is to see if any any service that - * going to be started depends on us */ - rc_strlist_add (&stopdeps, service); - deporder = rc_deptree_depends (deptree, types_n, - (const char **) stopdeps, - runlevel, RC_DEP_STRICT); - rc_strlist_free (stopdeps); - stopdeps = NULL; - found = false; - STRLIST_FOREACH (deporder, svc1, j) { - STRLIST_FOREACH (start_services, svc2, k) - if (strcmp (svc1, svc2) == 0) { - found = true; + /* We got this far! Or last check is to see if any any service + * that going to be started depends on us */ + if (! svc1) { + tmplist = rc_stringlist_new(); + rc_stringlist_add(tmplist, service->value); + deporder = rc_deptree_depends(deptree, types_n, tmplist, + runlevel, RC_DEP_STRICT); + rc_stringlist_free(tmplist); + svc2 = NULL; + TAILQ_FOREACH (svc1, deporder, entries) { + TAILQ_FOREACH(svc2, start_services, entries) + if (strcmp (svc1->value, svc2->value) == 0) + break; + if (svc2) break; - } - if (found) - break; + } + rc_stringlist_free(deporder); + + if (svc2) + continue; } - rc_strlist_free (deporder); - deporder = NULL; /* After all that we can finally stop the blighter! */ - if (! found) { - pid = rc_service_stop (service); - - if (pid > 0) { - add_pid (pid); - if (! parallel) { - rc_waitpid (pid); - remove_pid (pid); - } + pid = rc_service_stop(service->value); + if (pid > 0) { + add_pid(pid); + if (! parallel) { + rc_waitpid(pid); + remove_pid(pid); } } } /* Wait for our services to finish */ - wait_for_services (); + wait_for_services(); /* Notify the plugins we have finished */ - rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_OUT, runlevel); + rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_OUT, runlevel); hook_out = 0; - rmdir (RC_STOPPING); + rmdir(RC_STOPPING); /* Store the new runlevel */ if (newlevel) { - rc_runlevel_set (newlevel); - free (runlevel); - runlevel = xstrdup (newlevel); - setenv ("RC_SOFTLEVEL", runlevel, 1); + rc_runlevel_set(newlevel); + free(runlevel); + runlevel = xstrdup(newlevel); + setenv("RC_RUNLEVEL", runlevel, 1); } /* Run the halt script if needed */ - if (strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 || - strcmp (runlevel, RC_LEVEL_REBOOT) == 0) + if (strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0 || + strcmp(runlevel, RC_LEVEL_REBOOT) == 0) { - rc_logger_close (); - execl (HALTSH, HALTSH, runlevel, (char *) NULL); - eerrorx ("%s: unable to exec `%s': %s", - applet, HALTSH, strerror (errno)); + rc_logger_close(); + execl(HALTSH, HALTSH, runlevel, (char *) NULL); + eerrorx("%s: unable to exec `%s': %s", + applet, HALTSH, strerror(errno)); } /* Single user is done now */ - if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0) { - if (exists (INTERACTIVE)) - unlink (INTERACTIVE); - sulogin (false); + if (strcmp(runlevel, RC_LEVEL_SINGLE) == 0) { + if (exists(INTERACTIVE)) + unlink(INTERACTIVE); + sulogin(false); } - mkdir (RC_STARTING, 0755); - rc_plugin_run (RC_HOOK_RUNLEVEL_START_IN, runlevel); + mkdir(RC_STARTING, 0755); + rc_plugin_run(RC_HOOK_RUNLEVEL_START_IN, runlevel); hook_out = RC_HOOK_RUNLEVEL_START_OUT; /* Re-add our coldplugged services if they stopped */ - STRLIST_FOREACH (coldplugged_services, service, i) - rc_service_mark (service, RC_SERVICE_COLDPLUGGED); + TAILQ_FOREACH(service, coldplugged_services, entries) + rc_service_mark(service->value, RC_SERVICE_COLDPLUGGED); /* Order the services to start */ - deporder = rc_deptree_depends (deptree, types_nua, - (const char **) start_services, - runlevel, depoptions | RC_DEP_START); - rc_strlist_free (start_services); + rc_stringlist_sort(&start_services); + deporder = rc_deptree_depends(deptree, types_nua, start_services, + runlevel, depoptions | RC_DEP_START); + rc_stringlist_free(start_services); start_services = deporder; - deporder = NULL; #ifdef __linux__ /* mark any services skipped as started */ - if (PREVLEVEL && strcmp (PREVLEVEL, "N") == 0) { - if ((service = proc_getent ("noinitd"))) { - char *p = service; - char *token; - - while ((token = strsep (&p, ","))) - rc_service_mark (token, RC_SERVICE_STARTED); - free (service); + if (PREVLEVEL && strcmp(PREVLEVEL, "N") == 0) { + proc = p = proc_getent("noinitd"); + if (proc) { + while ((token = strsep(&p, ","))) + rc_service_mark(token, RC_SERVICE_STARTED); + free(proc); } } #endif - STRLIST_FOREACH (start_services, service, i) { - if (rc_service_state (service) & RC_SERVICE_STOPPED) { + TAILQ_FOREACH(service, start_services, entries) { + if (rc_service_state(service->value) & RC_SERVICE_STOPPED) { if (! interactive) - interactive = want_interactive (); + interactive = want_interactive(); if (interactive) { interactive_retry: - printf ("\n"); - einfo ("About to start the service %s", service); - eindent (); - einfo ("1) Start the service\t\t2) Skip the service"); - einfo ("3) Continue boot process\t\t4) Exit to shell"); - eoutdent (); + printf("\n"); + einfo("About to start the service %s", + service->value); + eindent(); + einfo("1) Start the service\t\t2) Skip the service"); + einfo("3) Continue boot process\t\t4) Exit to shell"); + eoutdent(); interactive_option: - switch (read_key (true)) { - case '1': break; - case '2': continue; - case '3': interactive = false; break; - case '4': sulogin (true); goto interactive_retry; - default: goto interactive_option; + switch (read_key(true)) { + case '1': break; + case '2': continue; + case '3': interactive = false; break; + case '4': sulogin(true); goto interactive_retry; + default: goto interactive_option; } } - pid = rc_service_start (service); + pid = rc_service_start(service->value); /* Remember the pid if we're running in parallel */ if (pid > 0) { - add_pid (pid); + add_pid(pid); if (! parallel) { - rc_waitpid (pid); - remove_pid (pid); + rc_waitpid(pid); + remove_pid(pid); } } } } /* Wait for our services to finish */ - wait_for_services (); + wait_for_services(); - rc_plugin_run (RC_HOOK_RUNLEVEL_START_OUT, runlevel); + rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, runlevel); hook_out = 0; #ifdef __linux__ /* mark any services skipped as stopped */ - if (PREVLEVEL && strcmp (PREVLEVEL, "N") == 0) { - if ((service = proc_getent ("noinitd"))) { - char *p = service; - char *token; - - while ((token = strsep (&p, ","))) - rc_service_mark (token, RC_SERVICE_STOPPED); - free (service); + if (PREVLEVEL && strcmp(PREVLEVEL, "N") == 0) { + proc = p = proc_getent("noinitd"); + if (proc) { + while ((token = strsep(&p, ","))) + rc_service_mark(token, RC_SERVICE_STOPPED); + free(proc); } } #endif /* Store our interactive status for boot */ - if (interactive && strcmp (runlevel, bootlevel) == 0) - mark_interactive (); + if (interactive && strcmp(runlevel, bootlevel) == 0) + mark_interactive(); else { - if (exists (INTERACTIVE)) - unlink (INTERACTIVE); + if (exists(INTERACTIVE)) + unlink(INTERACTIVE); } /* If we're in the boot runlevel and we regenerated our dependencies * we need to delete them so that they are regenerated again in the * default runlevel as they may depend on things that are now available */ - if (regen && strcmp (runlevel, bootlevel) == 0) - unlink (RC_DEPTREE); + if (regen && strcmp(runlevel, bootlevel) == 0) + unlink(RC_DEPTREE_CACHE); - return (EXIT_SUCCESS); + return EXIT_SUCCESS; } diff --git a/src/rc/runscript.c b/src/rc/runscript.c index ef9a3e2a..cfc2611a 100644 --- a/src/rc/runscript.c +++ b/src/rc/runscript.c @@ -34,6 +34,7 @@ #include <sys/ioctl.h> #include <sys/param.h> #include <sys/stat.h> + #include <dlfcn.h> #include <errno.h> #include <fcntl.h> @@ -60,11 +61,10 @@ #include "rc.h" #include "rc-misc.h" #include "rc-plugin.h" -#include "strlist.h" #define SELINUX_LIB RC_LIBDIR "/runscript_selinux.so" -#define PREFIX_LOCK RC_SVCDIR "/prefix.lock" +#define PREFIX_LOCK RC_SVCDIR "/prefix.lock" /* usecs to wait while we poll the fifo */ #define WAIT_INTERVAL 20000000 @@ -75,192 +75,187 @@ #define ONE_SECOND 1000000000 static const char *applet = NULL; -static char **applet_list = NULL; +static RC_STRINGLIST *applet_list = NULL; +static RC_STRINGLIST *restart_services = NULL; +static RC_STRINGLIST *need_services = NULL; +static RC_STRINGLIST *use_services = NULL; +static RC_STRINGLIST *services = NULL; +static RC_STRINGLIST *tmplist = NULL; static char *service = NULL; static char *exclusive = NULL; static char *mtime_test = NULL; -static rc_depinfo_t *deptree = NULL; -static char **services = NULL; -static char **tmplist = NULL; -static char **providelist = NULL; -static char **restart_services = NULL; -static char **need_services = NULL; -static char **use_services = NULL; -static char **env = NULL; -static char *tmp = NULL; -static char *softlevel = NULL; +static RC_DEPTREE *deptree = NULL; +static char *runlevel = NULL; static bool sighup = false; static char *ibsave = NULL; static bool in_background = false; -static rc_hook_t hook_out = 0; +static RC_HOOK hook_out = 0; static pid_t service_pid = 0; static char *prefix = NULL; static bool prefix_locked = false; static int signal_pipe[2] = { -1, -1 }; static int master_tty = -1; -extern char **environ; - -static const char *const types_b[] = { "broken", NULL }; -static const char *const types_n[] = { "ineed", NULL }; -static const char *const types_nu[] = { "ineed", "iuse", NULL }; -static const char *const types_nua[] = { "ineed", "iuse", "iafter", NULL }; - -static const char *const types_m[] = { "needsme", NULL }; -static const char *const types_mua[] = { "needsme", "usesme", "beforeme", NULL }; +static RC_STRINGLIST *types_b = NULL; +static RC_STRINGLIST *types_n = NULL; +static RC_STRINGLIST *types_nu = NULL; +static RC_STRINGLIST *types_nua = NULL; +static RC_STRINGLIST *types_m = NULL; +static RC_STRINGLIST *types_mua = NULL; #ifdef __linux__ -static void (*selinux_run_init_old) (void); -static void (*selinux_run_init_new) (int argc, char **argv); +static void (*selinux_run_init_old)(void); +static void (*selinux_run_init_new)(int argc, char **argv); -static void setup_selinux (int argc, char **argv); +static void setup_selinux(int argc, char **argv); -static void setup_selinux (int argc, char **argv) +static void setup_selinux(int argc, char **argv) { void *lib_handle = NULL; - if (! exists (SELINUX_LIB)) + if (! exists(SELINUX_LIB)) return; - lib_handle = dlopen (SELINUX_LIB, RTLD_NOW | RTLD_GLOBAL); + lib_handle = dlopen(SELINUX_LIB, RTLD_NOW | RTLD_GLOBAL); if (! lib_handle) { - eerror ("dlopen: %s", dlerror ()); + eerror("dlopen: %s", dlerror()); return; } selinux_run_init_old = (void (*)(void)) - dlfunc (lib_handle, "selinux_runscript"); + dlfunc(lib_handle, "selinux_runscript"); selinux_run_init_new = (void (*)(int, char **)) - dlfunc (lib_handle, "selinux_runscript2"); + dlfunc(lib_handle, "selinux_runscript2"); /* Use new run_init if it exists, else fall back to old */ if (selinux_run_init_new) - selinux_run_init_new (argc, argv); + selinux_run_init_new(argc, argv); else if (selinux_run_init_old) - selinux_run_init_old (); + selinux_run_init_old(); else /* This shouldnt happen... probably corrupt lib */ - eerrorx ("run_init is missing from runscript_selinux.so!"); + eerrorx("run_init is missing from runscript_selinux.so!"); - dlclose (lib_handle); + dlclose(lib_handle); } #endif -static void handle_signal (int sig) +static void handle_signal(int sig) { int serrno = errno; char signame[10] = { '\0' }; struct winsize ws; switch (sig) { - case SIGHUP: - sighup = true; - break; - - case SIGCHLD: - if (signal_pipe[1] > -1) { - if (write (signal_pipe[1], &sig, sizeof (sig)) == -1) - eerror ("%s: send: %s", service, strerror (errno)); - } else - rc_waitpid (-1); - break; - - case SIGWINCH: - if (master_tty >= 0) { - ioctl (fileno (stdout), TIOCGWINSZ, &ws); - ioctl (master_tty, TIOCSWINSZ, &ws); - } - break; + case SIGHUP: + sighup = true; + break; + + case SIGCHLD: + if (signal_pipe[1] > -1) { + if (write(signal_pipe[1], &sig, sizeof(sig)) == -1) + eerror("%s: send: %s", service, strerror(errno)); + } else + rc_waitpid (-1); + break; - case SIGINT: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGINT"); - /* FALLTHROUGH */ - case SIGTERM: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGTERM"); - /* FALLTHROUGH */ - case SIGQUIT: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGQUIT"); - /* Send the signal to our children too */ - if (service_pid > 0) - kill (service_pid, sig); - eerrorx ("%s: caught %s, aborting", applet, signame); - /* NOTREACHED */ - - default: - eerror ("%s: caught unknown signal %d", applet, sig); + case SIGWINCH: + if (master_tty >= 0) { + ioctl(fileno(stdout), TIOCGWINSZ, &ws); + ioctl(master_tty, TIOCSWINSZ, &ws); + } + break; + + case SIGINT: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGINT"); + /* FALLTHROUGH */ + case SIGTERM: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGTERM"); + /* FALLTHROUGH */ + case SIGQUIT: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGQUIT"); + /* Send the signal to our children too */ + if (service_pid > 0) + kill(service_pid, sig); + eerrorx("%s: caught %s, aborting", applet, signame); + /* NOTREACHED */ + + default: + eerror("%s: caught unknown signal %d", applet, sig); } /* Restore errno */ errno = serrno; } -static time_t get_mtime (const char *pathname, bool follow_link) +static time_t get_mtime(const char *pathname, bool follow_link) { struct stat buf; int retval; if (! pathname) - return (0); + return 0; - retval = follow_link ? stat (pathname, &buf) : lstat (pathname, &buf); + retval = follow_link ? stat(pathname, &buf) : lstat(pathname, &buf); if (! retval) - return (buf.st_mtime); + return buf.st_mtime; errno = 0; - return (0); + return 0; } -static bool in_control () +static const char *const tests[] = { + "starting", "started", "stopping", "inactive", "wasinactive", NULL +}; +static bool in_control() { char *path; + time_t m; time_t mtime; - const char *tests[] = { "starting", "started", "stopping", - "inactive", "wasinactive", NULL }; int i = 0; if (sighup) - return (false); + return false; - if (! mtime_test || ! exists (mtime_test)) - return (false); + if (! mtime_test || ! exists(mtime_test)) + return false; - if (rc_service_state (applet) & RC_SERVICE_STOPPED) - return (false); + if (rc_service_state(applet) & RC_SERVICE_STOPPED) + return false; - if (! (mtime = get_mtime (mtime_test, false))) - return (false); + if (! (mtime = get_mtime(mtime_test, false))) + return false; while (tests[i]) { - path = rc_strcatpaths (RC_SVCDIR, tests[i], applet, (char *) NULL); - if (exists (path)) { - time_t m = get_mtime (path, false); + path = rc_strcatpaths(RC_SVCDIR, tests[i], applet, (char *) NULL); + if (exists(path)) { + m = get_mtime(path, false); if (mtime < m && m != 0) { - free (path); - return (false); + free(path); + return false; } } - free (path); + free(path); i++; } - return (true); + return true; } -static void uncoldplug () +static void uncoldplug() { - char *cold = rc_strcatpaths (RC_SVCDIR, "coldplugged", applet, (char *) NULL); - if (exists (cold) && unlink (cold) != 0) - eerror ("%s: unlink `%s': %s", applet, cold, strerror (errno)); - free (cold); + char *cold = rc_strcatpaths(RC_SVCDIR, "coldplugged", applet, (char *) NULL); + if (exists(cold) && unlink(cold) != 0) + eerror("%s: unlink `%s': %s", applet, cold, strerror(errno)); + free(cold); } -static void start_services (char **list) { - char *svc; - int i; - rc_service_state_t state = rc_service_state (service); +static void start_services(RC_STRINGLIST *list) { + RC_STRING *svc; + RC_SERVICE state = rc_service_state (service); if (! list) return; @@ -270,102 +265,107 @@ static void start_services (char **list) { state & RC_SERVICE_STARTING || state & RC_SERVICE_STARTED) { - STRLIST_FOREACH (list, svc, i) { - if (rc_service_state (svc) & RC_SERVICE_STOPPED) { + TAILQ_FOREACH(svc, list, entries) { + if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) { if (state & RC_SERVICE_INACTIVE || state & RC_SERVICE_WASINACTIVE) { - rc_service_schedule_start (service, svc); - ewarn ("WARNING: %s is scheduled to started when %s has started", - svc, applet); + rc_service_schedule_start(service, svc->value); + ewarn("WARNING: %s is scheduled to started" + " when %s has started", + svc->value, applet); } else - rc_service_start (svc); + rc_service_start(svc->value); } } } } -static void restore_state (void) +static void restore_state(void) { - rc_service_state_t state; + RC_SERVICE state; - if (rc_in_plugin || ! in_control ()) + if (rc_in_plugin || ! in_control()) return; - state = rc_service_state (applet); + state = rc_service_state(applet); if (state & RC_SERVICE_STOPPING) { - if (state & RC_SERVICE_WASINACTIVE) - rc_service_mark (applet, RC_SERVICE_INACTIVE); + rc_service_mark(applet, RC_SERVICE_INACTIVE); else - rc_service_mark (applet, RC_SERVICE_STARTED); - if (rc_runlevel_stopping ()) - rc_service_mark (applet, RC_SERVICE_FAILED); + rc_service_mark(applet, RC_SERVICE_STARTED); + if (rc_runlevel_stopping()) + rc_service_mark(applet, RC_SERVICE_FAILED); } else if (state & RC_SERVICE_STARTING) { if (state & RC_SERVICE_WASINACTIVE) - rc_service_mark (applet, RC_SERVICE_INACTIVE); + rc_service_mark(applet, RC_SERVICE_INACTIVE); else - rc_service_mark (applet, RC_SERVICE_STOPPED); - if (rc_runlevel_starting ()) - rc_service_mark (applet, RC_SERVICE_FAILED); + rc_service_mark(applet, RC_SERVICE_STOPPED); + if (rc_runlevel_starting()) + rc_service_mark(applet, RC_SERVICE_FAILED); } if (exclusive) - unlink (exclusive); - free (exclusive); + unlink(exclusive); + free(exclusive); exclusive = NULL; } -static void cleanup (void) +static void cleanup(void) { - restore_state (); + restore_state(); if (! rc_in_plugin) { if (prefix_locked) - unlink (PREFIX_LOCK); + unlink(PREFIX_LOCK); if (hook_out) { - rc_plugin_run (hook_out, applet); + rc_plugin_run(hook_out, applet); if (hook_out == RC_HOOK_SERVICE_START_DONE) - rc_plugin_run (RC_HOOK_SERVICE_START_OUT, applet); + rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); else if (hook_out == RC_HOOK_SERVICE_STOP_DONE) - rc_plugin_run (RC_HOOK_SERVICE_STOP_OUT, applet); + rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); } if (restart_services) - start_services (restart_services); + start_services(restart_services); } - rc_plugin_unload (); - rc_deptree_free (deptree); - rc_strlist_free (services); - rc_strlist_free (providelist); - rc_strlist_free (need_services); - rc_strlist_free (use_services); - rc_strlist_free (restart_services); - rc_strlist_free (applet_list); - rc_strlist_free (tmplist); + rc_stringlist_free(types_b); + rc_stringlist_free(types_n); + rc_stringlist_free(types_nu); + rc_stringlist_free(types_nua); + rc_stringlist_free(types_m); + rc_stringlist_free(types_mua); + + rc_plugin_unload(); + rc_deptree_free(deptree); + + rc_stringlist_free(restart_services); + rc_stringlist_free(need_services); + rc_stringlist_free(use_services); + rc_stringlist_free(services); + rc_stringlist_free(applet_list); + rc_stringlist_free(tmplist); free (ibsave); - rc_strlist_free (env); - if (mtime_test) { if (! rc_in_plugin) - unlink (mtime_test); - free (mtime_test); + unlink(mtime_test); + free(mtime_test); } - free (exclusive); - free (service); - free (prefix); - free (softlevel); + free(exclusive); + free(service); + free(prefix); + free(runlevel); } -static int write_prefix (const char *buffer, size_t bytes, bool *prefixed) { +static int write_prefix(const char *buffer, size_t bytes, bool *prefixed) { unsigned int i; - const char *ec = ecolor (ECOLOR_HILITE); - const char *ec_normal = ecolor (ECOLOR_NORMAL); + const char *ec = ecolor(ECOLOR_HILITE); + const char *ec_normal = ecolor(ECOLOR_NORMAL); ssize_t ret = 0; - int fd = fileno (stdout); + int fd = fileno(stdout); for (i = 0; i < bytes; i++) { /* We don't prefix escape codes, like eend */ @@ -373,25 +373,25 @@ static int write_prefix (const char *buffer, size_t bytes, bool *prefixed) { *prefixed = true; if (! *prefixed) { - ret += write (fd, ec, strlen (ec)); - ret += write (fd, prefix, strlen (prefix)); - ret += write (fd, ec_normal, strlen (ec_normal)); - ret += write (fd, "|", 1); + ret += write(fd, ec, strlen(ec)); + ret += write(fd, prefix, strlen(prefix)); + ret += write(fd, ec_normal, strlen(ec_normal)); + ret += write(fd, "|", 1); *prefixed = true; } if (buffer[i] == '\n') *prefixed = false; - ret += write (fd, buffer + i, 1); + ret += write(fd, buffer + i, 1); } - return (ret); + return ret; } -static bool svc_exec (const char *arg1, const char *arg2) +static bool svc_exec(const char *arg1, const char *arg2) { bool execok; - int fdout = fileno (stdout); + int fdout = fileno(stdout); struct termios tt; struct winsize ws; int i; @@ -405,12 +405,12 @@ static bool svc_exec (const char *arg1, const char *arg2) int slave_tty; /* Setup our signal pipe */ - if (pipe (signal_pipe) == -1) - eerrorx ("%s: pipe: %s", service, applet); + if (pipe(signal_pipe) == -1) + eerrorx("%s: pipe: %s", service, applet); for (i = 0; i < 2; i++) - if ((flags = fcntl (signal_pipe[i], F_GETFD, 0) == -1 || - fcntl (signal_pipe[i], F_SETFD, flags | FD_CLOEXEC) == -1)) - eerrorx ("%s: fcntl: %s", service, strerror (errno)); + if ((flags = fcntl(signal_pipe[i], F_GETFD, 0) == -1 || + fcntl(signal_pipe[i], F_SETFD, flags | FD_CLOEXEC) == -1)) + eerrorx("%s: fcntl: %s", service, strerror(errno)); /* Open a pty for our prefixed output * We do this instead of mapping pipes to stdout, stderr so that @@ -418,127 +418,125 @@ static bool svc_exec (const char *arg1, const char *arg2) * The only loss is that we can no longer tell the difference * between the childs stdout or stderr */ master_tty = slave_tty = -1; - if (prefix && isatty (fdout)) { - tcgetattr (fdout, &tt); - ioctl (fdout, TIOCGWINSZ, &ws); + if (prefix && isatty(fdout)) { + tcgetattr(fdout, &tt); + ioctl(fdout, TIOCGWINSZ, &ws); /* If the below call fails due to not enough ptys then we don't * prefix the output, but we still work */ - openpty (&master_tty, &slave_tty, NULL, &tt, &ws); + openpty(&master_tty, &slave_tty, NULL, &tt, &ws); if (master_tty >= 0 && - (flags = fcntl (master_tty, F_GETFD, 0)) == 0) - fcntl (master_tty, F_SETFD, flags | FD_CLOEXEC); + (flags = fcntl(master_tty, F_GETFD, 0)) == 0) + fcntl(master_tty, F_SETFD, flags | FD_CLOEXEC); if (slave_tty >=0 && - (flags = fcntl (slave_tty, F_GETFD, 0)) == 0) - fcntl (slave_tty, F_SETFD, flags | FD_CLOEXEC); + (flags = fcntl(slave_tty, F_GETFD, 0)) == 0) + fcntl(slave_tty, F_SETFD, flags | FD_CLOEXEC); } service_pid = fork(); if (service_pid == -1) - eerrorx ("%s: fork: %s", service, strerror (errno)); + eerrorx("%s: fork: %s", service, strerror(errno)); if (service_pid == 0) { if (slave_tty >= 0) { - dup2 (slave_tty, 1); - dup2 (slave_tty, 2); + dup2(slave_tty, 1); + dup2(slave_tty, 2); } - if (exists (RC_SVCDIR "/runscript.sh")) { - execl (RC_SVCDIR "/runscript.sh", RC_SVCDIR "/runscript.sh", - service, arg1, arg2, (char *) NULL); - eerror ("%s: exec `" RC_SVCDIR "/runscript.sh': %s", - service, strerror (errno)); - _exit (EXIT_FAILURE); + if (exists(RC_SVCDIR "/runscript.sh")) { + execl(RC_SVCDIR "/runscript.sh", RC_SVCDIR "/runscript.sh", + service, arg1, arg2, (char *) NULL); + eerror("%s: exec `" RC_SVCDIR "/runscript.sh': %s", + service, strerror(errno)); + _exit(EXIT_FAILURE); } else { - execl (RC_LIBDIR "/sh/runscript.sh", RC_LIBDIR "/sh/runscript.sh", - service, arg1, arg2, (char *) NULL); - eerror ("%s: exec `" RC_LIBDIR "/sh/runscript.sh': %s", - service, strerror (errno)); - _exit (EXIT_FAILURE); + execl(RC_LIBDIR "/sh/runscript.sh", RC_LIBDIR "/sh/runscript.sh", + service, arg1, arg2, (char *) NULL); + eerror("%s: exec `" RC_LIBDIR "/sh/runscript.sh': %s", + service, strerror(errno)); + _exit(EXIT_FAILURE); } } - selfd = MAX (master_tty, signal_pipe[0]) + 1; - buffer = xmalloc (sizeof (char) * BUFSIZ); + selfd = MAX(master_tty, signal_pipe[0]) + 1; + buffer = xmalloc(sizeof(char) * BUFSIZ); for (;;) { - FD_ZERO (&rset); - FD_SET (signal_pipe[0], &rset); + FD_ZERO(&rset); + FD_SET(signal_pipe[0], &rset); if (master_tty >= 0) - FD_SET (master_tty, &rset); + FD_SET(master_tty, &rset); - if ((s = select (selfd, &rset, NULL, NULL, NULL)) == -1) { + if ((s = select(selfd, &rset, NULL, NULL, NULL)) == -1) { if (errno != EINTR) { - eerror ("%s: select: %s", service, strerror (errno)); + eerror("%s: select: %s", service, strerror(errno)); break; } } if (s > 0) { - if (master_tty >= 0 && FD_ISSET (master_tty, &rset)) { - bytes = read (master_tty, buffer, BUFSIZ); - write_prefix (buffer, bytes, &prefixed); + if (master_tty >= 0 && FD_ISSET(master_tty, &rset)) { + bytes = read(master_tty, buffer, BUFSIZ); + write_prefix(buffer, bytes, &prefixed); } /* Only SIGCHLD signals come down this pipe */ - if (FD_ISSET (signal_pipe[0], &rset)) + if (FD_ISSET(signal_pipe[0], &rset)) break; } } - free (buffer); - close (signal_pipe[0]); - close (signal_pipe[1]); + free(buffer); + close(signal_pipe[0]); + close(signal_pipe[1]); signal_pipe[0] = signal_pipe[1] = -1; if (master_tty >= 0) { /* Why did we do this? */ /* signal (SIGWINCH, SIG_IGN); */ - close (master_tty); + close(master_tty); master_tty = -1; } - execok = rc_waitpid (service_pid) == 0 ? true : false; + execok = rc_waitpid(service_pid) == 0 ? true : false; service_pid = 0; - return (execok); + return execok; } -static bool svc_wait (rc_depinfo_t *depinfo, const char *svc) +static bool svc_wait(const char *svc) { - char *s; - char *fifo; + char fifo[PATH_MAX]; struct timespec ts; int nloops = WAIT_MAX * (ONE_SECOND / WAIT_INTERVAL); bool retval = false; bool forever = false; - char **keywords = NULL; - int i; - - if (! service) - return (false); + RC_STRINGLIST *keywords; + RC_STRING *s; /* Some services don't have a timeout, like fsck */ - keywords = rc_deptree_depend (depinfo, svc, "keyword"); - STRLIST_FOREACH (keywords, s, i) { - if (strcmp (s, "notimeout") == 0) { - forever = true; - break; + keywords = rc_deptree_depend(deptree, svc, "keyword"); + if (keywords) { + TAILQ_FOREACH(s, keywords, entries) { + if (strcmp (s->value, "notimeout") == 0) { + forever = true; + break; + } } + rc_stringlist_free (keywords); } - rc_strlist_free (keywords); - fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename_c (svc), (char *) NULL); + snprintf(fifo, sizeof(fifo), RC_SVCDIR "/exclusive/%s", basename_c(svc)); ts.tv_sec = 0; ts.tv_nsec = WAIT_INTERVAL; while (nloops) { - if (! exists (fifo)) { + if (! exists(fifo)) { retval = true; break; } - if (nanosleep (&ts, NULL) == -1) { + if (nanosleep(&ts, NULL) == -1) { if (errno != EINTR) break; } @@ -547,190 +545,211 @@ static bool svc_wait (rc_depinfo_t *depinfo, const char *svc) nloops --; } - if (! exists (fifo)) + if (! exists(fifo)) retval = true; - free (fifo); - return (retval); + return retval; } -static rc_service_state_t svc_status () +static RC_SERVICE svc_status(void) { char status[10]; int (*e) (const char *fmt, ...) = &einfo; - - rc_service_state_t state = rc_service_state (service); + RC_SERVICE state = rc_service_state(service); if (state & RC_SERVICE_STOPPING) { - snprintf (status, sizeof (status), "stopping"); + snprintf(status, sizeof(status), "stopping"); e = &ewarn; } else if (state & RC_SERVICE_STARTING) { - snprintf (status, sizeof (status), "starting"); + snprintf(status, sizeof(status), "starting"); e = &ewarn; } else if (state & RC_SERVICE_INACTIVE) { - snprintf (status, sizeof (status), "inactive"); + snprintf(status, sizeof(status), "inactive"); e = &ewarn; } else if (state & RC_SERVICE_STARTED) { - if (geteuid () == 0 && rc_service_daemons_crashed (service)) { - snprintf (status, sizeof (status), "crashed"); + if (rc_service_daemons_crashed(service)) { + snprintf(status, sizeof (status), "crashed"); e = &eerror; } else - snprintf (status, sizeof (status), "started"); + snprintf(status, sizeof(status), "started"); } else - snprintf (status, sizeof (status), "stopped"); + snprintf(status, sizeof(status), "stopped"); - e ("status: %s", status); - return (state); + e("status: %s", status); + return state; } -static void make_exclusive () +static void make_exclusive(void) { char *path; size_t l; /* We create a fifo so that other services can wait until we complete */ if (! exclusive) - exclusive = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL); + exclusive = rc_strcatpaths(RC_SVCDIR, "exclusive", applet, (char *) NULL); - if (mkfifo (exclusive, 0600) != 0 && errno != EEXIST && + if (mkfifo(exclusive, 0600) != 0 && errno != EEXIST && (errno != EACCES || geteuid () == 0)) eerrorx ("%s: unable to create fifo `%s': %s", - applet, exclusive, strerror (errno)); + applet, exclusive, strerror(errno)); - path = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL); + path = rc_strcatpaths(RC_SVCDIR, "exclusive", applet, (char *) NULL); l = strlen (path) + 16; - mtime_test = xmalloc (sizeof (char) * l); - snprintf (mtime_test, l, "%s.%d", path, getpid ()); - free (path); - - if (exists (mtime_test) && unlink (mtime_test) != 0) { - eerror ("%s: unlink `%s': %s", - applet, mtime_test, strerror (errno)); - free (mtime_test); + mtime_test = xmalloc(sizeof (char) * l); + snprintf(mtime_test, l, "%s.%d", path, getpid()); + free(path); + + if (exists(mtime_test) && unlink(mtime_test) != 0) { + eerror("%s: unlink `%s': %s", + applet, mtime_test, strerror(errno)); + free(mtime_test); mtime_test = NULL; return; } - if (symlink (service, mtime_test) != 0) { - eerror ("%s: symlink `%s' to `%s': %s", - applet, service, mtime_test, strerror (errno)); - free (mtime_test); + if (symlink(service, mtime_test) != 0) { + eerror("%s: symlink `%s' to `%s': %s", + applet, service, mtime_test, strerror(errno)); + free(mtime_test); mtime_test = NULL; } } -static void unlink_mtime_test () +static void unlink_mtime_test(void) { - if (unlink (mtime_test) != 0) - eerror ("%s: unlink `%s': %s", applet, mtime_test, strerror (errno)); - free (mtime_test); + if (unlink(mtime_test) != 0) + eerror("%s: unlink `%s': %s", applet, mtime_test, strerror(errno)); + free(mtime_test); mtime_test = NULL; } -static void get_started_services () +static void get_started_services(void) +{ + RC_STRINGLIST *tmp = rc_services_in_state(RC_SERVICE_INACTIVE); + rc_stringlist_free(restart_services); + restart_services = rc_services_in_state(RC_SERVICE_STARTED); + TAILQ_CONCAT(restart_services, tmp); + free(tmp); +} + +static void setup_types(void) { - rc_strlist_free (tmplist); - tmplist = rc_services_in_state (RC_SERVICE_INACTIVE); - rc_strlist_free (restart_services); - restart_services = rc_services_in_state (RC_SERVICE_STARTED); - rc_strlist_join (&restart_services, tmplist); - rc_strlist_free (tmplist); - tmplist = NULL; + types_b = rc_stringlist_new(); + rc_stringlist_add(types_b, "broken"); + + types_n = rc_stringlist_new(); + rc_stringlist_add(types_n, "ineed"); + + types_nu = rc_stringlist_new(); + rc_stringlist_add(types_nu, "ineed"); + rc_stringlist_add(types_nu, "iuse"); + + types_nua = rc_stringlist_new(); + rc_stringlist_add(types_nua, "ineed"); + rc_stringlist_add(types_nua, "iuse"); + rc_stringlist_add(types_nua, "iafter"); + + types_m = rc_stringlist_new(); + rc_stringlist_add(types_m, "needsme"); + + types_mua = rc_stringlist_new(); + rc_stringlist_add(types_mua, "needsme"); + rc_stringlist_add(types_mua, "usesme"); + rc_stringlist_add(types_mua, "beforeme"); } -static void svc_start (bool deps) +static void svc_start(bool deps) { bool started; bool background = false; - char *svc; - char *svc2; - int i; - int j; + RC_STRING *svc; + RC_STRING *svc2; int depoptions = RC_DEP_TRACE; - rc_service_state_t state; + RC_SERVICE state; + bool first; + int n; + size_t len; + char *p; + char *tmp; - state = rc_service_state (service); + state = rc_service_state(service); - if (rc_yesno (getenv ("IN_HOTPLUG")) || in_background) { + if (rc_yesno(getenv("IN_HOTPLUG")) || in_background) { if (! state & RC_SERVICE_INACTIVE && ! state & RC_SERVICE_STOPPED) - exit (EXIT_FAILURE); + exit(EXIT_FAILURE); background = true; } if (state & RC_SERVICE_STARTED) { - ewarn ("WARNING: %s has already been started", applet); + ewarn("WARNING: %s has already been started", applet); return; } else if (state & RC_SERVICE_STARTING) - ewarnx ("WARNING: %s is already starting", applet); + ewarnx("WARNING: %s is already starting", applet); else if (state & RC_SERVICE_STOPPING) - ewarnx ("WARNING: %s is stopping", applet); + ewarnx("WARNING: %s is stopping", applet); else if (state & RC_SERVICE_INACTIVE && ! background) - ewarnx ("WARNING: %s has already started, but is inactive", applet); + ewarnx("WARNING: %s has already started, but is inactive", applet); - if (! rc_service_mark (service, RC_SERVICE_STARTING)) { + if (! rc_service_mark(service, RC_SERVICE_STARTING)) { if (errno == EACCES) - eerrorx ("%s: superuser access required", applet); - eerrorx ("ERROR: %s has been started by something else", applet); + eerrorx("%s: superuser access required", applet); + eerrorx("ERROR: %s has been started by something else", applet); } - make_exclusive (service); + make_exclusive(); hook_out = RC_HOOK_SERVICE_START_OUT; - rc_plugin_run (RC_HOOK_SERVICE_START_IN, applet); + rc_plugin_run(RC_HOOK_SERVICE_START_IN, applet); - if (rc_conf_yesno ("rc_depend_strict")) + if (rc_conf_yesno("rc_depend_strict")) depoptions |= RC_DEP_STRICT; if (deps) { if (! deptree && ((deptree = _rc_deptree_load (NULL)) == NULL)) - eerrorx ("failed to load deptree"); + eerrorx("failed to load deptree"); - rc_strlist_free (services); - services = rc_deptree_depends (deptree, types_b, - (const char * const *) applet_list, - softlevel, 0); - if (services) { + if (! types_b) + setup_types(); + + services = rc_deptree_depends(deptree, types_b, applet_list, + runlevel, 0); + if (TAILQ_FIRST(services)) { eerrorn ("ERROR: `%s' needs ", applet); - STRLIST_FOREACH (services, svc, i) { - if (i > 0) - fprintf (stderr, ", "); - fprintf (stderr, "%s", svc); + first = true; + TAILQ_FOREACH(svc, services, entries) { + if (first) + first = false; + else + fprintf(stderr, ", "); + fprintf(stderr, "%s", svc->value); } - exit (EXIT_FAILURE); + exit(EXIT_FAILURE); } - rc_strlist_free (services); + rc_stringlist_free(services); services = NULL; - rc_strlist_free (need_services); - need_services = rc_deptree_depends (deptree, types_n, - (const char * const *) applet_list, - softlevel, depoptions); - - rc_strlist_free (use_services); - use_services = rc_deptree_depends (deptree, types_nu, - (const char * const *) applet_list, - softlevel, depoptions); - - if (! rc_runlevel_starting ()) { - STRLIST_FOREACH (use_services, svc, i) - if (rc_service_state (svc) & RC_SERVICE_STOPPED) { - pid_t pid = rc_service_start (svc); - if (! rc_conf_yesno ("rc_parallel")) - rc_waitpid (pid); + need_services = rc_deptree_depends(deptree, types_n, applet_list, + runlevel, depoptions); + use_services = rc_deptree_depends(deptree, types_nu, applet_list, + runlevel, depoptions); + + if (! rc_runlevel_starting()) + TAILQ_FOREACH(svc, use_services, entries) + if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) { + pid_t pid = rc_service_start(svc->value); + if (! rc_conf_yesno("rc_parallel")) + rc_waitpid(pid); } - } /* Now wait for them to start */ - services = rc_deptree_depends (deptree, types_nua, - (const char * const *) applet_list, - softlevel, depoptions); + services = rc_deptree_depends(deptree, types_nua, applet_list, + runlevel, depoptions); /* We use tmplist to hold our scheduled by list */ - rc_strlist_free (tmplist); - tmplist = NULL; + tmplist = rc_stringlist_new(); - STRLIST_FOREACH (services, svc, i) { - rc_service_state_t svcs = rc_service_state (svc); + TAILQ_FOREACH(svc, services, entries) { + RC_SERVICE svcs = rc_service_state(svc->value); if (svcs & RC_SERVICE_STARTED) continue; @@ -738,270 +757,272 @@ static void svc_start (bool deps) * starting state which we are after */ if (svcs & RC_SERVICE_STARTING && svcs & RC_SERVICE_WASINACTIVE) { - bool use = false; - STRLIST_FOREACH (use_services, svc2, j) - if (strcmp (svc, svc2) == 0) { - use = true; + TAILQ_FOREACH(svc2, use_services, entries) { + if (strcmp (svc->value, svc2->value) == 0) break; } - if (! use) + if (! svc2) continue; } - if (! svc_wait (deptree, svc)) - eerror ("%s: timed out waiting for %s", applet, svc); - if ((svcs = rc_service_state (svc)) & RC_SERVICE_STARTED) + if (! svc_wait(svc->value)) + eerror ("%s: timed out waiting for %s", + applet, svc->value); + if ((svcs = rc_service_state(svc->value)) & RC_SERVICE_STARTED) continue; - - STRLIST_FOREACH (need_services, svc2, j) - if (strcmp (svc, svc2) == 0) { + TAILQ_FOREACH(svc2, need_services, entries) { + if (strcmp (svc->value, svc2->value) == 0) { if (svcs & RC_SERVICE_INACTIVE || svcs & RC_SERVICE_WASINACTIVE) - rc_strlist_add (&tmplist, svc); + rc_stringlist_add(tmplist, svc->value); else - eerrorx ("ERROR: cannot start %s as %s would not start", - applet, svc); + eerrorx("ERROR: cannot start %s as" + " %s would not start", + applet, svc->value); } + } } - if (tmplist) { - int n = 0; - size_t len = 0; - char *p; - + if (TAILQ_FIRST(tmplist)) { /* Set the state now, then unlink our exclusive so that our scheduled list is preserved */ - rc_service_mark (service, RC_SERVICE_STOPPED); - unlink_mtime_test (); - - STRLIST_FOREACH (tmplist, svc, i) { - rc_service_schedule_start (svc, service); - rc_strlist_free (providelist); - providelist = rc_deptree_depend (deptree, "iprovide", svc); - STRLIST_FOREACH (providelist, svc2, j) - rc_service_schedule_start (svc2, service); - - len += strlen (svc) + 2; + rc_service_mark(service, RC_SERVICE_STOPPED); + unlink_mtime_test(); + + rc_stringlist_free(use_services); + use_services = NULL; + len = 0; + n = 0; + TAILQ_FOREACH(svc, tmplist, entries) { + rc_service_schedule_start(svc->value, service); + use_services = rc_deptree_depend(deptree, "iprovide", + svc->value); + TAILQ_FOREACH (svc2, use_services, entries) + rc_service_schedule_start(svc2->value, service); + rc_stringlist_free(use_services); + use_services = NULL; + len += strlen(svc->value) + 2; n++; } len += 5; - tmp = xmalloc (sizeof (char) * len); - p = tmp; - STRLIST_FOREACH (tmplist, svc, i) { - if (i > 1) { - if (i == n) - p += snprintf (p, len, " or "); - else - p += snprintf (p, len, ", "); - } - p += snprintf (p, len, "%s", svc); + tmp = p = xmalloc(sizeof(char) * len); + TAILQ_FOREACH(svc, tmplist, entries) { + if (p != tmp) + p += snprintf(p, len, ", "); + p += snprintf(p, len, "%s", svc->value); } - ewarnx ("WARNING: %s is scheduled to start when %s has started", - applet, tmp); + free(tmp); + ewarnx("WARNING: %s is scheduled to start when %s has started", + applet, tmp); } - rc_strlist_free (services); + rc_stringlist_free(services); services = NULL; + rc_stringlist_free(tmplist); + tmplist = NULL; } if (ibsave) - setenv ("IN_BACKGROUND", ibsave, 1); + setenv("IN_BACKGROUND", ibsave, 1); hook_out = RC_HOOK_SERVICE_START_DONE; - rc_plugin_run (RC_HOOK_SERVICE_START_NOW, applet); - started = svc_exec ("start", NULL); + rc_plugin_run(RC_HOOK_SERVICE_START_NOW, applet); + started = svc_exec("start", NULL); if (ibsave) - unsetenv ("IN_BACKGROUND"); + unsetenv("IN_BACKGROUND"); - if (in_control ()) { + if (in_control()) { if (! started) - eerrorx ("ERROR: %s failed to start", applet); + eerrorx("ERROR: %s failed to start", applet); } else { - if (rc_service_state (service) & RC_SERVICE_INACTIVE) - ewarnx ("WARNING: %s has started, but is inactive", applet); + if (rc_service_state(service) & RC_SERVICE_INACTIVE) + ewarnx("WARNING: %s has started, but is inactive", applet); else - ewarnx ("WARNING: %s not under our control, aborting", applet); + ewarnx("WARNING: %s not under our control, aborting", applet); } - rc_service_mark (service, RC_SERVICE_STARTED); - unlink_mtime_test (); + rc_service_mark(service, RC_SERVICE_STARTED); + unlink_mtime_test(); hook_out = RC_HOOK_SERVICE_START_OUT; - rc_plugin_run (RC_HOOK_SERVICE_START_DONE, applet); + rc_plugin_run(RC_HOOK_SERVICE_START_DONE, applet); if (exclusive) - unlink (exclusive); + unlink(exclusive); /* Now start any scheduled services */ - rc_strlist_free (services); - services = rc_services_scheduled (service); - STRLIST_FOREACH (services, svc, i) - if (rc_service_state (svc) & RC_SERVICE_STOPPED) - rc_service_start (svc); - rc_strlist_free (services); - services = NULL; + services = rc_services_scheduled(service); + if (services) { + TAILQ_FOREACH(svc, services, entries) + if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) + rc_service_start(svc->value); + rc_stringlist_free(services); + services = NULL; + } /* Do the same for any services we provide */ - rc_strlist_free (tmplist); - tmplist = rc_deptree_depend (deptree, "iprovide", applet); - - STRLIST_FOREACH (tmplist, svc2, j) { - rc_strlist_free (services); - services = rc_services_scheduled (svc2); - STRLIST_FOREACH (services, svc, i) - if (rc_service_state (svc) & RC_SERVICE_STOPPED) - rc_service_start (svc); + tmplist = rc_deptree_depend(deptree, "iprovide", applet); + if (tmplist) { + TAILQ_FOREACH(svc, tmplist, entries) { + services = rc_services_scheduled(svc->value); + if (services) { + TAILQ_FOREACH(svc2, services, entries) + if (rc_service_state(svc2->value) & RC_SERVICE_STOPPED) + rc_service_start(svc2->value); + rc_stringlist_free(services); + services = NULL; + } + } + rc_stringlist_free(tmplist); + tmplist = NULL; } hook_out = 0; - rc_plugin_run (RC_HOOK_SERVICE_START_OUT, applet); + rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); } -static void svc_stop (bool deps) +static void svc_stop(bool deps) { bool stopped; - rc_service_state_t state = rc_service_state (service); + RC_SERVICE state = rc_service_state(service); + int depoptions = RC_DEP_TRACE; + RC_STRING *svc; - if (rc_runlevel_stopping () && + if (rc_runlevel_stopping() && state & RC_SERVICE_FAILED) exit (EXIT_FAILURE); - if (rc_yesno (getenv ("IN_HOTPLUG")) || in_background) + if (rc_yesno(getenv("IN_HOTPLUG")) || in_background) if (! (state & RC_SERVICE_STARTED) && ! (state & RC_SERVICE_INACTIVE)) exit (EXIT_FAILURE); if (state & RC_SERVICE_STOPPED) { - ewarn ("WARNING: %s is already stopped", applet); + ewarn("WARNING: %s is already stopped", applet); return; } else if (state & RC_SERVICE_STOPPING) - ewarnx ("WARNING: %s is already stopping", applet); + ewarnx("WARNING: %s is already stopping", applet); - if (! rc_service_mark (service, RC_SERVICE_STOPPING)) { + if (! rc_service_mark(service, RC_SERVICE_STOPPING)) { if (errno == EACCES) - eerrorx ("%s: superuser access required", applet); - eerrorx ("ERROR: %s has been stopped by something else", applet); + eerrorx("%s: superuser access required", applet); + eerrorx("ERROR: %s has been stopped by something else", applet); } - make_exclusive (service); + make_exclusive(); hook_out = RC_HOOK_SERVICE_STOP_OUT; - rc_plugin_run (RC_HOOK_SERVICE_STOP_IN, applet); + rc_plugin_run(RC_HOOK_SERVICE_STOP_IN, applet); - if (! rc_runlevel_stopping () && - rc_service_in_runlevel (service, RC_LEVEL_BOOT)) + if (! rc_runlevel_stopping() && + rc_service_in_runlevel(service, RC_LEVEL_BOOT)) ewarn ("WARNING: you are stopping a boot service"); if (deps && ! (state & RC_SERVICE_WASINACTIVE)) { - int depoptions = RC_DEP_TRACE; - char *svc; - int i; - if (rc_conf_yesno ("rc_depend_strict")) + if (rc_conf_yesno("rc_depend_strict")) depoptions |= RC_DEP_STRICT; - if (! deptree && ((deptree = _rc_deptree_load (NULL)) == NULL)) + if (! deptree && ((deptree = _rc_deptree_load(NULL)) == NULL)) eerrorx ("failed to load deptree"); - rc_strlist_free (tmplist); - tmplist = NULL; - rc_strlist_free (services); - services = rc_deptree_depends (deptree, types_m, - (const char * const *) applet_list, - softlevel, depoptions); - rc_strlist_reverse (services); - STRLIST_FOREACH (services, svc, i) { - rc_service_state_t svcs = rc_service_state (svc); + if (! types_m) + setup_types(); + + tmplist = rc_stringlist_new(); + services = rc_deptree_depends(deptree, types_m, applet_list, + runlevel, depoptions); + TAILQ_FOREACH_REVERSE(svc, services, rc_stringlist, entries) { + RC_SERVICE svcs = rc_service_state(svc->value); if (svcs & RC_SERVICE_STARTED || svcs & RC_SERVICE_INACTIVE) { - svc_wait (deptree, svc); - svcs = rc_service_state (svc); + svc_wait(svc->value); + svcs = rc_service_state(svc->value); if (svcs & RC_SERVICE_STARTED || svcs & RC_SERVICE_INACTIVE) { - pid_t pid = rc_service_stop (svc); - if (! rc_conf_yesno ("rc_parallel")) - rc_waitpid (pid); - rc_strlist_add (&tmplist, svc); + pid_t pid = rc_service_stop(svc->value); + if (! rc_conf_yesno("rc_parallel")) + rc_waitpid(pid); + rc_stringlist_add(tmplist, svc->value); } } } - rc_strlist_free (services); + rc_stringlist_free(services); services = NULL; - STRLIST_FOREACH (tmplist, svc, i) { - if (rc_service_state (svc) & RC_SERVICE_STOPPED) + TAILQ_FOREACH(svc, tmplist, entries) { + if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) continue; /* We used to loop 3 times here - maybe re-do this if needed */ - svc_wait (deptree, svc); - if (! (rc_service_state (svc) & RC_SERVICE_STOPPED)) { - if (rc_runlevel_stopping ()) { - /* If shutting down, we should stop even if a dependant failed */ - if (softlevel && - (strcmp (softlevel, RC_LEVEL_SHUTDOWN) == 0 || - strcmp (softlevel, RC_LEVEL_REBOOT) == 0 || - strcmp (softlevel, RC_LEVEL_SINGLE) == 0)) + svc_wait(svc->value); + if (! (rc_service_state(svc->value) & RC_SERVICE_STOPPED)) { + if (rc_runlevel_stopping()) { + /* If shutting down, we should stop even + * if a dependant failed */ + if (runlevel && + (strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0 || + strcmp(runlevel, RC_LEVEL_REBOOT) == 0 || + strcmp(runlevel, RC_LEVEL_SINGLE) == 0)) continue; - rc_service_mark (service, RC_SERVICE_FAILED); + rc_service_mark(service, RC_SERVICE_FAILED); } - eerrorx ("ERROR: cannot stop %s as %s is still up", - applet, svc); + eerrorx("ERROR: cannot stop %s as %s is still up", + applet, svc->value); } } - rc_strlist_free (tmplist); + rc_stringlist_free(tmplist); tmplist = NULL; /* We now wait for other services that may use us and are stopping This is important when a runlevel stops */ - services = rc_deptree_depends (deptree, types_mua, - (const char * const *) applet_list, - softlevel, depoptions); - STRLIST_FOREACH (services, svc, i) { - if (rc_service_state (svc) & RC_SERVICE_STOPPED) + services = rc_deptree_depends(deptree, types_mua, applet_list, + runlevel, depoptions); + TAILQ_FOREACH(svc, services, entries) { + if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) continue; - svc_wait (deptree, svc); + svc_wait(svc->value); } - - rc_strlist_free (services); + rc_stringlist_free (services); services = NULL; } /* If we're stopping localmount, set LC_ALL=C so that * bash doesn't load anything blocking the unmounting of /usr */ - if (strcmp (applet, "localmount") == 0) - setenv ("LC_ALL", "C", 1); + if (strcmp(applet, "localmount") == 0) + setenv("LC_ALL", "C", 1); if (ibsave) - setenv ("IN_BACKGROUND", ibsave, 1); + setenv("IN_BACKGROUND", ibsave, 1); hook_out = RC_HOOK_SERVICE_STOP_DONE; - rc_plugin_run (RC_HOOK_SERVICE_STOP_NOW, applet); - stopped = svc_exec ("stop", NULL); + rc_plugin_run(RC_HOOK_SERVICE_STOP_NOW, applet); + stopped = svc_exec("stop", NULL); if (ibsave) - unsetenv ("IN_BACKGROUND"); + unsetenv("IN_BACKGROUND"); - if (! in_control ()) - ewarnx ("WARNING: %s not under our control, aborting", applet); + if (! in_control()) + ewarnx("WARNING: %s not under our control, aborting", applet); if (! stopped) - eerrorx ("ERROR: %s failed to stop", applet); + eerrorx("ERROR: %s failed to stop", applet); if (in_background) - rc_service_mark (service, RC_SERVICE_INACTIVE); + rc_service_mark(service, RC_SERVICE_INACTIVE); else - rc_service_mark (service, RC_SERVICE_STOPPED); + rc_service_mark(service, RC_SERVICE_STOPPED); - unlink_mtime_test (); + unlink_mtime_test(); hook_out = RC_HOOK_SERVICE_STOP_OUT; - rc_plugin_run (RC_HOOK_SERVICE_STOP_DONE, applet); + rc_plugin_run(RC_HOOK_SERVICE_STOP_DONE, applet); if (exclusive) - unlink (exclusive); + unlink(exclusive); hook_out = 0; - rc_plugin_run (RC_HOOK_SERVICE_STOP_OUT, applet); + rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); } -static void svc_restart (bool deps) +static void svc_restart(bool deps) { /* This is hairly and a better way needs to be found I think! The issue is this - openvpn need net and dns. net can restart @@ -1012,22 +1033,22 @@ static void svc_restart (bool deps) our status is invalid. One workaround would be to introduce a new status, or status locking. */ if (! deps) { - rc_service_state_t state = rc_service_state (service); + RC_SERVICE state = rc_service_state(service); if (state & RC_SERVICE_STARTED || state & RC_SERVICE_INACTIVE) - svc_exec ("stop", "start"); + svc_exec("stop", "start"); else - svc_exec ("start", NULL); + svc_exec("start", NULL); return; } - if (! (rc_service_state (service) & RC_SERVICE_STOPPED)) { - get_started_services (); - svc_stop (deps); + if (! (rc_service_state(service) & RC_SERVICE_STOPPED)) { + get_started_services(); + svc_stop(deps); } - svc_start (deps); - start_services (restart_services); - rc_strlist_free (restart_services); + svc_start(deps); + start_services(restart_services); + rc_stringlist_free(restart_services); restart_services = NULL; } @@ -1048,128 +1069,94 @@ static const char * const longopts_help[] = { }; #include "_usage.c" -int runscript (int argc, char **argv) +int runscript(int argc, char **argv) { - size_t i; bool deps = true; bool doneone = false; char pid[16]; int retval; int opt; - char *svc; + RC_STRING *svc; + char dir[PATH_MAX]; + size_t l = 0; + size_t ll; + char *save; + int depoptions = RC_DEP_TRACE; /* Show help if insufficient args */ - if (argc < 2 || ! exists (argv[1])) { - fprintf (stderr, "runscript is not meant to be to run directly\n"); - exit (EXIT_FAILURE); + if (argc < 2 || ! exists(argv[1])) { + fprintf(stderr, "runscript is not meant to be to run directly\n"); + exit(EXIT_FAILURE); } - applet = basename_c (argv[1]); + applet = basename_c(argv[1]); if (argc < 3) - usage (EXIT_FAILURE); + usage(EXIT_FAILURE); if (*argv[1] == '/') - service = xstrdup (argv[1]); + service = xstrdup(argv[1]); else { - char d[PATH_MAX]; - getcwd (d, sizeof (d)); - i = strlen (d) + strlen (argv[1]) + 2; - service = xmalloc (sizeof (char) * i); - snprintf (service, i, "%s/%s", d, argv[1]); + getcwd(dir, sizeof(dir)); + l = strlen(dir) + strlen(argv[1]) + 2; + service = xmalloc(sizeof (char) * l); + snprintf(service, l, "%s/%s", dir, argv[1]); } - atexit (cleanup); + atexit(cleanup); /* Change dir to / to ensure all init scripts don't use stuff in pwd */ - chdir ("/"); + chdir("/"); #ifdef __linux__ /* coldplug events can trigger init scripts, but we don't want to run them until after rc sysinit has completed so we punt them to the boot runlevel */ - if (exists ("/dev/.rcsysinit")) { - eerror ("%s: cannot run until sysvinit completes", applet); - if (mkdir ("/dev/.rcboot", 0755) != 0 && errno != EEXIST) - eerrorx ("%s: mkdir `/dev/.rcboot': %s", applet, strerror (errno)); - tmp = rc_strcatpaths ("/dev/.rcboot", applet, (char *) NULL); - symlink (service, tmp); + if (exists("/dev/.rcsysinit")) { + eerror("%s: cannot run until sysvinit completes", applet); + if (mkdir("/dev/.rcboot", 0755) != 0 && errno != EEXIST) + eerrorx("%s: mkdir `/dev/.rcboot': %s", applet, strerror(errno)); + prefix = rc_strcatpaths("/dev/.rcboot", applet, (char *) NULL); + symlink(service, prefix); exit (EXIT_FAILURE); } #endif - if ((softlevel = xstrdup (getenv ("RC_SOFTLEVEL"))) == NULL) { - /* Ensure our environment is pure - Also, add our configuration to it */ - char *p; - env = env_filter (); - - if (env) { - -#ifdef __linux__ - /* clearenv isn't portable, but there's no harm in using it - if we have it */ - clearenv (); -#else - char *var; - /* No clearenv present here then. - We could manipulate environ directly ourselves, but it seems that - some kernels bitch about this according to the environ man pages - so we walk though environ and call unsetenv for each value. */ - while (environ[0]) { - tmp = xstrdup (environ[0]); - p = tmp; - var = strsep (&p, "="); - unsetenv (var); - free (tmp); - } - tmp = NULL; -#endif - } - - tmplist = env_config (); - rc_strlist_join (&env, tmplist); - rc_strlist_free (tmplist); - tmplist = NULL; - STRLIST_FOREACH (env, p, i) - putenv (p); - /* We don't free our list as that would be null in environ */ - - softlevel = rc_runlevel_get (); + if ((runlevel = xstrdup (getenv ("RC_RUNLEVEL"))) == NULL) { + env_filter(); + env_config(); + runlevel = rc_runlevel_get(); } - setenv ("EINFO_LOG", service, 1); - setenv ("SVCNAME", applet, 1); + setenv("EINFO_LOG", service, 1); + setenv("SVCNAME", applet, 1); /* Set an env var so that we always know our pid regardless of any subshells the init script may create so that our mark_service_* functions can always instruct us of this change */ - snprintf (pid, sizeof (pid), "%d", (int) getpid ()); - setenv ("RC_RUNSCRIPT_PID", pid, 1); + snprintf(pid, sizeof(pid), "%d", (int) getpid()); + setenv("RC_RUNSCRIPT_PID", pid, 1); /* eprefix is kinda klunky, but it works for our purposes */ - if (rc_conf_yesno ("rc_parallel")) { - size_t l = 0; - size_t ll; - + if (rc_conf_yesno("rc_parallel")) { /* Get the longest service name */ - services = rc_services_in_runlevel (NULL); - STRLIST_FOREACH (services, svc, i) { - ll = strlen (svc); + services = rc_services_in_runlevel(NULL); + TAILQ_FOREACH(svc, services, entries) { + ll = strlen(svc->value); if (ll > l) l = ll; } /* Make our prefix string */ - prefix = xmalloc (sizeof (char) * l + 1); - ll = strlen (applet); - memcpy (prefix, applet, ll); - memset (prefix + ll, ' ', l - ll); - memset (prefix + l, 0, 1); - eprefix (prefix); + prefix = xmalloc(sizeof(char) * l + 1); + ll = strlen(applet); + memcpy(prefix, applet, ll); + memset(prefix + ll, ' ', l - ll); + memset(prefix + l, 0, 1); + eprefix(prefix); } #ifdef __linux__ /* Ok, we are ready to go, so setup selinux if applicable */ - setup_selinux (argc, argv); + setup_selinux(argc, argv); #endif /* Punt the first arg as it's our service name */ @@ -1177,44 +1164,46 @@ int runscript (int argc, char **argv) argv++; /* Right then, parse any options there may be */ - while ((opt = getopt_long (argc, argv, getoptstring, - longopts, (int *) 0)) != -1) + while ((opt = getopt_long(argc, argv, getoptstring, longopts, (int *) 0)) != -1) switch (opt) { - case 'd': - setenv ("RC_DEBUG", "yes", 1); - break; - case 's': - if (! (rc_service_state (service) & RC_SERVICE_STARTED)) - exit (EXIT_FAILURE); - break; - case 'D': - deps = false; - break; - case_RC_COMMON_GETOPT - } + case 'd': + setenv("RC_DEBUG", "yes", 1); + break; + case 's': + if (! (rc_service_state(service) & RC_SERVICE_STARTED)) + exit(EXIT_FAILURE); + break; + case 'D': + deps = false; + break; + case_RC_COMMON_GETOPT + } /* Save the IN_BACKGROUND env flag so it's ONLY passed to the service that is being called and not any dependents */ - if (getenv ("IN_BACKGROUND")) { - ibsave = xstrdup (getenv ("IN_BACKGROUND")); - in_background = rc_yesno (ibsave); - unsetenv ("IN_BACKGROUND"); + if (getenv("IN_BACKGROUND")) { + ibsave = xstrdup(getenv("IN_BACKGROUND")); + in_background = rc_yesno(ibsave); + unsetenv("IN_BACKGROUND"); } - if (rc_yesno (getenv ("IN_HOTPLUG"))) { - if (! rc_conf_yesno ("rc_hotplug") || ! service_plugable (applet)) - eerrorx ("%s: not allowed to be hotplugged", applet); + if (rc_yesno(getenv("IN_HOTPLUG"))) { + if (! rc_conf_yesno("rc_hotplug") || ! service_plugable(applet)) + eerrorx("%s: not allowed to be hotplugged", applet); } /* Setup a signal handler */ - signal_setup (SIGHUP, handle_signal); - signal_setup (SIGINT, handle_signal); - signal_setup (SIGQUIT, handle_signal); - signal_setup (SIGTERM, handle_signal); - signal_setup (SIGCHLD, handle_signal); + signal_setup(SIGHUP, handle_signal); + signal_setup(SIGINT, handle_signal); + signal_setup(SIGQUIT, handle_signal); + signal_setup(SIGTERM, handle_signal); + signal_setup(SIGCHLD, handle_signal); /* Load our plugins */ - rc_plugin_load (); + rc_plugin_load(); + + applet_list = rc_stringlist_new(); + rc_stringlist_add(applet_list, applet); /* Now run each option */ retval = EXIT_SUCCESS; @@ -1229,99 +1218,95 @@ int runscript (int argc, char **argv) This is important as we stamp on the restart function now but some start/stop routines still need to behave differently if restarting. */ - unsetenv ("RC_CMD"); - setenv ("RC_CMD", optarg, 1); + unsetenv("RC_CMD"); + setenv("RC_CMD", optarg, 1); doneone = true; - rc_strlist_add (&applet_list, applet); if (strcmp (optarg, "describe") == 0 || strcmp (optarg, "help") == 0) { - char *save = prefix; - - eprefix (NULL); + save = prefix; + eprefix(NULL); prefix = NULL; - svc_exec (optarg, NULL); - eprefix (save); - } else if (strcmp (optarg, "ineed") == 0 || - strcmp (optarg, "iuse") == 0 || - strcmp (optarg, "needsme") == 0 || - strcmp (optarg, "usesme") == 0 || - strcmp (optarg, "iafter") == 0 || - strcmp (optarg, "ibefore") == 0 || - strcmp (optarg, "iprovide") == 0) + svc_exec(optarg, NULL); + eprefix(save); + } else if (strcmp(optarg, "ineed") == 0 || + strcmp(optarg, "iuse") == 0 || + strcmp(optarg, "needsme") == 0 || + strcmp(optarg, "usesme") == 0 || + strcmp(optarg, "iafter") == 0 || + strcmp(optarg, "ibefore") == 0 || + strcmp(optarg, "iprovide") == 0) { - int depoptions = RC_DEP_TRACE; - - if (rc_conf_yesno ("rc_depend_strict")) + if (rc_conf_yesno("rc_depend_strict")) depoptions |= RC_DEP_STRICT; - if (! deptree && ((deptree = _rc_deptree_load (NULL)) == NULL)) - eerrorx ("failed to load deptree"); - - rc_strlist_free (services); - rc_strlist_free (tmplist); - rc_strlist_add (&tmplist, optarg); - services = rc_deptree_depends (deptree, - (const char * const *) tmplist, - (const char * const *) applet_list, - softlevel, depoptions); - STRLIST_FOREACH (services, svc, i) - printf ("%s%s", i == 1 ? "" : " ", svc); - if (services) + if (! deptree && ((deptree = _rc_deptree_load(NULL)) == NULL)) + eerrorx("failed to load deptree"); + + tmplist = rc_stringlist_new(); + rc_stringlist_add(tmplist, optarg); + services = rc_deptree_depends(deptree, tmplist, applet_list, + runlevel, depoptions); + rc_stringlist_free(tmplist); + tmplist = NULL; + TAILQ_FOREACH(svc, services, entries) + printf("%s ", svc->value); + if (TAILQ_FIRST(services)) printf ("\n"); + rc_stringlist_free(services); + services = NULL; } else if (strcmp (optarg, "status") == 0) { - rc_service_state_t r = svc_status (service); + RC_SERVICE r = svc_status(); retval = (int) r; if (retval & RC_SERVICE_STARTED) retval = 0; } else { - if (strcmp (optarg, "conditionalrestart") == 0 || - strcmp (optarg, "condrestart") == 0) + if (strcmp(optarg, "conditionalrestart") == 0 || + strcmp(optarg, "condrestart") == 0) { - if (rc_service_state (service) & RC_SERVICE_STARTED) - svc_restart (deps); - } else if (strcmp (optarg, "restart") == 0) { + if (rc_service_state(service) & RC_SERVICE_STARTED) + svc_restart(deps); + } else if (strcmp(optarg, "restart") == 0) { svc_restart (deps); - } else if (strcmp (optarg, "start") == 0) { - svc_start (deps); - } else if (strcmp (optarg, "stop") == 0) { + } else if (strcmp(optarg, "start") == 0) { + svc_start(deps); + } else if (strcmp(optarg, "stop") == 0) { if (deps && in_background) - get_started_services (); + get_started_services(); - svc_stop (deps); + svc_stop(deps); if (deps) { if (! in_background && - ! rc_runlevel_stopping () && - rc_service_state (service) & RC_SERVICE_STOPPED) - uncoldplug (); + ! rc_runlevel_stopping() && + rc_service_state(service) & RC_SERVICE_STOPPED) + uncoldplug(); if (in_background && - rc_service_state (service) & RC_SERVICE_INACTIVE) + rc_service_state(service) & RC_SERVICE_INACTIVE) { - int j; - STRLIST_FOREACH (restart_services, svc, j) - if (rc_service_state (svc) & RC_SERVICE_STOPPED) - rc_service_schedule_start (service, svc); + TAILQ_FOREACH(svc, restart_services, entries) + if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) + rc_service_schedule_start(service, svc->value); } } - } else if (strcmp (optarg, "zap") == 0) { - einfo ("Manually resetting %s to stopped state", applet); - rc_service_mark (applet, RC_SERVICE_STOPPED); - uncoldplug (); + } else if (strcmp(optarg, "zap") == 0) { + einfo("Manually resetting %s to stopped state", applet); + rc_service_mark(applet, RC_SERVICE_STOPPED); + uncoldplug(); } else - svc_exec (optarg, NULL); + svc_exec(optarg, NULL); /* We should ensure this list is empty after an action is done */ - rc_strlist_free (restart_services); + rc_stringlist_free(restart_services); restart_services = NULL; } if (! doneone) - usage (EXIT_FAILURE); + usage(EXIT_FAILURE); } - return (retval); + return retval; } diff --git a/src/rc/start-stop-daemon.c b/src/rc/start-stop-daemon.c index 9ffeba05..bfb737a5 100644 --- a/src/rc/start-stop-daemon.c +++ b/src/rc/start-stop-daemon.c @@ -46,6 +46,7 @@ #include <sys/termios.h> #include <sys/time.h> #include <sys/wait.h> + #include <ctype.h> #include <errno.h> #include <fcntl.h> @@ -71,63 +72,57 @@ static struct pam_conv conv = { NULL, NULL}; #include "einfo.h" #include "rc.h" #include "rc-misc.h" -#include "strlist.h" -typedef struct schedulelist +typedef struct scheduleitem { enum { - schedule_timeout, - schedule_signal, - schedule_goto, - schedule_forever + SC_TIMEOUT, + SC_SIGNAL, + SC_GOTO, + SC_FOREVER } type; int value; - struct schedulelist *gotolist; - struct schedulelist *next; -} schedulelist_t; -static schedulelist_t *schedule; + struct scheduleitem *gotoitem; + STAILQ_ENTRY(scheduleitem) entries; +} SCHEDULEITEM; +STAILQ_HEAD(, scheduleitem) schedule; extern const char *applet; static char *changeuser; -static char **newenv; extern char **environ; -static void free_schedulelist (schedulelist_t **list) +static void free_schedulelist(void) { - schedulelist_t *here; - schedulelist_t *next; + SCHEDULEITEM *s1 = STAILQ_FIRST(&schedule); + SCHEDULEITEM *s2; - for (here = *list; here; here = next) { - next = here->next; - free (here); + while (s1) { + s2 = STAILQ_NEXT(s1, entries); + free(s1); + s1 = s2; } - - *list = NULL; + STAILQ_INIT(&schedule); } -static void cleanup (void) +static void cleanup(void) { if (changeuser) - free (changeuser); - - if (schedule) - free_schedulelist (&schedule); + free(changeuser); - if (newenv) - rc_strlist_free (newenv); + free_schedulelist(); } -static int parse_signal (const char *sig) +static int parse_signal(const char *sig) { typedef struct signalpair { const char *name; int signal; - } signalpair_t; + } SIGNALPAIR; - static const signalpair_t signallist[] = { + static const SIGNALPAIR signallist[] = { { "ABRT", SIGABRT }, { "ALRM", SIGALRM }, { "FPE", SIGFPE }, @@ -153,161 +148,158 @@ static int parse_signal (const char *sig) const char *s; if (! sig || *sig == '\0') - return (-1); + return -1; - if (sscanf (sig, "%u", &i) == 1) { - if (i > 0 && i < sizeof (signallist) / sizeof (signallist[0])) - return (i); - eerrorx ("%s: `%s' is not a valid signal", applet, sig); + if (sscanf(sig, "%u", &i) == 1) { + if (i > 0 && i < sizeof(signallist) / sizeof(signallist[0])) + return i; + eerrorx("%s: `%s' is not a valid signal", applet, sig); } - if (strncmp (sig, "SIG", 3) == 0) + if (strncmp(sig, "SIG", 3) == 0) s = sig + 3; else s = NULL; - for (i = 0; i < sizeof (signallist) / sizeof (signallist[0]); i++) - if (strcmp (sig, signallist[i].name) == 0 || - (s && strcmp (s, signallist[i].name) == 0)) - return (signallist[i].signal); + for (i = 0; i < sizeof(signallist) / sizeof(signallist[0]); i++) + if (strcmp(sig, signallist[i].name) == 0 || + (s && strcmp(s, signallist[i].name) == 0)) + return signallist[i].signal; - eerrorx ("%s: `%s' is not a valid signal", applet, sig); + eerrorx("%s: `%s' is not a valid signal", applet, sig); /* NOTREACHED */ } -static void parse_schedule_item (schedulelist_t *item, const char *string) +static SCHEDULEITEM *parse_schedule_item(const char *string) { const char *after_hyph; int sig; - - if (strcmp (string,"forever") == 0) - item->type = schedule_forever; - else if (isdigit ((int) string[0])) { - item->type = schedule_timeout; + SCHEDULEITEM *item = xmalloc(sizeof(*item)); + + item->value = 0; + item->gotoitem = NULL; + if (strcmp(string,"forever") == 0) + item->type = SC_FOREVER; + else if (isdigit((int) string[0])) { + item->type = SC_TIMEOUT; errno = 0; - if (sscanf (string, "%d", &item->value) != 1) - eerrorx ("%s: invalid timeout value in schedule `%s'", applet, - string); + if (sscanf(string, "%d", &item->value) != 1) + eerrorx("%s: invalid timeout value in schedule `%s'", applet, + string); } else if ((after_hyph = string + (string[0] == '-')) && - ((sig = parse_signal (after_hyph)) != -1)) + ((sig = parse_signal(after_hyph)) != -1)) { - item->type = schedule_signal; - item->value = (int) sig; + item->type = SC_SIGNAL; + item->value = (int)sig; } else - eerrorx ("%s: invalid schedule item `%s'", applet, string); + eerrorx("%s: invalid schedule item `%s'", applet, string); + + return item; } -static void parse_schedule (const char *string, int default_signal) +static void parse_schedule(const char *string, int timeout) { char buffer[20]; const char *slash; int count = 0; - schedulelist_t *repeatat = NULL; + SCHEDULEITEM *repeatat = NULL; size_t len; - schedulelist_t *next; + SCHEDULEITEM *item; if (string) for (slash = string; *slash; slash++) if (*slash == '/') count++; - if (schedule) - free_schedulelist (&schedule); - - schedule = xmalloc (sizeof (*schedule)); - schedule->gotolist = NULL; + free_schedulelist(); if (count == 0) { - schedule->type = schedule_signal; - schedule->value = default_signal; - schedule->next = xmalloc (sizeof (*schedule->next)); - next = schedule->next; - next->type = schedule_timeout; - next->gotolist = NULL; + item = xmalloc(sizeof(*item)); + item->type = SC_SIGNAL; + item->value = timeout; + item->gotoitem = NULL; + STAILQ_INSERT_TAIL(&schedule, item, entries); + + item = xmalloc(sizeof(*item)); + item->type = SC_TIMEOUT; + item->gotoitem = NULL; + STAILQ_INSERT_TAIL(&schedule, item, entries); if (string) { - if (sscanf (string, "%d", &next->value) != 1) - eerrorx ("%s: invalid timeout value in schedule", applet); - } - else - next->value = 5; - next->next = NULL; + if (sscanf(string, "%d", &item->value) != 1) + eerrorx("%s: invalid timeout value in schedule", applet); + } else + item->value = 5; return; } - next = schedule; while (string != NULL) { - if ((slash = strchr (string, '/'))) + if ((slash = strchr(string, '/'))) len = slash - string; else - len = strlen (string); + len = strlen(string); - if (len >= (ptrdiff_t) sizeof (buffer)) - eerrorx ("%s: invalid schedule item, far too long", applet); + if (len >= (ptrdiff_t) sizeof(buffer)) + eerrorx("%s: invalid schedule item, far too long", applet); - memcpy (buffer, string, len); + memcpy(buffer, string, len); buffer[len] = 0; string = slash ? slash + 1 : NULL; - parse_schedule_item (next, buffer); - if (next->type == schedule_forever) { + item = parse_schedule_item(buffer); + STAILQ_INSERT_TAIL(&schedule, item, entries); + if (item->type == SC_FOREVER) { if (repeatat) - eerrorx ("%s: invalid schedule, `forever' appears more than once", - applet); + eerrorx("%s: invalid schedule, `forever' " + "appears more than once", applet); - repeatat = next; + repeatat = item; continue; } - - if (string) { - next->next = xmalloc (sizeof (*next->next)); - next = next->next; - next->gotolist = NULL; - } } if (repeatat) { - next->next = xmalloc (sizeof (*next->next)); - next = next->next; - next->type = schedule_goto; - next->value = 0; - next->gotolist = repeatat; + item = xmalloc(sizeof(*item)); + item->type = SC_GOTO; + item->value = 0; + item->gotoitem = repeatat; + STAILQ_INSERT_TAIL(&schedule, item, entries); } - next->next = NULL; return; } -static pid_t get_pid (const char *pidfile, bool quiet) +static pid_t get_pid(const char *pidfile, bool quiet) { FILE *fp; pid_t pid; if (! pidfile) - return (-1); + return -1; - if ((fp = fopen (pidfile, "r")) == NULL) { + if ((fp = fopen(pidfile, "r")) == NULL) { if (! quiet) - eerror ("%s: fopen `%s': %s", applet, pidfile, strerror (errno)); - return (-1); + eerror("%s: fopen `%s': %s", applet, pidfile, strerror(errno)); + return -1; } - if (fscanf (fp, "%d", &pid) != 1) { + if (fscanf(fp, "%d", &pid) != 1) { if (! quiet) - eerror ("%s: no pid found in `%s'", applet, pidfile); - fclose (fp); - return (-1); + eerror("%s: no pid found in `%s'", applet, pidfile); + fclose(fp); + return -1; } - fclose (fp); + + fclose(fp); - return (pid); + return pid; } /* return number of processed killed, -1 on error */ -static int do_stop (const char *const *argv, const char *cmd, - const char *pidfile, uid_t uid,int sig, - bool quiet, bool verbose, bool test) +static int do_stop(const char *const *argv, const char *cmd, + const char *pidfile, uid_t uid,int sig, + bool quiet, bool verbose, bool test) { pid_t *pids; bool killed; @@ -316,30 +308,30 @@ static int do_stop (const char *const *argv, const char *cmd, int i; if (pidfile) { - if ((pid = get_pid (pidfile, quiet)) == -1) - return (quiet ? 0 : -1); - pids = rc_find_pids (NULL, NULL, 0, pid); + if ((pid = get_pid(pidfile, quiet)) == -1) + return quiet ? 0 : -1; + pids = rc_find_pids(NULL, NULL, 0, pid); } else - pids = rc_find_pids (argv, cmd, uid, pid); + pids = rc_find_pids(argv, cmd, uid, pid); if (! pids) - return (0); + return 0; for (i = 0; pids[i]; i++) { if (test) { if (! quiet) - einfo ("Would send signal %d to PID %d", sig, pids[i]); + einfo("Would send signal %d to PID %d", sig, pids[i]); nkilled++; continue; } if (verbose) - ebegin ("Sending signal %d to PID %d", sig, pids[i]); + ebegin("Sending signal %d to PID %d", sig, pids[i]); errno = 0; - killed = (kill (pids[i], sig) == 0 || errno == ESRCH ? true : false); + killed = (kill(pids[i], sig) == 0 || errno == ESRCH ? true : false); if (verbose) - eend (killed ? 0 : 1, "%s: failed to send signal %d to PID %d: %s", - applet, sig, pids[i], strerror (errno)); + eend(killed ? 0 : 1, "%s: failed to send signal %d to PID %d: %s", + applet, sig, pids[i], strerror(errno)); if (! killed) { nkilled = -1; } else { @@ -348,15 +340,15 @@ static int do_stop (const char *const *argv, const char *cmd, } } - free (pids); - return (nkilled); + free(pids); + return nkilled; } -static int run_stop_schedule (const char *const *argv, const char *cmd, - const char *pidfile, uid_t uid, - bool quiet, bool verbose, bool test) +static int run_stop_schedule(const char *const *argv, const char *cmd, + const char *pidfile, uid_t uid, + bool quiet, bool verbose, bool test) { - schedulelist_t *item = schedule; + SCHEDULEITEM *item = STAILQ_FIRST(&schedule); int nkilled = 0; int tkilled = 0; int nrunning = 0; @@ -365,119 +357,121 @@ static int run_stop_schedule (const char *const *argv, const char *cmd, if (verbose) { if (pidfile) - einfo ("Will stop PID in pidfile `%s'", pidfile); + einfo("Will stop PID in pidfile `%s'", pidfile); if (uid) - einfo ("Will stop processes owned by UID %d", uid); + einfo("Will stop processes owned by UID %d", uid); if (argv && *argv) - einfo ("Will stop processes of `%s'", *argv); + einfo("Will stop processes of `%s'", *argv); if (cmd) - einfo ("Will stop processes called `%s'", cmd); + einfo("Will stop processes called `%s'", cmd); } while (item) { - switch (item->type) { - case schedule_goto: - item = item->gotolist; - continue; + switch (item->type) { + case SC_GOTO: + item = item->gotoitem; + continue; - case schedule_signal: - nrunning = 0; - nkilled = do_stop (argv, cmd, pidfile, uid, item->value, - quiet, verbose, test); - if (nkilled == 0) { - if (tkilled == 0) { - if (! quiet) - eerror ("%s: no matching processes found", applet); - } - return (tkilled); + case SC_SIGNAL: + nrunning = 0; + nkilled = do_stop(argv, cmd, pidfile, uid, item->value, + quiet, verbose, test); + if (nkilled == 0) { + if (tkilled == 0) { + if (! quiet) + eerror("%s: no matching " + "processes found", applet); } - else if (nkilled == -1) - return (0); + return tkilled; + } + else if (nkilled == -1) + return 0; - tkilled += nkilled; + tkilled += nkilled; + break; + case SC_TIMEOUT: + if (item->value < 1) { + item = NULL; break; - case schedule_timeout: - if (item->value < 1) { - item = NULL; - break; - } + } - nloops = (ONE_SECOND / POLL_INTERVAL) * item->value; - ts.tv_sec = 0; - ts.tv_nsec = POLL_INTERVAL; - - while (nloops) { - if ((nrunning = do_stop (argv, cmd, pidfile, - uid, 0, true, false, true)) == 0) - return (true); - - if (nanosleep (&ts, NULL) == -1) { - if (errno == EINTR) - eerror ("%s: caught an interrupt", applet); - else { - eerror ("%s: nanosleep: %s", applet, strerror (errno)); - return (0); - } + nloops = (ONE_SECOND / POLL_INTERVAL) * item->value; + ts.tv_sec = 0; + ts.tv_nsec = POLL_INTERVAL; + + while (nloops) { + if ((nrunning = do_stop(argv, cmd, pidfile, + uid, 0, true, false, true)) == 0) + return true; + + if (nanosleep(&ts, NULL) == -1) { + if (errno == EINTR) + eerror("%s: caught an interrupt", applet); + else { + eerror("%s: nanosleep: %s", + applet, strerror(errno)); + return 0; } - nloops --; } - break; + nloops --; + } + break; - default: - eerror ("%s: invalid schedule item `%d'", applet, item->type); - return (0); + default: + eerror("%s: invalid schedule item `%d'", applet, item->type); + return 0; } if (item) - item = item->next; + item = STAILQ_NEXT(item, entries); } if (test || (tkilled > 0 && nrunning == 0)) - return (nkilled); + return nkilled; if (! quiet) { if (nrunning == 1) - eerror ("%s: %d process refused to stop", applet, nrunning); + eerror("%s: %d process refused to stop", applet, nrunning); else - eerror ("%s: %d process(es) refused to stop", applet, nrunning); + eerror("%s: %d process(es) refused to stop", applet, nrunning); } - return (-nrunning); + return -nrunning; } -static void handle_signal (int sig) +static void handle_signal(int sig) { int status; int serrno = errno; char signame[10] = { '\0' }; switch (sig) { - case SIGINT: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGINT"); - /* FALLTHROUGH */ - case SIGTERM: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGTERM"); - /* FALLTHROUGH */ - case SIGQUIT: - if (! signame[0]) - snprintf (signame, sizeof (signame), "SIGQUIT"); - eerrorx ("%s: caught %s, aborting", applet, signame); - /* NOTREACHED */ - - case SIGCHLD: - for (;;) { - if (waitpid (-1, &status, WNOHANG) < 0) { - if (errno != ECHILD) - eerror ("%s: waitpid: %s", applet, strerror (errno)); - break; - } + case SIGINT: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGINT"); + /* FALLTHROUGH */ + case SIGTERM: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGTERM"); + /* FALLTHROUGH */ + case SIGQUIT: + if (! signame[0]) + snprintf(signame, sizeof(signame), "SIGQUIT"); + eerrorx("%s: caught %s, aborting", applet, signame); + /* NOTREACHED */ + + case SIGCHLD: + for (;;) { + if (waitpid(-1, &status, WNOHANG) < 0) { + if (errno != ECHILD) + eerror("%s: waitpid: %s", applet, strerror(errno)); + break; } - break; + } + break; - default: - eerror ("%s: caught unknown signal %d", applet, sig); + default: + eerror("%s: caught unknown signal %d", applet, sig); } /* Restore errno */ @@ -537,7 +531,7 @@ static const char * const longopts_help[] = { }; #include "_usage.c" -int start_stop_daemon (int argc, char **argv) +int start_stop_daemon(int argc, char **argv) { int devnull_fd = -1; #ifdef TIOCNOTTY @@ -574,154 +568,160 @@ int start_stop_daemon (int argc, char **argv) int stderr_fd; pid_t pid; int i; - char *svcname = getenv ("SVCNAME"); - char *env; + char *svcname = getenv("SVCNAME"); + RC_STRINGLIST *env_list; + RC_STRING *env; + char *path; bool sethome = false; bool setuser = false; + char *p; + char *tmp; + struct passwd *pw; + struct group *gr; + char line[130]; + FILE *fp; + size_t len; - atexit (cleanup); + STAILQ_INIT(&schedule); + atexit(cleanup); - signal_setup (SIGINT, handle_signal); - signal_setup (SIGQUIT, handle_signal); - signal_setup (SIGTERM, handle_signal); + signal_setup(SIGINT, handle_signal); + signal_setup(SIGQUIT, handle_signal); + signal_setup(SIGTERM, handle_signal); - if ((env = getenv ("SSD_NICELEVEL"))) - if (sscanf (env, "%d", &nicelevel) != 1) - eerror ("%s: invalid nice level `%s' (SSD_NICELEVEL)", applet, env); + if ((path = getenv("SSD_NICELEVEL"))) + if (sscanf(path, "%d", &nicelevel) != 1) + eerror("%s: invalid nice level `%s' (SSD_NICELEVEL)", + applet, path); - while ((opt = getopt_long (argc, argv, "e:" getoptstring, longopts, - (int *) 0)) != -1) + while ((opt = getopt_long(argc, argv, "e:" getoptstring, longopts, + (int *) 0)) != -1) switch (opt) { - case 'K': /* --stop */ - stop = true; - break; - - case 'N': /* --nice */ - if (sscanf (optarg, "%d", &nicelevel) != 1) - eerrorx ("%s: invalid nice level `%s'", applet, optarg); - break; + case 'K': /* --stop */ + stop = true; + break; - case 'R': /* --retry <schedule>|<timeout> */ - parse_schedule (optarg, sig); - break; + case 'N': /* --nice */ + if (sscanf(optarg, "%d", &nicelevel) != 1) + eerrorx("%s: invalid nice level `%s'", applet, optarg); + break; - case 'S': /* --start */ - start = true; - break; + case 'R': /* --retry <schedule>|<timeout> */ + parse_schedule(optarg, sig); + break; - case 'b': /* --background */ - background = true; - break; + case 'S': /* --start */ + start = true; + break; - case 'u': /* --user <username>|<uid> */ - case 'c': /* --chuid <username>|<uid> */ - { - char *p = optarg; - char *cu = strsep (&p, ":"); - struct passwd *pw = NULL; + case 'b': /* --background */ + background = true; + break; - changeuser = xstrdup (cu); - if (sscanf (cu, "%d", &tid) != 1) - pw = getpwnam (cu); + case 'u': /* --user <username>|<uid> */ + case 'c': /* --chuid <username>|<uid> */ + { + p = optarg; + tmp = strsep(&p, ":"); + changeuser = xstrdup(tmp); + if (sscanf(tmp, "%d", &tid) != 1) + pw = getpwnam(tmp); + else + pw = getpwuid((uid_t) tid); + + if (! pw) + eerrorx("%s: user `%s' not found", applet, tmp); + uid = pw->pw_uid; + if (! gid) + gid = pw->pw_gid; + + if (p) { + tmp = strsep (&p, ":"); + if (sscanf(tmp, "%d", &tid) != 1) + gr = getgrnam(tmp); else - pw = getpwuid ((uid_t) tid); - - if (! pw) - eerrorx ("%s: user `%s' not found", applet, cu); - uid = pw->pw_uid; - if (! gid) - gid = pw->pw_gid; - - if (p) { - struct group *gr = NULL; - char *cg = strsep (&p, ":"); - - if (sscanf (cg, "%d", &tid) != 1) - gr = getgrnam (cg); - else - gr = getgrgid ((gid_t) tid); - - if (! gr) - eerrorx ("%s: group `%s' not found", applet, cg); - gid = gr->gr_gid; - } - } - break; + gr = getgrgid((gid_t) tid); - case 'd': /* --chdir /new/dir */ - ch_dir = optarg; - break; - - case 'e': /* --env */ - if (putenv (optarg) == 0) { - if (strncmp ("HOME=", optarg, 5) == 0) - sethome = true; - else if (strncmp ("USER=", optarg, 5) == 0) - setuser = true; + if (! gr) + eerrorx("%s: group `%s' not found", + applet, tmp); + gid = gr->gr_gid; } - break; + } + break; - case 'g': /* --group <group>|<gid> */ - { - struct group *gr = getgrnam (optarg); + case 'd': /* --chdir /new/dir */ + ch_dir = optarg; + break; - if (sscanf (optarg, "%d", &tid) != 1) - gr = getgrnam (optarg); - else - gr = getgrgid ((gid_t) tid); + case 'e': /* --env */ + if (putenv(optarg) == 0) { + if (strncmp("HOME=", optarg, 5) == 0) + sethome = true; + else if (strncmp("USER=", optarg, 5) == 0) + setuser = true; + } + break; - if (! gr) - eerrorx ("%s: group `%s' not found", applet, optarg); - gid = gr->gr_gid; - } - break; + case 'g': /* --group <group>|<gid> */ + { + if (sscanf(optarg, "%d", &tid) != 1) + gr = getgrnam(optarg); + else + gr = getgrgid((gid_t) tid); - case 'm': /* --make-pidfile */ - makepidfile = true; - break; + if (! gr) + eerrorx("%s: group `%s' not found", applet, optarg); + gid = gr->gr_gid; + } + break; - case 'n': /* --name <process-name> */ - cmd = optarg; - break; + case 'm': /* --make-pidfile */ + makepidfile = true; + break; - case 'o': /* --oknodo */ - oknodo = true; - break; + case 'n': /* --name <process-name> */ + cmd = optarg; + break; - case 'p': /* --pidfile <pid-file> */ - pidfile = optarg; - break; + case 'o': /* --oknodo */ + oknodo = true; + break; - case 's': /* --signal <signal> */ - sig = parse_signal (optarg); - break; + case 'p': /* --pidfile <pid-file> */ + pidfile = optarg; + break; - case 't': /* --test */ - test = true; - break; + case 's': /* --signal <signal> */ + sig = parse_signal(optarg); + break; - case 'r': /* --chroot /new/root */ - ch_root = optarg; - break; + case 't': /* --test */ + test = true; + break; - case 'a': - case 'x': /* --exec <executable> */ - exec = optarg; - break; + case 'r': /* --chroot /new/root */ + ch_root = optarg; + break; - case '1': /* --stdout /path/to/stdout.lgfile */ - redirect_stdout = optarg; - break; + case 'a': + case 'x': /* --exec <executable> */ + exec = optarg; + break; - case '2': /* --stderr /path/to/stderr.logfile */ - redirect_stderr = optarg; - break; + case '1': /* --stdout /path/to/stdout.lgfile */ + redirect_stdout = optarg; + break; + + case '2': /* --stderr /path/to/stderr.logfile */ + redirect_stderr = optarg; + break; - case_RC_COMMON_GETOPT + case_RC_COMMON_GETOPT } - quiet = rc_yesno (getenv ("EINFO_QUIET")); - verbose = rc_yesno (getenv ("EINFO_VERBOSE")); + quiet = rc_yesno(getenv("EINFO_QUIET")); + verbose = rc_yesno(getenv("EINFO_VERBOSE")); /* Allow start-stop-daemon --signal HUP --exec /usr/sbin/dnsmasq * instead of forcing --stop --oknodo as well */ @@ -736,22 +736,22 @@ int start_stop_daemon (int argc, char **argv) } if (start == stop) - eerrorx ("%s: need one of --start or --stop", applet); + eerrorx("%s: need one of --start or --stop", applet); if (start && ! exec) - eerrorx ("%s: --start needs --exec", applet); + eerrorx("%s: --start needs --exec", applet); if (stop && ! exec && ! pidfile && ! cmd && ! uid) - eerrorx ("%s: --stop needs --exec, --pidfile, --name or --user", applet); + eerrorx("%s: --stop needs --exec, --pidfile, --name or --user", applet); if (makepidfile && ! pidfile) - eerrorx ("%s: --make-pidfile is only relevant with --pidfile", applet); + eerrorx("%s: --make-pidfile is only relevant with --pidfile", applet); if (background && ! start) - eerrorx ("%s: --background is only relevant with --start", applet); + eerrorx("%s: --background is only relevant with --start", applet); if ((redirect_stdout || redirect_stderr) && ! background) - eerrorx ("%s: --stdout and --stderr are only relevant with --background", + eerrorx("%s: --stdout and --stderr are only relevant with --background", applet); argc -= optind; @@ -759,52 +759,49 @@ int start_stop_daemon (int argc, char **argv) /* Validate that the binary exists if we are starting */ if (exec) { - char *tmp; if (ch_root) - tmp = rc_strcatpaths (ch_root, exec, (char *) NULL); + tmp = rc_strcatpaths(ch_root, exec, (char *) NULL); else tmp = exec; - if (start && ! exists (tmp)) { - eerror ("%s: %s does not exist", applet, tmp); + if (start && ! exists(tmp)) { + eerror("%s: %s does not exist", applet, tmp); if (ch_root) - free (tmp); - exit (EXIT_FAILURE); + free(tmp); + exit(EXIT_FAILURE); } /* If we don't have a pidfile or name, check it's not * interpreted, otherwise we should fail */ if (! pidfile && ! cmd) { - char line[130]; - FILE *fp = fopen (tmp, "r"); - + fp = fopen (tmp, "r"); if (fp) { - fgets (line, sizeof (line), fp); - fclose (fp); + fgets(line, sizeof(line), fp); + fclose(fp); if (line[0] == '#' && line[1] == '!') { - size_t len = strlen (line) - 1; + len = strlen (line) - 1; /* Remove the trailing newline */ if (line[len] == '\n') line[len] = '\0'; - eerror ("%s: %s is a script", + eerror("%s: %s is a script", applet, exec); - eerror ("%s: and should be started, stopped or signalled with ", - applet); - eerror ("%s: --exec %s %s", + eerror("%s: and should be started, stopped" + " or signalled with ", applet); + eerror("%s: --exec %s %s", applet, line + 2, exec); - eerror ("%s: or you should specify a pidfile or process name", - applet); + eerror("%s: or you should specify a pidfile" + " or process name", applet); if (ch_root) - free (tmp); - exit (EXIT_FAILURE); + free(tmp); + exit(EXIT_FAILURE); } } } if (ch_root) - free (tmp); + free(tmp); } /* Add exec to our arguments */ @@ -813,83 +810,79 @@ int start_stop_daemon (int argc, char **argv) if (stop) { int result; - if (! schedule) { + if (! STAILQ_FIRST(&schedule)) { if (test || oknodo) - parse_schedule ("0", sig); + parse_schedule("0", sig); else - parse_schedule (NULL, sig); + parse_schedule(NULL, sig); } - result = run_stop_schedule ((const char *const *)argv, cmd, - pidfile, uid, quiet, verbose, test); + result = run_stop_schedule((const char *const *)argv, cmd, + pidfile, uid, quiet, verbose, test); if (result < 0) /* We failed to stop something */ - exit (EXIT_FAILURE); + exit(EXIT_FAILURE); if (test || oknodo) - return (result > 0 ? EXIT_SUCCESS : EXIT_FAILURE); + return result > 0 ? EXIT_SUCCESS : EXIT_FAILURE; /* Even if we have not actually killed anything, we should * remove information about it as it may have unexpectedly * crashed out. We should also return success as the end * result would be the same. */ - if (pidfile && exists (pidfile)) - unlink (pidfile); + if (pidfile && exists(pidfile)) + unlink(pidfile); if (svcname) - rc_service_daemon_set (svcname, - (const char *const *)argv, - cmd, pidfile, false); + rc_service_daemon_set(svcname, + (const char *const *)argv, + cmd, pidfile, false); - exit (EXIT_SUCCESS); + exit(EXIT_SUCCESS); } - if (do_stop ((const char * const *)argv, cmd, pidfile, uid, - 0, true, false, true) > 0) - eerrorx ("%s: %s is already running", applet, exec); + if (do_stop((const char * const *)argv, cmd, pidfile, uid, + 0, true, false, true) > 0) + eerrorx("%s: %s is already running", applet, exec); if (test) { if (quiet) exit (EXIT_SUCCESS); - einfon ("Would start"); + einfon("Would start"); while (argc-- >= 0) printf(" %s", *argv++); - printf ("\n"); - eindent (); + printf("\n"); + eindent(); if (uid != 0) - einfo ("as user id %d", uid); + einfo("as user id %d", uid); if (gid != 0) - einfo ("as group id %d", gid); + einfo("as group id %d", gid); if (ch_root) - einfo ("in root `%s'", ch_root); + einfo("in root `%s'", ch_root); if (ch_dir) - einfo ("in dir `%s'", ch_dir); + einfo("in dir `%s'", ch_dir); if (nicelevel != 0) - einfo ("with a priority of %d", nicelevel); - eoutdent (); - exit (EXIT_SUCCESS); + einfo("with a priority of %d", nicelevel); + eoutdent(); + exit(EXIT_SUCCESS); } - /* Ensure this is unset, so if the daemon does /etc/init.d/foo - Then we filter the environment accordingly */ - unsetenv ("RC_SOFTLEVEL"); - if (verbose) { - ebegin ("Detaching to start `%s'", exec); - eindent (); + ebegin("Detaching to start `%s'", exec); + eindent(); } if (background) - signal_setup (SIGCHLD, handle_signal); + signal_setup(SIGCHLD, handle_signal); - if ((pid = fork ()) == -1) - eerrorx ("%s: fork: %s", applet, strerror (errno)); + if ((pid = fork()) == -1) + eerrorx("%s: fork: %s", applet, strerror(errno)); /* Child process - lets go! */ if (pid == 0) { - pid_t mypid = getpid (); + pid_t mypid = getpid(); #ifdef TIOCNOTTY tty_fd = open("/dev/tty", O_RDWR); @@ -898,66 +891,66 @@ int start_stop_daemon (int argc, char **argv) devnull_fd = open("/dev/null", O_RDWR); if (nicelevel) { - if (setpriority (PRIO_PROCESS, mypid, nicelevel) == -1) - eerrorx ("%s: setpritory %d: %s", applet, nicelevel, + if (setpriority(PRIO_PROCESS, mypid, nicelevel) == -1) + eerrorx("%s: setpritory %d: %s", applet, nicelevel, strerror(errno)); } - if (ch_root && chroot (ch_root) < 0) - eerrorx ("%s: chroot `%s': %s", applet, ch_root, strerror (errno)); + if (ch_root && chroot(ch_root) < 0) + eerrorx("%s: chroot `%s': %s", applet, ch_root, strerror(errno)); if (ch_dir && chdir (ch_dir) < 0) - eerrorx ("%s: chdir `%s': %s", applet, ch_dir, strerror (errno)); + eerrorx("%s: chdir `%s': %s", applet, ch_dir, strerror(errno)); if (makepidfile && pidfile) { - FILE *fp = fopen (pidfile, "w"); + fp = fopen(pidfile, "w"); if (! fp) - eerrorx ("%s: fopen `%s': %s", applet, pidfile, strerror - (errno)); - fprintf (fp, "%d\n", mypid); - fclose (fp); + eerrorx("%s: fopen `%s': %s", applet, pidfile, + strerror(errno)); + fprintf(fp, "%d\n", mypid); + fclose(fp); } #ifdef HAVE_PAM if (changeuser != NULL) - pamr = pam_start ("start-stop-daemon", changeuser, &conv, &pamh); + pamr = pam_start("start-stop-daemon", changeuser, &conv, &pamh); else - pamr = pam_start ("start-stop-daemon", "nobody", &conv, &pamh); + pamr = pam_start("start-stop-daemon", "nobody", &conv, &pamh); if (pamr == PAM_SUCCESS) - pamr = pam_authenticate (pamh, PAM_SILENT); + pamr = pam_authenticate(pamh, PAM_SILENT); if (pamr == PAM_SUCCESS) - pamr = pam_acct_mgmt (pamh, PAM_SILENT); + pamr = pam_acct_mgmt(pamh, PAM_SILENT); if (pamr == PAM_SUCCESS) - pamr = pam_open_session (pamh, PAM_SILENT); + pamr = pam_open_session(pamh, PAM_SILENT); if (pamr != PAM_SUCCESS) - eerrorx ("%s: pam error: %s", applet, pam_strerror(pamh, pamr)); + eerrorx("%s: pam error: %s", applet, pam_strerror(pamh, pamr)); #endif - if (gid && setgid (gid)) - eerrorx ("%s: unable to set groupid to %d", applet, gid); - if (changeuser && initgroups (changeuser, gid)) - eerrorx ("%s: initgroups (%s, %d)", applet, changeuser, gid); - if (uid && setuid (uid)) + if (gid && setgid(gid)) + eerrorx("%s: unable to set groupid to %d", applet, gid); + if (changeuser && initgroups(changeuser, gid)) + eerrorx("%s: initgroups (%s, %d)", applet, changeuser, gid); + if (uid && setuid(uid)) eerrorx ("%s: unable to set userid to %d", applet, uid); else { - struct passwd *passwd = getpwuid (uid); - if (passwd) { + pw = getpwuid(uid); + if (pw) { if (! sethome) { - unsetenv ("HOME"); - if (passwd->pw_dir) - setenv ("HOME", passwd->pw_dir, 1); + unsetenv("HOME"); + if (pw->pw_dir) + setenv("HOME", pw->pw_dir, 1); } if (! setuser) { - unsetenv ("USER"); - if (passwd->pw_name) - setenv ("USER", passwd->pw_name, 1); + unsetenv("USER"); + if (pw->pw_name) + setenv("USER", pw->pw_name, 1); } } } /* Close any fd's to the passwd database */ - endpwent (); + endpwent(); #ifdef TIOCNOTTY ioctl(tty_fd, TIOCNOTTY, 0); @@ -965,84 +958,81 @@ int start_stop_daemon (int argc, char **argv) #endif /* Clean the environment of any RC_ variables */ - STRLIST_FOREACH (environ, env, i) { - if ((strncmp (env, "RC_", 3) == 0 && - strncmp (env, "RC_SERVICE=", strlen ("RC_SERVICE=")) != 0) || - strncmp (env, "SSD_NICELEVEL=", strlen ("SSD_NICELEVEL=")) == 0) + env_list = rc_stringlist_new(); + i = 0; + while(environ[i]) + rc_stringlist_add(env_list, environ[i++]); + TAILQ_FOREACH(env, env_list, entries) { + if ((strncmp(env->value, "RC_", 3) == 0 && + strncmp(env->value, "RC_SERVICE=", strlen("RC_SERVICE=")) != 0) || + strncmp(env->value, "SSD_NICELEVEL=", strlen("SSD_NICELEVEL=")) == 0) + { + p = strchr(env->value, '='); + *p = '\0'; + unsetenv(env->value); continue; - - /* For the path, remove the rcscript bin dir from it */ - if (strncmp (env, "PATH=", 5) == 0) { - char *path = xstrdup (env); - char *newpath = NULL; - char *p = path; - char *token; - char *np; - size_t l; - int t; - - p += 5; - while ((token = strsep (&p, ":"))) { - if (strcmp (token, RC_LIBDIR "/bin") == 0 || - strcmp (token, RC_LIBDIR "/sbin") == 0) - continue; - - t = strlen (token); - if (newpath) { - l = strlen (newpath); - newpath = xrealloc (newpath, sizeof (char) * (l + t + 2)); - np = newpath + l; - *np++ = ':'; - memcpy (np, token, sizeof (char) * strlen (token)); - np += t; - *np = '\0'; - } else { - l = strlen ("PATH=") + t + 1; - newpath = xmalloc (sizeof (char) * l); - snprintf (newpath, l, "PATH=%s", token); - } - } - rc_strlist_add (&newenv, newpath); - free (path); - free (newpath); - } else - rc_strlist_add (&newenv, env); + } + } + rc_stringlist_free(env_list); + + /* For the path, remove the rcscript bin dir from it */ + if ((path = getenv("PATH"))) { + size_t mx = strlen(path); + char *newpath = xmalloc(mx); + char *token; + char *np = newpath; + size_t l; + + p = path; + while ((token = strsep (&p, ":"))) { + if (strcmp (token, RC_LIBDIR "/bin") == 0 || + strcmp (token, RC_LIBDIR "/sbin") == 0) + continue; + + l = strlen (token); + if (np != newpath) + *np++ = ':'; + memcpy (np, token, l); + np += l; + *np = '\0'; + } + unsetenv("PATH"); + setenv("PATH", newpath, 1); } - umask (022); + umask(022); stdout_fd = devnull_fd; stderr_fd = devnull_fd; if (redirect_stdout) { - if ((stdout_fd = open (redirect_stdout, O_WRONLY | O_CREAT | O_APPEND, - S_IRUSR | S_IWUSR)) == -1) - eerrorx ("%s: unable to open the logfile for stdout `%s': %s", - applet, redirect_stdout, strerror (errno)); + if ((stdout_fd = open(redirect_stdout, O_WRONLY | O_CREAT | O_APPEND, + S_IRUSR | S_IWUSR)) == -1) + eerrorx("%s: unable to open the logfile for stdout `%s': %s", + applet, redirect_stdout, strerror(errno)); } if (redirect_stderr) { - if ((stderr_fd = open (redirect_stderr, O_WRONLY | O_CREAT | O_APPEND, - S_IRUSR | S_IWUSR)) == -1) - eerrorx ("%s: unable to open the logfile for stderr `%s': %s", - applet, redirect_stderr, strerror (errno)); + if ((stderr_fd = open(redirect_stderr, O_WRONLY | O_CREAT | O_APPEND, + S_IRUSR | S_IWUSR)) == -1) + eerrorx("%s: unable to open the logfile for stderr `%s': %s", + applet, redirect_stderr, strerror(errno)); } /* We don't redirect stdin as some daemons may need it */ if (background || quiet || redirect_stdout) - dup2 (stdout_fd, STDOUT_FILENO); + dup2(stdout_fd, STDOUT_FILENO); if (background || quiet || redirect_stderr) - dup2 (stderr_fd, STDERR_FILENO); + dup2(stderr_fd, STDERR_FILENO); - for (i = getdtablesize () - 1; i >= 3; --i) + for (i = getdtablesize() - 1; i >= 3; --i) close(i); - setsid (); - - execve (exec, argv, newenv); + setsid(); + execv(exec, argv); #ifdef HAVE_PAM if (pamr == PAM_SUCCESS) - pam_close_session (pamh, PAM_SILENT); + pam_close_session(pamh, PAM_SILENT); #endif - eerrorx ("%s: failed to exec `%s': %s", applet, exec, strerror (errno)); + eerrorx("%s: failed to exec `%s': %s", applet, exec, strerror(errno)); } /* Parent process */ @@ -1053,17 +1043,17 @@ int start_stop_daemon (int argc, char **argv) errno = 0; do { - pid = waitpid (savepid, &status, 0); + pid = waitpid(savepid, &status, 0); if (pid < 1) { - eerror ("waitpid %d: %s", savepid, strerror (errno)); - return (-1); + eerror("waitpid %d: %s", savepid, strerror(errno)); + return -1; } - } while (! WIFEXITED (status) && ! WIFSIGNALED (status)); + } while (! WIFEXITED(status) && ! WIFSIGNALED(status)); - if (! WIFEXITED (status) || WEXITSTATUS (status) != 0) { + if (! WIFEXITED(status) || WEXITSTATUS(status) != 0) { if (! quiet) - eerrorx ("%s: failed to start `%s'", applet, exec); - exit (EXIT_FAILURE); + eerrorx("%s: failed to start `%s'", applet, exec); + exit(EXIT_FAILURE); } pid = savepid; @@ -1081,12 +1071,12 @@ int start_stop_daemon (int argc, char **argv) ts.tv_nsec = POLL_INTERVAL; while (nloops) { - if (nanosleep (&ts, NULL) == -1) { + if (nanosleep(&ts, NULL) == -1) { if (errno == EINTR) - eerror ("%s: caught an interrupt", applet); + eerror("%s: caught an interrupt", applet); else { - eerror ("%s: nanosleep: %s", applet, strerror (errno)); - return (0); + eerror("%s: nanosleep: %s", applet, strerror(errno)); + return 0; } } @@ -1111,27 +1101,28 @@ int start_stop_daemon (int argc, char **argv) } else { if (pidfile) { /* The pidfile may not have been written yet - give it some time */ - if (get_pid (pidfile, true) == -1) { + if (get_pid(pidfile, true) == -1) { if (! nloopsp) - eerrorx ("%s: did not create a valid pid in `%s'", - applet, pidfile); + eerrorx("%s: did not create a valid pid in `%s'", + applet, pidfile); alive = true; } else nloopsp = 0; } - if (do_stop ((const char *const *)argv, cmd, - pidfile, uid, 0, true, false, true) > 0) + if (do_stop((const char *const *)argv, cmd, + pidfile, uid, 0, true, false, true) > 0) alive = true; } if (! alive) - eerrorx ("%s: %s died", applet, exec); + eerrorx("%s: %s died", applet, exec); } } if (svcname) - rc_service_daemon_set (svcname, (const char *const *)argv, cmd, pidfile, true); + rc_service_daemon_set(svcname, (const char *const *)argv, + cmd, pidfile, true); - exit (EXIT_SUCCESS); + exit(EXIT_SUCCESS); /* NOTREACHED */ } |