Merge lp:~upstart-devel/upstart/0.9 into lp:upstart

Proposed by James Hunt
Status: Rejected
Rejected by: Steve Langasek
Proposed branch: lp:~upstart-devel/upstart/0.9
Merge into: lp:upstart
Diff against target: 17059 lines (+10051/-881) (has conflicts)
67 files modified
.bzrignore (+4/-0)
ChangeLog (+453/-0)
Makefile.am (+1/-1)
NEWS (+101/-0)
conf/rc-sysinit.conf (+2/-0)
configure.ac (+11/-2)
contrib/bash_completion/upstart (+34/-10)
dbus/Upstart.conf (+6/-36)
dbus/com.ubuntu.Upstart.xml (+7/-0)
dbus/upstart.h (+1/-1)
extra/Makefile.am (+126/-0)
extra/conf/upstart-socket-bridge.conf (+16/-0)
extra/conf/upstart-udev-bridge.conf (+16/-0)
extra/man/socket-event.7 (+92/-0)
extra/man/upstart-socket-bridge.8 (+47/-0)
extra/man/upstart-udev-bridge.8 (+57/-0)
extra/upstart-socket-bridge.c (+644/-0)
extra/upstart-udev-bridge.c (+310/-0)
init/Makefile.am (+25/-0)
init/conf.c (+510/-53)
init/conf.h (+45/-2)
init/control.c (+111/-19)
init/control.h (+18/-0)
init/event.c (+22/-1)
init/event.h (+6/-1)
init/event_operator.c (+59/-0)
init/event_operator.h (+8/-0)
init/job.c (+46/-2)
init/job.h (+4/-1)
init/job_class.c (+113/-23)
init/job_class.h (+5/-1)
init/job_process.c (+59/-0)
init/job_process.h (+3/-1)
init/main.c (+244/-46)
init/man/init.5 (+225/-51)
init/man/init.8 (+34/-5)
init/parse_conf.c (+6/-0)
init/parse_job.c (+20/-6)
init/parse_job.h (+4/-2)
init/paths.h (+90/-6)
init/session.c (+279/-0)
init/session.h (+87/-0)
init/tests/test_blocked.c (+4/-1)
init/tests/test_conf.c (+1310/-15)
init/tests/test_control.c (+15/-10)
init/tests/test_environ.c (+3/-0)
init/tests/test_event.c (+28/-25)
init/tests/test_event_operator.c (+3/-0)
init/tests/test_job.c (+71/-76)
init/tests/test_job_class.c (+56/-64)
init/tests/test_job_process.c (+34/-29)
init/tests/test_parse_conf.c (+3/-0)
init/tests/test_parse_job.c (+285/-243)
init/tests/test_process.c (+3/-0)
init/tests/test_system.c (+3/-0)
po/POTFILES.in (+2/-0)
po/upstart.pot (+399/-73)
scripts/Makefile.am (+25/-0)
scripts/init-checkconf.sh (+248/-0)
scripts/initctl2dot.py (+571/-0)
scripts/man/init-checkconf.8 (+73/-0)
scripts/man/initctl2dot.8 (+87/-0)
util/Makefile.am (+1/-1)
util/initctl.c (+1030/-19)
util/initctl.h (+458/-0)
util/man/initctl.8 (+204/-35)
util/tests/test_initctl.c (+1184/-20)
Text conflict in ChangeLog
Text conflict in NEWS
Text conflict in configure.ac
Text conflict in init/conf.c
Text conflict in init/main.c
Text conflict in po/upstart.pot
To merge this branch: bzr merge lp:~upstart-devel/upstart/0.9
Reviewer Review Type Date Requested Status
Scott James Remnant (community) Needs Fixing
Review via email: mp+57694@code.launchpad.net

Description of the change

Hi Scott,

Now that the code is stabilising, here forthwith is the "0.9" branch containing the 4 branches we developed for natty...

1) lp:~canonical-scott/upstart/bridges
2) lp:~canonical-scott/upstart/session-support
3) lp:~jamesodhunt/upstart/override-support
4) lp:~jamesodhunt/upstart/upstart-job-visualisation

... with associated fixes to those branches.

Cheers,

James.

To post a comment you must log in.
Revision history for this message
Scott James Remnant (scott) wrote :

Please resubmit as individual merges for each change/set of changes

review: Needs Fixing
Revision history for this message
Scott James Remnant (scott) wrote :
Download full text (6.4 KiB)

Hi James, thanks for getting started on submitting this.

Unfortunately this is a massive merge with a large number of distinct
changes. These need to be submitted individually and separately. What's
more, I suspect that you don't mean to submit some of these changes as they
are Ubuntu-specific. I did a quick pass through the merge output and noted
at least:

 - changes to bash completion
 - indentation fixes (dbus/upstart.h)
 - massive manpage updates
 - supports d-bus session bus connection rather than system
 - disabling/changing of startup of event
 - alternative config dir
 - init-checkconf
 - initctl2dot

 - addition of socket bridge
 - addition of events-with-fds to upstart
 - addition of udev bridge
 - chroot session support
 - user session support
 - override file support

 - addition of "emits" tags to config files

There are also basic problems with this merge:

Text conflict in ChangeLog
Text conflict in NEWS
Text conflict in configure.ac
Text conflict in init/conf.c
Text conflict in init/main.c
Text conflict in po/upstart.pot

The individual submission branches should be cleaned up against trunk first

Scott

On Thu, Apr 14, 2011 at 7:47 AM, James Hunt <email address hidden>wrote:

> James Hunt has proposed merging lp:~upstart-devel/upstart/0.9 into
> lp:upstart.
>
> Requested reviews:
> Upstart Developers (upstart-devel)
>
> For more details, see:
> https://code.launchpad.net/~upstart-devel/upstart/0.9/+merge/57694
>
> Hi Scott,
>
> Now that the code is stabilising, here forthwith is the "0.9" branch
> containing the 4 branches we developed for natty...
>
> 1) lp:~canonical-scott/upstart/bridges
> 2) lp:~canonical-scott/upstart/session-support
> 3) lp:~jamesodhunt/upstart/override-support
> 4) lp:~jamesodhunt/upstart/upstart-job-visualisation
>
> ... with associated fixes to those branches.
>
> Cheers,
>
> James.
> --
> https://code.launchpad.net/~upstart-devel/upstart/0.9/+merge/57694
> Your team Upstart Developers is requested to review the proposed merge of
> lp:~upstart-devel/upstart/0.9 into lp:upstart.
>
> === modified file '.bzrignore'
> --- .bzrignore 2010-12-10 04:03:25 +0000
> +++ .bzrignore 2011-04-14 14:47:25 +0000
> @@ -59,3 +59,7 @@
> util/shutdown
> util/telinit
> util/test_*
> +extra/com.ubuntu.Upstart.[ch]
> +extra/com.ubuntu.Upstart.Job.[ch]
> +extra/upstart-socket-bridge
> +extra/upstart-udev-bridge
>
> === modified file 'ChangeLog'
> --- ChangeLog 2011-03-22 17:53:17 +0000
> +++ ChangeLog 2011-04-14 14:47:25 +0000
> @@ -1,3 +1,4 @@
> +<<<<<<< TREE
> 2011-03-22 Scott James Remnant <email address hidden>
>
> * configure.ac: Bump version to 1.3
> @@ -84,6 +85,414 @@
> the character before the ".conf" extension is not "/"
> * NEWS: Update.
>
> +=======
> +2011-04-06 James Hunt <email address hidden>
> +
> + * init/conf.c: conf_select_job(): Added Session parameter.
> + * init/control.c: control_get_job_by_name(): Handle multiple jobs
> with same
> + name (but different session) in job_classes hash.
> + * init/job_class.c:
> + - job_class_remove(): Added Session parameter.
> + - job_class_consider(): Handle multiple jobs with same nam...

Read more...

lp:~upstart-devel/upstart/0.9 updated
1286. By James Hunt

* init/conf.c:
  - conf_source_reload_file(): Added missing error return if override
    doesn't parse (code path currently unused).
  - Documentation updates.
* init/job.c: job_new(): Fix for nasty OOM scenario when an attempt is made
  to start a chroot job with same name as running single-instance non-chroot
  job. Previously, the path for a chrooted Job was set from the (nul) instance
  name of its parent JobClass. However, since that job instance name already
  existed outside the chroot and was already D-Bus registered,
  nih_dbus_object_new() (which allocates storage and is called by
  job_register()) returned NULL and kept doing so due to being called
  within NIH_MUST(). This resulted in OOM due to an as-yet unidentified
  D-Bus bug (possibly a leak in find_subtree_recurse()).
* init/session.h: Documentation updates.
* util/test_initctl.c: Cleaned up variable names
  in RUN_COMMAND macro.
* init/parse_job.c: Documentation updates.

1287. By James Hunt

* Bumped version to 0.9.6
* Updated Changelog and NEWS.

1288. By James Hunt

* control_get_job_by_name: Fix to relax session rigidity for user
  sessions (allow user sessions to see into the global
  namespace for backwards compatability) (LP: #767053).

1289. By James Hunt

* Bumped version to 0.9.7
* Updated Changelog and NEWS.

1290. By James Hunt

* scripts/init-checkconf.sh:
  - New function upstart_running.
  - We now check to ensure no other instance running.
  - Use list command rather than status since the latter requires an
    instance variable to be specified (LP: #770532).
  - Improve cleanup safety.
* scripts/man/init-checkconf.8: Added limitations section.

1291. By James Hunt

Updated changelog.

Unmerged revisions

1291. By James Hunt

Updated changelog.

1290. By James Hunt

* scripts/init-checkconf.sh:
  - New function upstart_running.
  - We now check to ensure no other instance running.
  - Use list command rather than status since the latter requires an
    instance variable to be specified (LP: #770532).
  - Improve cleanup safety.
* scripts/man/init-checkconf.8: Added limitations section.

1289. By James Hunt

* Bumped version to 0.9.7
* Updated Changelog and NEWS.

1288. By James Hunt

* control_get_job_by_name: Fix to relax session rigidity for user
  sessions (allow user sessions to see into the global
  namespace for backwards compatability) (LP: #767053).

1287. By James Hunt

* Bumped version to 0.9.6
* Updated Changelog and NEWS.

1286. By James Hunt

* init/conf.c:
  - conf_source_reload_file(): Added missing error return if override
    doesn't parse (code path currently unused).
  - Documentation updates.
* init/job.c: job_new(): Fix for nasty OOM scenario when an attempt is made
  to start a chroot job with same name as running single-instance non-chroot
  job. Previously, the path for a chrooted Job was set from the (nul) instance
  name of its parent JobClass. However, since that job instance name already
  existed outside the chroot and was already D-Bus registered,
  nih_dbus_object_new() (which allocates storage and is called by
  job_register()) returned NULL and kept doing so due to being called
  within NIH_MUST(). This resulted in OOM due to an as-yet unidentified
  D-Bus bug (possibly a leak in find_subtree_recurse()).
* init/session.h: Documentation updates.
* util/test_initctl.c: Cleaned up variable names
  in RUN_COMMAND macro.
* init/parse_job.c: Documentation updates.

1285. By James Hunt

* Bumped version to 0.9.5
* Updated Changelog and NEWS.

1284. By James Hunt

* init/conf.c: conf_select_job(): Added Session parameter.
* init/control.c: control_get_job_by_name(): Handle multiple jobs with same
  name (but different session) in job_classes hash.
* init/job_class.c:
  - job_class_remove(): Added Session parameter.
  - job_class_consider(): Handle multiple jobs with same name
    (but different session) in job_classes hash.
  - job_class_reconsider(): Handle multiple jobs with same name
    (but different session) in job_classes hash.
  - job_class_remove(): Handle incorrect session.
* init/job_process.c: job_process_spawn(): Updated for sessions and
  chroots.
* init/job_process.h: New enums for:
  - JOB_PROCESS_ERROR_SETUID
  - JOB_PROCESS_ERROR_SETGID
* init/session.c:
  - session_from_dbus(): Added ability to disable sessions.
  - Added disable_sessions variable, set via main().
* init/session.h: Added tabular comment summarising Session object
  contents for different environments.
* init/Makefile.am: Reverted special-casing for session.c.
* init/main.c: Addition of new command-line option "--no-sessions" to
  disable chroot+user sessions (providing a "traditional" Upstart
  environment. The primary use for this option is the test suite.
* init/man/init.8: Updates for "--no-sessions".
* init/tests/test_*.c: Replaced explicit Sessions with NULL
  session since tests are not yet session-aware (with the exception of
  test_job_process.c, all main() functions now set the
  UPSTART_NO_SESSIONS variable to disable sessions).
* util/tests/test_initctl.c:
  - START_UPSTART now specifies "--no-sessions"
  - test_check_config(): Added test for "--warn".
* scripts/init-checkconf.sh: Script now also checks any script
  sections found unless the new "--noscript" option is specified.
  Added required "--no-sessions" option to upstart_cmd to ensure Upstart
  treats clients requests in traditional manner.
* scripts/man/init-checkconf.8: Update for "--noscript".
* util/initctl.c: Added "--warn" option for check-config command to
  warn if any events or jobs are not known.

1283. By James Hunt

* init/tests/test_control.c: Added comment.
* scripts/initctl2dot.py: Fixes to handle 'emits' glob syntax:
  - header(): Change default node to be an event to simplify handling
    globs in 'emits' stanzas.
  - footer(): Updated for glob event nodes.
  - sanitize(): Protect against glob syntax.
  - show_event(): Update for glob event nodes.
  - show_job(): Explicit specification of record node.
  - show_edges(): Handle 'emits' glob syntax.

1282. By James Hunt

* po/upstart.pot: committed changes to file to resolve conflict on
  lp:ubuntu/upstart merge.

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-04-27 14:11:41 +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 'ChangeLog'
--- ChangeLog 2011-03-22 17:53:17 +0000
+++ ChangeLog 2011-04-27 14:11:41 +0000
@@ -1,3 +1,4 @@
1<<<<<<< TREE
12011-03-22 Scott James Remnant <scott@netsplit.com>22011-03-22 Scott James Remnant <scott@netsplit.com>
23
3 * configure.ac: Bump version to 1.34 * configure.ac: Bump version to 1.3
@@ -84,6 +85,450 @@
84 the character before the ".conf" extension is not "/"85 the character before the ".conf" extension is not "/"
85 * NEWS: Update.86 * NEWS: Update.
8687
88=======
892011-04-27 James Hunt <james.hunt@ubuntu.com>
90
91 * scripts/init-checkconf.sh:
92 - New function upstart_running.
93 - We now check to ensure no other instance running.
94 - Use list command rather than status since the latter requires an
95 instance variable to be specified (LP: #770532).
96 - Improve cleanup safety.
97 * scripts/man/init-checkconf.8: Added limitations section.
98
992011-04-20 James Hunt <james.hunt@ubuntu.com>
100
101 * control_get_job_by_name: Fix to relax session rigidity for user
102 sessions (allow user sessions to see into the global
103 namespace for backwards compatability) (LP: #767053).
104
1052011-04-15 James Hunt <james.hunt@ubuntu.com>
106
107 * init/conf.c:
108 - conf_source_reload_file(): Added missing error return if override
109 doesn't parse (code path currently unused).
110 - Documentation updates.
111 * init/job.c: job_new(): Fix for nasty OOM scenario when an attempt is made
112 to start a chroot job with same name as running single-instance non-chroot
113 job. Previously, the path for a chrooted Job was set from the (nul) instance
114 name of its parent JobClass. However, since that job instance name already
115 existed outside the chroot and was already D-Bus registered,
116 nih_dbus_object_new() (which allocates storage and is called by
117 job_register()) returned NULL and kept doing so due to being called
118 within NIH_MUST(). This resulted in OOM due to an as-yet unidentified
119 D-Bus bug (possibly a leak in find_subtree_recurse()).
120 * init/session.h: Documentation updates.
121 * util/test_initctl.c: Cleaned up variable names
122 in RUN_COMMAND macro.
123 * init/parse_job.c: Documentation updates.
124
1252011-04-06 James Hunt <james.hunt@ubuntu.com>
126
127 * init/conf.c: conf_select_job(): Added Session parameter.
128 * init/control.c: control_get_job_by_name(): Handle multiple jobs with same
129 name (but different session) in job_classes hash.
130 * init/job_class.c:
131 - job_class_remove(): Added Session parameter.
132 - job_class_consider(): Handle multiple jobs with same name
133 (but different session) in job_classes hash.
134 - job_class_reconsider(): Handle multiple jobs with same name
135 (but different session) in job_classes hash.
136 - job_class_remove(): Handle incorrect session.
137 * init/job_process.c: job_process_spawn(): Updated for sessions and
138 chroots.
139 * init/job_process.h: New enums for:
140 - JOB_PROCESS_ERROR_SETUID
141 - JOB_PROCESS_ERROR_SETGID
142 * init/session.c:
143 - session_from_dbus(): Added ability to disable sessions.
144 - Added disable_sessions variable, set via main().
145 * init/session.h: Added tabular comment summarising Session object
146 contents for different environments.
147 * init/Makefile.am: Reverted special-casing for session.c.
148 * init/main.c: Addition of new command-line option "--no-sessions" to
149 disable chroot+user sessions (providing a "traditional" Upstart
150 environment. The primary use for this option is the test suite.
151 * init/man/init.8: Updates for "--no-sessions".
152 * init/tests/test_*.c: Replaced explicit Sessions with NULL
153 session since tests are not yet session-aware (with the exception of
154 test_job_process.c, all main() functions now set the
155 UPSTART_NO_SESSIONS variable to disable sessions).
156 * util/tests/test_initctl.c:
157 - START_UPSTART now specifies "--no-sessions"
158 - test_check_config(): Added test for "--warn".
159 * scripts/init-checkconf.sh: Script now also checks any script
160 sections found unless the new "--noscript" option is specified.
161 Added required "--no-sessions" option to upstart_cmd to ensure Upstart
162 treats clients requests in traditional manner.
163 * scripts/man/init-checkconf.8: Update for "--noscript".
164 * util/initctl.c: Added "--warn" option for check-config command to
165 warn if any events or jobs are not known.
166
1672011-03-24 James Hunt <james.hunt@ubuntu.com>
168
169 * init/tests/test_control.c: Added comment.
170 * scripts/initctl2dot.py: Fixes to handle 'emits' glob syntax:
171 - header(): Change default node to be an event to simplify handling
172 globs in 'emits' stanzas.
173 - footer(): Updated for glob event nodes.
174 - sanitize(): Protect against glob syntax.
175 - show_event(): Update for glob event nodes.
176 - show_job(): Explicit specification of record node.
177 - show_edges(): Handle 'emits' glob syntax.
178
1792011-03-15 James Hunt <james.hunt@ubuntu.com>
180
181 * configure.ac: Bump version to 0.9.3.
182 * NEWS: Entry for version 0.9.3.
183 * conf/rc-sysinit.conf: Added emits stanza for runlevel event.
184 * extra/conf/upstart-socket-bridge.conf: Added emits stanza for socket
185 event.
186 * extra/conf/upstart-udev-bridge.conf: Added emits stanza for udev class
187 of events (using globs).
188 * init/man/init.5: Updated emits stanza section to explain use of
189 wildcard characters.
190 * util/initctl.c:
191 - New functions:
192 - allow_job(): Determine if specified job is erroneous or not.
193 Handles variables (such as instance variables).
194 - allow_event(): Determine if specified event is erroneous or not.
195 Handles globbing.
196 - eval_expr_tree():
197 - Added calls to allow_job() and allow_event().
198 - Slight simplification of operand-handling code.
199 * util/tests/test_initctl.c: Simplification of dbus_configured().
200
2012011-03-11 James Hunt <james.hunt@ubuntu.com>
202
203 * scripts/Makefile.am: Install improvements for
204 "make distcheck". Added uninstall for scripts.
205
2062011-03-10 James Hunt <james.hunt@ubuntu.com>
207
208 * extra/conf/upstart-socket-bridge.conf: Start as soon as networking is
209 available.
210 * extra/man/socket-event.7: Minor typo fixes and troff quoting for
211 dashes.
212 * extra/man/upstart-socket-bridge.8: Removed reference to socket(8) and
213 replaced with socket-event(7).
214 * extra/man/upstart-udev-bridge.8: Minor typo fixes, troff quoting for
215 dashes, and replaced literal quotes with troff quotes.
216 * init/control.c: Typo.
217 * init/main.c: Corrected indentation.
218 * init/man/init.5: Minor typo fixes, troff quoting for
219 dashes, and replaced literal quotes with troff quotes.
220 * init/man/init.8: Typo.
221 * scripts/init-checkconf.sh: Fixed to ensure safety and portability:
222 - Quoted all variables.
223 - Removed non-portable syntax.
224 - Changed to using getopt(1) rather than getopts(1), and added
225 long-options.
226 * scripts/initctl2dot.py:
227 - Changed from os.popen() to (safer)
228 subprocess.Popen()
229 - Formatting and typos.
230 * util/initctl.c: Typo.
231 * util/man/initctl.8: Minor typo fixes, troff quoting for
232 dashes, and replaced literal quotes with troff quotes.
233 * util/tests/test_initctl.c:
234 - START_UPSTART: improved comments and minor tidyup.
235 - test_show_config(): Placed tests for expected number of lines of
236 output *after* checking expected line values. This ensures that if
237 problems are encountered (for example D-Bus issues), the person
238 viewing the log has a hope of working out what went wrong :-)
239 - test_check_config(): As test_show_config().
240 - dbus_configured(): New function that performs a highly rudimentary
241 check to see if D-Bus appears to be configured for the environment
242 the tests run in.
243 - main(): Improved test for running tests within a chroot: we do now
244 run all tests assuming that D-Bus is found to be working within a
245 chroot environment.
246
2472011-03-07 James Hunt <james.hunt@ubuntu.com>
248
249 * extra/man/upstart-udev-bridge.8: Added examples.
250 * extra/Makefile.am: Create links to upstart-udev-bridge
251 man page for well-known Upstart udev events.
252 * util/initctl.h: Improved comments for CheckConfigData.
253 * scripts/init-checkconf.sh:
254 - cleanup(): Make use of $upstart_pid.
255 - main(): disown $upstart_pid to stop newer bash versions
256 displaying changed child process status.
257 * scripts/init2dot.py:
258 - Removed erroneous check option.
259 - Improved exaplanation of '-r' option.
260 * scripts/Makefile.am: Added manual pages.
261 * scripts/man/init-checkconf.8: New manual page.
262 * scripts/man/initctl2dot.8: New manual page.
263
2642011-03-04 James Hunt <james.hunt@ubuntu.com>
265
266 * contrib/Makefile.am: Fixed paths and names for scripts.
267 * extra/Makefile.am: Update for upstart-socket-bridge.
268 * util/tests/test_initctl.c:
269 - in_chroot(): New function to detect if in chroot environment.
270 - main(): Call in_chroot() to work around bug lp:728988.
271 - START_UPSTART(): Only try to connect 10 times. Don't use
272 upstart_open() since this uses the system bus whereas we care
273 about the session bus. Removed "--debug" as this confuses the
274 log output.
275 * Moved scripts from "contrib/utils/" to "scripts/" and ensured they
276 now install on "make install".
277 * Makefile.am: Added scripts directory.
278 * configure.ac: Added scripts/Makefile.
279 * Packaging changes for socket bridge.
280
2812011-03-03 James Hunt <james.hunt@ubuntu.com>
282
283 * extra/man/socket-event.7: Man page for new socket event.
284 * extra/man/upstart-socket-bridge.8: Man page for socket bridge.
285 * upstart-socket-bridge.conf: configuration file for socket
286 bridge.
287 * contrib/bash_completion/upstart: Updated for new initctl commands
288 "show-config" and "check-config".
289 * contrib/utils/init-check.sh: Script to determine if the
290 specified job configuration file (located outside of /etc/init/)
291 is valid or not.
292 * contrib/utils/initctl2dot.py: Simply Python script to convert new initctl
293 output to GraphViz dot format. Example usage:
294 initctl2dot.py -o - | dot -Tpng -o upstart.png
295 * init/control.h: New define for USE_SESSION_BUS_ENV.
296 * init/control.c:
297 - control_handle_bus_type(): New function to allow selection of
298 session bus via env var "UPSTART_USE_SESSION_BUS" (for testing).
299 - control_bus_open(): Connect to either D-Bus system bus or session bus.
300 * init/man/init.8: Updated for --confdir, --session, --no-startup-event
301 and --startup-event.
302 * init/main.c:
303 - Added new options '--startup-event' and '--no-startup-event'.
304 - Addition of --session and --confdir command-line option (required for
305 test framework to test changes to initctl).
306 - handle_confdir(): New function to select alternate confdir using env
307 var "UPSTART_CONFDIR" (for testing).
308 * init/paths.h:
309 - Renamed CONDIR to DEFAULT_CONFDIR to make its use clearer now it can be changed.
310 - Renamed CONFILE to DEFAULT_CONFFILE for parity with DEFAULT_CONFDIR.
311 - Added define for CONFDIR_ENV.
312 * util/initctl.c:
313 - Addition of --session command-line option (required for test framework to test
314 visualisation changes to initctl).
315 - Changed 'system_bus' variable to 'use_dbus' since now we can use either D-Bus bus type.
316 - Added 'dbus_bus_type' which encodes D-Bus bus type to use.
317 - Added 'verbose_detail' and 'enumerate_events' variables to
318 - Created new functions:
319 - show_config_action(): New function to handle 'show-config' command.
320 - job_class_condition_handler(): Handler function to retrieve job conditions.
321 - job_class_condition_err_handler(): Handler error function for
322 job_class_condition_handler().
323 - job_class_parse_events(): Convert RPN "start on" and "stop on" conditions to
324 human-readable format.
325 - job_class_show_emits(): Display events which job emits.
326 - job_class_show_conditions(): Make D-Bus calls to retrieve "start on" and
327 "stop on" conditions.
328 - dbus_bus_type_setter(): Used by option parser to distinguish system/session
329 D-Bus bus type.
330 - New functions for check-config command;
331 - check_config_action: Handler for new check-config command-line
332 option.
333 - ignored_events_setter(): handler for '--ignore-events' command-line
334 option for check-config command.
335 - eval_expr_tree(): Evaluate expression tree.
336 - check_condition(): High-level function to handle checking start
337 on/stop on conditions.
338 - tree_filter(): Used for filtering expression tree nodes.
339 - display_check_errors():
340 - Updated upstart_open() to handle multiple D-Bus bus types.
341 - status_action() and list_action() modified to call:
342 - job_class_show_emits()
343 - job_class_show_conditions()
344 * util/initctl.h: New file providing:
345 - stack-handling functionality for RPN parsing
346 - New macros:
347 - GET_JOB_NAME(): Determine if specified token refers to a job and
348 return it if true.
349 - IS_INIT_EVEN(): Determine if specified event is an internally
350 generated event.
351 - MAKE_EXPR_NODE(): Create an ExprNode object.
352 - MAKE_JOB_CONDITION(): Create a JobCondition object.
353 - New types required for check-config command:
354 - CheckConfigData
355 - JobCondition
356 - ConditionHandlerData
357 - ExprNode
358 * util/man/initctl.8:
359 - Updated for show-config section showing new "--enumerate" format output.
360 - Added section for check-config command.
361 * util/tests/test_initctl.c:
362 - added test_show_config() and test_check_config().
363 - new macros START_UPSTART, STOP_UPSTART, RUN_COMMAND, CREATE_FILE
364 and DELETE_FILE. These are required since due to the changes in initctl.c, we
365 actually need to run the initctl binary directly (as that is where all
366 the emits/start on/stop on parsing occurs). The test stategy adopted is to run
367 (a second instance of! :-) Upstart as a non-privileged user
368 connected to the session bus and using an alternate config
369 directory. Then, by invoking initctl, again connecting to the session
370 bus, we test the parsing functionality directly.
371
3722011-02-23 James Hunt <james.hunt@ubuntu.com>
373
374 * Fixes to allow "make check" to pass with Session support.
375
3762011-01-21 James Hunt <james.hunt@ubuntu.com>
377
378 * Override file support.
379
3802011-03-03 James Hunt <james.hunt@ubuntu.com>
381
382 * contrib/bash_completion/upstart: Updated for new initctl show-config
383 command.
384 * contrib/utils/init-checkconf.sh: Added '-i' option to specify path to
385 init daemon (for test builds). Ensure conf file exists.
386 * contrib/utils/initctl2dot.py: Updated for changed initctl show-config
387 output.
388 * util/Makefile.am: Added missing initctl.h to initctl_SOURCES.
389 * util/initctl.c:
390 - New functions to handle new check-config command.
391 - check_config_action: Handler for new check-config command-line
392 option.
393 - ignored_events_setter(): handler for '--ignore-events' command-line
394 option for check-config command.
395 - eval_expr_tree(): Evaluate expression tree.
396 - check_condition(): High-level function to handle checking start
397 on/stop on conditions.
398 - tree_filter(): Used for filtering expression tree nodes.
399 - display_check_errors():
400 - Removed ENSURE_ROOT() macros since this would conflict with user
401 sessions.
402 * util/initctl.h:
403 - New macros:
404 - GET_JOB_NAME(): Determine if specified token refers to a job and
405 return it if true.
406 - IS_INIT_EVEN(): Determine if specified event is an internally
407 generated event.
408 - MAKE_EXPR_NODE(): Create an ExprNode object.
409 - MAKE_JOB_CONDITION(): Create a JobCondition object.
410 - New types required for check-config command:
411 - CheckConfigData
412 - JobCondition
413 - ConditionHandlerData
414 - ExprNode
415 * util/man/initctl.8:
416 - Updated for show-config section showing new "--enumerate" format output.
417 - Added section for check-config command.
418 * util/tests/test_initctl.c:
419 - START_UPSTART(): Improved test to ensure Upstart has actually
420 started.
421 - STOP_UPSTART(): Improved test to ensure Upstart has actually
422 stopped.
423 - test_show_config(): Updated for new show-config --enumerate syntax.
424 - test_check_config(): New function to test check-config command.
425
4262011-02-17 James Hunt <james.hunt@ubuntu.com>
427
428 * contrib/utils/init-check.sh renamed to init-checkconf.sh.
429 * contrib/utils/initct2dot.py:
430 - updated to call "initctl show-config"
431 - Added options to allow specification of all colo(u)rs.
432 - Added a '--restrict-to-jobs' option to allow a sub-set of all jobs
433 to be viewed (along with their associated jobs and events).
434 - Code refactored.
435 * init/main.c:
436 - Added new options '--startup-event' and '--no-startup-event'.
437 * init/man/init.8: Updated for "initctl show-status".
438 * util/initctl.c:
439 - Reworked code so that rather than utilizing existing 'list' and
440 'status' commands, we now have a new command: 'show-status'. This is
441 more logical since it is obvious what it is doing and it also
442 doesn't pollute the dynamic data returned by 'status' and 'list' with
443 purely static info.
444 - upstart_open(): Improved dbus_bus_type usage (now only default to
445 system bus).
446 - show_config_action(): New function to handle 'show-config' command.
447 - job_class_parse_events(): Fixed uninitialized variable issue and
448 removed IS_JOB() macro in favour of the ultimately reliable
449 IS_JOB_EVENT() macro.
450 * util/initctl.h: Only enable stack debugging if DEBUG_STACK defined.
451 This ensures that "make check" doesn't fail due to stack DEBUG output.
452 * util/man/initctl.8: Updated for new 'show-config' command.
453 * util/tests/test_initctl.c:
454 - Improved START_UPSTART() and STOP_UPSTART() macros.
455 - Renamed test_status_and_list_action_detail() to
456 test_show_config_action() to reflect the new command under test.
457 - test_show_config_action(): Removed all (now-redundant) tests calling
458 "initctl status" and "initctl list" and updated for new 'show-config'
459 command.
460
4612011-02-15 James Hunt <james.hunt@ubuntu.com>
462
463 * contrib/bash_completion/upstart: Update for job visualisation.
464 * contrib/utils/init-check.sh: Script to determine if the
465 specified job configuration file (located outside of /etc/init/)
466 is valid or not.
467 * contrib/utils/initctl2dot.py: Simple Python script to convert new initctl
468 output to GraphViz dot format. Example usage:
469 initctl2dot.py > upstart.dot && dot -Tpng -o upstart.png upstart.dot
470 * dbus/upstart.h: Whitespace fix.
471 * init/control.c:
472 - control_handle_bus_type(): New function to allow selection of
473 session bus via env var "UPSTART_USE_SESSION_BUS" (for testing).
474 - control_bus_open(): Connect to either D-Bus system bus or session bus.
475 * init/control.h: New define for USE_SESSION_BUS_ENV.
476 * init/man/init.8: Update for --confdir and --session.
477 * init/main.c:
478 - Addition of --session and --confdir command-line option (required for
479 test framework to test changes to initctl).
480 - handle_confdir(): New function to select alternate confdir using env
481 var "UPSTART_CONFDIR" (for testing).
482 * init/paths.h:
483 - Renamed CONDIR to DEFAULT_CONFDIR to make its use clearer now it can be changed.
484 - Renamed CONFILE to DEFAULT_CONFFILE for parity with DEFAULT_CONFDIR.
485 - Added define for CONFDIR_ENV.
486 * util/initctl.c:
487 - Addition of --session command-line option (required for test framework to test
488 visualisation changes to initctl).
489 - Changed 'system_bus' variable to 'use_dbus' since now we can use either D-Bus
490 bus type.
491 - Added 'dbus_bus_type' which encodes D-Bus bus type to use.
492 - Added 'verbose_detail' and 'enumerate_events' variables to
493 - Created new functions:
494 - job_class_condition_handler(): Handler function to retrieve job conditions.
495 - job_class_condition_err_handler(): Handler error function for
496 job_class_condition_handler().
497 - job_class_parse_events(): Convert RPN "start on" and "stop on" conditions to
498 human-readable format.
499 - job_class_show_emits(): Display events which job emits.
500 - job_class_show_conditions(): Make D-Bus calls to retrieve "start on" and
501 "stop on" conditions.
502 - dbus_bus_type_setter(): Used by option parser to distinguish system/session
503 D-Bus bus type.
504 - Updated upstart_open() to handle multiple D-Bus bus types.
505 - Changed following functions to error with message if initctl run as
506 non-root user (without this, you get a very cryptic D-Bus error):
507 - start_action()
508 - stop_action()
509 - restart_action()
510 - reload_configuration_action()
511 - log_priority_action()
512 - status_action() and list_action() modified to call:
513 - job_class_show_emits()
514 - job_class_show_conditions()
515 * util/initctl.h: New file providing stack-handling functionality for RPN parsing.
516 * util/initctl.8: Updated for --session, and --detail/-d and
517 --enumerate/-e options to status and list commands.
518 * util/tests/test_initctl.c:
519 - new macros START_UPSTART, STOP_UPSTART, RUN_COMMAND, CREATE_FILE and DELETE_FILE.
520 These are required since due to the changes in initctl.c, we
521 actually need to run the initctl binary directly (as that is where all
522 the emits/start on/stop on parsing occurs). The test stategy adopted is to run
523 (a second instance of! :-) Upstart as a non-privileged user
524 connected to the session bus and using an alternate config
525 directory. Then, by invoking initctl, again connecting to the session
526 bus, we test the parsing functionality directly.
527 - test_status_and_list_action_detail(): New function to test '-d' and
528 '-e' options for status and list commands.
529 - updated all remaining functions to use 'use_dbus' rather than 'system_bus'.
530
531>>>>>>> MERGE-SOURCE
872011-01-06 Petr Lautrbach <plautrba@redhat.com>5322011-01-06 Petr Lautrbach <plautrba@redhat.com>
88533
89 * init/job_process.c (job_process_termianted): Don't rewind the534 * init/job_process.c (job_process_termianted): Don't rewind the
@@ -144,6 +589,14 @@
144589
1452010-12-10 Scott James Remnant <scott@netsplit.com>5902010-12-10 Scott James Remnant <scott@netsplit.com>
146591
592 * Socket bridge and udev bridge support.
593
5942010-12-10 Scott James Remnant <scott@netsplit.com>
595
596 * Session support (chroots, sessions and user-session).
597
5982010-12-10 Scott James Remnant <scott@netsplit.com>
599
147 * dbus/upstart.h (DBUS_SERVICE_UPSTART, DBUS_ADDRESS_UPSTART):600 * dbus/upstart.h (DBUS_SERVICE_UPSTART, DBUS_ADDRESS_UPSTART):
148 For debugging purposes, when -DDEBUG is given, change the values of601 For debugging purposes, when -DDEBUG is given, change the values of
149 these constants. You'll need to modify your own D-Bus configuration602 these constants. You'll need to modify your own D-Bus configuration
150603
=== modified file 'Makefile.am'
--- Makefile.am 2010-02-04 03:42:29 +0000
+++ Makefile.am 2011-04-27 14:11:41 +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 scripts
44
5EXTRA_DIST = HACKING5EXTRA_DIST = HACKING
66
77
=== modified file 'NEWS'
--- NEWS 2011-03-22 17:53:17 +0000
+++ NEWS 2011-04-27 14:11:41 +0000
@@ -1,3 +1,4 @@
1<<<<<<< TREE
11.3 xxxx-xx-xx21.3 xxxx-xx-xx
23
31.2 2011-03-22 "This sort of thing is my bag, baby"41.2 2011-03-22 "This sort of thing is my bag, baby"
@@ -31,6 +32,83 @@
3132
32 * Fixed an assertion when a file named /etc/init/.conf is created.33 * Fixed an assertion when a file named /etc/init/.conf is created.
33 Discovered by Коренберг Марк (Bug: #720573)34 Discovered by Коренберг Марк (Bug: #720573)
35=======
360.9.7 2011-04-20
37
38 * Fix for user sessions to retain backwards compatibility behaviour
39 where a non-privileged user can enquire on jobs owned by the
40 global namespace.
41
420.9.6 2011-04-15
43
44 * Fix for nasty OOM scenario when an attempt is made to start
45 a chroot job with same name as running single-instance
46 non-chroot job. Previously, the path for a chrooted Job
47 was set from the (nul) instance name of its parent JobClass.
48 However, since that job instance name already existed
49 outside the chroot and was already D-Bus registered,
50 nih_dbus_object_new() (which allocates storage and is
51 called by job_register()) returned NULL and kept doing so
52 due to being called within NIH_MUST(). This resulted in
53 OOM due to an as-yet unidentified D-Bus bug (possibly a
54 leak in find_subtree_recurse()).
55
560.9.5 2011-04-06
57
58 * Important fixes for user and chroot sessions.
59 * scripts/init-checkconf.sh: Now checks script sections too.
60 * util/initctl.c: Added "--warn" option for check-config command
61 to warn if any events or jobs are not known.
62
630.9.4 2011-03-24
64
65 * scripts/initctl2dot.py: Fix to handle 'emits' glob syntax
66 which was causing script to fail for upstart-udev-bridge.
67
680.9.3 2011-03-15
69
70 * Added missing emits stanzas for supplied .conf files.
71
72 * Added wildcard/globbing facility to initctl.c (for check-config
73 command).
74
75 * Updated man page on emits stanza syntax.
76
770.9.2 2011-03-11
78
79 * Improvements to existing documentation.
80 * scripts/man/init-checkconf.8: New manual page.
81 * scripts/man/initctl2dot.8: New manual page.
82 * packaging improvements (including "make distcheck" fix).
83 * extra/man/upstart-udev-bridge.8: Added examples.
84 * extra/Makefile.am: Create links to upstart-udev-bridge
85 man page for well-known Upstart udev events.
86
870.9.1 2011-03-03
88
89 * Added supporting documentation for upstart-socket-bridge and
90 sessions and chroot support.
91
92 * Added job configuration file for upstart-socket-bridge.
93
94 * Added job/event visualisation support. This comprises a new
95 initctl command, "show-config" which generates human-readable
96 (and machine parseable) output showing start on, stop on and
97 emits details for each job. See initctl.8 for further details.
98 The output from show-config is used by the new script
99 contrib/utils/initctl2dot.py which graphs the data in GraphViz
100 format.
101
102 * Added new initctl command check-config allowing unreachable
103 job conditions to be detected. See initctl.8 for further
104 details.
105
106 * Added script contrib/utils/init-checkconf.sh which allows
107 non-privileged users to check job configuration files for syntax
108 errors prior to installing in /etc/init/.
109
1100.9.0 2011-02-24
111>>>>>>> MERGE-SOURCE
34112
35 * utmp entries will be replaced with DEAD_PROCESS ones when a113 * utmp entries will be replaced with DEAD_PROCESS ones when a
36 pid supervised by Upstart terminates. (Bug: #183729)114 pid supervised by Upstart terminates. (Bug: #183729)
@@ -41,6 +119,29 @@
41 * Included bash completion script in contrib directory.119 * Included bash completion script in contrib directory.
42 (Bug: #672067)120 (Bug: #672067)
43121
122 * Addition of Session support (chroots, sessions and
123 user-session).
124
125 * Socket bridge support allowing jobs to be started based on
126 socket connections. Examples of supported syntax:
127
128 start on socket PROTO=inet PORT=1234
129 start on socket PROTO=unix PATH=/var/run/.s.pgsql.1234
130 start on socket PROTO=unix PATH=@/at/upstart/example
131
132 * udev bridge support imported from Ubuntu. See
133 "man 8 upstart-udev-bridge" for further details.
134
135 * Override file support allowing the creation of files named
136 "<job_conf>.override" whose contents override that found in
137 "<job_conf>.conf". Useful to modify a job without touching its
138 .conf file. For example, a job can now be disabled simply by
139 doing:
140
141 echo "manual" >> /etc/init/jobname.override
142
143 See "man 5 init" for further details.
144
440.6.7 2010-12-14 "Return of the Mole"1450.6.7 2010-12-14 "Return of the Mole"
45146
46 * A new "manual" stanza has been added to the configuration, this147 * A new "manual" stanza has been added to the configuration, this
47148
=== modified file 'conf/rc-sysinit.conf'
--- conf/rc-sysinit.conf 2010-02-04 03:59:06 +0000
+++ conf/rc-sysinit.conf 2011-04-27 14:11:41 +0000
@@ -13,6 +13,8 @@
13# or by faking an old /etc/inittab entry13# or by faking an old /etc/inittab entry
14env DEFAULT_RUNLEVEL=214env DEFAULT_RUNLEVEL=2
1515
16emits runlevel
17
16# There can be no previous runlevel here, but there might be old18# There can be no previous runlevel here, but there might be old
17# information in /var/run/utmp that we pick up, and we don't want19# information in /var/run/utmp that we pick up, and we don't want
18# that.20# that.
1921
=== modified file 'configure.ac'
--- configure.ac 2011-03-22 17:53:17 +0000
+++ configure.ac 2011-04-27 14:11:41 +0000
@@ -1,8 +1,13 @@
1# Process this file with autoconf to produce a configure script.1# Process this file with autoconf to produce a configure script.
22
3AC_PREREQ(2.61)3AC_PREREQ(2.61)
4<<<<<<< TREE
4AC_INIT([upstart], [1.3], [upstart-devel@lists.ubuntu.com])5AC_INIT([upstart], [1.3], [upstart-devel@lists.ubuntu.com])
5NIH_COPYRIGHT([[Copyright © 2011 Scott James Remnant, Google Inc., Canonical Ltd.]])6NIH_COPYRIGHT([[Copyright © 2011 Scott James Remnant, Google Inc., Canonical Ltd.]])
7=======
8AC_INIT([upstart], [0.9.7], [upstart-devel@lists.ubuntu.com])
9NIH_COPYRIGHT([[Copyright © 2011 Canonical Ltd.]])
10>>>>>>> MERGE-SOURCE
6AC_CONFIG_SRCDIR([init/main.c])11AC_CONFIG_SRCDIR([init/main.c])
7AC_CONFIG_MACRO_DIR([m4])12AC_CONFIG_MACRO_DIR([m4])
813
@@ -30,6 +35,9 @@
30PKG_CHECK_MODULES([NIH], [libnih >= 1.0.2])35PKG_CHECK_MODULES([NIH], [libnih >= 1.0.2])
31PKG_CHECK_MODULES([NIH_DBUS], [libnih-dbus >= 1.0.0])36PKG_CHECK_MODULES([NIH_DBUS], [libnih-dbus >= 1.0.0])
32PKG_CHECK_MODULES([DBUS], [dbus-1 >= 1.2.16])37PKG_CHECK_MODULES([DBUS], [dbus-1 >= 1.2.16])
38PKG_CHECK_MODULES([UDEV], [libudev >= 146], [have_udev=yes], [have_udev=no])
39
40AM_CONDITIONAL([HAVE_UDEV], [test "$have_udev" = yes])
3341
34# Checks for header files.42# Checks for header files.
35AC_CHECK_HEADERS([valgrind/valgrind.h])43AC_CHECK_HEADERS([valgrind/valgrind.h])
@@ -63,7 +71,8 @@
6371
6472
65AC_CONFIG_FILES([ Makefile intl/Makefile73AC_CONFIG_FILES([ Makefile intl/Makefile
66 dbus/Makefile init/Makefile util/Makefile conf/Makefile74 dbus/Makefile init/Makefile util/Makefile extra/Makefile
67 doc/Makefile contrib/Makefile po/Makefile.in ])75 conf/Makefile doc/Makefile contrib/Makefile po/Makefile.in
76 scripts/Makefile ])
68AC_CONFIG_HEADERS([config.h])77AC_CONFIG_HEADERS([config.h])
69AC_OUTPUT78AC_OUTPUT
7079
=== modified file 'contrib/bash_completion/upstart'
--- contrib/bash_completion/upstart 2010-12-21 13:54:49 +0000
+++ contrib/bash_completion/upstart 2011-04-27 14:11:41 +0000
@@ -3,7 +3,7 @@
3#3#
4# We don't provide completion for 'init' itself for obvious reasons.4# We don't provide completion for 'init' itself for obvious reasons.
5have initctl &&5have initctl &&
6_upstart_conf_events()6_upstart_conf_jobs()
7{7{
8 initctl list|awk '{print $1}'8 initctl list|awk '{print $1}'
9} &&9} &&
@@ -13,7 +13,7 @@
13} &&13} &&
14_upstart_events()14_upstart_events()
15{15{
16 (_upstart_conf_events;_upstart_named_events)|tr ' ' '\n'|sort -u16 (_upstart_conf_jobs;_upstart_named_events)|tr ' ' '\n'|sort -u
17} &&17} &&
18_upstart_startable_events()18_upstart_startable_events()
19{19{
@@ -46,8 +46,32 @@
46 return 046 return 0
47 ;;47 ;;
4848
49 reload|restart|status)49 -e|--enumerate)
50 COMPREPLY=( $(compgen -W "$(_upstart_conf_events)" -- ${cur}) )50 # handle visualisation options after show-config command
51 for cmd in show-config
52 do
53 cwords=${COMP_WORDS[@]##}
54 filtered_cwords=${COMP_WORDS[@]##${cmd}}
55 if [ "$filtered_cwords" != "$cwords" ]
56 then
57 COMPREPLY=( $(compgen -W "${vis_opts} $(_upstart_conf_jobs)" -- ${cur}) )
58 return 0
59 fi
60 done
61 ;;
62
63 reload|restart)
64 COMPREPLY=( $(compgen -W "$(_upstart_conf_jobs)" -- ${cur}) )
65 return 0
66 ;;
67
68 status)
69 COMPREPLY=( $(compgen -W "${vis_opts} $(_upstart_conf_jobs)" -- ${cur}) )
70 return 0
71 ;;
72
73 show-config)
74 COMPREPLY=( $(compgen -W "-e --enumerate $(_upstart_conf_jobs)" -- ${cur}) )
51 return 075 return 0
52 ;;76 ;;
5377
@@ -71,7 +95,7 @@
71 ;;95 ;;
72 esac96 esac
7397
74 opts="--help --version -q --quiet -v --verbose --system --dest="98 opts="--help --version -q --quiet -v --verbose --session --system --dest="
75 cmds=$(initctl help|grep "^ [^ ]"|awk '{print $1}')99 cmds=$(initctl help|grep "^ [^ ]"|awk '{print $1}')
76100
77 COMPREPLY=( $(compgen -W "${opts} ${cmds}" -- ${cur}) )101 COMPREPLY=( $(compgen -W "${opts} ${cmds}" -- ${cur}) )
@@ -84,7 +108,7 @@
84 COMPREPLY=()108 COMPREPLY=()
85 _get_comp_words_by_ref cur prev109 _get_comp_words_by_ref cur prev
86110
87 opts="--help --version -q --quiet -v --verbose --system --dest= \111 opts="--help --version -q --quiet -v --verbose --session --system --dest= \
88 -n --no-wait"112 -n --no-wait"
89113
90 case "$prev" in114 case "$prev" in
@@ -104,7 +128,7 @@
104 COMPREPLY=()128 COMPREPLY=()
105 _get_comp_words_by_ref cur prev129 _get_comp_words_by_ref cur prev
106130
107 opts="--help --version -q --quiet -v --verbose --system --dest= \131 opts="--help --version -q --quiet -v --verbose --session --system --dest= \
108 -n --no-wait"132 -n --no-wait"
109133
110 case "$prev" in134 case "$prev" in
@@ -124,7 +148,7 @@
124 COMPREPLY=()148 COMPREPLY=()
125 _get_comp_words_by_ref cur prev149 _get_comp_words_by_ref cur prev
126150
127 opts="--help --version -q --quiet -v --verbose --system --dest= \151 opts="--help --version -q --quiet -v --verbose --session --system --dest= \
128 -n --no-wait"152 -n --no-wait"
129153
130 case "$prev" in154 case "$prev" in
@@ -145,7 +169,7 @@
145 COMPREPLY=()169 COMPREPLY=()
146 _get_comp_words_by_ref cur prev170 _get_comp_words_by_ref cur prev
147171
148 opts="--help --version -q --quiet -v --verbose --system --dest="172 opts="--help --version -q -d --detail -e --enumerate --quiet -v --verbose --session --system --dest="
149173
150 case "$prev" in174 case "$prev" in
151 --help|--version)175 --help|--version)
@@ -165,7 +189,7 @@
165 COMPREPLY=()189 COMPREPLY=()
166 _get_comp_words_by_ref cur prev190 _get_comp_words_by_ref cur prev
167191
168 opts="--help --version -q --quiet -v --verbose --system --dest="192 opts="--help --version -q --quiet -v --verbose --session --system --dest="
169193
170 case "$prev" in194 case "$prev" in
171 --help|--version)195 --help|--version)
172196
=== added directory 'contrib/utils'
=== modified file 'dbus/Upstart.conf'
--- dbus/Upstart.conf 2009-07-02 17:46:41 +0000
+++ dbus/Upstart.conf 2011-04-27 14:11:41 +0000
@@ -9,12 +9,14 @@
9 <allow own="com.ubuntu.Upstart" />9 <allow own="com.ubuntu.Upstart" />
10 </policy>10 </policy>
1111
12 <!-- Permit the root user to invoke all of the methods on Upstart, its jobs12 <!-- Allow any user to invoke all of the methods on Upstart, its jobs
13 or their instances, and to get and set properties. -->13 or their instances, and to get and set properties - since Upstart
14 <policy user="root">14 isolates commands by user. -->
15 <policy context="default">
16 <allow send_destination="com.ubuntu.Upstart"
17 send_interface="org.freedesktop.DBus.Introspectable" />
15 <allow send_destination="com.ubuntu.Upstart"18 <allow send_destination="com.ubuntu.Upstart"
16 send_interface="org.freedesktop.DBus.Properties" />19 send_interface="org.freedesktop.DBus.Properties" />
17
18 <allow send_destination="com.ubuntu.Upstart"20 <allow send_destination="com.ubuntu.Upstart"
19 send_interface="com.ubuntu.Upstart0_6" />21 send_interface="com.ubuntu.Upstart0_6" />
20 <allow send_destination="com.ubuntu.Upstart"22 <allow send_destination="com.ubuntu.Upstart"
@@ -22,36 +24,4 @@
22 <allow send_destination="com.ubuntu.Upstart"24 <allow send_destination="com.ubuntu.Upstart"
23 send_interface="com.ubuntu.Upstart0_6.Instance" />25 send_interface="com.ubuntu.Upstart0_6.Instance" />
24 </policy>26 </policy>
25
26 <!-- Allow any user to introspect Upstart's interfaces, to obtain the
27 values of properties (but not set them) and to invoke selected
28 methods on Upstart and its jobs that are used to walk information. -->
29 <policy context="default">
30 <allow send_destination="com.ubuntu.Upstart"
31 send_interface="org.freedesktop.DBus.Introspectable" />
32
33 <allow send_destination="com.ubuntu.Upstart"
34 send_interface="org.freedesktop.DBus.Properties"
35 send_type="method_call" send_member="Get" />
36 <allow send_destination="com.ubuntu.Upstart"
37 send_interface="org.freedesktop.DBus.Properties"
38 send_type="method_call" send_member="GetAll" />
39
40 <allow send_destination="com.ubuntu.Upstart"
41 send_interface="com.ubuntu.Upstart0_6"
42 send_type="method_call" send_member="GetJobByName" />
43 <allow send_destination="com.ubuntu.Upstart"
44 send_interface="com.ubuntu.Upstart0_6"
45 send_type="method_call" send_member="GetAllJobs" />
46
47 <allow send_destination="com.ubuntu.Upstart"
48 send_interface="com.ubuntu.Upstart0_6.Job"
49 send_type="method_call" send_member="GetInstance" />
50 <allow send_destination="com.ubuntu.Upstart"
51 send_interface="com.ubuntu.Upstart0_6.Job"
52 send_type="method_call" send_member="GetInstanceByName" />
53 <allow send_destination="com.ubuntu.Upstart"
54 send_interface="com.ubuntu.Upstart0_6.Job"
55 send_type="method_call" send_member="GetAllInstances" />
56 </policy>
57</busconfig>27</busconfig>
5828
=== 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-04-27 14:11:41 +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
=== modified file 'dbus/upstart.h'
--- dbus/upstart.h 2010-12-10 04:04:51 +0000
+++ dbus/upstart.h 2011-04-27 14:11:41 +0000
@@ -31,7 +31,7 @@
31# define DBUS_SERVICE_UPSTART "com.ubuntu.TestUpstart"31# define DBUS_SERVICE_UPSTART "com.ubuntu.TestUpstart"
32# else32# else
33# define DBUS_SERVICE_UPSTART "com.ubuntu.Upstart"33# define DBUS_SERVICE_UPSTART "com.ubuntu.Upstart"
34#endif34# endif
35#endif35#endif
3636
3737
3838
=== added directory 'extra'
=== added file 'extra/Makefile.am'
--- extra/Makefile.am 1970-01-01 00:00:00 +0000
+++ extra/Makefile.am 2011-04-27 14:11:41 +0000
@@ -0,0 +1,126 @@
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
48sbin_PROGRAMS += \
49 upstart-udev-bridge
50
51upstart_udev_bridge_SOURCES = \
52 upstart-udev-bridge.c
53nodist_upstart_udev_bridge_SOURCES = \
54 $(com_ubuntu_Upstart_OUTPUTS)
55upstart_udev_bridge_LDADD = \
56 $(LTLIBINTL) \
57 $(NIH_LIBS) \
58 $(NIH_DBUS_LIBS) \
59 $(DBUS_LIBS) \
60 $(UDEV_LIBS)
61
62install-data-hook:
63 src=`echo upstart-udev-bridge| sed '$(transform)'`.8; \
64 for symlink in \
65 net-device-added \
66 net-device-removed \
67 graphics-device-added \
68 drm-device-added; do \
69 inst=`echo $$symlink | sed '$(transform)'`.7; \
70 echo " ln -sf '$(man8dir)/$$src' '$(DESTDIR)$(man7dir)/$$inst'"; \
71 ln -sf "$(man8dir)/$$src" "$(DESTDIR)$(man7dir)/$$inst"; \
72 done
73
74else
75EXTRA_DIST = \
76 man/upstart-udev-bridge.8
77
78endif
79
80
81com_ubuntu_Upstart_OUTPUTS = \
82 com.ubuntu.Upstart.c \
83 com.ubuntu.Upstart.h
84
85com_ubuntu_Upstart_XML = \
86 ../dbus/com.ubuntu.Upstart.xml
87
88$(com_ubuntu_Upstart_OUTPUTS): $(com_ubuntu_Upstart_XML)
89 $(AM_V_GEN)$(NIH_DBUS_TOOL) \
90 --package=$(PACKAGE) \
91 --mode=proxy --prefix=upstart \
92 --default-interface=com.ubuntu.Upstart0_6 \
93 --output=$@ $<
94
95
96com_ubuntu_Upstart_Job_OUTPUTS = \
97 com.ubuntu.Upstart.Job.c \
98 com.ubuntu.Upstart.Job.h
99
100com_ubuntu_Upstart_Job_XML = \
101 ../dbus/com.ubuntu.Upstart.Job.xml
102
103$(com_ubuntu_Upstart_Job_OUTPUTS): $(com_ubuntu_Upstart_Job_XML)
104 $(AM_V_GEN)$(NIH_DBUS_TOOL) \
105 --package=$(PACKAGE) \
106 --mode=proxy --prefix=job_class \
107 --default-interface=com.ubuntu.Upstart0_6.Job \
108 --output=$@ $<
109
110
111# These have to be built sources because we can't compile object files
112# without the header file existing first
113BUILT_SOURCES = \
114 $(com_ubuntu_Upstart_OUTPUTS) \
115 $(com_ubuntu_Upstart_Job_OUTPUTS)
116
117CLEANFILES = \
118 $(com_ubuntu_Upstart_OUTPUTS) \
119 $(com_ubuntu_Upstart_Job_OUTPUTS)
120
121
122clean-local:
123 rm -f *.gcno *.gcda
124
125maintainer-clean-local:
126 rm -f *.gcov
0127
=== 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-04-27 14:11:41 +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-04-27 14:11:41 +0000
@@ -0,0 +1,16 @@
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
8emits *-device-*
9
10start on starting udev
11stop on stopped udev
12
13expect daemon
14respawn
15
16exec upstart-udev-bridge --daemon
017
=== 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-04-27 14:11:41 +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-04-27 14:11:41 +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-04-27 14:11:41 +0000
@@ -0,0 +1,57 @@
1.TH upstart\-udev\-bridge 8 2011-03-08 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
18It emits events which match the pattern "\fIS\fP\-device\-\fIA\fP" where
19\(aqS\(aq is the udev \fIsubsystem\fP and \(aqA\(aq is the udev \fIaction\fP.
20See \fBudev\fP(7) and for further details.
21
22Assuming \fI/sys\fP is mounted, possible values for \fIsubsystem\fP for
23your system are viewable via \fI/sys/class/\fP.
24
25.\"
26.SH EXAMPLES
27
28.IP net\-device\-added
29Event emitted when a network device is added.
30.IP net\-device\-removed
31Event emitted when a network device is removed.
32.IP graphics\-card\-added
33Event emitted when a graphics device is available to the system.
34.\"
35.SH NOTES
36This is a temporary tool until
37.BR init (8)
38itself gains the functionality to read them directly; you should not
39rely on its behaviour.
40.\"
41.SH AUTHOR
42Written by Scott James Remnant
43.RB < scott@netsplit.com >
44.\"
45.SH BUGS
46Report bugs at
47.RB < https://launchpad.net/ubuntu/+source/upstart/+bugs >
48.\"
49.SH COPYRIGHT
50Copyright \(co 2009,2010,2011 Canonical Ltd.
51.PP
52This is free software; see the source for copying conditions. There is NO
53warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
54.SH SEE ALSO
55.BR init (5)
56.BR init (8)
57.BR udev (7)
058
=== 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-04-27 14:11:41 +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 sock);
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-04-27 14:11:41 +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/Makefile.am'
--- init/Makefile.am 2010-02-04 03:42:29 +0000
+++ init/Makefile.am 2011-04-27 14:11:41 +0000
@@ -40,6 +40,7 @@
40 system.c system.h \40 system.c system.h \
41 environ.c environ.h \41 environ.c environ.h \
42 process.c process.h \42 process.c process.h \
43 session.c session.h \
43 job_class.c job_class.h \44 job_class.c job_class.h \
44 job_process.c job_process.h \45 job_process.c job_process.h \
45 job.c job.h \46 job.c job.h \
@@ -144,20 +145,24 @@
144tests: $(BUILT_SOURCES) $(check_PROGRAMS)145tests: $(BUILT_SOURCES) $(check_PROGRAMS)
145146
146test_system_SOURCES = tests/test_system.c147test_system_SOURCES = tests/test_system.c
148test_system_CFLAGS = $(AM_CFLAGS) -DTEST
147test_system_LDADD = \149test_system_LDADD = \
148 system.o \150 system.o \
149 $(NIH_LIBS)151 $(NIH_LIBS)
150152
151test_environ_SOURCES = tests/test_environ.c153test_environ_SOURCES = tests/test_environ.c
154test_environ_CFLAGS = $(AM_CFLAGS) -DTEST
152test_environ_LDADD = \155test_environ_LDADD = \
153 environ.o \156 environ.o \
154 $(NIH_LIBS)157 $(NIH_LIBS)
155158
156test_process_SOURCES = tests/test_process.c159test_process_SOURCES = tests/test_process.c
160test_process_CFLAGS = $(AM_CFLAGS) -DTEST
157test_process_LDADD = \161test_process_LDADD = \
158 system.o environ.o process.o \162 system.o environ.o process.o \
159 job_class.o job_process.o job.o event.o event_operator.o blocked.o \163 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
160 parse_job.o parse_conf.o conf.o control.o \164 parse_job.o parse_conf.o conf.o control.o \
165 session.o \
161 com.ubuntu.Upstart.o \166 com.ubuntu.Upstart.o \
162 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \167 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
163 $(NIH_LIBS) \168 $(NIH_LIBS) \
@@ -165,10 +170,12 @@
165 $(DBUS_LIBS)170 $(DBUS_LIBS)
166171
167test_job_class_SOURCES = tests/test_job_class.c172test_job_class_SOURCES = tests/test_job_class.c
173test_job_class_CFLAGS = $(AM_CFLAGS) -DTEST
168test_job_class_LDADD = \174test_job_class_LDADD = \
169 system.o environ.o process.o \175 system.o environ.o process.o \
170 job_class.o job_process.o job.o event.o event_operator.o blocked.o \176 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
171 parse_job.o parse_conf.o conf.o control.o \177 parse_job.o parse_conf.o conf.o control.o \
178 session.o \
172 com.ubuntu.Upstart.o \179 com.ubuntu.Upstart.o \
173 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \180 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
174 $(NIH_LIBS) \181 $(NIH_LIBS) \
@@ -176,10 +183,12 @@
176 $(DBUS_LIBS)183 $(DBUS_LIBS)
177184
178test_job_process_SOURCES = tests/test_job_process.c185test_job_process_SOURCES = tests/test_job_process.c
186test_job_process_CFLAGS = $(AM_CFLAGS) -DTEST
179test_job_process_LDADD = \187test_job_process_LDADD = \
180 system.o environ.o process.o \188 system.o environ.o process.o \
181 job_class.o job_process.o job.o event.o event_operator.o blocked.o \189 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
182 parse_job.o parse_conf.o conf.o control.o \190 parse_job.o parse_conf.o conf.o control.o \
191 session.o \
183 com.ubuntu.Upstart.o \192 com.ubuntu.Upstart.o \
184 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \193 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
185 $(NIH_LIBS) \194 $(NIH_LIBS) \
@@ -187,10 +196,12 @@
187 $(DBUS_LIBS)196 $(DBUS_LIBS)
188197
189test_job_SOURCES = tests/test_job.c198test_job_SOURCES = tests/test_job.c
199test_job_CFLAGS = $(AM_CFLAGS) -DTEST
190test_job_LDADD = \200test_job_LDADD = \
191 system.o environ.o process.o \201 system.o environ.o process.o \
192 job_class.o job_process.o job.o event.o event_operator.o blocked.o \202 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
193 parse_job.o parse_conf.o conf.o control.o \203 parse_job.o parse_conf.o conf.o control.o \
204 session.o \
194 com.ubuntu.Upstart.o \205 com.ubuntu.Upstart.o \
195 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \206 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
196 $(NIH_LIBS) \207 $(NIH_LIBS) \
@@ -198,10 +209,12 @@
198 $(DBUS_LIBS)209 $(DBUS_LIBS)
199210
200test_event_SOURCES = tests/test_event.c211test_event_SOURCES = tests/test_event.c
212test_event_CFLAGS = $(AM_CFLAGS) -DTEST
201test_event_LDADD = \213test_event_LDADD = \
202 system.o environ.o process.o \214 system.o environ.o process.o \
203 job_class.o job_process.o job.o event.o event_operator.o blocked.o \215 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
204 parse_job.o parse_conf.o conf.o control.o \216 parse_job.o parse_conf.o conf.o control.o \
217 session.o \
205 com.ubuntu.Upstart.o \218 com.ubuntu.Upstart.o \
206 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \219 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
207 $(NIH_LIBS) \220 $(NIH_LIBS) \
@@ -209,10 +222,12 @@
209 $(DBUS_LIBS)222 $(DBUS_LIBS)
210223
211test_event_operator_SOURCES = tests/test_event_operator.c224test_event_operator_SOURCES = tests/test_event_operator.c
225test_event_operator_CFLAGS = $(AM_CFLAGS) -DTEST
212test_event_operator_LDADD = \226test_event_operator_LDADD = \
213 system.o environ.o process.o \227 system.o environ.o process.o \
214 job_class.o job_process.o job.o event.o event_operator.o blocked.o \228 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
215 parse_job.o parse_conf.o conf.o control.o \229 parse_job.o parse_conf.o conf.o control.o \
230 session.o \
216 com.ubuntu.Upstart.o \231 com.ubuntu.Upstart.o \
217 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \232 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
218 $(NIH_LIBS) \233 $(NIH_LIBS) \
@@ -220,10 +235,12 @@
220 $(DBUS_LIBS)235 $(DBUS_LIBS)
221236
222test_blocked_SOURCES = tests/test_blocked.c237test_blocked_SOURCES = tests/test_blocked.c
238test_blocked_CFLAGS = $(AM_CFLAGS) -DTEST
223test_blocked_LDADD = \239test_blocked_LDADD = \
224 system.o environ.o process.o \240 system.o environ.o process.o \
225 job_class.o job_process.o job.o event.o event_operator.o blocked.o \241 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
226 parse_job.o parse_conf.o conf.o control.o \242 parse_job.o parse_conf.o conf.o control.o \
243 session.o \
227 com.ubuntu.Upstart.o \244 com.ubuntu.Upstart.o \
228 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \245 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
229 $(NIH_LIBS) \246 $(NIH_LIBS) \
@@ -231,10 +248,12 @@
231 $(DBUS_LIBS)248 $(DBUS_LIBS)
232249
233test_parse_job_SOURCES = tests/test_parse_job.c250test_parse_job_SOURCES = tests/test_parse_job.c
251test_parse_job_CFLAGS = $(AM_CFLAGS) -DTEST
234test_parse_job_LDADD = \252test_parse_job_LDADD = \
235 system.o environ.o process.o \253 system.o environ.o process.o \
236 job_class.o job_process.o job.o event.o event_operator.o blocked.o \254 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
237 parse_job.o parse_conf.o conf.o control.o \255 parse_job.o parse_conf.o conf.o control.o \
256 session.o \
238 com.ubuntu.Upstart.o \257 com.ubuntu.Upstart.o \
239 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \258 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
240 $(NIH_LIBS) \259 $(NIH_LIBS) \
@@ -242,10 +261,12 @@
242 $(DBUS_LIBS)261 $(DBUS_LIBS)
243262
244test_parse_conf_SOURCES = tests/test_parse_conf.c263test_parse_conf_SOURCES = tests/test_parse_conf.c
264test_parse_conf_CFLAGS = $(AM_CFLAGS) -DTEST
245test_parse_conf_LDADD = \265test_parse_conf_LDADD = \
246 system.o environ.o process.o \266 system.o environ.o process.o \
247 job_class.o job_process.o job.o event.o event_operator.o blocked.o \267 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
248 parse_job.o parse_conf.o conf.o control.o \268 parse_job.o parse_conf.o conf.o control.o \
269 session.o \
249 com.ubuntu.Upstart.o \270 com.ubuntu.Upstart.o \
250 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \271 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
251 $(NIH_LIBS) \272 $(NIH_LIBS) \
@@ -253,10 +274,12 @@
253 $(DBUS_LIBS)274 $(DBUS_LIBS)
254275
255test_conf_SOURCES = tests/test_conf.c276test_conf_SOURCES = tests/test_conf.c
277test_conf_CFLAGS = $(AM_CFLAGS) -DTEST
256test_conf_LDADD = \278test_conf_LDADD = \
257 system.o environ.o process.o \279 system.o environ.o process.o \
258 job_class.o job_process.o job.o event.o event_operator.o blocked.o \280 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
259 parse_job.o parse_conf.o conf.o control.o \281 parse_job.o parse_conf.o conf.o control.o \
282 session.o \
260 com.ubuntu.Upstart.o \283 com.ubuntu.Upstart.o \
261 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \284 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
262 $(NIH_LIBS) \285 $(NIH_LIBS) \
@@ -264,10 +287,12 @@
264 $(DBUS_LIBS)287 $(DBUS_LIBS)
265288
266test_control_SOURCES = tests/test_control.c289test_control_SOURCES = tests/test_control.c
290test_control_CFLAGS = $(AM_CFLAGS) -DTEST
267test_control_LDADD = \291test_control_LDADD = \
268 system.o environ.o process.o \292 system.o environ.o process.o \
269 job_class.o job_process.o job.o event.o event_operator.o blocked.o \293 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
270 parse_job.o parse_conf.o conf.o control.o \294 parse_job.o parse_conf.o conf.o control.o \
295 session.o \
271 com.ubuntu.Upstart.o \296 com.ubuntu.Upstart.o \
272 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \297 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
273 $(NIH_LIBS) \298 $(NIH_LIBS) \
274299
=== modified file 'init/conf.c'
--- init/conf.c 2011-03-15 18:44:09 +0000
+++ init/conf.c 2011-04-27 14:11:41 +0000
@@ -2,8 +2,12 @@
2 *2 *
3 * conf.c - configuration management3 * conf.c - configuration management
4 *4 *
5<<<<<<< TREE
5 * Copyright © 2011 Google Inc.6 * Copyright © 2011 Google Inc.
6 * Copyright © 2009 Canonical Ltd.7 * Copyright © 2009 Canonical Ltd.
8=======
9 * Copyright © 2009, 2010 Canonical Ltd.
10>>>>>>> MERGE-SOURCE
7 * Author: Scott James Remnant <scott@netsplit.com>.11 * Author: Scott James Remnant <scott@netsplit.com>.
8 *12 *
9 * This program is free software; you can redistribute it and/or modify13 * This program is free software; you can redistribute it and/or modify
@@ -49,7 +53,7 @@
49#include "parse_conf.h"53#include "parse_conf.h"
50#include "conf.h"54#include "conf.h"
51#include "errors.h"55#include "errors.h"
5256#include "paths.h"
5357
54/* Prototypes for static functions */58/* Prototypes for static functions */
55static int conf_source_reload_file (ConfSource *source)59static int conf_source_reload_file (ConfSource *source)
@@ -71,9 +75,19 @@
71 struct stat *statbuf)75 struct stat *statbuf)
72 __attribute__ ((warn_unused_result));76 __attribute__ ((warn_unused_result));
7377
74static int conf_reload_path (ConfSource *source, const char *path)78static int conf_reload_path (ConfSource *source, const char *path,
75 __attribute__ ((warn_unused_result));79 const char *override_path)
7680 __attribute__ ((warn_unused_result));
81
82static inline int is_conf_file (const char *path)
83 __attribute__ ((warn_unused_result));
84
85static inline int is_conf_file_std (const char *path)
86 __attribute__ ((warn_unused_result));
87
88static inline int
89is_conf_file_override (const char *path)
90 __attribute__ ((warn_unused_result));
7791
78/**92/**
79 * conf_sources:93 * conf_sources:
@@ -86,6 +100,115 @@
86100
87101
88/**102/**
103 * is_conf_file_std:
104 * @path: path to check.
105 *
106 * Determine if specified path contains a legitimate
107 * configuration file name.
108 *
109 * Returns: TRUE if @path contains a valid configuration file name,
110 * else FALSE.
111 *
112 **/
113static inline int
114is_conf_file_std (const char *path)
115{
116 char *ptr = strrchr (path, '.');
117
118 if (ptr && IS_CONF_EXT_STD (ptr))
119 return TRUE;
120
121 return FALSE;
122}
123
124/**
125 * is_conf_file_override:
126 * @path: path to check.
127 *
128 * Determine if specified path contains a legitimate
129 * override file name.
130 *
131 * Returns: TRUE if @path contains a valid override file name,
132 * else FALSE.
133 *
134 **/
135static inline int
136is_conf_file_override (const char *path)
137{
138 char *ptr = strrchr (path, '.');
139
140 if (ptr && IS_CONF_EXT_OVERRIDE (ptr))
141 return TRUE;
142
143 return FALSE;
144}
145
146/**
147 * is_conf_file:
148 * @path: path to check.
149 *
150 * Determine if specified path contains a legitimate
151 * configuration file or override file name.
152 *
153 * Returns: TRUE if @path contains a valid configuration
154 * file or override file name, else FALSE.
155 *
156 **/
157static inline int
158is_conf_file (const char *path)
159{
160 char *ptr = strrchr (path, '.');
161
162 if (ptr && IS_CONF_EXT (ptr))
163 return TRUE;
164
165 return FALSE;
166}
167
168/**
169 * Convert a configuration file name to an override file name and vice
170 * versa.
171 *
172 * For example, if @path is "foo.conf", this function will return
173 * "foo.override", whereas if @path is "foo.override", it will return
174 * "foo.conf".
175 *
176 * Note that this function should be static, but isn't to allow the
177 * tests to access it.
178 *
179 * @parent: parent of returned path,
180 * @path: path to a configuration file.
181 *
182 * Returns: newly allocated toggled path, or NULL on error.
183 **/
184char *
185toggle_conf_name (const void *parent,
186 const char *path)
187{
188 char *new_path;
189 char *ext;
190 char *new_ext;
191 size_t len;
192
193 ext = strrchr (path, '.');
194 if (!ext)
195 return NULL;
196
197 new_ext = IS_CONF_EXT_STD (ext)
198 ? CONF_EXT_OVERRIDE
199 : CONF_EXT_STD;
200
201 len = strlen (new_ext);
202
203 new_path = NIH_MUST (nih_strndup (parent, path, (ext - path) + len));
204
205 memcpy (new_path + (ext - path), new_ext, len);
206
207 return new_path;
208}
209
210
211/**
89 * conf_init:212 * conf_init:
90 *213 *
91 * Initialise the conf_sources list.214 * Initialise the conf_sources list.
@@ -147,6 +270,7 @@
147270
148 source->type = type;271 source->type = type;
149 source->watch = NULL;272 source->watch = NULL;
273 source->session = NULL;
150274
151 source->flag = FALSE;275 source->flag = FALSE;
152 source->files = nih_hash_string_new (source, 0);276 source->files = nih_hash_string_new (source, 0);
@@ -233,10 +357,9 @@
233 NihError *err;357 NihError *err;
234358
235 err = nih_error_get ();359 err = nih_error_get ();
236 if (err->number != ENOENT)360 nih_error ("%s: %s: %s", source->path,
237 nih_error ("%s: %s: %s", source->path,361 _("Unable to load configuration"),
238 _("Unable to load configuration"),362 err->message);
239 err->message);
240 nih_free (err);363 nih_free (err);
241 }364 }
242 }365 }
@@ -329,10 +452,16 @@
329conf_source_reload_file (ConfSource *source)452conf_source_reload_file (ConfSource *source)
330{453{
331 NihError *err = NULL;454 NihError *err = NULL;
455 nih_local char *override_path = NULL;
456
457 struct stat statbuf;
332458
333 nih_assert (source != NULL);459 nih_assert (source != NULL);
334 nih_assert (source->type == CONF_FILE);460 nih_assert (source->type == CONF_FILE);
335461
462 /* this function should only be called for standard
463 * configuration files.
464 */
336 if (! source->watch) {465 if (! source->watch) {
337 nih_local char *dpath = NULL;466 nih_local char *dpath = NULL;
338 char *dname;467 char *dname;
@@ -361,7 +490,7 @@
361 /* Parse the file itself. If this fails, then we can discard the490 /* Parse the file itself. If this fails, then we can discard the
362 * inotify error, since this one will be better.491 * inotify error, since this one will be better.
363 */492 */
364 if (conf_reload_path (source, source->path) < 0) {493 if (conf_reload_path (source, source->path, NULL) < 0) {
365 if (err)494 if (err)
366 nih_free (err);495 nih_free (err);
367496
@@ -382,6 +511,23 @@
382 nih_free (err);511 nih_free (err);
383 }512 }
384513
514 if (! is_conf_file_std (source->path))
515 return 0;
516
517 override_path = toggle_conf_name (NULL, source->path);
518
519 if (stat (override_path, &statbuf) != 0)
520 return 0;
521
522 nih_debug ("Updating configuration for %s from %s",
523 source->path, override_path);
524 if (conf_reload_path (source, source->path, override_path) < 0) {
525 if (err)
526 nih_free (err);
527
528 return -1;
529 }
530
385 return 0;531 return 0;
386}532}
387533
@@ -501,19 +647,18 @@
501 * @is_dir: TRUE of @path is a directory.647 * @is_dir: TRUE of @path is a directory.
502 *648 *
503 * This is the file filter used for the jobs directory, we only care649 * This is the file filter used for the jobs directory, we only care
504 * about paths with the ".conf" extension. Directories that650 * about paths with particular extensions (see IS_CONF_EXT).
505 * match the nih_file_ignore() function are also ignored.651 *
506 *652 * Directories that match the nih_file_ignore() function are also ignored.
507 * Returns: FALSE if @path ends in ".conf", or is the original source,653 *
508 * TRUE otherwise.654 * Returns: FALSE if @path ends in ".conf" or ".override",
655 * or is the original source, TRUE otherwise.
509 **/656 **/
510static int657static int
511conf_dir_filter (ConfSource *source,658conf_dir_filter (ConfSource *source,
512 const char *path,659 const char *path,
513 int is_dir)660 int is_dir)
514{661{
515 char *ptr;
516
517 nih_assert (source != NULL);662 nih_assert (source != NULL);
518 nih_assert (path != NULL);663 nih_assert (path != NULL);
519664
@@ -523,8 +668,12 @@
523 if (is_dir)668 if (is_dir)
524 return nih_file_ignore (NULL, path);669 return nih_file_ignore (NULL, path);
525670
671<<<<<<< TREE
526 ptr = strrchr (path, '.');672 ptr = strrchr (path, '.');
527 if (ptr && (ptr > path) && (ptr[-1] != '/') && (! strcmp (ptr, ".conf")))673 if (ptr && (ptr > path) && (ptr[-1] != '/') && (! strcmp (ptr, ".conf")))
674=======
675 if (is_conf_file (path))
676>>>>>>> MERGE-SOURCE
528 return FALSE;677 return FALSE;
529678
530 return TRUE;679 return TRUE;
@@ -546,29 +695,92 @@
546 * After checking that it was a regular file that was changed, we reload it;695 * After checking that it was a regular file that was changed, we reload it;
547 * we expect this to fail sometimes since the file may be only partially696 * we expect this to fail sometimes since the file may be only partially
548 * written.697 * written.
549 **/698 **/
550static void699static void
551conf_create_modify_handler (ConfSource *source,700conf_create_modify_handler (ConfSource *source,
552 NihWatch *watch,701 NihWatch *watch,
553 const char *path,702 const char *path,
554 struct stat *statbuf)703 struct stat *statbuf)
555{704{
705 ConfFile *file = NULL;
706 const char *error_path = path;
707 nih_local char *new_path = NULL;
708 int ret;
709
556 nih_assert (source != NULL);710 nih_assert (source != NULL);
557 nih_assert (watch != NULL);711 nih_assert (watch != NULL);
558 nih_assert (path != NULL);712 nih_assert (path != NULL);
559 nih_assert (statbuf != NULL);713 nih_assert (statbuf != NULL);
560714
715 /* note that symbolic links are ignored */
561 if (! S_ISREG (statbuf->st_mode))716 if (! S_ISREG (statbuf->st_mode))
562 return;717 return;
563718
564 if (conf_reload_path (source, path) < 0) {719 new_path = toggle_conf_name (NULL, path);
720 file = (ConfFile *)nih_hash_lookup (source->files, new_path);
721
722 if (is_conf_file_override (path)) {
723 if (! file) {
724 /* override file has no corresponding conf file */
725 nih_debug ("Ignoring orphan override file %s", path);
726 return;
727 }
728
729 /* reload conf file */
730 nih_debug ("Loading configuration file %s", new_path);
731 ret = conf_reload_path (source, new_path, NULL);
732 if (ret < 0) {
733 error_path = new_path;
734 goto error;
735 }
736
737 /* overlay override settings */
738 nih_debug ("Loading override file %s for %s", path, new_path);
739 ret = conf_reload_path (source, new_path, path);
740 if (ret < 0) {
741 error_path = path;
742 goto error;
743 }
744 } else {
745 nih_debug ("Loading configuration and override files for %s", path);
746
747 /* load conf file */
748 nih_debug ("Loading configuration file %s", path);
749 ret = conf_reload_path (source, path, NULL);
750 if (ret < 0) {
751 error_path = path;
752 goto error;
753 }
754
755 /* ensure we ignore directory changes (which won't have overrides. */
756 if (is_conf_file_std (path)) {
757 struct stat st;
758 if (stat (new_path, &st) == 0) {
759 /* overlay override settings */
760 nih_debug ("Loading override file %s for %s", new_path, path);
761 ret = conf_reload_path (source, path, new_path);
762 if (ret < 0) {
763 error_path = new_path;
764 goto error;
765 }
766 }
767
768 }
769 }
770
771 return;
772
773error:
774 {
565 NihError *err;775 NihError *err;
566776
567 err = nih_error_get ();777 err = nih_error_get ();
568 nih_error ("%s: %s: %s", path,778 nih_error ("%s: %s: %s", error_path,
569 _("Error while loading configuration file"),779 _("Error while loading configuration file"),
570 err->message);780 err->message);
571 nih_free (err);781 nih_free (err);
782 if (file)
783 nih_unref (file, source);
572 }784 }
573}785}
574786
@@ -585,13 +797,14 @@
585 *797 *
586 * We lookup the file in our hash table, and if we can find it, perform798 * We lookup the file in our hash table, and if we can find it, perform
587 * the usual deletion of it.799 * the usual deletion of it.
588 **/800 **/
589static void801static void
590conf_delete_handler (ConfSource *source,802conf_delete_handler (ConfSource *source,
591 NihWatch *watch,803 NihWatch *watch,
592 const char *path)804 const char *path)
593{805{
594 ConfFile *file;806 ConfFile *file;
807 nih_local char *new_path = NULL;
595808
596 nih_assert (source != NULL);809 nih_assert (source != NULL);
597 nih_assert (watch != NULL);810 nih_assert (watch != NULL);
@@ -603,7 +816,11 @@
603 * it's probably a directory or something, so just ignore it.816 * it's probably a directory or something, so just ignore it.
604 */817 */
605 file = (ConfFile *)nih_hash_lookup (source->files, path);818 file = (ConfFile *)nih_hash_lookup (source->files, path);
606 if (! file) {819 /* Note we have to be careful to consider deletion of directories too.
820 * This is handled implicitly by the override check which will return
821 * false if passed a directory in this case.
822 */
823 if (! file && ! is_conf_file_override (path)) {
607 if (! strcmp (watch->path, path)) {824 if (! strcmp (watch->path, path)) {
608 nih_warn ("%s: %s", source->path,825 nih_warn ("%s: %s", source->path,
609 _("Configuration directory deleted"));826 _("Configuration directory deleted"));
@@ -614,7 +831,30 @@
614 return;831 return;
615 }832 }
616833
617 nih_unref (file, source);834 /* non-override files (and directories) are the simple case, so handle
835 * them and leave.
836 */
837 if (! is_conf_file_override (path)) {
838 nih_unref (file, source);
839 return;
840 }
841
842 /* if an override file is deleted for which there is a corresponding
843 * conf file, reload the conf file to remove any modifications
844 * introduced by the override file.
845 */
846 new_path = toggle_conf_name (NULL, path);
847 file = (ConfFile *)nih_hash_lookup (source->files, new_path);
848
849 if (file) {
850 nih_debug ("Reloading configuration for %s on deletion of overide (%s)",
851 new_path, path);
852
853 if ( conf_reload_path (source, new_path, NULL) < 0 ) {
854 nih_warn ("%s: %s", new_path,
855 _("Unable to reload configuration after override deletion"));
856 }
857 }
618}858}
619859
620/**860/**
@@ -637,22 +877,61 @@
637 const char *path,877 const char *path,
638 struct stat *statbuf)878 struct stat *statbuf)
639{879{
880 ConfFile *file = NULL;
881 nih_local char *new_path = NULL;
882
640 nih_assert (source != NULL);883 nih_assert (source != NULL);
641 nih_assert (dirname != NULL);884 nih_assert (dirname != NULL);
642 nih_assert (path != NULL);885 nih_assert (path != NULL);
643 nih_assert (statbuf != NULL);886 nih_assert (statbuf != NULL);
644887
888 /* We assume that CONF_EXT_STD files are visited before
889 * CONF_EXT_OVERRIDE files. Happily, this assumption is currently
890 * valid since CONF_EXT_STD comes before CONF_EXT_OVERRIDE if ordered
891 * alphabetically.
892 *
893 * If this were ever to change (for example if we decided to
894 * rename the CONF_EXT_OVERRIDE files to end in ".abc", say), the logic
895 * in this function would be erroneous since it would never be possible when
896 * visiting an override file (before a conf file) to lookup a conf file
897 * in the hash, since the conf file would not yet have been seen and thus would
898 * not exist in the hash (yet).
899 */
900 nih_assert (CONF_EXT_STD[1] < CONF_EXT_OVERRIDE[1]);
901
645 if (! S_ISREG (statbuf->st_mode))902 if (! S_ISREG (statbuf->st_mode))
646 return 0;903 return 0;
647904
648 if (conf_reload_path (source, path) < 0) {905 if (is_conf_file_std (path)) {
649 NihError *err;906 if (conf_reload_path (source, path, NULL) < 0) {
650907 NihError *err;
651 err = nih_error_get ();908
652 nih_error ("%s: %s: %s", path,909 err = nih_error_get ();
653 _("Error while loading configuration file"),910 nih_error ("%s: %s: %s", path,
654 err->message);911 _("Error while loading configuration file"),
655 nih_free (err);912 err->message);
913 nih_free (err);
914 }
915 return 0;
916 }
917
918 new_path = toggle_conf_name (NULL, path);
919 file = (ConfFile *)nih_hash_lookup (source->files, new_path);
920
921 if (file) {
922 /* we're visiting an override file with an associated conf file that
923 * has already been loaded, so just overlay the override file. If
924 * there is no corresponding conf file, we ignore the override file.
925 */
926 if (conf_reload_path (source, new_path, path) < 0) {
927 NihError *err;
928
929 err = nih_error_get ();
930 nih_error ("%s: %s: %s", new_path,
931 _("Error while reloading configuration file"),
932 err->message);
933 nih_free (err);
934 }
656 }935 }
657936
658 return 0;937 return 0;
@@ -662,16 +941,20 @@
662/**941/**
663 * conf_reload_path:942 * conf_reload_path:
664 * @source: configuration source,943 * @source: configuration source,
665 * @path: path of file to be reloaded.944 * @path: path of conf file to be reloaded.
945 * @override_path: if not NULL and @path refers to a path associated with @source,
946 * overlay the contents of @path into the existing @source entry for
947 * @path. If FALSE, discard any existing knowledge of @path.
666 *948 *
667 * This function is used to parse the file at @path in the context of the949 * This function is used to parse the file at @path (or @override_path) in the
668 * given configuration @source. Necessary ConfFile structures are allocated950 * context of the given configuration @source. Necessary ConfFile structures
669 * and attached to @source as appropriate. CONF_FILE sources always have951 * are allocated and attached to @source as appropriate. CONF_FILE sources
670 * a single ConfFile when the file exists.952 * always have a single ConfFile when the file exists.
671 *953 *
672 * If the file has been parsed before, then the existing item is deleted and954 * If the file has been parsed before, then the existing item is deleted and
673 * freed if the file fails to load, or after the new item has been parsed.955 * freed if the file fails to load, or after the new item has been parsed.
674 * Items are not reused between reloads.956 * Items are only reused between reloads if @override_path is
957 * non-NULL.
675 *958 *
676 * Physical errors are returned, parse errors are not.959 * Physical errors are returned, parse errors are not.
677 *960 *
@@ -679,36 +962,47 @@
679 **/962 **/
680static int963static int
681conf_reload_path (ConfSource *source,964conf_reload_path (ConfSource *source,
682 const char *path)965 const char *path,
966 const char *override_path)
683{967{
684 ConfFile *file;968 ConfFile *file = NULL;
685 nih_local char *buf = NULL;969 nih_local char *buf = NULL;
686 const char *start, *end;970 const char *start, *end;
687 nih_local char *name = NULL;971 nih_local char *name = NULL;
688 size_t len, pos, lineno;972 size_t len, pos, lineno;
689 NihError *err = NULL;973 NihError *err = NULL;
974 const char *path_to_load;
690975
691 nih_assert (source != NULL);976 nih_assert (source != NULL);
692 nih_assert (path != NULL);977 nih_assert (path != NULL);
693978
694 /* Look up the old file in memory, and then free it. In cases979 path_to_load = (override_path ? override_path : path);
695 * of failure, we discard it anyway, so there's no particular reason980
981 /* If there is no corresponding override file, look up the old
982 * conf file in memory, and then free it. In cases of failure,
983 * we discard it anyway, so there's no particular reason
696 * to keep it around anymore.984 * to keep it around anymore.
985 *
986 * Note: if @override_path has been specified, do not
987 * free the file if found, since we want to _update_ the
988 * existing entry.
697 */989 */
698 file = (ConfFile *)nih_hash_lookup (source->files, path);990 file = (ConfFile *)nih_hash_lookup (source->files, path);
699 if (file)991 if (! override_path && file)
700 nih_unref (file, source);992 nih_unref (file, source);
701993
702 /* Read the file into memory for parsing, if this fails we don't994 /* Read the file into memory for parsing, if this fails we don't
703 * bother creating a new ConfFile structure for it and bail out995 * bother creating a new ConfFile structure for it and bail out
704 * now.996 * now.
705 */997 */
706 buf = nih_file_read (NULL, path, &len);998 buf = nih_file_read (NULL, path_to_load, &len);
707 if (! buf)999 if (! buf)
708 return -1;1000 return -1;
7091001
710 /* Parse the file, storing the item in a new ConfFile structure. */1002 /* Create a new ConfFile structure (if no @override_path specified) */
711 file = NIH_MUST (conf_file_new (source, path));1003 file = (ConfFile *)nih_hash_lookup (source->files, path);
1004 if (! file)
1005 file = NIH_MUST (conf_file_new (source, path));
7121006
713 pos = 0;1007 pos = 0;
714 lineno = 1;1008 lineno = 1;
@@ -717,7 +1011,14 @@
717 case CONF_FILE:1011 case CONF_FILE:
718 case CONF_DIR:1012 case CONF_DIR:
719 /* Simple file of options; usually no item attached to it. */1013 /* Simple file of options; usually no item attached to it. */
720 nih_debug ("Loading configuration from %s", path);1014 if (override_path) {
1015 nih_debug ("Updating configuration for %s from %s",
1016 path, override_path);
1017 } else {
1018 nih_debug ("Loading configuration from %s %s",
1019 (source->type == CONF_DIR ? "directory" : "file"), path);
1020 }
1021
721 if (parse_conf (file, buf, len, &pos, &lineno) < 0)1022 if (parse_conf (file, buf, len, &pos, &lineno) < 0)
722 err = nih_error_get ();1023 err = nih_error_get ();
7231024
@@ -735,7 +1036,7 @@
735 start++;1036 start++;
7361037
737 end = strrchr (start, '.');1038 end = strrchr (start, '.');
738 if (end && (! strcmp (end, ".conf"))) {1039 if (end && IS_CONF_EXT (end)) {
739 name = NIH_MUST (nih_strndup (NULL, start, end - start));1040 name = NIH_MUST (nih_strndup (NULL, start, end - start));
740 } else {1041 } else {
741 name = NIH_MUST (nih_strdup (NULL, start));1042 name = NIH_MUST (nih_strdup (NULL, start));
@@ -744,8 +1045,14 @@
744 /* Create a new job item and parse the buffer to produce1045 /* Create a new job item and parse the buffer to produce
745 * the job definition.1046 * the job definition.
746 */1047 */
747 nih_debug ("Loading %s from %s", name, path);1048 if (override_path) {
748 file->job = parse_job (NULL, name, buf, len, &pos, &lineno);1049 nih_debug ("Updating %s (%s) with %s",
1050 name, path, override_path);
1051 } else {
1052 nih_debug ("Loading %s from %s", name, path);
1053 }
1054 file->job = parse_job (NULL, source->session, file->job,
1055 name, buf, len, &pos, &lineno);
749 if (file->job) {1056 if (file->job) {
750 job_class_consider (file->job);1057 job_class_consider (file->job);
751 } else {1058 } else {
@@ -779,7 +1086,7 @@
779 case PARSE_EXPECTED_OPERATOR:1086 case PARSE_EXPECTED_OPERATOR:
780 case PARSE_EXPECTED_VARIABLE:1087 case PARSE_EXPECTED_VARIABLE:
781 case PARSE_MISMATCHED_PARENS:1088 case PARSE_MISMATCHED_PARENS:
782 nih_error ("%s:%zi: %s", path, lineno, err->message);1089 nih_error ("%s:%zi: %s", path_to_load, lineno, err->message);
783 nih_free (err);1090 nih_free (err);
784 err = NULL;1091 err = NULL;
785 break;1092 break;
@@ -849,7 +1156,8 @@
8491156
850/**1157/**
851 * conf_select_job:1158 * conf_select_job:
852 * @name: name of job class to locate.1159 * @name: name of job class to locate,
1160 * @session: session class name belongs to.
853 *1161 *
854 * Select the best available class of a job named @name from the registered1162 * Select the best available class of a job named @name from the registered
855 * configuration sources.1163 * configuration sources.
@@ -857,7 +1165,7 @@
857 * Returns: Best available job class or NULL if none available.1165 * Returns: Best available job class or NULL if none available.
858 **/1166 **/
859JobClass *1167JobClass *
860conf_select_job (const char *name)1168conf_select_job (const char *name, const Session *session)
861{1169{
862 nih_assert (name != NULL);1170 nih_assert (name != NULL);
8631171
@@ -869,6 +1177,9 @@
869 if (source->type != CONF_JOB_DIR)1177 if (source->type != CONF_JOB_DIR)
870 continue;1178 continue;
8711179
1180 if (source->session != session)
1181 continue;
1182
872 NIH_HASH_FOREACH (source->files, file_iter) {1183 NIH_HASH_FOREACH (source->files, file_iter) {
873 ConfFile *file = (ConfFile *)file_iter;1184 ConfFile *file = (ConfFile *)file_iter;
8741185
@@ -882,3 +1193,149 @@
8821193
883 return NULL;1194 return NULL;
884}1195}
1196
1197#ifdef DEBUG
1198
1199size_t
1200debug_count_list_entries (const NihList *list)
1201{
1202 size_t i = 0;
1203 NIH_LIST_FOREACH (list, iter) {
1204 i++;
1205 }
1206 return i;
1207}
1208
1209size_t
1210debug_count_hash_entries (const NihHash *hash)
1211{
1212 size_t i = 0;
1213 NIH_HASH_FOREACH_SAFE (hash, iter) {
1214 i++;
1215 }
1216 return i;
1217}
1218
1219void
1220debug_show_job_class (const JobClass *job)
1221{
1222 int i;
1223 char **env = (char **)job->env;
1224 char **export = (char **)job->export;
1225
1226 nih_assert (job);
1227
1228 nih_debug ("JobClass %p: name='%s', path='%s', task=%d, "
1229 "respawn=%d, console=%x, deleted=%d, debug=%d",
1230 job, job->name, job->path, job->task,
1231 job->respawn, job->console, job->deleted, job->debug);
1232
1233 nih_debug ("\tstart_on=%p, stop_on=%p, emits=%p, process=%p",
1234 job->start_on, job->stop_on, job->emits, job->process);
1235
1236 nih_debug ("\tauthor='%s', description='%s'",
1237 job->author, job->description);
1238
1239 if (env && *env) {
1240 nih_debug ("\tenv:");
1241 i = 0;
1242 while ( *env ) {
1243 nih_debug ("\t\tenv[%d]='%s' (len=%u+1)",
1244 i, *env, strlen (*env));
1245 env++;
1246 ++i;
1247 }
1248 } else {
1249 nih_debug ("\tenv: none.");
1250 }
1251
1252
1253 if (export && *export) {
1254 nih_debug ("\texport:");
1255 i = 0;
1256 while ( *export ) {
1257 nih_debug ("\t\tenv[%d]='%s' (len=%u+1)",
1258 i, *export, strlen (*export));
1259 export++;
1260 ++i;
1261 }
1262 }
1263 else {
1264 nih_debug ("\texport: none");
1265 }
1266}
1267
1268void
1269debug_show_job_classes (void)
1270{
1271 nih_debug ("job_classes:");
1272
1273 NIH_HASH_FOREACH_SAFE (job_classes, iter) {
1274 JobClass *job = (JobClass *)iter;
1275 debug_show_job_class (job);
1276 }
1277}
1278
1279void
1280debug_show_event (const Event *event)
1281{
1282 nih_assert (event);
1283
1284 nih_debug ("Event %p: name='%s', progress=%x, failed=%d, "
1285 "blockers=%d, blocking=%p",
1286 event, event->name, event->progress, event->failed,
1287 event->blockers, (void *)&event->blocking);
1288}
1289
1290void
1291debug_show_conf_file (const ConfFile *file)
1292{
1293 nih_assert (file);
1294
1295 nih_debug ("ConfFile %p: path='%s', source=%p, flag=%x, job=%p",
1296 file, file->path, file->source, file->flag, file->job);
1297
1298 /* Some ConfFile objects won't have any JobClass details, for example,
1299 * the ConfFile object associated with "/etc/init.conf".
1300 */
1301 if (! file->job) {
1302 nih_debug ("ConfFile %p: job: no JobClass object.", file);
1303 return;
1304 }
1305
1306 nih_debug ("ConfFile %p: job:", file);
1307 debug_show_job_class (file->job);
1308}
1309
1310void
1311debug_show_conf_source (const ConfSource *source)
1312{
1313 nih_assert (source);
1314
1315 nih_debug ("ConfSource %p: path='%s', type=%x, flag=%x",
1316 source, source->path, source->type, source->flag);
1317
1318 nih_debug ("ConfSource %p files (%d):", source,
1319 debug_count_hash_entries (source->files));
1320
1321 NIH_HASH_FOREACH (source->files, file_iter) {
1322 ConfFile *file = (ConfFile *)file_iter;
1323 debug_show_conf_file (file);
1324 }
1325}
1326
1327void
1328debug_show_conf_sources (void)
1329{
1330 nih_assert (conf_sources);
1331
1332 nih_debug ("conf_sources:");
1333
1334 NIH_LIST_FOREACH (conf_sources, iter) {
1335 ConfSource *source = (ConfSource *)iter;
1336 debug_show_conf_source (source);
1337 }
1338}
1339
1340#endif /* DEBUG */
1341
8851342
=== modified file 'init/conf.h'
--- init/conf.h 2009-07-09 08:36:52 +0000
+++ init/conf.h 2011-04-27 14:11:41 +0000
@@ -1,6 +1,6 @@
1/* upstart1/* upstart
2 *2 *
3 * Copyright © 2009 Canonical Ltd.3 * Copyright © 2010 Canonical Ltd.
4 * Author: Scott James Remnant <scott@netsplit.com>.4 * Author: Scott James Remnant <scott@netsplit.com>.
5 *5 *
6 * This program is free software; you can redistribute it and/or modify6 * This program is free software; you can redistribute it and/or modify
@@ -26,6 +26,7 @@
26#include <nih/list.h>26#include <nih/list.h>
27#include <nih/watch.h>27#include <nih/watch.h>
2828
29#include "session.h"
29#include "job_class.h"30#include "job_class.h"
3031
3132
@@ -47,6 +48,7 @@
47/**48/**
48 * ConfSource:49 * ConfSource:
49 * @entry: list header,50 * @entry: list header,
51 * @session: attached session,
50 * @path: path to source,52 * @path: path to source,
51 * @type: type of source,53 * @type: type of source,
52 * @watch: NihWatch structure for automatic change notification,54 * @watch: NihWatch structure for automatic change notification,
@@ -64,6 +66,7 @@
64 **/66 **/
65typedef struct conf_source {67typedef struct conf_source {
66 NihList entry;68 NihList entry;
69 Session * session;
67 char *path;70 char *path;
68 ConfSourceType type;71 ConfSourceType type;
6972
@@ -122,7 +125,47 @@
122125
123int conf_file_destroy (ConfFile *file);126int conf_file_destroy (ConfFile *file);
124127
125JobClass * conf_select_job (const char *name);128JobClass * conf_select_job (const char *name, const Session *session);
129
130char *toggle_conf_name (const void *parent, const char *path)
131 __attribute__ ((warn_unused_result, malloc));
132
133#ifdef DEBUG
134
135/* used for debugging only */
136
137size_t
138debug_count_hash_entries (const NihHash *hash);
139
140size_t
141debug_count_list_entries (const NihList *list)
142 __attribute__ ((unused));
143
144void
145debug_show_job_class (const JobClass *job)
146 __attribute__ ((unused));
147
148void
149debug_show_job_classes (void)
150 __attribute__ ((unused));
151
152void
153debug_show_event (const Event *event)
154 __attribute__ ((unused));
155
156void
157debug_show_conf_file(const ConfFile *file)
158 __attribute__ ((unused));
159
160void
161debug_show_conf_source(const ConfSource *source)
162 __attribute__ ((unused));
163
164void
165debug_show_conf_sources(void)
166 __attribute__ ((unused));
167
168#endif
126169
127NIH_END_EXTERN170NIH_END_EXTERN
128171
129172
=== modified file 'init/control.c'
--- init/control.c 2009-07-11 11:47:12 +0000
+++ init/control.c 2011-04-27 14:11:41 +0000
@@ -2,7 +2,7 @@
2 *2 *
3 * control.c - D-Bus connections, objects and methods3 * control.c - D-Bus connections, objects and methods
4 *4 *
5 * Copyright © 2009 Canonical Ltd.5 * Copyright © 2010 Canonical Ltd.
6 * Author: Scott James Remnant <scott@netsplit.com>.6 * Author: Scott James Remnant <scott@netsplit.com>.
7 *7 *
8 * This program is free software; you can redistribute it and/or modify8 * This program is free software; you can redistribute it and/or modify
@@ -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>
@@ -46,6 +48,7 @@
46#include "dbus/upstart.h"48#include "dbus/upstart.h"
4749
48#include "environ.h"50#include "environ.h"
51#include "session.h"
49#include "job_class.h"52#include "job_class.h"
50#include "blocked.h"53#include "blocked.h"
51#include "conf.h"54#include "conf.h"
@@ -54,12 +57,19 @@
5457
55#include "com.ubuntu.Upstart.h"58#include "com.ubuntu.Upstart.h"
5659
57
58/* Prototypes for static functions */60/* Prototypes for static functions */
59static int control_server_connect (DBusServer *server, DBusConnection *conn);61static int control_server_connect (DBusServer *server, DBusConnection *conn);
60static void control_disconnected (DBusConnection *conn);62static void control_disconnected (DBusConnection *conn);
61static void control_register_all (DBusConnection *conn);63static void control_register_all (DBusConnection *conn);
6264
65/**
66 * use_session_bus:
67 *
68 * If TRUE, connect to the D-Bus session bus rather than the system bus.
69 *
70 * Used for testing.
71 **/
72int use_session_bus = FALSE;
6373
64/**74/**
65 * control_server_address:75 * control_server_address:
@@ -78,7 +88,7 @@
78/**88/**
79 * control_bus:89 * control_bus:
80 *90 *
81 * Open connection to D-Bus system bus. The connection may be opened with91 * Open connection to a D-Bus bus. The connection may be opened with
82 * control_bus_open() and if lost will become NULL.92 * control_bus_open() and if lost will become NULL.
83 **/93 **/
84DBusConnection *control_bus = NULL;94DBusConnection *control_bus = NULL;
@@ -86,7 +96,7 @@
86/**96/**
87 * control_conns:97 * control_conns:
88 *98 *
89 * Open control connections, including the connection to the D-Bus system99 * Open control connections, including the connection to a D-Bus
90 * bus and any private client connections.100 * bus and any private client connections.
91 **/101 **/
92NihList *control_conns = NULL;102NihList *control_conns = NULL;
@@ -190,8 +200,9 @@
190/**200/**
191 * control_bus_open:201 * control_bus_open:
192 *202 *
193 * Open a connection to the D-Bus system bus and store it in the control_bus203 * Open a connection to the appropriate D-Bus bus and store it in the
194 * global. The connection is handled automatically in the main loop.204 * control_bus global. The connection is handled automatically
205 * in the main loop.
195 *206 *
196 * Returns: zero on success, negative value on raised error.207 * Returns: zero on success, negative value on raised error.
197 **/208 **/
@@ -207,10 +218,13 @@
207218
208 control_init ();219 control_init ();
209220
221 control_handle_bus_type ();
222
210 /* Connect to the D-Bus System Bus and hook everything up into223 /* Connect to the D-Bus System Bus and hook everything up into
211 * our own main loop automatically.224 * our own main loop automatically.
212 */225 */
213 conn = nih_dbus_bus (DBUS_BUS_SYSTEM, control_disconnected);226 conn = nih_dbus_bus (use_session_bus ? DBUS_BUS_SESSION : DBUS_BUS_SYSTEM,
227 control_disconnected);
214 if (! conn)228 if (! conn)
215 return -1;229 return -1;
216230
@@ -382,7 +396,9 @@
382 const char *name,396 const char *name,
383 char **job)397 char **job)
384{398{
385 JobClass *class;399 Session *session;
400 JobClass *class = NULL;
401 JobClass *global_class = NULL;
386402
387 nih_assert (message != NULL);403 nih_assert (message != NULL);
388 nih_assert (name != NULL);404 nih_assert (name != NULL);
@@ -397,8 +413,30 @@
397 return -1;413 return -1;
398 }414 }
399415
400 /* Lookup the job and copy its path into the reply */416 /* Get the relevant session */
401 class = (JobClass *)nih_hash_lookup (job_classes, name);417 session = session_from_dbus (NULL, message);
418
419 /* Lookup the job */
420 class = (JobClass *)nih_hash_search (job_classes, name, NULL);
421
422 while (class && (class->session != session)) {
423
424 /* Found a match in the global session which may be used
425 * later if no matching user session job exists.
426 */
427 if ((! class->session) && (session && ! session->chroot))
428 global_class = class;
429
430 class = (JobClass *)nih_hash_search (job_classes, name,
431 &class->entry);
432 }
433
434 /* If no job with the given name exists in the appropriate
435 * session, look in the global namespace (aka the NULL session).
436 */
437 if (! class)
438 class = global_class;
439
402 if (! class) {440 if (! class) {
403 nih_dbus_error_raise_printf (441 nih_dbus_error_raise_printf (
404 DBUS_INTERFACE_UPSTART ".Error.UnknownJob",442 DBUS_INTERFACE_UPSTART ".Error.UnknownJob",
@@ -406,6 +444,7 @@
406 return -1;444 return -1;
407 }445 }
408446
447 /* Copy the path */
409 *job = nih_strdup (message, class->path);448 *job = nih_strdup (message, class->path);
410 if (! *job)449 if (! *job)
411 nih_return_system_error (-1);450 nih_return_system_error (-1);
@@ -432,6 +471,7 @@
432 NihDBusMessage *message,471 NihDBusMessage *message,
433 char ***jobs)472 char ***jobs)
434{473{
474 Session *session;
435 char **list;475 char **list;
436 size_t len;476 size_t len;
437477
@@ -445,9 +485,16 @@
445 if (! list)485 if (! list)
446 nih_return_system_error (-1);486 nih_return_system_error (-1);
447487
488 /* Get the relevant session */
489 session = session_from_dbus (NULL, message);
490
448 NIH_HASH_FOREACH (job_classes, iter) {491 NIH_HASH_FOREACH (job_classes, iter) {
449 JobClass *class = (JobClass *)iter;492 JobClass *class = (JobClass *)iter;
450493
494 if ((class->session || (session && session->chroot))
495 && (class->session != session))
496 continue;
497
451 if (! nih_str_array_add (&list, message, &len,498 if (! nih_str_array_add (&list, message, &len,
452 class->path)) {499 class->path)) {
453 nih_error_raise_system ();500 nih_error_raise_system ();
@@ -462,13 +509,24 @@
462}509}
463510
464511
512int
513control_emit_event (void *data,
514 NihDBusMessage *message,
515 const char *name,
516 char * const *env,
517 int wait)
518{
519 return control_emit_event_with_file (data, message, name, env, wait, -1);
520}
521
465/**522/**
466 * control_emit_event:523 * control_emit_event_with_file:
467 * @data: not used,524 * @data: not used,
468 * @message: D-Bus connection and message received,525 * @message: D-Bus connection and message received,
469 * @name: name of event to emit,526 * @name: name of event to emit,
470 * @env: environment of environment,527 * @env: environment of environment,
471 * @wait: whether to wait for event completion before returning.528 * @wait: whether to wait for event completion before returning,
529 * @file: file descriptor.
472 *530 *
473 * Implements the top half of the EmitEvent method of the com.ubuntu.Upstart531 * Implements the top half of the EmitEvent method of the com.ubuntu.Upstart
474 * interface, the bottom half may be found in event_finished().532 * interface, the bottom half may be found in event_finished().
@@ -488,11 +546,12 @@
488 * Returns: zero on success, negative value on raised error.546 * Returns: zero on success, negative value on raised error.
489 **/547 **/
490int548int
491control_emit_event (void *data,549control_emit_event_with_file (void *data,
492 NihDBusMessage *message,550 NihDBusMessage *message,
493 const char *name,551 const char *name,
494 char * const *env,552 char * const *env,
495 int wait)553 int wait,
554 int file)
496{555{
497 Event *event;556 Event *event;
498 Blocked *blocked;557 Blocked *blocked;
@@ -505,6 +564,7 @@
505 if (! strlen (name)) {564 if (! strlen (name)) {
506 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,565 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
507 _("Name may not be empty string"));566 _("Name may not be empty string"));
567 close (file);
508 return -1;568 return -1;
509 }569 }
510570
@@ -512,19 +572,36 @@
512 if (! environ_all_valid (env)) {572 if (! environ_all_valid (env)) {
513 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,573 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
514 _("Env must be KEY=VALUE pairs"));574 _("Env must be KEY=VALUE pairs"));
575 close (file);
515 return -1;576 return -1;
516 }577 }
517578
518 /* Make the event and block the message on it */579 /* Make the event and block the message on it */
519 event = event_new (NULL, name, (char **)env);580 event = event_new (NULL, name, (char **)env);
520 if (! event)581 if (! event) {
521 nih_return_system_error (-1);582 nih_error_raise_system ();
583 close (file);
584 return -1;
585 }
586
587 event->fd = file;
588 if (event->fd >= 0) {
589 long flags;
590
591 flags = fcntl (event->fd, F_GETFD);
592 flags &= ~FD_CLOEXEC;
593 fcntl (event->fd, F_SETFD, flags);
594 }
595
596 /* Obtain the session */
597 event->session = session_from_dbus (NULL, message);
522598
523 if (wait) {599 if (wait) {
524 blocked = blocked_new (event, BLOCKED_EMIT_METHOD, message);600 blocked = blocked_new (event, BLOCKED_EMIT_METHOD, message);
525 if (! blocked) {601 if (! blocked) {
526 nih_error_raise_system ();602 nih_error_raise_system ();
527 nih_free (event);603 nih_free (event);
604 close (file);
528 return -1;605 return -1;
529 }606 }
530607
@@ -669,3 +746,18 @@
669746
670 return 0;747 return 0;
671}748}
749
750/**
751 * control_handle_bus_type:
752 *
753 * Determine D-Bus bus type to connect to.
754 **/
755void
756control_handle_bus_type (void)
757{
758 if (getenv (USE_SESSION_BUS_ENV))
759 use_session_bus = TRUE;
760
761 if (use_session_bus)
762 nih_debug ("Using session bus");
763}
672764
=== modified file 'init/control.h'
--- init/control.h 2009-07-09 08:36:52 +0000
+++ init/control.h 2011-04-27 14:11:41 +0000
@@ -27,6 +27,18 @@
27#include <nih-dbus/dbus_connection.h>27#include <nih-dbus/dbus_connection.h>
28#include <nih-dbus/dbus_message.h>28#include <nih-dbus/dbus_message.h>
2929
30/**
31 * USE_SESSION_BUS_ENV:
32 *
33 * If this environment variable is set to any value, connect to
34 * D-Bus session bus rather than the system bus.
35 *
36 * Used for testing.
37 **/
38#ifndef USE_SESSION_BUS_ENV
39#define USE_SESSION_BUS_ENV "UPSTART_USE_SESSION_BUS"
40#endif
41
3042
31NIH_BEGIN_EXTERN43NIH_BEGIN_EXTERN
3244
@@ -60,6 +72,10 @@
60 const char *name, char * const *env,72 const char *name, char * const *env,
61 int wait)73 int wait)
62 __attribute__ ((warn_unused_result));74 __attribute__ ((warn_unused_result));
75int control_emit_event_with_file (void *data, NihDBusMessage *message,
76 const char *name, char * const *env,
77 int wait, int file)
78 __attribute__ ((warn_unused_result));
6379
64int control_get_version (void *data, NihDBusMessage *message,80int control_get_version (void *data, NihDBusMessage *message,
65 char **version)81 char **version)
@@ -72,6 +88,8 @@
72 const char *log_priority)88 const char *log_priority)
73 __attribute__ ((warn_unused_result));89 __attribute__ ((warn_unused_result));
7490
91void control_handle_bus_type (void);
92
75NIH_END_EXTERN93NIH_END_EXTERN
7694
77#endif /* INIT_CONTROL_H */95#endif /* INIT_CONTROL_H */
7896
=== modified file 'init/event.c'
--- init/event.c 2010-12-14 15:32:41 +0000
+++ init/event.c 2011-04-27 14:11:41 +0000
@@ -2,7 +2,7 @@
2 *2 *
3 * event.c - event queue and handling3 * event.c - event queue and handling
4 *4 *
5 * Copyright © 2010 Canonical Ltd.5 * Copyright © 2009, 2010 Canonical Ltd.
6 * Author: Scott James Remnant <scott@netsplit.com>.6 * Author: Scott James Remnant <scott@netsplit.com>.
7 *7 *
8 * This program is free software; you can redistribute it and/or modify8 * This program is free software; you can redistribute it and/or modify
@@ -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->session = NULL;
128 event->fd = -1;
126 event->progress = EVENT_PENDING;129 event->progress = EVENT_PENDING;
127 event->failed = FALSE;130 event->failed = FALSE;
128131
@@ -293,6 +296,13 @@
293 NIH_HASH_FOREACH_SAFE (job_classes, iter) {296 NIH_HASH_FOREACH_SAFE (job_classes, iter) {
294 JobClass *class = (JobClass *)iter;297 JobClass *class = (JobClass *)iter;
295298
299 /* Only affect jobs within the same session as the event
300 * unless the event has no session, in which case do them
301 * all.
302 */
303 if (event->session && (class->session != event->session))
304 continue;
305
296 /* We stop first so that if an event is listed both as a306 /* We stop first so that if an event is listed both as a
297 * stop and start event, it causes an active running process307 * stop and start event, it causes an active running process
298 * to be killed, the stop script then the start script to be308 * to be killed, the stop script then the start script to be
@@ -393,8 +403,16 @@
393 job->start_env = env;403 job->start_env = env;
394 nih_ref (job->start_env, job);404 nih_ref (job->start_env, job);
395405
406 nih_discard (env);
407 env = NULL;
408
396 job_finished (job, FALSE);409 job_finished (job, FALSE);
397410
411 NIH_MUST (event_operator_fds (class->start_on, job,
412 &job->fds, &job->num_fds,
413 &job->start_env, &len,
414 "UPSTART_FDS"));
415
398 event_operator_events (job->class->start_on,416 event_operator_events (job->class->start_on,
399 job, &job->blocking);417 job, &job->blocking);
400418
@@ -459,6 +477,8 @@
459 nih_free (blocked);477 nih_free (blocked);
460 }478 }
461479
480 close (event->fd);
481
462 if (event->failed) {482 if (event->failed) {
463 char *name;483 char *name;
464484
@@ -470,6 +490,7 @@
470 failed = NIH_MUST (nih_sprintf (NULL, "%s/failed",490 failed = NIH_MUST (nih_sprintf (NULL, "%s/failed",
471 event->name));491 event->name));
472 new_event = NIH_MUST (event_new (NULL, failed, NULL));492 new_event = NIH_MUST (event_new (NULL, failed, NULL));
493 new_event->session = event->session;
473494
474 if (event->env)495 if (event->env)
475 new_event->env = NIH_MUST (nih_str_array_copy (496 new_event->env = NIH_MUST (nih_str_array_copy (
476497
=== modified file 'init/event.h'
--- init/event.h 2009-07-09 08:36:52 +0000
+++ init/event.h 2011-04-27 14:11:41 +0000
@@ -1,6 +1,6 @@
1/* upstart1/* upstart
2 *2 *
3 * Copyright © 2009 Canonical Ltd.3 * Copyright © 2010 Canonical Ltd.
4 * Author: Scott James Remnant <scott@netsplit.com>.4 * Author: Scott James Remnant <scott@netsplit.com>.
5 *5 *
6 * This program is free software; you can redistribute it and/or modify6 * This program is free software; you can redistribute it and/or modify
@@ -23,6 +23,8 @@
23#include <nih/macros.h>23#include <nih/macros.h>
24#include <nih/list.h>24#include <nih/list.h>
2525
26#include "session.h"
27
2628
27/**29/**
28 * EventProgress:30 * EventProgress:
@@ -40,6 +42,7 @@
40/**42/**
41 * Event:43 * Event:
42 * @entry: list header,44 * @entry: list header,
45 * @session: session the event is attached to,
43 * @name: string name of the event,46 * @name: string name of the event,
44 * @env: NULL-terminated array of environment variables,47 * @env: NULL-terminated array of environment variables,
45 * @progress: progress of event,48 * @progress: progress of event,
@@ -61,8 +64,10 @@
61typedef struct event {64typedef struct event {
62 NihList entry;65 NihList entry;
6366
67 Session * session;
64 char *name;68 char *name;
65 char **env;69 char **env;
70 int fd;
6671
67 EventProgress progress;72 EventProgress progress;
68 int failed;73 int failed;
6974
=== modified file 'init/event_operator.c'
--- init/event_operator.c 2010-11-19 14:34:51 +0000
+++ init/event_operator.c 2011-04-27 14:11:41 +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-04-27 14:11:41 +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-04-27 14:11:41 +0000
@@ -47,6 +47,7 @@
47#include "events.h"47#include "events.h"
48#include "environ.h"48#include "environ.h"
49#include "process.h"49#include "process.h"
50#include "session.h"
50#include "job_class.h"51#include "job_class.h"
51#include "job.h"52#include "job.h"
52#include "job_process.h"53#include "job_process.h"
@@ -99,8 +100,14 @@
99100
100 job->class = class;101 job->class = class;
101102
102 job->path = nih_dbus_path (job, DBUS_PATH_UPSTART, "jobs",103 if (job->class->session && job->class->session->chroot) {
103 class->name, job->name, NULL);104 /* JobClass already contains a valid D-Bus path prefix for the job */
105 job->path = nih_dbus_path (job, class->path, job->name, NULL);
106 } else {
107 job->path = nih_dbus_path (job, DBUS_PATH_UPSTART, "jobs",
108 class->name, job->name, NULL);
109 }
110
104 if (! job->path)111 if (! job->path)
105 goto error;112 goto error;
106113
@@ -118,6 +125,9 @@
118 goto error;125 goto error;
119 }126 }
120127
128 job->fds = NULL;
129 job->num_fds = 0;
130
121 job->pid = nih_alloc (job, sizeof (pid_t) * PROCESS_LAST);131 job->pid = nih_alloc (job, sizeof (pid_t) * PROCESS_LAST);
122 if (! job->pid)132 if (! job->pid)
123 goto error;133 goto error;
@@ -906,6 +916,7 @@
906 }916 }
907917
908 event = NIH_MUST (event_new (NULL, name, env));918 event = NIH_MUST (event_new (NULL, name, env));
919 event->session = job->class->session;
909920
910 if (block) {921 if (block) {
911 Blocked *blocked;922 Blocked *blocked;
@@ -1102,11 +1113,22 @@
1102 NihDBusMessage *message,1113 NihDBusMessage *message,
1103 int wait)1114 int wait)
1104{1115{
1116 Session *session;
1105 Blocked *blocked = NULL;1117 Blocked *blocked = NULL;
11061118
1107 nih_assert (job != NULL);1119 nih_assert (job != NULL);
1108 nih_assert (message != NULL);1120 nih_assert (message != NULL);
11091121
1122 /* Don't permit out-of-session modification */
1123 session = session_from_dbus (NULL, message);
1124 if (session != job->class->session) {
1125 nih_dbus_error_raise_printf (
1126 DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1127 _("You do not have permission to modify job: %s"),
1128 job_name (job));
1129 return -1;
1130 }
1131
1110 if (job->goal == JOB_START) {1132 if (job->goal == JOB_START) {
1111 nih_dbus_error_raise_printf (1133 nih_dbus_error_raise_printf (
1112 DBUS_INTERFACE_UPSTART ".Error.AlreadyStarted",1134 DBUS_INTERFACE_UPSTART ".Error.AlreadyStarted",
@@ -1166,11 +1188,22 @@
1166 NihDBusMessage *message,1188 NihDBusMessage *message,
1167 int wait)1189 int wait)
1168{1190{
1191 Session *session;
1169 Blocked *blocked = NULL;1192 Blocked *blocked = NULL;
11701193
1171 nih_assert (job != NULL);1194 nih_assert (job != NULL);
1172 nih_assert (message != NULL);1195 nih_assert (message != NULL);
11731196
1197 /* Don't permit out-of-session modification */
1198 session = session_from_dbus (NULL, message);
1199 if (session != job->class->session) {
1200 nih_dbus_error_raise_printf (
1201 DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1202 _("You do not have permission to modify job: %s"),
1203 job_name (job));
1204 return -1;
1205 }
1206
1174 if (job->goal == JOB_STOP) {1207 if (job->goal == JOB_STOP) {
1175 nih_dbus_error_raise_printf (1208 nih_dbus_error_raise_printf (
1176 DBUS_INTERFACE_UPSTART ".Error.AlreadyStopped",1209 DBUS_INTERFACE_UPSTART ".Error.AlreadyStopped",
@@ -1231,11 +1264,22 @@
1231 NihDBusMessage *message,1264 NihDBusMessage *message,
1232 int wait)1265 int wait)
1233{1266{
1267 Session *session;
1234 Blocked *blocked = NULL;1268 Blocked *blocked = NULL;
12351269
1236 nih_assert (job != NULL);1270 nih_assert (job != NULL);
1237 nih_assert (message != NULL);1271 nih_assert (message != NULL);
12381272
1273 /* Don't permit out-of-session modification */
1274 session = session_from_dbus (NULL, message);
1275 if (session != job->class->session) {
1276 nih_dbus_error_raise_printf (
1277 DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1278 _("You do not have permission to modify job: %s"),
1279 job_name (job));
1280 return -1;
1281 }
1282
1239 if (job->goal == JOB_STOP) {1283 if (job->goal == JOB_STOP) {
1240 nih_dbus_error_raise_printf (1284 nih_dbus_error_raise_printf (
1241 DBUS_INTERFACE_UPSTART ".Error.AlreadyStopped",1285 DBUS_INTERFACE_UPSTART ".Error.AlreadyStopped",
12421286
=== modified file 'init/job.h'
--- init/job.h 2009-07-03 16:38:02 +0000
+++ init/job.h 2011-04-27 14:11:41 +0000
@@ -1,6 +1,6 @@
1/* upstart1/* upstart
2 *2 *
3 * Copyright © 2009 Canonical Ltd.3 * Copyright © 2010 Canonical Ltd.
4 * Author: Scott James Remnant <scott@netsplit.com>.4 * Author: Scott James Remnant <scott@netsplit.com>.
5 *5 *
6 * This program is free software; you can redistribute it and/or modify6 * This program is free software; you can redistribute it and/or modify
@@ -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 'init/job_class.c'
--- init/job_class.c 2010-12-14 15:30:06 +0000
+++ init/job_class.c 2011-04-27 14:11:41 +0000
@@ -44,6 +44,7 @@
4444
45#include "environ.h"45#include "environ.h"
46#include "process.h"46#include "process.h"
47#include "session.h"
47#include "job_class.h"48#include "job_class.h"
48#include "job.h"49#include "job.h"
49#include "event_operator.h"50#include "event_operator.h"
@@ -99,7 +100,7 @@
99100
100/* Prototypes for static functions */101/* Prototypes for static functions */
101static void job_class_add (JobClass *class);102static void job_class_add (JobClass *class);
102static int job_class_remove (JobClass *class);103static int job_class_remove (JobClass *class, const Session *session);
103104
104105
105/**106/**
@@ -127,13 +128,15 @@
127128
128/**129/**
129 * job_class_new:130 * job_class_new:
131 *
130 * @parent: parent for new job class,132 * @parent: parent for new job class,
131 * @name: name of new job class.133 * @name: name of new job class,
134 * @session: session.
132 *135 *
133 * Allocates and returns a new JobClass structure with the @name given.136 * Allocates and returns a new JobClass structure with the given @name
134 * It will not be automatically added to the job classes table, it is up137 * and @session. It will not be automatically added to the job classes
135 * to the caller to ensure this is done using job_class_register() once138 * table, it is up to the caller to ensure this is done using
136 * the class has been set up.139 * job_class_register() once the class has been set up.
137 *140 *
138 * If @parent is not NULL, it should be a pointer to another object which141 * If @parent is not NULL, it should be a pointer to another object which
139 * will be used as a parent for the returned job class. When all parents142 * will be used as a parent for the returned job class. When all parents
@@ -144,7 +147,8 @@
144 **/147 **/
145JobClass *148JobClass *
146job_class_new (const void *parent,149job_class_new (const void *parent,
147 const char *name)150 const char *name,
151 Session * session)
148{152{
149 JobClass *class;153 JobClass *class;
150 int i;154 int i;
@@ -164,8 +168,41 @@
164 if (! class->name)168 if (! class->name)
165 goto error;169 goto error;
166170
167 class->path = nih_dbus_path (class, DBUS_PATH_UPSTART, "jobs",171 class->session = session;
168 class->name, NULL);172 if (class->session
173 && class->session->chroot
174 && class->session->user) {
175 nih_local char *uid = NULL;
176
177 uid = nih_sprintf (NULL, "%d", class->session->user);
178 if (! uid)
179 goto error;
180
181 class->path = nih_dbus_path (class, DBUS_PATH_UPSTART, "jobs",
182 session->chroot, uid,
183 class->name, NULL);
184
185 } else if (class->session
186 && class->session->chroot) {
187 class->path = nih_dbus_path (class, DBUS_PATH_UPSTART, "jobs",
188 session->chroot,
189 class->name, NULL);
190
191 } else if (class->session
192 && class->session->user) {
193 nih_local char *uid = NULL;
194
195 uid = nih_sprintf (NULL, "%d", class->session->user);
196 if (! uid)
197 goto error;
198
199 class->path = nih_dbus_path (class, DBUS_PATH_UPSTART, "jobs",
200 uid, class->name, NULL);
201
202 } else {
203 class->path = nih_dbus_path (class, DBUS_PATH_UPSTART, "jobs",
204 class->name, NULL);
205 }
169 if (! class->path)206 if (! class->path)
170 goto error;207 goto error;
171208
@@ -220,7 +257,7 @@
220 class->chdir = NULL;257 class->chdir = NULL;
221258
222 class->deleted = FALSE;259 class->deleted = FALSE;
223 class->debug = FALSE;260 class->debug = FALSE;
224261
225 return class;262 return class;
226263
@@ -243,19 +280,27 @@
243int280int
244job_class_consider (JobClass *class)281job_class_consider (JobClass *class)
245{282{
246 JobClass *registered, *best;283 JobClass *registered = NULL, *best = NULL;
247284
248 nih_assert (class != NULL);285 nih_assert (class != NULL);
249286
250 job_class_init ();287 job_class_init ();
251288
252 best = conf_select_job (class->name);289 best = conf_select_job (class->name, class->session);
253 nih_assert (best != NULL);290 nih_assert (best != NULL);
254291 nih_assert (best->session == class->session);
255 registered = (JobClass *)nih_hash_lookup (job_classes, class->name);292
293 registered = (JobClass *)nih_hash_search (job_classes, class->name, NULL);
294
295 /* If we found an entry, ensure we only consider the appropriate session */
296 while (registered && registered->session != class->session)
297 {
298 registered = (JobClass *)nih_hash_search (job_classes, class->name, &registered->entry);
299 }
300
256 if (registered != best) {301 if (registered != best) {
257 if (registered)302 if (registered)
258 if (! job_class_remove (registered))303 if (! job_class_remove (registered, class->session))
259 return FALSE;304 return FALSE;
260305
261 job_class_add (best);306 job_class_add (best);
@@ -280,18 +325,25 @@
280int325int
281job_class_reconsider (JobClass *class)326job_class_reconsider (JobClass *class)
282{327{
283 JobClass *registered, *best;328 JobClass *registered = NULL, *best = NULL;
284329
285 nih_assert (class != NULL);330 nih_assert (class != NULL);
286331
287 job_class_init ();332 job_class_init ();
288333
289 best = conf_select_job (class->name);334 best = conf_select_job (class->name, class->session);
290335
291 registered = (JobClass *)nih_hash_lookup (job_classes, class->name);336 registered = (JobClass *)nih_hash_search (job_classes, class->name, NULL);
337
338 /* If we found an entry, ensure we only consider the appropriate session */
339 while (registered && registered->session != class->session)
340 {
341 registered = (JobClass *)nih_hash_search (job_classes, class->name, &registered->entry);
342 }
343
292 if (registered == class) {344 if (registered == class) {
293 if (class != best) {345 if (class != best) {
294 if (! job_class_remove (class))346 if (! job_class_remove (class, class->session))
295 return FALSE;347 return FALSE;
296348
297 job_class_add (best);349 job_class_add (best);
@@ -332,19 +384,24 @@
332384
333/**385/**
334 * job_class_remove:386 * job_class_remove:
335 * @class: class to remove.387 * @class: class to remove,
388 * @session: Session of @class.
336 *389 *
337 * Removes @class from the hash table and unregisters it from all current390 * Removes @class from the hash table and unregisters it from all current
338 * D-Bus connections.391 * D-Bus connections.
339 *392 *
340 * Returns: TRUE if class could be unregistered, FALSE if there are393 * Returns: TRUE if class could be unregistered, FALSE if there are
341 * active instances that prevent unregistration.394 * active instances that prevent unregistration, or if @session
395 * does not match the session associated with @class.
342 **/396 **/
343static int397static int
344job_class_remove (JobClass *class)398job_class_remove (JobClass *class, const Session *session)
345{399{
346 nih_assert (class != NULL);400 nih_assert (class != NULL);
347401
402 if (class->session != session)
403 return FALSE;
404
348 control_init ();405 control_init ();
349406
350 /* Return if we have any active instances */407 /* Return if we have any active instances */
@@ -694,6 +751,7 @@
694 char * const *env,751 char * const *env,
695 int wait)752 int wait)
696{753{
754 Session *session;
697 Blocked *blocked = NULL;755 Blocked *blocked = NULL;
698 Job *job;756 Job *job;
699 nih_local char **start_env = NULL;757 nih_local char **start_env = NULL;
@@ -704,6 +762,16 @@
704 nih_assert (message != NULL);762 nih_assert (message != NULL);
705 nih_assert (env != NULL);763 nih_assert (env != NULL);
706764
765 /* Don't permit out-of-session modification */
766 session = session_from_dbus (NULL, message);
767 if (session != class->session) {
768 nih_dbus_error_raise_printf (
769 DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
770 _("You do not have permission to modify job: %s"),
771 class->name);
772 return -1;
773 }
774
707 /* Verify that the environment is valid */775 /* Verify that the environment is valid */
708 if (! environ_all_valid (env)) {776 if (! environ_all_valid (env)) {
709 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,777 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
@@ -813,6 +881,7 @@
813 char * const *env,881 char * const *env,
814 int wait)882 int wait)
815{883{
884 Session *session;
816 Blocked *blocked = NULL;885 Blocked *blocked = NULL;
817 Job *job;886 Job *job;
818 nih_local char **stop_env = NULL;887 nih_local char **stop_env = NULL;
@@ -823,6 +892,16 @@
823 nih_assert (message != NULL);892 nih_assert (message != NULL);
824 nih_assert (env != NULL);893 nih_assert (env != NULL);
825894
895 /* Don't permit out-of-session modification */
896 session = session_from_dbus (NULL, message);
897 if (session != class->session) {
898 nih_dbus_error_raise_printf (
899 DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
900 _("You do not have permission to modify job: %s"),
901 class->name);
902 return -1;
903 }
904
826 /* Verify that the environment is valid */905 /* Verify that the environment is valid */
827 if (! environ_all_valid (env)) {906 if (! environ_all_valid (env)) {
828 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,907 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
@@ -937,6 +1016,7 @@
937 char * const *env,1016 char * const *env,
938 int wait)1017 int wait)
939{1018{
1019 Session *session;
940 Blocked *blocked = NULL;1020 Blocked *blocked = NULL;
941 Job *job;1021 Job *job;
942 nih_local char **restart_env = NULL;1022 nih_local char **restart_env = NULL;
@@ -947,6 +1027,16 @@
947 nih_assert (message != NULL);1027 nih_assert (message != NULL);
948 nih_assert (env != NULL);1028 nih_assert (env != NULL);
9491029
1030 /* Don't permit out-of-session modification */
1031 session = session_from_dbus (NULL, message);
1032 if (session != class->session) {
1033 nih_dbus_error_raise_printf (
1034 DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1035 _("You do not have permission to modify job: %s"),
1036 class->name);
1037 return -1;
1038 }
1039
950 /* Verify that the environment is valid */1040 /* Verify that the environment is valid */
951 if (! environ_all_valid (env)) {1041 if (! environ_all_valid (env)) {
952 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,1042 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
9531043
=== modified file 'init/job_class.h'
--- init/job_class.h 2010-12-14 15:30:06 +0000
+++ init/job_class.h 2011-04-27 14:11:41 +0000
@@ -35,6 +35,7 @@
3535
36#include "process.h"36#include "process.h"
37#include "event_operator.h"37#include "event_operator.h"
38#include "session.h"
3839
3940
40/**41/**
@@ -71,6 +72,7 @@
71 * @entry: list header,72 * @entry: list header,
72 * @name: unique name,73 * @name: unique name,
73 * @path: path of D-Bus object,74 * @path: path of D-Bus object,
75 * @session: attached session,
74 * @instance: pattern to uniquely identify multiple instances,76 * @instance: pattern to uniquely identify multiple instances,
75 * @instances: hash table of active instances,77 * @instances: hash table of active instances,
76 * @description: description; intended for humans,78 * @description: description; intended for humans,
@@ -109,6 +111,7 @@
109111
110 char *name;112 char *name;
111 char *path;113 char *path;
114 Session * session;
112115
113 char *instance;116 char *instance;
114 NihHash *instances;117 NihHash *instances;
@@ -159,7 +162,8 @@
159void job_class_init (void);162void job_class_init (void);
160163
161JobClass * job_class_new (const void *parent,164JobClass * job_class_new (const void *parent,
162 const char *name)165 const char *name,
166 Session *session)
163 __attribute__ ((warn_unused_result, malloc));167 __attribute__ ((warn_unused_result, malloc));
164168
165int job_class_consider (JobClass *class);169int job_class_consider (JobClass *class);
166170
=== modified file 'init/job_process.c'
--- init/job_process.c 2011-03-22 17:46:46 +0000
+++ init/job_process.c 2011-04-27 14:11:41 +0000
@@ -41,6 +41,7 @@
41#include <unistd.h>41#include <unistd.h>
42#include <utmp.h>42#include <utmp.h>
43#include <utmpx.h>43#include <utmpx.h>
44#include <pwd.h>
4445
45#include <nih/macros.h>46#include <nih/macros.h>
46#include <nih/alloc.h>47#include <nih/alloc.h>
@@ -511,6 +512,16 @@
511 }512 }
512 }513 }
513514
515 /* Handle changing a chroot session job prior to dealing with
516 * the 'chroot' stanza.
517 */
518 if (class->session && class->session->chroot) {
519 if (chroot (class->session->chroot) < 0) {
520 nih_error_raise_system ();
521 job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CHROOT, 0);
522 }
523 }
524
514 /* Change the root directory, confining path resolution within it;525 /* Change the root directory, confining path resolution within it;
515 * we do this before the working directory call so that is always526 * we do this before the working directory call so that is always
516 * relative to the new root.527 * relative to the new root.
@@ -566,6 +577,54 @@
566 }577 }
567 }578 }
568579
580 /* Handle unprivileged user job by dropping privileges to
581 * their level.
582 */
583 if (class->session && class->session->user) {
584 uid_t uid = class->session->user;
585 struct passwd *pw = NULL;
586
587 /* D-Bus does not expose a public API call to allow
588 * us to query a users primary group.
589 * _dbus_user_info_fill_uid () seems to exist for this
590 * purpose, but is a "secret" API. It is unclear why
591 * D-Bus neglects the gid when it allows the uid
592 * to be queried directly.
593 *
594 * Our only recourse is to disallow user sessions in a
595 * chroot and assume that all other user sessions
596 * originate from the local system. In this way, we can
597 * bypass D-Bus and use getpwuid ().
598 */
599
600 if (class->session->chroot) {
601 /* We cannot determine the group id of the user
602 * session in the chroot via D-Bus, so disallow
603 * all jobs in such an environment.
604 */
605 _nih_error_raise (__FILE__, __LINE__, __FUNCTION__,
606 EPERM, strerror (EPERM));
607 }
608
609 pw = getpwuid (uid);
610
611 if (!pw)
612 nih_return_system_error (-1);
613
614 nih_assert (pw->pw_uid == uid);
615
616 if (uid && setuid (uid) < 0) {
617 nih_error_raise_system ();
618 job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SETUID, 0);
619 }
620
621 if (pw->pw_gid && setgid (pw->pw_gid) < 0) {
622 nih_error_raise_system ();
623 job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SETGID, 0);
624 }
625 }
626
627
569 /* Execute the process, if we escape from here it failed */628 /* Execute the process, if we escape from here it failed */
570 if (execvp (argv[0], argv) < 0) {629 if (execvp (argv[0], argv) < 0) {
571 nih_error_raise_system ();630 nih_error_raise_system ();
572631
=== modified file 'init/job_process.h'
--- init/job_process.h 2009-07-09 11:01:53 +0000
+++ init/job_process.h 2011-04-27 14:11:41 +0000
@@ -45,7 +45,9 @@
45 JOB_PROCESS_ERROR_CHROOT,45 JOB_PROCESS_ERROR_CHROOT,
46 JOB_PROCESS_ERROR_CHDIR,46 JOB_PROCESS_ERROR_CHDIR,
47 JOB_PROCESS_ERROR_PTRACE,47 JOB_PROCESS_ERROR_PTRACE,
48 JOB_PROCESS_ERROR_EXEC48 JOB_PROCESS_ERROR_EXEC,
49 JOB_PROCESS_ERROR_SETUID,
50 JOB_PROCESS_ERROR_SETGID,
49} JobProcessErrorType;51} JobProcessErrorType;
5052
51/**53/**
5254
=== modified file 'init/main.c'
--- init/main.c 2011-03-16 22:54:56 +0000
+++ init/main.c 2011-04-27 14:11:41 +0000
@@ -71,6 +71,8 @@
71static void usr1_handler (void *data, NihSignal *signal);71static void usr1_handler (void *data, NihSignal *signal);
72#endif /* DEBUG */72#endif /* DEBUG */
7373
74static void handle_confdir (void);
75
7476
75/**77/**
76 * argv0:78 * argv0:
@@ -90,12 +92,53 @@
9092
9193
92/**94/**
95 * conf_dir:
96 *
97 * Full path to job configuration file directory.
98 *
99 **/
100static char *conf_dir = NULL;
101
102/**
103 * initial_event:
104 *
105 * Alternate event to emit at startup (rather than STARTUP_EVENT).
106 **/
107static char *initial_event = NULL;
108
109/**
110 * disable_startup_event:
111 *
112 * If TRUE, do not emit a startup event.
113 **/
114static int disable_startup_event = FALSE;
115
116extern int use_session_bus;
117
118extern int disable_sessions;
119
120/**
93 * options:121 * options:
94 *122 *
95 * Command-line options we accept.123 * Command-line options we accept.
96 **/124 **/
97static NihOption options[] = {125static NihOption options[] = {
126 { 0, "confdir", N_("specify alternative directory to load configuration files from"),
127 NULL, "DIR", &conf_dir, NULL },
128
129 { 0, "startup-event", N_("specify an alternative initial event (for testing)"),
130 NULL, "NAME", &initial_event, NULL },
131
132 { 0, "no-startup-event", N_("do not emit any startup event (for testing)"),
133 NULL, NULL, &disable_startup_event, NULL },
134
135 { 0, "no-sessions", N_("Disable user and chroot sessions"),
136 NULL, NULL, &disable_sessions, NULL },
137
98 { 0, "restart", NULL, NULL, NULL, &restart, NULL },138 { 0, "restart", NULL, NULL, NULL, &restart, NULL },
139
140 { 0, "session", N_("use D-Bus session bus rather than system bus (for testing)"),
141 NULL, NULL, &use_session_bus, NULL },
99142
100 /* Ignore invalid options */143 /* Ignore invalid options */
101 { '-', "--", NULL, NULL, NULL, NULL, NULL },144 { '-', "--", NULL, NULL, NULL, NULL, NULL },
@@ -124,7 +167,11 @@
124 if (! args)167 if (! args)
125 exit (1);168 exit (1);
126169
170 handle_confdir ();
171 control_handle_bus_type ();
172
127#ifndef DEBUG173#ifndef DEBUG
174<<<<<<< TREE
128 /* Check we're root */175 /* Check we're root */
129 if (getuid ()) {176 if (getuid ()) {
130 nih_fatal (_("Need to be root"));177 nih_fatal (_("Need to be root"));
@@ -208,10 +255,105 @@
208 err->message);255 err->message);
209 nih_free (err);256 nih_free (err);
210 }257 }
258=======
259 if (use_session_bus == FALSE) {
260
261 /* Check we're root */
262 if (getuid ()) {
263 nih_fatal (_("Need to be root"));
264 exit (1);
265 }
266
267 /* Check we're process #1 */
268 if (getpid () > 1) {
269 execv (TELINIT, argv);
270 /* Ignore failure, probably just that telinit doesn't exist */
271
272 nih_fatal (_("Not being executed as init"));
273 exit (1);
274 }
275
276 /* Clear our arguments from the command-line, so that we show up in
277 * ps or top output as /sbin/init, with no extra flags.
278 *
279 * This is a very Linux-specific trick; by deleting the NULL
280 * terminator at the end of the last argument, we fool the kernel
281 * into believing we used a setproctitle()-a-like to extend the
282 * argument space into the environment space, and thus make it use
283 * strlen() instead of its own assumed length. In fact, we've done
284 * the exact opposite, and shrunk the command line length to just that
285 * of whatever is in argv[0].
286 *
287 * If we don't do this, and just write \0 over the rest of argv, for
288 * example; the command-line length still includes those \0s, and ps
289 * will show whitespace in their place.
290 */
291 if (argc > 1) {
292 char *arg_end;
293
294 arg_end = argv[argc-1] + strlen (argv[argc-1]);
295 *arg_end = ' ';
296 }
297
298
299 /* Become the leader of a new session and process group, shedding
300 * any controlling tty (which we shouldn't have had anyway - but
301 * you never know what initramfs did).
302 */
303 setsid ();
304
305 /* Set the standard file descriptors to the ordinary console device,
306 * resetting it to sane defaults unless we're inheriting from another
307 * init process which we know left it in a sane state.
308 */
309 if (system_setup_console (CONSOLE_OUTPUT, (! restart)) < 0)
310 nih_free (nih_error_get ());
311 if (system_setup_console (CONSOLE_NONE, FALSE) < 0)
312 nih_free (nih_error_get ());
313
314 /* Set the PATH environment variable */
315 setenv ("PATH", PATH, TRUE);
316
317 /* Switch to the root directory in case we were started from some
318 * strange place, or worse, some directory in the initramfs that's
319 * going to go away soon.
320 */
321 if (chdir ("/"))
322 nih_warn ("%s: %s", _("Unable to set root directory"),
323 strerror (errno));
324
325 /* Mount the /proc and /sys filesystems, which are pretty much
326 * essential for any Linux system; not to mention used by
327 * ourselves.
328 */
329 if (system_mount ("proc", "/proc") < 0) {
330 NihError *err;
331
332 err = nih_error_get ();
333 nih_warn ("%s: %s", _("Unable to mount /proc filesystem"),
334 err->message);
335 nih_free (err);
336 }
337
338 if (system_mount ("sysfs", "/sys") < 0) {
339 NihError *err;
340
341 err = nih_error_get ();
342 nih_warn ("%s: %s", _("Unable to mount /sys filesystem"),
343 err->message);
344 nih_free (err);
345 }
346 } else {
347 nih_log_set_priority (NIH_LOG_DEBUG);
348 nih_debug ("Running with UID %d as PID %d (PPID %d)",
349 (int)getuid (), (int)getpid (), (int)getppid ());
350 }
351
352>>>>>>> MERGE-SOURCE
211#else /* DEBUG */353#else /* DEBUG */
212 nih_log_set_priority (NIH_LOG_DEBUG);354 nih_log_set_priority (NIH_LOG_DEBUG);
213 nih_debug ("Running as PID %d (PPID %d)",355 nih_debug ("Running with UID %d as PID %d (PPID %d)",
214 (int)getpid (), (int)getppid ());356 (int)getuid (), (int)getpid (), (int)getppid ());
215#endif /* DEBUG */357#endif /* DEBUG */
216358
217359
@@ -223,11 +365,13 @@
223 nih_signal_reset ();365 nih_signal_reset ();
224366
225#ifndef DEBUG367#ifndef DEBUG
226 /* Catch fatal errors immediately rather than waiting for a new368 if (use_session_bus == FALSE) {
227 * iteration through the main loop.369 /* Catch fatal errors immediately rather than waiting for a new
228 */370 * iteration through the main loop.
229 nih_signal_set_handler (SIGSEGV, crash_handler);371 */
230 nih_signal_set_handler (SIGABRT, crash_handler);372 nih_signal_set_handler (SIGSEGV, crash_handler);
373 nih_signal_set_handler (SIGABRT, crash_handler);
374 }
231#endif /* DEBUG */375#endif /* DEBUG */
232376
233 /* Don't ignore SIGCHLD or SIGALRM, but don't respond to them377 /* Don't ignore SIGCHLD or SIGALRM, but don't respond to them
@@ -238,33 +382,35 @@
238 nih_signal_set_handler (SIGALRM, nih_signal_handler);382 nih_signal_set_handler (SIGALRM, nih_signal_handler);
239383
240#ifndef DEBUG384#ifndef DEBUG
241 /* Ask the kernel to send us SIGINT when control-alt-delete is385 if (use_session_bus == FALSE) {
242 * pressed; generate an event with the same name.386 /* Ask the kernel to send us SIGINT when control-alt-delete is
243 */387 * pressed; generate an event with the same name.
244 reboot (RB_DISABLE_CAD);388 */
245 nih_signal_set_handler (SIGINT, nih_signal_handler);389 reboot (RB_DISABLE_CAD);
246 NIH_MUST (nih_signal_add_handler (NULL, SIGINT, cad_handler, NULL));390 nih_signal_set_handler (SIGINT, nih_signal_handler);
247391 NIH_MUST (nih_signal_add_handler (NULL, SIGINT, cad_handler, NULL));
248 /* Ask the kernel to send us SIGWINCH when alt-uparrow is pressed;392
249 * generate a keyboard-request event.393 /* Ask the kernel to send us SIGWINCH when alt-uparrow is pressed;
250 */394 * generate a keyboard-request event.
251 if (ioctl (0, KDSIGACCEPT, SIGWINCH) == 0) {395 */
252 nih_signal_set_handler (SIGWINCH, nih_signal_handler);396 if (ioctl (0, KDSIGACCEPT, SIGWINCH) == 0) {
253 NIH_MUST (nih_signal_add_handler (NULL, SIGWINCH,397 nih_signal_set_handler (SIGWINCH, nih_signal_handler);
254 kbd_handler, NULL));398 NIH_MUST (nih_signal_add_handler (NULL, SIGWINCH,
399 kbd_handler, NULL));
400 }
401
402 /* powstatd sends us SIGPWR when it changes /etc/powerstatus */
403 nih_signal_set_handler (SIGPWR, nih_signal_handler);
404 NIH_MUST (nih_signal_add_handler (NULL, SIGPWR, pwr_handler, NULL));
405
406 /* SIGHUP instructs us to re-load our configuration */
407 nih_signal_set_handler (SIGHUP, nih_signal_handler);
408 NIH_MUST (nih_signal_add_handler (NULL, SIGHUP, hup_handler, NULL));
409
410 /* SIGUSR1 instructs us to reconnect to D-Bus */
411 nih_signal_set_handler (SIGUSR1, nih_signal_handler);
412 NIH_MUST (nih_signal_add_handler (NULL, SIGUSR1, usr1_handler, NULL));
255 }413 }
256
257 /* powstatd sends us SIGPWR when it changes /etc/powerstatus */
258 nih_signal_set_handler (SIGPWR, nih_signal_handler);
259 NIH_MUST (nih_signal_add_handler (NULL, SIGPWR, pwr_handler, NULL));
260
261 /* SIGHUP instructs us to re-load our configuration */
262 nih_signal_set_handler (SIGHUP, nih_signal_handler);
263 NIH_MUST (nih_signal_add_handler (NULL, SIGHUP, hup_handler, NULL));
264
265 /* SIGUSR1 instructs us to reconnect to D-Bus */
266 nih_signal_set_handler (SIGUSR1, nih_signal_handler);
267 NIH_MUST (nih_signal_add_handler (NULL, SIGUSR1, usr1_handler, NULL));
268#endif /* DEBUG */414#endif /* DEBUG */
269415
270416
@@ -278,26 +424,28 @@
278424
279425
280 /* Read configuration */426 /* Read configuration */
281 NIH_MUST (conf_source_new (NULL, CONFFILE, CONF_FILE));427 NIH_MUST (conf_source_new (NULL, DEFAULT_CONFFILE, CONF_FILE));
282 NIH_MUST (conf_source_new (NULL, CONFDIR, CONF_JOB_DIR));428 NIH_MUST (conf_source_new (NULL, conf_dir, CONF_JOB_DIR));
283429
284 conf_reload ();430 conf_reload ();
285431
286 /* Create a listening server for private connections. */432 /* Create a listening server for private connections. */
287 while (control_server_open () < 0) {433 if (use_session_bus == FALSE) {
288 NihError *err;434 while (control_server_open () < 0) {
435 NihError *err;
289436
290 err = nih_error_get ();437 err = nih_error_get ();
291 if (err->number != ENOMEM) {438 if (err->number != ENOMEM) {
292 nih_warn ("%s: %s", _("Unable to listen for private connections"),439 nih_warn ("%s: %s", _("Unable to listen for private connections"),
293 err->message);440 err->message);
441 nih_free (err);
442 break;
443 }
294 nih_free (err);444 nih_free (err);
295 break;
296 }445 }
297 nih_free (err);
298 }446 }
299447
300 /* Open connection to the system bus; we normally expect this to448 /* Open connection to the appropriate D-Bus bus; we normally expect this to
301 * fail and will try again later - don't let ENOMEM stop us though.449 * fail and will try again later - don't let ENOMEM stop us though.
302 */450 */
303 while (control_bus_open () < 0) {451 while (control_bus_open () < 0) {
@@ -313,6 +461,7 @@
313 }461 }
314462
315#ifndef DEBUG463#ifndef DEBUG
464<<<<<<< TREE
316 /* Now that the startup is complete, send all further logging output465 /* Now that the startup is complete, send all further logging output
317 * to kmsg instead of to the console.466 * to kmsg instead of to the console.
318 */467 */
@@ -320,14 +469,32 @@
320 nih_free (nih_error_get ());469 nih_free (nih_error_get ());
321470
322 nih_log_set_logger (logger_kmsg);471 nih_log_set_logger (logger_kmsg);
472=======
473 if (use_session_bus == FALSE) {
474 /* Now that the startup is complete, send all further logging output
475 * to syslog instead of to the console.
476 */
477 openlog (program_name, LOG_CONS, LOG_DAEMON);
478 nih_log_set_logger (nih_logger_syslog);
479 }
480>>>>>>> MERGE-SOURCE
323#endif /* DEBUG */481#endif /* DEBUG */
324482
325483
326 /* Generate and run the startup event or read the state from the484 /* Generate and run the startup event or read the state from the
327 * init daemon that exec'd us485 * init daemon that exec'd us
328 */486 */
329 if (! restart) {487 if (! restart ) {
330 NIH_MUST (event_new (NULL, STARTUP_EVENT, NULL));488 if (disable_startup_event) {
489 nih_debug ("Startup event disabled");
490 } else {
491 NIH_MUST (event_new (NULL,
492 initial_event
493 ? initial_event
494 : STARTUP_EVENT,
495 NULL));
496 }
497
331 } else {498 } else {
332 sigset_t mask;499 sigset_t mask;
333500
@@ -336,6 +503,9 @@
336 sigprocmask (SIG_SETMASK, &mask, NULL);503 sigprocmask (SIG_SETMASK, &mask, NULL);
337 }504 }
338505
506 if (disable_sessions)
507 nih_debug ("Sessions disabled");
508
339 /* Run through the loop at least once to deal with signals that were509 /* Run through the loop at least once to deal with signals that were
340 * delivered to the previous process while the mask was set or to510 * delivered to the previous process while the mask was set or to
341 * process the startup event we emitted.511 * process the startup event we emitted.
@@ -573,3 +743,31 @@
573 }743 }
574}744}
575#endif /* DEBUG */745#endif /* DEBUG */
746
747/**
748 * handle_confdir:
749 *
750 * Determine where system configuration files should be loaded from.
751 **/
752static void
753handle_confdir (void)
754{
755 char *dir;
756
757 /* user has already specified directory on command-line */
758 if (conf_dir)
759 goto out;
760
761 conf_dir = DEFAULT_CONFDIR;
762
763 dir = getenv (CONFDIR_ENV);
764 if (! dir)
765 return;
766
767 conf_dir = dir;
768
769out:
770 nih_debug ("Using alternate configuration directory %s",
771 conf_dir);
772}
773
576774
=== modified file 'init/man/init.5'
--- init/man/init.5 2011-03-15 18:36:57 +0000
+++ init/man/init.5 2011-04-27 14:11:41 +0000
@@ -1,42 +1,117 @@
1.TH init 5 2010-12-14 "Upstart"1.TH init 5 2011-03-03 "Upstart"
2.\"2.\"
3.SH NAME3.SH NAME
4init \- Upstart init daemon job configuration4init \- Upstart init daemon job configuration
5.\"5.\"
6.SH SYNOPSIS6.SH SYNOPSIS
7.B /etc/init7.B /etc/init/
8
9.B $HOME/.init/
8.\"10.\"
9.SH DESCRIPTION11.SH DESCRIPTION
10On startup, the Upstart12On startup, the Upstart
11.BR init (8)13.BR init (8)
12daemon reads its job configuration from the14daemon reads its job configuration from files in the
13.I /etc/init15.I /etc/init/
14directory, and watches for future changes using16directory, and watches for future changes to these files using
15.BR inotify (7).17.BR inotify (7).
1618
17Files in this directory must end in19If D\-Bus has been configured to allow non\-privileged users to invoke all
20Upstart D\-Bus methods, Upstart is also able to manage User Jobs. See
21.B User Jobs
22for further details.
23
24To be considered by Upstart, files in this directory must have a
25recognized suffix and may also be present in sub\-directories. There are
26two recognized suffixes:
27
28.IP \(bu 4
29Files ending in
18.I .conf30.I .conf
19and may also be present in sub-directories.31are called configuration files, or simply "conf files" for short.
2032These are the primary vehicle for specifying a job.
21Each file defines a single service or task, with the name taken from its33.IP \(bu 4
22relative path within the directory without the extension. For example a34Files ending in
23job defined in35.I .override
24.I /etc/init/rc-sysinit.conf36are called override files. If an override file is present, the stanzas
37it contains take precedence over those equivalently named stanzas in the
38corresponding configuration file contents for a particular job.
39The main use for override files is to modify how a job will run without
40having to modify its configuration file directly. See the section
41\fBOverride File Handling\fP below for further details.
42.P
43A job can thus be defined by either:
44.IP \[bu] 2
45A single configuration file.
46.IP \[bu]
47A single configuration file \fBand\fP a single override file.
48.P
49Unless explicitly stated otherwise, any reference to a jobs
50configuration can refer both to a configuration file or an override
51file.
52
53Each configuration file defines the template for a single \fIservice\fP
54(long\-running process or daemon) or \fItask\fP (short\-lived process).
55
56Note that a configuration file is not itself a job: it is a description
57of an environmenta job could be run in. A job is the runtime embodiment
58of a configuration file.
59
60The configuration file name as displayed by Upstart and associated
61tooling is taken from its relative path within the directory without the
62extension. For example a configuration file
63.I /etc/init/rc\-sysinit.conf
25is named64is named
26.IR rc-sysinit ,65.IR rc\-sysinit ,
27while a job defined in66while a configuration file
28.I /etc/init/net/apache.conf67.I /etc/init/net/apache.conf
29is named68is named
30.IR net/apache .69.IR net/apache .
3170Since override files only modify the way a configuration file is
32These files are plain text and should not be executable.71interpreted, they are not named.
33.\"72
34.SS Format73Configuration files are plain text and should not be executable.
74.\"
75.SS User Jobs
76
77A User Job is a job configuration file created by a non\-privileged user
78in the
79.B $HOME/.init/
80directory. Job configuration files in this directory have
81the same syntax as system job configuration files.
82
83Any user can create user jobs, but that user can control
84.I only
85jobs they create.
86
87Users are able to manage their jobs using the standard
88.BR initctl (8)
89facility.
90
91Note that a user job configuration file cannot have the same name as a
92system job configuration file.
93
94.\"
95.SS Chroot Support
96
97Upstart is able to manage jobs within a \fBchroot\fP(2). To control jobs
98within the chroot environment, use the standard
99.BR initctl (8)
100facility. Note that it is not necessary to install D\-Bus within the
101chroot (in fact it is not recommended).
102
103Note that User Jobs can be created within a chroot environment.
104
105.\"
106.SS Configuration File Format
35Each line begins with a configuration stanza and continues until either107Each line begins with a configuration stanza and continues until either
36the end of the line or a line containing a closing stanza. Line breaks108the end of the line or a line containing a closing stanza. Line breaks
37within a stanza are permitted within single or double quotes, or if109within a stanza are permitted within single or double quotes, or if
38preceeded by a blackslash.110preceeded by a blackslash.
39111
112If a stanza is duplicated, the last occurence will be used. Unrecognized
113stanzas will generate parse errors, which will stop a job from running.
114
40Stanzas and their arguments are delimited by whitespace, which consists115Stanzas and their arguments are delimited by whitespace, which consists
41of one or more space or tab characters which are otherwise ignored unless116of one or more space or tab characters which are otherwise ignored unless
42placed within single or double quotes.117placed within single or double quotes.
@@ -69,7 +144,7 @@
69entire command being passed to a shell for expansion.144entire command being passed to a shell for expansion.
70145
71.nf146.nf
72exec /usr/sbin/acpid -c $EVENTSDIR -s $SOCKET147exec /usr/sbin/acpid \-c $EVENTSDIR \-s $SOCKET
73.fi148.fi
74.\"149.\"
75.TP150.TP
@@ -78,7 +153,7 @@
78be executed using153be executed using
79.BR sh(1).154.BR sh(1).
80The155The
81.I -e156.I \-e
82shell option is always used, so any command that fails will terminate157shell option is always used, so any command that fails will terminate
83the script.158the script.
84159
@@ -92,7 +167,7 @@
92.nf167.nf
93script168script
94 dd bs=1 if=/proc/kmsg of=$KMSGSINK169 dd bs=1 if=/proc/kmsg of=$KMSGSINK
95 exec /sbin/klogd -P $KMSGSINK170 exec /sbin/klogd \-P $KMSGSINK
96end script171end script
97.fi172.fi
98173
@@ -105,14 +180,14 @@
105stanza.180stanza.
106181
107.TP182.TP
108.B pre-start exec\fR|\fBscript\fR...183.B pre\-start exec\fR|\fBscript\fR...
109This process will be run after the job's184This process will be run after the job's
110.BR starting (7)185.BR starting (7)
111event has finished, but before the main process is run. It is typically186event has finished, but before the main process is run. It is typically
112used to prepare the environment, such as making necessary directories.187used to prepare the environment, such as making necessary directories.
113.\"188.\"
114.TP189.TP
115.B post-start exec\fR|\fBscript\fR...190.B post\-start exec\fR|\fBscript\fR...
116This process will be run before the job's191This process will be run before the job's
117.BR started (7)192.BR started (7)
118event is emitted, but after the main process has been spawned. It is193event is emitted, but after the main process has been spawned. It is
@@ -122,7 +197,7 @@
122event until the main process is ready to receive clients.197event until the main process is ready to receive clients.
123.\"198.\"
124.TP199.TP
125.B pre-stop exec\fR|\fBscript\fR...200.B pre\-stop exec\fR|\fBscript\fR...
126This process is run if the job is stopped by an event listed in its201This process is run if the job is stopped by an event listed in its
127.B stop on202.B stop on
128stanza or by the203stanza or by the
@@ -136,7 +211,7 @@
136command without arguments to cancel the stop.211command without arguments to cancel the stop.
137.\"212.\"
138.TP213.TP
139.B post-stop exec\fR|\fBscript\fR...214.B post\-stop exec\fR|\fBscript\fR...
140This process is run after the main process has been killed and before215This process is run after the main process has been killed and before
141the job's216the job's
142.BR stopped (7)217.BR stopped (7)
@@ -144,19 +219,19 @@
144such as removing temporary directories.219such as removing temporary directories.
145220
146.PP221.PP
147All of these processes, including the main process, are optional. Services222All of these processes, including the main process, are optional.
148without a main process will appear to be running until they are stopped,223Services without a main process will appear to be running until they are
149this is commonly used to define states such as runlevels. It's quite224stopped: this is commonly used to define states such as runlevels. It
150permissable to have no main process, but to have225is permissable to have no main process, but to have
151.B pre-start226.B pre\-start
152and227and
153.B post-stop228.B post\-stop
154processes for the state.229processes for the state.
155230
156.RS231.RS
157.nf232.nf
158pre-start exec ifup -a233pre\-start exec ifup \-a
159post-stop exec ifdown -a234post\-stop exec ifdown \-a
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches