aboutsummaryrefslogtreecommitdiff
path: root/src/runscript.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/runscript.c')
-rw-r--r--src/runscript.c1851
1 files changed, 886 insertions, 965 deletions
diff --git a/src/runscript.c b/src/runscript.c
index a36b264e..76ecd586 100644
--- a/src/runscript.c
+++ b/src/runscript.c
@@ -65,1056 +65,977 @@ void setup_selinux (int argc, char **argv);
#ifdef __linux__
void setup_selinux (int argc, char **argv)
{
- void *lib_handle = NULL;
-
- lib_handle = dlopen (SELINUX_LIB, RTLD_NOW | RTLD_GLOBAL);
- if (lib_handle)
- {
- /* FIXME: the below code generates the warning
- ISO C forbids assignment between function pointer and 'void *'
- which sucks ass
+ void *lib_handle = NULL;
+
+ lib_handle = dlopen (SELINUX_LIB, RTLD_NOW | RTLD_GLOBAL);
+ if (lib_handle) {
+ /* FIXME: the below code generates the warning
+ ISO C forbids assignment between function pointer and 'void *'
+ which sucks ass
http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html */
- selinux_run_init_old = dlsym (lib_handle, "selinux_runscript");
- selinux_run_init_new = dlsym (lib_handle, "selinux_runscript2");
-
- /* Use new run_init if it rc_exists, else fall back to old */
- if (selinux_run_init_new)
- selinux_run_init_new (argc, argv);
- else if (selinux_run_init_old)
- selinux_run_init_old ();
- else
- /* This shouldnt happen... probably corrupt lib */
- eerrorx ("run_init is missing from runscript_selinux.so!");
- }
+ selinux_run_init_old = dlsym (lib_handle, "selinux_runscript");
+ selinux_run_init_new = dlsym (lib_handle, "selinux_runscript2");
+
+ /* Use new run_init if it rc_exists, else fall back to old */
+ if (selinux_run_init_new)
+ selinux_run_init_new (argc, argv);
+ else if (selinux_run_init_old)
+ selinux_run_init_old ();
+ else
+ /* This shouldnt happen... probably corrupt lib */
+ eerrorx ("run_init is missing from runscript_selinux.so!");
+ }
}
#endif
static void handle_signal (int sig)
{
- pid_t pid;
- int status;
- int serrno = errno;
- char signame[10] = { '\0' };
-
- switch (sig)
- {
- case SIGHUP:
- sighup = true;
- break;
-
- case SIGCHLD:
- do
- {
- pid = waitpid (-1, &status, WNOHANG);
- if (pid < 0)
- {
- if (errno != ECHILD)
- eerror ("waitpid: %s", strerror (errno));
- return;
- }
- } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
- break;
-
- case SIGINT:
- if (! signame[0])
- snprintf (signame, sizeof (signame), "SIGINT");
- case SIGTERM:
- if (! signame[0])
- snprintf (signame, sizeof (signame), "SIGTERM");
- case SIGQUIT:
- if (! signame[0])
- snprintf (signame, sizeof (signame), "SIGQUIT");
- eerrorx ("%s: caught %s, aborting", applet, signame);
-
- default:
- eerror ("%s: caught unknown signal %d", applet, sig);
- }
-
- /* Restore errno */
- errno = serrno;
+ pid_t pid;
+ int status;
+ int serrno = errno;
+ char signame[10] = { '\0' };
+
+ switch (sig) {
+ case SIGHUP:
+ sighup = true;
+ break;
+
+ case SIGCHLD:
+ do {
+ pid = waitpid (-1, &status, WNOHANG);
+ if (pid < 0) {
+ if (errno != ECHILD)
+ eerror ("waitpid: %s", strerror (errno));
+ return;
+ }
+ } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
+ break;
+
+ case SIGINT:
+ if (! signame[0])
+ snprintf (signame, sizeof (signame), "SIGINT");
+ case SIGTERM:
+ if (! signame[0])
+ snprintf (signame, sizeof (signame), "SIGTERM");
+ case SIGQUIT:
+ if (! signame[0])
+ snprintf (signame, sizeof (signame), "SIGQUIT");
+ eerrorx ("%s: caught %s, aborting", applet, signame);
+
+ default:
+ eerror ("%s: caught unknown signal %d", applet, sig);
+ }
+
+ /* Restore errno */
+ errno = serrno;
}
static time_t get_mtime (const char *pathname, bool follow_link)
{
- struct stat buf;
- int retval;
+ struct stat buf;
+ int retval;
- if (! pathname)
- return (0);
+ if (! pathname)
+ return (0);
- retval = follow_link ? stat (pathname, &buf) : lstat (pathname, &buf);
- if (! retval)
- return (buf.st_mtime);
+ retval = follow_link ? stat (pathname, &buf) : lstat (pathname, &buf);
+ if (! retval)
+ return (buf.st_mtime);
- errno = 0;
- return (0);
+ errno = 0;
+ return (0);
}
static bool in_control ()
{
- char *path;
- time_t mtime;
- const char *tests[] = { "starting", "started", "stopping",
- "inactive", "wasinactive", NULL };
- int i = 0;
-
- if (sighup)
- return (false);
-
- if (! mtime_test || ! rc_exists (mtime_test))
- return (false);
-
- if (rc_service_state (applet, rc_service_stopped))
- return (false);
-
- if (! (mtime = get_mtime (mtime_test, false)))
- return (false);
-
- while (tests[i])
- {
- path = rc_strcatpaths (RC_SVCDIR, tests[i], applet, (char *) NULL);
- if (rc_exists (path))
- {
- time_t m = get_mtime (path, false);
- if (mtime < m && m != 0)
- {
- free (path);
- return (false);
- }
- }
- free (path);
- i++;
- }
-
- return (true);
+ char *path;
+ time_t mtime;
+ const char *tests[] = { "starting", "started", "stopping",
+ "inactive", "wasinactive", NULL };
+ int i = 0;
+
+ if (sighup)
+ return (false);
+
+ if (! mtime_test || ! rc_exists (mtime_test))
+ return (false);
+
+ if (rc_service_state (applet, rc_service_stopped))
+ return (false);
+
+ if (! (mtime = get_mtime (mtime_test, false)))
+ return (false);
+
+ while (tests[i]) {
+ path = rc_strcatpaths (RC_SVCDIR, tests[i], applet, (char *) NULL);
+ if (rc_exists (path)) {
+ time_t m = get_mtime (path, false);
+ if (mtime < m && m != 0) {
+ free (path);
+ return (false);
+ }
+ }
+ free (path);
+ i++;
+ }
+
+ return (true);
}
static void uncoldplug (char *service)
{
- char *cold = rc_strcatpaths (RC_SVCDIR "coldplugged", basename (service),
- (char *) NULL);
- if (rc_exists (cold) && unlink (cold) != 0)
- eerror ("%s: unlink `%s': %s", applet, cold, strerror (errno));
- free (cold);
+ char *cold = rc_strcatpaths (RC_SVCDIR "coldplugged", basename (service),
+ (char *) NULL);
+ if (rc_exists (cold) && unlink (cold) != 0)
+ eerror ("%s: unlink `%s': %s", applet, cold, strerror (errno));
+ free (cold);
}
static void cleanup (void)
{
- /* Flush our buffered output if any */
- eflush ();
-
- if (hook_out)
- rc_plugin_run (hook_out, applet);
- rc_plugin_unload ();
-
- if (deptree)
- rc_free_deptree (deptree);
- if (services)
- rc_strlist_free (services);
- if (types)
- rc_strlist_free (types);
- if (svclist)
- rc_strlist_free (svclist);
- if (providelist)
- rc_strlist_free (providelist);
- if (restart_services)
- rc_strlist_free (restart_services);
- if (need_services)
- rc_strlist_free (need_services);
- if (tmplist)
- rc_strlist_free (tmplist);
- if (mycmd)
- free (mycmd);
- if (myarg1)
- free (myarg1);
- if (myarg2)
- free (myarg2);
- if (ibsave)
- free (ibsave);
-
- if (in_control ())
- {
- if (rc_service_state (applet, rc_service_stopping))
- {
- /* If the we're shutting down, do it cleanly */
- if ((softlevel &&
- rc_runlevel_stopping () &&
- (strcmp (softlevel, RC_LEVEL_SHUTDOWN) == 0 ||
- strcmp (softlevel, RC_LEVEL_REBOOT) == 0)))
- rc_mark_service (applet, rc_service_stopped);
- else if (rc_service_state (applet, rc_service_wasinactive))
- rc_mark_service (applet, rc_service_inactive);
- else
- rc_mark_service (applet, rc_service_started);
- }
- else if (rc_service_state (applet, rc_service_starting))
- {
- if (rc_service_state (applet, rc_service_wasinactive))
- rc_mark_service (applet, rc_service_inactive);
- else
- rc_mark_service (applet, rc_service_stopped);
- }
- if (exclusive && rc_exists (exclusive))
- unlink (exclusive);
- }
-
- if (env)
- rc_strlist_free (env);
-
- if (mtime_test)
- {
- unlink (mtime_test);
- free (mtime_test);
- }
- if (exclusive)
- free (exclusive);
-
- if (applet)
- free (applet);
+ /* Flush our buffered output if any */
+ eflush ();
+
+ if (hook_out)
+ rc_plugin_run (hook_out, applet);
+ rc_plugin_unload ();
+
+ if (deptree)
+ rc_free_deptree (deptree);
+ if (services)
+ rc_strlist_free (services);
+ if (types)
+ rc_strlist_free (types);
+ if (svclist)
+ rc_strlist_free (svclist);
+ if (providelist)
+ rc_strlist_free (providelist);
+ if (restart_services)
+ rc_strlist_free (restart_services);
+ if (need_services)
+ rc_strlist_free (need_services);
+ if (tmplist)
+ rc_strlist_free (tmplist);
+ if (mycmd)
+ free (mycmd);
+ if (myarg1)
+ free (myarg1);
+ if (myarg2)
+ free (myarg2);
+ if (ibsave)
+ free (ibsave);
+
+ if (in_control ()) {
+ if (rc_service_state (applet, rc_service_stopping)) {
+ /* If the we're shutting down, do it cleanly */
+ if ((softlevel &&
+ rc_runlevel_stopping () &&
+ (strcmp (softlevel, RC_LEVEL_SHUTDOWN) == 0 ||
+ strcmp (softlevel, RC_LEVEL_REBOOT) == 0)))
+ rc_mark_service (applet, rc_service_stopped);
+ else if (rc_service_state (applet, rc_service_wasinactive))
+ rc_mark_service (applet, rc_service_inactive);
+ else
+ rc_mark_service (applet, rc_service_started);
+ }
+ else if (rc_service_state (applet, rc_service_starting))
+ {
+ if (rc_service_state (applet, rc_service_wasinactive))
+ rc_mark_service (applet, rc_service_inactive);
+ else
+ rc_mark_service (applet, rc_service_stopped);
+ }
+ if (exclusive && rc_exists (exclusive))
+ unlink (exclusive);
+ }
+
+ if (env)
+ rc_strlist_free (env);
+
+ if (mtime_test)
+ {
+ unlink (mtime_test);
+ free (mtime_test);
+ }
+ if (exclusive)
+ free (exclusive);
+
+ if (applet)
+ free (applet);
}
static bool svc_exec (const char *service, const char *arg1, const char *arg2)
{
- int status = 0;
- pid_t pid;
-
- /* We need to disable our child signal handler now so we block
- until our script returns. */
- signal (SIGCHLD, NULL);
-
- pid = fork();
-
- if (pid == -1)
- eerrorx ("%s: fork: %s", service, strerror (errno));
- if (pid == 0)
- {
- mycmd = rc_xstrdup (service);
- myarg1 = rc_xstrdup (arg1);
- if (arg2)
- myarg2 = rc_xstrdup (arg2);
-
- if (rc_exists (RC_SVCDIR "runscript.sh"))
- {
- execl (RC_SVCDIR "runscript.sh", mycmd, mycmd, myarg1, myarg2,
- (char *) NULL);
- eerrorx ("%s: exec `" RC_SVCDIR "runscript.sh': %s",
- service, strerror (errno));
- }
- else
- {
- execl (RC_LIBDIR "sh/runscript.sh", mycmd, mycmd, myarg1, myarg2,
- (char *) NULL);
- eerrorx ("%s: exec `" RC_LIBDIR "sh/runscript.sh': %s",
- service, strerror (errno));
- }
- }
-
- do
- {
- if (waitpid (pid, &status, 0) < 0)
- {
- if (errno != ECHILD)
- eerror ("waitpid: %s", strerror (errno));
- break;
- }
- } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
-
- /* Done, so restore the signal handler */
- signal (SIGCHLD, handle_signal);
-
- if (WIFEXITED (status))
- return (WEXITSTATUS (status) ? false : true);
-
- return (false);
+ int status = 0;
+ pid_t pid;
+
+ /* We need to disable our child signal handler now so we block
+ until our script returns. */
+ signal (SIGCHLD, NULL);
+
+ pid = fork();
+
+ if (pid == -1)
+ eerrorx ("%s: fork: %s", service, strerror (errno));
+ if (pid == 0) {
+ mycmd = rc_xstrdup (service);
+ myarg1 = rc_xstrdup (arg1);
+ if (arg2)
+ myarg2 = rc_xstrdup (arg2);
+
+ if (rc_exists (RC_SVCDIR "runscript.sh")) {
+ execl (RC_SVCDIR "runscript.sh", mycmd, mycmd, myarg1, myarg2,
+ (char *) NULL);
+ eerrorx ("%s: exec `" RC_SVCDIR "runscript.sh': %s",
+ service, strerror (errno));
+ } else {
+ execl (RC_LIBDIR "sh/runscript.sh", mycmd, mycmd, myarg1, myarg2,
+ (char *) NULL);
+ eerrorx ("%s: exec `" RC_LIBDIR "sh/runscript.sh': %s",
+ service, strerror (errno));
+ }
+ }
+
+ do {
+ if (waitpid (pid, &status, 0) < 0) {
+ if (errno != ECHILD)
+ eerror ("waitpid: %s", strerror (errno));
+ break;
+ }
+ } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
+
+ /* Done, so restore the signal handler */
+ signal (SIGCHLD, handle_signal);
+
+ if (WIFEXITED (status))
+ return (WEXITSTATUS (status) ? false : true);
+
+ return (false);
}
static rc_service_state_t svc_status (const char *service)
{
- char status[10];
- int (*e) (const char *fmt, ...) = &einfo;
-
- rc_service_state_t retval = rc_service_stopped;
-
- if (rc_service_state (service, rc_service_stopping))
- {
- snprintf (status, sizeof (status), "stopping");
- e = &ewarn;
- retval = rc_service_stopping;
- }
- else if (rc_service_state (service, rc_service_starting))
- {
- snprintf (status, sizeof (status), "starting");
- e = &ewarn;
- retval = rc_service_starting;
- }
- else if (rc_service_state (service, rc_service_inactive))
- {
- snprintf (status, sizeof (status), "inactive");
- e = &ewarn;
- retval = rc_service_inactive;
- }
- else if (rc_service_state (service, rc_service_crashed))
- {
- snprintf (status, sizeof (status), "crashed");
- e = &eerror;
- retval = rc_service_crashed;
- }
- else if (rc_service_state (service, rc_service_started))
- {
- snprintf (status, sizeof (status), "started");
- retval = rc_service_started;
- }
- else
- snprintf (status, sizeof (status), "stopped");
-
- e ("status: %s", status);
- return (retval);
+ char status[10];
+ int (*e) (const char *fmt, ...) = &einfo;
+
+ rc_service_state_t retval = rc_service_stopped;
+
+ if (rc_service_state (service, rc_service_stopping)) {
+ snprintf (status, sizeof (status), "stopping");
+ e = &ewarn;
+ retval = rc_service_stopping;
+ } else if (rc_service_state (service, rc_service_starting)) {
+ snprintf (status, sizeof (status), "starting");
+ e = &ewarn;
+ retval = rc_service_starting;
+ } else if (rc_service_state (service, rc_service_inactive)) {
+ snprintf (status, sizeof (status), "inactive");
+ e = &ewarn;
+ retval = rc_service_inactive;
+ } else if (rc_service_state (service, rc_service_crashed)) {
+ snprintf (status, sizeof (status), "crashed");
+ e = &eerror;
+ retval = rc_service_crashed;
+ } else if (rc_service_state (service, rc_service_started)) {
+ snprintf (status, sizeof (status), "started");
+ retval = rc_service_started;
+ } else
+ snprintf (status, sizeof (status), "stopped");
+
+ e ("status: %s", status);
+ return (retval);
}
static void make_exclusive (const char *service)
{
- char *path;
- int i;
-
- /* We create a fifo so that other services can wait until we complete */
- if (! exclusive)
- exclusive = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL);
-
- if (mkfifo (exclusive, 0600) != 0 && errno != EEXIST &&
- (errno != EACCES || geteuid () == 0))
- eerrorx ("%s: unable to create fifo `%s': %s",
- applet, exclusive, strerror (errno));
-
- path = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL);
- i = strlen (path) + 16;
- mtime_test = rc_xmalloc (sizeof (char *) * i);
- snprintf (mtime_test, i, "%s.%d", path, getpid ());
- free (path);
-
- if (rc_exists (mtime_test) && unlink (mtime_test) != 0)
- {
- eerror ("%s: unlink `%s': %s",
- applet, mtime_test, strerror (errno));
- free (mtime_test);
- mtime_test = NULL;
- return;
- }
-
- if (symlink (service, mtime_test) != 0)
- {
- eerror ("%s: symlink `%s' to `%s': %s",
- applet, service, mtime_test, strerror (errno));
- free (mtime_test);
- mtime_test = NULL;
- }
+ char *path;
+ int i;
+
+ /* We create a fifo so that other services can wait until we complete */
+ if (! exclusive)
+ exclusive = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL);
+
+ if (mkfifo (exclusive, 0600) != 0 && errno != EEXIST &&
+ (errno != EACCES || geteuid () == 0))
+ eerrorx ("%s: unable to create fifo `%s': %s",
+ applet, exclusive, strerror (errno));
+
+ path = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL);
+ i = strlen (path) + 16;
+ mtime_test = rc_xmalloc (sizeof (char *) * i);
+ snprintf (mtime_test, i, "%s.%d", path, getpid ());
+ free (path);
+
+ if (rc_exists (mtime_test) && unlink (mtime_test) != 0) {
+ eerror ("%s: unlink `%s': %s",
+ applet, mtime_test, strerror (errno));
+ free (mtime_test);
+ mtime_test = NULL;
+ return;
+ }
+
+ if (symlink (service, mtime_test) != 0) {
+ eerror ("%s: symlink `%s' to `%s': %s",
+ applet, service, mtime_test, strerror (errno));
+ free (mtime_test);
+ mtime_test = NULL;
+ }
}
static void unlink_mtime_test ()
{
- if (unlink (mtime_test) != 0)
- eerror ("%s: unlink `%s': %s", applet, mtime_test, strerror (errno));
- free (mtime_test);
- mtime_test = NULL;
+ if (unlink (mtime_test) != 0)
+ eerror ("%s: unlink `%s': %s", applet, mtime_test, strerror (errno));
+ free (mtime_test);
+ mtime_test = NULL;
}
static void get_started_services ()
{
- char *service;
- int i;
+ char *service;
+ int i;
- rc_strlist_free (tmplist);
- tmplist = rc_services_in_state (rc_service_inactive);
+ rc_strlist_free (tmplist);
+ tmplist = rc_services_in_state (rc_service_inactive);
- rc_strlist_free (restart_services);
- restart_services = rc_services_in_state (rc_service_started);
+ rc_strlist_free (restart_services);
+ restart_services = rc_services_in_state (rc_service_started);
- STRLIST_FOREACH (tmplist, service, i)
- restart_services = rc_strlist_addsort (restart_services, service);
+ STRLIST_FOREACH (tmplist, service, i)
+ restart_services = rc_strlist_addsort (restart_services, service);
- rc_strlist_free (tmplist);
- tmplist = NULL;
+ rc_strlist_free (tmplist);
+ tmplist = NULL;
}
static void svc_start (const char *service, bool deps)
{
- bool started;
- bool background = false;
- char *svc;
- char *svc2;
- int i;
- int j;
- int depoptions = RC_DEP_TRACE;
-
- rc_plugin_run (rc_hook_service_start_in, applet);
- hook_out = rc_hook_service_start_out;
-
- if (rc_is_env ("RC_STRICT_DEPEND", "yes"))
- depoptions |= RC_DEP_STRICT;
-
- if (rc_is_env ("IN_HOTPLUG", "1") || in_background)
- {
- if (! rc_service_state (service, rc_service_inactive))
- exit (EXIT_FAILURE);
- background = true;
- }
-
- if (rc_service_state (service, rc_service_started))
- ewarnx ("WARNING: %s has already been started", applet);
- else if (rc_service_state (service, rc_service_starting))
- ewarnx ("WARNING: %s is already starting", applet);
- else if (rc_service_state (service, rc_service_stopping))
- ewarnx ("WARNING: %s is stopping", applet);
- else if (rc_service_state (service, rc_service_inactive) && ! background)
- ewarnx ("WARNING: %s has already started, but is inactive", applet);
-
- if (! rc_mark_service (service, rc_service_starting))
- eerrorx ("ERROR: %s has been started by something else", applet);
-
- make_exclusive (service);
-
- if (deps)
- {
- if (! deptree && ((deptree = rc_load_deptree ()) == NULL))
- eerrorx ("failed to load deptree");
-
- rc_strlist_free (types);
- types = rc_strlist_add (NULL, "broken");
- rc_strlist_free (svclist);
- svclist = rc_strlist_add (NULL, applet);
- rc_strlist_free (services);
- services = rc_get_depends (deptree, types, svclist, softlevel, 0);
- if (services)
- {
- eerrorn ("ERROR: `%s' needs ", applet);
- STRLIST_FOREACH (services, svc, i)
- {
- if (i > 0)
- fprintf (stderr, ", ");
- fprintf (stderr, "%s", svc);
- }
- exit (EXIT_FAILURE);
- }
- rc_strlist_free (services);
- services = NULL;
-
- rc_strlist_free (types);
- types = rc_strlist_add (NULL, "ineed");
- rc_strlist_free (need_services);
- need_services = rc_get_depends (deptree, types, svclist,
- softlevel, depoptions);
- types = rc_strlist_add (types, "iuse");
- if (! rc_runlevel_starting ())
- {
- services = rc_get_depends (deptree, types, svclist,
- softlevel, depoptions);
- STRLIST_FOREACH (services, svc, i)
- if (rc_service_state (svc, rc_service_stopped))
- rc_start_service (svc);
-
- rc_strlist_free (services);
- }
-
- /* Now wait for them to start */
- types = rc_strlist_add (types, "iafter");
- services = rc_get_depends (deptree, types, svclist,
- softlevel, depoptions);
-
- /* We use tmplist to hold our scheduled by list */
- rc_strlist_free (tmplist);
- tmplist = NULL;
-
- STRLIST_FOREACH (services, svc, i)
- {
- if (rc_service_state (svc, rc_service_started))
- continue;
- if (! rc_wait_service (svc))
- eerror ("%s: timed out waiting for %s", applet, svc);
- if (rc_service_state (svc, rc_service_started))
- continue;
-
- STRLIST_FOREACH (need_services, svc2, j)
- if (strcmp (svc, svc2) == 0)
- {
- if (rc_service_state (svc, rc_service_inactive) ||
- rc_service_state (svc, rc_service_wasinactive))
- tmplist = rc_strlist_add (tmplist, svc);
- else
- eerrorx ("ERROR: cannot start %s as %s would not start",
- applet, svc);
- }
- }
-
- if (tmplist)
- {
- int n = 0;
- int len = 0;
- char *p;
-
- /* Set the state now, then unlink our exclusive so that
- our scheduled list is preserved */
- rc_mark_service (service, rc_service_stopped);
- unlink_mtime_test ();
-
- rc_strlist_free (types);
- types = rc_strlist_add (NULL, "iprovide");
- STRLIST_FOREACH (tmplist, svc, i)
- {
- rc_schedule_start_service (svc, service);
-
- rc_strlist_free (svclist);
- svclist = rc_strlist_add (NULL, svc);
- rc_strlist_free (providelist);
- providelist = rc_get_depends (deptree, types, svclist,
- softlevel, depoptions);
- STRLIST_FOREACH (providelist, svc2, j)
- rc_schedule_start_service (svc2, service);
-
- len += strlen (svc) + 2;
- n++;
- }
-
- len += 5;
- tmp = rc_xmalloc (sizeof (char *) * len);
- p = tmp;
- STRLIST_FOREACH (tmplist, svc, i)
- {
- if (i > 1)
- {
- if (i == n - 1)
- p += snprintf (p, len, " or ");
- else
- p += snprintf (p, len, ", ");
- }
- p += snprintf (p, len, "%s", svc);
- }
- ewarnx ("WARNING: %s is scheduled to start when %s has started",
- applet, tmp);
- }
-
- rc_strlist_free (services);
- services = NULL;
- rc_strlist_free (types);
- types = NULL;
- rc_strlist_free (svclist);
- svclist = NULL;
- }
-
- if (ibsave)
- setenv ("IN_BACKGROUND", ibsave, 1);
- rc_plugin_run (rc_hook_service_start_now, applet);
- started = svc_exec (service, "start", NULL);
- if (ibsave)
- unsetenv ("IN_BACKGROUND");
-
- if (in_control ())
- {
- if (! started)
- {
- if (rc_service_state (service, rc_service_wasinactive))
- rc_mark_service (service, rc_service_inactive);
- else
- {
- rc_mark_service (service, rc_service_stopped);
- if (rc_runlevel_starting ())
- rc_mark_service (service, rc_service_failed);
- }
- rc_plugin_run (rc_hook_service_start_done, applet);
- eerrorx ("ERROR: %s failed to start", applet);
- }
- rc_mark_service (service, rc_service_started);
- unlink_mtime_test ();
- rc_plugin_run (rc_hook_service_start_done, applet);
- }
- else
- {
- rc_plugin_run (rc_hook_service_start_done, applet);
- if (rc_service_state (service, rc_service_inactive))
- ewarnx ("WARNING: %s has started, but is inactive", applet);
- else
- ewarnx ("WARNING: %s not under our control, aborting", applet);
- }
-
- /* Now start any scheduled services */
- rc_strlist_free (services);
- services = rc_services_scheduled (service);
- STRLIST_FOREACH (services, svc, i)
- if (rc_service_state (svc, rc_service_stopped))
- rc_start_service (svc);
- rc_strlist_free (services);
- services = NULL;
-
- /* Do the same for any services we provide */
- rc_strlist_free (types);
- types = rc_strlist_add (NULL, "iprovide");
- rc_strlist_free (svclist);
- svclist = rc_strlist_add (NULL, applet);
- rc_strlist_free (tmplist);
- tmplist = rc_get_depends (deptree, types, svclist, softlevel, depoptions);
-
- STRLIST_FOREACH (tmplist, svc2, j)
- {
- rc_strlist_free (services);
- services = rc_services_scheduled (svc2);
- STRLIST_FOREACH (services, svc, i)
- if (rc_service_state (svc, rc_service_stopped))
- rc_start_service (svc);
- }
-
- hook_out = 0;
- rc_plugin_run (rc_hook_service_start_out, applet);
+ bool started;
+ bool background = false;
+ char *svc;
+ char *svc2;
+ int i;
+ int j;
+ int depoptions = RC_DEP_TRACE;
+
+ rc_plugin_run (rc_hook_service_start_in, applet);
+ hook_out = rc_hook_service_start_out;
+
+ if (rc_is_env ("RC_STRICT_DEPEND", "yes"))
+ depoptions |= RC_DEP_STRICT;
+
+ if (rc_is_env ("IN_HOTPLUG", "1") || in_background) {
+ if (! rc_service_state (service, rc_service_inactive))
+ exit (EXIT_FAILURE);
+ background = true;
+ }
+
+ if (rc_service_state (service, rc_service_started))
+ ewarnx ("WARNING: %s has already been started", applet);
+ else if (rc_service_state (service, rc_service_starting))
+ ewarnx ("WARNING: %s is already starting", applet);
+ else if (rc_service_state (service, rc_service_stopping))
+ ewarnx ("WARNING: %s is stopping", applet);
+ else if (rc_service_state (service, rc_service_inactive) && ! background)
+ ewarnx ("WARNING: %s has already started, but is inactive", applet);
+
+ if (! rc_mark_service (service, rc_service_starting))
+ eerrorx ("ERROR: %s has been started by something else", applet);
+
+ make_exclusive (service);
+
+ if (deps) {
+ if (! deptree && ((deptree = rc_load_deptree ()) == NULL))
+ eerrorx ("failed to load deptree");
+
+ rc_strlist_free (types);
+ types = rc_strlist_add (NULL, "broken");
+ rc_strlist_free (svclist);
+ svclist = rc_strlist_add (NULL, applet);
+ rc_strlist_free (services);
+ services = rc_get_depends (deptree, types, svclist, softlevel, 0);
+ if (services) {
+ eerrorn ("ERROR: `%s' needs ", applet);
+ STRLIST_FOREACH (services, svc, i) {
+ if (i > 0)
+ fprintf (stderr, ", ");
+ fprintf (stderr, "%s", svc);
+ }
+ exit (EXIT_FAILURE);
+ }
+ rc_strlist_free (services);
+ services = NULL;
+
+ rc_strlist_free (types);
+ types = rc_strlist_add (NULL, "ineed");
+ rc_strlist_free (need_services);
+ need_services = rc_get_depends (deptree, types, svclist,
+ softlevel, depoptions);
+ types = rc_strlist_add (types, "iuse");
+ if (! rc_runlevel_starting ()) {
+ services = rc_get_depends (deptree, types, svclist,
+ softlevel, depoptions);
+ STRLIST_FOREACH (services, svc, i)
+ if (rc_service_state (svc, rc_service_stopped))
+ rc_start_service (svc);
+
+ rc_strlist_free (services);
+ }
+
+ /* Now wait for them to start */
+ types = rc_strlist_add (types, "iafter");
+ services = rc_get_depends (deptree, types, svclist,
+ softlevel, depoptions);
+
+ /* We use tmplist to hold our scheduled by list */
+ rc_strlist_free (tmplist);
+ tmplist = NULL;
+
+ STRLIST_FOREACH (services, svc, i) {
+ if (rc_service_state (svc, rc_service_started))
+ continue;
+ if (! rc_wait_service (svc))
+ eerror ("%s: timed out waiting for %s", applet, svc);
+ if (rc_service_state (svc, rc_service_started))
+ continue;
+
+ STRLIST_FOREACH (need_services, svc2, j)
+ if (strcmp (svc, svc2) == 0) {
+ if (rc_service_state (svc, rc_service_inactive) ||
+ rc_service_state (svc, rc_service_wasinactive))
+ tmplist = rc_strlist_add (tmplist, svc);
+ else
+ eerrorx ("ERROR: cannot start %s as %s would not start",
+ applet, svc);
+ }
+ }
+
+ if (tmplist) {
+ int n = 0;
+ int len = 0;
+ char *p;
+
+ /* Set the state now, then unlink our exclusive so that
+ our scheduled list is preserved */
+ rc_mark_service (service, rc_service_stopped);
+ unlink_mtime_test ();
+
+ rc_strlist_free (types);
+ types = rc_strlist_add (NULL, "iprovide");
+ STRLIST_FOREACH (tmplist, svc, i) {
+ rc_schedule_start_service (svc, service);
+
+ rc_strlist_free (svclist);
+ svclist = rc_strlist_add (NULL, svc);
+ rc_strlist_free (providelist);
+ providelist = rc_get_depends (deptree, types, svclist,
+ softlevel, depoptions);
+ STRLIST_FOREACH (providelist, svc2, j)
+ rc_schedule_start_service (svc2, service);
+
+ len += strlen (svc) + 2;
+ n++;
+ }
+
+ len += 5;
+ tmp = rc_xmalloc (sizeof (char *) * len);
+ p = tmp;
+ STRLIST_FOREACH (tmplist, svc, i) {
+ if (i > 1) {
+ if (i == n - 1)
+ p += snprintf (p, len, " or ");
+ else
+ p += snprintf (p, len, ", ");
+ }
+ p += snprintf (p, len, "%s", svc);
+ }
+ ewarnx ("WARNING: %s is scheduled to start when %s has started",
+ applet, tmp);
+ }
+
+ rc_strlist_free (services);
+ services = NULL;
+ rc_strlist_free (types);
+ types = NULL;
+ rc_strlist_free (svclist);
+ svclist = NULL;
+ }
+
+ if (ibsave)
+ setenv ("IN_BACKGROUND", ibsave, 1);
+ rc_plugin_run (rc_hook_service_start_now, applet);
+ started = svc_exec (service, "start", NULL);
+ if (ibsave)
+ unsetenv ("IN_BACKGROUND");
+
+ if (in_control ()) {
+ if (! started) {
+ if (rc_service_state (service, rc_service_wasinactive))
+ rc_mark_service (service, rc_service_inactive);
+ else {
+ rc_mark_service (service, rc_service_stopped);
+ if (rc_runlevel_starting ())
+ rc_mark_service (service, rc_service_failed);
+ }
+ rc_plugin_run (rc_hook_service_start_done, applet);
+ eerrorx ("ERROR: %s failed to start", applet);
+ }
+ rc_mark_service (service, rc_service_started);
+ unlink_mtime_test ();
+ rc_plugin_run (rc_hook_service_start_done, applet);
+ } else {
+ rc_plugin_run (rc_hook_service_start_done, applet);
+ if (rc_service_state (service, rc_service_inactive))
+ ewarnx ("WARNING: %s has started, but is inactive", applet);
+ else
+ ewarnx ("WARNING: %s not under our control, aborting", applet);
+ }
+
+ /* Now start any scheduled services */
+ rc_strlist_free (services);
+ services = rc_services_scheduled (service);
+ STRLIST_FOREACH (services, svc, i)
+ if (rc_service_state (svc, rc_service_stopped))
+ rc_start_service (svc);
+ rc_strlist_free (services);
+ services = NULL;
+
+ /* Do the same for any services we provide */
+ rc_strlist_free (types);
+ types = rc_strlist_add (NULL, "iprovide");
+ rc_strlist_free (svclist);
+ svclist = rc_strlist_add (NULL, applet);
+ rc_strlist_free (tmplist);
+ tmplist = rc_get_depends (deptree, types, svclist, softlevel, depoptions);
+
+ STRLIST_FOREACH (tmplist, svc2, j) {
+ rc_strlist_free (services);
+ services = rc_services_scheduled (svc2);
+ STRLIST_FOREACH (services, svc, i)
+ if (rc_service_state (svc, rc_service_stopped))
+ rc_start_service (svc);
+ }
+
+ hook_out = 0;
+ rc_plugin_run (rc_hook_service_start_out, applet);
}
static void svc_stop (const char *service, bool deps)
{
- bool stopped;
-
- hook_out = rc_hook_service_stop_out;
-
- if (rc_runlevel_stopping () &&
- rc_service_state (service, rc_service_failed))
- exit (EXIT_FAILURE);
-
- if (rc_is_env ("IN_HOTPLUG", "1") || in_background)
- if (! rc_service_state (service, rc_service_started))
- exit (EXIT_FAILURE);
-
- if (rc_service_state (service, rc_service_stopped))
- ewarnx ("WARNING: %s is already stopped", applet);
- else if (rc_service_state (service, rc_service_stopping))
- ewarnx ("WARNING: %s is already stopping", applet);
-
- if (! rc_mark_service (service, rc_service_stopping))
- eerrorx ("ERROR: %s has been stopped by something else", applet);
-
- make_exclusive (service);
-
- if (! rc_runlevel_stopping () &&
- rc_service_in_runlevel (service, RC_LEVEL_BOOT))
- ewarn ("WARNING: you are stopping a boot service");
-
- if (deps || ! rc_service_state (service, rc_service_wasinactive))
- {
- int depoptions = RC_DEP_TRACE;
- char *svc;
- int i;
-
- if (rc_is_env ("RC_STRICT_DEPEND", "yes"))
- depoptions |= RC_DEP_STRICT;
-
- if (! deptree && ((deptree = rc_load_deptree ()) == NULL))
- eerrorx ("failed to load deptree");
-
- rc_strlist_free (types);
- types = rc_strlist_add (NULL, "needsme");
- rc_strlist_free (svclist);
- svclist = rc_strlist_add (NULL, applet);
- rc_strlist_free (tmplist);
- tmplist = NULL;
- rc_strlist_free (services);
- services = rc_get_depends (deptree, types, svclist,
- softlevel, depoptions);
- rc_strlist_reverse (services);
- STRLIST_FOREACH (services, svc, i)
- {
- if (rc_service_state (svc, rc_service_started) ||
- rc_service_state (svc, rc_service_inactive))
- {
- rc_wait_service (svc);
- if (rc_service_state (svc, rc_service_started) ||
- rc_service_state (svc, rc_service_inactive))
- {
- rc_stop_service (svc);
- tmplist = rc_strlist_add (tmplist, svc);
- }
- }
- }
- rc_strlist_free (services);
- services = NULL;
-
- STRLIST_FOREACH (tmplist, svc, i)
- {
- if (rc_service_state (svc, rc_service_stopped))
- continue;
-
- /* We used to loop 3 times here - maybe re-do this if needed */
- rc_wait_service (svc);
- if (! rc_service_state (svc, rc_service_stopped))
- {
- if (rc_runlevel_stopping ())
- rc_mark_service (svc, rc_service_failed);
- eerrorx ("ERROR: cannot stop %s as %s is still up",
- applet, svc);
- }
- }
- rc_strlist_free (tmplist);
- tmplist = NULL;
-
- /* We now wait for other services that may use us and are stopping
- This is important when a runlevel stops */
- types = rc_strlist_add (types, "usesme");
- types = rc_strlist_add (types, "ibefore");
- services = rc_get_depends (deptree, types, svclist,
- softlevel, depoptions);
- STRLIST_FOREACH (services, svc, i)
- {
- if (rc_service_state (svc, rc_service_stopped))
- continue;
- rc_wait_service (svc);
- }
-
- rc_strlist_free (services);
- services = NULL;
- rc_strlist_free (types);
- types = NULL;
- }
-
- if (ibsave)
- setenv ("IN_BACKGROUND", ibsave, 1);
- rc_plugin_run (rc_hook_service_stop_now, applet);
- stopped = svc_exec (service, "stop", NULL);
- if (ibsave)
- unsetenv ("IN_BACKGROUND");
-
- if (! in_control ())
- {
- rc_plugin_run (rc_hook_service_stop_done, applet);
- ewarnx ("WARNING: %s not under our control, aborting", applet);
- }
-
- if (! stopped)
- {
- if (rc_service_state (service, rc_service_wasinactive))
- rc_mark_service (service, rc_service_inactive);
- else
- rc_mark_service (service, rc_service_started);
- rc_plugin_run (rc_hook_service_stop_done, applet);
- eerrorx ("ERROR: %s failed to stop", applet);
- }
-
- if (in_background)
- rc_mark_service (service, rc_service_inactive);
- else
- rc_mark_service (service, rc_service_stopped);
-
- unlink_mtime_test ();
- rc_plugin_run (rc_hook_service_stop_done, applet);
- hook_out = 0;
- rc_plugin_run (rc_hook_service_stop_out, applet);
+ bool stopped;
+
+ hook_out = rc_hook_service_stop_out;
+
+ if (rc_runlevel_stopping () &&
+ rc_service_state (service, rc_service_failed))
+ exit (EXIT_FAILURE);
+
+ if (rc_is_env ("IN_HOTPLUG", "1") || in_background)
+ if (! rc_service_state (service, rc_service_started))
+ exit (EXIT_FAILURE);
+
+ if (rc_service_state (service, rc_service_stopped))
+ ewarnx ("WARNING: %s is already stopped", applet);
+ else if (rc_service_state (service, rc_service_stopping))
+ ewarnx ("WARNING: %s is already stopping", applet);
+
+ if (! rc_mark_service (service, rc_service_stopping))
+ eerrorx ("ERROR: %s has been stopped by something else", applet);
+
+ make_exclusive (service);
+
+ if (! rc_runlevel_stopping () &&
+ rc_service_in_runlevel (service, RC_LEVEL_BOOT))
+ ewarn ("WARNING: you are stopping a boot service");
+
+ if (deps || ! rc_service_state (service, rc_service_wasinactive)) {
+ int depoptions = RC_DEP_TRACE;
+ char *svc;
+ int i;
+
+ if (rc_is_env ("RC_STRICT_DEPEND", "yes"))
+ depoptions |= RC_DEP_STRICT;
+
+ if (! deptree && ((deptree = rc_load_deptree ()) == NULL))
+ eerrorx ("failed to load deptree");
+
+ rc_strlist_free (types);
+ types = rc_strlist_add (NULL, "needsme");
+ rc_strlist_free (svclist);
+ svclist = rc_strlist_add (NULL, applet);
+ rc_strlist_free (tmplist);
+ tmplist = NULL;
+ rc_strlist_free (services);
+ services = rc_get_depends (deptree, types, svclist,
+ softlevel, depoptions);
+ rc_strlist_reverse (services);
+ STRLIST_FOREACH (services, svc, i) {
+ if (rc_service_state (svc, rc_service_started) ||
+ rc_service_state (svc, rc_service_inactive))
+ {
+ rc_wait_service (svc);
+ if (rc_service_state (svc, rc_service_started) ||
+ rc_service_state (svc, rc_service_inactive))
+ {
+ rc_stop_service (svc);
+ tmplist = rc_strlist_add (tmplist, svc);
+ }
+ }
+ }
+ rc_strlist_free (services);
+ services = NULL;
+
+ STRLIST_FOREACH (tmplist, svc, i) {
+ if (rc_service_state (svc, rc_service_stopped))
+ continue;
+
+ /* We used to loop 3 times here - maybe re-do this if needed */
+ rc_wait_service (svc);
+ if (! rc_service_state (svc, rc_service_stopped)) {
+ if (rc_runlevel_stopping ())
+ rc_mark_service (svc, rc_service_failed);
+ eerrorx ("ERROR: cannot stop %s as %s is still up",
+ applet, svc);
+ }
+ }
+ rc_strlist_free (tmplist);
+ tmplist = NULL;
+
+ /* We now wait for other services that may use us and are stopping
+ This is important when a runlevel stops */
+ types = rc_strlist_add (types, "usesme");
+ types = rc_strlist_add (types, "ibefore");
+ services = rc_get_depends (deptree, types, svclist,
+ softlevel, depoptions);
+ STRLIST_FOREACH (services, svc, i) {
+ if (rc_service_state (svc, rc_service_stopped))
+ continue;
+ rc_wait_service (svc);
+ }
+
+ rc_strlist_free (services);
+ services = NULL;
+ rc_strlist_free (types);
+ types = NULL;
+ }
+
+ if (ibsave)
+ setenv ("IN_BACKGROUND", ibsave, 1);
+ rc_plugin_run (rc_hook_service_stop_now, applet);
+ stopped = svc_exec (service, "stop", NULL);
+ if (ibsave)
+ unsetenv ("IN_BACKGROUND");
+
+ if (! in_control ()) {
+ rc_plugin_run (rc_hook_service_stop_done, applet);
+ ewarnx ("WARNING: %s not under our control, aborting", applet);
+ }
+
+ if (! stopped) {
+ if (rc_service_state (service, rc_service_wasinactive))
+ rc_mark_service (service, rc_service_inactive);
+ else
+ rc_mark_service (service, rc_service_started);
+ rc_plugin_run (rc_hook_service_stop_done, applet);
+ eerrorx ("ERROR: %s failed to stop", applet);
+ }
+
+ if (in_background)
+ rc_mark_service (service, rc_service_inactive);
+ else
+ rc_mark_service (service, rc_service_stopped);
+
+ unlink_mtime_test ();
+ rc_plugin_run (rc_hook_service_stop_done, applet);
+ hook_out = 0;
+ rc_plugin_run (rc_hook_service_stop_out, applet);
}
static void svc_restart (const char *service, bool deps)
{
- char *svc;
- int i;
- bool inactive = false;
-
- /* This is hairly and a better way needs to be found I think!
- The issue is this - openvpn need net and dns. net can restart
- dns via resolvconf, so you could have openvpn trying to restart dnsmasq
- which in turn is waiting on net which in turn is waiting on dnsmasq.
- The work around is for resolvconf to restart it's services with --nodeps
- which means just that. The downside is that there is a small window when
- our status is invalid.
- One workaround would be to introduce a new status, or status locking. */
- if (! deps)
- {
- if (rc_service_state (service, rc_service_started) ||
- rc_service_state (service, rc_service_inactive))
- svc_exec (service, "stop", "start");
- else
- svc_exec (service, "start", NULL);
- return;
- }
-
- if (! rc_service_state (service, rc_service_stopped))
- {
- get_started_services ();
- svc_stop (service, deps);
-
- /* Flush our buffered output if any */
- eflush ();
- }
-
- svc_start (service, deps);
-
- inactive = rc_service_state (service, rc_service_inactive);
- if (! inactive)
- inactive = rc_service_state (service, rc_service_wasinactive);
-
- if (inactive ||
- rc_service_state (service, rc_service_starting) ||
- rc_service_state (service, rc_service_started))
- {
- STRLIST_FOREACH (restart_services, svc, i)
- {
- if (rc_service_state (svc, rc_service_stopped))
- {
- if (inactive)
- {
- rc_schedule_start_service (service, svc);
- ewarn ("WARNING: %s is scheduled to started when %s has started",
- svc, basename (service));
- }
- else
- rc_start_service (svc);
- }
- }
- }
+ char *svc;
+ int i;
+ bool inactive = false;
+
+ /* This is hairly and a better way needs to be found I think!
+ The issue is this - openvpn need net and dns. net can restart
+ dns via resolvconf, so you could have openvpn trying to restart dnsmasq
+ which in turn is waiting on net which in turn is waiting on dnsmasq.
+ The work around is for resolvconf to restart it's services with --nodeps
+ which means just that. The downside is that there is a small window when
+ our status is invalid.
+ One workaround would be to introduce a new status, or status locking. */
+ if (! deps) {
+ if (rc_service_state (service, rc_service_started) ||
+ rc_service_state (service, rc_service_inactive))
+ svc_exec (service, "stop", "start");
+ else
+ svc_exec (service, "start", NULL);
+ return;
+ }
+
+ if (! rc_service_state (service, rc_service_stopped)) {
+ get_started_services ();
+ svc_stop (service, deps);
+
+ /* Flush our buffered output if any */
+ eflush ();
+ }
+
+ svc_start (service, deps);
+
+ inactive = rc_service_state (service, rc_service_inactive);
+ if (! inactive)
+ inactive = rc_service_state (service, rc_service_wasinactive);
+
+ if (inactive ||
+ rc_service_state (service, rc_service_starting) ||
+ rc_service_state (service, rc_service_started))
+ {
+ STRLIST_FOREACH (restart_services, svc, i) {
+ if (rc_service_state (svc, rc_service_stopped)) {
+ if (inactive) {
+ rc_schedule_start_service (service, svc);
+ ewarn ("WARNING: %s is scheduled to started when %s has started",
+ svc, basename (service));
+ } else
+ rc_start_service (svc);
+ }
+ }
+ }
}
int main (int argc, char **argv)
{
- const char *service = argv[1];
- int i;
- bool deps = true;
- bool doneone = false;
- char pid[16];
- int retval;
- bool ifstarted = false;
-
- applet = strdup (basename (service));
- atexit (cleanup);
-
- /* Show help if insufficient args */
- if (argc < 3)
- {
- execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
- eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
- applet, strerror (errno));
- }
+ const char *service = argv[1];
+ int i;
+ bool deps = true;
+ bool doneone = false;
+ char pid[16];
+ int retval;
+ bool ifstarted = false;
+
+ applet = strdup (basename (service));
+ atexit (cleanup);
+
+ /* Show help if insufficient args */
+ if (argc < 3) {
+ execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
+ eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
+ applet, strerror (errno));
+ }
#ifdef __linux__
- /* coldplug events can trigger init scripts, but we don't want to run them
- until after rc sysinit has completed so we punt them to the boot runlevel */
- if (rc_exists ("/dev/.rcsysinit"))
- {
- eerror ("%s: cannot run until sysvinit completes", applet);
- if (mkdir ("/dev/.rcboot", 0755) != 0 && errno != EEXIST)
- eerrorx ("%s: mkdir `/dev/.rcboot': %s", applet, strerror (errno));
- tmp = rc_strcatpaths ("/dev/.rcboot", applet, (char *) NULL);
- symlink (service, tmp);
- exit (EXIT_FAILURE);
- }
+ /* coldplug events can trigger init scripts, but we don't want to run them
+ until after rc sysinit has completed so we punt them to the boot runlevel */
+ if (rc_exists ("/dev/.rcsysinit")) {
+ eerror ("%s: cannot run until sysvinit completes", applet);
+ if (mkdir ("/dev/.rcboot", 0755) != 0 && errno != EEXIST)
+ eerrorx ("%s: mkdir `/dev/.rcboot': %s", applet, strerror (errno));
+ tmp = rc_strcatpaths ("/dev/.rcboot", applet, (char *) NULL);
+ symlink (service, tmp);
+ exit (EXIT_FAILURE);
+ }
#endif
- if ((softlevel = getenv ("RC_SOFTLEVEL")) == NULL)
- {
- /* Ensure our environment is pure
- Also, add our configuration to it */
- env = rc_filter_env ();
- env = rc_config_env (env);
+ if ((softlevel = getenv ("RC_SOFTLEVEL")) == NULL) {
+ /* Ensure our environment is pure
+ Also, add our configuration to it */
+ env = rc_filter_env ();
+ env = rc_config_env (env);
- if (env)
- {
- char *p;
+ if (env) {
+ char *p;
#ifdef __linux__
- /* clearenv isn't portable, but there's no harm in using it
- if we have it */
- clearenv ();
+ /* clearenv isn't portable, but there's no harm in using it
+ if we have it */
+ clearenv ();
#else
- char *var;
- /* No clearenv present here then.
- We could manipulate environ directly ourselves, but it seems that
- some kernels bitch about this according to the environ man pages
- so we walk though environ and call unsetenv for each value. */
- while (environ[0])
- {
- tmp = rc_xstrdup (environ[0]);
- p = tmp;
- var = strsep (&p, "=");
- unsetenv (var);
- free (tmp);
- }
- tmp = NULL;
+ char *var;
+ /* No clearenv present here then.
+ We could manipulate environ directly ourselves, but it seems that
+ some kernels bitch about this according to the environ man pages
+ so we walk though environ and call unsetenv for each value. */
+ while (environ[0]) {
+ tmp = rc_xstrdup (environ[0]);
+ p = tmp;
+ var = strsep (&p, "=");
+ unsetenv (var);
+ free (tmp);
+ }
+ tmp = NULL;
#endif
- STRLIST_FOREACH (env, p, i)
- putenv (p);
+ STRLIST_FOREACH (env, p, i)
+ putenv (p);
- /* We don't free our list as that would be null in environ */
- }
+ /* We don't free our list as that would be null in environ */
+ }
- softlevel = rc_get_runlevel ();
+ softlevel = rc_get_runlevel ();
- /* If not called from RC or another service then don't be parallel */
- unsetenv ("RC_PARALLEL_STARTUP");
- }
+ /* If not called from RC or another service then don't be parallel */
+ unsetenv ("RC_PARALLEL_STARTUP");
+ }
- setenv ("RC_ELOG", service, 1);
- setenv ("SVCNAME", applet, 1);
+ setenv ("RC_ELOG", service, 1);
+ setenv ("SVCNAME", applet, 1);
- /* Set an env var so that we always know our pid regardless of any
- subshells the init script may create so that our mark_service_*
- functions can always instruct us of this change */
- snprintf (pid, sizeof (pid), "%d", (int) getpid ());
- setenv ("RC_RUNSCRIPT_PID", pid, 1);
+ /* Set an env var so that we always know our pid regardless of any
+ subshells the init script may create so that our mark_service_*
+ functions can always instruct us of this change */
+ snprintf (pid, sizeof (pid), "%d", (int) getpid ());
+ setenv ("RC_RUNSCRIPT_PID", pid, 1);
- if (rc_is_env ("RC_PARALLEL_STARTUP", "yes"))
- {
- char ebname[PATH_MAX];
- char *eb;
+ if (rc_is_env ("RC_PARALLEL_STARTUP", "yes")) {
+ char ebname[PATH_MAX];
+ char *eb;
- snprintf (ebname, sizeof (ebname), "%s.%s", applet, pid);
- eb = rc_strcatpaths (RC_SVCDIR "ebuffer", ebname, (char *) NULL);
- setenv ("RC_EBUFFER", eb, 1);
- free (eb);
- }
+ snprintf (ebname, sizeof (ebname), "%s.%s", applet, pid);
+ eb = rc_strcatpaths (RC_SVCDIR "ebuffer", ebname, (char *) NULL);
+ setenv ("RC_EBUFFER", eb, 1);
+ free (eb);
+ }
- /* Save the IN_BACKGROUND env flag so it's ONLY passed to the service
- that is being called and not any dependents */
- if (getenv ("IN_BACKGROUND"))
- {
- in_background = rc_is_env ("IN_BACKGROUND", "true");
- ibsave = strdup (getenv ("IN_BACKGROUND"));
- unsetenv ("IN_BACKGROUND");
- }
+ /* Save the IN_BACKGROUND env flag so it's ONLY passed to the service
+ that is being called and not any dependents */
+ if (getenv ("IN_BACKGROUND")) {
+ in_background = rc_is_env ("IN_BACKGROUND", "true");
+ ibsave = strdup (getenv ("IN_BACKGROUND"));
+ unsetenv ("IN_BACKGROUND");
+ }
#ifdef __linux__
- /* Ok, we are ready to go, so setup selinux if applicable */
- setup_selinux (argc, argv);
+ /* Ok, we are ready to go, so setup selinux if applicable */
+ setup_selinux (argc, argv);
#endif
- /* Right then, parse any options there may be */
- for (i = 2; i < argc; i++)
- {
- if (strlen (argv[i]) < 2 || argv[i][0] != '-' || argv[i][1] != '-')
- continue;
-
- if (strcmp (argv[i], "--debug") == 0)
- setenv ("RC_DEBUG", "yes", 1);
- else if (strcmp (argv[i], "--help") == 0)
- {
- execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
- eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
- applet, strerror (errno));
- }
- else if (strcmp (argv[i],"--ifstarted") == 0)
- ifstarted = true;
- else if (strcmp (argv[i], "--nocolour") == 0 ||
- strcmp (argv[i], "--nocolor") == 0)
- setenv ("RC_NOCOLOR", "yes", 1);
- else if (strcmp (argv[i], "--nodeps") == 0)
- deps = false;
- else if (strcmp (argv[i], "--quiet") == 0)
- setenv ("RC_QUIET", "yes", 1);
- else if (strcmp (argv[i], "--verbose") == 0)
- setenv ("RC_VERBOSE", "yes", 1);
- else if (strcmp (argv[i], "--version") == 0)
- printf ("version me\n");
- else
- eerror ("%s: unknown option `%s'", applet, argv[i]);
- }
-
- if (ifstarted && ! rc_service_state (applet, rc_service_started))
- {
- if (! rc_is_env("RC_QUIET", "yes"))
- eerror ("ERROR: %s is not started", applet);
- exit (EXIT_FAILURE);
- }
-
- if (rc_is_env ("IN_HOTPLUG", "1"))
- {
- if (! rc_is_env ("RC_HOTPLUG", "yes") || ! rc_allow_plug (applet))
- eerrorx ("%s: not allowed to be hotplugged", applet);
- }
-
- /* Setup a signal handler */
- signal (SIGHUP, handle_signal);
- signal (SIGINT, handle_signal);
- signal (SIGQUIT, handle_signal);
- signal (SIGTERM, handle_signal);
- signal (SIGCHLD, handle_signal);
-
- /* Load our plugins */
- rc_plugin_load ();
-
- /* Now run each option */
- retval = EXIT_SUCCESS;
- for (i = 2; i < argc; i++)
- {
- /* Abort on a sighup here */
- if (sighup)
- exit (EXIT_FAILURE);
-
- if (strlen (argv[i]) < 2 ||
- (argv[i][0] == '-' && argv[i][1] == '-'))
- continue;
-
- /* Export the command we're running.
- This is important as we stamp on the restart function now but
- some start/stop routines still need to behave differently if
- restarting. */
- unsetenv ("RC_CMD");
- setenv ("RC_CMD", argv[i], 1);
-
- doneone = true;
- if (strcmp (argv[i], "conditionalrestart") == 0 ||
- strcmp (argv[i], "condrestart") == 0)
- {
- if (rc_service_state (service, rc_service_started))
- svc_restart (service, deps);
- }
- else if (strcmp (argv[i], "restart") == 0)
- svc_restart (service, deps);
- else if (strcmp (argv[i], "start") == 0)
- svc_start (service, deps);
- else if (strcmp (argv[i], "status") == 0)
- {
- rc_service_state_t r = svc_status (service);
- retval = (int) r;
- }
- else if (strcmp (argv[i], "stop") == 0)
- {
- if (in_background)
- get_started_services ();
-
- svc_stop (service, deps);
-
- if (! in_background &&
- ! rc_runlevel_stopping () &&
- rc_service_state (service, rc_service_stopped))
- uncoldplug (applet);
-
- if (in_background &&
- rc_service_state (service, rc_service_inactive))
- {
- char *svc;
- int j;
- STRLIST_FOREACH (restart_services, svc, j)
- if (rc_service_state (svc, rc_service_stopped))
- rc_schedule_start_service (service, svc);
- }
- }
- else if (strcmp (argv[i], "zap") == 0)
- {
- einfo ("Manually resetting %s to stopped state", applet);
- rc_mark_service (applet, rc_service_stopped);
- uncoldplug (applet);
- }
- else if (strcmp (argv[i], "help") == 0)
- {
- execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, "help", (char *) NULL);
- eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
- applet, strerror (errno));
- }
- else
- svc_exec (service, argv[i], NULL);
-
- /* Flush our buffered output if any */
- eflush ();
-
- /* We should ensure this list is empty after an action is done */
- rc_strlist_free (restart_services);
- restart_services = NULL;
- }
-
- if (! doneone)
- {
- execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
- eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
- applet, strerror (errno));
- }
-
- return (retval);
+ /* Right then, parse any options there may be */
+ for (i = 2; i < argc; i++) {
+ if (strlen (argv[i]) < 2 || argv[i][0] != '-' || argv[i][1] != '-')
+ continue;
+
+ if (strcmp (argv[i], "--debug") == 0)
+ setenv ("RC_DEBUG", "yes", 1);
+ else if (strcmp (argv[i], "--help") == 0) {
+ execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
+ eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
+ applet, strerror (errno));
+ } else if (strcmp (argv[i],"--ifstarted") == 0)
+ ifstarted = true;
+ else if (strcmp (argv[i], "--nocolour") == 0 ||
+ strcmp (argv[i], "--nocolor") == 0)
+ setenv ("RC_NOCOLOR", "yes", 1);
+ else if (strcmp (argv[i], "--nodeps") == 0)
+ deps = false;
+ else if (strcmp (argv[i], "--quiet") == 0)
+ setenv ("RC_QUIET", "yes", 1);
+ else if (strcmp (argv[i], "--verbose") == 0)
+ setenv ("RC_VERBOSE", "yes", 1);
+ else if (strcmp (argv[i], "--version") == 0)
+ printf ("version me\n");
+ else
+ eerror ("%s: unknown option `%s'", applet, argv[i]);
+ }
+
+ if (ifstarted && ! rc_service_state (applet, rc_service_started)) {
+ if (! rc_is_env("RC_QUIET", "yes"))
+ eerror ("ERROR: %s is not started", applet);
+ exit (EXIT_FAILURE);
+ }
+
+ if (rc_is_env ("IN_HOTPLUG", "1")) {
+ if (! rc_is_env ("RC_HOTPLUG", "yes") || ! rc_allow_plug (applet))
+ eerrorx ("%s: not allowed to be hotplugged", applet);
+ }
+
+ /* Setup a signal handler */
+ signal (SIGHUP, handle_signal);
+ signal (SIGINT, handle_signal);
+ signal (SIGQUIT, handle_signal);
+ signal (SIGTERM, handle_signal);
+ signal (SIGCHLD, handle_signal);
+
+ /* Load our plugins */
+ rc_plugin_load ();
+
+ /* Now run each option */
+ retval = EXIT_SUCCESS;
+ for (i = 2; i < argc; i++) {
+ /* Abort on a sighup here */
+ if (sighup)
+ exit (EXIT_FAILURE);
+
+ if (strlen (argv[i]) < 2 ||
+ (argv[i][0] == '-' && argv[i][1] == '-'))
+ continue;
+
+ /* Export the command we're running.
+ This is important as we stamp on the restart function now but
+ some start/stop routines still need to behave differently if
+ restarting. */
+ unsetenv ("RC_CMD");
+ setenv ("RC_CMD", argv[i], 1);
+
+ doneone = true;
+ if (strcmp (argv[i], "conditionalrestart") == 0 ||
+ strcmp (argv[i], "condrestart") == 0)
+ {
+ if (rc_service_state (service, rc_service_started))
+ svc_restart (service, deps);
+ }
+ else if (strcmp (argv[i], "restart") == 0)
+ svc_restart (service, deps);
+ else if (strcmp (argv[i], "start") == 0)
+ svc_start (service, deps);
+ else if (strcmp (argv[i], "status") == 0) {
+ rc_service_state_t r = svc_status (service);
+ retval = (int) r;
+ } else if (strcmp (argv[i], "stop") == 0) {
+ if (in_background)
+ get_started_services ();
+
+ svc_stop (service, deps);
+
+ if (! in_background &&
+ ! rc_runlevel_stopping () &&
+ rc_service_state (service, rc_service_stopped))
+ uncoldplug (applet);
+
+ if (in_background &&
+ rc_service_state (service, rc_service_inactive))
+ {
+ char *svc;
+ int j;
+ STRLIST_FOREACH (restart_services, svc, j)
+ if (rc_service_state (svc, rc_service_stopped))
+ rc_schedule_start_service (service, svc);
+ }
+ } else if (strcmp (argv[i], "zap") == 0) {
+ einfo ("Manually resetting %s to stopped state", applet);
+ rc_mark_service (applet, rc_service_stopped);
+ uncoldplug (applet);
+ } else if (strcmp (argv[i], "help") == 0) {
+ execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, "help", (char *) NULL);
+ eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
+ applet, strerror (errno));
+ }else
+ svc_exec (service, argv[i], NULL);
+
+ /* Flush our buffered output if any */
+ eflush ();
+
+ /* We should ensure this list is empty after an action is done */
+ rc_strlist_free (restart_services);
+ restart_services = NULL;
+ }
+
+ if (! doneone) {
+ execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
+ eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
+ applet, strerror (errno));
+ }
+
+ return (retval);
}