diff options
Diffstat (limited to 'src/openrc/rc.c')
-rw-r--r-- | src/openrc/rc.c | 137 |
1 files changed, 119 insertions, 18 deletions
diff --git a/src/openrc/rc.c b/src/openrc/rc.c index 36b2e2e2..dca94a7f 100644 --- a/src/openrc/rc.c +++ b/src/openrc/rc.c @@ -49,12 +49,20 @@ #include "helpers.h" const char *extraopts = NULL; -const char getoptstring[] = "a:no:s:S" getoptstring_COMMON; +const char getoptstring[] = "a:no:s:S" getoptstring_COMMON +#ifdef RC_USER_SERVICES +getoptstring_USER_SERVICES +#endif +; + const struct option longopts[] = { { "no-stop", 0, NULL, 'n' }, { "override", 1, NULL, 'o' }, { "service", 1, NULL, 's' }, { "sys", 0, NULL, 'S' }, +#ifdef RC_USER_SERVICES + longopts_USER_SERVICES +#endif longopts_COMMON }; const char * const longopts_help[] = { @@ -62,6 +70,9 @@ const char * const longopts_help[] = { "override the next runlevel to change into\nwhen leaving single user or boot runlevels", "runs the service specified with the rest\nof the arguments", "output the RC system type, if any", +#ifdef RC_USER_SERVICES + longopts_help_USER_SERVICES +#endif longopts_help_COMMON }; const char *usagestring = "" \ @@ -70,7 +81,8 @@ const char *usagestring = "" \ #define INITSH RC_LIBEXECDIR "/sh/init.sh" #define INITEARLYSH RC_LIBEXECDIR "/sh/init-early.sh" -#define INTERACTIVE RC_SVCDIR "/interactive" +#define INTERACTIVE_FILE "/interactive" +#define INTERACTIVE RC_SVCDIR INTERACTIVE_FILE #define DEVBOOT "/dev/.rcboot" @@ -95,16 +107,24 @@ clean_failed(void) DIR *dp; struct dirent *d; char *path; + char *svcdir = RC_SVCDIR; + char *failed_path; +#ifdef RC_USER_SERVICES + if (rc_is_user()) { + svcdir = rc_user_svcdir(); + } +#endif + xasprintf(&failed_path, "%s/%s", svcdir, "/failed"); /* Clean the failed services state dir now */ - if ((dp = opendir(RC_SVCDIR "/failed"))) { + if ((dp = opendir(failed_path))) { while ((d = readdir(dp))) { if (d->d_name[0] == '.' && (d->d_name[1] == '\0' || (d->d_name[1] == '.' && d->d_name[2] == '\0'))) continue; - xasprintf(&path, RC_SVCDIR "/failed/%s", d->d_name); + xasprintf(&path, "%s/%s", failed_path, d->d_name); if (unlink(path)) eerror("%s: unlink `%s': %s", applet, path, strerror(errno)); @@ -112,12 +132,24 @@ clean_failed(void) } closedir(dp); } + free(failed_path); +#ifdef RC_USER_SERVICES + if (rc_is_user()) { + free(svcdir); + } +#endif } static void cleanup(void) { RC_PID *p, *tmp; + char *rc_starting = RC_STARTING; + char *rc_stopping = RC_STOPPING; + +#ifdef RC_USER_SERVICES + char *user_svcdir; +#endif if (!rc_in_logger && !rc_in_plugin && applet && (strcmp(applet, "rc") == 0 || strcmp(applet, "openrc") == 0)) @@ -132,11 +164,27 @@ cleanup(void) free(termios_orig); } +#ifdef RC_USER_SERVICES + if (rc_is_user()) { + user_svcdir = rc_user_svcdir(); + xasprintf(&rc_starting, "%s/%s", user_svcdir, RC_STARTING_FOLDER); + xasprintf(&rc_stopping, "%s/%s", user_svcdir, RC_STOPPING_FOLDER); + free(user_svcdir); + } +#endif + /* Clean runlevel start, stop markers */ - rmdir(RC_STARTING); - rmdir(RC_STOPPING); + rmdir(rc_starting); + rmdir(rc_stopping); clean_failed(); rc_logger_close(); + +#ifdef RC_USER_SERVICES + if (rc_is_user()) { + free(rc_starting); + free(rc_stopping); + } +#endif } LIST_FOREACH_SAFE(p, &service_pids, entries, tmp) { @@ -211,9 +259,24 @@ want_interactive(void) static void mark_interactive(void) { - FILE *fp = fopen(INTERACTIVE, "w"); + FILE *fp; + char *interactive_path = INTERACTIVE; +#ifdef RC_USER_SERVICES + char *svcdir; + if (rc_is_user()) { + svcdir = rc_user_svcdir(); + xasprintf(&interactive_path, "%s/%s", svcdir, INTERACTIVE_FILE); + free(svcdir); + } +#endif + fp = fopen(interactive_path, "w"); if (fp) fclose(fp); +#ifdef RC_USER_SERVICES + if (rc_is_user()) { + free(interactive_path); + } +#endif } static void @@ -649,9 +712,18 @@ do_start_services(const RC_STRINGLIST *start_services, bool parallel) bool interactive = false; RC_SERVICE state; bool crashed = false; + char *interactive_path = INTERACTIVE; +#ifdef RC_USER_SERVICES + char *svcdir; + if (rc_is_user()) { + svcdir = rc_user_svcdir(); + xasprintf(&interactive_path, "%s/%s", svcdir, INTERACTIVE_FILE); + free(svcdir); + } +#endif if (!rc_yesno(getenv("EINFO_QUIET"))) - interactive = exists(INTERACTIVE); + interactive = exists(interactive_path); errno = 0; crashed = rc_conf_yesno("rc_crashed_start"); if (errno == ENOENT) @@ -710,10 +782,15 @@ do_start_services(const RC_STRINGLIST *start_services, bool parallel) strcmp(runlevel, getenv("RC_BOOTLEVEL")) == 0)) mark_interactive(); else { - if (exists(INTERACTIVE)) - unlink(INTERACTIVE); + if (exists(interactive_path)) + unlink(interactive_path); } +#ifdef RC_USER_SERVICES + if (rc_is_user()) { + free(interactive_path); + } +#endif } #ifdef RC_DEBUG @@ -754,10 +831,16 @@ int main(int argc, char **argv) int depoptions = RC_DEP_STRICT | RC_DEP_TRACE; char *krunlevel = NULL; char *pidstr = NULL; + char *rc_starting = RC_STARTING; + char *rc_stopping = RC_STOPPING; int opt; bool parallel; int regen = 0; bool nostop = false; +#ifdef RC_USER_SERVICES + char *user_svcdir = NULL; + char *user_sysconfdir = NULL; +#endif #ifdef __linux__ char *proc; char *p; @@ -784,11 +867,6 @@ int main(int argc, char **argv) if (chdir("/") == -1) eerror("chdir: %s", strerror(errno)); - /* Ensure our environment is pure - * Also, add our configuration to it */ - env_filter(); - env_config(); - /* complain about old configuration settings if they exist */ if (exists(RC_CONF_OLD)) { ewarn("%s still exists on your system and should be removed.", @@ -833,10 +911,18 @@ int main(int argc, char **argv) printf("%s\n", systype); exit(EXIT_SUCCESS); /* NOTREACHED */ +#ifdef RC_USER_SERVICES + case_RC_USER_SERVICES +#endif case_RC_COMMON_GETOPT } } + /* Ensure our environment is pure + * Also, add our configuration to it */ + env_filter(); + env_config(); + if (strcmp(applet, "rc") == 0) ewarn("rc is deprecated, please use openrc instead."); newlevel = argv[optind++]; @@ -858,6 +944,15 @@ int main(int argc, char **argv) setenv("RC_PID", pidstr, 1); free(pidstr); +#ifdef RC_USER_SERVICES + if (rc_is_user()) { + user_svcdir = rc_user_svcdir(); + xasprintf(&rc_stopping, "%s/%s", user_svcdir, RC_STOPPING_FOLDER); + xasprintf(&rc_starting, "%s/%s", user_svcdir, RC_STARTING_FOLDER); + free(user_svcdir); + } +#endif + /* Create a list of all services which should be started for the new or * current runlevel including those in boot, sysinit and hotplugged * runlevels. Clearly, some of these will already be started so we @@ -960,7 +1055,7 @@ int main(int argc, char **argv) /* Clean the failed services state dir */ 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': %s", @@ -1046,7 +1141,7 @@ int main(int argc, char **argv) going_down ? newlevel : runlevel); hook_out = 0; - rmdir(RC_STOPPING); + rmdir(rc_stopping); /* Store the new runlevel */ if (newlevel) { @@ -1063,7 +1158,7 @@ int main(int argc, char **argv) rc_logger_close(); #endif - mkdir(RC_STARTING, 0755); + mkdir(rc_starting, 0755); rc_plugin_run(RC_HOOK_RUNLEVEL_START_IN, runlevel); hook_out = RC_HOOK_RUNLEVEL_START_OUT; @@ -1111,6 +1206,12 @@ int main(int argc, char **argv) } rc_stringlist_free(runlevel_chain); } +#ifdef RC_USER_SERVICES + if (rc_is_user()) { + free(rc_stopping); + free(rc_starting); + } +#endif #ifdef __linux__ /* If the "noinit" parameter was passed on the kernel command line then |