2 * splash.c - Splash plugin for the Gentoo RC system.
4 * Copyright (c) 2007-2008, Michal Januszewski <spock@gentoo.org>
6 * Original splash plugin compatible with baselayout-1's splash-functions.sh
7 * written by Roy Marples <uberlord@gentoo.org>.
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License v2. See the file COPYING in the main directory of this archive for
22 #include <sys/ioctl.h>
29 /* Some queue.h implenetations don't have this macro */
31 #define TAILQ_CONCAT(head1, head2, field) do { \
32 if (!TAILQ_EMPTY(head2)) { \
33 *(head1)->tqh_last = (head2)->tqh_first; \
34 (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
35 (head1)->tqh_last = (head2)->tqh_last; \
36 TAILQ_INIT((head2)); \
41 #define SPLASH_CMD "export SPLASH_XRES='%d'; export SPLASH_YRES='%d';" \
42 "export SOFTLEVEL='%s'; export BOOTLEVEL='%s';" \
43 "export DEFAULTLEVEL='%s'; export svcdir=${RC_SVCDIR};" \
44 ". /sbin/splash-functions.sh; %s %s %s"
46 static char *bootlevel
= NULL
;
47 static char *defaultlevel
= NULL
;
48 static RC_STRINGLIST
*svcs
= NULL
;
49 static RC_STRINGLIST
*svcs_done
= NULL
;
50 static int svcs_cnt
= 0;
51 static int svcs_done_cnt
= 0;
52 static pid_t pid_daemon
= 0;
53 static fbspl_cfg_t
*config
= NULL
;
59 * Check whether a strlist contains a specific item.
61 static bool list_has(RC_STRINGLIST
*list
, const char *item
)
66 TAILQ_FOREACH(s
, list
, entries
)
67 if (strcmp(s
->value
, item
) == 0)
74 * Count the number of items in a strlist.
76 static int strlist_count(RC_STRINGLIST
*list
)
82 TAILQ_FOREACH(s
, list
, entries
)
89 * Create a strlist from a file pointer. Can be used
90 * to get a list of words printed by an app/script.
92 static void get_list_fp(RC_STRINGLIST
*list
, FILE *fp
)
98 while (fgets(buffer
, 512, fp
)) {
101 /* Remove the newline character */
102 if (p
[strlen(p
)-1] == '\n')
105 /* Strip leading spaces/tabs */
106 while ((*p
== ' ') || (*p
== '\t'))
109 /* Get entry - we do not want comments */
110 token
= strsep(&p
, "#");
111 if (!(token
&& (strlen(token
) > 1)))
114 while ((p
= strsep(&token
, " ")) != NULL
) {
116 rc_stringlist_add(list
, p
);
123 * Create a strlist from a file. Used for svcs_start/svcs_stop.
125 static void get_list(RC_STRINGLIST
*list
, const char *file
)
129 if (!(fp
= fopen(file
, "r"))) {
130 ewarn("%s: `%s': %s", __func__
, file
, strerror(errno
));
132 get_list_fp(list
, fp
);
138 * Get splash settings from /etc/conf.d/splash
140 static int splash_config_gentoo(fbspl_cfg_t
*cfg
, fbspl_type_t type
)
142 RC_STRINGLIST
*confd
;
145 confd
= rc_config_load("/etc/conf.d/splash");
147 t
= rc_config_value(confd
, "SPLASH_KDMODE");
149 if (!strcasecmp(t
, "graphics")) {
150 cfg
->kdmode
= KD_GRAPHICS
;
151 } else if (!strcasecmp(t
, "text")) {
152 cfg
->kdmode
= KD_TEXT
;
156 t
= rc_config_value(confd
, "SPLASH_PROFILE");
158 if (!strcasecmp(t
, "on") || !strcasecmp(t
, "yes"))
162 t
= rc_config_value(confd
, "SPLASH_TTY");
165 if (sscanf(t
, "%d", &i
) == 1 && i
> 0) {
170 t
= rc_config_value(confd
, "SPLASH_THEME");
172 fbsplash_acc_theme_set(t
);
174 t
= rc_config_value(confd
, "SPLASH_MODE_REQ");
176 if (!strcasecmp(t
, "verbose")) {
177 cfg
->reqmode
= FBSPL_MODE_VERBOSE
;
178 } else if (!strcasecmp(t
, "silent")) {
179 cfg
->reqmode
= FBSPL_MODE_VERBOSE
| FBSPL_MODE_SILENT
;
180 } else if (!strcasecmp(t
, "silentonly")) {
181 cfg
->reqmode
= FBSPL_MODE_SILENT
;
185 t
= rc_config_value(confd
, "SPLASH_VERBOSE_ON_ERRORS");
186 if (t
&& (!strcasecmp(t
, "on") || !strcasecmp(t
, "yes")))
191 t
= rc_config_value(confd
, "SPLASH_REBOOT_MESSAGE");
193 fbsplash_acc_message_set(t
);
197 t
= rc_config_value(confd
, "SPLASH_SHUTDOWN_MESSAGE");
199 fbsplash_acc_message_set(t
);
204 t
= rc_config_value(confd
, "SPLASH_BOOT_MESSAGE");
206 fbsplash_acc_message_set(t
);
210 t
= rc_config_value(confd
, "SPLASH_TEXTBOX");
212 if (!strcasecmp(t
, "on") || !strcasecmp(t
, "yes"))
213 cfg
->textbox_visible
= true;
216 t
= rc_config_value(confd
, "SPLASH_AUTOVERBOSE");
218 cfg
->autoverbose
= atoi(t
);
221 t
= rc_config_value(confd
, "SPLASH_EFFECTS");
225 while ((opt
= strsep(&t
, ",")) != NULL
) {
226 if (!strcmp(opt
, "fadein")) {
227 cfg
->effects
|= FBSPL_EFF_FADEIN
;
228 } else if (!strcmp(opt
, "fadeout")) {
229 cfg
->effects
|= FBSPL_EFF_FADEOUT
;
234 rc_stringlist_free(confd
);
239 * Call a function from /sbin/splash-functions.sh.
240 * This is rather slow, so use it only when really necessary.
242 static int splash_call(const char *cmd
, const char *arg1
, const char *arg2
)
246 char *soft
= getenv("RC_RUNLEVEL");
251 l
= strlen(SPLASH_CMD
) + strlen(soft
) + strlen(cmd
) + 10;
257 c
= malloc(sizeof(char*) * l
);
261 snprintf(c
, l
, SPLASH_CMD
, xres
, yres
,
262 arg1
? (strcmp(arg1
, RC_LEVEL_SYSINIT
) == 0 ? bootlevel
: soft
) : soft
,
263 bootlevel
, defaultlevel
, cmd
, arg1
? arg1
: "", arg2
? arg2
: "");
270 * Run a theme hook script.
272 static int splash_theme_hook(const char *name
, const char *type
, const char *arg1
)
279 fbsplash_profile("%s %s %s\n", type
, name
, arg1
);
281 fbsplash_profile("%s %s\n", type
, name
);
284 l
+= strlen(config
->theme
);
286 buf
= malloc(l
* sizeof(char*));
287 snprintf(buf
, l
, "/etc/splash/%s/scripts/%s-%s", config
->theme
, name
, type
);
288 if (stat(buf
, &st
) != 0) {
293 l
= splash_call(buf
, arg1
, NULL
);
299 * Update service state.
301 static int splash_svc_state(const char *name
, const char *state
, bool paint
)
304 splash_theme_hook(state
, "pre", name
);
307 if (!strcmp(state
, "svc_started")) {
308 fbsplash_send("log Service '%s' started.\n", name
);
309 } else if (!strcmp(state
, "svc_start_failed")) {
310 fbsplash_send("log Service '%s' failed to start.\n", name
);
311 } else if (!strcmp(state
, "svc_stopped")) {
312 fbsplash_send("log Service '%s' stopped.\n", name
);
313 } else if (!strcmp(state
, "svc_stop_failed")) {
314 fbsplash_send("log Service '%s' failed to stop.\n", name
);
317 fbsplash_send("update_svc %s %s\n", name
, state
);
320 fbsplash_send("paint\n");
321 splash_theme_hook(state
, "post", name
);
328 * Get the resolution that the silent splash will use.
330 static void splash_init_res()
332 struct fb_var_screeninfo var
;
335 if ((fh
= open("/dev/fb0", O_RDONLY
)) == -1)
336 if ((fh
= open("/dev/fb/0", O_RDONLY
)) == -1)
339 if (ioctl(fh
, FBIOGET_VSCREENINFO
, &var
))
344 fbsplash_get_res(config
->theme
, (int*)&var
.xres
, (int*)&var
.yres
);
350 * Init splash config variables and check that the splash daemon
353 static int splash_init(bool start
)
357 config
->verbosity
= FBSPL_VERB_QUIET
;
358 if (fbsplash_check_daemon(&pid_daemon
)) {
359 config
->verbosity
= FBSPL_VERB_NORMAL
;
363 config
->verbosity
= FBSPL_VERB_NORMAL
;
366 ewarn("%s: We already have a svcs list!", __func__
);
367 rc_stringlist_free(svcs
);
369 svcs
= rc_stringlist_new();
373 get_list(svcs
, FBSPLASH_CACHEDIR
"/svcs_start");
374 svcs_cnt
= strlist_count(svcs
);
376 svcs_done
= rc_services_in_state(RC_SERVICE_STARTED
);
378 tmp
= rc_services_in_state(RC_SERVICE_INACTIVE
);
379 if (svcs_done
&& tmp
) {
380 TAILQ_CONCAT(svcs_done
, tmp
, entries
);
385 tmp
= rc_services_in_state(RC_SERVICE_FAILED
);
386 if (svcs_done
&& tmp
) {
387 TAILQ_CONCAT(svcs_done
, tmp
, entries
);
392 tmp
= rc_services_in_state(RC_SERVICE_SCHEDULED
);
393 if (svcs_done
&& tmp
) {
394 TAILQ_CONCAT(svcs_done
, tmp
, entries
);
399 svcs_done_cnt
= strlist_count(svcs_done
);
400 /* .. or rebooting? */
402 get_list(svcs
, FBSPLASH_CACHEDIR
"/svcs_stop");
403 svcs_cnt
= strlist_count(svcs
);
405 svcs_done
= rc_services_in_state(RC_SERVICE_STARTED
);
407 tmp
= rc_services_in_state(RC_SERVICE_STARTING
);
408 if (svcs_done
&& tmp
) {
409 TAILQ_CONCAT(svcs_done
, tmp
, entries
);
414 tmp
= rc_services_in_state(RC_SERVICE_INACTIVE
);
415 if (svcs_done
&& tmp
) {
416 TAILQ_CONCAT(svcs_done
, tmp
, entries
);
421 svcs_done_cnt
= svcs_cnt
- strlist_count(svcs_done
);
430 * Handle the start/stop of a single service.
432 static int splash_svc_handle(const char *name
, const char *state
, bool skip
)
435 /* If we don't have any services, something must be broken.
436 * Bail out since there is nothing we can do about it. */
440 /* Don't process services twice. */
441 if (list_has(svcs_done
, name
))
445 svcs_done
= rc_stringlist_new();
446 rc_stringlist_add(svcs_done
, name
);
450 /* Recalculate progress */
451 config
->progress
= svcs_done_cnt
* FBSPL_PROGRESS_MAX
/ svcs_cnt
;
453 splash_theme_hook(state
, "pre", name
);
454 splash_svc_state(name
, state
, 0);
455 fbsplash_send("progress %d\n", config
->progress
);
456 fbsplash_send("paint\n");
457 splash_theme_hook(state
, "post", name
);
463 * Create a list of services that will be started during bootup.
465 int splash_svcs_start()
469 RC_STRINGLIST
*t
, *deporder
;
473 fp
= fopen(FBSPLASH_CACHEDIR
"/svcs_start", "w");
475 ewarn("%s: `%s': %s", __func__
, FBSPLASH_CACHEDIR
"/svcs_start", strerror(errno
));
479 if ((deptree
= rc_deptree_load()) == NULL
) {
480 eerror("%s: failed to load deptree", __func__
);
485 deporder
= rc_deptree_order(deptree
, bootlevel
, RC_DEP_START
);
487 /* Save what we've got so far to the svcs_start. */
490 TAILQ_FOREACH(s
, deporder
, entries
) {
493 fprintf(fp
, "%s", s
->value
);
499 deporder
= rc_deptree_order(deptree
, defaultlevel
, RC_DEP_START
);
501 /* Print the new services and skip ones that have already been started
502 * in the 'boot' runlevel. */
504 TAILQ_FOREACH(s
, deporder
, entries
) {
506 TAILQ_FOREACH(r
, t
, entries
) {
507 if (!strcmp(s
->value
, r
->value
)) {
513 fprintf(fp
, " %s", s
->value
);
518 rc_stringlist_free(deporder
);
519 rc_stringlist_free(t
);
520 rc_deptree_free(deptree
);
528 * Create a list of services that will be stopped during reboot/shutdown.
530 int splash_svcs_stop(const char *runlevel
)
533 RC_STRINGLIST
*deporder
;
538 fp
= fopen(FBSPLASH_CACHEDIR
"/svcs_stop", "w");
540 ewarn("%s: `%s': %s", __func__
, FBSPLASH_CACHEDIR
"/svcs_stop", strerror(errno
));
544 if ((deptree
= rc_deptree_load()) == NULL
) {
545 eerror("%s: failed to load deptree", __func__
);
550 deporder
= rc_deptree_order(deptree
, runlevel
, RC_DEP_STOP
);
554 TAILQ_FOREACH(s
, deporder
, entries
) {
557 fprintf(fp
, "%s", s
->value
);
562 rc_stringlist_free(deporder
);
563 rc_deptree_free(deptree
);
570 * Start the splash daemon during boot/reboot.
572 static int splash_start(const char *runlevel
)
579 /* Get a list of services that we'll have to handle. */
580 /* We're rebooting/shutting down. */
581 if (!strcmp(runlevel
, RC_LEVEL_SHUTDOWN
) || !strcmp(runlevel
, RC_LEVEL_REBOOT
)) {
582 if ((err
= fbsplash_cache_prep()))
584 splash_svcs_stop(runlevel
);
588 if ((err
= fbsplash_cache_prep()))
594 splash_theme_hook("rc_init", "pre", runlevel
);
596 /* Perform sanity checks (console=, CONSOLE= etc). */
597 if (fbsplash_check_sanity())
600 /* Start the splash daemon */
601 snprintf(buf
, 2048, "BOOT_MSG='%s' " FBSPLASH_DAEMON
" --theme=\"%s\" --pidfile=" FBSPLASH_PIDFILE
" --type=%s %s %s %s",
602 config
->message
, config
->theme
,
603 (config
->type
== fbspl_reboot
) ? "reboot" : ((config
->type
== fbspl_shutdown
) ? "shutdown" : "bootup"),
604 (config
->kdmode
== KD_GRAPHICS
) ? "--kdgraphics" : "",
605 (config
->textbox_visible
) ? "--textbox" : "",
606 (config
->effects
& (FBSPL_EFF_FADEOUT
| FBSPL_EFF_FADEIN
)) ? "--effects=fadeout,fadein" :
607 ((config
->effects
& FBSPL_EFF_FADEOUT
) ? "--effects=fadeout" :
608 ((config
->effects
& FBSPL_EFF_FADEIN
) ? "--effects=fadein" : "")));
611 if (err
== -1 || WEXITSTATUS(err
) != 0) {
612 eerror("Failed to start the splash daemon, error code %d", err
);
616 err
= splash_init(start
);
620 /* Set the initial state of all services. */
622 TAILQ_FOREACH(s
, svcs
, entries
)
623 splash_svc_state(s
->value
, start
? "svc_inactive_start" : "svc_inactive_stop", 0);
625 fbsplash_set_evdev();
626 fbsplash_send("set autoverbose %d\n", config
->autoverbose
);
627 fbsplash_send("set tty silent %d\n", config
->tty_s
);
628 fbsplash_send("set mode silent\n");
629 fbsplash_send("repaint\n");
634 * Stop the splash daemon.
636 static int splash_stop(const char *runlevel
)
638 char *save
[] = { "profile", "svcs_start", NULL
};
643 if (rc_service_state("xdm") & RC_SERVICE_STARTED
) {
644 fbsplash_send("exit staysilent\n");
646 fbsplash_send("exit\n");
648 snprintf(buf
, 128, "/proc/%d", pid_daemon
);
650 /* Wait up to 1.0s for the splash daemon to exit. */
651 while (stat(buf
, &st
) == 0 && cnt
< 100) {
656 /* Just to be sure we aren't stuck in a black ex-silent tty.. */
657 if (fbsplash_is_silent())
658 fbsplash_set_verbose(0);
660 /* If we don't get a runlevel argument, then we're being executed
661 * because of a rc-abort event and we don't save any data. */
662 if (runlevel
== NULL
) {
663 return fbsplash_cache_cleanup(NULL
);
665 return fbsplash_cache_cleanup(save
);
669 int rc_plugin_hook(RC_HOOK hook
, const char *name
)
672 fbspl_type_t type
= fbspl_bootup
;
677 runlev
= rc_runlevel_get();
678 if (!strcmp(runlev
, RC_LEVEL_REBOOT
))
680 else if (!strcmp(runlev
, RC_LEVEL_SHUTDOWN
))
681 type
= fbspl_shutdown
;
683 /* Get boot and default levels from env variables exported by RC.
684 * If unavailable, use the default ones. */
685 bootlevel
= getenv("RC_BOOTLEVEL");
686 defaultlevel
= getenv("RC_DEFAULTLEVEL");
688 /* We generally do nothing if we're in sysinit. Except if the
689 * autoconfig service is present, when we get a list of services
690 * that will be started by it and mark them as coldplugged. */
691 if (name
&& !strcmp(name
, RC_LEVEL_SYSINIT
)) {
692 if (hook
== RC_HOOK_RUNLEVEL_START_OUT
&& rc_service_in_runlevel("autoconfig", defaultlevel
)) {
697 fp
= popen("if [ -e /etc/init.d/autoconfig ]; then . /etc/init.d/autoconfig ; list_services ; fi", "r");
701 list
= rc_stringlist_new();
702 get_list_fp(list
, fp
);
703 TAILQ_FOREACH(s
, list
, entries
)
704 rc_service_mark(s
->value
, RC_SERVICE_COLDPLUGGED
);
706 rc_stringlist_free(list
);
711 /* Don't do anything if we're starting/stopping a service, but
712 * we aren't in the middle of a runlevel switch. */
713 if (!(rc_runlevel_starting() || rc_runlevel_stopping())) {
714 if (hook
!= RC_HOOK_RUNLEVEL_STOP_IN
&&
715 hook
!= RC_HOOK_RUNLEVEL_STOP_OUT
&&
716 hook
!= RC_HOOK_RUNLEVEL_START_IN
&&
717 hook
!= RC_HOOK_RUNLEVEL_START_OUT
)
720 /* We're starting/stopping a runlevel. Check whether we're
721 * actually booting/rebooting. */
722 if (rc_runlevel_starting() && strcmp(runlev
, bootlevel
) &&
723 strcmp(runlev
, defaultlevel
) && strcmp(runlev
, RC_LEVEL_SYSINIT
))
726 if (rc_runlevel_stopping() && strcmp(runlev
, bootlevel
) &&
727 strcmp(runlev
, RC_LEVEL_REBOOT
) && strcmp(runlev
, RC_LEVEL_SHUTDOWN
))
732 config
= fbsplash_lib_init(type
);
733 splash_config_gentoo(config
, type
);
734 fbsplash_parse_kcmdline(false);
737 /* Extremely weird.. should never happen. */
743 /* Don't do anything if we're not running in silent mode. */
744 if (!(config
->reqmode
& FBSPL_MODE_SILENT
))
748 case RC_HOOK_RUNLEVEL_STOP_IN
:
749 /* Start the splash daemon on reboot. The theme hook is called
750 * from splash_start(). */
751 if (strcmp(name
, RC_LEVEL_REBOOT
) == 0 || strcmp(name
, RC_LEVEL_SHUTDOWN
) == 0) {
752 if ((i
= splash_start(name
))) {
753 fbsplash_set_verbose(0);
757 if (rc_service_state("gpm") & RC_SERVICE_STARTED
) {
758 fbsplash_send("set gpm\n");
759 fbsplash_send("repaint\n");
762 splash_theme_hook("rc_init", "post", name
);
766 splash_theme_hook("rc_exit", "pre", name
);
767 splash_theme_hook("rc_exit", "post", name
);
768 fbsplash_lib_cleanup();
773 case RC_HOOK_RUNLEVEL_STOP_OUT
:
774 /* Make sure the progress indicator reaches 100%, even if
775 * something went wrong along the way. */
776 if (strcmp(name
, RC_LEVEL_REBOOT
) == 0 || strcmp(name
, RC_LEVEL_SHUTDOWN
) == 0) {
777 config
->verbosity
= FBSPL_VERB_QUIET
;
778 i
= fbsplash_check_daemon(&pid_daemon
);
779 config
->verbosity
= FBSPL_VERB_NORMAL
;
785 fbsplash_send("progress %d\n", FBSPL_PROGRESS_MAX
);
786 fbsplash_send("paint\n");
787 fbsplash_cache_cleanup(NULL
);
791 case RC_HOOK_RUNLEVEL_START_IN
:
792 /* Start the splash daemon during boot right after we finish
793 * sysinit and are entering the boot runlevel. Due to historical
794 * reasons, we simulate a full sysinit cycle here for the theme
796 if (strcmp(name
, bootlevel
) == 0) {
797 if ((i
= splash_start(RC_LEVEL_SYSINIT
)))
798 fbsplash_set_verbose(0);
799 splash_theme_hook("rc_init", "post", RC_LEVEL_SYSINIT
);
800 splash_theme_hook("rc_exit", "pre", RC_LEVEL_SYSINIT
);
801 splash_theme_hook("rc_exit", "post", RC_LEVEL_SYSINIT
);
803 splash_theme_hook("rc_init", "pre", name
);
804 splash_theme_hook("rc_init", "post", name
);
807 case RC_HOOK_RUNLEVEL_START_OUT
:
808 /* Stop the splash daemon after boot-up is finished. */
809 if (strcmp(name
, bootlevel
)) {
810 config
->verbosity
= FBSPL_VERB_QUIET
;
811 i
= fbsplash_check_daemon(&pid_daemon
);
812 config
->verbosity
= FBSPL_VERB_NORMAL
;
818 /* Make sure the progress indicator reaches 100%, even if
819 * something went wrong along the way. */
820 fbsplash_send("progress %d\n", FBSPL_PROGRESS_MAX
);
821 fbsplash_send("paint\n");
822 splash_theme_hook("rc_exit", "pre", name
);
823 i
= splash_stop(name
);
824 splash_theme_hook("rc_exit", "post", name
);
825 fbsplash_lib_cleanup();
830 case RC_HOOK_SERVICE_START_NOW
:
832 /* If we've been inactive, do nothing since the service has
833 * already been handled before it went inactive. */
834 if (rc_service_state(name
) & RC_SERVICE_WASINACTIVE
)
837 /* If we're starting or stopping a service, we're being called by
838 * runscript and thus have to reload our config. */
839 if (splash_init(true)) {
843 i
= splash_svc_handle(name
, "svc_start", skip
);
846 case RC_HOOK_SERVICE_START_OUT
:
847 /* If a service gets scheduled, we want to increment the progress
848 * bar (as it is no longer blocking boot completion). However,
849 * the service may actually start during boot (some time after
850 * being scheduled), so we don't want to increment the progress
851 * bar twice. The following if clause satisfies this by catching
852 * the first case but not the second. */
853 if ((rc_service_state(name
) & RC_SERVICE_SCHEDULED
) &&
854 !(rc_service_state(name
) & RC_SERVICE_STARTING
)) {
860 case RC_HOOK_SERVICE_START_DONE
:
861 config
->verbosity
= FBSPL_VERB_QUIET
;
862 i
= fbsplash_check_daemon(&pid_daemon
);
863 config
->verbosity
= FBSPL_VERB_NORMAL
;
869 if (!(rc_service_state(name
) & RC_SERVICE_FAILED
) &&
870 !(rc_service_state(name
) & RC_SERVICE_STOPPED
)) {
873 if (!strcmp(name
, "gpm")) {
877 /* Wait up to 0.25s for the GPM socket to appear. */
878 while (stat("/dev/gpmctl", &st
) == 0 && cnt
< 25) {
882 fbsplash_send("set gpm\n");
885 i
= splash_svc_state(name
, "svc_started", 1);
888 fbsplash_send("repaint\n");
891 i
= splash_svc_state(name
, "svc_start_failed", 1);
892 if (config
->vonerr
) {
893 fbsplash_set_verbose(0);
896 fbsplash_lib_cleanup();
900 case RC_HOOK_SERVICE_STOP_NOW
:
901 if (splash_init(false)) {
906 /* We need to stop localmount from unmounting our cache dir.
907 Luckily plugins can add to the unmount list. */
908 if (name
&& !strcmp(name
, "localmount")) {
909 char *umounts
= getenv("RC_NO_UMOUNTS");
912 fprintf(rc_environ_fd
, "RC_NO_UMOUNTS=%s:%s", umounts
, FBSPLASH_CACHEDIR
);
914 fprintf(rc_environ_fd
, "RC_NO_UMOUNTS=%s", FBSPLASH_CACHEDIR
);
916 i
= splash_svc_handle(name
, "svc_stop", false);
919 case RC_HOOK_SERVICE_STOP_DONE
:
920 config
->verbosity
= FBSPL_VERB_QUIET
;
921 i
= fbsplash_check_daemon(&pid_daemon
);
922 config
->verbosity
= FBSPL_VERB_NORMAL
;
928 if (rc_service_state(name
) & RC_SERVICE_STOPPED
) {
929 i
= splash_svc_state(name
, "svc_stopped", 1);
931 i
= splash_svc_state(name
, "svc_stop_failed", 1);
932 if (config
->vonerr
) {
933 fbsplash_set_verbose(0);
936 fbsplash_lib_cleanup();
941 i
= splash_stop(name
);
942 fbsplash_lib_cleanup();
951 rc_stringlist_free(svcs
);