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