Merge lp:~jamesodhunt/upstart/upstream-udev+socket-bridges into lp:upstart

Proposed by James Hunt
Status: Merged
Merged at revision: 1307
Proposed branch: lp:~jamesodhunt/upstart/upstream-udev+socket-bridges
Merge into: lp:upstart
Diff against target: 2371 lines (+1631/-110)
34 files modified
.bzrignore (+4/-0)
Makefile.am (+1/-1)
configure.ac (+6/-3)
dbus/com.ubuntu.Upstart.xml (+7/-0)
extra/Makefile.am (+125/-0)
extra/conf/upstart-socket-bridge.conf (+16/-0)
extra/conf/upstart-udev-bridge.conf (+16/-0)
extra/man/socket-event.7 (+92/-0)
extra/man/upstart-socket-bridge.8 (+47/-0)
extra/man/upstart-udev-bridge.8 (+57/-0)
extra/upstart-socket-bridge.c (+644/-0)
extra/upstart-udev-bridge.c (+310/-0)
init/conf.c (+0/-1)
init/control.c (+38/-9)
init/control.h (+4/-0)
init/environ.c (+0/-1)
init/environ.h (+0/-1)
init/event.c (+13/-0)
init/event.h (+1/-0)
init/event_operator.c (+59/-0)
init/event_operator.h (+8/-0)
init/job.c (+3/-0)
init/job.h (+3/-0)
init/job_process.c (+0/-1)
init/job_process.h (+0/-1)
init/main.c (+0/-1)
init/tests/test_conf.c (+0/-1)
init/tests/test_control.c (+0/-1)
init/tests/test_environ.c (+0/-1)
init/tests/test_job_class.c (+0/-1)
init/tests/test_job_process.c (+0/-1)
po/POTFILES.in (+2/-0)
po/upstart.pot (+175/-85)
util/reboot.c (+0/-1)
To merge this branch: bzr merge lp:~jamesodhunt/upstart/upstream-udev+socket-bridges
Reviewer Review Type Date Requested Status
Upstart Developers Pending
Review via email: mp+63583@code.launchpad.net

Description of the change

* Makefile.am: Added extra directory.
* New files:
  - extra/Makefile.am
  - extra/conf/upstart-socket-bridge.conf
  - extra/conf/upstart-udev-bridge.conf
  - extra/man/socket-event.7
  - extra/man/upstart-socket-bridge.8
  - extra/man/upstart-udev-bridge.8
  - extra/upstart-socket-bridge.c
  - extra/upstart-udev-bridge.c
* configure.ac:
  - Check for udev (for upstart-udev-bridge).
  - Add extra/Makefile to AC_CONFIG_FILES.
* dbus/com.ubuntu.Upstart.xml: Add EmitEventWithFile method.
* init/control.c:
  - control_emit_event(): Now a wrapper for control_emit_event_with_file.
  - control_emit_event_with_file(): New function that operates on an fd.
* init/control.h: Prototype for control_emit_event_with_file().
* init/event.c:
  - event_new(): Initialize event fd.
  - event_pending_handle_jobs(): Now calls event_operator_fds().
* init/event.c: Add fd to Event struct.
* init/event_operator.c: event_operator_fds(): New function.
* init/event_operator.h: Prototype for event_operator_fds().
* init/job.c: job_new(): Initialize fd members.
* init/job.h: Add fds and num_fds to Job struct.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2010-12-10 04:03:25 +0000
3+++ .bzrignore 2011-06-06 17:07:26 +0000
4@@ -59,3 +59,7 @@
5 util/shutdown
6 util/telinit
7 util/test_*
8+extra/com.ubuntu.Upstart.[ch]
9+extra/com.ubuntu.Upstart.Job.[ch]
10+extra/upstart-socket-bridge
11+extra/upstart-udev-bridge
12
13=== modified file 'Makefile.am'
14--- Makefile.am 2010-02-04 03:42:29 +0000
15+++ Makefile.am 2011-06-06 17:07:26 +0000
16@@ -1,6 +1,6 @@
17 ## Process this file with automake to produce Makefile.in
18
19-SUBDIRS = intl dbus init util conf doc contrib po
20+SUBDIRS = intl dbus init util extra conf doc contrib po
21
22 EXTRA_DIST = HACKING
23
24
25=== modified file 'configure.ac'
26--- configure.ac 2011-03-22 17:53:17 +0000
27+++ configure.ac 2011-06-06 17:07:26 +0000
28@@ -2,7 +2,7 @@
29
30 AC_PREREQ(2.61)
31 AC_INIT([upstart], [1.3], [upstart-devel@lists.ubuntu.com])
32-NIH_COPYRIGHT([[Copyright © 2011 Scott James Remnant, Google Inc., Canonical Ltd.]])
33+NIH_COPYRIGHT([[Copyright © 2011 Scott James Remnant, Canonical Ltd.]])
34 AC_CONFIG_SRCDIR([init/main.c])
35 AC_CONFIG_MACRO_DIR([m4])
36
37@@ -30,6 +30,9 @@
38 PKG_CHECK_MODULES([NIH], [libnih >= 1.0.2])
39 PKG_CHECK_MODULES([NIH_DBUS], [libnih-dbus >= 1.0.0])
40 PKG_CHECK_MODULES([DBUS], [dbus-1 >= 1.2.16])
41+PKG_CHECK_MODULES([UDEV], [libudev >= 146], [have_udev=yes], [have_udev=no])
42+
43+AM_CONDITIONAL([HAVE_UDEV], [test "$have_udev" = yes])
44
45 # Checks for header files.
46 AC_CHECK_HEADERS([valgrind/valgrind.h])
47@@ -63,7 +66,7 @@
48
49
50 AC_CONFIG_FILES([ Makefile intl/Makefile
51- dbus/Makefile init/Makefile util/Makefile conf/Makefile
52- doc/Makefile contrib/Makefile po/Makefile.in ])
53+ dbus/Makefile init/Makefile util/Makefile extra/Makefile
54+ conf/Makefile doc/Makefile contrib/Makefile po/Makefile.in ])
55 AC_CONFIG_HEADERS([config.h])
56 AC_OUTPUT
57
58=== modified file 'dbus/com.ubuntu.Upstart.xml'
59--- dbus/com.ubuntu.Upstart.xml 2009-07-03 16:08:10 +0000
60+++ dbus/com.ubuntu.Upstart.xml 2011-06-06 17:07:26 +0000
61@@ -49,6 +49,13 @@
62 <arg name="env" type="as" direction="in" />
63 <arg name="wait" type="b" direction="in" />
64 </method>
65+ <method name="EmitEventWithFile">
66+ <annotation name="com.netsplit.Nih.Method.Async" value="true" />
67+ <arg name="name" type="s" direction="in" />
68+ <arg name="env" type="as" direction="in" />
69+ <arg name="wait" type="b" direction="in" />
70+ <arg name="file" type="h" direction="in" />
71+ </method>
72
73 <!-- Basic information about Upstart -->
74 <property name="version" type="s" access="read" />
75
76=== added directory 'extra'
77=== added file 'extra/Makefile.am'
78--- extra/Makefile.am 1970-01-01 00:00:00 +0000
79+++ extra/Makefile.am 2011-06-06 17:07:26 +0000
80@@ -0,0 +1,125 @@
81+## Process this file with automake to produce Makefile.in
82+
83+AM_CFLAGS = \
84+ $(NIH_CFLAGS) \
85+ $(NIH_DBUS_CFLAGS) \
86+ $(DBUS_CFLAGS) \
87+ $(UDEV_CFLAGS)
88+
89+AM_CPPFLAGS = \
90+ -DLOCALEDIR="\"$(localedir)\"" \
91+ -DSBINDIR="\"$(sbindir)\"" \
92+ -I$(top_builddir) -I$(top_srcdir) -iquote$(builddir) -iquote$(srcdir) \
93+ -I$(top_srcdir)/intl
94+
95+
96+initdir = $(sysconfdir)/init
97+
98+
99+sbin_PROGRAMS = \
100+ upstart-socket-bridge
101+
102+dist_init_DATA = \
103+ conf/upstart-socket-bridge.conf
104+
105+dist_man_MANS = \
106+ man/upstart-socket-bridge.8 \
107+ man/socket-event.7
108+
109+upstart_socket_bridge_SOURCES = \
110+ upstart-socket-bridge.c
111+nodist_upstart_socket_bridge_SOURCES = \
112+ $(com_ubuntu_Upstart_OUTPUTS) \
113+ $(com_ubuntu_Upstart_Job_OUTPUTS)
114+upstart_socket_bridge_LDADD = \
115+ $(LTLIBINTL) \
116+ $(NIH_LIBS) \
117+ $(NIH_DBUS_LIBS) \
118+ $(DBUS_LIBS)
119+
120+
121+if HAVE_UDEV
122+dist_init_DATA += \
123+ conf/upstart-udev-bridge.conf
124+
125+dist_man_MANS += \
126+ man/upstart-udev-bridge.8
127+
128+sbin_PROGRAMS += \
129+ upstart-udev-bridge
130+
131+upstart_udev_bridge_SOURCES = \
132+ upstart-udev-bridge.c
133+nodist_upstart_udev_bridge_SOURCES = \
134+ $(com_ubuntu_Upstart_OUTPUTS)
135+upstart_udev_bridge_LDADD = \
136+ $(LTLIBINTL) \
137+ $(NIH_LIBS) \
138+ $(NIH_DBUS_LIBS) \
139+ $(DBUS_LIBS) \
140+ $(UDEV_LIBS)
141+
142+install-data-hook:
143+ src=`echo upstart-udev-bridge| sed '$(transform)'`.8; \
144+ for symlink in \
145+ net-device-added \
146+ net-device-removed \
147+ graphics-device-added \
148+ drm-device-added; do \
149+ inst=`echo $$symlink | sed '$(transform)'`.7; \
150+ echo " ln -sf '$(man8dir)/$$src' '$(DESTDIR)$(man7dir)/$$inst'"; \
151+ ln -sf "$(man8dir)/$$src" "$(DESTDIR)$(man7dir)/$$inst"; \
152+ done
153+
154+else
155+EXTRA_DIST = \
156+ man/upstart-udev-bridge.8
157+endif
158+
159+
160+com_ubuntu_Upstart_OUTPUTS = \
161+ com.ubuntu.Upstart.c \
162+ com.ubuntu.Upstart.h
163+
164+com_ubuntu_Upstart_XML = \
165+ ../dbus/com.ubuntu.Upstart.xml
166+
167+$(com_ubuntu_Upstart_OUTPUTS): $(com_ubuntu_Upstart_XML)
168+ $(AM_V_GEN)$(NIH_DBUS_TOOL) \
169+ --package=$(PACKAGE) \
170+ --mode=proxy --prefix=upstart \
171+ --default-interface=com.ubuntu.Upstart0_6 \
172+ --output=$@ $<
173+
174+
175+com_ubuntu_Upstart_Job_OUTPUTS = \
176+ com.ubuntu.Upstart.Job.c \
177+ com.ubuntu.Upstart.Job.h
178+
179+com_ubuntu_Upstart_Job_XML = \
180+ ../dbus/com.ubuntu.Upstart.Job.xml
181+
182+$(com_ubuntu_Upstart_Job_OUTPUTS): $(com_ubuntu_Upstart_Job_XML)
183+ $(AM_V_GEN)$(NIH_DBUS_TOOL) \
184+ --package=$(PACKAGE) \
185+ --mode=proxy --prefix=job_class \
186+ --default-interface=com.ubuntu.Upstart0_6.Job \
187+ --output=$@ $<
188+
189+
190+# These have to be built sources because we can't compile object files
191+# without the header file existing first
192+BUILT_SOURCES = \
193+ $(com_ubuntu_Upstart_OUTPUTS) \
194+ $(com_ubuntu_Upstart_Job_OUTPUTS)
195+
196+CLEANFILES = \
197+ $(com_ubuntu_Upstart_OUTPUTS) \
198+ $(com_ubuntu_Upstart_Job_OUTPUTS)
199+
200+
201+clean-local:
202+ rm -f *.gcno *.gcda
203+
204+maintainer-clean-local:
205+ rm -f *.gcov
206
207=== added directory 'extra/conf'
208=== added file 'extra/conf/upstart-socket-bridge.conf'
209--- extra/conf/upstart-socket-bridge.conf 1970-01-01 00:00:00 +0000
210+++ extra/conf/upstart-socket-bridge.conf 2011-06-06 17:07:26 +0000
211@@ -0,0 +1,16 @@
212+# upstart-socket-bridge - Bridge socket events into upstart
213+#
214+# This helper daemon receives socket(7) events and
215+# emits equivalent Upstart events.
216+
217+description "Bridge socket events into upstart"
218+
219+emits socket
220+
221+start on net-device-up IFACE=lo
222+stop on runlevel [!2345]
223+
224+expect daemon
225+respawn
226+
227+exec upstart-socket-bridge --daemon
228
229=== added file 'extra/conf/upstart-udev-bridge.conf'
230--- extra/conf/upstart-udev-bridge.conf 1970-01-01 00:00:00 +0000
231+++ extra/conf/upstart-udev-bridge.conf 2011-06-06 17:07:26 +0000
232@@ -0,0 +1,16 @@
233+# upstart-udev-bridge - Bridge udev events into upstart
234+#
235+# This helper daemon receives udev events from the netlink socket and
236+# emits equivalent Upstart events.
237+
238+description "Bridge udev events into upstart"
239+
240+emits *-device-*
241+
242+start on starting udev
243+stop on stopped udev
244+
245+expect daemon
246+respawn
247+
248+exec upstart-udev-bridge --daemon
249
250=== added directory 'extra/man'
251=== added file 'extra/man/socket-event.7'
252--- extra/man/socket-event.7 1970-01-01 00:00:00 +0000
253+++ extra/man/socket-event.7 2011-06-06 17:07:26 +0000
254@@ -0,0 +1,92 @@
255+.TH socket\-event 8 2011-03-08 upstart
256+.\"
257+.SH NAME
258+socket \- event signalling that a socket connection has been made
259+.\"
260+.SH SYNOPSIS
261+.B socket
262+.BI PROTO\fR= PROTO
263+.BI PORT\fR= PORT
264+.BI ADDR\fR= ADDR
265+
266+.B socket
267+.BI PROTO\fR= PROTO
268+.BI PATH\fR= PATH
269+.\"
270+.SH DESCRIPTION
271+
272+The
273+.B socket
274+event is generated by the
275+.BR upstart\-socket\-bridge (8)
276+daemon when a socket connection is made whose details match the
277+socket event condition and environment specified in a jobs
278+.B start on
279+or
280+.B stop on
281+stanza.
282+
283+When an incoming connection is detected, the file descriptor
284+representing the socket is passed to the job in question to allow it to
285+.BR accept (2)
286+the connection. Additionally, the environment variable
287+.B UPSTART_JOB
288+will contain the name of the event ("socket") and the environment
289+variable
290+.B UPSTART_FDS
291+will contain the number of the file descriptor corresponding to the
292+listening socket.
293+.\"
294+.SH EXAMPLES
295+.\"
296+.SS Internet socket
297+Start web server when first client connects from localhost:
298+.RS
299+.nf
300+
301+start on socket PROTO=inet PORT=80 ADDR=127.0.0.1
302+.fi
303+.RE
304+.\"
305+.SS Local socket
306+.P
307+.RS
308+.nf
309+
310+start on socket PROTO=unix PATH=/var/run/.s.pgsql.1234
311+.fi
312+.FE
313+.\"
314+.SS Abstract socket
315+.P
316+
317+.RS
318+.nf
319+
320+start on socket PROTO=unix PATH=@/at/upstart/example
321+.fi
322+.FE
323+.\"
324+.SH AUTHOR
325+Written by Scott James Remnant
326+.RB < scott@netsplit.com >
327+
328+Manual page written by James Hunt
329+.RB < james.hunt@ubuntu.com >
330+.\"
331+.SH BUGS
332+Report bugs at
333+.RB < https://launchpad.net/upstart/+bugs >
334+.\"
335+.SH COPYRIGHT
336+Copyright \(co 2011 Canonical Ltd.
337+.PP
338+This is free software; see the source for copying conditions. There is NO
339+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
340+.\"
341+.SH SEE ALSO
342+.BR init (5)
343+.BR init (8)
344+.BR socket (2)
345+.BR socket (7)
346+.BR upstart\-socket\-bridge (8)
347
348=== added file 'extra/man/upstart-socket-bridge.8'
349--- extra/man/upstart-socket-bridge.8 1970-01-01 00:00:00 +0000
350+++ extra/man/upstart-socket-bridge.8 2011-06-06 17:07:26 +0000
351@@ -0,0 +1,47 @@
352+.TH upstart-socket-bridge 8 2011-03-08 upstart
353+.\"
354+.SH NAME
355+upstart-socket-bridge \- Bridge between Upstart and sockets
356+.\"
357+.SH SYNOPSIS
358+.B upstart-socket-bridge
359+.RI [ OPTIONS ]...
360+.\"
361+.SH DESCRIPTION
362+The
363+.B upstart-socket-bridge
364+queries the Upstart
365+.BR init (8)
366+daemon for all job configurations which
367+.B start on
368+or
369+.B stop on
370+the socket event. It then waits for an incoming connection on each
371+specified
372+.BR socket (7)
373+and when detected emits the socket event (\fBsocket\-event\fP (7)),
374+setting a number of environment variables for the job to query.
375+.\"
376+.SH AUTHOR
377+Written by Scott James Remnant
378+.RB < scott@netsplit.com >
379+
380+Manual page written by James Hunt
381+.RB < james.hunt@ubuntu.com >
382+.\"
383+.SH BUGS
384+Report bugs at
385+.RB < https://launchpad.net/upstart/+bugs >
386+.\"
387+.SH COPYRIGHT
388+Copyright \(co 2011 Canonical Ltd.
389+.PP
390+This is free software; see the source for copying conditions. There is NO
391+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
392+.\"
393+.SH SEE ALSO
394+.BR init (5)
395+.BR init (8)
396+.BR socket (2)
397+.BR socket (7)
398+.BR socket\-event (7)
399
400=== added file 'extra/man/upstart-udev-bridge.8'
401--- extra/man/upstart-udev-bridge.8 1970-01-01 00:00:00 +0000
402+++ extra/man/upstart-udev-bridge.8 2011-06-06 17:07:26 +0000
403@@ -0,0 +1,57 @@
404+.TH upstart\-udev\-bridge 8 2011-03-08 upstart
405+.\"
406+.SH NAME
407+upstart\-udev\-bridge \- Bridge between Upstart and udev
408+.\"
409+.SH SYNOPSIS
410+.B upstart\-udev\-bridge
411+.RI [ OPTIONS ]...
412+.\"
413+.SH DESCRIPTION
414+.B upstart\-udev\-bridge
415+receives information about kernel uevents that
416+.BR udev (8)
417+has completed and creates
418+.BR init (8)
419+events for them.
420+
421+It emits events which match the pattern "\fIS\fP\-device\-\fIA\fP" where
422+\(aqS\(aq is the udev \fIsubsystem\fP and \(aqA\(aq is the udev \fIaction\fP.
423+See \fBudev\fP(7) and for further details.
424+
425+Assuming \fI/sys\fP is mounted, possible values for \fIsubsystem\fP for
426+your system are viewable via \fI/sys/class/\fP.
427+
428+.\"
429+.SH EXAMPLES
430+
431+.IP net\-device\-added
432+Event emitted when a network device is added.
433+.IP net\-device\-removed
434+Event emitted when a network device is removed.
435+.IP graphics\-card\-added
436+Event emitted when a graphics device is available to the system.
437+.\"
438+.SH NOTES
439+This is a temporary tool until
440+.BR init (8)
441+itself gains the functionality to read them directly; you should not
442+rely on its behaviour.
443+.\"
444+.SH AUTHOR
445+Written by Scott James Remnant
446+.RB < scott@netsplit.com >
447+.\"
448+.SH BUGS
449+Report bugs at
450+.RB < https://launchpad.net/ubuntu/+source/upstart/+bugs >
451+.\"
452+.SH COPYRIGHT
453+Copyright \(co 2009,2010,2011 Canonical Ltd.
454+.PP
455+This is free software; see the source for copying conditions. There is NO
456+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
457+.SH SEE ALSO
458+.BR init (5)
459+.BR init (8)
460+.BR udev (7)
461
462=== added file 'extra/upstart-socket-bridge.c'
463--- extra/upstart-socket-bridge.c 1970-01-01 00:00:00 +0000
464+++ extra/upstart-socket-bridge.c 2011-06-06 17:07:26 +0000
465@@ -0,0 +1,644 @@
466+/* upstart
467+ *
468+ * Copyright © 2010 Canonical Ltd.
469+ * Author: Scott James Remnant <scott@netsplit.com>.
470+ *
471+ * This program is free software; you can redistribute it and/or modify
472+ * it under the terms of the GNU General Public License version 2, as
473+ * published by the Free Software Foundation.
474+ *
475+ * This program is distributed in the hope that it will be useful,
476+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
477+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
478+ * GNU General Public License for more details.
479+ *
480+ * You should have received a copy of the GNU General Public License along
481+ * with this program; if not, write to the Free Software Foundation, Inc.,
482+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
483+ */
484+
485+#ifdef HAVE_CONFIG_H
486+# include <config.h>
487+#endif /* HAVE_CONFIG_H */
488+
489+
490+#include <sys/epoll.h>
491+#include <sys/types.h>
492+#include <sys/socket.h>
493+#include <sys/un.h>
494+
495+#include <netinet/in.h>
496+#include <arpa/inet.h>
497+
498+#include <errno.h>
499+#include <stdlib.h>
500+#include <string.h>
501+#include <syslog.h>
502+#include <unistd.h>
503+
504+#include <nih/macros.h>
505+#include <nih/alloc.h>
506+#include <nih/list.h>
507+#include <nih/hash.h>
508+#include <nih/string.h>
509+#include <nih/io.h>
510+#include <nih/option.h>
511+#include <nih/main.h>
512+#include <nih/logging.h>
513+#include <nih/error.h>
514+
515+#include <nih-dbus/dbus_connection.h>
516+#include <nih-dbus/dbus_proxy.h>
517+
518+#include "dbus/upstart.h"
519+#include "com.ubuntu.Upstart.h"
520+#include "com.ubuntu.Upstart.Job.h"
521+
522+
523+/* Structure we use for tracking jobs */
524+typedef struct job {
525+ NihList entry;
526+ char *path;
527+ NihList sockets;
528+} Job;
529+
530+/* Structure we use for tracking listening sockets */
531+typedef struct socket {
532+ NihList entry;
533+
534+ union {
535+ struct sockaddr addr;
536+ struct sockaddr_in sin_addr;
537+ struct sockaddr_un sun_addr;
538+ };
539+ socklen_t addrlen;
540+
541+ int sock;
542+} Socket;
543+
544+
545+/* Prototypes for static functions */
546+static void epoll_watcher (void *data, NihIoWatch *watch,
547+ NihIoEvents events);
548+static void upstart_job_added (void *data, NihDBusMessage *message,
549+ const char *job);
550+static void upstart_job_removed (void *data, NihDBusMessage *message,
551+ const char *job);
552+static void job_add_socket (Job *job, char **socket_info);
553+static void socket_destroy (Socket *socket);
554+static void upstart_disconnected (DBusConnection *connection);
555+static void emit_event_reply (Socket *sock, NihDBusMessage *message);
556+static void emit_event_error (Socket *sock, NihDBusMessage *message);
557+
558+
559+/**
560+ * daemonise:
561+ *
562+ * Set to TRUE if we should become a daemon, rather than just running
563+ * in the foreground.
564+ **/
565+static int daemonise = FALSE;
566+
567+/**
568+ * epoll_fd:
569+ *
570+ * Shared epoll file descriptor for listening on.
571+ **/
572+static int epoll_fd = -1;
573+
574+/**
575+ * jobs:
576+ *
577+ * Jobs that we're monitoring.
578+ **/
579+static NihHash *jobs = NULL;
580+
581+/**
582+ * upstart:
583+ *
584+ * Proxy to Upstart daemon.
585+ **/
586+static NihDBusProxy *upstart = NULL;
587+
588+
589+/**
590+ * options:
591+ *
592+ * Command-line options accepted by this program.
593+ **/
594+static NihOption options[] = {
595+ { 0, "daemon", N_("Detach and run in the background"),
596+ NULL, NULL, &daemonise, NULL },
597+
598+ NIH_OPTION_LAST
599+};
600+
601+
602+int
603+main (int argc,
604+ char *argv[])
605+{
606+ char ** args;
607+ DBusConnection *connection;
608+ char ** job_class_paths;
609+ int ret;
610+
611+ nih_main_init (argv[0]);
612+
613+ nih_option_set_synopsis (_("Bridge socket events into upstart"));
614+ nih_option_set_help (
615+ _("By default, upstart-socket-bridge does not detach from the "
616+ "console and remains in the foreground. Use the --daemon "
617+ "option to have it detach."));
618+
619+ args = nih_option_parser (NULL, argc, argv, options, FALSE);
620+ if (! args)
621+ exit (1);
622+
623+ /* Create an epoll file descriptor for listening on; use this so
624+ * we can do edge triggering rather than level.
625+ */
626+ epoll_fd = epoll_create1 (0);
627+ if (epoll_fd < 0) {
628+ nih_fatal ("%s: %s", _("Could not create epoll descriptor"),
629+ strerror (errno));
630+ exit (1);
631+ }
632+
633+ NIH_MUST (nih_io_add_watch (NULL, epoll_fd, NIH_IO_READ,
634+ epoll_watcher, NULL));
635+
636+ /* Allocate jobs hash table */
637+ jobs = NIH_MUST (nih_hash_string_new (NULL, 0));
638+
639+ /* Initialise the connection to Upstart */
640+ connection = NIH_SHOULD (nih_dbus_connect (DBUS_ADDRESS_UPSTART, upstart_disconnected));
641+ if (! connection) {
642+ NihError *err;
643+
644+ err = nih_error_get ();
645+ nih_fatal ("%s: %s", _("Could not connect to Upstart"),
646+ err->message);
647+ nih_free (err);
648+
649+ exit (1);
650+ }
651+
652+ upstart = NIH_SHOULD (nih_dbus_proxy_new (NULL, connection,
653+ NULL, DBUS_PATH_UPSTART,
654+ NULL, NULL));
655+ if (! upstart) {
656+ NihError *err;
657+
658+ err = nih_error_get ();
659+ nih_fatal ("%s: %s", _("Could not create Upstart proxy"),
660+ err->message);
661+ nih_free (err);
662+
663+ exit (1);
664+ }
665+
666+ /* Connect signals to be notified when jobs come and go */
667+ if (! nih_dbus_proxy_connect (upstart, &upstart_com_ubuntu_Upstart0_6, "JobAdded",
668+ (NihDBusSignalHandler)upstart_job_added, NULL)) {
669+ NihError *err;
670+
671+ err = nih_error_get ();
672+ nih_fatal ("%s: %s", _("Could not create JobAdded signal connection"),
673+ err->message);
674+ nih_free (err);
675+
676+ exit (1);
677+ }
678+
679+ if (! nih_dbus_proxy_connect (upstart, &upstart_com_ubuntu_Upstart0_6, "JobRemoved",
680+ (NihDBusSignalHandler)upstart_job_removed, NULL)) {
681+ NihError *err;
682+
683+ err = nih_error_get ();
684+ nih_fatal ("%s: %s", _("Could not create JobRemoved signal connection"),
685+ err->message);
686+ nih_free (err);
687+
688+ exit (1);
689+ }
690+
691+ /* Request a list of all current jobs */
692+ if (upstart_get_all_jobs_sync (NULL, upstart, &job_class_paths) < 0) {
693+ NihError *err;
694+
695+ err = nih_error_get ();
696+ nih_fatal ("%s: %s", _("Could not obtain job list"),
697+ err->message);
698+ nih_free (err);
699+
700+ exit (1);
701+ }
702+
703+ for (char **job_class_path = job_class_paths;
704+ job_class_path && *job_class_path; job_class_path++)
705+ upstart_job_added (NULL, NULL, *job_class_path);
706+
707+ nih_free (job_class_paths);
708+
709+ /* Become daemon */
710+ if (daemonise) {
711+ if (nih_main_daemonise () < 0) {
712+ NihError *err;
713+
714+ err = nih_error_get ();
715+ nih_fatal ("%s: %s", _("Unable to become daemon"),
716+ err->message);
717+ nih_free (err);
718+
719+ exit (1);
720+ }
721+
722+ /* Send all logging output to syslog */
723+ openlog (program_name, LOG_PID, LOG_DAEMON);
724+ nih_log_set_logger (nih_logger_syslog);
725+ }
726+
727+ /* Handle TERM and INT signals gracefully */
728+ nih_signal_set_handler (SIGTERM, nih_signal_handler);
729+ NIH_MUST (nih_signal_add_handler (NULL, SIGTERM, nih_main_term_signal, NULL));
730+
731+ if (! daemonise) {
732+ nih_signal_set_handler (SIGINT, nih_signal_handler);
733+ NIH_MUST (nih_signal_add_handler (NULL, SIGINT, nih_main_term_signal, NULL));
734+ }
735+
736+ ret = nih_main_loop ();
737+
738+ return ret;
739+}
740+
741+
742+static void
743+epoll_watcher (void * data,
744+ NihIoWatch *watch,
745+ NihIoEvents events)
746+{
747+ struct epoll_event event[1024];
748+ int num_events;
749+
750+ num_events = epoll_wait (epoll_fd, event, 1024, 0);
751+ if (num_events < 0) {
752+ nih_error ("%s: %s", _("Error from epoll"), strerror (errno));
753+ return;
754+ } else if (num_events == 0)
755+ return;
756+
757+ for (int i = 0; i < num_events; i++) {
758+ Socket *sock = (Socket *)event[i].data.ptr;
759+ nih_local char **env = NULL;
760+ size_t env_len = 0;
761+ char *var;
762+ DBusPendingCall *pending_call;
763+
764+ if (event[i].events & EPOLLIN)
765+ nih_debug ("%p EPOLLIN", sock);
766+ if (event[i].events & EPOLLERR)
767+ nih_debug ("%p EPOLLERR", sock);
768+ if (event[i].events & EPOLLHUP)
769+ nih_debug ("%p EPOLLHUP", sock);
770+
771+ env = NIH_MUST (nih_str_array_new (NULL));
772+
773+ switch (sock->addr.sa_family) {
774+ case AF_INET:
775+ NIH_MUST (nih_str_array_add (&env, NULL, &env_len,
776+ "PROTO=inet"));
777+
778+ var = NIH_MUST (nih_sprintf (NULL, "PORT=%d",
779+ ntohs (sock->sin_addr.sin_port)));
780+ NIH_MUST (nih_str_array_addp (&env, NULL, &env_len,
781+ var));
782+ nih_discard (var);
783+
784+ var = NIH_MUST (nih_sprintf (NULL, "ADDR=%s",
785+ inet_ntoa (sock->sin_addr.sin_addr)));
786+ NIH_MUST (nih_str_array_addp (&env, NULL, &env_len,
787+ var));
788+ nih_discard (var);
789+ break;
790+ case AF_UNIX:
791+ NIH_MUST (nih_str_array_add (&env, NULL, &env_len,
792+ "PROTO=unix"));
793+
794+ var = NIH_MUST (nih_sprintf (NULL, "PATH=%s",
795+ sock->sun_addr.sun_path));
796+ NIH_MUST (nih_str_array_addp (&env, NULL, &env_len,
797+ var));
798+ nih_discard (var);
799+ break;
800+ default:
801+ nih_assert_not_reached ();
802+ }
803+
804+ pending_call = NIH_SHOULD (upstart_emit_event_with_file (
805+ upstart, "socket", env, TRUE,
806+ sock->sock,
807+ (UpstartEmitEventWithFileReply)emit_event_reply,
808+ (NihDBusErrorHandler)emit_event_error,
809+ sock,
810+ NIH_DBUS_TIMEOUT_NEVER));
811+ if (! pending_call) {
812+ NihError *err;
813+
814+ err = nih_error_get ();
815+ nih_warn ("%s: %s", _("Could not send socket event"),
816+ err->message);
817+ nih_free (err);
818+ }
819+
820+ dbus_pending_call_unref (pending_call);
821+
822+ // might be EPOLLIN
823+ // might be EPOLLERR
824+ // might be EPOLLHUP
825+ }
826+}
827+
828+
829+static void
830+upstart_job_added (void * data,
831+ NihDBusMessage *message,
832+ const char * job_class_path)
833+{
834+ nih_local NihDBusProxy *job_class = NULL;
835+ nih_local char ***start_on = NULL;
836+ nih_local char ***stop_on = NULL;
837+ Job *job;
838+
839+ nih_assert (job_class_path != NULL);
840+
841+ /* Obtain a proxy to the job */
842+ job_class = nih_dbus_proxy_new (NULL, upstart->connection,
843+ upstart->name, job_class_path,
844+ NULL, NULL);
845+ if (! job_class) {
846+ NihError *err;
847+
848+ err = nih_error_get ();
849+ nih_error ("Could not create proxy for job %s: %s",
850+ job_class_path, err->message);
851+ nih_free (err);
852+
853+ return;
854+ }
855+
856+ job_class->auto_start = FALSE;
857+
858+ /* Obtain the start_on and stop_on properties of the job */
859+ if (job_class_get_start_on_sync (NULL, job_class, &start_on) < 0) {
860+ NihError *err;
861+
862+ err = nih_error_get ();
863+ nih_error ("Could not obtain job start condition %s: %s",
864+ job_class_path, err->message);
865+ nih_free (err);
866+
867+ return;
868+ }
869+
870+ if (job_class_get_stop_on_sync (NULL, job_class, &stop_on) < 0) {
871+ NihError *err;
872+
873+ err = nih_error_get ();
874+ nih_error ("Could not obtain job stop condition %s: %s",
875+ job_class_path, err->message);
876+ nih_free (err);
877+
878+ return;
879+ }
880+
881+ /* Free any existing record for the job (should never happen,
882+ * but worth being safe).
883+ */
884+ job = (Job *)nih_hash_lookup (jobs, job_class_path);
885+ if (job)
886+ nih_free (job);
887+
888+ /* Create new record for the job */
889+ job = NIH_MUST (nih_new (NULL, Job));
890+ job->path = NIH_MUST (nih_strdup (job, job_class_path));
891+
892+ nih_list_init (&job->entry);
893+ nih_list_init (&job->sockets);
894+
895+ /* Find out whether this job listens for any socket events */
896+ for (char ***event = start_on; event && *event && **event; event++)
897+ if (! strcmp (**event, "socket"))
898+ job_add_socket (job, *event);
899+ for (char ***event = stop_on; event && *event && **event; event++)
900+ if (! strcmp (**event, "socket"))
901+ job_add_socket (job, *event);
902+
903+ /* If we didn't end up with any sockets, free the job and move on */
904+ if (NIH_LIST_EMPTY (&job->sockets)) {
905+ nih_free (job);
906+ return;
907+ }
908+
909+ nih_debug ("Job got added %s", job_class_path);
910+
911+ nih_alloc_set_destructor (job, nih_list_destroy);
912+ nih_hash_add (jobs, &job->entry);
913+}
914+
915+static void
916+upstart_job_removed (void * data,
917+ NihDBusMessage *message,
918+ const char * job_path)
919+{
920+ Job *job;
921+
922+ nih_assert (job_path != NULL);
923+
924+ job = (Job *)nih_hash_lookup (jobs, job_path);
925+ if (job) {
926+ nih_debug ("Job went away %s", job_path);
927+ nih_free (job);
928+ }
929+}
930+
931+
932+static void
933+job_add_socket (Job * job,
934+ char **socket_info)
935+{
936+ Socket *sock;
937+ nih_local char *error = NULL;
938+ int components = 0;
939+ struct epoll_event event;
940+
941+ nih_assert (job != NULL);
942+ nih_assert (socket_info != NULL);
943+ nih_assert (! strcmp(socket_info[0], "socket"));
944+
945+ sock = NIH_MUST (nih_new (job, Socket));
946+ memset (sock, 0, sizeof (Socket));
947+ sock->sock = -1;
948+
949+ nih_list_init (&sock->entry);
950+
951+ nih_debug ("Found socket");
952+ for (char **env = socket_info + 1; env && *env; env++) {
953+ char *val;
954+ size_t name_len;
955+
956+ val = strchr (*env, '=');
957+ if (! val) {
958+ nih_warn ("Ignored socket event without variable name in %s",
959+ job->path);
960+ goto error;
961+ }
962+
963+ name_len = val - *env;
964+ val++;
965+
966+ if (! strncmp (*env, "PROTO", name_len)) {
967+ if (! strcmp (val, "inet")) {
968+ sock->addrlen = sizeof sock->sin_addr;
969+ sock->sin_addr.sin_family = AF_INET;
970+ sock->sin_addr.sin_addr.s_addr = INADDR_ANY;
971+ components = 1;
972+ } else if (! strcmp (val, "unix")) {
973+ sock->addrlen = sizeof sock->sun_addr;
974+ sock->sun_addr.sun_family = AF_UNIX;
975+ components = 1;
976+ } else {
977+ nih_warn ("Ignored socket event with unknown PROTO=%s in %s",
978+ val, job->path);
979+ goto error;
980+ }
981+
982+ } else if (! strncmp (*env, "PORT", name_len)
983+ && (sock->sin_addr.sin_family == AF_INET)) {
984+ sock->sin_addr.sin_port = htons (atoi (val));
985+ components--;
986+
987+ } else if (! strncmp (*env, "ADDR", name_len)
988+ && (sock->sin_addr.sin_family == AF_INET)) {
989+ if (inet_aton (val, &(sock->sin_addr.sin_addr)) == 0) {
990+ nih_warn ("Ignored socket event with invalid ADDR=%s in %s",
991+ val, job->path);
992+ goto error;
993+ }
994+
995+ } else if (! strncmp (*env, "PATH", name_len)
996+ && (sock->sun_addr.sun_family == AF_UNIX)) {
997+ strncpy (sock->sun_addr.sun_path, val,
998+ sizeof sock->sun_addr.sun_path);
999+
1000+ if (sock->sun_addr.sun_path[0] == '@')
1001+ sock->sun_addr.sun_path[0] = '\0';
1002+
1003+ components--;
1004+
1005+ } else {
1006+ nih_warn ("Ignored socket event with unknown variable %.*s in %s",
1007+ (int)name_len, *env, job->path);
1008+ goto error;
1009+ }
1010+ }
1011+
1012+ /* Missing any required components? */
1013+ if (components) {
1014+ nih_warn ("Ignored incomplete socket event in %s",
1015+ job->path);
1016+ goto error;
1017+ }
1018+
1019+ /* Let's try and set this baby up */
1020+ sock->sock = socket (sock->addr.sa_family, SOCK_STREAM, 0);
1021+ if (sock->sock < 0) {
1022+ nih_warn ("Failed to create socket in %s: %s",
1023+ job->path, strerror (errno));
1024+ goto error;
1025+ }
1026+
1027+ int opt = 1;
1028+ if (setsockopt (sock->sock, SOL_SOCKET, SO_REUSEADDR,
1029+ &opt, sizeof opt) < 0) {
1030+ nih_warn ("Failed to set socket reuse in %s: %s",
1031+ job->path, strerror (errno));
1032+ goto error;
1033+ }
1034+
1035+ if (bind (sock->sock, &sock->addr, sock->addrlen) < 0) {
1036+ nih_warn ("Failed to bind socket in %s: %s",
1037+ job->path, strerror (errno));
1038+ goto error;
1039+ }
1040+
1041+ if (listen (sock->sock, SOMAXCONN) < 0) {
1042+ nih_warn ("Failed to listen on socket in %s: %s",
1043+ job->path, strerror (errno));
1044+ goto error;
1045+ }
1046+
1047+ /* We have a listening socket, now we want to be notified when someone
1048+ * connects; but we just want one notification, we don't want to get
1049+ * a DDoS of wake-ups while waiting for the service to start.
1050+ *
1051+ * The solution is to use epoll in edge-triggered mode, this will
1052+ * fire only on initial connection until a new one comes in.
1053+ */
1054+ event.events = EPOLLIN | EPOLLET;
1055+ event.data.ptr = sock;
1056+
1057+ if (epoll_ctl (epoll_fd, EPOLL_CTL_ADD, sock->sock, &event) < 0) {
1058+ nih_warn ("Failed to watch socket in %s: %s",
1059+ job->path, strerror (errno));
1060+ goto error;
1061+ }
1062+
1063+ /* Okay then, add to the job */
1064+ nih_alloc_set_destructor (sock, socket_destroy);
1065+ nih_list_add (&job->sockets, &sock->entry);
1066+
1067+ return;
1068+
1069+error:
1070+ if (sock->sock != -1)
1071+ close (sock->sock);
1072+ nih_free (sock);
1073+}
1074+
1075+static void
1076+socket_destroy (Socket *sock)
1077+{
1078+ epoll_ctl (epoll_fd, EPOLL_CTL_DEL, sock->sock, NULL);
1079+ close (sock->sock);
1080+
1081+ nih_list_destroy (&sock->entry);
1082+}
1083+
1084+
1085+static void
1086+upstart_disconnected (DBusConnection *connection)
1087+{
1088+ nih_fatal (_("Disconnected from Upstart"));
1089+ nih_main_loop_exit (1);
1090+}
1091+
1092+
1093+static void
1094+emit_event_reply (Socket * sock,
1095+ NihDBusMessage *message)
1096+{
1097+ nih_debug ("Event completed");
1098+}
1099+
1100+static void
1101+emit_event_error (Socket * sock,
1102+ NihDBusMessage *message)
1103+{
1104+ NihError *err;
1105+
1106+ err = nih_error_get ();
1107+ nih_warn ("%s: %s", _("Error emitting socket event"), err->message);
1108+ nih_free (err);
1109+}
1110
1111=== added file 'extra/upstart-udev-bridge.c'
1112--- extra/upstart-udev-bridge.c 1970-01-01 00:00:00 +0000
1113+++ extra/upstart-udev-bridge.c 2011-06-06 17:07:26 +0000
1114@@ -0,0 +1,310 @@
1115+/* upstart
1116+ *
1117+ * Copyright © 2009 Canonical Ltd.
1118+ * Author: Scott James Remnant <scott@netsplit.com>.
1119+ *
1120+ * This program is free software; you can redistribute it and/or modify
1121+ * it under the terms of the GNU General Public License version 2, as
1122+ * published by the Free Software Foundation.
1123+ *
1124+ * This program is distributed in the hope that it will be useful,
1125+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1126+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1127+ * GNU General Public License for more details.
1128+ *
1129+ * You should have received a copy of the GNU General Public License along
1130+ * with this program; if not, write to the Free Software Foundation, Inc.,
1131+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1132+ */
1133+
1134+#ifdef HAVE_CONFIG_H
1135+# include <config.h>
1136+#endif /* HAVE_CONFIG_H */
1137+
1138+
1139+#include <libudev.h>
1140+
1141+#include <stdlib.h>
1142+#include <string.h>
1143+#include <syslog.h>
1144+
1145+#include <nih/macros.h>
1146+#include <nih/alloc.h>
1147+#include <nih/string.h>
1148+#include <nih/io.h>
1149+#include <nih/option.h>
1150+#include <nih/main.h>
1151+#include <nih/logging.h>
1152+#include <nih/error.h>
1153+
1154+#include <nih-dbus/dbus_connection.h>
1155+#include <nih-dbus/dbus_proxy.h>
1156+
1157+#include "dbus/upstart.h"
1158+#include "com.ubuntu.Upstart.h"
1159+
1160+
1161+/* Prototypes for static functions */
1162+static void udev_monitor_watcher (struct udev_monitor *udev_monitor,
1163+ NihIoWatch *watch, NihIoEvents events);
1164+static void upstart_disconnected (DBusConnection *connection);
1165+static void emit_event_error (void *data, NihDBusMessage *message);
1166+
1167+
1168+/**
1169+ * daemonise:
1170+ *
1171+ * Set to TRUE if we should become a daemon, rather than just running
1172+ * in the foreground.
1173+ **/
1174+static int daemonise = FALSE;
1175+
1176+/**
1177+ * upstart:
1178+ *
1179+ * Proxy to Upstart daemon.
1180+ **/
1181+static NihDBusProxy *upstart = NULL;
1182+
1183+
1184+/**
1185+ * options:
1186+ *
1187+ * Command-line options accepted by this program.
1188+ **/
1189+static NihOption options[] = {
1190+ { 0, "daemon", N_("Detach and run in the background"),
1191+ NULL, NULL, &daemonise, NULL },
1192+
1193+ NIH_OPTION_LAST
1194+};
1195+
1196+
1197+int
1198+main (int argc,
1199+ char *argv[])
1200+{
1201+ char ** args;
1202+ DBusConnection * connection;
1203+ struct udev * udev;
1204+ struct udev_monitor *udev_monitor;
1205+ int ret;
1206+
1207+ nih_main_init (argv[0]);
1208+
1209+ nih_option_set_synopsis (_("Bridge udev events into upstart"));
1210+ nih_option_set_help (
1211+ _("By default, upstart-udev-bridge does not detach from the "
1212+ "console and remains in the foreground. Use the --daemon "
1213+ "option to have it detach."));
1214+
1215+ args = nih_option_parser (NULL, argc, argv, options, FALSE);
1216+ if (! args)
1217+ exit (1);
1218+
1219+ /* Initialise the connection to Upstart */
1220+ connection = NIH_SHOULD (nih_dbus_connect (DBUS_ADDRESS_UPSTART, upstart_disconnected));
1221+ if (! connection) {
1222+ NihError *err;
1223+
1224+ err = nih_error_get ();
1225+ nih_fatal ("%s: %s", _("Could not connect to Upstart"),
1226+ err->message);
1227+ nih_free (err);
1228+
1229+ exit (1);
1230+ }
1231+
1232+ upstart = NIH_SHOULD (nih_dbus_proxy_new (NULL, connection,
1233+ NULL, DBUS_PATH_UPSTART,
1234+ NULL, NULL));
1235+ if (! upstart) {
1236+ NihError *err;
1237+
1238+ err = nih_error_get ();
1239+ nih_fatal ("%s: %s", _("Could not create Upstart proxy"),
1240+ err->message);
1241+ nih_free (err);
1242+
1243+ exit (1);
1244+ }
1245+
1246+ /* Initialise the connection to udev */
1247+ nih_assert (udev = udev_new ());
1248+ nih_assert (udev_monitor = udev_monitor_new_from_netlink (udev, "udev"));
1249+ nih_assert (udev_monitor_enable_receiving (udev_monitor) == 0);
1250+ udev_monitor_set_receive_buffer_size(udev_monitor, 128*1024*1024);
1251+
1252+ NIH_MUST (nih_io_add_watch (NULL, udev_monitor_get_fd (udev_monitor),
1253+ NIH_IO_READ,
1254+ (NihIoWatcher)udev_monitor_watcher,
1255+ udev_monitor));
1256+
1257+ /* Become daemon */
1258+ if (daemonise) {
1259+ if (nih_main_daemonise () < 0) {
1260+ NihError *err;
1261+
1262+ err = nih_error_get ();
1263+ nih_fatal ("%s: %s", _("Unable to become daemon"),
1264+ err->message);
1265+ nih_free (err);
1266+
1267+ exit (1);
1268+ }
1269+
1270+ /* Send all logging output to syslog */
1271+ openlog (program_name, LOG_PID, LOG_DAEMON);
1272+ nih_log_set_logger (nih_logger_syslog);
1273+ }
1274+
1275+ /* Handle TERM and INT signals gracefully */
1276+ nih_signal_set_handler (SIGTERM, nih_signal_handler);
1277+ NIH_MUST (nih_signal_add_handler (NULL, SIGTERM, nih_main_term_signal, NULL));
1278+
1279+ if (! daemonise) {
1280+ nih_signal_set_handler (SIGINT, nih_signal_handler);
1281+ NIH_MUST (nih_signal_add_handler (NULL, SIGINT, nih_main_term_signal, NULL));
1282+ }
1283+
1284+ ret = nih_main_loop ();
1285+
1286+ return ret;
1287+}
1288+
1289+
1290+static void
1291+udev_monitor_watcher (struct udev_monitor *udev_monitor,
1292+ NihIoWatch * watch,
1293+ NihIoEvents events)
1294+{
1295+ struct udev_device * udev_device;
1296+ const char * subsystem;
1297+ const char * action;
1298+ const char * kernel;
1299+ const char * devpath;
1300+ const char * devname;
1301+ nih_local char * name = NULL;
1302+ nih_local char ** env = NULL;
1303+ size_t env_len = 0;
1304+ DBusPendingCall * pending_call;
1305+
1306+ udev_device = udev_monitor_receive_device (udev_monitor);
1307+ if (! udev_device)
1308+ return;
1309+
1310+ subsystem = udev_device_get_subsystem (udev_device);
1311+ action = udev_device_get_action (udev_device);
1312+ kernel = udev_device_get_sysname (udev_device);
1313+ devpath = udev_device_get_devpath (udev_device);
1314+ devname = udev_device_get_devnode (udev_device);
1315+
1316+ if (! strcmp (action, "add")) {
1317+ name = NIH_MUST (nih_sprintf (NULL, "%s-device-added",
1318+ subsystem));
1319+ } else if (! strcmp (action, "change")) {
1320+ name = NIH_MUST (nih_sprintf (NULL, "%s-device-changed",
1321+ subsystem));
1322+ } else if (! strcmp (action, "remove")) {
1323+ name = NIH_MUST (nih_sprintf (NULL, "%s-device-removed",
1324+ subsystem));
1325+ } else {
1326+ name = NIH_MUST (nih_sprintf (NULL, "%s-device-%s",
1327+ subsystem, action));
1328+ }
1329+
1330+ env = NIH_MUST (nih_str_array_new (NULL));
1331+
1332+ if (kernel) {
1333+ nih_local char *var = NULL;
1334+
1335+ var = NIH_MUST (nih_sprintf (NULL, "KERNEL=%s", kernel));
1336+ NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
1337+ }
1338+
1339+ if (devpath) {
1340+ nih_local char *var = NULL;
1341+
1342+ var = NIH_MUST (nih_sprintf (NULL, "DEVPATH=%s", devpath));
1343+ NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
1344+ }
1345+
1346+ if (devname) {
1347+ nih_local char *var = NULL;
1348+
1349+ var = NIH_MUST (nih_sprintf (NULL, "DEVNAME=%s", devname));
1350+ NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
1351+ }
1352+
1353+ if (subsystem) {
1354+ nih_local char *var = NULL;
1355+
1356+ var = NIH_MUST (nih_sprintf (NULL, "SUBSYSTEM=%s", subsystem));
1357+ NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
1358+ }
1359+
1360+ if (action) {
1361+ nih_local char *var = NULL;
1362+
1363+ var = NIH_MUST (nih_sprintf (NULL, "ACTION=%s", action));
1364+ NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
1365+ }
1366+
1367+ for (struct udev_list_entry *list_entry = udev_device_get_properties_list_entry (udev_device);
1368+ list_entry != NULL;
1369+ list_entry = udev_list_entry_get_next (list_entry)) {
1370+ const char * key;
1371+ nih_local char *var = NULL;
1372+
1373+ key = udev_list_entry_get_name (list_entry);
1374+ if (! strcmp (key, "DEVPATH"))
1375+ continue;
1376+ if (! strcmp (key, "DEVNAME"))
1377+ continue;
1378+ if (! strcmp (key, "SUBSYSTEM"))
1379+ continue;
1380+ if (! strcmp (key, "ACTION"))
1381+ continue;
1382+
1383+ var = NIH_MUST (nih_sprintf (NULL, "%s=%s", key,
1384+ udev_list_entry_get_value (list_entry)));
1385+ NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
1386+ }
1387+
1388+ nih_debug ("%s %s", name, devname);
1389+
1390+ pending_call = NIH_SHOULD (upstart_emit_event (upstart,
1391+ name, env, FALSE,
1392+ NULL, emit_event_error, NULL,
1393+ NIH_DBUS_TIMEOUT_NEVER));
1394+ if (! pending_call) {
1395+ NihError *err;
1396+
1397+ err = nih_error_get ();
1398+ nih_warn ("%s", err->message);
1399+ nih_free (err);
1400+ }
1401+
1402+ dbus_pending_call_unref (pending_call);
1403+
1404+ udev_device_unref (udev_device);
1405+}
1406+
1407+
1408+static void
1409+upstart_disconnected (DBusConnection *connection)
1410+{
1411+ nih_fatal (_("Disconnected from Upstart"));
1412+ nih_main_loop_exit (1);
1413+}
1414+
1415+static void
1416+emit_event_error (void * data,
1417+ NihDBusMessage *message)
1418+{
1419+ NihError *err;
1420+
1421+ err = nih_error_get ();
1422+ nih_warn ("%s", err->message);
1423+ nih_free (err);
1424+}
1425
1426=== modified file 'init/conf.c'
1427--- init/conf.c 2011-03-15 18:44:09 +0000
1428+++ init/conf.c 2011-06-06 17:07:26 +0000
1429@@ -2,7 +2,6 @@
1430 *
1431 * conf.c - configuration management
1432 *
1433- * Copyright © 2011 Google Inc.
1434 * Copyright © 2009 Canonical Ltd.
1435 * Author: Scott James Remnant <scott@netsplit.com>.
1436 *
1437
1438=== modified file 'init/control.c'
1439--- init/control.c 2009-07-11 11:47:12 +0000
1440+++ init/control.c 2011-06-06 17:07:26 +0000
1441@@ -25,8 +25,10 @@
1442
1443 #include <dbus/dbus.h>
1444
1445+#include <fcntl.h>
1446 #include <stdio.h>
1447 #include <string.h>
1448+#include <unistd.h>
1449
1450 #include <nih/macros.h>
1451 #include <nih/alloc.h>
1452@@ -462,13 +464,24 @@
1453 }
1454
1455
1456+int
1457+control_emit_event (void *data,
1458+ NihDBusMessage *message,
1459+ const char *name,
1460+ char * const *env,
1461+ int wait)
1462+{
1463+ return control_emit_event_with_file (data, message, name, env, wait, -1);
1464+}
1465+
1466 /**
1467- * control_emit_event:
1468+ * control_emit_event_with_file:
1469 * @data: not used,
1470 * @message: D-Bus connection and message received,
1471 * @name: name of event to emit,
1472 * @env: environment of environment,
1473- * @wait: whether to wait for event completion before returning.
1474+ * @wait: whether to wait for event completion before returning,
1475+ * @file: file descriptor.
1476 *
1477 * Implements the top half of the EmitEvent method of the com.ubuntu.Upstart
1478 * interface, the bottom half may be found in event_finished().
1479@@ -488,11 +501,12 @@
1480 * Returns: zero on success, negative value on raised error.
1481 **/
1482 int
1483-control_emit_event (void *data,
1484- NihDBusMessage *message,
1485- const char *name,
1486- char * const *env,
1487- int wait)
1488+control_emit_event_with_file (void *data,
1489+ NihDBusMessage *message,
1490+ const char *name,
1491+ char * const *env,
1492+ int wait,
1493+ int file)
1494 {
1495 Event *event;
1496 Blocked *blocked;
1497@@ -505,6 +519,7 @@
1498 if (! strlen (name)) {
1499 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
1500 _("Name may not be empty string"));
1501+ close (file);
1502 return -1;
1503 }
1504
1505@@ -512,19 +527,33 @@
1506 if (! environ_all_valid (env)) {
1507 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
1508 _("Env must be KEY=VALUE pairs"));
1509+ close (file);
1510 return -1;
1511 }
1512
1513 /* Make the event and block the message on it */
1514 event = event_new (NULL, name, (char **)env);
1515- if (! event)
1516- nih_return_system_error (-1);
1517+ if (! event) {
1518+ nih_error_raise_system ();
1519+ close (file);
1520+ return -1;
1521+ }
1522+
1523+ event->fd = file;
1524+ if (event->fd >= 0) {
1525+ long flags;
1526+
1527+ flags = fcntl (event->fd, F_GETFD);
1528+ flags &= ~FD_CLOEXEC;
1529+ fcntl (event->fd, F_SETFD, flags);
1530+ }
1531
1532 if (wait) {
1533 blocked = blocked_new (event, BLOCKED_EMIT_METHOD, message);
1534 if (! blocked) {
1535 nih_error_raise_system ();
1536 nih_free (event);
1537+ close (file);
1538 return -1;
1539 }
1540
1541
1542=== modified file 'init/control.h'
1543--- init/control.h 2009-07-09 08:36:52 +0000
1544+++ init/control.h 2011-06-06 17:07:26 +0000
1545@@ -60,6 +60,10 @@
1546 const char *name, char * const *env,
1547 int wait)
1548 __attribute__ ((warn_unused_result));
1549+int control_emit_event_with_file (void *data, NihDBusMessage *message,
1550+ const char *name, char * const *env,
1551+ int wait, int file)
1552+ __attribute__ ((warn_unused_result));
1553
1554 int control_get_version (void *data, NihDBusMessage *message,
1555 char **version)
1556
1557=== modified file 'init/environ.c'
1558--- init/environ.c 2011-03-16 22:42:48 +0000
1559+++ init/environ.c 2011-06-06 17:07:26 +0000
1560@@ -2,7 +2,6 @@
1561 *
1562 * environ.c - environment table utilities
1563 *
1564- * Copyright © 2011 Google Inc.
1565 * Copyright © 2009 Canonical Ltd.
1566 * Author: Scott James Remnant <scott@netsplit.com>.
1567 *
1568
1569=== modified file 'init/environ.h'
1570--- init/environ.h 2011-03-16 22:42:48 +0000
1571+++ init/environ.h 2011-06-06 17:07:26 +0000
1572@@ -1,6 +1,5 @@
1573 /* upstart
1574 *
1575- * Copyright © 2011 Google Inc.
1576 * Copyright © 2009 Canonical Ltd.
1577 * Author: Scott James Remnant <scott@netsplit.com>.
1578 *
1579
1580=== modified file 'init/event.c'
1581--- init/event.c 2010-12-14 15:32:41 +0000
1582+++ init/event.c 2011-06-06 17:07:26 +0000
1583@@ -25,6 +25,7 @@
1584
1585
1586 #include <string.h>
1587+#include <unistd.h>
1588
1589 #include <nih/macros.h>
1590 #include <nih/alloc.h>
1591@@ -123,6 +124,8 @@
1592
1593 nih_list_init (&event->entry);
1594
1595+ event->fd = -1;
1596+
1597 event->progress = EVENT_PENDING;
1598 event->failed = FALSE;
1599
1600@@ -393,8 +396,16 @@
1601 job->start_env = env;
1602 nih_ref (job->start_env, job);
1603
1604+ nih_discard (env);
1605+ env = NULL;
1606+
1607 job_finished (job, FALSE);
1608
1609+ NIH_MUST (event_operator_fds (class->start_on, job,
1610+ &job->fds, &job->num_fds,
1611+ &job->start_env, &len,
1612+ "UPSTART_FDS"));
1613+
1614 event_operator_events (job->class->start_on,
1615 job, &job->blocking);
1616
1617@@ -459,6 +470,8 @@
1618 nih_free (blocked);
1619 }
1620
1621+ close (event->fd);
1622+
1623 if (event->failed) {
1624 char *name;
1625
1626
1627=== modified file 'init/event.h'
1628--- init/event.h 2009-07-09 08:36:52 +0000
1629+++ init/event.h 2011-06-06 17:07:26 +0000
1630@@ -63,6 +63,7 @@
1631
1632 char *name;
1633 char **env;
1634+ int fd;
1635
1636 EventProgress progress;
1637 int failed;
1638
1639=== modified file 'init/event_operator.c'
1640--- init/event_operator.c 2010-11-19 14:34:51 +0000
1641+++ init/event_operator.c 2011-06-06 17:07:26 +0000
1642@@ -552,6 +552,65 @@
1643 return *env;
1644 }
1645
1646+int *
1647+event_operator_fds (EventOperator *root,
1648+ const void *parent,
1649+ int **fds,
1650+ size_t *num_fds,
1651+ char ***env,
1652+ size_t *len,
1653+ const char *key)
1654+{
1655+ nih_local char *evlist = NULL;
1656+
1657+ nih_assert (root != NULL);
1658+ nih_assert (fds != NULL);
1659+ nih_assert (num_fds != NULL);
1660+ nih_assert (env != NULL);
1661+ nih_assert (len != NULL);
1662+ nih_assert (key != NULL);
1663+
1664+ /* Initialise the event list variable with the name given. */
1665+ evlist = nih_sprintf (NULL, "%s=", key);
1666+ if (! evlist)
1667+ return NULL;
1668+
1669+ *num_fds = 0;
1670+ NIH_TREE_FOREACH_FULL (&root->node, iter,
1671+ (NihTreeFilter)event_operator_filter, NULL) {
1672+ EventOperator *oper = (EventOperator *)iter;
1673+
1674+ if (oper->type != EVENT_MATCH)
1675+ continue;
1676+
1677+ nih_assert (oper->event != NULL);
1678+
1679+ if (oper->event->fd >= 0) {
1680+ *fds = nih_realloc (*fds, parent, sizeof (int) * (*num_fds + 1));
1681+ if (! *fds)
1682+ return NULL;
1683+
1684+ (*fds)[(*num_fds)++] = oper->event->fd;
1685+
1686+ if (evlist[strlen (evlist) - 1] != '=') {
1687+ if (! nih_strcat_sprintf (&evlist, NULL, " %d",
1688+ oper->event->fd))
1689+ return NULL;
1690+ } else {
1691+ if (! nih_strcat_sprintf (&evlist, NULL, "%d",
1692+ oper->event->fd))
1693+ return NULL;
1694+ }
1695+ }
1696+ }
1697+
1698+ if (*num_fds)
1699+ if (! environ_add (env, parent, len, TRUE, evlist))
1700+ return NULL;
1701+
1702+ return (void *)1;
1703+}
1704+
1705 /**
1706 * event_operator_events:
1707 * @root: operator tree to collect from,
1708
1709=== modified file 'init/event_operator.h'
1710--- init/event_operator.h 2009-06-23 09:29:35 +0000
1711+++ init/event_operator.h 2011-06-06 17:07:26 +0000
1712@@ -95,6 +95,14 @@
1713 char ** event_operator_environment (EventOperator *root, char ***env,
1714 const void *parent, size_t *len,
1715 const char *key);
1716+int *
1717+event_operator_fds (EventOperator *root,
1718+ const void *parent,
1719+ int **fds,
1720+ size_t *num_fds,
1721+ char ***env,
1722+ size_t *len,
1723+ const char *key);
1724 void event_operator_events (EventOperator *root,
1725 const void *parent, NihList *list);
1726
1727
1728=== modified file 'init/job.c'
1729--- init/job.c 2010-12-14 15:32:41 +0000
1730+++ init/job.c 2011-06-06 17:07:26 +0000
1731@@ -118,6 +118,9 @@
1732 goto error;
1733 }
1734
1735+ job->fds = NULL;
1736+ job->num_fds = 0;
1737+
1738 job->pid = nih_alloc (job, sizeof (pid_t) * PROCESS_LAST);
1739 if (! job->pid)
1740 goto error;
1741
1742=== modified file 'init/job.h'
1743--- init/job.h 2009-07-03 16:38:02 +0000
1744+++ init/job.h 2011-06-06 17:07:26 +0000
1745@@ -134,6 +134,9 @@
1746 char **stop_env;
1747 EventOperator *stop_on;
1748
1749+ int *fds;
1750+ size_t num_fds;
1751+
1752 pid_t *pid;
1753 Event *blocker;
1754 NihList blocking;
1755
1756=== modified file 'init/job_process.c'
1757--- init/job_process.c 2011-05-12 20:42:28 +0000
1758+++ init/job_process.c 2011-06-06 17:07:26 +0000
1759@@ -2,7 +2,6 @@
1760 *
1761 * job_process.c - job process handling
1762 *
1763- * Copyright © 2011 Google Inc.
1764 * Copyright © 2011 Canonical Ltd.
1765 * Author: Scott James Remnant <scott@netsplit.com>.
1766 *
1767
1768=== modified file 'init/job_process.h'
1769--- init/job_process.h 2011-05-12 19:21:16 +0000
1770+++ init/job_process.h 2011-06-06 17:07:26 +0000
1771@@ -1,6 +1,5 @@
1772 /* upstart
1773 *
1774- * Copyright © 2011 Google Inc.
1775 * Copyright © 2009 Canonical Ltd.
1776 * Author: Scott James Remnant <scott@netsplit.com>.
1777 *
1778
1779=== modified file 'init/main.c'
1780--- init/main.c 2011-03-16 22:54:56 +0000
1781+++ init/main.c 2011-06-06 17:07:26 +0000
1782@@ -1,6 +1,5 @@
1783 /* upstart
1784 *
1785- * Copyright © 2011 Google Inc.
1786 * Copyright © 2010 Canonical Ltd.
1787 * Author: Scott James Remnant <scott@netsplit.com>.
1788 *
1789
1790=== modified file 'init/tests/test_conf.c'
1791--- init/tests/test_conf.c 2011-02-17 23:38:17 +0000
1792+++ init/tests/test_conf.c 2011-06-06 17:07:26 +0000
1793@@ -2,7 +2,6 @@
1794 *
1795 * test_conf.c - test suite for init/conf.c
1796 *
1797- * Copyright © 2011 Google Inc.
1798 * Copyright © 2009 Canonical Ltd.
1799 * Author: Scott James Remnant <scott@netsplit.com>.
1800 *
1801
1802=== modified file 'init/tests/test_control.c'
1803--- init/tests/test_control.c 2011-03-16 22:42:48 +0000
1804+++ init/tests/test_control.c 2011-06-06 17:07:26 +0000
1805@@ -2,7 +2,6 @@
1806 *
1807 * test_dbus.c - test suite for init/dbus.c
1808 *
1809- * Copyright © 2011 Google Inc.
1810 * Copyright © 2010 Canonical Ltd.
1811 * Author: Scott James Remnant <scott@netsplit.com>.
1812 *
1813
1814=== modified file 'init/tests/test_environ.c'
1815--- init/tests/test_environ.c 2011-03-16 22:42:48 +0000
1816+++ init/tests/test_environ.c 2011-06-06 17:07:26 +0000
1817@@ -2,7 +2,6 @@
1818 *
1819 * test_environ.c - test suite for init/environ.c
1820 *
1821- * Copyright © 2011 Google Inc.
1822 * Copyright © 2009 Canonical Ltd.
1823 * Author: Scott James Remnant <scott@netsplit.com>.
1824 *
1825
1826=== modified file 'init/tests/test_job_class.c'
1827--- init/tests/test_job_class.c 2011-05-12 20:42:28 +0000
1828+++ init/tests/test_job_class.c 2011-06-06 17:07:26 +0000
1829@@ -2,7 +2,6 @@
1830 *
1831 * test_job_class.c - test suite for init/job_class.c
1832 *
1833- * Copyright © 2011 Google Inc.
1834 * Copyright © 2010 Canonical Ltd.
1835 * Author: Scott James Remnant <scott@netsplit.com>.
1836 *
1837
1838=== modified file 'init/tests/test_job_process.c'
1839--- init/tests/test_job_process.c 2011-05-12 19:21:16 +0000
1840+++ init/tests/test_job_process.c 2011-06-06 17:07:26 +0000
1841@@ -2,7 +2,6 @@
1842 *
1843 * test_job_process.c - test suite for init/job_process.c
1844 *
1845- * Copyright © 2011 Google Inc.
1846 * Copyright © 2011 Canonical Ltd.
1847 * Author: Scott James Remnant <scott@netsplit.com>.
1848 *
1849
1850=== modified file 'po/POTFILES.in'
1851--- po/POTFILES.in 2011-05-05 09:06:21 +0000
1852+++ po/POTFILES.in 2011-06-06 17:07:26 +0000
1853@@ -20,3 +20,5 @@
1854 util/runlevel.c
1855 util/shutdown.c
1856 util/telinit.c
1857+
1858+extra/upstart-udev-bridge.c
1859
1860=== modified file 'po/upstart.pot'
1861--- po/upstart.pot 2011-03-22 17:52:25 +0000
1862+++ po/upstart.pot 2011-06-06 17:07:26 +0000
1863@@ -6,12 +6,13 @@
1864 #, fuzzy
1865 msgid ""
1866 msgstr ""
1867-"Project-Id-Version: upstart 1.2\n"
1868+"Project-Id-Version: upstart 1.3\n"
1869 "Report-Msgid-Bugs-To: new@bugs.launchpad.net\n"
1870-"POT-Creation-Date: 2011-03-22 10:52-0700\n"
1871+"POT-Creation-Date: 2011-05-15 15:48+0100\n"
1872 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1873 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1874 "Language-Team: LANGUAGE <LL@li.org>\n"
1875+"Language: \n"
1876 "MIME-Version: 1.0\n"
1877 "Content-Type: text/plain; charset=CHARSET\n"
1878 "Content-Transfer-Encoding: 8bit\n"
1879@@ -46,305 +47,364 @@
1880 msgid "Configuration directory deleted"
1881 msgstr ""
1882
1883-#: init/control.c:155
1884+#: init/control.c:157
1885 msgid "Connection from private client"
1886 msgstr ""
1887
1888-#: init/control.c:290
1889+#: init/control.c:292
1890 msgid "Disconnected from system bus"
1891 msgstr ""
1892
1893-#: init/control.c:356 init/main.c:546
1894+#: init/control.c:358 init/main.c:546
1895 msgid "Reloading configuration"
1896 msgstr ""
1897
1898-#: init/control.c:396 init/control.c:507
1899+#: init/control.c:398 init/control.c:521
1900 msgid "Name may not be empty string"
1901 msgstr ""
1902
1903-#: init/control.c:405
1904+#: init/control.c:407
1905 #, c-format
1906 msgid "Unknown job: %s"
1907 msgstr ""
1908
1909-#: init/control.c:514 init/job_class.c:522 init/job_class.c:710
1910-#: init/job_class.c:829 init/job_class.c:953
1911+#: init/control.c:529 init/job_class.c:524 init/job_class.c:712
1912+#: init/job_class.c:831 init/job_class.c:955
1913 msgid "Env must be KEY=VALUE pairs"
1914 msgstr ""
1915
1916-#: init/control.c:666
1917+#: init/control.c:695
1918 msgid "The log priority given was not recognised"
1919 msgstr ""
1920
1921-#: init/event.c:273
1922+#: init/errors.h:58
1923+msgid "Illegal parameter"
1924+msgstr ""
1925+
1926+#: init/errors.h:59
1927+msgid "Unknown parameter"
1928+msgstr ""
1929+
1930+#: init/errors.h:60 init/errors.h:71
1931+msgid "Expected operator"
1932+msgstr ""
1933+
1934+#: init/errors.h:61
1935+msgid "Mismatched braces"
1936+msgstr ""
1937+
1938+#: init/errors.h:62
1939+msgid "Illegal interval, expected number of seconds"
1940+msgstr ""
1941+
1942+#: init/errors.h:63
1943+msgid "Illegal exit status, expected integer"
1944+msgstr ""
1945+
1946+#: init/errors.h:64
1947+msgid "Illegal signal status, expected integer"
1948+msgstr ""
1949+
1950+#: init/errors.h:65
1951+msgid "Illegal file creation mask, expected octal integer"
1952+msgstr ""
1953+
1954+#: init/errors.h:66
1955+msgid "Illegal nice value, expected -20 to 19"
1956+msgstr ""
1957+
1958+#: init/errors.h:67
1959+msgid "Illegal oom adjustment, expected -16 to 15 or 'never'"
1960+msgstr ""
1961+
1962+#: init/errors.h:68
1963+msgid "Illegal oom score adjustment, expected -999 to 1000 or 'never'"
1964+msgstr ""
1965+
1966+#: init/errors.h:69
1967+msgid "Illegal limit, expected 'unlimited' or integer"
1968+msgstr ""
1969+
1970+#: init/errors.h:70
1971+msgid "Expected event"
1972+msgstr ""
1973+
1974+#: init/errors.h:72
1975+msgid "Expected variable name before value"
1976+msgstr ""
1977+
1978+#: init/errors.h:73
1979+msgid "Mismatched parentheses"
1980+msgstr ""
1981+
1982+#: init/errors.h:74
1983+msgid "Name already taken"
1984+msgstr ""
1985+
1986+#: init/event.c:276
1987 #, c-format
1988 msgid "Handling %s event"
1989 msgstr ""
1990
1991-#: init/event.c:373
1992+#: init/event.c:376
1993 #, c-format
1994 msgid "Failed to obtain %s instance: %s"
1995 msgstr ""
1996
1997-#: init/event.c:448
1998+#: init/event.c:459
1999 msgid "Event failed"
2000 msgstr ""
2001
2002-#: init/job.c:223
2003+#: init/job.c:226
2004 #, c-format
2005 msgid "%s goal changed from %s to %s"
2006 msgstr ""
2007
2008-#: init/job.c:294
2009+#: init/job.c:297
2010 #, c-format
2011 msgid "%s state changed from %s to %s"
2012 msgstr ""
2013
2014-#: init/job.c:713 init/job.c:751
2015+#: init/job.c:716 init/job.c:754
2016 msgid "Job failed to start"
2017 msgstr ""
2018
2019-#: init/job.c:726 init/job.c:762
2020+#: init/job.c:729 init/job.c:765
2021 msgid "Job failed while stopping"
2022 msgstr ""
2023
2024-#: init/job.c:738 init/job.c:773
2025+#: init/job.c:741 init/job.c:776
2026 msgid "Job failed to restart"
2027 msgstr ""
2028
2029-#: init/job.c:966
2030+#: init/job.c:969
2031 msgid "stop"
2032 msgstr ""
2033
2034-#: init/job.c:968
2035+#: init/job.c:971
2036 msgid "start"
2037 msgstr ""
2038
2039-#: init/job.c:970
2040+#: init/job.c:973
2041 msgid "respawn"
2042 msgstr ""
2043
2044-#: init/job.c:1015
2045+#: init/job.c:1018
2046 msgid "waiting"
2047 msgstr ""
2048
2049-#: init/job.c:1017
2050+#: init/job.c:1020
2051 msgid "starting"
2052 msgstr ""
2053
2054-#: init/job.c:1019 init/process.c:80
2055+#: init/job.c:1022 init/process.c:80
2056 msgid "pre-start"
2057 msgstr ""
2058
2059-#: init/job.c:1021
2060+#: init/job.c:1024
2061 msgid "spawned"
2062 msgstr ""
2063
2064-#: init/job.c:1023 init/process.c:82
2065+#: init/job.c:1026 init/process.c:82
2066 msgid "post-start"
2067 msgstr ""
2068
2069-#: init/job.c:1025
2070+#: init/job.c:1028
2071 msgid "running"
2072 msgstr ""
2073
2074-#: init/job.c:1027 init/process.c:84
2075+#: init/job.c:1030 init/process.c:84
2076 msgid "pre-stop"
2077 msgstr ""
2078
2079-#: init/job.c:1029
2080+#: init/job.c:1032
2081 msgid "stopping"
2082 msgstr ""
2083
2084-#: init/job.c:1031
2085+#: init/job.c:1034
2086 msgid "killed"
2087 msgstr ""
2088
2089-#: init/job.c:1033 init/process.c:86
2090+#: init/job.c:1036 init/process.c:86
2091 msgid "post-stop"
2092 msgstr ""
2093
2094-#: init/job.c:1113 init/job_class.c:756
2095+#: init/job.c:1116 init/job_class.c:758
2096 #, c-format
2097 msgid "Job is already running: %s"
2098 msgstr ""
2099
2100-#: init/job.c:1177 init/job.c:1242 init/job_class.c:875 init/job_class.c:998
2101+#: init/job.c:1180 init/job.c:1245 init/job_class.c:877 init/job_class.c:1000
2102 #, c-format
2103 msgid "Job has already been stopped: %s"
2104 msgstr ""
2105
2106-#: init/job_class.c:559 init/job_class.c:604 init/job_class.c:867
2107-#: init/job_class.c:990
2108+#: init/job_class.c:561 init/job_class.c:606 init/job_class.c:869
2109+#: init/job_class.c:992
2110 #, c-format
2111 msgid "Unknown instance: %s"
2112 msgstr ""
2113
2114-#: init/job_process.c:279
2115+#: init/job_process.c:277
2116 #, c-format
2117 msgid "Failed to spawn %s %s process: %s"
2118 msgstr ""
2119
2120-#: init/job_process.c:285
2121+#: init/job_process.c:283
2122 msgid "Temporary process spawn error"
2123 msgstr ""
2124
2125-#: init/job_process.c:292
2126+#: init/job_process.c:290
2127 #, c-format
2128 msgid "%s %s process (%d)"
2129 msgstr ""
2130
2131-#: init/job_process.c:399
2132+#: init/job_process.c:403
2133 #, c-format
2134 msgid "Pausing %s (%d) [pre-exec] for debug"
2135 msgstr ""
2136
2137-#: init/job_process.c:453
2138+#: init/job_process.c:473
2139 #, c-format
2140 msgid "Failed to open system console: %s"
2141 msgstr ""
2142
2143-#: init/job_process.c:669
2144+#: init/job_process.c:697
2145+#, c-format
2146+msgid "unable to move script fd: %s"
2147+msgstr ""
2148+
2149+#: init/job_process.c:702
2150 #, c-format
2151 msgid "unable to open console: %s"
2152 msgstr ""
2153
2154-#: init/job_process.c:724
2155+#: init/job_process.c:757
2156 #, c-format
2157 msgid "unable to set \"%s\" resource limit: %s"
2158 msgstr ""
2159
2160-#: init/job_process.c:729
2161+#: init/job_process.c:762
2162 #, c-format
2163 msgid "unable to set priority: %s"
2164 msgstr ""
2165
2166-#: init/job_process.c:734
2167+#: init/job_process.c:767
2168 #, c-format
2169 msgid "unable to set oom adjustment: %s"
2170 msgstr ""
2171
2172-#: init/job_process.c:739
2173+#: init/job_process.c:772
2174 #, c-format
2175 msgid "unable to change root directory: %s"
2176 msgstr ""
2177
2178-#: init/job_process.c:744
2179+#: init/job_process.c:777
2180 #, c-format
2181 msgid "unable to change working directory: %s"
2182 msgstr ""
2183
2184-#: init/job_process.c:749
2185+#: init/job_process.c:782
2186 #, c-format
2187 msgid "unable to set trace: %s"
2188 msgstr ""
2189
2190-#: init/job_process.c:754
2191+#: init/job_process.c:787
2192 #, c-format
2193 msgid "unable to execute: %s"
2194 msgstr ""
2195
2196-#: init/job_process.c:785
2197-#, c-format
2198-msgid "Sending TERM signal to %s %s process (%d)"
2199-msgstr ""
2200-
2201-#: init/job_process.c:793
2202-#, c-format
2203-msgid "Failed to send TERM signal to %s %s process (%d): %s"
2204-msgstr ""
2205-
2206-#: init/job_process.c:833
2207-#, c-format
2208-msgid "Sending KILL signal to %s %s process (%d)"
2209-msgstr ""
2210-
2211-#: init/job_process.c:841
2212-#, c-format
2213-msgid "Failed to send KILL signal to %s %s process (%d): %s"
2214-msgstr ""
2215-
2216-#: init/job_process.c:901
2217+#: init/job_process.c:818 init/job_process.c:868
2218+#, c-format
2219+msgid "Sending %s signal to %s %s process (%d)"
2220+msgstr ""
2221+
2222+#: init/job_process.c:827 init/job_process.c:877
2223+#, c-format
2224+msgid "Failed to send %s signal to %s %s process (%d): %s"
2225+msgstr ""
2226+
2227+#: init/job_process.c:938
2228 #, c-format
2229 msgid "%s %s process (%d) terminated with status %d"
2230 msgstr ""
2231
2232-#: init/job_process.c:906
2233+#: init/job_process.c:943
2234 #, c-format
2235 msgid "%s %s process (%d) exited normally"
2236 msgstr ""
2237
2238-#: init/job_process.c:921
2239+#: init/job_process.c:958
2240 #, c-format
2241 msgid "%s %s process (%d) killed by %s signal"
2242 msgstr ""
2243
2244-#: init/job_process.c:925
2245+#: init/job_process.c:962
2246 #, c-format
2247 msgid "%s %s process (%d) killed by signal %d"
2248 msgstr ""
2249
2250-#: init/job_process.c:939
2251+#: init/job_process.c:976
2252 #, c-format
2253 msgid "%s %s process (%d) stopped by %s signal"
2254 msgstr ""
2255
2256-#: init/job_process.c:943
2257+#: init/job_process.c:980
2258 #, c-format
2259 msgid "%s %s process (%d) stopped by signal %d"
2260 msgstr ""
2261
2262-#: init/job_process.c:957
2263+#: init/job_process.c:994
2264 #, c-format
2265 msgid "%s %s process (%d) continued by %s signal"
2266 msgstr ""
2267
2268-#: init/job_process.c:961
2269+#: init/job_process.c:998
2270 #, c-format
2271 msgid "%s %s process (%d) continued by signal %d"
2272 msgstr ""
2273
2274-#: init/job_process.c:1096
2275+#: init/job_process.c:1133
2276 #, c-format
2277 msgid "%s respawning too fast, stopped"
2278 msgstr ""
2279
2280-#: init/job_process.c:1102
2281+#: init/job_process.c:1139
2282 #, c-format
2283 msgid "%s %s process ended, respawning"
2284 msgstr ""
2285
2286-#: init/job_process.c:1342
2287+#: init/job_process.c:1379
2288 #, c-format
2289 msgid "Failed to set ptrace options for %s %s process (%d): %s"
2290 msgstr ""
2291
2292-#: init/job_process.c:1355 init/job_process.c:1550
2293+#: init/job_process.c:1392 init/job_process.c:1587
2294 #, c-format
2295 msgid "Failed to continue traced %s %s process (%d): %s"
2296 msgstr ""
2297
2298-#: init/job_process.c:1395 init/job_process.c:1486 init/job_process.c:1541
2299+#: init/job_process.c:1432 init/job_process.c:1523 init/job_process.c:1578
2300 #, c-format
2301 msgid "Failed to detach traced %s %s process (%d): %s"
2302 msgstr ""
2303
2304-#: init/job_process.c:1435
2305+#: init/job_process.c:1472
2306 #, c-format
2307 msgid "Failed to deliver signal to traced %s %s process (%d): %s"
2308 msgstr ""
2309
2310-#: init/job_process.c:1470
2311+#: init/job_process.c:1507
2312 #, c-format
2313 msgid "Failed to obtain child process id for %s %s process (%d): %s"
2314 msgstr ""
2315
2316-#: init/job_process.c:1477
2317+#: init/job_process.c:1514
2318 #, c-format
2319 msgid "%s %s process (%d) became new process (%d)"
2320 msgstr ""
2321
2322-#: init/job_process.c:1536
2323+#: init/job_process.c:1573
2324 #, c-format
2325 msgid "%s %s process (%d) executable changed"
2326 msgstr ""
2327@@ -819,3 +879,33 @@
2328 #, c-format
2329 msgid "%s: illegal runlevel: %s\n"
2330 msgstr ""
2331+
2332+#: extra/upstart-udev-bridge.c:76
2333+msgid "Detach and run in the background"
2334+msgstr ""
2335+
2336+#: extra/upstart-udev-bridge.c:95
2337+msgid "Bridge udev events into upstart"
2338+msgstr ""
2339+
2340+#: extra/upstart-udev-bridge.c:97
2341+msgid ""
2342+"By default, upstart-udev-bridge does not detach from the console and remains "
2343+"in the foreground. Use the --daemon option to have it detach."
2344+msgstr ""
2345+
2346+#: extra/upstart-udev-bridge.c:111
2347+msgid "Could not connect to Upstart"
2348+msgstr ""
2349+
2350+#: extra/upstart-udev-bridge.c:125
2351+msgid "Could not create Upstart proxy"
2352+msgstr ""
2353+
2354+#: extra/upstart-udev-bridge.c:149
2355+msgid "Unable to become daemon"
2356+msgstr ""
2357+
2358+#: extra/upstart-udev-bridge.c:297
2359+msgid "Disconnected from Upstart"
2360+msgstr ""
2361
2362=== modified file 'util/reboot.c'
2363--- util/reboot.c 2011-03-16 22:18:22 +0000
2364+++ util/reboot.c 2011-06-06 17:07:26 +0000
2365@@ -1,6 +1,5 @@
2366 /* upstart
2367 *
2368- * Copyright © 2011 Google Inc.
2369 * Copyright © 2010 Canonical Ltd.
2370 * Author: Scott James Remnant <scott@netsplit.com>.
2371 *

Subscribers

People subscribed via source and target branches