Implement "want" dependency

The want dependency is similar to the use dependency. If a service
script, for example called service1, adds "want service2" to its depend
function, OpenRC will attempt to start service2, if it exists on the
system,  when service1 is started.

However, service1 will start regardless of the status of
service2.

X-Gentoo-Bug: 406021
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=406021
This commit is contained in:
Ian Stakenvicius 2015-10-26 15:20:58 -04:00 committed by William Hubbs
parent ddb895b355
commit 33d3f33b3c
7 changed files with 77 additions and 42 deletions

View File

@ -175,6 +175,8 @@ will refuse to stop until any services that need it have stopped.
.It Ic use .It Ic use
The service will attempt to start any services we use that have been added The service will attempt to start any services we use that have been added
to the runlevel. to the runlevel.
.It Ic want
The service will attempt to start any services we want.
.It Ic after .It Ic after
The service will start after these services and stop before these services. The service will start after these services and stop before these services.
.It Ic before .It Ic before

View File

@ -16,6 +16,9 @@ need() {
use() { use() {
[ -n "$*" ] && echo "$RC_SVCNAME iuse $*" >&3 [ -n "$*" ] && echo "$RC_SVCNAME iuse $*" >&3
} }
want() {
[ -n "$*" ] && echo "$RC_SVCNAME iwant $*" >&3
}
before() { before() {
[ -n "$*" ] && echo "$RC_SVCNAME ibefore $*" >&3 [ -n "$*" ] && echo "$RC_SVCNAME ibefore $*" >&3
} }

View File

@ -66,6 +66,9 @@ need() {
use() { use() {
[ -n "$*" ] && echo "use $*" [ -n "$*" ] && echo "use $*"
} }
want() {
[ -n "$*" ] && echo "want $*"
}
before() { before() {
[ -n "$*" ] && echo "before $*" [ -n "$*" ] && echo "before $*"
} }

View File

@ -192,7 +192,9 @@ valid_service(const char *runlevel, const char *service, const char *type)
if (!runlevel || if (!runlevel ||
strcmp(type, "ineed") == 0 || strcmp(type, "ineed") == 0 ||
strcmp(type, "needsme") == 0) strcmp(type, "needsme") == 0 ||
strcmp(type, "iwant") == 0 ||
strcmp(type, "wantsme") == 0)
return true; return true;
if (rc_service_in_runlevel(service, runlevel)) if (rc_service_in_runlevel(service, runlevel))
@ -543,6 +545,7 @@ rc_deptree_order(const RC_DEPTREE *deptree, const char *runlevel, int options)
types = rc_stringlist_new(); types = rc_stringlist_new();
rc_stringlist_add(types, "ineed"); rc_stringlist_add(types, "ineed");
rc_stringlist_add(types, "iuse"); rc_stringlist_add(types, "iuse");
rc_stringlist_add(types, "iwant");
rc_stringlist_add(types, "iafter"); rc_stringlist_add(types, "iafter");
services = rc_deptree_depends(deptree, types, list, runlevel, services = rc_deptree_depends(deptree, types, list, runlevel,
RC_DEP_STRICT | RC_DEP_TRACE | options); RC_DEP_STRICT | RC_DEP_TRACE | options);
@ -648,6 +651,7 @@ typedef struct deppair
static const DEPPAIR deppairs[] = { static const DEPPAIR deppairs[] = {
{ "ineed", "needsme" }, { "ineed", "needsme" },
{ "iuse", "usesme" }, { "iuse", "usesme" },
{ "iwant", "wantsme" },
{ "iafter", "ibefore" }, { "iafter", "ibefore" },
{ "ibefore", "iafter" }, { "ibefore", "iafter" },
{ "iprovide", "providedby" }, { "iprovide", "providedby" },
@ -844,6 +848,7 @@ rc_deptree_update(void)
/* If we're after something, remove us from the before list */ /* If we're after something, remove us from the before list */
if (strcmp(type, "iafter") == 0 || if (strcmp(type, "iafter") == 0 ||
strcmp(type, "ineed") == 0 || strcmp(type, "ineed") == 0 ||
strcmp(type, "iwant") == 0 ||
strcmp(type, "iuse") == 0) { strcmp(type, "iuse") == 0) {
if ((dt = get_deptype(depinfo, "ibefore"))) if ((dt = get_deptype(depinfo, "ibefore")))
rc_stringlist_delete(dt->services, depend); rc_stringlist_delete(dt->services, depend);
@ -957,6 +962,7 @@ rc_deptree_update(void)
/* Phase 5 - Remove broken before directives */ /* Phase 5 - Remove broken before directives */
types = rc_stringlist_new(); types = rc_stringlist_new();
rc_stringlist_add(types, "ineed"); rc_stringlist_add(types, "ineed");
rc_stringlist_add(types, "iwant");
rc_stringlist_add(types, "iuse"); rc_stringlist_add(types, "iuse");
rc_stringlist_add(types, "iafter"); rc_stringlist_add(types, "iafter");
TAILQ_FOREACH(depinfo, deptree, entries) { TAILQ_FOREACH(depinfo, deptree, entries) {

View File

@ -78,19 +78,23 @@ static const char *applet;
static char *service, *runlevel, *ibsave, *prefix; static char *service, *runlevel, *ibsave, *prefix;
static RC_DEPTREE *deptree; static RC_DEPTREE *deptree;
static RC_STRINGLIST *applet_list, *services, *tmplist; static RC_STRINGLIST *applet_list, *services, *tmplist;
static RC_STRINGLIST *restart_services, *need_services, *use_services; static RC_STRINGLIST *restart_services;
static RC_STRINGLIST *need_services;
static RC_STRINGLIST *use_services;
static RC_STRINGLIST *want_services;
static RC_HOOK hook_out; static RC_HOOK hook_out;
static int exclusive_fd = -1, master_tty = -1; static int exclusive_fd = -1, master_tty = -1;
static bool sighup, in_background, deps, dry_run; static bool sighup, in_background, deps, dry_run;
static pid_t service_pid; static pid_t service_pid;
static int signal_pipe[2] = { -1, -1 }; static int signal_pipe[2] = { -1, -1 };
static RC_STRINGLIST *deptypes_b; static RC_STRINGLIST *deptypes_b; /* broken deps */
static RC_STRINGLIST *deptypes_n; static RC_STRINGLIST *deptypes_n; /* needed deps */
static RC_STRINGLIST *deptypes_nu; static RC_STRINGLIST *deptypes_nw; /* need+want deps */
static RC_STRINGLIST *deptypes_nua; static RC_STRINGLIST *deptypes_nwu; /* need+want+use deps */
static RC_STRINGLIST *deptypes_m; static RC_STRINGLIST *deptypes_nwua; /* need+want+use+after deps */
static RC_STRINGLIST *deptypes_mua; static RC_STRINGLIST *deptypes_m; /* needed deps for stopping */
static RC_STRINGLIST *deptypes_mwua; /* need+want+use+after deps for stopping */
static void static void
handle_signal(int sig) handle_signal(int sig)
@ -237,14 +241,16 @@ cleanup(void)
#ifdef DEBUG_MEMORY #ifdef DEBUG_MEMORY
rc_stringlist_free(deptypes_b); rc_stringlist_free(deptypes_b);
rc_stringlist_free(deptypes_n); rc_stringlist_free(deptypes_n);
rc_stringlist_free(deptypes_nu); rc_stringlist_free(deptypes_nw);
rc_stringlist_free(deptypes_nua); rc_stringlist_free(deptypes_nwu);
rc_stringlist_free(deptypes_nwua);
rc_stringlist_free(deptypes_m); rc_stringlist_free(deptypes_m);
rc_stringlist_free(deptypes_mua); rc_stringlist_free(deptypes_mwua);
rc_deptree_free(deptree); rc_deptree_free(deptree);
rc_stringlist_free(restart_services); rc_stringlist_free(restart_services);
rc_stringlist_free(need_services); rc_stringlist_free(need_services);
rc_stringlist_free(use_services); rc_stringlist_free(use_services);
rc_stringlist_free(want_services);
rc_stringlist_free(services); rc_stringlist_free(services);
rc_stringlist_free(applet_list); rc_stringlist_free(applet_list);
rc_stringlist_free(tmplist); rc_stringlist_free(tmplist);
@ -530,22 +536,29 @@ setup_deptypes(void)
deptypes_n = rc_stringlist_new(); deptypes_n = rc_stringlist_new();
rc_stringlist_add(deptypes_n, "ineed"); rc_stringlist_add(deptypes_n, "ineed");
deptypes_nu = rc_stringlist_new(); deptypes_nw = rc_stringlist_new();
rc_stringlist_add(deptypes_nu, "ineed"); rc_stringlist_add(deptypes_nw, "ineed");
rc_stringlist_add(deptypes_nu, "iuse"); rc_stringlist_add(deptypes_nw, "iwant");
deptypes_nua = rc_stringlist_new(); deptypes_nwu = rc_stringlist_new();
rc_stringlist_add(deptypes_nua, "ineed"); rc_stringlist_add(deptypes_nwu, "ineed");
rc_stringlist_add(deptypes_nua, "iuse"); rc_stringlist_add(deptypes_nwu, "iwant");
rc_stringlist_add(deptypes_nua, "iafter"); rc_stringlist_add(deptypes_nwu, "iuse");
deptypes_nwua = rc_stringlist_new();
rc_stringlist_add(deptypes_nwua, "ineed");
rc_stringlist_add(deptypes_nwua, "iwant");
rc_stringlist_add(deptypes_nwua, "iuse");
rc_stringlist_add(deptypes_nwua, "iafter");
deptypes_m = rc_stringlist_new(); deptypes_m = rc_stringlist_new();
rc_stringlist_add(deptypes_m, "needsme"); rc_stringlist_add(deptypes_m, "needsme");
deptypes_mua = rc_stringlist_new(); deptypes_mwua = rc_stringlist_new();
rc_stringlist_add(deptypes_mua, "needsme"); rc_stringlist_add(deptypes_mwua, "needsme");
rc_stringlist_add(deptypes_mua, "usesme"); rc_stringlist_add(deptypes_mwua, "wantsme");
rc_stringlist_add(deptypes_mua, "beforeme"); rc_stringlist_add(deptypes_mwua, "usesme");
rc_stringlist_add(deptypes_mwua, "beforeme");
} }
static void static void
@ -631,7 +644,9 @@ svc_start_deps(void)
need_services = rc_deptree_depends(deptree, deptypes_n, need_services = rc_deptree_depends(deptree, deptypes_n,
applet_list, runlevel, depoptions); applet_list, runlevel, depoptions);
use_services = rc_deptree_depends(deptree, deptypes_nu, want_services = rc_deptree_depends(deptree, deptypes_nw,
applet_list, runlevel, depoptions);
use_services = rc_deptree_depends(deptree, deptypes_nwu,
applet_list, runlevel, depoptions); applet_list, runlevel, depoptions);
if (!rc_runlevel_starting()) { if (!rc_runlevel_starting()) {
@ -659,7 +674,7 @@ svc_start_deps(void)
return; return;
/* Now wait for them to start */ /* Now wait for them to start */
services = rc_deptree_depends(deptree, deptypes_nua, applet_list, services = rc_deptree_depends(deptree, deptypes_nwua, applet_list,
runlevel, depoptions); runlevel, depoptions);
/* We use tmplist to hold our scheduled by list */ /* We use tmplist to hold our scheduled by list */
tmplist = rc_stringlist_new(); tmplist = rc_stringlist_new();
@ -674,6 +689,7 @@ svc_start_deps(void)
state & RC_SERVICE_WASINACTIVE) state & RC_SERVICE_WASINACTIVE)
{ {
if (!rc_stringlist_find(need_services, svc->value) && if (!rc_stringlist_find(need_services, svc->value) &&
!rc_stringlist_find(want_services, svc->value) &&
!rc_stringlist_find(use_services, svc->value)) !rc_stringlist_find(use_services, svc->value))
continue; continue;
} }
@ -927,7 +943,7 @@ svc_stop_deps(RC_SERVICE state)
/* We now wait for other services that may use us and are /* We now wait for other services that may use us and are
* stopping. This is important when a runlevel stops */ * stopping. This is important when a runlevel stops */
services = rc_deptree_depends(deptree, deptypes_mua, applet_list, services = rc_deptree_depends(deptree, deptypes_mwua, applet_list,
runlevel, depoptions); runlevel, depoptions);
TAILQ_FOREACH(svc, services, entries) { TAILQ_FOREACH(svc, services, entries) {
if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) if (rc_service_state(svc->value) & RC_SERVICE_STOPPED)
@ -1298,8 +1314,10 @@ openrc_run(int argc, char **argv)
prefix = save; prefix = save;
} else if (strcmp(optarg, "ineed") == 0 || } else if (strcmp(optarg, "ineed") == 0 ||
strcmp(optarg, "iuse") == 0 || strcmp(optarg, "iuse") == 0 ||
strcmp(optarg, "iwant") == 0 ||
strcmp(optarg, "needsme") == 0 || strcmp(optarg, "needsme") == 0 ||
strcmp(optarg, "usesme") == 0 || strcmp(optarg, "usesme") == 0 ||
strcmp(optarg, "wantsme") == 0 ||
strcmp(optarg, "iafter") == 0 || strcmp(optarg, "iafter") == 0 ||
strcmp(optarg, "ibefore") == 0 || strcmp(optarg, "ibefore") == 0 ||
strcmp(optarg, "iprovide") == 0) strcmp(optarg, "iprovide") == 0)

View File

@ -343,6 +343,7 @@ rc_status(int argc, char **argv)
} }
needsme = rc_stringlist_new(); needsme = rc_stringlist_new();
rc_stringlist_add(needsme, "needsme"); rc_stringlist_add(needsme, "needsme");
rc_stringlist_add(needsme, "wantsme");
nservices = rc_stringlist_new(); nservices = rc_stringlist_new();
alist = rc_stringlist_new(); alist = rc_stringlist_new();
l = rc_stringlist_add(alist, ""); l = rc_stringlist_add(alist, "");
@ -365,7 +366,7 @@ rc_status(int argc, char **argv)
* be added to the list * be added to the list
*/ */
unsetenv("RC_SVCNAME"); unsetenv("RC_SVCNAME");
print_level("Dynamic", "needed"); print_level("Dynamic", "needed/wanted");
print_services(NULL, nservices); print_services(NULL, nservices);
print_level("Dynamic", "manual"); print_level("Dynamic", "manual");
print_services(NULL, services); print_services(NULL, services);

View File

@ -155,8 +155,8 @@ cleanup(void)
rc_stringlist_free(hotplugged_services); rc_stringlist_free(hotplugged_services);
rc_stringlist_free(stop_services); rc_stringlist_free(stop_services);
rc_stringlist_free(start_services); rc_stringlist_free(start_services);
rc_stringlist_free(types_n); rc_stringlist_free(types_nw);
rc_stringlist_free(types_nua); rc_stringlist_free(types_nwua);
rc_deptree_free(deptree); rc_deptree_free(deptree);
free(runlevel); free(runlevel);
#endif #endif
@ -519,7 +519,7 @@ runlevel_config(const char *service, const char *level)
} }
static void static void
do_stop_services(RC_STRINGLIST *types_n, RC_STRINGLIST *start_services, do_stop_services(RC_STRINGLIST *types_nw, RC_STRINGLIST *start_services,
const RC_STRINGLIST *stop_services, const RC_DEPTREE *deptree, const RC_STRINGLIST *stop_services, const RC_DEPTREE *deptree,
const char *newlevel, bool parallel, bool going_down) const char *newlevel, bool parallel, bool going_down)
{ {
@ -530,9 +530,10 @@ do_stop_services(RC_STRINGLIST *types_n, RC_STRINGLIST *start_services,
RC_STRINGLIST *nostop; RC_STRINGLIST *nostop;
bool crashed, nstop; bool crashed, nstop;
if (!types_n) { if (!types_nw) {
types_n = rc_stringlist_new(); types_nw = rc_stringlist_new();
rc_stringlist_add(types_n, "needsme"); rc_stringlist_add(types_nw, "needsme");
rc_stringlist_add(types_nw, "wantsme");
} }
crashed = rc_conf_yesno("rc_crashed_stop"); crashed = rc_conf_yesno("rc_crashed_stop");
@ -591,7 +592,7 @@ do_stop_services(RC_STRINGLIST *types_n, RC_STRINGLIST *start_services,
if (!svc1) { if (!svc1) {
tmplist = rc_stringlist_new(); tmplist = rc_stringlist_new();
rc_stringlist_add(tmplist, service->value); rc_stringlist_add(tmplist, service->value);
deporder = rc_deptree_depends(deptree, types_n, deporder = rc_deptree_depends(deptree, types_nw,
tmplist, newlevel ? newlevel : runlevel, tmplist, newlevel ? newlevel : runlevel,
RC_DEP_STRICT | RC_DEP_TRACE); RC_DEP_STRICT | RC_DEP_TRACE);
rc_stringlist_free(tmplist); rc_stringlist_free(tmplist);
@ -754,8 +755,8 @@ main(int argc, char **argv)
static RC_STRINGLIST *hotplugged_services; static RC_STRINGLIST *hotplugged_services;
static RC_STRINGLIST *stop_services; static RC_STRINGLIST *stop_services;
static RC_STRINGLIST *start_services; static RC_STRINGLIST *start_services;
static RC_STRINGLIST *types_n; static RC_STRINGLIST *types_nw;
static RC_STRINGLIST *types_nua; static RC_STRINGLIST *types_nwua;
static RC_DEPTREE *deptree; static RC_DEPTREE *deptree;
RC_STRINGLIST *deporder = NULL; RC_STRINGLIST *deporder = NULL;
RC_STRINGLIST *tmplist; RC_STRINGLIST *tmplist;
@ -996,13 +997,14 @@ main(int argc, char **argv)
if (stop_services) if (stop_services)
rc_stringlist_sort(&stop_services); rc_stringlist_sort(&stop_services);
types_nua = rc_stringlist_new(); types_nwua = rc_stringlist_new();
rc_stringlist_add(types_nua, "ineed"); rc_stringlist_add(types_nwua, "ineed");
rc_stringlist_add(types_nua, "iuse"); rc_stringlist_add(types_nwua, "iwant");
rc_stringlist_add(types_nua, "iafter"); rc_stringlist_add(types_nwua, "iuse");
rc_stringlist_add(types_nwua, "iafter");
if (stop_services) { if (stop_services) {
tmplist = rc_deptree_depends(deptree, types_nua, stop_services, tmplist = rc_deptree_depends(deptree, types_nwua, stop_services,
runlevel, depoptions | RC_DEP_STOP); runlevel, depoptions | RC_DEP_STOP);
rc_stringlist_free(stop_services); rc_stringlist_free(stop_services);
stop_services = tmplist; stop_services = tmplist;
@ -1047,7 +1049,7 @@ main(int argc, char **argv)
/* Now stop the services that shouldn't be running */ /* Now stop the services that shouldn't be running */
if (stop_services && !nostop) if (stop_services && !nostop)
do_stop_services(types_n, start_services, stop_services, deptree, newlevel, parallel, going_down); do_stop_services(types_nw, start_services, stop_services, deptree, newlevel, parallel, going_down);
/* Wait for our services to finish */ /* Wait for our services to finish */
wait_for_services(); wait_for_services();
@ -1109,7 +1111,7 @@ main(int argc, char **argv)
/* Start those services. */ /* Start those services. */
rc_stringlist_sort(&run_services); rc_stringlist_sort(&run_services);
deporder = rc_deptree_depends(deptree, types_nua, run_services, rlevel->value, depoptions | RC_DEP_START); deporder = rc_deptree_depends(deptree, types_nwua, run_services, rlevel->value, depoptions | RC_DEP_START);
rc_stringlist_free(run_services); rc_stringlist_free(run_services);
run_services = deporder; run_services = deporder;
do_start_services(run_services, parallel); do_start_services(run_services, parallel);