Lines 79-94
Link Here
|
79 |
|
79 |
|
80 |
const char *applet = NULL; |
80 |
const char *applet = NULL; |
81 |
static char *runlevel; |
81 |
static char *runlevel; |
82 |
static RC_STRINGLIST *hotplugged_services; |
|
|
83 |
static RC_STRINGLIST *stop_services; |
84 |
static RC_STRINGLIST *start_services; |
85 |
static RC_STRINGLIST *types_n; |
86 |
static RC_STRINGLIST *types_nua; |
87 |
static RC_DEPTREE *deptree; |
88 |
static RC_HOOK hook_out; |
82 |
static RC_HOOK hook_out; |
89 |
|
|
|
90 |
struct termios *termios_orig = NULL; |
83 |
struct termios *termios_orig = NULL; |
91 |
|
|
|
92 |
RC_PIDLIST service_pids; |
84 |
RC_PIDLIST service_pids; |
93 |
|
85 |
|
94 |
static void |
86 |
static void |
Lines 113-120
Link Here
|
113 |
snprintf(path, l, RC_SVCDIR "/failed/%s", d->d_name); |
105 |
snprintf(path, l, RC_SVCDIR "/failed/%s", d->d_name); |
114 |
if (path) { |
106 |
if (path) { |
115 |
if (unlink(path)) |
107 |
if (unlink(path)) |
116 |
eerror("%s: unlink `%s': %s", |
108 |
eerror("%s: unlink `%s': %s", applet, path, strerror(errno)); |
117 |
applet, path, strerror(errno)); |
|
|
118 |
free(path); |
109 |
free(path); |
119 |
} |
110 |
} |
120 |
} |
111 |
} |
Lines 524-530
Link Here
|
524 |
} |
515 |
} |
525 |
|
516 |
|
526 |
static void |
517 |
static void |
527 |
do_stop_services(const char *newlevel, bool parallel, bool going_down) |
518 |
do_stop_services(const RC_STRINGLIST *types_n, const RC_STRINGLIST *start_services, |
|
|
519 |
const RC_STRINGLIST *stop_services, const RC_DEPTREE *deptree, |
520 |
const char *newlevel, bool parallel, bool going_down) |
528 |
{ |
521 |
{ |
529 |
pid_t pid; |
522 |
pid_t pid; |
530 |
RC_STRING *service, *svc1, *svc2; |
523 |
RC_STRING *service, *svc1, *svc2; |
Lines 581-588
Link Here
|
581 |
* be stopped if we have a runlevel |
574 |
* be stopped if we have a runlevel |
582 |
* configuration file for either the current |
575 |
* configuration file for either the current |
583 |
* or next so we use the correct one. */ |
576 |
* or next so we use the correct one. */ |
584 |
if (!runlevel_config(service->value,runlevel) && |
577 |
if (!runlevel_config(service->value, runlevel) && |
585 |
!runlevel_config(service->value,newlevel)) |
578 |
!runlevel_config(service->value, newlevel)) |
586 |
continue; |
579 |
continue; |
587 |
} |
580 |
} |
588 |
else |
581 |
else |
Lines 627-633
Link Here
|
627 |
} |
620 |
} |
628 |
|
621 |
|
629 |
static void |
622 |
static void |
630 |
do_start_services(bool parallel) |
623 |
do_start_services(const RC_STRINGLIST *start_services, bool parallel) |
631 |
{ |
624 |
{ |
632 |
RC_STRING *service; |
625 |
RC_STRING *service; |
633 |
pid_t pid; |
626 |
pid_t pid; |
Lines 754-759
Link Here
|
754 |
{ |
747 |
{ |
755 |
const char *bootlevel = NULL; |
748 |
const char *bootlevel = NULL; |
756 |
char *newlevel = NULL; |
749 |
char *newlevel = NULL; |
|
|
750 |
static RC_STRINGLIST *hotplugged_services; |
751 |
static RC_STRINGLIST *stop_services; |
752 |
static RC_STRINGLIST *start_services; |
753 |
static RC_STRINGLIST *types_n; |
754 |
static RC_STRINGLIST *types_nua; |
755 |
static RC_DEPTREE *deptree; |
757 |
RC_STRINGLIST *deporder = NULL; |
756 |
RC_STRINGLIST *deporder = NULL; |
758 |
RC_STRINGLIST *tmplist; |
757 |
RC_STRINGLIST *tmplist; |
759 |
RC_STRING *service; |
758 |
RC_STRING *service; |
Lines 893-898
Link Here
|
893 |
/* Now we start handling our children */ |
892 |
/* Now we start handling our children */ |
894 |
signal_setup(SIGCHLD, handle_signal); |
893 |
signal_setup(SIGCHLD, handle_signal); |
895 |
|
894 |
|
|
|
895 |
/* Are we heading for a shutdown or a transition to single user mode? */ |
896 |
if (newlevel && |
896 |
if (newlevel && |
897 |
(strcmp(newlevel, RC_LEVEL_SHUTDOWN) == 0 || |
897 |
(strcmp(newlevel, RC_LEVEL_SHUTDOWN) == 0 || |
898 |
strcmp(newlevel, RC_LEVEL_SINGLE) == 0)) |
898 |
strcmp(newlevel, RC_LEVEL_SINGLE) == 0)) |
Lines 972-979
Link Here
|
972 |
applet, RC_STOPPING, strerror(errno)); |
972 |
applet, RC_STOPPING, strerror(errno)); |
973 |
} |
973 |
} |
974 |
|
974 |
|
975 |
/* Build a list of all services to stop and then work out the |
975 |
/* Create a list of all services which we could stop (assuming |
976 |
* correct order for stopping them */ |
976 |
* they won't be active in the new or current runlevel) including |
|
|
977 |
* all those services which have been started, are inactive or |
978 |
* are currently starting. Clearly, some of these will be listed |
979 |
* in the new or current runlevel so we won't actually be stopping |
980 |
* them all. |
981 |
*/ |
977 |
stop_services = rc_services_in_state(RC_SERVICE_STARTED); |
982 |
stop_services = rc_services_in_state(RC_SERVICE_STARTED); |
978 |
tmplist = rc_services_in_state(RC_SERVICE_INACTIVE); |
983 |
tmplist = rc_services_in_state(RC_SERVICE_INACTIVE); |
979 |
TAILQ_CONCAT(stop_services, tmplist, entries); |
984 |
TAILQ_CONCAT(stop_services, tmplist, entries); |
Lines 990-1026
Link Here
|
990 |
rc_stringlist_add(types_nua, "iafter"); |
995 |
rc_stringlist_add(types_nua, "iafter"); |
991 |
|
996 |
|
992 |
if (stop_services) { |
997 |
if (stop_services) { |
993 |
tmplist = rc_deptree_depends(deptree, types_nua, stop_services, |
998 |
tmplist = rc_deptree_depends(deptree, types_nua, stop_services, runlevel, depoptions | RC_DEP_STOP); |
994 |
runlevel, depoptions | RC_DEP_STOP); |
|
|
995 |
rc_stringlist_free(stop_services); |
999 |
rc_stringlist_free(stop_services); |
996 |
stop_services = tmplist; |
1000 |
stop_services = tmplist; |
997 |
} |
1001 |
} |
998 |
|
1002 |
|
999 |
/* Load our list of start services */ |
1003 |
/* Create a list of all services which should be started for the new or |
|
|
1004 |
* current runlevel including those in boot, sysinit and hotplugged |
1005 |
* runlevels. Clearly, some of these will already be started so we |
1006 |
* won't actually be starting them all. |
1007 |
*/ |
1000 |
hotplugged_services = rc_services_in_state(RC_SERVICE_HOTPLUGGED); |
1008 |
hotplugged_services = rc_services_in_state(RC_SERVICE_HOTPLUGGED); |
1001 |
start_services = rc_services_in_runlevel_stacked(newlevel ? |
1009 |
start_services = rc_services_in_runlevel_stacked(newlevel ? newlevel : runlevel); |
1002 |
newlevel : runlevel); |
|
|
1003 |
if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && |
1010 |
if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && |
1004 |
strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SYSINIT) != 0) |
1011 |
strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SYSINIT) != 0) |
1005 |
{ |
1012 |
{ |
1006 |
tmplist = rc_services_in_runlevel(RC_LEVEL_SYSINIT); |
1013 |
tmplist = rc_services_in_runlevel(RC_LEVEL_SYSINIT); |
1007 |
TAILQ_CONCAT(start_services, tmplist, entries); |
1014 |
TAILQ_CONCAT(start_services, tmplist, entries); |
1008 |
free(tmplist); |
1015 |
free(tmplist); |
1009 |
if (strcmp(newlevel ? newlevel : runlevel, |
1016 |
// If we are NOT headed for the single-user runlevel... |
1010 |
RC_LEVEL_SINGLE) != 0) |
1017 |
if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0) |
1011 |
{ |
1018 |
{ |
1012 |
if (strcmp(newlevel ? newlevel : runlevel, |
1019 |
// If we are NOT headed for the boot runlevel... |
1013 |
bootlevel) != 0) |
1020 |
if (strcmp(newlevel ? newlevel : runlevel, bootlevel) != 0) |
1014 |
{ |
1021 |
{ |
1015 |
tmplist = rc_services_in_runlevel(bootlevel); |
1022 |
tmplist = rc_services_in_runlevel(bootlevel); |
1016 |
TAILQ_CONCAT(start_services, tmplist, entries); |
1023 |
TAILQ_CONCAT(start_services, tmplist, entries); |
1017 |
free(tmplist); |
1024 |
free(tmplist); |
1018 |
} |
1025 |
} |
1019 |
if (hotplugged_services) { |
1026 |
if (hotplugged_services) { |
1020 |
TAILQ_FOREACH(service, hotplugged_services, |
1027 |
TAILQ_FOREACH(service, hotplugged_services, entries) |
1021 |
entries) |
1028 |
rc_stringlist_addu(start_services, service->value); |
1022 |
rc_stringlist_addu(start_services, |
|
|
1023 |
service->value); |
1024 |
} |
1029 |
} |
1025 |
} |
1030 |
} |
1026 |
} |
1031 |
} |
Lines 1029-1042
Link Here
|
1029 |
|
1034 |
|
1030 |
/* Now stop the services that shouldn't be running */ |
1035 |
/* Now stop the services that shouldn't be running */ |
1031 |
if (stop_services && !nostop) |
1036 |
if (stop_services && !nostop) |
1032 |
do_stop_services(newlevel, parallel, going_down); |
1037 |
do_stop_services(types_n, start_services, stop_services, deptree, newlevel, parallel, going_down); |
1033 |
|
1038 |
|
1034 |
/* Wait for our services to finish */ |
1039 |
/* Wait for our services to finish */ |
1035 |
wait_for_services(); |
1040 |
wait_for_services(); |
1036 |
|
1041 |
|
1037 |
/* Notify the plugins we have finished */ |
1042 |
/* Notify the plugins we have finished */ |
1038 |
rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_OUT, |
1043 |
rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_OUT, going_down ? newlevel : runlevel); |
1039 |
going_down ? newlevel : runlevel); |
|
|
1040 |
hook_out = 0; |
1044 |
hook_out = 0; |
1041 |
|
1045 |
|
1042 |
rmdir(RC_STOPPING); |
1046 |
rmdir(RC_STOPPING); |
Lines 1065-1082
Link Here
|
1065 |
TAILQ_FOREACH(service, hotplugged_services, entries) |
1069 |
TAILQ_FOREACH(service, hotplugged_services, entries) |
1066 |
rc_service_mark(service->value, RC_SERVICE_HOTPLUGGED); |
1070 |
rc_service_mark(service->value, RC_SERVICE_HOTPLUGGED); |
1067 |
|
1071 |
|
1068 |
/* Order the services to start */ |
|
|
1069 |
if (start_services) { |
1070 |
rc_stringlist_sort(&start_services); |
1071 |
deporder = rc_deptree_depends(deptree, types_nua, |
1072 |
start_services, runlevel, |
1073 |
depoptions | RC_DEP_START); |
1074 |
rc_stringlist_free(start_services); |
1075 |
start_services = deporder; |
1076 |
} |
1077 |
|
1078 |
#ifdef __linux__ |
1072 |
#ifdef __linux__ |
1079 |
/* mark any services skipped as started */ |
1073 |
/* If the "noinit" parameter was passed on the kernel command line then |
|
|
1074 |
* mark the specified services as started so they will not be started |
1075 |
* by us. */ |
1080 |
proc = p = rc_proc_getent("noinit"); |
1076 |
proc = p = rc_proc_getent("noinit"); |
1081 |
if (proc) { |
1077 |
if (proc) { |
1082 |
while ((token = strsep(&p, ","))) |
1078 |
while ((token = strsep(&p, ","))) |
Lines 1085-1103
Link Here
|
1085 |
} |
1081 |
} |
1086 |
#endif |
1082 |
#endif |
1087 |
|
1083 |
|
1088 |
if (start_services) { |
1084 |
// If we have a list of services to start then... |
1089 |
do_start_services(parallel); |
1085 |
if (start_services) |
1090 |
/* FIXME: If we skip the boot runlevel and go straight |
1086 |
{ |
1091 |
* to default from sysinit, we should now re-evaluate our |
1087 |
// Get a list of the chained runlevels which compose the target runlevel |
1092 |
* start services + hotplugged services and call |
1088 |
RC_STRINGLIST *runlevel_chain = rc_stringlist_new(); |
1093 |
* do_start_services a second time. */ |
1089 |
rc_get_runlevel_chain(runlevel, runlevel_chain); |
|
|
1090 |
|
1091 |
// Loop through them in reverse order. |
1092 |
RC_STRING *rlevel; |
1093 |
TAILQ_FOREACH_REVERSE(rlevel, runlevel_chain, rc_stringlist, entries) |
1094 |
{ |
1095 |
// Get a list of all the services in that runlevel |
1096 |
RC_STRINGLIST *run_services = rc_services_in_runlevel(rlevel->value); |
1097 |
|
1098 |
// Start those services. |
1099 |
rc_stringlist_sort(&run_services); |
1100 |
deporder = rc_deptree_depends(deptree, types_nua, run_services, rlevel->value, depoptions | RC_DEP_START); |
1101 |
rc_stringlist_free(run_services); |
1102 |
run_services = deporder; |
1103 |
do_start_services(run_services, parallel); |
1094 |
|
1104 |
|
1095 |
/* Wait for our services to finish */ |
1105 |
/* Wait for our services to finish */ |
1096 |
wait_for_services(); |
1106 |
wait_for_services(); |
|
|
1107 |
|
1108 |
// Free the list of services, we're done with it. |
1109 |
rc_stringlist_free(run_services); |
1110 |
} |
1111 |
rc_stringlist_free(runlevel_chain); |
1097 |
} |
1112 |
} |
1098 |
|
1113 |
|
1099 |
#ifdef __linux__ |
1114 |
#ifdef __linux__ |
1100 |
/* mark any services skipped as stopped */ |
1115 |
/* If the "noinit" parameter was passed on the kernel command line then |
|
|
1116 |
* mark the specified services as stopped so that our records reflect |
1117 |
* reality. */ |
1101 |
proc = p = rc_proc_getent("noinit"); |
1118 |
proc = p = rc_proc_getent("noinit"); |
1102 |
if (proc) { |
1119 |
if (proc) { |
1103 |
while ((token = strsep(&p, ","))) |
1120 |
while ((token = strsep(&p, ","))) |