aboutsummaryrefslogtreecommitdiff
path: root/src/librc/librc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/librc/librc.c')
-rw-r--r--src/librc/librc.c420
1 files changed, 368 insertions, 52 deletions
diff --git a/src/librc/librc.c b/src/librc/librc.c
index b3c98adb..9063b934 100644
--- a/src/librc/librc.c
+++ b/src/librc/librc.c
@@ -40,7 +40,8 @@
# include <sys/sysctl.h>
#endif
-#define RC_RUNLEVEL RC_SVCDIR "/softlevel"
+#define RC_RUNLEVEL_FOLDER "/softlevel"
+#define RC_RUNLEVEL RC_SVCDIR RC_RUNLEVEL_FOLDER
#ifndef S_IXUGO
# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
@@ -477,6 +478,7 @@ get_runlevel_chain(const char *runlevel, RC_STRINGLIST *level_list, RC_STRINGLIS
RC_STRINGLIST *dirs;
RC_STRING *d, *parent;
const char *nextlevel;
+ char *runlevel_dir = RC_RUNLEVELDIR;
/*
* If we haven't been passed a runlevel or a level list, or
@@ -498,7 +500,15 @@ get_runlevel_chain(const char *runlevel, RC_STRINGLIST *level_list, RC_STRINGLIS
* We can now do exactly the above procedure for our chained
* runlevels.
*/
- snprintf(path, sizeof(path), "%s/%s", RC_RUNLEVELDIR, runlevel);
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ char *user_sysconf = rc_user_sysconfdir();
+ xasprintf(&runlevel_dir, "%s/%s", user_sysconf, RC_USER_RUNLEVELS_FOLDER);
+ free(user_sysconf);
+ }
+#endif
+
+ snprintf(path, sizeof(path), "%s/%s", runlevel_dir, runlevel);
dirs = ls_dir(path, LS_DIR);
TAILQ_FOREACH(d, dirs, entries) {
nextlevel = d->value;
@@ -521,33 +531,78 @@ get_runlevel_chain(const char *runlevel, RC_STRINGLIST *level_list, RC_STRINGLIS
rc_stringlist_delete(ancestor_list, nextlevel);
}
rc_stringlist_free(dirs);
+
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ free(runlevel_dir);
+ }
+#endif
}
bool
rc_runlevel_starting(void)
{
- return exists(RC_STARTING);
+ char *rc_starting = RC_STARTING;
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ char *user_svcdir = rc_user_svcdir();
+ xasprintf(&rc_starting, "%s/%s", user_svcdir, RC_STARTING_FOLDER);
+ free(user_svcdir);
+ }
+#endif
+ return exists(rc_starting);
}
bool
rc_runlevel_stopping(void)
{
- return exists(RC_STOPPING);
+ char *rc_stopping = RC_STOPPING;
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ char *user_svcdir = rc_user_svcdir();
+ xasprintf(&rc_stopping, "%s/%s", user_svcdir, RC_STOPPING_FOLDER);
+ free(user_svcdir);
+ }
+#endif
+ return exists(rc_stopping);
}
RC_STRINGLIST *rc_runlevel_list(void)
{
- return ls_dir(RC_RUNLEVELDIR, LS_DIR);
+ char *runlevel_dir = RC_RUNLEVELDIR;
+ RC_STRINGLIST *runlevels;
+#ifdef RC_USER_SERVICES
+ char *user_sysconfdir;
+ if (rc_is_user()) {
+ user_sysconfdir = rc_user_sysconfdir();
+ xasprintf(&runlevel_dir, "%s/%s", user_sysconfdir, RC_USER_RUNLEVELS_FOLDER);
+ }
+#endif
+ runlevels = ls_dir(runlevel_dir, LS_DIR);
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ free(runlevel_dir);
+ }
+#endif
+ return runlevels;
}
char *
rc_runlevel_get(void)
{
FILE *fp;
- char *runlevel = NULL;
+ char *runlevel = NULL, *runlevel_path = RC_RUNLEVEL;
size_t i;
- if ((fp = fopen(RC_RUNLEVEL, "r"))) {
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ char *path = rc_user_svcdir();
+ xasprintf(&runlevel_path, "%s/%s", path, RC_RUNLEVEL_FOLDER);
+ free(path);
+ }
+#endif
+
+ if ((fp = fopen(runlevel_path, "r"))) {
runlevel = xmalloc(sizeof(char) * PATH_MAX);
if (fgets(runlevel, PATH_MAX, fp)) {
i = strlen(runlevel) - 1;
@@ -558,6 +613,13 @@ rc_runlevel_get(void)
fclose(fp);
}
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ free(runlevel_path);
+ }
+#endif
+
+
if (!runlevel || !*runlevel) {
free(runlevel);
runlevel = xstrdup(RC_LEVEL_SYSINIT);
@@ -569,12 +631,30 @@ rc_runlevel_get(void)
bool
rc_runlevel_set(const char *runlevel)
{
- FILE *fp = fopen(RC_RUNLEVEL, "w");
+ char *runlevel_path = RC_RUNLEVEL;
+ FILE *fp;
+
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ char *path = rc_user_svcdir();
+ xasprintf(&runlevel_path, "%s/%s", path, RC_RUNLEVEL_FOLDER);
+ free(path);
+ }
+#endif
+
+ fp = fopen(runlevel_path, "w");
if (!fp)
return false;
fprintf(fp, "%s", runlevel);
fclose(fp);
+
+
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ free(runlevel_path);
+ }
+#endif
return true;
}
@@ -587,7 +667,19 @@ rc_runlevel_exists(const char *runlevel)
if (!runlevel || strcmp(runlevel, "") == 0 || strcmp(runlevel, ".") == 0 ||
strcmp(runlevel, "..") == 0)
return false;
- snprintf(path, sizeof(path), "%s/%s", RC_RUNLEVELDIR, runlevel);
+
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ char *user_path = rc_user_sysconfdir();
+ snprintf(path, sizeof(path), "%s/%s/%s",
+ user_path, RC_USER_RUNLEVELS_FOLDER, runlevel);
+ } else {
+#endif
+ snprintf(path, sizeof(path), "%s/%s", RC_RUNLEVELDIR, runlevel);
+#ifdef RC_USER_SERVICES
+ }
+#endif
+
if (stat(path, &buf) == 0 && S_ISDIR(buf.st_mode))
return true;
return false;
@@ -597,11 +689,28 @@ bool
rc_runlevel_stack(const char *dst, const char *src)
{
char d[PATH_MAX], s[PATH_MAX];
+ char *runlevel_dir = RC_RUNLEVELDIR;
if (!rc_runlevel_exists(dst) || !rc_runlevel_exists(src))
return false;
+
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ char *user_sysconf = rc_user_sysconfdir();
+ xasprintf(&runlevel_dir, "%s/%s", user_sysconf, RC_USER_RUNLEVELS_FOLDER);
+ free(user_sysconf);
+ }
+#endif
+
snprintf(s, sizeof(s), "../%s", src);
- snprintf(d, sizeof(s), "%s/%s/%s", RC_RUNLEVELDIR, dst, src);
+ snprintf(d, sizeof(s), "%s/%s/%s", runlevel_dir, dst, src);
+
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ free(runlevel_dir);
+ }
+#endif
+
return (symlink(s, d) == 0 ? true : false);
}
@@ -609,8 +718,23 @@ bool
rc_runlevel_unstack(const char *dst, const char *src)
{
char path[PATH_MAX];
+ char *runlevel_dir = RC_RUNLEVELDIR;
+
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ char *user_sysconf = rc_user_sysconfdir();
+ xasprintf(&runlevel_dir, "%s/%s", user_sysconf, RC_USER_RUNLEVELS_FOLDER);
+ free(user_sysconf);
+ }
+#endif
+
+ snprintf(path, sizeof(path), "%s/%s/%s", runlevel_dir, dst, src);
- snprintf(path, sizeof(path), "%s/%s/%s", RC_RUNLEVELDIR, dst, src);
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ free(runlevel_dir);
+ }
+#endif
return (unlink(path) == 0 ? true : false);
}
@@ -632,9 +756,16 @@ rc_service_resolve(const char *service)
{
char buffer[PATH_MAX];
char file[PATH_MAX];
+ char *svcdir = RC_SVCDIR;
int r;
struct stat buf;
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ svcdir = rc_user_svcdir();
+ }
+#endif
+
if (!service)
return NULL;
@@ -642,14 +773,20 @@ rc_service_resolve(const char *service)
return xstrdup(service);
/* First check started services */
- snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s", "started", service);
+ snprintf(file, sizeof(file), "%s/%s/%s", svcdir, "started", service);
if (lstat(file, &buf) || !S_ISLNK(buf.st_mode)) {
- snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
- "inactive", service);
+ snprintf(file, sizeof(file), "%s/%s/%s",
+ svcdir, "inactive", service);
if (lstat(file, &buf) || !S_ISLNK(buf.st_mode))
*file = '\0';
}
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ free(svcdir);
+ }
+#endif
+
if (*file) {
memset(buffer, 0, sizeof(buffer));
r = readlink(file, buffer, sizeof(buffer)-1);
@@ -657,6 +794,24 @@ rc_service_resolve(const char *service)
return xstrdup(buffer);
}
+#ifdef RC_USER_SERVICES
+ /* If we're in user services mode, try user services*/
+ if (rc_is_user()) {
+ /* User defined services have preference to system provided */
+ char *user_sysconfdir = rc_user_sysconfdir();
+ snprintf(file, sizeof(file), "%s/%s/%s",
+ user_sysconfdir, RC_USER_INITDIR_FOLDER, service);
+ free(user_sysconfdir);
+ if (stat(file, &buf) == 0)
+ return xstrdup(file);
+
+ snprintf(file, sizeof(file), "%s/%s",
+ RC_SYS_USER_INITDIR, service);
+ if (stat(file, &buf) == 0)
+ return xstrdup(file);
+ }
+#endif
+
#ifdef RC_LOCAL_INITDIR
/* Nope, so lets see if the user has written it */
snprintf(file, sizeof(file), RC_LOCAL_INITDIR "/%s", service);
@@ -791,9 +946,24 @@ bool
rc_service_in_runlevel(const char *service, const char *runlevel)
{
char file[PATH_MAX];
+ char *runlevel_dir = RC_RUNLEVELDIR;
+
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ char *user_sysconf = rc_user_sysconfdir();
+ xasprintf(&runlevel_dir, "%s/%s", user_sysconf, RC_USER_RUNLEVELS_FOLDER);
+ free(user_sysconf);
+ }
+#endif
+ snprintf(file, sizeof(file), "%s/%s/%s",
+ runlevel_dir, runlevel, basename_c(service));
+
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ free(runlevel_dir);
+ }
+#endif
- snprintf(file, sizeof(file), RC_RUNLEVELDIR "/%s/%s",
- runlevel, basename_c(service));
return exists(file);
}
@@ -811,6 +981,12 @@ rc_service_mark(const char *service, const RC_SERVICE state)
RC_STRINGLIST *dirs;
RC_STRING *dir;
int serrno;
+ char *svcdir = RC_SVCDIR;
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ svcdir = rc_user_svcdir();
+ }
+#endif
if (!init)
return false;
@@ -822,8 +998,8 @@ rc_service_mark(const char *service, const RC_SERVICE state)
return false;
}
- snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
- rc_parse_service_state(state), base);
+ snprintf(file, sizeof(file), "%s/%s/%s",
+ svcdir,rc_parse_service_state(state), base);
if (exists(file))
unlink(file);
i = symlink(init, file);
@@ -849,15 +1025,16 @@ rc_service_mark(const char *service, const RC_SERVICE state)
s != RC_SERVICE_SCHEDULED) &&
(!skip_wasinactive || s != RC_SERVICE_WASINACTIVE))
{
- snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
- rc_service_state_names[i].name, base);
+ snprintf(file, sizeof(file), "%s/%s/%s",
+ svcdir, rc_service_state_names[i].name, base);
if (exists(file)) {
if ((state == RC_SERVICE_STARTING ||
state == RC_SERVICE_STOPPING) &&
s == RC_SERVICE_INACTIVE)
{
snprintf(was, sizeof(was),
- RC_SVCDIR "/%s/%s",
+ "%s/%s/%s",
+ svcdir,
rc_parse_service_state(RC_SERVICE_WASINACTIVE),
base);
if (symlink(init, was) == -1) {
@@ -879,19 +1056,19 @@ rc_service_mark(const char *service, const RC_SERVICE state)
state == RC_SERVICE_STOPPED ||
state == RC_SERVICE_INACTIVE)
{
- snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
- "exclusive", base);
+ snprintf(file, sizeof(file), "%s/%s/%s",
+ svcdir, "exclusive", base);
unlink(file);
}
/* Remove any options and daemons the service may have stored */
if (state == RC_SERVICE_STOPPED) {
- snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
- "options", base);
+ snprintf(file, sizeof(file), "%s/%s/%s",
+ svcdir, "options", base);
rm_dir(file, true);
- snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
- "daemons", base);
+ snprintf(file, sizeof(file), "%s/%s/%s",
+ svcdir, "daemons", base);
rm_dir(file, true);
rc_service_schedule_clear(service);
@@ -899,7 +1076,7 @@ rc_service_mark(const char *service, const RC_SERVICE state)
/* These are final states, so remove us from scheduled */
if (state == RC_SERVICE_STARTED || state == RC_SERVICE_STOPPED) {
- snprintf(file, sizeof(file), RC_SVCDIR "/%s", "scheduled");
+ snprintf(file, sizeof(file), "%s/%s", svcdir, "scheduled");
dirs = ls_dir(file, 0);
TAILQ_FOREACH(dir, dirs, entries) {
snprintf(was, sizeof(was), "%s/%s/%s",
@@ -927,10 +1104,16 @@ rc_service_state(const char *service)
RC_STRINGLIST *dirs;
RC_STRING *dir;
const char *base = basename_c(service);
+ char *svcdir = RC_SVCDIR;
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ svcdir = rc_user_svcdir();
+ }
+#endif
for (i = 0; rc_service_state_names[i].name; i++) {
- snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
- rc_service_state_names[i].name, base);
+ snprintf(file, sizeof(file), "%s/%s/%s",
+ svcdir, rc_service_state_names[i].name, base);
if (exists(file)) {
if (rc_service_state_names[i].state <= 0x10)
state = rc_service_state_names[i].state;
@@ -944,11 +1127,14 @@ rc_service_state(const char *service)
state |= RC_SERVICE_CRASHED;
}
if (state & RC_SERVICE_STOPPED) {
- dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
+ char *scheduled;
+ xasprintf(&scheduled, "%s/%s", svcdir, "/scheduled");
+ dirs = ls_dir(scheduled, 0);
+ free(scheduled);
TAILQ_FOREACH(dir, dirs, entries) {
snprintf(file, sizeof(file),
- RC_SVCDIR "/scheduled/%s/%s",
- dir->value, service);
+ "%s/scheduled/%s/%s",
+ svcdir, dir->value, service);
if (exists(file)) {
state |= RC_SERVICE_SCHEDULED;
break;
@@ -966,9 +1152,15 @@ rc_service_value_get(const char *service, const char *option)
char *buffer = NULL;
size_t len = 0;
char file[PATH_MAX];
+ char *svcdir = RC_SVCDIR;
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ svcdir = rc_user_svcdir();
+ }
+#endif
- snprintf(file, sizeof(file), RC_SVCDIR "/options/%s/%s",
- service, option);
+ snprintf(file, sizeof(file), "%s/options/%s/%s",
+ svcdir, service, option);
rc_getfile(file, &buffer, &len);
return buffer;
@@ -981,8 +1173,14 @@ rc_service_value_set(const char *service, const char *option,
FILE *fp;
char file[PATH_MAX];
char *p = file;
+ char *svcdir = RC_SVCDIR;
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ svcdir = rc_user_svcdir();
+ }
+#endif
- p += snprintf(file, sizeof(file), RC_SVCDIR "/options/%s", service);
+ p += snprintf(file, sizeof(file), "%s/options/%s", svcdir, service);
if (mkdir(file, 0755) != 0 && errno != EEXIST)
return false;
@@ -1006,13 +1204,19 @@ rc_service_schedule_start(const char *service, const char *service_to_start)
char *p = file;
char *init;
bool retval;
+ char *svcdir = RC_SVCDIR;
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ svcdir = rc_user_svcdir();
+ }
+#endif
/* service may be a provided service, like net */
if (!service || !rc_service_exists(service_to_start))
return false;
- p += snprintf(file, sizeof(file), RC_SVCDIR "/scheduled/%s",
- basename_c(service));
+ p += snprintf(file, sizeof(file), "%s/scheduled/%s",
+ svcdir, basename_c(service));
if (mkdir(file, 0755) != 0 && errno != EEXIST)
return false;
@@ -1028,9 +1232,15 @@ bool
rc_service_schedule_clear(const char *service)
{
char dir[PATH_MAX];
+ char *svcdir = RC_SVCDIR;
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ svcdir = rc_user_svcdir();
+ }
+#endif
- snprintf(dir, sizeof(dir), RC_SVCDIR "/scheduled/%s",
- basename_c(service));
+ snprintf(dir, sizeof(dir), "%s/scheduled/%s",
+ svcdir, basename_c(service));
if (!rm_dir(dir, true) && errno == ENOENT)
return true;
return false;
@@ -1041,6 +1251,7 @@ rc_services_in_runlevel(const char *runlevel)
{
char dir[PATH_MAX];
RC_STRINGLIST *list = NULL;
+ char *runlevel_dir = RC_RUNLEVELDIR;
if (!runlevel) {
#ifdef RC_PKG_INITDIR
@@ -1049,9 +1260,28 @@ rc_services_in_runlevel(const char *runlevel)
#ifdef RC_LOCAL_INITDIR
RC_STRINGLIST *local = ls_dir(RC_LOCAL_INITDIR, LS_INITD);
#endif
+#ifdef RC_USER_SERVICES
+ RC_STRINGLIST *local_user;
+ RC_STRINGLIST *sys_user;
+ char *user_sysconf;
+ char *user_initdir;
+ if (rc_is_user()) {
+ user_sysconf = rc_user_sysconfdir();
+ xasprintf(&user_initdir, "%s/%s", user_sysconf, RC_USER_INITDIR_FOLDER);
+
+ local_user = ls_dir(user_initdir, LS_INITD);
+ sys_user = ls_dir(RC_SYS_USER_INITDIR, LS_INITD);
+
+ list = rc_stringlist_new();
+ } else {
+#endif
list = ls_dir(RC_INITDIR, LS_INITD);
+#ifdef RC_USER_SERVICES
+ }
+#endif
+
#ifdef RC_PKG_INITDIR
TAILQ_CONCAT(list, pkg, entries);
rc_stringlist_free(pkg);
@@ -1060,13 +1290,37 @@ rc_services_in_runlevel(const char *runlevel)
TAILQ_CONCAT(list, local, entries);
rc_stringlist_free(local);
#endif
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ TAILQ_CONCAT(list, local_user, entries);
+ TAILQ_CONCAT(list, sys_user, entries);
+ rc_stringlist_free(local_user);
+ rc_stringlist_free(sys_user);
+ free(user_sysconf);
+ free(user_initdir);
+ }
+#endif
return list;
}
/* These special levels never contain any services */
if (strcmp(runlevel, RC_LEVEL_SINGLE) != 0) {
- snprintf(dir, sizeof(dir), RC_RUNLEVELDIR "/%s", runlevel);
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ char *user_sysconf = rc_user_sysconfdir();
+ xasprintf(&runlevel_dir, "%s/%s", user_sysconf, RC_USER_RUNLEVELS_FOLDER);
+ free(user_sysconf);
+ }
+#endif
+ snprintf(dir, sizeof(dir), "%s/%s", runlevel_dir, runlevel);
list = ls_dir(dir, LS_INITD);
+
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ free(runlevel_dir);
+ }
+#endif
+
}
if (!list)
list = rc_stringlist_new();
@@ -1099,9 +1353,16 @@ rc_services_in_state(RC_SERVICE state)
RC_STRING *d;
char dir[PATH_MAX];
char *p = dir;
+ char *svcdir = RC_SVCDIR;
- p += snprintf(dir, sizeof(dir), RC_SVCDIR "/%s",
- rc_parse_service_state(state));
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ svcdir = rc_user_svcdir();
+ }
+#endif
+
+ p += snprintf(dir, sizeof(dir), "%s/%s",
+ svcdir, rc_parse_service_state(state));
if (state != RC_SERVICE_SCHEDULED)
return ls_dir(dir, LS_INITD);
@@ -1120,6 +1381,13 @@ rc_services_in_state(RC_SERVICE state)
}
}
rc_stringlist_free(dirs);
+
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ free(svcdir);
+ }
+#endif
+
return list;
}
@@ -1131,7 +1399,15 @@ rc_service_add(const char *runlevel, const char *service)
char file[PATH_MAX];
char path[MAXPATHLEN] = { '\0' };
char binit[PATH_MAX];
+ char *runlevel_dir = RC_RUNLEVELDIR;
char *i;
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ char *user_sysconf = rc_user_sysconfdir();
+ xasprintf(&runlevel_dir, "%s/%s", user_sysconf, RC_USER_RUNLEVELS_FOLDER);
+ free(user_sysconf);
+ }
+#endif
if (!rc_runlevel_exists(runlevel)) {
errno = ENOENT;
@@ -1144,8 +1420,14 @@ rc_service_add(const char *runlevel, const char *service)
}
i = init = rc_service_resolve(service);
- snprintf(file, sizeof(file), RC_RUNLEVELDIR "/%s/%s",
- runlevel, basename_c(service));
+ snprintf(file, sizeof(file), "%s/%s/%s",
+ runlevel_dir, runlevel, basename_c(service));
+
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ free(runlevel_dir);
+ }
+#endif
/* We need to ensure that only things in /etc/init.d are added
* to the boot runlevel */
@@ -1172,9 +1454,25 @@ bool
rc_service_delete(const char *runlevel, const char *service)
{
char file[PATH_MAX];
+ char *runlevel_dir = RC_RUNLEVELDIR;
+
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ char *user_sysconf = rc_user_sysconfdir();
+ xasprintf(&runlevel_dir, "%s/%s", user_sysconf, RC_USER_RUNLEVELS_FOLDER);
+ free(user_sysconf);
+ }
+#endif
+
+ snprintf(file, sizeof(file), "%s/%s/%s",
+ runlevel_dir, runlevel, basename_c(service));
+
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ free(runlevel_dir);
+ }
+#endif
- snprintf(file, sizeof(file), RC_RUNLEVELDIR "/%s/%s",
- runlevel, basename_c(service));
if (unlink(file) == 0)
return true;
return false;
@@ -1183,14 +1481,25 @@ rc_service_delete(const char *runlevel, const char *service)
RC_STRINGLIST *
rc_services_scheduled_by(const char *service)
{
- RC_STRINGLIST *dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
+ RC_STRINGLIST *dirs;
RC_STRINGLIST *list = rc_stringlist_new();
RC_STRING *dir;
char file[PATH_MAX];
+ char *scheduled;
+ char *svcdir = RC_SVCDIR;
+
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ svcdir = rc_user_svcdir();
+ }
+#endif
+ xasprintf(&scheduled, "%s/%s", svcdir, "/scheduled");
+ dirs = ls_dir(scheduled, 0);
+ free(scheduled);
TAILQ_FOREACH(dir, dirs, entries) {
- snprintf(file, sizeof(file), RC_SVCDIR "/scheduled/%s/%s",
- dir->value, service);
+ snprintf(file, sizeof(file), "%s/scheduled/%s/%s",
+ svcdir, dir->value, service);
if (exists(file))
rc_stringlist_add(list, file);
}
@@ -1202,8 +1511,15 @@ RC_STRINGLIST *
rc_services_scheduled(const char *service)
{
char dir[PATH_MAX];
+ char *svcdir = RC_SVCDIR;
+
+#ifdef RC_USER_SERVICES
+ if (rc_is_user()) {
+ svcdir = rc_user_svcdir();
+ }
+#endif
- snprintf(dir, sizeof(dir), RC_SVCDIR "/scheduled/%s",
- basename_c(service));
+ snprintf(dir, sizeof(dir), "%s/scheduled/%s",
+ svcdir, basename_c(service));
return ls_dir(dir, LS_INITD);
}