Initial doxygen documentation for rc.h and einfo.h. Plus some header clean ups.

This commit is contained in:
Roy Marples 2007-09-25 15:38:21 +00:00
parent a2e5c4513e
commit 1e4e8ed27a
11 changed files with 464 additions and 149 deletions

View File

@ -75,13 +75,13 @@ RC_BINLINKS = einfon einfo ewarnn ewarn eerrorn eerror ebegin eend ewend \
service_inactive service_wasinactive \
service_coldplugged \
is_runlevel_start is_runlevel_stop service_started_daemon \
checkown fstabinfo mountinfo rc-depend
checkown fstabinfo mountinfo rc-depend \
get_options save_options
RC_SBINLINKS = mark_service_starting mark_service_inactive \
mark_service_started \
mark_service_stopping mark_service_stopped \
mark_service_inactive mark_service_wasinactive \
mark_service_coldplugged \
get_options save_options rc-abort
mark_service_started mark_service_stopping \
mark_service_stopped mark_service_inactive \
mark_service_wasinactive mark_service_coldplugged \
rc-abort
BINLINKS = rc-status
SBINLINKS = env-update rc-update runscript start-stop-daemon
ALL_LINKS = $(sort $(BINLINKS) $(SBINLINKS) $(RC_BINLINKS) $(RC_SBINLINKS))

View File

@ -1,4 +1,4 @@
/*
/*!
* @file _usage.c
* @brief standardize help/usage output across all our programs
* @internal

View File

@ -1,21 +1,31 @@
/*
rc.h
Header file for external applications to get RC information.
Copyright 2007 Gentoo Foundation
Released under the GPLv2
*/
/*!
* @file einfo.h
* @brief Describes how to interface with the einfo library
*
* Copyright 2007 Gentoo Foundation
* Released under the GPLv2
*/
#ifndef __EINFO_H__
#define __EINFO_H__
#define EINFO_PRINTF
#define EINFO_XPRINTF
#define EEND_PRINTF
#ifdef __GNUC__
# define EINFO_PRINTF(_one, _two) __attribute__ ((__format__ (__printf__, _one, _two)))
# define EINFO_XPRINTF(_one, _two) __attribute__ ((__noreturn__, __format__ (__printf__, _one, _two)))
# undef EINFO_PRINTF
# undef EINFO_XPRINTF
# undef EEND_PRINTF
# define EINFO_PRINTF __attribute__ ((__format__ (__printf__, 1, 2)))
# define EINFO_XPRINTF __attribute__ ((__noreturn__, __format__ (__printf__, 1, 2)))
# define EEND_PRINTF __attribute__ ((__format__ (__printf__, 2, 3)))
#endif
#include <sys/types.h>
#include <stdbool.h>
/*! @brief Color types to use */
typedef enum
{
ecolor_good,
@ -26,46 +36,83 @@ typedef enum
ecolor_normal
} einfo_color_t;
/* We work out if the terminal supports colour or not through the use
of the TERM env var. We cache the reslt in a static bool, so
subsequent calls are very fast.
The n suffix means that a newline is NOT appended to the string
The v suffix means that we only print it when RC_VERBOSE=yes
NOTE We use the v suffix here so we can add veinfo for va_list
in the future, but veinfo is used by shell scripts as they don't
have the va_list concept
*/
/*! @brief Returns the ASCII code for the color */
const char *ecolor (einfo_color_t);
void elog (int level, const char *fmt, ...) EINFO_PRINTF (2, 3);
int einfon (const char *fmt, ...) EINFO_PRINTF (1, 2);
int ewarnn (const char *fmt, ...) EINFO_PRINTF (1, 2);
int eerrorn (const char *fmt, ...) EINFO_PRINTF (1, 2);
int einfo (const char *fmt, ...) EINFO_PRINTF(1, 2);
int ewarn (const char *fmt, ...) EINFO_PRINTF (1, 2);
void ewarnx (const char *fmt, ...) EINFO_XPRINTF (1,2);
int eerror (const char *fmt, ...) EINFO_PRINTF (1,2);
void eerrorx (const char *fmt, ...) EINFO_XPRINTF (1,2);
int ebegin (const char *fmt, ...) EINFO_PRINTF (1, 2);
int eend (int retval, const char *fmt, ...) EINFO_PRINTF (2, 3);
int ewend (int retval, const char *fmt, ...) EINFO_PRINTF (2, 3);
/*! @brief Writes to syslog. */
void elog (int level, const char *fmt, ...) EEND_PRINTF;
/*!
* @brief Display informational messages.
*
* The einfo family of functions display messages in a consistent manner
* across Gentoo applications. Basically they prefix the message with
* " * ". If the terminal can handle color then we color the * based on
* the command used. Otherwise we are identical to the printf function.
*
* - einfo - green
* - ewarn - yellow
* - eerror - red
*
* The n suffix denotes that no new line should be printed.
* The v suffix means only print if RC_VERBOSE is yes.
*/
/*@{*/
int einfon (const char *fmt, ...) EINFO_PRINTF;
int ewarnn (const char *fmt, ...) EINFO_PRINTF;
int eerrorn (const char *fmt, ...) EINFO_PRINTF;
int einfo (const char *fmt, ...) EINFO_PRINTF;
int ewarn (const char *fmt, ...) EINFO_PRINTF;
void ewarnx (const char *fmt, ...) EINFO_XPRINTF;
int eerror (const char *fmt, ...) EINFO_PRINTF;
void eerrorx (const char *fmt, ...) EINFO_XPRINTF;
int einfovn (const char *fmt, ...) EINFO_PRINTF;
int ewarnvn (const char *fmt, ...) EINFO_PRINTF;
int ebeginvn (const char *fmt, ...) EINFO_PRINTF;
int eendvn (int retval, const char *fmt, ...) EEND_PRINTF;
int ewendvn (int retval, const char *fmt, ...) EEND_PRINTF;
int einfov (const char *fmt, ...) EINFO_PRINTF;
int ewarnv (const char *fmt, ...) EINFO_PRINTF;
/*@}*/
/*! @ingroup ebegin
* @brief Display informational messages that may take some time.
*
* Similar to einfo, but we add ... to the end of the message */
/*@{*/
int ebeginv (const char *fmt, ...) EINFO_PRINTF;
int ebegin (const char *fmt, ...) EINFO_PRINTF;
/*@}*/
/*! @ingroup eend
* @brief End an ebegin.
*
* If you ebegin, you should eend also.
* eend places [ ok ] or [ !! ] at the end of the terminal line depending on
* retval (0 or ok, anything else for !!)
*
* ebracket allows you to specifiy the position, color and message */
/*@{*/
int eend (int retval, const char *fmt, ...) EEND_PRINTF;
int ewend (int retval, const char *fmt, ...) EEND_PRINTF;
void ebracket (int col, einfo_color_t color, const char *msg);
int eendv (int retval, const char *fmt, ...) EEND_PRINTF;
int ewendv (int retval, const char *fmt, ...) EEND_PRINTF;
/*@}*/
/*! @ingroup eindent
* @brief Indents the einfo lines.
*
* For each indent you should outdent when done */
/*@{*/
void eindent (void);
void eoutdent (void);
int einfovn (const char *fmt, ...) EINFO_PRINTF (1, 2);
int ewarnvn (const char *fmt, ...) EINFO_PRINTF (1, 2);
int ebeginvn (const char *fmt, ...) EINFO_PRINTF (1, 2);
int eendvn (int retval, const char *fmt, ...) EINFO_PRINTF (2, 3);
int ewendvn (int retval, const char *fmt, ...) EINFO_PRINTF (2, 3);
int einfov (const char *fmt, ...) EINFO_PRINTF (1, 2);
int ewarnv (const char *fmt, ...) EINFO_PRINTF (1, 2);
int ebeginv (const char *fmt, ...) EINFO_PRINTF (1, 2);
int eendv (int retval, const char *fmt, ...) EINFO_PRINTF (2, 3);
int ewendv (int retval, const char *fmt, ...) EINFO_PRINTF (2, 3);
void eindentv (void);
void eoutdentv (void);
/* Pointer to a string that is always prefixed to einfo/ewarn/error */
/*! @brief Prefix each einfo line with something */
void eprefix (const char *prefix);
#endif

View File

@ -588,9 +588,10 @@ char **rc_make_env (void)
bool has_net_fs_list = false;
FILE *fp;
char buffer[PATH_MAX];
char *runlevel = rc_get_runlevel ();
/* Don't trust environ for softlevel yet */
snprintf (buffer, PATH_MAX, "%s.%s", RC_CONFIG, rc_get_runlevel());
snprintf (buffer, PATH_MAX, "%s.%s", RC_CONFIG, runlevel);
if (rc_exists (buffer))
config = rc_get_config (buffer);
else
@ -632,10 +633,9 @@ char **rc_make_env (void)
rc_strlist_add (&env, "RC_BOOTLEVEL=" RC_LEVEL_BOOT);
p = rc_get_runlevel ();
i = strlen ("RC_SOFTLEVEL=") + strlen (p) + 1;
i = strlen ("RC_SOFTLEVEL=") + strlen (runlevel) + 1;
line = rc_xmalloc (sizeof (char *) * i);
snprintf (line, i, "RC_SOFTLEVEL=%s", p);
snprintf (line, i, "RC_SOFTLEVEL=%s", runlevel);
rc_strlist_add (&env, line);
free (line);
@ -717,6 +717,7 @@ char **rc_make_env (void)
free (line);
}
free (runlevel);
return (env);
}
librc_hidden_def(rc_make_env)

View File

@ -135,7 +135,7 @@ int rc_strlist_delete (char ***list, const char *item)
}
librc_hidden_def(rc_strlist_delete)
int rc_strlist_join (char ***list1, char **list2)
char *rc_strlist_join (char ***list1, char **list2)
{
char **lst1 = *list1;
char **newlist;
@ -143,7 +143,7 @@ int rc_strlist_join (char ***list1, char **list2)
int j = 0;
if (! list2)
return (0);
return (NULL);
while (lst1 && lst1[i])
i++;
@ -164,7 +164,7 @@ int rc_strlist_join (char ***list1, char **list2)
newlist[i] = NULL;
*list1 = newlist;
return (0);
return (newlist[i == 0 ? 0 : i - 1]);
}
librc_hidden_def(rc_strlist_join)

View File

@ -65,24 +65,23 @@ librc_hidden_def(rc_get_runlevels)
char *rc_get_runlevel (void)
{
FILE *fp;
static char buffer[PATH_MAX];
char buffer[RC_LINEBUFFER];
char *runlevel = NULL;
if (! (fp = fopen (SOFTLEVEL, "r"))) {
snprintf (buffer, sizeof (buffer), "sysinit");
return (buffer);
}
if (fgets (buffer, PATH_MAX, fp)) {
int i = strlen (buffer) - 1;
if (buffer[i] == '\n')
buffer[i] = 0;
if ((fp = fopen (SOFTLEVEL, "r"))) {
if (fgets (buffer, PATH_MAX, fp)) {
int i = strlen (buffer) - 1;
if (buffer[i] == '\n')
buffer[i] = 0;
runlevel = rc_xstrdup (buffer);
}
fclose (fp);
return (buffer);
}
fclose (fp);
snprintf (buffer, sizeof (buffer), "sysinit");
return (buffer);
if (! runlevel)
runlevel = rc_xstrdup (RC_LEVEL_SYSINIT);
return (runlevel);
}
librc_hidden_def(rc_get_runlevel)
@ -452,31 +451,27 @@ bool rc_service_state (const char *service, const rc_service_state_t state)
}
librc_hidden_def(rc_service_state)
bool rc_get_service_option (const char *service, const char *option,
char *value)
char *rc_get_service_option (const char *service, const char *option)
{
FILE *fp;
char buffer[RC_LINEBUFFER];
char *file = rc_strcatpaths (RC_SVCDIR, "options", service, option,
(char *) NULL);
bool retval = false;
char *value = NULL;
if (rc_exists (file)) {
if ((fp = fopen (file, "r")) == NULL)
eerror ("fopen `%s': %s", file, strerror (errno));
else {
memset (buffer, 0, sizeof (buffer));
while (fgets (buffer, RC_LINEBUFFER, fp)) {
memcpy (value, buffer, strlen (buffer));
value += strlen (buffer);
}
if (fgets (buffer, RC_LINEBUFFER, fp))
value = rc_xstrdup (buffer);
fclose (fp);
retval = true;
}
}
free (file);
return (retval);
return (value);
}
librc_hidden_def(rc_get_service_option)

View File

@ -117,8 +117,11 @@ int rc_status (int argc, char **argv)
while (optind < argc)
rc_strlist_add (&levels, argv[optind++]);
if (! levels)
rc_strlist_add (&levels, rc_get_runlevel ());
if (! levels) {
level = rc_get_runlevel ();
rc_strlist_add (&levels, level);
free (level);
}
STRLIST_FOREACH (levels, level, i) {
print_level (level);

View File

@ -208,8 +208,11 @@ int rc_update (int argc, char **argv)
eerror ("%s: service `%s' does not exist", applet, service);
else {
retval = EXIT_SUCCESS;
if (! runlevels)
rc_strlist_add (&runlevels, rc_get_runlevel ());
if (! runlevels) {
runlevel = rc_get_runlevel ();
rc_strlist_add (&runlevels, runlevel);
free (runlevel);
}
STRLIST_FOREACH (runlevels, runlevel, i) {
if (action & DOADD) {
if (! add (runlevel, service))

View File

@ -359,11 +359,12 @@ static int do_options (int argc, char **argv)
eerrorx ("%s: no option specified", applet);
if (strcmp (applet, "get_options") == 0) {
char buffer[1024];
memset (buffer, 0, 1024);
ok = rc_get_service_option (service, argv[0], buffer);
if (ok)
printf ("%s", buffer);
char *option = rc_get_service_option (service, argv[0]);
if (option) {
printf ("%s", option);
free (option);
ok = true;
}
} else if (strcmp (applet, "save_options") == 0)
ok = rc_set_service_option (service, argv[0], argv[1]);
else

386
src/rc.h
View File

@ -1,32 +1,45 @@
/*
rc.h
Header file for external applications to get RC information.
Copyright 2007 Gentoo Foundation
Released under the GPLv2
*/
/*!
* @file rc.h
* @brief Describes how to interface with the RC library
* @internal
*
* Copyright 2007 Gentoo Foundation
* Released under the GPLv2
*/
#ifndef __RC_H__
#define __RC_H__
#define SENTINEL
#ifdef __GNUC__
# define GCC_VERSION (__GNUC__ * 1000 + __GNUC__MINOR )
# define GCC_VERSION (__GNUC__ * 1000 + __GNUC__MINOR)
# if (GCC_VERSION >= 3005)
# undef SENTINEL
# define SENTINEL __attribute__ ((__sentinel__))
# endif
#endif
#ifndef SENTINEL
# define SENTINEL
#endif
#include <sys/types.h>
#include <stdbool.h>
#include <stdio.h>
/* Special level names */
/*! @name Reserved runlevel names */
#define RC_LEVEL_SYSINIT "sysinit"
#define RC_LEVEL_SINGLE "single"
#define RC_LEVEL_SHUTDOWN "shutdown"
#define RC_LEVEL_REBOOT "reboot"
/*! @name rc_ls_dir options */
/*! Ensure that an init.d service exists for each file returned */
#define RC_LS_INITD 0x01
/*! @name RC
* A service can be given as a full path or just its name.
* If its just a name then we try to resolve the service to a full path.
* This should allow the use if local init.d directories in the future. */
/*! @brief States a service can be in */
typedef enum
{
rc_service_started,
@ -41,114 +54,272 @@ typedef enum
rc_service_crashed
} rc_service_state_t;
/*! Resolves a service name to its full path.
* @param service to check
* @return pointer to full path of service */
char *rc_resolve_service (const char *service);
/*! 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);
/*! Lists the extra options a service has
* @param service to load the options from
* @return NULL terminated string list of options */
char **rc_service_options (const char *service);
/*! 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);
/*! 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);
/*! Checks if a service in in a state
* @param service to check
* @param state service should be in
* @return true if service is in the requested state, otherwise false */
bool rc_service_state (const char *service, rc_service_state_t state);
/*! 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_mark_service (const char *service, rc_service_state_t state);
/*! Stop a service
* @param service to stop
* @return pid of service stopping process */
pid_t rc_stop_service (const char *service);
/*! Start a service
* @param service to start
* @return pid of the service starting process */
pid_t rc_start_service (const char *service);
/*! Wait for a process to finish
* @param pid to wait for
* @return exit status of the process */
int rc_waitpid (pid_t pid);
/*! 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 */
void rc_schedule_start_service (const char *service,
const char *service_to_start);
/*! 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);
/*! Clear the list of services scheduled to be started by this service
* @param service to clear */
void rc_schedule_clear (const char *service);
/*! Wait for a service to finish
* @param service to wait for
* @return true if service finished before timeout, otherwise false */
bool rc_wait_service (const char *service);
bool rc_get_service_option (const char *service, const char *option,
char *value);
/*! Return a saved value for a service
* @param service to check
* @param option to load
* @return saved value */
char *rc_get_service_option (const char *service, const char *option);
/*! 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_set_service_option (const char *service, const char *option,
const char *value);
/*! Save the arguments to find a running daemon
* @param service to save arguments for
* @param exec that we started
* @param name of the process (optional)
* @param pidfile of the process (optional)
* @param started if true, add the arguments otherwise remove existing matching arguments */
void rc_set_service_daemon (const char *service, const char *exec,
const char *name, const char *pidfile,
bool started);
/*! 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 *exec,
int indx);
/*! Check if the service is allowed to be hot/cold plugged
* @param service to check
* @return true if allowed, otherwise false */
bool rc_allow_plug (char *service);
/*! Return the current runlevel.
* @return the current runlevel */
char *rc_get_runlevel (void);
/*! Set the runlevel.
* This just changes the stored runlevel and does not start or stop any services.
* @param runlevel to store */
void rc_set_runlevel (const char *runlevel);
/*! 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);
/*! Return a NULL terminated list of runlevels
* @return a NULL terminated list of runlevels */
char **rc_get_runlevels (void);
/*! Is the runlevel starting?
* @return true if yes, otherwise false */
bool rc_runlevel_starting (void);
/*! Is the runlevel stopping?
* @return true if yes, otherwise false */
bool rc_runlevel_stopping (void);
/*! 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);
/*! 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);
/*! List the services in a runlevel
* @param runlevel to list
* @return NULL terminated list of services */
char **rc_services_in_runlevel (const char *runlevel);
/*! 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);
/*! 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);
/* Find pids based on criteria - free the pointer returned after use */
/*! Find processes based on criteria.
* All of these are optional.
* pid overrides anything else.
* If both exec and cmd are given then we ignore exec.
* @param exec to check for
* @param cmd to check for
* @param uid to check for
* @param pid to check for
* @return NULL terminated list of pids */
pid_t *rc_find_pids (const char *exec, const char *cmd,
uid_t uid, pid_t pid);
/* Checks that all daemons started with start-stop-daemon by the service
are still running. If so, return false otherwise true.
You should check that the service has been started before calling this. */
/*! 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);
/* Dependency tree structs and functions. */
/*! @name Dependency options
* These options can change the services found by the rc_get_depinfo and
* rc_get_depends functions. */
/*! Trace provided services */
#define RC_DEP_TRACE 0x01
/*! Only use services added to runlevels */
#define RC_DEP_STRICT 0x02
/*! Runlevel is starting */
#define RC_DEP_START 0x04
/*! Runlevel is stopping */
#define RC_DEP_STOP 0x08
/*! @name Dependencies
* We analyse each init script and cache the resultant dependency tree.
* This tree can be accessed using the below structures and functions. */
/*! 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;
/* Options for rc_dep_depends and rc_order_services.
When changing runlevels, you should use RC_DEP_START and RC_DEP_STOP for
the start and stop lists as we tweak the provided services for this. */
#define RC_DEP_TRACE 0x01
#define RC_DEP_STRICT 0x02
#define RC_DEP_START 0x04
#define RC_DEP_STOP 0x08
/*! 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.
* @param force an update
* @return 0 if successful, otherwise -1 */
int rc_update_deptree (bool force);
/*! Load the cached dependency tree and return a pointer to it.
* This pointer should be freed with rc_free_deptree when done.
* @return pointer to the dependency tree */
rc_depinfo_t *rc_load_deptree (void);
/*! Get a services depedency information from a loaded tree
* @param deptree to search
* @param service to find
* @return service dependency information */
rc_depinfo_t *rc_get_depinfo (rc_depinfo_t *deptree, const char *service);
/*! Get a depenency type from the service dependency information
* @param depinfo service dependency to search
* @param type to find
* @return service dependency type information */
rc_deptype_t *rc_get_deptype (rc_depinfo_t *depinfo, const char *type);
char **rc_get_depends (rc_depinfo_t *deptree, char **types,
char **services, const char *runlevel, int options);
/* List all the services that should be started, in order, the the
given runlevel, including sysinit and boot services where
approriate.
If reboot, shutdown or single are given then we list all the services
we that we need to shutdown in order. */
/*! List all the services that should be stoppned and then started, in order,
* for the given runlevel, including sysinit and boot services where
* approriate.
* @param deptree to search
* @param runlevel to change into
* @param options to pass
* @return NULL terminated list of services in order */
char **rc_order_services (rc_depinfo_t *deptree, const char *runlevel,
int options);
/*! Free a deptree and its information
* @param deptree to free */
void rc_free_deptree (rc_depinfo_t *deptree);
/* Plugin handler
For each plugin loaded we will call it's _name_hook with the below
enum and either the runlevel name or service name. For example
int _splash_hook (rc_hook_t hook, const char *name);
Plugins are called when rc does something. This does not indicate an
end result and the plugin should use the above functions to query things
like service status.
The service hooks have extra ones - now and done. This is because after
start_in we may start other services before we start the service in
question. now shows we really will start the service now and done shows
when we have done it as may start scheduled services at this point. */
/*! @name Plugins
* For each plugin loaded we will call rc_plugin_hook with the below
* enum and either the runlevel name or service name.
*
* Plugins are called when rc does something. This does not indicate an
* end result and the plugin should use the above functions to query things
* like service status.
*
* The service hooks have extra ones - now and done. This is because after
* start_in we may start other services before we start the service in
* question. now shows we really will start the service now and done shows
* when we have done it as may start scheduled services at this point. */
/*! Points at which a plugin can hook into RC */
typedef enum
{
rc_hook_runlevel_stop_in = 1,
rc_hook_runlevel_stop_out = 4,
rc_hook_runlevel_start_in = 5,
rc_hook_runlevel_start_out = 8,
/* We reserved a few numbers if we need rc_runlevel_stop_now and done */
rc_hook_abort = 99,
/* We send the abort if an init script requests we abort and drop
/*! We send the abort if an init script requests we abort and drop
* into single user mode if system not fully booted */
rc_hook_abort = 99,
rc_hook_service_stop_in = 101,
rc_hook_service_stop_now,
rc_hook_service_stop_done,
@ -159,53 +330,146 @@ typedef enum
rc_hook_service_start_out
} rc_hook_t;
/* Plugins should write FOO=BAR to this fd to set any environment variables
* they wish. At this time we only support the setting of one env var. */
/*! 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);
/*! Plugins should write FOO=BAR to this fd to set any environment
* variables they wish. Variables should be separated by NULLs. */
extern FILE *rc_environ_fd;
/* RC utility functions.
Although not directly related to RC in general, they are used by RC
itself and the supporting applications. */
/*! @name Memory Allocation
* Ensure that if we cannot allocate the memory then we exit */
/*@{*/
/*! Allocate a block of memory
* @param size of memory to allocate
* @return pointer to memory */
void *rc_xmalloc (size_t size);
/*! Re-size a block of memory
* @param ptr to the block of memory to re-size
* @param size memory should be
* @return pointer to memory block */
void *rc_xrealloc (void *ptr, size_t size);
/*! Duplicate a NULL terminated string
* @param str to duplicate
* @return pointer to the new string */
char *rc_xstrdup (const char *str);
/*@}*/
/* Concat paths adding '/' if needed. */
/*! @name Utility
* Although not RC specific functions, they are used by the supporting
* applications */
/*! 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;
/*! Check if an environment variable matches the given value
* @param variable to check
* @param value it should be
* @return true if it matches */
bool rc_is_env (const char *variable, const char *value);
/*! Check if the file exists or not
* @param pathname to check
* @return true if it exists, otherwise false */
bool rc_exists (const char *pathname);
/*! Check if the file is a real file
* @param pathname to check
* @return true if it's a real file, otherwise false */
bool rc_is_file (const char *pathname);
/*! Check if the file is a symbolic link or not
* @param pathname to check
* @return true if it's a symbolic link, otherwise false */
bool rc_is_link (const char *pathname);
/*! Check if the file is a directory or not
* @param pathname to check
* @return true if it's a directory, otherwise false */
bool rc_is_dir (const char *pathname);
/*! Check if the file is marked executable or not
* @param pathname to check
* @return true if it's marked executable, otherwise false */
bool rc_is_exec (const char *pathname);
#define RC_LS_INITD 0x01
/*! Return a NULL terminted sorted list of the contents of the directory
* @param dir to list
* @param options any options to apply
* @return NULL terminated list */
char **rc_ls_dir (const char *dir, int options);
/*! Remove a directory
* @param pathname to remove
* @param top remove the top level directory too
* @return true if successful, otherwise false */
bool rc_rm_dir (const char *pathname, bool top);
/* Config file functions */
/*! @name Configuration */
/*! Return a NULL terminated list of non comment lines from a file. */
char **rc_get_list (const char *file);
/*! Return a NULL terminated list of key=value lines from a file. */
char **rc_get_config (const char *file);
/*! Return the value of the entry from a key=value list. */
char *rc_get_config_entry (char **list, const char *entry);
/* Make an environment list which filters out all unwanted values
and loads it up with our RC config */
/*! Return a NULL terminated string list of variables allowed through
* from the current environemnt. */
char **rc_filter_env (void);
/*! Return a NULL terminated string list of enviroment variables made from
* our configuration files. */
char **rc_make_env (void);
/* Handy functions for dealing with string arrays of 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.*/
/*! 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);
/*! 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);
/*! 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 0 on success, otherwise -1 */
int rc_strlist_delete (char ***list, const char *item);
/* join moves items from list2 to list1, so list2 is empty
* on return. It still needs to be freed though. */
int rc_strlist_join (char ***list1, char **list2);
/*! 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);
/*! Reverses the contents of the list.
* @param list to reverse */
void rc_strlist_reverse (char **list);
/*! Frees each item on the list and the list itself.
* @param list to free */
void rc_strlist_free (char **list);
#endif

View File

@ -307,6 +307,7 @@ static void cleanup (void)
free (applet);
free (prefix);
free (service);
free (softlevel);
}
static int write_prefix (const char *buffer, size_t bytes, bool *prefixed) {
@ -1029,7 +1030,7 @@ int runscript (int argc, char **argv)
}
#endif
if ((softlevel = getenv ("RC_SOFTLEVEL")) == NULL) {
if ((softlevel = rc_xstrdup (getenv ("RC_SOFTLEVEL"))) == NULL) {
/* Ensure our environment is pure
Also, add our configuration to it */
tmplist = rc_make_env();