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 "export RUNLEVEL='%s'; . /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
);
137 static void fix_rc_variable(char *s
)
140 char *t
= strstr(s
, "\\$");
143 memmove(t
, t
+1, strlen(t
));
151 * Get splash settings from /etc/conf.d/splash
153 static int splash_config_gentoo(fbspl_cfg_t
*cfg
, fbspl_type_t type
)
155 RC_STRINGLIST
*confd
;
158 confd
= rc_config_load("/etc/conf.d/splash");
160 t
= rc_config_value(confd
, "SPLASH_KDMODE");
162 if (!strcasecmp(t
, "graphics")) {
163 cfg
->kdmode
= KD_GRAPHICS
;
164 } else if (!strcasecmp(t
, "text")) {
165 cfg
->kdmode
= KD_TEXT
;
169 t
= rc_config_value(confd
, "SPLASH_PROFILE");
171 if (!strcasecmp(t
, "on") || !strcasecmp(t
, "yes"))
175 t
= rc_config_value(confd
, "SPLASH_TTY");
178 if (sscanf(t
, "%d", &i
) == 1 && i
> 0) {
183 t
= rc_config_value(confd
, "SPLASH_THEME");
185 fbsplash_acc_theme_set(t
);
187 t
= rc_config_value(confd
, "SPLASH_MODE_REQ");
189 if (!strcasecmp(t
, "verbose")) {
190 cfg
->reqmode
= FBSPL_MODE_VERBOSE
;
191 } else if (!strcasecmp(t
, "silent")) {
192 cfg
->reqmode
= FBSPL_MODE_VERBOSE
| FBSPL_MODE_SILENT
;
193 } else if (!strcasecmp(t
, "silentonly")) {
194 cfg
->reqmode
= FBSPL_MODE_SILENT
;
198 t
= rc_config_value(confd
, "SPLASH_VERBOSE_ON_ERRORS");
199 if (t
&& (!strcasecmp(t
, "on") || !strcasecmp(t
, "yes")))
204 t
= rc_config_value(confd
, "SPLASH_REBOOT_MESSAGE");
207 fbsplash_acc_message_set(t
);
212 t
= rc_config_value(confd
, "SPLASH_SHUTDOWN_MESSAGE");
215 fbsplash_acc_message_set(t
);
221 t
= rc_config_value(confd
, "SPLASH_BOOT_MESSAGE");
224 fbsplash_acc_message_set(t
);
229 t
= rc_config_value(confd
, "SPLASH_TEXTBOX");
231 if (!strcasecmp(t
, "on") || !strcasecmp(t
, "yes"))
232 cfg
->textbox_visible
= true;
235 t
= rc_config_value(confd
, "SPLASH_AUTOVERBOSE");
237 cfg
->autoverbose
= atoi(t
);
240 t
= rc_config_value(confd
, "SPLASH_EFFECTS");
244 while ((opt
= strsep(&t
, ",")) != NULL
) {
245 if (!strcmp(opt
, "fadein")) {
246 cfg
->effects
|= FBSPL_EFF_FADEIN
;
247 } else if (!strcmp(opt
, "fadeout")) {
248 cfg
->effects
|= FBSPL_EFF_FADEOUT
;
253 t
= rc_config_value(confd
, "SPLASH_XSERVICE");
255 fbsplash_acc_xservice_set(t
);
257 fbsplash_acc_xservice_set("xdm");
259 rc_stringlist_free(confd
);
263 static const char *splash_sysvinit_runlevel(const char *runlevel
)
265 const char *runlev
= runlevel
? runlevel
: rc_runlevel_get();
267 if (!strcmp(runlev
, RC_LEVEL_SHUTDOWN
)) {
268 char *t
= getenv("RC_REBOOT");
269 if (t
&& !strcmp(t
, "YES")) {
274 } else if (!strcmp(runlev
, RC_LEVEL_SYSINIT
)) {
276 } else if (!strcmp(runlev
, RC_LEVEL_SINGLE
)) {
285 * Call a function from /sbin/splash-functions.sh.
286 * This is rather slow, so use it only when really necessary.
288 static int splash_call(const char *cmd
, const char *arg1
, const char *arg2
, const char *runlevel
)
292 char *soft
= getenv("RC_RUNLEVEL");
297 l
= strlen(SPLASH_CMD
) + strlen(soft
) + strlen(cmd
) + 10;
303 c
= malloc(sizeof(char*) * l
);
307 snprintf(c
, l
, SPLASH_CMD
, xres
, yres
,
308 arg1
? (strcmp(arg1
, RC_LEVEL_SYSINIT
) == 0 ? bootlevel
: soft
) : soft
,
309 bootlevel
, defaultlevel
, runlevel
,
310 cmd
, arg1
? arg1
: "", arg2
? arg2
: "");
317 * Run a theme hook script.
319 static int splash_theme_hook(const char *name
, const char *type
, const char *arg1
)
326 fbsplash_profile("%s %s %s\n", type
, name
, arg1
);
328 fbsplash_profile("%s %s\n", type
, name
);
331 l
+= strlen(config
->theme
);
333 buf
= malloc(l
* sizeof(char*));
334 snprintf(buf
, l
, "/etc/splash/%s/scripts/%s-%s", config
->theme
, name
, type
);
335 if (stat(buf
, &st
) != 0) {
340 if (!strcmp(name
, "rc_init") || !strcmp(name
, "rc_exit")) {
341 const char *t
= splash_sysvinit_runlevel(arg1
);
342 l
= splash_call(buf
, arg1
, t
, t
);
343 } else if (!strcmp(name
, "svc_started") || !strcmp(name
, "svc_stopped")) {
345 * Set the 2nd parameter to 0 so that we don't break themes using the
346 * legacy interface in which these events contained an error code.
348 l
= splash_call(buf
, arg1
, "0", splash_sysvinit_runlevel(NULL
));
350 l
= splash_call(buf
, arg1
, NULL
, splash_sysvinit_runlevel(NULL
));
357 * Update service state.
359 static int splash_svc_state(const char *name
, const char *state
, bool paint
)
362 splash_theme_hook(state
, "pre", name
);
364 if (!strcmp(state
, "svc_started")) {
365 fbsplash_send("log Service '%s' started.\n", name
);
366 } else if (!strcmp(state
, "svc_start_failed")) {
367 fbsplash_send("log Service '%s' failed to start.\n", name
);
368 } else if (!strcmp(state
, "svc_stopped")) {
369 fbsplash_send("log Service '%s' stopped.\n", name
);
370 } else if (!strcmp(state
, "svc_stop_failed")) {
371 fbsplash_send("log Service '%s' failed to stop.\n", name
);
374 fbsplash_send("update_svc %s %s\n", name
, state
);
377 fbsplash_send("paint\n");
378 splash_theme_hook(state
, "post", name
);
385 * Get the resolution that the silent splash will use.
387 static void splash_init_res()
389 struct fb_var_screeninfo var
;
392 if ((fh
= open("/dev/fb0", O_RDONLY
)) == -1)
393 if ((fh
= open("/dev/fb/0", O_RDONLY
)) == -1)
396 if (ioctl(fh
, FBIOGET_VSCREENINFO
, &var
))
401 fbsplash_get_res(config
->theme
, (int*)&var
.xres
, (int*)&var
.yres
);
407 * Init splash config variables and check that the splash daemon
410 static int splash_init(bool start
)
414 config
->verbosity
= FBSPL_VERB_QUIET
;
415 if (fbsplash_check_daemon(&pid_daemon
)) {
416 config
->verbosity
= FBSPL_VERB_NORMAL
;
420 config
->verbosity
= FBSPL_VERB_NORMAL
;
423 ewarn("%s: We already have a svcs list!", __func__
);
424 rc_stringlist_free(svcs
);
426 svcs
= rc_stringlist_new();
430 get_list(svcs
, FBSPLASH_CACHEDIR
"/svcs_start");
431 svcs_cnt
= strlist_count(svcs
);
433 svcs_done
= rc_services_in_state(RC_SERVICE_STARTED
);
435 tmp
= rc_services_in_state(RC_SERVICE_INACTIVE
);
436 if (svcs_done
&& tmp
) {
437 TAILQ_CONCAT(svcs_done
, tmp
, entries
);
442 tmp
= rc_services_in_state(RC_SERVICE_FAILED
);
443 if (svcs_done
&& tmp
) {
444 TAILQ_CONCAT(svcs_done
, tmp
, entries
);
449 tmp
= rc_services_in_state(RC_SERVICE_SCHEDULED
);
450 if (svcs_done
&& tmp
) {
451 TAILQ_CONCAT(svcs_done
, tmp
, entries
);
456 svcs_done_cnt
= strlist_count(svcs_done
);
457 /* .. or rebooting? */
459 get_list(svcs
, FBSPLASH_CACHEDIR
"/svcs_stop");
460 svcs_cnt
= strlist_count(svcs
);
462 svcs_done
= rc_services_in_state(RC_SERVICE_STARTED
);
464 tmp
= rc_services_in_state(RC_SERVICE_STARTING
);
465 if (svcs_done
&& tmp
) {
466 TAILQ_CONCAT(svcs_done
, tmp
, entries
);
471 tmp
= rc_services_in_state(RC_SERVICE_INACTIVE
);
472 if (svcs_done
&& tmp
) {
473 TAILQ_CONCAT(svcs_done
, tmp
, entries
);
478 svcs_done_cnt
= svcs_cnt
- strlist_count(svcs_done
);
487 * Handle the start/stop of a single service.
489 static int splash_svc_handle(const char *name
, const char *state
, bool skip
)
492 /* If we don't have any services, something must be broken.
493 * Bail out since there is nothing we can do about it. */
497 /* Don't process services twice. */
498 if (list_has(svcs_done
, name
))
502 svcs_done
= rc_stringlist_new();
503 rc_stringlist_add(svcs_done
, name
);
507 /* Recalculate progress */
508 config
->progress
= svcs_done_cnt
* FBSPL_PROGRESS_MAX
/ svcs_cnt
;
510 splash_theme_hook(state
, "pre", name
);
511 splash_svc_state(name
, state
, 0);
512 fbsplash_send("progress %d\n", config
->progress
);
513 fbsplash_send("paint\n");
514 splash_theme_hook(state
, "post", name
);
520 * Create a list of services that will be started during bootup.
522 int splash_svcs_start()
526 RC_STRINGLIST
*t
, *deporder
;
530 fp
= fopen(FBSPLASH_CACHEDIR
"/svcs_start", "w");
532 ewarn("%s: `%s': %s", __func__
, FBSPLASH_CACHEDIR
"/svcs_start", strerror(errno
));
536 if ((deptree
= rc_deptree_load()) == NULL
) {
537 eerror("%s: failed to load deptree", __func__
);
542 deporder
= rc_deptree_order(deptree
, bootlevel
, RC_DEP_START
);
544 /* Save what we've got so far to the svcs_start. */
547 TAILQ_FOREACH(s
, deporder
, entries
) {
550 fprintf(fp
, "%s", s
->value
);
556 deporder
= rc_deptree_order(deptree
, defaultlevel
, RC_DEP_START
);
558 /* Print the new services and skip ones that have already been started
559 * in the 'boot' runlevel. */
561 TAILQ_FOREACH(s
, deporder
, entries
) {
563 TAILQ_FOREACH(r
, t
, entries
) {
564 if (!strcmp(s
->value
, r
->value
)) {
570 fprintf(fp
, " %s", s
->value
);
575 rc_stringlist_free(deporder
);
576 rc_stringlist_free(t
);
577 rc_deptree_free(deptree
);
585 * Create a list of services that will be stopped during reboot/shutdown.
587 int splash_svcs_stop(const char *runlevel
)
590 RC_STRINGLIST
*deporder
;
595 fp
= fopen(FBSPLASH_CACHEDIR
"/svcs_stop", "w");
597 ewarn("%s: `%s': %s", __func__
, FBSPLASH_CACHEDIR
"/svcs_stop", strerror(errno
));
601 if ((deptree
= rc_deptree_load()) == NULL
) {
602 eerror("%s: failed to load deptree", __func__
);
607 deporder
= rc_deptree_order(deptree
, runlevel
, RC_DEP_STOP
);
611 TAILQ_FOREACH(s
, deporder
, entries
) {
614 fprintf(fp
, "%s", s
->value
);
619 rc_stringlist_free(deporder
);
620 rc_deptree_free(deptree
);
627 * Start the splash daemon during boot/reboot.
629 static int splash_start(const char *runlevel
)
636 /* Get a list of services that we'll have to handle. */
637 /* We're rebooting/shutting down. */
638 if (!strcmp(runlevel
, RC_LEVEL_SHUTDOWN
)) {
639 if ((err
= fbsplash_cache_prep()))
641 splash_svcs_stop(runlevel
);
645 if ((err
= fbsplash_cache_prep()))
651 splash_theme_hook("rc_init", "pre", runlevel
);
653 /* Perform sanity checks (console=, CONSOLE= etc). */
654 if (fbsplash_check_sanity())
657 /* Start the splash daemon */
658 snprintf(buf
, 2048, "BOOT_MSG='%s' " FBSPLASH_DAEMON
" --theme=\"%s\" --pidfile=" FBSPLASH_PIDFILE
" --type=%s %s %s %s",
659 config
->message
, config
->theme
,
660 (config
->type
== fbspl_reboot
) ? "reboot" : ((config
->type
== fbspl_shutdown
) ? "shutdown" : "bootup"),
661 (config
->kdmode
== KD_GRAPHICS
) ? "--kdgraphics" : "",
662 (config
->textbox_visible
) ? "--textbox" : "",
663 ((config
->effects
& (FBSPL_EFF_FADEOUT
| FBSPL_EFF_FADEIN
)) == (FBSPL_EFF_FADEOUT
| FBSPL_EFF_FADEIN
)) ? "--effects=fadeout,fadein" :
664 ((config
->effects
& FBSPL_EFF_FADEOUT
) ? "--effects=fadeout" :
665 ((config
->effects
& FBSPL_EFF_FADEIN
) ? "--effects=fadein" : "")));
668 if (err
== -1 || WEXITSTATUS(err
) != 0) {
669 eerror("Failed to start the splash daemon, error code %d", err
);
673 err
= splash_init(start
);
677 /* Set the initial state of all services. */
679 TAILQ_FOREACH(s
, svcs
, entries
)
680 splash_svc_state(s
->value
, start
? "svc_inactive_start" : "svc_inactive_stop", 0);
682 fbsplash_set_evdev();
683 fbsplash_send("set autoverbose %d\n", config
->autoverbose
);
684 fbsplash_send("set tty silent %d\n", config
->tty_s
);
685 fbsplash_send("set mode silent\n");
686 fbsplash_send("repaint\n");
691 * Stop the splash daemon.
693 static int splash_stop(const char *runlevel
)
695 char *save
[] = { "profile", "svcs_start", NULL
};
700 if (rc_service_state(config
->xservice
) & RC_SERVICE_STARTED
) {
701 fbsplash_send("exit staysilent\n");
703 fbsplash_send("exit\n");
705 snprintf(buf
, 128, "/proc/%d", pid_daemon
);
707 /* Wait up to 1.0s for the splash daemon to exit. */
708 while (stat(buf
, &st
) == 0 && cnt
< 100) {
713 /* Just to be sure we aren't stuck in a black ex-silent tty.. */
714 if (fbsplash_is_silent() && !(rc_service_state(config
->xservice
) & RC_SERVICE_STARTED
))
715 fbsplash_set_verbose(0);
717 /* If we don't get a runlevel argument, then we're being executed
718 * because of a rc-abort event and we don't save any data. */
719 return fbsplash_cache_cleanup(save
);
722 int rc_plugin_hook(RC_HOOK hook
, const char *name
)
725 fbspl_type_t type
= fbspl_bootup
;
730 runlev
= rc_runlevel_get();
731 if (!strcmp(runlev
, RC_LEVEL_SHUTDOWN
)) {
732 if (!strcmp(splash_sysvinit_runlevel(NULL
), "6")) {
735 type
= fbspl_shutdown
;
739 /* Get boot and default levels from env variables exported by RC.
740 * If unavailable, use the default ones. */
741 bootlevel
= getenv("RC_BOOTLEVEL");
742 defaultlevel
= getenv("RC_DEFAULTLEVEL");
744 /* We generally do nothing if we're in sysinit. Except if the
745 * autoconfig service is present, when we get a list of services
746 * that will be started by it and mark them as coldplugged. */
747 if (name
&& !strcmp(name
, RC_LEVEL_SYSINIT
)) {
748 if (hook
== RC_HOOK_RUNLEVEL_START_OUT
&& rc_service_in_runlevel("autoconfig", defaultlevel
)) {
753 fp
= popen("if [ -e /etc/init.d/autoconfig ]; then . /etc/init.d/autoconfig ; list_services ; fi", "r");
757 list
= rc_stringlist_new();
758 get_list_fp(list
, fp
);
759 TAILQ_FOREACH(s
, list
, entries
)
760 rc_service_mark(s
->value
, RC_SERVICE_HOTPLUGGED
);
762 rc_stringlist_free(list
);
767 /* Don't do anything if we're starting/stopping a service, but
768 * we aren't in the middle of a runlevel switch. */
769 if (!(rc_runlevel_starting() || rc_runlevel_stopping())) {
770 if (hook
!= RC_HOOK_RUNLEVEL_STOP_IN
&&
771 hook
!= RC_HOOK_RUNLEVEL_STOP_OUT
&&
772 hook
!= RC_HOOK_RUNLEVEL_START_IN
&&
773 hook
!= RC_HOOK_RUNLEVEL_START_OUT
)
778 /* We're starting/stopping a runlevel. Check whether we're
779 * actually booting/rebooting. */
780 if (rc_runlevel_starting() && strcmp(runlev
, bootlevel
) &&
781 strcmp(runlev
, RC_LEVEL_SYSINIT
) && fbsplash_check_daemon(&pid
))
784 if (rc_runlevel_stopping() && strcmp(runlev
, bootlevel
) &&
785 strcmp(runlev
, RC_LEVEL_SHUTDOWN
))
790 config
= fbsplash_lib_init(type
);
791 splash_config_gentoo(config
, type
);
792 fbsplash_parse_kcmdline(false);
795 /* Extremely weird.. should never happen. */
801 /* Don't do anything if we're not running in silent mode. */
802 if (!(config
->reqmode
& FBSPL_MODE_SILENT
))
806 case RC_HOOK_RUNLEVEL_STOP_IN
:
807 /* Start the splash daemon on reboot. The theme hook is called
808 * from splash_start(). */
809 if (strcmp(name
, RC_LEVEL_SHUTDOWN
) == 0) {
810 if ((i
= splash_start(name
))) {
811 fbsplash_set_verbose(0);
815 if (rc_service_state("gpm") & RC_SERVICE_STARTED
) {
816 fbsplash_send("set gpm\n");
817 fbsplash_send("repaint\n");
820 splash_theme_hook("rc_init", "post", name
);
824 splash_theme_hook("rc_exit", "pre", name
);
825 splash_theme_hook("rc_exit", "post", name
);
826 fbsplash_lib_cleanup();
831 case RC_HOOK_RUNLEVEL_STOP_OUT
:
832 /* Make sure the progress indicator reaches 100%, even if
833 * something went wrong along the way. */
834 if (strcmp(name
, RC_LEVEL_SHUTDOWN
) == 0) {
835 config
->verbosity
= FBSPL_VERB_QUIET
;
836 i
= fbsplash_check_daemon(&pid_daemon
);
837 config
->verbosity
= FBSPL_VERB_NORMAL
;
843 fbsplash_send("progress %d\n", FBSPL_PROGRESS_MAX
);
844 fbsplash_send("paint\n");
845 fbsplash_cache_cleanup(NULL
);
849 case RC_HOOK_RUNLEVEL_START_IN
:
850 /* Start the splash daemon during boot right after we finish
851 * sysinit and are entering the boot runlevel. Due to historical
852 * reasons, we simulate a full sysinit cycle here for the theme
854 if (strcmp(name
, bootlevel
) == 0) {
855 if ((i
= splash_start(RC_LEVEL_SYSINIT
)))
856 fbsplash_set_verbose(0);
857 splash_theme_hook("rc_init", "post", RC_LEVEL_SYSINIT
);
858 splash_theme_hook("rc_exit", "pre", RC_LEVEL_SYSINIT
);
859 splash_theme_hook("rc_exit", "post", RC_LEVEL_SYSINIT
);
861 splash_theme_hook("rc_init", "pre", name
);
862 splash_theme_hook("rc_init", "post", name
);
865 case RC_HOOK_RUNLEVEL_START_OUT
:
866 /* Stop the splash daemon after boot-up is finished. */
867 if (strcmp(name
, bootlevel
)) {
868 config
->verbosity
= FBSPL_VERB_QUIET
;
869 i
= fbsplash_check_daemon(&pid_daemon
);
870 config
->verbosity
= FBSPL_VERB_NORMAL
;
876 /* Make sure the progress indicator reaches 100%, even if
877 * something went wrong along the way. */
878 fbsplash_send("progress %d\n", FBSPL_PROGRESS_MAX
);
879 fbsplash_send("paint\n");
880 splash_theme_hook("rc_exit", "pre", name
);
881 i
= splash_stop(name
);
882 splash_theme_hook("rc_exit", "post", name
);
883 fbsplash_lib_cleanup();
888 case RC_HOOK_SERVICE_START_NOW
:
890 /* If we've been inactive, do nothing since the service has
891 * already been handled before it went inactive. */
892 if (rc_service_state(name
) & RC_SERVICE_WASINACTIVE
)
895 /* If we're starting or stopping a service, we're being called by
896 * runscript and thus have to reload our config. */
897 if (splash_init(true)) {
901 i
= splash_svc_handle(name
, "svc_start", skip
);
904 case RC_HOOK_SERVICE_START_OUT
:
905 /* If a service gets scheduled, we want to increment the progress
906 * bar (as it is no longer blocking boot completion). However,
907 * the service may actually start during boot (some time after
908 * being scheduled), so we don't want to increment the progress
909 * bar twice. The following if clause satisfies this by catching
910 * the first case but not the second. */
911 if ((rc_service_state(name
) & RC_SERVICE_SCHEDULED
) &&
912 !(rc_service_state(name
) & RC_SERVICE_STARTING
)) {
918 case RC_HOOK_SERVICE_START_DONE
:
919 config
->verbosity
= FBSPL_VERB_QUIET
;
920 i
= fbsplash_check_daemon(&pid_daemon
);
921 config
->verbosity
= FBSPL_VERB_NORMAL
;
927 if (!(rc_service_state(name
) & RC_SERVICE_FAILED
) &&
928 !(rc_service_state(name
) & RC_SERVICE_STOPPED
)) {
931 if (!strcmp(name
, "gpm")) {
935 /* Wait up to 0.25s for the GPM socket to appear. */
936 while (stat("/dev/gpmctl", &st
) == 0 && cnt
< 25) {
940 fbsplash_send("set gpm\n");
943 i
= splash_svc_state(name
, "svc_started", 1);
946 fbsplash_send("repaint\n");
949 i
= splash_svc_state(name
, "svc_start_failed", 1);
950 if (config
->vonerr
) {
951 fbsplash_set_verbose(0);
954 fbsplash_lib_cleanup();
958 case RC_HOOK_SERVICE_STOP_NOW
:
959 if (splash_init(false)) {
964 /* We need to stop localmount from unmounting our cache dir.
965 Luckily plugins can add to the unmount list. */
966 if (name
&& !strcmp(name
, "localmount")) {
967 char *umounts
= getenv("RC_NO_UMOUNTS");
970 fprintf(rc_environ_fd
, "RC_NO_UMOUNTS=%s:" FBSPLASH_CACHEDIR
":/etc/splash/%s", umounts
, config
->theme
);
972 fprintf(rc_environ_fd
, "RC_NO_UMOUNTS=" FBSPLASH_CACHEDIR
":/etc/splash/%s", config
->theme
);
974 i
= splash_svc_handle(name
, "svc_stop", false);
977 case RC_HOOK_SERVICE_STOP_DONE
:
978 config
->verbosity
= FBSPL_VERB_QUIET
;
979 i
= fbsplash_check_daemon(&pid_daemon
);
980 config
->verbosity
= FBSPL_VERB_NORMAL
;
986 if (rc_service_state(name
) & RC_SERVICE_STOPPED
) {
987 i
= splash_svc_state(name
, "svc_stopped", 1);
989 i
= splash_svc_state(name
, "svc_stop_failed", 1);
990 if (config
->vonerr
) {
991 fbsplash_set_verbose(0);
994 fbsplash_lib_cleanup();
999 i
= splash_stop(name
);
1000 fbsplash_lib_cleanup();
1009 rc_stringlist_free(svcs
);