=== modified file 'extra/Makefile.am'
--- extra/Makefile.am	2011-06-06 15:49:43 +0000
+++ extra/Makefile.am	2012-12-19 14:54:21 +0000
@@ -17,13 +17,16 @@
 
 
 sbin_PROGRAMS = \
-	upstart-socket-bridge
+	upstart-socket-bridge \
+	upstart-event-bridge
 
 dist_init_DATA = \
-	conf/upstart-socket-bridge.conf
+	conf/upstart-socket-bridge.conf \
+	conf/upstart-event-bridge.conf
 
 dist_man_MANS = \
 	man/upstart-socket-bridge.8 \
+	man/upstart-event-bridge.8 \
 	man/socket-event.7
 
 upstart_socket_bridge_SOURCES = \
@@ -37,6 +40,18 @@
 	$(NIH_DBUS_LIBS) \
 	$(DBUS_LIBS)
 
+upstart_event_bridge_SOURCES = \
+	upstart-event-bridge.c
+nodist_upstart_event_bridge_SOURCES = \
+	$(com_ubuntu_Upstart_OUTPUTS) \
+	$(com_ubuntu_Upstart_Job_OUTPUTS)
+upstart_event_bridge_LDADD = \
+	$(LTLIBINTL) \
+	$(NIH_LIBS) \
+	$(NIH_DBUS_LIBS) \
+	$(DBUS_LIBS)
+
+
 
 if HAVE_UDEV
 dist_init_DATA += \

=== added file 'extra/conf/upstart-event-bridge.conf'
--- extra/conf/upstart-event-bridge.conf	1970-01-01 00:00:00 +0000
+++ extra/conf/upstart-event-bridge.conf	2012-12-19 14:54:21 +0000
@@ -0,0 +1,16 @@
+# upstart-events-bridge - Bridge system upstarts events into session upstart
+#
+# This helper daemon receives system upstart events from the DBus system bus
+# and emits equivalent events (with a :sys:) prefix to the session bus
+
+description	"Bridge Upstart system events into session Upstart"
+
+emits :sys:*
+
+start on started dbus
+stop on stopped dbus
+
+expect daemon
+respawn
+
+exec upstart-events-bridge --daemon

=== added file 'extra/man/upstart-event-bridge.8'
--- extra/man/upstart-event-bridge.8	1970-01-01 00:00:00 +0000
+++ extra/man/upstart-event-bridge.8	2012-12-19 14:54:21 +0000
@@ -0,0 +1,65 @@
+.TH upstart\-events\-bridge 8 2011-03-08 upstart
+.\"
+.SH NAME
+upstart\-events\-bridge \- Bridge between system Upstart and session Upstart
+.\"
+.SH SYNOPSIS
+.B upstart\-events\-bridge
+.RI [ OPTIONS ]...
+.\"
+.SH DESCRIPTION
+.B upstart\-events\-bridge
+receives information about Upstart system
+.BR events (8)
+have completed and creates Upstart session events for them.
+
+It emits events which match the pattern ":sys:*". Forwarding any event that's
+triggered on the system upstart as well as a virtual "restarted" event when
+upstart itself is restarted (during upgrades).
+
+See \fBevents\fP(7) and for further details.
+
+.\"
+.SH OPTIONS
+.\"
+.TP
+.B \-\-daemon
+Detach and run in the background.
+.\"
+.TP
+.B \-\-debug
+Enable debugging output.
+.\"
+.TP
+.B \-\-help
+Show brief usage summary.
+.\"
+.TP
+.B \-\-verbose
+Enable verbose output.
+.\"
+.SH EXAMPLES
+
+Some examples of Upstart events generated by this bridge:
+.IP :sys:restarted
+Event emitted when the system Upstart is restarted.
+.IP :sys:*
+Any event emitted on the system Upstart.
+.\"
+.SH AUTHOR
+Written by Stéphane Graber
+.RB < stgraber@ubuntu.com >
+.\"
+.SH BUGS
+Report bugs at 
+.RB < https://launchpad.net/ubuntu/+source/upstart/+bugs >
+.\"
+.SH COPYRIGHT
+Copyright \(co 2012 Canonical Ltd.
+.PP
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+.SH SEE ALSO
+.BR init (5)
+.BR init (8)
+.BR events (7)

=== added file 'extra/upstart-event-bridge.c'
--- extra/upstart-event-bridge.c	1970-01-01 00:00:00 +0000
+++ extra/upstart-event-bridge.c	2012-12-19 14:54:21 +0000
@@ -0,0 +1,309 @@
+/* upstart
+ *
+ * Copyright © 2012 Canonical Ltd.
+ * Author: Stéphane Graber <stgraber@ubuntu.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <ctype.h>
+
+#include <nih/macros.h>
+#include <nih/alloc.h>
+#include <nih/string.h>
+#include <nih/io.h>
+#include <nih/option.h>
+#include <nih/main.h>
+#include <nih/logging.h>
+#include <nih/error.h>
+
+#include <nih-dbus/dbus_connection.h>
+#include <nih-dbus/dbus_proxy.h>
+
+#include "dbus/upstart.h"
+#include "com.ubuntu.Upstart.h"
+
+
+/* Prototypes for static functions */
+static void upstart_disconnected (DBusConnection *connection);
+static void upstart_forward_event    (void *data, NihDBusMessage *message,
+				  const char *path);
+static void upstart_forward_restarted    (void *data, NihDBusMessage *message,
+				  const char *path);
+static void emit_event_error     (void *data, NihDBusMessage *message);
+
+/**
+ * daemonise:
+ *
+ * Set to TRUE if we should become a daemon, rather than just running
+ * in the foreground.
+ **/
+static int daemonise = FALSE;
+
+/**
+ * system_upstart:
+ *
+ * Proxy to system Upstart daemon.
+ **/
+static NihDBusProxy *system_upstart = NULL;
+
+/**
+ * session_upstart:
+ *
+ * Proxy to session Upstart daemon.
+ **/
+static NihDBusProxy *session_upstart = NULL;
+
+/**
+ * options:
+ *
+ * Command-line options accepted by this program.
+ **/
+static NihOption options[] = {
+	{ 0, "daemon", N_("Detach and run in the background"),
+	  NULL, NULL, &daemonise, NULL },
+
+	NIH_OPTION_LAST
+};
+
+
+int
+main (int   argc,
+      char *argv[])
+{
+	char **              args;
+	DBusConnection *     system_connection;
+	DBusConnection *     session_connection;
+	int                  ret;
+
+
+	nih_main_init (argv[0]);
+
+	nih_option_set_synopsis (_("Bridge system upstart events into session upstart"));
+	nih_option_set_help (
+		_("By default, upstart-event-bridge does not detach from the "
+		  "console and remains in the foreground.  Use the --daemon "
+		  "option to have it detach."));
+
+	args = nih_option_parser (NULL, argc, argv, options, FALSE);
+	if (! args)
+		exit (1);
+
+	/* Initialise the connection to system Upstart */
+	system_connection = NIH_SHOULD (nih_dbus_bus (DBUS_BUS_SYSTEM, upstart_disconnected));
+
+	if (! system_connection) {
+		NihError *err;
+
+		err = nih_error_get ();
+		nih_fatal ("%s: %s", _("Could not connect to system Upstart"),
+			   err->message);
+		nih_free (err);
+
+		exit (1);
+	}
+
+	system_upstart = NIH_SHOULD (nih_dbus_proxy_new (NULL, system_connection,
+						  DBUS_SERVICE_UPSTART, DBUS_PATH_UPSTART,
+						  NULL, NULL));
+	if (! system_upstart) {
+		NihError *err;
+
+		err = nih_error_get ();
+		nih_fatal ("%s: %s", _("Could not create Upstart proxy"),
+			   err->message);
+		nih_free (err);
+
+		exit (1);
+	}
+
+	if (! nih_dbus_proxy_connect (system_upstart, &upstart_com_ubuntu_Upstart0_6, "EventEmitted",
+				      (NihDBusSignalHandler)upstart_forward_event, NULL)) {
+		NihError *err;
+
+		err = nih_error_get ();
+		nih_fatal ("%s: %s", _("Could not create EventEmitted signal connection"),
+			   err->message);
+		nih_free (err);
+
+		exit (1);
+	}
+
+	if (! nih_dbus_proxy_connect (system_upstart, &upstart_com_ubuntu_Upstart0_6, "Restarted",
+				      (NihDBusSignalHandler)upstart_forward_restarted, NULL)) {
+		NihError *err;
+
+		err = nih_error_get ();
+		nih_fatal ("%s: %s", _("Could not create Restarted signal connection"),
+			   err->message);
+		nih_free (err);
+
+		exit (1);
+	}
+
+	/* Initialise the connection to session Upstart */
+	session_connection = nih_dbus_bus (DBUS_BUS_SESSION, upstart_disconnected);
+
+	if (! session_connection) {
+		NihError *err;
+
+		err = nih_error_get ();
+		nih_fatal ("%s: %s", _("Could not connect to session Upstart"),
+			   err->message);
+		nih_free (err);
+
+		exit (1);
+	}
+
+	session_upstart = NIH_SHOULD (nih_dbus_proxy_new (NULL, session_connection,
+						  DBUS_SERVICE_UPSTART, DBUS_PATH_UPSTART,
+						  NULL, NULL));
+	if (! session_upstart) {
+		NihError *err;
+
+		err = nih_error_get ();
+		nih_fatal ("%s: %s", _("Could not create Upstart proxy"),
+			   err->message);
+		nih_free (err);
+
+		exit (1);
+	}
+
+	/* Become daemon */
+	if (daemonise) {
+		if (nih_main_daemonise () < 0) {
+			NihError *err;
+
+			err = nih_error_get ();
+			nih_fatal ("%s: %s", _("Unable to become daemon"),
+				   err->message);
+			nih_free (err);
+
+			exit (1);
+		}
+
+		/* Send all logging output to syslog */
+		openlog (program_name, LOG_PID, LOG_DAEMON);
+		nih_log_set_logger (nih_logger_syslog);
+	}
+
+	/* Handle TERM and INT signals gracefully */
+	nih_signal_set_handler (SIGTERM, nih_signal_handler);
+	NIH_MUST (nih_signal_add_handler (NULL, SIGTERM, nih_main_term_signal, NULL));
+
+	if (! daemonise) {
+		nih_signal_set_handler (SIGINT, nih_signal_handler);
+		NIH_MUST (nih_signal_add_handler (NULL, SIGINT, nih_main_term_signal, NULL));
+	}
+
+	ret = nih_main_loop ();
+
+	return ret;
+}
+
+static void
+upstart_disconnected (DBusConnection *connection)
+{
+	nih_fatal (_("Disconnected from Upstart"));
+	nih_main_loop_exit (1);
+}
+
+static void
+upstart_forward_event (void *          data,
+		     NihDBusMessage *message,
+		     const char *    path)
+{
+	char *              event_name = NULL;
+	nih_local char *    new_event_name = NULL;
+	char **             event_env = NULL;
+	int                 event_env_count = 0;
+	DBusError           error;
+	DBusPendingCall *   pending_call;
+
+	dbus_error_init (&error);
+
+	/* Extract information from the original event */
+	if (!dbus_message_get_args (message->message, &error,
+	        DBUS_TYPE_STRING, &event_name,
+	        DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &event_env, &event_env_count,
+	        DBUS_TYPE_INVALID)) {
+		nih_error("DBUS error: %s", error.message);
+		dbus_error_free(&error);
+		return;
+	}
+
+	nih_assert (event_name != NULL);
+
+	/* Build the new event name */
+	NIH_MUST (nih_strcat_sprintf (&new_event_name, NULL, ":sys:%s", event_name));
+
+	/* Re-transmit the event */
+	pending_call = upstart_emit_event (session_upstart,
+			new_event_name, event_env, FALSE,
+			NULL, emit_event_error, NULL,
+			NIH_DBUS_TIMEOUT_NEVER);
+
+	if (! pending_call) {
+		NihError *err;
+		err = nih_error_get ();
+		nih_warn ("%s", err->message);
+		nih_free (err);
+	}
+
+	dbus_pending_call_unref (pending_call);
+	dbus_free_string_array (event_env);
+}
+
+static void
+upstart_forward_restarted (void *          data,
+		     NihDBusMessage *message,
+		     const char *    path)
+{
+	DBusPendingCall *   pending_call;
+
+	/* Re-transmit the event */
+	pending_call = upstart_emit_event (session_upstart,
+			":sys:restarted", NULL, FALSE,
+			NULL, emit_event_error, NULL,
+			NIH_DBUS_TIMEOUT_NEVER);
+
+	if (! pending_call) {
+		NihError *err;
+		err = nih_error_get ();
+		nih_warn ("%s", err->message);
+		nih_free (err);
+	}
+
+	dbus_pending_call_unref (pending_call);
+}
+
+static void
+emit_event_error (void *          data,
+		  NihDBusMessage *message)
+{
+	NihError *err;
+
+	err = nih_error_get ();
+	nih_warn ("%s", err->message);
+	nih_free (err);
+}

