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 #define SPLASH_CMD "export SPLASH_XRES='%d'; export SPLASH_YRES='%d';" \
30 "export SOFTLEVEL='%s'; export BOOTLEVEL='%s';" \
31 "export DEFAULTLEVEL='%s'; export svcdir=${RC_SVCDIR};" \
32 ". /sbin/splash-functions.sh; %s %s %s"
34 static char *bootlevel
= NULL
;
35 static char *defaultlevel
= NULL
;
36 static char **svcs
= NULL
;
37 static char **svcs_done
= NULL
;
38 static int svcs_cnt
= 0;
39 static int svcs_done_cnt
= 0;
40 static pid_t pid_daemon
= 0;
41 static fbspl_cfg_t
*config
= NULL
;
47 * Check whether a strlist contains a specific item.
49 static bool list_has(char **list
, const char *item
)
51 for (; list
&& *list
; list
++) {
52 if (strcmp(*list
, item
) == 0)
59 * Merge two strlists keeping them sorted.
61 static char** strlist_merge_sort(char **dest
, char **src
)
65 for (i
= 0; src
&& src
[i
]; i
++) {
66 rc_strlist_addsort(&dest
, src
[i
]);
72 * Count the number of items in a strlist.
74 static int strlist_count(char **list
)
78 for (c
= 0; list
&& *list
; list
++)
85 * Create a strlist from a file pointer. Can be used
86 * to get a list of words printed by an app/script.
88 static char **get_list_fp(char **list
, FILE *fp
)
94 while (fgets(buffer
, 512, fp
)) {
97 /* Remove the newline character */
98 if (p
[strlen(p
)-1] == '\n')
101 /* Strip leading spaces/tabs */
102 while ((*p
== ' ') || (*p
== '\t'))
105 /* Get entry - we do not want comments */
106 token
= strsep(&p
, "#");
107 if (!(token
&& (strlen(token
) > 1)))
110 while ((p
= strsep(&token
, " ")) != NULL
) {
112 rc_strlist_add(&list
, p
);
121 * Create a strlist from a file. Used for svcs_start/svcs_stop.
123 static char **get_list(char **list
, const char *file
)
127 if (!(fp
= fopen(file
, "r"))) {
128 ewarn("%s: `%s': %s", __func__
, file
, strerror(errno
));
132 list
= get_list_fp(list
, fp
);
139 * Get splash settings from /etc/conf.d/splash
141 static int splash_config_gentoo(fbspl_cfg_t
*cfg
, fbspl_type_t type
)
146 confd
= rc_config_load("/etc/conf.d/splash");
148 t
= rc_config_value(confd
, "SPLASH_KDMODE");
150 if (!strcasecmp(t
, "graphics")) {
151 cfg
->kdmode
= KD_GRAPHICS
;
152 } else if (!strcasecmp(t
, "text")) {
153 cfg
->kdmode
= KD_TEXT
;
157 t
= rc_config_value(confd
, "SPLASH_PROFILE");
159 if (!strcasecmp(t
, "on") || !strcasecmp(t
, "yes"))
163 t
= rc_config_value(confd
, "SPLASH_TTY");
166 if (sscanf(t
, "%d", &i
) == 1 && i
> 0) {
171 t
= rc_config_value(confd
, "SPLASH_THEME");
173 fbsplash_acc_theme_set(t
);
175 t
= rc_config_value(confd
, "SPLASH_MODE_REQ");
177 if (!strcasecmp(t
, "verbose")) {
178 cfg
->reqmode
= FBSPL_MODE_VERBOSE
;
179 } else if (!strcasecmp(t
, "silent")) {
180 cfg
->reqmode
= FBSPL_MODE_VERBOSE
| FBSPL_MODE_SILENT
;
181 } else if (!strcasecmp(t
, "silentonly")) {
182 cfg
->reqmode
= FBSPL_MODE_SILENT
;
186 t
= rc_config_value(confd
, "SPLASH_VERBOSE_ON_ERRORS");
187 if (t
&& (!strcasecmp(t
, "on") || !strcasecmp(t
, "yes")))
192 t
= rc_config_value(confd
, "SPLASH_REBOOT_MESSAGE");
194 fbsplash_acc_message_set(t
);
198 t
= rc_config_value(confd
, "SPLASH_SHUTDOWN_MESSAGE");
200 fbsplash_acc_message_set(t
);
205 t
= rc_config_value(confd
, "SPLASH_BOOT_MESSAGE");
207 fbsplash_acc_message_set(t
);
211 t
= rc_config_value(confd
, "SPLASH_TEXTBOX");
213 if (!strcasecmp(t
, "on") || !strcasecmp(t
, "yes"))
214 cfg
->textbox_visible
= true;
217 t
= rc_config_value(confd
, "SPLASH_AUTOVERBOSE");
219 cfg
->autoverbose
= atoi(t
);
222 t
= rc_config_value(confd
, "SPLASH_EFFECTS");
226 while ((opt
= strsep(&t
, ",")) != NULL
) {
227 if (!strcmp(opt
, "fadein")) {
228 cfg
->effects
|= FBSPL_EFF_FADEIN
;
229 } else if (!strcmp(opt
, "fadeout")) {
230 cfg
->effects
|= FBSPL_EFF_FADEOUT
;
235 rc_strlist_free(confd
);
240 * Call a function from /sbin/splash-functions.sh.
241 * This is rather slow, so use it only when really necessary.
243 static int splash_call(const char *cmd
, const char *arg1
, const char *arg2
)
247 char *soft
= getenv("RC_SOFTLEVEL");
252 l
= strlen(SPLASH_CMD
) + strlen(soft
) + strlen(cmd
) + 10;
258 c
= malloc(sizeof(char*) * l
);
262 snprintf(c
, l
, SPLASH_CMD
, xres
, yres
,
263 arg1
? (strcmp(arg1
, RC_LEVEL_SYSINIT
) == 0 ? bootlevel
: soft
) : soft
,
264 bootlevel
, defaultlevel
, cmd
, arg1
? arg1
: "", arg2
? arg2
: "");
271 * Run a theme hook script.
273 static int splash_theme_hook(const char *name
, const char *type
, const char *arg1
)
280 fbsplash_profile("%s %s %s\n", type
, name
, arg1
);
282 fbsplash_profile("%s %s\n", type
, name
);
285 l
+= strlen(config
->theme
);
287 buf
= malloc(l
* sizeof(char*));
288 snprintf(buf
, l
, "/etc/splash/%s/scripts/%s-%s", config
->theme
, name
, type
);
289 if (stat(buf
, &st
) != 0) {
294 l
= splash_call(buf
, arg1
, NULL
);
300 * Update service state.
302 static int splash_svc_state(const char *name
, const char *state
, bool paint
)
305 splash_theme_hook(state
, "pre", name
);
308 if (!strcmp(state
, "svc_started")) {
309 fbsplash_send("log Service '%s' started.\n", name
);
310 } else if (!strcmp(state
, "svc_start_failed")) {
311 fbsplash_send("log Service '%s' failed to start.\n", name
);
312 } else if (!strcmp(state
, "svc_stopped")) {
313 fbsplash_send("log Service '%s' stopped.\n", name
);
314 } else if (!strcmp(state
, "svc_stop_failed")) {
315 fbsplash_send("log Service '%s' failed to stop.\n", name
);
318 fbsplash_send("update_svc %s %s\n", name
, state
);
321 fbsplash_send("paint\n");
322 splash_theme_hook(state
, "post", name
);
329 * Get the resolution that the silent splash will use.
331 static void splash_init_res()
333 struct fb_var_screeninfo var
;
336 if ((fh
= open("/dev/fb0", O_RDONLY
)) == -1)
337 if ((fh
= open("/dev/fb/0", O_RDONLY
)) == -1)
340 if (ioctl(fh
, FBIOGET_VSCREENINFO
, &var
))
345 fbsplash_get_res(config
->theme
, (int*)&var
.xres
, (int*)&var
.yres
);
351 * Init splash config variables and check that the splash daemon
354 static int splash_init(bool start
)
358 config
->verbosity
= FBSPL_VERB_QUIET
;
359 if (fbsplash_check_daemon(&pid_daemon
)) {
360 config
->verbosity
= FBSPL_VERB_NORMAL
;
364 config
->verbosity
= FBSPL_VERB_NORMAL
;
367 ewarn("%s: We already have a svcs list!", __func__
);
371 svcs
= get_list(NULL
, FBSPLASH_CACHEDIR
"/svcs_start");
372 svcs_cnt
= strlist_count(svcs
);
374 svcs_done
= rc_services_in_state(RC_SERVICE_STARTED
);
376 tmp
= rc_services_in_state(RC_SERVICE_INACTIVE
);
377 svcs_done
= strlist_merge_sort(svcs_done
, tmp
);
378 rc_strlist_free(tmp
);
380 tmp
= rc_services_in_state(RC_SERVICE_FAILED
);
381 svcs_done
= strlist_merge_sort(svcs_done
, tmp
);
382 rc_strlist_free(tmp
);
384 tmp
= rc_services_in_state(RC_SERVICE_SCHEDULED
);
385 svcs_done
= strlist_merge_sort(svcs_done
, tmp
);
386 rc_strlist_free(tmp
);
388 svcs_done_cnt
= strlist_count(svcs_done
);
389 /* .. or rebooting? */
391 svcs
= get_list(NULL
, FBSPLASH_CACHEDIR
"/svcs_stop");
392 svcs_cnt
= strlist_count(svcs
);
394 svcs_done
= rc_services_in_state(RC_SERVICE_STARTED
);
396 tmp
= rc_services_in_state(RC_SERVICE_STARTING
);
397 svcs_done
= strlist_merge_sort(svcs_done
, tmp
);
398 rc_strlist_free(tmp
);
400 tmp
= rc_services_in_state(RC_SERVICE_INACTIVE
);
401 svcs_done
= strlist_merge_sort(svcs_done
, tmp
);
402 rc_strlist_free(tmp
);
404 svcs_done_cnt
= svcs_cnt
- strlist_count(svcs_done
);
413 * Handle the start/stop of a single service.
415 static int splash_svc_handle(const char *name
, const char *state
, bool skip
)
418 /* If we don't have any services, something must be broken.
419 * Bail out since there is nothing we can do about it. */
423 /* Don't process services twice. */
424 if (list_has(svcs_done
, name
))
427 rc_strlist_add(&svcs_done
, name
);
431 /* Recalculate progress */
432 config
->progress
= svcs_done_cnt
* FBSPL_PROGRESS_MAX
/ svcs_cnt
;
434 splash_theme_hook(state
, "pre", name
);
435 splash_svc_state(name
, state
, 0);
436 fbsplash_send("progress %d\n", config
->progress
);
437 fbsplash_send("paint\n");
438 splash_theme_hook(state
, "post", name
);
444 * Create a list of services that will be started during bootup.
446 int splash_svcs_start()
448 rc_depinfo_t
*deptree
;
450 char **t
, **deporder
, *s
, *r
;
453 fp
= fopen(FBSPLASH_CACHEDIR
"/svcs_start", "w");
455 ewarn("%s: `%s': %s", __func__
, FBSPLASH_CACHEDIR
"/svcs_start", strerror(errno
));
459 if ((deptree
= rc_deptree_load()) == NULL
) {
460 eerror("%s: failed to load deptree", __func__
);
465 deporder
= rc_deptree_order(deptree
, bootlevel
, RC_DEP_START
);
467 /* Save what we've got so far to the svcs_start. */
469 if (deporder
&& deporder
[0]) {
470 while ((s
= deporder
[i
++])) {
473 fprintf(fp
, "%s", s
);
478 deporder
= rc_deptree_order(deptree
, defaultlevel
, RC_DEP_START
);
480 /* Print the new services and skip ones that have already been started
481 * in the 'boot' runlevel. */
483 if (deporder
&& deporder
[0]) {
484 while ((s
= deporder
[i
])) {
486 while ((r
= t
[j
++])) {
487 if (!strcmp(deporder
[i
], r
))
490 fprintf(fp
, " %s", s
);
495 rc_strlist_free(deporder
);
497 rc_deptree_free(deptree
);
505 * Create a list of services that will be stopped during reboot/shutdown.
507 int splash_svcs_stop(const char *runlevel
)
509 rc_depinfo_t
*deptree
;
514 fp
= fopen(FBSPLASH_CACHEDIR
"/svcs_stop", "w");
516 ewarn("%s: `%s': %s", __func__
, FBSPLASH_CACHEDIR
"/svcs_stop", strerror(errno
));
520 if ((deptree
= rc_deptree_load()) == NULL
) {
521 eerror("%s: failed to load deptree", __func__
);
526 deporder
= rc_deptree_order(deptree
, runlevel
, RC_DEP_STOP
);
529 if (deporder
&& deporder
[0]) {
530 while ((s
= deporder
[i
++])) {
533 fprintf(fp
, "%s", s
);
537 rc_strlist_free(deporder
);
538 rc_deptree_free(deptree
);
545 * Start the splash daemon during boot/reboot.
547 static int splash_start(const char *runlevel
)
553 /* Get a list of services that we'll have to handle. */
554 /* We're rebooting/shutting down. */
555 if (!strcmp(runlevel
, RC_LEVEL_SHUTDOWN
) || !strcmp(runlevel
, RC_LEVEL_REBOOT
)) {
556 if ((err
= fbsplash_cache_prep()))
558 splash_svcs_stop(runlevel
);
562 if ((err
= fbsplash_cache_prep()))
568 splash_theme_hook("rc_init", "pre", runlevel
);
570 /* Perform sanity checks (console=, CONSOLE= etc). */
571 if (fbsplash_check_sanity())
574 /* Start the splash daemon */
575 snprintf(buf
, 2048, "BOOT_MSG='%s' " FBSPLASH_DAEMON
" --theme=\"%s\" --pidfile=" FBSPLASH_PIDFILE
" --type=%s %s %s %s",
576 config
->message
, config
->theme
,
577 (config
->type
== fbspl_reboot
) ? "reboot" : ((config
->type
== fbspl_shutdown
) ? "shutdown" : "bootup"),
578 (config
->kdmode
== KD_GRAPHICS
) ? "--kdgraphics" : "",
579 (config
->textbox_visible
) ? "--textbox" : "",
580 (config
->effects
& (FBSPL_EFF_FADEOUT
| FBSPL_EFF_FADEIN
)) ? "--effects=fadeout,fadein" :
581 ((config
->effects
& FBSPL_EFF_FADEOUT
) ? "--effects=fadeout" :
582 ((config
->effects
& FBSPL_EFF_FADEIN
) ? "--effects=fadein" : "")));
585 if (err
== -1 || WEXITSTATUS(err
) != 0) {
586 eerror("Failed to start the splash daemon, error code %d", err
);
590 err
= splash_init(start
);
594 /* Set the initial state of all services. */
595 for (i
= 0; svcs
&& svcs
[i
]; i
++) {
596 splash_svc_state(svcs
[i
], start
? "svc_inactive_start" : "svc_inactive_stop", 0);
599 fbsplash_set_evdev();
600 fbsplash_send("set autoverbose %d\n", config
->autoverbose
);
601 fbsplash_send("set tty silent %d\n", config
->tty_s
);
602 fbsplash_send("set mode silent\n");
603 fbsplash_send("repaint\n");
608 * Stop the splash daemon.
610 static int splash_stop(const char *runlevel
)
612 char *save
[] = { "profile", "svcs_start", NULL
};
617 if (rc_service_state("xdm") & RC_SERVICE_STARTED
) {
618 fbsplash_send("exit staysilent\n");
620 fbsplash_send("exit\n");
622 snprintf(buf
, 128, "/proc/%d", pid_daemon
);
624 /* Wait up to 1.0s for the splash daemon to exit. */
625 while (stat(buf
, &st
) == 0 && cnt
< 100) {
630 /* Just to be sure we aren't stuck in a black ex-silent tty.. */
631 if (fbsplash_is_silent())
632 fbsplash_set_verbose(0);
634 /* If we don't get a runlevel argument, then we're being executed
635 * because of a rc-abort event and we don't save any data. */
636 if (runlevel
== NULL
) {
637 return fbsplash_cache_cleanup(NULL
);
639 return fbsplash_cache_cleanup(save
);
643 int rc_plugin_hook (rc_hook_t hook
, const char *name
)
646 fbspl_type_t type
= fbspl_bootup
;
651 runlev
= rc_runlevel_get();
652 if (!strcmp(runlev
, RC_LEVEL_REBOOT
))
654 else if (!strcmp(runlev
, RC_LEVEL_SHUTDOWN
))
655 type
= fbspl_shutdown
;
657 /* Get boot and default levels from env variables exported by RC.
658 * If unavailable, use the default ones. */
659 bootlevel
= getenv("RC_BOOTLEVEL");
660 defaultlevel
= getenv("RC_DEFAULTLEVEL");
662 /* We generally do nothing if we're in sysinit. Except if the
663 * autoconfig service is present, when we get a list of services
664 * that will be started by it and mark them as coldplugged. */
665 if (name
&& !strcmp(name
, RC_LEVEL_SYSINIT
)) {
666 if (hook
== RC_HOOK_RUNLEVEL_START_OUT
&& rc_service_in_runlevel("autoconfig", defaultlevel
)) {
671 fp
= popen("if [ -e /etc/init.d/autoconfig ]; then . /etc/init.d/autoconfig ; list_services ; fi", "r");
675 list
= get_list_fp(NULL
, fp
);
676 for (i
= 0; list
&& list
[i
]; i
++) {
677 rc_service_mark(list
[i
], RC_SERVICE_COLDPLUGGED
);
684 /* Don't do anything if we're starting/stopping a service, but
685 * we aren't in the middle of a runlevel switch. */
686 if (!(rc_runlevel_starting() || rc_runlevel_stopping())) {
687 if (hook
!= RC_HOOK_RUNLEVEL_STOP_IN
&&
688 hook
!= RC_HOOK_RUNLEVEL_STOP_OUT
&&
689 hook
!= RC_HOOK_RUNLEVEL_START_IN
&&
690 hook
!= RC_HOOK_RUNLEVEL_START_OUT
)
693 /* We're starting/stopping a runlevel. Check whether we're
694 * actually booting/rebooting. */
695 if (rc_runlevel_starting() && strcmp(runlev
, bootlevel
) &&
696 strcmp(runlev
, defaultlevel
) && strcmp(runlev
, RC_LEVEL_SYSINIT
))
699 if (rc_runlevel_stopping() && strcmp(runlev
, bootlevel
) &&
700 strcmp(runlev
, RC_LEVEL_REBOOT
) && strcmp(runlev
, RC_LEVEL_SHUTDOWN
))
705 config
= fbsplash_lib_init(type
);
706 splash_config_gentoo(config
, type
);
707 fbsplash_parse_kcmdline(false);
710 /* Extremely weird.. should never happen. */
716 /* Don't do anything if we're not running in silent mode. */
717 if (!(config
->reqmode
& FBSPL_MODE_SILENT
))
721 case RC_HOOK_RUNLEVEL_STOP_IN
:
722 /* Start the splash daemon on reboot. The theme hook is called
723 * from splash_start(). */
724 if (strcmp(name
, RC_LEVEL_REBOOT
) == 0 || strcmp(name
, RC_LEVEL_SHUTDOWN
) == 0) {
725 if ((i
= splash_start(name
))) {
726 fbsplash_set_verbose(0);
730 if (rc_service_state("gpm") & RC_SERVICE_STARTED
) {
731 fbsplash_send("set gpm\n");
732 fbsplash_send("repaint\n");
735 splash_theme_hook("rc_init", "post", name
);
739 splash_theme_hook("rc_exit", "pre", name
);
740 splash_theme_hook("rc_exit", "post", name
);
741 fbsplash_lib_cleanup();
746 case RC_HOOK_RUNLEVEL_STOP_OUT
:
747 /* Make sure the progress indicator reaches 100%, even if
748 * something went wrong along the way. */
749 if (strcmp(name
, RC_LEVEL_REBOOT
) == 0 || strcmp(name
, RC_LEVEL_SHUTDOWN
) == 0) {
750 config
->verbosity
= FBSPL_VERB_QUIET
;
751 i
= fbsplash_check_daemon(&pid_daemon
);
752 config
->verbosity
= FBSPL_VERB_NORMAL
;
758 fbsplash_send("progress %d\n", FBSPL_PROGRESS_MAX
);
759 fbsplash_send("paint\n");
760 fbsplash_cache_cleanup(NULL
);
764 case RC_HOOK_RUNLEVEL_START_IN
:
765 /* Start the splash daemon during boot right after we finish
766 * sysinit and are entering the boot runlevel. Due to historical
767 * reasons, we simulate a full sysinit cycle here for the theme
769 if (strcmp(name
, bootlevel
) == 0) {
770 if ((i
= splash_start(RC_LEVEL_SYSINIT
)))
771 fbsplash_set_verbose(0);
772 splash_theme_hook("rc_init", "post", RC_LEVEL_SYSINIT
);
773 splash_theme_hook("rc_exit", "pre", RC_LEVEL_SYSINIT
);
774 splash_theme_hook("rc_exit", "post", RC_LEVEL_SYSINIT
);
776 splash_theme_hook("rc_init", "pre", name
);
777 splash_theme_hook("rc_init", "post", name
);
780 case RC_HOOK_RUNLEVEL_START_OUT
:
781 /* Stop the splash daemon after boot-up is finished. */
782 if (strcmp(name
, bootlevel
)) {
783 config
->verbosity
= FBSPL_VERB_QUIET
;
784 i
= fbsplash_check_daemon(&pid_daemon
);
785 config
->verbosity
= FBSPL_VERB_NORMAL
;
791 /* Make sure the progress indicator reaches 100%, even if
792 * something went wrong along the way. */
793 fbsplash_send("progress %d\n", FBSPL_PROGRESS_MAX
);
794 fbsplash_send("paint\n");
795 splash_theme_hook("rc_exit", "pre", name
);
796 i
= splash_stop(name
);
797 splash_theme_hook("rc_exit", "post", name
);
798 fbsplash_lib_cleanup();
803 case RC_HOOK_SERVICE_START_NOW
:
805 /* If we've been inactive, do nothing since the service has
806 * already been handled before it went inactive. */
807 if (rc_service_state(name
) & RC_SERVICE_WASINACTIVE
)
810 /* If we're starting or stopping a service, we're being called by
811 * runscript and thus have to reload our config. */
812 if (splash_init(true)) {
816 i
= splash_svc_handle(name
, "svc_start", skip
);
819 case RC_HOOK_SERVICE_START_OUT
:
820 /* If a service gets scheduled, we want to increment the progress
821 * bar (as it is no longer blocking boot completion). However,
822 * the service may actually start during boot (some time after
823 * being scheduled), so we don't want to increment the progress
824 * bar twice. The following if clause satisfies this by catching
825 * the first case but not the second. */
826 if ((rc_service_state(name
) & RC_SERVICE_SCHEDULED
) &&
827 !(rc_service_state(name
) & RC_SERVICE_STARTING
)) {
833 case RC_HOOK_SERVICE_START_DONE
:
834 config
->verbosity
= FBSPL_VERB_QUIET
;
835 i
= fbsplash_check_daemon(&pid_daemon
);
836 config
->verbosity
= FBSPL_VERB_NORMAL
;
842 if (!(rc_service_state(name
) & RC_SERVICE_FAILED
) &&
843 !(rc_service_state(name
) & RC_SERVICE_STOPPED
)) {
846 if (!strcmp(name
, "gpm")) {
850 /* Wait up to 0.25s for the GPM socket to appear. */
851 while (stat("/dev/gpmctl", &st
) == 0 && cnt
< 25) {
855 fbsplash_send("set gpm\n");
858 i
= splash_svc_state(name
, "svc_started", 1);
861 fbsplash_send("repaint\n");
864 i
= splash_svc_state(name
, "svc_start_failed", 1);
865 if (config
->vonerr
) {
866 fbsplash_set_verbose(0);
869 fbsplash_lib_cleanup();
873 case RC_HOOK_SERVICE_STOP_NOW
:
874 if (splash_init(false)) {
879 /* We need to stop localmount from unmounting our cache dir.
880 Luckily plugins can add to the unmount list. */
881 if (name
&& !strcmp(name
, "localmount")) {
882 char *umounts
= getenv("RC_NO_UMOUNTS");
885 fprintf(rc_environ_fd
, "RC_NO_UMOUNTS=%s:%s", umounts
, FBSPLASH_CACHEDIR
);
887 fprintf(rc_environ_fd
, "RC_NO_UMOUNTS=%s", FBSPLASH_CACHEDIR
);
889 i
= splash_svc_handle(name
, "svc_stop", false);
892 case RC_HOOK_SERVICE_STOP_DONE
:
893 config
->verbosity
= FBSPL_VERB_QUIET
;
894 i
= fbsplash_check_daemon(&pid_daemon
);
895 config
->verbosity
= FBSPL_VERB_NORMAL
;
901 if (rc_service_state(name
) & RC_SERVICE_STOPPED
) {
902 i
= splash_svc_state(name
, "svc_stopped", 1);
904 i
= splash_svc_state(name
, "svc_stop_failed", 1);
905 if (config
->vonerr
) {
906 fbsplash_set_verbose(0);
909 fbsplash_lib_cleanup();
914 i
= splash_stop(name
);
915 fbsplash_lib_cleanup();
924 rc_strlist_free(svcs
);