aboutsummaryrefslogtreecommitdiff
path: root/src/rc/rc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rc/rc.c')
-rw-r--r--src/rc/rc.c1230
1 files changed, 584 insertions, 646 deletions
diff --git a/src/rc/rc.c b/src/rc/rc.c
index 98b44cc8..6a6aa0a4 100644
--- a/src/rc/rc.c
+++ b/src/rc/rc.c
@@ -42,10 +42,18 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#include <sys/stat.h>
#include <sys/utsname.h>
#include <sys/wait.h>
+
+/* So we can coldplug net devices */
+#ifdef BSD
+# include <sys/socket.h>
+# include <ifaddrs.h>
+#endif
+
#include <errno.h>
#include <dirent.h>
#include <ctype.h>
#include <getopt.h>
+#include <libgen.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
@@ -56,19 +64,12 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#include <termios.h>
#include <unistd.h>
-/* So we can coldplug net devices */
-#ifdef BSD
-# include <sys/socket.h>
-# include <ifaddrs.h>
-#endif
-
#include "builtins.h"
#include "einfo.h"
#include "rc.h"
#include "rc-logger.h"
#include "rc-misc.h"
#include "rc-plugin.h"
-#include "strlist.h"
#include "version.h"
@@ -81,43 +82,31 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#define INTERACTIVE RC_SVCDIR "/interactive"
-#define DEVBOOT "/dev/.rcboot"
-
-/* Cleanup anything in main */
-#define CHAR_FREE(_item) if (_item) { \
- free (_item); \
- _item = NULL; \
-}
-
-extern char **environ;
+#define DEVBOOT "/dev/.rcboot"
static char *RUNLEVEL = NULL;
static char *PREVLEVEL = NULL;
const char *applet = NULL;
static char *runlevel = NULL;
-static char **env = NULL;
-static char **newenv = NULL;
-static char **coldplugged_services = NULL;
-static char **stop_services = NULL;
-static char **start_services = NULL;
-static rc_depinfo_t *deptree = NULL;
-static rc_hook_t hook_out = 0;
-static char *tmp = NULL;
+static RC_STRINGLIST *coldplugged_services = NULL;
+static RC_STRINGLIST *stop_services = NULL;
+static RC_STRINGLIST *start_services = NULL;
+static RC_STRINGLIST *types_n = NULL;
+static RC_STRINGLIST *types_nua = NULL;
+static RC_DEPTREE *deptree = NULL;
+static RC_HOOK hook_out = 0;
struct termios *termios_orig = NULL;
-typedef struct pidlist
+typedef struct piditem
{
pid_t pid;
- struct pidlist *next;
-} pidlist_t;
-static pidlist_t *service_pids = NULL;
-
-static const char *const types_n[] = { "needsme", NULL };
-static const char *const types_nua[] = { "ineed", "iuse", "iafter", NULL };
+ LIST_ENTRY(piditem) entries;
+} PIDITEM;
+LIST_HEAD(, piditem) service_pids;
-static void clean_failed (void)
+static void clean_failed(void)
{
DIR *dp;
struct dirent *d;
@@ -125,70 +114,71 @@ static void clean_failed (void)
char *path;
/* Clean the failed services state dir now */
- if ((dp = opendir (RC_SVCDIR "/failed"))) {
- while ((d = readdir (dp))) {
+ if ((dp = opendir(RC_SVCDIR "/failed"))) {
+ while ((d = readdir(dp))) {
if (d->d_name[0] == '.' &&
(d->d_name[1] == '\0' ||
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
continue;
- l = strlen (RC_SVCDIR "/failed/") + strlen (d->d_name) + 1;
- path = xmalloc (sizeof (char) * l);
- snprintf (path, l, RC_SVCDIR "/failed/%s", d->d_name);
+ l = strlen(RC_SVCDIR "/failed/") + strlen(d->d_name) + 1;
+ path = xmalloc(sizeof(char) * l);
+ snprintf(path, l, RC_SVCDIR "/failed/%s", d->d_name);
if (path) {
- if (unlink (path))
- eerror ("%s: unlink `%s': %s", applet, path,
- strerror (errno));
- free (path);
+ if (unlink(path))
+ eerror("%s: unlink `%s': %s", applet, path,
+ strerror(errno));
+ free(path);
}
}
- closedir (dp);
+ closedir(dp);
}
}
-static void cleanup (void)
+static void cleanup(void)
{
- if (applet && strcmp (applet, "rc") == 0) {
- pidlist_t *pl = service_pids;
+ if (applet && strcmp(applet, "rc") == 0) {
+ PIDITEM *p1 = LIST_FIRST(&service_pids);
+ PIDITEM *p2;
if (hook_out)
- rc_plugin_run (hook_out, runlevel);
+ rc_plugin_run(hook_out, runlevel);
- rc_plugin_unload ();
+ rc_plugin_unload();
if (! rc_in_plugin && termios_orig) {
- tcsetattr (fileno (stdin), TCSANOW, termios_orig);
- free (termios_orig);
+ tcsetattr(fileno(stdin), TCSANOW, termios_orig);
+ free(termios_orig);
}
- while (pl) {
- pidlist_t *p = pl->next;
- free (pl);
- pl = p;
+ while (p1) {
+ p2 = LIST_NEXT(p1, entries);
+ free(p1);
+ p1 = p2;
}
- rc_strlist_free (env);
- rc_strlist_free (newenv);
- rc_strlist_free (coldplugged_services);
- rc_strlist_free (stop_services);
- rc_strlist_free (start_services);
- rc_deptree_free (deptree);
+ rc_stringlist_free(coldplugged_services);
+ rc_stringlist_free(stop_services);
+ rc_stringlist_free(start_services);
+ rc_stringlist_free(types_n);
+ rc_stringlist_free(types_nua);
+ rc_deptree_free(deptree);
/* Clean runlevel start, stop markers */
if (! rc_in_plugin && ! rc_in_logger) {
- rmdir (RC_STARTING);
- rmdir (RC_STOPPING);
- clean_failed ();
+ rmdir(RC_STARTING);
+ rmdir(RC_STOPPING);
+ clean_failed();
- rc_logger_close ();
+ rc_logger_close();
}
- free (runlevel);
+ free(runlevel);
}
}
#ifdef __linux__
-static char *proc_getent (const char *ent)
+static char *proc_getent(const char *ent)
{
FILE *fp;
char *proc;
@@ -196,50 +186,50 @@ static char *proc_getent (const char *ent)
char *value = NULL;
int i;
- if (! exists ("/proc/cmdline"))
- return (NULL);
+ if (! exists("/proc/cmdline"))
+ return NULL;
- if (! (fp = fopen ("/proc/cmdline", "r"))) {
- eerror ("failed to open `/proc/cmdline': %s", strerror (errno));
- return (NULL);
+ if (! (fp = fopen("/proc/cmdline", "r"))) {
+ eerror("failed to open `/proc/cmdline': %s", strerror(errno));
+ return NULL;
}
- if ((proc = rc_getline (fp)) &&
- (p = strstr (proc, ent)))
+ if ((proc = rc_getline(fp)) &&
+ (p = strstr(proc, ent)))
{
i = p - proc;
if (i == '\0' || proc[i - 1] == ' ') {
- p += strlen (ent);
+ p += strlen(ent);
if (*p == '=')
p++;
- value = xstrdup (strsep (&p, " "));
+ value = xstrdup(strsep(&p, " "));
}
} else
errno = ENOENT;
- free (proc);
- fclose (fp);
+ free(proc);
+ fclose(fp);
- return (value);
+ return value;
}
#endif
-static char read_key (bool block)
+static char read_key(bool block)
{
struct termios termios;
char c = 0;
- int fd = fileno (stdin);
+ int fd = fileno(stdin);
- if (! isatty (fd))
- return (false);
+ if (! isatty(fd))
+ return false;
/* Now save our terminal settings. We need to restore them at exit as we
* will be changing it for non-blocking reads for Interactive */
if (! termios_orig) {
- termios_orig = xmalloc (sizeof (*termios_orig));
- tcgetattr (fd, termios_orig);
+ termios_orig = xmalloc(sizeof(*termios_orig));
+ tcgetattr(fd, termios_orig);
}
- tcgetattr (fd, &termios);
+ tcgetattr(fd, &termios);
termios.c_lflag &= ~(ICANON | ECHO);
if (block)
termios.c_cc[VMIN] = 1;
@@ -247,49 +237,49 @@ static char read_key (bool block)
termios.c_cc[VMIN] = 0;
termios.c_cc[VTIME] = 0;
}
- tcsetattr (fd, TCSANOW, &termios);
+ tcsetattr(fd, TCSANOW, &termios);
- read (fd, &c, 1);
+ read(fd, &c, 1);
- tcsetattr (fd, TCSANOW, termios_orig);
+ tcsetattr(fd, TCSANOW, termios_orig);
- return (c);
+ return c;
}
-static bool want_interactive (void)
+static bool want_interactive(void)
{
char c;
static bool gotinteractive;
static bool interactive;
- if (rc_yesno (getenv ("EINFO_QUIET")))
- return (false);
+ if (rc_yesno(getenv("EINFO_QUIET")))
+ return false;
if (PREVLEVEL &&
- strcmp (PREVLEVEL, "N") != 0 &&
- strcmp (PREVLEVEL, "S") != 0 &&
- strcmp (PREVLEVEL, "1") != 0)
- return (false);
+ strcmp(PREVLEVEL, "N") != 0 &&
+ strcmp(PREVLEVEL, "S") != 0 &&
+ strcmp(PREVLEVEL, "1") != 0)
+ return false;
if (! gotinteractive) {
gotinteractive = true;
- interactive = rc_conf_yesno ("rc_interactive");
+ interactive = rc_conf_yesno("rc_interactive");
}
if (! interactive)
- return (false);
+ return false;
- c = read_key (false);
- return ((c == 'I' || c == 'i') ? true : false);
+ c = read_key(false);
+ return (c == 'I' || c == 'i') ? true : false;
}
-static void mark_interactive (void)
+static void mark_interactive(void)
{
- FILE *fp = fopen (INTERACTIVE, "w");
+ FILE *fp = fopen(INTERACTIVE, "w");
if (fp)
- fclose (fp);
+ fclose(fp);
}
-static void sulogin (bool cont)
+static void sulogin(bool cont)
{
int status = 0;
struct sigaction sa;
@@ -297,287 +287,276 @@ static void sulogin (bool cont)
sigset_t old;
pid_t pid;
#ifdef __linux__
- const char *sys = rc_sys ();
+ const char *sys = rc_sys();
/* VSERVER and OPENVZ systems cannot do a sulogin */
- if (sys && (strcmp (sys, "VSERVER") == 0 || strcmp (sys, "OPENVZ") == 0)) {
- execl ("/sbin/halt", "/sbin/halt", "-f", (char *) NULL);
- eerrorx ("%s: unable to exec `/sbin/halt': %s", applet, strerror (errno));
+ if (sys && (strcmp(sys, "VSERVER") == 0 || strcmp(sys, "OPENVZ") == 0)) {
+ execl("/sbin/halt", "/sbin/halt", "-f", (char *) NULL);
+ eerrorx("%s: unable to exec `/sbin/halt': %s",
+ applet, strerror(errno));
}
#endif
- newenv = env_filter ();
-
if (! cont) {
- rc_logger_close ();
+ rc_logger_close();
#ifdef __linux__
- execle ("/sbin/sulogin", "/sbin/sulogin", (char *) NULL, newenv);
- eerrorx ("%s: unable to exec `/sbin/sulogin': %s", applet, strerror (errno));
+ execl("/sbin/sulogin", "/sbin/sulogin", (char *) NULL);
+ eerrorx("%s: unable to exec `/sbin/sulogin': %s",
+ applet, strerror(errno));
#else
- exit (EXIT_SUCCESS);
+ exit(EXIT_SUCCESS);
#endif
}
/* We need to block signals until we have forked */
- memset (&sa, 0, sizeof (sa));
+ memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
- sigemptyset (&sa.sa_mask);
- sigfillset (&full);
- sigprocmask (SIG_SETMASK, &full, &old);
- pid = vfork ();
+ sigemptyset(&sa.sa_mask);
+ sigfillset(&full);
+ sigprocmask(SIG_SETMASK, &full, &old);
+ pid = vfork();
if (pid == -1)
- eerrorx ("%s: fork: %s", applet, strerror (errno));
+ eerrorx("%s: fork: %s", applet, strerror(errno));
if (pid == 0) {
/* Restore default handlers */
- sigaction (SIGCHLD, &sa, NULL);
- sigaction (SIGHUP, &sa, NULL);
- sigaction (SIGINT, &sa, NULL);
- sigaction (SIGQUIT, &sa, NULL);
- sigaction (SIGTERM, &sa, NULL);
- sigaction (SIGUSR1, &sa, NULL);
- sigaction (SIGWINCH, &sa, NULL);
+ sigaction(SIGCHLD, &sa, NULL);
+ sigaction(SIGHUP, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGQUIT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGUSR1, &sa, NULL);
+ sigaction(SIGWINCH, &sa, NULL);
/* Unmask signals */
- sigprocmask (SIG_SETMASK, &old, NULL);
+ sigprocmask(SIG_SETMASK, &old, NULL);
if (termios_orig)
- tcsetattr (fileno (stdin), TCSANOW, termios_orig);
+ tcsetattr(fileno(stdin), TCSANOW, termios_orig);
#ifdef __linux__
- execle (SULOGIN, SULOGIN, (char *) NULL, newenv);
- eerror ("%s: unable to exec `%s': %s", applet, SULOGIN,
- strerror (errno));
+ execl(SULOGIN, SULOGIN, (char *) NULL);
+ eerror("%s: unable to exec `%s': %s", applet, SULOGIN,
+ strerror(errno));
#else
- execle ("/bin/sh", "/bin/sh", (char *) NULL, newenv);
- eerror ("%s: unable to exec `/bin/sh': %s", applet,
- strerror (errno));
+ execl("/bin/sh", "/bin/sh", (char *) NULL);
+ eerror("%s: unable to exec `/bin/sh': %s", applet,
+ strerror(errno));
#endif
- _exit (EXIT_FAILURE);
+ _exit(EXIT_FAILURE);
}
/* Unmask signals and wait for child */
- sigprocmask (SIG_SETMASK, &old, NULL);
- waitpid (pid, &status, 0);
+ sigprocmask(SIG_SETMASK, &old, NULL);
+ waitpid(pid, &status, 0);
}
-static void single_user (void)
+static void single_user(void)
{
- rc_logger_close ();
+ rc_logger_close();
- execl (SHUTDOWN, SHUTDOWN, "now", (char *) NULL);
- eerrorx ("%s: unable to exec `" SHUTDOWN "': %s",
- applet, strerror (errno));
+ execl(SHUTDOWN, SHUTDOWN, "now", (char *) NULL);
+ eerrorx("%s: unable to exec `" SHUTDOWN "': %s",
+ applet, strerror(errno));
}
-static bool set_ksoftlevel (const char *level)
+static bool set_ksoftlevel(const char *level)
{
FILE *fp;
if (! level ||
- strcmp (level, getenv ("RC_BOOTLEVEL")) == 0 ||
- strcmp (level, RC_LEVEL_SINGLE) == 0 ||
- strcmp (level, RC_LEVEL_SYSINIT) == 0)
+ strcmp(level, getenv ("RC_BOOTLEVEL")) == 0 ||
+ strcmp(level, RC_LEVEL_SINGLE) == 0 ||
+ strcmp(level, RC_LEVEL_SYSINIT) == 0)
{
- if (exists (RC_KSOFTLEVEL) &&
- unlink (RC_KSOFTLEVEL) != 0)
- eerror ("unlink `%s': %s", RC_KSOFTLEVEL, strerror (errno));
- return (false);
+ if (exists(RC_KSOFTLEVEL) &&
+ unlink(RC_KSOFTLEVEL) != 0)
+ eerror("unlink `%s': %s", RC_KSOFTLEVEL, strerror(errno));
+ return false;
}
- if (! (fp = fopen (RC_KSOFTLEVEL, "w"))) {
- eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno));
- return (false);
+ if (! (fp = fopen(RC_KSOFTLEVEL, "w"))) {
+ eerror("fopen `%s': %s", RC_KSOFTLEVEL, strerror(errno));
+ return false;
}
- fprintf (fp, "%s", level);
- fclose (fp);
- return (true);
+ fprintf(fp, "%s", level);
+ fclose(fp);
+ return true;
}
-static int get_ksoftlevel (char *buffer, int buffer_len)
+static int get_ksoftlevel(char *buffer, int buffer_len)
{
FILE *fp;
int i = 0;
- if (! exists (RC_KSOFTLEVEL))
- return (0);
+ if (! exists(RC_KSOFTLEVEL))
+ return 0;
- if (! (fp = fopen (RC_KSOFTLEVEL, "r"))) {
- eerror ("fopen `%s': %s", RC_KSOFTLEVEL, strerror (errno));
- return (-1);
+ if (! (fp = fopen(RC_KSOFTLEVEL, "r"))) {
+ eerror("fopen `%s': %s", RC_KSOFTLEVEL, strerror(errno));
+ return -1;
}
- if (fgets (buffer, buffer_len, fp)) {
- i = strlen (buffer) - 1;
+ if (fgets(buffer, buffer_len, fp)) {
+ i = strlen(buffer) - 1;
if (buffer[i] == '\n')
buffer[i] = 0;
}
- fclose (fp);
- return (i);
+ fclose(fp);
+ return i;
}
-static void add_pid (pid_t pid)
+static void add_pid(pid_t pid)
{
- pidlist_t *sp = service_pids;
- if (sp) {
- while (sp->next)
- sp = sp->next;
- sp->next = xmalloc (sizeof (*sp->next));
- sp = sp->next;
- } else
- sp = service_pids = xmalloc (sizeof (*sp));
- memset (sp, 0, sizeof (*sp));
- sp->pid = pid;
+ PIDITEM *p = xmalloc(sizeof(*p));
+ p->pid = pid;
+ LIST_INSERT_HEAD(&service_pids, p, entries);
}
-static void remove_pid (pid_t pid)
+static void remove_pid(pid_t pid)
{
- pidlist_t *last = NULL;
- pidlist_t *pl;
+ PIDITEM *p;
- for (pl = service_pids; pl; pl = pl->next) {
- if (pl->pid == pid) {
- if (last)
- last->next = pl->next;
- else
- service_pids = pl->next;
- free (pl);
- break;
+ LIST_FOREACH(p, &service_pids, entries)
+ if (p->pid == pid) {
+ LIST_REMOVE(p, entries);
+ free(p);
+ return;
}
- last = pl;
- }
}
-static void wait_for_services ()
+static void wait_for_services(void)
{
- while (waitpid (0, 0, 0) != -1);
+ while (waitpid(0, 0, 0) != -1);
}
-static void handle_signal (int sig)
+static void handle_signal(int sig)
{
int serrno = errno;
char signame[10] = { '\0' };
- pidlist_t *pl;
pid_t pid;
+ PIDITEM *pi;
int status = 0;
struct winsize ws;
sigset_t sset;
switch (sig) {
- case SIGCHLD:
- do {
- pid = waitpid (-1, &status, WNOHANG);
- if (pid < 0) {
- if (errno != ECHILD)
- eerror ("waitpid: %s", strerror (errno));
- return;
- }
- } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
-
- /* Remove that pid from our list */
- if (pid > 0)
- remove_pid (pid);
- break;
-
- case SIGWINCH:
- if (rc_logger_tty >= 0) {
- ioctl (STDIN_FILENO, TIOCGWINSZ, &ws);
- ioctl (rc_logger_tty, TIOCSWINSZ, &ws);
+ case SIGCHLD:
+ do {
+ pid = waitpid(-1, &status, WNOHANG);
+ if (pid < 0) {
+ if (errno != ECHILD)
+ eerror("waitpid: %s", strerror(errno));
+ return;
}
- break;
-
- case SIGINT:
- if (! signame[0])
- snprintf (signame, sizeof (signame), "SIGINT");
- /* FALLTHROUGH */
- case SIGTERM:
- if (! signame[0])
- snprintf (signame, sizeof (signame), "SIGTERM");
- /* FALLTHROUGH */
- case SIGQUIT:
- if (! signame[0])
- snprintf (signame, sizeof (signame), "SIGQUIT");
- eerrorx ("%s: caught %s, aborting", applet, signame);
- /* NOTREACHED */
- case SIGUSR1:
- eerror ("rc: Aborting!");
-
- /* Block child signals */
- sigemptyset (&sset);
- sigaddset (&sset, SIGCHLD);
- sigprocmask (SIG_BLOCK, &sset, NULL);
-
- /* Kill any running services we have started */
- for (pl = service_pids; pl; pl = pl->next)
- kill (pl->pid, SIGTERM);
-
- /* Notify plugins we are aborting */
- rc_plugin_run (RC_HOOK_ABORT, NULL);
-
- /* Only drop into single user mode if we're booting */
- if ((PREVLEVEL &&
- (strcmp (PREVLEVEL, "S") == 0 ||
- strcmp (PREVLEVEL, "1") == 0)) ||
- (RUNLEVEL &&
- (strcmp (RUNLEVEL, "S") == 0 ||
- strcmp (RUNLEVEL, "1") == 0)))
- single_user ();
-
- exit (EXIT_FAILURE);
- /* NOTREACHED */
+ } while (! WIFEXITED(status) && ! WIFSIGNALED(status));
- default:
- eerror ("%s: caught unknown signal %d", applet, sig);
+ /* Remove that pid from our list */
+ if (pid > 0)
+ remove_pid(pid);
+ break;
+
+ case SIGWINCH:
+ if (rc_logger_tty >= 0) {
+ ioctl(STDIN_FILENO, TIOCGWINSZ, &ws);
+ ioctl(rc_logger_tty, TIOCSWINSZ, &ws);
+ }
+ break;
+
+ case SIGINT:
+ if (! signame[0])
+ snprintf(signame, sizeof(signame), "SIGINT");
+ /* FALLTHROUGH */
+ case SIGTERM:
+ if (! signame[0])
+ snprintf(signame, sizeof(signame), "SIGTERM");
+ /* FALLTHROUGH */
+ case SIGQUIT:
+ if (! signame[0])
+ snprintf(signame, sizeof(signame), "SIGQUIT");
+ eerrorx("%s: caught %s, aborting", applet, signame);
+ /* NOTREACHED */
+ case SIGUSR1:
+ eerror("rc: Aborting!");
+
+ /* Block child signals */
+ sigemptyset(&sset);
+ sigaddset(&sset, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &sset, NULL);
+
+ /* Kill any running services we have started */
+ LIST_FOREACH(pi, &service_pids, entries)
+ kill(pi->pid, SIGTERM);
+
+ /* Notify plugins we are aborting */
+ rc_plugin_run(RC_HOOK_ABORT, NULL);
+
+ /* Only drop into single user mode if we're booting */
+ if ((PREVLEVEL &&
+ (strcmp(PREVLEVEL, "S") == 0 ||
+ strcmp(PREVLEVEL, "1") == 0)) ||
+ (RUNLEVEL &&
+ (strcmp(RUNLEVEL, "S") == 0 ||
+ strcmp(RUNLEVEL, "1") == 0)))
+ single_user();
+
+ exit(EXIT_FAILURE);
+ /* NOTREACHED */
+
+ default:
+ eerror("%s: caught unknown signal %d", applet, sig);
}
/* Restore errno */
errno = serrno;
}
-static void run_script (const char *script)
+static void run_script(const char *script)
{
int status = 0;
- pid_t pid = vfork ();
+ pid_t pid = vfork();
+ pid_t wpid;
if (pid < 0)
- eerrorx ("%s: vfork: %s", applet, strerror (errno));
+ eerrorx("%s: vfork: %s", applet, strerror(errno));
else if (pid == 0) {
- execl (script, script, (char *) NULL);
- eerror ("%s: unable to exec `%s': %s",
- script, applet, strerror (errno));
- _exit (EXIT_FAILURE);
+ execl(script, script, (char *) NULL);
+ eerror("%s: unable to exec `%s': %s",
+ script, applet, strerror(errno));
+ _exit(EXIT_FAILURE);
}
do {
- pid_t wpid = waitpid (pid, &status, 0);
+ wpid = waitpid(pid, &status, 0);
if (wpid < 1)
- eerror ("waitpid: %s", strerror (errno));
- } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
+ eerror("waitpid: %s", strerror(errno));
+ } while (! WIFEXITED(status) && ! WIFSIGNALED(status));
- if (! WIFEXITED (status) || ! WEXITSTATUS (status) == 0)
- eerrorx ("%s: failed to exec `%s'", applet, script);
+ if (! WIFEXITED(status) || ! WEXITSTATUS(status) == 0)
+ eerrorx("%s: failed to exec `%s'", applet, script);
}
-static void do_coldplug (void)
+static void do_coldplug(void)
{
- size_t s;
- int i;
+ size_t l;
DIR *dp;
struct dirent *d;
char *service;
+ RC_STRING *s;
#ifdef BSD
struct ifaddrs *ifap;
struct ifaddrs *ifa;
+ char *p;
#endif
- if (! rc_conf_yesno ("rc_coldplug") && errno != ENOENT)
+ if (! rc_conf_yesno("rc_coldplug") && errno != ENOENT)
return;
/* We need to ensure our state dirs exist.
* We should have a better call than this, but oh well. */
- rc_deptree_update_needed ();
+ rc_deptree_update_needed();
#ifdef BSD
if (getifaddrs(&ifap) == 0) {
@@ -585,33 +564,33 @@ static void do_coldplug (void)
if (ifa->ifa_addr->sa_family != AF_LINK)
continue;
- s = strlen ("net.") + strlen (ifa->ifa_name) + 1;
- tmp = xmalloc (sizeof (char) * s);
- snprintf (tmp, s, "net.%s", ifa->ifa_name);
- if (rc_service_exists (tmp) &&
- service_plugable (tmp))
- rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED);
- CHAR_FREE (tmp);
+ l = strlen("net.") + strlen(ifa->ifa_name) + 1;
+ service = xmalloc(sizeof (char) * l);
+ snprintf(service, l, "net.%s", ifa->ifa_name);
+ if (rc_service_exists(service) &&
+ service_plugable(service))
+ rc_service_mark(service, RC_SERVICE_COLDPLUGGED);
+ free(service);
}
freeifaddrs (ifap);
}
/* The mice are a little more tricky.
* If we coldplug anything else, we'll probably do it here. */
- if ((dp = opendir ("/dev"))) {
- while ((d = readdir (dp))) {
- if (strncmp (d->d_name, "psm", 3) == 0 ||
- strncmp (d->d_name, "ums", 3) == 0)
+ if ((dp = opendir("/dev"))) {
+ while ((d = readdir(dp))) {
+ if (strncmp(d->d_name, "psm", 3) == 0 ||
+ strncmp(d->d_name, "ums", 3) == 0)
{
- char *p = d->d_name + 3;
- if (p && isdigit ((int) *p)) {
- s = strlen ("moused.") + strlen (d->d_name) + 1;
- tmp = xmalloc (sizeof (char) * s);
- snprintf (tmp, s, "moused.%s", d->d_name);
- if (rc_service_exists (tmp) &&
- service_plugable (tmp))
- rc_service_mark (tmp, RC_SERVICE_COLDPLUGGED);
- CHAR_FREE (tmp);
+ p = d->d_name + 3;
+ if (p && isdigit((int) *p)) {
+ l = strlen("moused.") + strlen(d->d_name) + 1;
+ service = xmalloc(sizeof(char) * l);
+ snprintf (service, l, "moused.%s", d->d_name);
+ if (rc_service_exists (service) &&
+ service_plugable (service))
+ rc_service_mark (service, RC_SERVICE_COLDPLUGGED);
+ free(service);
}
}
}
@@ -624,41 +603,57 @@ static void do_coldplug (void)
* its coldplugging thing. runscript knows when we're not ready so it
* stores a list of coldplugged services in DEVBOOT for us to pick up
* here when we are ready for them */
- if ((dp = opendir (DEVBOOT))) {
- while ((d = readdir (dp))) {
+ if ((dp = opendir(DEVBOOT))) {
+ while ((d = readdir(dp))) {
if (d->d_name[0] == '.' &&
(d->d_name[1] == '\0' ||
(d->d_name[1] == '.' && d->d_name[2] == '\0')))
continue;
- if (rc_service_exists (d->d_name) &&
- service_plugable (d->d_name))
- rc_service_mark (d->d_name, RC_SERVICE_COLDPLUGGED);
-
- s = strlen (DEVBOOT "/") + strlen (d->d_name) + 1;
- tmp = xmalloc (sizeof (char) * s);
- snprintf (tmp, s, DEVBOOT "/%s", d->d_name);
- if (tmp) {
- if (unlink (tmp))
- eerror ("%s: unlink `%s': %s", applet, tmp,
- strerror (errno));
- free (tmp);
- }
+ if (rc_service_exists(d->d_name) &&
+ service_plugable(d->d_name))
+ rc_service_mark(d->d_name, RC_SERVICE_COLDPLUGGED);
+
+ l = strlen(DEVBOOT "/") + strlen(d->d_name) + 1;
+ service = xmalloc(sizeof (char) * l);
+ snprintf(service, l, DEVBOOT "/%s", d->d_name);
+ if (unlink(service))
+ eerror("%s: unlink `%s': %s", applet, service,
+ strerror(errno));
+ free(service);
}
- closedir (dp);
- rmdir (DEVBOOT);
+ closedir(dp);
+ rmdir(DEVBOOT);
}
#endif
- if (rc_yesno (getenv ("EINFO_QUIET")))
+ if (rc_yesno(getenv("EINFO_QUIET")))
return;
/* Load our list of coldplugged services and display them */
- einfon ("Device initiated services:%s", ecolor (ECOLOR_HILITE));
- coldplugged_services = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
- STRLIST_FOREACH (coldplugged_services, service, i)
- printf (" %s", service);
- printf ("%s\n", ecolor (ECOLOR_NORMAL));
+ einfon("Device initiated services:%s", ecolor(ECOLOR_HILITE));
+ coldplugged_services = rc_services_in_state(RC_SERVICE_COLDPLUGGED);
+ TAILQ_FOREACH(s, coldplugged_services, entries)
+ printf(" %s", s->value);
+ printf ("%s\n", ecolor(ECOLOR_NORMAL));
+}
+
+static bool runlevel_config(const char *service, const char *level)
+{
+ char *init = rc_service_resolve(service);
+ char *conf;
+ size_t l;
+ bool retval;
+
+ init = dirname(init);
+ init = dirname(init);
+ l = strlen(init) + strlen(level) + strlen(service) + 10;
+ conf = xmalloc(sizeof(char) * l);
+ snprintf(conf, l, "%s/conf.d/%s.%s", init, service, level);
+ retval = exists(conf);
+ free(conf);
+
+ return retval;
}
#include "_usage.h"
@@ -673,16 +668,14 @@ static const char * const longopts_help[] = {
};
#include "_usage.c"
-int main (int argc, char **argv)
+int main(int argc, char **argv)
{
const char *bootlevel = NULL;
- const char *sys = rc_sys ();
+ const char *sys = rc_sys();
char *newlevel = NULL;
- char *service = NULL;
- char **deporder = NULL;
- char **tmplist;
- int i = 0;
- int j = 0;
+ RC_STRINGLIST *deporder = NULL;
+ RC_STRINGLIST *tmplist;
+ RC_STRING *service;
bool going_down = false;
bool interactive = false;
int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
@@ -692,116 +685,94 @@ int main (int argc, char **argv)
bool parallel;
int regen = 0;
pid_t pid;
+ RC_STRING *svc1;
+ RC_STRING *svc2 = NULL;
+ struct utsname uts;
+#ifdef __linux__
+ char *cmd;
+ char *proc;
+ char *p;
+ char *token;
+#endif
- applet = basename_c (argv[0]);
- atexit (cleanup);
+ applet = basename_c(argv[0]);
+ LIST_INIT(&service_pids);
+ atexit(cleanup);
if (! applet)
- eerrorx ("arguments required");
+ eerrorx("arguments required");
- if (argc > 1 && (strcmp (argv[1], "--version") == 0)) {
- printf ("%s (OpenRC", applet);
+ if (argc > 1 && (strcmp(argv[1], "--version") == 0)) {
+ printf("%s (OpenRC", applet);
if (sys)
- printf (" [%s]", sys);
- printf (") " VERSION
+ printf(" [%s]", sys);
+ printf(") " VERSION
#ifdef BRANDING
- " (" BRANDING ")"
+ " (" BRANDING ")"
#endif
- "\n");
- exit (EXIT_SUCCESS);
+ "\n");
+ exit(EXIT_SUCCESS);
}
/* Run our built in applets. If we ran one, we don't return. */
- run_applets (argc, argv);
+ run_applets(argc, argv);
argc--;
argv++;
/* Change dir to / to ensure all scripts don't use stuff in pwd */
- chdir ("/");
+ chdir("/");
/* RUNLEVEL is set by sysvinit as is a magic number
* RC_SOFTLEVEL is set by us and is the name for this magic number
* even though all our userland documentation refers to runlevel */
- RUNLEVEL = getenv ("RUNLEVEL");
- PREVLEVEL = getenv ("PREVLEVEL");
+ RUNLEVEL = getenv("RUNLEVEL");
+ PREVLEVEL = getenv("PREVLEVEL");
/* Ensure our environment is pure
* Also, add our configuration to it */
- env = env_filter ();
- tmplist = env_config ();
- rc_strlist_join (&env, tmplist);
- rc_strlist_free (tmplist);
-
- if (env) {
- char *p;
-
-#ifdef __linux__
- /* clearenv isn't portable, but there's no harm in using it
- * if we have it */
- clearenv ();
-#else
- char *var;
- /* No clearenv present here then.
- * We could manipulate environ directly ourselves, but it seems that
- * some kernels bitch about this according to the environ man pages
- * so we walk though environ and call unsetenv for each value. */
- while (environ[0]) {
- tmp = xstrdup (environ[0]);
- p = tmp;
- var = strsep (&p, "=");
- unsetenv (var);
- free (tmp);
- }
- tmp = NULL;
-#endif
-
- STRLIST_FOREACH (env, p, i)
- if (strcmp (p, "RC_SOFTLEVEL") != 0 && strcmp (p, "SOFTLEVEL") != 0)
- putenv (p);
-
- /* We don't free our list as that would be null in environ */
- }
+ env_filter();
+ env_config();
argc++;
argv--;
- while ((opt = getopt_long (argc, argv, getoptstring,
- longopts, (int *) 0)) != -1)
+ while ((opt = getopt_long(argc, argv, getoptstring,
+ longopts, (int *) 0)) != -1)
{
switch (opt) {
- case 'o':
- if (*optarg == '\0')
- optarg = NULL;
- exit (set_ksoftlevel (optarg) ? EXIT_SUCCESS : EXIT_FAILURE);
- /* NOTREACHED */
- case_RC_COMMON_GETOPT
+ case 'o':
+ if (*optarg == '\0')
+ optarg = NULL;
+ exit(set_ksoftlevel(optarg) ? EXIT_SUCCESS : EXIT_FAILURE);
+ /* NOTREACHED */
+ case_RC_COMMON_GETOPT
}
}
newlevel = argv[optind++];
/* Enable logging */
- setenv ("EINFO_LOG", "rc", 1);
+ setenv("EINFO_LOG", "rc", 1);
/* Export our PID */
- snprintf (pidstr, sizeof (pidstr), "%d", getpid ());
- setenv ("RC_PID", pidstr, 1);
+ snprintf(pidstr, sizeof(pidstr), "%d", getpid());
+ setenv("RC_PID", pidstr, 1);
/* Load current softlevel */
- bootlevel = getenv ("RC_BOOTLEVEL");
- runlevel = rc_runlevel_get ();
+ bootlevel = getenv("RC_BOOTLEVEL");
+ runlevel = rc_runlevel_get();
- rc_logger_open (newlevel ? newlevel : runlevel);
+ rc_logger_open(newlevel ? newlevel : runlevel);
/* Setup a signal handler */
- signal_setup (SIGINT, handle_signal);
- signal_setup (SIGQUIT, handle_signal);
- signal_setup (SIGTERM, handle_signal);
- signal_setup (SIGUSR1, handle_signal);
- signal_setup (SIGWINCH, handle_signal);
-
- if (! rc_yesno (getenv ("EINFO_QUIET")))
- interactive = exists (INTERACTIVE);
- rc_plugin_load ();
+ signal_setup(SIGINT, handle_signal);
+ signal_setup(SIGQUIT, handle_signal);
+ signal_setup(SIGTERM, handle_signal);
+ signal_setup(SIGUSR1, handle_signal);
+ signal_setup(SIGWINCH, handle_signal);
+
+ if (! rc_yesno(getenv("EINFO_QUIET")))
+ interactive = exists(INTERACTIVE);
+ rc_plugin_load();
/* Check we're in the runlevel requested, ie from
* rc single
@@ -809,450 +780,417 @@ int main (int argc, char **argv)
* rc reboot
*/
if (newlevel) {
- if (strcmp (newlevel, RC_LEVEL_SYSINIT) == 0
+ if (strcmp(newlevel, RC_LEVEL_SYSINIT) == 0
#ifndef PREFIX
&& RUNLEVEL &&
- (strcmp (RUNLEVEL, "S") == 0 ||
- strcmp (RUNLEVEL, "1") == 0)
+ (strcmp(RUNLEVEL, "S") == 0 ||
+ strcmp(RUNLEVEL, "1") == 0)
#endif
- )
+ )
{
-
- struct utsname uts;
/* OK, we're either in runlevel 1 or single user mode */
-#ifdef __linux__
- char *cmd;
-#endif
/* exec init-early.sh if it exists
* This should just setup the console to use the correct
* font. Maybe it should setup the keyboard too? */
- if (exists (INITEARLYSH))
- run_script (INITEARLYSH);
+ if (exists(INITEARLYSH))
+ run_script(INITEARLYSH);
- uname (&uts);
- printf ("\n %sOpenRC %s" VERSION "%s is starting up %s",
- ecolor (ECOLOR_GOOD), ecolor (ECOLOR_HILITE),
- ecolor (ECOLOR_NORMAL), ecolor (ECOLOR_BRACKET));
+ uname(&uts);
+ printf("\n %sOpenRC %s" VERSION "%s is starting up %s",
+ ecolor(ECOLOR_GOOD), ecolor(ECOLOR_HILITE),
+ ecolor(ECOLOR_NORMAL), ecolor(ECOLOR_BRACKET));
#ifdef BRANDING
- printf (BRANDING " (%s)", uts.machine);
+ printf(BRANDING " (%s)", uts.machine);
#else
- printf ("%s %s (%s)",
- uts.sysname,
- uts.release,
- uts.machine);
+ printf("%s %s (%s)",
+ uts.sysname,
+ uts.release,
+ uts.machine);
#endif
if (sys)
- printf (" [%s]", sys);
+ printf(" [%s]", sys);
- printf ("%s\n\n", ecolor (ECOLOR_NORMAL));
+ printf("%s\n\n", ecolor(ECOLOR_NORMAL));
- if (! rc_yesno (getenv ("EINFO_QUIET")) &&
- rc_conf_yesno ("rc_interactive"))
- printf ("Press %sI%s to enter interactive boot mode\n\n",
- ecolor (ECOLOR_GOOD), ecolor (ECOLOR_NORMAL));
+ if (! rc_yesno(getenv ("EINFO_QUIET")) &&
+ rc_conf_yesno("rc_interactive"))
+ printf("Press %sI%s to enter interactive boot mode\n\n",
+ ecolor(ECOLOR_GOOD), ecolor(ECOLOR_NORMAL));
- setenv ("RC_SOFTLEVEL", newlevel, 1);
- rc_plugin_run (RC_HOOK_RUNLEVEL_START_IN, newlevel);
+ setenv("RC_SOFTLEVEL", newlevel, 1);
+ rc_plugin_run(RC_HOOK_RUNLEVEL_START_IN, newlevel);
hook_out = RC_HOOK_RUNLEVEL_START_OUT;
- run_script (INITSH);
+ run_script(INITSH);
#ifdef __linux__
/* If we requested a softlevel, save it now */
- set_ksoftlevel (NULL);
- if ((cmd = proc_getent ("softlevel"))) {
- set_ksoftlevel (cmd);
- free (cmd);
+ set_ksoftlevel(NULL);
+ if ((cmd = proc_getent("softlevel"))) {
+ set_ksoftlevel(cmd);
+ free(cmd);
}
#endif
/* Setup our coldplugged services now */
- do_coldplug ();
+ do_coldplug();
- rc_plugin_run (RC_HOOK_RUNLEVEL_START_OUT, newlevel);
+ rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, newlevel);
hook_out = 0;
- if (want_interactive ())
- mark_interactive ();
+ if (want_interactive())
+ mark_interactive();
- exit (EXIT_SUCCESS);
- } else if (strcmp (newlevel, RC_LEVEL_SINGLE) == 0) {
+ exit(EXIT_SUCCESS);
+ } else if (strcmp(newlevel, RC_LEVEL_SINGLE) == 0) {
#ifndef PREFIX
if (! RUNLEVEL ||
- (strcmp (RUNLEVEL, "S") != 0 &&
- strcmp (RUNLEVEL, "1") != 0))
+ (strcmp(RUNLEVEL, "S") != 0 &&
+ strcmp(RUNLEVEL, "1") != 0))
{
/* Remember the current runlevel for when we come back */
- set_ksoftlevel (runlevel);
- single_user ();
+ set_ksoftlevel(runlevel);
+ single_user();
}
#endif
- } else if (strcmp (newlevel, RC_LEVEL_REBOOT) == 0) {
+ } else if (strcmp(newlevel, RC_LEVEL_REBOOT) == 0) {
if (! RUNLEVEL ||
- strcmp (RUNLEVEL, "6") != 0)
+ strcmp(RUNLEVEL, "6") != 0)
{
- rc_logger_close ();
- execl (SHUTDOWN, SHUTDOWN, "-r", "now", (char *) NULL);
- eerrorx ("%s: unable to exec `" SHUTDOWN "': %s",
- applet, strerror (errno));
+ rc_logger_close();
+ execl(SHUTDOWN, SHUTDOWN, "-r", "now", (char *) NULL);
+ eerrorx("%s: unable to exec `" SHUTDOWN "': %s",
+ applet, strerror(errno));
}
- } else if (strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0) {
+ } else if (strcmp(newlevel, RC_LEVEL_SHUTDOWN) == 0) {
if (! RUNLEVEL ||
- strcmp (RUNLEVEL, "0") != 0)
+ strcmp(RUNLEVEL, "0") != 0)
{
- rc_logger_close ();
- execl (SHUTDOWN, SHUTDOWN,
+ rc_logger_close();
+ execl(SHUTDOWN, SHUTDOWN,
#ifdef __linux__
- "-h",
+ "-h",
#else
- "-p",
+ "-p",
#endif
- "now", (char *) NULL);
- eerrorx ("%s: unable to exec `" SHUTDOWN "': %s",
- applet, strerror (errno));
+ "now", (char *) NULL);
+ eerrorx("%s: unable to exec `" SHUTDOWN "': %s",
+ applet, strerror(errno));
}
}
}
/* Now we start handling our children */
- signal_setup (SIGCHLD, handle_signal);
+ signal_setup(SIGCHLD, handle_signal);
/* We should only use ksoftlevel if we were in single user mode
* If not, we need to erase ksoftlevel now. */
if (PREVLEVEL &&
- (strcmp (PREVLEVEL, "1") == 0 ||
- strcmp (PREVLEVEL, "S") == 0 ||
- strcmp (PREVLEVEL, "N") == 0))
+ (strcmp(PREVLEVEL, "1") == 0 ||
+ strcmp(PREVLEVEL, "S") == 0 ||
+ strcmp(PREVLEVEL, "N") == 0))
{
/* Try not to join boot and ksoftlevels together */
if (! newlevel ||
- strcmp (newlevel, getenv ("RC_BOOTLEVEL")) != 0)
- if (get_ksoftlevel (ksoftbuffer, sizeof (ksoftbuffer)))
+ strcmp(newlevel, getenv("RC_BOOTLEVEL")) != 0)
+ if (get_ksoftlevel(ksoftbuffer, sizeof(ksoftbuffer)))
newlevel = ksoftbuffer;
} else if (! RUNLEVEL ||
- (strcmp (RUNLEVEL, "1") != 0 &&
- strcmp (RUNLEVEL, "S") != 0 &&
- strcmp (RUNLEVEL, "N") != 0))
+ (strcmp(RUNLEVEL, "1") != 0 &&
+ strcmp(RUNLEVEL, "S") != 0 &&
+ strcmp(RUNLEVEL, "N") != 0))
{
- set_ksoftlevel (NULL);
+ set_ksoftlevel(NULL);
}
if (newlevel &&
- (strcmp (newlevel, RC_LEVEL_REBOOT) == 0 ||
- strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0 ||
- strcmp (newlevel, RC_LEVEL_SINGLE) == 0))
+ (strcmp(newlevel, RC_LEVEL_REBOOT) == 0 ||
+ strcmp(newlevel, RC_LEVEL_SHUTDOWN) == 0 ||
+ strcmp(newlevel, RC_LEVEL_SINGLE) == 0))
{
going_down = true;
- rc_runlevel_set (newlevel);
- setenv ("RC_SOFTLEVEL", newlevel, 1);
+ rc_runlevel_set(newlevel);
+ setenv("RC_RUNLEVEL", newlevel, 1);
#ifdef __FreeBSD__
/* FIXME: we shouldn't have todo this */
/* For some reason, wait_for_services waits for the logger proccess
* to finish as well, but only on FreeBSD. We cannot allow this so
* we stop logging now. */
- rc_logger_close ();
+ rc_logger_close();
#endif
- rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_IN, newlevel);
+ rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_IN, newlevel);
} else {
- rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_IN, runlevel);
+ rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_IN, runlevel);
}
hook_out = RC_HOOK_RUNLEVEL_STOP_OUT;
/* Check if runlevel is valid if we're changing */
- if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down) {
- if (! rc_runlevel_exists (newlevel))
+ if (newlevel && strcmp(runlevel, newlevel) != 0 && ! going_down) {
+ if (! rc_runlevel_exists(newlevel))
eerrorx ("%s: is not a valid runlevel", newlevel);
}
/* Load our deptree */
- if ((deptree = _rc_deptree_load (&regen)) == NULL)
- eerrorx ("failed to load deptree");
+ if ((deptree = _rc_deptree_load(&regen)) == NULL)
+ eerrorx("failed to load deptree");
/* Clean the failed services state dir */
- clean_failed ();
+ clean_failed();
- if (mkdir (RC_STOPPING, 0755) != 0) {
+ if (mkdir(RC_STOPPING, 0755) != 0) {
if (errno == EACCES)
- eerrorx ("%s: superuser access required", applet);
- eerrorx ("%s: failed to create stopping dir: %s",
- applet, strerror (errno));
+ eerrorx("%s: superuser access required", applet);
+ eerrorx("%s: failed to create stopping dir `%s': %s",
+ applet, RC_STOPPING, strerror(errno));
}
/* Build a list of all services to stop and then work out the
* correct order for stopping them */
- stop_services = rc_services_in_state (RC_SERVICE_STARTING);
-
- tmplist = rc_services_in_state (RC_SERVICE_INACTIVE);
- rc_strlist_join (&stop_services, tmplist);
- rc_strlist_free (tmplist);
-
- tmplist = rc_services_in_state (RC_SERVICE_STARTED);
- rc_strlist_join (&stop_services, tmplist);
- rc_strlist_free (tmplist);
-
- deporder = rc_deptree_depends (deptree, types_nua,
- (const char **) stop_services,
- runlevel, depoptions | RC_DEP_STOP);
-
- rc_strlist_free (stop_services);
- stop_services = deporder;
- deporder = NULL;
- rc_strlist_reverse (stop_services);
+ stop_services = rc_services_in_state(RC_SERVICE_STARTED);
+ tmplist = rc_services_in_state(RC_SERVICE_INACTIVE);
+ TAILQ_CONCAT(stop_services, tmplist);
+ free(tmplist);
+ tmplist = rc_services_in_state(RC_SERVICE_STARTING);
+ TAILQ_CONCAT(stop_services, tmplist);
+ free(tmplist);
+ rc_stringlist_sort(&stop_services);
+
+ types_n = rc_stringlist_new();
+ rc_stringlist_add(types_n, "needsme");
+
+ types_nua = rc_stringlist_new();
+ rc_stringlist_add(types_nua, "ineed");
+ rc_stringlist_add(types_nua, "iuse");
+ rc_stringlist_add(types_nua, "iafter");
+
+ tmplist = rc_deptree_depends(deptree, types_nua, stop_services,
+ runlevel, depoptions | RC_DEP_STOP);
+ rc_stringlist_free(stop_services);
+ stop_services = tmplist;
/* Load our list of coldplugged services */
- coldplugged_services = rc_services_in_state (RC_SERVICE_COLDPLUGGED);
- if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 &&
- strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
- strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0)
+ coldplugged_services = rc_services_in_state(RC_SERVICE_COLDPLUGGED);
+ if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 &&
+ strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
+ strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0)
{
/* We need to include the boot runlevel services if we're not in it */
- start_services = rc_services_in_runlevel (bootlevel);
+ start_services = rc_services_in_runlevel(bootlevel);
if (strcmp (newlevel ? newlevel : runlevel, bootlevel) != 0) {
- tmplist = rc_services_in_runlevel (newlevel ? newlevel : runlevel);
- rc_strlist_join (&start_services, tmplist);
- rc_strlist_free (tmplist);
+ tmplist = rc_services_in_runlevel(newlevel ? newlevel : runlevel);
+ TAILQ_CONCAT(start_services, tmplist);
+ free(tmplist);
}
- STRLIST_FOREACH (coldplugged_services, service, i)
- rc_strlist_add (&start_services, service);
+ TAILQ_FOREACH(service, coldplugged_services, entries)
+ rc_stringlist_addu(start_services, service->value);
}
/* Save our softlevel now */
if (going_down)
- rc_runlevel_set (newlevel);
+ rc_runlevel_set(newlevel);
- parallel = rc_conf_yesno ("rc_parallel");
+ parallel = rc_conf_yesno("rc_parallel");
/* Now stop the services that shouldn't be running */
- STRLIST_FOREACH (stop_services, service, i) {
- bool found = false;
- char *conf = NULL;
- char **stopdeps = NULL;
- char *svc1 = NULL;
- char *svc2 = NULL;
- int k;
-
- if (rc_service_state (service) & RC_SERVICE_STOPPED)
+ TAILQ_FOREACH_REVERSE(service, stop_services, rc_stringlist, entries) {
+ if (rc_service_state(service->value) & RC_SERVICE_STOPPED)
continue;
/* We always stop the service when in these runlevels */
if (going_down) {
- pid = rc_service_stop (service);
+ pid = rc_service_stop(service->value);
if (pid > 0 && ! parallel)
- rc_waitpid (pid);
+ rc_waitpid(pid);
continue;
}
/* If we're in the start list then don't bother stopping us */
- STRLIST_FOREACH (start_services, svc1, j)
- if (strcmp (svc1, service) == 0) {
- found = true;
+ TAILQ_FOREACH(svc1, start_services, entries)
+ if (strcmp (svc1->value, service->value) == 0)
break;
- }
- /* Unless we would use a different config file */
- if (found) {
- size_t len;
- if (! newlevel)
- continue;
-
- len = strlen (service) + strlen (runlevel) + 2;
- tmp = xmalloc (sizeof (char) * len);
- snprintf (tmp, len, "%s.%s", service, runlevel);
- conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
- found = exists (conf);
- CHAR_FREE (conf);
- CHAR_FREE (tmp);
- if (! found) {
- len = strlen (service) + strlen (newlevel) + 2;
- tmp = xmalloc (sizeof (char) * len);
- snprintf (tmp, len, "%s.%s", service, newlevel);
- conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
- found = exists (conf);
- CHAR_FREE (conf);
- CHAR_FREE (tmp);
- if (!found)
+ if (svc1) {
+ if (newlevel && strcmp(runlevel, newlevel) != 0) {
+ /* So we're in the start list. But we should
+ * be stopped if we have a runlevel
+ * configuration file for either the current
+ * or next so we use the correct one. */
+ if (! runlevel_config(service->value, runlevel) &&
+ ! runlevel_config(service->value, newlevel))
continue;
}
- } else {
- /* Allow coldplugged services not to be in the runlevels list */
- if (rc_service_state (service) & RC_SERVICE_COLDPLUGGED)
+ else
continue;
}
- /* We got this far! Or last check is to see if any any service that
- * going to be started depends on us */
- rc_strlist_add (&stopdeps, service);
- deporder = rc_deptree_depends (deptree, types_n,
- (const char **) stopdeps,
- runlevel, RC_DEP_STRICT);
- rc_strlist_free (stopdeps);
- stopdeps = NULL;
- found = false;
- STRLIST_FOREACH (deporder, svc1, j) {
- STRLIST_FOREACH (start_services, svc2, k)
- if (strcmp (svc1, svc2) == 0) {
- found = true;
+ /* We got this far! Or last check is to see if any any service
+ * that going to be started depends on us */
+ if (! svc1) {
+ tmplist = rc_stringlist_new();
+ rc_stringlist_add(tmplist, service->value);
+ deporder = rc_deptree_depends(deptree, types_n, tmplist,
+ runlevel, RC_DEP_STRICT);
+ rc_stringlist_free(tmplist);
+ svc2 = NULL;
+ TAILQ_FOREACH (svc1, deporder, entries) {
+ TAILQ_FOREACH(svc2, start_services, entries)
+ if (strcmp (svc1->value, svc2->value) == 0)
+ break;
+ if (svc2)
break;
- }
- if (found)
- break;
+ }
+ rc_stringlist_free(deporder);
+
+ if (svc2)
+ continue;
}
- rc_strlist_free (deporder);
- deporder = NULL;
/* After all that we can finally stop the blighter! */
- if (! found) {
- pid = rc_service_stop (service);
-
- if (pid > 0) {
- add_pid (pid);
- if (! parallel) {
- rc_waitpid (pid);
- remove_pid (pid);
- }
+ pid = rc_service_stop(service->value);
+ if (pid > 0) {
+ add_pid(pid);
+ if (! parallel) {
+ rc_waitpid(pid);
+ remove_pid(pid);
}
}
}
/* Wait for our services to finish */
- wait_for_services ();
+ wait_for_services();
/* Notify the plugins we have finished */
- rc_plugin_run (RC_HOOK_RUNLEVEL_STOP_OUT, runlevel);
+ rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_OUT, runlevel);
hook_out = 0;
- rmdir (RC_STOPPING);
+ rmdir(RC_STOPPING);
/* Store the new runlevel */
if (newlevel) {
- rc_runlevel_set (newlevel);
- free (runlevel);
- runlevel = xstrdup (newlevel);
- setenv ("RC_SOFTLEVEL", runlevel, 1);
+ rc_runlevel_set(newlevel);
+ free(runlevel);
+ runlevel = xstrdup(newlevel);
+ setenv("RC_RUNLEVEL", runlevel, 1);
}
/* Run the halt script if needed */
- if (strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
- strcmp (runlevel, RC_LEVEL_REBOOT) == 0)
+ if (strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
+ strcmp(runlevel, RC_LEVEL_REBOOT) == 0)
{
- rc_logger_close ();
- execl (HALTSH, HALTSH, runlevel, (char *) NULL);
- eerrorx ("%s: unable to exec `%s': %s",
- applet, HALTSH, strerror (errno));
+ rc_logger_close();
+ execl(HALTSH, HALTSH, runlevel, (char *) NULL);
+ eerrorx("%s: unable to exec `%s': %s",
+ applet, HALTSH, strerror(errno));
}
/* Single user is done now */
- if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0) {
- if (exists (INTERACTIVE))
- unlink (INTERACTIVE);
- sulogin (false);
+ if (strcmp(runlevel, RC_LEVEL_SINGLE) == 0) {
+ if (exists(INTERACTIVE))
+ unlink(INTERACTIVE);
+ sulogin(false);
}
- mkdir (RC_STARTING, 0755);
- rc_plugin_run (RC_HOOK_RUNLEVEL_START_IN, runlevel);
+ mkdir(RC_STARTING, 0755);
+ rc_plugin_run(RC_HOOK_RUNLEVEL_START_IN, runlevel);
hook_out = RC_HOOK_RUNLEVEL_START_OUT;
/* Re-add our coldplugged services if they stopped */
- STRLIST_FOREACH (coldplugged_services, service, i)
- rc_service_mark (service, RC_SERVICE_COLDPLUGGED);
+ TAILQ_FOREACH(service, coldplugged_services, entries)
+ rc_service_mark(service->value, RC_SERVICE_COLDPLUGGED);
/* Order the services to start */
- deporder = rc_deptree_depends (deptree, types_nua,
- (const char **) start_services,
- runlevel, depoptions | RC_DEP_START);
- rc_strlist_free (start_services);
+ rc_stringlist_sort(&start_services);
+ deporder = rc_deptree_depends(deptree, types_nua, start_services,
+ runlevel, depoptions | RC_DEP_START);
+ rc_stringlist_free(start_services);
start_services = deporder;
- deporder = NULL;
#ifdef __linux__
/* mark any services skipped as started */
- if (PREVLEVEL && strcmp (PREVLEVEL, "N") == 0) {
- if ((service = proc_getent ("noinitd"))) {
- char *p = service;
- char *token;
-
- while ((token = strsep (&p, ",")))
- rc_service_mark (token, RC_SERVICE_STARTED);
- free (service);
+ if (PREVLEVEL && strcmp(PREVLEVEL, "N") == 0) {
+ proc = p = proc_getent("noinitd");
+ if (proc) {
+ while ((token = strsep(&p, ",")))
+ rc_service_mark(token, RC_SERVICE_STARTED);
+ free(proc);
}
}
#endif
- STRLIST_FOREACH (start_services, service, i) {
- if (rc_service_state (service) & RC_SERVICE_STOPPED) {
+ TAILQ_FOREACH(service, start_services, entries) {
+ if (rc_service_state(service->value) & RC_SERVICE_STOPPED) {
if (! interactive)
- interactive = want_interactive ();
+ interactive = want_interactive();
if (interactive) {
interactive_retry:
- printf ("\n");
- einfo ("About to start the service %s", service);
- eindent ();
- einfo ("1) Start the service\t\t2) Skip the service");
- einfo ("3) Continue boot process\t\t4) Exit to shell");
- eoutdent ();
+ printf("\n");
+ einfo("About to start the service %s",
+ service->value);
+ eindent();
+ einfo("1) Start the service\t\t2) Skip the service");
+ einfo("3) Continue boot process\t\t4) Exit to shell");
+ eoutdent();
interactive_option:
- switch (read_key (true)) {
- case '1': break;
- case '2': continue;
- case '3': interactive = false; break;
- case '4': sulogin (true); goto interactive_retry;
- default: goto interactive_option;
+ switch (read_key(true)) {
+ case '1': break;
+ case '2': continue;
+ case '3': interactive = false; break;
+ case '4': sulogin(true); goto interactive_retry;
+ default: goto interactive_option;
}
}
- pid = rc_service_start (service);
+ pid = rc_service_start(service->value);
/* Remember the pid if we're running in parallel */
if (pid > 0) {
- add_pid (pid);
+ add_pid(pid);
if (! parallel) {
- rc_waitpid (pid);
- remove_pid (pid);
+ rc_waitpid(pid);
+ remove_pid(pid);
}
}
}
}
/* Wait for our services to finish */
- wait_for_services ();
+ wait_for_services();
- rc_plugin_run (RC_HOOK_RUNLEVEL_START_OUT, runlevel);
+ rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, runlevel);
hook_out = 0;
#ifdef __linux__
/* mark any services skipped as stopped */
- if (PREVLEVEL && strcmp (PREVLEVEL, "N") == 0) {
- if ((service = proc_getent ("noinitd"))) {
- char *p = service;
- char *token;
-
- while ((token = strsep (&p, ",")))
- rc_service_mark (token, RC_SERVICE_STOPPED);
- free (service);
+ if (PREVLEVEL && strcmp(PREVLEVEL, "N") == 0) {
+ proc = p = proc_getent("noinitd");
+ if (proc) {
+ while ((token = strsep(&p, ",")))
+ rc_service_mark(token, RC_SERVICE_STOPPED);
+ free(proc);
}
}
#endif
/* Store our interactive status for boot */
- if (interactive && strcmp (runlevel, bootlevel) == 0)
- mark_interactive ();
+ if (interactive && strcmp(runlevel, bootlevel) == 0)
+ mark_interactive();
else {
- if (exists (INTERACTIVE))
- unlink (INTERACTIVE);
+ if (exists(INTERACTIVE))
+ unlink(INTERACTIVE);
}
/* If we're in the boot runlevel and we regenerated our dependencies
* we need to delete them so that they are regenerated again in the
* default runlevel as they may depend on things that are now available */
- if (regen && strcmp (runlevel, bootlevel) == 0)
- unlink (RC_DEPTREE);
+ if (regen && strcmp(runlevel, bootlevel) == 0)
+ unlink(RC_DEPTREE_CACHE);
- return (EXIT_SUCCESS);
+ return EXIT_SUCCESS;
}