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