aboutsummaryrefslogtreecommitdiff
path: root/src/librc.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2007-04-11 12:44:47 +0000
committerRoy Marples <roy@marples.name>2007-04-11 12:44:47 +0000
commite6674b2caee26d2421215d29977cb91d5731ec8a (patch)
tree330ef9a3fd817a50ed62438e346e560be08f19fe /src/librc.c
parent55884f7959e1c80e573eb7cc3c8749197c11c4c9 (diff)
Cuddle up to LKML C style
Diffstat (limited to 'src/librc.c')
-rw-r--r--src/librc.c1251
1 files changed, 602 insertions, 649 deletions
diff --git a/src/librc.c b/src/librc.c
index a34702d4..1ea95c6f 100644
--- a/src/librc.c
+++ b/src/librc.c
@@ -39,777 +39,730 @@
#define SOFTLEVEL RC_SVCDIR "softlevel"
static const char *rc_service_state_names[] = {
- "started",
- "stopped",
- "starting",
- "stopping",
- "inactive",
- "wasinactive",
- "coldplugged",
- "failed",
- "scheduled",
- NULL
+ "started",
+ "stopped",
+ "starting",
+ "stopping",
+ "inactive",
+ "wasinactive",
+ "coldplugged",
+ "failed",
+ "scheduled",
+ NULL
};
bool rc_runlevel_starting (void)
{
- return (rc_is_dir (RC_SVCDIR "softscripts.old"));
+ return (rc_is_dir (RC_SVCDIR "softscripts.old"));
}
bool rc_runlevel_stopping (void)
{
- return (rc_is_dir (RC_SVCDIR "softscripts.new"));
+ return (rc_is_dir (RC_SVCDIR "softscripts.new"));
}
char **rc_get_runlevels (void)
{
- char **dirs = rc_ls_dir (NULL, RC_RUNLEVELDIR, 0);
- char **runlevels = NULL;
- int i;
- char *dir;
-
- STRLIST_FOREACH (dirs, dir, i)
- {
- char *path = rc_strcatpaths (RC_RUNLEVELDIR, dir, (char *) NULL);
- if (rc_is_dir (path))
- runlevels = rc_strlist_addsort (runlevels, dir);
- free (path);
- }
- rc_strlist_free (dirs);
-
- return (runlevels);
+ char **dirs = rc_ls_dir (NULL, RC_RUNLEVELDIR, 0);
+ char **runlevels = NULL;
+ int i;
+ char *dir;
+
+ STRLIST_FOREACH (dirs, dir, i) {
+ char *path = rc_strcatpaths (RC_RUNLEVELDIR, dir, (char *) NULL);
+ if (rc_is_dir (path))
+ runlevels = rc_strlist_addsort (runlevels, dir);
+ free (path);
+ }
+ rc_strlist_free (dirs);
+
+ return (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;
- fclose (fp);
- return (buffer);
- }
-
- fclose (fp);
- snprintf (buffer, sizeof (buffer), "sysinit");
- return (buffer);
+ 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;
+ fclose (fp);
+ return (buffer);
+ }
+
+ fclose (fp);
+ snprintf (buffer, sizeof (buffer), "sysinit");
+ return (buffer);
}
void rc_set_runlevel (const char *runlevel)
{
- FILE *fp = fopen (SOFTLEVEL, "w");
- if (! fp)
- eerrorx ("failed to open `" SOFTLEVEL "': %s", strerror (errno));
- fprintf (fp, "%s", runlevel);
- fclose (fp);
+ FILE *fp = fopen (SOFTLEVEL, "w");
+ if (! fp)
+ eerrorx ("failed to open `" SOFTLEVEL "': %s", strerror (errno));
+ fprintf (fp, "%s", runlevel);
+ fclose (fp);
}
bool rc_runlevel_exists (const char *runlevel)
{
- char *path;
- bool retval;
+ char *path;
+ bool retval;
- if (! runlevel)
- return (false);
+ if (! runlevel)
+ return (false);
- path = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL);
- retval = rc_is_dir (path);
- free (path);
- return (retval);
+ path = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL);
+ retval = rc_is_dir (path);
+ free (path);
+ return (retval);
}
/* Resolve a service name to it's full path */
char *rc_resolve_service (const char *service)
{
- char buffer[PATH_MAX];
- char *file;
- int r = 0;
-
- if (! service)
- return (NULL);
-
- if (service[0] == '/')
- return (strdup (service));
-
- file = rc_strcatpaths (RC_SVCDIR, "started", service, (char *) NULL);
- if (! rc_is_link (file))
- {
- free (file);
- file = rc_strcatpaths (RC_SVCDIR, "inactive", service, (char *) NULL);
- if (! rc_is_link (file))
- {
- free (file);
- file = NULL;
- }
- }
-
- memset (buffer, 0, sizeof (buffer));
- if (file)
- {
- r = readlink (file, buffer, sizeof (buffer));
- free (file);
- if (r > 0)
- return strdup (buffer);
- }
-
- snprintf (buffer, sizeof (buffer), RC_INITDIR "%s", service);
- return (strdup (buffer));
+ char buffer[PATH_MAX];
+ char *file;
+ int r = 0;
+
+ if (! service)
+ return (NULL);
+
+ if (service[0] == '/')
+ return (strdup (service));
+
+ file = rc_strcatpaths (RC_SVCDIR, "started", service, (char *) NULL);
+ if (! rc_is_link (file)) {
+ free (file);
+ file = rc_strcatpaths (RC_SVCDIR, "inactive", service, (char *) NULL);
+ if (! rc_is_link (file)) {
+ free (file);
+ file = NULL;
+ }
+ }
+
+ memset (buffer, 0, sizeof (buffer));
+ if (file) {
+ r = readlink (file, buffer, sizeof (buffer));
+ free (file);
+ if (r > 0)
+ return strdup (buffer);
+ }
+
+ snprintf (buffer, sizeof (buffer), RC_INITDIR "%s", service);
+ return (strdup (buffer));
}
bool rc_service_exists (const char *service)
{
- char *file;
- bool retval = false;
- int len;
-
- if (! service)
- return (false);
-
- 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);
-
- file = rc_resolve_service (service);
- if (rc_exists (file))
- retval = rc_is_exec (file);
- free (file);
- return (retval);
+ char *file;
+ bool retval = false;
+ int len;
+
+ if (! service)
+ return (false);
+
+ 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);
+
+ file = rc_resolve_service (service);
+ if (rc_exists (file))
+ retval = rc_is_exec (file);
+ free (file);
+ return (retval);
}
bool rc_service_in_runlevel (const char *service, const char *runlevel)
{
- char *file;
- bool retval;
+ char *file;
+ bool retval;
- if (! runlevel || ! service)
- return (false);
+ if (! runlevel || ! service)
+ return (false);
- if (! rc_service_exists (service))
- return (false);
+ if (! rc_service_exists (service))
+ return (false);
- file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service),
- (char *) NULL);
- retval = rc_exists (file);
- free (file);
+ file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service),
+ (char *) NULL);
+ retval = rc_exists (file);
+ free (file);
- return (retval);
+ return (retval);
}
bool rc_mark_service (const char *service, const rc_service_state_t state)
{
- char *file;
- int i = 0;
- int skip_state = -1;
- char *base;
- char *init = rc_resolve_service (service);
- bool skip_wasinactive = false;
-
- if (! service)
- return (false);
-
- base = basename (service);
-
- if (state != rc_service_stopped)
- {
- if (! rc_is_file(init))
- {
- free (init);
- return (false);
- }
-
- file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], base,
- (char *) NULL);
- if (rc_exists (file))
- unlink (file);
- i = symlink (init, file);
- if (i != 0)
- {
- free (file);
- free (init);
- einfo ("%d %s %s", state, rc_service_state_names[state], base);
- eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno));
- return (false);
- }
-
- free (file);
- skip_state = state;
- }
-
- if (state == rc_service_coldplugged)
- {
- free (init);
- return (true);
- }
-
- /* Remove any old states now */
- i = 0;
- while (rc_service_state_names[i])
- {
- if ((i != skip_state &&
- i != rc_service_stopped &&
- i != rc_service_coldplugged &&
- i != rc_service_scheduled &&
- i != rc_service_crashed) &&
- (! skip_wasinactive || i != rc_service_wasinactive))
- {
- file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[i], base,
- (char *) NULL);
- if (rc_exists (file))
- {
- if ((state == rc_service_starting ||
- state == rc_service_stopping) &&
- i == rc_service_inactive)
- {
- char *wasfile = rc_strcatpaths (RC_SVCDIR,
- rc_service_state_names[rc_service_wasinactive],
- base, (char *) NULL);
-
- if (symlink (init, wasfile) != 0)
- eerror ("symlink `%s' to `%s': %s", init, wasfile,
- strerror (errno));
-
- skip_wasinactive = true;
- free (wasfile);
- }
-
- errno = 0;
- if (unlink (file) != 0 && errno != ENOENT)
- eerror ("failed to delete `%s': %s", file,
- strerror (errno));
- }
- free (file);
- }
- i++;
- }
-
- /* Remove the exclusive state if we're inactive */
- if (state == rc_service_started ||
- state == rc_service_stopped ||
- state == rc_service_inactive)
- {
- file = rc_strcatpaths (RC_SVCDIR, "exclusive", base, (char *) NULL);
- if (rc_exists (file))
- if (unlink (file) != 0)
- eerror ("unlink `%s': %s", file, strerror (errno));
- 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);
-
- if (rc_is_dir (dir))
- rc_rm_dir (dir, true);
- free (dir);
-
- dir = rc_strcatpaths (RC_SVCDIR, "daemons", base, (char *) NULL);
- if (rc_is_dir (dir))
- rc_rm_dir (dir, true);
- free (dir);
-
- rc_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 = rc_ls_dir (NULL, sdir, 0);
- char *dir;
- int serrno;
-
- STRLIST_FOREACH (dirs, dir, i)
- {
- char *bdir = rc_strcatpaths (sdir, dir, (char *) NULL);
- file = rc_strcatpaths (bdir, base, (char *) NULL);
- if (rc_exists (file))
- if (unlink (file) != 0)
- eerror ("unlink `%s': %s", file, strerror (errno));
- free (file);
-
- /* Try and remove the dir - we don't care about errors */
- serrno = errno;
- rmdir (bdir);
- errno = serrno;
- free (bdir);
- }
- rc_strlist_free (dirs);
- free (sdir);
- }
-
- free (init);
- return (true);
+ char *file;
+ int i = 0;
+ int skip_state = -1;
+ char *base;
+ char *init = rc_resolve_service (service);
+ bool skip_wasinactive = false;
+
+ if (! service)
+ return (false);
+
+ base = basename (service);
+
+ if (state != rc_service_stopped) {
+ if (! rc_is_file(init)) {
+ free (init);
+ return (false);
+ }
+
+ file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], base,
+ (char *) NULL);
+ if (rc_exists (file))
+ unlink (file);
+ i = symlink (init, file);
+ if (i != 0) {
+ free (file);
+ free (init);
+ einfo ("%d %s %s", state, rc_service_state_names[state], base);
+ eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno));
+ return (false);
+ }
+
+ free (file);
+ skip_state = state;
+ }
+
+ if (state == rc_service_coldplugged) {
+ free (init);
+ return (true);
+ }
+
+ /* Remove any old states now */
+ i = 0;
+ while (rc_service_state_names[i]) {
+ if ((i != skip_state &&
+ i != rc_service_stopped &&
+ i != rc_service_coldplugged &&
+ i != rc_service_scheduled &&
+ i != rc_service_crashed) &&
+ (! skip_wasinactive || i != rc_service_wasinactive))
+ {
+ file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[i], base,
+ (char *) NULL);
+ if (rc_exists (file)) {
+ if ((state == rc_service_starting ||
+ state == rc_service_stopping) &&
+ i == rc_service_inactive)
+ {
+ char *wasfile = rc_strcatpaths (RC_SVCDIR,
+ rc_service_state_names[rc_service_wasinactive],
+ base, (char *) NULL);
+
+ if (symlink (init, wasfile) != 0)
+ eerror ("symlink `%s' to `%s': %s", init, wasfile,
+ strerror (errno));
+
+ skip_wasinactive = true;
+ free (wasfile);
+ }
+
+ errno = 0;
+ if (unlink (file) != 0 && errno != ENOENT)
+ eerror ("failed to delete `%s': %s", file,
+ strerror (errno));
+ }
+ free (file);
+ }
+ i++;
+ }
+
+ /* Remove the exclusive state if we're inactive */
+ if (state == rc_service_started ||
+ state == rc_service_stopped ||
+ state == rc_service_inactive)
+ {
+ file = rc_strcatpaths (RC_SVCDIR, "exclusive", base, (char *) NULL);
+ if (rc_exists (file))
+ if (unlink (file) != 0)
+ eerror ("unlink `%s': %s", file, strerror (errno));
+ 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);
+
+ if (rc_is_dir (dir))
+ rc_rm_dir (dir, true);
+ free (dir);
+
+ dir = rc_strcatpaths (RC_SVCDIR, "daemons", base, (char *) NULL);
+ if (rc_is_dir (dir))
+ rc_rm_dir (dir, true);
+ free (dir);
+
+ rc_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 = rc_ls_dir (NULL, sdir, 0);
+ char *dir;
+ int serrno;
+
+ STRLIST_FOREACH (dirs, dir, i) {
+ char *bdir = rc_strcatpaths (sdir, dir, (char *) NULL);
+ file = rc_strcatpaths (bdir, base, (char *) NULL);
+ if (rc_exists (file))
+ if (unlink (file) != 0)
+ eerror ("unlink `%s': %s", file, strerror (errno));
+ free (file);
+
+ /* Try and remove the dir - we don't care about errors */
+ serrno = errno;
+ rmdir (bdir);
+ errno = serrno;
+ free (bdir);
+ }
+ rc_strlist_free (dirs);
+ free (sdir);
+ }
+
+ free (init);
+ return (true);
}
bool rc_service_state (const char *service, const rc_service_state_t state)
{
- char *file;
- bool retval;
-
- /* If the init script does not exist then we are stopped */
- if (! rc_service_exists (service))
- return (state == rc_service_stopped ? true : false);
-
- /* We check stopped state by not being in any of the others */
- if (state == rc_service_stopped)
- return ( ! (rc_service_state (service, rc_service_started) ||
- rc_service_state (service, rc_service_starting) ||
- rc_service_state (service, rc_service_stopping) ||
- rc_service_state (service, rc_service_inactive)));
-
- /* The crashed state and scheduled states are virtual */
- if (state == rc_service_crashed)
- return (rc_service_daemons_crashed (service));
- else if (state == rc_service_scheduled)
- {
- char **services = rc_services_scheduled_by (service);
- retval = (services);
- if (services)
- free (services);
- return (retval);
- }
-
- /* Now we just check if a file by the service name rc_exists
- in the state dir */
- file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state],
- basename (service), (char*) NULL);
- retval = rc_exists (file);
- free (file);
- return (retval);
+ char *file;
+ bool retval;
+
+ /* If the init script does not exist then we are stopped */
+ if (! rc_service_exists (service))
+ return (state == rc_service_stopped ? true : false);
+
+ /* We check stopped state by not being in any of the others */
+ if (state == rc_service_stopped)
+ return ( ! (rc_service_state (service, rc_service_started) ||
+ rc_service_state (service, rc_service_starting) ||
+ rc_service_state (service, rc_service_stopping) ||
+ rc_service_state (service, rc_service_inactive)));
+
+ /* The crashed state and scheduled states are virtual */
+ if (state == rc_service_crashed)
+ return (rc_service_daemons_crashed (service));
+ else if (state == rc_service_scheduled) {
+ char **services = rc_services_scheduled_by (service);
+ retval = (services);
+ if (services)
+ free (services);
+ return (retval);
+ }
+
+ /* Now we just check if a file by the service name rc_exists
+ in the state dir */
+ file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state],
+ basename (service), (char*) NULL);
+ retval = rc_exists (file);
+ free (file);
+ return (retval);
}
bool rc_get_service_option (const char *service, const char *option,
- char *value)
+ char *value)
{
- FILE *fp;
- char buffer[RC_LINEBUFFER];
- char *file = rc_strcatpaths (RC_SVCDIR, "options", service, option,
- (char *) NULL);
- bool retval = false;
-
- 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);
- }
- fclose (fp);
- retval = true;
- }
- }
-
- free (file);
- return (retval);
+ FILE *fp;
+ char buffer[RC_LINEBUFFER];
+ char *file = rc_strcatpaths (RC_SVCDIR, "options", service, option,
+ (char *) NULL);
+ bool retval = false;
+
+ 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);
+ }
+ fclose (fp);
+ retval = true;
+ }
+ }
+
+ free (file);
+ return (retval);
}
bool rc_set_service_option (const char *service, const char *option,
- const char *value)
+ const char *value)
{
- FILE *fp;
- char *path = rc_strcatpaths (RC_SVCDIR, "options", service, (char *) NULL);
- char *file = rc_strcatpaths (path, option, (char *) NULL);
- bool retval = false;
-
- if (! rc_is_dir (path))
- {
- if (mkdir (path, 0755) != 0)
- {
- eerror ("mkdir `%s': %s", path, strerror (errno));
- free (path);
- free (file);
- return (false);
- }
- }
-
- if ((fp = fopen (file, "w")) == NULL)
- eerror ("fopen `%s': %s", file, strerror (errno));
- else
- {
- if (value)
- fprintf (fp, "%s", value);
- fclose (fp);
- retval = true;
- }
-
- free (path);
- free (file);
- return (retval);
+ FILE *fp;
+ char *path = rc_strcatpaths (RC_SVCDIR, "options", service, (char *) NULL);
+ char *file = rc_strcatpaths (path, option, (char *) NULL);
+ bool retval = false;
+
+ if (! rc_is_dir (path)) {
+ if (mkdir (path, 0755) != 0) {
+ eerror ("mkdir `%s': %s", path, strerror (errno));
+ free (path);
+ free (file);
+ return (false);
+ }
+ }
+
+ if ((fp = fopen (file, "w")) == NULL)
+ eerror ("fopen `%s': %s", file, strerror (errno));
+ else {
+ if (value)
+ fprintf (fp, "%s", value);
+ fclose (fp);
+ retval = true;
+ }
+
+ free (path);
+ free (file);
+ return (retval);
}
static pid_t _exec_service (const char *service, const char *arg)
{
- char *file;
- char *fifo;
- pid_t pid = -1;
- pid_t savedpid;
- int status;
-
- file = rc_resolve_service (service);
- if (! rc_is_file (file))
- {
- rc_mark_service (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 (service),
- (char *) NULL);
-
- if (mkfifo (fifo, 0600) != 0 && errno != EEXIST)
- {
- eerror ("unable to create fifo `%s': %s", fifo, strerror (errno));
- free (fifo);
- free (file);
- return (-1);
- }
-
- if ((pid = fork ()) == 0)
- {
- char *myarg = strdup (arg);
- int e = 0;
- execl (file, file, myarg, (char *) NULL);
- e = errno;
- free (myarg);
- unlink (fifo);
- free (fifo);
- eerrorx ("unable to exec `%s': %s", file, strerror (errno));
- }
-
- free (fifo);
- free (file);
-
- if (pid == -1)
- {
- eerror ("unable to fork: %s", strerror (errno));
- return (pid);
- }
-
- if (rc_is_env ("RC_PARALLEL_STARTUP", "yes"))
- return (pid);
-
- savedpid = pid;
- errno = 0;
- do
- {
- pid = waitpid (savedpid, &status, 0);
- if (pid < 0)
- {
- if (errno != ECHILD)
- eerror ("waitpid %d: %s", savedpid, strerror (errno));
- return (-1);
- }
- } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
-
- return (0);
+ char *file;
+ char *fifo;
+ pid_t pid = -1;
+ pid_t savedpid;
+ int status;
+
+ file = rc_resolve_service (service);
+ if (! rc_is_file (file)) {
+ rc_mark_service (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 (service),
+ (char *) NULL);
+
+ if (mkfifo (fifo, 0600) != 0 && errno != EEXIST) {
+ eerror ("unable to create fifo `%s': %s", fifo, strerror (errno));
+ free (fifo);
+ free (file);
+ return (-1);
+ }
+
+ if ((pid = fork ()) == 0) {
+ char *myarg = strdup (arg);
+ int e = 0;
+ execl (file, file, myarg, (char *) NULL);
+ e = errno;
+ free (myarg);
+ unlink (fifo);
+ free (fifo);
+ eerrorx ("unable to exec `%s': %s", file, strerror (errno));
+ }
+
+ free (fifo);
+ free (file);
+
+ if (pid == -1) {
+ eerror ("unable to fork: %s", strerror (errno));
+ return (pid);
+ }
+
+ if (rc_is_env ("RC_PARALLEL_STARTUP", "yes"))
+ return (pid);
+
+ savedpid = pid;
+ errno = 0;
+ do {
+ pid = waitpid (savedpid, &status, 0);
+ if (pid < 0) {
+ if (errno != ECHILD)
+ eerror ("waitpid %d: %s", savedpid, strerror (errno));
+ return (-1);
+ }
+ } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
+
+ return (0);
}
pid_t rc_stop_service (const char *service)
{
- if (rc_service_state (service, rc_service_stopped))
- return (0);
+ if (rc_service_state (service, rc_service_stopped))
+ return (0);
- return (_exec_service (service, "stop"));
+ return (_exec_service (service, "stop"));
}
pid_t rc_start_service (const char *service)
{
- if (! rc_service_state (service, rc_service_stopped))
- return (0);
+ if (! rc_service_state (service, rc_service_stopped))
+ return (0);
- return (_exec_service (service, "start"));
+ return (_exec_service (service, "start"));
}
void rc_schedule_start_service (const char *service,
- const char *service_to_start)
+ const char *service_to_start)
{
- char *dir;
- char *init;
- char *file;
-
- /* service may be a provided service, like net */
- if (! service || ! rc_service_exists (service_to_start))
- return;
-
- dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service),
- (char *) NULL);
- if (! rc_is_dir (dir))
- if (mkdir (dir, 0755) != 0)
- {
- eerror ("mkdir `%s': %s", dir, strerror (errno));
- free (dir);
- return;
- }
-
- init = rc_resolve_service (service_to_start);
- file = rc_strcatpaths (dir, basename (service_to_start), (char *) NULL);
- if (! rc_exists (file) && symlink (init, file) != 0)
- eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno));
-
- free (init);
- free (file);
- free (dir);
+ char *dir;
+ char *init;
+ char *file;
+
+ /* service may be a provided service, like net */
+ if (! service || ! rc_service_exists (service_to_start))
+ return;
+
+ dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service),
+ (char *) NULL);
+ if (! rc_is_dir (dir))
+ if (mkdir (dir, 0755) != 0) {
+ eerror ("mkdir `%s': %s", dir, strerror (errno));
+ free (dir);
+ return;
+ }
+
+ init = rc_resolve_service (service_to_start);
+ file = rc_strcatpaths (dir, basename (service_to_start), (char *) NULL);
+ if (! rc_exists (file) && symlink (init, file) != 0)
+ eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno));
+
+ free (init);
+ free (file);
+ free (dir);
}
void rc_schedule_clear (const char *service)
{
- char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service),
- (char *) NULL);
+ char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service),
+ (char *) NULL);
- if (rc_is_dir (dir))
- rc_rm_dir (dir, true);
- free (dir);
+ if (rc_is_dir (dir))
+ rc_rm_dir (dir, true);
+ free (dir);
}
bool rc_wait_service (const char *service)
{
- char *fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename (service),
- (char *) NULL);
- struct timeval tv;
- struct timeval stopat;
- struct timeval now;
- bool retval = false;
-
- if (gettimeofday (&stopat, NULL) != 0)
- {
- eerror ("gettimeofday: %s", strerror (errno));
- return (false);
- }
- stopat.tv_sec += WAIT_MAX;
-
- while (true)
- {
- if (! rc_exists (fifo))
- {
- retval = true;
- break;
- }
-
- tv.tv_sec = 0;
- tv.tv_usec = WAIT_INTERVAL;
- if (select (0, 0, 0, 0, &tv) < 0)
- {
- if (errno != EINTR)
- eerror ("select: %s",strerror (errno));
- break;
- }
-
- /* Don't hang around forever */
- if (gettimeofday (&now, NULL) != 0)
- {
- eerror ("gettimeofday: %s", strerror (errno));
- break;
- }
- if (timercmp (&now, &stopat, >))
- break;
- }
-
- free (fifo);
- return (retval);
+ char *fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename (service),
+ (char *) NULL);
+ struct timeval tv;
+ struct timeval stopat;
+ struct timeval now;
+ bool retval = false;
+
+ if (gettimeofday (&stopat, NULL) != 0) {
+ eerror ("gettimeofday: %s", strerror (errno));
+ return (false);
+ }
+ stopat.tv_sec += WAIT_MAX;
+
+ while (true) {
+ if (! rc_exists (fifo)) {
+ retval = true;
+ break;
+ }
+
+ tv.tv_sec = 0;
+ tv.tv_usec = WAIT_INTERVAL;
+ if (select (0, 0, 0, 0, &tv) < 0) {
+ if (errno != EINTR)
+ eerror ("select: %s",strerror (errno));
+ break;
+ }
+
+ /* Don't hang around forever */
+ if (gettimeofday (&now, NULL) != 0) {
+ eerror ("gettimeofday: %s", strerror (errno));
+ break;
+ }
+
+ if (timercmp (&now, &stopat, >))
+ break;
+ }
+
+ free (fifo);
+ return (retval);
}
char **rc_services_in_runlevel (const char *runlevel)
{
- char *dir;
- char **list = NULL;
+ char *dir;
+ char **list = NULL;
- if (! runlevel)
- return (rc_ls_dir (NULL, RC_INITDIR, RC_LS_INITD));
+ if (! runlevel)
+ return (rc_ls_dir (NULL, RC_INITDIR, RC_LS_INITD));
- /* These special levels never contain any services */
- if (strcmp (runlevel, RC_LEVEL_SYSINIT) == 0 ||
- strcmp (runlevel, RC_LEVEL_SINGLE) == 0)
- return (NULL);
+ /* 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);
- if (! rc_is_dir (dir))
- eerror ("runlevel `%s' does not exist", runlevel);
- else
- list = rc_ls_dir (list, dir, RC_LS_INITD);
+ dir = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL);
+ if (! rc_is_dir (dir))
+ eerror ("runlevel `%s' does not exist", runlevel);
+ else
+ list = rc_ls_dir (list, dir, RC_LS_INITD);
- free (dir);
- return (list);
+ free (dir);
+ return (list);
}
char **rc_services_in_state (rc_service_state_t state)
{
- char *dir = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state],
- (char *) NULL);
- char **list = NULL;
-
- if (state == rc_service_scheduled)
- {
- char **dirs = rc_ls_dir (NULL, dir, 0);
- char *d;
- int i;
-
- STRLIST_FOREACH (dirs, d, i)
- {
- char *p = rc_strcatpaths (dir, d, (char *) NULL);
- char **entries = rc_ls_dir (NULL, p, RC_LS_INITD);
- char *e;
- int j;
-
- STRLIST_FOREACH (entries, e, j)
- list = rc_strlist_addsortu (list, e);
-
- if (entries)
- free (entries);
- }
-
- if (dirs)
- free (dirs);
- }
- else
- {
- if (rc_is_dir (dir))
- list = rc_ls_dir (list, dir, RC_LS_INITD);
- }
-
- free (dir);
- return (list);
+ char *dir = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state],
+ (char *) NULL);
+ char **list = NULL;
+
+ if (state == rc_service_scheduled) {
+ char **dirs = rc_ls_dir (NULL, dir, 0);
+ char *d;
+ int i;
+
+ STRLIST_FOREACH (dirs, d, i) {
+ char *p = rc_strcatpaths (dir, d, (char *) NULL);
+ char **entries = rc_ls_dir (NULL, p, RC_LS_INITD);
+ char *e;
+ int j;
+
+ STRLIST_FOREACH (entries, e, j)
+ list = rc_strlist_addsortu (list, e);
+
+ if (entries)
+ free (entries);
+ }
+
+ if (dirs)
+ free (dirs);
+ } else {
+ if (rc_is_dir (dir))
+ list = rc_ls_dir (list, dir, RC_LS_INITD);
+ }
+
+ free (dir);
+ return (list);
}
bool rc_service_add (const char *runlevel, const char *service)
{
- bool retval;
- char *init;
- char *file;
-
- if (! rc_runlevel_exists (runlevel))
- {
- errno = ENOENT;
- return (false);
- }
-
- if (rc_service_in_runlevel (service, runlevel))
- {
- errno = EEXIST;
- return (false);
- }
-
- init = rc_resolve_service (service);
- file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service),
- (char *) NULL);
- retval = (symlink (init, file) == 0);
- free (init);
- free (file);
- return (retval);
+ bool retval;
+ char *init;
+ char *file;
+
+ if (! rc_runlevel_exists (runlevel)) {
+ errno = ENOENT;
+ return (false);
+ }
+
+ if (rc_service_in_runlevel (service, runlevel)) {
+ errno = EEXIST;
+ return (false);
+ }
+
+ init = rc_resolve_service (service);
+ file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service),
+ (char *) NULL);
+ retval = (symlink (init, file) == 0);
+ free (init);
+ free (file);
+ return (retval);
}
bool rc_service_delete (const char *runlevel, const char *service)
{
- char *file;
- bool retval = false;
+ char *file;
+ bool retval = false;
- if (! runlevel || ! service)
- return (false);
+ if (! runlevel || ! service)
+ return (false);
- file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service),
- (char *) NULL);
- if (unlink (file) == 0)
- retval = true;
+ file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service),
+ (char *) NULL);
+ if (unlink (file) == 0)
+ retval = true;
- free (file);
- return (retval);
+ free (file);
+ return (retval);
}
char **rc_services_scheduled_by (const char *service)
{
- char **dirs = rc_ls_dir (NULL, RC_SVCDIR "scheduled", 0);
- char **list = NULL;
- char *dir;
- int i;
-
- STRLIST_FOREACH (dirs, dir, i)
- {
- char *file = rc_strcatpaths (RC_SVCDIR "scheduled", dir, service,
- (char *) NULL);
- if (rc_exists (file))
- list = rc_strlist_add (list, file);
- free (file);
- }
- rc_strlist_free (dirs);
-
- return (list);
+ char **dirs = rc_ls_dir (NULL, RC_SVCDIR "scheduled", 0);
+ char **list = NULL;
+ char *dir;
+ int i;
+
+ STRLIST_FOREACH (dirs, dir, i) {
+ char *file = rc_strcatpaths (RC_SVCDIR "scheduled", dir, service,
+ (char *) NULL);
+ if (rc_exists (file))
+ list = rc_strlist_add (list, file);
+ free (file);
+ }
+ rc_strlist_free (dirs);
+
+ return (list);
}
char **rc_services_scheduled (const char *service)
{
- char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service),
- (char *) NULL);
- char **list = NULL;
+ char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service),
+ (char *) NULL);
+ char **list = NULL;
- if (rc_is_dir (dir))
- list = rc_ls_dir (list, dir, RC_LS_INITD);
+ if (rc_is_dir (dir))
+ list = rc_ls_dir (list, dir, RC_LS_INITD);
- free (dir);
- return (list);
+ free (dir);
+ return (list);
}
bool rc_allow_plug (char *service)
{
- char *list;
- char *p;
- char *star;
- char *token;
- bool allow = true;
- char *match = getenv ("RC_PLUG_SERVICES");
- if (! match)
- return true;
-
- list = strdup (match);
- p = list;
- while ((token = strsep (&p, " ")))
- {
- bool truefalse = true;
- if (token[0] == '!')
- {
- truefalse = false;
- token++;
- }
-
- star = strchr (token, '*');
- if (star)
- {
- if (strncmp (service, token, star - token) == 0)
- {
- allow = truefalse;
- break;
- }
- }
- else
- {
- if (strcmp (service, token) == 0)
- {
- allow = truefalse;
- break;
- }
- }
- }
-
- free (list);
- return (allow);
+ char *list;
+ char *p;
+ char *star;
+ char *token;
+ bool allow = true;
+ char *match = getenv ("RC_PLUG_SERVICES");
+ if (! match)
+ return true;
+
+ list = strdup (match);
+ p = list;
+ while ((token = strsep (&p, " "))) {
+ bool truefalse = true;
+ if (token[0] == '!') {
+ truefalse = false;
+ token++;
+ }
+
+ star = strchr (token, '*');
+ if (star) {
+ if (strncmp (service, token, star - token) == 0) {
+ allow = truefalse;
+ break;
+ }
+ } else {
+ if (strcmp (service, token) == 0) {
+ allow = truefalse;
+ break;
+ }
+ }
+ }
+
+ free (list);
+ return (allow);
}