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 750-755
Link Here
|
750 |
{ |
743 |
{ |
751 |
const char *bootlevel = NULL; |
744 |
const char *bootlevel = NULL; |
752 |
char *newlevel = NULL; |
745 |
char *newlevel = NULL; |
|
|
746 |
static RC_STRINGLIST *hotplugged_services; |
747 |
static RC_STRINGLIST *stop_services; |
748 |
static RC_STRINGLIST *start_services; |
749 |
static RC_STRINGLIST *types_n; |
750 |
static RC_STRINGLIST *types_nua; |
751 |
static RC_DEPTREE *deptree; |
752 |
|
753 |
RC_STRINGLIST *deporder = NULL; |
753 |
RC_STRINGLIST *deporder = NULL; |
754 |
RC_STRINGLIST *tmplist; |
754 |
RC_STRINGLIST *tmplist; |
755 |
RC_STRING *service; |
755 |
RC_STRING *service; |
Lines 885-890
Link Here
|
885 |
/* Now we start handling our children */ |
885 |
/* Now we start handling our children */ |
886 |
signal_setup(SIGCHLD, handle_signal); |
886 |
signal_setup(SIGCHLD, handle_signal); |
887 |
|
887 |
|
|
|
888 |
/* Are we heading for a shutdown or a transition to single user mode? */ |
888 |
if (newlevel && |
889 |
if (newlevel && |
889 |
(strcmp(newlevel, RC_LEVEL_SHUTDOWN) == 0 || |
890 |
(strcmp(newlevel, RC_LEVEL_SHUTDOWN) == 0 || |
890 |
strcmp(newlevel, RC_LEVEL_SINGLE) == 0)) |
891 |
strcmp(newlevel, RC_LEVEL_SINGLE) == 0)) |
Lines 964-971
Link Here
|
964 |
applet, RC_STOPPING, strerror(errno)); |
965 |
applet, RC_STOPPING, strerror(errno)); |
965 |
} |
966 |
} |
966 |
|
967 |
|
967 |
/* Build a list of all services to stop and then work out the |
968 |
/* Create a list of all services which we could stop (assuming |
968 |
* correct order for stopping them */ |
969 |
* they won't be active in the new or current runlevel) including |
|
|
970 |
* all those services which have been started, are inactive or |
971 |
* are currently starting. Clearly, some of these will be listed |
972 |
* in the new or current runlevel so we won't actually be stopping |
973 |
* them all. |
974 |
*/ |
969 |
stop_services = rc_services_in_state(RC_SERVICE_STARTED); |
975 |
stop_services = rc_services_in_state(RC_SERVICE_STARTED); |
970 |
tmplist = rc_services_in_state(RC_SERVICE_INACTIVE); |
976 |
tmplist = rc_services_in_state(RC_SERVICE_INACTIVE); |
971 |
TAILQ_CONCAT(stop_services, tmplist, entries); |
977 |
TAILQ_CONCAT(stop_services, tmplist, entries); |
Lines 982-1018
Link Here
|
982 |
rc_stringlist_add(types_nua, "iafter"); |
988 |
rc_stringlist_add(types_nua, "iafter"); |
983 |
|
989 |
|
984 |
if (stop_services) { |
990 |
if (stop_services) { |
985 |
tmplist = rc_deptree_depends(deptree, types_nua, stop_services, |
991 |
tmplist = rc_deptree_depends(deptree, types_nua, stop_services, runlevel, depoptions | RC_DEP_STOP); |
986 |
runlevel, depoptions | RC_DEP_STOP); |
|
|
987 |
rc_stringlist_free(stop_services); |
992 |
rc_stringlist_free(stop_services); |
988 |
stop_services = tmplist; |
993 |
stop_services = tmplist; |
989 |
} |
994 |
} |
990 |
|
995 |
|
991 |
/* Load our list of start services */ |
996 |
/* Create a list of all services which should be started for the new or |
|
|
997 |
* current runlevel including those in boot, sysinit and hotplugged |
998 |
* runlevels. Clearly, some of these will already be started so we |
999 |
* won't actually be starting them all. |
1000 |
*/ |
992 |
hotplugged_services = rc_services_in_state(RC_SERVICE_HOTPLUGGED); |
1001 |
hotplugged_services = rc_services_in_state(RC_SERVICE_HOTPLUGGED); |
993 |
start_services = rc_services_in_runlevel_stacked(newlevel ? |
1002 |
start_services = rc_services_in_runlevel_stacked(newlevel ? newlevel : runlevel); |
994 |
newlevel : runlevel); |
|
|
995 |
if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && |
1003 |
if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && |
996 |
strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SYSINIT) != 0) |
1004 |
strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SYSINIT) != 0) |
997 |
{ |
1005 |
{ |
998 |
tmplist = rc_services_in_runlevel(RC_LEVEL_SYSINIT); |
1006 |
tmplist = rc_services_in_runlevel(RC_LEVEL_SYSINIT); |
999 |
TAILQ_CONCAT(start_services, tmplist, entries); |
1007 |
TAILQ_CONCAT(start_services, tmplist, entries); |
1000 |
free(tmplist); |
1008 |
free(tmplist); |
1001 |
if (strcmp(newlevel ? newlevel : runlevel, |
1009 |
// If we are NOT headed for the single-user runlevel... |
1002 |
RC_LEVEL_SINGLE) != 0) |
1010 |
if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0) |
1003 |
{ |
1011 |
{ |
1004 |
if (strcmp(newlevel ? newlevel : runlevel, |
1012 |
// If we are NOT headed for the boot runlevel... |
1005 |
bootlevel) != 0) |
1013 |
if (strcmp(newlevel ? newlevel : runlevel, bootlevel) != 0) |
1006 |
{ |
1014 |
{ |
1007 |
tmplist = rc_services_in_runlevel(bootlevel); |
1015 |
tmplist = rc_services_in_runlevel(bootlevel); |
1008 |
TAILQ_CONCAT(start_services, tmplist, entries); |
1016 |
TAILQ_CONCAT(start_services, tmplist, entries); |
1009 |
free(tmplist); |
1017 |
free(tmplist); |
1010 |
} |
1018 |
} |
1011 |
if (hotplugged_services) { |
1019 |
if (hotplugged_services) { |
1012 |
TAILQ_FOREACH(service, hotplugged_services, |
1020 |
TAILQ_FOREACH(service, hotplugged_services, entries) |
1013 |
entries) |
1021 |
rc_stringlist_addu(start_services, service->value); |
1014 |
rc_stringlist_addu(start_services, |
|
|
1015 |
service->value); |
1016 |
} |
1022 |
} |
1017 |
} |
1023 |
} |
1018 |
} |
1024 |
} |
Lines 1021-1034
Link Here
|
1021 |
|
1027 |
|
1022 |
/* Now stop the services that shouldn't be running */ |
1028 |
/* Now stop the services that shouldn't be running */ |
1023 |
if (stop_services) |
1029 |
if (stop_services) |
1024 |
do_stop_services(newlevel, parallel, going_down); |
1030 |
do_stop_services(types_n, start_services, stop_services, deptree, newlevel, parallel, going_down); |
1025 |
|
1031 |
|
1026 |
/* Wait for our services to finish */ |
1032 |
/* Wait for our services to finish */ |
1027 |
wait_for_services(); |
1033 |
wait_for_services(); |
1028 |
|
1034 |
|
1029 |
/* Notify the plugins we have finished */ |
1035 |
/* Notify the plugins we have finished */ |
1030 |
rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_OUT, |
1036 |
rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_OUT, going_down ? newlevel : runlevel); |
1031 |
going_down ? newlevel : runlevel); |
|
|
1032 |
hook_out = 0; |
1037 |
hook_out = 0; |
1033 |
|
1038 |
|
1034 |
rmdir(RC_STOPPING); |
1039 |
rmdir(RC_STOPPING); |
Lines 1057-1074
Link Here
|
1057 |
TAILQ_FOREACH(service, hotplugged_services, entries) |
1062 |
TAILQ_FOREACH(service, hotplugged_services, entries) |
1058 |
rc_service_mark(service->value, RC_SERVICE_HOTPLUGGED); |
1063 |
rc_service_mark(service->value, RC_SERVICE_HOTPLUGGED); |
1059 |
|
1064 |
|
1060 |
/* Order the services to start */ |
|
|
1061 |
if (start_services) { |
1062 |
rc_stringlist_sort(&start_services); |
1063 |
deporder = rc_deptree_depends(deptree, types_nua, |
1064 |
start_services, runlevel, |
1065 |
depoptions | RC_DEP_START); |
1066 |
rc_stringlist_free(start_services); |
1067 |
start_services = deporder; |
1068 |
} |
1069 |
|
1070 |
#ifdef __linux__ |
1065 |
#ifdef __linux__ |
1071 |
/* mark any services skipped as started */ |
1066 |
/* If the "noinit" parameter was passed on the kernel command line then |
|
|
1067 |
* mark the specified services as started so they will not be started |
1068 |
* by us. */ |
1072 |
proc = p = rc_proc_getent("noinit"); |
1069 |
proc = p = rc_proc_getent("noinit"); |
1073 |
if (proc) { |
1070 |
if (proc) { |
1074 |
while ((token = strsep(&p, ","))) |
1071 |
while ((token = strsep(&p, ","))) |
Lines 1077-1095
Link Here
|
1077 |
} |
1074 |
} |
1078 |
#endif |
1075 |
#endif |
1079 |
|
1076 |
|
1080 |
if (start_services) { |
1077 |
// If we have a list of services to start then... |
1081 |
do_start_services(parallel); |
1078 |
if (start_services) |
1082 |
/* FIXME: If we skip the boot runlevel and go straight |
1079 |
{ |
1083 |
* to default from sysinit, we should now re-evaluate our |
1080 |
// Get a list of the chained runlevels which compose the target runlevel |
1084 |
* start services + hotplugged services and call |
1081 |
RC_STRINGLIST *runlevel_chain = rc_stringlist_new(); |
1085 |
* do_start_services a second time. */ |
1082 |
rc_get_runlevel_chain(runlevel, runlevel_chain); |
|
|
1083 |
|
1084 |
// Loop through them in reverse order. |
1085 |
RC_STRING *rlevel; |
1086 |
TAILQ_FOREACH_REVERSE(rlevel, runlevel_chain, rc_stringlist, entries) |
1087 |
{ |
1088 |
// Get a list of all the services in that runlevel |
1089 |
RC_STRINGLIST *run_services = rc_services_in_runlevel(rlevel->value); |
1090 |
|
1091 |
// Start those services. |
1092 |
rc_stringlist_sort(&run_services); |
1093 |
deporder = rc_deptree_depends(deptree, types_nua, run_services, rlevel->value, depoptions | RC_DEP_START); |
1094 |
rc_stringlist_free(run_services); |
1095 |
run_services = deporder; |
1096 |
do_start_services(run_services, parallel); |
1086 |
|
1097 |
|
1087 |
/* Wait for our services to finish */ |
1098 |
/* Wait for our services to finish */ |
1088 |
wait_for_services(); |
1099 |
wait_for_services(); |
|
|
1100 |
|
1101 |
// Free the list of services, we're done with it. |
1102 |
rc_stringlist_free(run_services); |
1103 |
} |
1104 |
rc_stringlist_free(runlevel_chain); |
1089 |
} |
1105 |
} |
1090 |
|
1106 |
|
1091 |
#ifdef __linux__ |
1107 |
#ifdef __linux__ |
1092 |
/* mark any services skipped as stopped */ |
1108 |
/* If the "noinit" parameter was passed on the kernel command line then |
|
|
1109 |
* mark the specified services as stopped so that our records reflect |
1110 |
* reality. */ |
1093 |
proc = p = rc_proc_getent("noinit"); |
1111 |
proc = p = rc_proc_getent("noinit"); |
1094 |
if (proc) { |
1112 |
if (proc) { |
1095 |
while ((token = strsep(&p, ","))) |
1113 |
while ((token = strsep(&p, ","))) |