Merge lp:~jamesodhunt/upstart/upstream-udev+socket-bridges into lp:upstart
- upstream-udev+socket-bridges
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Upstart Developers | Pending | ||
Review via email: mp+63583@code.launchpad.net |
Commit message
Description of the change
* Makefile.am: Added extra directory.
* New files:
- extra/Makefile.am
- extra/conf/
- extra/conf/
- extra/man/
- extra/man/
- extra/man/
- extra/upstart-
- extra/upstart-
* configure.ac:
- Check for udev (for upstart-
- Add extra/Makefile to AC_CONFIG_FILES.
* dbus/com.
* init/control.c:
- control_
- control_
* init/control.h: Prototype for control_
* init/event.c:
- event_new(): Initialize event fd.
- event_pending_
* init/event.c: Add fd to Event struct.
* init/event_
* init/event_
* init/job.c: job_new(): Initialize fd members.
* init/job.h: Add fds and num_fds to Job struct.
Preview Diff
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 | * |