aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2007-09-25 15:38:21 +0000
committerRoy Marples <roy@marples.name>2007-09-25 15:38:21 +0000
commit1e4e8ed27ae95096255283e92a75738bc7e296e5 (patch)
tree5f152e91cce64bc2c9b0c6336b4078e470ac14da
parenta2e5c4513e2955bc0a77c401ea12cc210eab305b (diff)
Initial doxygen documentation for rc.h and einfo.h. Plus some header clean ups.
-rw-r--r--src/Makefile12
-rw-r--r--src/_usage.c2
-rw-r--r--src/einfo.h129
-rw-r--r--src/librc-misc.c9
-rw-r--r--src/librc-strlist.c6
-rw-r--r--src/librc.c43
-rw-r--r--src/rc-status.c7
-rw-r--r--src/rc-update.c7
-rw-r--r--src/rc.c11
-rw-r--r--src/rc.h386
-rw-r--r--src/runscript.c3
11 files changed, 465 insertions, 150 deletions
diff --git a/src/Makefile b/src/Makefile
index 4807ed03..d657d9eb 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -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))
diff --git a/src/_usage.c b/src/_usage.c
index 28f98150..66ae8df0 100644
--- a/src/_usage.c
+++ b/src/_usage.c
@@ -1,4 +1,4 @@
-/*
+/*!
* @file _usage.c
* @brief standardize help/usage output across all our programs
* @internal
diff --git a/src/einfo.h b/src/einfo.h
index dc07b903..94c99072 100644
--- a/src/einfo.h
+++ b/src/einfo.h
@@ -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
diff --git a/src/librc-misc.c b/src/librc-misc.c
index ebf020e2..bd92e584 100644
--- a/src/librc-misc.c
+++ b/src/librc-misc.c
@@ -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)
diff --git a/src/librc-strlist.c b/src/librc-strlist.c
index 14d08baa..9645acb0 100644
--- a/src/librc-strlist.c
+++ b/src/librc-strlist.c
@@ -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)
diff --git a/src/librc.c b/src/librc.c
index f501719e..dd2e0b6b 100644
--- a/src/librc.c
+++ b/src/librc.c
@@ -65,24 +65,23 @@ librc_hidden_def(rc_get_runlevels)
char *rc_get_runlevel (void)
{
FILE *fp;
- static char buffer[PATH_MAX];
-
- 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;
+ char buffer[RC_LINEBUFFER];
+ char *runlevel = NULL;
+
+ 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)
diff --git a/src/rc-status.c b/src/rc-status.c
index f75bfb83..cd4a24f8 100644
--- a/src/rc-status.c
+++ b/src/rc-status.c
@@ -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);
diff --git a/src/rc-update.c b/src/rc-update.c
index fc9ef504..34f10b91 100644
--- a/src/rc-update.c
+++ b/src/rc-update.c
@@ -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))
diff --git a/src/rc.c b/src/rc.c
index 2ae3d560..c84c49e5 100644
--- a/src/rc.c
+++ b/src/rc.c
@@ -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
diff --git a/src/rc.h b/src/rc.h
index c0916144..a4d88d77 100644
--- a/src/rc.h
+++ b/src/rc.h
@@ -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
diff --git a/src/runscript.c b/src/runscript.c
index 200d8d88..550653ab 100644
--- a/src/runscript.c
+++ b/src/runscript.c
@@ -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();