3
* Copyright © 2009 Canonical Ltd.
4
* Author: Scott James Remnant <scott@netsplit.com>.
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2, as
8
* published by the Free Software Foundation.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License along
16
* with this program; if not, write to the Free Software Foundation, Inc.,
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
#endif /* HAVE_CONFIG_H */
31
#include <nih/macros.h>
32
#include <nih/alloc.h>
33
#include <nih/string.h>
35
#include <nih/option.h>
37
#include <nih/logging.h>
38
#include <nih/error.h>
40
#include <nih-dbus/dbus_connection.h>
41
#include <nih-dbus/dbus_proxy.h>
43
#include "dbus/upstart.h"
44
#include "com.ubuntu.Upstart.h"
47
/* Prototypes for static functions */
48
static void udev_monitor_watcher (struct udev_monitor *udev_monitor,
49
NihIoWatch *watch, NihIoEvents events);
50
static void upstart_disconnected (DBusConnection *connection);
51
static void emit_event_error (void *data, NihDBusMessage *message);
57
* Set to TRUE if we should become a daemon, rather than just running
60
static int daemonise = FALSE;
65
* Proxy to Upstart daemon.
67
static NihDBusProxy *upstart = NULL;
73
* Command-line options accepted by this program.
75
static NihOption options[] = {
76
{ 0, "daemon", N_("Detach and run in the background"),
77
NULL, NULL, &daemonise, NULL },
88
DBusConnection * connection;
90
struct udev_monitor *udev_monitor;
93
nih_main_init (argv[0]);
95
nih_option_set_synopsis (_("Bridge udev events into upstart"));
97
_("By default, upstart-udev-bridge does not detach from the "
98
"console and remains in the foreground. Use the --daemon "
99
"option to have it detach."));
101
args = nih_option_parser (NULL, argc, argv, options, FALSE);
105
/* Initialise the connection to Upstart */
106
connection = NIH_SHOULD (nih_dbus_connect (DBUS_ADDRESS_UPSTART, upstart_disconnected));
110
err = nih_error_get ();
111
nih_fatal ("%s: %s", _("Could not connect to Upstart"),
118
upstart = NIH_SHOULD (nih_dbus_proxy_new (NULL, connection,
119
NULL, DBUS_PATH_UPSTART,
124
err = nih_error_get ();
125
nih_fatal ("%s: %s", _("Could not create Upstart proxy"),
132
/* Initialise the connection to udev */
133
nih_assert (udev = udev_new ());
134
nih_assert (udev_monitor = udev_monitor_new_from_netlink (udev, "udev"));
135
nih_assert (udev_monitor_enable_receiving (udev_monitor) == 0);
136
udev_monitor_set_receive_buffer_size(udev_monitor, 128*1024*1024);
138
NIH_MUST (nih_io_add_watch (NULL, udev_monitor_get_fd (udev_monitor),
140
(NihIoWatcher)udev_monitor_watcher,
145
if (nih_main_daemonise () < 0) {
148
err = nih_error_get ();
149
nih_fatal ("%s: %s", _("Unable to become daemon"),
156
/* Send all logging output to syslog */
157
openlog (program_name, LOG_PID, LOG_DAEMON);
158
nih_log_set_logger (nih_logger_syslog);
161
/* Handle TERM and INT signals gracefully */
162
nih_signal_set_handler (SIGTERM, nih_signal_handler);
163
NIH_MUST (nih_signal_add_handler (NULL, SIGTERM, nih_main_term_signal, NULL));
166
nih_signal_set_handler (SIGINT, nih_signal_handler);
167
NIH_MUST (nih_signal_add_handler (NULL, SIGINT, nih_main_term_signal, NULL));
170
ret = nih_main_loop ();
177
udev_monitor_watcher (struct udev_monitor *udev_monitor,
181
struct udev_device * udev_device;
182
const char * subsystem;
185
const char * devpath;
186
const char * devname;
187
nih_local char * name = NULL;
188
nih_local char ** env = NULL;
190
DBusPendingCall * pending_call;
192
udev_device = udev_monitor_receive_device (udev_monitor);
196
subsystem = udev_device_get_subsystem (udev_device);
197
action = udev_device_get_action (udev_device);
198
kernel = udev_device_get_sysname (udev_device);
199
devpath = udev_device_get_devpath (udev_device);
200
devname = udev_device_get_devnode (udev_device);
202
if (! strcmp (action, "add")) {
203
name = NIH_MUST (nih_sprintf (NULL, "%s-device-added",
205
} else if (! strcmp (action, "change")) {
206
name = NIH_MUST (nih_sprintf (NULL, "%s-device-changed",
208
} else if (! strcmp (action, "remove")) {
209
name = NIH_MUST (nih_sprintf (NULL, "%s-device-removed",
212
name = NIH_MUST (nih_sprintf (NULL, "%s-device-%s",
216
env = NIH_MUST (nih_str_array_new (NULL));
219
nih_local char *var = NULL;
221
var = NIH_MUST (nih_sprintf (NULL, "KERNEL=%s", kernel));
222
NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
226
nih_local char *var = NULL;
228
var = NIH_MUST (nih_sprintf (NULL, "DEVPATH=%s", devpath));
229
NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
233
nih_local char *var = NULL;
235
var = NIH_MUST (nih_sprintf (NULL, "DEVNAME=%s", devname));
236
NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
240
nih_local char *var = NULL;
242
var = NIH_MUST (nih_sprintf (NULL, "SUBSYSTEM=%s", subsystem));
243
NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
247
nih_local char *var = NULL;
249
var = NIH_MUST (nih_sprintf (NULL, "ACTION=%s", action));
250
NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
253
for (struct udev_list_entry *list_entry = udev_device_get_properties_list_entry (udev_device);
255
list_entry = udev_list_entry_get_next (list_entry)) {
257
nih_local char *var = NULL;
259
key = udev_list_entry_get_name (list_entry);
260
if (! strcmp (key, "DEVPATH"))
262
if (! strcmp (key, "DEVNAME"))
264
if (! strcmp (key, "SUBSYSTEM"))
266
if (! strcmp (key, "ACTION"))
269
var = NIH_MUST (nih_sprintf (NULL, "%s=%s", key,
270
udev_list_entry_get_value (list_entry)));
271
NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
274
nih_debug ("%s %s", name, devname);
276
pending_call = NIH_SHOULD (upstart_emit_event (upstart,
278
NULL, emit_event_error, NULL,
279
NIH_DBUS_TIMEOUT_NEVER));
280
if (! pending_call) {
283
err = nih_error_get ();
284
nih_warn ("%s", err->message);
288
dbus_pending_call_unref (pending_call);
290
udev_device_unref (udev_device);
295
upstart_disconnected (DBusConnection *connection)
297
nih_fatal (_("Disconnected from Upstart"));
298
nih_main_loop_exit (1);
302
emit_event_error (void * data,
303
NihDBusMessage *message)
307
err = nih_error_get ();
308
nih_warn ("%s", err->message);