aboutsummaryrefslogtreecommitdiff
path: root/src/rc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rc')
-rw-r--r--src/rc/rc-plugin.c7
-rw-r--r--src/rc/rc.c524
-rw-r--r--src/rc/runscript.c195
-rw-r--r--src/rc/start-stop-daemon.c16
4 files changed, 394 insertions, 348 deletions
diff --git a/src/rc/rc-plugin.c b/src/rc/rc-plugin.c
index f0ee5a61..034f79d2 100644
--- a/src/rc/rc-plugin.c
+++ b/src/rc/rc-plugin.c
@@ -79,7 +79,7 @@ void rc_plugin_load(void)
DIR *dp;
struct dirent *d;
PLUGIN *plugin;
- char *p;
+ char file[PATH_MAX];
void *h;
int (*fptr)(RC_HOOK, const char *);
@@ -96,9 +96,8 @@ void rc_plugin_load(void)
if (d->d_name[0] == '.')
continue;
- p = rc_strcatpaths(RC_PLUGINDIR, d->d_name, NULL);
- h = dlopen(p, RTLD_LAZY);
- free(p);
+ snprintf(file, sizeof(file), RC_PLUGINDIR "/%s", d->d_name);
+ h = dlopen(file, RTLD_LAZY);
if (! h) {
eerror("dlopen: %s", dlerror());
continue;
diff --git a/src/rc/rc.c b/src/rc/rc.c
index d906870c..04b814e6 100644
--- a/src/rc/rc.c
+++ b/src/rc/rc.c
@@ -633,6 +633,116 @@ static void do_coldplug(void)
printf ("%s\n", ecolor(ECOLOR_NORMAL));
}
+static void do_newlevel(const char *newlevel)
+{
+ struct utsname uts;
+ const char *sys;
+#ifdef __linux__
+ char *cmd;
+#endif
+
+ if (strcmp(newlevel, RC_LEVEL_SYSINIT) == 0
+#ifndef PREFIX
+ && RUNLEVEL &&
+ (strcmp(RUNLEVEL, "S") == 0 ||
+ strcmp(RUNLEVEL, "1") == 0)
+#endif
+ )
+ {
+ /* OK, we're either in runlevel 1 or single user mode */
+
+ /* 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);
+
+ 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);
+#else
+ printf("%s %s (%s)",
+ uts.sysname,
+ uts.release,
+ uts.machine);
+#endif
+
+ if ((sys = rc_sys()))
+ printf(" [%s]", sys);
+
+ 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));
+
+ setenv("RC_SOFTLEVEL", newlevel, 1);
+ rc_plugin_run(RC_HOOK_RUNLEVEL_START_IN, newlevel);
+ hook_out = RC_HOOK_RUNLEVEL_START_OUT;
+ 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);
+ }
+#endif
+
+ /* Setup our coldplugged services now */
+ do_coldplug();
+
+ rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, newlevel);
+ hook_out = 0;
+
+ if (want_interactive())
+ mark_interactive();
+
+ exit(EXIT_SUCCESS);
+ } else if (strcmp(newlevel, RC_LEVEL_SINGLE) == 0) {
+#ifndef PREFIX
+ if (! RUNLEVEL ||
+ (strcmp(RUNLEVEL, "S") != 0 &&
+ strcmp(RUNLEVEL, "1") != 0))
+ {
+ /* Remember the current runlevel for when we come back */
+ set_ksoftlevel(runlevel);
+ single_user();
+ }
+#endif
+ } else if (strcmp(newlevel, RC_LEVEL_REBOOT) == 0) {
+ if (! RUNLEVEL ||
+ strcmp(RUNLEVEL, "6") != 0)
+ {
+ 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) {
+ if (! RUNLEVEL ||
+ strcmp(RUNLEVEL, "0") != 0)
+ {
+ rc_logger_close();
+ execl(SHUTDOWN, SHUTDOWN,
+#ifdef __linux__
+ "-h",
+#else
+ "-p",
+#endif
+ "now", (char *) NULL);
+ eerrorx("%s: unable to exec `" SHUTDOWN "': %s",
+ applet, strerror(errno));
+ }
+ }
+}
+
+
static bool runlevel_config(const char *service, const char *level)
{
char *init = rc_service_resolve(service);
@@ -651,6 +761,140 @@ static bool runlevel_config(const char *service, const char *level)
return retval;
}
+static void do_stop_services(const char *newlevel, bool going_down, bool parallel)
+{
+ pid_t pid;
+ RC_STRING *service, *svc1, *svc2;
+ RC_STRINGLIST *deporder, *tmplist;
+
+ if (! types_n) {
+ types_n = rc_stringlist_new();
+ rc_stringlist_add(types_n, "needsme");
+ }
+
+ 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->value);
+ if (pid > 0 && ! parallel)
+ rc_waitpid(pid);
+ continue;
+ }
+
+ /* If we're in the start list then don't bother stopping us */
+ TAILQ_FOREACH(svc1, start_services, entries)
+ if (strcmp (svc1->value, service->value) == 0)
+ break;
+
+ 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
+ continue;
+ }
+
+ /* 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;
+ }
+ rc_stringlist_free(deporder);
+
+ if (svc2)
+ continue;
+ }
+
+ /* After all that we can finally stop the blighter! */
+ pid = rc_service_stop(service->value);
+ if (pid > 0) {
+ add_pid(pid);
+ if (! parallel) {
+ rc_waitpid(pid);
+ remove_pid(pid);
+ }
+ }
+ }
+}
+
+static void do_start_services(bool parallel)
+{
+ RC_STRING *service;
+ pid_t pid;
+ bool interactive = false;
+
+ if (! rc_yesno(getenv("EINFO_QUIET")))
+ interactive = exists(INTERACTIVE);
+
+ TAILQ_FOREACH(service, start_services, entries) {
+ if (rc_service_state(service->value) & RC_SERVICE_STOPPED) {
+ if (! interactive)
+ interactive = want_interactive();
+
+ if (interactive) {
+interactive_retry:
+ 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;
+ }
+ }
+
+ pid = rc_service_start(service->value);
+
+ /* Remember the pid if we're running in parallel */
+ if (pid > 0) {
+ add_pid(pid);
+
+ if (! parallel) {
+ rc_waitpid(pid);
+ remove_pid(pid);
+ }
+ }
+ }
+ }
+
+ /* Store our interactive status for boot */
+ if (interactive && strcmp(runlevel, getenv("RC_BOOTLEVEL")) == 0)
+ mark_interactive();
+ else {
+ if (exists(INTERACTIVE))
+ unlink(INTERACTIVE);
+ }
+
+}
+
#include "_usage.h"
#define getoptstring "o:" getoptstring_COMMON
static const struct option longopts[] = {
@@ -666,25 +910,18 @@ static const char * const longopts_help[] = {
int main(int argc, char **argv)
{
const char *bootlevel = NULL;
- const char *sys = rc_sys();
char *newlevel = NULL;
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;
char ksoftbuffer [PATH_MAX];
char pidstr[6];
int opt;
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;
@@ -698,8 +935,8 @@ int main(int argc, char **argv)
if (argc > 1 && (strcmp(argv[1], "--version") == 0)) {
printf("%s (OpenRC", applet);
- if (sys)
- printf(" [%s]", sys);
+ if ((bootlevel = rc_sys()))
+ printf(" [%s]", bootlevel);
printf(") " VERSION
#ifdef BRANDING
" (" BRANDING ")"
@@ -765,8 +1002,6 @@ int main(int argc, char **argv)
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
@@ -774,107 +1009,8 @@ int main(int argc, char **argv)
* rc shutdown
* rc reboot
*/
- if (newlevel) {
- if (strcmp(newlevel, RC_LEVEL_SYSINIT) == 0
-#ifndef PREFIX
- && RUNLEVEL &&
- (strcmp(RUNLEVEL, "S") == 0 ||
- strcmp(RUNLEVEL, "1") == 0)
-#endif
- )
- {
- /* OK, we're either in runlevel 1 or single user mode */
-
- /* 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);
-
- 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);
-#else
- printf("%s %s (%s)",
- uts.sysname,
- uts.release,
- uts.machine);
-#endif
-
- if (sys)
- printf(" [%s]", sys);
-
- 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));
-
- setenv("RC_SOFTLEVEL", newlevel, 1);
- rc_plugin_run(RC_HOOK_RUNLEVEL_START_IN, newlevel);
- hook_out = RC_HOOK_RUNLEVEL_START_OUT;
- 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);
- }
-#endif
-
- /* Setup our coldplugged services now */
- do_coldplug();
-
- rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, newlevel);
- hook_out = 0;
-
- if (want_interactive())
- mark_interactive();
-
- exit(EXIT_SUCCESS);
- } else if (strcmp(newlevel, RC_LEVEL_SINGLE) == 0) {
-#ifndef PREFIX
- if (! RUNLEVEL ||
- (strcmp(RUNLEVEL, "S") != 0 &&
- strcmp(RUNLEVEL, "1") != 0))
- {
- /* Remember the current runlevel for when we come back */
- set_ksoftlevel(runlevel);
- single_user();
- }
-#endif
- } else if (strcmp(newlevel, RC_LEVEL_REBOOT) == 0) {
- if (! RUNLEVEL ||
- strcmp(RUNLEVEL, "6") != 0)
- {
- 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) {
- if (! RUNLEVEL ||
- strcmp(RUNLEVEL, "0") != 0)
- {
- rc_logger_close();
- execl(SHUTDOWN, SHUTDOWN,
-#ifdef __linux__
- "-h",
-#else
- "-p",
-#endif
- "now", (char *) NULL);
- eerrorx("%s: unable to exec `" SHUTDOWN "': %s",
- applet, strerror(errno));
- }
- }
- }
+ if (newlevel)
+ do_newlevel(newlevel);
/* Now we start handling our children */
signal_setup(SIGCHLD, handle_signal);
@@ -946,15 +1082,23 @@ int main(int argc, char **argv)
* correct order for stopping them */
stop_services = rc_services_in_state(RC_SERVICE_STARTED);
tmplist = rc_services_in_state(RC_SERVICE_INACTIVE);
- TAILQ_CONCAT(stop_services, tmplist, entries);
- free(tmplist);
+ if (tmplist) {
+ if (stop_services) {
+ TAILQ_CONCAT(stop_services, tmplist, entries);
+ free(tmplist);
+ } else
+ stop_services = tmplist;
+ }
tmplist = rc_services_in_state(RC_SERVICE_STARTING);
- TAILQ_CONCAT(stop_services, tmplist, entries);
- free(tmplist);
+ if (tmplist) {
+ if (stop_services) {
+ TAILQ_CONCAT(stop_services, tmplist, entries);
+ free(tmplist);
+ } else
+ stop_services = 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");
@@ -976,12 +1120,18 @@ int main(int argc, char **argv)
start_services = rc_services_in_runlevel(bootlevel);
if (strcmp (newlevel ? newlevel : runlevel, bootlevel) != 0) {
tmplist = rc_services_in_runlevel(newlevel ? newlevel : runlevel);
- TAILQ_CONCAT(start_services, tmplist, entries);
- free(tmplist);
+ if (tmplist) {
+ if (start_services) {
+ TAILQ_CONCAT(start_services, tmplist, entries);
+ free(tmplist);
+ } else
+ start_services = tmplist;
+ }
}
- TAILQ_FOREACH(service, coldplugged_services, entries)
- rc_stringlist_addu(start_services, service->value);
+ if (coldplugged_services)
+ TAILQ_FOREACH(service, coldplugged_services, entries)
+ rc_stringlist_addu(start_services, service->value);
}
/* Save our softlevel now */
@@ -991,69 +1141,8 @@ int main(int argc, char **argv)
parallel = rc_conf_yesno("rc_parallel");
/* Now stop the services that shouldn't be running */
- 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->value);
- if (pid > 0 && ! parallel)
- rc_waitpid(pid);
- continue;
- }
-
- /* If we're in the start list then don't bother stopping us */
- TAILQ_FOREACH(svc1, start_services, entries)
- if (strcmp (svc1->value, service->value) == 0)
- break;
-
- 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
- continue;
- }
-
- /* 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;
- }
- rc_stringlist_free(deporder);
-
- if (svc2)
- continue;
- }
-
- /* After all that we can finally stop the blighter! */
- pid = rc_service_stop(service->value);
- if (pid > 0) {
- add_pid(pid);
- if (! parallel) {
- rc_waitpid(pid);
- remove_pid(pid);
- }
- }
- }
+ if (stop_services)
+ do_stop_services(newlevel, parallel, going_down);
/* Wait for our services to finish */
wait_for_services();
@@ -1094,15 +1183,18 @@ int main(int argc, char **argv)
hook_out = RC_HOOK_RUNLEVEL_START_OUT;
/* Re-add our coldplugged services if they stopped */
- TAILQ_FOREACH(service, coldplugged_services, entries)
- rc_service_mark(service->value, RC_SERVICE_COLDPLUGGED);
+ if (coldplugged_services)
+ TAILQ_FOREACH(service, coldplugged_services, entries)
+ rc_service_mark(service->value, RC_SERVICE_COLDPLUGGED);
/* Order the services to start */
- rc_stringlist_sort(&start_services);
- deporder = rc_deptree_depends(deptree, types_nua, start_services,
+ if (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;
+ rc_stringlist_free(start_services);
+ start_services = deporder;
+ }
#ifdef __linux__
/* mark any services skipped as started */
@@ -1116,47 +1208,13 @@ int main(int argc, char **argv)
}
#endif
- TAILQ_FOREACH(service, start_services, entries) {
- if (rc_service_state(service->value) & RC_SERVICE_STOPPED) {
- if (! interactive)
- interactive = want_interactive();
-
- if (interactive) {
-interactive_retry:
- 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;
- }
- }
-
- pid = rc_service_start(service->value);
-
- /* Remember the pid if we're running in parallel */
- if (pid > 0) {
- add_pid(pid);
+ if (start_services) {
+ do_start_services(parallel);
- if (! parallel) {
- rc_waitpid(pid);
- remove_pid(pid);
- }
- }
- }
+ /* Wait for our services to finish */
+ wait_for_services();
}
- /* Wait for our services to finish */
- wait_for_services();
-
rc_plugin_run(RC_HOOK_RUNLEVEL_START_OUT, runlevel);
hook_out = 0;
@@ -1172,14 +1230,6 @@ interactive_option:
}
#endif
- /* Store our interactive status for boot */
- if (interactive && strcmp(runlevel, bootlevel) == 0)
- mark_interactive();
- else {
- 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 */
diff --git a/src/rc/runscript.c b/src/rc/runscript.c
index e7a094f8..704d32fe 100644
--- a/src/rc/runscript.c
+++ b/src/rc/runscript.c
@@ -82,8 +82,8 @@ static RC_STRINGLIST *use_services = NULL;
static RC_STRINGLIST *services = NULL;
static RC_STRINGLIST *tmplist = NULL;
static char *service = NULL;
-static char *exclusive = NULL;
-static char *mtime_test = NULL;
+static char exclusive[PATH_MAX] = { '\0' };
+static char mtime_test[PATH_MAX] = { '\0' };
static RC_DEPTREE *deptree = NULL;
static char *runlevel = NULL;
static bool sighup = false;
@@ -212,7 +212,7 @@ static const char *const tests[] = {
};
static bool in_control()
{
- char *path;
+ char file[PATH_MAX];
time_t m;
time_t mtime;
int i = 0;
@@ -230,15 +230,12 @@ static bool in_control()
return false;
while (tests[i]) {
- path = rc_strcatpaths(RC_SVCDIR, tests[i], applet, (char *) NULL);
- if (exists(path)) {
- m = get_mtime(path, false);
- if (mtime < m && m != 0) {
- free(path);
+ snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s", tests[i], applet);
+ if (exists(file)) {
+ m = get_mtime(file, false);
+ if (mtime < m && m != 0)
return false;
- }
}
- free(path);
i++;
}
@@ -247,10 +244,11 @@ static bool in_control()
static void uncoldplug()
{
- char *cold = rc_strcatpaths(RC_SVCDIR, "coldplugged", applet, (char *) NULL);
- if (exists(cold) && unlink(cold) != 0)
- eerror("%s: unlink `%s': %s", applet, cold, strerror(errno));
- free(cold);
+ char file[PATH_MAX];
+
+ snprintf(file, sizeof(file), RC_SVCDIR "/coldplugged/%s", applet);
+ if (exists(file) && unlink(file) != 0)
+ eerror("%s: unlink `%s': %s", applet, file, strerror(errno));
}
static void start_services(RC_STRINGLIST *list) {
@@ -305,10 +303,10 @@ static void restore_state(void)
rc_service_mark(applet, RC_SERVICE_FAILED);
}
- if (exclusive)
+ if (*exclusive) {
unlink(exclusive);
- free(exclusive);
- exclusive = NULL;
+ *exclusive = '\0';
+ }
}
static void cleanup(void)
@@ -347,17 +345,12 @@ static void cleanup(void)
rc_stringlist_free(applet_list);
rc_stringlist_free(tmplist);
free (ibsave);
-
- if (mtime_test)
- {
- if (! rc_in_plugin)
- unlink(mtime_test);
- free(mtime_test);
- }
- free(exclusive);
free(service);
free(prefix);
free(runlevel);
+
+ if (*mtime_test && ! rc_in_plugin)
+ unlink(mtime_test);
}
static int write_prefix(const char *buffer, size_t bytes, bool *prefixed) {
@@ -580,37 +573,29 @@ static RC_SERVICE svc_status(void)
static void make_exclusive(void)
{
- char *path;
- size_t l;
-
/* 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 (! *exclusive)
+ snprintf(exclusive, sizeof(exclusive), RC_SVCDIR "/exclusive/%s",
+ applet);
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);
- l = strlen (path) + 16;
- mtime_test = xmalloc(sizeof (char) * l);
- snprintf(mtime_test, l, "%s.%d", path, getpid());
- free(path);
+ snprintf(mtime_test, sizeof(mtime_test), RC_SVCDIR "/exclusive/%s.%d", applet, getpid());
if (exists(mtime_test) && unlink(mtime_test) != 0) {
eerror("%s: unlink `%s': %s",
applet, mtime_test, strerror(errno));
- free(mtime_test);
- mtime_test = NULL;
+ *mtime_test = '\0';
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;
+ *mtime_test = '\0';
}
}
@@ -618,8 +603,7 @@ static void unlink_mtime_test(void)
{
if (unlink(mtime_test) != 0)
eerror("%s: unlink `%s': %s", applet, mtime_test, strerror(errno));
- free(mtime_test);
- mtime_test = NULL;
+ *mtime_test = '\0';
}
static void get_started_services(void)
@@ -627,8 +611,13 @@ static void get_started_services(void)
RC_STRINGLIST *tmp = rc_services_in_state(RC_SERVICE_INACTIVE);
rc_stringlist_free(restart_services);
restart_services = rc_services_in_state(RC_SERVICE_STARTED);
- TAILQ_CONCAT(restart_services, tmp, entries);
- free(tmp);
+ if (tmp) {
+ if (restart_services) {
+ TAILQ_CONCAT(restart_services, tmp, entries);
+ free(tmp);
+ } else
+ restart_services = tmp;
+ }
}
static void setup_types(void)
@@ -713,8 +702,8 @@ static void svc_start(bool deps)
services = rc_deptree_depends(deptree, types_b, applet_list,
runlevel, 0);
- if (TAILQ_FIRST(services)) {
- eerrorn ("ERROR: `%s' needs ", applet);
+ if (services && TAILQ_FIRST(services)) {
+ eerrorn("ERROR: `%s' needs ", applet);
first = true;
TAILQ_FOREACH(svc, services, entries) {
if (first)
@@ -733,7 +722,7 @@ static void svc_start(bool deps)
use_services = rc_deptree_depends(deptree, types_nu, applet_list,
runlevel, depoptions);
- if (! rc_runlevel_starting())
+ if (! rc_runlevel_starting() && use_services)
TAILQ_FOREACH(svc, use_services, entries)
if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) {
pid_t pid = rc_service_start(svc->value);
@@ -746,8 +735,7 @@ static void svc_start(bool deps)
runlevel, depoptions);
/* We use tmplist to hold our scheduled by list */
- tmplist = rc_stringlist_new();
-
+ tmplist = NULL;
TAILQ_FOREACH(svc, services, entries) {
RC_SERVICE svcs = rc_service_state(svc->value);
if (svcs & RC_SERVICE_STARTED)
@@ -768,14 +756,19 @@ static void svc_start(bool deps)
if (! svc_wait(svc->value))
eerror ("%s: timed out waiting for %s",
applet, svc->value);
+ if (! need_services)
+ continue;
if ((svcs = rc_service_state(svc->value)) & RC_SERVICE_STARTED)
continue;
TAILQ_FOREACH(svc2, need_services, entries) {
if (strcmp (svc->value, svc2->value) == 0) {
if (svcs & RC_SERVICE_INACTIVE ||
svcs & RC_SERVICE_WASINACTIVE)
- rc_stringlist_add(tmplist, svc->value);
- else
+ {
+ if (! tmplist)
+ tmplist = rc_stringlist_new();
+ rc_stringlist_add(tmplist, svc->value);
+ } else
eerrorx("ERROR: cannot start %s as"
" %s would not start",
applet, svc->value);
@@ -783,7 +776,7 @@ static void svc_start(bool deps)
}
}
- if (TAILQ_FIRST(tmplist)) {
+ if (tmplist && TAILQ_FIRST(tmplist)) {
/* Set the state now, then unlink our exclusive so that
our scheduled list is preserved */
rc_service_mark(service, RC_SERVICE_STOPPED);
@@ -813,14 +806,14 @@ static void svc_start(bool deps)
p += snprintf(p, len, "%s", svc->value);
}
free(tmp);
+ rc_stringlist_free(tmplist);
+ tmplist = NULL;
ewarnx("WARNING: %s is scheduled to start when %s has started",
- applet, tmp);
+ applet, tmp);
}
rc_stringlist_free(services);
services = NULL;
- rc_stringlist_free(tmplist);
- tmplist = NULL;
}
if (ibsave)
@@ -928,65 +921,73 @@ static void svc_stop(bool deps)
if (! types_m)
setup_types();
- tmplist = rc_stringlist_new();
+ tmplist = NULL;
services = rc_deptree_depends(deptree, types_m, applet_list,
runlevel, depoptions);
- TAILQ_FOREACH_REVERSE(svc, services, rc_stringlist, entries) {
- RC_SERVICE svcs = rc_service_state(svc->value);
- if (svcs & RC_SERVICE_STARTED ||
- svcs & RC_SERVICE_INACTIVE)
- {
- svc_wait(svc->value);
- svcs = rc_service_state(svc->value);
+ if (services) {
+ TAILQ_FOREACH_REVERSE(svc, services, rc_stringlist, entries) {
+ RC_SERVICE svcs = rc_service_state(svc->value);
if (svcs & RC_SERVICE_STARTED ||
- svcs & RC_SERVICE_INACTIVE)
+ svcs & RC_SERVICE_INACTIVE)
{
- pid_t pid = rc_service_stop(svc->value);
- if (! rc_conf_yesno("rc_parallel"))
- rc_waitpid(pid);
- rc_stringlist_add(tmplist, svc->value);
+ svc_wait(svc->value);
+ svcs = rc_service_state(svc->value);
+ if (svcs & RC_SERVICE_STARTED ||
+ svcs & RC_SERVICE_INACTIVE)
+ {
+ pid_t pid = rc_service_stop(svc->value);
+ if (! rc_conf_yesno("rc_parallel"))
+ rc_waitpid(pid);
+ if (! tmplist)
+ tmplist = rc_stringlist_new();
+ rc_stringlist_add(tmplist, svc->value);
+ }
}
}
+ rc_stringlist_free(services);
+ services = NULL;
}
- rc_stringlist_free(services);
- services = NULL;
- TAILQ_FOREACH(svc, tmplist, entries) {
- if (rc_service_state(svc->value) & RC_SERVICE_STOPPED)
- continue;
+ if (tmplist) {
+ TAILQ_FOREACH(svc, tmplist, entries) {
+ if (rc_service_state(svc->value) & RC_SERVICE_STOPPED)
+ continue;
- /* We used to loop 3 times here - maybe re-do this if needed */
- svc_wait(svc->value);
- if (! (rc_service_state(svc->value) & RC_SERVICE_STOPPED)) {
- if (rc_runlevel_stopping()) {
- /* If shutting down, we should stop even
- * if a dependant failed */
- if (runlevel &&
- (strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
- strcmp(runlevel, RC_LEVEL_REBOOT) == 0 ||
- strcmp(runlevel, RC_LEVEL_SINGLE) == 0))
- continue;
- rc_service_mark(service, RC_SERVICE_FAILED);
- }
+ /* We used to loop 3 times here - maybe re-do this if needed */
+ svc_wait(svc->value);
+ if (! (rc_service_state(svc->value) & RC_SERVICE_STOPPED)) {
+ if (rc_runlevel_stopping()) {
+ /* If shutting down, we should stop even
+ * if a dependant failed */
+ if (runlevel &&
+ (strcmp(runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
+ strcmp(runlevel, RC_LEVEL_REBOOT) == 0 ||
+ strcmp(runlevel, RC_LEVEL_SINGLE) == 0))
+ continue;
+ rc_service_mark(service, RC_SERVICE_FAILED);
+ }
- eerrorx("ERROR: cannot stop %s as %s is still up",
- applet, svc->value);
+ eerrorx("ERROR: cannot stop %s as %s is still up",
+ applet, svc->value);
+ }
}
+ rc_stringlist_free(tmplist);
+ tmplist = NULL;
}
- rc_stringlist_free(tmplist);
- tmplist = NULL;
/* We now wait for other services that may use us and are stopping
This is important when a runlevel stops */
services = rc_deptree_depends(deptree, types_mua, applet_list,
runlevel, depoptions);
- TAILQ_FOREACH(svc, services, entries) {
- if (rc_service_state(svc->value) & RC_SERVICE_STOPPED)
- continue;
- svc_wait(svc->value);
+ if (services) {
+ TAILQ_FOREACH(svc, services, entries) {
+ if (rc_service_state(svc->value) & RC_SERVICE_STOPPED)
+ continue;
+ svc_wait(svc->value);
+ }
+ rc_stringlist_free (services);
+ services = NULL;
}
- rc_stringlist_free (services);
- services = NULL;
}
/* If we're stopping localmount, set LC_ALL=C so that
@@ -1114,8 +1115,8 @@ int runscript(int argc, char **argv)
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));
- prefix = rc_strcatpaths("/dev/.rcboot", applet, (char *) NULL);
- symlink(service, prefix);
+ snprintf(exclusive, sizeof(exclusive), "/dev/.rcboot/%s", applet);
+ symlink(service, exclusive);
exit (EXIT_FAILURE);
}
#endif
diff --git a/src/rc/start-stop-daemon.c b/src/rc/start-stop-daemon.c
index 9b1c109e..6aec70b5 100644
--- a/src/rc/start-stop-daemon.c
+++ b/src/rc/start-stop-daemon.c
@@ -51,6 +51,7 @@
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
+#include <limits.h>
#include <grp.h>
#include <pwd.h>
#include <signal.h>
@@ -590,6 +591,7 @@ int start_stop_daemon(int argc, char **argv)
bool setuser = false;
char *p;
char *tmp;
+ char exec_file[PATH_MAX];
struct passwd *pw;
struct group *gr;
char line[130];
@@ -773,14 +775,13 @@ int start_stop_daemon(int argc, char **argv)
/* Validate that the binary exists if we are starting */
if (exec) {
- if (ch_root)
- tmp = rc_strcatpaths(ch_root, exec, (char *) NULL);
- else
+ if (ch_root) {
+ snprintf(exec_file, sizeof(exec_file), "%s/%s", ch_root, exec);
+ tmp = exec_file;
+ } else
tmp = exec;
if (start && ! exists(tmp)) {
eerror("%s: %s does not exist", applet, tmp);
- if (ch_root)
- free(tmp);
exit(EXIT_FAILURE);
}
@@ -807,15 +808,10 @@ int start_stop_daemon(int argc, char **argv)
applet, line + 2, exec);
eerror("%s: or you should specify a pidfile"
" or process name", applet);
- if (ch_root)
- free(tmp);
exit(EXIT_FAILURE);
}
}
}
-
- if (ch_root)
- free(tmp);
}
/* Add exec to our arguments */