Merge lp:~jamesodhunt/upstart/upstart-dconf-bridge into lp:upstart
- upstart-dconf-bridge
- Merge into trunk
Proposed by
James Hunt
Status: | Merged |
---|---|
Merged at revision: | 1519 |
Proposed branch: | lp:~jamesodhunt/upstart/upstart-dconf-bridge |
Merge into: | lp:upstart |
Diff against target: |
922 lines (+826/-5) 7 files modified
ChangeLog (+46/-3) configure.ac (+11/-0) extra/Makefile.am (+33/-2) extra/conf-session/upstart-dconf-bridge.conf (+10/-0) extra/man/dconf-event.7 (+52/-0) extra/man/upstart-dconf-bridge.8 (+66/-0) extra/upstart-dconf-bridge.c (+608/-0) |
To merge this branch: | bzr merge lp:~jamesodhunt/upstart/upstart-dconf-bridge |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Upstart Reviewers | Pending | ||
Review via email: mp+177650@code.launchpad.net |
Commit message
Description of the change
New user bridge that emits Upstart events on dconf key changes.
To post a comment you must log in.
- 1472. By James Hunt
-
* extra/Makefile.am:
- Add missing DCONF_CFLAGS.
- Ensure upstart-dconf-bridge sources are always distributed,
regardless of whether the local system is able to build it, or has
disabled building it. - 1473. By James Hunt
-
* Sync with lp:upstart.
- 1474. By James Hunt
-
* Sync with lp:upstart taking care to set extra/Makefile.am's EXTRA_DIST
correctly.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'ChangeLog' | |||
2 | --- ChangeLog 2013-08-15 09:51:55 +0000 | |||
3 | +++ ChangeLog 2013-08-15 13:38:35 +0000 | |||
4 | @@ -2,9 +2,14 @@ | |||
5 | 2 | 2 | ||
6 | 3 | * configure.ac: | 3 | * configure.ac: |
7 | 4 | - Allow udev bridge to be disabled. | 4 | - Allow udev bridge to be disabled. |
11 | 5 | * extra/Makefile.am: Ensure source for upstart-udev-bridge is | 5 | * extra/Makefile.am: |
12 | 6 | distributed, regardless of whether the local system is able to build | 6 | - Ensure source for upstart-udev-bridge is distributed, |
13 | 7 | it, or has disabled building it. | 7 | regardless of whether the local system is able to build it, |
14 | 8 | or has disabled building it. | ||
15 | 9 | - Add missing DCONF_CFLAGS. | ||
16 | 10 | - Ensure upstart-dconf-bridge sources are always distributed, | ||
17 | 11 | regardless of whether the local system is able to build it, or has | ||
18 | 12 | disabled building it. | ||
19 | 8 | 13 | ||
20 | 9 | 2013-07-31 James Hunt <james.hunt@ubuntu.com> | 14 | 2013-07-31 James Hunt <james.hunt@ubuntu.com> |
21 | 10 | 15 | ||
22 | @@ -12,6 +17,18 @@ | |||
23 | 12 | since the NIH main loop may be iterated once more before | 17 | since the NIH main loop may be iterated once more before |
24 | 13 | shutdown. | 18 | shutdown. |
25 | 14 | 19 | ||
26 | 20 | 2013-07-30 James Hunt <james.hunt@ubuntu.com> | ||
27 | 21 | |||
28 | 22 | * extra/man/dconf-event.7: New man page. | ||
29 | 23 | * extra/man/upstart-dconf-bridge.8: New man page. | ||
30 | 24 | * extra/upstart-dconf-bridge.c: Bridge will now only emit | ||
31 | 25 | events on dconf changes if any jobs care about them | ||
32 | 26 | (unless --always is specified). | ||
33 | 27 | * extra/conf-session/upstart-dconf-bridge.conf: Sample conf | ||
34 | 28 | file for dconf bridge. | ||
35 | 29 | * extra/Makefile.am: Added dconf bridge man pages and sample | ||
36 | 30 | conf to distribution. | ||
37 | 31 | |||
38 | 15 | 2013-07-25 James Hunt <james.hunt@ubuntu.com> | 32 | 2013-07-25 James Hunt <james.hunt@ubuntu.com> |
39 | 16 | 33 | ||
40 | 17 | * extra/Makefile.am: Renamed to upstart-local-bridge. | 34 | * extra/Makefile.am: Renamed to upstart-local-bridge. |
41 | @@ -124,6 +141,32 @@ | |||
42 | 124 | part of the earlier Session deserialisation. (LP: #1199778) | 141 | part of the earlier Session deserialisation. (LP: #1199778) |
43 | 125 | * init/state.c: Formatting. | 142 | * init/state.c: Formatting. |
44 | 126 | 143 | ||
45 | 144 | 2013-07-09 James Hunt <james.hunt@ubuntu.com> | ||
46 | 145 | |||
47 | 146 | * {configure.ac,Makefile.am}: Allow upstart-dconf-bridge to be | ||
48 | 147 | disabled even if dependencies are available (--disable-dconf-bridge). | ||
49 | 148 | * extra/upstart-dconf-bridge.c: Changed event name to simply 'dconf' | ||
50 | 149 | with fixed first argument of 'TYPE=changed' for consistency with | ||
51 | 150 | other bridge events and to accommodate future dconf API changes. | ||
52 | 151 | |||
53 | 152 | 2013-07-08 James Hunt <james.hunt@ubuntu.com> | ||
54 | 153 | |||
55 | 154 | * extra/upstart-dconf-bridge.c: dconf_changed(): | ||
56 | 155 | - Simplified logic after desrt clarified 'changed' signal | ||
57 | 156 | behaviour. | ||
58 | 157 | |||
59 | 158 | 2013-07-05 James Hunt <james.hunt@ubuntu.com> | ||
60 | 159 | |||
61 | 160 | * extra/upstart-dconf-bridge.c: | ||
62 | 161 | - Added DCONF_EVENT. | ||
63 | 162 | - Reformatted to be more consistent with other bridges. | ||
64 | 163 | - main(): | ||
65 | 164 | - Connect to UPSTART_SESSION rather than D-Bus session bus. | ||
66 | 165 | - Handle generation of pidfile name. | ||
67 | 166 | - dconf_changed(): | ||
68 | 167 | - Correct path logic and ensure that if the changes array contains | ||
69 | 168 | values that they are separated correctly from the prefix. | ||
70 | 169 | |||
71 | 127 | 2013-07-04 James Hunt <james.hunt@ubuntu.com> | 170 | 2013-07-04 James Hunt <james.hunt@ubuntu.com> |
72 | 128 | 171 | ||
73 | 129 | * NEWS: Release 1.9.1 | 172 | * NEWS: Release 1.9.1 |
74 | 130 | 173 | ||
75 | === modified file 'configure.ac' | |||
76 | --- configure.ac 2013-08-15 09:51:55 +0000 | |||
77 | +++ configure.ac 2013-08-15 13:38:35 +0000 | |||
78 | @@ -30,7 +30,9 @@ | |||
79 | 30 | PKG_CHECK_MODULES([NIH], [libnih >= 1.0.2]) | 30 | PKG_CHECK_MODULES([NIH], [libnih >= 1.0.2]) |
80 | 31 | PKG_CHECK_MODULES([NIH_DBUS], [libnih-dbus >= 1.0.0]) | 31 | PKG_CHECK_MODULES([NIH_DBUS], [libnih-dbus >= 1.0.0]) |
81 | 32 | PKG_CHECK_MODULES([DBUS], [dbus-1 >= 1.2.16]) | 32 | PKG_CHECK_MODULES([DBUS], [dbus-1 >= 1.2.16]) |
82 | 33 | PKG_CHECK_MODULES([GIO], [gio-2.0 >= 2.36], [have_gio=yes], [have_gio=no]) | ||
83 | 33 | PKG_CHECK_MODULES([UDEV], [libudev >= 146], [have_udev=yes], [have_udev=no]) | 34 | PKG_CHECK_MODULES([UDEV], [libudev >= 146], [have_udev=yes], [have_udev=no]) |
84 | 35 | PKG_CHECK_MODULES([DCONF], [dconf >= 0.14], [have_dconf=yes], [have_dconf=no]) | ||
85 | 34 | 36 | ||
86 | 35 | AC_ARG_ENABLE([udev-bridge], | 37 | AC_ARG_ENABLE([udev-bridge], |
87 | 36 | AS_HELP_STRING([--disable-udev-bridge], | 38 | AS_HELP_STRING([--disable-udev-bridge], |
88 | @@ -39,6 +41,15 @@ | |||
89 | 39 | 41 | ||
90 | 40 | AM_CONDITIONAL([ENABLE_UDEV_BRIDGE], [test "$have_udev" = yes && test "$udev_bridge" = yes]) | 42 | AM_CONDITIONAL([ENABLE_UDEV_BRIDGE], [test "$have_udev" = yes && test "$udev_bridge" = yes]) |
91 | 41 | 43 | ||
92 | 44 | AC_ARG_ENABLE([dconf-bridge], | ||
93 | 45 | AS_HELP_STRING([--disable-dconf-bridge], | ||
94 | 46 | [Disable building of upstart-dconf-bridge even if required dependencies available]), | ||
95 | 47 | [dconf_bridge=no], [dconf_bridge=yes]) | ||
96 | 48 | |||
97 | 49 | AM_CONDITIONAL([ENABLE_DCONF_BRIDGE], [test "$have_dconf" = yes && | ||
98 | 50 | test "$have_gio" = yes && | ||
99 | 51 | test "$dconf_bridge" = yes]) | ||
100 | 52 | |||
101 | 42 | # Reasons for requiring this library version: | 53 | # Reasons for requiring this library version: |
102 | 43 | # | 54 | # |
103 | 44 | # 1) RFC 4627, the JSON "memo" (it is *NOT* a standard!) helpfully fails | 55 | # 1) RFC 4627, the JSON "memo" (it is *NOT* a standard!) helpfully fails |
104 | 45 | 56 | ||
105 | === modified file 'extra/Makefile.am' | |||
106 | --- extra/Makefile.am 2013-08-15 09:51:55 +0000 | |||
107 | +++ extra/Makefile.am 2013-08-15 13:38:35 +0000 | |||
108 | @@ -1,10 +1,14 @@ | |||
109 | 1 | ## Process this file with automake to produce Makefile.in | 1 | ## Process this file with automake to produce Makefile.in |
110 | 2 | 2 | ||
111 | 3 | # Required to allow conditional appends below | ||
112 | 4 | EXTRA_DIST = | ||
113 | 5 | |||
114 | 3 | AM_CFLAGS = \ | 6 | AM_CFLAGS = \ |
115 | 4 | $(NIH_CFLAGS) \ | 7 | $(NIH_CFLAGS) \ |
116 | 5 | $(NIH_DBUS_CFLAGS) \ | 8 | $(NIH_DBUS_CFLAGS) \ |
117 | 6 | $(DBUS_CFLAGS) \ | 9 | $(DBUS_CFLAGS) \ |
119 | 7 | $(UDEV_CFLAGS) | 10 | $(UDEV_CFLAGS) \ |
120 | 11 | $(DCONF_CFLAGS) | ||
121 | 8 | 12 | ||
122 | 9 | AM_CPPFLAGS = \ | 13 | AM_CPPFLAGS = \ |
123 | 10 | -DLOCALEDIR="\"$(localedir)\"" \ | 14 | -DLOCALEDIR="\"$(localedir)\"" \ |
124 | @@ -102,6 +106,33 @@ | |||
125 | 102 | $(NIH_DBUS_LIBS) \ | 106 | $(NIH_DBUS_LIBS) \ |
126 | 103 | $(DBUS_LIBS) | 107 | $(DBUS_LIBS) |
127 | 104 | 108 | ||
128 | 109 | dist_sessions_DATA += \ | ||
129 | 110 | conf-session/upstart-dconf-bridge.conf | ||
130 | 111 | |||
131 | 112 | dist_man_MANS += \ | ||
132 | 113 | man/upstart-dconf-bridge.8 \ | ||
133 | 114 | man/dconf-event.7 | ||
134 | 115 | |||
135 | 116 | if ENABLE_DCONF_BRIDGE | ||
136 | 117 | sbin_PROGRAMS += \ | ||
137 | 118 | upstart-dconf-bridge | ||
138 | 119 | |||
139 | 120 | upstart_dconf_bridge_SOURCES = \ | ||
140 | 121 | upstart-dconf-bridge.c | ||
141 | 122 | nodist_upstart_dconf_bridge_SOURCES = \ | ||
142 | 123 | $(com_ubuntu_Upstart_OUTPUTS) | ||
143 | 124 | upstart_dconf_bridge_LDADD = \ | ||
144 | 125 | $(LTLIBINTL) \ | ||
145 | 126 | $(NIH_LIBS) \ | ||
146 | 127 | $(NIH_DBUS_LIBS) \ | ||
147 | 128 | $(DBUS_LIBS) \ | ||
148 | 129 | $(GIO_LIBS) \ | ||
149 | 130 | $(DCONF_LIBS) | ||
150 | 131 | else | ||
151 | 132 | EXTRA_DIST += \ | ||
152 | 133 | upstart-dconf-bridge.c | ||
153 | 134 | endif | ||
154 | 135 | |||
155 | 105 | dist_init_DATA += \ | 136 | dist_init_DATA += \ |
156 | 106 | conf/upstart-udev-bridge.conf | 137 | conf/upstart-udev-bridge.conf |
157 | 107 | 138 | ||
158 | @@ -136,7 +167,7 @@ | |||
159 | 136 | done | 167 | done |
160 | 137 | 168 | ||
161 | 138 | else | 169 | else |
163 | 139 | EXTRA_DIST = \ | 170 | EXTRA_DIST += \ |
164 | 140 | upstart-udev-bridge.c \ | 171 | upstart-udev-bridge.c \ |
165 | 141 | man/upstart-udev-bridge.8 | 172 | man/upstart-udev-bridge.8 |
166 | 142 | endif | 173 | endif |
167 | 143 | 174 | ||
168 | === added file 'extra/conf-session/upstart-dconf-bridge.conf' | |||
169 | --- extra/conf-session/upstart-dconf-bridge.conf 1970-01-01 00:00:00 +0000 | |||
170 | +++ extra/conf-session/upstart-dconf-bridge.conf 2013-08-15 13:38:35 +0000 | |||
171 | @@ -0,0 +1,10 @@ | |||
172 | 1 | description "Bridge dconf events into session upstart" | ||
173 | 2 | |||
174 | 3 | emits dconf | ||
175 | 4 | |||
176 | 5 | start on started dbus | ||
177 | 6 | stop on stopped dbus | ||
178 | 7 | |||
179 | 8 | respawn | ||
180 | 9 | |||
181 | 10 | exec upstart-dconf-bridge | ||
182 | 0 | 11 | ||
183 | === added file 'extra/man/dconf-event.7' | |||
184 | --- extra/man/dconf-event.7 1970-01-01 00:00:00 +0000 | |||
185 | +++ extra/man/dconf-event.7 2013-08-15 13:38:35 +0000 | |||
186 | @@ -0,0 +1,52 @@ | |||
187 | 1 | .TH dconf\-event 7 2013-07-09 upstart | ||
188 | 2 | .\" | ||
189 | 3 | .SH NAME | ||
190 | 4 | dconf \- event signalling that a dconf key has been changed | ||
191 | 5 | .\" | ||
192 | 6 | .SH SYNOPSIS | ||
193 | 7 | .B dconf | ||
194 | 8 | .BI TYPE\fR= changed | ||
195 | 9 | .BI KEY\fR= KEY | ||
196 | 10 | .BI VALUE\fR= VALUE | ||
197 | 11 | .\" | ||
198 | 12 | .SH DESCRIPTION | ||
199 | 13 | |||
200 | 14 | The | ||
201 | 15 | .B dconf | ||
202 | 16 | event is generated by the | ||
203 | 17 | .BR upstart\-dconf\-bridge (8) | ||
204 | 18 | daemon when a dconf key changes whose details match the | ||
205 | 19 | .I dconf | ||
206 | 20 | event condition and environment specified in a job's | ||
207 | 21 | .B start on | ||
208 | 22 | or | ||
209 | 23 | .B stop on | ||
210 | 24 | stanza. | ||
211 | 25 | |||
212 | 26 | .\" | ||
213 | 27 | .SH EXAMPLES | ||
214 | 28 | .\" | ||
215 | 29 | .IP "start on dconf TYPE=changed KEY=/desktop/gnome/remote-access/notify-on-connect VALUE=true" | ||
216 | 30 | |||
217 | 31 | Start job when the user allows remote access to their desktop. | ||
218 | 32 | .\" | ||
219 | 33 | .SH AUTHOR | ||
220 | 34 | Written by James Hunt | ||
221 | 35 | .RB < james.hunt@canonical.com > | ||
222 | 36 | .\" | ||
223 | 37 | .SH BUGS | ||
224 | 38 | Report bugs at | ||
225 | 39 | .RB < https://launchpad.net/upstart/+bugs > | ||
226 | 40 | .\" | ||
227 | 41 | .SH COPYRIGHT | ||
228 | 42 | Copyright \(co 2013 Canonical Ltd. | ||
229 | 43 | .PP | ||
230 | 44 | This is free software; see the source for copying conditions. There is NO | ||
231 | 45 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
232 | 46 | .\" | ||
233 | 47 | .SH SEE ALSO | ||
234 | 48 | .BR dconf (7) | ||
235 | 49 | .BR gsettings (1) | ||
236 | 50 | .BR init (5) | ||
237 | 51 | .BR init (8) | ||
238 | 52 | .BR upstart\-dconf\-bridge (8) | ||
239 | 0 | 53 | ||
240 | === added file 'extra/man/upstart-dconf-bridge.8' | |||
241 | --- extra/man/upstart-dconf-bridge.8 1970-01-01 00:00:00 +0000 | |||
242 | +++ extra/man/upstart-dconf-bridge.8 2013-08-15 13:38:35 +0000 | |||
243 | @@ -0,0 +1,66 @@ | |||
244 | 1 | .TH upstart\-dconf\-bridge 8 2013-07-09 upstart | ||
245 | 2 | .\" | ||
246 | 3 | .SH NAME | ||
247 | 4 | upstart\-dconf\-bridge \- Bridge between Upstart and dconf/gsettings | ||
248 | 5 | .\" | ||
249 | 6 | .SH SYNOPSIS | ||
250 | 7 | .B upstart\-dconf\-bridge | ||
251 | 8 | .RI [ OPTIONS ]... | ||
252 | 9 | .\" | ||
253 | 10 | .SH DESCRIPTION | ||
254 | 11 | .B upstart\-dconf\-bridge | ||
255 | 12 | receives information about dconf/gsettings changes | ||
256 | 13 | and creates | ||
257 | 14 | .BR init (8) | ||
258 | 15 | events for them. | ||
259 | 16 | |||
260 | 17 | With no options (and if there are jobs which have registered an interest | ||
261 | 18 | in the event), monitors dconf changes and emits | ||
262 | 19 | an Upstart event called | ||
263 | 20 | .I dconf | ||
264 | 21 | with details of the dconf change. | ||
265 | 22 | |||
266 | 23 | See \fBdconf\fP(7) and for further details. | ||
267 | 24 | |||
268 | 25 | .\" | ||
269 | 26 | .SH OPTIONS | ||
270 | 27 | .\" | ||
271 | 28 | .TP | ||
272 | 29 | .B \-\-always | ||
273 | 30 | Always emit events on receipt of dconf changes regardless of whether jobs | ||
274 | 31 | care about them. | ||
275 | 32 | .TP | ||
276 | 33 | .B \-\-daemon | ||
277 | 34 | Detach and run in the background. | ||
278 | 35 | .\" | ||
279 | 36 | .TP | ||
280 | 37 | .B \-\-debug | ||
281 | 38 | Enable debugging output. | ||
282 | 39 | .\" | ||
283 | 40 | .TP | ||
284 | 41 | .B \-\-help | ||
285 | 42 | Show brief usage summary. | ||
286 | 43 | .\" | ||
287 | 44 | .TP | ||
288 | 45 | .B \-\-verbose | ||
289 | 46 | Enable verbose output. | ||
290 | 47 | .\" | ||
291 | 48 | .SH AUTHOR | ||
292 | 49 | Written by James Hunt | ||
293 | 50 | .RB < james.hunt@canonical.com > | ||
294 | 51 | .\" | ||
295 | 52 | .SH BUGS | ||
296 | 53 | Report bugs at | ||
297 | 54 | .RB < https://launchpad.net/ubuntu/+source/upstart/+bugs > | ||
298 | 55 | .\" | ||
299 | 56 | .SH COPYRIGHT | ||
300 | 57 | Copyright \(co 2013 Canonical Ltd. | ||
301 | 58 | .PP | ||
302 | 59 | This is free software; see the source for copying conditions. There is NO | ||
303 | 60 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
304 | 61 | .SH SEE ALSO | ||
305 | 62 | .BR dconf (7) | ||
306 | 63 | .BR dconf\-event (7) | ||
307 | 64 | .BR gsettings (1) | ||
308 | 65 | .BR init (5) | ||
309 | 66 | .BR init (8) | ||
310 | 0 | 67 | ||
311 | === added file 'extra/upstart-dconf-bridge.c' | |||
312 | --- extra/upstart-dconf-bridge.c 1970-01-01 00:00:00 +0000 | |||
313 | +++ extra/upstart-dconf-bridge.c 2013-08-15 13:38:35 +0000 | |||
314 | @@ -0,0 +1,608 @@ | |||
315 | 1 | /* upstart-dconf-bridge | ||
316 | 2 | * | ||
317 | 3 | * Copyright © 2012-2013 Canonical Ltd. | ||
318 | 4 | * Author: Stéphane Graber <stgraber@ubuntu.com>. | ||
319 | 5 | * Author: Thomas Bechtold <thomasbechtold@jpberlin.de>. | ||
320 | 6 | * Author: James Hunt <james.hunt@ubuntu.com>. | ||
321 | 7 | * | ||
322 | 8 | * This program is free software; you can redistribute it and/or modify | ||
323 | 9 | * it under the terms of the GNU General Public License version 2, as | ||
324 | 10 | * published by the Free Software Foundation. | ||
325 | 11 | * | ||
326 | 12 | * This program is distributed in the hope that it will be useful, | ||
327 | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
328 | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
329 | 15 | * GNU General Public License for more details. | ||
330 | 16 | * | ||
331 | 17 | * You should have received a copy of the GNU General Public License along | ||
332 | 18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
333 | 19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
334 | 20 | */ | ||
335 | 21 | |||
336 | 22 | #ifdef HAVE_CONFIG_H | ||
337 | 23 | # include <config.h> | ||
338 | 24 | #endif /* HAVE_CONFIG_H */ | ||
339 | 25 | |||
340 | 26 | #include <dconf.h> | ||
341 | 27 | #include <gio/gio.h> | ||
342 | 28 | |||
343 | 29 | #include <stdlib.h> | ||
344 | 30 | #include <string.h> | ||
345 | 31 | #include <syslog.h> | ||
346 | 32 | #include <ctype.h> | ||
347 | 33 | |||
348 | 34 | #include <nih/macros.h> | ||
349 | 35 | #include <nih/alloc.h> | ||
350 | 36 | #include <nih/string.h> | ||
351 | 37 | #include <nih/hash.h> | ||
352 | 38 | #include <nih/io.h> | ||
353 | 39 | #include <nih/option.h> | ||
354 | 40 | #include <nih/main.h> | ||
355 | 41 | #include <nih/logging.h> | ||
356 | 42 | #include <nih/error.h> | ||
357 | 43 | |||
358 | 44 | #include <nih-dbus/dbus_connection.h> | ||
359 | 45 | #include <nih-dbus/dbus_proxy.h> | ||
360 | 46 | |||
361 | 47 | #include "dbus/upstart.h" | ||
362 | 48 | #include "com.ubuntu.Upstart.h" | ||
363 | 49 | #include "com.ubuntu.Upstart.Job.h" | ||
364 | 50 | |||
365 | 51 | /** | ||
366 | 52 | * DCONF_EVENT: | ||
367 | 53 | * | ||
368 | 54 | * Name of event this program emits. | ||
369 | 55 | **/ | ||
370 | 56 | #define DCONF_EVENT "dconf" | ||
371 | 57 | |||
372 | 58 | /* Prototypes for static functions */ | ||
373 | 59 | static void dconf_changed (DConfClient *client, const gchar *prefix, | ||
374 | 60 | const gchar * const *changes, const gchar *tag, | ||
375 | 61 | GDBusProxy *upstart); | ||
376 | 62 | |||
377 | 63 | static void handle_upstart_job (GDBusProxy *proxy, gchar *sender_name, | ||
378 | 64 | gchar *signal_name, GVariant *parameters, | ||
379 | 65 | gpointer user_data); | ||
380 | 66 | |||
381 | 67 | static int handle_existing_jobs (GDBusProxy *upstart_proxy) | ||
382 | 68 | __attribute__ ((warn_unused_result)); | ||
383 | 69 | |||
384 | 70 | static int job_needs_event (const char *object_path) | ||
385 | 71 | __attribute__ ((warn_unused_result)); | ||
386 | 72 | |||
387 | 73 | static int jobs_need_event (void) | ||
388 | 74 | __attribute__ ((warn_unused_result)); | ||
389 | 75 | |||
390 | 76 | /** | ||
391 | 77 | * Structure we use for tracking jobs | ||
392 | 78 | * | ||
393 | 79 | * @entry: list header, | ||
394 | 80 | * @path: D-Bus path of job being tracked. | ||
395 | 81 | **/ | ||
396 | 82 | typedef struct job { | ||
397 | 83 | NihList entry; | ||
398 | 84 | char *path; | ||
399 | 85 | } Job; | ||
400 | 86 | |||
401 | 87 | /** | ||
402 | 88 | * daemonise: | ||
403 | 89 | * | ||
404 | 90 | * Set to TRUE if we should become a daemon, rather than just running | ||
405 | 91 | * in the foreground. | ||
406 | 92 | **/ | ||
407 | 93 | static int daemonise = FALSE; | ||
408 | 94 | |||
409 | 95 | /** | ||
410 | 96 | * always: | ||
411 | 97 | * | ||
412 | 98 | * If TRUE, always emit Upstart events, regardless of whether | ||
413 | 99 | * existing jobs care about DBUS_EVENT. | ||
414 | 100 | */ | ||
415 | 101 | static int always = FALSE; | ||
416 | 102 | |||
417 | 103 | /** | ||
418 | 104 | * jobs: | ||
419 | 105 | * | ||
420 | 106 | * Jobs that we're monitoring. | ||
421 | 107 | **/ | ||
422 | 108 | static NihHash *jobs = NULL; | ||
423 | 109 | |||
424 | 110 | /** | ||
425 | 111 | * connection: | ||
426 | 112 | * | ||
427 | 113 | * D-Bus connection to Upstart. | ||
428 | 114 | **/ | ||
429 | 115 | GDBusConnection *connection = NULL; | ||
430 | 116 | |||
431 | 117 | /** | ||
432 | 118 | * options: | ||
433 | 119 | * | ||
434 | 120 | * Command-line options accepted by this program. | ||
435 | 121 | **/ | ||
436 | 122 | static NihOption options[] = { | ||
437 | 123 | { 0, "always", N_("Always emit an event on a dconf change"), | ||
438 | 124 | NULL, NULL, &always, NULL }, | ||
439 | 125 | { 0, "daemon", N_("Detach and run in the background"), | ||
440 | 126 | NULL, NULL, &daemonise, NULL }, | ||
441 | 127 | NIH_OPTION_LAST | ||
442 | 128 | }; | ||
443 | 129 | |||
444 | 130 | int | ||
445 | 131 | main (int argc, | ||
446 | 132 | char *argv[]) | ||
447 | 133 | { | ||
448 | 134 | char **args; | ||
449 | 135 | DConfClient *client; | ||
450 | 136 | GMainLoop *mainloop; | ||
451 | 137 | GDBusProxy *upstart_proxy; | ||
452 | 138 | GError *error = NULL; | ||
453 | 139 | char *user_session_addr = NULL; | ||
454 | 140 | nih_local char **user_session_path = NULL; | ||
455 | 141 | char *path_element = NULL; | ||
456 | 142 | char *pidfile_path = NULL; | ||
457 | 143 | char *pidfile = NULL; | ||
458 | 144 | |||
459 | 145 | client = dconf_client_new (); | ||
460 | 146 | mainloop = g_main_loop_new (NULL, FALSE); | ||
461 | 147 | |||
462 | 148 | /* Use NIH to parse the arguments */ | ||
463 | 149 | nih_main_init (argv[0]); | ||
464 | 150 | |||
465 | 151 | nih_option_set_synopsis (_("Bridge dconf events into upstart")); | ||
466 | 152 | nih_option_set_help ( | ||
467 | 153 | _("By default, upstart-dconf-bridge does not detach from the " | ||
468 | 154 | "console and remains in the foreground. Use the --daemon " | ||
469 | 155 | "option to have it detach.")); | ||
470 | 156 | |||
471 | 157 | args = nih_option_parser (NULL, argc, argv, options, FALSE); | ||
472 | 158 | if (! args) | ||
473 | 159 | exit (1); | ||
474 | 160 | |||
475 | 161 | user_session_addr = getenv ("UPSTART_SESSION"); | ||
476 | 162 | if (! user_session_addr) { | ||
477 | 163 | nih_fatal (_("UPSTART_SESSION isn't set in environment")); | ||
478 | 164 | exit (1); | ||
479 | 165 | } | ||
480 | 166 | |||
481 | 167 | /* Connect to the Upstart session */ | ||
482 | 168 | connection = g_dbus_connection_new_for_address_sync (user_session_addr, | ||
483 | 169 | G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, | ||
484 | 170 | NULL, /* GDBusAuthObserver*/ | ||
485 | 171 | NULL, /* GCancellable */ | ||
486 | 172 | &error); | ||
487 | 173 | |||
488 | 174 | if (! connection) { | ||
489 | 175 | g_error ("D-BUS Upstart session init error: %s", | ||
490 | 176 | (error && error->message) ? error->message : "Unknown error"); | ||
491 | 177 | g_clear_error (&error); | ||
492 | 178 | exit (1); | ||
493 | 179 | } | ||
494 | 180 | |||
495 | 181 | /* Allocate jobs hash table */ | ||
496 | 182 | jobs = NIH_MUST (nih_hash_string_new (NULL, 0)); | ||
497 | 183 | |||
498 | 184 | /* Get an Upstart proxy object */ | ||
499 | 185 | upstart_proxy = g_dbus_proxy_new_sync (connection, | ||
500 | 186 | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, | ||
501 | 187 | NULL, /* GDBusInterfaceInfo */ | ||
502 | 188 | NULL, /* name */ | ||
503 | 189 | "/com/ubuntu/Upstart", | ||
504 | 190 | "com.ubuntu.Upstart0_6", | ||
505 | 191 | NULL, /* GCancellable */ | ||
506 | 192 | &error); | ||
507 | 193 | |||
508 | 194 | if (! upstart_proxy) { | ||
509 | 195 | g_error ("D-BUS Upstart proxy error: %s", | ||
510 | 196 | (error && error->message) ? error->message : "Unknown error"); | ||
511 | 197 | g_clear_error (&error); | ||
512 | 198 | exit (1); | ||
513 | 199 | } | ||
514 | 200 | |||
515 | 201 | /* Connect signal to be notified when jobs come and go */ | ||
516 | 202 | g_signal_connect (upstart_proxy, "g-signal", (GCallback) handle_upstart_job, NULL); | ||
517 | 203 | |||
518 | 204 | if (! handle_existing_jobs (upstart_proxy)) | ||
519 | 205 | exit (1); | ||
520 | 206 | |||
521 | 207 | if (daemonise) { | ||
522 | 208 | /* Deal with the pidfile location when becoming a daemon. | ||
523 | 209 | * We need to be able to run one bridge per upstart daemon. | ||
524 | 210 | * Store the PID file in XDG_RUNTIME_DIR or HOME and include the pid of | ||
525 | 211 | * the Upstart instance (last part of the DBus path) in the filename. | ||
526 | 212 | */ | ||
527 | 213 | |||
528 | 214 | /* Extract PID from UPSTART_SESSION */ | ||
529 | 215 | user_session_path = nih_str_split (NULL, user_session_addr, "/", TRUE); | ||
530 | 216 | |||
531 | 217 | for (int i = 0; user_session_path && user_session_path[i]; i++) | ||
532 | 218 | path_element = user_session_path[i]; | ||
533 | 219 | |||
534 | 220 | if (! path_element) { | ||
535 | 221 | nih_fatal (_("Invalid value for UPSTART_SESSION")); | ||
536 | 222 | exit (1); | ||
537 | 223 | } | ||
538 | 224 | |||
539 | 225 | pidfile_path = getenv ("XDG_RUNTIME_DIR"); | ||
540 | 226 | if (!pidfile_path) | ||
541 | 227 | pidfile_path = getenv ("HOME"); | ||
542 | 228 | |||
543 | 229 | if (pidfile_path) { | ||
544 | 230 | NIH_MUST (nih_strcat_sprintf (&pidfile, NULL, | ||
545 | 231 | "%s/upstart-dconf-bridge.%s.pid", | ||
546 | 232 | pidfile_path, path_element)); | ||
547 | 233 | nih_main_set_pidfile (pidfile); | ||
548 | 234 | } | ||
549 | 235 | |||
550 | 236 | if (nih_main_daemonise () < 0) { | ||
551 | 237 | NihError *err; | ||
552 | 238 | |||
553 | 239 | err = nih_error_get (); | ||
554 | 240 | nih_fatal ("%s: %s", _("Unable to become daemon"), | ||
555 | 241 | err->message); | ||
556 | 242 | nih_free (err); | ||
557 | 243 | |||
558 | 244 | exit (1); | ||
559 | 245 | } | ||
560 | 246 | } | ||
561 | 247 | |||
562 | 248 | /* Handle TERM and INT signals gracefully */ | ||
563 | 249 | nih_signal_set_handler (SIGTERM, nih_signal_handler); | ||
564 | 250 | NIH_MUST (nih_signal_add_handler (NULL, SIGTERM, nih_main_term_signal, NULL)); | ||
565 | 251 | |||
566 | 252 | /* Listen for any dconf change */ | ||
567 | 253 | g_signal_connect (client, "changed", (GCallback) dconf_changed, upstart_proxy); | ||
568 | 254 | dconf_client_watch_sync (client, "/"); | ||
569 | 255 | |||
570 | 256 | /* Start the glib mainloop */ | ||
571 | 257 | g_main_loop_run (mainloop); | ||
572 | 258 | |||
573 | 259 | g_object_unref (client); | ||
574 | 260 | g_object_unref (upstart_proxy); | ||
575 | 261 | g_object_unref (connection); | ||
576 | 262 | g_main_loop_unref (mainloop); | ||
577 | 263 | |||
578 | 264 | exit (0); | ||
579 | 265 | } | ||
580 | 266 | |||
581 | 267 | /** | ||
582 | 268 | * handle_upstart_job: | ||
583 | 269 | * | ||
584 | 270 | * Called when an Upstart D-Bus signal is emitted. | ||
585 | 271 | **/ | ||
586 | 272 | static void | ||
587 | 273 | handle_upstart_job (GDBusProxy *proxy, | ||
588 | 274 | gchar *sender_name, | ||
589 | 275 | gchar *signal_name, | ||
590 | 276 | GVariant *parameters, | ||
591 | 277 | gpointer user_data) | ||
592 | 278 | { | ||
593 | 279 | GVariantIter iter; | ||
594 | 280 | GVariant *child; | ||
595 | 281 | const gchar *job_class_path; | ||
596 | 282 | Job *job; | ||
597 | 283 | int add; | ||
598 | 284 | |||
599 | 285 | nih_assert (signal_name); | ||
600 | 286 | nih_assert (parameters); | ||
601 | 287 | nih_assert (jobs); | ||
602 | 288 | |||
603 | 289 | if (! strcmp (signal_name, "JobAdded")) { | ||
604 | 290 | add = 1; | ||
605 | 291 | } else if (! strcmp (signal_name, "JobRemoved")) { | ||
606 | 292 | add = 0; | ||
607 | 293 | } else { | ||
608 | 294 | return; | ||
609 | 295 | } | ||
610 | 296 | |||
611 | 297 | nih_assert (g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE)); | ||
612 | 298 | |||
613 | 299 | g_variant_iter_init (&iter, parameters); | ||
614 | 300 | |||
615 | 301 | nih_assert (g_variant_iter_n_children (&iter) == 1); | ||
616 | 302 | |||
617 | 303 | child = g_variant_iter_next_value (&iter); | ||
618 | 304 | |||
619 | 305 | job_class_path = g_variant_get_string (child, NULL); | ||
620 | 306 | nih_assert (g_variant_is_object_path (job_class_path)); | ||
621 | 307 | |||
622 | 308 | /* Free any existing record for the job if we are adding | ||
623 | 309 | * (should never happen, but worth being safe). | ||
624 | 310 | */ | ||
625 | 311 | job = (Job *)nih_hash_lookup (jobs, job_class_path); | ||
626 | 312 | if (job) | ||
627 | 313 | nih_free (job); | ||
628 | 314 | |||
629 | 315 | /* Job isn't interested in DCONF_EVENT */ | ||
630 | 316 | if (add && ! job_needs_event (job_class_path)) | ||
631 | 317 | goto out; | ||
632 | 318 | |||
633 | 319 | if (add) | ||
634 | 320 | nih_debug ("Job got added %s for event %s", job_class_path, DCONF_EVENT); | ||
635 | 321 | else | ||
636 | 322 | nih_debug ("Job went away %s", job_class_path); | ||
637 | 323 | |||
638 | 324 | /* We're removing, so job done */ | ||
639 | 325 | if (! add) | ||
640 | 326 | goto out; | ||
641 | 327 | |||
642 | 328 | /* Create new record for the job */ | ||
643 | 329 | job = NIH_MUST (nih_new (NULL, Job)); | ||
644 | 330 | job->path = NIH_MUST (nih_strdup (job, job_class_path)); | ||
645 | 331 | |||
646 | 332 | nih_list_init (&job->entry); | ||
647 | 333 | nih_alloc_set_destructor (job, nih_list_destroy); | ||
648 | 334 | nih_hash_add (jobs, &job->entry); | ||
649 | 335 | |||
650 | 336 | out: | ||
651 | 337 | g_variant_unref (child); | ||
652 | 338 | } | ||
653 | 339 | |||
654 | 340 | /** | ||
655 | 341 | * dconf_changed: | ||
656 | 342 | * | ||
657 | 343 | * Emit an Upstart event corresponding to a dconf key change. | ||
658 | 344 | **/ | ||
659 | 345 | static void | ||
660 | 346 | dconf_changed (DConfClient *client, | ||
661 | 347 | const gchar *prefix, | ||
662 | 348 | const gchar * const *changes, | ||
663 | 349 | const gchar *tag, | ||
664 | 350 | GDBusProxy *upstart) | ||
665 | 351 | { | ||
666 | 352 | GVariant *value; | ||
667 | 353 | gchar *value_str = NULL; | ||
668 | 354 | gchar *path = NULL; | ||
669 | 355 | gchar *env_key = NULL; | ||
670 | 356 | gchar *env_value = NULL; | ||
671 | 357 | GVariant *event; | ||
672 | 358 | GVariantBuilder builder; | ||
673 | 359 | int i = 0; | ||
674 | 360 | |||
675 | 361 | /* dconf currently only currently supports the changed signal, | ||
676 | 362 | * but parameterise to allow for a future API change. | ||
677 | 363 | */ | ||
678 | 364 | const gchar *event_type = "TYPE=changed"; | ||
679 | 365 | |||
680 | 366 | if (! jobs_need_event () && ! always) | ||
681 | 367 | return; | ||
682 | 368 | |||
683 | 369 | /* Iterate through the various changes */ | ||
684 | 370 | while (changes[i] != NULL) { | ||
685 | 371 | path = g_strconcat (prefix, changes[i], NULL); | ||
686 | 372 | |||
687 | 373 | value = dconf_client_read (client, path); | ||
688 | 374 | value_str = g_variant_print (value, FALSE); | ||
689 | 375 | |||
690 | 376 | env_key = g_strconcat ("KEY=", path, NULL); | ||
691 | 377 | env_value = g_strconcat ("VALUE=", value_str, NULL); | ||
692 | 378 | |||
693 | 379 | /* Build event environment as GVariant */ | ||
694 | 380 | g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE); | ||
695 | 381 | |||
696 | 382 | g_variant_builder_add (&builder, "s", DCONF_EVENT); | ||
697 | 383 | |||
698 | 384 | g_variant_builder_open (&builder, G_VARIANT_TYPE_ARRAY); | ||
699 | 385 | g_variant_builder_add (&builder, "s", event_type); | ||
700 | 386 | g_variant_builder_add (&builder, "s", env_key); | ||
701 | 387 | g_variant_builder_add (&builder, "s", env_value); | ||
702 | 388 | g_variant_builder_close (&builder); | ||
703 | 389 | |||
704 | 390 | g_variant_builder_add (&builder, "b", FALSE); | ||
705 | 391 | event = g_variant_builder_end (&builder); | ||
706 | 392 | |||
707 | 393 | /* Send the event */ | ||
708 | 394 | g_dbus_proxy_call (upstart, | ||
709 | 395 | "EmitEvent", | ||
710 | 396 | event, | ||
711 | 397 | G_DBUS_CALL_FLAGS_NONE, | ||
712 | 398 | -1, | ||
713 | 399 | NULL, | ||
714 | 400 | NULL, /* GAsyncReadyCallback | ||
715 | 401 | we don't care about the answer */ | ||
716 | 402 | NULL); | ||
717 | 403 | |||
718 | 404 | g_variant_builder_clear (&builder); | ||
719 | 405 | g_variant_unref (value); | ||
720 | 406 | g_free (path); | ||
721 | 407 | g_free (value_str); | ||
722 | 408 | g_free (env_key); | ||
723 | 409 | g_free (env_value); | ||
724 | 410 | |||
725 | 411 | i += 1; | ||
726 | 412 | } | ||
727 | 413 | } | ||
728 | 414 | |||
729 | 415 | /** | ||
730 | 416 | * jobs_need_event: | ||
731 | 417 | * | ||
732 | 418 | * Returns: TRUE if any jobs need DCONF_EVENT, else FALSE. | ||
733 | 419 | **/ | ||
734 | 420 | static int | ||
735 | 421 | jobs_need_event (void) | ||
736 | 422 | { | ||
737 | 423 | NIH_HASH_FOREACH (jobs, iter) { | ||
738 | 424 | return TRUE; | ||
739 | 425 | } | ||
740 | 426 | |||
741 | 427 | return FALSE; | ||
742 | 428 | } | ||
743 | 429 | |||
744 | 430 | /** | ||
745 | 431 | * job_needs_event: | ||
746 | 432 | * @object_path: Full D-Bus object path for job. | ||
747 | 433 | * | ||
748 | 434 | * Returns: TRUE if job specified by @object_path specifies DCONF_EVENT | ||
749 | 435 | * in its 'start on' or 'stop on' stanza, else FALSE. | ||
750 | 436 | **/ | ||
751 | 437 | static int | ||
752 | 438 | job_needs_event (const char *class_path) | ||
753 | 439 | { | ||
754 | 440 | GDBusProxy *job_proxy; | ||
755 | 441 | GError *error = NULL; | ||
756 | 442 | GVariantIter iter; | ||
757 | 443 | const gchar *event_name; | ||
758 | 444 | int ret = FALSE; | ||
759 | 445 | |||
760 | 446 | /* Arrays of arrays of strings (aas) */ | ||
761 | 447 | GVariant *start_on = NULL; | ||
762 | 448 | GVariant *stop_on = NULL; | ||
763 | 449 | |||
764 | 450 | /* Array containing event name and optional environment | ||
765 | 451 | * variable elements. | ||
766 | 452 | */ | ||
767 | 453 | GVariant *event_element; | ||
768 | 454 | |||
769 | 455 | /* Either an event name or "/AND" or "/OR" */ | ||
770 | 456 | GVariant *event; | ||
771 | 457 | |||
772 | 458 | nih_assert (class_path); | ||
773 | 459 | |||
774 | 460 | job_proxy = g_dbus_proxy_new_sync (connection, | ||
775 | 461 | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, | ||
776 | 462 | NULL, /* GDBusInterfaceInfo */ | ||
777 | 463 | NULL, /* name */ | ||
778 | 464 | class_path, | ||
779 | 465 | "com.ubuntu.Upstart0_6.Job", | ||
780 | 466 | NULL, /* GCancellable */ | ||
781 | 467 | &error); | ||
782 | 468 | |||
783 | 469 | start_on = g_dbus_proxy_get_cached_property (job_proxy, "start_on"); | ||
784 | 470 | nih_assert (g_variant_is_of_type (start_on, G_VARIANT_TYPE_ARRAY)); | ||
785 | 471 | |||
786 | 472 | g_variant_iter_init (&iter, start_on); | ||
787 | 473 | |||
788 | 474 | while ((event_element = g_variant_iter_next_value (&iter))) { | ||
789 | 475 | nih_assert (g_variant_is_of_type (event_element, G_VARIANT_TYPE_ARRAY)); | ||
790 | 476 | |||
791 | 477 | /* First element is always the event name */ | ||
792 | 478 | event = g_variant_get_child_value (event_element, 0); | ||
793 | 479 | nih_assert (g_variant_is_of_type (event, G_VARIANT_TYPE_STRING)); | ||
794 | 480 | |||
795 | 481 | event_name = g_variant_get_string (event, NULL); | ||
796 | 482 | |||
797 | 483 | if (! strcmp (event_name, DCONF_EVENT)) | ||
798 | 484 | ret = TRUE; | ||
799 | 485 | |||
800 | 486 | g_variant_unref (event_element); | ||
801 | 487 | g_variant_unref (event); | ||
802 | 488 | |||
803 | 489 | if (ret) | ||
804 | 490 | goto out; | ||
805 | 491 | } | ||
806 | 492 | |||
807 | 493 | /* Now handle stop on */ | ||
808 | 494 | stop_on = g_dbus_proxy_get_cached_property (job_proxy, "stop_on"); | ||
809 | 495 | nih_assert (g_variant_is_of_type (stop_on, G_VARIANT_TYPE_ARRAY)); | ||
810 | 496 | |||
811 | 497 | g_variant_iter_init (&iter, stop_on); | ||
812 | 498 | |||
813 | 499 | while ((event_element = g_variant_iter_next_value (&iter))) { | ||
814 | 500 | nih_assert (g_variant_is_of_type (event_element, G_VARIANT_TYPE_ARRAY)); | ||
815 | 501 | |||
816 | 502 | /* First element is always the event name */ | ||
817 | 503 | event = g_variant_get_child_value (event_element, 0); | ||
818 | 504 | nih_assert (g_variant_is_of_type (event, G_VARIANT_TYPE_STRING)); | ||
819 | 505 | |||
820 | 506 | event_name = g_variant_get_string (event, NULL); | ||
821 | 507 | |||
822 | 508 | if (! strcmp (event_name, DCONF_EVENT)) | ||
823 | 509 | ret = TRUE; | ||
824 | 510 | |||
825 | 511 | g_variant_unref (event_element); | ||
826 | 512 | g_variant_unref (event); | ||
827 | 513 | |||
828 | 514 | if (ret) | ||
829 | 515 | goto out; | ||
830 | 516 | } | ||
831 | 517 | |||
832 | 518 | out: | ||
833 | 519 | if (start_on) | ||
834 | 520 | g_variant_unref (start_on); | ||
835 | 521 | |||
836 | 522 | if (stop_on) | ||
837 | 523 | g_variant_unref (stop_on); | ||
838 | 524 | |||
839 | 525 | g_object_unref (job_proxy); | ||
840 | 526 | |||
841 | 527 | return ret; | ||
842 | 528 | } | ||
843 | 529 | |||
844 | 530 | /** | ||
845 | 531 | * handle_existing_jobs: | ||
846 | 532 | * | ||
847 | 533 | * @upstart_proxy: Upstart proxy. | ||
848 | 534 | * | ||
849 | 535 | * Add all existing jobs which specify DCONF_EVENT to the list | ||
850 | 536 | * of tracked jobs. | ||
851 | 537 | * | ||
852 | 538 | * Returns: TRUE or FALSE on error. | ||
853 | 539 | **/ | ||
854 | 540 | static int | ||
855 | 541 | handle_existing_jobs (GDBusProxy *upstart_proxy) | ||
856 | 542 | { | ||
857 | 543 | GVariant *result; | ||
858 | 544 | GVariant *child; | ||
859 | 545 | GVariant *proxy_job; | ||
860 | 546 | const gchar *job_class_path; | ||
861 | 547 | GError *error = NULL; | ||
862 | 548 | GVariantIter iter; | ||
863 | 549 | Job *job; | ||
864 | 550 | |||
865 | 551 | nih_assert (upstart_proxy); | ||
866 | 552 | |||
867 | 553 | result = g_dbus_proxy_call_sync (upstart_proxy, | ||
868 | 554 | "GetAllJobs", | ||
869 | 555 | NULL, | ||
870 | 556 | G_DBUS_CALL_FLAGS_NO_AUTO_START, | ||
871 | 557 | -1, | ||
872 | 558 | NULL, | ||
873 | 559 | &error); | ||
874 | 560 | |||
875 | 561 | if (! result) { | ||
876 | 562 | g_error ("D-BUS Upstart proxy error: %s", | ||
877 | 563 | (error && error->message) | ||
878 | 564 | ? error->message | ||
879 | 565 | : "Unknown error"); | ||
880 | 566 | g_clear_error (&error); | ||
881 | 567 | return FALSE; | ||
882 | 568 | } | ||
883 | 569 | |||
884 | 570 | nih_assert (g_variant_is_of_type (result, G_VARIANT_TYPE_TUPLE)); | ||
885 | 571 | nih_assert (g_variant_n_children (result) == 1); | ||
886 | 572 | |||
887 | 573 | child = g_variant_get_child_value (result, 0); | ||
888 | 574 | |||
889 | 575 | nih_assert (g_variant_is_of_type (child, G_VARIANT_TYPE_OBJECT_PATH_ARRAY)); | ||
890 | 576 | |||
891 | 577 | g_variant_iter_init (&iter, child); | ||
892 | 578 | |||
893 | 579 | while ((proxy_job = g_variant_iter_next_value (&iter))) { | ||
894 | 580 | job_class_path = g_variant_get_string (proxy_job, NULL); | ||
895 | 581 | |||
896 | 582 | /* Free any existing record for the job if we are adding | ||
897 | 583 | * (should never happen, but worth being safe). | ||
898 | 584 | */ | ||
899 | 585 | job = (Job *)nih_hash_lookup (jobs, job_class_path); | ||
900 | 586 | if (job) | ||
901 | 587 | nih_free (job); | ||
902 | 588 | |||
903 | 589 | if (job_needs_event (job_class_path)) { | ||
904 | 590 | /* Create new record for the job */ | ||
905 | 591 | job = NIH_MUST (nih_new (NULL, Job)); | ||
906 | 592 | job->path = NIH_MUST (nih_strdup (job, job_class_path)); | ||
907 | 593 | |||
908 | 594 | nih_list_init (&job->entry); | ||
909 | 595 | nih_alloc_set_destructor (job, nih_list_destroy); | ||
910 | 596 | nih_hash_add (jobs, &job->entry); | ||
911 | 597 | |||
912 | 598 | nih_debug ("Job added %s for event %s", job_class_path, DCONF_EVENT); | ||
913 | 599 | } | ||
914 | 600 | |||
915 | 601 | g_variant_unref (proxy_job); | ||
916 | 602 | } | ||
917 | 603 | |||
918 | 604 | g_variant_unref (child); | ||
919 | 605 | g_variant_unref (result); | ||
920 | 606 | |||
921 | 607 | return TRUE; | ||
922 | 608 | } |