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