Merge lp:~jamesodhunt/upstart/upstream-session-support into lp:upstart

Proposed by James Hunt
Status: Superseded
Proposed branch: lp:~jamesodhunt/upstart/upstream-session-support
Merge into: lp:upstart
Diff against target: 13049 lines (+6349/-1012)
56 files modified
ChangeLog (+219/-0)
Makefile.am (+1/-1)
TESTING.sessions (+264/-0)
conf/rc-sysinit.conf (+2/-0)
configure.ac (+3/-2)
contrib/bash_completion/upstart (+96/-36)
dbus/Upstart.conf (+6/-36)
dbus/upstart.h (+1/-1)
init/Makefile.am (+12/-0)
init/conf.c (+10/-5)
init/conf.h (+5/-2)
init/control.c (+73/-10)
init/control.h (+15/-1)
init/environ.c (+0/-1)
init/environ.h (+0/-1)
init/event.c (+10/-0)
init/event.h (+5/-1)
init/job.c (+44/-3)
init/job.h (+1/-1)
init/job_class.c (+113/-23)
init/job_class.h (+5/-1)
init/job_process.c (+59/-1)
init/job_process.h (+4/-3)
init/main.c (+234/-136)
init/man/init.5 (+87/-34)
init/man/init.8 (+30/-4)
init/parse_job.c (+4/-2)
init/parse_job.h (+4/-3)
init/paths.h (+25/-2)
init/session.c (+279/-0)
init/session.h (+87/-0)
init/tests/test_blocked.c (+4/-1)
init/tests/test_conf.c (+15/-13)
init/tests/test_control.c (+15/-11)
init/tests/test_environ.c (+3/-1)
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/-65)
init/tests/test_job_process.c (+34/-30)
init/tests/test_parse_conf.c (+3/-0)
init/tests/test_parse_job.c (+263/-260)
init/tests/test_process.c (+3/-0)
init/tests/test_system.c (+3/-0)
po/upstart.pot (+292/-148)
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 (+1014/-17)
util/initctl.h (+458/-0)
util/man/initctl.8 (+200/-34)
util/reboot.c (+0/-1)
util/tests/test_initctl.c (+1181/-19)
To merge this branch: bzr merge lp:~jamesodhunt/upstart/upstream-session-support
Reviewer Review Type Date Requested Status
Upstart Developers Pending
Review via email: mp+63395@code.launchpad.net

This proposal supersedes a proposal from 2011-05-15.

This proposal has been superseded by a proposal from 2011-06-06.

Description of the change

Addition of session support, for user sessions and chroot sessions.

Code is lp:~canonical-scott/upstart/session-support plus associated fixes:

  Add session support. Note that there are no automatically runnable and
  explicit tests yet. However, see TESTING.sessions.

  * TESTING.sessions: ASCII (reStructuredText) document explaining
    how to run manual tests for session support (for chroots).
  * dbus/Upstart.conf: Simplified to support allowing users to invoke
    all methods (since Upstart now isolates commands by user).
  * init/Makefile.am: Added session.[ch] files.
  * init/session.c: New file. Note that session_from_dbus() will disable sessions
    (by returning the NULL session) if environment variable "UPSTART_NO_SESSIONS"
    is set to any value (used by tests).
  * init/session.h: New file.
  * init/parse_job.h: parse_job(): Add session pointer to prototype.
  * init/parse_job.c:
    - parse_job(): Add session parameter.
    - Update calls to job_class_new() to pass session pointer.
  * init/job.c: job_new(): Crucial change to ensure chroot sessions have
    a unique D-Bus name (LP:#728531).
  * init/job_class.c:
    - job_class_new(): Add session parameter and session support.
    - job_class_remove(): Add session parameter to prototype.
    - job_class_consider(): Only consider jobs from the appropriate session.
    - job_class_reconsider(): Only consider jobs from the appropriate session.
    - job_class_start(): Disallow out-of-session modification.
    - job_class_stop(): Disallow out-of-session modification.
    - job_class_restart(): Disallow out-of-session modification.
  * init/main.c: Add "--no-sessions" command-line option to disable
    sessions and revert to traditional behaviour.
  * init/job_class.h:
    - job_class_new(): Add session pointer to prototype.
    - JobClass: Add session member.
  * init/job_process.c: job_process_spawn():
    - Call chroot(2) for chroot sessions.
    - Call setuid(2) for user session jobs.
  * init/job.c:
    - job_emit_event(): Set session for event.
    - job_start(): Disallow out-of-session modification.
    - job_stop(): Disallow out-of-session modification.
    - job_restart(): Disallow out-of-session modification.
  * init/event.h: Event: Add session member.
  * init/event.c:
    - event_new(): initialize session to NULL.
    - event_pending_handle_jobs(): Add session handling.
    - event_finished(): Set session for failure event.
  * init/control.c:
    - control_get_job_by_name(): Add session handling.
    - control_get_all_jobs(): Add session handling.
    - control_emit_event(): Add session handling.
  * init/conf.c:
    - conf_source_new(): Initialise session to NULL.
    - conf_reload_path(): Pass session to parse_job().
    - conf_select_job(): Add session parameter.
  * init/conf.h:
    - ConfSource: Add session member.
    - conf_select_job(): Add session parameter to prototype.
  * All tests updated to set "UPSTART_NO_SESSIONS".

To post a comment you must log in.
1259. By James Hunt

* TESTING.sessions: Added missing awk param.

1260. By James Hunt

* TESTING.sessions:
  - Added missing "set -x" call to force log output.
  - Formatting.
  - Added remaining expected outcomes.

1261. By James Hunt

* init/man/init.5: Update for User Jobs.
* init/man/init.8: Mention $HOME/.init/ for User Jobs.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ChangeLog'
2--- ChangeLog 2011-05-12 20:42:28 +0000
3+++ ChangeLog 2011-06-06 15:17:24 +0000
4@@ -1,3 +1,222 @@
5+2011-06-03 James Hunt <james.hunt@ubuntu.com>
6+
7+ Add session support. Note that there are no automatically runnable and
8+ explicit tests yet. However, see TESTING.sessions.
9+
10+ * TESTING.sessions: ASCII (reStructuredText) document explaining
11+ how to run manual tests for session support (for chroots).
12+ * dbus/Upstart.conf: Simplified to support allowing users to invoke
13+ all methods (since Upstart now isolates commands by user).
14+ * init/Makefile.am: Added session.[ch] files.
15+ * init/session.c: New file. Note that session_from_dbus() will disable sessions
16+ (by returning the NULL session) if environment variable "UPSTART_NO_SESSIONS"
17+ is set to any value (used by tests).
18+ * init/session.h: New file.
19+ * init/parse_job.h: parse_job(): Add session pointer to prototype.
20+ * init/parse_job.c:
21+ - parse_job(): Add session parameter.
22+ - Update calls to job_class_new() to pass session pointer.
23+ * init/job.c: job_new(): Crucial change to ensure chroot sessions have
24+ a unique D-Bus name (LP:#728531).
25+ * init/job_class.c:
26+ - job_class_new(): Add session parameter and session support.
27+ - job_class_remove(): Add session parameter to prototype.
28+ - job_class_consider(): Only consider jobs from the appropriate session.
29+ - job_class_reconsider(): Only consider jobs from the appropriate session.
30+ - job_class_start(): Disallow out-of-session modification.
31+ - job_class_stop(): Disallow out-of-session modification.
32+ - job_class_restart(): Disallow out-of-session modification.
33+ * init/main.c: Add "--no-sessions" command-line option to disable
34+ sessions and revert to traditional behaviour.
35+ * init/job_class.h:
36+ - job_class_new(): Add session pointer to prototype.
37+ - JobClass: Add session member.
38+ * init/job_process.c: job_process_spawn():
39+ - Call chroot(2) for chroot sessions.
40+ - Call setuid(2) for user session jobs.
41+ * init/job.c:
42+ - job_emit_event(): Set session for event.
43+ - job_start(): Disallow out-of-session modification.
44+ - job_stop(): Disallow out-of-session modification.
45+ - job_restart(): Disallow out-of-session modification.
46+ * init/event.h: Event: Add session member.
47+ * init/event.c:
48+ - event_new(): initialize session to NULL.
49+ - event_pending_handle_jobs(): Add session handling.
50+ - event_finished(): Set session for failure event.
51+ * init/control.c:
52+ - control_get_job_by_name(): Add session handling.
53+ - control_get_all_jobs(): Add session handling.
54+ - control_emit_event(): Add session handling.
55+ * init/conf.c:
56+ - conf_source_new(): Initialise session to NULL.
57+ - conf_reload_path(): Pass session to parse_job().
58+ - conf_select_job(): Add session parameter.
59+ * init/conf.h:
60+ - ConfSource: Add session member.
61+ - conf_select_job(): Add session parameter to prototype.
62+ * All tests updated to set "UPSTART_NO_SESSIONS" (to disable
63+ sessions).
64+
65+2011-06-02 James Hunt <james.hunt@ubuntu.com>
66+
67+ * contrib/bash_completion/upstart:
68+ - Made function names more meaningful:
69+ - _upstart_jobs: Now returns a unique list
70+ - _upstart_events (nee _upstart_named_events ) now considers all
71+ "emits" tokens.
72+ - Updates for "check-config" and "show-config".
73+ - Added "--session" option.
74+ - Added "--no-wait" for emit, reload and restart.
75+
76+ Man page updates.
77+
78+ * init/man/init.5:
79+ - Quoted dashes.
80+ - Explain handling of duplicated stanzas.
81+ - "respawn": Document default count and interval.
82+ - "emits": Reference "initctl check-config".
83+ - Added BUGS section.
84+ - Added copyright.
85+ * init/man/init.8:
86+ - Quoted dashes.
87+ - See Also: Added control-alt-delete(7).
88+ * util/man/initctl.8:
89+ - Quoted dashes.
90+ - "restart": Clarified meaning.
91+ - "list": Explained "stop/waiting" jobs.
92+
93+2011-06-01 James Hunt <james.hunt@ubuntu.com>
94+
95+ Add D-Bus session support to initctl.
96+
97+ * util/initctl.c:
98+ - Added "--session" command-line option.
99+ - dbus_bus_type_setter(): New function used by option parser to
100+ distinguish system/session D-Bus bus type.
101+ - system_bus variable now replaced by two others: use_dbus (boolean)
102+ and dbus_bus_type.
103+ - upstart_open(): Updated to handle multiple D-Bus bus types.
104+ * util/man/initctl.8: Update for "--session" option.
105+ * util/tests/test_initctl.c: Updated to make use of use_dbus and
106+ dbus_bus_type rather than system_bus.
107+
108+ Add "show-config" command to initctl.
109+
110+ * util/initctl.c:
111+ - New functions:
112+ - job_class_condition_handler(): Handler function to retrieve job conditions.
113+ - job_class_condition_err_handler(): Handler error function for
114+ job_class_condition_handler().
115+ - job_class_parse_events(): Convert RPN "start on" and "stop on" conditions to
116+ human-readable format.
117+ - job_class_show_emits(): Display events which job emits.
118+ - job_class_show_conditions(): Make D-Bus calls to retrieve "start on" and
119+ "stop on" conditions.
120+ - show_config_action: Handle "show-config" command..
121+ * util/initctl.h: New file providing stack-handling functionality for
122+ RPN parsing for "show-config" command.
123+ * util/Makefile.am: Added initctl.h to initctl_SOURCES.
124+ * util/man/initctl.8: Updated for "show-config" command and associated
125+ options.
126+ * util/tests/test_initctl.c:
127+ - New macros START_UPSTART, STOP_UPSTART, RUN_COMMAND, CREATE_FILE and DELETE_FILE.
128+ These are required since due to the introduction of the
129+ "show-config" initctl command, initctl is no longer solely a proxy
130+ to Upstart: it now has some intelligence (it parses the
131+ "emits", "start on" and "stop on" conditions) and thus must be
132+ tested directly.
133+ - test_show_config(): New function to test "initctl show-config".
134+ - in_chroot(): New function to detect if tests are being run from
135+ within a chroot environment.
136+ - dbus_configured(): New function which performs a basic check to
137+ establish if D-Bus is configured correctly.
138+ - main(): Added call to test_show_config(), conditional on
139+ a non-chroot environment and a working D-Bus system.
140+
141+ Add "check-config" command to initctl.
142+
143+ * util/initctl.c:
144+ - New functions:
145+ - allow_event(): Determine if specified event is erroneous or not.
146+ Handles globbing.
147+ - allow_job(): Determine if specified job is erroneous or not.
148+ Handles variables (such as instance variables).
149+ - check_condition(): High-level function to handle checking start
150+ on/stop on conditions.
151+ - check_config_action: Handler for "check-config" command.
152+ - display_check_errors(): Display errors from expression tree nodes
153+ that are in error.
154+ - eval_expr_tree(): Evaluate expression tree.
155+ - ignored_events_setter(): handler for '--ignore-events' command-line
156+ option for "check-config" command.
157+ - tree_filter(): Used for filtering expression tree nodes.
158+ - show_config_action(): Update for check-config mode.
159+ - job_class_parse_events(): Update for check-config mode.
160+ - job_class_show_emits(): Update for check-config mode.
161+ * util/initctl.h:
162+ - Added structs for JobCondition, CheckConfigData and ExprNode.
163+ - New macros: MAKE_EXPR_NODE() and MAKE_JOB_CONDITION().
164+ * util/tests/test_initctl.c:
165+ - test_check_config(): New function to test "initctl check-config".
166+ - main(): Added call to test_check_config(), conditional on
167+ a non-chroot environment and a working D-Bus system.
168+ * util/man/initctl.8: Updated for "check-config" command and associated
169+ options.
170+ * conf/rc-sysinit.conf: Added "emits" stanza, required by
171+ "check-config".
172+
173+ Addition of initctl2dot script for visualisation.
174+
175+ * Makefile.am: Added scripts directory.
176+ * configure.ac: Updated AC_CONFIG_FILES for scripts/Makefile.
177+ * scripts/Makefile.am: Makefile for scripts.
178+ * scripts/initctl2dot.py: Python script to produce dot(1) graphs of
179+ "initctl show-config" output.
180+ * scripts/man/initctl2dot.8: Man page for initctl2dot.py script.
181+
182+ Addition of init-checkconf script.
183+
184+ * scripts/init-checkconf.sh: Script to determine if specified job
185+ config file is valid or not.
186+ * scripts/man/init-checkconf.8: Man page for init-checkconf.sh.
187+ * scripts/Makefile.am: Added init-checkconf script and man
188+ page.
189+
190+2011-05-31 James Hunt <james.hunt@ubuntu.com>
191+
192+ Add command-line option to use D-Bus session bus (for testing).
193+
194+ * init/control.c:
195+ - Added new boolean use_session_bus.
196+ - Updated comments.
197+ - control_handle_bus_type(): New function to allow selection of
198+ session bus via env var "UPSTART_USE_SESSION_BUS".
199+ Also logs use of session bus if use_session_bus set.
200+ - control_bus_open(): Now connects to either D-Bus system bus or session bus.
201+ * init/control.h: New define for USE_SESSION_BUS_ENV.
202+ * init/main.c: Addition of "--session" command-line option.
203+ * init/man/init.8: Update for new "--session" command-line option.
204+
205+ * Corrected copyright notices.
206+
207+ Add option to allow alternate location for job config files.
208+
209+ * init/main.c:
210+ - Added "--confdir <dir>" command-line option.
211+ - handle_confdir(): New function to select alternate confdir using env
212+ var "UPSTART_CONFDIR" or command-line option (for testing).
213+ * init/paths.h: Added define for CONFDIR_ENV.
214+ * init/man/init.8: Update for new "--confdir" command-line option.
215+
216+ Add ability to suppress initial event and/or change its name.
217+
218+ * init/main.c: New command-line options: "--no-startup-event" and
219+ "--startup-event". If "--no-startup-event" specified, log message as a
220+ debug aid.
221+ * init/man/init.8: Documentation for new command-line options:
222+ "--no-startup-event" and "--startup-event".
223+
224 2011-05-12 Marc - A. Dahlhaus <mad@wol.de>
225
226 * init/job_class.h (JobClass): Add kill signal member
227
228=== modified file 'Makefile.am'
229--- Makefile.am 2010-02-04 03:42:29 +0000
230+++ Makefile.am 2011-06-06 15:17:24 +0000
231@@ -1,6 +1,6 @@
232 ## Process this file with automake to produce Makefile.in
233
234-SUBDIRS = intl dbus init util conf doc contrib po
235+SUBDIRS = intl dbus init util conf doc contrib po scripts
236
237 EXTRA_DIST = HACKING
238
239
240=== added file 'TESTING.sessions'
241--- TESTING.sessions 1970-01-01 00:00:00 +0000
242+++ TESTING.sessions 2011-06-06 15:17:24 +0000
243@@ -0,0 +1,264 @@
244+.. contents::
245+
246+=============================
247+Testing Sessions with Upstart
248+=============================
249+
250+Upstart now has support for chroots which are implemented by creating a
251+separate session for every user within each chroot. It also has partial
252+support for user sessions, but since this is experimental (and disabled
253+in Ubuntu), this document does not cover testing this feature.
254+
255+The session support does not yet provide full tests (as would be run by
256+"``make check``"). This is partly due to the complexity of automatically
257+testing some of the scenarios below.
258+
259+This document attempts to outline the minimum set of tests that should
260+be performed to ensure that chroot support works as expected.
261+
262+Assumptions
263+===========
264+
265+You are running an Ubuntu or Debian system.
266+
267+Setup
268+=====
269+
270+#. Install a chroot environement (such as ``schroot(1)``) and configure it.
271+#. run, "``debootstrap(8)``" to install the same release as you are running into your chroot.
272+#. Create the following files *outside* your chroot.
273+
274+ - ``/etc/init/foo.conf``::
275+
276+ start on wibble
277+
278+ script
279+ exec 2>>/tmp/foo.$$.log
280+ set -x
281+ echo "foo: stat=`stat /`"
282+ echo "foo: env=`env`"
283+ sleep 999
284+ end script
285+
286+ - ``/etc/init/outside_chroot.conf``::
287+
288+ start on A
289+
290+ script
291+ exec 2>>/tmp/outside_chroot.$$.log
292+ set -x
293+ echo "in_chroot: stat=`stat /`"
294+ echo "in_chroot: env=`env`"
295+ sleep 999
296+ end script
297+
298+#. Create following files inside chroot environment.
299+
300+ - ``/path/to/chroot/etc/init/foo.conf``::
301+
302+ start on wibble
303+
304+ script
305+ exec 2>>/tmp/foo.$$.log
306+ set -x
307+ echo "foo: stat=`stat /`"
308+ echo "foo: env=`env`"
309+ sleep 999
310+ end script
311+
312+ - ``/path/to/chroot/etc/init/in_chroot.conf``::
313+
314+ start on A
315+
316+ script
317+ exec 2>>/tmp/in_chroot.$$.log
318+ set -x
319+ echo "in_chroot: stat=`stat /`"
320+ echo "in_chroot: env=`env`"
321+ sleep 999
322+ end script
323+
324+
325+Run as non-``root`` with no chroot
326+==================================
327+
328+- ``initctl list``
329+
330+ Ensure list is contents of ``/etc/init/``: the command below should
331+ return no output::
332+
333+ cmp <(initctl list|awk '{print $1}'|sort -u) <(cd /etc/init && ls *.conf|cut -d: -f2-|sed 's/\.conf//g'|sort -u)
334+
335+- ``initctl status cron``
336+
337+ Should work.
338+
339+- ``initctl show-config``
340+
341+ Should work.
342+
343+- ``initctl check-config``
344+
345+ Should work.
346+
347+- ``start foo``
348+
349+ Should fail ("``initctl: Rejected send message``").
350+
351+- ``stop cron``
352+
353+ Should fail ("``initctl: Rejected send message``").
354+
355+- ``restart cron``
356+
357+ Should fail ("``initctl: Rejected send message``").
358+
359+- ``initctl emit bar``
360+
361+ Should fail ("``initctl: Rejected send message``").
362+
363+Run as ``root`` with no chroot
364+==============================
365+
366+- ``initctl list``
367+
368+ Ensure list is contents of ``/etc/init/``: command below should return no output::
369+
370+ cmp <(initctl list|awk '{print $1}'|sort -u) <(cd /etc/init && ls *.conf|cut -d: -f2-|sed 's/\.conf//g'|sort -u)
371+
372+- ``initctl status outside_chroot``
373+
374+ Should work.
375+
376+- ``initctl status in_chroot``
377+
378+ Should fail with message::
379+
380+ initct: Unknown job: in_chroot
381+
382+- ``initctl show-config``
383+
384+ Should work.
385+
386+- ``initctl check-config``
387+
388+ Should work.
389+
390+- ``start in_chroot``
391+
392+ Should fail with message::
393+
394+ initct: Unknown job: in_chroot
395+
396+- ``start outside_chroot``
397+
398+ Should work.
399+
400+- ``stop in_chroot``
401+
402+ Should fail with message::
403+
404+ initct: Unknown job: in_chroot
405+
406+- ``restart outside_chroot``
407+
408+ Should work.
409+
410+- ``stop outside_chroot``
411+
412+ Should work.
413+
414+- ``initctl emit wibble``
415+
416+ - Ensure ``/etc/init/foo.conf`` runs by looking at the log and ensuring
417+ the inode for the stat of '``/``' is the same as running "``stat /``" on
418+ the command-line.
419+
420+ * Ensure ``/path/to/chroot/etc/init/foo.conf`` does *NOT* run.
421+
422+- ``initctl emit A``
423+
424+ - Ensure ``/etc/init/outside_chroot.conf`` runs.
425+
426+ - Ensure ``/path/to/chroot/etc/init/in_chroot.conf`` does *NOT* run.
427+
428+Run as ``root`` inside a chroot
429+===============================
430+
431+- ``initctl list``
432+
433+ Ensure list is contents of ``/path/to/chroot/etc/init/``: command below should return no output::
434+
435+ cmp <(initctl list|awk '{print $1}'|sort -u) <(cd /etc/init && ls *.conf|cut -d: -f2-|sed 's/\.conf//g'|sort -u)
436+
437+- ``initctl status in_chroot``
438+
439+ Should work.
440+
441+- ``initctl status outside_chroot``
442+
443+ Should fail with message::
444+
445+ initct: Unknown job: outside_chroot
446+
447+- ``initctl show-config``
448+
449+ Should work.
450+
451+- ``initctl check-config``
452+
453+ Should work.
454+
455+- ``start outside_chroot``
456+
457+ Should fail with message::
458+
459+ initct: Unknown job: outside_chroot
460+
461+- ``stop outside_chroot``
462+
463+ Should fail with message::
464+
465+ initct: Unknown job: outside_chroot
466+
467+- ``start in_chroot``
468+
469+ Should work.
470+
471+- ``restart in_chroot``
472+
473+ Should work.
474+
475+- ``stop in_chroot``
476+
477+ Should work.
478+
479+- ``initctl emit wibble``
480+
481+ - Ensure ``/path/to/chroot/etc/init/foo.conf`` runs by looking at the log and ensuring
482+ the inode for the stat of '``/``' is the same as running "``stat /``" on the command-line.
483+
484+ - Ensure ``/etc/init/foo.conf`` does *NOT* run.
485+
486+- ``initctl emit A``
487+
488+ - Ensure ``/path/to/chroot/etc/init/in_chroot.conf`` runs.
489+
490+ - Ensure ``/etc/init/outside_chroot.conf`` does *NOT* run.
491+
492+Run as non-root inside a chroot
493+===============================
494+
495+Not supported.
496+
497+Run with ``--no-sessions``
498+==========================
499+
500+The "``--no-sessions``" option makes Upstart behave as it used to prior to
501+the introduction of session support.
502+
503+#. Reboot system and specify "``--no-sessions``" on kernel command-line.
504+
505+.. Ensure "``initctl list``" within a chroot displays the same list as
506+ "``initctl list``" run outside of any chroot environment.
507+
508
509=== modified file 'conf/rc-sysinit.conf'
510--- conf/rc-sysinit.conf 2010-02-04 03:59:06 +0000
511+++ conf/rc-sysinit.conf 2011-06-06 15:17:24 +0000
512@@ -13,6 +13,8 @@
513 # or by faking an old /etc/inittab entry
514 env DEFAULT_RUNLEVEL=2
515
516+emits runlevel
517+
518 # There can be no previous runlevel here, but there might be old
519 # information in /var/run/utmp that we pick up, and we don't want
520 # that.
521
522=== modified file 'configure.ac'
523--- configure.ac 2011-03-22 17:53:17 +0000
524+++ configure.ac 2011-06-06 15:17:24 +0000
525@@ -2,7 +2,7 @@
526
527 AC_PREREQ(2.61)
528 AC_INIT([upstart], [1.3], [upstart-devel@lists.ubuntu.com])
529-NIH_COPYRIGHT([[Copyright © 2011 Scott James Remnant, Google Inc., Canonical Ltd.]])
530+NIH_COPYRIGHT([[Copyright © 2011 Scott James Remnant, Canonical Ltd.]])
531 AC_CONFIG_SRCDIR([init/main.c])
532 AC_CONFIG_MACRO_DIR([m4])
533
534@@ -64,6 +64,7 @@
535
536 AC_CONFIG_FILES([ Makefile intl/Makefile
537 dbus/Makefile init/Makefile util/Makefile conf/Makefile
538- doc/Makefile contrib/Makefile po/Makefile.in ])
539+ doc/Makefile contrib/Makefile po/Makefile.in
540+ scripts/Makefile ])
541 AC_CONFIG_HEADERS([config.h])
542 AC_OUTPUT
543
544=== modified file 'contrib/bash_completion/upstart'
545--- contrib/bash_completion/upstart 2010-12-21 13:54:49 +0000
546+++ contrib/bash_completion/upstart 2011-06-06 15:17:24 +0000
547@@ -3,26 +3,28 @@
548 #
549 # We don't provide completion for 'init' itself for obvious reasons.
550 have initctl &&
551-_upstart_conf_events()
552-{
553- initctl list|awk '{print $1}'
554-} &&
555-_upstart_named_events()
556-{
557- (cd /etc/init && grep '^emits ' *.conf|sed 's/^emits //g')
558-} &&
559-_upstart_events()
560-{
561- (_upstart_conf_events;_upstart_named_events)|tr ' ' '\n'|sort -u
562-} &&
563-_upstart_startable_events()
564+_upstart_jobs()
565+{
566+ initctl list|awk '{print $1}'|sort -u
567+} &&
568+_upstart_startable_jobs()
569 {
570 initctl list|cut -d\, -f1|awk '$2 == "stop/waiting" {print $1}'
571 } &&
572-_upstart_stoppable_events()
573+_upstart_stoppable_jobs()
574 {
575 initctl list|cut -d\, -f1|awk '$2 == "start/running" {print $1}'
576 } &&
577+_upstart_events()
578+{
579+ # note that we don't provide the internal events such as "starting"
580+ # (and those from mountall) since the user should be using the
581+ # associated command to emit such events.
582+ (cd /etc/init && \
583+ egrep '^[[:space:]]*emits ' *.conf |\
584+ cut -d: -f2- | sed 's/^[[:space:]]*emits //g' |\
585+ tr ' ' '\n' | awk '{print $NF}' | grep -v ^$|sort -u)
586+} &&
587 _upstart_initctl()
588 {
589 _get_comp_words_by_ref cur prev
590@@ -32,34 +34,92 @@
591 case "$prev" in
592
593 start)
594- COMPREPLY=( $(compgen -W "-n --no-wait $(_upstart_startable_events)" -- ${cur}) )
595+ COMPREPLY=( $(compgen -W "-n --no-wait $(_upstart_startable_jobs)" -- ${cur}) )
596 return 0
597 ;;
598
599 stop)
600- COMPREPLY=( $(compgen -W "-n --no-wait $(_upstart_stoppable_events)" -- ${cur}) )
601+ COMPREPLY=( $(compgen -W "-n --no-wait $(_upstart_stoppable_jobs)" -- ${cur}) )
602 return 0
603 ;;
604
605 emit)
606- COMPREPLY=( $(compgen -W "$(_upstart_events)" -- ${cur}) )
607- return 0
608- ;;
609-
610- reload|restart|status)
611- COMPREPLY=( $(compgen -W "$(_upstart_conf_events)" -- ${cur}) )
612+ COMPREPLY=( $(compgen -W "-n --no-wait $(_upstart_events)" -- ${cur}) )
613+ return 0
614+ ;;
615+
616+ -i|--ignore-events)
617+ # handle visualisation options after check-config command
618+ for cmd in check-config
619+ do
620+ cwords=${COMP_WORDS[@]##}
621+ filtered_cwords=${COMP_WORDS[@]##${cmd}}
622+ if [ "$filtered_cwords" != "$cwords" ]
623+ then
624+ COMPREPLY=( $(compgen -W "$(_upstart_jobs)" -- ${cur}) )
625+ return 0
626+ fi
627+ done
628+ ;;
629+
630+ -e|--enumerate)
631+ # handle visualisation options after show-config command
632+ for cmd in show-config
633+ do
634+ cwords=${COMP_WORDS[@]##}
635+ filtered_cwords=${COMP_WORDS[@]##${cmd}}
636+ if [ "$filtered_cwords" != "$cwords" ]
637+ then
638+ COMPREPLY=( $(compgen -W "$(_upstart_jobs)" -- ${cur}) )
639+ return 0
640+ fi
641+ done
642+ ;;
643+
644+ reload|restart)
645+ COMPREPLY=( $(compgen -W "-n --no-wait $(_upstart_stoppable_jobs)" -- ${cur}) )
646+ return 0
647+ ;;
648+
649+ status)
650+ COMPREPLY=( $(compgen -W "$(_upstart_jobs)" -- ${cur}) )
651+ return 0
652+ ;;
653+
654+ check-config)
655+ COMPREPLY=( $(compgen -W "-w --warn -i --ignore-events= $(_upstart_jobs)" -- ${cur}) )
656+ return 0
657+ ;;
658+ show-config)
659+ COMPREPLY=( $(compgen -W "-e --enumerate $(_upstart_jobs)" -- ${cur}) )
660 return 0
661 ;;
662
663 -n|--no-wait)
664- # allow no wait after start/stop commands
665- for cmd in start stop
666+ # allow 'no wait' for certain commands
667+ for cmd in start stop restart emit
668 do
669 cwords=${COMP_WORDS[@]##}
670 filtered_cwords=${COMP_WORDS[@]##${cmd}}
671 if [ "$filtered_cwords" != "$cwords" ]
672 then
673- COMPREPLY=( $(compgen -W "$(_upstart_${cmd}able_events)" -- ${cur}) )
674+ case "$cmd" in
675+ start)
676+ COMPREPLY=( $(compgen -W "$(_upstart_startable_jobs)" -- ${cur}) )
677+ ;;
678+
679+ stop)
680+ COMPREPLY=( $(compgen -W "$(_upstart_stoppable_jobs)" -- ${cur}) )
681+ ;;
682+
683+ restart)
684+ COMPREPLY=( $(compgen -W "$(_upstart_stoppable_jobs)" -- ${cur}) )
685+ ;;
686+
687+ emit)
688+ COMPREPLY=( $(compgen -W "$(_upstart_events)" -- ${cur}) )
689+ ;;
690+ esac
691 return 0
692 fi
693 done
694@@ -71,7 +131,7 @@
695 ;;
696 esac
697
698- opts="--help --version -q --quiet -v --verbose --system --dest="
699+ opts="--help --version -q --quiet -v --verbose --session --system --dest="
700 cmds=$(initctl help|grep "^ [^ ]"|awk '{print $1}')
701
702 COMPREPLY=( $(compgen -W "${opts} ${cmds}" -- ${cur}) )
703@@ -84,7 +144,7 @@
704 COMPREPLY=()
705 _get_comp_words_by_ref cur prev
706
707- opts="--help --version -q --quiet -v --verbose --system --dest= \
708+ opts="--help --version -q --quiet -v --verbose --session --system --dest= \
709 -n --no-wait"
710
711 case "$prev" in
712@@ -94,7 +154,7 @@
713 ;;
714 esac
715
716- COMPREPLY=( $(compgen -W "$opts $(_upstart_startable_events)" -- ${cur}) )
717+ COMPREPLY=( $(compgen -W "$opts $(_upstart_startable_jobs)" -- ${cur}) )
718 return 0
719 } && complete -F _upstart_start start
720
721@@ -104,7 +164,7 @@
722 COMPREPLY=()
723 _get_comp_words_by_ref cur prev
724
725- opts="--help --version -q --quiet -v --verbose --system --dest= \
726+ opts="--help --version -q --quiet -v --verbose --session --system --dest= \
727 -n --no-wait"
728
729 case "$prev" in
730@@ -114,7 +174,7 @@
731 ;;
732 esac
733
734- COMPREPLY=( $(compgen -W "$opts $(_upstart_stoppable_events)" -- ${cur}) )
735+ COMPREPLY=( $(compgen -W "$opts $(_upstart_stoppable_jobs)" -- ${cur}) )
736 return 0
737 } && complete -F _upstart_stop stop
738
739@@ -124,7 +184,7 @@
740 COMPREPLY=()
741 _get_comp_words_by_ref cur prev
742
743- opts="--help --version -q --quiet -v --verbose --system --dest= \
744+ opts="--help --version -q --quiet -v --verbose --session --system --dest= \
745 -n --no-wait"
746
747 case "$prev" in
748@@ -134,7 +194,7 @@
749 ;;
750 esac
751
752- COMPREPLY=( $(compgen -W "$opts $(_upstart_events)" -- ${cur}) )
753+ COMPREPLY=( $(compgen -W "$opts $(_upstart_stoppable_jobs)" -- ${cur}) )
754 return 0
755
756 } && complete -F _upstart_restart restart
757@@ -145,7 +205,7 @@
758 COMPREPLY=()
759 _get_comp_words_by_ref cur prev
760
761- opts="--help --version -q --quiet -v --verbose --system --dest="
762+ opts="--help --version -q -d --detail -e --enumerate --quiet -v --verbose --session --system --dest="
763
764 case "$prev" in
765 --help|--version)
766@@ -154,7 +214,7 @@
767 ;;
768 esac
769
770- COMPREPLY=( $(compgen -W "$opts $(_upstart_events)" -- ${cur}) )
771+ COMPREPLY=( $(compgen -W "$opts $(_upstart_jobs)" -- ${cur}) )
772 return 0
773
774 } && complete -F _upstart_status status
775@@ -165,7 +225,7 @@
776 COMPREPLY=()
777 _get_comp_words_by_ref cur prev
778
779- opts="--help --version -q --quiet -v --verbose --system --dest="
780+ opts="--help --version -q --quiet -v --verbose --session --system --dest="
781
782 case "$prev" in
783 --help|--version)
784@@ -174,7 +234,7 @@
785 ;;
786 esac
787
788- COMPREPLY=( $(compgen -W "$opts $(_upstart_events)" -- ${cur}) )
789+ COMPREPLY=( $(compgen -W "$opts $(_upstart_stoppable_jobs)" -- ${cur}) )
790 return 0
791
792 } && complete -F _upstart_reload reload
793
794=== modified file 'dbus/Upstart.conf'
795--- dbus/Upstart.conf 2009-07-02 17:46:41 +0000
796+++ dbus/Upstart.conf 2011-06-06 15:17:24 +0000
797@@ -9,12 +9,14 @@
798 <allow own="com.ubuntu.Upstart" />
799 </policy>
800
801- <!-- Permit the root user to invoke all of the methods on Upstart, its jobs
802- or their instances, and to get and set properties. -->
803- <policy user="root">
804+ <!-- Allow any user to invoke all of the methods on Upstart, its jobs
805+ or their instances, and to get and set properties - since Upstart
806+ isolates commands by user. -->
807+ <policy context="default">
808+ <allow send_destination="com.ubuntu.Upstart"
809+ send_interface="org.freedesktop.DBus.Introspectable" />
810 <allow send_destination="com.ubuntu.Upstart"
811 send_interface="org.freedesktop.DBus.Properties" />
812-
813 <allow send_destination="com.ubuntu.Upstart"
814 send_interface="com.ubuntu.Upstart0_6" />
815 <allow send_destination="com.ubuntu.Upstart"
816@@ -22,36 +24,4 @@
817 <allow send_destination="com.ubuntu.Upstart"
818 send_interface="com.ubuntu.Upstart0_6.Instance" />
819 </policy>
820-
821- <!-- Allow any user to introspect Upstart's interfaces, to obtain the
822- values of properties (but not set them) and to invoke selected
823- methods on Upstart and its jobs that are used to walk information. -->
824- <policy context="default">
825- <allow send_destination="com.ubuntu.Upstart"
826- send_interface="org.freedesktop.DBus.Introspectable" />
827-
828- <allow send_destination="com.ubuntu.Upstart"
829- send_interface="org.freedesktop.DBus.Properties"
830- send_type="method_call" send_member="Get" />
831- <allow send_destination="com.ubuntu.Upstart"
832- send_interface="org.freedesktop.DBus.Properties"
833- send_type="method_call" send_member="GetAll" />
834-
835- <allow send_destination="com.ubuntu.Upstart"
836- send_interface="com.ubuntu.Upstart0_6"
837- send_type="method_call" send_member="GetJobByName" />
838- <allow send_destination="com.ubuntu.Upstart"
839- send_interface="com.ubuntu.Upstart0_6"
840- send_type="method_call" send_member="GetAllJobs" />
841-
842- <allow send_destination="com.ubuntu.Upstart"
843- send_interface="com.ubuntu.Upstart0_6.Job"
844- send_type="method_call" send_member="GetInstance" />
845- <allow send_destination="com.ubuntu.Upstart"
846- send_interface="com.ubuntu.Upstart0_6.Job"
847- send_type="method_call" send_member="GetInstanceByName" />
848- <allow send_destination="com.ubuntu.Upstart"
849- send_interface="com.ubuntu.Upstart0_6.Job"
850- send_type="method_call" send_member="GetAllInstances" />
851- </policy>
852 </busconfig>
853
854=== modified file 'dbus/upstart.h'
855--- dbus/upstart.h 2010-12-10 04:04:51 +0000
856+++ dbus/upstart.h 2011-06-06 15:17:24 +0000
857@@ -31,7 +31,7 @@
858 # define DBUS_SERVICE_UPSTART "com.ubuntu.TestUpstart"
859 # else
860 # define DBUS_SERVICE_UPSTART "com.ubuntu.Upstart"
861-#endif
862+# endif
863 #endif
864
865
866
867=== modified file 'init/Makefile.am'
868--- init/Makefile.am 2010-02-04 03:42:29 +0000
869+++ init/Makefile.am 2011-06-06 15:17:24 +0000
870@@ -40,6 +40,7 @@
871 system.c system.h \
872 environ.c environ.h \
873 process.c process.h \
874+ session.c session.h \
875 job_class.c job_class.h \
876 job_process.c job_process.h \
877 job.c job.h \
878@@ -158,6 +159,7 @@
879 system.o environ.o process.o \
880 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
881 parse_job.o parse_conf.o conf.o control.o \
882+ session.o \
883 com.ubuntu.Upstart.o \
884 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
885 $(NIH_LIBS) \
886@@ -169,6 +171,7 @@
887 system.o environ.o process.o \
888 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
889 parse_job.o parse_conf.o conf.o control.o \
890+ session.o \
891 com.ubuntu.Upstart.o \
892 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
893 $(NIH_LIBS) \
894@@ -180,6 +183,7 @@
895 system.o environ.o process.o \
896 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
897 parse_job.o parse_conf.o conf.o control.o \
898+ session.o \
899 com.ubuntu.Upstart.o \
900 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
901 $(NIH_LIBS) \
902@@ -191,6 +195,7 @@
903 system.o environ.o process.o \
904 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
905 parse_job.o parse_conf.o conf.o control.o \
906+ session.o \
907 com.ubuntu.Upstart.o \
908 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
909 $(NIH_LIBS) \
910@@ -202,6 +207,7 @@
911 system.o environ.o process.o \
912 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
913 parse_job.o parse_conf.o conf.o control.o \
914+ session.o \
915 com.ubuntu.Upstart.o \
916 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
917 $(NIH_LIBS) \
918@@ -213,6 +219,7 @@
919 system.o environ.o process.o \
920 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
921 parse_job.o parse_conf.o conf.o control.o \
922+ session.o \
923 com.ubuntu.Upstart.o \
924 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
925 $(NIH_LIBS) \
926@@ -224,6 +231,7 @@
927 system.o environ.o process.o \
928 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
929 parse_job.o parse_conf.o conf.o control.o \
930+ session.o \
931 com.ubuntu.Upstart.o \
932 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
933 $(NIH_LIBS) \
934@@ -235,6 +243,7 @@
935 system.o environ.o process.o \
936 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
937 parse_job.o parse_conf.o conf.o control.o \
938+ session.o \
939 com.ubuntu.Upstart.o \
940 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
941 $(NIH_LIBS) \
942@@ -246,6 +255,7 @@
943 system.o environ.o process.o \
944 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
945 parse_job.o parse_conf.o conf.o control.o \
946+ session.o \
947 com.ubuntu.Upstart.o \
948 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
949 $(NIH_LIBS) \
950@@ -257,6 +267,7 @@
951 system.o environ.o process.o \
952 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
953 parse_job.o parse_conf.o conf.o control.o \
954+ session.o \
955 com.ubuntu.Upstart.o \
956 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
957 $(NIH_LIBS) \
958@@ -268,6 +279,7 @@
959 system.o environ.o process.o \
960 job_class.o job_process.o job.o event.o event_operator.o blocked.o \
961 parse_job.o parse_conf.o conf.o control.o \
962+ session.o \
963 com.ubuntu.Upstart.o \
964 com.ubuntu.Upstart.Job.o com.ubuntu.Upstart.Instance.o \
965 $(NIH_LIBS) \
966
967=== modified file 'init/conf.c'
968--- init/conf.c 2011-03-15 18:44:09 +0000
969+++ init/conf.c 2011-06-06 15:17:24 +0000
970@@ -2,8 +2,7 @@
971 *
972 * conf.c - configuration management
973 *
974- * Copyright © 2011 Google Inc.
975- * Copyright © 2009 Canonical Ltd.
976+ * Copyright © 2009,2010,2011 Canonical Ltd.
977 * Author: Scott James Remnant <scott@netsplit.com>.
978 *
979 * This program is free software; you can redistribute it and/or modify
980@@ -147,6 +146,7 @@
981
982 source->type = type;
983 source->watch = NULL;
984+ source->session = NULL;
985
986 source->flag = FALSE;
987 source->files = nih_hash_string_new (source, 0);
988@@ -745,7 +745,8 @@
989 * the job definition.
990 */
991 nih_debug ("Loading %s from %s", name, path);
992- file->job = parse_job (NULL, name, buf, len, &pos, &lineno);
993+ file->job = parse_job (NULL, source->session,
994+ name, buf, len, &pos, &lineno);
995 if (file->job) {
996 job_class_consider (file->job);
997 } else {
998@@ -849,7 +850,8 @@
999
1000 /**
1001 * conf_select_job:
1002- * @name: name of job class to locate.
1003+ * @name: name of job class to locate,
1004+ * @session: session class name belongs to.
1005 *
1006 * Select the best available class of a job named @name from the registered
1007 * configuration sources.
1008@@ -857,7 +859,7 @@
1009 * Returns: Best available job class or NULL if none available.
1010 **/
1011 JobClass *
1012-conf_select_job (const char *name)
1013+conf_select_job (const char *name, const Session *session)
1014 {
1015 nih_assert (name != NULL);
1016
1017@@ -869,6 +871,9 @@
1018 if (source->type != CONF_JOB_DIR)
1019 continue;
1020
1021+ if (source->session != session)
1022+ continue;
1023+
1024 NIH_HASH_FOREACH (source->files, file_iter) {
1025 ConfFile *file = (ConfFile *)file_iter;
1026
1027
1028=== modified file 'init/conf.h'
1029--- init/conf.h 2009-07-09 08:36:52 +0000
1030+++ init/conf.h 2011-06-06 15:17:24 +0000
1031@@ -1,6 +1,6 @@
1032 /* upstart
1033 *
1034- * Copyright © 2009 Canonical Ltd.
1035+ * Copyright © 2010,2011 Canonical Ltd.
1036 * Author: Scott James Remnant <scott@netsplit.com>.
1037 *
1038 * This program is free software; you can redistribute it and/or modify
1039@@ -26,6 +26,7 @@
1040 #include <nih/list.h>
1041 #include <nih/watch.h>
1042
1043+#include "session.h"
1044 #include "job_class.h"
1045
1046
1047@@ -47,6 +48,7 @@
1048 /**
1049 * ConfSource:
1050 * @entry: list header,
1051+ * @session: attached session,
1052 * @path: path to source,
1053 * @type: type of source,
1054 * @watch: NihWatch structure for automatic change notification,
1055@@ -64,6 +66,7 @@
1056 **/
1057 typedef struct conf_source {
1058 NihList entry;
1059+ Session * session;
1060 char *path;
1061 ConfSourceType type;
1062
1063@@ -122,7 +125,7 @@
1064
1065 int conf_file_destroy (ConfFile *file);
1066
1067-JobClass * conf_select_job (const char *name);
1068+JobClass * conf_select_job (const char *name, const Session *session);
1069
1070 NIH_END_EXTERN
1071
1072
1073=== modified file 'init/control.c'
1074--- init/control.c 2009-07-11 11:47:12 +0000
1075+++ init/control.c 2011-06-06 15:17:24 +0000
1076@@ -2,7 +2,7 @@
1077 *
1078 * control.c - D-Bus connections, objects and methods
1079 *
1080- * Copyright © 2009 Canonical Ltd.
1081+ * Copyright © 2009-2011 Canonical Ltd.
1082 * Author: Scott James Remnant <scott@netsplit.com>.
1083 *
1084 * This program is free software; you can redistribute it and/or modify
1085@@ -46,6 +46,7 @@
1086 #include "dbus/upstart.h"
1087
1088 #include "environ.h"
1089+#include "session.h"
1090 #include "job_class.h"
1091 #include "blocked.h"
1092 #include "conf.h"
1093@@ -54,12 +55,19 @@
1094
1095 #include "com.ubuntu.Upstart.h"
1096
1097-
1098 /* Prototypes for static functions */
1099 static int control_server_connect (DBusServer *server, DBusConnection *conn);
1100 static void control_disconnected (DBusConnection *conn);
1101 static void control_register_all (DBusConnection *conn);
1102
1103+/**
1104+ * use_session_bus:
1105+ *
1106+ * If TRUE, connect to the D-Bus sessio bus rather than the system bus.
1107+ *
1108+ * Used for testing.
1109+ **/
1110+int use_session_bus = FALSE;
1111
1112 /**
1113 * control_server_address:
1114@@ -78,7 +86,7 @@
1115 /**
1116 * control_bus:
1117 *
1118- * Open connection to D-Bus system bus. The connection may be opened with
1119+ * Open connection to a D-Bus bus. The connection may be opened with
1120 * control_bus_open() and if lost will become NULL.
1121 **/
1122 DBusConnection *control_bus = NULL;
1123@@ -86,7 +94,7 @@
1124 /**
1125 * control_conns:
1126 *
1127- * Open control connections, including the connection to the D-Bus system
1128+ * Open control connections, including the connection to a D-Bus
1129 * bus and any private client connections.
1130 **/
1131 NihList *control_conns = NULL;
1132@@ -190,8 +198,9 @@
1133 /**
1134 * control_bus_open:
1135 *
1136- * Open a connection to the D-Bus system bus and store it in the control_bus
1137- * global. The connection is handled automatically in the main loop.
1138+ * Open a connection to the appropriate D-Bus bus and store it in the
1139+ * control_bus global. The connection is handled automatically
1140+ * in the main loop.
1141 *
1142 * Returns: zero on success, negative value on raised error.
1143 **/
1144@@ -207,10 +216,13 @@
1145
1146 control_init ();
1147
1148+ control_handle_bus_type ();
1149+
1150 /* Connect to the D-Bus System Bus and hook everything up into
1151 * our own main loop automatically.
1152 */
1153- conn = nih_dbus_bus (DBUS_BUS_SYSTEM, control_disconnected);
1154+ conn = nih_dbus_bus (use_session_bus ? DBUS_BUS_SESSION : DBUS_BUS_SYSTEM,
1155+ control_disconnected);
1156 if (! conn)
1157 return -1;
1158
1159@@ -382,7 +394,9 @@
1160 const char *name,
1161 char **job)
1162 {
1163- JobClass *class;
1164+ Session *session;
1165+ JobClass *class = NULL;
1166+ JobClass *global_class = NULL;
1167
1168 nih_assert (message != NULL);
1169 nih_assert (name != NULL);
1170@@ -397,8 +411,30 @@
1171 return -1;
1172 }
1173
1174- /* Lookup the job and copy its path into the reply */
1175- class = (JobClass *)nih_hash_lookup (job_classes, name);
1176+ /* Get the relevant session */
1177+ session = session_from_dbus (NULL, message);
1178+
1179+ /* Lookup the job */
1180+ class = (JobClass *)nih_hash_search (job_classes, name, NULL);
1181+
1182+ while (class && (class->session != session)) {
1183+
1184+ /* Found a match in the global session which may be used
1185+ * later if no matching user session job exists.
1186+ */
1187+ if ((! class->session) && (session && ! session->chroot))
1188+ global_class = class;
1189+
1190+ class = (JobClass *)nih_hash_search (job_classes, name,
1191+ &class->entry);
1192+ }
1193+
1194+ /* If no job with the given name exists in the appropriate
1195+ * session, look in the global namespace (aka the NULL session).
1196+ */
1197+ if (! class)
1198+ class = global_class;
1199+
1200 if (! class) {
1201 nih_dbus_error_raise_printf (
1202 DBUS_INTERFACE_UPSTART ".Error.UnknownJob",
1203@@ -406,6 +442,7 @@
1204 return -1;
1205 }
1206
1207+ /* Copy the path */
1208 *job = nih_strdup (message, class->path);
1209 if (! *job)
1210 nih_return_system_error (-1);
1211@@ -432,6 +469,7 @@
1212 NihDBusMessage *message,
1213 char ***jobs)
1214 {
1215+ Session *session;
1216 char **list;
1217 size_t len;
1218
1219@@ -445,9 +483,16 @@
1220 if (! list)
1221 nih_return_system_error (-1);
1222
1223+ /* Get the relevant session */
1224+ session = session_from_dbus (NULL, message);
1225+
1226 NIH_HASH_FOREACH (job_classes, iter) {
1227 JobClass *class = (JobClass *)iter;
1228
1229+ if ((class->session || (session && session->chroot))
1230+ && (class->session != session))
1231+ continue;
1232+
1233 if (! nih_str_array_add (&list, message, &len,
1234 class->path)) {
1235 nih_error_raise_system ();
1236@@ -520,6 +565,9 @@
1237 if (! event)
1238 nih_return_system_error (-1);
1239
1240+ /* Obtain the session */
1241+ event->session = session_from_dbus (NULL, message);
1242+
1243 if (wait) {
1244 blocked = blocked_new (event, BLOCKED_EMIT_METHOD, message);
1245 if (! blocked) {
1246@@ -669,3 +717,18 @@
1247
1248 return 0;
1249 }
1250+
1251+/**
1252+ * control_handle_bus_type:
1253+ *
1254+ * Determine D-Bus bus type to connect to.
1255+ **/
1256+void
1257+control_handle_bus_type (void)
1258+{
1259+ if (getenv (USE_SESSION_BUS_ENV))
1260+ use_session_bus = TRUE;
1261+
1262+ if (use_session_bus)
1263+ nih_debug ("Using session bus");
1264+}
1265
1266=== modified file 'init/control.h'
1267--- init/control.h 2009-07-09 08:36:52 +0000
1268+++ init/control.h 2011-06-06 15:17:24 +0000
1269@@ -1,6 +1,6 @@
1270 /* upstart
1271 *
1272- * Copyright © 2009 Canonical Ltd.
1273+ * Copyright © 2009-2011 Canonical Ltd.
1274 * Author: Scott James Remnant <scott@netsplit.com>.
1275 *
1276 * This program is free software; you can redistribute it and/or modify
1277@@ -27,6 +27,18 @@
1278 #include <nih-dbus/dbus_connection.h>
1279 #include <nih-dbus/dbus_message.h>
1280
1281+/**
1282+ * USE_SESSION_BUS_ENV:
1283+ *
1284+ * If this environment variable is set to any value, connect to
1285+ * D-Bus session bus rather than the system bus.
1286+ *
1287+ * Used for testing.
1288+ **/
1289+#ifndef USE_SESSION_BUS_ENV
1290+#define USE_SESSION_BUS_ENV "UPSTART_USE_SESSION_BUS"
1291+#endif
1292+
1293
1294 NIH_BEGIN_EXTERN
1295
1296@@ -72,6 +84,8 @@
1297 const char *log_priority)
1298 __attribute__ ((warn_unused_result));
1299
1300+void control_handle_bus_type (void);
1301+
1302 NIH_END_EXTERN
1303
1304 #endif /* INIT_CONTROL_H */
1305
1306=== modified file 'init/environ.c'
1307--- init/environ.c 2011-03-16 22:42:48 +0000
1308+++ init/environ.c 2011-06-06 15:17:24 +0000
1309@@ -2,7 +2,6 @@
1310 *
1311 * environ.c - environment table utilities
1312 *
1313- * Copyright © 2011 Google Inc.
1314 * Copyright © 2009 Canonical Ltd.
1315 * Author: Scott James Remnant <scott@netsplit.com>.
1316 *
1317
1318=== modified file 'init/environ.h'
1319--- init/environ.h 2011-03-16 22:42:48 +0000
1320+++ init/environ.h 2011-06-06 15:17:24 +0000
1321@@ -1,6 +1,5 @@
1322 /* upstart
1323 *
1324- * Copyright © 2011 Google Inc.
1325 * Copyright © 2009 Canonical Ltd.
1326 * Author: Scott James Remnant <scott@netsplit.com>.
1327 *
1328
1329=== modified file 'init/event.c'
1330--- init/event.c 2010-12-14 15:32:41 +0000
1331+++ init/event.c 2011-06-06 15:17:24 +0000
1332@@ -123,6 +123,8 @@
1333
1334 nih_list_init (&event->entry);
1335
1336+ event->session = NULL;
1337+
1338 event->progress = EVENT_PENDING;
1339 event->failed = FALSE;
1340
1341@@ -293,6 +295,13 @@
1342 NIH_HASH_FOREACH_SAFE (job_classes, iter) {
1343 JobClass *class = (JobClass *)iter;
1344
1345+ /* Only affect jobs within the same session as the event
1346+ * unless the event has no session, in which case do them
1347+ * all.
1348+ */
1349+ if (event->session && (class->session != event->session))
1350+ continue;
1351+
1352 /* We stop first so that if an event is listed both as a
1353 * stop and start event, it causes an active running process
1354 * to be killed, the stop script then the start script to be
1355@@ -470,6 +479,7 @@
1356 failed = NIH_MUST (nih_sprintf (NULL, "%s/failed",
1357 event->name));
1358 new_event = NIH_MUST (event_new (NULL, failed, NULL));
1359+ new_event->session = event->session;
1360
1361 if (event->env)
1362 new_event->env = NIH_MUST (nih_str_array_copy (
1363
1364=== modified file 'init/event.h'
1365--- init/event.h 2009-07-09 08:36:52 +0000
1366+++ init/event.h 2011-06-06 15:17:24 +0000
1367@@ -1,6 +1,6 @@
1368 /* upstart
1369 *
1370- * Copyright © 2009 Canonical Ltd.
1371+ * Copyright © 2010 Canonical Ltd.
1372 * Author: Scott James Remnant <scott@netsplit.com>.
1373 *
1374 * This program is free software; you can redistribute it and/or modify
1375@@ -23,6 +23,8 @@
1376 #include <nih/macros.h>
1377 #include <nih/list.h>
1378
1379+#include "session.h"
1380+
1381
1382 /**
1383 * EventProgress:
1384@@ -40,6 +42,7 @@
1385 /**
1386 * Event:
1387 * @entry: list header,
1388+ * @session: session the event is attached to,
1389 * @name: string name of the event,
1390 * @env: NULL-terminated array of environment variables,
1391 * @progress: progress of event,
1392@@ -61,6 +64,7 @@
1393 typedef struct event {
1394 NihList entry;
1395
1396+ Session * session;
1397 char *name;
1398 char **env;
1399
1400
1401=== modified file 'init/job.c'
1402--- init/job.c 2010-12-14 15:32:41 +0000
1403+++ init/job.c 2011-06-06 15:17:24 +0000
1404@@ -2,7 +2,7 @@
1405 *
1406 * job.c - core state machine of tasks and services
1407 *
1408- * Copyright © 2010 Canonical Ltd.
1409+ * Copyright © 2010,2011 Canonical Ltd.
1410 * Author: Scott James Remnant <scott@netsplit.com>.
1411 *
1412 * This program is free software; you can redistribute it and/or modify
1413@@ -47,6 +47,7 @@
1414 #include "events.h"
1415 #include "environ.h"
1416 #include "process.h"
1417+#include "session.h"
1418 #include "job_class.h"
1419 #include "job.h"
1420 #include "job_process.h"
1421@@ -99,8 +100,14 @@
1422
1423 job->class = class;
1424
1425- job->path = nih_dbus_path (job, DBUS_PATH_UPSTART, "jobs",
1426- class->name, job->name, NULL);
1427+ if (job->class->session && job->class->session->chroot) {
1428+ /* JobClass already contains a valid D-Bus path prefix for the job */
1429+ job->path = nih_dbus_path (job, class->path, job->name, NULL);
1430+ } else {
1431+ job->path = nih_dbus_path (job, DBUS_PATH_UPSTART, "jobs",
1432+ class->name, job->name, NULL);
1433+ }
1434+
1435 if (! job->path)
1436 goto error;
1437
1438@@ -906,6 +913,7 @@
1439 }
1440
1441 event = NIH_MUST (event_new (NULL, name, env));
1442+ event->session = job->class->session;
1443
1444 if (block) {
1445 Blocked *blocked;
1446@@ -1102,11 +1110,22 @@
1447 NihDBusMessage *message,
1448 int wait)
1449 {
1450+ Session *session;
1451 Blocked *blocked = NULL;
1452
1453 nih_assert (job != NULL);
1454 nih_assert (message != NULL);
1455
1456+ /* Don't permit out-of-session modification */
1457+ session = session_from_dbus (NULL, message);
1458+ if (session != job->class->session) {
1459+ nih_dbus_error_raise_printf (
1460+ DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1461+ _("You do not have permission to modify job: %s"),
1462+ job_name (job));
1463+ return -1;
1464+ }
1465+
1466 if (job->goal == JOB_START) {
1467 nih_dbus_error_raise_printf (
1468 DBUS_INTERFACE_UPSTART ".Error.AlreadyStarted",
1469@@ -1166,11 +1185,22 @@
1470 NihDBusMessage *message,
1471 int wait)
1472 {
1473+ Session *session;
1474 Blocked *blocked = NULL;
1475
1476 nih_assert (job != NULL);
1477 nih_assert (message != NULL);
1478
1479+ /* Don't permit out-of-session modification */
1480+ session = session_from_dbus (NULL, message);
1481+ if (session != job->class->session) {
1482+ nih_dbus_error_raise_printf (
1483+ DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1484+ _("You do not have permission to modify job: %s"),
1485+ job_name (job));
1486+ return -1;
1487+ }
1488+
1489 if (job->goal == JOB_STOP) {
1490 nih_dbus_error_raise_printf (
1491 DBUS_INTERFACE_UPSTART ".Error.AlreadyStopped",
1492@@ -1231,11 +1261,22 @@
1493 NihDBusMessage *message,
1494 int wait)
1495 {
1496+ Session *session;
1497 Blocked *blocked = NULL;
1498
1499 nih_assert (job != NULL);
1500 nih_assert (message != NULL);
1501
1502+ /* Don't permit out-of-session modification */
1503+ session = session_from_dbus (NULL, message);
1504+ if (session != job->class->session) {
1505+ nih_dbus_error_raise_printf (
1506+ DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1507+ _("You do not have permission to modify job: %s"),
1508+ job_name (job));
1509+ return -1;
1510+ }
1511+
1512 if (job->goal == JOB_STOP) {
1513 nih_dbus_error_raise_printf (
1514 DBUS_INTERFACE_UPSTART ".Error.AlreadyStopped",
1515
1516=== modified file 'init/job.h'
1517--- init/job.h 2009-07-03 16:38:02 +0000
1518+++ init/job.h 2011-06-06 15:17:24 +0000
1519@@ -1,6 +1,6 @@
1520 /* upstart
1521 *
1522- * Copyright © 2009 Canonical Ltd.
1523+ * Copyright © 2010 Canonical Ltd.
1524 * Author: Scott James Remnant <scott@netsplit.com>.
1525 *
1526 * This program is free software; you can redistribute it and/or modify
1527
1528=== modified file 'init/job_class.c'
1529--- init/job_class.c 2011-05-12 20:42:28 +0000
1530+++ init/job_class.c 2011-06-06 15:17:24 +0000
1531@@ -2,7 +2,7 @@
1532 *
1533 * job_class.c - job class definition handling
1534 *
1535- * Copyright © 2010 Canonical Ltd.
1536+ * Copyright © 2010,2011 Canonical Ltd.
1537 * Author: Scott James Remnant <scott@netsplit.com>.
1538 *
1539 * This program is free software; you can redistribute it and/or modify
1540@@ -45,6 +45,7 @@
1541
1542 #include "environ.h"
1543 #include "process.h"
1544+#include "session.h"
1545 #include "job_class.h"
1546 #include "job.h"
1547 #include "event_operator.h"
1548@@ -100,7 +101,7 @@
1549
1550 /* Prototypes for static functions */
1551 static void job_class_add (JobClass *class);
1552-static int job_class_remove (JobClass *class);
1553+static int job_class_remove (JobClass *class, const Session *session);
1554
1555
1556 /**
1557@@ -128,13 +129,15 @@
1558
1559 /**
1560 * job_class_new:
1561+ *
1562 * @parent: parent for new job class,
1563- * @name: name of new job class.
1564+ * @name: name of new job class,
1565+ * @session: session.
1566 *
1567- * Allocates and returns a new JobClass structure with the @name given.
1568- * It will not be automatically added to the job classes table, it is up
1569- * to the caller to ensure this is done using job_class_register() once
1570- * the class has been set up.
1571+ * Allocates and returns a new JobClass structure with the given @name
1572+ * and @session. It will not be automatically added to the job classes
1573+ * table, it is up to the caller to ensure this is done using
1574+ * job_class_register() once the class has been set up.
1575 *
1576 * If @parent is not NULL, it should be a pointer to another object which
1577 * will be used as a parent for the returned job class. When all parents
1578@@ -145,7 +148,8 @@
1579 **/
1580 JobClass *
1581 job_class_new (const void *parent,
1582- const char *name)
1583+ const char *name,
1584+ Session * session)
1585 {
1586 JobClass *class;
1587 int i;
1588@@ -165,8 +169,41 @@
1589 if (! class->name)
1590 goto error;
1591
1592- class->path = nih_dbus_path (class, DBUS_PATH_UPSTART, "jobs",
1593- class->name, NULL);
1594+ class->session = session;
1595+ if (class->session
1596+ && class->session->chroot
1597+ && class->session->user) {
1598+ nih_local char *uid = NULL;
1599+
1600+ uid = nih_sprintf (NULL, "%d", class->session->user);
1601+ if (! uid)
1602+ goto error;
1603+
1604+ class->path = nih_dbus_path (class, DBUS_PATH_UPSTART, "jobs",
1605+ session->chroot, uid,
1606+ class->name, NULL);
1607+
1608+ } else if (class->session
1609+ && class->session->chroot) {
1610+ class->path = nih_dbus_path (class, DBUS_PATH_UPSTART, "jobs",
1611+ session->chroot,
1612+ class->name, NULL);
1613+
1614+ } else if (class->session
1615+ && class->session->user) {
1616+ nih_local char *uid = NULL;
1617+
1618+ uid = nih_sprintf (NULL, "%d", class->session->user);
1619+ if (! uid)
1620+ goto error;
1621+
1622+ class->path = nih_dbus_path (class, DBUS_PATH_UPSTART, "jobs",
1623+ uid, class->name, NULL);
1624+
1625+ } else {
1626+ class->path = nih_dbus_path (class, DBUS_PATH_UPSTART, "jobs",
1627+ class->name, NULL);
1628+ }
1629 if (! class->path)
1630 goto error;
1631
1632@@ -245,19 +282,27 @@
1633 int
1634 job_class_consider (JobClass *class)
1635 {
1636- JobClass *registered, *best;
1637+ JobClass *registered = NULL, *best = NULL;
1638
1639 nih_assert (class != NULL);
1640
1641 job_class_init ();
1642
1643- best = conf_select_job (class->name);
1644+ best = conf_select_job (class->name, class->session);
1645 nih_assert (best != NULL);
1646-
1647- registered = (JobClass *)nih_hash_lookup (job_classes, class->name);
1648+ nih_assert (best->session == class->session);
1649+
1650+ registered = (JobClass *)nih_hash_search (job_classes, class->name, NULL);
1651+
1652+ /* If we found an entry, ensure we only consider the appropriate session */
1653+ while (registered && registered->session != class->session)
1654+ {
1655+ registered = (JobClass *)nih_hash_search (job_classes, class->name, &registered->entry);
1656+ }
1657+
1658 if (registered != best) {
1659 if (registered)
1660- if (! job_class_remove (registered))
1661+ if (! job_class_remove (registered, class->session))
1662 return FALSE;
1663
1664 job_class_add (best);
1665@@ -282,18 +327,25 @@
1666 int
1667 job_class_reconsider (JobClass *class)
1668 {
1669- JobClass *registered, *best;
1670+ JobClass *registered = NULL, *best = NULL;
1671
1672 nih_assert (class != NULL);
1673
1674 job_class_init ();
1675
1676- best = conf_select_job (class->name);
1677-
1678- registered = (JobClass *)nih_hash_lookup (job_classes, class->name);
1679+ best = conf_select_job (class->name, class->session);
1680+
1681+ registered = (JobClass *)nih_hash_search (job_classes, class->name, NULL);
1682+
1683+ /* If we found an entry, ensure we only consider the appropriate session */
1684+ while (registered && registered->session != class->session)
1685+ {
1686+ registered = (JobClass *)nih_hash_search (job_classes, class->name, &registered->entry);
1687+ }
1688+
1689 if (registered == class) {
1690 if (class != best) {
1691- if (! job_class_remove (class))
1692+ if (! job_class_remove (class, class->session))
1693 return FALSE;
1694
1695 job_class_add (best);
1696@@ -334,19 +386,24 @@
1697
1698 /**
1699 * job_class_remove:
1700- * @class: class to remove.
1701+ * @class: class to remove,
1702+ * @session: Session of @class.
1703 *
1704 * Removes @class from the hash table and unregisters it from all current
1705 * D-Bus connections.
1706 *
1707 * Returns: TRUE if class could be unregistered, FALSE if there are
1708- * active instances that prevent unregistration.
1709+ * active instances that prevent unregistration, or if @session
1710+ * does not match the session associated with @class.
1711 **/
1712 static int
1713-job_class_remove (JobClass *class)
1714+job_class_remove (JobClass *class, const Session *session)
1715 {
1716 nih_assert (class != NULL);
1717
1718+ if (class->session != session)
1719+ return FALSE;
1720+
1721 control_init ();
1722
1723 /* Return if we have any active instances */
1724@@ -696,6 +753,7 @@
1725 char * const *env,
1726 int wait)
1727 {
1728+ Session *session;
1729 Blocked *blocked = NULL;
1730 Job *job;
1731 nih_local char **start_env = NULL;
1732@@ -706,6 +764,16 @@
1733 nih_assert (message != NULL);
1734 nih_assert (env != NULL);
1735
1736+ /* Don't permit out-of-session modification */
1737+ session = session_from_dbus (NULL, message);
1738+ if (session != class->session) {
1739+ nih_dbus_error_raise_printf (
1740+ DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1741+ _("You do not have permission to modify job: %s"),
1742+ class->name);
1743+ return -1;
1744+ }
1745+
1746 /* Verify that the environment is valid */
1747 if (! environ_all_valid (env)) {
1748 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
1749@@ -815,6 +883,7 @@
1750 char * const *env,
1751 int wait)
1752 {
1753+ Session *session;
1754 Blocked *blocked = NULL;
1755 Job *job;
1756 nih_local char **stop_env = NULL;
1757@@ -825,6 +894,16 @@
1758 nih_assert (message != NULL);
1759 nih_assert (env != NULL);
1760
1761+ /* Don't permit out-of-session modification */
1762+ session = session_from_dbus (NULL, message);
1763+ if (session != class->session) {
1764+ nih_dbus_error_raise_printf (
1765+ DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1766+ _("You do not have permission to modify job: %s"),
1767+ class->name);
1768+ return -1;
1769+ }
1770+
1771 /* Verify that the environment is valid */
1772 if (! environ_all_valid (env)) {
1773 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
1774@@ -939,6 +1018,7 @@
1775 char * const *env,
1776 int wait)
1777 {
1778+ Session *session;
1779 Blocked *blocked = NULL;
1780 Job *job;
1781 nih_local char **restart_env = NULL;
1782@@ -949,6 +1029,16 @@
1783 nih_assert (message != NULL);
1784 nih_assert (env != NULL);
1785
1786+ /* Don't permit out-of-session modification */
1787+ session = session_from_dbus (NULL, message);
1788+ if (session != class->session) {
1789+ nih_dbus_error_raise_printf (
1790+ DBUS_INTERFACE_UPSTART ".Error.PermissionDenied",
1791+ _("You do not have permission to modify job: %s"),
1792+ class->name);
1793+ return -1;
1794+ }
1795+
1796 /* Verify that the environment is valid */
1797 if (! environ_all_valid (env)) {
1798 nih_dbus_error_raise_printf (DBUS_ERROR_INVALID_ARGS,
1799
1800=== modified file 'init/job_class.h'
1801--- init/job_class.h 2011-05-12 20:42:28 +0000
1802+++ init/job_class.h 2011-06-06 15:17:24 +0000
1803@@ -35,6 +35,7 @@
1804
1805 #include "process.h"
1806 #include "event_operator.h"
1807+#include "session.h"
1808
1809
1810 /**
1811@@ -71,6 +72,7 @@
1812 * @entry: list header,
1813 * @name: unique name,
1814 * @path: path of D-Bus object,
1815+ * @session: attached session,
1816 * @instance: pattern to uniquely identify multiple instances,
1817 * @instances: hash table of active instances,
1818 * @description: description; intended for humans,
1819@@ -110,6 +112,7 @@
1820
1821 char *name;
1822 char *path;
1823+ Session * session;
1824
1825 char *instance;
1826 NihHash *instances;
1827@@ -161,7 +164,8 @@
1828 void job_class_init (void);
1829
1830 JobClass * job_class_new (const void *parent,
1831- const char *name)
1832+ const char *name,
1833+ Session *session)
1834 __attribute__ ((warn_unused_result, malloc));
1835
1836 int job_class_consider (JobClass *class);
1837
1838=== modified file 'init/job_process.c'
1839--- init/job_process.c 2011-05-12 20:42:28 +0000
1840+++ init/job_process.c 2011-06-06 15:17:24 +0000
1841@@ -2,7 +2,6 @@
1842 *
1843 * job_process.c - job process handling
1844 *
1845- * Copyright © 2011 Google Inc.
1846 * Copyright © 2011 Canonical Ltd.
1847 * Author: Scott James Remnant <scott@netsplit.com>.
1848 *
1849@@ -41,6 +40,7 @@
1850 #include <unistd.h>
1851 #include <utmp.h>
1852 #include <utmpx.h>
1853+#include <pwd.h>
1854
1855 #include <nih/macros.h>
1856 #include <nih/alloc.h>
1857@@ -539,6 +539,16 @@
1858 }
1859 }
1860
1861+ /* Handle changing a chroot session job prior to dealing with
1862+ * the 'chroot' stanza.
1863+ */
1864+ if (class->session && class->session->chroot) {
1865+ if (chroot (class->session->chroot) < 0) {
1866+ nih_error_raise_system ();
1867+ job_process_error_abort (fds[1], JOB_PROCESS_ERROR_CHROOT, 0);
1868+ }
1869+ }
1870+
1871 /* Change the root directory, confining path resolution within it;
1872 * we do this before the working directory call so that is always
1873 * relative to the new root.
1874@@ -594,6 +604,54 @@
1875 }
1876 }
1877
1878+ /* Handle unprivileged user job by dropping privileges to
1879+ * their level.
1880+ */
1881+ if (class->session && class->session->user) {
1882+ uid_t uid = class->session->user;
1883+ struct passwd *pw = NULL;
1884+
1885+ /* D-Bus does not expose a public API call to allow
1886+ * us to query a users primary group.
1887+ * _dbus_user_info_fill_uid () seems to exist for this
1888+ * purpose, but is a "secret" API. It is unclear why
1889+ * D-Bus neglects the gid when it allows the uid
1890+ * to be queried directly.
1891+ *
1892+ * Our only recourse is to disallow user sessions in a
1893+ * chroot and assume that all other user sessions
1894+ * originate from the local system. In this way, we can
1895+ * bypass D-Bus and use getpwuid ().
1896+ */
1897+
1898+ if (class->session->chroot) {
1899+ /* We cannot determine the group id of the user
1900+ * session in the chroot via D-Bus, so disallow
1901+ * all jobs in such an environment.
1902+ */
1903+ _nih_error_raise (__FILE__, __LINE__, __FUNCTION__,
1904+ EPERM, strerror (EPERM));
1905+ }
1906+
1907+ pw = getpwuid (uid);
1908+
1909+ if (!pw)
1910+ nih_return_system_error (-1);
1911+
1912+ nih_assert (pw->pw_uid == uid);
1913+
1914+ if (uid && setuid (uid) < 0) {
1915+ nih_error_raise_system ();
1916+ job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SETUID, 0);
1917+ }
1918+
1919+ if (pw->pw_gid && setgid (pw->pw_gid) < 0) {
1920+ nih_error_raise_system ();
1921+ job_process_error_abort (fds[1], JOB_PROCESS_ERROR_SETGID, 0);
1922+ }
1923+ }
1924+
1925+
1926 /* Execute the process, if we escape from here it failed */
1927 if (execvp (argv[0], argv) < 0) {
1928 nih_error_raise_system ();
1929
1930=== modified file 'init/job_process.h'
1931--- init/job_process.h 2011-05-12 19:21:16 +0000
1932+++ init/job_process.h 2011-06-06 15:17:24 +0000
1933@@ -1,7 +1,6 @@
1934 /* upstart
1935 *
1936- * Copyright © 2011 Google Inc.
1937- * Copyright © 2009 Canonical Ltd.
1938+ * Copyright © 2009,2010,2011 Canonical Ltd.
1939 * Author: Scott James Remnant <scott@netsplit.com>.
1940 *
1941 * This program is free software; you can redistribute it and/or modify
1942@@ -57,7 +56,9 @@
1943 JOB_PROCESS_ERROR_CHROOT,
1944 JOB_PROCESS_ERROR_CHDIR,
1945 JOB_PROCESS_ERROR_PTRACE,
1946- JOB_PROCESS_ERROR_EXEC
1947+ JOB_PROCESS_ERROR_EXEC,
1948+ JOB_PROCESS_ERROR_SETUID,
1949+ JOB_PROCESS_ERROR_SETGID,
1950 } JobProcessErrorType;
1951
1952 /**
1953
1954=== modified file 'init/main.c'
1955--- init/main.c 2011-03-16 22:54:56 +0000
1956+++ init/main.c 2011-06-06 15:17:24 +0000
1957@@ -1,7 +1,6 @@
1958 /* upstart
1959 *
1960- * Copyright © 2011 Google Inc.
1961- * Copyright © 2010 Canonical Ltd.
1962+ * Copyright © 2009-2011 Canonical Ltd.
1963 * Author: Scott James Remnant <scott@netsplit.com>.
1964 *
1965 * This program is free software; you can redistribute it and/or modify
1966@@ -71,6 +70,8 @@
1967 static void usr1_handler (void *data, NihSignal *signal);
1968 #endif /* DEBUG */
1969
1970+static void handle_confdir (void);
1971+
1972
1973 /**
1974 * argv0:
1975@@ -89,14 +90,55 @@
1976 static int restart = FALSE;
1977
1978
1979+extern int disable_sessions;
1980+
1981+/**
1982+ * conf_dir:
1983+ *
1984+ * Full path to job configuration file directory.
1985+ *
1986+ **/
1987+static char *conf_dir = NULL;
1988+
1989+/**
1990+ * initial_event:
1991+ *
1992+ * Alternate event to emit at startup (rather than STARTUP_EVENT).
1993+ **/
1994+static char *initial_event = NULL;
1995+
1996+/**
1997+ * disable_startup_event:
1998+ *
1999+ * If TRUE, do not emit a startup event.
2000+ **/
2001+static int disable_startup_event = FALSE;
2002+
2003+extern int use_session_bus;
2004+
2005 /**
2006 * options:
2007 *
2008 * Command-line options we accept.
2009 **/
2010 static NihOption options[] = {
2011+ { 0, "confdir", N_("specify alternative directory to load configuration files from"),
2012+ NULL, "DIR", &conf_dir, NULL },
2013+
2014+ { 0, "no-sessions", N_("Disable user and chroot sessions"),
2015+ NULL, NULL, &disable_sessions, NULL },
2016+
2017+ { 0, "no-startup-event", N_("do not emit any startup event (for testing)"),
2018+ NULL, NULL, &disable_startup_event, NULL },
2019+
2020 { 0, "restart", NULL, NULL, NULL, &restart, NULL },
2021
2022+ { 0, "session", N_("use D-Bus session bus rather than system bus (for testing)"),
2023+ NULL, NULL, &use_session_bus, NULL },
2024+
2025+ { 0, "startup-event", N_("specify an alternative initial event (for testing)"),
2026+ NULL, "NAME", &initial_event, NULL },
2027+
2028 /* Ignore invalid options */
2029 { '-', "--", NULL, NULL, NULL, NULL, NULL },
2030
2031@@ -124,94 +166,105 @@
2032 if (! args)
2033 exit (1);
2034
2035+ handle_confdir ();
2036+ control_handle_bus_type ();
2037+
2038 #ifndef DEBUG
2039- /* Check we're root */
2040- if (getuid ()) {
2041- nih_fatal (_("Need to be root"));
2042- exit (1);
2043- }
2044-
2045- /* Check we're process #1 */
2046- if (getpid () > 1) {
2047- execv (TELINIT, argv);
2048- /* Ignore failure, probably just that telinit doesn't exist */
2049-
2050- nih_fatal (_("Not being executed as init"));
2051- exit (1);
2052- }
2053-
2054- /* Clear our arguments from the command-line, so that we show up in
2055- * ps or top output as /sbin/init, with no extra flags.
2056- *
2057- * This is a very Linux-specific trick; by deleting the NULL
2058- * terminator at the end of the last argument, we fool the kernel
2059- * into believing we used a setproctitle()-a-like to extend the
2060- * argument space into the environment space, and thus make it use
2061- * strlen() instead of its own assumed length. In fact, we've done
2062- * the exact opposite, and shrunk the command line length to just that
2063- * of whatever is in argv[0].
2064- *
2065- * If we don't do this, and just write \0 over the rest of argv, for
2066- * example; the command-line length still includes those \0s, and ps
2067- * will show whitespace in their place.
2068- */
2069- if (argc > 1) {
2070- char *arg_end;
2071-
2072- arg_end = argv[argc-1] + strlen (argv[argc-1]);
2073- *arg_end = ' ';
2074- }
2075-
2076-
2077- /* Become the leader of a new session and process group, shedding
2078- * any controlling tty (which we shouldn't have had anyway - but
2079- * you never know what initramfs did).
2080- */
2081- setsid ();
2082-
2083- /* Set the standard file descriptors to the ordinary console device,
2084- * resetting it to sane defaults unless we're inheriting from another
2085- * init process which we know left it in a sane state.
2086- */
2087- if (system_setup_console (CONSOLE_OUTPUT, (! restart)) < 0)
2088- nih_free (nih_error_get ());
2089-
2090- /* Set the PATH environment variable */
2091- setenv ("PATH", PATH, TRUE);
2092-
2093- /* Switch to the root directory in case we were started from some
2094- * strange place, or worse, some directory in the initramfs that's
2095- * going to go away soon.
2096- */
2097- if (chdir ("/"))
2098- nih_warn ("%s: %s", _("Unable to set root directory"),
2099- strerror (errno));
2100-
2101- /* Mount the /proc and /sys filesystems, which are pretty much
2102- * essential for any Linux system; not to mention used by
2103- * ourselves.
2104- */
2105- if (system_mount ("proc", "/proc") < 0) {
2106- NihError *err;
2107-
2108- err = nih_error_get ();
2109- nih_warn ("%s: %s", _("Unable to mount /proc filesystem"),
2110- err->message);
2111- nih_free (err);
2112- }
2113-
2114- if (system_mount ("sysfs", "/sys") < 0) {
2115- NihError *err;
2116-
2117- err = nih_error_get ();
2118- nih_warn ("%s: %s", _("Unable to mount /sys filesystem"),
2119- err->message);
2120- nih_free (err);
2121- }
2122+ if (use_session_bus == FALSE) {
2123+
2124+ /* Check we're root */
2125+ if (getuid ()) {
2126+ nih_fatal (_("Need to be root"));
2127+ exit (1);
2128+ }
2129+
2130+ /* Check we're process #1 */
2131+ if (getpid () > 1) {
2132+ execv (TELINIT, argv);
2133+ /* Ignore failure, probably just that telinit doesn't exist */
2134+
2135+ nih_fatal (_("Not being executed as init"));
2136+ exit (1);
2137+ }
2138+
2139+ /* Clear our arguments from the command-line, so that we show up in
2140+ * ps or top output as /sbin/init, with no extra flags.
2141+ *
2142+ * This is a very Linux-specific trick; by deleting the NULL
2143+ * terminator at the end of the last argument, we fool the kernel
2144+ * into believing we used a setproctitle()-a-like to extend the
2145+ * argument space into the environment space, and thus make it use
2146+ * strlen() instead of its own assumed length. In fact, we've done
2147+ * the exact opposite, and shrunk the command line length to just that
2148+ * of whatever is in argv[0].
2149+ *
2150+ * If we don't do this, and just write \0 over the rest of argv, for
2151+ * example; the command-line length still includes those \0s, and ps
2152+ * will show whitespace in their place.
2153+ */
2154+ if (argc > 1) {
2155+ char *arg_end;
2156+
2157+ arg_end = argv[argc-1] + strlen (argv[argc-1]);
2158+ *arg_end = ' ';
2159+ }
2160+
2161+
2162+ /* Become the leader of a new session and process group, shedding
2163+ * any controlling tty (which we shouldn't have had anyway - but
2164+ * you never know what initramfs did).
2165+ */
2166+ setsid ();
2167+
2168+ /* Set the standard file descriptors to the ordinary console device,
2169+ * resetting it to sane defaults unless we're inheriting from another
2170+ * init process which we know left it in a sane state.
2171+ */
2172+ if (system_setup_console (CONSOLE_OUTPUT, (! restart)) < 0)
2173+ nih_free (nih_error_get ());
2174+
2175+ /* Set the PATH environment variable */
2176+ setenv ("PATH", PATH, TRUE);
2177+
2178+ /* Switch to the root directory in case we were started from some
2179+ * strange place, or worse, some directory in the initramfs that's
2180+ * going to go away soon.
2181+ */
2182+ if (chdir ("/"))
2183+ nih_warn ("%s: %s", _("Unable to set root directory"),
2184+ strerror (errno));
2185+
2186+ /* Mount the /proc and /sys filesystems, which are pretty much
2187+ * essential for any Linux system; not to mention used by
2188+ * ourselves.
2189+ */
2190+ if (system_mount ("proc", "/proc") < 0) {
2191+ NihError *err;
2192+
2193+ err = nih_error_get ();
2194+ nih_warn ("%s: %s", _("Unable to mount /proc filesystem"),
2195+ err->message);
2196+ nih_free (err);
2197+ }
2198+
2199+ if (system_mount ("sysfs", "/sys") < 0) {
2200+ NihError *err;
2201+
2202+ err = nih_error_get ();
2203+ nih_warn ("%s: %s", _("Unable to mount /sys filesystem"),
2204+ err->message);
2205+ nih_free (err);
2206+ }
2207+ } else {
2208+ nih_log_set_priority (NIH_LOG_DEBUG);
2209+ nih_debug ("Running with UID %d as PID %d (PPID %d)",
2210+ (int)getuid (), (int)getpid (), (int)getppid ());
2211+ }
2212+
2213 #else /* DEBUG */
2214 nih_log_set_priority (NIH_LOG_DEBUG);
2215- nih_debug ("Running as PID %d (PPID %d)",
2216- (int)getpid (), (int)getppid ());
2217+ nih_debug ("Running with UID %d as PID %d (PPID %d)",
2218+ (int)getuid (), (int)getpid (), (int)getppid ());
2219 #endif /* DEBUG */
2220
2221
2222@@ -223,11 +276,13 @@
2223 nih_signal_reset ();
2224
2225 #ifndef DEBUG
2226- /* Catch fatal errors immediately rather than waiting for a new
2227- * iteration through the main loop.
2228- */
2229- nih_signal_set_handler (SIGSEGV, crash_handler);
2230- nih_signal_set_handler (SIGABRT, crash_handler);
2231+ if (use_session_bus == FALSE) {
2232+ /* Catch fatal errors immediately rather than waiting for a new
2233+ * iteration through the main loop.
2234+ */
2235+ nih_signal_set_handler (SIGSEGV, crash_handler);
2236+ nih_signal_set_handler (SIGABRT, crash_handler);
2237+ }
2238 #endif /* DEBUG */
2239
2240 /* Don't ignore SIGCHLD or SIGALRM, but don't respond to them
2241@@ -238,33 +293,35 @@
2242 nih_signal_set_handler (SIGALRM, nih_signal_handler);
2243
2244 #ifndef DEBUG
2245- /* Ask the kernel to send us SIGINT when control-alt-delete is
2246- * pressed; generate an event with the same name.
2247- */
2248- reboot (RB_DISABLE_CAD);
2249- nih_signal_set_handler (SIGINT, nih_signal_handler);
2250- NIH_MUST (nih_signal_add_handler (NULL, SIGINT, cad_handler, NULL));
2251-
2252- /* Ask the kernel to send us SIGWINCH when alt-uparrow is pressed;
2253- * generate a keyboard-request event.
2254- */
2255- if (ioctl (0, KDSIGACCEPT, SIGWINCH) == 0) {
2256- nih_signal_set_handler (SIGWINCH, nih_signal_handler);
2257- NIH_MUST (nih_signal_add_handler (NULL, SIGWINCH,
2258- kbd_handler, NULL));
2259+ if (use_session_bus == FALSE) {
2260+ /* Ask the kernel to send us SIGINT when control-alt-delete is
2261+ * pressed; generate an event with the same name.
2262+ */
2263+ reboot (RB_DISABLE_CAD);
2264+ nih_signal_set_handler (SIGINT, nih_signal_handler);
2265+ NIH_MUST (nih_signal_add_handler (NULL, SIGINT, cad_handler, NULL));
2266+
2267+ /* Ask the kernel to send us SIGWINCH when alt-uparrow is pressed;
2268+ * generate a keyboard-request event.
2269+ */
2270+ if (ioctl (0, KDSIGACCEPT, SIGWINCH) == 0) {
2271+ nih_signal_set_handler (SIGWINCH, nih_signal_handler);
2272+ NIH_MUST (nih_signal_add_handler (NULL, SIGWINCH,
2273+ kbd_handler, NULL));
2274+ }
2275+
2276+ /* powstatd sends us SIGPWR when it changes /etc/powerstatus */
2277+ nih_signal_set_handler (SIGPWR, nih_signal_handler);
2278+ NIH_MUST (nih_signal_add_handler (NULL, SIGPWR, pwr_handler, NULL));
2279+
2280+ /* SIGHUP instructs us to re-load our configuration */
2281+ nih_signal_set_handler (SIGHUP, nih_signal_handler);
2282+ NIH_MUST (nih_signal_add_handler (NULL, SIGHUP, hup_handler, NULL));
2283+
2284+ /* SIGUSR1 instructs us to reconnect to D-Bus */
2285+ nih_signal_set_handler (SIGUSR1, nih_signal_handler);
2286+ NIH_MUST (nih_signal_add_handler (NULL, SIGUSR1, usr1_handler, NULL));
2287 }
2288-
2289- /* powstatd sends us SIGPWR when it changes /etc/powerstatus */
2290- nih_signal_set_handler (SIGPWR, nih_signal_handler);
2291- NIH_MUST (nih_signal_add_handler (NULL, SIGPWR, pwr_handler, NULL));
2292-
2293- /* SIGHUP instructs us to re-load our configuration */
2294- nih_signal_set_handler (SIGHUP, nih_signal_handler);
2295- NIH_MUST (nih_signal_add_handler (NULL, SIGHUP, hup_handler, NULL));
2296-
2297- /* SIGUSR1 instructs us to reconnect to D-Bus */
2298- nih_signal_set_handler (SIGUSR1, nih_signal_handler);
2299- NIH_MUST (nih_signal_add_handler (NULL, SIGUSR1, usr1_handler, NULL));
2300 #endif /* DEBUG */
2301
2302
2303@@ -279,25 +336,27 @@
2304
2305 /* Read configuration */
2306 NIH_MUST (conf_source_new (NULL, CONFFILE, CONF_FILE));
2307- NIH_MUST (conf_source_new (NULL, CONFDIR, CONF_JOB_DIR));
2308+ NIH_MUST (conf_source_new (NULL, conf_dir, CONF_JOB_DIR));
2309
2310 conf_reload ();
2311
2312 /* Create a listening server for private connections. */
2313- while (control_server_open () < 0) {
2314- NihError *err;
2315+ if (use_session_bus == FALSE) {
2316+ while (control_server_open () < 0) {
2317+ NihError *err;
2318
2319- err = nih_error_get ();
2320- if (err->number != ENOMEM) {
2321- nih_warn ("%s: %s", _("Unable to listen for private connections"),
2322- err->message);
2323+ err = nih_error_get ();
2324+ if (err->number != ENOMEM) {
2325+ nih_warn ("%s: %s", _("Unable to listen for private connections"),
2326+ err->message);
2327+ nih_free (err);
2328+ break;
2329+ }
2330 nih_free (err);
2331- break;
2332 }
2333- nih_free (err);
2334 }
2335
2336- /* Open connection to the system bus; we normally expect this to
2337+ /* Open connection to the appropriate D-Bus bus; we normally expect this to
2338 * fail and will try again later - don't let ENOMEM stop us though.
2339 */
2340 while (control_bus_open () < 0) {
2341@@ -313,21 +372,32 @@
2342 }
2343
2344 #ifndef DEBUG
2345- /* Now that the startup is complete, send all further logging output
2346- * to kmsg instead of to the console.
2347- */
2348- if (system_setup_console (CONSOLE_NONE, FALSE) < 0)
2349- nih_free (nih_error_get ());
2350+ if (use_session_bus == FALSE) {
2351+ /* Now that the startup is complete, send all further logging output
2352+ * to kmsg instead of to the console.
2353+ */
2354+ if (system_setup_console (CONSOLE_NONE, FALSE) < 0)
2355+ nih_free (nih_error_get ());
2356
2357- nih_log_set_logger (logger_kmsg);
2358+ nih_log_set_logger (logger_kmsg);
2359+ }
2360 #endif /* DEBUG */
2361
2362
2363 /* Generate and run the startup event or read the state from the
2364 * init daemon that exec'd us
2365 */
2366- if (! restart) {
2367- NIH_MUST (event_new (NULL, STARTUP_EVENT, NULL));
2368+ if (! restart ) {
2369+ if (disable_startup_event) {
2370+ nih_debug ("Startup event disabled");
2371+ } else {
2372+ NIH_MUST (event_new (NULL,
2373+ initial_event
2374+ ? initial_event
2375+ : STARTUP_EVENT,
2376+ NULL));
2377+ }
2378+
2379 } else {
2380 sigset_t mask;
2381
2382@@ -573,3 +643,31 @@
2383 }
2384 }
2385 #endif /* DEBUG */
2386+
2387+/**
2388+ * handle_confdir:
2389+ *
2390+ * Determine where system configuration files should be loaded from.
2391+ **/
2392+static void
2393+handle_confdir (void)
2394+{
2395+ char *dir;
2396+
2397+ /* user has already specified directory on command-line */
2398+ if (conf_dir)
2399+ goto out;
2400+
2401+ conf_dir = CONFDIR;
2402+
2403+ dir = getenv (CONFDIR_ENV);
2404+ if (! dir)
2405+ return;
2406+
2407+ conf_dir = dir;
2408+
2409+out:
2410+ nih_debug ("Using alternate configuration directory %s",
2411+ conf_dir);
2412+}
2413+
2414
2415=== modified file 'init/man/init.5'
2416--- init/man/init.5 2011-05-12 20:42:28 +0000
2417+++ init/man/init.5 2011-06-06 15:17:24 +0000
2418@@ -9,9 +9,9 @@
2419 .SH DESCRIPTION
2420 On startup, the Upstart
2421 .BR init (8)
2422-daemon reads its job configuration from the
2423-.I /etc/init
2424-directory, and watches for future changes using
2425+daemon reads its job configuration from files in the
2426+.I /etc/init/
2427+directory, and watches for future changes to these files using
2428 .BR inotify (7).
2429
2430 Files in this directory must end in
2431@@ -37,6 +37,9 @@
2432 within a stanza are permitted within single or double quotes, or if
2433 preceeded by a blackslash.
2434
2435+If a stanza is duplicated, the last occurence will be used. Unrecognized
2436+stanzas will generate parse errors, which will stop a job from running.
2437+
2438 Stanzas and their arguments are delimited by whitespace, which consists
2439 of one or more space or tab characters which are otherwise ignored unless
2440 placed within single or double quotes.
2441@@ -69,7 +72,7 @@
2442 entire command being passed to a shell for expansion.
2443
2444 .nf
2445-exec /usr/sbin/acpid -c $EVENTSDIR -s $SOCKET
2446+exec /usr/sbin/acpid \-c $EVENTSDIR \-s $SOCKET
2447 .fi
2448 .\"
2449 .TP
2450@@ -78,7 +81,7 @@
2451 be executed using
2452 .BR sh(1).
2453 The
2454-.I -e
2455+.I \-e
2456 shell option is always used, so any command that fails will terminate
2457 the script.
2458
2459@@ -92,7 +95,7 @@
2460 .nf
2461 script
2462 dd bs=1 if=/proc/kmsg of=$KMSGSINK
2463- exec /sbin/klogd -P $KMSGSINK
2464+ exec /sbin/klogd \-P $KMSGSINK
2465 end script
2466 .fi
2467
2468@@ -105,14 +108,14 @@
2469 stanza.
2470
2471 .TP
2472-.B pre-start exec\fR|\fBscript\fR...
2473+.B pre\-start exec\fR|\fBscript\fR...
2474 This process will be run after the job's
2475 .BR starting (7)
2476 event has finished, but before the main process is run. It is typically
2477 used to prepare the environment, such as making necessary directories.
2478 .\"
2479 .TP
2480-.B post-start exec\fR|\fBscript\fR...
2481+.B post\-start exec\fR|\fBscript\fR...
2482 This process will be run before the job's
2483 .BR started (7)
2484 event is emitted, but after the main process has been spawned. It is
2485@@ -122,7 +125,7 @@
2486 event until the main process is ready to receive clients.
2487 .\"
2488 .TP
2489-.B pre-stop exec\fR|\fBscript\fR...
2490+.B pre\-stop exec\fR|\fBscript\fR...
2491 This process is run if the job is stopped by an event listed in its
2492 .B stop on
2493 stanza or by the
2494@@ -136,7 +139,7 @@
2495 command without arguments to cancel the stop.
2496 .\"
2497 .TP
2498-.B post-stop exec\fR|\fBscript\fR...
2499+.B post\-stop exec\fR|\fBscript\fR...
2500 This process is run after the main process has been killed and before
2501 the job's
2502 .BR stopped (7)
2503@@ -144,19 +147,19 @@
2504 such as removing temporary directories.
2505
2506 .PP
2507-All of these processes, including the main process, are optional. Services
2508-without a main process will appear to be running until they are stopped,
2509-this is commonly used to define states such as runlevels. It's quite
2510-permissable to have no main process, but to have
2511-.B pre-start
2512+All of these processes, including the main process, are optional.
2513+Services without a main process will appear to be running until they are
2514+stopped: this is commonly used to define states such as runlevels. It
2515+is permissable to have no main process, but to have
2516+.B pre\-start
2517 and
2518-.B post-stop
2519+.B post\-stop
2520 processes for the state.
2521
2522 .RS
2523 .nf
2524-pre-start exec ifup -a
2525-post-stop exec ifdown -a
2526+pre\-start exec ifup \-a
2527+post\-stop exec ifdown \-a
2528 .fi
2529 .RE
2530 .\"
2531@@ -238,9 +241,9 @@
2532 .nf
2533 start on started gdm or started kdm
2534
2535-start on device-added SUBSYSTEM=tty DEVPATH=ttyS*
2536+start on device\-added SUBSYSTEM=tty DEVPATH=ttyS*
2537
2538-start on net-device-added INTERFACE!=lo
2539+start on net\-device\-added INTERFACE!=lo
2540 .fi
2541 .TP
2542 .B stop on \fIEVENT \fR[[\fIKEY=\fR]\fIVALUE\fR]... [\fBand\fR|\fBor\fR...]
2543@@ -249,7 +252,7 @@
2544 .B stop on
2545 stanza defines the set of events that will cause the job to be automatically
2546 stopped. It has the same syntax as
2547-.B start on
2548+\fBstart on\fP.
2549
2550 .I VALUE
2551 may additionally expand the value of any variable that came from the
2552@@ -258,7 +261,7 @@
2553 .nf
2554 stop on stopping gdm or stopping kdm
2555
2556-stop on device-removed DEVPATH=$DEVPATH
2557+stop on device\-removed DEVPATH=$DEVPATH
2558 .fi
2559
2560 .TP
2561@@ -284,11 +287,11 @@
2562 it will not be present if the job was started manually.
2563
2564 In addition, the
2565-.B pre-stop
2566+.B pre\-stop
2567 and
2568-.B post-stop
2569+.B post\-stop
2570 scripts are run with the environment of the events or commands that
2571-stopped the job. THe
2572+stopped the job. The
2573 .B UPSTART_STOP_EVENTS
2574 environment variable contains the list of events that stopped the job,
2575 it will not be present if the job was stopped manually.
2576@@ -306,7 +309,8 @@
2577 .B env \fIKEY\fR[=\fIVALUE\fR]
2578 Defines a default environment variable, the value of which may be overriden
2579 by the event or command that starts the job.
2580-If no value is given, then the value is taken from the
2581+If \'KEY=VALUE\' is specified, the variable KEY is given the value VALUE.
2582+If only \'KEY\' is given, then the value is taken from the
2583 .BR init (8)
2584 daemon's own environment.
2585 .\"
2586@@ -366,7 +370,7 @@
2587 times in
2588 .I INTERVAL
2589 seconds, it will be considered to be having deeper problems and will
2590-be stopped.
2591+be stopped. Default COUNT is 10. Default INTERVAL is 5 seconds.
2592
2593 This only applies to automatic respawns and not the
2594 .BR restart (8)
2595@@ -385,7 +389,8 @@
2596 .SS Instances
2597 By default, only one instance of any job is permitted to exist at one
2598 time. Attempting to start a job when it's already starting or running
2599-results in an error.
2600+results in an error. Note that a job is considered to be running if its
2601+pre\-start process is running.
2602
2603 Multiple instances may be permitted by defining the names of those
2604 instances. If an instance with the same name is not already starting
2605@@ -405,12 +410,12 @@
2606
2607 .nf
2608 instance $CONFFILE
2609-exec /sbin/httpd -c $CONFFILE
2610+exec /sbin/httpd \-c $CONFFILE
2611 .fi
2612
2613 .nf
2614 instance $TTY
2615-exec /sbin/getty -8 38300 $TTY
2616+exec /sbin/getty \-8 38300 $TTY
2617 .fi
2618
2619 These jobs appear in the
2620@@ -461,6 +466,11 @@
2621
2622 This stanza allows a job to document in its job configuration what events
2623 it emits itself, and may be useful for graphing possible transitions.
2624+
2625+The
2626+.BR initctl "(8) " check\-config
2627+command attempts to use this stanza to resolve events.
2628+
2629 .\"
2630 .SS Process environment
2631 Many common adjustments to the process environment, such as resource
2632@@ -481,7 +491,7 @@
2633 is special, it not only connects the job to the system console but sets
2634 the job to be the owner of the system console, which means it will receive
2635 certain signals from the kernel when special key combinations such as
2636-Control-C are pressed.
2637+Control\-C are pressed.
2638 .\"
2639 .TP
2640 .B umask \fIUMASK
2641@@ -586,7 +596,7 @@
2642 .I SIGSTOP
2643 signal to indicate that it is ready.
2644 .BR init (8)
2645-will wait for this signal before running the job's post-start script,
2646+will wait for this signal before running the job's post\-start script,
2647 or considering the job to be running.
2648
2649 .BR init (8)
2650@@ -600,7 +610,7 @@
2651 after being run.
2652 .BR init (8)
2653 will follow this daemonisation, and will wait for this to occur before
2654-running the job's post-start script or considering the job to be running.
2655+running the job's post\-start script or considering the job to be running.
2656
2657 Without this stanza
2658 .BR init (8)
2659@@ -612,13 +622,56 @@
2660 Specifies that the job's main process will fork once after being run.
2661 .BR init (8)
2662 will follow this fork, and will wait for this to occur before
2663-running the job's post-start script or considering the job to be running.
2664+running the job's post\-start script or considering the job to be running.
2665
2666 Without this stanza
2667 .BR init (8)
2668 is unable to supervise forking processes and will believe them to have
2669 stopped as soon as they fork on startup.
2670 .\"
2671+.SH BUGS
2672+The
2673+.B and
2674+and
2675+.B or
2676+operators allowed with
2677+.B start on
2678+and
2679+.B stop on
2680+do not work intuitively: operands to the right of either operator are
2681+only evaluated once and state information is then discarded. This can
2682+lead to jobs with complex \fBstart on\fP or \fPstop on\fP conditions
2683+not behaving as expected \fIwhen restarted\fP. For example, if a job
2684+encodes the following condition:
2685+.ti +4
2686+.sp 1
2687+.nf
2688+start on A and (B or C)
2689+.fi
2690+.P
2691+When \(aqA\(aq and \(aqB\(aq become true, the condition is satisfied so
2692+the job will be run. However, if the job ends and subsequently \(aqA\(aq
2693+and \(aqC\(aq become true, the job will \fInot\fP be re\-run even though
2694+the condtion is satisfied. Avoid using complex conditions with jobs
2695+which need to be restarted.
2696+.\"
2697+.SH AUTHOR
2698+Manual page written by Scott James Remnant
2699+.RB < scott@netsplit.com >
2700+and James Hunt
2701+.RB < james.hunt@canonical.com > .
2702+.\"
2703+.SH REPORTING BUGS
2704+Report bugs at
2705+.RB < https://launchpad.net/upstart/+bugs >
2706+.\"
2707+.SH COPYRIGHT
2708+Copyright \(co 2009-2011 Canonical Ltd.
2709+.br
2710+This is free software; see the source for copying conditions. There is NO
2711+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
2712+
2713+.\"
2714 .SH SEE ALSO
2715 .BR init (8)
2716 .BR sh (1)
2717
2718=== modified file 'init/man/init.8'
2719--- init/man/init.8 2010-02-04 19:26:17 +0000
2720+++ init/man/init.8 2011-06-06 15:17:24 +0000
2721@@ -1,4 +1,4 @@
2722-.TH init 8 2010-02-04 "Upstart"
2723+.TH init 8 2011-04-06 "Upstart"
2724 .\"
2725 .SH NAME
2726 init \- Upstart process management daemon
2727@@ -64,7 +64,32 @@
2728 by placing them on the kernel command-line.
2729 .\"
2730 .TP
2731-.B --verbose
2732+.B \-\-confdir \fIdirectory\fP
2733+Read job configuration files from a directory other than
2734+\fI/etc/init\fP.
2735+.\"
2736+.TP
2737+.B \-\-no\-sessions
2738+Disable user and chroot sessions.
2739+.\"
2740+.TP
2741+.B \-\-no\-startup\-event
2742+Suppress emission of the initial startup event. This option should only
2743+be used for testing since it will stop the
2744+.BR init (8)
2745+daemon from starting \fBany\fP jobs automatically.
2746+.\"
2747+.TP
2748+.B \-\-session
2749+Connect to the D\-Bus session bus. This should only be used for testing.
2750+.\"
2751+.TP
2752+.B \-\-startup-event \fIevent\fP
2753+Specify a different initial startup event from the standard
2754+.BR startup (7) .
2755+.\"
2756+.TP
2757+.B \-\-verbose
2758 Outputs verbose messages about job state changes and event emissions to the
2759 system console or log, useful for debugging boot.
2760 .\"
2761@@ -90,18 +115,19 @@
2762 .RB < https://launchpad.net/upstart/+bugs >
2763 .\"
2764 .SH COPYRIGHT
2765-Copyright \(co 2010 Canonical Ltd.
2766+Copyright \(co 2009\-2011 Canonical Ltd.
2767 .br
2768 This is free software; see the source for copying conditions. There is NO
2769 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
2770 .\"
2771 .SH SEE ALSO
2772+.BR control\-alt\-delete (7)
2773 .BR init (5)
2774 .BR initctl (8)
2775-.BR telinit (8)
2776 .BR runlevel (7)
2777 .BR startup (7)
2778 .BR starting (7)
2779 .BR started (7)
2780 .BR stopping (7)
2781 .BR stopped (7)
2782+.BR telinit (8)
2783
2784=== modified file 'init/parse_job.c'
2785--- init/parse_job.c 2011-05-12 20:42:28 +0000
2786+++ init/parse_job.c 2011-06-06 15:17:24 +0000
2787@@ -2,7 +2,7 @@
2788 *
2789 * parse_job.c - job definition parsing
2790 *
2791- * Copyright © 2010 Canonical Ltd.
2792+ * Copyright © 2010,2011 Canonical Ltd.
2793 * Author: Scott James Remnant <scott@netsplit.com>.
2794 *
2795 * This program is free software; you can redistribute it and/or modify
2796@@ -263,6 +263,7 @@
2797 /**
2798 * parse_job:
2799 * @parent: parent object for new job,
2800+ * @session: session,
2801 * @name: name of new job,
2802 * @file: file or string to parse,
2803 * @len: length of @file,
2804@@ -282,6 +283,7 @@
2805 **/
2806 JobClass *
2807 parse_job (const void *parent,
2808+ Session * session,
2809 const char *name,
2810 const char *file,
2811 size_t len,
2812@@ -294,7 +296,7 @@
2813 nih_assert (file != NULL);
2814 nih_assert (pos != NULL);
2815
2816- class = job_class_new (parent, name);
2817+ class = job_class_new (parent, name, session);
2818 if (! class)
2819 nih_return_system_error (NULL);
2820
2821
2822=== modified file 'init/parse_job.h'
2823--- init/parse_job.h 2009-06-23 09:29:35 +0000
2824+++ init/parse_job.h 2011-06-06 15:17:24 +0000
2825@@ -1,6 +1,6 @@
2826 /* upstart
2827 *
2828- * Copyright © 2009 Canonical Ltd.
2829+ * Copyright © 2010 Canonical Ltd.
2830 * Author: Scott James Remnant <scott@netsplit.com>.
2831 *
2832 * This program is free software; you can redistribute it and/or modify
2833@@ -22,13 +22,14 @@
2834
2835 #include <nih/macros.h>
2836
2837+#include "session.h"
2838 #include "job_class.h"
2839
2840
2841 NIH_BEGIN_EXTERN
2842
2843-JobClass *parse_job (const void *parent, const char *name,
2844- const char *file, size_t len,
2845+JobClass *parse_job (const void *parent, Session *session,
2846+ const char *name, const char *file, size_t len,
2847 size_t *pos, size_t *lineno)
2848 __attribute__ ((warn_unused_result, malloc));
2849
2850
2851=== modified file 'init/paths.h'
2852--- init/paths.h 2010-02-26 15:27:14 +0000
2853+++ init/paths.h 2011-06-06 15:17:24 +0000
2854@@ -1,6 +1,6 @@
2855 /* upstart
2856 *
2857- * Copyright © 2010 Canonical Ltd.
2858+ * Copyright © 2010-2011 Canonical Ltd.
2859 * Author: Scott James Remnant <scott@netsplit.com>.
2860 *
2861 * This program is free software; you can redistribute it and/or modify
2862@@ -67,12 +67,35 @@
2863 /**
2864 * CONFDIR:
2865 *
2866- * Top-level directory of the system configuration files.
2867+ * Default top-level directory of the system configuration files.
2868 **/
2869 #ifndef CONFDIR
2870 #define CONFDIR "/etc/init"
2871 #endif
2872
2873+/**
2874+ * USERCONFDIR:
2875+ *
2876+ * Sub-directory of user's home directory for their jobs.
2877+ **/
2878+#ifndef USERCONFDIR
2879+#define USERCONFDIR ".init"
2880+#endif
2881+
2882+
2883+/**
2884+ * CONFDIR_ENV:
2885+ *
2886+ * If this environment variable is set, read configuration files
2887+ * from the location specified, rather than CONFDIR.
2888+ *
2889+ * Value is expected to be the full path to an alternative job
2890+ * configuration directory.
2891+ **/
2892+#ifndef CONFDIR_ENV
2893+#define CONFDIR_ENV "UPSTART_CONFDIR"
2894+#endif
2895+
2896
2897 /**
2898 * SHELL:
2899
2900=== added file 'init/session.c'
2901--- init/session.c 1970-01-01 00:00:00 +0000
2902+++ init/session.c 2011-06-06 15:17:24 +0000
2903@@ -0,0 +1,279 @@
2904+/* upstart
2905+ *
2906+ * session.c - session segregation
2907+ *
2908+ * Copyright © 2010,2011 Canonical Ltd.
2909+ * Author: Scott James Remnant <scott@netsplit.com>.
2910+ *
2911+ * This program is free software; you can redistribute it and/or modify
2912+ * it under the terms of the GNU General Public License version 2, as
2913+ * published by the Free Software Foundation.
2914+ *
2915+ * This program is distributed in the hope that it will be useful,
2916+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2917+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2918+ * GNU General Public License for more details.
2919+ *
2920+ * You should have received a copy of the GNU General Public License along
2921+ * with this program; if not, write to the Free Software Foundation, Inc.,
2922+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2923+ */
2924+
2925+#ifdef HAVE_CONFIG_H
2926+# include <config.h>
2927+#endif /* HAVE_CONFIG_H */
2928+
2929+
2930+#include <dbus/dbus.h>
2931+
2932+#include <sys/types.h>
2933+
2934+#include <pwd.h>
2935+#include <errno.h>
2936+#include <limits.h>
2937+#include <string.h>
2938+#include <unistd.h>
2939+
2940+#include <nih/macros.h>
2941+#include <nih/alloc.h>
2942+#include <nih/list.h>
2943+#include <nih/string.h>
2944+#include <nih/logging.h>
2945+#include <nih/error.h>
2946+
2947+#include <nih-dbus/dbus_message.h>
2948+
2949+#include "session.h"
2950+#include "conf.h"
2951+#include "paths.h"
2952+
2953+
2954+/**
2955+ * sessions:
2956+ *
2957+ * This list holds the list of known sessions; each item is a Session
2958+ * structure.
2959+ **/
2960+NihList *sessions = NULL;
2961+
2962+/**
2963+ * disable_sessions:
2964+ *
2965+ * If TRUE, disable user and chroot sessions, resulting in a
2966+ * "traditional" (pre-session support) system.
2967+ **/
2968+int disable_sessions = FALSE;
2969+
2970+
2971+/* Prototypes for static functions */
2972+static void session_create_conf_source (Session *sesson);
2973+
2974+
2975+/**
2976+ * session_init:
2977+ *
2978+ * Initialise the sessions list.
2979+ **/
2980+void
2981+session_init (void)
2982+{
2983+ if (! sessions)
2984+ sessions = NIH_MUST (nih_list_new (NULL));
2985+}
2986+
2987+
2988+Session *
2989+session_new (const void *parent,
2990+ const char *chroot,
2991+ uid_t user)
2992+{
2993+ Session *session;
2994+
2995+ nih_assert ((chroot != NULL) || (user != 0));
2996+
2997+ session_init ();
2998+
2999+ session = nih_new (parent, Session);
3000+ if (! session)
3001+ return NULL;
3002+
3003+ nih_list_init (&session->entry);
3004+
3005+ if (chroot) {
3006+ session->chroot = nih_strdup (session, chroot);
3007+ if (! session->chroot) {
3008+ nih_free (session);
3009+ return NULL;
3010+ }
3011+ } else {
3012+ session->chroot = NULL;
3013+ }
3014+
3015+ session->user = user;
3016+
3017+ session->conf_path = NULL;
3018+
3019+ nih_alloc_set_destructor (session, nih_list_destroy);
3020+
3021+ nih_list_add (sessions, &session->entry);
3022+
3023+ return session;
3024+}
3025+
3026+Session *
3027+session_from_dbus (const void *parent,
3028+ NihDBusMessage *message)
3029+{
3030+ const char *sender;
3031+ DBusError dbus_error;
3032+ unsigned long unix_user;
3033+ unsigned long unix_process_id;
3034+ char root[PATH_MAX];
3035+ Session *session;
3036+
3037+ nih_assert (message != NULL);
3038+
3039+ /* Handle explicit command-line request and alternative request
3040+ * method (primarily for test framework) to disable session support.
3041+ */
3042+ if (disable_sessions || getenv ("UPSTART_NO_SESSIONS"))
3043+ return NULL;
3044+
3045+ session_init ();
3046+
3047+ /* Ask D-Bus nicely for the origin uid and/or pid of the caller;
3048+ * sadly we can't ask the bus daemon for the origin pid, so that
3049+ * one will just have to stay user-session only.
3050+ */
3051+ dbus_error_init (&dbus_error);
3052+
3053+ sender = dbus_message_get_sender (message->message);
3054+ if (sender) {
3055+ unix_user = dbus_bus_get_unix_user (message->connection, sender,
3056+ &dbus_error);
3057+ if (unix_user == (unsigned long)-1) {
3058+ dbus_error_free (&dbus_error);
3059+ unix_user = 0;
3060+ }
3061+
3062+ unix_process_id = 0;
3063+
3064+ } else {
3065+ if (! dbus_connection_get_unix_user (message->connection,
3066+ &unix_user))
3067+ unix_process_id = 0;
3068+
3069+ if (! dbus_connection_get_unix_process_id (message->connection,
3070+ &unix_process_id))
3071+ unix_process_id = 0;
3072+ }
3073+
3074+ /* If we retrieved a process id, look up the root path for it;
3075+ * if it's just '/' don't worry so much about it.
3076+ */
3077+ if (unix_process_id) {
3078+ nih_local char *symlink = NULL;
3079+ ssize_t len;
3080+
3081+ symlink = NIH_MUST (nih_sprintf (NULL, "/proc/%lu/root",
3082+ unix_process_id));
3083+ len = readlink (symlink, root, sizeof root);
3084+ if (len < 0)
3085+ return NULL;
3086+
3087+ root[len] = '\0';
3088+
3089+ if (! strcmp (root, "/")) {
3090+ unix_process_id = 0;
3091+ if (! unix_user)
3092+ return NULL;
3093+ }
3094+
3095+ } else if (! unix_user) {
3096+ /* No process id or user id found, return the NULL session */
3097+ return NULL;
3098+
3099+ }
3100+
3101+ /* Now find in the existing Sessions list */
3102+ NIH_LIST_FOREACH (sessions, iter) {
3103+ Session *session = (Session *)iter;
3104+
3105+ if (unix_process_id) {
3106+ if (! session->chroot)
3107+ continue;
3108+
3109+ /* ignore sessions relating to other chroots */
3110+ if (strcmp (session->chroot, root))
3111+ continue;
3112+ }
3113+
3114+ /* ignore sessions relating to other users */
3115+ if (unix_user != session->user)
3116+ continue;
3117+
3118+ if (! session->conf_path)
3119+ session_create_conf_source (session);
3120+
3121+ return session;
3122+ }
3123+
3124+
3125+ /* Didn't find one, make a new one */
3126+ session = NIH_MUST (session_new (parent, unix_process_id ? root : NULL,
3127+ unix_user));
3128+ session_create_conf_source (session);
3129+
3130+ return session;
3131+}
3132+
3133+static void
3134+session_create_conf_source (Session *session)
3135+{
3136+ ConfSource *source;
3137+
3138+ nih_assert (session != NULL);
3139+ nih_assert (session->conf_path == NULL);
3140+
3141+ if (session->chroot)
3142+ session->conf_path = NIH_MUST (nih_strdup (NULL, session->chroot));
3143+ if (session->user) {
3144+ struct passwd *pwd;
3145+
3146+ pwd = getpwuid (session->user);
3147+ if (! pwd) {
3148+ nih_error ("%d: %s: %s", session->user,
3149+ _("Unable to lookup home directory"),
3150+ strerror (errno));
3151+
3152+ nih_free (session->conf_path);
3153+ session->conf_path = NULL;
3154+ return;
3155+ }
3156+
3157+ NIH_MUST (nih_strcat_sprintf (&session->conf_path, NULL, "%s/%s",
3158+ pwd->pw_dir, USERCONFDIR));
3159+ } else {
3160+ NIH_MUST (nih_strcat (&session->conf_path, NULL, CONFDIR));
3161+ }
3162+
3163+ source = NIH_MUST (conf_source_new (session, session->conf_path,
3164+ CONF_JOB_DIR));
3165+ source->session = session;
3166+
3167+ if (conf_source_reload (source) < 0) {
3168+ NihError *err;
3169+
3170+ err = nih_error_get ();
3171+ if (err->number != ENOENT)
3172+ nih_error ("%s: %s: %s", source->path,
3173+ _("Unable to load configuration"),
3174+ err->message);
3175+ nih_free (err);
3176+
3177+ nih_free (source);
3178+ nih_free (session->conf_path);
3179+ session->conf_path = NULL;
3180+ return;
3181+ }
3182+}
3183
3184=== added file 'init/session.h'
3185--- init/session.h 1970-01-01 00:00:00 +0000
3186+++ init/session.h 2011-06-06 15:17:24 +0000
3187@@ -0,0 +1,87 @@
3188+/* upstart
3189+ *
3190+ * Copyright © 2010,2011 Canonical Ltd.
3191+ * Author: Scott James Remnant <scott@netsplit.com>.
3192+ *
3193+ * This program is free software; you can redistribute it and/or modify
3194+ * it under the terms of the GNU General Public License version 2, as
3195+ * published by the Free Software Foundation.
3196+ *
3197+ * This program is distributed in the hope that it will be useful,
3198+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3199+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3200+ * GNU General Public License for more details.
3201+ *
3202+ * You should have received a copy of the GNU General Public License along
3203+ * with this program; if not, write to the Free Software Foundation, Inc.,
3204+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
3205+ */
3206+
3207+#ifndef INIT_SESSION_H
3208+#define INIT_SESSION_H
3209+
3210+#include <sys/types.h>
3211+
3212+#include <nih/macros.h>
3213+#include <nih/list.h>
3214+
3215+#include <nih-dbus/dbus_message.h>
3216+
3217+
3218+/**
3219+ * Session:
3220+ * @entry: list header,
3221+ * @chroot: path all jobs are chrooted to,
3222+ * @user: uid all jobs are switched to,
3223+ * @conf_path: configuration path.
3224+ *
3225+ * This structure is used to identify collections of jobs
3226+ * that share either a common @chroot and/or common @user.
3227+ *
3228+ * Summary of Session values for different environments:
3229+ *
3230+ * +-------------+---------------------------------------+
3231+ * | D-Bus | Session |
3232+ * +------+------+--------+-----+------------------------+
3233+ * | user | PID | chroot | uid | Object contents |
3234+ * +------+------+--------+-----+------------------------+
3235+ * | 0 | >0 | no | 0 | NULL (*1) |
3236+ * | >0 | "0" | no | >0 | only uid set. |
3237+ * | 0 | >0 | yes | 0 | chroot + conf_path set |
3238+ * | >0 | ?? | yes | >0 | XXX: fails (*2) |
3239+ * +------+------+--------+-----+------------------------+
3240+ *
3241+ * Notes:
3242+ *
3243+ * (*1) - The "NULL session" represents the "traditional" environment
3244+ * before sessions were introduced (namely a non-chroot environment
3245+ * where all job and event operations were handled by uid 0 (root)).
3246+ *
3247+ * (*2) - error is:
3248+ *
3249+ * initctl: Unable to connect to system bus: Failed to connect to socket
3250+ * /var/run/dbus/system_bus_socket: No such file or directory
3251+ *
3252+ **/
3253+typedef struct session {
3254+ NihList entry;
3255+ char * chroot;
3256+ uid_t user;
3257+ char * conf_path;
3258+} Session;
3259+
3260+
3261+NIH_BEGIN_EXTERN
3262+
3263+extern NihList *sessions;
3264+
3265+void session_init (void);
3266+
3267+Session *session_new (const void *parent, const char *chroot, uid_t user)
3268+ __attribute__ ((malloc, warn_unused_result));
3269+
3270+Session *session_from_dbus (const void *parent, NihDBusMessage *message);
3271+
3272+NIH_END_EXTERN
3273+
3274+#endif /* INIT_SESSION_H */
3275
3276=== modified file 'init/tests/test_blocked.c'
3277--- init/tests/test_blocked.c 2009-06-23 09:29:35 +0000
3278+++ init/tests/test_blocked.c 2011-06-06 15:17:24 +0000
3279@@ -46,7 +46,7 @@
3280 * in a list.
3281 */
3282 TEST_FEATURE ("with job");
3283- class = job_class_new (NULL, "test");
3284+ class = job_class_new (NULL, "test", NULL);
3285 job = job_new (class, "");
3286
3287 TEST_ALLOC_FAIL {
3288@@ -364,6 +364,9 @@
3289 main (int argc,
3290 char *argv[])
3291 {
3292+ /* run tests in legacy (pre-session support) mode */
3293+ setenv ("UPSTART_NO_SESSIONS", "1", 1);
3294+
3295 test_new ();
3296
3297 return 0;
3298
3299=== modified file 'init/tests/test_conf.c'
3300--- init/tests/test_conf.c 2011-02-17 23:38:17 +0000
3301+++ init/tests/test_conf.c 2011-06-06 15:17:24 +0000
3302@@ -2,7 +2,6 @@
3303 *
3304 * test_conf.c - test suite for init/conf.c
3305 *
3306- * Copyright © 2011 Google Inc.
3307 * Copyright © 2009 Canonical Ltd.
3308 * Author: Scott James Remnant <scott@netsplit.com>.
3309 *
3310@@ -3309,9 +3308,9 @@
3311 */
3312 TEST_FEATURE ("with not-current job");
3313 file = conf_file_new (source, "/path/to/file");
3314- job = file->job = job_class_new (NULL, "foo");
3315+ job = file->job = job_class_new (NULL, "foo", NULL);
3316
3317- other = job_class_new (NULL, "foo");
3318+ other = job_class_new (NULL, "foo", NULL);
3319 nih_hash_add (job_classes, &other->entry);
3320
3321 TEST_FREE_TAG (job);
3322@@ -3331,7 +3330,7 @@
3323 */
3324 TEST_FEATURE ("with stopped job");
3325 file = conf_file_new (source, "/path/to/file");
3326- job = file->job = job_class_new (NULL, "foo");
3327+ job = file->job = job_class_new (NULL, "foo", NULL);
3328
3329 nih_hash_add (job_classes, &job->entry);
3330
3331@@ -3351,7 +3350,7 @@
3332 */
3333 TEST_FEATURE ("with running job");
3334 file = conf_file_new (source, "/path/to/file");
3335- job = file->job = job_class_new (NULL, "foo");
3336+ job = file->job = job_class_new (NULL, "foo", NULL);
3337
3338 nih_hash_add (job_classes, &job->entry);
3339
3340@@ -3391,26 +3390,26 @@
3341 source2 = conf_source_new (NULL, "/tmp/bar", CONF_JOB_DIR);
3342
3343 file1 = conf_file_new (source2, "/tmp/bar/frodo");
3344- class1 = file1->job = job_class_new (NULL, "frodo");
3345+ class1 = file1->job = job_class_new (NULL, "frodo", NULL);
3346
3347 file2 = conf_file_new (source2, "/tmp/bar/bilbo");
3348
3349 file3 = conf_file_new (source2, "/tmp/bar/drogo");
3350- class2 = file3->job = job_class_new (NULL, "drogo");
3351+ class2 = file3->job = job_class_new (NULL, "drogo", NULL);
3352
3353 source3 = conf_source_new (NULL, "/tmp/baz", CONF_JOB_DIR);
3354
3355 file4 = conf_file_new (source3, "/tmp/baz/frodo");
3356- class3 = file4->job = job_class_new (NULL, "frodo");
3357+ class3 = file4->job = job_class_new (NULL, "frodo", NULL);
3358
3359 file5 = conf_file_new (source2, "/tmp/bar/bilbo");
3360- class4 = file5->job = job_class_new (NULL, "bilbo");
3361+ class4 = file5->job = job_class_new (NULL, "bilbo", NULL);
3362
3363
3364 /* Check that a job with only one file is returned.
3365 */
3366 TEST_FEATURE ("with one file");
3367- ptr = conf_select_job ("drogo");
3368+ ptr = conf_select_job ("drogo", NULL);
3369
3370 TEST_EQ_P (ptr, class2);
3371
3372@@ -3419,7 +3418,7 @@
3373 * returned.
3374 */
3375 TEST_FEATURE ("with multiple files");
3376- ptr = conf_select_job ("frodo");
3377+ ptr = conf_select_job ("frodo", NULL);
3378
3379 TEST_EQ_P (ptr, class1);
3380
3381@@ -3427,7 +3426,7 @@
3382 /* Check that files with no attached job are ignored.
3383 */
3384 TEST_FEATURE ("with file but no attached job");
3385- ptr = conf_select_job ("bilbo");
3386+ ptr = conf_select_job ("bilbo", NULL);
3387
3388 TEST_EQ_P (ptr, class4);
3389
3390@@ -3435,7 +3434,7 @@
3391 /* Check that when there is no match, NULL is returned.
3392 */
3393 TEST_FEATURE ("with no match");
3394- ptr = conf_select_job ("meep");
3395+ ptr = conf_select_job ("meep", NULL);
3396
3397 TEST_EQ_P (ptr, NULL);
3398
3399@@ -3450,6 +3449,9 @@
3400 main (int argc,
3401 char *argv[])
3402 {
3403+ /* run tests in legacy (pre-session support) mode */
3404+ setenv ("UPSTART_NO_SESSIONS", "1", 1);
3405+
3406 test_source_new ();
3407 test_file_new ();
3408 test_source_reload_job_dir ();
3409
3410=== modified file 'init/tests/test_control.c'
3411--- init/tests/test_control.c 2011-03-16 22:42:48 +0000
3412+++ init/tests/test_control.c 2011-06-06 15:17:24 +0000
3413@@ -2,7 +2,6 @@
3414 *
3415 * test_dbus.c - test suite for init/dbus.c
3416 *
3417- * Copyright © 2011 Google Inc.
3418 * Copyright © 2010 Canonical Ltd.
3419 * Author: Scott James Remnant <scott@netsplit.com>.
3420 *
3421@@ -234,10 +233,10 @@
3422 * new connection has them automatically registered.
3423 */
3424 TEST_FEATURE ("with existing jobs");
3425- class1 = job_class_new (NULL, "foo");
3426+ class1 = job_class_new (NULL, "foo", NULL);
3427 nih_hash_add (job_classes, &class1->entry);
3428
3429- class2 = job_class_new (NULL, "bar");
3430+ class2 = job_class_new (NULL, "bar", NULL);
3431 job1 = job_new (class2, "test1");
3432 job2 = job_new (class2, "test2");
3433 nih_hash_add (job_classes, &class2->entry);
3434@@ -334,7 +333,6 @@
3435 nih_free (class1);
3436 nih_free (class2);
3437
3438-
3439 control_server_close ();
3440
3441 dbus_shutdown ();
3442@@ -535,10 +533,10 @@
3443 refuse_registration = FALSE;
3444 server_conn = NULL;
3445
3446- class1 = job_class_new (NULL, "foo");
3447+ class1 = job_class_new (NULL, "foo", NULL);
3448 nih_hash_add (job_classes, &class1->entry);
3449
3450- class2 = job_class_new (NULL, "bar");
3451+ class2 = job_class_new (NULL, "bar", NULL);
3452 job1 = job_new (class2, "test1");
3453 job2 = job_new (class2, "test2");
3454 nih_hash_add (job_classes, &class2->entry);
3455@@ -933,9 +931,12 @@
3456
3457 strcpy (filename, dirname);
3458 strcat (filename, "/baz");
3459+
3460+ /* XXX: note that this will generate an error message when this
3461+ * test runs sine "/baz" does not exist as a directory.
3462+ */
3463 source3 = conf_source_new (NULL, filename, CONF_DIR);
3464
3465-
3466 message = nih_new (NULL, NihDBusMessage);
3467 message->connection = NULL;
3468 message->message = NULL;
3469@@ -987,7 +988,7 @@
3470 nih_error_init ();
3471 job_class_init ();
3472
3473- class = job_class_new (NULL, "test");
3474+ class = job_class_new (NULL, "test", NULL);
3475 nih_hash_add (job_classes, &class->entry);
3476
3477
3478@@ -1102,13 +1103,13 @@
3479 * in an array allocated as a child of the message structure.
3480 */
3481 TEST_FEATURE ("with registered jobs");
3482- class1 = job_class_new (NULL, "frodo");
3483+ class1 = job_class_new (NULL, "frodo", NULL);
3484 nih_hash_add (job_classes, &class1->entry);
3485
3486- class2 = job_class_new (NULL, "bilbo");
3487+ class2 = job_class_new (NULL, "bilbo", NULL);
3488 nih_hash_add (job_classes, &class2->entry);
3489
3490- class3 = job_class_new (NULL, "sauron");
3491+ class3 = job_class_new (NULL, "sauron", NULL);
3492 nih_hash_add (job_classes, &class3->entry);
3493
3494 TEST_ALLOC_FAIL {
3495@@ -2180,6 +2181,9 @@
3496 main (int argc,
3497 char *argv[])
3498 {
3499+ /* run tests in legacy (pre-session support) mode */
3500+ setenv ("UPSTART_NO_SESSIONS", "1", 1);
3501+
3502 test_server_open ();
3503 test_server_connect ();
3504 test_server_close ();
3505
3506=== modified file 'init/tests/test_environ.c'
3507--- init/tests/test_environ.c 2011-03-16 22:42:48 +0000
3508+++ init/tests/test_environ.c 2011-06-06 15:17:24 +0000
3509@@ -2,7 +2,6 @@
3510 *
3511 * test_environ.c - test suite for init/environ.c
3512 *
3513- * Copyright © 2011 Google Inc.
3514 * Copyright © 2009 Canonical Ltd.
3515 * Author: Scott James Remnant <scott@netsplit.com>.
3516 *
3517@@ -1587,6 +1586,9 @@
3518 main (int argc,
3519 char *argv[])
3520 {
3521+ /* run tests in legacy (pre-session support) mode */
3522+ setenv ("UPSTART_NO_SESSIONS", "1", 1);
3523+
3524 test_add ();
3525 test_append ();
3526 test_set ();
3527
3528=== modified file 'init/tests/test_event.c'
3529--- init/tests/test_event.c 2010-02-04 08:33:40 +0000
3530+++ init/tests/test_event.c 2011-06-06 15:17:24 +0000
3531@@ -233,7 +233,7 @@
3532 TEST_ALLOC_SAFE {
3533 event = event_new (NULL, "test", NULL);
3534
3535- class = job_class_new (NULL, "test");
3536+ class = job_class_new (NULL, "test", NULL);
3537 class->task = TRUE;
3538 class->process[PROCESS_MAIN] = process_new (class->process);
3539 class->process[PROCESS_MAIN]->command = "echo";
3540@@ -292,7 +292,7 @@
3541
3542 TEST_FREE_TAG (event1);
3543
3544- class = job_class_new (NULL, "test");
3545+ class = job_class_new (NULL, "test", NULL);
3546 class->task = TRUE;
3547
3548 class->start_on = event_operator_new (
3549@@ -327,7 +327,7 @@
3550
3551 TEST_FREE_TAG (event1);
3552
3553- class = job_class_new (NULL, "test");
3554+ class = job_class_new (NULL, "test", NULL);
3555 class->task = TRUE;
3556
3557 class->start_on = event_operator_new (
3558@@ -386,7 +386,7 @@
3559 TEST_FREE_TAG (event1);
3560 TEST_FREE_TAG (event2);
3561
3562- class = job_class_new (NULL, "test");
3563+ class = job_class_new (NULL, "test", NULL);
3564 class->task = TRUE;
3565
3566 assert (nih_str_array_add (&(class->env), class,
3567@@ -502,7 +502,7 @@
3568
3569 TEST_FREE_TAG (event2);
3570
3571- class = job_class_new (NULL, "test");
3572+ class = job_class_new (NULL, "test", NULL);
3573 class->task = TRUE;
3574
3575 assert (nih_str_array_add (&(class->env), class,
3576@@ -628,7 +628,7 @@
3577
3578 TEST_FREE_TAG (event2);
3579
3580- class = job_class_new (NULL, "test");
3581+ class = job_class_new (NULL, "test", NULL);
3582 class->task = TRUE;
3583
3584 assert (nih_str_array_add (&(class->env), class,
3585@@ -796,7 +796,7 @@
3586
3587 TEST_FREE_TAG (event2);
3588
3589- class = job_class_new (NULL, "test");
3590+ class = job_class_new (NULL, "test", NULL);
3591 class->task = TRUE;
3592
3593 assert (nih_str_array_add (&(class->env), class,
3594@@ -921,7 +921,7 @@
3595
3596 TEST_FREE_TAG (event1);
3597
3598- class = job_class_new (NULL, "test");
3599+ class = job_class_new (NULL, "test", NULL);
3600 class->instance = "$FRODO";
3601 class->task = TRUE;
3602
3603@@ -1000,7 +1000,7 @@
3604
3605 TEST_FREE_TAG (event1);
3606
3607- class = job_class_new (NULL, "test");
3608+ class = job_class_new (NULL, "test", NULL);
3609 class->instance = "$FRODO";
3610 class->task = TRUE;
3611
3612@@ -1084,7 +1084,7 @@
3613
3614 TEST_FREE_TAG (event1);
3615
3616- class = job_class_new (NULL, "test");
3617+ class = job_class_new (NULL, "test", NULL);
3618 class->instance = "$TIPPLE";
3619 class->task = TRUE;
3620
3621@@ -1127,7 +1127,7 @@
3622
3623 TEST_FREE_TAG (event1);
3624
3625- class = job_class_new (NULL, "test");
3626+ class = job_class_new (NULL, "test", NULL);
3627 class->task = TRUE;
3628
3629 class->process[PROCESS_POST_STOP] = process_new (class);
3630@@ -1175,7 +1175,7 @@
3631
3632 TEST_FREE_TAG (event1);
3633
3634- class = job_class_new (NULL, "test");
3635+ class = job_class_new (NULL, "test", NULL);
3636 class->task = TRUE;
3637
3638 class->process[PROCESS_POST_STOP] = process_new (class);
3639@@ -1250,7 +1250,7 @@
3640
3641 TEST_FREE_TAG (event1);
3642
3643- class = job_class_new (NULL, "test");
3644+ class = job_class_new (NULL, "test", NULL);
3645 class->task = TRUE;
3646
3647 class->process[PROCESS_POST_STOP] = process_new (class);
3648@@ -1329,7 +1329,7 @@
3649
3650 TEST_FREE_TAG (event1);
3651
3652- class = job_class_new (NULL, "test");
3653+ class = job_class_new (NULL, "test", NULL);
3654 class->task = TRUE;
3655
3656 class->process[PROCESS_POST_STOP] = process_new (class);
3657@@ -1439,7 +1439,7 @@
3658
3659 TEST_FREE_TAG (event1);
3660
3661- class = job_class_new (NULL, "test");
3662+ class = job_class_new (NULL, "test", NULL);
3663 class->task = TRUE;
3664
3665 class->process[PROCESS_POST_STOP] = process_new (class);
3666@@ -1527,7 +1527,7 @@
3667
3668 TEST_FREE_TAG (event1);
3669
3670- class = job_class_new (NULL, "test");
3671+ class = job_class_new (NULL, "test", NULL);
3672 class->task = TRUE;
3673
3674 class->process[PROCESS_POST_STOP] = process_new (class);
3675@@ -1623,7 +1623,7 @@
3676
3677 TEST_FREE_TAG (event);
3678
3679- class = job_class_new (NULL, "test");
3680+ class = job_class_new (NULL, "test", NULL);
3681 class->process[PROCESS_MAIN] = process_new (class->process);
3682 class->process[PROCESS_MAIN]->command = "echo";
3683
3684@@ -1657,7 +1657,7 @@
3685
3686 TEST_FREE_TAG (event);
3687
3688- class = job_class_new (NULL, "test");
3689+ class = job_class_new (NULL, "test", NULL);
3690 class->process[PROCESS_MAIN] = process_new (class->process);
3691 class->process[PROCESS_MAIN]->command = "echo";
3692
3693@@ -1699,7 +1699,7 @@
3694
3695 TEST_FREE_TAG (event);
3696
3697- class = job_class_new (NULL, "test");
3698+ class = job_class_new (NULL, "test", NULL);
3699 class->process[PROCESS_MAIN] = process_new (class->process);
3700 class->process[PROCESS_MAIN]->command = "echo";
3701
3702@@ -1740,7 +1740,7 @@
3703
3704 TEST_FREE_TAG (event);
3705
3706- class = job_class_new (NULL, "foo");
3707+ class = job_class_new (NULL, "foo", NULL);
3708
3709 job = job_new (class, "");
3710 job->goal = JOB_STOP;
3711@@ -1773,7 +1773,7 @@
3712
3713 TEST_FREE_TAG (event);
3714
3715- class = job_class_new (NULL, "foo");
3716+ class = job_class_new (NULL, "foo", NULL);
3717
3718 job = job_new (class, "");
3719 job->goal = JOB_START;
3720@@ -1804,7 +1804,7 @@
3721
3722 TEST_FREE_TAG (event);
3723
3724- class = job_class_new (NULL, "foo");
3725+ class = job_class_new (NULL, "foo", NULL);
3726
3727 job = job_new (class, "");
3728 job->goal = JOB_STOP;
3729@@ -1846,7 +1846,7 @@
3730
3731 TEST_FREE_TAG (event);
3732
3733- class = job_class_new (NULL, "foo");
3734+ class = job_class_new (NULL, "foo", NULL);
3735
3736 job = job_new (class, "");
3737 job->goal = JOB_START;
3738@@ -1889,7 +1889,7 @@
3739
3740 TEST_FREE_TAG (event);
3741
3742- class = job_class_new (NULL, "foo");
3743+ class = job_class_new (NULL, "foo", NULL);
3744 class->process[PROCESS_POST_STOP] = process_new (class);
3745 class->process[PROCESS_POST_STOP]->command = "echo";
3746
3747@@ -1934,7 +1934,7 @@
3748
3749 TEST_FREE_TAG (event);
3750
3751- class = job_class_new (NULL, "foo");
3752+ class = job_class_new (NULL, "foo", NULL);
3753 class->process[PROCESS_PRE_START] = process_new (class);
3754 class->process[PROCESS_PRE_START]->command = "echo";
3755
3756@@ -1974,6 +1974,9 @@
3757 main (int argc,
3758 char *argv[])
3759 {
3760+ /* run tests in legacy (pre-session support) mode */
3761+ setenv ("UPSTART_NO_SESSIONS", "1", 1);
3762+
3763 test_new ();
3764 test_block ();
3765 test_unblock ();
3766
3767=== modified file 'init/tests/test_event_operator.c'
3768--- init/tests/test_event_operator.c 2010-02-04 20:08:59 +0000
3769+++ init/tests/test_event_operator.c 2011-06-06 15:17:24 +0000
3770@@ -1325,6 +1325,9 @@
3771 main (int argc,
3772 char *argv[])
3773 {
3774+ /* run tests in legacy (pre-session support) mode */
3775+ setenv ("UPSTART_NO_SESSIONS", "1", 1);
3776+
3777 test_operator_new ();
3778 test_operator_copy ();
3779 test_operator_destroy ();
3780
3781=== modified file 'init/tests/test_job.c'
3782--- init/tests/test_job.c 2010-12-14 15:32:41 +0000
3783+++ init/tests/test_job.c 2011-06-06 15:17:24 +0000
3784@@ -86,7 +86,7 @@
3785 * list of the class and have sensible defaults.
3786 */
3787 TEST_FEATURE ("with no name");
3788- class = job_class_new (NULL, "test");
3789+ class = job_class_new (NULL, "test", NULL);
3790 class->stop_on = event_operator_new (class, EVENT_MATCH, "baz", NULL);
3791
3792 TEST_ALLOC_FAIL {
3793@@ -284,7 +284,7 @@
3794 * using its path, and have a InstanceAdded signal emitted.
3795 */
3796 TEST_FEATURE ("with signal emission");
3797- class = job_class_new (NULL, "test");
3798+ class = job_class_new (NULL, "test", NULL);
3799 job = job_new (class, "fred");
3800
3801 assert (dbus_connection_get_object_path_data (conn, job->path,
3802@@ -324,7 +324,7 @@
3803 * is still registered.
3804 */
3805 TEST_FEATURE ("without signal emission");
3806- class = job_class_new (NULL, "test");
3807+ class = job_class_new (NULL, "test", NULL);
3808 job = job_new (class, "fred");
3809
3810 assert (dbus_connection_get_object_path_data (conn, job->path,
3811@@ -359,7 +359,6 @@
3812
3813 nih_free (class);
3814
3815-
3816 TEST_DBUS_CLOSE (conn);
3817 TEST_DBUS_CLOSE (client_conn);
3818 TEST_DBUS_END (dbus_pid);
3819@@ -386,7 +385,7 @@
3820
3821 program_name = "test";
3822
3823- class = job_class_new (NULL, "test");
3824+ class = job_class_new (NULL, "test", NULL);
3825 class->process[PROCESS_MAIN] = process_new (class);
3826 class->process[PROCESS_MAIN]->command = "echo";
3827 class->process[PROCESS_PRE_START] = process_new (class);
3828@@ -691,7 +690,7 @@
3829 TEST_FILENAME (dirname);
3830 mkdir (dirname, 0700);
3831
3832- class = job_class_new (NULL, "test");
3833+ class = job_class_new (NULL, "test", NULL);
3834 class->process[PROCESS_MAIN] = process_new (class);
3835 class->process[PROCESS_MAIN]->command = nih_sprintf (
3836 class->process[PROCESS_MAIN], "touch %s/run", dirname);
3837@@ -3736,7 +3735,7 @@
3838 TEST_ALLOC_SAFE {
3839 source = conf_source_new (NULL, "/tmp", CONF_JOB_DIR);
3840 file = conf_file_new (source, "/tmp/test");
3841- file->job = job_class_new (NULL, "test");
3842+ file->job = job_class_new (NULL, "test", NULL);
3843 replacement = file->job;
3844
3845 job = job_new (class, "");
3846@@ -3805,7 +3804,7 @@
3847 TEST_ALLOC_SAFE {
3848 source = conf_source_new (NULL, "/tmp", CONF_JOB_DIR);
3849 file = conf_file_new (source, "/tmp/test");
3850- file->job = job_class_new (NULL, "test");
3851+ file->job = job_class_new (NULL, "test", NULL);
3852 replacement = file->job;
3853
3854 job = job_new (class, "");
3855@@ -3882,7 +3881,7 @@
3856 TEST_FEATURE ("post-stop to waiting for deleted job");
3857 source = conf_source_new (NULL, "/tmp", CONF_JOB_DIR);
3858 file = conf_file_new (source, "/tmp/test");
3859- file->job = job_class_new (NULL, "test");
3860+ file->job = job_class_new (NULL, "test", NULL);
3861 replacement = file->job;
3862
3863 class->deleted = TRUE;
3864@@ -3951,11 +3950,11 @@
3865 void
3866 test_next_state (void)
3867 {
3868- JobClass *class;
3869+ JobClass *class;
3870 Job *job;
3871
3872 TEST_FUNCTION ("job_next_state");
3873- class = job_class_new (NULL, "test");
3874+ class = job_class_new (NULL, "test", NULL);
3875 class->process[PROCESS_MAIN] = process_new (class);
3876 class->process[PROCESS_MAIN]->command = "echo";
3877
3878@@ -4210,7 +4209,7 @@
3879 * as failed before freeing the blocking list.
3880 */
3881 TEST_FEATURE ("with no current failure");
3882- class = job_class_new (NULL, "test");
3883+ class = job_class_new (NULL, "test", NULL);
3884 job = job_new (class, "");
3885
3886 event1 = event_new (NULL, "foo", NULL);
3887@@ -4251,7 +4250,7 @@
3888 * since these were added after the first failure.
3889 */
3890 TEST_FEATURE ("with previous failure");
3891- class = job_class_new (NULL, "test");
3892+ class = job_class_new (NULL, "test", NULL);
3893 job = job_new (class, "");
3894 job->failed = TRUE;
3895 job->failed_process = PROCESS_PRE_START;
3896@@ -4289,7 +4288,6 @@
3897
3898 nih_free (class);
3899
3900-
3901 event_poll ();
3902 }
3903
3904@@ -4307,7 +4305,7 @@
3905 * is unblocked and the list itself is then freed.
3906 */
3907 TEST_FEATURE ("with blocked events");
3908- class = job_class_new (NULL, "test");
3909+ class = job_class_new (NULL, "test", NULL);
3910 job = job_new (class, "");
3911
3912 event1 = event_new (NULL, "foo", NULL);
3913@@ -4343,7 +4341,7 @@
3914 * unblocked and marked as failed.
3915 */
3916 TEST_FEATURE ("with blocked events and failure");
3917- class = job_class_new (NULL, "test");
3918+ class = job_class_new (NULL, "test", NULL);
3919 job = job_new (class, "");
3920
3921 event1 = event_new (NULL, "foo", NULL);
3922@@ -4379,7 +4377,7 @@
3923 * still works (and just does nothing).
3924 */
3925 TEST_FEATURE ("without blocked events");
3926- class = job_class_new (NULL, "test");
3927+ class = job_class_new (NULL, "test", NULL);
3928 job = job_new (class, "");
3929
3930 job_finished (job, TRUE);
3931@@ -4388,7 +4386,6 @@
3932
3933 nih_free (class);
3934
3935-
3936 event_poll ();
3937 }
3938
3939@@ -4407,7 +4404,7 @@
3940 * event event emitted with the job name set.
3941 */
3942 TEST_FEATURE ("with singleton in starting state");
3943- class = job_class_new (NULL, "test");
3944+ class = job_class_new (NULL, "test", NULL);
3945
3946 job = job_new (class, "");
3947 job->goal = JOB_START;
3948@@ -4446,7 +4443,7 @@
3949 * instance name set.
3950 */
3951 TEST_FEATURE ("with instance in starting state");
3952- class = job_class_new (NULL, "test");
3953+ class = job_class_new (NULL, "test", NULL);
3954 class->instance = "$FOO";
3955
3956 job = job_new (class, "foo");
3957@@ -4486,7 +4483,7 @@
3958 * event emitted with the job name set.
3959 */
3960 TEST_FEATURE ("with singleton in running state");
3961- class = job_class_new (NULL, "test");
3962+ class = job_class_new (NULL, "test", NULL);
3963
3964 job = job_new (class, "");
3965 job->goal = JOB_START;
3966@@ -4516,7 +4513,7 @@
3967 * instance name set.
3968 */
3969 TEST_FEATURE ("with instance in running state");
3970- class = job_class_new (NULL, "test");
3971+ class = job_class_new (NULL, "test", NULL);
3972 class->instance = "$FOO";
3973
3974 job = job_new (class, "foo");
3975@@ -4548,7 +4545,7 @@
3976 * result as "ok"
3977 */
3978 TEST_FEATURE ("with non-failed singleton in stopping state");
3979- class = job_class_new (NULL, "test");
3980+ class = job_class_new (NULL, "test", NULL);
3981
3982 job = job_new (class, "");
3983 job->goal = JOB_STOP;
3984@@ -4588,7 +4585,7 @@
3985 * also has the instance name set before the result information.
3986 */
3987 TEST_FEATURE ("with non-failed instance in stopping state");
3988- class = job_class_new (NULL, "test");
3989+ class = job_class_new (NULL, "test", NULL);
3990 class->instance = "$FOO";
3991
3992 job = job_new (class, "foo");
3993@@ -4631,7 +4628,7 @@
3994 * exit status members set.
3995 */
3996 TEST_FEATURE ("with failed singleton in stopping state");
3997- class = job_class_new (NULL, "test");
3998+ class = job_class_new (NULL, "test", NULL);
3999
4000 job = job_new (class, "");
4001 job->goal = JOB_STOP;
4002@@ -4677,7 +4674,7 @@
4003 * set before the result information.
4004 */
4005 TEST_FEATURE ("with failed instance in stopping state");
4006- class = job_class_new (NULL, "test");
4007+ class = job_class_new (NULL, "test", NULL);
4008 class->instance = "$FOO";
4009
4010 job = job_new (class, "foo");
4011@@ -4725,7 +4722,7 @@
4012 * members set.
4013 */
4014 TEST_FEATURE ("with killed singleton in stopping state");
4015- class = job_class_new (NULL, "test");
4016+ class = job_class_new (NULL, "test", NULL);
4017
4018 job = job_new (class, "");
4019 job->goal = JOB_STOP;
4020@@ -4771,7 +4768,7 @@
4021 * result information.
4022 */
4023 TEST_FEATURE ("with killed instance in stopping state");
4024- class = job_class_new (NULL, "test");
4025+ class = job_class_new (NULL, "test", NULL);
4026 class->instance = "$FOO";
4027
4028 job = job_new (class, "foo");
4029@@ -4819,7 +4816,7 @@
4030 * signal members set.
4031 */
4032 TEST_FEATURE ("with unknown killed singleton in stopping state");
4033- class = job_class_new (NULL, "test");
4034+ class = job_class_new (NULL, "test", NULL);
4035
4036 job = job_new (class, "");
4037 job->goal = JOB_STOP;
4038@@ -4865,7 +4862,7 @@
4039 * the result information.
4040 */
4041 TEST_FEATURE ("with unknown killed instance in stopping state");
4042- class = job_class_new (NULL, "test");
4043+ class = job_class_new (NULL, "test", NULL);
4044 class->instance = "$FOO";
4045
4046 job = job_new (class, "foo");
4047@@ -4912,7 +4909,7 @@
4048 * the job name set, the result as failed, and just the process set.
4049 */
4050 TEST_FEATURE ("with unstarted singleton in stopping state");
4051- class = job_class_new (NULL, "test");
4052+ class = job_class_new (NULL, "test", NULL);
4053
4054 job = job_new (class, "");
4055 job->goal = JOB_STOP;
4056@@ -4957,7 +4954,7 @@
4057 * the result information.
4058 */
4059 TEST_FEATURE ("with unstarted instance in stopping state");
4060- class = job_class_new (NULL, "test");
4061+ class = job_class_new (NULL, "test", NULL);
4062 class->instance = "$FOO";
4063
4064 job = job_new (class, "foo");
4065@@ -5003,7 +5000,7 @@
4066 * the result as failed and the process set to respawn.
4067 */
4068 TEST_FEATURE ("with failed respawn singleton in stopping state");
4069- class = job_class_new (NULL, "test");
4070+ class = job_class_new (NULL, "test", NULL);
4071
4072 job = job_new (class, "");
4073 job->goal = JOB_STOP;
4074@@ -5048,7 +5045,7 @@
4075 * information.
4076 */
4077 TEST_FEATURE ("with failed respawn instance in stopping state");
4078- class = job_class_new (NULL, "test");
4079+ class = job_class_new (NULL, "test", NULL);
4080 class->instance = "$FOO";
4081
4082 job = job_new (class, "foo");
4083@@ -5094,7 +5091,7 @@
4084 * result as "ok"
4085 */
4086 TEST_FEATURE ("with non-failed singleton in stopped state");
4087- class = job_class_new (NULL, "test");
4088+ class = job_class_new (NULL, "test", NULL);
4089
4090 job = job_new (class, "");
4091 job->goal = JOB_STOP;
4092@@ -5125,7 +5122,7 @@
4093 * also has the instance name set before the result information.
4094 */
4095 TEST_FEATURE ("with non-failed instance in waiting state");
4096- class = job_class_new (NULL, "test");
4097+ class = job_class_new (NULL, "test", NULL);
4098 class->instance = "$FOO";
4099
4100 job = job_new (class, "foo");
4101@@ -5159,7 +5156,7 @@
4102 * exit status members set.
4103 */
4104 TEST_FEATURE ("with failed singleton in waiting state");
4105- class = job_class_new (NULL, "test");
4106+ class = job_class_new (NULL, "test", NULL);
4107
4108 job = job_new (class, "");
4109 job->goal = JOB_STOP;
4110@@ -5196,7 +5193,7 @@
4111 * set before the result information.
4112 */
4113 TEST_FEATURE ("with failed instance in waiting state");
4114- class = job_class_new (NULL, "test");
4115+ class = job_class_new (NULL, "test", NULL);
4116 class->instance = "$FOO";
4117
4118 job = job_new (class, "foo");
4119@@ -5235,7 +5232,7 @@
4120 * members set.
4121 */
4122 TEST_FEATURE ("with killed singleton in waiting state");
4123- class = job_class_new (NULL, "test");
4124+ class = job_class_new (NULL, "test", NULL);
4125
4126 job = job_new (class, "");
4127 job->goal = JOB_STOP;
4128@@ -5272,7 +5269,7 @@
4129 * result information.
4130 */
4131 TEST_FEATURE ("with killed instance in waiting state");
4132- class = job_class_new (NULL, "test");
4133+ class = job_class_new (NULL, "test", NULL);
4134 class->instance = "$FOO";
4135
4136 job = job_new (class, "foo");
4137@@ -5311,7 +5308,7 @@
4138 * signal members set.
4139 */
4140 TEST_FEATURE ("with unknown killed singleton in waiting state");
4141- class = job_class_new (NULL, "test");
4142+ class = job_class_new (NULL, "test", NULL);
4143
4144 job = job_new (class, "");
4145 job->goal = JOB_STOP;
4146@@ -5348,7 +5345,7 @@
4147 * the result information.
4148 */
4149 TEST_FEATURE ("with unknown killed instance in waiting state");
4150- class = job_class_new (NULL, "test");
4151+ class = job_class_new (NULL, "test", NULL);
4152 class->instance = "$FOO";
4153
4154 job = job_new (class, "foo");
4155@@ -5386,7 +5383,7 @@
4156 * the job name set, the result as failed, and just the process set.
4157 */
4158 TEST_FEATURE ("with unstarted singleton in waiting state");
4159- class = job_class_new (NULL, "test");
4160+ class = job_class_new (NULL, "test", NULL);
4161
4162 job = job_new (class, "");
4163 job->goal = JOB_STOP;
4164@@ -5422,7 +5419,7 @@
4165 * the result information.
4166 */
4167 TEST_FEATURE ("with unstarted instance in waiting state");
4168- class = job_class_new (NULL, "test");
4169+ class = job_class_new (NULL, "test", NULL);
4170 class->instance = "$FOO";
4171
4172 job = job_new (class, "foo");
4173@@ -5459,7 +5456,7 @@
4174 * the result as failed and the process set to respawn.
4175 */
4176 TEST_FEATURE ("with failed respawn singleton in waiting state");
4177- class = job_class_new (NULL, "test");
4178+ class = job_class_new (NULL, "test", NULL);
4179
4180 job = job_new (class, "");
4181 job->goal = JOB_STOP;
4182@@ -5495,7 +5492,7 @@
4183 * information.
4184 */
4185 TEST_FEATURE ("with failed respawn instance in waiting state");
4186- class = job_class_new (NULL, "test");
4187+ class = job_class_new (NULL, "test", NULL);
4188 class->instance = "$FOO";
4189
4190 job = job_new (class, "foo");
4191@@ -5540,7 +5537,7 @@
4192
4193 /* Check that the name of a non-instance job is returned. */
4194 TEST_FEATURE ("with non-instance job");
4195- class = job_class_new (NULL, "test");
4196+ class = job_class_new (NULL, "test", NULL);
4197 job = job_new (class, "");
4198
4199 TEST_ALLOC_FAIL {
4200@@ -5554,7 +5551,7 @@
4201
4202 /* Check that the name of an instance job is returned. */
4203 TEST_FEATURE ("with instance job");
4204- class = job_class_new (NULL, "test");
4205+ class = job_class_new (NULL, "test", NULL);
4206 class->instance = "$FOO";
4207 job = job_new (class, "foo");
4208
4209@@ -5571,7 +5568,7 @@
4210 * value.
4211 */
4212 TEST_FEATURE ("with multiple calls");
4213- class = job_class_new (NULL, "test");
4214+ class = job_class_new (NULL, "test", NULL);
4215 job = job_new (class, "");
4216
4217 ret = job_name (job);
4218@@ -5842,7 +5839,6 @@
4219 NihError *error;
4220 NihDBusError *dbus_error;
4221
4222-
4223 TEST_FUNCTION ("job_start");
4224 nih_error_init ();
4225 nih_main_loop_init ();
4226@@ -5858,8 +5854,9 @@
4227 * the reply will be sent to the sender.
4228 */
4229 TEST_FEATURE ("with stopping job");
4230- class = job_class_new (NULL, "test");
4231+ class = job_class_new (NULL, "test", NULL);
4232 job = job_new (class, "");
4233+ TEST_NE_P (job, NULL);
4234
4235 job->goal = JOB_STOP;
4236 job->state = JOB_STOPPING;
4237@@ -5944,7 +5941,7 @@
4238 * and no blocking entry created.
4239 */
4240 TEST_FEATURE ("with no wait");
4241- class = job_class_new (NULL, "test");
4242+ class = job_class_new (NULL, "test", NULL);
4243 job = job_new (class, "");
4244
4245 job->goal = JOB_STOP;
4246@@ -6014,7 +6011,7 @@
4247 * a D-Bus error is raised immediately.
4248 */
4249 TEST_FEATURE ("with starting job");
4250- class = job_class_new (NULL, "test");
4251+ class = job_class_new (NULL, "test", NULL);
4252 job = job_new (class, "");
4253
4254 job->goal = JOB_START;
4255@@ -6062,7 +6059,6 @@
4256
4257 nih_free (class);
4258
4259-
4260 TEST_DBUS_CLOSE (conn);
4261 TEST_DBUS_CLOSE (client_conn);
4262 TEST_DBUS_END (dbus_pid);
4263@@ -6087,7 +6083,6 @@
4264 NihError *error;
4265 NihDBusError *dbus_error;
4266
4267-
4268 TEST_FUNCTION ("job_stop");
4269 nih_error_init ();
4270 nih_main_loop_init ();
4271@@ -6103,7 +6098,7 @@
4272 * the reply will be sent to the sender and the instance deleted.
4273 */
4274 TEST_FEATURE ("with running job");
4275- class = job_class_new (NULL, "test");
4276+ class = job_class_new (NULL, "test", NULL);
4277 job = job_new (class, "");
4278
4279 job->goal = JOB_START;
4280@@ -6182,7 +6177,7 @@
4281 * no blocking entry created.
4282 */
4283 TEST_FEATURE ("with no wait");
4284- class = job_class_new (NULL, "test");
4285+ class = job_class_new (NULL, "test", NULL);
4286 job = job_new (class, "");
4287
4288 job->goal = JOB_START;
4289@@ -6248,7 +6243,7 @@
4290 * a D-Bus error is raised immediately.
4291 */
4292 TEST_FEATURE ("with stopping job");
4293- class = job_class_new (NULL, "test");
4294+ class = job_class_new (NULL, "test", NULL);
4295 job = job_new (class, "");
4296
4297 job->goal = JOB_STOP;
4298@@ -6296,7 +6291,6 @@
4299
4300 nih_free (class);
4301
4302-
4303 TEST_DBUS_CLOSE (conn);
4304 TEST_DBUS_CLOSE (client_conn);
4305 TEST_DBUS_END (dbus_pid);
4306@@ -6321,7 +6315,6 @@
4307 NihError *error;
4308 NihDBusError *dbus_error;
4309
4310-
4311 TEST_FUNCTION ("job_restart");
4312 nih_error_init ();
4313 nih_main_loop_init ();
4314@@ -6337,7 +6330,7 @@
4315 * it back through to running, the reply will be sent to the sender.
4316 */
4317 TEST_FEATURE ("with running job");
4318- class = job_class_new (NULL, "test");
4319+ class = job_class_new (NULL, "test", NULL);
4320 job = job_new (class, "");
4321
4322 job->goal = JOB_START;
4323@@ -6426,7 +6419,7 @@
4324 * and no blocking entry created.
4325 */
4326 TEST_FEATURE ("with no wait");
4327- class = job_class_new (NULL, "test");
4328+ class = job_class_new (NULL, "test", NULL);
4329 job = job_new (class, "");
4330
4331 job->goal = JOB_START;
4332@@ -6499,7 +6492,7 @@
4333 * a D-Bus error is raised immediately.
4334 */
4335 TEST_FEATURE ("with stopping job");
4336- class = job_class_new (NULL, "test");
4337+ class = job_class_new (NULL, "test", NULL);
4338 job = job_new (class, "");
4339
4340 job->goal = JOB_STOP;
4341@@ -6547,7 +6540,6 @@
4342
4343 nih_free (class);
4344
4345-
4346 TEST_DBUS_CLOSE (conn);
4347 TEST_DBUS_CLOSE (client_conn);
4348 TEST_DBUS_END (dbus_pid);
4349@@ -6578,7 +6570,7 @@
4350 TEST_FEATURE ("with instance name");
4351 TEST_ALLOC_FAIL {
4352 TEST_ALLOC_SAFE {
4353- class = job_class_new (NULL, "test");
4354+ class = job_class_new (NULL, "test", NULL);
4355 job = job_new (class, "instance name");
4356
4357 message = nih_new (NULL, NihDBusMessage);
4358@@ -6618,7 +6610,7 @@
4359 TEST_FEATURE ("with no instance name");
4360 TEST_ALLOC_FAIL {
4361 TEST_ALLOC_SAFE {
4362- class = job_class_new (NULL, "test");
4363+ class = job_class_new (NULL, "test", NULL);
4364 job = job_new (class, "");
4365
4366 message = nih_new (NULL, NihDBusMessage);
4367@@ -6671,7 +6663,7 @@
4368
4369 TEST_ALLOC_FAIL {
4370 TEST_ALLOC_SAFE {
4371- class = job_class_new (NULL, "test");
4372+ class = job_class_new (NULL, "test", NULL);
4373 job = job_new (class, "");
4374 job->goal = JOB_START;
4375
4376@@ -6725,7 +6717,7 @@
4377
4378 TEST_ALLOC_FAIL {
4379 TEST_ALLOC_SAFE {
4380- class = job_class_new (NULL, "test");
4381+ class = job_class_new (NULL, "test", NULL);
4382 job = job_new (class, "");
4383 job->goal = JOB_START;
4384 job->state = JOB_RUNNING;
4385@@ -6783,7 +6775,7 @@
4386 TEST_FEATURE ("with no processes");
4387 TEST_ALLOC_FAIL {
4388 TEST_ALLOC_SAFE {
4389- class = job_class_new (NULL, "test");
4390+ class = job_class_new (NULL, "test", NULL);
4391 job = job_new (class, "");
4392 job->goal = JOB_START;
4393 job->state = JOB_STARTING;
4394@@ -6827,7 +6819,7 @@
4395 TEST_FEATURE ("with pre-start process");
4396 TEST_ALLOC_FAIL {
4397 TEST_ALLOC_SAFE {
4398- class = job_class_new (NULL, "test");
4399+ class = job_class_new (NULL, "test", NULL);
4400 class->process[PROCESS_PRE_START] = process_new (class);
4401 class->process[PROCESS_PRE_START]->command = "echo";
4402
4403@@ -6882,7 +6874,7 @@
4404 TEST_FEATURE ("with post-start process and no main process");
4405 TEST_ALLOC_FAIL {
4406 TEST_ALLOC_SAFE {
4407- class = job_class_new (NULL, "test");
4408+ class = job_class_new (NULL, "test", NULL);
4409 class->process[PROCESS_POST_START] = process_new (class);
4410 class->process[PROCESS_POST_START]->command = "echo";
4411
4412@@ -6936,7 +6928,7 @@
4413 TEST_FEATURE ("with main process");
4414 TEST_ALLOC_FAIL {
4415 TEST_ALLOC_SAFE {
4416- class = job_class_new (NULL, "test");
4417+ class = job_class_new (NULL, "test", NULL);
4418 class->process[PROCESS_MAIN] = process_new (class);
4419 class->process[PROCESS_MAIN]->command = "echo";
4420
4421@@ -6991,7 +6983,7 @@
4422 TEST_FEATURE ("with main process and post-start process");
4423 TEST_ALLOC_FAIL {
4424 TEST_ALLOC_SAFE {
4425- class = job_class_new (NULL, "test");
4426+ class = job_class_new (NULL, "test", NULL);
4427 class->process[PROCESS_POST_START] = process_new (class);
4428 class->process[PROCESS_POST_START]->command = "echo";
4429 class->process[PROCESS_MAIN] = process_new (class);
4430@@ -7055,7 +7047,7 @@
4431 TEST_FEATURE ("with main process and pre-stop process");
4432 TEST_ALLOC_FAIL {
4433 TEST_ALLOC_SAFE {
4434- class = job_class_new (NULL, "test");
4435+ class = job_class_new (NULL, "test", NULL);
4436 class->process[PROCESS_MAIN] = process_new (class);
4437 class->process[PROCESS_MAIN]->command = "echo";
4438 class->process[PROCESS_PRE_STOP] = process_new (class);
4439@@ -7119,7 +7111,7 @@
4440 TEST_FEATURE ("with pre-stop process and no main process");
4441 TEST_ALLOC_FAIL {
4442 TEST_ALLOC_SAFE {
4443- class = job_class_new (NULL, "test");
4444+ class = job_class_new (NULL, "test", NULL);
4445 class->process[PROCESS_PRE_STOP] = process_new (class);
4446 class->process[PROCESS_PRE_STOP]->command = "echo";
4447
4448@@ -7173,7 +7165,7 @@
4449 TEST_FEATURE ("with post-stop process");
4450 TEST_ALLOC_FAIL {
4451 TEST_ALLOC_SAFE {
4452- class = job_class_new (NULL, "test");
4453+ class = job_class_new (NULL, "test", NULL);
4454 class->process[PROCESS_POST_STOP] = process_new (class);
4455 class->process[PROCESS_POST_STOP]->command = "echo";
4456
4457@@ -7226,6 +7218,9 @@
4458 main (int argc,
4459 char *argv[])
4460 {
4461+ /* run tests in legacy (pre-session support) mode */
4462+ setenv ("UPSTART_NO_SESSIONS", "1", 1);
4463+
4464 test_new ();
4465 test_register ();
4466 test_change_goal ();
4467
4468=== modified file 'init/tests/test_job_class.c'
4469--- init/tests/test_job_class.c 2011-05-12 20:42:28 +0000
4470+++ init/tests/test_job_class.c 2011-06-06 15:17:24 +0000
4471@@ -2,7 +2,6 @@
4472 *
4473 * test_job_class.c - test suite for init/job_class.c
4474 *
4475- * Copyright © 2011 Google Inc.
4476 * Copyright © 2010 Canonical Ltd.
4477 * Author: Scott James Remnant <scott@netsplit.com>.
4478 *
4479@@ -66,7 +65,7 @@
4480 {
4481 JobClass *class;
4482 int i;
4483-
4484+
4485 /* Check that we can create a new JobClass structure; the structure
4486 * should be allocated with nih_alloc but not placed in the jobs
4487 * hash.
4488@@ -75,8 +74,7 @@
4489 job_class_init ();
4490
4491 TEST_ALLOC_FAIL {
4492- class = job_class_new (NULL, "test");
4493-
4494+ class = job_class_new (NULL, "test", NULL);
4495 if (test_alloc_failed) {
4496 TEST_EQ_P (class, NULL);
4497 continue;
4498@@ -180,15 +178,15 @@
4499 source2 = conf_source_new (NULL, "/tmp/bar", CONF_JOB_DIR);
4500
4501 file1 = conf_file_new (source2, "/tmp/bar/frodo");
4502- class1 = file1->job = job_class_new (NULL, "frodo");
4503+ class1 = file1->job = job_class_new (NULL, "frodo", NULL);
4504
4505 file2 = conf_file_new (source2, "/tmp/bar/bilbo");
4506- class2 = file2->job = job_class_new (NULL, "bilbo");
4507+ class2 = file2->job = job_class_new (NULL, "bilbo", NULL);
4508
4509 source3 = conf_source_new (NULL, "/tmp/baz", CONF_JOB_DIR);
4510
4511 file3 = conf_file_new (source3, "/tmp/baz/frodo");
4512- class3 = file3->job = job_class_new (NULL, "frodo");
4513+ class3 = file3->job = job_class_new (NULL, "frodo", NULL);
4514
4515
4516 control_init ();
4517@@ -381,7 +379,7 @@
4518 * becomes the hash table member.
4519 */
4520 TEST_FEATURE ("with replacable registered class and not best class");
4521- class4 = job_class_new (NULL, "frodo");
4522+ class4 = job_class_new (NULL, "frodo", NULL);
4523 nih_hash_add (job_classes, &class4->entry);
4524 job_class_register (class4, conn, FALSE);
4525
4526@@ -479,15 +477,15 @@
4527 source2 = conf_source_new (NULL, "/tmp/bar", CONF_JOB_DIR);
4528
4529 file1 = conf_file_new (source2, "/tmp/bar/frodo");
4530- class1 = file1->job = job_class_new (NULL, "frodo");
4531+ class1 = file1->job = job_class_new (NULL, "frodo", NULL);
4532
4533 file2 = conf_file_new (source2, "/tmp/bar/bilbo");
4534- class2 = file2->job = job_class_new (NULL, "bilbo");
4535+ class2 = file2->job = job_class_new (NULL, "bilbo", NULL);
4536
4537 source3 = conf_source_new (NULL, "/tmp/baz", CONF_JOB_DIR);
4538
4539 file3 = conf_file_new (source3, "/tmp/baz/frodo");
4540- class3 = file3->job = job_class_new (NULL, "frodo");
4541+ class3 = file3->job = job_class_new (NULL, "frodo", NULL);
4542
4543
4544 control_init ();
4545@@ -720,7 +718,7 @@
4546 nih_free (source2);
4547 nih_free (source1);
4548
4549- class4 = job_class_new (NULL, "frodo");
4550+ class4 = job_class_new (NULL, "frodo", NULL);
4551 nih_hash_add (job_classes, &class4->entry);
4552 job_class_register (class4, conn, FALSE);
4553
4554@@ -789,7 +787,7 @@
4555 * announce it.
4556 */
4557 TEST_FEATURE ("with signal emission");
4558- class = job_class_new (NULL, "test");
4559+ class = job_class_new (NULL, "test", NULL);
4560
4561 assert (dbus_connection_get_object_path_data (conn, class->path,
4562 (void **)&object));
4563@@ -826,7 +824,7 @@
4564 * by emitting a signal immediately afterwards.
4565 */
4566 TEST_FEATURE ("without signal emission");
4567- class = job_class_new (NULL, "test");
4568+ class = job_class_new (NULL, "test", NULL);
4569
4570 assert (dbus_connection_get_object_path_data (conn, class->path,
4571 (void **)&object));
4572@@ -860,7 +858,6 @@
4573
4574 nih_free (class);
4575
4576-
4577 TEST_DBUS_CLOSE (conn);
4578 TEST_DBUS_CLOSE (client_conn);
4579 TEST_DBUS_END (dbus_pid);
4580@@ -895,7 +892,7 @@
4581 assert (! dbus_error_is_set (&dbus_error));
4582
4583
4584- class = job_class_new (NULL, "test");
4585+ class = job_class_new (NULL, "test", NULL);
4586
4587 assert (dbus_connection_get_object_path_data (conn, class->path,
4588 (void **)&object));
4589@@ -931,7 +928,6 @@
4590
4591 nih_free (class);
4592
4593-
4594 TEST_DBUS_CLOSE (conn);
4595 TEST_DBUS_CLOSE (client_conn);
4596 TEST_DBUS_END (dbus_pid);
4597@@ -953,7 +949,7 @@
4598 * just have the built-ins in the returned environment.
4599 */
4600 TEST_FEATURE ("with no configured environment");
4601- class = job_class_new (NULL, "test");
4602+ class = job_class_new (NULL, "test", NULL);
4603
4604 TEST_ALLOC_FAIL {
4605 env = job_class_environment (NULL, class, &len);
4606@@ -983,7 +979,7 @@
4607 * will have those appended to the environment as well as the builtins.
4608 */
4609 TEST_FEATURE ("with configured environment");
4610- class = job_class_new (NULL, "test");
4611+ class = job_class_new (NULL, "test", NULL);
4612
4613 class->env = nih_str_array_new (class);
4614 assert (nih_str_array_add (&(class->env), class, NULL, "FOO=BAR"));
4615@@ -1020,7 +1016,7 @@
4616 /* Check that configured environment override built-ins.
4617 */
4618 TEST_FEATURE ("with configuration overriding built-ins");
4619- class = job_class_new (NULL, "test");
4620+ class = job_class_new (NULL, "test", NULL);
4621
4622 class->env = nih_str_array_new (class);
4623 assert (nih_str_array_add (&(class->env), class, NULL, "FOO=BAR"));
4624@@ -1068,7 +1064,6 @@
4625 NihError *error;
4626 NihDBusError *dbus_error;
4627
4628-
4629 TEST_FUNCTION ("job_class_get_instance");
4630 nih_error_init ();
4631
4632@@ -1079,7 +1074,7 @@
4633 TEST_FEATURE ("with running job");
4634 TEST_ALLOC_FAIL {
4635 TEST_ALLOC_SAFE {
4636- class = job_class_new (NULL, "test");
4637+ class = job_class_new (NULL, "test", NULL);
4638 job = job_new (class, "");
4639
4640 message = nih_new (NULL, NihDBusMessage);
4641@@ -1116,7 +1111,7 @@
4642 /* Check that if there's no such instance, a D-Bus error is raised.
4643 */
4644 TEST_FEATURE ("with unknown job");
4645- class = job_class_new (NULL, "test");
4646+ class = job_class_new (NULL, "test", NULL);
4647
4648 message = nih_new (NULL, NihDBusMessage);
4649 message->connection = NULL;
4650@@ -1147,7 +1142,7 @@
4651 TEST_FEATURE ("with environment");
4652 TEST_ALLOC_FAIL {
4653 TEST_ALLOC_SAFE {
4654- class = job_class_new (NULL, "test");
4655+ class = job_class_new (NULL, "test", NULL);
4656 class->instance = "$FOO";
4657
4658 job = job_new (class, "wibble");
4659@@ -1191,7 +1186,7 @@
4660 * is returned.
4661 */
4662 TEST_FEATURE ("with invalid environment");
4663- class = job_class_new (NULL, "test");
4664+ class = job_class_new (NULL, "test", NULL);
4665 class->instance = "$FOO";
4666
4667 job = job_new (class, "wibble");
4668@@ -1234,7 +1229,7 @@
4669 TEST_FUNCTION ("job_class_get_instance_by_name");
4670 nih_error_init ();
4671
4672- class = job_class_new (NULL, "test");
4673+ class = job_class_new (NULL, "test", NULL);
4674
4675
4676 /* Check that when given a known instance name, the path to that
4677@@ -1364,7 +1359,7 @@
4678 nih_error_init ();
4679 job_class_init ();
4680
4681- class = job_class_new (NULL, "test");
4682+ class = job_class_new (NULL, "test", NULL);
4683
4684
4685 /* Check that paths for each of the active instances are returned
4686@@ -1461,7 +1456,6 @@
4687 nih_free (message);
4688 }
4689
4690-
4691 nih_free (class);
4692 }
4693
4694@@ -1483,7 +1477,6 @@
4695 NihError *error;
4696 NihDBusError *dbus_error;
4697
4698-
4699 TEST_FUNCTION ("job_class_start");
4700 nih_error_init ();
4701 nih_main_loop_init ();
4702@@ -1499,7 +1492,7 @@
4703 * the reply will be sent to the sender.
4704 */
4705 TEST_FEATURE ("with new job");
4706- class = job_class_new (NULL, "test");
4707+ class = job_class_new (NULL, "test", NULL);
4708
4709 method = dbus_message_new_method_call (
4710 dbus_bus_get_unique_name (conn),
4711@@ -1590,7 +1583,7 @@
4712 * immediately and the job not blocked.
4713 */
4714 TEST_FEATURE ("with no wait");
4715- class = job_class_new (NULL, "test");
4716+ class = job_class_new (NULL, "test", NULL);
4717
4718 method = dbus_message_new_method_call (
4719 dbus_bus_get_unique_name (conn),
4720@@ -1670,7 +1663,7 @@
4721 * it through to running, the reply will be sent to the sender.
4722 */
4723 TEST_FEATURE ("with stopping job");
4724- class = job_class_new (NULL, "test");
4725+ class = job_class_new (NULL, "test", NULL);
4726 job = job_new (class, "");
4727
4728 job->goal = JOB_STOP;
4729@@ -1771,7 +1764,7 @@
4730 * a D-Bus error is raised immediately.
4731 */
4732 TEST_FEATURE ("with starting job");
4733- class = job_class_new (NULL, "test");
4734+ class = job_class_new (NULL, "test", NULL);
4735 job = job_new (class, "");
4736
4737 job->goal = JOB_START;
4738@@ -1827,7 +1820,7 @@
4739 * when it's starting.
4740 */
4741 TEST_FEATURE ("with environment");
4742- class = job_class_new (NULL, "test");
4743+ class = job_class_new (NULL, "test", NULL);
4744 class->instance = "$FOO";
4745
4746 method = dbus_message_new_method_call (
4747@@ -1928,7 +1921,7 @@
4748 * is returned.
4749 */
4750 TEST_FEATURE ("with invalid environment");
4751- class = job_class_new (NULL, "test");
4752+ class = job_class_new (NULL, "test", NULL);
4753
4754 method = dbus_message_new_method_call (
4755 dbus_bus_get_unique_name (conn),
4756@@ -1974,7 +1967,6 @@
4757
4758 nih_free (class);
4759
4760-
4761 TEST_DBUS_CLOSE (conn);
4762 TEST_DBUS_CLOSE (client_conn);
4763 TEST_DBUS_END (dbus_pid);
4764@@ -2000,7 +1992,6 @@
4765 NihError *error;
4766 NihDBusError *dbus_error;
4767
4768-
4769 TEST_FUNCTION ("job_class_stop");
4770 nih_error_init ();
4771 nih_main_loop_init ();
4772@@ -2016,7 +2007,7 @@
4773 * will be sent to the sender.
4774 */
4775 TEST_FEATURE ("with running job");
4776- class = job_class_new (NULL, "test");
4777+ class = job_class_new (NULL, "test", NULL);
4778 job = job_new (class, "");
4779
4780 job->goal = JOB_START;
4781@@ -2099,7 +2090,7 @@
4782 * and no blocking entry created.
4783 */
4784 TEST_FEATURE ("with no wait");
4785- class = job_class_new (NULL, "test");
4786+ class = job_class_new (NULL, "test", NULL);
4787 job = job_new (class, "");
4788
4789 job->goal = JOB_START;
4790@@ -2169,7 +2160,7 @@
4791 * a D-Bus error is raised immediately.
4792 */
4793 TEST_FEATURE ("with stopping job");
4794- class = job_class_new (NULL, "test");
4795+ class = job_class_new (NULL, "test", NULL);
4796 job = job_new (class, "");
4797
4798 job->goal = JOB_STOP;
4799@@ -2224,7 +2215,7 @@
4800 * immediately.
4801 */
4802 TEST_FEATURE ("with unknown job");
4803- class = job_class_new (NULL, "test");
4804+ class = job_class_new (NULL, "test", NULL);
4805
4806 method = dbus_message_new_method_call (
4807 dbus_bus_get_unique_name (conn),
4808@@ -2273,7 +2264,7 @@
4809 * for the pre-stop script.
4810 */
4811 TEST_FEATURE ("with environment");
4812- class = job_class_new (NULL, "test");
4813+ class = job_class_new (NULL, "test", NULL);
4814 class->instance = "$FOO";
4815
4816 job = job_new (class, "wibble");
4817@@ -2362,7 +2353,7 @@
4818 * is returned.
4819 */
4820 TEST_FEATURE ("with invalid environment");
4821- class = job_class_new (NULL, "test");
4822+ class = job_class_new (NULL, "test", NULL);
4823 job = job_new (class, "");
4824
4825 job->goal = JOB_START;
4826@@ -2410,7 +2401,6 @@
4827
4828 nih_free (class);
4829
4830-
4831 TEST_DBUS_CLOSE (conn);
4832 TEST_DBUS_CLOSE (client_conn);
4833 TEST_DBUS_END (dbus_pid);
4834@@ -2437,7 +2427,6 @@
4835 NihError *error;
4836 NihDBusError *dbus_error;
4837
4838-
4839 TEST_FUNCTION ("job_class_restart");
4840 nih_error_init ();
4841 nih_main_loop_init ();
4842@@ -2453,7 +2442,7 @@
4843 * through to waiting, the reply will be sent to the sender.
4844 */
4845 TEST_FEATURE ("with running job");
4846- class = job_class_new (NULL, "test");
4847+ class = job_class_new (NULL, "test", NULL);
4848 job = job_new (class, "");
4849
4850 job->goal = JOB_START;
4851@@ -2550,7 +2539,7 @@
4852 * entry created.
4853 */
4854 TEST_FEATURE ("with no wait");
4855- class = job_class_new (NULL, "test");
4856+ class = job_class_new (NULL, "test", NULL);
4857 job = job_new (class, "");
4858
4859 job->goal = JOB_START;
4860@@ -2631,7 +2620,7 @@
4861 * a D-Bus error is raised immediately.
4862 */
4863 TEST_FEATURE ("with stopping job");
4864- class = job_class_new (NULL, "test");
4865+ class = job_class_new (NULL, "test", NULL);
4866 job = job_new (class, "");
4867
4868 job->goal = JOB_STOP;
4869@@ -2686,7 +2675,7 @@
4870 * immediately.
4871 */
4872 TEST_FEATURE ("with unknown job");
4873- class = job_class_new (NULL, "test");
4874+ class = job_class_new (NULL, "test", NULL);
4875
4876 method = dbus_message_new_method_call (
4877 dbus_bus_get_unique_name (conn),
4878@@ -2735,7 +2724,7 @@
4879 * when it's starting again.
4880 */
4881 TEST_FEATURE ("with environment");
4882- class = job_class_new (NULL, "test");
4883+ class = job_class_new (NULL, "test", NULL);
4884 class->instance = "$FOO";
4885
4886 job = job_new (class, "wibble");
4887@@ -2848,7 +2837,7 @@
4888 * is returned.
4889 */
4890 TEST_FEATURE ("with invalid environment");
4891- class = job_class_new (NULL, "test");
4892+ class = job_class_new (NULL, "test", NULL);
4893 job = job_new (class, "");
4894
4895 job->goal = JOB_START;
4896@@ -2896,7 +2885,6 @@
4897
4898 nih_free (class);
4899
4900-
4901 TEST_DBUS_CLOSE (conn);
4902 TEST_DBUS_CLOSE (client_conn);
4903 TEST_DBUS_END (dbus_pid);
4904@@ -2925,7 +2913,7 @@
4905
4906 TEST_ALLOC_FAIL {
4907 TEST_ALLOC_SAFE {
4908- class = job_class_new (NULL, "test");
4909+ class = job_class_new (NULL, "test", NULL);
4910
4911 message = nih_new (NULL, NihDBusMessage);
4912 message->connection = NULL;
4913@@ -2977,7 +2965,7 @@
4914 TEST_FEATURE ("with description");
4915 TEST_ALLOC_FAIL {
4916 TEST_ALLOC_SAFE {
4917- class = job_class_new (NULL, "test");
4918+ class = job_class_new (NULL, "test", NULL);
4919 class->description = nih_strdup (class, "a test job");
4920
4921 message = nih_new (NULL, NihDBusMessage);
4922@@ -3017,7 +3005,7 @@
4923 TEST_FEATURE ("with no description");
4924 TEST_ALLOC_FAIL {
4925 TEST_ALLOC_SAFE {
4926- class = job_class_new (NULL, "test");
4927+ class = job_class_new (NULL, "test", NULL);
4928
4929 message = nih_new (NULL, NihDBusMessage);
4930 message->connection = NULL;
4931@@ -3069,7 +3057,7 @@
4932 TEST_FEATURE ("with author");
4933 TEST_ALLOC_FAIL {
4934 TEST_ALLOC_SAFE {
4935- class = job_class_new (NULL, "test");
4936+ class = job_class_new (NULL, "test", NULL);
4937 class->author = nih_strdup (class, "a test job");
4938
4939 message = nih_new (NULL, NihDBusMessage);
4940@@ -3109,7 +3097,7 @@
4941 TEST_FEATURE ("with no author");
4942 TEST_ALLOC_FAIL {
4943 TEST_ALLOC_SAFE {
4944- class = job_class_new (NULL, "test");
4945+ class = job_class_new (NULL, "test", NULL);
4946
4947 message = nih_new (NULL, NihDBusMessage);
4948 message->connection = NULL;
4949@@ -3161,7 +3149,7 @@
4950 TEST_FEATURE ("with version");
4951 TEST_ALLOC_FAIL {
4952 TEST_ALLOC_SAFE {
4953- class = job_class_new (NULL, "test");
4954+ class = job_class_new (NULL, "test", NULL);
4955 class->version = nih_strdup (class, "a test job");
4956
4957 message = nih_new (NULL, NihDBusMessage);
4958@@ -3201,7 +3189,7 @@
4959 TEST_FEATURE ("with no version");
4960 TEST_ALLOC_FAIL {
4961 TEST_ALLOC_SAFE {
4962- class = job_class_new (NULL, "test");
4963+ class = job_class_new (NULL, "test", NULL);
4964
4965 message = nih_new (NULL, NihDBusMessage);
4966 message->connection = NULL;
4967@@ -3256,7 +3244,7 @@
4968
4969 TEST_ALLOC_FAIL {
4970 TEST_ALLOC_SAFE {
4971- class = job_class_new (NULL, "test");
4972+ class = job_class_new (NULL, "test", NULL);
4973
4974 class->start_on = event_operator_new (
4975 class, EVENT_OR, NULL, NULL);
4976@@ -3351,7 +3339,7 @@
4977
4978 TEST_ALLOC_FAIL {
4979 TEST_ALLOC_SAFE {
4980- class = job_class_new (NULL, "test");
4981+ class = job_class_new (NULL, "test", NULL);
4982
4983 message = nih_new (NULL, NihDBusMessage);
4984 message->connection = NULL;
4985@@ -3407,7 +3395,7 @@
4986
4987 TEST_ALLOC_FAIL {
4988 TEST_ALLOC_SAFE {
4989- class = job_class_new (NULL, "test");
4990+ class = job_class_new (NULL, "test", NULL);
4991
4992 class->stop_on = event_operator_new (
4993 class, EVENT_OR, NULL, NULL);
4994@@ -3502,7 +3490,7 @@
4995
4996 TEST_ALLOC_FAIL {
4997 TEST_ALLOC_SAFE {
4998- class = job_class_new (NULL, "test");
4999+ class = job_class_new (NULL, "test", NULL);
5000
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches