diff options
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/Makefile.am | 11 | ||||
-rw-r--r-- | src/main.c | 43 | ||||
-rw-r--r-- | src/ply-boot-splash-plugin.h | 48 | ||||
-rw-r--r-- | src/ply-boot-splash.c | 249 | ||||
-rw-r--r-- | src/ply-boot-splash.h | 46 | ||||
-rw-r--r-- | src/ply-utils.c | 49 | ||||
-rw-r--r-- | src/ply-utils.h | 9 | ||||
-rw-r--r-- | src/tests/Makefile.am | 1 | ||||
-rw-r--r-- | src/tests/ply-boot-splash-test.am | 17 |
10 files changed, 470 insertions, 5 deletions
diff --git a/configure.ac b/configure.ac index 8e0828d..09afbf4 100644 --- a/configure.ac +++ b/configure.ac @@ -32,7 +32,7 @@ AC_SUBST(IMAGE_CFLAGS) AC_SUBST(IMAGE_LIBS) PLYMOUTH_CFLAGS="" -PLYMOUTH_LIBS="-lm" +PLYMOUTH_LIBS="-lm -ldl" AC_SUBST(PLYMOUTH_CFLAGS) AC_SUBST(PLYMOUTH_LIBS) diff --git a/src/Makefile.am b/src/Makefile.am index b2c9416..eda2a2b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,11 +2,14 @@ SUBDIRS = tests INCLUDES = -I$(top_srcdir) \ -I$(srcdir) -plymouth_CFLAGS = -plymouth_LDADD = +plymouth_CFLAGS = $(PLYMOUTH_CFLAGS) +plymouth_LDADD = $(PLYMOUTH_LIBS) plymouth_SOURCES = \ ply-boot-server.h \ ply-boot-server.c \ + ply-boot-splash-plugin.h \ + ply-boot-splash.h \ + ply-boot-splash.c \ ply-list.h \ ply-list.c \ ply-logger.h \ @@ -20,8 +23,8 @@ plymouth_SOURCES = \ ply-utils.h \ ply-utils.c \ main.c -rhgb_client_CFLAGS = -rhgb_client_LDADD = +rhgb_client_CFLAGS = $(PLYMOUTH_CFLAGS) +rhgb_client_LDADD = $(PLYMOUTH_LIBS) rhgb_client_SOURCES = ply-utils.h \ ply-utils.c \ ply-logger.h \ @@ -32,6 +32,7 @@ #include <unistd.h> #include "ply-boot-server.h" +#include "ply-boot-splash.h" #include "ply-event-loop.h" #include "ply-logger.h" #include "ply-terminal-session.h" @@ -41,6 +42,7 @@ typedef struct { ply_event_loop_t *loop; ply_boot_server_t *boot_server; + ply_boot_splash_t *boot_splash; ply_terminal_session_t *session; } state_t; @@ -56,6 +58,8 @@ static void on_update (state_t *state, const char *status) { + ply_boot_splash_update_status (state->boot_splash, + status); } static void @@ -72,6 +76,7 @@ on_quit (state_t *state) { ply_terminal_session_close_log (state->session); umount ("/sysroot"); + ply_boot_splash_hide (state->boot_splash); ply_event_loop_exit (state->loop, 0); } @@ -90,6 +95,7 @@ start_boot_server (state_t *state) ply_save_errno (); ply_boot_server_free (server); ply_restore_errno (); + return NULL; } ply_boot_server_attach_to_event_loop (server, state->loop); @@ -97,6 +103,27 @@ start_boot_server (state_t *state) return server; } +static ply_boot_splash_t * +start_boot_splash (state_t *state, + const char *module_path) +{ + ply_boot_splash_t *splash; + + splash = ply_boot_splash_new (module_path); + + if (!ply_boot_splash_show (splash)) + { + ply_save_errno (); + ply_boot_splash_free (splash); + ply_restore_errno (); + return NULL; + } + + ply_boot_splash_attach_to_event_loop (splash, state->loop); + + return splash; +} + static ply_terminal_session_t * spawn_session (state_t *state, char **argv) @@ -140,6 +167,22 @@ main (int argc, state.loop = ply_event_loop_new (); state.boot_server = start_boot_server (&state); + + if (state.boot_server == NULL) + { + ply_error ("could not log bootup: %m"); + return EX_UNAVAILABLE; + } + + state.boot_splash = start_boot_splash (&state, + "fedora-fade-in.so"); + + if (state.boot_splash == NULL) + { + ply_error ("could not start boot splash: %m"); + return EX_UNAVAILABLE; + } + state.session = spawn_session (&state, argv + 1); if (state.session == NULL) diff --git a/src/ply-boot-splash-plugin.h b/src/ply-boot-splash-plugin.h new file mode 100644 index 0000000..c0996b3 --- /dev/null +++ b/src/ply-boot-splash-plugin.h @@ -0,0 +1,48 @@ +/* ply-boot-splash-plugin.h - plugin interface for ply_boot_splash_t + * + * Copyright (C) 2007 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written By: Ray Strode <rstrode@redhat.com> + */ +#ifndef PLY_BOOT_SPLASH_PLUGIN_H +#define PLY_BOOT_SPLASH_PLUGIN_H + +#include <stdbool.h> +#include <stdint.h> +#include <unistd.h> + +#include "ply-event-loop.h" + +typedef intptr_t ply_boot_splash_plugin_t; + +typedef struct +{ + ply_boot_splash_plugin_t * (* create_plugin) (void); + void (* destroy_plugin) (ply_boot_splash_plugin_t *plugin); + + void (* show_splash_screen) (ply_boot_splash_plugin_t *plugin); + void (* update_status) (ply_boot_splash_plugin_t *plugin, + const char *status); + void (* hide_splash_screen) (ply_boot_splash_plugin_t *plugin); + void (* attach_to_event_loop) (ply_boot_splash_plugin_t *plugin, + ply_event_loop_t *loop); + +} ply_boot_splash_plugin_interface_t; + +#endif /* PLY_BOOT_SPLASH_PLUGIN_H */ +/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/ply-boot-splash.c b/src/ply-boot-splash.c new file mode 100644 index 0000000..dce7f78 --- /dev/null +++ b/src/ply-boot-splash.c @@ -0,0 +1,249 @@ +/* ply-boot-splash.h - APIs for putting up a splash screen + * + * Copyright (C) 2007 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by: Ray Strode <rstrode@redhat.com> + */ +#include "config.h" +#include "ply-boot-splash.h" + +#include <assert.h> +#include <errno.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <unistd.h> + +#include "ply-boot-splash-plugin.h" +#include "ply-event-loop.h" +#include "ply-list.h" +#include "ply-logger.h" +#include "ply-utils.h" + +struct _ply_boot_splash +{ + ply_event_loop_t *loop; + ply_module_handle_t *module_handle; + const ply_boot_splash_plugin_interface_t *plugin_interface; + ply_boot_splash_plugin_t *plugin; + + char *module_name; + char *status; + + uint32_t is_shown : 1; +}; + +typedef const ply_boot_splash_plugin_interface_t * + (* get_plugin_interface_function_t) (void); + +ply_boot_splash_t * +ply_boot_splash_new (const char *module_name) +{ + ply_boot_splash_t *splash; + + assert (module_name != NULL); + + splash = calloc (1, sizeof (ply_boot_splash_t)); + splash->loop = NULL; + splash->module_name = strdup (module_name); + splash->module_handle = NULL; + splash->is_shown = false; + + return splash; +} + +void +ply_boot_splash_free (ply_boot_splash_t *splash) +{ + if (splash == NULL) + return; + + if (splash->is_shown) + ply_boot_splash_hide (splash); + + free (splash->module_name); + free (splash); +} + +static bool +ply_boot_splash_load_plugin (ply_boot_splash_t *splash) +{ + assert (splash != NULL); + assert (splash->module_name != NULL); + + get_plugin_interface_function_t get_boot_splash_plugin_interface; + + splash->module_handle = ply_open_module (splash->module_name); + + if (splash->module_handle == NULL) + return false; + + get_boot_splash_plugin_interface = (get_plugin_interface_function_t) + ply_module_look_up_function (splash->module_handle, + "ply_boot_splash_plugin_get_interface"); + + if (get_boot_splash_plugin_interface == NULL) + { + ply_close_module (splash->module_handle); + splash->module_handle = NULL; + return false; + } + + splash->plugin_interface = get_boot_splash_plugin_interface (); + + if (splash->plugin_interface == NULL) + { + ply_close_module (splash->module_handle); + splash->module_handle = NULL; + return false; + } + + splash->plugin = splash->plugin_interface->create_plugin (); + + assert (splash->plugin != NULL); + + return true; +} + +static void +ply_boot_splash_unload_plugin (ply_boot_splash_t *splash) +{ + assert (splash != NULL); + assert (splash->plugin != NULL); + assert (splash->plugin_interface != NULL); + assert (splash->module_handle != NULL); + + splash->plugin_interface->destroy_plugin (splash->plugin); + splash->plugin = NULL; + + ply_close_module (splash->module_handle); + splash->plugin_interface = NULL; + splash->module_handle = NULL; +} + +bool +ply_boot_splash_show (ply_boot_splash_t *splash) +{ + assert (splash != NULL); + assert (splash->module_name != NULL); + assert (splash->loop != NULL); + + if (!ply_boot_splash_load_plugin (splash)) + return false; + + assert (splash->plugin_interface != NULL); + assert (splash->plugin != NULL); + assert (splash->plugin_interface->attach_to_event_loop != NULL); + assert (splash->plugin_interface->show_splash_screen != NULL); + + splash->plugin_interface->attach_to_event_loop (splash->plugin, + splash->loop); + splash->plugin_interface->show_splash_screen (splash->plugin); + + splash->is_shown = true; + return true; +} + +void +ply_boot_splash_update_status (ply_boot_splash_t *splash, + const char *status) +{ + assert (splash != NULL); + assert (status != NULL); + assert (splash->plugin_interface != NULL); + assert (splash->plugin != NULL); + assert (splash->plugin_interface->update_status != NULL); + assert (splash->is_shown); + + splash->plugin_interface->update_status (splash->plugin, status); +} + +void +ply_boot_splash_hide (ply_boot_splash_t *splash) +{ + assert (splash != NULL); + assert (splash->plugin_interface != NULL); + assert (splash->plugin != NULL); + assert (splash->plugin_interface->hide_splash_screen != NULL); + + splash->plugin_interface->hide_splash_screen (splash->plugin); + + ply_boot_splash_unload_plugin (splash); + splash->is_shown = false; +} + +static void +ply_boot_splash_detach_from_event_loop (ply_boot_splash_t *splash) +{ + assert (splash != NULL); + splash->loop = NULL; +} + +void +ply_boot_splash_attach_to_event_loop (ply_boot_splash_t *splash, + ply_event_loop_t *loop) +{ + assert (splash != NULL); + assert (loop != NULL); + assert (splash->loop == NULL); + + splash->loop = loop; + + ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t) + ply_boot_splash_detach_from_event_loop, + splash); +} + +#ifdef PLY_BOOT_SPLASH_ENABLE_TEST + +#include <stdio.h> + +#include "ply-event-loop.h" +#include "ply-boot-splash.h" + +int +main (int argc, + char **argv) +{ + ply_event_loop_t *loop; + ply_boot_splash_t *splash; + int exit_code; + + exit_code = 0; + + loop = ply_event_loop_new (); + + splash = ply_boot_splash_new ("fedora-fade-in.so"); + ply_boot_splash_attach_to_event_loop (splash, loop); + + if (!ply_boot_splash_show (splash)) + { + perror ("could not start boot status daemon"); + return errno; + } + + exit_code = ply_event_loop_run (loop); + ply_boot_splash_free (splash); + + return exit_code; +} + +#endif /* PLY_BOOT_SPLASH_ENABLE_TEST */ +/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/ply-boot-splash.h b/src/ply-boot-splash.h new file mode 100644 index 0000000..6ccdb15 --- /dev/null +++ b/src/ply-boot-splash.h @@ -0,0 +1,46 @@ +/* ply-boot-splash.h - APIs for putting up a splash screen + * + * Copyright (C) 2007 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written By: Ray Strode <rstrode@redhat.com> + */ +#ifndef PLY_BOOT_SPLASH_H +#define PLY_BOOT_SPLASH_H + +#include <stdbool.h> +#include <stdint.h> +#include <unistd.h> + +#include "ply-event-loop.h" + +typedef struct _ply_boot_splash ply_boot_splash_t; + +#ifndef PLY_HIDE_FUNCTION_DECLARATIONS +ply_boot_splash_t *ply_boot_splash_new (const char *module_name); +void ply_boot_splash_free (ply_boot_splash_t *splash); +bool ply_boot_splash_show (ply_boot_splash_t *splash); +void ply_boot_splash_update_status (ply_boot_splash_t *splash, + const char *status); +void ply_boot_splash_hide (ply_boot_splash_t *splash); +void ply_boot_splash_attach_to_event_loop (ply_boot_splash_t *splash, + ply_event_loop_t *loop); + +#endif + +#endif /* PLY_BOOT_SPLASH_H */ +/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/ply-utils.c b/src/ply-utils.c index abf1d2f..2136f4b 100644 --- a/src/ply-utils.c +++ b/src/ply-utils.c @@ -37,6 +37,8 @@ #include <sys/types.h> #include <sys/un.h> +#include <dlfcn.h> + #ifndef PLY_OPEN_FILE_DESCRIPTORS_DIR #define PLY_OPEN_FILE_DESCRIPTORS_DIR "/proc/self/fd" #endif @@ -577,4 +579,51 @@ ply_file_system_is_mounted (const char *type, return true; } +ply_module_handle_t * +ply_open_module (const char *module_path) +{ + ply_module_handle_t *handle; + + assert (module_path != NULL); + + handle = (ply_module_handle_t *) dlopen (module_path, RTLD_NOW | RTLD_LOCAL); + + if (handle == NULL) + { + dlerror (); + if (errno == 0) + errno = ELIBACC; + } + + return handle; +} + +ply_module_function_t +ply_module_look_up_function (ply_module_handle_t *handle, + const char *function_name) +{ + ply_module_function_t function; + + assert (handle != NULL); + assert (function_name != NULL); + + dlerror (); + function = (ply_module_function_t) dlsym (handle, function_name); + + if (dlerror () == NULL) + { + if (errno == 0) + errno = ELIBACC; + + return NULL; + } + + return function; +} + +void +ply_close_module (ply_module_handle_t *handle) +{ + dlclose (handle); +} /* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/ply-utils.h b/src/ply-utils.h index 6a81a62..6a59deb 100644 --- a/src/ply-utils.h +++ b/src/ply-utils.h @@ -38,6 +38,9 @@ #define CLAMP(a,b,c) (MIN (MAX ((a), (b)), (c))) #endif +typedef intptr_t ply_module_handle_t; +typedef void (* ply_module_function_t) (void); + #ifndef PLY_HIDE_FUNCTION_DECLARATIONS bool ply_open_unidirectional_pipe (int *sender_fd, int *receiver_fd); @@ -68,6 +71,12 @@ bool ply_directory_exists (const char *dir); bool ply_file_exists (const char *file); bool ply_file_system_is_mounted (const char *type, const char *path); + +ply_module_handle_t *ply_open_module (const char *module_path); +ply_module_function_t ply_module_look_up_function (ply_module_handle_t *handle, + const char *function_name); +void ply_close_module (ply_module_handle_t *handle); + #endif #endif /* PLY_UTILS_H */ diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index 6fa2e10..c43d0e3 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -14,5 +14,6 @@ include $(srcdir)/ply-list-test.am include $(srcdir)/ply-event-loop-test.am include $(srcdir)/ply-boot-client-test.am include $(srcdir)/ply-boot-server-test.am +include $(srcdir)/ply-boot-splash-test.am noinst_PROGRAMS = $(TESTS) diff --git a/src/tests/ply-boot-splash-test.am b/src/tests/ply-boot-splash-test.am new file mode 100644 index 0000000..6b5d4b6 --- /dev/null +++ b/src/tests/ply-boot-splash-test.am @@ -0,0 +1,17 @@ +TESTS += ply-boot-splash-test + +ply_boot_splash_test_CFLAGS = $(PLYMOUTH_CFLAGS) -DPLY_BOOT_SPLASH_ENABLE_TEST +ply_boot_splash_test_LDADD = $(PLYMOUTH_LIBS) + +ply_boot_splash_test_SOURCES = \ + $(srcdir)/../ply-utils.h \ + $(srcdir)/../ply-utils.c \ + $(srcdir)/../ply-logger.h \ + $(srcdir)/../ply-logger.c \ + $(srcdir)/../ply-list.h \ + $(srcdir)/../ply-list.c \ + $(srcdir)/../ply-event-loop.h \ + $(srcdir)/../ply-event-loop.c \ + $(srcdir)/../ply-boot-splash-plugin.h \ + $(srcdir)/../ply-boot-splash.h \ + $(srcdir)/../ply-boot-splash.c |