~xnox/upstart/upstart-async-run-dead-code

« back to all changes in this revision

Viewing changes to extra/upstart-udev-bridge.c

  • Committer: Scott James Remnant
  • Date: 2010-12-10 04:42:34 UTC
  • mto: This revision was merged to the branch mainline in revision 1307.
  • Revision ID: scott@netsplit.com-20101210044234-viqv07o1s06n8s8n
Import the udev bridge from Ubuntu

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* upstart
 
2
 *
 
3
 * Copyright © 2009 Canonical Ltd.
 
4
 * Author: Scott James Remnant <scott@netsplit.com>.
 
5
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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.
 
18
 */
 
19
 
 
20
#ifdef HAVE_CONFIG_H
 
21
# include <config.h>
 
22
#endif /* HAVE_CONFIG_H */
 
23
 
 
24
 
 
25
#include <libudev.h>
 
26
 
 
27
#include <stdlib.h>
 
28
#include <string.h>
 
29
#include <syslog.h>
 
30
 
 
31
#include <nih/macros.h>
 
32
#include <nih/alloc.h>
 
33
#include <nih/string.h>
 
34
#include <nih/io.h>
 
35
#include <nih/option.h>
 
36
#include <nih/main.h>
 
37
#include <nih/logging.h>
 
38
#include <nih/error.h>
 
39
 
 
40
#include <nih-dbus/dbus_connection.h>
 
41
#include <nih-dbus/dbus_proxy.h>
 
42
 
 
43
#include "dbus/upstart.h"
 
44
#include "com.ubuntu.Upstart.h"
 
45
 
 
46
 
 
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);
 
52
 
 
53
 
 
54
/**
 
55
 * daemonise:
 
56
 *
 
57
 * Set to TRUE if we should become a daemon, rather than just running
 
58
 * in the foreground.
 
59
 **/
 
60
static int daemonise = FALSE;
 
61
 
 
62
/**
 
63
 * upstart:
 
64
 *
 
65
 * Proxy to Upstart daemon.
 
66
 **/
 
67
static NihDBusProxy *upstart = NULL;
 
68
 
 
69
 
 
70
/**
 
71
 * options:
 
72
 *
 
73
 * Command-line options accepted by this program.
 
74
 **/
 
75
static NihOption options[] = {
 
76
        { 0, "daemon", N_("Detach and run in the background"),
 
77
          NULL, NULL, &daemonise, NULL },
 
78
 
 
79
        NIH_OPTION_LAST
 
80
};
 
81
 
 
82
 
 
83
int
 
84
main (int   argc,
 
85
      char *argv[])
 
86
{
 
87
        char **              args;
 
88
        DBusConnection *     connection;
 
89
        struct udev *        udev;
 
90
        struct udev_monitor *udev_monitor;
 
91
        int                  ret;
 
92
 
 
93
        nih_main_init (argv[0]);
 
94
 
 
95
        nih_option_set_synopsis (_("Bridge udev events into upstart"));
 
96
        nih_option_set_help (
 
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."));
 
100
 
 
101
        args = nih_option_parser (NULL, argc, argv, options, FALSE);
 
102
        if (! args)
 
103
                exit (1);
 
104
 
 
105
        /* Initialise the connection to Upstart */
 
106
        connection = NIH_SHOULD (nih_dbus_connect (DBUS_ADDRESS_UPSTART, upstart_disconnected));
 
107
        if (! connection) {
 
108
                NihError *err;
 
109
 
 
110
                err = nih_error_get ();
 
111
                nih_fatal ("%s: %s", _("Could not connect to Upstart"),
 
112
                           err->message);
 
113
                nih_free (err);
 
114
 
 
115
                exit (1);
 
116
        }
 
117
 
 
118
        upstart = NIH_SHOULD (nih_dbus_proxy_new (NULL, connection,
 
119
                                                  NULL, DBUS_PATH_UPSTART,
 
120
                                                  NULL, NULL));
 
121
        if (! upstart) {
 
122
                NihError *err;
 
123
 
 
124
                err = nih_error_get ();
 
125
                nih_fatal ("%s: %s", _("Could not create Upstart proxy"),
 
126
                           err->message);
 
127
                nih_free (err);
 
128
 
 
129
                exit (1);
 
130
        }
 
131
 
 
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);
 
137
 
 
138
        NIH_MUST (nih_io_add_watch (NULL, udev_monitor_get_fd (udev_monitor),
 
139
                                    NIH_IO_READ,
 
140
                                    (NihIoWatcher)udev_monitor_watcher,
 
141
                                    udev_monitor));
 
142
 
 
143
        /* Become daemon */
 
144
        if (daemonise) {
 
145
                if (nih_main_daemonise () < 0) {
 
146
                        NihError *err;
 
147
 
 
148
                        err = nih_error_get ();
 
149
                        nih_fatal ("%s: %s", _("Unable to become daemon"),
 
150
                                   err->message);
 
151
                        nih_free (err);
 
152
 
 
153
                        exit (1);
 
154
                }
 
155
 
 
156
                /* Send all logging output to syslog */
 
157
                openlog (program_name, LOG_PID, LOG_DAEMON);
 
158
                nih_log_set_logger (nih_logger_syslog);
 
159
        }
 
160
 
 
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));
 
164
 
 
165
        if (! daemonise) {
 
166
                nih_signal_set_handler (SIGINT, nih_signal_handler);
 
167
                NIH_MUST (nih_signal_add_handler (NULL, SIGINT, nih_main_term_signal, NULL));
 
168
        }
 
169
 
 
170
        ret = nih_main_loop ();
 
171
 
 
172
        return ret;
 
173
}
 
174
 
 
175
 
 
176
static void
 
177
udev_monitor_watcher (struct udev_monitor *udev_monitor,
 
178
                      NihIoWatch *         watch,
 
179
                      NihIoEvents          events)
 
180
{
 
181
        struct udev_device *    udev_device;
 
182
        const char *            subsystem;
 
183
        const char *            action;
 
184
        const char *            kernel;
 
185
        const char *            devpath;
 
186
        const char *            devname;
 
187
        nih_local char *        name = NULL;
 
188
        nih_local char **       env = NULL;
 
189
        size_t                  env_len = 0;
 
190
        DBusPendingCall *       pending_call;
 
191
 
 
192
        udev_device = udev_monitor_receive_device (udev_monitor);
 
193
        if (! udev_device)
 
194
                return;
 
195
 
 
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);
 
201
 
 
202
        if (! strcmp (action, "add")) {
 
203
                name = NIH_MUST (nih_sprintf (NULL, "%s-device-added",
 
204
                                              subsystem));
 
205
        } else if (! strcmp (action, "change")) {
 
206
                name = NIH_MUST (nih_sprintf (NULL, "%s-device-changed",
 
207
                                              subsystem));
 
208
        } else if (! strcmp (action, "remove")) {
 
209
                name = NIH_MUST (nih_sprintf (NULL, "%s-device-removed",
 
210
                                              subsystem));
 
211
        } else {
 
212
                name = NIH_MUST (nih_sprintf (NULL, "%s-device-%s",
 
213
                                              subsystem, action));
 
214
        }
 
215
 
 
216
        env = NIH_MUST (nih_str_array_new (NULL));
 
217
 
 
218
        if (kernel) {
 
219
                nih_local char *var = NULL;
 
220
 
 
221
                var = NIH_MUST (nih_sprintf (NULL, "KERNEL=%s", kernel));
 
222
                NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
 
223
        }
 
224
 
 
225
        if (devpath) {
 
226
                nih_local char *var = NULL;
 
227
 
 
228
                var = NIH_MUST (nih_sprintf (NULL, "DEVPATH=%s", devpath));
 
229
                NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
 
230
        }
 
231
 
 
232
        if (devname) {
 
233
                nih_local char *var = NULL;
 
234
 
 
235
                var = NIH_MUST (nih_sprintf (NULL, "DEVNAME=%s", devname));
 
236
                NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
 
237
        }
 
238
 
 
239
        if (subsystem) {
 
240
                nih_local char *var = NULL;
 
241
 
 
242
                var = NIH_MUST (nih_sprintf (NULL, "SUBSYSTEM=%s", subsystem));
 
243
                NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
 
244
        }
 
245
 
 
246
        if (action) {
 
247
                nih_local char *var = NULL;
 
248
 
 
249
                var = NIH_MUST (nih_sprintf (NULL, "ACTION=%s", action));
 
250
                NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
 
251
        }
 
252
 
 
253
        for (struct udev_list_entry *list_entry = udev_device_get_properties_list_entry (udev_device);
 
254
             list_entry != NULL;
 
255
             list_entry = udev_list_entry_get_next (list_entry)) {
 
256
                const char *    key;
 
257
                nih_local char *var = NULL;
 
258
 
 
259
                key = udev_list_entry_get_name (list_entry);
 
260
                if (! strcmp (key, "DEVPATH"))
 
261
                        continue;
 
262
                if (! strcmp (key, "DEVNAME"))
 
263
                        continue;
 
264
                if (! strcmp (key, "SUBSYSTEM"))
 
265
                        continue;
 
266
                if (! strcmp (key, "ACTION"))
 
267
                        continue;
 
268
 
 
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));
 
272
        }
 
273
 
 
274
        nih_debug ("%s %s", name, devname);
 
275
 
 
276
        pending_call = NIH_SHOULD (upstart_emit_event (upstart,
 
277
                                                       name, env, FALSE,
 
278
                                                       NULL, emit_event_error, NULL,
 
279
                                                       NIH_DBUS_TIMEOUT_NEVER));
 
280
        if (! pending_call) {
 
281
                NihError *err;
 
282
 
 
283
                err = nih_error_get ();
 
284
                nih_warn ("%s", err->message);
 
285
                nih_free (err);
 
286
        }
 
287
 
 
288
        dbus_pending_call_unref (pending_call);
 
289
 
 
290
        udev_device_unref (udev_device);
 
291
}
 
292
 
 
293
 
 
294
static void
 
295
upstart_disconnected (DBusConnection *connection)
 
296
{
 
297
        nih_fatal (_("Disconnected from Upstart"));
 
298
        nih_main_loop_exit (1);
 
299
}
 
300
 
 
301
static void
 
302
emit_event_error (void *          data,
 
303
                  NihDBusMessage *message)
 
304
{
 
305
        NihError *err;
 
306
 
 
307
        err = nih_error_get ();
 
308
        nih_warn ("%s", err->message);
 
309
        nih_free (err);
 
310
}