diff options
Diffstat (limited to 'src/openrc')
| -rw-r--r-- | src/openrc/meson.build | 4 | ||||
| -rw-r--r-- | src/openrc/rc.c | 137 | 
2 files changed, 121 insertions, 20 deletions
| diff --git a/src/openrc/meson.build b/src/openrc/meson.build index 9ab32ef4..3ad0d62b 100644 --- a/src/openrc/meson.build +++ b/src/openrc/meson.build @@ -1,6 +1,6 @@  executable('openrc',    ['rc.c', 'rc-logger.c', misc_c, plugin_c, usage_c, version_h], -  c_args : cc_branding_flags, +  c_args : [cc_branding_flags, cc_user_services_flags],    link_with: [libeinfo, librc],    dependencies: [dl_dep, util_dep],    include_directories: [incdir, einfo_incdir, rc_incdir], @@ -9,7 +9,7 @@ executable('openrc',  executable('rc',    ['rc.c', 'rc-logger.c', misc_c, plugin_c, usage_c, version_h], -  c_args : cc_branding_flags, +  c_args : [cc_branding_flags, cc_user_services_flags],    link_with: [libeinfo, librc],    dependencies: [dl_dep, util_dep],    include_directories: [incdir, einfo_incdir, rc_incdir], 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 | 
