upstart-bridge: add new helper program

This commit adds a new program, plymouth-upstart-bridge,
the listens for upstart state changes and sends them to plymouth,
or prints them out as appropriate.
calculate-0.9.5
Colin Watson 13 years ago committed by Ray Strode
parent 852c016e0d
commit 61e5859672

1
.gitignore vendored

@ -31,6 +31,7 @@ plymouth-generate-initrd
plymouth-populate-initrd
plymouth-set-default-theme
plymouth-log-viewer
plymouth-upstart-bridge
plymouthd
*.pc
tags

@ -225,6 +225,23 @@ if test x$enable_gdm_transition = xyes; then
AC_DEFINE(PLY_ENABLE_GDM_TRANSITION, 1, [Enable smooth transition to GDM])
fi
AC_ARG_ENABLE(upstart-monitoring, AS_HELP_STRING([--enable-upstart-monitoring],[listen for messages on the Upstart D-Bus interface]),enable_upstart_monitoring=$enableval,enable_upstart_monitoring=no)
if test x$enable_upstart_monitoring = xyes; then
PKG_CHECK_MODULES(DBUS, [dbus-1])
AC_SUBST(DBUS_CFLAGS)
AC_SUBST(DBUS_LIBS)
AC_CHECK_HEADERS([ncursesw/term.h ncurses/term.h term.h], [break])
AC_CHECK_LIB([ncursesw], [initscr],
[CURSES_LIBS="$CURSES_LIBS -lncursesw"],
[AC_CHECK_LIB([ncurses], [initscr],
[CURSES_LIBS="$CURSES_LIBS -lncurses"],
[AC_CHECK_LIB([curses], [initscr],
[CURSES_LIBS="$CURSES_LIBS -lcurses"],
[AC_MSG_ERROR([no curses library found])])])])
AC_SUBST(CURSES_LIBS)
fi
AM_CONDITIONAL(ENABLE_UPSTART_MONITORING, [test "$enable_upstart_monitoring" = yes])
AC_ARG_WITH(system-root-install, AS_HELP_STRING([--with-system-root-install],[Install client in /bin and daemon in /sbin]),with_system_root_install=${withval},with_system_root_install=yes)
AM_CONDITIONAL(WITH_SYSTEM_ROOT_INSTALL, [test "$with_system_root_install" = yes])
@ -398,6 +415,7 @@ AC_CONFIG_FILES([Makefile
src/client/ply-boot-client.pc
src/client/Makefile
src/viewer/Makefile
src/upstart-bridge/Makefile
src/tests/Makefile
src/libply/tests/Makefile
src/client/tests/Makefile

@ -1,4 +1,7 @@
SUBDIRS = libply libply-splash-core libply-splash-graphics . plugins client viewer tests
if ENABLE_UPSTART_MONITORING
SUBDIRS += upstart-bridge
endif
INCLUDES = -I$(top_srcdir) \
-I$(srcdir)/libply \
-I$(srcdir)/libply-splash-core \

@ -0,0 +1,21 @@
INCLUDES = -I$(top_srcdir) \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/libply \
-I$(top_srcdir)/src/client \
-I$(srcdir)
plymouthdir = $(plymouthclientdir)
plymouth_PROGRAMS = plymouth-upstart-bridge
plymouth_upstart_bridge_CFLAGS = $(PLYMOUTH_CFLAGS) $(DBUS_CFLAGS)
plymouth_upstart_bridge_LDADD = \
$(PLYMOUTH_LIBS) \
$(DBUS_LIBS) \
$(CURSES_LIBS) \
../libply/libply.la \
../client/libply-boot-client.la
plymouth_upstart_bridge_SOURCES = \
$(srcdir)/../ply-boot-protocol.h \
$(srcdir)/ply-upstart-monitor.h \
$(srcdir)/ply-upstart-monitor.c \
$(srcdir)/plymouth-upstart-bridge.c

File diff suppressed because it is too large Load Diff

@ -0,0 +1,68 @@
/* ply-upstart-monitor.h - Upstart D-Bus listener
*
* Copyright (C) 2010, 2011 Canonical Ltd.
*
* 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: Colin Watson <cjwatson@ubuntu.com>
*/
#ifndef PLY_UPSTART_H
#define PLY_UPSTART_H
#include <stdbool.h>
#include "ply-event-loop.h"
typedef struct _ply_upstart_monitor ply_upstart_monitor_t;
typedef struct {
char *name;
char *description;
bool is_task;
} ply_upstart_monitor_job_properties_t;
typedef struct {
char *name;
char *goal;
char *state;
uint32_t failed : 1;
} ply_upstart_monitor_instance_properties_t;
typedef void (* ply_upstart_monitor_state_changed_handler_t) (void *user_data,
const char *old_state,
ply_upstart_monitor_job_properties_t *job,
ply_upstart_monitor_instance_properties_t *instance);
typedef void (* ply_upstart_monitor_failed_handler_t) (void *user_data,
ply_upstart_monitor_job_properties_t *job,
ply_upstart_monitor_instance_properties_t *instance,
int status);
#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
ply_upstart_monitor_t *ply_upstart_monitor_new (ply_event_loop_t *loop);
void ply_upstart_monitor_free (ply_upstart_monitor_t *upstart);
bool ply_upstart_monitor_connect_to_event_loop (ply_upstart_monitor_t *upstart,
ply_event_loop_t *loop);
void ply_upstart_monitor_add_state_changed_handler (ply_upstart_monitor_t *upstart,
ply_upstart_monitor_state_changed_handler_t handler,
void *user_data);
void ply_upstart_monitor_add_failed_handler (ply_upstart_monitor_t *upstart,
ply_upstart_monitor_failed_handler_t handler,
void *user_data);
#endif
#endif
/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */

@ -0,0 +1,339 @@
/* plymouth-upstart-bridge.c - bridge Upstart job state changes to Plymouth
*
* Copyright (C) 2010, 2011 Canonical Ltd.
*
* 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: Colin Watson <cjwatson@ubuntu.com>
*/
#include "config.h"
#include <stdbool.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#if defined(HAVE_NCURSESW_TERM_H)
#include <ncursesw/term.h>
#elif defined(HAVE_NCURSES_TERM_H)
#include <ncurses/term.h>
#else
#include <term.h>
#endif
#include "ply-boot-client.h"
#include "ply-command-parser.h"
#include "ply-event-loop.h"
#include "ply-logger.h"
#include "ply-upstart-monitor.h"
typedef struct
{
ply_event_loop_t *loop;
ply_boot_client_t *client;
ply_upstart_monitor_t *upstart;
ply_command_parser_t *command_parser;
} state_t;
#ifndef TERMINAL_COLOR_RED
#define TERMINAL_COLOR_RED 1
#endif
/* We don't care about the difference between "not a string capability" and
* "cancelled or absent".
*/
static const char *
get_string_capability (const char *name)
{
const char *value;
value = tigetstr ((char *) name);
if (value == (const char *) -1)
value = NULL;
return value;
}
static bool
terminal_ignores_new_line_after_80_chars (void)
{
return tigetflag ((char *) "xenl") != 0;
}
static int
get_number_of_columns (void)
{
int number_of_columns;
number_of_columns = tigetnum ((char *) "cols");
return number_of_columns;
}
static bool
can_set_cursor_column (void)
{
const char *capability;
capability = get_string_capability ("hpa");
return capability != NULL;
}
static void
set_cursor_column (int column)
{
const char *capability;
const char *terminal_string;
capability = get_string_capability ("hpa");
terminal_string = tiparm (capability, column);
fputs (terminal_string, stdout);
}
static bool
can_set_fg_color (void)
{
const char *capability;
capability = get_string_capability ("setaf");
return capability != NULL;
}
static void
set_fg_color (int color)
{
const char *capability;
const char *terminal_string;
capability = get_string_capability ("setaf");
terminal_string = tiparm (capability, color);
fputs (terminal_string, stdout);
}
static void
unset_fg_color (void)
{
const char *terminal_string;
terminal_string = get_string_capability ("op");
if (terminal_string == NULL)
return;
fputs (terminal_string, stdout);
}
static void
update_status (state_t *state,
ply_upstart_monitor_job_properties_t *job,
ply_upstart_monitor_instance_properties_t *instance,
const char *action,
bool is_okay)
{
ply_boot_client_update_daemon (state->client, job->name, NULL, NULL, state);
if (job->description == NULL)
return;
printf (" * %s%s%s",
action ? action : "", action ? " " : "", job->description);
if (terminal_ignores_new_line_after_80_chars () && can_set_cursor_column ())
{
int number_of_columns, column;
number_of_columns = get_number_of_columns ();
if (number_of_columns < (int) strlen("[fail]"))
number_of_columns = 80;
column = number_of_columns - strlen ("[fail]") - 1;
set_cursor_column (column);
if (is_okay)
puts ("[ OK ]");
else
{
bool supports_color;
supports_color = can_set_fg_color ();
fputs ("[", stdout);
if (supports_color)
set_fg_color (TERMINAL_COLOR_RED);
fputs ("fail", stdout);
if (supports_color)
unset_fg_color ();
puts ("]");
}
}
else
{
if (is_okay)
puts (" ...done.");
else
puts (" ...fail!");
}
}
static void
on_failed (void *data,
ply_upstart_monitor_job_properties_t *job,
ply_upstart_monitor_instance_properties_t *instance,
int status)
{
state_t *state = data;
if (job->is_task)
update_status (state, job, instance, NULL, false);
else
{
if (strcmp (instance->goal, "start") == 0)
update_status (state, job, instance, "Starting", false);
else if (strcmp (instance->goal, "stop") == 0)
update_status (state, job, instance, "Stopping", false);
}
}
static void
on_state_changed (state_t *state,
const char *old_state,
ply_upstart_monitor_job_properties_t *job,
ply_upstart_monitor_instance_properties_t *instance)
{
if (instance->failed)
return;
if (job->is_task)
{
if (strcmp (instance->state, "waiting") == 0)
update_status (state, job, instance, NULL, true);
}
else
{
if (strcmp (instance->goal, "start") == 0)
{
if (strcmp (instance->state, "running") == 0)
update_status (state, job, instance, "Starting", true);
}
else if (strcmp (instance->goal, "stop") == 0)
{
if (strcmp (instance->state, "waiting") == 0)
update_status (state, job, instance, "Stopping", true);
}
}
}
static void
on_disconnect (state_t *state)
{
ply_trace ("disconnected from boot status daemon");
ply_event_loop_exit (state->loop, 0);
}
int
main (int argc,
char **argv)
{
state_t state = { 0 };
bool should_help, should_be_verbose;
bool is_connected;
int exit_code;
exit_code = 0;
signal (SIGPIPE, SIG_IGN);
state.loop = ply_event_loop_new ();
state.client = ply_boot_client_new ();
state.command_parser = ply_command_parser_new ("plymouth-upstart-bridge", "Upstart job state bridge");
ply_command_parser_add_options (state.command_parser,
"help", "This help message", PLY_COMMAND_OPTION_TYPE_FLAG,
"debug", "Enable verbose debug logging", PLY_COMMAND_OPTION_TYPE_FLAG,
NULL);
if (!ply_command_parser_parse_arguments (state.command_parser, state.loop, argv, argc))
{
char *help_string;
help_string = ply_command_parser_get_help_string (state.command_parser);
ply_error ("%s", help_string);
free (help_string);
return 1;
}
ply_command_parser_get_options (state.command_parser,
"help", &should_help,
"debug", &should_be_verbose,
NULL);
if (should_help)
{
char *help_string;
help_string = ply_command_parser_get_help_string (state.command_parser);
puts (help_string);
free (help_string);
return 0;
}
if (should_be_verbose && !ply_is_tracing ())
ply_toggle_tracing ();
setupterm (NULL, STDOUT_FILENO, NULL);
is_connected = ply_boot_client_connect (state.client,
(ply_boot_client_disconnect_handler_t)
on_disconnect, &state);
if (!is_connected)
{
ply_trace ("daemon not running");
return 1;
}
ply_boot_client_attach_to_event_loop (state.client, state.loop);
state.upstart = ply_upstart_monitor_new (state.loop);
if (!state.upstart)
return 1;
ply_upstart_monitor_add_state_changed_handler (state.upstart,
(ply_upstart_monitor_state_changed_handler_t)
on_state_changed, &state);
ply_upstart_monitor_add_failed_handler (state.upstart, on_failed, &state);
exit_code = ply_event_loop_run (state.loop);
ply_upstart_monitor_free (state.upstart);
ply_boot_client_free (state.client);
ply_event_loop_free (state.loop);
return exit_code;
}
/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
Loading…
Cancel
Save