Merge lp:~jamesodhunt/upstart/upstream-socket-bridge into lp:upstart

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
Reviewer Review Type Date Requested Status
Upstart Developers Pending
Review via email: mp+61036@code.launchpad.net

Description of the change

Minor fixes and documentation for upstart-socket-bridge:

* extra/Makefile.am: Added socket-bridge.conf and manual pages
  to distribution.
* extra/upstart-socket-bridge.c: job_add_socket(): memset fix (before, only
  part of the Socket object was being initialized).
* New files:
  - extra/conf/upstart-socket-bridge.conf: Job configuration file for
    socket bridge.
  - extra/man/socket-event.7: Man page for socket event. Naming is due
    to collision with existing socket(7) page.
  - extra/man/upstart-socket-bridge.8: Man page for socket bridge.

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
=== modified file '.bzrignore'
--- .bzrignore 2010-12-10 04:03:25 +0000
+++ .bzrignore 2011-05-15 18:31:10 +0000
@@ -59,3 +59,7 @@
59util/shutdown59util/shutdown
60util/telinit60util/telinit
61util/test_*61util/test_*
62extra/com.ubuntu.Upstart.[ch]
63extra/com.ubuntu.Upstart.Job.[ch]
64extra/upstart-socket-bridge
65extra/upstart-udev-bridge
6266
=== modified file 'Makefile.am'
--- Makefile.am 2010-02-04 03:42:29 +0000
+++ Makefile.am 2011-05-15 18:31:10 +0000
@@ -1,6 +1,6 @@
1## Process this file with automake to produce Makefile.in1## Process this file with automake to produce Makefile.in
22
3SUBDIRS = intl dbus init util conf doc contrib po3SUBDIRS = intl dbus init util extra conf doc contrib po
44
5EXTRA_DIST = HACKING5EXTRA_DIST = HACKING
66
77
=== modified file 'configure.ac'
--- configure.ac 2011-03-22 17:53:17 +0000
+++ configure.ac 2011-05-15 18:31:10 +0000
@@ -30,6 +30,9 @@
30PKG_CHECK_MODULES([NIH], [libnih >= 1.0.2])30PKG_CHECK_MODULES([NIH], [libnih >= 1.0.2])
31PKG_CHECK_MODULES([NIH_DBUS], [libnih-dbus >= 1.0.0])31PKG_CHECK_MODULES([NIH_DBUS], [libnih-dbus >= 1.0.0])
32PKG_CHECK_MODULES([DBUS], [dbus-1 >= 1.2.16])32PKG_CHECK_MODULES([DBUS], [dbus-1 >= 1.2.16])
33PKG_CHECK_MODULES([UDEV], [libudev >= 146], [have_udev=yes], [have_udev=no])
34
35AM_CONDITIONAL([HAVE_UDEV], [test "$have_udev" = yes])
3336
34# Checks for header files.37# Checks for header files.
35AC_CHECK_HEADERS([valgrind/valgrind.h])38AC_CHECK_HEADERS([valgrind/valgrind.h])
@@ -63,7 +66,7 @@
6366
6467
65AC_CONFIG_FILES([ Makefile intl/Makefile68AC_CONFIG_FILES([ Makefile intl/Makefile
66 dbus/Makefile init/Makefile util/Makefile conf/Makefile69 dbus/Makefile init/Makefile util/Makefile extra/Makefile
67 doc/Makefile contrib/Makefile po/Makefile.in ])70 conf/Makefile doc/Makefile contrib/Makefile po/Makefile.in ])
68AC_CONFIG_HEADERS([config.h])71AC_CONFIG_HEADERS([config.h])
69AC_OUTPUT72AC_OUTPUT
7073
=== modified file 'dbus/com.ubuntu.Upstart.xml'
--- dbus/com.ubuntu.Upstart.xml 2009-07-03 16:08:10 +0000
+++ dbus/com.ubuntu.Upstart.xml 2011-05-15 18:31:10 +0000
@@ -49,6 +49,13 @@
49 <arg name="env" type="as" direction="in" />49 <arg name="env" type="as" direction="in" />
50 <arg name="wait" type="b" direction="in" />50 <arg name="wait" type="b" direction="in" />
51 </method>51 </method>
52 <method name="EmitEventWithFile">
53 <annotation name="com.netsplit.Nih.Method.Async" value="true" />
54 <arg name="name" type="s" direction="in" />
55 <arg name="env" type="as" direction="in" />
56 <arg name="wait" type="b" direction="in" />
57 <arg name="file" type="h" direction="in" />
58 </method>
5259
53 <!-- Basic information about Upstart -->60 <!-- Basic information about Upstart -->
54 <property name="version" type="s" access="read" />61 <property name="version" type="s" access="read" />
5562
=== added directory 'extra'
=== added file 'extra/Makefile.am'
--- extra/Makefile.am 1970-01-01 00:00:00 +0000
+++ extra/Makefile.am 2011-05-15 18:31:10 +0000
@@ -0,0 +1,113 @@
1## Process this file with automake to produce Makefile.in
2
3AM_CFLAGS = \
4 $(NIH_CFLAGS) \
5 $(NIH_DBUS_CFLAGS) \
6 $(DBUS_CFLAGS) \
7 $(UDEV_CFLAGS)
8
9AM_CPPFLAGS = \
10 -DLOCALEDIR="\"$(localedir)\"" \
11 -DSBINDIR="\"$(sbindir)\"" \
12 -I$(top_builddir) -I$(top_srcdir) -iquote$(builddir) -iquote$(srcdir) \
13 -I$(top_srcdir)/intl
14
15
16initdir = $(sysconfdir)/init
17
18
19sbin_PROGRAMS = \
20 upstart-socket-bridge
21
22dist_init_DATA = \
23 conf/upstart-socket-bridge.conf
24
25dist_man_MANS = \
26 man/upstart-socket-bridge.8 \
27 man/socket-event.7
28
29upstart_socket_bridge_SOURCES = \
30 upstart-socket-bridge.c
31nodist_upstart_socket_bridge_SOURCES = \
32 $(com_ubuntu_Upstart_OUTPUTS) \
33 $(com_ubuntu_Upstart_Job_OUTPUTS)
34upstart_socket_bridge_LDADD = \
35 $(LTLIBINTL) \
36 $(NIH_LIBS) \
37 $(NIH_DBUS_LIBS) \
38 $(DBUS_LIBS)
39
40
41if HAVE_UDEV
42dist_init_DATA += \
43 conf/upstart-udev-bridge.conf
44
45dist_man_MANS += \
46 man/upstart-udev-bridge.8
47
48
49sbin_PROGRAMS += \
50 upstart-udev-bridge
51
52upstart_udev_bridge_SOURCES = \
53 upstart-udev-bridge.c
54nodist_upstart_udev_bridge_SOURCES = \
55 $(com_ubuntu_Upstart_OUTPUTS)
56upstart_udev_bridge_LDADD = \
57 $(LTLIBINTL) \
58 $(NIH_LIBS) \
59 $(NIH_DBUS_LIBS) \
60 $(DBUS_LIBS) \
61 $(UDEV_LIBS)
62else
63EXTRA_DIST = \
64 man/upstart-udev-bridge.8
65endif
66
67
68com_ubuntu_Upstart_OUTPUTS = \
69 com.ubuntu.Upstart.c \
70 com.ubuntu.Upstart.h
71
72com_ubuntu_Upstart_XML = \
73 ../dbus/com.ubuntu.Upstart.xml
74
75$(com_ubuntu_Upstart_OUTPUTS): $(com_ubuntu_Upstart_XML)
76 $(AM_V_GEN)$(NIH_DBUS_TOOL) \
77 --package=$(PACKAGE) \
78 --mode=proxy --prefix=upstart \
79 --default-interface=com.ubuntu.Upstart0_6 \
80 --output=$@ $<
81
82
83com_ubuntu_Upstart_Job_OUTPUTS = \
84 com.ubuntu.Upstart.Job.c \
85 com.ubuntu.Upstart.Job.h
86
87com_ubuntu_Upstart_Job_XML = \
88 ../dbus/com.ubuntu.Upstart.Job.xml
89
90$(com_ubuntu_Upstart_Job_OUTPUTS): $(com_ubuntu_Upstart_Job_XML)
91 $(AM_V_GEN)$(NIH_DBUS_TOOL) \
92 --package=$(PACKAGE) \
93 --mode=proxy --prefix=job_class \
94 --default-interface=com.ubuntu.Upstart0_6.Job \
95 --output=$@ $<
96
97
98# These have to be built sources because we can't compile object files
99# without the header file existing first
100BUILT_SOURCES = \
101 $(com_ubuntu_Upstart_OUTPUTS) \
102 $(com_ubuntu_Upstart_Job_OUTPUTS)
103
104CLEANFILES = \
105 $(com_ubuntu_Upstart_OUTPUTS) \
106 $(com_ubuntu_Upstart_Job_OUTPUTS)
107
108
109clean-local:
110 rm -f *.gcno *.gcda
111
112maintainer-clean-local:
113 rm -f *.gcov
0114
=== added directory 'extra/conf'
=== added file 'extra/conf/upstart-socket-bridge.conf'
--- extra/conf/upstart-socket-bridge.conf 1970-01-01 00:00:00 +0000
+++ extra/conf/upstart-socket-bridge.conf 2011-05-15 18:31:10 +0000
@@ -0,0 +1,16 @@
1# upstart-socket-bridge - Bridge socket events into upstart
2#
3# This helper daemon receives socket(7) events and
4# emits equivalent Upstart events.
5
6description "Bridge socket events into upstart"
7
8emits socket
9
10start on net-device-up IFACE=lo
11stop on runlevel [!2345]
12
13expect daemon
14respawn
15
16exec upstart-socket-bridge --daemon
017
=== added file 'extra/conf/upstart-udev-bridge.conf'
--- extra/conf/upstart-udev-bridge.conf 1970-01-01 00:00:00 +0000
+++ extra/conf/upstart-udev-bridge.conf 2011-05-15 18:31:10 +0000
@@ -0,0 +1,14 @@
1# upstart-udev-bridge - Bridge udev events into upstart
2#
3# This helper daemon receives udev events from the netlink socket and
4# emits equivalent Upstart events.
5
6description "Bridge udev events into upstart"
7
8start on starting udev
9stop on stopped udev
10
11expect daemon
12respawn
13
14exec upstart-udev-bridge --daemon
015
=== added directory 'extra/man'
=== added file 'extra/man/socket-event.7'
--- extra/man/socket-event.7 1970-01-01 00:00:00 +0000
+++ extra/man/socket-event.7 2011-05-15 18:31:10 +0000
@@ -0,0 +1,92 @@
1.TH socket\-event 8 2011-03-08 upstart
2.\"
3.SH NAME
4socket \- event signalling that a socket connection has been made
5.\"
6.SH SYNOPSIS
7.B socket
8.BI PROTO\fR= PROTO
9.BI PORT\fR= PORT
10.BI ADDR\fR= ADDR
11
12.B socket
13.BI PROTO\fR= PROTO
14.BI PATH\fR= PATH
15.\"
16.SH DESCRIPTION
17
18The
19.B socket
20event is generated by the
21.BR upstart\-socket\-bridge (8)
22daemon when a socket connection is made whose details match the
23socket event condition and environment specified in a jobs
24.B start on
25or
26.B stop on
27stanza.
28
29When an incoming connection is detected, the file descriptor
30representing the socket is passed to the job in question to allow it to
31.BR accept (2)
32the connection. Additionally, the environment variable
33.B UPSTART_JOB
34will contain the name of the event ("socket") and the environment
35variable
36.B UPSTART_FDS
37will contain the number of the file descriptor corresponding to the
38listening socket.
39.\"
40.SH EXAMPLES
41.\"
42.SS Internet socket
43Start web server when first client connects from localhost:
44.RS
45.nf
46
47start on socket PROTO=inet PORT=80 ADDR=127.0.0.1
48.fi
49.RE
50.\"
51.SS Local socket
52.P
53.RS
54.nf
55
56start on socket PROTO=unix PATH=/var/run/.s.pgsql.1234
57.fi
58.FE
59.\"
60.SS Abstract socket
61.P
62
63.RS
64.nf
65
66start on socket PROTO=unix PATH=@/at/upstart/example
67.fi
68.FE
69.\"
70.SH AUTHOR
71Written by Scott James Remnant
72.RB < scott@netsplit.com >
73
74Manual page written by James Hunt
75.RB < james.hunt@ubuntu.com >
76.\"
77.SH BUGS
78Report bugs at
79.RB < https://launchpad.net/upstart/+bugs >
80.\"
81.SH COPYRIGHT
82Copyright \(co 2011 Canonical Ltd.
83.PP
84This is free software; see the source for copying conditions. There is NO
85warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
86.\"
87.SH SEE ALSO
88.BR init (5)
89.BR init (8)
90.BR socket (2)
91.BR socket (7)
92.BR upstart\-socket\-bridge (8)
093
=== added file 'extra/man/upstart-socket-bridge.8'
--- extra/man/upstart-socket-bridge.8 1970-01-01 00:00:00 +0000
+++ extra/man/upstart-socket-bridge.8 2011-05-15 18:31:10 +0000
@@ -0,0 +1,47 @@
1.TH upstart-socket-bridge 8 2011-03-08 upstart
2.\"
3.SH NAME
4upstart-socket-bridge \- Bridge between Upstart and sockets
5.\"
6.SH SYNOPSIS
7.B upstart-socket-bridge
8.RI [ OPTIONS ]...
9.\"
10.SH DESCRIPTION
11The
12.B upstart-socket-bridge
13queries the Upstart
14.BR init (8)
15daemon for all job configurations which
16.B start on
17or
18.B stop on
19the socket event. It then waits for an incoming connection on each
20specified
21.BR socket (7)
22and when detected emits the socket event (\fBsocket\-event\fP (7)),
23setting a number of environment variables for the job to query.
24.\"
25.SH AUTHOR
26Written by Scott James Remnant
27.RB < scott@netsplit.com >
28
29Manual page written by James Hunt
30.RB < james.hunt@ubuntu.com >
31.\"
32.SH BUGS
33Report bugs at
34.RB < https://launchpad.net/upstart/+bugs >
35.\"
36.SH COPYRIGHT
37Copyright \(co 2011 Canonical Ltd.
38.PP
39This is free software; see the source for copying conditions. There is NO
40warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
41.\"
42.SH SEE ALSO
43.BR init (5)
44.BR init (8)
45.BR socket (2)
46.BR socket (7)
47.BR socket\-event (7)
048
=== added file 'extra/man/upstart-udev-bridge.8'
--- extra/man/upstart-udev-bridge.8 1970-01-01 00:00:00 +0000
+++ extra/man/upstart-udev-bridge.8 2011-05-15 18:31:10 +0000
@@ -0,0 +1,35 @@
1.TH upstart-udev-bridge 8 2009-09-07 upstart
2.\"
3.SH NAME
4upstart-udev-bridge \- Bridge between Upstart and udev
5.\"
6.SH SYNOPSIS
7.B upstart-udev-bridge
8.RI [ OPTIONS ]...
9.\"
10.SH DESCRIPTION
11.B upstart-udev-bridge
12receives information about kernel uevents that
13.BR udev (8)
14has completed and creates
15.BR init (8)
16events for them.
17
18This is a temporary tool until
19.BR init (8)
20itself gains the functionality to read them directly; you should not
21rely on its behaviour.
22.\"
23.SH AUTHOR
24Written by Scott James Remnant
25.RB < scott@netsplit.com >
26.\"
27.SH BUGS
28Report bugs at
29.RB < https://launchpad.net/ubuntu/+source/upstart/+bugs >
30.\"
31.SH COPYRIGHT
32Copyright \(co 2009 Canonical Ltd.
33.PP
34This is free software; see the source for copying conditions. There is NO
35warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
036
=== added file 'extra/upstart-socket-bridge.c'
--- extra/upstart-socket-bridge.c 1970-01-01 00:00:00 +0000
+++ extra/upstart-socket-bridge.c 2011-05-15 18:31:10 +0000
@@ -0,0 +1,644 @@
1/* upstart
2 *
3 * Copyright © 2010 Canonical Ltd.
4 * Author: Scott James Remnant <scott@netsplit.com>.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#ifdef HAVE_CONFIG_H
21# include <config.h>
22#endif /* HAVE_CONFIG_H */
23
24
25#include <sys/epoll.h>
26#include <sys/types.h>
27#include <sys/socket.h>
28#include <sys/un.h>
29
30#include <netinet/in.h>
31#include <arpa/inet.h>
32
33#include <errno.h>
34#include <stdlib.h>
35#include <string.h>
36#include <syslog.h>
37#include <unistd.h>
38
39#include <nih/macros.h>
40#include <nih/alloc.h>
41#include <nih/list.h>
42#include <nih/hash.h>
43#include <nih/string.h>
44#include <nih/io.h>
45#include <nih/option.h>
46#include <nih/main.h>
47#include <nih/logging.h>
48#include <nih/error.h>
49
50#include <nih-dbus/dbus_connection.h>
51#include <nih-dbus/dbus_proxy.h>
52
53#include "dbus/upstart.h"
54#include "com.ubuntu.Upstart.h"
55#include "com.ubuntu.Upstart.Job.h"
56
57
58/* Structure we use for tracking jobs */
59typedef struct job {
60 NihList entry;
61 char *path;
62 NihList sockets;
63} Job;
64
65/* Structure we use for tracking listening sockets */
66typedef struct socket {
67 NihList entry;
68
69 union {
70 struct sockaddr addr;
71 struct sockaddr_in sin_addr;
72 struct sockaddr_un sun_addr;
73 };
74 socklen_t addrlen;
75
76 int sock;
77} Socket;
78
79
80/* Prototypes for static functions */
81static void epoll_watcher (void *data, NihIoWatch *watch,
82 NihIoEvents events);
83static void upstart_job_added (void *data, NihDBusMessage *message,
84 const char *job);
85static void upstart_job_removed (void *data, NihDBusMessage *message,
86 const char *job);
87static void job_add_socket (Job *job, char **socket_info);
88static void socket_destroy (Socket *socket);
89static void upstart_disconnected (DBusConnection *connection);
90static void emit_event_reply (Socket *sock, NihDBusMessage *message);
91static void emit_event_error (Socket *sock, NihDBusMessage *message);
92
93
94/**
95 * daemonise:
96 *
97 * Set to TRUE if we should become a daemon, rather than just running
98 * in the foreground.
99 **/
100static int daemonise = FALSE;
101
102/**
103 * epoll_fd:
104 *
105 * Shared epoll file descriptor for listening on.
106 **/
107static int epoll_fd = -1;
108
109/**
110 * jobs:
111 *
112 * Jobs that we're monitoring.
113 **/
114static NihHash *jobs = NULL;
115
116/**
117 * upstart:
118 *
119 * Proxy to Upstart daemon.
120 **/
121static NihDBusProxy *upstart = NULL;
122
123
124/**
125 * options:
126 *
127 * Command-line options accepted by this program.
128 **/
129static NihOption options[] = {
130 { 0, "daemon", N_("Detach and run in the background"),
131 NULL, NULL, &daemonise, NULL },
132
133 NIH_OPTION_LAST
134};
135
136
137int
138main (int argc,
139 char *argv[])
140{
141 char ** args;
142 DBusConnection *connection;
143 char ** job_class_paths;
144 int ret;
145
146 nih_main_init (argv[0]);
147
148 nih_option_set_synopsis (_("Bridge socket events into upstart"));
149 nih_option_set_help (
150 _("By default, upstart-socket-bridge does not detach from the "
151 "console and remains in the foreground. Use the --daemon "
152 "option to have it detach."));
153
154 args = nih_option_parser (NULL, argc, argv, options, FALSE);
155 if (! args)
156 exit (1);
157
158 /* Create an epoll file descriptor for listening on; use this so
159 * we can do edge triggering rather than level.
160 */
161 epoll_fd = epoll_create1 (0);
162 if (epoll_fd < 0) {
163 nih_fatal ("%s: %s", _("Could not create epoll descriptor"),
164 strerror (errno));
165 exit (1);
166 }
167
168 NIH_MUST (nih_io_add_watch (NULL, epoll_fd, NIH_IO_READ,
169 epoll_watcher, NULL));
170
171 /* Allocate jobs hash table */
172 jobs = NIH_MUST (nih_hash_string_new (NULL, 0));
173
174 /* Initialise the connection to Upstart */
175 connection = NIH_SHOULD (nih_dbus_connect (DBUS_ADDRESS_UPSTART, upstart_disconnected));
176 if (! connection) {
177 NihError *err;
178
179 err = nih_error_get ();
180 nih_fatal ("%s: %s", _("Could not connect to Upstart"),
181 err->message);
182 nih_free (err);
183
184 exit (1);
185 }
186
187 upstart = NIH_SHOULD (nih_dbus_proxy_new (NULL, connection,
188 NULL, DBUS_PATH_UPSTART,
189 NULL, NULL));
190 if (! upstart) {
191 NihError *err;
192
193 err = nih_error_get ();
194 nih_fatal ("%s: %s", _("Could not create Upstart proxy"),
195 err->message);
196 nih_free (err);
197
198 exit (1);
199 }
200
201 /* Connect signals to be notified when jobs come and go */
202 if (! nih_dbus_proxy_connect (upstart, &upstart_com_ubuntu_Upstart0_6, "JobAdded",
203 (NihDBusSignalHandler)upstart_job_added, NULL)) {
204 NihError *err;
205
206 err = nih_error_get ();
207 nih_fatal ("%s: %s", _("Could not create JobAdded signal connection"),
208 err->message);
209 nih_free (err);
210
211 exit (1);
212 }
213
214 if (! nih_dbus_proxy_connect (upstart, &upstart_com_ubuntu_Upstart0_6, "JobRemoved",
215 (NihDBusSignalHandler)upstart_job_removed, NULL)) {
216 NihError *err;
217
218 err = nih_error_get ();
219 nih_fatal ("%s: %s", _("Could not create JobRemoved signal connection"),
220 err->message);
221 nih_free (err);
222
223 exit (1);
224 }
225
226 /* Request a list of all current jobs */
227 if (upstart_get_all_jobs_sync (NULL, upstart, &job_class_paths) < 0) {
228 NihError *err;
229
230 err = nih_error_get ();
231 nih_fatal ("%s: %s", _("Could not obtain job list"),
232 err->message);
233 nih_free (err);
234
235 exit (1);
236 }
237
238 for (char **job_class_path = job_class_paths;
239 job_class_path && *job_class_path; job_class_path++)
240 upstart_job_added (NULL, NULL, *job_class_path);
241
242 nih_free (job_class_paths);
243
244 /* Become daemon */
245 if (daemonise) {
246 if (nih_main_daemonise () < 0) {
247 NihError *err;
248
249 err = nih_error_get ();
250 nih_fatal ("%s: %s", _("Unable to become daemon"),
251 err->message);
252 nih_free (err);
253
254 exit (1);
255 }
256
257 /* Send all logging output to syslog */
258 openlog (program_name, LOG_PID, LOG_DAEMON);
259 nih_log_set_logger (nih_logger_syslog);
260 }
261
262 /* Handle TERM and INT signals gracefully */
263 nih_signal_set_handler (SIGTERM, nih_signal_handler);
264 NIH_MUST (nih_signal_add_handler (NULL, SIGTERM, nih_main_term_signal, NULL));
265
266 if (! daemonise) {
267 nih_signal_set_handler (SIGINT, nih_signal_handler);
268 NIH_MUST (nih_signal_add_handler (NULL, SIGINT, nih_main_term_signal, NULL));
269 }
270
271 ret = nih_main_loop ();
272
273 return ret;
274}
275
276
277static void
278epoll_watcher (void * data,
279 NihIoWatch *watch,
280 NihIoEvents events)
281{
282 struct epoll_event event[1024];
283 int num_events;
284
285 num_events = epoll_wait (epoll_fd, event, 1024, 0);
286 if (num_events < 0) {
287 nih_error ("%s: %s", _("Error from epoll"), strerror (errno));
288 return;
289 } else if (num_events == 0)
290 return;
291
292 for (int i = 0; i < num_events; i++) {
293 Socket *sock = (Socket *)event[i].data.ptr;
294 nih_local char **env = NULL;
295 size_t env_len = 0;
296 char *var;
297 DBusPendingCall *pending_call;
298
299 if (event[i].events & EPOLLIN)
300 nih_debug ("%p EPOLLIN", sock);
301 if (event[i].events & EPOLLERR)
302 nih_debug ("%p EPOLLERR", sock);
303 if (event[i].events & EPOLLHUP)
304 nih_debug ("%p EPOLLHUP", sock);
305
306 env = NIH_MUST (nih_str_array_new (NULL));
307
308 switch (sock->addr.sa_family) {
309 case AF_INET:
310 NIH_MUST (nih_str_array_add (&env, NULL, &env_len,
311 "PROTO=inet"));
312
313 var = NIH_MUST (nih_sprintf (NULL, "PORT=%d",
314 ntohs (sock->sin_addr.sin_port)));
315 NIH_MUST (nih_str_array_addp (&env, NULL, &env_len,
316 var));
317 nih_discard (var);
318
319 var = NIH_MUST (nih_sprintf (NULL, "ADDR=%s",
320 inet_ntoa (sock->sin_addr.sin_addr)));
321 NIH_MUST (nih_str_array_addp (&env, NULL, &env_len,
322 var));
323 nih_discard (var);
324 break;
325 case AF_UNIX:
326 NIH_MUST (nih_str_array_add (&env, NULL, &env_len,
327 "PROTO=unix"));
328
329 var = NIH_MUST (nih_sprintf (NULL, "PATH=%s",
330 sock->sun_addr.sun_path));
331 NIH_MUST (nih_str_array_addp (&env, NULL, &env_len,
332 var));
333 nih_discard (var);
334 break;
335 default:
336 nih_assert_not_reached ();
337 }
338
339 pending_call = NIH_SHOULD (upstart_emit_event_with_file (
340 upstart, "socket", env, TRUE,
341 sock->sock,
342 (UpstartEmitEventWithFileReply)emit_event_reply,
343 (NihDBusErrorHandler)emit_event_error,
344 sock,
345 NIH_DBUS_TIMEOUT_NEVER));
346 if (! pending_call) {
347 NihError *err;
348
349 err = nih_error_get ();
350 nih_warn ("%s: %s", _("Could not send socket event"),
351 err->message);
352 nih_free (err);
353 }
354
355 dbus_pending_call_unref (pending_call);
356
357 // might be EPOLLIN
358 // might be EPOLLERR
359 // might be EPOLLHUP
360 }
361}
362
363
364static void
365upstart_job_added (void * data,
366 NihDBusMessage *message,
367 const char * job_class_path)
368{
369 nih_local NihDBusProxy *job_class = NULL;
370 nih_local char ***start_on = NULL;
371 nih_local char ***stop_on = NULL;
372 Job *job;
373
374 nih_assert (job_class_path != NULL);
375
376 /* Obtain a proxy to the job */
377 job_class = nih_dbus_proxy_new (NULL, upstart->connection,
378 upstart->name, job_class_path,
379 NULL, NULL);
380 if (! job_class) {
381 NihError *err;
382
383 err = nih_error_get ();
384 nih_error ("Could not create proxy for job %s: %s",
385 job_class_path, err->message);
386 nih_free (err);
387
388 return;
389 }
390
391 job_class->auto_start = FALSE;
392
393 /* Obtain the start_on and stop_on properties of the job */
394 if (job_class_get_start_on_sync (NULL, job_class, &start_on) < 0) {
395 NihError *err;
396
397 err = nih_error_get ();
398 nih_error ("Could not obtain job start condition %s: %s",
399 job_class_path, err->message);
400 nih_free (err);
401
402 return;
403 }
404
405 if (job_class_get_stop_on_sync (NULL, job_class, &stop_on) < 0) {
406 NihError *err;
407
408 err = nih_error_get ();
409 nih_error ("Could not obtain job stop condition %s: %s",
410 job_class_path, err->message);
411 nih_free (err);
412
413 return;
414 }
415
416 /* Free any existing record for the job (should never happen,
417 * but worth being safe).
418 */
419 job = (Job *)nih_hash_lookup (jobs, job_class_path);
420 if (job)
421 nih_free (job);
422
423 /* Create new record for the job */
424 job = NIH_MUST (nih_new (NULL, Job));
425 job->path = NIH_MUST (nih_strdup (job, job_class_path));
426
427 nih_list_init (&job->entry);
428 nih_list_init (&job->sockets);
429
430 /* Find out whether this job listens for any socket events */
431 for (char ***event = start_on; event && *event && **event; event++)
432 if (! strcmp (**event, "socket"))
433 job_add_socket (job, *event);
434 for (char ***event = stop_on; event && *event && **event; event++)
435 if (! strcmp (**event, "socket"))
436 job_add_socket (job, *event);
437
438 /* If we didn't end up with any sockets, free the job and move on */
439 if (NIH_LIST_EMPTY (&job->sockets)) {
440 nih_free (job);
441 return;
442 }
443
444 nih_debug ("Job got added %s", job_class_path);
445
446 nih_alloc_set_destructor (job, nih_list_destroy);
447 nih_hash_add (jobs, &job->entry);
448}
449
450static void
451upstart_job_removed (void * data,
452 NihDBusMessage *message,
453 const char * job_path)
454{
455 Job *job;
456
457 nih_assert (job_path != NULL);
458
459 job = (Job *)nih_hash_lookup (jobs, job_path);
460 if (job) {
461 nih_debug ("Job went away %s", job_path);
462 nih_free (job);
463 }
464}
465
466
467static void
468job_add_socket (Job * job,
469 char **socket_info)
470{
471 Socket *sock;
472 nih_local char *error = NULL;
473 int components = 0;
474 struct epoll_event event;
475
476 nih_assert (job != NULL);
477 nih_assert (socket_info != NULL);
478 nih_assert (! strcmp(socket_info[0], "socket"));
479
480 sock = NIH_MUST (nih_new (job, Socket));
481 memset (sock, 0, sizeof (Socket));
482 sock->sock = -1;
483
484 nih_list_init (&sock->entry);
485
486 nih_debug ("Found socket");
487 for (char **env = socket_info + 1; env && *env; env++) {
488 char *val;
489 size_t name_len;
490
491 val = strchr (*env, '=');
492 if (! val) {
493 nih_warn ("Ignored socket event without variable name in %s",
494 job->path);
495 goto error;
496 }
497
498 name_len = val - *env;
499 val++;
500
501 if (! strncmp (*env, "PROTO", name_len)) {
502 if (! strcmp (val, "inet")) {
503 sock->addrlen = sizeof sock->sin_addr;
504 sock->sin_addr.sin_family = AF_INET;
505 sock->sin_addr.sin_addr.s_addr = INADDR_ANY;
506 components = 1;
507 } else if (! strcmp (val, "unix")) {
508 sock->addrlen = sizeof sock->sun_addr;
509 sock->sun_addr.sun_family = AF_UNIX;
510 components = 1;
511 } else {
512 nih_warn ("Ignored socket event with unknown PROTO=%s in %s",
513 val, job->path);
514 goto error;
515 }
516
517 } else if (! strncmp (*env, "PORT", name_len)
518 && (sock->sin_addr.sin_family == AF_INET)) {
519 sock->sin_addr.sin_port = htons (atoi (val));
520 components--;
521
522 } else if (! strncmp (*env, "ADDR", name_len)
523 && (sock->sin_addr.sin_family == AF_INET)) {
524 if (inet_aton (val, &(sock->sin_addr.sin_addr)) == 0) {
525 nih_warn ("Ignored socket event with invalid ADDR=%s in %s",
526 val, job->path);
527 goto error;
528 }
529
530 } else if (! strncmp (*env, "PATH", name_len)
531 && (sock->sun_addr.sun_family == AF_UNIX)) {
532 strncpy (sock->sun_addr.sun_path, val,
533 sizeof sock->sun_addr.sun_path);
534
535 if (sock->sun_addr.sun_path[0] == '@')
536 sock->sun_addr.sun_path[0] = '\0';
537
538 components--;
539
540 } else {
541 nih_warn ("Ignored socket event with unknown variable %.*s in %s",
542 (int)name_len, *env, job->path);
543 goto error;
544 }
545 }
546
547 /* Missing any required components? */
548 if (components) {
549 nih_warn ("Ignored incomplete socket event in %s",
550 job->path);
551 goto error;
552 }
553
554 /* Let's try and set this baby up */
555 sock->sock = socket (sock->addr.sa_family, SOCK_STREAM, 0);
556 if (sock->sock < 0) {
557 nih_warn ("Failed to create socket in %s: %s",
558 job->path, strerror (errno));
559 goto error;
560 }
561
562 int opt = 1;
563 if (setsockopt (sock->sock, SOL_SOCKET, SO_REUSEADDR,
564 &opt, sizeof opt) < 0) {
565 nih_warn ("Failed to set socket reuse in %s: %s",
566 job->path, strerror (errno));
567 goto error;
568 }
569
570 if (bind (sock->sock, &sock->addr, sock->addrlen) < 0) {
571 nih_warn ("Failed to bind socket in %s: %s",
572 job->path, strerror (errno));
573 goto error;
574 }
575
576 if (listen (sock->sock, SOMAXCONN) < 0) {
577 nih_warn ("Failed to listen on socket in %s: %s",
578 job->path, strerror (errno));
579 goto error;
580 }
581
582 /* We have a listening socket, now we want to be notified when someone
583 * connects; but we just want one notification, we don't want to get
584 * a DDoS of wake-ups while waiting for the service to start.
585 *
586 * The solution is to use epoll in edge-triggered mode, this will
587 * fire only on initial connection until a new one comes in.
588 */
589 event.events = EPOLLIN | EPOLLET;
590 event.data.ptr = sock;
591
592 if (epoll_ctl (epoll_fd, EPOLL_CTL_ADD, sock->sock, &event) < 0) {
593 nih_warn ("Failed to watch socket in %s: %s",
594 job->path, strerror (errno));
595 goto error;
596 }
597
598 /* Okay then, add to the job */
599 nih_alloc_set_destructor (sock, socket_destroy);
600 nih_list_add (&job->sockets, &sock->entry);
601
602 return;
603
604error:
605 if (sock->sock != -1)
606 close (sock->sock);
607 nih_free (sock);
608}
609
610static void
611socket_destroy (Socket *sock)
612{
613 epoll_ctl (epoll_fd, EPOLL_CTL_DEL, sock->sock, NULL);
614 close (sock->sock);
615
616 nih_list_destroy (&sock->entry);
617}
618
619
620static void
621upstart_disconnected (DBusConnection *connection)
622{
623 nih_fatal (_("Disconnected from Upstart"));
624 nih_main_loop_exit (1);
625}
626
627
628static void
629emit_event_reply (Socket * sock,
630 NihDBusMessage *message)
631{
632 nih_debug ("Event completed");
633}
634
635static void
636emit_event_error (Socket * sock,
637 NihDBusMessage *message)
638{
639 NihError *err;
640
641 err = nih_error_get ();
642 nih_warn ("%s: %s", _("Error emitting socket event"), err->message);
643 nih_free (err);
644}
0645
=== added file 'extra/upstart-udev-bridge.c'
--- extra/upstart-udev-bridge.c 1970-01-01 00:00:00 +0000
+++ extra/upstart-udev-bridge.c 2011-05-15 18:31:10 +0000
@@ -0,0 +1,310 @@
1/* upstart
2 *
3 * Copyright © 2009 Canonical Ltd.
4 * Author: Scott James Remnant <scott@netsplit.com>.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#ifdef HAVE_CONFIG_H
21# include <config.h>
22#endif /* HAVE_CONFIG_H */
23
24
25#include <libudev.h>
26
27#include <stdlib.h>
28#include <string.h>
29#include <syslog.h>
30
31#include <nih/macros.h>
32#include <nih/alloc.h>
33#include <nih/string.h>
34#include <nih/io.h>
35#include <nih/option.h>
36#include <nih/main.h>
37#include <nih/logging.h>
38#include <nih/error.h>
39
40#include <nih-dbus/dbus_connection.h>
41#include <nih-dbus/dbus_proxy.h>
42
43#include "dbus/upstart.h"
44#include "com.ubuntu.Upstart.h"
45
46
47/* Prototypes for static functions */
48static void udev_monitor_watcher (struct udev_monitor *udev_monitor,
49 NihIoWatch *watch, NihIoEvents events);
50static void upstart_disconnected (DBusConnection *connection);
51static void emit_event_error (void *data, NihDBusMessage *message);
52
53
54/**
55 * daemonise:
56 *
57 * Set to TRUE if we should become a daemon, rather than just running
58 * in the foreground.
59 **/
60static int daemonise = FALSE;
61
62/**
63 * upstart:
64 *
65 * Proxy to Upstart daemon.
66 **/
67static NihDBusProxy *upstart = NULL;
68
69
70/**
71 * options:
72 *
73 * Command-line options accepted by this program.
74 **/
75static NihOption options[] = {
76 { 0, "daemon", N_("Detach and run in the background"),
77 NULL, NULL, &daemonise, NULL },
78
79 NIH_OPTION_LAST
80};
81
82
83int
84main (int argc,
85 char *argv[])
86{
87 char ** args;
88 DBusConnection * connection;
89 struct udev * udev;
90 struct udev_monitor *udev_monitor;
91 int ret;
92
93 nih_main_init (argv[0]);
94
95 nih_option_set_synopsis (_("Bridge udev events into upstart"));
96 nih_option_set_help (
97 _("By default, upstart-udev-bridge does not detach from the "
98 "console and remains in the foreground. Use the --daemon "
99 "option to have it detach."));
100
101 args = nih_option_parser (NULL, argc, argv, options, FALSE);
102 if (! args)
103 exit (1);
104
105 /* Initialise the connection to Upstart */
106 connection = NIH_SHOULD (nih_dbus_connect (DBUS_ADDRESS_UPSTART, upstart_disconnected));
107 if (! connection) {
108 NihError *err;
109
110 err = nih_error_get ();
111 nih_fatal ("%s: %s", _("Could not connect to Upstart"),
112 err->message);
113 nih_free (err);
114
115 exit (1);
116 }
117
118 upstart = NIH_SHOULD (nih_dbus_proxy_new (NULL, connection,
119 NULL, DBUS_PATH_UPSTART,
120 NULL, NULL));
121 if (! upstart) {
122 NihError *err;
123
124 err = nih_error_get ();
125 nih_fatal ("%s: %s", _("Could not create Upstart proxy"),
126 err->message);
127 nih_free (err);
128
129 exit (1);
130 }
131
132 /* Initialise the connection to udev */
133 nih_assert (udev = udev_new ());
134 nih_assert (udev_monitor = udev_monitor_new_from_netlink (udev, "udev"));
135 nih_assert (udev_monitor_enable_receiving (udev_monitor) == 0);
136 udev_monitor_set_receive_buffer_size(udev_monitor, 128*1024*1024);
137
138 NIH_MUST (nih_io_add_watch (NULL, udev_monitor_get_fd (udev_monitor),
139 NIH_IO_READ,
140 (NihIoWatcher)udev_monitor_watcher,
141 udev_monitor));
142
143 /* Become daemon */
144 if (daemonise) {
145 if (nih_main_daemonise () < 0) {
146 NihError *err;
147
148 err = nih_error_get ();
149 nih_fatal ("%s: %s", _("Unable to become daemon"),
150 err->message);
151 nih_free (err);
152
153 exit (1);
154 }
155
156 /* Send all logging output to syslog */
157 openlog (program_name, LOG_PID, LOG_DAEMON);
158 nih_log_set_logger (nih_logger_syslog);
159 }
160
161 /* Handle TERM and INT signals gracefully */
162 nih_signal_set_handler (SIGTERM, nih_signal_handler);
163 NIH_MUST (nih_signal_add_handler (NULL, SIGTERM, nih_main_term_signal, NULL));
164
165 if (! daemonise) {
166 nih_signal_set_handler (SIGINT, nih_signal_handler);
167 NIH_MUST (nih_signal_add_handler (NULL, SIGINT, nih_main_term_signal, NULL));
168 }
169
170 ret = nih_main_loop ();
171
172 return ret;
173}
174
175
176static void
177udev_monitor_watcher (struct udev_monitor *udev_monitor,
178 NihIoWatch * watch,
179 NihIoEvents events)
180{
181 struct udev_device * udev_device;
182 const char * subsystem;
183 const char * action;
184 const char * kernel;
185 const char * devpath;
186 const char * devname;
187 nih_local char * name = NULL;
188 nih_local char ** env = NULL;
189 size_t env_len = 0;
190 DBusPendingCall * pending_call;
191
192 udev_device = udev_monitor_receive_device (udev_monitor);
193 if (! udev_device)
194 return;
195
196 subsystem = udev_device_get_subsystem (udev_device);
197 action = udev_device_get_action (udev_device);
198 kernel = udev_device_get_sysname (udev_device);
199 devpath = udev_device_get_devpath (udev_device);
200 devname = udev_device_get_devnode (udev_device);
201
202 if (! strcmp (action, "add")) {
203 name = NIH_MUST (nih_sprintf (NULL, "%s-device-added",
204 subsystem));
205 } else if (! strcmp (action, "change")) {
206 name = NIH_MUST (nih_sprintf (NULL, "%s-device-changed",
207 subsystem));
208 } else if (! strcmp (action, "remove")) {
209 name = NIH_MUST (nih_sprintf (NULL, "%s-device-removed",
210 subsystem));
211 } else {
212 name = NIH_MUST (nih_sprintf (NULL, "%s-device-%s",
213 subsystem, action));
214 }
215
216 env = NIH_MUST (nih_str_array_new (NULL));
217
218 if (kernel) {
219 nih_local char *var = NULL;
220
221 var = NIH_MUST (nih_sprintf (NULL, "KERNEL=%s", kernel));
222 NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
223 }
224
225 if (devpath) {
226 nih_local char *var = NULL;
227
228 var = NIH_MUST (nih_sprintf (NULL, "DEVPATH=%s", devpath));
229 NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
230 }
231
232 if (devname) {
233 nih_local char *var = NULL;
234
235 var = NIH_MUST (nih_sprintf (NULL, "DEVNAME=%s", devname));
236 NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
237 }
238
239 if (subsystem) {
240 nih_local char *var = NULL;
241
242 var = NIH_MUST (nih_sprintf (NULL, "SUBSYSTEM=%s", subsystem));
243 NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
244 }
245
246 if (action) {
247 nih_local char *var = NULL;
248
249 var = NIH_MUST (nih_sprintf (NULL, "ACTION=%s", action));
250 NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
251 }
252
253 for (struct udev_list_entry *list_entry = udev_device_get_properties_list_entry (udev_device);
254 list_entry != NULL;
255 list_entry = udev_list_entry_get_next (list_entry)) {
256 const char * key;
257 nih_local char *var = NULL;
258
259 key = udev_list_entry_get_name (list_entry);
260 if (! strcmp (key, "DEVPATH"))
261 continue;
262 if (! strcmp (key, "DEVNAME"))
263 continue;
264 if (! strcmp (key, "SUBSYSTEM"))
265 continue;
266 if (! strcmp (key, "ACTION"))
267 continue;
268
269 var = NIH_MUST (nih_sprintf (NULL, "%s=%s", key,
270 udev_list_entry_get_value (list_entry)));
271 NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var));
272 }
273
274 nih_debug ("%s %s", name, devname);
275
276 pending_call = NIH_SHOULD (upstart_emit_event (upstart,
277 name, env, FALSE,
278 NULL, emit_event_error, NULL,
279 NIH_DBUS_TIMEOUT_NEVER));
280 if (! pending_call) {
281 NihError *err;
282
283 err = nih_error_get ();
284 nih_warn ("%s", err->message);
285 nih_free (err);
286 }
287
288 dbus_pending_call_unref (pending_call);
289
290 udev_device_unref (udev_device);
291}
292
293
294static void
295upstart_disconnected (DBusConnection *connection)
296{
297 nih_fatal (_("Disconnected from Upstart"));
298 nih_main_loop_exit (1);
299}
300
301static void
302emit_event_error (void * data,
303 NihDBusMessage *message)
304{
305 NihError *err;
306
307 err = nih_error_get ();
308 nih_warn ("%s", err->message);
309 nih_free (err);
310}
0311
=== modified file 'init/control.c'
--- init/control.c 2009-07-11 11:47:12 +0000
+++ init/control.c 2011-05-15 18:31:10 +0000
@@ -25,8 +25,10 @@
2525
26#include <dbus/dbus.h>26#include <dbus/dbus.h>
2727
28#include <fcntl.h>
28#include <stdio.h>29#include <stdio.h>
29#include <string.h>30#include <string.h>
31#include <unistd.h>
3032
31#include <nih/macros.h>33#include <nih/macros.h>
32#include <nih/alloc.h>34#include <nih/alloc.h>
@@ -462,13 +464,24 @@
462}464}
463465
464466
467int
468control_emit_event (void *data,
469 NihDBusMessage *message,
470 const char *name,
471 char * const *env,
472 int wait)
473{
474 return control_emit_event_with_file (data, message, name, env, wait, -1);
475}
476
465/**477/**
466 * control_emit_event:478 * control_emit_event_with_file:
467 * @data: not used,479 * @data: not used,
468 * @message: D-Bus connection and message received,480 * @message: D-Bus connection and message received,
469 * @name: name of event to emit,481 * @name: name of event to emit,
470 * @env: environment of environment,482 * @env: environment of environment,
471 * @wait: whether to wait for event completion before returning.483 * @wait: whether to wait for event completion before returning,
484 * @file: file descriptor.
472 *485 *
473 * Implements the top half of the EmitEvent method of the com.ubuntu.Upstart486 * Implements the top half of the EmitEvent method of the com.ubuntu.Upstart
474 * interface, the bottom half may be found in event_finished().487 * interface, the bottom half may be found in event_finished().
@@ -488,11 +501,12 @@
488 * Returns: zero on success, negative value on raised error.501 * Returns: zero on success, negative value on raised error.
489 **/502 **/
490int503int
491control_emit_event (void *data,504control_emit_event_with_file (void *data,
492 NihDBusMessage *message,505 NihDBusMessage *message,
493 const char *name,506 const char *name,
494 char * const *env,507 char * const *env,
495 int wait)508 int wait,
509 int file)
496{510{
497 Event *event;511 Event *event;
498 Blocked *blocked;512 Blocked *blocked;
@@ -505,6 +519,7 @@
505 if (! strlen (name)) {519 if (! strlen (name)) {
506 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,520 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
507 _("Name may not be empty string"));521 _("Name may not be empty string"));
522 close (file);
508 return -1;523 return -1;
509 }524 }
510525
@@ -512,19 +527,33 @@
512 if (! environ_all_valid (env)) {527 if (! environ_all_valid (env)) {
513 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,528 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
514 _("Env must be KEY=VALUE pairs"));529 _("Env must be KEY=VALUE pairs"));
530 close (file);
515 return -1;531 return -1;
516 }532 }
517533
518 /* Make the event and block the message on it */534 /* Make the event and block the message on it */
519 event = event_new (NULL, name, (char **)env);535 event = event_new (NULL, name, (char **)env);
520 if (! event)536 if (! event) {
521 nih_return_system_error (-1);537 nih_error_raise_system ();
538 close (file);
539 return -1;
540 }
541
542 event->fd = file;
543 if (event->fd >= 0) {
544 long flags;
545
546 flags = fcntl (event->fd, F_GETFD);
547 flags &= ~FD_CLOEXEC;
548 fcntl (event->fd, F_SETFD, flags);
549 }
522550
523 if (wait) {551 if (wait) {
524 blocked = blocked_new (event, BLOCKED_EMIT_METHOD, message);552 blocked = blocked_new (event, BLOCKED_EMIT_METHOD, message);
525 if (! blocked) {553 if (! blocked) {
526 nih_error_raise_system ();554 nih_error_raise_system ();
527 nih_free (event);555 nih_free (event);
556 close (file);
528 return -1;557 return -1;
529 }558 }
530559
531560
=== modified file 'init/control.h'
--- init/control.h 2009-07-09 08:36:52 +0000
+++ init/control.h 2011-05-15 18:31:10 +0000
@@ -60,6 +60,10 @@
60 const char *name, char * const *env,60 const char *name, char * const *env,
61 int wait)61 int wait)
62 __attribute__ ((warn_unused_result));62 __attribute__ ((warn_unused_result));
63int control_emit_event_with_file (void *data, NihDBusMessage *message,
64 const char *name, char * const *env,
65 int wait, int file)
66 __attribute__ ((warn_unused_result));
6367
64int control_get_version (void *data, NihDBusMessage *message,68int control_get_version (void *data, NihDBusMessage *message,
65 char **version)69 char **version)
6670
=== modified file 'init/event.c'
--- init/event.c 2010-12-14 15:32:41 +0000
+++ init/event.c 2011-05-15 18:31:10 +0000
@@ -25,6 +25,7 @@
2525
2626
27#include <string.h>27#include <string.h>
28#include <unistd.h>
2829
29#include <nih/macros.h>30#include <nih/macros.h>
30#include <nih/alloc.h>31#include <nih/alloc.h>
@@ -123,6 +124,8 @@
123124
124 nih_list_init (&event->entry);125 nih_list_init (&event->entry);
125126
127 event->fd = -1;
128
126 event->progress = EVENT_PENDING;129 event->progress = EVENT_PENDING;
127 event->failed = FALSE;130 event->failed = FALSE;
128131
@@ -393,8 +396,16 @@
393 job->start_env = env;396 job->start_env = env;
394 nih_ref (job->start_env, job);397 nih_ref (job->start_env, job);
395398
399 nih_discard (env);
400 env = NULL;
401
396 job_finished (job, FALSE);402 job_finished (job, FALSE);
397403
404 NIH_MUST (event_operator_fds (class->start_on, job,
405 &job->fds, &job->num_fds,
406 &job->start_env, &len,
407 "UPSTART_FDS"));
408
398 event_operator_events (job->class->start_on,409 event_operator_events (job->class->start_on,
399 job, &job->blocking);410 job, &job->blocking);
400411
@@ -459,6 +470,8 @@
459 nih_free (blocked);470 nih_free (blocked);
460 }471 }
461472
473 close (event->fd);
474
462 if (event->failed) {475 if (event->failed) {
463 char *name;476 char *name;
464477
465478
=== modified file 'init/event.h'
--- init/event.h 2009-07-09 08:36:52 +0000
+++ init/event.h 2011-05-15 18:31:10 +0000
@@ -63,6 +63,7 @@
6363
64 char *name;64 char *name;
65 char **env;65 char **env;
66 int fd;
6667
67 EventProgress progress;68 EventProgress progress;
68 int failed;69 int failed;
6970
=== modified file 'init/event_operator.c'
--- init/event_operator.c 2010-11-19 14:34:51 +0000
+++ init/event_operator.c 2011-05-15 18:31:10 +0000
@@ -552,6 +552,65 @@
552 return *env;552 return *env;
553}553}
554554
555int *
556event_operator_fds (EventOperator *root,
557 const void *parent,
558 int **fds,
559 size_t *num_fds,
560 char ***env,
561 size_t *len,
562 const char *key)
563{
564 nih_local char *evlist = NULL;
565
566 nih_assert (root != NULL);
567 nih_assert (fds != NULL);
568 nih_assert (num_fds != NULL);
569 nih_assert (env != NULL);
570 nih_assert (len != NULL);
571 nih_assert (key != NULL);
572
573 /* Initialise the event list variable with the name given. */
574 evlist = nih_sprintf (NULL, "%s=", key);
575 if (! evlist)
576 return NULL;
577
578 *num_fds = 0;
579 NIH_TREE_FOREACH_FULL (&root->node, iter,
580 (NihTreeFilter)event_operator_filter, NULL) {
581 EventOperator *oper = (EventOperator *)iter;
582
583 if (oper->type != EVENT_MATCH)
584 continue;
585
586 nih_assert (oper->event != NULL);
587
588 if (oper->event->fd >= 0) {
589 *fds = nih_realloc (*fds, parent, sizeof (int) * (*num_fds + 1));
590 if (! *fds)
591 return NULL;
592
593 (*fds)[(*num_fds)++] = oper->event->fd;
594
595 if (evlist[strlen (evlist) - 1] != '=') {
596 if (! nih_strcat_sprintf (&evlist, NULL, " %d",
597 oper->event->fd))
598 return NULL;
599 } else {
600 if (! nih_strcat_sprintf (&evlist, NULL, "%d",
601 oper->event->fd))
602 return NULL;
603 }
604 }
605 }
606
607 if (*num_fds)
608 if (! environ_add (env, parent, len, TRUE, evlist))
609 return NULL;
610
611 return (void *)1;
612}
613
555/**614/**
556 * event_operator_events:615 * event_operator_events:
557 * @root: operator tree to collect from,616 * @root: operator tree to collect from,
558617
=== modified file 'init/event_operator.h'
--- init/event_operator.h 2009-06-23 09:29:35 +0000
+++ init/event_operator.h 2011-05-15 18:31:10 +0000
@@ -95,6 +95,14 @@
95char ** event_operator_environment (EventOperator *root, char ***env,95char ** event_operator_environment (EventOperator *root, char ***env,
96 const void *parent, size_t *len,96 const void *parent, size_t *len,
97 const char *key);97 const char *key);
98int *
99event_operator_fds (EventOperator *root,
100 const void *parent,
101 int **fds,
102 size_t *num_fds,
103 char ***env,
104 size_t *len,
105 const char *key);
98void event_operator_events (EventOperator *root,106void event_operator_events (EventOperator *root,
99 const void *parent, NihList *list);107 const void *parent, NihList *list);
100108
101109
=== modified file 'init/job.c'
--- init/job.c 2010-12-14 15:32:41 +0000
+++ init/job.c 2011-05-15 18:31:10 +0000
@@ -118,6 +118,9 @@
118 goto error;118 goto error;
119 }119 }
120120
121 job->fds = NULL;
122 job->num_fds = 0;
123
121 job->pid = nih_alloc (job, sizeof (pid_t) * PROCESS_LAST);124 job->pid = nih_alloc (job, sizeof (pid_t) * PROCESS_LAST);
122 if (! job->pid)125 if (! job->pid)
123 goto error;126 goto error;
124127
=== modified file 'init/job.h'
--- init/job.h 2009-07-03 16:38:02 +0000
+++ init/job.h 2011-05-15 18:31:10 +0000
@@ -134,6 +134,9 @@
134 char **stop_env;134 char **stop_env;
135 EventOperator *stop_on;135 EventOperator *stop_on;
136136
137 int *fds;
138 size_t num_fds;
139
137 pid_t *pid;140 pid_t *pid;
138 Event *blocker;141 Event *blocker;
139 NihList blocking;142 NihList blocking;
140143
=== modified file 'po/POTFILES.in'
--- po/POTFILES.in 2011-05-05 09:06:21 +0000
+++ po/POTFILES.in 2011-05-15 18:31:10 +0000
@@ -20,3 +20,5 @@
20util/runlevel.c20util/runlevel.c
21util/shutdown.c21util/shutdown.c
22util/telinit.c22util/telinit.c
23
24extra/upstart-udev-bridge.c
2325
=== modified file 'po/upstart.pot'
--- po/upstart.pot 2011-03-22 17:52:25 +0000
+++ po/upstart.pot 2011-05-15 18:31:10 +0000
@@ -6,12 +6,13 @@
6#, fuzzy6#, fuzzy
7msgid ""7msgid ""
8msgstr ""8msgstr ""
9"Project-Id-Version: upstart 1.2\n"9"Project-Id-Version: upstart 1.3\n"
10"Report-Msgid-Bugs-To: new@bugs.launchpad.net\n"10"Report-Msgid-Bugs-To: new@bugs.launchpad.net\n"
11"POT-Creation-Date: 2011-03-22 10:52-0700\n"11"POT-Creation-Date: 2011-05-15 15:48+0100\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"14"Language-Team: LANGUAGE <LL@li.org>\n"
15"Language: \n"
15"MIME-Version: 1.0\n"16"MIME-Version: 1.0\n"
16"Content-Type: text/plain; charset=CHARSET\n"17"Content-Type: text/plain; charset=CHARSET\n"
17"Content-Transfer-Encoding: 8bit\n"18"Content-Transfer-Encoding: 8bit\n"
@@ -46,305 +47,364 @@
46msgid "Configuration directory deleted"47msgid "Configuration directory deleted"
47msgstr ""48msgstr ""
4849
49#: init/control.c:15550#: init/control.c:157
50msgid "Connection from private client"51msgid "Connection from private client"
51msgstr ""52msgstr ""
5253
53#: init/control.c:29054#: init/control.c:292
54msgid "Disconnected from system bus"55msgid "Disconnected from system bus"
55msgstr ""56msgstr ""
5657
57#: init/control.c:356 init/main.c:54658#: init/control.c:358 init/main.c:546
58msgid "Reloading configuration"59msgid "Reloading configuration"
59msgstr ""60msgstr ""
6061
61#: init/control.c:396 init/control.c:50762#: init/control.c:398 init/control.c:521
62msgid "Name may not be empty string"63msgid "Name may not be empty string"
63msgstr ""64msgstr ""
6465
65#: init/control.c:40566#: init/control.c:407
66#, c-format67#, c-format
67msgid "Unknown job: %s"68msgid "Unknown job: %s"
68msgstr ""69msgstr ""
6970
70#: init/control.c:514 init/job_class.c:522 init/job_class.c:71071#: init/control.c:529 init/job_class.c:524 init/job_class.c:712
71#: init/job_class.c:829 init/job_class.c:95372#: init/job_class.c:831 init/job_class.c:955
72msgid "Env must be KEY=VALUE pairs"73msgid "Env must be KEY=VALUE pairs"
73msgstr ""74msgstr ""
7475
75#: init/control.c:66676#: init/control.c:695
76msgid "The log priority given was not recognised"77msgid "The log priority given was not recognised"
77msgstr ""78msgstr ""
7879
79#: init/event.c:27380#: init/errors.h:58
81msgid "Illegal parameter"
82msgstr ""
83
84#: init/errors.h:59
85msgid "Unknown parameter"
86msgstr ""
87
88#: init/errors.h:60 init/errors.h:71
89msgid "Expected operator"
90msgstr ""
91
92#: init/errors.h:61
93msgid "Mismatched braces"
94msgstr ""
95
96#: init/errors.h:62
97msgid "Illegal interval, expected number of seconds"
98msgstr ""
99
100#: init/errors.h:63
101msgid "Illegal exit status, expected integer"
102msgstr ""
103
104#: init/errors.h:64
105msgid "Illegal signal status, expected integer"
106msgstr ""
107
108#: init/errors.h:65
109msgid "Illegal file creation mask, expected octal integer"
110msgstr ""
111
112#: init/errors.h:66
113msgid "Illegal nice value, expected -20 to 19"
114msgstr ""
115
116#: init/errors.h:67
117msgid "Illegal oom adjustment, expected -16 to 15 or 'never'"
118msgstr ""
119
120#: init/errors.h:68
121msgid "Illegal oom score adjustment, expected -999 to 1000 or 'never'"
122msgstr ""
123
124#: init/errors.h:69
125msgid "Illegal limit, expected 'unlimited' or integer"
126msgstr ""
127
128#: init/errors.h:70
129msgid "Expected event"
130msgstr ""
131
132#: init/errors.h:72
133msgid "Expected variable name before value"
134msgstr ""
135
136#: init/errors.h:73
137msgid "Mismatched parentheses"
138msgstr ""
139
140#: init/errors.h:74
141msgid "Name already taken"
142msgstr ""
143
144#: init/event.c:276
80#, c-format145#, c-format
81msgid "Handling %s event"146msgid "Handling %s event"
82msgstr ""147msgstr ""
83148
84#: init/event.c:373149#: init/event.c:376
85#, c-format150#, c-format
86msgid "Failed to obtain %s instance: %s"151msgid "Failed to obtain %s instance: %s"
87msgstr ""152msgstr ""
88153
89#: init/event.c:448154#: init/event.c:459
90msgid "Event failed"155msgid "Event failed"
91msgstr ""156msgstr ""
92157
93#: init/job.c:223158#: init/job.c:226
94#, c-format159#, c-format
95msgid "%s goal changed from %s to %s"160msgid "%s goal changed from %s to %s"
96msgstr ""161msgstr ""
97162
98#: init/job.c:294163#: init/job.c:297
99#, c-format164#, c-format
100msgid "%s state changed from %s to %s"165msgid "%s state changed from %s to %s"
101msgstr ""166msgstr ""
102167
103#: init/job.c:713 init/job.c:751168#: init/job.c:716 init/job.c:754
104msgid "Job failed to start"169msgid "Job failed to start"
105msgstr ""170msgstr ""
106171
107#: init/job.c:726 init/job.c:762172#: init/job.c:729 init/job.c:765
108msgid "Job failed while stopping"173msgid "Job failed while stopping"
109msgstr ""174msgstr ""
110175
111#: init/job.c:738 init/job.c:773176#: init/job.c:741 init/job.c:776
112msgid "Job failed to restart"177msgid "Job failed to restart"
113msgstr ""178msgstr ""
114179
115#: init/job.c:966180#: init/job.c:969
116msgid "stop"181msgid "stop"
117msgstr ""182msgstr ""
118183
119#: init/job.c:968184#: init/job.c:971
120msgid "start"185msgid "start"
121msgstr ""186msgstr ""
122187
123#: init/job.c:970188#: init/job.c:973
124msgid "respawn"189msgid "respawn"
125msgstr ""190msgstr ""
126191
127#: init/job.c:1015192#: init/job.c:1018
128msgid "waiting"193msgid "waiting"
129msgstr ""194msgstr ""
130195
131#: init/job.c:1017196#: init/job.c:1020
132msgid "starting"197msgid "starting"
133msgstr ""198msgstr ""
134199
135#: init/job.c:1019 init/process.c:80200#: init/job.c:1022 init/process.c:80
136msgid "pre-start"201msgid "pre-start"
137msgstr ""202msgstr ""
138203
139#: init/job.c:1021204#: init/job.c:1024
140msgid "spawned"205msgid "spawned"
141msgstr ""206msgstr ""
142207
143#: init/job.c:1023 init/process.c:82208#: init/job.c:1026 init/process.c:82
144msgid "post-start"209msgid "post-start"
145msgstr ""210msgstr ""
146211
147#: init/job.c:1025212#: init/job.c:1028
148msgid "running"213msgid "running"
149msgstr ""214msgstr ""
150215
151#: init/job.c:1027 init/process.c:84216#: init/job.c:1030 init/process.c:84
152msgid "pre-stop"217msgid "pre-stop"
153msgstr ""218msgstr ""
154219
155#: init/job.c:1029220#: init/job.c:1032
156msgid "stopping"221msgid "stopping"
157msgstr ""222msgstr ""
158223
159#: init/job.c:1031224#: init/job.c:1034
160msgid "killed"225msgid "killed"
161msgstr ""226msgstr ""
162227
163#: init/job.c:1033 init/process.c:86228#: init/job.c:1036 init/process.c:86
164msgid "post-stop"229msgid "post-stop"
165msgstr ""230msgstr ""
166231
167#: init/job.c:1113 init/job_class.c:756232#: init/job.c:1116 init/job_class.c:758
168#, c-format233#, c-format
169msgid "Job is already running: %s"234msgid "Job is already running: %s"
170msgstr ""235msgstr ""
171236
172#: init/job.c:1177 init/job.c:1242 init/job_class.c:875 init/job_class.c:998237#: init/job.c:1180 init/job.c:1245 init/job_class.c:877 init/job_class.c:1000
173#, c-format238#, c-format
174msgid "Job has already been stopped: %s"239msgid "Job has already been stopped: %s"
175msgstr ""240msgstr ""
176241
177#: init/job_class.c:559 init/job_class.c:604 init/job_class.c:867242#: init/job_class.c:561 init/job_class.c:606 init/job_class.c:869
178#: init/job_class.c:990243#: init/job_class.c:992
179#, c-format244#, c-format
180msgid "Unknown instance: %s"245msgid "Unknown instance: %s"
181msgstr ""246msgstr ""
182247
183#: init/job_process.c:279248#: init/job_process.c:277
184#, c-format249#, c-format
185msgid "Failed to spawn %s %s process: %s"250msgid "Failed to spawn %s %s process: %s"
186msgstr ""251msgstr ""
187252
188#: init/job_process.c:285253#: init/job_process.c:283
189msgid "Temporary process spawn error"254msgid "Temporary process spawn error"
190msgstr ""255msgstr ""
191256
192#: init/job_process.c:292257#: init/job_process.c:290
193#, c-format258#, c-format
194msgid "%s %s process (%d)"259msgid "%s %s process (%d)"
195msgstr ""260msgstr ""
196261
197#: init/job_process.c:399262#: init/job_process.c:403
198#, c-format263#, c-format
199msgid "Pausing %s (%d) [pre-exec] for debug"264msgid "Pausing %s (%d) [pre-exec] for debug"
200msgstr ""265msgstr ""
201266
202#: init/job_process.c:453267#: init/job_process.c:473
203#, c-format268#, c-format
204msgid "Failed to open system console: %s"269msgid "Failed to open system console: %s"
205msgstr ""270msgstr ""
206271
207#: init/job_process.c:669272#: init/job_process.c:697
273#, c-format
274msgid "unable to move script fd: %s"
275msgstr ""
276
277#: init/job_process.c:702
208#, c-format278#, c-format
209msgid "unable to open console: %s"279msgid "unable to open console: %s"
210msgstr ""280msgstr ""
211281
212#: init/job_process.c:724282#: init/job_process.c:757
213#, c-format283#, c-format
214msgid "unable to set \"%s\" resource limit: %s"284msgid "unable to set \"%s\" resource limit: %s"
215msgstr ""285msgstr ""
216286
217#: init/job_process.c:729287#: init/job_process.c:762
218#, c-format288#, c-format
219msgid "unable to set priority: %s"289msgid "unable to set priority: %s"
220msgstr ""290msgstr ""
221291
222#: init/job_process.c:734292#: init/job_process.c:767
223#, c-format293#, c-format
224msgid "unable to set oom adjustment: %s"294msgid "unable to set oom adjustment: %s"
225msgstr ""295msgstr ""
226296
227#: init/job_process.c:739297#: init/job_process.c:772
228#, c-format298#, c-format
229msgid "unable to change root directory: %s"299msgid "unable to change root directory: %s"
230msgstr ""300msgstr ""
231301
232#: init/job_process.c:744302#: init/job_process.c:777
233#, c-format303#, c-format
234msgid "unable to change working directory: %s"304msgid "unable to change working directory: %s"
235msgstr ""305msgstr ""
236306
237#: init/job_process.c:749307#: init/job_process.c:782
238#, c-format308#, c-format
239msgid "unable to set trace: %s"309msgid "unable to set trace: %s"
240msgstr ""310msgstr ""
241311
242#: init/job_process.c:754312#: init/job_process.c:787
243#, c-format313#, c-format
244msgid "unable to execute: %s"314msgid "unable to execute: %s"
245msgstr ""315msgstr ""
246316
247#: init/job_process.c:785317#: init/job_process.c:818 init/job_process.c:868
248#, c-format318#, c-format
249msgid "Sending TERM signal to %s %s process (%d)"319msgid "Sending %s signal to %s %s process (%d)"
250msgstr ""320msgstr ""
251321
252#: init/job_process.c:793322#: init/job_process.c:827 init/job_process.c:877
253#, c-format323#, c-format
254msgid "Failed to send TERM signal to %s %s process (%d): %s"324msgid "Failed to send %s signal to %s %s process (%d): %s"
255msgstr ""325msgstr ""
256326
257#: init/job_process.c:833327#: init/job_process.c:938
258#, c-format
259msgid "Sending KILL signal to %s %s process (%d)"
260msgstr ""
261
262#: init/job_process.c:841
263#, c-format
264msgid "Failed to send KILL signal to %s %s process (%d): %s"
265msgstr ""
266
267#: init/job_process.c:901
268#, c-format328#, c-format
269msgid "%s %s process (%d) terminated with status %d"329msgid "%s %s process (%d) terminated with status %d"
270msgstr ""330msgstr ""
271331
272#: init/job_process.c:906332#: init/job_process.c:943
273#, c-format333#, c-format
274msgid "%s %s process (%d) exited normally"334msgid "%s %s process (%d) exited normally"
275msgstr ""335msgstr ""
276336
277#: init/job_process.c:921337#: init/job_process.c:958
278#, c-format338#, c-format
279msgid "%s %s process (%d) killed by %s signal"339msgid "%s %s process (%d) killed by %s signal"
280msgstr ""340msgstr ""
281341
282#: init/job_process.c:925342#: init/job_process.c:962
283#, c-format343#, c-format
284msgid "%s %s process (%d) killed by signal %d"344msgid "%s %s process (%d) killed by signal %d"
285msgstr ""345msgstr ""
286346
287#: init/job_process.c:939347#: init/job_process.c:976
288#, c-format348#, c-format
289msgid "%s %s process (%d) stopped by %s signal"349msgid "%s %s process (%d) stopped by %s signal"
290msgstr ""350msgstr ""
291351
292#: init/job_process.c:943352#: init/job_process.c:980
293#, c-format353#, c-format
294msgid "%s %s process (%d) stopped by signal %d"354msgid "%s %s process (%d) stopped by signal %d"
295msgstr ""355msgstr ""
296356
297#: init/job_process.c:957357#: init/job_process.c:994
298#, c-format358#, c-format
299msgid "%s %s process (%d) continued by %s signal"359msgid "%s %s process (%d) continued by %s signal"
300msgstr ""360msgstr ""
301361
302#: init/job_process.c:961362#: init/job_process.c:998
303#, c-format363#, c-format
304msgid "%s %s process (%d) continued by signal %d"364msgid "%s %s process (%d) continued by signal %d"
305msgstr ""365msgstr ""
306366
307#: init/job_process.c:1096367#: init/job_process.c:1133
308#, c-format368#, c-format
309msgid "%s respawning too fast, stopped"369msgid "%s respawning too fast, stopped"
310msgstr ""370msgstr ""
311371
312#: init/job_process.c:1102372#: init/job_process.c:1139
313#, c-format373#, c-format
314msgid "%s %s process ended, respawning"374msgid "%s %s process ended, respawning"
315msgstr ""375msgstr ""
316376
317#: init/job_process.c:1342377#: init/job_process.c:1379
318#, c-format378#, c-format
319msgid "Failed to set ptrace options for %s %s process (%d): %s"379msgid "Failed to set ptrace options for %s %s process (%d): %s"
320msgstr ""380msgstr ""
321381
322#: init/job_process.c:1355 init/job_process.c:1550382#: init/job_process.c:1392 init/job_process.c:1587
323#, c-format383#, c-format
324msgid "Failed to continue traced %s %s process (%d): %s"384msgid "Failed to continue traced %s %s process (%d): %s"
325msgstr ""385msgstr ""
326386
327#: init/job_process.c:1395 init/job_process.c:1486 init/job_process.c:1541387#: init/job_process.c:1432 init/job_process.c:1523 init/job_process.c:1578
328#, c-format388#, c-format
329msgid "Failed to detach traced %s %s process (%d): %s"389msgid "Failed to detach traced %s %s process (%d): %s"
330msgstr ""390msgstr ""
331391
332#: init/job_process.c:1435392#: init/job_process.c:1472
333#, c-format393#, c-format
334msgid "Failed to deliver signal to traced %s %s process (%d): %s"394msgid "Failed to deliver signal to traced %s %s process (%d): %s"
335msgstr ""395msgstr ""
336396
337#: init/job_process.c:1470397#: init/job_process.c:1507
338#, c-format398#, c-format
339msgid "Failed to obtain child process id for %s %s process (%d): %s"399msgid "Failed to obtain child process id for %s %s process (%d): %s"
340msgstr ""400msgstr ""
341401
342#: init/job_process.c:1477402#: init/job_process.c:1514
343#, c-format403#, c-format
344msgid "%s %s process (%d) became new process (%d)"404msgid "%s %s process (%d) became new process (%d)"
345msgstr ""405msgstr ""
346406
347#: init/job_process.c:1536407#: init/job_process.c:1573
348#, c-format408#, c-format
349msgid "%s %s process (%d) executable changed"409msgid "%s %s process (%d) executable changed"
350msgstr ""410msgstr ""
@@ -819,3 +879,33 @@
819#, c-format879#, c-format
820msgid "%s: illegal runlevel: %s\n"880msgid "%s: illegal runlevel: %s\n"
821msgstr ""881msgstr ""
882
883#: extra/upstart-udev-bridge.c:76
884msgid "Detach and run in the background"
885msgstr ""
886
887#: extra/upstart-udev-bridge.c:95
888msgid "Bridge udev events into upstart"
889msgstr ""
890
891#: extra/upstart-udev-bridge.c:97
892msgid ""
893"By default, upstart-udev-bridge does not detach from the console and remains "
894"in the foreground. Use the --daemon option to have it detach."
895msgstr ""
896
897#: extra/upstart-udev-bridge.c:111
898msgid "Could not connect to Upstart"
899msgstr ""
900
901#: extra/upstart-udev-bridge.c:125
902msgid "Could not create Upstart proxy"
903msgstr ""
904
905#: extra/upstart-udev-bridge.c:149
906msgid "Unable to become daemon"
907msgstr ""
908
909#: extra/upstart-udev-bridge.c:297
910msgid "Disconnected from Upstart"
911msgstr ""

Subscribers

People subscribed via source and target branches