Merge tag '0.18.3' into debian
New upstream release 0.18.3
Benda Xu
8 years ago
0 | # Using Busybox as your Default Shell with OpenRC | |
1 | ||
2 | If you have/bin/sh linked to busybox, you need to be aware of several | |
3 | incompatibilities between busybox's applets and the standalone | |
4 | counterparts. Since it is possible to configure busybox to not include | |
5 | these applets or to prefer the standalone counterparts, OpenRC does not | |
6 | attempt to support the busybox applets. | |
7 | ||
8 | For now, it is recommended that you disable the following busybox | |
9 | configuration settings for best results with OpenRC. | |
10 | ||
11 | CONFIG_START_STOP_DAEMON -- The start-stop-daemon applet is not compatible with | |
12 | start-stop-daemon in OpenRC. | |
13 | ||
14 | CONFIG_MOUNT -- The mount applet does not support the -O [no]_netdev options to | |
15 | skip over or include network file systems when the -a option is present. | |
16 | ||
17 | CONFIG_UMOUNT -- The umount applet does not support the -O option along with -a. | |
18 | ||
19 | CONFIG_SWAPONOFF -- The swapon applet does not support the -e option | |
20 | or recognize the nofail option in fstab. | |
21 | ||
22 | CONFIG_SETFONT -- The setfont applet does not support the -u option from kbd. | |
23 | ||
24 | CONFIG_IP -- The ip applet doesn't support the "scope" modifier for | |
25 | "ip route add" and "ip address add". | |
26 | ||
27 | CONFIG_BB_SYSCTL -- The sysctl applet does not support the --system command | |
28 | line switch. | |
29 | ||
30 | There is work to get most of these supported by busybox, so this file | |
31 | will be updated as things change. |
0 | commit 248a7dcda351ef4172c28cc686bfe7b93fa522ff | |
1 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
2 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
3 | ||
4 | mtab: typo fix | |
5 | ||
6 | commit bb451fd7b4a200b63ba355ef2ea5ba35444f49e7 | |
7 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
8 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
9 | ||
10 | update ChangeLog | |
11 | ||
12 | commit fb23cbe204b9adeb817e2f5be7a1bb827bb9a477 | |
13 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
14 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
15 | ||
16 | mtab: make /etc/mtab as a file configurable | |
17 | ||
18 | commit a4346bb7f5fc09e81a61032ebc05f70692a4a04c | |
19 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
20 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
21 | ||
22 | start work on 0.18.3 | |
23 | ||
24 | commit 776346e2cd4a43ffeaf268b8a89927d9f3f9eca5 | |
25 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
26 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
27 | ||
28 | update changelog | |
29 | ||
30 | commit ce71ffbfbe5e44bb61a3f00faf8466071dab5ea7 | |
31 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
32 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
33 | ||
34 | openrc-run.sh: fix new required_* tests to exit properly | |
35 | ||
36 | commit d9ee8ca5842983b59cc2c6e595d21e9a26a4f000 | |
37 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
38 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
39 | ||
40 | update changelog | |
41 | ||
42 | commit 4e44e2cd73fb7fe08fb229bc3192d14f97dc2aa2 | |
43 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
44 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
45 | ||
46 | typo fix | |
47 | ||
48 | X-Gentoo-Bug: 563010 | |
49 | X-Gentoo-Bug: https://bugs.gentoo.org/show_bug.cgi?id=563010 | |
50 | ||
51 | commit 88b807f9bcea5ec5bf5c5edb3c7161bf5c12d2d0 | |
52 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
53 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
54 | ||
55 | increment version number | |
56 | ||
57 | commit feba5d86b73b0df5587b178e80e85129a60861cd | |
58 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
59 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
60 | ||
61 | mountinfo: make sure the netdev variable is initialized on Linux | |
62 | ||
63 | This fixes the following regression: | |
64 | ||
65 | X-Gentoo-Bug: 562668 | |
66 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=562668 | |
67 | ||
68 | commit 3b1e96a6a3af3de68a18558f3a6ebac31430a1cd | |
69 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
70 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
71 | ||
72 | openrc-run.sh: allow spaces in required_{files,dirs} | |
73 | ||
74 | X-Gentoo-Bug: 562320 | |
75 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=562320 | |
76 | ||
77 | commit 79998bdf9cb5089f423e00bfa4bc3816b64c58d4 | |
78 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
79 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
80 | ||
81 | increment version number | |
82 | ||
83 | commit 050ddfae4ad1ad0dc5993766e0bd90739bd41de9 | |
84 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
85 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
86 | ||
87 | Update ChangeLog | |
88 | ||
89 | commit d5116cc697c9eb275ab8497939ab41504e5ce578 | |
90 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
91 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
92 | ||
93 | localmount: white space cleanup | |
94 | ||
95 | commit b86d170037197d7bdcda57c7d4c09c17bda97f31 | |
96 | Author: Ian Stakenvicius <axs@gentoo.org> | |
97 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
98 | ||
99 | localmount: clean up handling of aufs branches | |
100 | ||
101 | X-Gentoo-Bug: 560008 | |
102 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=560008 | |
103 | ||
104 | commit 6fa0d6318bcd5c98548cff2ff840bca116892ca5 | |
105 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
106 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
107 | ||
108 | mtab: fix update logic | |
109 | ||
110 | This advises users to remove mtab from their runlevels if /etc/mtab is a | |
111 | symlink, and it creates the symlink if /etc/mtab does not exist on a | |
112 | system. | |
113 | ||
114 | X-Gentoo-Bug: 560060 | |
115 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=560060 | |
116 | ||
117 | commit 80d3928b0d13f09a9c1e82bd27c9fff943d84d43 | |
118 | Author: Austin S. Hemmelgarn <ahferroin7@gmail.com> | |
119 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
120 | ||
121 | cgroups: Add the hugetlb, net_cls and pids controllers | |
122 | ||
123 | Note from WilliamH: I slightly rearranged the code and added the | |
124 | settings in rc.conf. | |
125 | ||
126 | X-Gentoo-Bug: 555488 | |
127 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=555488 | |
128 | ||
129 | commit 17ef205bc63a4e231dccee719394a7a8563f8c3f | |
130 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
131 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
132 | ||
133 | sysfs: use printf instead of echo to write to cgroup files | |
134 | ||
135 | This is needed for compatibility with musl and printf is also posix. | |
136 | ||
137 | X-Gentoo-Bug: 562334 | |
138 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=562334 | |
139 | ||
140 | commit b20a1951adf9a705a903fb3047b7ef26c013103c | |
141 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
142 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
143 | ||
144 | rc-cgroup.sh: Do not add leading spaces to cgroup values | |
145 | ||
146 | We were starting the value we write to the cgroup setting file with | |
147 | leading spaces and this was causing issues. This change makes sure that | |
148 | we aren't adding leading spaces to the value. | |
149 | ||
150 | X-Gentoo-Bug: 562354 | |
151 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=562354 | |
152 | ||
153 | commit bf0c0dd5644436efe4986c2b259b755d111266b9 | |
154 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
155 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
156 | ||
157 | bootmisc: convert errors in clean_run function to warnings | |
158 | ||
159 | X-Gentoo-Bug: 552418 | |
160 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=552418 | |
161 | ||
162 | commit 1558ad2b9ebf319b85876a940d31d513bf21324f | |
163 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
164 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
165 | ||
166 | bootmisc: only remove temp directory if umount is successful | |
167 | ||
168 | Change the clean_run function to only remove the temp directory if the | |
169 | umount was successful. | |
170 | ||
171 | X-Gentoo-Bug: 561230 | |
172 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=561230 | |
173 | ||
174 | commit 5f4f2420364098835522da868a9e75205c9e4f9c | |
175 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
176 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
177 | ||
178 | mountinfo: fix --netdev and --nonetdev on Linux | |
179 | ||
180 | On Linux, the --netdev and --nonetdev switches were not working. They | |
181 | were both returning false. After this change, they operate based on the | |
182 | presence or abscence of the _netdev option in mount options. | |
183 | ||
184 | commit b3f7ff901f7d3ed00b9f73c601193ac507f62eaf | |
185 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
186 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
187 | ||
188 | mountinfo: read /proc/self/mounts instead of /proc/mounts on Linux | |
189 | ||
190 | commit a59365a582c3a8c9a8b863b572fddcb65fccadfd | |
191 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
192 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
193 | ||
194 | start-stop-daemon.sh: complain in start if command is undefined | |
195 | ||
196 | The default start-stop-daemon start function expects the command | |
197 | variable to be defined to point to the daemon we want to start. | |
198 | ||
199 | If the variable is undefined, this means that there will be nothing to | |
200 | start, and in this case we should complain because it is possible that | |
201 | the script writer made a typo in the variable name. | |
202 | ||
203 | commit dac5966ca40610797d2b2aabef17154ca3dc20af | |
204 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
205 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
206 | ||
207 | Revert "local/netmount: remove uses of -O [no]_netdev" | |
208 | ||
209 | This reverts commit 2a439c85bd69efc14847b4397bd6783cac051405. | |
210 | There is another use case for -O involving iscsi, so we can't remove it. | |
211 | ||
212 | commit 3b6a6df4b5b818e576a88444632d5c73cffd1c57 | |
213 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
214 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
215 | ||
216 | openrc-run: rename some dependency variables and a function for clarity | |
217 | ||
218 | All of the dependency type lists had the types_ prefix in their names; | |
219 | this has been changed to deptypes_ to make them more self documenting. | |
220 | ||
221 | Along the same lines, the setup_types function was renamed | |
222 | setup_deptypes. | |
223 | ||
224 | commit b047ea47e97d7e8b96d6d0e064613f6860c8eb36 | |
225 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
226 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
227 | ||
228 | localmount/netmount: on Linux, fail if some file systems do not mount | |
229 | ||
230 | The following return codes are returned by mount -a: | |
231 | ||
232 | 0: all file systems mounted. | |
233 | 32: no file systems mounted. | |
234 | 64: some file systems mounted. | |
235 | ||
236 | The localmount/netmount services should fail if all file systems that | |
237 | should mount did not mount. | |
238 | ||
239 | commit b652752339690e10a55ae50d046f4cf2a98daf1a | |
240 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
241 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
242 | ||
243 | Make localmount and netmount always succeed on non-linux | |
244 | ||
245 | commit 2a439c85bd69efc14847b4397bd6783cac051405 | |
246 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
247 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
248 | ||
249 | local/netmount: remove uses of -O [no]_netdev | |
250 | ||
251 | This was causing an incompatibility with busybox, and we do not use it | |
252 | in Gentoo. | |
253 | ||
254 | commit 7341cd882fba522c1f1d183603334839bd4df7fc | |
255 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
256 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
257 | ||
258 | allow localmount and netmount to fail | |
259 | ||
260 | commit 279f1e5d1013309d99509ab4b7b57521f8a4aba4 | |
261 | Author: Mike Frysinger <vapier@gentoo.org> | |
262 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
263 | ||
264 | binfmt: fix indent on return | |
265 | ||
266 | commit c256a7aa80c683eca6194c80b57294e4d51c9a16 | |
267 | Author: Doug Freed <dwfreed@mtu.edu> | |
268 | Commit: Doug Freed <dwfreed@mtu.edu> | |
269 | ||
270 | savecache: clean up implementation | |
271 | ||
272 | X-Gentoo-Bug: 557222 | |
273 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=557222 | |
274 | ||
275 | commit 6a422982579786cb8308af04ccca6622afa06e50 | |
276 | Author: Jason Zaman <jason@perfinion.com> | |
277 | Commit: Doug Freed <dwfreed@mtu.edu> | |
278 | ||
279 | tmpfiles: run restorecon on the entire path | |
280 | ||
281 | The tmpfiles "d" entry will create a full path and only the last dir in | |
282 | the path will have its SELinux label set correctly. This patch will | |
283 | restorecon the parents as well so that the selinux labels are correct. | |
284 | ||
285 | eg, "d /run/libvirt/lxc", then "lxc" would have the correct SELinux | |
286 | label but "libvirt" would not. | |
287 | ||
288 | Signed-off-by: Jason Zaman <jason@perfinion.com> | |
289 | ||
290 | commit f69833a1e17d1cf65e96a34fcc0e48caf9d90d64 | |
291 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
292 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
293 | ||
294 | mountinfo: fix -e and -E options | |
295 | ||
296 | Add the -e and -E options to getoptstring so they are recognized. | |
297 | ||
298 | commit eeadca0b8a5b87c26e60a58563251604350a7a3b | |
299 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
300 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
301 | ||
302 | Add EERROR_QUIET and EINFO_QUIET to environment whitelist | |
303 | ||
304 | commit dde339070b4850dc1fadf4992cc01d3468992106 | |
305 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
306 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
307 | ||
308 | Increment version | |
309 | ||
310 | commit 1736be3bc3ebbc1440f87b49fc353e81fb0a6037 | |
311 | Author: Doug Freed <dwfreed@mtu.edu> | |
312 | Commit: Doug Freed <dwfreed@mtu.edu> | |
313 | ||
314 | savecache: Fix unable to create cache message | |
315 | ||
316 | The cache is created in $RC_LIBEXECDIR, not $RC_SVCDIR, so fix the error | |
317 | message when we fail to create it to match. | |
318 | ||
319 | commit a36a635b016a7427dd1739a26c951fedf22f0dec | |
320 | Author: Mike Gilbert <floppym@gentoo.org> | |
321 | Commit: Doug Freed <dwfreed@mtu.edu> | |
322 | ||
323 | tmpfiles: Recognize type 'v' (create btrfs subvol) | |
324 | ||
325 | This change does NOT implement btrfs subvol creation. Instead, it | |
326 | treats 'v' the same as 'd', which is an acceptable fallback | |
327 | according to the manual. | |
328 | ||
329 | Fixes #58 | |
330 | ||
331 | commit 9310ccc06bcadd8897aed51cd51c94fccb7d9c07 | |
332 | Author: Mike Gilbert <floppym@gentoo.org> | |
333 | Commit: Doug Freed <dwfreed@mtu.edu> | |
334 | ||
335 | Remove execute bit from tmpfiles.sh.in | |
336 | ||
337 | commit 0c2e4eb3cd7935d375b74099a3a9a5fe519e6cab | |
338 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
339 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
340 | ||
341 | Update ChangeLog | |
342 | ||
343 | commit d2ce07e227ec95370e8aee5f1199edc6ad61aff9 | |
344 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
345 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
346 | ||
347 | Add rc-sstat script | |
348 | ||
349 | The rc-sstat script is written to display status of s6 services and | |
350 | run rc-status to display all services status. | |
351 | ||
352 | This currently only works on Linux. | |
353 | ||
354 | commit b209fe3859c05c286037843bb34058f849c54b15 | |
355 | Author: Mike Gilbert <floppym@gentoo.org> | |
356 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
357 | ||
358 | bootmisc: Don't call dmesg in systemd-nspawn containers | |
359 | ||
360 | This fixes #57. | |
361 | ||
362 | commit c94c8288cd5217b01c24d6f048c64ebbc30bee02 | |
363 | Author: Mike Frysinger <vapier@gentoo.org> | |
364 | Commit: Mike Frysinger <vapier@gentoo.org> | |
365 | ||
366 | fix link to s6 website | |
367 | ||
368 | commit bcb9c44e73ccf332c7c961a6f82520699c6e776d | |
369 | Author: Mike Gilbert <floppym@gentoo.org> | |
370 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
371 | ||
372 | man: Document the stopsig variable | |
373 | ||
374 | This variable can be used to set the signal to send if the service is | |
375 | using start-stop-daemon. | |
376 | ||
377 | This fixes #56 | |
378 | ||
379 | commit bbabf546f9d72cbfc48bd839a6d01b402ee6cced | |
380 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
381 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
382 | ||
383 | Document bash's handling of ulimit options | |
384 | ||
385 | When bash is used in posix mode for the shell, the ulimit command uses | |
386 | a block size of 512 bytes for the -c and -f options. | |
387 | ||
388 | X-Gentoo-Bug: 549238 | |
389 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=549238 | |
390 | ||
391 | commit a7fcc1e264b035177b4e524a40b27145baa86969 | |
392 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
393 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
394 | ||
395 | S6: kick the scanner and sleep 1.5 seconds to avoid a race condition | |
396 | ||
397 | commit b79d058f162d8b49ccc968744e7cb1b7a7ba729c | |
398 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
399 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
400 | ||
401 | s6: Use s6-svc -Dd to stop services | |
402 | ||
403 | This allows us to get rid of the sleep call in the stop function. Also, | |
404 | we set a configurable timeout value for stopping daemons. | |
405 | ||
406 | commit ddce529c71c2e9f01d8e5666e27050b6ed6c6761 | |
407 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
408 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
409 | ||
410 | More s6 fixes | |
411 | ||
412 | - When no service link is in the scan directory, show the default | |
413 | stopped message. | |
414 | - Do not remove the service link when stopping the service. | |
415 | ||
416 | commit e372f97bebd4866633ad56aa5d5b1ae59fa88118 | |
417 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
418 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
419 | ||
420 | Fix the s6 handling | |
421 | ||
422 | This changes the default s6 service directory to /var/svc.d, also | |
423 | it changes the code to work with the individual services instead of | |
424 | forcing a rescan when a service is started or stopped. | |
425 | ||
426 | commit c2abf4b436b8cca8ebed395ff08f5fdc546eadac | |
427 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
428 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
429 | ||
430 | Start work on 0.17 | |
431 | ||
432 | commit d247ac4cbbe0ab62564ef82a5940b4f1a03973b3 | |
433 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
434 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
435 | ||
436 | Update changelog | |
437 | ||
438 | commit bb2d7becfd3008379f8f69b5d036922281aa211f | |
439 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
440 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
441 | ||
442 | Add support for the s6 supervision suite | |
443 | ||
444 | commit 0f9354becfbd54f9800c93092aa26be859dcf16a | |
445 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
446 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
447 | ||
448 | man: Clarify the documentation for command_args | |
449 | ||
450 | The command_args variable only works if using start-stop-daemon to start | |
451 | the daemon. | |
452 | ||
453 | commit a15fa1a3b12a5372c1b3c8d5df7e489648bef913 | |
454 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
455 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
456 | ||
457 | Rework supervisor integration framework | |
458 | ||
459 | The original way of doing this allowed users to change the supervisor in | |
460 | conf.d/*. This changes this so that the supervisor setup can be done in | |
461 | the service script itself. | |
462 | ||
463 | commit 0198affc742297b6e203bbcecc14436682119cc7 | |
464 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
465 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
466 | ||
467 | The rc_supervisor variable is a service configuration variable | |
468 | ||
469 | This variable should not be changed globally unless you really know what | |
470 | you are doing. | |
471 | ||
472 | commit abef2fcb2dbcc277bb05f0d9c674d4b47826f17f | |
473 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
474 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
475 | ||
476 | Make the default start, stop and status functions overridable | |
477 | ||
478 | This will make it possible to add support for supervision suites such as | |
479 | runit and s6. | |
480 | ||
481 | commit 0b435ddd834bd18254c4d3341acdebf0829921f5 | |
482 | Author: Jakob Drexel <jake42@rommel.stw.uni-erlangen.de> | |
483 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
484 | ||
485 | librc: Fix crash if the service name is the same as the including runlevel | |
486 | ||
487 | If a service has the same name as the runlevel it is in, openrc will | |
488 | crash on changing to such runlevel. It goes in a recursive madness and | |
489 | eventually gets a SEGV while in snprintf (don't know why). | |
490 | ||
491 | This fixes two errors: | |
492 | 1. ls_dir stats files not with full path -> stat always returns != 0 | |
493 | 2. ls_dir adds files to list if stat failed | |
494 | ||
495 | This fixes #53. | |
496 | ||
497 | X-Gentoo-Bug: 537304 | |
498 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=537304 | |
499 | ||
500 | commit 9f6427ea57c6c950b4d1c356ad1bfb0aa8deb40b | |
501 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
502 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
503 | ||
504 | Start work on 0.16 | |
505 | ||
506 | commit 60488069c08201cbfbc661a3e7bd1fafa31fceed | |
507 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
508 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
509 | ||
510 | update ChangeLog | |
511 | ||
512 | commit 9225bfa6918cfd488c8f1055cf986b542f1f157e | |
513 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
514 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
515 | ||
516 | Build: make snapshot remove .git directory from tarball | |
517 | ||
518 | commit 7bd456ed7bf35da2d7a53650baa33637e178064e | |
519 | Author: Mike Gilbert <floppym@gentoo.org> | |
520 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
521 | ||
522 | Disable service scripts for systemd-nspawn | |
523 | ||
524 | This adds the -systemd-nspawn keyword to service scripts which are not | |
525 | intended to run in systemd-nspawn containers. | |
526 | ||
527 | This fixes #52. | |
528 | ||
529 | X-Gentoo-Bug: 548058 | |
530 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=548058 | |
531 | ||
532 | commit c709e6077c6eda3f4f7e7222298213413254ee0f | |
533 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
534 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
535 | ||
536 | Add support for systemd-nspawn containers | |
537 | ||
538 | This adds support for running OpenRC in a container created by | |
539 | the systemd-nspawn utility. | |
540 | ||
541 | This fixes #52. | |
542 | ||
543 | X-Gentoo-Bug: 548058 | |
544 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=548058 | |
545 | ||
546 | commit a27d577da8cf4f1c7f9784a043ecf02d71a81ca6 | |
547 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
548 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
549 | ||
550 | Build: fix the dist target | |
551 | ||
552 | The dist target now creates an archive based on the version setting. | |
553 | This makes it possible to create an archive identical to the ones github | |
554 | generates once the release is tagged. | |
555 | ||
556 | commit 8b9349208696e5caed1a8b34f066cec4ee642194 | |
557 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
558 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
559 | ||
560 | convert all references from runscript to openrc-run | |
561 | ||
562 | commit 4b1b457cd15cc1609c101b99a49a5e4c67b62567 | |
563 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
564 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
565 | ||
566 | Start work on 0.15 | |
567 | ||
568 | commit 1d6602bb8e7062323ead03eaa0c4ae307c517b9e | |
569 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
570 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
571 | ||
572 | Add ChangeLog | |
573 | ||
574 | commit a6391f44ee6c68d674ae8425983467b971710d5d | |
575 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
576 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
577 | ||
578 | mtab: move toward requiring /etc/mtab to be a symbolic link | |
579 | ||
580 | This changes the mtab service in the following way: | |
581 | ||
582 | - If /etc/mtab is a symbolic link, success is returned. | |
583 | - If /etc is not writable, we warn that we could not update /etc/mtab | |
584 | and return success. | |
585 | - If /etc/mtab does not exist, we create a symbolic link from | |
586 | /etc/mtab to /proc/self/mounts. | |
587 | - Otherwise, we warn that updating /etc/mtab as a file is | |
588 | deprecated and continue to update it after outputting instructions to | |
589 | the user for how to move it to a symbolic link. | |
590 | ||
591 | commit a8c6dbac96a20eb35ce55befe0e64d89dd30de4d | |
592 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
593 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
594 | ||
595 | typo fix in NEWS | |
596 | ||
597 | The binfmt service should be added to the boot runlevel, not sysinit. | |
598 | ||
599 | commit a7c0400177e504fe07e7c39168b7a92e40ab334a | |
600 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
601 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
602 | ||
603 | Update news | |
604 | ||
605 | commit 03803ae8e966755e8bf6d52b61209792cb830cf4 | |
606 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
607 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
608 | ||
609 | start-stop-daemon: redirect stdin if --background option is used | |
610 | ||
611 | X-Gentoo-Bug: 498684 | |
612 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=498684 | |
613 | ||
614 | commit 1c2f7bf607ee7e24dca0a2710cef9e9b24e819f7 | |
615 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
616 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
617 | ||
618 | Convert feature removal schedule to markdown | |
619 | ||
620 | commit 1ebffa517f6f1dafc206d5ee943d3cacd25feaf6 | |
621 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
622 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
623 | ||
624 | Convert news to markdown | |
625 | ||
626 | commit e6dd26d185e4a9722f4d4813a084ca77eba913c7 | |
627 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
628 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
629 | ||
630 | convert README.history to markdown | |
631 | ||
632 | commit 628b35e1beeea6aaab181b1511b2a879bdc45b61 | |
633 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
634 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
635 | ||
636 | Update busybox documentation | |
637 | ||
638 | Convert README.busybox to markdown and add the note on the sysctl applet | |
639 | incompatibility. | |
640 | ||
641 | commit ebc32aadada564095b70f0ff439a9863102a2ae5 | |
642 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
643 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
644 | ||
645 | Convert style guide to markdown | |
646 | ||
647 | commit 362dfa33804d2ba5bed241f697aac0178be07d3d | |
648 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
649 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
650 | ||
651 | README.md: small formatting changes | |
652 | ||
653 | commit dccc0a91292240022c4b120304b9198055d0d240 | |
654 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
655 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
656 | ||
657 | Update README.md format and bug reporting information | |
658 | ||
659 | commit c2aa56a7c49214b1fef355f79dfcd94265efe089 | |
660 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
661 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
662 | ||
663 | Rename README README.md | |
664 | ||
665 | This fixes #26. | |
666 | ||
667 | commit 23d806ca24845261fd89104c16bc28a60505fe5c | |
668 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
669 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
670 | ||
671 | savecache: clean up creation of cache directory | |
672 | ||
673 | The cache directory should be created via mkdir -p instead of | |
674 | mkdir. This makes sure all parent directories are created. | |
675 | ||
676 | Also, we now display an error message explaining that we were unable to | |
677 | create the cache directory if creation fails. | |
678 | ||
679 | commit de7d184909d561b68b411325d32471c047549bca | |
680 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
681 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
682 | ||
683 | savecache: fix check for $RC_LIBEXECDIR writability | |
684 | ||
685 | We were originally checking to see if $RC_LIBEXECDIR/cache was writable. For | |
686 | a new install, this check will fail since this path does not exist. This | |
687 | is also incorrect because later we create $RC_LIBEXECDIR/cache. | |
688 | ||
689 | The correct check is checkpath -W $RC_LIBEXECDIR, and this fixes the | |
690 | issue. | |
691 | ||
692 | X-Gentoo-Bug: 544632 | |
693 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=544632 | |
694 | ||
695 | commit 15ab3f39c69ff8d69fd08a9cde7495a04b4dec9e | |
696 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
697 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
698 | ||
699 | cgroups: use printf to write to cgroup files | |
700 | ||
701 | This fixes #33. | |
702 | ||
703 | commit ee1768a419122d288256cce1723d4997bd965eab | |
704 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
705 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
706 | ||
707 | Add binfmt service to sysinit runlevel | |
708 | ||
709 | This makes binfmt processing behave like tmpfiles processing which | |
710 | follows the same specification as systemd. | |
711 | ||
712 | This fixes #48. | |
713 | ||
714 | X-Gentoo-Bug: 545162 | |
715 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=545162 | |
716 | ||
717 | commit 95ed0665393c353dbc24afb8c63c615402136f5d | |
718 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
719 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
720 | ||
721 | procfs: do not force loading of usbcore module | |
722 | ||
723 | It appears that the only reason we were force loading the usbcore | |
724 | module was to facilitate mounting usbfs. Since we no longer mount | |
725 | usbfs, this is no longer necessary. | |
726 | ||
727 | X-Gentoo-Bug: 480312 | |
728 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=480312 | |
729 | ||
730 | commit 4c5132421f37bd6831eab1f9527a197340f2e9ae | |
731 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
732 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
733 | ||
734 | procfs: remove usbfs and usbdevfs support | |
735 | ||
736 | The usbfs and usbdevfs file systems have been deprecated since | |
737 | Linux-2.6.32, so we remove the code to automount them. | |
738 | ||
739 | X-Gentoo-Bug: 480312 | |
740 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=480312 | |
741 | ||
742 | commit 6d81d3be1bcba81a68086f2a17561d13e1f844e6 | |
743 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
744 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
745 | ||
746 | procfs: do not test for the existence of /proc/filesystems | |
747 | ||
748 | The test for the existence of /proc/filesystems is redundant since we | |
749 | always return success. | |
750 | ||
751 | commit 8d307a6fadd516f26d9c72016119277a7a5c1946 | |
752 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
753 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
754 | ||
755 | procfs: remove redundant check for OpenVZ | |
756 | ||
757 | The check for OpenVZ is not necessary since the procfs service already | |
758 | will not run on OpenVZ due to the keywords setting. | |
759 | ||
760 | commit 62addf118067dd2cd57c3f5fee35c9e80f9fec42 | |
761 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
762 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
763 | ||
764 | Move SELinux mount to sysfs service | |
765 | ||
766 | The selinux file system is mounted under /sys, so move the code for it | |
767 | to the appropriate service. | |
768 | ||
769 | X-Gentoo-Bug: 546290 | |
770 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=546290 | |
771 | ||
772 | commit 1eab656ca1d3258ff00495710a68ad459ce50d3e | |
773 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
774 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
775 | ||
776 | Fix tmpfiles processing | |
777 | ||
778 | Tmpfiles.d processing had /run overriding /usr/lib and /etc, but this is | |
779 | not correct. The correct order, from lowest to highest, for tmpfiles | |
780 | processing is: | |
781 | ||
782 | * /usr/lib/tmpfiles.d/*.conf | |
783 | * /run/tmpfiles.d/*.conf | |
784 | * /etc/tmpfiles.d | |
785 | ||
786 | This means /run/tmpfiles.d/*.conf can override /etc/tmpfiles.d/*.conf, | |
787 | but /etc/tmpfiles.d/*.conf can override both of them. | |
788 | ||
789 | This fixes #49. | |
790 | ||
791 | commit 731a3affdce31e2971a84cde11df2d122049ec99 | |
792 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
793 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
794 | ||
795 | Fix script execution in the local service | |
796 | ||
797 | The local service should use eval when it executes scripts since it has | |
798 | the redirection set up in a variable. | |
799 | ||
800 | This fixes #50. | |
801 | X-Gentoo-Bug: 545012 | |
802 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=545012 | |
803 | ||
804 | commit 3e9bb3b021620654f99a0ead71ed73d34b5c6826 | |
805 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
806 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
807 | ||
808 | Make sysctl on Linux respect rc_verbose setting | |
809 | ||
810 | We do not need to spam the console with variable settings by default. | |
811 | This fixes #51. | |
812 | ||
813 | X-Gentoo-Bug: 541922 | |
814 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=541922 | |
815 | ||
816 | commit c068762c4cf49e7ea9719dcab2e5f7d4c4e7e2e5 | |
817 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
818 | Commit: Doug Freed <dwfreed@mtu.edu> | |
819 | ||
820 | Fix rc_verbose processing | |
821 | ||
822 | We were processing the rc_verbose setting before we sourced the | |
823 | configuration file where it was set; this fixes the issue. | |
824 | ||
825 | Fixes #46 | |
826 | ||
827 | commit b8ab99b5d3ee1a93f215157c36fb120857afde64 | |
828 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
829 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
830 | ||
831 | checkpath: Remove the last HAVE_SELINUX test | |
832 | ||
833 | commit a4cf61e8bf827dc405a547c314e840dab11fc979 | |
834 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
835 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
836 | ||
837 | selinux: unconditionally include the header and provide stub methods | |
838 | ||
839 | If selinux is disabled, then stub methods will be provided instead of | |
840 | calling the real methods. This removes some warnings about unused | |
841 | parameters which used to be covered up with #ifdef HAVE_SELINUX. | |
842 | ||
843 | Signed-off-by: Jason Zaman <jason@perfinion.com> | |
844 | ||
845 | commit d38cc8f2210e839c4935208917138e4809ece758 | |
846 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
847 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
848 | ||
849 | checkpath: fix warning about selinux_on being unused | |
850 | ||
851 | commit f085ae400c60289f61d99e9e80ce037beedf38b4 | |
852 | Author: Doug Freed <dwfreed@mtu.edu> | |
853 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
854 | ||
855 | Fix some compiler warnings | |
856 | ||
857 | librc: Fix C90 warning (mixed declaration and code) | |
858 | rc: Fix warning about discarding const qualifier | |
859 | ||
860 | Fixes #45. | |
861 | ||
862 | commit c1faafcad8197a821282b8e56a10132e27eb5d9f | |
863 | Author: Will Miles <wmiles@sgl.com> | |
864 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
865 | ||
866 | start-stop-daemon: Fix regression for --test | |
867 | ||
868 | The previous fix to --test (PR #34) prevented reading one too many | |
869 | arguments when --exec -or --name was not specified, but created a | |
870 | regression where the last argument would not print if either of those | |
871 | arguments was specified. This corrects the issue. | |
872 | ||
873 | Fixes #41. | |
874 | ||
875 | commit de93587affb17675e6f7cab2b85613d61e11b98b | |
876 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
877 | Commit: Doug Freed <dwfreed@mtu.edu> | |
878 | ||
879 | Silence warning about _DEFAULT_SOURCE for Linux/glibc | |
880 | ||
881 | In >=glibc-2.20, the _BSD_SOURCE macro is deprecated in favor of | |
882 | _DEFAULT_SOURCE. This adds -D_DEFAULT_SOURCE to CPPFLAGS on Linux. | |
883 | ||
884 | Fixes #44 | |
885 | ||
886 | commit be497229b64613ebfbc4073985107a275d49f78e | |
887 | Author: Anthony Donnelly <Amzo@archbsd.com> | |
888 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
889 | ||
890 | Fix savecore service on FreeBSD | |
891 | ||
892 | savecore -C only needs the dumpdevice otherwise it causes an error on startup. | |
893 | ||
894 | This fixes #40. | |
895 | ||
896 | commit e16b7183e90090ecee539697508582d208859a8b | |
897 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
898 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
899 | ||
900 | mk/os-GNU.mk: fix typo | |
901 | ||
902 | MAX_PATH should have been PATH_MAX | |
903 | ||
904 | commit ccd83a5e9cc24833e1ab098cac1688f69ab6e9b6 | |
905 | Author: Will Miles <wmiles@sgl.com> | |
906 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
907 | ||
908 | savecache: Make sure cache directory exists before running checkpath | |
909 | ||
910 | checkpath -W can fail if the specified path doesn't actually exist yet. | |
911 | In this case savecache script should attempt to create the path if it is | |
912 | missing, however it is pre-empted by the checkpath call. This patch adds | |
913 | an explicit existence test before executing checkpath. | |
914 | ||
915 | This fixes #36. | |
916 | ||
917 | commit 7bbb73574b44972b0c1b364e24f71623068d7a1c | |
918 | Author: Robin H. Johnson <robbat2@gentoo.org> | |
919 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
920 | ||
921 | bootmisc: clean_run safety improvements. | |
922 | ||
923 | If /tmp or / are read-only, the clean_run function can fail in some very | |
924 | bad ways. | |
925 | ||
926 | 1. dir=$(mktemp -d) returns an EMPTY string on error. | |
927 | 2. "mount -o bind / $dir", and don't check the result of that, | |
928 | 3. "rm -rf $dir/run/*", which removes the REAL /run contents | |
929 | 4. box gets very weird from this point forward | |
930 | ||
931 | Signed-Off-By: Robin H. Johnson <robbat2@gentoo.org> | |
932 | Signed-Off-By: Chip Parker <infowolfe@gmail.com> | |
933 | Reported-by: Chip Parker <infowolfe@gmail.com> | |
934 | Tested-by: Chip Parker <infowolfe@gmail.com> | |
935 | ||
936 | commit a0378f38713e630e1af9101c2ece5d27ca2130fe | |
937 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
938 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
939 | ||
940 | checkpath: do not chown or chmod symbolic links | |
941 | ||
942 | This is another security fix. If you use chown() or chmod() on a | |
943 | symbolic link, it affects the referenced file, not the symbolic link | |
944 | itself. | |
945 | ||
946 | X-Gentoo-Bug: 540006 | |
947 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=540006 | |
948 | ||
949 | commit 423f82bae9f91f1f5a27d30a2542d8884c6f757a | |
950 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
951 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
952 | ||
953 | ChangeLog: show authors and committers | |
954 | ||
955 | commit 9dfb85d5d236dd126d13d039eb02a97aa0e6c8ac | |
956 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
957 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
958 | ||
959 | local: fix redirections | |
960 | ||
961 | The local service now redirects stdout and stderr for the scripts it | |
962 | runs to /dev/null unless it is run in verbose mode. | |
963 | ||
964 | X-Gentoo-Bug: 537444 | |
965 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=537444 | |
966 | ||
967 | commit 6781667641580fef852ccffc2f42d060f791b354 | |
968 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
969 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
970 | ||
971 | typo fix | |
972 | ||
973 | commit b17af3c85fc94ecc12857146ba2133a3782ead52 | |
974 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
975 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
976 | ||
977 | checkpath: security fix for -m and -o options | |
978 | ||
979 | Do not change permissions on the target if it is a file and has multiple | |
980 | hard links. This is necessary because a hard link can be an attack | |
981 | vector to gain privilege escalation. | |
982 | ||
983 | X-Gentoo-Bug: 540006 | |
984 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=540006 | |
985 | ||
986 | commit 3100114bc104741145fb6c1d4b1664759114cc5c | |
987 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
988 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
989 | ||
990 | Add nfsclient to netmount use dependencies | |
991 | ||
992 | X-Gentoo-Bug: 537996 | |
993 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=537996 | |
994 | ||
995 | commit 3f80f22e22ec16ed517397fd303c3df99f9340fc | |
996 | Author: Will Miles <wmiles@sgl.com> | |
997 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
998 | ||
999 | Prioritize local includes and libraries | |
1000 | ||
1001 | This fixes #35. | |
1002 | ||
1003 | commit 8250ac94dfc6156075081e0e2d0986cb51b3098d | |
1004 | Author: Consus <consus@gmx.com> | |
1005 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1006 | ||
1007 | tmpfiles.*: Follow OpenRC's message style | |
1008 | ||
1009 | Just to be consistent. | |
1010 | ||
1011 | commit fbdd669ba7c5d1a67129236b4ffcd76198340a1b | |
1012 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
1013 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1014 | ||
1015 | Makefile: add variable for path to source tree | |
1016 | ||
1017 | Add a new variable, ${TOP}, to the top level makefile, which points to | |
1018 | the path of the source tree. | |
1019 | ||
1020 | commit cddb4aad08615420320f75050042d946b18d2bb5 | |
1021 | Author: Will Miles <wmiles@sgl.com> | |
1022 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1023 | ||
1024 | Fix off-by-one error in --test argument printout in start-stop-daemon. | |
1025 | ||
1026 | Fixes #34. | |
1027 | ||
1028 | commit 3c5dc0ec7774a72e243da43ac5180ea36a311ad8 | |
1029 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
1030 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1031 | ||
1032 | tmpfiles.dev: pass --boot to tmpfiles.sh so kmod works properly | |
1033 | ||
1034 | commit 7e3a33c8f5ccae03e035cf4c9d1c3c01a0f57b1e | |
1035 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
1036 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1037 | ||
1038 | Add description for cgroup_cleanup | |
1039 | ||
1040 | X-Gentoo-Bug: 535184 | |
1041 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=535184 | |
1042 | ||
1043 | commit 74478830a8d035c078e986b57efd40a5c48bc896 | |
1044 | Author: Doug Freed <dwfreed@mtu.edu> | |
1045 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1046 | ||
1047 | fix double free of pidfile | |
1048 | ||
1049 | This fixes a double free of the pidfile variable. For discussion of this | |
1050 | issue, see the bug. | |
1051 | ||
1052 | X-Gentoo-Bug: 531600 | |
1053 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=531600 | |
1054 | ||
1055 | commit 6a9679377f4de257f02de1d16a513df14b4c25ba | |
1056 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
1057 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1058 | ||
1059 | Do not call the shell to evaluate CHANGELOG_LIMIT | |
1060 | ||
1061 | The git log command understands dates such as "1 year ago", so there is | |
1062 | no need to use the date command. | |
1063 | ||
1064 | commit 72186ea3bbbf0b09b88a6f3e1fb23bf04ce1ddad | |
1065 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
1066 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1067 | ||
1068 | etc/rc and etc/rc.shutdown: change references from rc to openrc | |
1069 | ||
1070 | commit 3647db7a27f7a5ca14b33b14effeb945fd986210 | |
1071 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
1072 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1073 | ||
1074 | Add target to create ChangeLog | |
1075 | ||
1076 | This was added by request because some users are requesting a ChangeLog. | |
1077 | ||
1078 | This fixes #29. | |
1079 | ||
1080 | commit 7a92eb888794819a339babd0ee220b6aa3993db1 | |
1081 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
1082 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1083 | ||
1084 | rename git.mk to gitver.mk | |
1085 | ||
1086 | This is a more descriptive name since this file only sets the gitver | |
1087 | variable. | |
1088 | ||
1089 | commit 30cc3cdb76a66c7c0f89a52db4e5cff77b570e31 | |
1090 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
1091 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1092 | ||
1093 | Make sysfs behave like netmount and localmount | |
1094 | ||
1095 | sysfs now mounts all related sysfs file systems and returns success, | |
1096 | like netmount and localmount. | |
1097 | ||
1098 | Also, we now check to make sure the cgroups are not mounted before we | |
1099 | mount them. | |
1100 | ||
1101 | X-Gentoo-Bug: 530138 | |
1102 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=530138 | |
1103 | ||
1104 | commit dff6e4a004afeaa64f4ccb07c7d31bb821b043b4 | |
1105 | Author: S. Gilles <sgilles@umd.edu> | |
1106 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1107 | ||
1108 | Fix mdoc warning for empty line in rc-update man page. | |
1109 | ||
1110 | X-Gentoo-Bug: 529374 | |
1111 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=529374 | |
1112 | ||
1113 | commit 3fad31a994f7eb14f3f001f3980eb2b0ae8fe4f1 | |
1114 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
1115 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1116 | ||
1117 | init.d: add osclock to ignore patterns | |
1118 | ||
1119 | commit 8d0ca13fbd38e782bae655eca6646dabc8d63899 | |
1120 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
1121 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1122 | ||
1123 | devfs: optionally add missing symbolic links | |
1124 | ||
1125 | If symbolic links for /dev/{fd,stdin,stdout,stderr,core} do not exist | |
1126 | once /dev is mounted, we should create them. | |
1127 | ||
1128 | commit 93ba67eff9333e434c969bb8131467f777546764 | |
1129 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
1130 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1131 | ||
1132 | netmount: unmount nfs file systems | |
1133 | ||
1134 | commit 1932360adca3f9fe9b47bcfad7b8bd5efbd33bee | |
1135 | Author: Jason Zaman <jason@perfinion.com> | |
1136 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1137 | ||
1138 | Integrate the functionality from runscript_selinux.so | |
1139 | ||
1140 | runscript used to dlopen() runscript_selinux.so. This adds equivalent | |
1141 | functionality directly in to runscript instead. It authenticates with | |
1142 | either PAM or shadow and optionally has a dep on audit. | |
1143 | ||
1144 | X-Gentoo-Bug: 517450 | |
1145 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=517450 | |
1146 | ||
1147 | commit be952bebb3647069fb93b9791ee3439698f697ca | |
1148 | Author: Alexander Vershilov <alexander.vershilov@gmail.com> | |
1149 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1150 | ||
1151 | Fix incorrect handling of chroot option. | |
1152 | Fixes #28. | |
1153 | ||
1154 | X-Gentoo-Bug: #527370 | |
1155 | X-Gentoo-Bug-Url: https://bugs.gentoo.org/show_bug.cgi?id=527370 | |
1156 | ||
1157 | commit 0bfde472d0154f14ea88c0f5ddd21a510443d713 | |
1158 | Author: Ralph Sennhauser <sera@gentoo.org> | |
1159 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1160 | ||
1161 | Add osclock service | |
1162 | ||
1163 | This scripts sole purpose is to "provide clock" on OSs that already | |
1164 | take care of the clock being properly set. | |
1165 | ||
1166 | commit ba0a11fc94d303e208dd364b06c1c2a75bcdd62b | |
1167 | Author: Johan Bergström <bugs@bergstroem.nu> | |
1168 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1169 | ||
1170 | Pass ncurses cflags to build | |
1171 | ||
1172 | Fixes #25 | |
1173 | Note from William Hubbs: | |
1174 | The original patch overwrote CFLAGS. I modified this patch to add the | |
1175 | ncurses cflags to CPPFLAGS instead of overwriting CFLAGS. | |
1176 | ||
1177 | commit 7700e6fe796cabfa22eefddc024d66257a28d4dc | |
1178 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
1179 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1180 | ||
1181 | Fix compile errors created by bundling queue.h | |
1182 | ||
1183 | commit 6ca79042b9aa9752e577346e6f355356ef8f2f9a | |
1184 | Author: Anthony G. Basile <blueness@gentoo.org> | |
1185 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1186 | ||
1187 | helpers.h, start-stop-daemon.c: remove uneeded macros | |
1188 | ||
1189 | TAILQ_CONCAT, TAILQ_FOREACH_SAFE and LIST_FOREACH_SAFE are defined | |
1190 | in our bundled queue.h and are no longer required. | |
1191 | ||
1192 | commit 1e0a4bebdefd06af09ba8f2459287d3ca28f89d7 | |
1193 | Author: Anthony G. Basile <blueness@gentoo.org> | |
1194 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1195 | ||
1196 | Bundle <sys/queue.h> from NetBSD | |
1197 | ||
1198 | We are bundling this to allow building on musl-based systems since musl | |
1199 | does not include <sys/queue.h>. | |
1200 | ||
1201 | commit ca6b86be44fc7ed618a7ab3bd021e208d38878b1 | |
1202 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
1203 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1204 | ||
1205 | Fix all tests for GNU/kFreeBSD | |
1206 | ||
1207 | It is necessary to check for both the kernel and c library because | |
1208 | __FreeBSD_kernel is also defined on native FreeBSD [1]. | |
1209 | ||
1210 | [1] http://sourceforge.net/p/predef/wiki/OperatingSystems/ | |
1211 | ||
1212 | commit 4ac289b5397a688393c596a9a01651c94d3b5711 | |
1213 | Author: Gabriele Giacone <1o5g4r8o@gmail.com> | |
1214 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1215 | ||
1216 | Fix rc_svcdir for GNU/Hurd | |
1217 | ||
1218 | commit 875f03e27c3475675f7b9572b071dd8c26257be7 | |
1219 | Author: Svante Signell <svante.signell@gmail.com> | |
1220 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1221 | ||
1222 | fix defines for GNU/Hurd | |
1223 | ||
1224 | commit 203b754f843fe6af0a40e983d557a9cdbc89f84b | |
1225 | Author: Svante Signell <svante.signell@gmail.com> | |
1226 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1227 | ||
1228 | add missing files for GNU/Hurd | |
1229 | ||
1230 | commit 89c8a62a1078e770e12c47f06c8dbc9c2924e771 | |
1231 | Author: Gabriele Giacone <1o5g4r8o@gmail.com> | |
1232 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1233 | ||
1234 | Fix rc_svcdir for GNU/kFreeBSD | |
1235 | ||
1236 | commit d8e1d9a6edf94ecac580e80e1113f4fdbdc5a23b | |
1237 | Author: Gabriele Giacone <1o5g4r8o@gmail.com> | |
1238 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1239 | ||
1240 | Add missing files for GNU/kFreeBSD | |
1241 | ||
1242 | commit 3f82edbeb9251149c6aff071d6537379af4e5eea | |
1243 | Author: Svante Signell <svante.signell@gmail.com> | |
1244 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1245 | ||
1246 | Fix GNU/kFreeBSD port | |
1247 | ||
1248 | Check for __FreeBSD_kernel instead of __GLIBC__ in source files. | |
1249 | ||
1250 | note from William Hubbs: | |
1251 | I was told this is a better check for GNU/kFreeBSD than checking the | |
1252 | C library the source is being compiled against. | |
1253 | GNU/kFreeBSD than checking which library we are using. | |
1254 | ||
1255 | commit 86e9aa0d36813e2630c6613cd71c3ce8db642f71 | |
1256 | Author: Anthony G. Basile <blueness@gentoo.org> | |
1257 | Commit: Anthony G. Basile <blueness@gentoo.org> | |
1258 | ||
1259 | einfo.h, rc.h.in: simplify __BEGIN_DECLS logic | |
1260 | ||
1261 | There is no need to redefine __BEGIN_DECLS and __END_DECLS. | |
1262 | We simplify the logic here and avoid undefining these macros. | |
1263 | ||
1264 | commit 4a08517cac3c68c232694db7288654b58b68b8ba | |
1265 | Author: Anthony G. Basile <blueness@gentoo.org> | |
1266 | Commit: Anthony G. Basile <blueness@gentoo.org> | |
1267 | ||
1268 | einfo.h, rc.h.in: ensure __BEGIN_DECLS is defined | |
1269 | ||
1270 | Some Standard C Libraries, like musl, don't define __BEGIN_DECLS | |
1271 | or __END_DECLS. We add some ifdef magic to ensure these are | |
1272 | available. | |
1273 | ||
1274 | commit 9bf789f78890c8b5879d29acb9fb0e23285baee4 | |
1275 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
1276 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1277 | ||
1278 | Update news file wrt chroot variable | |
1279 | ||
1280 | commit f9acd65497c6e561fbf5420386a99d681fede859 | |
1281 | Author: Alexander Vershilov <alexander.vershilov@gmail.com> | |
1282 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1283 | ||
1284 | librc:look for the pid file in a chroot if defined | |
1285 | ||
1286 | X-Gentoo-Bug: 524388 | |
1287 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=524388 | |
1288 | ||
1289 | commit 8c7ea4e9e8da500877a514402bbe90aababda2d6 | |
1290 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
1291 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1292 | ||
1293 | runscript.sh: add chroot support | |
1294 | ||
1295 | This adds support for a chroot variable which will be passed to the | |
1296 | start-stop-daemon --chroot switch to runscript.sh when starting a | |
1297 | daemon. This also needs to be saved so it can be used in locating the | |
1298 | pid file when stopping the daemon. | |
1299 | ||
1300 | X-Gentoo-Bug: 524388 | |
1301 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=524388 | |
1302 | ||
1303 | commit 5f1439f1aac14618592789042e05daaf80f55a15 | |
1304 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
1305 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1306 | ||
1307 | Add NEWS file | |
1308 | ||
1309 | commit 85da4a5e2621dc5f5356d440735aa058008a1b7e | |
1310 | Author: William Hubbs <w.d.hubbs@gmail.com> | |
1311 | Commit: William Hubbs <w.d.hubbs@gmail.com> | |
1312 | ||
1313 | add back nfs and nfs4 file systems | |
1314 | ||
1315 | Fix gentoo bug #427996 correctly. | |
1316 | We should attempt to mount the file systems, but not try to start the | |
1317 | daemons. The previous fix removed mounting the file systems as well as | |
1318 | starting the daemons. | |
1319 | ||
1320 | X-Gentoo-Bug: 508574 | |
1321 | X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=508574 |
0 | The following is a list of files and features that are going to be removed in | |
1 | the source tree. Every entry should contain what exactly is going away, why it | |
2 | is happening, and who is going to be doing the work. When the feature is | |
3 | removed, it should also be removed from this file. | |
4 | ||
5 | --------------------------- | |
6 | ||
7 | What: Service pause action | |
8 | ||
9 | When: 1.0 | |
10 | ||
11 | Why: ... | |
12 | ||
13 | Who: | |
14 | ||
15 | --------------------------- | |
16 | ||
17 | What: start-stop-daemon options --startas, --chuid , --oknodo | |
18 | ||
19 | When: 1.0 | |
20 | ||
21 | Why: Obsolete or replaced by other options. | |
22 | --startas => use --name or --exec | |
23 | --chuid => use --user | |
24 | --oknodo => ignore return code instead | |
25 | ||
26 | Who: | |
27 | ||
28 | --------------------------- | |
29 | ||
30 | What: runscript and rc symbolic links | |
31 | ||
32 | When: 1.0 | |
33 | ||
34 | Why: Deprecated in favor of openrc-run and openrc due to naming | |
35 | conflicts with other software. | |
36 | ||
37 | Who: | |
38 | ||
39 | --------------------------- | |
40 | ||
41 | What: support for the opts variable in service scripts | |
42 | ||
43 | When: 1.0 | |
44 | ||
45 | Why: Depprecated in favor of extra_commands, extra_started_commands | |
46 | and extra_stopped_commands. | |
47 | ||
48 | Who: | |
49 | ||
50 | --------------------------- | |
51 | ||
52 | What: support for local_start and local_stop | |
53 | ||
54 | When: 1.0 | |
55 | ||
56 | Why: Depprecated in favor of executable scripts in @SYSCONFDIR@/local.d | |
57 | ||
58 | Who: | |
59 | ||
60 | --------------------------- | |
61 | ||
62 | What: the mtab service script | |
63 | ||
64 | When: make warnings more visible in 1.0, remove in 2.0 | |
65 | ||
66 | Why: /etc/mtab should be a symbolic link to /proc/self/mounts on modern | |
67 | Linux systems | |
68 | ||
69 | Who: | |
70 | ||
71 | --------------------------- |
0 | # Features Scheduled for Removal | |
1 | ||
2 | The following is a list of files and features that are going to be removed in | |
3 | the source tree. Every entry should contain what exactly is going away, why it | |
4 | is happening, and who is going to be doing the work. When the feature is | |
5 | removed, it should also be removed from this file. | |
6 | ||
7 | ## Service pause action | |
8 | ||
9 | When: 1.0 | |
10 | ||
11 | Why: The same affect can be obtained with the --nodeps option to stop. | |
12 | ||
13 | Who: | |
14 | ||
15 | ## start-stop-daemon options --startas, --chuid , --oknodo | |
16 | ||
17 | When: 1.0 | |
18 | ||
19 | Why: Obsolete or replaced by other options. | |
20 | ||
21 | * --startas => use --name or --exec | |
22 | * --chuid => use --user | |
23 | * --oknodo => ignore return code instead | |
24 | ||
25 | Who: | |
26 | ||
27 | ## runscript and rc symbolic links | |
28 | ||
29 | When: 1.0 | |
30 | ||
31 | Why: Deprecated in favor of openrc-run and openrc due to naming | |
32 | conflicts with other software. | |
33 | ||
34 | Who: | |
35 | ||
36 | ## support for the opts variable in service scripts | |
37 | ||
38 | When: 1.0 | |
39 | ||
40 | Why: Depprecated in favor of extra_commands, extra_started_commands | |
41 | and extra_stopped_commands. | |
42 | ||
43 | Who: | |
44 | ||
45 | ## support for local_start and local_stop | |
46 | ||
47 | When: 1.0 | |
48 | ||
49 | Why: Depprecated in favor of executable scripts in @SYSCONFDIR@/local.d | |
50 | ||
51 | Who: | |
52 | ||
53 | ## the mtab service script | |
54 | ||
55 | When: make warnings more visible in 1.0, remove in 2.0 | |
56 | ||
57 | Why: /etc/mtab should be a symbolic link to /proc/self/mounts on modern | |
58 | Linux systems | |
59 | ||
60 | Who: |
0 | # OpenRC History | |
1 | ||
2 | This history of OpenRC was written by Daniel Robbins, Roy Marples, William | |
3 | Hubbs and others. | |
4 | ||
5 | The Gentoo modular init scripts were developed by Daniel Robbins for Gentoo | |
6 | Linux 1.0_rc6 during most of 2001 and released in September 2001. After their | |
7 | development, the dependency-based init script system was maintained by a | |
8 | number of senior developers, starting with Azarah (Martin Schlemmer), with | |
9 | migration to the new init system assisted by Woodchip (Donnie Davies) who | |
10 | converted all ebuild init scripts to work with the new system. As Grant | |
11 | Goodyear notes: | |
12 | ||
13 | "My recollection is that one of woodchip's more impressive early feats | |
14 | was the complete replacement of all of the init scripts in Portage | |
15 | for Gentoo Linux 1.0_rc6. Through 1.0_rc5 Gentoo had used fairly | |
16 | standard rc scripts modified from Stampede Linux, but for 1.0_rc6 Daniel | |
17 | Robbins (drobbins) and Martin Schlemmer (azarah) had created a new | |
18 | dependency-based init script system that is still used today. Within a | |
19 | span of days Donny rewrote every single init script in the Portage tree | |
20 | and committed new masked packages to await the release of 1.0_rc6. Thanks to | |
21 | woodchip (and drobbins and azarah, of course) the | |
22 | transition to the new init scripts was nearly painless." [1] | |
23 | ||
24 | Roy Marples became a Gentoo/Linux developer in 2004 and wrote the modular | |
25 | network scripts for the Gentoo baselayout package. Towards the end of 2005, | |
26 | he became the primary maintainer for baselayout and the init scripts. | |
27 | ||
28 | At the start of 2007, He announced the ongoing development of | |
29 | baselayout-2, containing a rewritten core coded in C and allowing POSIX sh | |
30 | init scripts instead of forcing the use of bash. By mid 2007, He had | |
31 | re-implemented the Gentoo init script design created by Daniel Robbins, | |
32 | using an entirely new code base. Alpha and pre-release baselayout-2 | |
33 | snapshots were added to Gentoo's Portage tree as an optional component. | |
34 | ||
35 | Toward the end of 2007, Roy retired as a Gentoo developer. | |
36 | Baselayout-2 was still in the pre stage, and aside from the gentoo-fbsd | |
37 | users, it was masked. However, He desired to keep the baselayout-2 | |
38 | project moving forward as an independent project. The Gentoo Council | |
39 | permitted Him to release OpenRC under the 2-clause BSD license, | |
40 | managed by him as an external project. | |
41 | ||
42 | Around mid-2010, Roy decided to no longer maintain OpenRC. At this | |
43 | point, he transferred development back to Gentoo. | |
44 | ||
45 | William Hubbs, and several other Gentoo developers, started working on | |
46 | OpenRC around this point and brought OpenRC-0.8.x to Gentoo Linux's stable | |
47 | tree in 2011. | |
48 | ||
49 | In 2013 the OpenRC team became independent from Gentoo again and moved primary | |
50 | development to github. | |
51 | ||
52 | Daniel Robbins continues to maintain an independent, forked | |
53 | version of OpenRC for Funtoo Linux, which includes a Funtoo-specific network | |
54 | configuration system. | |
55 | ||
56 | [1] http://www.gentoo.org/news/en/gwn/20040426-newsletter.xml |
1 | 1 | # Copyright (c) 2007-2009 Roy Marples <roy@marples.name> |
2 | 2 | # Released under the 2-clause BSD license. |
3 | 3 | |
4 | include Makefile.inc | |
4 | TOP:= ${dir ${realpath ${firstword ${MAKEFILE_LIST}}}} | |
5 | MK= ${TOP}/mk | |
6 | ||
7 | include ${TOP}/Makefile.inc | |
5 | 8 | |
6 | 9 | SUBDIR= conf.d etc init.d local.d man scripts sh src sysctl.d |
7 | 10 | |
16 | 19 | |
17 | 20 | INSTALLAFTER= _installafter |
18 | 21 | |
19 | MK= mk | |
20 | 22 | include ${MK}/sys.mk |
21 | 23 | include ${MK}/os.mk |
22 | 24 | include ${MK}/subdir.mk |
23 | 25 | include ${MK}/dist.mk |
24 | include ${MK}/git.mk | |
26 | include ${MK}/gitver.mk | |
25 | 27 | |
26 | 28 | _installafter: |
27 | 29 | ifeq (${MKPREFIX},yes) |
0 | # OpenRC NEWS | |
1 | ||
2 | This file will contain a list of notable changes for each release. Note | |
3 | the information in this file is in reverse order. | |
4 | ||
5 | ## OpenRC-0.18.3 | |
6 | ||
7 | Modern Linux systems expect /etc/mtab to be a symbolic link to | |
8 | /proc/self/mounts. Reasons for this change include support for mount | |
9 | namespaces, which will not work if /etc/mtab is a file. | |
10 | By default, the mtab service enforces this on each reboot. | |
11 | ||
12 | If you find that this breaks your system in some way, please do the | |
13 | following: | |
14 | ||
15 | - Set mtab_is_file=yes in /etc/conf.d/mtab. | |
16 | ||
17 | - Restart mtab. This will recreate the /etc/mtab file. | |
18 | ||
19 | - Check for an issue on https://github.com/openrc/openrc/issues | |
20 | explaining why you need /etc/mtab to be a file. If there isn't one, | |
21 | please open one and explain in detail why you need this to be a file. | |
22 | If there is one, please add your comments to it. Please give concrete | |
23 | examples of why it is important that /etc/mtab be a file instead of a | |
24 | symbolic link. Those comments will be taken into consideration for how | |
25 | long to keep supporting mtab as a file or when the support can be | |
26 | removed. | |
27 | ||
28 | ## OpenRC-0.18 | |
29 | ||
30 | The behaviour of localmount and netmount in this version is changing. In | |
31 | the past, these services always started successfully. In this version, | |
32 | they will be able to fail if file systems they mount fail to mount. If | |
33 | you have file systems listed in fstab which should not be mounted at | |
34 | boot time, make sure to add noauto to the mount options. If you have | |
35 | file systems that you want to attempt to mount at boot time but failure | |
36 | should be allowed, add nofail to the mount options for these file | |
37 | systems in fstab. | |
38 | ||
39 | ## OpenRC-0.14 | |
40 | ||
41 | The binfmt service, which registers misc binary formats with the Linux | |
42 | kernel, has been separated from the procfs service. This service will be | |
43 | automatically added to the boot runlevel for new Linux installs. When | |
44 | you upgrade, you will need to use rc-update to add it to your boot | |
45 | runlevel. | |
46 | ||
47 | The procfs service no longer automounts the deprecated usbfs and | |
48 | usbdevfs file systems. Nothing should be using usbdevfs any longer, and | |
49 | if you still need usbfs it can be added to fstab. | |
50 | ||
51 | Related to the above change, the procfs service no longer attempts to | |
52 | modprobe the usbcore module. If your device manager does not load it, | |
53 | you will need to configure the modules service to do so. | |
54 | ||
55 | The override order of binfmt.d and tmpfiles.d directories has been | |
56 | changed to match systemd. Files in /run/binfmt.d and /run/tmpfiles.d | |
57 | override their /usr/lib counterparts, and files in the /etc counterparts | |
58 | override both /usr/lib and /run. | |
59 | ||
60 | ## OpenRC-0.13.2 | |
61 | ||
62 | A chroot variable has been added to the service script variables. | |
63 | This fixes the support for running a service in a chroot. | |
64 | This is documented in man 8 openrc-run. | |
65 | ||
66 | The netmount service now mounts nfs file systems. | |
67 | This change was made to correct a fix for an earlier bug. | |
68 | ||
69 | ## OpenRC-0.13 | |
70 | ||
71 | /sbin/rc was renamed to /sbin/openrc and /sbin/runscript was renamed to | |
72 | /sbin/openrc-run due to naming conflicts with other software. | |
73 | ||
74 | Backward compatible symbolic links are currently in place so your | |
75 | system will keep working if you are using the old names; however, it is | |
76 | strongly advised that you migrate to the new names because the symbolic | |
77 | links will be removed in the future. | |
78 | Warnings have been added to assist with this migration; however, due to the | |
79 | level of noise they produce, they only appear in verbose mode in this release. | |
80 | ||
81 | The devfs script now handles the initial mounting and setup of the | |
82 | /dev directory. If /dev has already been mounted by the kernel or an | |
83 | initramfs, devfs will remount /dev with the correct mount options | |
84 | instead of mounting a second /dev over the existing mount point. | |
85 | ||
86 | It attempts to mount /dev from fstab first if an entry exists there. If | |
87 | it doesn't it attempts to mount devtmpfs if it is configured in the | |
88 | kernel. If not, it attempts to mount tmpfs. | |
89 | If none of these is available, an error message is displayed and static | |
90 | /dev is assumed. | |
91 | ||
92 | ## OpenRC-0.12 | |
93 | ||
94 | The net.* scripts, originally from Gentoo Linux, have | |
95 | been removed. If you need these scripts, look for a package called | |
96 | netifrc, which is maintained by them. |
0 | OpenRC README | |
1 | ||
2 | ||
3 | Installation | |
4 | ------------ | |
5 | make install | |
6 | Yup, that simple. Works with GNU make. | |
7 | ||
8 | You may wish to tweak the installation with the below arguments | |
9 | PROGLDFLAGS=-static | |
10 | LIBNAME=lib64 | |
11 | DESTDIR=/tmp/openrc-image | |
12 | MKNET=no | |
13 | MKPAM=pam | |
14 | MKPREFIX=yes | |
15 | MKPKGCONFIG=no | |
16 | MKSELINUX=yes | |
17 | MKSTATICLIBS=no | |
18 | MKTERMCAP=ncurses | |
19 | MKTERMCAP=termcap | |
20 | MKTOOLS=yes | |
21 | PKG_PREFIX=/usr/pkg | |
22 | LOCAL_PREFIX=/usr/local | |
23 | PREFIX=/usr/local | |
24 | ||
25 | We don't support building a static OpenRC with PAM. | |
26 | You may need to use PROGLDFLAGS=-Wl,-Bstatic on glibc instead of just -static. | |
27 | If you debug memory under valgrind, add -DDEBUG_MEMORY to your CPPFLAGS | |
28 | so that all malloc memory should be freed at exit. | |
29 | If you are building OpenRC for a Gentoo Prefix installation, add | |
30 | MKPREFIX=yes. | |
31 | ||
32 | You can also brand OpenRC if you so wish like so | |
33 | BRANDING=\"Gentoo/$(uname -s)\" | |
34 | ||
35 | PKG_PREFIX should be set to where packages install to by default. | |
36 | LOCAL_PREFIX should be set when to where user maintained packages are. | |
37 | Only set LOCAL_PREFIX if different from PKG_PREFIX. | |
38 | PREFIX should be set when OpenRC is not installed to /. | |
39 | ||
40 | If any of the following files exist then we do not overwrite them | |
41 | /etc/devd.conf | |
42 | /etc/rc | |
43 | /etc/rc.shutdown | |
44 | /etc/conf.d/* | |
45 | ||
46 | rc and rc.shutdown are the hooks from the BSD init into OpenRC. | |
47 | devd.conf is modified from FreeBSD to call /etc/rc.devd which is a generic | |
48 | hook into OpenRC. | |
49 | inittab is the same, but for SysVInit as used by most Linux distributions. | |
50 | This can be found in the support folder. | |
51 | Obviously, if you're installing this onto a system that does not use OpenRC | |
52 | by default then you may wish to backup the above listed files, remove them | |
53 | and then install so that the OS hooks into OpenRC. | |
54 | ||
55 | init.d.misc is not installed by default as the scripts will need | |
56 | tweaking on a per distro basis. They are also non essential to the operation | |
57 | of the system. | |
58 | ||
59 | As of OpenRC-0.12, the net.* scripts, originally from Gentoo Linux, have | |
60 | been removed. If you need these scripts, look for a package called | |
61 | netifrc, which is maintained by them. | |
62 | ||
63 | As of OpenRC-0.13, two binaries have been renamed due to naming | |
64 | conflicts with other software. The /sbin/rc binary was renamed to | |
65 | /sbin/openrc, and /sbin/runscript was renamed to /sbin/openrc-run. | |
66 | ||
67 | Backward compatible symbolic links are currently in place so your | |
68 | system will keep working if you are using the old names; however, it is | |
69 | strongly advised that you migrate to the new names because the symbolic | |
70 | links will be removed in the future. | |
71 | ||
72 | Warnings have been added to assist with this migration; however, they | |
73 | only show in verbose mode in this release due to the level of noise they | |
74 | produce. | |
75 | ||
76 | Also, the devfs script now handles the initial mounting and setup of the | |
77 | /dev directory. If /dev has already been mounted by the kernel or an | |
78 | initramfs, devfs will remount /dev with the correct mount options | |
79 | instead of mounting a second /dev over the existing mount point. | |
80 | ||
81 | It attempts to mount /dev from fstab first if an entry exists there. If | |
82 | it doesn't it attempts to mount devtmpfs if it is configured in the | |
83 | kernel. If not, it attempts to mount tmpfs. | |
84 | If none of these is available, an error message is displayed and static | |
85 | /dev is assumed. | |
86 | ||
87 | Reporting Bugs | |
88 | -------------- | |
89 | Since Gentoo Linux is hosting OpenRC development, Bugs should go to | |
90 | the Gentoo Bugzilla: | |
91 | http://bugs.gentoo.org/ | |
92 | They should be filed under the "Gentoo Hosted Projects" product and | |
93 | the "openrc" component. |
0 | Using Busybox as your Default Shell | |
1 | ----------------------------------- | |
2 | ||
3 | ||
4 | If you have/bin/sh linked to busybox, you need to be aware of several | |
5 | incompatibilities between busybox's applets and the standalone | |
6 | counterparts. Since it is possible to configure busybox to not include | |
7 | these applets or to prefer the standalone counterparts, OpenRC does not | |
8 | attempt to support the busybox applets. | |
9 | ||
10 | For now, it is recommended that you disable the following busybox | |
11 | configuration settings for best results with OpenRC. | |
12 | ||
13 | CONFIG_START_STOP_DAEMON -- The start-stop-daemon applet is not compatible with | |
14 | start-stop-daemon in OpenRC. | |
15 | ||
16 | CONFIG_MOUNT -- The mount applet does not support the -O [no]_netdev options to | |
17 | skip over or include network file systems when the -a option is present. | |
18 | ||
19 | CONFIG_UMOUNT -- The umount applet does not support the -O option along with -a. | |
20 | ||
21 | CONFIG_SWAPONOFF -- The swapon applet does not support the -e option | |
22 | or recognize the nofail option in fstab. | |
23 | ||
24 | CONFIG_SETFONT -- The setfont applet does not support the -u option from kbd. | |
25 | ||
26 | CONFIG_IP -- The ip applet doesn't support the "scope" modifier for | |
27 | "ip route add" and "ip address add". | |
28 | ||
29 | There is work to get most of these supported by busybox, so this file | |
30 | will be updated as things change. |
0 | This history of OpenRC was written by Daniel Robbins, Roy Marples, William | |
1 | Hubbs and others. | |
2 | ||
3 | The Gentoo modular init scripts were developed by Daniel Robbins for Gentoo | |
4 | Linux 1.0_rc6 during most of 2001 and released in September 2001. After their | |
5 | development, the dependency-based init script system was maintained by a | |
6 | number of senior developers, starting with Azarah (Martin Schlemmer), with | |
7 | migration to the new init system assisted by Woodchip (Donnie Davies) who | |
8 | converted all ebuild init scripts to work with the new system. As Grant | |
9 | Goodyear notes: | |
10 | ||
11 | "My recollection is that one of woodchip's more impressive early feats | |
12 | was the complete replacement of all of the init scripts in Portage | |
13 | for Gentoo Linux 1.0_rc6. Through 1.0_rc5 Gentoo had used fairly | |
14 | standard rc scripts modified from Stampede Linux, but for 1.0_rc6 Daniel | |
15 | Robbins (drobbins) and Martin Schlemmer (azarah) had created a new | |
16 | dependency-based init script system that is still used today. Within a | |
17 | span of days Donny rewrote every single init script in the Portage tree | |
18 | and committed new masked packages to await the release of 1.0_rc6. Thanks to | |
19 | woodchip (and drobbins and azarah, of course) the | |
20 | transition to the new init scripts was nearly painless." [1] | |
21 | ||
22 | Roy Marples became a Gentoo/Linux developer in 2004 and wrote the modular | |
23 | network scripts for the Gentoo baselayout package. Towards the end of 2005, | |
24 | he became the primary maintainer for baselayout and the init scripts. | |
25 | ||
26 | At the start of 2007, He announced the ongoing development of | |
27 | baselayout-2, containing a rewritten core coded in C and allowing POSIX sh | |
28 | init scripts instead of forcing the use of bash. By mid 2007, He had | |
29 | re-implemented the Gentoo init script design created by Daniel Robbins, | |
30 | using an entirely new code base. Alpha and pre-release baselayout-2 | |
31 | snapshots were added to Gentoo's Portage tree as an optional component. | |
32 | ||
33 | Toward the end of 2007, Roy retired as a Gentoo developer. | |
34 | Baselayout-2 was still in the pre stage, and aside from the gentoo-fbsd | |
35 | users, it was masked. However, He desired to keep the baselayout-2 | |
36 | project moving forward as an independent project. The Gentoo Council | |
37 | permitted Him to release OpenRC under the 2-clause BSD license, | |
38 | managed by him as an external project. | |
39 | ||
40 | Around mid-2010, Roy decided to no longer maintain OpenRC. At this | |
41 | point, he transferred development back to Gentoo. | |
42 | ||
43 | William Hubbs, and several other Gentoo developers, started working on | |
44 | OpenRC around this point and brought OpenRC-0.8.x to Gentoo Linux's stable | |
45 | tree in 2011. | |
46 | ||
47 | In 2013 the OpenRC team became independent from Gentoo again and moved primary | |
48 | development to github. | |
49 | ||
50 | Daniel Robbins continues to maintain an independent, forked | |
51 | version of OpenRC for Funtoo Linux, which includes a Funtoo-specific network | |
52 | configuration system. | |
53 | ||
54 | [1] http://www.gentoo.org/news/en/gwn/20040426-newsletter.xml |
0 | # OpenRC README | |
1 | ||
2 | OpenRC is a dependency-based init system that works with the | |
3 | system-provided init program, normally `/sbin/init`. Currently, it does | |
4 | not have an init program of its own. | |
5 | ||
6 | ## Installation | |
7 | ||
8 | OpenRC requires GNU make. | |
9 | ||
10 | Once you have GNU Make installed, the default OpenRC installation can be | |
11 | executed using this command: | |
12 | ||
13 | make install | |
14 | ||
15 | ## Configuration | |
16 | ||
17 | You may wish to configure the installation by passing one or more of the | |
18 | below arguments to the make command | |
19 | ||
20 | ``` | |
21 | PROGLDFLAGS=-static | |
22 | LIBNAME=lib64 | |
23 | DESTDIR=/tmp/openrc-image | |
24 | MKNET=no | |
25 | MKPAM=pam | |
26 | MKPREFIX=yes | |
27 | MKPKGCONFIG=no | |
28 | MKSELINUX=yes | |
29 | MKSTATICLIBS=no | |
30 | MKTERMCAP=ncurses | |
31 | MKTERMCAP=termcap | |
32 | MKTOOLS=yes | |
33 | PKG_PREFIX=/usr/pkg | |
34 | LOCAL_PREFIX=/usr/local | |
35 | PREFIX=/usr/local | |
36 | BRANDING=\"Gentoo/$(uname -s)\" | |
37 | ``` | |
38 | ||
39 | ## Notes | |
40 | ||
41 | We don't support building a static OpenRC with PAM. | |
42 | ||
43 | You may need to use `PROGLDFLAGS=-Wl,-Bstatic` on glibc instead of just `-static`. | |
44 | ||
45 | If you debug memory under valgrind, add `-DDEBUG_MEMORY` | |
46 | to your `CPPFLAGS` so that all malloc memory should be freed at exit. | |
47 | ||
48 | If you are building OpenRC for a Gentoo Prefix installation, add `MKPREFIX=yes`. | |
49 | ||
50 | `PKG_PREFIX` should be set to where packages install to by default. | |
51 | ||
52 | `LOCAL_PREFIX` should be set when to where user maintained packages are. | |
53 | Only set `LOCAL_PREFIX` if different from `PKG_PREFIX`. | |
54 | ||
55 | `PREFIX` should be set when OpenRC is not installed to /. | |
56 | ||
57 | If any of the following files exist then we do not overwrite them | |
58 | ||
59 | ``` | |
60 | /etc/devd.conf | |
61 | /etc/rc | |
62 | /etc/rc.shutdown | |
63 | /etc/conf.d/* | |
64 | ``` | |
65 | ||
66 | `rc` and `rc.shutdown` are the hooks from the BSD init into OpenRC. | |
67 | ||
68 | `devd.conf` is modified from FreeBSD to call `/etc/rc.devd` which is a | |
69 | generic hook into OpenRC. | |
70 | ||
71 | `inittab` is the same, but for SysVInit as used by most Linux distributions. | |
72 | This can be found in the support folder. | |
73 | ||
74 | Obviously, if you're installing this onto a system that does not use | |
75 | OpenRC by default then you may wish to backup the above listed files, | |
76 | remove them and then install so that the OS hooks into OpenRC. | |
77 | ||
78 | `init.d.misc` is not installed by default as the scripts will need | |
79 | tweaking on a per distro basis. They are also non essential to the | |
80 | operation of the system. | |
81 | ||
82 | ## Reporting Bugs | |
83 | ||
84 | If you are using Gentoo Linux, bugs can be filed on their bugzilla under | |
85 | the `gentoo hosted projects` product and the `openrc` component [1]. | |
86 | Otherwise, you can report issues on our github [2]. | |
87 | ||
88 | Better yet, if you can contribute code, please feel free to submit pull | |
89 | requests [3]. | |
90 | ||
91 | ## IRC Channel | |
92 | ||
93 | We have an official irc channel, #openrc on freenode, feel free to join | |
94 | us there. | |
95 | ||
96 | [1] https://bugs.gentoo.org/ | |
97 | [2] https://github.com/openrc/openrc/issues | |
98 | [3] https://github.com/openrc/openrc/pulls |
0 | This is the openrc style manual. It governs the coding style of all code | |
1 | in this repository. Follow it. Contact openrc@gentoo.org for any questions | |
2 | or fixes you might notice. | |
3 | ||
4 | ########## | |
5 | # C CODE # | |
6 | ########## | |
7 | ||
8 | The BSD Kernel Normal Form (KNF) style is used: | |
9 | http://en.wikipedia.org/wiki/Indent_style#BSD_KNF_style | |
10 | Basically, it's like K&R/LKML, but wrapped lines that are indented use 4 spaces. | |
11 | ||
12 | Highlights: | |
13 | - no trailing whitespace | |
14 | - indented code use tabs (not line wrapped) | |
15 | - cuddle the braces (except for functions) | |
16 | - space after native statements and before paren (for/if/while/...) | |
17 | - no space between function and paren | |
18 | - pointer asterisk cuddles the variable, not the type | |
19 | ||
20 | void foo(int c) | |
21 | { | |
22 | int ret = 0; | |
23 | ||
24 | if (c > 1000) | |
25 | return; | |
26 | ||
27 | while (c--) { | |
28 | bar(c); | |
29 | ret++; | |
30 | } | |
31 | ||
32 | return ret; | |
33 | } | |
34 | ||
35 | ################## | |
36 | # COMMIT MESSAGES # | |
37 | ################## | |
38 | ||
39 | The following is an example of a correctly formatted git commit message | |
40 | for this repository. Most of this information came from this blog post | |
41 | [1], so I would like to thank the author. | |
42 | ||
43 | ### cut here ### | |
44 | Capitalized, short (50 chars or less) summary | |
45 | ||
46 | More detailed explanatory text, if necessary. Wrap it to about 72 | |
47 | characters or so. In some contexts, the first line is treated as the | |
48 | subject of an email and the rest of the text as the body. The blank | |
49 | line separating the summary from the body is critical (unless you omit | |
50 | the body entirely); tools like rebase can get confused if you run the | |
51 | two together. | |
52 | ||
53 | Write your commit message in the imperative: "Fix bug" and not "Fixed | |
54 | bug." This convention matches up with commit messages generated by | |
55 | commands like git merge and git revert. | |
56 | ||
57 | Further paragraphs come after blank lines. | |
58 | ||
59 | - Bullet points are okay, too | |
60 | ||
61 | - Typically a hyphen or asterisk is used for the bullet, preceded by a | |
62 | single space, with blank lines in between, but conventions vary here | |
63 | ||
64 | - Use a hanging indent | |
65 | ||
66 | Reported-by: User Name <email> | |
67 | X-[Distro]-Bug: BugID | |
68 | X-[Distro]-Bug-URL: URL for the bug (on the distribution's web site typically) | |
69 | ### cut here ### | |
70 | ||
71 | If you did not write the code and the patch does not include authorship | |
72 | information in a format git can use, please use the --author option of the | |
73 | git commit command to make the authorship correct. | |
74 | ||
75 | The Reported-by tag is required if the person who reported the bug is | |
76 | different from the author and committer. | |
77 | ||
78 | The X-[Distro]-Bug/Bug-URL tags are required if this commit is related | |
79 | to a bug reported to us by a specific distribution of linux or a | |
80 | *BSD. Also, [Distro] should be replaced with the name of the | |
81 | distribution, e.g. X-Gentoo-Bug. | |
82 | ||
83 | [1] http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html | |
84 |
0 | # OpenRC Style Guide | |
1 | ||
2 | This is the openrc style manual. It governs the coding style of all code | |
3 | in this repository. Follow it. Contact openrc@gentoo.org for any questions | |
4 | or fixes you might notice. | |
5 | ||
6 | ## C CODE | |
7 | ||
8 | The BSD Kernel Normal Form (KNF) style is used [1]. Basically, it is like | |
9 | K&R/LKML, but wrapped lines that are indented use 4 spaces. Here are the | |
10 | highlights. | |
11 | ||
12 | - no trailing whitespace | |
13 | - indented code use tabs (not line wrapped) | |
14 | - cuddle the braces (except for functions) | |
15 | - space after native statements and before paren (for/if/while/...) | |
16 | - no space between function and paren | |
17 | - pointer asterisk cuddles the variable, not the type | |
18 | ||
19 | ``` | |
20 | void foo(int c) | |
21 | { | |
22 | int ret = 0; | |
23 | ||
24 | if (c > 1000) | |
25 | return; | |
26 | ||
27 | while (c--) { | |
28 | bar(c); | |
29 | ret++; | |
30 | } | |
31 | ||
32 | return ret; | |
33 | } | |
34 | ``` | |
35 | ||
36 | ## COMMIT MESSAGES | |
37 | ||
38 | The following is an example of a correctly formatted git commit message | |
39 | for this repository. Most of this information came from this blog post | |
40 | [2], so I would like to thank the author. | |
41 | ||
42 | ``` | |
43 | Capitalized, short (50 chars or less) summary | |
44 | ||
45 | More detailed explanatory text, if necessary. Wrap it to about 72 | |
46 | characters or so. In some contexts, the first line is treated as the | |
47 | subject of an email and the rest of the text as the body. The blank | |
48 | line separating the summary from the body is critical (unless you omit | |
49 | the body entirely); tools like rebase can get confused if you run the | |
50 | two together. | |
51 | ||
52 | Write your commit message in the imperative: "Fix bug" and not "Fixed | |
53 | bug." This convention matches up with commit messages generated by | |
54 | commands like git merge and git revert. | |
55 | ||
56 | Further paragraphs come after blank lines. | |
57 | ||
58 | - Bullet points are okay, too | |
59 | ||
60 | - Typically a hyphen or asterisk is used for the bullet, preceded by a | |
61 | single space, with blank lines in between, but conventions vary here | |
62 | ||
63 | - Use a hanging indent | |
64 | ||
65 | Reported-by: User Name <email> | |
66 | X-[Distro]-Bug: BugID | |
67 | X-[Distro]-Bug-URL: URL for the bug (on the distribution's web site typically) | |
68 | ``` | |
69 | ||
70 | If you did not write the code and the patch does not include authorship | |
71 | information in a format git can use, please use the --author option of the | |
72 | git commit command to make the authorship correct. | |
73 | ||
74 | The Reported-by tag is required if the person who reported the bug is | |
75 | different from the author and committer. | |
76 | ||
77 | The X-[Distro]-Bug/Bug-URL tags are required if this commit is related | |
78 | to a bug reported to us by a specific distribution of linux or a | |
79 | *BSD. Also, [Distro] should be replaced with the name of the | |
80 | distribution, e.g. X-Gentoo-Bug. | |
81 | ||
82 | [1] http://en.wikipedia.org/wiki/Indent_style#BSD_KNF_style | |
83 | [2] http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html |
14 | 14 | |
15 | 15 | CONF-FreeBSD= ipfw moused powerd rarpd savecore syscons |
16 | 16 | |
17 | CONF-Linux= consolefont devfs dmesg hwclock keymaps killprocs modules | |
17 | CONF-Linux= consolefont devfs dmesg hwclock keymaps killprocs modules mtab | |
18 | 18 | |
19 | 19 | CONF-NetBSD= moused rarpd savecore |
20 | 20 |
0 | # This setting controls whether /etc/mtab is a file or symbolic link. | |
1 | # Most of the time, you shouldn't touch this. However, if the default | |
2 | # breaks your system in some way, please see the NEWS.md file that comes | |
3 | # with OpenRC for the actions to take. | |
4 | # mtab_is_file=no |
0 | ||
1 | # You can assign a default route | |
2 | #defaultroute="gw 192.168.0.1" | |
3 | #defaultroute6="gw 2001:a:b:c" |
0 | # Separate multiple routes using ; or new lines. | |
1 | ||
2 | # Example static routes. See route(8) for syntax. | |
3 | #staticroute="net 192.168.0.0 10.73.1.1 netmask 255.255.255.0 | |
4 | #net 192.168.1.0 10.73.1.1 netmask 255.255.255.0" |
0 | # Separate multiple routes using ; or new lines. | |
1 | # /etc/route.conf(5) takes precedence over this configuration. | |
2 | ||
3 | # Example static routes. See route(8) for syntax. | |
4 | # FIXME: "net ..." not supported | |
5 | #staticroute="net 192.168.0.0 -netmask 255.255.255.0 --address 10.73.1.1 | |
6 | #net 192.168.1.0 -netmask 255.255.255.0 --address 10.73.1.1" |
0 | ############################################################################## | |
1 | # GNU/Hurd SPECIFIC OPTIONS | |
2 | ||
3 | # This is the subsystem type. Valid options on GNU/Hurd: | |
4 | # "" - nothing special | |
5 | # "subhurd" - Hurd subhurds (to be checked) | |
6 | # If this is commented out, automatic detection will be used. | |
7 | # | |
8 | # This should be set to the value representing the environment this file is | |
9 | # PRESENTLY in, not the virtualization the environment is capable of. | |
10 | #rc_sys="" | |
11 | # This is the number of tty's used in most of the rc-scripts (like | |
12 | # consolefont, numlock, etc ...) | |
13 | #rc_tty_number=6? |
1 | 1 | # LINUX SPECIFIC OPTIONS |
2 | 2 | |
3 | 3 | # This is the subsystem type. Valid options on Linux: |
4 | # "" - nothing special | |
5 | # "lxc" - Linux Containers | |
6 | # "openvz" - Linux OpenVZ | |
7 | # "prefix" - Prefix | |
8 | # "uml" - Usermode Linux | |
9 | # "vserver" - Linux vserver | |
10 | # "xen0" - Xen0 Domain | |
11 | # "xenU" - XenU Domain | |
4 | # "" - nothing special | |
5 | # "lxc" - Linux Containers | |
6 | # "openvz" - Linux OpenVZ | |
7 | # "prefix" - Prefix | |
8 | # "uml" - Usermode Linux | |
9 | # "vserver" - Linux vserver | |
10 | # "systemd-nspawn" - Container created by the systemd-nspawn utility | |
11 | # "xen0" - Xen0 Domain | |
12 | # "xenU" - XenU Domain | |
12 | 13 | # If this is commented out, automatic detection will be used. |
13 | 14 | # |
14 | 15 | # This should be set to the value representing the environment this file is |
60 | 61 | # Set the devices controller settings for this service. |
61 | 62 | #rc_cgroup_devices="" |
62 | 63 | |
64 | # Set the hugetlb controller settings for this service. | |
65 | #rc_cgroup_hugetlb="" | |
66 | ||
63 | 67 | # Set the memory controller settings for this service. |
64 | 68 | #rc_cgroup_memory="" |
65 | 69 | |
70 | # Set the net_cls controller settings for this service. | |
71 | #rc_cgroup_net_cls="" | |
72 | ||
66 | 73 | # Set the net_prio controller settings for this service. |
67 | 74 | #rc_cgroup_net_prio="" |
75 | ||
76 | # Set the pids controller settings for this service. | |
77 | #rc_cgroup_pids="" | |
68 | 78 | |
69 | 79 | # Set this to YES if yu want all of the processes in a service's cgroup |
70 | 80 | # killed when the service is stopped or restarted. |
115 | 115 | #SSD_NICELEVEL="-19" |
116 | 116 | |
117 | 117 | # Pass ulimit parameters |
118 | # If you are using bash in POSIX mode for your shell, note that the | |
119 | # ulimit command uses a block size of 512 bytes for the -c and -f | |
120 | # options | |
118 | 121 | #rc_ulimit="-u 30" |
119 | 122 | |
120 | 123 | # It's possible to define extra dependencies for services like so |
9 | 9 | trap : SIGINT |
10 | 10 | trap "echo 'Boot interrupted'; exit 1" SIGQUIT |
11 | 11 | |
12 | /sbin/rc sysinit || exit 1 | |
13 | /sbin/rc boot || exit 1 | |
14 | /sbin/rc default | |
12 | /sbin/openrc sysinit || exit 1 | |
13 | /sbin/openrc boot || exit 1 | |
14 | /sbin/openrc default | |
15 | 15 | |
16 | 16 | # We don't actually care if rc default worked or not, we should exit 0 |
17 | 17 | # to allow logins |
13 | 13 | [ -z "$TERM" -o "$TERM" = "dumb" ] && TERM="@TERM@" && export TERM |
14 | 14 | |
15 | 15 | action=${1:-shutdown} |
16 | exec /sbin/rc "${action}" | |
16 | exec /sbin/openrc "${action}" |
1 | 1 | |
2 | 2 | DIR= ${INITDIR} |
3 | 3 | SRCS= bootmisc.in fsck.in hostname.in local.in localmount.in loopback.in \ |
4 | netmount.in root.in savecache.in swap.in swapfiles.in \ | |
5 | tmpfiles.setup.in swclock.in sysctl.in urandom.in ${SRCS-${OS}} | |
4 | netmount.in osclock.in root.in savecache.in swap.in swapfiles.in \ | |
5 | tmpfiles.setup.in swclock.in sysctl.in urandom.in s6-svscan.in ${SRCS-${OS}} | |
6 | 6 | BIN= ${OBJS} |
7 | 7 | |
8 | 8 | # Are we installing our network scripts? |
20 | 20 | SRCS-FreeBSD+= adjkerntz.in devd.in dumpon.in encswap.in ipfw.in \ |
21 | 21 | mixer.in nscd.in powerd.in syscons.in |
22 | 22 | |
23 | SRCS-Linux= devfs.in dmesg.in hwclock.in consolefont.in keymaps.in \ | |
23 | SRCS-Linux= binfmt.in devfs.in dmesg.in hwclock.in consolefont.in keymaps.in \ | |
24 | 24 | killprocs.in modules.in mount-ro.in mtab.in numlock.in \ |
25 | 25 | procfs.in sysfs.in termencoding.in tmpfiles.dev.in |
26 | 26 |
0 | #!@SBINDIR@/openrc-run | |
1 | # Copyright 2015 William Hubbs <w.d.hubbs@gmail.com> | |
2 | # Released under the 2-clause BSD license. | |
3 | ||
4 | description="Register misc binary format handlers" | |
5 | ||
6 | depend() | |
7 | { | |
8 | after procfs | |
9 | use modules devfs | |
10 | keyword -openvz -prefix -systemd-nspawn -vserver -lxc | |
11 | } | |
12 | ||
13 | start() | |
14 | { | |
15 | ebegin "Loading custom binary format handlers" | |
16 | "$RC_LIBEXECDIR"/sh/binfmt.sh | |
17 | eend $? | |
18 | return 0 | |
19 | } |
118 | 118 | { |
119 | 119 | [ "$RC_SYS" = VSERVER -o "$RC_SYS" = LXC ] && return 0 |
120 | 120 | local dir |
121 | # If / is still read-only due to a problem, this will fail! | |
122 | if ! checkpath -W /; then | |
123 | ewarn "/ is not writable; unable to clean up underlying /run" | |
124 | return 1 | |
125 | fi | |
126 | if ! checkpath -W /tmp; then | |
127 | ewarn "/tmp is not writable; unable to clean up underlying /run" | |
128 | return 1 | |
129 | fi | |
130 | # Now we know that we can modify /tmp and / | |
131 | # if mktemp -d fails, it returns an EMPTY string | |
132 | # STDERR: mktemp: failed to create directory via template ‘/tmp/tmp.XXXXXXXXXX’: Read-only file system | |
133 | # STDOUT: '' | |
134 | rc=0 | |
121 | 135 | dir=$(mktemp -d) |
122 | mount --bind / $dir | |
123 | rm -rf $dir/run/* | |
124 | umount $dir | |
125 | rm -rf $dir | |
136 | if [ -n "$dir" -a -d $dir -a -w $dir ]; then | |
137 | mount --bind / $dir && rm -rf $dir/run/* || rc=1 | |
138 | umount $dir && rmdir $dir | |
139 | else | |
140 | rc=1 | |
141 | fi | |
142 | if [ $rc -ne 0 ]; then | |
143 | ewarn "Could not clean up underlying /run on /" | |
144 | return 1 | |
145 | fi | |
126 | 146 | } |
127 | 147 | |
128 | 148 | start() |
192 | 212 | if yesno $log_dmesg; then |
193 | 213 | if $logw || checkpath -W /var/log; then |
194 | 214 | # Create an 'after-boot' dmesg log |
195 | if [ "$RC_SYS" != VSERVER -a "$RC_SYS" != OPENVZ -a "$RC_SYS" != LXC ]; then | |
196 | dmesg > /var/log/dmesg | |
197 | chmod 640 /var/log/dmesg | |
198 | fi | |
215 | case "$RC_SYS" in | |
216 | VSERVER|OPENVZ|LXC|SYSTEMD-NSPAWN) ;; | |
217 | *) | |
218 | dmesg > /var/log/dmesg | |
219 | chmod 640 /var/log/dmesg | |
220 | ;; | |
221 | esac | |
199 | 222 | fi |
200 | 223 | fi |
201 | 224 |
7 | 7 | { |
8 | 8 | need localmount termencoding |
9 | 9 | after hotplug bootmisc |
10 | keyword -openvz -prefix -uml -vserver -xenu -lxc | |
10 | keyword -openvz -prefix -systemd-nspawn -uml -vserver -xenu -lxc | |
11 | 11 | } |
12 | 12 | |
13 | 13 | start() |
7 | 7 | { |
8 | 8 | provide dev-mount |
9 | 9 | before dev |
10 | keyword -prefix -vserver -lxc | |
10 | keyword -prefix -systemd-nspawn -vserver -lxc | |
11 | 11 | } |
12 | 12 | |
13 | 13 | mount_dev() |
68 | 68 | # so udev can add its start-message to dmesg |
69 | 69 | [ -c /dev/kmsg ] || mknod -m 660 /dev/kmsg c 1 11 |
70 | 70 | |
71 | # Mount required stuff as user may not have then in /etc/fstab | |
71 | # extra symbolic links not provided by default | |
72 | [ -e /dev/fd ] || ln -snf /proc/self/fd /dev/fd | |
73 | [ -e /dev/stdin ] || ln -snf /proc/self/fd/0 /dev/stdin | |
74 | [ -e /dev/stdout ] || ln -snf /proc/self/fd/1 /dev/stdout | |
75 | [ -e /dev/stderr ] || ln -snf /proc/self/fd/2 /dev/stderr | |
76 | [ -e /proc/kcore ] && ln -snf /proc/kcore /dev/core | |
77 | ||
78 | # Mount required directories as user may not have them in /etc/fstab | |
72 | 79 | for x in \ |
73 | 80 | "mqueue /dev/mqueue 1777 ,nodev mqueue" \ |
74 | 81 | "devpts /dev/pts 0755 ,gid=5,mode=0620 devpts" \ |
6 | 6 | depend() |
7 | 7 | { |
8 | 8 | before dev modules |
9 | keyword -lxc -prefix -vserver | |
9 | keyword -lxc -prefix -systemd-nspawn -vserver | |
10 | 10 | } |
11 | 11 | |
12 | 12 | start() |
8 | 8 | depend() |
9 | 9 | { |
10 | 10 | use dev clock modules |
11 | keyword -jail -openvz -prefix -timeout -vserver -lxc -uml | |
11 | keyword -jail -openvz -prefix -systemd-nspawn -timeout -vserver -lxc -uml | |
12 | 12 | } |
13 | 13 | |
14 | 14 | _abort() { |
4 | 4 | description="Sets the hostname of the machine." |
5 | 5 | |
6 | 6 | depend() { |
7 | keyword -prefix -lxc | |
7 | keyword -prefix -systemd-nspawn -lxc | |
8 | 8 | } |
9 | 9 | |
10 | 10 | start() |
27 | 27 | else |
28 | 28 | before * |
29 | 29 | fi |
30 | keyword -openvz -prefix -uml -vserver -xenu -lxc | |
30 | keyword -openvz -prefix -systemd-nspawn -uml -vserver -xenu -lxc | |
31 | 31 | } |
32 | 32 | |
33 | 33 | setupopts() |
7 | 7 | { |
8 | 8 | need localmount termencoding |
9 | 9 | after bootmisc |
10 | keyword -openvz -prefix -uml -vserver -xenu -lxc | |
10 | keyword -openvz -prefix -systemd-nspawn -uml -vserver -xenu -lxc | |
11 | 11 | } |
12 | 12 | |
13 | 13 | start() |
13 | 13 | { |
14 | 14 | ebegin "Starting local" |
15 | 15 | |
16 | local file has_errors=0 retval | |
16 | local file has_errors=0 redirect retval | |
17 | yesno $rc_verbose || redirect='> /dev/null 2>&1' | |
17 | 18 | eindent |
18 | 19 | for file in @SYSCONFDIR@/local.d/*.start; do |
19 | 20 | if [ -x "${file}" ]; then |
20 | 21 | vebegin "Executing \"${file}\"" |
21 | "${file}" 2>&1 >/dev/null | |
22 | eval "${file}" $redirect | |
22 | 23 | retval=$? |
23 | 24 | if [ ${retval} -ne 0 ]; then |
24 | 25 | has_errors=1 |
51 | 52 | { |
52 | 53 | ebegin "Stopping local" |
53 | 54 | |
54 | local file has_errors=0 retval | |
55 | local file has_errors=0 redirect retval | |
56 | yesno $rc_verbose || redirect='> /dev/null 2>&1' | |
55 | 57 | eindent |
56 | 58 | for file in @SYSCONFDIR@/local.d/*.stop; do |
57 | 59 | if [ -x "${file}" ]; then |
58 | 60 | vebegin "Executing \"${file}\"" |
59 | "${file}" 2>&1 >/dev/null | |
61 | eval "${file}" $redirect | |
60 | 62 | retval=$? |
61 | 63 | if [ ${retval} -ne 0 ]; then |
62 | 64 | has_errors=1 |
8 | 8 | need fsck |
9 | 9 | use lvm modules mtab |
10 | 10 | after lvm modules |
11 | keyword -jail -prefix -vserver -lxc | |
11 | keyword -jail -prefix -systemd-nspawn -vserver -lxc | |
12 | 12 | } |
13 | 13 | |
14 | 14 | start() |
15 | 15 | { |
16 | 16 | # Mount local filesystems in /etc/fstab. |
17 | local types="noproc" x= no_netdev= | |
17 | local types="noproc" x= no_netdev= rc= | |
18 | 18 | for x in $net_fs_list $extra_net_fs_list; do |
19 | 19 | types="${types},no${x}" |
20 | 20 | done |
28 | 28 | ebegin "Mounting local filesystems" |
29 | 29 | mount -at "$types" $no_netdev |
30 | 30 | eend $? "Some local filesystem failed to mount" |
31 | ||
32 | # Always return 0 - some local mounts may not be critical for boot | |
33 | return 0 | |
31 | rc=$? | |
32 | if [ "$RC_UNAME" != Linux ]; then | |
33 | rc=0 | |
34 | fi | |
35 | return $rc | |
34 | 36 | } |
35 | 37 | |
36 | 38 | stop() |
62 | 64 | |
63 | 65 | . "$RC_LIBEXECDIR"/sh/rc-mount.sh |
64 | 66 | |
67 | if [ "$RC_UNAME" = Linux ] && [ -d /sys/fs/aufs ] ; then | |
68 | #if / is aufs we remount it noxino during shutdown | |
69 | if mountinfo -q -f '^aufs$' / ; then | |
70 | mount -o remount,noxino,rw / | |
71 | sync | |
72 | fi | |
73 | ||
74 | local aufs_branch aufs_mount_point aufs_si_id aufs_br_id branches | |
75 | for aufs_si_dir in /sys/fs/aufs/si*; do | |
76 | [ -d "${aufs_si_dir}" ] || continue | |
77 | aufs_si_id="si=${aufs_si_dir#/sys/fs/aufs/si_}" | |
78 | aufs_mount_point="$(mountinfo -o ${aufs_si_id})" | |
79 | branches="$aufs_si_dir/br[0-9] $aufs_si_dir/br[0-9][0-9] $aufs_si_dir/br[0-9][0-9][0-9]" | |
80 | for x in $branches; do | |
81 | [ -e "${x}" ] || continue | |
82 | aufs_branch=$(sed 's/=.*//g' $x) | |
83 | eindent | |
84 | if ! mount -o "remount,del:$aufs_branch" "$aufs_mount_point" > /dev/null 2>&1; then | |
85 | ewarn "Failed to remove branch $aufs_branch from aufs \ | |
86 | $aufs_mount_point" | |
87 | fi | |
88 | eoutdent | |
89 | sync | |
90 | done | |
91 | done | |
92 | fi | |
93 | ||
65 | 94 | # Umount loop devices |
66 | 95 | einfo "Unmounting loop devices" |
67 | 96 | eindent |
5 | 5 | |
6 | 6 | depend() |
7 | 7 | { |
8 | keyword -jail -prefix -vserver | |
8 | keyword -jail -prefix -systemd-nspawn -vserver | |
9 | 9 | } |
10 | 10 | |
11 | 11 | start() |
6 | 6 | depend() |
7 | 7 | { |
8 | 8 | use isapnp |
9 | keyword -openvz -prefix -vserver -lxc | |
9 | keyword -openvz -prefix -systemd-nspawn -vserver -lxc | |
10 | 10 | } |
11 | 11 | |
12 | 12 | start() |
6 | 6 | depend() |
7 | 7 | { |
8 | 8 | need killprocs savecache |
9 | keyword -openvz -prefix -vserver -lxc | |
9 | keyword -openvz -prefix -systemd-nspawn -vserver -lxc | |
10 | 10 | } |
11 | 11 | |
12 | 12 | start() |
6 | 6 | depend() |
7 | 7 | { |
8 | 8 | need root |
9 | keyword -prefix | |
9 | keyword -prefix -systemd-nspawn | |
10 | 10 | } |
11 | 11 | |
12 | 12 | start() |
13 | 13 | { |
14 | if [ -L /etc/mtab ]; then | |
15 | return 0 | |
14 | local rc=0 | |
15 | ebegin "Updating /etc/mtab" | |
16 | if ! checkpath -W /etc; then | |
17 | rc=1 | |
18 | elif ! yesno ${mtab_is_file:-no}; then | |
19 | [ ! -L /etc/mtab ] && [ -f /etc/mtab ] && | |
20 | ewarn "Removing /etc/mtab file" | |
21 | einfo "Creating mtab symbolic link" | |
22 | ln -snf /proc/self/mounts /etc/mtab | |
23 | else | |
24 | [ -L /etc/mtab ] && ewarn "Removing /etc/mtab symbolic link" | |
25 | rm -f /etc/mtab | |
26 | einfo "Creating mtab file" | |
27 | # With / as tmpfs we cannot umount -at tmpfs in localmount as that | |
28 | # makes / readonly and dismounts all tmpfs even if in use which is | |
29 | # not good. Luckily, umount uses /etc/mtab instead of /proc/mounts | |
30 | # which allows this hack to work. | |
31 | grep -v "^[! ]* / tmpfs " /proc/mounts > /etc/mtab | |
32 | ||
33 | # Remove stale backups | |
34 | rm -f /etc/mtab~ /etc/mtab~~ | |
16 | 35 | fi |
17 | ||
18 | ebegin "Updating /etc/mtab" | |
19 | vewarn "The support for updating /etc/mtab as a file is" | |
20 | vewarn "deprecated and will be removed in the future." | |
21 | vewarn "Please run the following command as root on your system." | |
22 | vewarn | |
23 | vewarn "ln -snf /proc/self/mounts /etc/mtab" | |
24 | if ! echo 2>/dev/null >/etc/mtab; then | |
25 | ewend 1 "/etc/mtab is not updateable" | |
26 | return 0 | |
27 | fi | |
28 | ||
29 | # With / as tmpfs we cannot umount -at tmpfs in localmount as that | |
30 | # makes / readonly and dismounts all tmpfs even if in use which is | |
31 | # not good. Luckily, umount uses /etc/mtab instead of /proc/mounts | |
32 | # which allows this hack to work. | |
33 | grep -v "^[! ]* / tmpfs " /proc/mounts > /etc/mtab | |
34 | ||
35 | # Remove stale backups | |
36 | rm -f /etc/mtab~ /etc/mtab~~ | |
37 | eend 0 | |
36 | eend $rc "/etc is not writable; unable to create /etc/mtab" | |
37 | return 0 | |
38 | 38 | } |
1 | 1 | # Copyright (c) 2007-2009 Roy Marples <roy@marples.name> |
2 | 2 | # Released under the 2-clause BSD license. |
3 | 3 | |
4 | description="Mounts network shares, other than NFS, according to /etc/fstab." | |
5 | # We skip all NFS shares in this script because they require extra | |
6 | # daemons to be running on the client in order to work correctly. | |
7 | # It is best to allow nfs-utils to handle all nfs shares. | |
4 | description="Mounts network shares according to /etc/fstab." | |
8 | 5 | |
9 | 6 | depend() |
10 | 7 | { |
11 | 8 | config /etc/fstab |
12 | use afc-client amd autofs openvpn | |
9 | use afc-client amd nfsclient autofs openvpn | |
13 | 10 | use dns |
14 | keyword -jail -prefix -vserver -lxc | |
11 | keyword -jail -prefix -systemd-nspawn -vserver -lxc | |
15 | 12 | } |
16 | 13 | |
17 | 14 | start() |
18 | 15 | { |
19 | 16 | local x= fs= rc= |
20 | 17 | for x in $net_fs_list $extra_net_fs_list; do |
21 | case "$x" in | |
22 | nfs|nfs4) | |
23 | continue | |
24 | ;; | |
25 | esac | |
26 | 18 | fs="$fs${fs:+,}$x" |
27 | 19 | done |
28 | 20 | |
34 | 26 | rc=$? |
35 | 27 | fi |
36 | 28 | ewend $rc "Could not mount all network filesystems" |
37 | return 0 | |
29 | if [ "$RC_UNAME" != Linux ]; then | |
30 | rc=0 | |
31 | fi | |
32 | return $rc | |
38 | 33 | } |
39 | 34 | |
40 | 35 | stop() |
45 | 40 | . "$RC_LIBEXECDIR"/sh/rc-mount.sh |
46 | 41 | |
47 | 42 | for x in $net_fs_list $extra_net_fs_list; do |
48 | case "$x" in | |
49 | nfs|nfs4) | |
50 | continue | |
51 | ;; | |
52 | *) | |
53 | fs="$fs${fs:+,}$x" | |
54 | ;; | |
55 | esac | |
43 | fs="$fs${fs:+,}$x" | |
56 | 44 | done |
57 | 45 | if [ -n "$fs" ]; then |
58 | 46 | umount -at $fs || eerror "Failed to simply unmount filesystems" |
61 | 49 | eindent |
62 | 50 | fs= |
63 | 51 | for x in $net_fs_list $extra_net_fs_list; do |
64 | case "$x" in | |
65 | nfs|nfs4) | |
66 | continue | |
67 | ;; | |
68 | *) | |
69 | fs="$fs${fs:+|}$x" | |
70 | ;; | |
71 | esac | |
52 | fs="$fs${fs:+|}$x" | |
72 | 53 | done |
73 | 54 | [ -n "$fs" ] && fs="^($fs)$" |
74 | 55 | do_unmount umount ${fs:+--fstype-regex} $fs --netdev |
8 | 8 | depend() |
9 | 9 | { |
10 | 10 | need localmount |
11 | keyword -openvz -prefix -vserver -lxc | |
11 | keyword -openvz -prefix -systemd-nspawn -vserver -lxc | |
12 | 12 | } |
13 | 13 | |
14 | 14 | _setleds() |
0 | #!@SBINDIR@/openrc-run | |
1 | # Copyright (c) 2014 Ralph Sennhauser <sera@igentoo.org> | |
2 | # Released under the 2-clause BSD license. | |
3 | ||
4 | # Can be used on OSs that take care of the clock. | |
5 | ||
6 | description="Provides clock" | |
7 | ||
8 | depend() | |
9 | { | |
10 | provide clock | |
11 | } |
7 | 7 | { |
8 | 8 | use modules devfs |
9 | 9 | need localmount |
10 | keyword -openvz -prefix -vserver -lxc | |
10 | keyword -openvz -prefix -systemd-nspawn -vserver -lxc | |
11 | 11 | } |
12 | 12 | |
13 | 13 | start() |
14 | 14 | { |
15 | # Make sure we insert usbcore if it's a module | |
16 | if [ -f /proc/modules -a ! -d /sys/module/usbcore -a ! -d /proc/bus/usb ]; then | |
17 | modprobe -q usbcore | |
18 | fi | |
19 | ||
20 | [ -e /proc/filesystems ] || return 0 | |
21 | ||
22 | 15 | # Setup Kernel Support for miscellaneous Binary Formats |
23 | 16 | if [ -d /proc/sys/fs/binfmt_misc -a ! -e /proc/sys/fs/binfmt_misc/register ]; then |
17 | modprobe -q binfmt-misc | |
24 | 18 | if grep -qs binfmt_misc /proc/filesystems; then |
25 | 19 | ebegin "Mounting misc binary format filesystem" |
26 | 20 | mount -t binfmt_misc -o nodev,noexec,nosuid \ |
27 | 21 | binfmt_misc /proc/sys/fs/binfmt_misc |
28 | if eend $? ; then | |
29 | local fmts | |
30 | ebegin "Loading custom binary format handlers" | |
31 | fmts=$(grep -hsv -e '^[#;]' -e '^[[:space:]]*$' \ | |
32 | /run/binfmt.d/*.conf \ | |
33 | /etc/binfmt.d/*.conf \ | |
34 | ""/usr/lib/binfmt.d/*.conf) | |
35 | if [ -n "${fmts}" ]; then | |
36 | echo "${fmts}" > /proc/sys/fs/binfmt_misc/register | |
37 | fi | |
38 | 22 | eend $? |
39 | fi | |
40 | 23 | fi |
41 | 24 | fi |
42 | ||
43 | [ "$RC_SYS" = "OPENVZ" ] && return 0 | |
44 | ||
45 | # Check what USB fs the kernel support. Currently | |
46 | # 2.5+ kernels, and later 2.4 kernels have 'usbfs', | |
47 | # while older kernels have 'usbdevfs'. | |
48 | if [ -d /proc/bus/usb -a ! -e /proc/bus/usb/devices ]; then | |
49 | local usbfs=$(grep -Fow usbfs /proc/filesystems || | |
50 | grep -Fow usbdevfs /proc/filesystems) | |
51 | if [ -n "$usbfs" ]; then | |
52 | ebegin "Mounting USB device filesystem [$usbfs]" | |
53 | local usbgid="$(getent group usb | \ | |
54 | sed -e 's/.*:.*:\(.*\):.*/\1/')" | |
55 | mount -t $usbfs \ | |
56 | -o ${usbgid:+devmode=0664,devgid=$usbgid,}noexec,nosuid \ | |
57 | usbfs /proc/bus/usb | |
58 | eend $? | |
59 | fi | |
60 | fi | |
61 | ||
62 | # Setup Kernel Support for SELinux | |
63 | if [ -d /sys/fs/selinux ] && ! mountinfo -q /sys/fs/selinux; then | |
64 | if grep -qs selinuxfs /proc/filesystems; then | |
65 | ebegin "Mounting SELinux filesystem" | |
66 | mount -t selinuxfs selinuxfs /sys/fs/selinux | |
67 | eend $? | |
68 | fi | |
69 | fi | |
70 | ||
71 | 25 | return 0 |
72 | 26 | } |
6 | 6 | depend() |
7 | 7 | { |
8 | 8 | need fsck |
9 | keyword -jail -openvz -prefix -vserver -lxc | |
9 | keyword -jail -openvz -prefix -systemd-nspawn -vserver -lxc | |
10 | 10 | } |
11 | 11 | |
12 | 12 | start() |
0 | #!@SBINDIR@/openrc-run | |
1 | # Copyright (C) 2015 William Hubbs <w.d.hubbs@gmail.com> | |
2 | # Released under the 2-clause BSD license. | |
3 | ||
4 | command=/bin/s6-svscan | |
5 | command_args="${RC_SVCDIR}"/s6-scan | |
6 | command_background=yes | |
7 | pidfile=/var/run/s6-svscan.pid | |
8 | ||
9 | depend() | |
10 | { | |
11 | need localmount | |
12 | } | |
13 | ||
14 | start_pre() | |
15 | { | |
16 | einfo "Creating s6 scan directory" | |
17 | checkpath -d -m 0755 "$RC_SVCDIR"/s6-scan | |
18 | return $? | |
19 | } | |
20 | ||
21 | stop_post() | |
22 | { | |
23 | ebegin "Stopping any remaining s6 services" | |
24 | s6-svc -dx "${RC_SVCDIR}"/s6-scan/* 2>/dev/null || true | |
25 | eend $? | |
26 | ||
27 | ebegin "Stopping any remaining s6 service loggers" | |
28 | s6-svc -dx "${RC_SVCDIR}"/s6-scan/*/log 2>/dev/null || true | |
29 | eend $? | |
30 | } |
6 | 6 | start() |
7 | 7 | { |
8 | 8 | if [ -e "$RC_SVCDIR"/clock-skewed ]; then |
9 | ewarn "WARNING: clock skew detected!" | |
9 | ewarn "Clock skew detected!" | |
10 | 10 | if ! yesno "${RC_GOINGDOWN}"; then |
11 | 11 | eerror "Not saving deptree cache" |
12 | 12 | return 1 |
13 | 13 | fi |
14 | 14 | fi |
15 | if ! checkpath -W "$RC_LIBEXECDIR"; then | |
16 | ewarn "WARNING: ${RC_LIBEXECDIR} is not writable!" | |
17 | if ! yesno "${RC_GOINGDOWN}"; then | |
18 | ewarn "Unable to save deptree cache" | |
15 | if [ ! -d "$RC_LIBEXECDIR"/cache ]; then | |
16 | if ! checkpath -W "$RC_LIBEXECDIR"; then | |
17 | eerror "${RC_LIBEXECDIR} is not writable!" | |
18 | eerror "Unable to save dependency cache" | |
19 | if yesno "${RC_GOINGDOWN}"; then | |
20 | return 0 | |
21 | fi | |
19 | 22 | return 1 |
20 | 23 | fi |
21 | return 0 | |
24 | rm -rf "$RC_LIBEXECDIR"/cache | |
25 | if ! mkdir -p "$RC_LIBEXECDIR"/cache; then | |
26 | eerror "Unable to create $RC_LIBEXECDIR/cache" | |
27 | eerror "Unable to save dependency cache" | |
28 | if yesno "${RC_GOINGDOWN}"; then | |
29 | return 0 | |
30 | fi | |
31 | return 1 | |
32 | fi | |
33 | fi | |
34 | if ! checkpath -W "$RC_LIBEXECDIR"/cache; then | |
35 | eerror "${RC_LIBEXECDIR}/cache is not writable!" | |
36 | eerror "Unable to save dependency cache" | |
37 | if yesno "${RC_GOINGDOWN}"; then | |
38 | return 0 | |
39 | fi | |
40 | return 1 | |
22 | 41 | fi |
23 | 42 | ebegin "Saving dependency cache" |
24 | local rc= | |
25 | if [ ! -d "$RC_LIBEXECDIR"/cache ]; then | |
26 | rm -rf "$RC_LIBEXECDIR"/cache | |
27 | if ! mkdir "$RC_LIBEXECDIR"/cache; then | |
28 | rc=$? | |
29 | if yesno "${RC_GOINGDOWN}"; then | |
30 | rc=0 | |
31 | fi | |
32 | eend $rc | |
33 | return $rc | |
34 | fi | |
35 | fi | |
36 | local save= | |
43 | local rc=0 save= | |
37 | 44 | for x in deptree depconfig shutdowntime softlevel nettree rc.log; do |
38 | 45 | [ -e "$RC_SVCDIR/$x" ] && save="$save $RC_SVCDIR/$x" |
39 | 46 | done |
40 | 47 | if [ -n "$save" ]; then |
41 | cp -p $save "$RC_LIBEXECDIR"/cache 2>/dev/null | |
48 | cp -p $save "$RC_LIBEXECDIR"/cache | |
49 | rc=$? | |
42 | 50 | fi |
43 | rc=$? | |
44 | 51 | if yesno "${RC_GOINGDOWN}"; then |
45 | rc=0 | |
52 | if [ $rc -ne 0 ]; then | |
53 | eerror "Unable to save dependency cache" | |
54 | fi | |
55 | eend 0 | |
46 | 56 | fi |
47 | eend $rc | |
57 | eend $rc "Unable to save dependency cache" | |
48 | 58 | } |
22 | 22 | # Don't quote ${dump_device}, so that if it's unset, |
23 | 23 | # savecore will check on the partitions listed in fstab |
24 | 24 | # without errors in the output |
25 | savecore -C "$dump_dir" $dump_device >/dev/null | |
25 | savecore -C $dump_device >/dev/null | |
26 | 26 | else |
27 | 27 | ls "$dump_dir"/bsd* > /dev/null 2>&1 |
28 | 28 | fi |
4 | 4 | depend() |
5 | 5 | { |
6 | 6 | before localmount |
7 | keyword -jail -openvz -prefix -vserver -lxc | |
7 | keyword -jail -openvz -prefix -systemd-nspawn -vserver -lxc | |
8 | 8 | } |
9 | 9 | |
10 | 10 | start() |
4 | 4 | depend() |
5 | 5 | { |
6 | 6 | need localmount |
7 | keyword -jail -openvz -prefix -vserver -lxc | |
7 | keyword -jail -openvz -prefix -systemd-nspawn -vserver -lxc | |
8 | 8 | } |
9 | 9 | |
10 | 10 | start() |
7 | 7 | { |
8 | 8 | before * |
9 | 9 | provide clock |
10 | keyword -openvz -prefix -uml -vserver -xenu -lxc | |
10 | keyword -openvz -prefix -systemd-nspawn -uml -vserver -xenu -lxc | |
11 | 11 | } |
12 | 12 | |
13 | 13 | # swclock is an OpenRC built in |
0 | #!@SBINDIR@/openrc-run | |
1 | # Copyright (c) 2007-2009 Roy Marples <roy@marples.name> | |
2 | # Released under the 2-clause BSD license. | |
3 | ||
4 | depend() | |
5 | { | |
6 | before bootmisc logger | |
7 | keyword -prefix | |
8 | } | |
9 | ||
10 | start() | |
11 | { | |
12 | [ -e /etc/sysctl.conf ] || return 0 | |
13 | local retval=0 var= comments= conf= | |
14 | ebegin "Configuring kernel parameters" | |
15 | eindent | |
16 | for conf in @SYSCONFDIR@/sysctl.conf @SYSCONFDIR@/sysctl.d/*.conf; do | |
17 | if [ -r "$conf" ]; then | |
18 | vebegin "applying $conf" | |
19 | while read var comments; do | |
20 | case "$var" in | |
21 | ""|"#"*) continue;; | |
22 | esac | |
23 | sysctl -w "$var" >/dev/null || retval=1 | |
24 | done < "$conf" | |
25 | veend $retval | |
26 | fi | |
27 | done | |
28 | eoutdent | |
29 | eend $retval "Some errors were encountered" | |
30 | } |
0 | #!@PREFIX@/sbin/openrc-run | |
1 | # Copyright (c) 2007-2009 Roy Marples <roy@marples.name> | |
2 | # Released under the 2-clause BSD license. | |
3 | #FIXME: Modify for GNU/Hurd | |
4 | ||
5 | depend() | |
6 | { | |
7 | before bootmisc logger | |
8 | keyword -prefix | |
9 | } | |
10 | ||
11 | start() | |
12 | { | |
13 | [ -e /etc/sysctl.conf ] || return 0 | |
14 | local retval=0 var= comments= conf= | |
15 | ebegin "Configuring kernel parameters" | |
16 | eindent | |
17 | for conf in @SYSCONFDIR@/sysctl.conf @SYSCONFDIR@/sysctl.d/*.conf; do | |
18 | if [ -r "$conf" ]; then | |
19 | vebegin "applying $conf" | |
20 | while read var comments; do | |
21 | case "$var" in | |
22 | ""|"#"*) continue;; | |
23 | esac | |
24 | sysctl -w "$var" >/dev/null || retval=1 | |
25 | done < "$conf" | |
26 | veend $retval | |
27 | fi | |
28 | done | |
29 | eoutdent | |
30 | eend $retval "Some errors were encountered" | |
31 | } |
4 | 4 | depend() |
5 | 5 | { |
6 | 6 | before bootmisc logger |
7 | keyword -prefix -vserver | |
7 | keyword -prefix -systemd-nspawn -vserver | |
8 | 8 | } |
9 | 9 | |
10 | 10 | start() |
11 | 11 | { |
12 | local quiet | |
13 | yesno $rc_verbose || quiet=-q | |
14 | ||
12 | 15 | ebegin "Configuring kernel parameters" |
13 | sysctl --system | |
16 | sysctl ${quiet} --system | |
14 | 17 | eend $? "Unable to configure some kernel parameters" |
15 | 18 | } |
7 | 7 | |
8 | 8 | depend() |
9 | 9 | { |
10 | keyword -lxc -prefix -vserver | |
10 | keyword -lxc -prefix -systemd-nspawn -vserver | |
11 | 11 | } |
12 | 12 | |
13 | 13 | mount_sys() |
81 | 81 | fi |
82 | 82 | fi |
83 | 83 | |
84 | # Setup Kernel Support for SELinux | |
85 | if [ -d /sys/fs/selinux ] && ! mountinfo -q /sys/fs/selinux; then | |
86 | if grep -qs selinuxfs /proc/filesystems; then | |
87 | ebegin "Mounting SELinux filesystem" | |
88 | mount -t selinuxfs selinuxfs /sys/fs/selinux | |
89 | eend $? | |
90 | fi | |
91 | fi | |
92 | ||
84 | 93 | # setup up kernel support for efivarfs |
85 | 94 | # slightly complicated, as if it's build as a module but NOT yet loaded, |
86 | 95 | # it will NOT appear in /proc/filesystems yet |
106 | 115 | mount -n -t cgroup \ |
107 | 116 | -o none,${sysfs_opts},name=openrc,release_agent="$agent" \ |
108 | 117 | openrc /sys/fs/cgroup/openrc |
109 | echo 1 > /sys/fs/cgroup/openrc/notify_on_release | |
118 | printf 1 > /sys/fs/cgroup/openrc/notify_on_release | |
110 | 119 | fi |
111 | 120 | |
112 | 121 | yesno ${rc_controller_cgroups:-YES} && [ -e /proc/cgroups ] || return 0 |
113 | 122 | while read name hier groups enabled rest; do |
114 | 123 | case "${enabled}" in |
115 | 1) mkdir /sys/fs/cgroup/${name} | |
124 | 1) mountinfo -q /sys/fs/cgroup/${name} && continue | |
125 | mkdir /sys/fs/cgroup/${name} | |
116 | 126 | mount -n -t cgroup -o ${sysfs_opts},${name} \ |
117 | 127 | ${name} /sys/fs/cgroup/${name} |
118 | 128 | ;; |
128 | 138 | restorecon -rF /sys/fs/cgroup >/dev/null 2>&1 |
129 | 139 | eend $? |
130 | 140 | fi |
131 | ||
132 | return 0 | |
133 | 141 | } |
134 | 142 | |
135 | 143 | start() |
136 | 144 | { |
137 | local retval | |
138 | 145 | mount_sys |
139 | retval=$? | |
140 | if [ $retval -eq 0 ]; then | |
141 | mount_misc | |
142 | retval=$? | |
143 | fi | |
144 | if [ $retval -eq 0 ]; then | |
145 | mount_cgroups | |
146 | retval=$? | |
147 | fi | |
148 | ||
146 | mount_misc | |
147 | mount_cgroups | |
149 | 148 | restorecon_sys |
150 | ||
151 | return $retval | |
149 | return 0 | |
152 | 150 | } |
8 | 8 | |
9 | 9 | depend() |
10 | 10 | { |
11 | keyword -lxc -openvz -prefix -uml -vserver -xenu | |
11 | keyword -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu | |
12 | 12 | use root |
13 | 13 | after bootmisc |
14 | 14 | } |
1 | 1 | # Copyright 1999-2012 Gentoo Foundation |
2 | 2 | # Released under the 2-clause BSD license. |
3 | 3 | |
4 | description="set up tmpfiles.d entries" | |
4 | description="Set up tmpfiles.d entries" | |
5 | 5 | |
6 | 6 | depend() |
7 | 7 | { |
12 | 12 | |
13 | 13 | start() |
14 | 14 | { |
15 | ebegin "setting up tmpfiles.d entries for /dev" | |
16 | @LIBEXECDIR@/sh/tmpfiles.sh --prefix=/dev --create ${tmpfiles_opts} | |
15 | ebegin "Setting up tmpfiles.d entries for /dev" | |
16 | @LIBEXECDIR@/sh/tmpfiles.sh --prefix=/dev --create --boot ${tmpfiles_opts} | |
17 | 17 | eend $? |
18 | 18 | return 0 |
19 | 19 | } |
1 | 1 | # Copyright 1999-2012 Gentoo Foundation |
2 | 2 | # Released under the 2-clause BSD license. |
3 | 3 | |
4 | description="set up tmpfiles.d entries" | |
4 | description="Set up tmpfiles.d entries" | |
5 | 5 | |
6 | 6 | depend() |
7 | 7 | { |
10 | 10 | |
11 | 11 | start() |
12 | 12 | { |
13 | ebegin "setting up tmpfiles.d entries" | |
13 | ebegin "Setting up tmpfiles.d entries" | |
14 | 14 | @LIBEXECDIR@/sh/tmpfiles.sh --exclude-prefix=/dev --create --remove --boot \ |
15 | 15 | ${tmpfiles_opts} |
16 | 16 | eend $? |
7 | 7 | depend() |
8 | 8 | { |
9 | 9 | need localmount |
10 | keyword -jail -lxc -openvz -prefix | |
10 | keyword -jail -lxc -openvz -prefix -systemd-nspawn | |
11 | 11 | } |
12 | 12 | |
13 | 13 | save_seed() |
0 | MK= ../mk | |
1 | include ${MK}/sys.mk | |
2 | include ${MK}/os.mk | |
3 | ||
0 | 4 | MAN3= einfo.3 \ |
1 | 5 | rc_config.3 rc_deptree.3 rc_find_pids.3 rc_plugin_hook.3 \ |
2 | 6 | rc_runlevel.3 rc_service.3 rc_stringlist.3 |
3 | 7 | MAN8= rc-service.8 rc-status.8 rc-update.8 openrc.8 openrc-run.8 \ |
4 | 8 | service.8 start-stop-daemon.8 |
9 | ||
10 | ifeq (${OS},Linux) | |
11 | MAN8 += rc-sstat.8 | |
12 | endif | |
5 | 13 | |
6 | 14 | # Handy macro to create symlinks |
7 | 15 | # This does rely on correctly formatting our manpages! |
15 | 23 | fi; \ |
16 | 24 | done; |
17 | 25 | |
18 | MK= ../mk | |
19 | include ${MK}/sys.mk | |
20 | 26 | include ${MK}/gitignore.mk |
21 | 27 | |
22 | 28 | all: |
106 | 106 | String describing the service. |
107 | 107 | .It Ar description_$command |
108 | 108 | String describing the extra command. |
109 | .It Ar supervisor | |
110 | Supervisor to use to monitor this daemon. If this is unset, | |
111 | start-stop-daemon will be used. The only alternate supervisor we support | |
112 | in this release is S6 from Skarnet software. To use this, set | |
113 | supervisor=s6. | |
114 | .It Ar s6_service_path | |
115 | The path to the s6 service directory if you are monitoring this service | |
116 | with S6. The default is /var/svc.d/${RC_SVCNAME}. | |
117 | .It Ar s6_svwait_options_start | |
118 | The options to pass to s6-svwait when starting the service via s6. | |
119 | .It Ar s6_service_timeout_stop | |
120 | The amount of time, in milliseconds, s6-svc should wait for the service | |
121 | to go down when stopping the service. The default is 10000. | |
109 | 122 | .It Ar start_stop_daemon_args |
110 | 123 | List of arguments passed to start-stop-daemon when starting the daemon. |
111 | 124 | .It Ar command |
113 | 126 | .Nm start-stop-daemon |
114 | 127 | if no start or stop function is defined by the service. |
115 | 128 | .It Ar command_args |
116 | List of arguments to pass to the daemon when starting. | |
129 | List of arguments to pass to the daemon when starting via | |
130 | .Nm start-stop-daemon . | |
117 | 131 | .It Ar command_background |
118 | 132 | Set this to "true", "yes" or "1" (case-insensitive) to force the daemon into |
119 | 133 | the background. This implies the "--make-pidfile" and "--pidfile" option of |
120 | 134 | .Xr start-stop-daemon 8 |
121 | 135 | so the pidfile variable must be set. |
136 | .It Ar chroot | |
137 | .Xr start-stop-daemon 8 | |
138 | will chroot into this path before writing the pid file or starting the daemon. | |
122 | 139 | .It Ar pidfile |
123 | 140 | Pidfile to use for the above defined command. |
124 | 141 | .It Ar name |
125 | 142 | Display name used for the above defined command. |
143 | .It Ar stopsig | |
144 | Signal to send when stopping the daemon. | |
126 | 145 | .It Ar retry |
127 | 146 | Retry schedule to use when stopping the daemon. It can either be a |
128 | 147 | timeout in seconds or multiple signal/timeout pairs (like SIGTERM/5). |
130 | 149 | A list of directories which must exist for the service to start. |
131 | 150 | .It Ar required_files |
132 | 151 | A list of files which must exist for the service to start. |
152 | .It Ar start_inactive | |
153 | Set to yes to have the service marked inactive when it starts. This is | |
154 | used along with in_background_fake to support re-entrant services. | |
155 | .It Ar in_background_fake | |
156 | Space separated list of commands which should always succeed when | |
157 | in_background is yes. | |
133 | 158 | .El |
134 | 159 | .Sh DEPENDENCIES |
135 | 160 | You should define a |
0 | .\" Copyright (c) 2015 William Hubbs | |
1 | .\" | |
2 | .\" Redistribution and use in source and binary forms, with or without | |
3 | .\" modification, are permitted provided that the following conditions | |
4 | .\" are met: | |
5 | .\" 1. Redistributions of source code must retain the above copyright | |
6 | .\" notice, this list of conditions and the following disclaimer. | |
7 | .\" 2. Redistributions in binary form must reproduce the above copyright | |
8 | .\" notice, this list of conditions and the following disclaimer in the | |
9 | .\" documentation and/or other materials provided with the distribution. | |
10 | .\" | |
11 | .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
12 | .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
13 | .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
14 | .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
15 | .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
16 | .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
17 | .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
18 | .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
19 | .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
20 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
21 | .\" SUCH DAMAGE. | |
22 | .\" | |
23 | .Dd April 24, 2008 | |
24 | .Dt RC-sstat 8 SMM | |
25 | .Os OpenRC | |
26 | .Sh NAME | |
27 | .Nm rc-sstat | |
28 | .Nd show status info about services supervised by s6 then rc-status | |
29 | info | |
30 | .Sh SYNOPSIS | |
31 | .Nm | |
32 | .Sh DESCRIPTION | |
33 | .Nm | |
34 | gathers and displays information about the status of services supervised | |
35 | by s6 then runs rc-status to show info about nnormal OpenRC services. | |
36 | .Pp | |
37 | .Sh EXIT STATUS | |
38 | .Nm | |
39 | exits 1 if there is an internal error or exits with the same exit codes | |
40 | as rc-status. | |
41 | .Sh SEE ALSO | |
42 | .Xr rc-status 8 , | |
43 | .Xr rc-update 8 | |
44 | .Sh AUTHORS | |
45 | .An William Hubbs <w.d.hubbs@gmail.com> |
86 | 86 | .Fl s , -stack |
87 | 87 | option is given then we either add or remove the runlevel from the runlevel. |
88 | 88 | This allows inheritance of runlevels. |
89 | ||
89 | .Pp | |
90 | 90 | If the |
91 | 91 | .Fl a, -all |
92 | 92 | option is given, we remove the service from all runlevels. This is |
5 | 5 | |
6 | 6 | .depend: ${SRCS} |
7 | 7 | rm -f .depend |
8 | ${CC} ${CPPFLAGS} -MM ${SRCS} > .depend | |
8 | ${CC} ${LOCAL_CPPFLAGS} ${CPPFLAGS} -MM ${SRCS} > .depend | |
9 | 9 | |
10 | 10 | depend: .depend extra_depend |
11 | 11 |
1 | 1 | # Copyright (c) 2008 Roy Marples <roy@marples.name> |
2 | 2 | # Released under the 2-clause BSD license. |
3 | 3 | |
4 | GITREF?= HEAD | |
4 | GITREF?= ${VERSION} | |
5 | 5 | DISTPREFIX?= ${NAME}-${VERSION} |
6 | 6 | DISTFILE?= ${DISTPREFIX}.tar.bz2 |
7 | 7 | |
8 | 8 | CLEANFILES+= ${NAME}-*.tar.bz2 |
9 | ||
10 | CHANGELOG_LIMIT?= --after="1 year ago" | |
9 | 11 | |
10 | 12 | _SNAP_SH= date -u +%Y%m%d%H%M |
11 | 13 | _SNAP:= $(shell ${_SNAP_SH}) |
12 | 14 | SNAP= ${_SNAP} |
13 | 15 | SNAPDIR= ${DISTPREFIX}-${SNAP} |
14 | 16 | SNAPFILE= ${SNAPDIR}.tar.bz2 |
17 | ||
18 | changelog: | |
19 | git log ${CHANGELOG_LIMIT} --format=full > ChangeLog | |
15 | 20 | |
16 | 21 | dist: |
17 | 22 | git archive --prefix=${DISTPREFIX}/ ${GITREF} | bzip2 > ${DISTFILE} |
28 | 33 | mkdir /tmp/${SNAPDIR} |
29 | 34 | cp -RPp * /tmp/${SNAPDIR} |
30 | 35 | (cd /tmp/${SNAPDIR}; make clean) |
31 | find /tmp/${SNAPDIR} -name .svn -exec rm -rf -- {} \; 2>/dev/null || true | |
36 | rm -rf /tmp/${SNAPDIR}/.git 2>/dev/null || true | |
32 | 37 | tar -cvjpf ${SNAPFILE} -C /tmp ${SNAPDIR} |
33 | 38 | rm -rf /tmp/${SNAPDIR} |
34 | 39 | ls -l ${SNAPFILE} |
0 | _GITVER_SH= if git rev-parse --short HEAD >/dev/null 2>&1; then \ | |
1 | printf "."; \ | |
2 | git rev-parse --short HEAD; \ | |
3 | else \ | |
4 | echo ""; \ | |
5 | fi | |
6 | _GITVER:= $(shell ${_GITVER_SH}) | |
7 | GITVER= ${_GITVER} |
0 | _GITVER_SH= if git rev-parse --short HEAD >/dev/null 2>&1; then \ | |
1 | printf "."; \ | |
2 | git rev-parse --short HEAD; \ | |
3 | else \ | |
4 | echo ""; \ | |
5 | fi | |
6 | _GITVER:= $(shell ${_GITVER_SH}) | |
7 | GITVER= ${_GITVER} |
20 | 20 | CLEANFILES+= ${OBJS} ${SOBJS} ${_LIBS} ${SHLIB_LINK} |
21 | 21 | |
22 | 22 | %.o: %.c |
23 | ${CC} ${CFLAGS} ${CPPFLAGS} -c $< -o $@ | |
23 | ${CC} ${LOCAL_CFLAGS} ${LOCAL_CPPFLAGS} ${CFLAGS} ${CPPFLAGS} -c $< -o $@ | |
24 | 24 | |
25 | 25 | %.So: %.c |
26 | ${CC} ${PICFLAG} -DPIC ${CPPFLAGS} ${CFLAGS} -c $< -o $@ | |
26 | ${CC} ${PICFLAG} -DPIC ${LOCAL_CFLAGS} ${LOCAL_CPPFLAGS} ${CPPFLAGS} ${CFLAGS} -c $< -o $@ | |
27 | 27 | |
28 | 28 | all: depend ${_LIBS} |
29 | 29 | |
39 | 39 | @${ECHO} building shared library $@ |
40 | 40 | @rm -f $@ ${SHLIB_LINK} |
41 | 41 | @ln -fs $@ ${SHLIB_LINK} |
42 | ${CC} ${CFLAGS} ${LDFLAGS} -shared -Wl,-x \ | |
42 | ${CC} ${LOCAL_CFLAGS} ${CFLAGS} ${LOCAL_LDFLAGS} ${LDFLAGS} -shared -Wl,-x \ | |
43 | 43 | -o $@ -Wl,-soname,${SONAME} \ |
44 | 44 | ${SOBJS} ${LDADD} |
45 | 45 |
2 | 2 | |
3 | 3 | # Generic definitions |
4 | 4 | |
5 | SFX= .GNU-kFreeBSD.in | |
6 | PKG_PREFIX?= /usr | |
7 | ||
5 | 8 | CPPFLAGS+= -D_BSD_SOURCE -D_XOPEN_SOURCE=700 |
6 | 9 | LIBDL= -Wl,-Bdynamic -ldl |
7 | 10 | LIBKVM?= |
8 | include ${MK}/os-BSD.mk |
0 | # Copyright (c) 2008 Roy Marples <roy@marples.name> | |
1 | # Released under the 2-clause BSD license. | |
2 | ||
3 | SFX= .GNU.in | |
4 | PKG_PREFIX?= /usr | |
5 | ||
6 | CPPFLAGS+= -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -DMAXPATHLEN=4096 -DPATH_MAX=4096 | |
7 | LIBDL= -Wl,-Bdynamic -ldl |
3 | 3 | SFX= .Linux.in |
4 | 4 | PKG_PREFIX?= /usr |
5 | 5 | |
6 | CPPFLAGS+= -D_BSD_SOURCE -D_XOPEN_SOURCE=700 | |
6 | CPPFLAGS+= -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700 | |
7 | 7 | LIBDL= -Wl,-Bdynamic -ldl |
8 | 8 | |
9 | 9 | ifeq (${MKSELINUX},yes) |
10 | 10 | CPPFLAGS+= -DHAVE_SELINUX |
11 | LIBSELINUX= -lselinux | |
11 | LIBSELINUX?= -lselinux | |
12 | 12 | LDADD += $(LIBSELINUX) |
13 | ||
14 | ifneq (${MKPAM},pam) | |
15 | # if using selinux but not pam then we need crypt | |
16 | LIBCRYPT?= -lcrypt | |
17 | LDADD += $(LIBCRYPT) | |
13 | 18 | endif |
19 | ||
20 | endif | |
21 | ||
22 | ifeq (${MKAUDIT},yes) | |
23 | LIBAUDIT?= -laudit | |
24 | CPPFLAGS+= -DHAVE_AUDIT | |
25 | LDADD+= ${LIBAUDIT} | |
26 | endif |
1 | 1 | LIBPAM?= -lpam |
2 | 2 | CPPFLAGS+= -DHAVE_PAM |
3 | 3 | LDADD+= ${LIBPAM} |
4 | ||
5 | ifeq (${MKSELINUX},yes) | |
6 | # with selinux, pam_misc is needed too | |
7 | LIBPAM_MISC?= -lpam_misc | |
8 | LDADD+= ${LIBPAM_MISC} | |
9 | endif | |
4 | 10 | |
5 | 11 | PAMDIR?= /etc/pam.d |
6 | 12 | PAMMODE?= 0644 |
0 | # rules to build a library | |
0 | # rules to build a program | |
1 | 1 | # based on FreeBSD's bsd.prog.mk |
2 | 2 | |
3 | 3 | # Copyright (c) 2008 Roy Marples <roy@marples.name> |
24 | 24 | all: depend ${PROG} |
25 | 25 | |
26 | 26 | %.o: %.c |
27 | ${CC} ${CFLAGS} ${CPPFLAGS} -c $< -o $@ | |
27 | ${CC} ${LOCAL_CFLAGS} ${LOCAL_CPPFLAGS} ${CFLAGS} ${CPPFLAGS} -c $< -o $@ | |
28 | 28 | |
29 | 29 | ${PROG}: ${SCRIPTS} ${OBJS} |
30 | ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${OBJS} ${LDADD} | |
30 | ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ ${OBJS} ${LDADD} | |
31 | 31 | |
32 | 32 | clean: |
33 | 33 | rm -f ${CLEANFILES} |
0 | 0 | ifeq (${MKTERMCAP},ncurses) |
1 | LTERMCAP:= $(shell pkg-config ncurses --libs 2> /dev/null) | |
1 | TERMCAP_CFLAGS:= $(shell pkg-config ncurses --cflags 2> /dev/null) | |
2 | LTERMCAP:= $(shell pkg-config ncurses --libs 2> /dev/null) | |
2 | 3 | ifeq ($(LTERMCAP),) |
3 | 4 | LIBTERMCAP?= -lncurses |
4 | 5 | else |
5 | 6 | LIBTERMCAP?= $(LTERMCAP) |
6 | 7 | endif |
7 | CPPFLAGS+= -DHAVE_TERMCAP | |
8 | CPPFLAGS+= -DHAVE_TERMCAP ${TERMCAP_CFLAGS} | |
8 | 9 | LDADD+= ${LIBTERMCAP} |
9 | 10 | else ifeq (${MKTERMCAP},termcap) |
10 | 11 | LIBTERMCAP?= -ltermcap |
33 | 33 | # FreeBSD specific stuff |
34 | 34 | BOOT-FreeBSD+= adjkerntz dumpon syscons |
35 | 35 | |
36 | BOOT-Linux+= hwclock keymaps modules mtab procfs termencoding tmpfiles.setup | |
36 | BOOT-Linux+= binfmt hwclock keymaps modules mtab procfs termencoding \ | |
37 | tmpfiles.setup | |
37 | 38 | SHUTDOWN-Linux= killprocs mount-ro |
38 | 39 | SYSINIT-Linux= devfs dmesg sysfs tmpfiles.dev |
39 | 40 |
0 | # Using S6 with OpenRC | |
1 | ||
2 | Beginning with OpenRC-0.16, we support using the s6 supervision suite | |
3 | from Skarmet Software in place of start-stop-daemon for monitoring | |
4 | daemons [1]. | |
5 | ||
6 | ## Setup | |
7 | ||
8 | Documenting s6 in detail is beyond the scope of this guide. It will | |
9 | document how to set up OpenRC services to communicate with s6. | |
10 | ||
11 | ### Use Default start, stop and status functions | |
12 | ||
13 | If you write your own start, stop and status functions in your service | |
14 | script, none of this will work. You must allow OpenRC to use the default | |
15 | functions. | |
16 | ||
17 | ### Dependencies | |
18 | ||
19 | All OpenRC service scripts that want their daemons monitored by s6 | |
20 | should have the following line added to their dependencies to make sure | |
21 | the s6 scan directory is being monitored. | |
22 | ||
23 | need s6-svscan | |
24 | ||
25 | ### Variable Settings | |
26 | ||
27 | The most important setting is the supervisor variable. At the top of | |
28 | your service script, you should set this variable as follows: | |
29 | ||
30 | supervisor=s6 | |
31 | ||
32 | Several other variables affect s6 services. They are documented on the | |
33 | openrc-run man page, but I will list them here for convenience: | |
34 | ||
35 | s6_service_path - the path to the s6 service directory. The default is | |
36 | /var/svc.d/$RC_SVCNAME. | |
37 | ||
38 | s6_svwait_options_start - the options to pass to s6-svwait when starting | |
39 | the service. If this is not set, s6-svwait will not be called. | |
40 | ||
41 | s6_service_timeout_stop - the amount of time, in milliseconds, s6-svc | |
42 | should wait for a service to go down when stopping. | |
43 | ||
44 | This is very early support, so feel free to file bugs if you have | |
45 | issues. | |
46 | ||
47 | [1] http://www.skarnet.org/software/s6 |
0 | rc-sstat |
0 | MK= ../mk | |
1 | include ${MK}/os.mk | |
2 | ||
0 | 3 | DIR= ${LIBEXECDIR}/bin |
1 | 4 | BIN= on_ac_power |
5 | INSTALLAFTER = _installafter | |
2 | 6 | |
3 | MK= ../mk | |
7 | ifeq (${OS},Linux) | |
8 | SRCS+= rc-sstat.in | |
9 | BIN+= rc-sstat | |
10 | endif | |
11 | ||
12 | _installafter: | |
13 | ifeq (${OS},Linux) | |
14 | ${INSTALL} -d ${DESTDIR}${SBINDIR} | |
15 | ln -s ${DIR}/rc-sstat ${DESTDIR}/${SBINDIR}/rc-sstat | |
16 | endif | |
17 | ||
4 | 18 | include ${MK}/scripts.mk |
0 | #!@SHELL@ | |
1 | ||
2 | # Define variables | |
3 | scandir="/run/openrc/s6-scan" | |
4 | statfile=/dev/shm/s6-svstat.${USER} | |
5 | ||
6 | color_red='\E[01;31m' | |
7 | color_green='\E[32m' | |
8 | color_yellow='\E[01;33m' | |
9 | ||
10 | # Time Modules | |
11 | uptimeModules() { | |
12 | # Given a single integer argument representing seconds of uptime... | |
13 | # convert uptime to a friendly human readable string: '2d 16h 58m 46s' | |
14 | # define a variable to keep track of the longest length uptime string | |
15 | uSec=${1:-0} | |
16 | ||
17 | uDay=$(( $uSec / 86400 )) | |
18 | uSec=$(( $uSec % 86400 )) | |
19 | uHour=$(( $uSec / 3600 )) | |
20 | uSec=$(( $uSec % 3600 )) | |
21 | uMin=$(( $uSec / 60 )) | |
22 | uSec=$(( $uSec % 60 )) | |
23 | ||
24 | [ $uDay -ne 0 ] && pDay="${uDay}d " || pDay="" | |
25 | [ $uHour -ne 0 ] && pHour="${uHour}h " || pHour="" | |
26 | [ $uMin -ne 0 ] && pMin="${uMin}m " || pMin="" | |
27 | [ $uSec -ne 0 ] && pSec="${uSec}s " || pSec="" | |
28 | ||
29 | parsedUptime="$( echo ${pDay}${pHour}${pMin}${pSec} | sed 's#[ \t]*$##' )" | |
30 | uCharCount=${#parsedUptime} | |
31 | } | |
32 | ||
33 | # Make sure we are running as root | |
34 | if [ $(id -u) != 0 ]; then | |
35 | printf "This command must be run as root\n" | |
36 | exit 1 | |
37 | fi | |
38 | ||
39 | # Make sure scandir exists | |
40 | if [ ! -d $scandir ]; then | |
41 | printf "%s\n" "$scandir does not exist" | |
42 | exit 1 | |
43 | fi | |
44 | ||
45 | # Make sure s6-svscan is running | |
46 | if ! pgrep s6-svscan >/dev/null ; then | |
47 | printf "s6-svscan is not running\n" | |
48 | exit 1 | |
49 | fi | |
50 | ||
51 | # If TERM is undefined (launching sstat through an ssh command) then make it vt100 | |
52 | if [ -z $TERM -o $TERM = "dumb" ]; then | |
53 | export TERM=vt100 | |
54 | fi | |
55 | ||
56 | # Gather list of candidate services s6-supervise may be supervising | |
57 | # filter for folders and symlinks at /run/openrc/s6-scan/* ommiting output starting with '.' | |
58 | services="$(find $scandir -maxdepth 1 -mindepth 1 \( -type d -or -type l \) | awk -F'/' '{ if ( $NF !~ "^\\." ) print $NF}')" | |
59 | if [ -z "$services" ]; then | |
60 | printf "s6 found no services configured for supervision\n" | |
61 | exit 1 | |
62 | fi | |
63 | ||
64 | # Gather status for each service from s6-svstat | |
65 | # write to tmp file in memory for non I/O bound repeatative access | |
66 | rm -f $statfile 2>/dev/null | |
67 | for service in $services ; do | |
68 | echo "$service $(s6-svstat ${scandir}/${service})" >> $statfile | |
69 | done | |
70 | ||
71 | # Define longest string from parsed uptime (default to 7 to match string length of 'Up Time') | |
72 | timeStringLength=7 | |
73 | for uptime in $(awk '$2 == "up" {print $5}' $statfile | sort -run) | |
74 | do | |
75 | uptimeModules $uptime | |
76 | [ ${uCharCount} -gt $timeStringLength ] && timeStringLength=$uCharCount | |
77 | done | |
78 | ||
79 | ||
80 | # Print the status header like so... | |
81 | # Service Name State PID Up Time Start Time | |
82 | #---------------------------- ----- ----- -------------- ------------------- | |
83 | printf "\n" | |
84 | printf "%28s %5s %5s %${timeStringLength}s %19s\n" "Service Name" "State" "PID" "Up Time" "Start Time" | |
85 | for dashes in 28 5 5 $timeStringLength 19 ; do | |
86 | printf "%0.s-" $(seq 1 $dashes) ; echo -n ' ' | |
87 | done && printf "\n" | |
88 | ||
89 | ||
90 | # sshd up (pid 26300) 80373 seconds | |
91 | cat $statfile | \ | |
92 | while read line | |
93 | do | |
94 | set $line | |
95 | ||
96 | service=$1 | |
97 | state=$2 | |
98 | pid=${4/)/} | |
99 | time=$5 | |
100 | ||
101 | # call function to convert time in seconds and define additional variables | |
102 | uptimeModules $time | |
103 | ||
104 | if [ "$state" = up ]; then | |
105 | if [ $time -lt 30 ]; then | |
106 | # uptime < 30 seconds, color the whole line yellow | |
107 | echo -en "$color_yellow" | |
108 | # 1st 4 columns are printed with printf for space padding | |
109 | printf "%28s %5s %5s %${timeStringLength}s" $service $state $pid "$parsedUptime" | |
110 | # 4th column is output from date -d | |
111 | echo -e " $(date -d "${time} seconds ago" "+%F %T")" | |
112 | # reset terminal colors | |
113 | tput sgr0 | |
114 | else | |
115 | printf "%28s" $service | |
116 | # uptime > 30 seconds, color just the "state" value green | |
117 | echo -en "$color_green" | |
118 | printf " %5s" $state | |
119 | # reset terminal colors | |
120 | tput sgr0 | |
121 | printf " %5s" $pid | |
122 | printf " %${timeStringLength}s" "$parsedUptime" | |
123 | echo -e " $(date -d "${time} seconds ago" "+%F %T")" | |
124 | fi | |
125 | else | |
126 | printf "%28s" $service | |
127 | echo -en "$color_red" | |
128 | printf " %5s" $state | |
129 | tput sgr0 | |
130 | echo "" | |
131 | fi | |
132 | done | |
133 | ||
134 | # Cleanup | |
135 | rm -f $statfile 2>/dev/null | |
136 | ||
137 | printf "\n\n" | |
138 | ||
139 | rc-status |
0 | 0 | functions.sh |
1 | 1 | gendepends.sh |
2 | 2 | rc-functions.sh |
3 | runscript.sh | |
3 | openrc-run.sh | |
4 | 4 | cgroup-release-agent.sh |
5 | 5 | init.sh |
6 | 6 | init-early.sh |
7 | 7 | rc-cgroup.sh |
8 | 8 | tmpfiles.sh |
9 | 9 | migrate-to-run.sh |
10 | binfmt.sh |
0 | 0 | DIR= ${LIBEXECDIR}/sh |
1 | 1 | SRCS= init.sh.in functions.sh.in gendepends.sh.in \ |
2 | rc-functions.sh.in runscript.sh.in tmpfiles.sh.in ${SRCS-${OS}} | |
3 | INC= rc-mount.sh functions.sh rc-functions.sh | |
4 | BIN= gendepends.sh init.sh runscript.sh tmpfiles.sh ${BIN-${OS}} | |
2 | openrc-run.sh.in rc-functions.sh.in tmpfiles.sh.in ${SRCS-${OS}} | |
3 | INC= rc-mount.sh functions.sh rc-functions.sh s6.sh start-stop-daemon.sh | |
4 | BIN= gendepends.sh init.sh openrc-run.sh tmpfiles.sh ${BIN-${OS}} | |
5 | 5 | |
6 | 6 | INSTALLAFTER= _installafter |
7 | 7 | |
11 | 11 | SRCS-FreeBSD= |
12 | 12 | BIN-FreeBSD= |
13 | 13 | |
14 | SRCS-Linux= cgroup-release-agent.sh.in init-early.sh.in migrate-to-run.sh.in \ | |
15 | rc-cgroup.sh.in | |
16 | BIN-Linux= cgroup-release-agent.sh init-early.sh migrate-to-run.sh \ | |
14 | SRCS-Linux= binfmt.sh.in cgroup-release-agent.sh.in init-early.sh.in \ | |
15 | migrate-to-run.sh.in rc-cgroup.sh.in | |
16 | BIN-Linux= binfmt.sh cgroup-release-agent.sh init-early.sh migrate-to-run.sh \ | |
17 | 17 | rc-cgroup.sh |
18 | 18 | |
19 | 19 | SRCS-NetBSD= |
0 | #!@SHELL@ | |
1 | # This is a reimplementation of the systemd binfmt.d code to register | |
2 | # misc binary formats with the kernel. | |
3 | # | |
4 | # Copyright (c) 2015 William Hubbs <w.d.hubbs@gmail.com> | |
5 | # Released under the 2-clause BSD license. | |
6 | # | |
7 | # See the binfmt.d manpage as well: | |
8 | # http://0pointer.de/public/systemd-man/binfmt.d.html | |
9 | # This script should match the manpage as of 2015/03/31 | |
10 | # | |
11 | ||
12 | apply_file() { | |
13 | [ $# -lt 1 ] && return 0 | |
14 | FILE="$1" | |
15 | LINENUM=0 | |
16 | ||
17 | ### FILE FORMAT ### | |
18 | # See https://www.kernel.org/doc/Documentation/binfmt_misc.txt | |
19 | while read line; do | |
20 | LINENUM=$(( LINENUM+1 )) | |
21 | case $line in | |
22 | \#*) continue ;; | |
23 | \;*) continue ;; | |
24 | esac | |
25 | ||
26 | echo "${line}" > /proc/sys/fs/binfmt_misc/register | |
27 | rc=$? | |
28 | if [ $rc -ne 0 ]; then | |
29 | printf "binfmt: invalid entry on line %d of \`%s'\n" \ | |
30 | "$LINENUM" "$FILE" >&2 | |
31 | error=1 | |
32 | fi | |
33 | done <$FILE | |
34 | return $rc | |
35 | } | |
36 | ||
37 | [ -e /proc/sys/fs/binfmt_misc/register ] || exit 0 | |
38 | error=0 | |
39 | if [ $# -gt 0 ]; then | |
40 | while [ $# -gt 0 ]; do | |
41 | apply_file "$1" | |
42 | shift | |
43 | done | |
44 | else | |
45 | # The hardcoding of these paths is intentional; we are following the | |
46 | # systemd spec. | |
47 | binfmt_dirs='/usr/lib/binfmt.d/ /run/binfmt.d/ /etc/binfmt.d/' | |
48 | binfmt_basenames='' | |
49 | binfmt_d='' | |
50 | ||
51 | # Build a list of sorted unique basenames | |
52 | # directories declared later in the binfmt_d list will override earlier | |
53 | # directories, on a per file basename basis. | |
54 | # `/run/binfmt.d/foo.conf' supersedes `/usr/lib/binfmt.d/foo.conf'. | |
55 | # `/run/binfmt.d/foo.conf' will always be read after `/etc/binfmt.d/bar.conf' | |
56 | for d in ${binfmt_dirs} ; do | |
57 | [ -d $d ] && for f in ${d}/*.conf ; do | |
58 | case "${f##*/}" in | |
59 | systemd.conf|systemd-*.conf) continue;; | |
60 | esac | |
61 | [ -e $f ] && binfmt_basenames="${binfmt_basenames}\n${f##*/}" | |
62 | done # for f in ${d} | |
63 | done # for d in ${binfmt_dirs} | |
64 | binfmt_basenames="$(printf "${binfmt_basenames}\n" | sort -u )" | |
65 | ||
66 | for b in $binfmt_basenames ; do | |
67 | real_f='' | |
68 | for d in $binfmt_dirs ; do | |
69 | f=${d}/${b} | |
70 | [ -e "${f}" ] && real_f=$f | |
71 | done | |
72 | [ -e "${real_f}" ] && binfmt_d="${binfmt_d} ${real_f}" | |
73 | done | |
74 | ||
75 | # loop through the gathered fragments, sorted globally by filename. | |
76 | # `/run/binfmt.d/foo.conf' will always be read after `/etc/binfmt.d/bar.conf' | |
77 | for FILE in $binfmt_d ; do | |
78 | apply_file "$FILE" | |
79 | done | |
80 | fi | |
81 | ||
82 | exit $error | |
83 | ||
84 | # vim: set ts=2 sw=2 sts=2 noet ft=sh: |
0 | #!@SHELL@ | |
1 | # Copyright (c) 2007-2009 Roy Marples <roy@marples.name> | |
2 | # Released under the 2-clause BSD license. | |
3 | ||
4 | if [ ! -d /run ]; then | |
5 | ebegin "Creating /run" | |
6 | mkdir -p /run | |
7 | eend $? | |
8 | fi | |
9 | ||
10 | if [ -L $RC_SVCDIR ]; then | |
11 | rm $RC_SVCDIR | |
12 | fi | |
13 | ||
14 | ebegin "Mounting /run" | |
15 | if ! fstabinfo --mount /run; then | |
16 | mount -t tmpfs -o mode=0755,noexec,nosuid,size=10% tmpfs /run | |
17 | if [ $? != 0 ]; then | |
18 | eerror "Unable to mount tmpfs on /run." | |
19 | eerror "Can't continue." | |
20 | exit 1 | |
21 | fi | |
22 | fi | |
23 | eend | |
24 | ||
25 | ebegin "Creating $RC_SVCDIR" | |
26 | mkdir -p $RC_SVCDIR | |
27 | eend $? | |
28 | ||
29 | if [ -e "$RC_LIBEXECDIR"/cache/deptree ]; then | |
30 | cp -p "$RC_LIBEXECDIR"/cache/* "$RC_SVCDIR" 2>/dev/null | |
31 | fi | |
32 | ||
33 | echo sysinit >"$RC_SVCDIR"/softlevel | |
34 | exit 0 |
0 | #!@SHELL@ | |
1 | # Copyright (c) 2007-2009 Roy Marples <roy@marples.name> | |
2 | # Copyright (c) 2014 Svante Signell <svante.signell@gmail.com> | |
3 | # Released under the 2-clause BSD license. | |
4 | ||
5 | if [ ! -d /run ]; then | |
6 | ebegin "Creating /run" | |
7 | mkdir -p /run | |
8 | eend $? | |
9 | fi | |
10 | ||
11 | if [ -L $RC_SVCDIR ]; then | |
12 | rm $RC_SVCDIR | |
13 | fi | |
14 | ||
15 | if ! mountinfo -q /run; then | |
16 | ebegin "Mounting /run" | |
17 | if ! fstabinfo --mount /run; then | |
18 | mount -t tmpfs -o mode=0755,no-suid,size=10% tmpfs /run | |
19 | if [ $? != 0 ]; then | |
20 | eerror "Unable to mount tmpfs on /run." | |
21 | eerror "Can't continue." | |
22 | exit 1 | |
23 | fi | |
24 | fi | |
25 | eend | |
26 | fi | |
27 | ||
28 | ebegin "Creating $RC_SVCDIR" | |
29 | mkdir -p $RC_SVCDIR | |
30 | eend $? | |
31 | ||
32 | if [ -e "$RC_LIBEXECDIR"/cache/deptree ]; then | |
33 | cp -p "$RC_LIBEXECDIR"/cache/* "$RC_SVCDIR" 2>/dev/null | |
34 | fi | |
35 | ||
36 | echo sysinit >"$RC_SVCDIR"/softlevel | |
37 | exit 0 |
0 | #!@SHELL@ | |
1 | # Shell wrapper for openrc-run | |
2 | ||
3 | # Copyright (c) 2007-2009 Roy Marples <roy@marples.name> | |
4 | # Released under the 2-clause BSD license. | |
5 | ||
6 | verify_boot() | |
7 | { | |
8 | if [ ! -e ${RC_SVCDIR}/softlevel ]; then | |
9 | eerror "You are attempting to run an openrc service on a" | |
10 | eerror "system which openrc did not boot." | |
11 | eerror "You may be inside a chroot or you may have used" | |
12 | eerror "another initialization system to boot this system." | |
13 | eerror "In this situation, you will get unpredictable results!" | |
14 | eerror | |
15 | eerror "If you really want to do this, issue the following command:" | |
16 | eerror "touch ${RC_SVCDIR}/softlevel" | |
17 | exit 1 | |
18 | fi | |
19 | return 0 | |
20 | } | |
21 | ||
22 | sourcex() | |
23 | { | |
24 | if [ "$1" = "-e" ]; then | |
25 | shift | |
26 | [ -e "$1" ] || return 1 | |
27 | fi | |
28 | if ! . "$1"; then | |
29 | eerror "$RC_SVCNAME: error loading $1" | |
30 | exit 1 | |
31 | fi | |
32 | } | |
33 | ||
34 | sourcex "@LIBEXECDIR@/sh/functions.sh" | |
35 | sourcex "@LIBEXECDIR@/sh/rc-functions.sh" | |
36 | case $RC_SYS in | |
37 | PREFIX|SYSTEMD-NSPAWN) ;; | |
38 | *) sourcex -e "@LIBEXECDIR@/sh/rc-cgroup.sh";; | |
39 | esac | |
40 | ||
41 | # Support LiveCD foo | |
42 | if sourcex -e "/sbin/livecd-functions.sh"; then | |
43 | livecd_read_commandline | |
44 | fi | |
45 | ||
46 | if [ -z "$1" -o -z "$2" ]; then | |
47 | eerror "$RC_SVCNAME: not enough arguments" | |
48 | exit 1 | |
49 | fi | |
50 | ||
51 | # So daemons know where to recall us if needed | |
52 | RC_SERVICE="$1" ; export RC_SERVICE | |
53 | shift | |
54 | ||
55 | # Compat | |
56 | SVCNAME=$RC_SVCNAME ; export SVCNAME | |
57 | ||
58 | # Dependency function | |
59 | config() { | |
60 | [ -n "$*" ] && echo "config $*" | |
61 | } | |
62 | need() { | |
63 | [ -n "$*" ] && echo "need $*" | |
64 | } | |
65 | use() { | |
66 | [ -n "$*" ] && echo "use $*" | |
67 | } | |
68 | before() { | |
69 | [ -n "$*" ] && echo "before $*" | |
70 | } | |
71 | after() { | |
72 | [ -n "$*" ] && echo "after $*" | |
73 | } | |
74 | provide() { | |
75 | [ -n "$*" ] && echo "provide $*" | |
76 | } | |
77 | keyword() { | |
78 | [ -n "$*" ] && echo "keyword $*" | |
79 | } | |
80 | ||
81 | # Describe the init script to the user | |
82 | describe() | |
83 | { | |
84 | if [ -n "$description" ]; then | |
85 | einfo "$description" | |
86 | else | |
87 | ewarn "No description for $RC_SVCNAME" | |
88 | fi | |
89 | ||
90 | local svc= desc= | |
91 | for svc in ${extra_commands:-$opts} $extra_started_commands \ | |
92 | $extra_stopped_commands; do | |
93 | eval desc=\$description_$svc | |
94 | if [ -n "$desc" ]; then | |
95 | einfo "$HILITE$svc$NORMAL: $desc" | |
96 | else | |
97 | ewarn "$HILITE$svc$NORMAL: no description" | |
98 | fi | |
99 | done | |
100 | } | |
101 | ||
102 | # Report status | |
103 | _status() | |
104 | { | |
105 | if service_stopping; then | |
106 | ewarn "status: stopping" | |
107 | return 4 | |
108 | elif service_starting; then | |
109 | ewarn "status: starting" | |
110 | return 8 | |
111 | elif service_inactive; then | |
112 | ewarn "status: inactive" | |
113 | return 16 | |
114 | elif service_started; then | |
115 | if service_crashed; then | |
116 | eerror "status: crashed" | |
117 | return 32 | |
118 | fi | |
119 | einfo "status: started" | |
120 | return 0 | |
121 | else | |
122 | einfo "status: stopped" | |
123 | return 3 | |
124 | fi | |
125 | } | |
126 | ||
127 | # Template start / stop / status functions | |
128 | # These functions select the appropriate function to call from the | |
129 | # supervisor modules | |
130 | start() | |
131 | { | |
132 | local func=ssd_start | |
133 | case "$supervisor" in | |
134 | s6) func=s6_start ;; | |
135 | ?*) | |
136 | ewarn "Invalid supervisor, \"$supervisor\", using start-stop-daemon" | |
137 | ;; | |
138 | esac | |
139 | $func | |
140 | } | |
141 | ||
142 | stop() | |
143 | { | |
144 | local func=ssd_stop | |
145 | case "$supervisor" in | |
146 | s6) func=s6_stop ;; | |
147 | ?*) | |
148 | ewarn "Invalid supervisor, \"$supervisor\", using start-stop-daemon" | |
149 | ;; | |
150 | esac | |
151 | $func | |
152 | } | |
153 | ||
154 | status() | |
155 | { | |
156 | local func=ssd_status | |
157 | case "$supervisor" in | |
158 | s6) func=s6_status ;; | |
159 | ?*) | |
160 | ewarn "Invalid supervisor, \"$supervisor\", using start-stop-daemon" | |
161 | ;; | |
162 | esac | |
163 | $func | |
164 | } | |
165 | ||
166 | yesno $RC_DEBUG && set -x | |
167 | ||
168 | _conf_d=${RC_SERVICE%/*}/../conf.d | |
169 | # If we're net.eth0 or openvpn.work then load net or openvpn config | |
170 | _c=${RC_SVCNAME%%.*} | |
171 | if [ -n "$_c" -a "$_c" != "$RC_SVCNAME" ]; then | |
172 | if ! sourcex -e "$_conf_d/$_c.$RC_RUNLEVEL"; then | |
173 | sourcex -e "$_conf_d/$_c" | |
174 | fi | |
175 | fi | |
176 | unset _c | |
177 | ||
178 | # Overlay with our specific config | |
179 | if ! sourcex -e "$_conf_d/$RC_SVCNAME.$RC_RUNLEVEL"; then | |
180 | sourcex -e "$_conf_d/$RC_SVCNAME" | |
181 | fi | |
182 | unset _conf_d | |
183 | ||
184 | # Load any system overrides | |
185 | sourcex -e "@SYSCONFDIR@/rc.conf" | |
186 | ||
187 | # load service supervisor functions | |
188 | sourcex "@LIBEXECDIR@/sh/s6.sh" | |
189 | sourcex "@LIBEXECDIR@/sh/start-stop-daemon.sh" | |
190 | ||
191 | # Set verbose mode | |
192 | if yesno "${rc_verbose:-$RC_VERBOSE}"; then | |
193 | EINFO_VERBOSE=yes | |
194 | export EINFO_VERBOSE | |
195 | fi | |
196 | ||
197 | for _cmd; do | |
198 | if [ "$_cmd" != status -a "$_cmd" != describe ]; then | |
199 | # Apply any ulimit defined | |
200 | [ -n "${rc_ulimit:-$RC_ULIMIT}" ] && \ | |
201 | ulimit ${rc_ulimit:-$RC_ULIMIT} | |
202 | # Apply cgroups settings if defined | |
203 | if [ "$(command -v cgroup_add_service)" = \ | |
204 | "cgroup_add_service" ] | |
205 | then | |
206 | if [ -d /sys/fs/cgroup -a ! -w /sys/fs/cgroup ]; then | |
207 | eerror "No permission to apply cgroup settings" | |
208 | break | |
209 | fi | |
210 | cgroup_add_service /sys/fs/cgroup/openrc | |
211 | cgroup_add_service /sys/fs/cgroup/systemd/system | |
212 | fi | |
213 | [ "$(command -v cgroup_set_limits)" = \ | |
214 | "cgroup_set_limits" ] && \ | |
215 | cgroup_set_limits | |
216 | break | |
217 | fi | |
218 | done | |
219 | ||
220 | # Load our script | |
221 | sourcex "$RC_SERVICE" | |
222 | ||
223 | eval "printf '%s\n' $required_dirs" | while read _d; do | |
224 | if [ -n "$_d" ] && [ ! -d "$_d" ]; then | |
225 | eerror "$RC_SVCNAME: \`$_d' is not a directory" | |
226 | exit 1 | |
227 | fi | |
228 | done | |
229 | [ $? -ne 0 ] && exit 1 | |
230 | unset _d | |
231 | ||
232 | eval "printf '%s\n' $required_files" | while read _f; do | |
233 | if [ -n "$_f" ] && [ ! -r "$_f" ]; then | |
234 | eerror "$RC_SVCNAME: \`$_f' is not readable" | |
235 | exit 1 | |
236 | fi | |
237 | done | |
238 | [ $? -ne 0 ] && exit 1 | |
239 | unset _f | |
240 | ||
241 | if [ -n "$opts" ]; then | |
242 | ewarn "Use of the opts variable is deprecated and will be" | |
243 | ewarn "removed in the future." | |
244 | ewarn "Please use extra_commands, extra_started_commands or extra_stopped_commands." | |
245 | fi | |
246 | ||
247 | while [ -n "$1" ]; do | |
248 | # Special case depend | |
249 | if [ "$1" = depend ]; then | |
250 | shift | |
251 | ||
252 | # Enter the dir of the init script to fix the globbing | |
253 | # bug 412677 | |
254 | cd ${RC_SERVICE%/*} | |
255 | _depend | |
256 | cd / | |
257 | continue | |
258 | fi | |
259 | # See if we have the required function and run it | |
260 | for _cmd in describe start stop status ${extra_commands:-$opts} \ | |
261 | $extra_started_commands $extra_stopped_commands | |
262 | do | |
263 | if [ "$_cmd" = "$1" ]; then | |
264 | if [ "$(command -v "$1")" = "$1" ]; then | |
265 | # If we're in the background, we may wish to | |
266 | # fake some commands. We do this so we can | |
267 | # "start" ourselves from inactive which then | |
268 | # triggers other services to start which | |
269 | # depend on us. | |
270 | # A good example of this is openvpn. | |
271 | if yesno $IN_BACKGROUND; then | |
272 | for _cmd in $in_background_fake; do | |
273 | if [ "$_cmd" = "$1" ]; then | |
274 | shift | |
275 | continue 3 | |
276 | fi | |
277 | done | |
278 | fi | |
279 | # Check to see if we need to be started before | |
280 | # we can run this command | |
281 | for _cmd in $extra_started_commands; do | |
282 | if [ "$_cmd" = "$1" ]; then | |
283 | if verify_boot && ! service_started; then | |
284 | eerror "$RC_SVCNAME: cannot \`$1' as it has not been started" | |
285 | exit 1 | |
286 | fi | |
287 | fi | |
288 | done | |
289 | # Check to see if we need to be stopped before | |
290 | # we can run this command | |
291 | for _cmd in $extra_stopped_commands; do | |
292 | if [ "$_cmd" = "$1" ]; then | |
293 | if verify_boot && ! service_stopped; then | |
294 | eerror "$RC_SVCNAME: cannot \`$1' as it has not been stopped" | |
295 | exit 1 | |
296 | fi | |
297 | fi | |
298 | done | |
299 | unset _cmd | |
300 | case $1 in | |
301 | start|stop|status) verify_boot;; | |
302 | esac | |
303 | if [ "$(command -v "$1_pre")" = "$1_pre" ] | |
304 | then | |
305 | "$1"_pre || exit $? | |
306 | fi | |
307 | "$1" || exit $? | |
308 | if [ "$(command -v "$1_post")" = "$1_post" ] | |
309 | then | |
310 | "$1"_post || exit $? | |
311 | fi | |
312 | [ "$(command -v cgroup_cleanup)" = "cgroup_cleanup" -a \ | |
313 | "$1" = "stop" ] && \ | |
314 | yesno "${rc_cgroup_cleanup}" && \ | |
315 | cgroup_cleanup | |
316 | shift | |
317 | continue 2 | |
318 | else | |
319 | if [ "$_cmd" = "start" -o "$_cmd" = "stop" ] | |
320 | then | |
321 | shift | |
322 | continue 2 | |
323 | else | |
324 | eerror "$RC_SVCNAME: function \`$1' defined but does not exist" | |
325 | exit 1 | |
326 | fi | |
327 | fi | |
328 | fi | |
329 | done | |
330 | eerror "$RC_SVCNAME: unknown function \`$1'" | |
331 | exit 1 | |
332 | done | |
333 | ||
334 | exit 0 |
0 | 0 | #!@SHELL@ |
1 | 1 | # Copyright (c) 2012 Alexander Vershilov <qnikst@gentoo.org> |
2 | 2 | # Released under the 2-clause BSD license. |
3 | ||
3 | 4 | extra_stopped_commands="${extra_stopped_commands} cgroup_cleanup" |
5 | description_cgroup_cleanup="Kill all processes in the cgroup" | |
4 | 6 | |
5 | 7 | cgroup_find_path() |
6 | 8 | { |
45 | 47 | $controller.*) |
46 | 48 | if [ -n "$name" -a -f "$cgroup/$name" -a -n "$val" ]; then |
47 | 49 | veinfo "$RC_SVCNAME: Setting $cgroup/$name to $val" |
48 | echo $val > "$cgroup/$name" | |
50 | printf "%s" "$val" > "$cgroup/$name" | |
49 | 51 | fi |
50 | 52 | name=$1 |
51 | 53 | val= |
52 | 54 | ;; |
53 | 55 | *) |
54 | val="$val $1" | |
56 | [ -n "$val" ] && | |
57 | val="$val $1" || | |
58 | val="$1" | |
55 | 59 | ;; |
56 | 60 | esac |
57 | 61 | shift |
58 | 62 | done |
59 | 63 | if [ -n "$name" -a -f "$cgroup/$name" -a -n "$val" ]; then |
60 | 64 | veinfo "$RC_SVCNAME: Setting $cgroup/$name to $val" |
61 | echo $val > "$cgroup/$name" | |
65 | printf "%s" "$val" > "$cgroup/$name" | |
62 | 66 | fi |
63 | 67 | |
64 | 68 | if [ -f "$cgroup/tasks" ]; then |
65 | 69 | veinfo "$RC_SVCNAME: adding to $cgroup/tasks" |
66 | echo 0 > "$cgroup/tasks" | |
70 | printf "%d" 0 > "$cgroup/tasks" | |
67 | 71 | fi |
68 | 72 | |
69 | 73 | return 0 |
76 | 80 | # cgroups. But may lead to a problems where that inheriting |
77 | 81 | # is needed. |
78 | 82 | for d in /sys/fs/cgroup/* ; do |
79 | [ -f "${d}"/tasks ] && echo 0 > "${d}"/tasks | |
83 | [ -f "${d}"/tasks ] && printf "%d" 0 > "${d}"/tasks | |
80 | 84 | done |
81 | 85 | |
82 | 86 | openrc_cgroup=/sys/fs/cgroup/openrc |
83 | 87 | if [ -d "$openrc_cgroup" ]; then |
84 | 88 | cgroup="$openrc_cgroup/$RC_SVCNAME" |
85 | 89 | mkdir -p "$cgroup" |
86 | [ -f "$cgroup/tasks" ] && echo 0 > "$cgroup/tasks" | |
90 | [ -f "$cgroup/tasks" ] && printf "%d" 0 > "$cgroup/tasks" | |
87 | 91 | fi |
88 | 92 | } |
89 | 93 | |
104 | 108 | local devices="${rc_cgroup_devices:-$RC_CGROUP_DEVICES}" |
105 | 109 | [ -n "$devices" ] && cgroup_set_values devices "$devices" |
106 | 110 | |
111 | local hugetlb="${rc_cgroup_hugetlb:-$RC_CGROUP_HUGETLB}" | |
112 | [ -n "$hugetlb" ] && cgroup_set_values hugetlb "$hugetlb" | |
113 | ||
107 | 114 | local memory="${rc_cgroup_memory:-$RC_CGROUP_MEMORY}" |
108 | 115 | [ -n "$memory" ] && cgroup_set_values memory "$memory" |
109 | 116 | |
117 | local net_cls="${rc_cgroup_net_cls:-$RC_CGROUP_NET_CLS}" | |
118 | [ -n "$net_cls" ] && cgroup_set_values net_cls "$net_cls" | |
119 | ||
110 | 120 | local net_prio="${rc_cgroup_net_prio:-$RC_CGROUP_NET_PRIO}" |
111 | 121 | [ -n "$net_prio" ] && cgroup_set_values net_prio "$net_prio" |
122 | ||
123 | local pids="${rc_cgroup_pids:-$RC_CGROUP_PIDS}" | |
124 | [ -n "$pids" ] && cgroup_set_values pids "$pids" | |
112 | 125 | |
113 | 126 | return 0 |
114 | 127 | } |
84 | 84 | return 1 |
85 | 85 | } |
86 | 86 | |
87 | # Called from runscript.sh or gendepends.sh | |
87 | # Called from openrc-run.sh or gendepends.sh | |
88 | 88 | _depend() { |
89 | 89 | depend |
90 | 90 | local _rc_svcname=$(shell_var "$RC_SVCNAME") _deptype= _depends= |
0 | #!@SHELL@ | |
1 | # Shell wrapper for runscript | |
2 | ||
3 | # Copyright (c) 2007-2009 Roy Marples <roy@marples.name> | |
4 | # Released under the 2-clause BSD license. | |
5 | ||
6 | verify_boot() | |
7 | { | |
8 | if [ ! -e ${RC_SVCDIR}/softlevel ]; then | |
9 | eerror "You are attempting to run an openrc service on a" | |
10 | eerror "system which openrc did not boot." | |
11 | eerror "You may be inside a chroot or you may have used" | |
12 | eerror "another initialization system to boot this system." | |
13 | eerror "In this situation, you will get unpredictable results!" | |
14 | eerror | |
15 | eerror "If you really want to do this, issue the following command:" | |
16 | eerror "touch ${RC_SVCDIR}/softlevel" | |
17 | exit 1 | |
18 | fi | |
19 | return 0 | |
20 | } | |
21 | ||
22 | sourcex() | |
23 | { | |
24 | if [ "$1" = "-e" ]; then | |
25 | shift | |
26 | [ -e "$1" ] || return 1 | |
27 | fi | |
28 | if ! . "$1"; then | |
29 | eerror "$RC_SVCNAME: error loading $1" | |
30 | exit 1 | |
31 | fi | |
32 | } | |
33 | ||
34 | sourcex "@LIBEXECDIR@/sh/functions.sh" | |
35 | sourcex "@LIBEXECDIR@/sh/rc-functions.sh" | |
36 | [ "$RC_SYS" != "PREFIX" ] && sourcex -e "@LIBEXECDIR@/sh/rc-cgroup.sh" | |
37 | ||
38 | # Support LiveCD foo | |
39 | if sourcex -e "/sbin/livecd-functions.sh"; then | |
40 | livecd_read_commandline | |
41 | fi | |
42 | ||
43 | if [ -z "$1" -o -z "$2" ]; then | |
44 | eerror "$RC_SVCNAME: not enough arguments" | |
45 | exit 1 | |
46 | fi | |
47 | ||
48 | # So daemons know where to recall us if needed | |
49 | RC_SERVICE="$1" ; export RC_SERVICE | |
50 | shift | |
51 | ||
52 | # Compat | |
53 | SVCNAME=$RC_SVCNAME ; export SVCNAME | |
54 | ||
55 | # Dependency function | |
56 | config() { | |
57 | [ -n "$*" ] && echo "config $*" | |
58 | } | |
59 | need() { | |
60 | [ -n "$*" ] && echo "need $*" | |
61 | } | |
62 | use() { | |
63 | [ -n "$*" ] && echo "use $*" | |
64 | } | |
65 | before() { | |
66 | [ -n "$*" ] && echo "before $*" | |
67 | } | |
68 | after() { | |
69 | [ -n "$*" ] && echo "after $*" | |
70 | } | |
71 | provide() { | |
72 | [ -n "$*" ] && echo "provide $*" | |
73 | } | |
74 | keyword() { | |
75 | [ -n "$*" ] && echo "keyword $*" | |
76 | } | |
77 | ||
78 | # Describe the init script to the user | |
79 | describe() | |
80 | { | |
81 | if [ -n "$description" ]; then | |
82 | einfo "$description" | |
83 | else | |
84 | ewarn "No description for $RC_SVCNAME" | |
85 | fi | |
86 | ||
87 | local svc= desc= | |
88 | for svc in ${extra_commands:-$opts} $extra_started_commands \ | |
89 | $extra_stopped_commands; do | |
90 | eval desc=\$description_$svc | |
91 | if [ -n "$desc" ]; then | |
92 | einfo "$HILITE$svc$NORMAL: $desc" | |
93 | else | |
94 | ewarn "$HILITE$svc$NORMAL: no description" | |
95 | fi | |
96 | done | |
97 | } | |
98 | ||
99 | # Report status | |
100 | _status() | |
101 | { | |
102 | if service_stopping; then | |
103 | ewarn "status: stopping" | |
104 | return 4 | |
105 | elif service_starting; then | |
106 | ewarn "status: starting" | |
107 | return 8 | |
108 | elif service_inactive; then | |
109 | ewarn "status: inactive" | |
110 | return 16 | |
111 | elif service_started; then | |
112 | if service_crashed; then | |
113 | eerror "status: crashed" | |
114 | return 32 | |
115 | fi | |
116 | einfo "status: started" | |
117 | return 0 | |
118 | else | |
119 | einfo "status: stopped" | |
120 | return 3 | |
121 | fi | |
122 | } | |
123 | ||
124 | # Template start / stop / status functions | |
125 | start() | |
126 | { | |
127 | [ -n "$command" ] || return 0 | |
128 | local _background= | |
129 | ebegin "Starting ${name:-$RC_SVCNAME}" | |
130 | if yesno "${command_background}"; then | |
131 | if [ -z "${pidfile}" ]; then | |
132 | eend 1 "command_background option used but no pidfile specified" | |
133 | return 1 | |
134 | fi | |
135 | _background="--background --make-pidfile" | |
136 | fi | |
137 | if yesno "$start_inactive"; then | |
138 | local _inactive=false | |
139 | service_inactive && _inactive=true | |
140 | mark_service_inactive | |
141 | fi | |
142 | eval start-stop-daemon --start \ | |
143 | --exec $command \ | |
144 | ${procname:+--name} $procname \ | |
145 | ${pidfile:+--pidfile} $pidfile \ | |
146 | $_background $start_stop_daemon_args \ | |
147 | -- $command_args | |
148 | if eend $? "Failed to start $RC_SVCNAME"; then | |
149 | service_set_value "command" "${command}" | |
150 | [ -n "${pidfile}" ] && service_set_value "pidfile" "${pidfile}" | |
151 | [ -n "${procname}" ] && service_set_value "procname" "${procname}" | |
152 | return 0 | |
153 | fi | |
154 | if yesno "$start_inactive"; then | |
155 | if ! $_inactive; then | |
156 | mark_service_stopped | |
157 | fi | |
158 | fi | |
159 | return 1 | |
160 | } | |
161 | ||
162 | stop() | |
163 | { | |
164 | local startcommand="$(service_get_value "command")" | |
165 | local startpidfile="$(service_get_value "pidfile")" | |
166 | local startprocname="$(service_get_value "procname")" | |
167 | command="${startcommand:-$command}" | |
168 | pidfile="${startpidfile:-$pidfile}" | |
169 | procname="${startprocname:-$procname}" | |
170 | [ -n "$command" -o -n "$procname" -o -n "$pidfile" ] || return 0 | |
171 | ebegin "Stopping ${name:-$RC_SVCNAME}" | |
172 | start-stop-daemon --stop \ | |
173 | ${retry:+--retry} $retry \ | |
174 | ${command:+--exec} $command \ | |
175 | ${procname:+--name} $procname \ | |
176 | ${pidfile:+--pidfile} $pidfile \ | |
177 | ${stopsig:+--signal} $stopsig | |
178 | eend $? "Failed to stop $RC_SVCNAME" | |
179 | } | |
180 | ||
181 | status() | |
182 | { | |
183 | _status | |
184 | } | |
185 | ||
186 | yesno $RC_DEBUG && set -x | |
187 | ||
188 | _conf_d=${RC_SERVICE%/*}/../conf.d | |
189 | # If we're net.eth0 or openvpn.work then load net or openvpn config | |
190 | _c=${RC_SVCNAME%%.*} | |
191 | if [ -n "$_c" -a "$_c" != "$RC_SVCNAME" ]; then | |
192 | if ! sourcex -e "$_conf_d/$_c.$RC_RUNLEVEL"; then | |
193 | sourcex -e "$_conf_d/$_c" | |
194 | fi | |
195 | fi | |
196 | unset _c | |
197 | ||
198 | # Overlay with our specific config | |
199 | if ! sourcex -e "$_conf_d/$RC_SVCNAME.$RC_RUNLEVEL"; then | |
200 | sourcex -e "$_conf_d/$RC_SVCNAME" | |
201 | fi | |
202 | unset _conf_d | |
203 | ||
204 | # Load any system overrides | |
205 | sourcex -e "@SYSCONFDIR@/rc.conf" | |
206 | ||
207 | # Apply any ulimit defined | |
208 | [ -n "${rc_ulimit:-$RC_ULIMIT}" ] && ulimit ${rc_ulimit:-$RC_ULIMIT} | |
209 | ||
210 | # Set verbose mode | |
211 | if yesno "${rc_verbose:-$RC_VERBOSE}"; then | |
212 | EINFO_VERBOSE=yes | |
213 | export EINFO_VERBOSE | |
214 | fi | |
215 | ||
216 | # Apply cgroups settings if defined | |
217 | if [ "$1" = "start" ] ; then | |
218 | if [ "$(command -v cgroup_add_service)" = "cgroup_add_service" ]; then | |
219 | cgroup_add_service /sys/fs/cgroup/openrc | |
220 | cgroup_add_service /sys/fs/cgroup/systemd/system | |
221 | fi | |
222 | [ "$(command -v cgroup_set_limits)" = "cgroup_set_limits" ] && \ | |
223 | cgroup_set_limits | |
224 | fi | |
225 | ||
226 | # Load our script | |
227 | sourcex "$RC_SERVICE" | |
228 | ||
229 | for _d in $required_dirs; do | |
230 | if [ ! -d $_d ]; then | |
231 | eerror "$RC_SVCNAME: \`$_d' is not a directory" | |
232 | exit 1 | |
233 | fi | |
234 | done | |
235 | unset _d | |
236 | ||
237 | for _f in $required_files; do | |
238 | if [ ! -r $_f ]; then | |
239 | eerror "$RC_SVCNAME: \`$_f' is not readable" | |
240 | exit 1 | |
241 | fi | |
242 | done | |
243 | unset _f | |
244 | ||
245 | if [ -n "$opts" ]; then | |
246 | ewarn "Use of the opts variable is deprecated and will be" | |
247 | ewarn "removed in the future." | |
248 | ewarn "Please use extra_commands, extra_started_commands or extra_stopped_commands." | |
249 | fi | |
250 | ||
251 | while [ -n "$1" ]; do | |
252 | # Special case depend | |
253 | if [ "$1" = depend ]; then | |
254 | shift | |
255 | ||
256 | # Enter the dir of the init script to fix the globbing | |
257 | # bug 412677 | |
258 | cd ${RC_SERVICE%/*} | |
259 | _depend | |
260 | cd / | |
261 | continue | |
262 | fi | |
263 | # See if we have the required function and run it | |
264 | for _cmd in describe start stop status ${extra_commands:-$opts} \ | |
265 | $extra_started_commands $extra_stopped_commands | |
266 | do | |
267 | if [ "$_cmd" = "$1" ]; then | |
268 | if [ "$(command -v "$1")" = "$1" ]; then | |
269 | # If we're in the background, we may wish to | |
270 | # fake some commands. We do this so we can | |
271 | # "start" ourselves from inactive which then | |
272 | # triggers other services to start which | |
273 | # depend on us. | |
274 | # A good example of this is openvpn. | |
275 | if yesno $IN_BACKGROUND; then | |
276 | for _cmd in $in_background_fake; do | |
277 | if [ "$_cmd" = "$1" ]; then | |
278 | shift | |
279 | continue 3 | |
280 | fi | |
281 | done | |
282 | fi | |
283 | # Check to see if we need to be started before | |
284 | # we can run this command | |
285 | for _cmd in $extra_started_commands; do | |
286 | if [ "$_cmd" = "$1" ]; then | |
287 | if verify_boot && ! service_started; then | |
288 | eerror "$RC_SVCNAME: cannot \`$1' as it has not been started" | |
289 | exit 1 | |
290 | fi | |
291 | fi | |
292 | done | |
293 | # Check to see if we need to be stopped before | |
294 | # we can run this command | |
295 | for _cmd in $extra_stopped_commands; do | |
296 | if [ "$_cmd" = "$1" ]; then | |
297 | if verify_boot && ! service_stopped; then | |
298 | eerror "$RC_SVCNAME: cannot \`$1' as it has not been stopped" | |
299 | exit 1 | |
300 | fi | |
301 | fi | |
302 | done | |
303 | unset _cmd | |
304 | case $1 in | |
305 | start|stop|status) verify_boot;; | |
306 | esac | |
307 | if [ "$(command -v "$1_pre")" = "$1_pre" ] | |
308 | then | |
309 | "$1"_pre || exit $? | |
310 | fi | |
311 | "$1" || exit $? | |
312 | if [ "$(command -v "$1_post")" = "$1_post" ] | |
313 | then | |
314 | "$1"_post || exit $? | |
315 | fi | |
316 | [ "$(command -v cgroup_cleanup)" = "cgroup_cleanup" -a \ | |
317 | "$1" = "stop" ] && \ | |
318 | yesno "${rc_cgroup_cleanup}" && \ | |
319 | cgroup_cleanup | |
320 | shift | |
321 | continue 2 | |
322 | else | |
323 | if [ "$_cmd" = "start" -o "$_cmd" = "stop" ] | |
324 | then | |
325 | shift | |
326 | continue 2 | |
327 | else | |
328 | eerror "$RC_SVCNAME: function \`$1' defined but does not exist" | |
329 | exit 1 | |
330 | fi | |
331 | fi | |
332 | fi | |
333 | done | |
334 | eerror "$RC_SVCNAME: unknown function \`$1'" | |
335 | exit 1 | |
336 | done | |
337 | ||
338 | exit 0 |
0 | # Start / stop / status functions for s6 support | |
1 | # Copyright (c) 2015 William Hubbs <w.d.hubbs@gmail.com> | |
2 | # Released under the 2-clause BSD license. | |
3 | ||
4 | [ -z "${s6_service_path}" ] && s6_service_path="/var/svc.d/${RC_SVCNAME}" | |
5 | ||
6 | s6_start() | |
7 | { | |
8 | if [ ! -d "${s6_service_path}" ]; then | |
9 | eerror "${s6_service_path} does not exist." | |
10 | return 1 | |
11 | fi | |
12 | s6_service_link="${RC_SVCDIR}/s6-scan/${s6_service_path##*/}" | |
13 | ebegin "Starting ${name:-$RC_SVCNAME}" | |
14 | ln -sf "${s6_service_path}" "${s6_service_link}" | |
15 | s6-svscanctl -na "${RC_SVCDIR}"/s6-scan | |
16 | sleep 1.5 | |
17 | s6-svc -u "${s6_service_link}" | |
18 | if [ -n "$s6_svwait_options_start" ]; then | |
19 | s6-svwait ${s6_svwait_options_start} "${s6_service_link}" | |
20 | fi | |
21 | sleep 1.5 | |
22 | set -- $(s6-svstat "${s6_service_link}") | |
23 | [ "$1" = "up" ] | |
24 | eend $? "Failed to start $RC_SVCNAME" | |
25 | } | |
26 | ||
27 | s6_stop() | |
28 | { | |
29 | if [ ! -d "${s6_service_path}" ]; then | |
30 | eerror "${s6_service_path} does not exist." | |
31 | return 1 | |
32 | fi | |
33 | s6_service_link="${RC_SVCDIR}/s6-scan/${s6_service_path##*/}" | |
34 | ebegin "Stopping ${name:-$RC_SVCNAME}" | |
35 | s6-svc -Dd -T ${s6_service_timeout_stop:-10000} "${s6_service_link}" | |
36 | set -- $(s6-svstat "${s6_service_link}") | |
37 | [ "$1" = "down" ] | |
38 | eend $? "Failed to stop $RC_SVCNAME" | |
39 | } | |
40 | ||
41 | s6_status() | |
42 | { | |
43 | s6_service_link="${RC_SVCDIR}/s6-scan/${s6_service_path##*/}" | |
44 | if [ -L "${s6_service_link}" ]; then | |
45 | s6-svstat "${s6_service_link}" | |
46 | else | |
47 | _status | |
48 | fi | |
49 | } |
0 | # start / stop / status functions for start-stop-daemon | |
1 | # Copyright (c) 2007-2009 Roy Marples <roy@marples.name> | |
2 | # Released under the 2-clause BSD license. | |
3 | ||
4 | ssd_start() | |
5 | { | |
6 | if [ -z "$command" ]; then | |
7 | ewarn "The command variable is undefined." | |
8 | ewarn "There is nothing for ${name:-$RC_SVCNAME} to start." | |
9 | ewarn "If this is what you intend, please write a start function." | |
10 | ewarn "This will become a failure in a future release." | |
11 | return 0 | |
12 | fi | |
13 | ||
14 | local _background= | |
15 | ebegin "Starting ${name:-$RC_SVCNAME}" | |
16 | if yesno "${command_background}"; then | |
17 | if [ -z "${pidfile}" ]; then | |
18 | eend 1 "command_background option used but no pidfile specified" | |
19 | return 1 | |
20 | fi | |
21 | if [ -n "${command_args_background}" ]; then | |
22 | eend 1 "command_background used with command_args_background" | |
23 | return 1 | |
24 | fi | |
25 | _background="--background --make-pidfile" | |
26 | fi | |
27 | if yesno "$start_inactive"; then | |
28 | local _inactive=false | |
29 | service_inactive && _inactive=true | |
30 | mark_service_inactive | |
31 | fi | |
32 | eval start-stop-daemon --start \ | |
33 | --exec $command \ | |
34 | ${procname:+--name} $procname \ | |
35 | ${pidfile:+--pidfile} $pidfile \ | |
36 | ${command_user+--user} $command_user \ | |
37 | $_background $start_stop_daemon_args \ | |
38 | -- $command_args $command_args_background | |
39 | if eend $? "Failed to start $RC_SVCNAME"; then | |
40 | service_set_value "command" "${command}" | |
41 | [ -n "${pidfile}" ] && service_set_value "pidfile" "${pidfile}" | |
42 | [ -n "${procname}" ] && service_set_value "procname" "${procname}" | |
43 | return 0 | |
44 | fi | |
45 | if yesno "$start_inactive"; then | |
46 | if ! $_inactive; then | |
47 | mark_service_stopped | |
48 | fi | |
49 | fi | |
50 | return 1 | |
51 | } | |
52 | ||
53 | ssd_stop() | |
54 | { | |
55 | local startcommand="$(service_get_value "command")" | |
56 | local startpidfile="$(service_get_value "pidfile")" | |
57 | local startprocname="$(service_get_value "procname")" | |
58 | command="${startcommand:-$command}" | |
59 | pidfile="${startpidfile:-$pidfile}" | |
60 | procname="${startprocname:-$procname}" | |
61 | [ -n "$command" -o -n "$procname" -o -n "$pidfile" ] || return 0 | |
62 | ebegin "Stopping ${name:-$RC_SVCNAME}" | |
63 | start-stop-daemon --stop \ | |
64 | ${retry:+--retry} $retry \ | |
65 | ${command:+--exec} $command \ | |
66 | ${procname:+--name} $procname \ | |
67 | ${pidfile:+--pidfile} $pidfile \ | |
68 | ${stopsig:+--signal} $stopsig | |
69 | ||
70 | eend $? "Failed to stop $RC_SVCNAME" | |
71 | } | |
72 | ||
73 | ssd_status() | |
74 | { | |
75 | _status | |
76 | } |
52 | 52 | done |
53 | 53 | } |
54 | 54 | |
55 | splitpath() { | |
56 | local path=$1 | |
57 | while [ -n "$path" ]; do | |
58 | echo $path | |
59 | path=${path%/*} | |
60 | done | |
61 | } | |
62 | ||
55 | 63 | _restorecon() { |
56 | 64 | local path=$1 |
57 | 65 | if [ -x /sbin/restorecon ]; then |
58 | dryrun_or_real restorecon -F "$path" | |
66 | dryrun_or_real restorecon -F $(splitpath "$path") | |
59 | 67 | fi |
60 | 68 | } |
61 | 69 | |
79 | 87 | fi |
80 | 88 | } |
81 | 89 | |
90 | _C() { | |
91 | # recursively copy a file or directory | |
92 | local path=$1 mode=$2 uid=$3 gid=$4 age=$5 arg=$6 | |
93 | if [ ! -e "$path" ]; then | |
94 | dryrun_or_real cp -r "$arg" "$path" | |
95 | _restorecon "$path" | |
96 | [ $uid != '-' ] && dryrun_or_real chown "$uid" "$path" | |
97 | [ $gid != '-' ] && dryrun_or_real chgrp "$gid" "$path" | |
98 | [ $mode != '-' ] && dryrun_or_real chmod "$mode" "$path" | |
99 | fi | |
100 | } | |
82 | 101 | |
83 | 102 | _f() { |
84 | 103 | # Create a file if it doesn't exist yet |
110 | 129 | |
111 | 130 | if [ ! -d "$path" ]; then |
112 | 131 | dryrun_or_real mkdir -p "$path" 2>/dev/null |
132 | _restorecon "$path" | |
113 | 133 | dryrun_or_real $CHECKPATH -dq -m "$mode" -o "$uid:$gid" "$path" |
114 | 134 | fi |
115 | 135 | } |
125 | 145 | |
126 | 146 | if [ $CREATE -gt 0 ]; then |
127 | 147 | dryrun_or_real mkdir -p "$path" 2>/dev/null |
148 | _restorecon "$path" | |
128 | 149 | dryrun_or_real $CHECKPATH -Dq -m "$mode" -o "$uid:$gid" "$path" |
129 | 150 | fi |
151 | } | |
152 | ||
153 | _v() { | |
154 | # Create a subvolume if the path does not exist yet and the file system | |
155 | # supports this (btrfs). Otherwise create a normal directory. | |
156 | # TODO: Implement btrfs subvol creation. | |
157 | _d "$@" | |
130 | 158 | } |
131 | 159 | |
132 | 160 | _L() { |
233 | 261 | FILE= |
234 | 262 | fragments= |
235 | 263 | # XXX: The harcoding of /usr/lib/ is an explicit choice by upstream |
236 | tmpfiles_dirs='/usr/lib/tmpfiles.d/ /etc/tmpfiles.d/ /run/tmpfiles.d/' | |
264 | tmpfiles_dirs='/usr/lib/tmpfiles.d/ /run/tmpfiles.d/ /etc/tmpfiles.d/' | |
237 | 265 | tmpfiles_basenames='' |
238 | 266 | tmpfiles_d='' |
239 | 267 | # Build a list of sorted unique basenames |
303 | 331 | # But IS allowed when globs are expanded for the x/r/R/z/Z types. |
304 | 332 | while read cmd path mode uid gid age arg; do |
305 | 333 | LINENUM=$(( LINENUM+1 )) |
334 | FORCE=0 | |
306 | 335 | |
307 | 336 | # Unless we have both command and path, skip this line. |
308 | 337 | if [ -z "$cmd" -o -z "$path" ]; then |
310 | 339 | fi |
311 | 340 | |
312 | 341 | case $cmd in |
313 | *!) [ "$BOOT" -eq "1" ] || continue; cmd=${cmd%!} ;; | |
342 | \#*) continue ;; | |
314 | 343 | esac |
344 | ||
345 | while [ ${#cmd} -gt 1 ]; do | |
346 | case $cmd in | |
347 | *!) cmd=${cmd%!}; [ "$BOOT" -eq "1" ] || continue 2 ;; | |
348 | *+) cmd=${cmd%+}; FORCE=1; ;; | |
349 | *) warninvalid ; continue 2 ;; | |
350 | esac | |
351 | done | |
315 | 352 | |
316 | 353 | # whine about invalid entries |
317 | 354 | case $cmd in |
318 | f|F|w|d|D|p|L|c|b|x|X|r|R|z|Z) ;; | |
319 | \#*) continue ;; | |
355 | f|F|w|d|D|v|p|L|c|C|b|x|X|r|R|z|Z) ;; | |
320 | 356 | *) warninvalid ; continue ;; |
321 | 357 | esac |
322 | 358 | |
324 | 360 | if [ "$mode" = '-' -o "$mode" = '' ]; then |
325 | 361 | case "$cmd" in |
326 | 362 | p|f|F) mode=0644 ;; |
327 | d|D) mode=0755 ;; | |
328 | z|Z|x|r|R|L) ;; | |
363 | d|D|v) mode=0755 ;; | |
364 | C|z|Z|x|r|R|L) ;; | |
329 | 365 | esac |
330 | 366 | fi |
331 | 367 | |
337 | 373 | |
338 | 374 | [ -n "$EXCLUDE" ] && checkprefix $path $EXCLUDE && continue |
339 | 375 | [ -n "$PREFIX" ] && ! checkprefix $path $PREFIX && continue |
376 | ||
377 | if [ $FORCE -gt 0 ]; then | |
378 | case $cmd in | |
379 | p|L|c|b) [ -f "$path" ] && dryrun_or_real rm -f "$path" | |
380 | esac | |
381 | fi | |
382 | ||
340 | 383 | [ "$VERBOSE" -eq "1" ] && echo _$cmd "$@" |
341 | 384 | _$cmd "$@" |
342 | 385 | rc=$? |
46 | 46 | #endif |
47 | 47 | |
48 | 48 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) |
49 | ||
50 | /* Some libc implemntations don't have these */ | |
51 | #ifndef TAILQ_CONCAT | |
52 | #define TAILQ_CONCAT(head1, head2, field) do { \ | |
53 | if (!TAILQ_EMPTY(head2)) { \ | |
54 | *(head1)->tqh_last = (head2)->tqh_first; \ | |
55 | (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ | |
56 | (head1)->tqh_last = (head2)->tqh_last; \ | |
57 | TAILQ_INIT((head2)); \ | |
58 | } \ | |
59 | } while (0) | |
60 | #endif | |
61 | ||
62 | #ifndef TAILQ_FOREACH_SAFE | |
63 | #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ | |
64 | for ((var) = TAILQ_FIRST((head)); \ | |
65 | (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ | |
66 | (var) = (tvar)) | |
67 | #endif | |
68 | 49 | |
69 | 50 | #ifdef __GLIBC__ |
70 | 51 | # if ! defined (__UCLIBC__) && ! defined (__dietlibc__) |
0 | /* $NetBSD: queue.h,v 1.67 2014/05/17 21:22:56 rmind Exp $ */ | |
1 | ||
2 | /* | |
3 | * Copyright (c) 1991, 1993 | |
4 | * The Regents of the University of California. All rights reserved. | |
5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | |
14 | * 3. Neither the name of the University nor the names of its contributors | |
15 | * may be used to endorse or promote products derived from this software | |
16 | * without specific prior written permission. | |
17 | * | |
18 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
19 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
24 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
28 | * SUCH DAMAGE. | |
29 | * | |
30 | * @(#)queue.h 8.5 (Berkeley) 8/20/94 | |
31 | */ | |
32 | ||
33 | #ifndef _SYS_QUEUE_H_ | |
34 | #define _SYS_QUEUE_H_ | |
35 | ||
36 | /* | |
37 | * This file defines five types of data structures: singly-linked lists, | |
38 | * lists, simple queues, tail queues, and circular queues. | |
39 | * | |
40 | * A singly-linked list is headed by a single forward pointer. The | |
41 | * elements are singly linked for minimum space and pointer manipulation | |
42 | * overhead at the expense of O(n) removal for arbitrary elements. New | |
43 | * elements can be added to the list after an existing element or at the | |
44 | * head of the list. Elements being removed from the head of the list | |
45 | * should use the explicit macro for this purpose for optimum | |
46 | * efficiency. A singly-linked list may only be traversed in the forward | |
47 | * direction. Singly-linked lists are ideal for applications with large | |
48 | * datasets and few or no removals or for implementing a LIFO queue. | |
49 | * | |
50 | * A list is headed by a single forward pointer (or an array of forward | |
51 | * pointers for a hash table header). The elements are doubly linked | |
52 | * so that an arbitrary element can be removed without a need to | |
53 | * traverse the list. New elements can be added to the list before | |
54 | * or after an existing element or at the head of the list. A list | |
55 | * may only be traversed in the forward direction. | |
56 | * | |
57 | * A simple queue is headed by a pair of pointers, one the head of the | |
58 | * list and the other to the tail of the list. The elements are singly | |
59 | * linked to save space, so elements can only be removed from the | |
60 | * head of the list. New elements can be added to the list after | |
61 | * an existing element, at the head of the list, or at the end of the | |
62 | * list. A simple queue may only be traversed in the forward direction. | |
63 | * | |
64 | * A tail queue is headed by a pair of pointers, one to the head of the | |
65 | * list and the other to the tail of the list. The elements are doubly | |
66 | * linked so that an arbitrary element can be removed without a need to | |
67 | * traverse the list. New elements can be added to the list before or | |
68 | * after an existing element, at the head of the list, or at the end of | |
69 | * the list. A tail queue may be traversed in either direction. | |
70 | * | |
71 | * A circle queue is headed by a pair of pointers, one to the head of the | |
72 | * list and the other to the tail of the list. The elements are doubly | |
73 | * linked so that an arbitrary element can be removed without a need to | |
74 | * traverse the list. New elements can be added to the list before or after | |
75 | * an existing element, at the head of the list, or at the end of the list. | |
76 | * A circle queue may be traversed in either direction, but has a more | |
77 | * complex end of list detection. | |
78 | * | |
79 | * For details on the use of these macros, see the queue(3) manual page. | |
80 | */ | |
81 | ||
82 | /* | |
83 | * Include the definition of NULL only on NetBSD because sys/null.h | |
84 | * is not available elsewhere. This conditional makes the header | |
85 | * portable and it can simply be dropped verbatim into any system. | |
86 | * The caveat is that on other systems some other header | |
87 | * must provide NULL before the macros can be used. | |
88 | */ | |
89 | #ifdef __NetBSD__ | |
90 | #include <sys/null.h> | |
91 | #endif | |
92 | ||
93 | #if defined(QUEUEDEBUG) | |
94 | # if defined(_KERNEL) | |
95 | # define QUEUEDEBUG_ABORT(...) panic(__VA_ARGS__) | |
96 | # else | |
97 | # include <err.h> | |
98 | # define QUEUEDEBUG_ABORT(...) err(1, __VA_ARGS__) | |
99 | # endif | |
100 | #endif | |
101 | ||
102 | /* | |
103 | * Singly-linked List definitions. | |
104 | */ | |
105 | #define SLIST_HEAD(name, type) \ | |
106 | struct name { \ | |
107 | struct type *slh_first; /* first element */ \ | |
108 | } | |
109 | ||
110 | #define SLIST_HEAD_INITIALIZER(head) \ | |
111 | { NULL } | |
112 | ||
113 | #define SLIST_ENTRY(type) \ | |
114 | struct { \ | |
115 | struct type *sle_next; /* next element */ \ | |
116 | } | |
117 | ||
118 | /* | |
119 | * Singly-linked List access methods. | |
120 | */ | |
121 | #define SLIST_FIRST(head) ((head)->slh_first) | |
122 | #define SLIST_END(head) NULL | |
123 | #define SLIST_EMPTY(head) ((head)->slh_first == NULL) | |
124 | #define SLIST_NEXT(elm, field) ((elm)->field.sle_next) | |
125 | ||
126 | #define SLIST_FOREACH(var, head, field) \ | |
127 | for((var) = (head)->slh_first; \ | |
128 | (var) != SLIST_END(head); \ | |
129 | (var) = (var)->field.sle_next) | |
130 | ||
131 | #define SLIST_FOREACH_SAFE(var, head, field, tvar) \ | |
132 | for ((var) = SLIST_FIRST((head)); \ | |
133 | (var) != SLIST_END(head) && \ | |
134 | ((tvar) = SLIST_NEXT((var), field), 1); \ | |
135 | (var) = (tvar)) | |
136 | ||
137 | /* | |
138 | * Singly-linked List functions. | |
139 | */ | |
140 | #define SLIST_INIT(head) do { \ | |
141 | (head)->slh_first = SLIST_END(head); \ | |
142 | } while (/*CONSTCOND*/0) | |
143 | ||
144 | #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ | |
145 | (elm)->field.sle_next = (slistelm)->field.sle_next; \ | |
146 | (slistelm)->field.sle_next = (elm); \ | |
147 | } while (/*CONSTCOND*/0) | |
148 | ||
149 | #define SLIST_INSERT_HEAD(head, elm, field) do { \ | |
150 | (elm)->field.sle_next = (head)->slh_first; \ | |
151 | (head)->slh_first = (elm); \ | |
152 | } while (/*CONSTCOND*/0) | |
153 | ||
154 | #define SLIST_REMOVE_AFTER(slistelm, field) do { \ | |
155 | (slistelm)->field.sle_next = \ | |
156 | SLIST_NEXT(SLIST_NEXT((slistelm), field), field); \ | |
157 | } while (/*CONSTCOND*/0) | |
158 | ||
159 | #define SLIST_REMOVE_HEAD(head, field) do { \ | |
160 | (head)->slh_first = (head)->slh_first->field.sle_next; \ | |
161 | } while (/*CONSTCOND*/0) | |
162 | ||
163 | #define SLIST_REMOVE(head, elm, type, field) do { \ | |
164 | if ((head)->slh_first == (elm)) { \ | |
165 | SLIST_REMOVE_HEAD((head), field); \ | |
166 | } \ | |
167 | else { \ | |
168 | struct type *curelm = (head)->slh_first; \ | |
169 | while(curelm->field.sle_next != (elm)) \ | |
170 | curelm = curelm->field.sle_next; \ | |
171 | curelm->field.sle_next = \ | |
172 | curelm->field.sle_next->field.sle_next; \ | |
173 | } \ | |
174 | } while (/*CONSTCOND*/0) | |
175 | ||
176 | ||
177 | /* | |
178 | * List definitions. | |
179 | */ | |
180 | #define LIST_HEAD(name, type) \ | |
181 | struct name { \ | |
182 | struct type *lh_first; /* first element */ \ | |
183 | } | |
184 | ||
185 | #define LIST_HEAD_INITIALIZER(head) \ | |
186 | { NULL } | |
187 | ||
188 | #define LIST_ENTRY(type) \ | |
189 | struct { \ | |
190 | struct type *le_next; /* next element */ \ | |
191 | struct type **le_prev; /* address of previous next element */ \ | |
192 | } | |
193 | ||
194 | /* | |
195 | * List access methods. | |
196 | */ | |
197 | #define LIST_FIRST(head) ((head)->lh_first) | |
198 | #define LIST_END(head) NULL | |
199 | #define LIST_EMPTY(head) ((head)->lh_first == LIST_END(head)) | |
200 | #define LIST_NEXT(elm, field) ((elm)->field.le_next) | |
201 | ||
202 | #define LIST_FOREACH(var, head, field) \ | |
203 | for ((var) = ((head)->lh_first); \ | |
204 | (var) != LIST_END(head); \ | |
205 | (var) = ((var)->field.le_next)) | |
206 | ||
207 | #define LIST_FOREACH_SAFE(var, head, field, tvar) \ | |
208 | for ((var) = LIST_FIRST((head)); \ | |
209 | (var) != LIST_END(head) && \ | |
210 | ((tvar) = LIST_NEXT((var), field), 1); \ | |
211 | (var) = (tvar)) | |
212 | ||
213 | #define LIST_MOVE(head1, head2) do { \ | |
214 | LIST_INIT((head2)); \ | |
215 | if (!LIST_EMPTY((head1))) { \ | |
216 | (head2)->lh_first = (head1)->lh_first; \ | |
217 | LIST_INIT((head1)); \ | |
218 | } \ | |
219 | } while (/*CONSTCOND*/0) | |
220 | ||
221 | /* | |
222 | * List functions. | |
223 | */ | |
224 | #if defined(QUEUEDEBUG) | |
225 | #define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) \ | |
226 | if ((head)->lh_first && \ | |
227 | (head)->lh_first->field.le_prev != &(head)->lh_first) \ | |
228 | QUEUEDEBUG_ABORT("LIST_INSERT_HEAD %p %s:%d", (head), \ | |
229 | __FILE__, __LINE__); | |
230 | #define QUEUEDEBUG_LIST_OP(elm, field) \ | |
231 | if ((elm)->field.le_next && \ | |
232 | (elm)->field.le_next->field.le_prev != \ | |
233 | &(elm)->field.le_next) \ | |
234 | QUEUEDEBUG_ABORT("LIST_* forw %p %s:%d", (elm), \ | |
235 | __FILE__, __LINE__); \ | |
236 | if (*(elm)->field.le_prev != (elm)) \ | |
237 | QUEUEDEBUG_ABORT("LIST_* back %p %s:%d", (elm), \ | |
238 | __FILE__, __LINE__); | |
239 | #define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) \ | |
240 | (elm)->field.le_next = (void *)1L; \ | |
241 | (elm)->field.le_prev = (void *)1L; | |
242 | #else | |
243 | #define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) | |
244 | #define QUEUEDEBUG_LIST_OP(elm, field) | |
245 | #define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) | |
246 | #endif | |
247 | ||
248 | #define LIST_INIT(head) do { \ | |
249 | (head)->lh_first = LIST_END(head); \ | |
250 | } while (/*CONSTCOND*/0) | |
251 | ||
252 | #define LIST_INSERT_AFTER(listelm, elm, field) do { \ | |
253 | QUEUEDEBUG_LIST_OP((listelm), field) \ | |
254 | if (((elm)->field.le_next = (listelm)->field.le_next) != \ | |
255 | LIST_END(head)) \ | |
256 | (listelm)->field.le_next->field.le_prev = \ | |
257 | &(elm)->field.le_next; \ | |
258 | (listelm)->field.le_next = (elm); \ | |
259 | (elm)->field.le_prev = &(listelm)->field.le_next; \ | |
260 | } while (/*CONSTCOND*/0) | |
261 | ||
262 | #define LIST_INSERT_BEFORE(listelm, elm, field) do { \ | |
263 | QUEUEDEBUG_LIST_OP((listelm), field) \ | |
264 | (elm)->field.le_prev = (listelm)->field.le_prev; \ | |
265 | (elm)->field.le_next = (listelm); \ | |
266 | *(listelm)->field.le_prev = (elm); \ | |
267 | (listelm)->field.le_prev = &(elm)->field.le_next; \ | |
268 | } while (/*CONSTCOND*/0) | |
269 | ||
270 | #define LIST_INSERT_HEAD(head, elm, field) do { \ | |
271 | QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field) \ | |
272 | if (((elm)->field.le_next = (head)->lh_first) != LIST_END(head))\ | |
273 | (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ | |
274 | (head)->lh_first = (elm); \ | |
275 | (elm)->field.le_prev = &(head)->lh_first; \ | |
276 | } while (/*CONSTCOND*/0) | |
277 | ||
278 | #define LIST_REMOVE(elm, field) do { \ | |
279 | QUEUEDEBUG_LIST_OP((elm), field) \ | |
280 | if ((elm)->field.le_next != NULL) \ | |
281 | (elm)->field.le_next->field.le_prev = \ | |
282 | (elm)->field.le_prev; \ | |
283 | *(elm)->field.le_prev = (elm)->field.le_next; \ | |
284 | QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \ | |
285 | } while (/*CONSTCOND*/0) | |
286 | ||
287 | #define LIST_REPLACE(elm, elm2, field) do { \ | |
288 | if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ | |
289 | (elm2)->field.le_next->field.le_prev = \ | |
290 | &(elm2)->field.le_next; \ | |
291 | (elm2)->field.le_prev = (elm)->field.le_prev; \ | |
292 | *(elm2)->field.le_prev = (elm2); \ | |
293 | QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \ | |
294 | } while (/*CONSTCOND*/0) | |
295 | ||
296 | /* | |
297 | * Simple queue definitions. | |
298 | */ | |
299 | #define SIMPLEQ_HEAD(name, type) \ | |
300 | struct name { \ | |
301 | struct type *sqh_first; /* first element */ \ | |
302 | struct type **sqh_last; /* addr of last next element */ \ | |
303 | } | |
304 | ||
305 | #define SIMPLEQ_HEAD_INITIALIZER(head) \ | |
306 | { NULL, &(head).sqh_first } | |
307 | ||
308 | #define SIMPLEQ_ENTRY(type) \ | |
309 | struct { \ | |
310 | struct type *sqe_next; /* next element */ \ | |
311 | } | |
312 | ||
313 | /* | |
314 | * Simple queue access methods. | |
315 | */ | |
316 | #define SIMPLEQ_FIRST(head) ((head)->sqh_first) | |
317 | #define SIMPLEQ_END(head) NULL | |
318 | #define SIMPLEQ_EMPTY(head) ((head)->sqh_first == SIMPLEQ_END(head)) | |
319 | #define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) | |
320 | ||
321 | #define SIMPLEQ_FOREACH(var, head, field) \ | |
322 | for ((var) = ((head)->sqh_first); \ | |
323 | (var) != SIMPLEQ_END(head); \ | |
324 | (var) = ((var)->field.sqe_next)) | |
325 | ||
326 | #define SIMPLEQ_FOREACH_SAFE(var, head, field, next) \ | |
327 | for ((var) = ((head)->sqh_first); \ | |
328 | (var) != SIMPLEQ_END(head) && \ | |
329 | ((next = ((var)->field.sqe_next)), 1); \ | |
330 | (var) = (next)) | |
331 | ||
332 | /* | |
333 | * Simple queue functions. | |
334 | */ | |
335 | #define SIMPLEQ_INIT(head) do { \ | |
336 | (head)->sqh_first = NULL; \ | |
337 | (head)->sqh_last = &(head)->sqh_first; \ | |
338 | } while (/*CONSTCOND*/0) | |
339 | ||
340 | #define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ | |
341 | if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ | |
342 | (head)->sqh_last = &(elm)->field.sqe_next; \ | |
343 | (head)->sqh_first = (elm); \ | |
344 | } while (/*CONSTCOND*/0) | |
345 | ||
346 | #define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ | |
347 | (elm)->field.sqe_next = NULL; \ | |
348 | *(head)->sqh_last = (elm); \ | |
349 | (head)->sqh_last = &(elm)->field.sqe_next; \ | |
350 | } while (/*CONSTCOND*/0) | |
351 | ||
352 | #define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ | |
353 | if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ | |
354 | (head)->sqh_last = &(elm)->field.sqe_next; \ | |
355 | (listelm)->field.sqe_next = (elm); \ | |
356 | } while (/*CONSTCOND*/0) | |
357 | ||
358 | #define SIMPLEQ_REMOVE_HEAD(head, field) do { \ | |
359 | if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ | |
360 | (head)->sqh_last = &(head)->sqh_first; \ | |
361 | } while (/*CONSTCOND*/0) | |
362 | ||
363 | #define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ | |
364 | if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \ | |
365 | == NULL) \ | |
366 | (head)->sqh_last = &(elm)->field.sqe_next; \ | |
367 | } while (/*CONSTCOND*/0) | |
368 | ||
369 | #define SIMPLEQ_REMOVE(head, elm, type, field) do { \ | |
370 | if ((head)->sqh_first == (elm)) { \ | |
371 | SIMPLEQ_REMOVE_HEAD((head), field); \ | |
372 | } else { \ | |
373 | struct type *curelm = (head)->sqh_first; \ | |
374 | while (curelm->field.sqe_next != (elm)) \ | |
375 | curelm = curelm->field.sqe_next; \ | |
376 | if ((curelm->field.sqe_next = \ | |
377 | curelm->field.sqe_next->field.sqe_next) == NULL) \ | |
378 | (head)->sqh_last = &(curelm)->field.sqe_next; \ | |
379 | } \ | |
380 | } while (/*CONSTCOND*/0) | |
381 | ||
382 | #define SIMPLEQ_CONCAT(head1, head2) do { \ | |
383 | if (!SIMPLEQ_EMPTY((head2))) { \ | |
384 | *(head1)->sqh_last = (head2)->sqh_first; \ | |
385 | (head1)->sqh_last = (head2)->sqh_last; \ | |
386 | SIMPLEQ_INIT((head2)); \ | |
387 | } \ | |
388 | } while (/*CONSTCOND*/0) | |
389 | ||
390 | #define SIMPLEQ_LAST(head, type, field) \ | |
391 | (SIMPLEQ_EMPTY((head)) ? \ | |
392 | NULL : \ | |
393 | ((struct type *)(void *) \ | |
394 | ((char *)((head)->sqh_last) - offsetof(struct type, field)))) | |
395 | ||
396 | /* | |
397 | * Tail queue definitions. | |
398 | */ | |
399 | #define _TAILQ_HEAD(name, type, qual) \ | |
400 | struct name { \ | |
401 | qual type *tqh_first; /* first element */ \ | |
402 | qual type *qual *tqh_last; /* addr of last next element */ \ | |
403 | } | |
404 | #define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,) | |
405 | ||
406 | #define TAILQ_HEAD_INITIALIZER(head) \ | |
407 | { TAILQ_END(head), &(head).tqh_first } | |
408 | ||
409 | #define _TAILQ_ENTRY(type, qual) \ | |
410 | struct { \ | |
411 | qual type *tqe_next; /* next element */ \ | |
412 | qual type *qual *tqe_prev; /* address of previous next element */\ | |
413 | } | |
414 | #define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,) | |
415 | ||
416 | /* | |
417 | * Tail queue access methods. | |
418 | */ | |
419 | #define TAILQ_FIRST(head) ((head)->tqh_first) | |
420 | #define TAILQ_END(head) (NULL) | |
421 | #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) | |
422 | #define TAILQ_LAST(head, headname) \ | |
423 | (*(((struct headname *)((head)->tqh_last))->tqh_last)) | |
424 | #define TAILQ_PREV(elm, headname, field) \ | |
425 | (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) | |
426 | #define TAILQ_EMPTY(head) (TAILQ_FIRST(head) == TAILQ_END(head)) | |
427 | ||
428 | ||
429 | #define TAILQ_FOREACH(var, head, field) \ | |
430 | for ((var) = ((head)->tqh_first); \ | |
431 | (var) != TAILQ_END(head); \ | |
432 | (var) = ((var)->field.tqe_next)) | |
433 | ||
434 | #define TAILQ_FOREACH_SAFE(var, head, field, next) \ | |
435 | for ((var) = ((head)->tqh_first); \ | |
436 | (var) != TAILQ_END(head) && \ | |
437 | ((next) = TAILQ_NEXT(var, field), 1); (var) = (next)) | |
438 | ||
439 | #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ | |
440 | for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last));\ | |
441 | (var) != TAILQ_END(head); \ | |
442 | (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) | |
443 | ||
444 | #define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev) \ | |
445 | for ((var) = TAILQ_LAST((head), headname); \ | |
446 | (var) != TAILQ_END(head) && \ | |
447 | ((prev) = TAILQ_PREV((var), headname, field), 1); (var) = (prev)) | |
448 | ||
449 | /* | |
450 | * Tail queue functions. | |
451 | */ | |
452 | #if defined(QUEUEDEBUG) | |
453 | #define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) \ | |
454 | if ((head)->tqh_first && \ | |
455 | (head)->tqh_first->field.tqe_prev != &(head)->tqh_first) \ | |
456 | QUEUEDEBUG_ABORT("TAILQ_INSERT_HEAD %p %s:%d", (head), \ | |
457 | __FILE__, __LINE__); | |
458 | #define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) \ | |
459 | if (*(head)->tqh_last != NULL) \ | |
460 | QUEUEDEBUG_ABORT("TAILQ_INSERT_TAIL %p %s:%d", (head), \ | |
461 | __FILE__, __LINE__); | |
462 | #define QUEUEDEBUG_TAILQ_OP(elm, field) \ | |
463 | if ((elm)->field.tqe_next && \ | |
464 | (elm)->field.tqe_next->field.tqe_prev != \ | |
465 | &(elm)->field.tqe_next) \ | |
466 | QUEUEDEBUG_ABORT("TAILQ_* forw %p %s:%d", (elm), \ | |
467 | __FILE__, __LINE__); \ | |
468 | if (*(elm)->field.tqe_prev != (elm)) \ | |
469 | QUEUEDEBUG_ABORT("TAILQ_* back %p %s:%d", (elm), \ | |
470 | __FILE__, __LINE__); | |
471 | #define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) \ | |
472 | if ((elm)->field.tqe_next == NULL && \ | |
473 | (head)->tqh_last != &(elm)->field.tqe_next) \ | |
474 | QUEUEDEBUG_ABORT("TAILQ_PREREMOVE head %p elm %p %s:%d",\ | |
475 | (head), (elm), __FILE__, __LINE__); | |
476 | #define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) \ | |
477 | (elm)->field.tqe_next = (void *)1L; \ | |
478 | (elm)->field.tqe_prev = (void *)1L; | |
479 | #else | |
480 | #define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) | |
481 | #define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) | |
482 | #define QUEUEDEBUG_TAILQ_OP(elm, field) | |
483 | #define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) | |
484 | #define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) | |
485 | #endif | |
486 | ||
487 | #define TAILQ_INIT(head) do { \ | |
488 | (head)->tqh_first = TAILQ_END(head); \ | |
489 | (head)->tqh_last = &(head)->tqh_first; \ | |
490 | } while (/*CONSTCOND*/0) | |
491 | ||
492 | #define TAILQ_INSERT_HEAD(head, elm, field) do { \ | |
493 | QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field) \ | |
494 | if (((elm)->field.tqe_next = (head)->tqh_first) != TAILQ_END(head))\ | |
495 | (head)->tqh_first->field.tqe_prev = \ | |
496 | &(elm)->field.tqe_next; \ | |
497 | else \ | |
498 | (head)->tqh_last = &(elm)->field.tqe_next; \ | |
499 | (head)->tqh_first = (elm); \ | |
500 | (elm)->field.tqe_prev = &(head)->tqh_first; \ | |
501 | } while (/*CONSTCOND*/0) | |
502 | ||
503 | #define TAILQ_INSERT_TAIL(head, elm, field) do { \ | |
504 | QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field) \ | |
505 | (elm)->field.tqe_next = TAILQ_END(head); \ | |
506 | (elm)->field.tqe_prev = (head)->tqh_last; \ | |
507 | *(head)->tqh_last = (elm); \ | |
508 | (head)->tqh_last = &(elm)->field.tqe_next; \ | |
509 | } while (/*CONSTCOND*/0) | |
510 | ||
511 | #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ | |
512 | QUEUEDEBUG_TAILQ_OP((listelm), field) \ | |
513 | if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != \ | |
514 | TAILQ_END(head)) \ | |
515 | (elm)->field.tqe_next->field.tqe_prev = \ | |
516 | &(elm)->field.tqe_next; \ | |
517 | else \ | |
518 | (head)->tqh_last = &(elm)->field.tqe_next; \ | |
519 | (listelm)->field.tqe_next = (elm); \ | |
520 | (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ | |
521 | } while (/*CONSTCOND*/0) | |
522 | ||
523 | #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ | |
524 | QUEUEDEBUG_TAILQ_OP((listelm), field) \ | |
525 | (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ | |
526 | (elm)->field.tqe_next = (listelm); \ | |
527 | *(listelm)->field.tqe_prev = (elm); \ | |
528 | (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ | |
529 | } while (/*CONSTCOND*/0) | |
530 | ||
531 | #define TAILQ_REMOVE(head, elm, field) do { \ | |
532 | QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field) \ | |
533 | QUEUEDEBUG_TAILQ_OP((elm), field) \ | |
534 | if (((elm)->field.tqe_next) != TAILQ_END(head)) \ | |
535 | (elm)->field.tqe_next->field.tqe_prev = \ | |
536 | (elm)->field.tqe_prev; \ | |
537 | else \ | |
538 | (head)->tqh_last = (elm)->field.tqe_prev; \ | |
539 | *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ | |
540 | QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \ | |
541 | } while (/*CONSTCOND*/0) | |
542 | ||
543 | #define TAILQ_REPLACE(head, elm, elm2, field) do { \ | |
544 | if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != \ | |
545 | TAILQ_END(head)) \ | |
546 | (elm2)->field.tqe_next->field.tqe_prev = \ | |
547 | &(elm2)->field.tqe_next; \ | |
548 | else \ | |
549 | (head)->tqh_last = &(elm2)->field.tqe_next; \ | |
550 | (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ | |
551 | *(elm2)->field.tqe_prev = (elm2); \ | |
552 | QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \ | |
553 | } while (/*CONSTCOND*/0) | |
554 | ||
555 | #define TAILQ_CONCAT(head1, head2, field) do { \ | |
556 | if (!TAILQ_EMPTY(head2)) { \ | |
557 | *(head1)->tqh_last = (head2)->tqh_first; \ | |
558 | (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ | |
559 | (head1)->tqh_last = (head2)->tqh_last; \ | |
560 | TAILQ_INIT((head2)); \ | |
561 | } \ | |
562 | } while (/*CONSTCOND*/0) | |
563 | ||
564 | /* | |
565 | * Singly-linked Tail queue declarations. | |
566 | */ | |
567 | #define STAILQ_HEAD(name, type) \ | |
568 | struct name { \ | |
569 | struct type *stqh_first; /* first element */ \ | |
570 | struct type **stqh_last; /* addr of last next element */ \ | |
571 | } | |
572 | ||
573 | #define STAILQ_HEAD_INITIALIZER(head) \ | |
574 | { NULL, &(head).stqh_first } | |
575 | ||
576 | #define STAILQ_ENTRY(type) \ | |
577 | struct { \ | |
578 | struct type *stqe_next; /* next element */ \ | |
579 | } | |
580 | ||
581 | /* | |
582 | * Singly-linked Tail queue access methods. | |
583 | */ | |
584 | #define STAILQ_FIRST(head) ((head)->stqh_first) | |
585 | #define STAILQ_END(head) NULL | |
586 | #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) | |
587 | #define STAILQ_EMPTY(head) (STAILQ_FIRST(head) == STAILQ_END(head)) | |
588 | ||
589 | /* | |
590 | * Singly-linked Tail queue functions. | |
591 | */ | |
592 | #define STAILQ_INIT(head) do { \ | |
593 | (head)->stqh_first = NULL; \ | |
594 | (head)->stqh_last = &(head)->stqh_first; \ | |
595 | } while (/*CONSTCOND*/0) | |
596 | ||
597 | #define STAILQ_INSERT_HEAD(head, elm, field) do { \ | |
598 | if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \ | |
599 | (head)->stqh_last = &(elm)->field.stqe_next; \ | |
600 | (head)->stqh_first = (elm); \ | |
601 | } while (/*CONSTCOND*/0) | |
602 | ||
603 | #define STAILQ_INSERT_TAIL(head, elm, field) do { \ | |
604 | (elm)->field.stqe_next = NULL; \ | |
605 | *(head)->stqh_last = (elm); \ | |
606 | (head)->stqh_last = &(elm)->field.stqe_next; \ | |
607 | } while (/*CONSTCOND*/0) | |
608 | ||
609 | #define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ | |
610 | if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\ | |
611 | (head)->stqh_last = &(elm)->field.stqe_next; \ | |
612 | (listelm)->field.stqe_next = (elm); \ | |
613 | } while (/*CONSTCOND*/0) | |
614 | ||
615 | #define STAILQ_REMOVE_HEAD(head, field) do { \ | |
616 | if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \ | |
617 | (head)->stqh_last = &(head)->stqh_first; \ | |
618 | } while (/*CONSTCOND*/0) | |
619 | ||
620 | #define STAILQ_REMOVE(head, elm, type, field) do { \ | |
621 | if ((head)->stqh_first == (elm)) { \ | |
622 | STAILQ_REMOVE_HEAD((head), field); \ | |
623 | } else { \ | |
624 | struct type *curelm = (head)->stqh_first; \ | |
625 | while (curelm->field.stqe_next != (elm)) \ | |
626 | curelm = curelm->field.stqe_next; \ | |
627 | if ((curelm->field.stqe_next = \ | |
628 | curelm->field.stqe_next->field.stqe_next) == NULL) \ | |
629 | (head)->stqh_last = &(curelm)->field.stqe_next; \ | |
630 | } \ | |
631 | } while (/*CONSTCOND*/0) | |
632 | ||
633 | #define STAILQ_FOREACH(var, head, field) \ | |
634 | for ((var) = ((head)->stqh_first); \ | |
635 | (var); \ | |
636 | (var) = ((var)->field.stqe_next)) | |
637 | ||
638 | #define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ | |
639 | for ((var) = STAILQ_FIRST((head)); \ | |
640 | (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ | |
641 | (var) = (tvar)) | |
642 | ||
643 | #define STAILQ_CONCAT(head1, head2) do { \ | |
644 | if (!STAILQ_EMPTY((head2))) { \ | |
645 | *(head1)->stqh_last = (head2)->stqh_first; \ | |
646 | (head1)->stqh_last = (head2)->stqh_last; \ | |
647 | STAILQ_INIT((head2)); \ | |
648 | } \ | |
649 | } while (/*CONSTCOND*/0) | |
650 | ||
651 | #define STAILQ_LAST(head, type, field) \ | |
652 | (STAILQ_EMPTY((head)) ? \ | |
653 | NULL : \ | |
654 | ((struct type *)(void *) \ | |
655 | ((char *)((head)->stqh_last) - offsetof(struct type, field)))) | |
656 | ||
657 | ||
658 | #ifndef _KERNEL | |
659 | /* | |
660 | * Circular queue definitions. Do not use. We still keep the macros | |
661 | * for compatibility but because of pointer aliasing issues their use | |
662 | * is discouraged! | |
663 | */ | |
664 | ||
665 | /* | |
666 | * __launder_type(): We use this ugly hack to work around the the compiler | |
667 | * noticing that two types may not alias each other and elide tests in code. | |
668 | * We hit this in the CIRCLEQ macros when comparing 'struct name *' and | |
669 | * 'struct type *' (see CIRCLEQ_HEAD()). Modern compilers (such as GCC | |
670 | * 4.8) declare these comparisons as always false, causing the code to | |
671 | * not run as designed. | |
672 | * | |
673 | * This hack is only to be used for comparisons and thus can be fully const. | |
674 | * Do not use for assignment. | |
675 | * | |
676 | * If we ever choose to change the ABI of the CIRCLEQ macros, we could fix | |
677 | * this by changing the head/tail sentinal values, but see the note above | |
678 | * this one. | |
679 | */ | |
680 | static __inline const void * __launder_type(const void *); | |
681 | static __inline const void * | |
682 | __launder_type(const void *__x) | |
683 | { | |
684 | __asm __volatile("" : "+r" (__x)); | |
685 | return __x; | |
686 | } | |
687 | ||
688 | #if defined(QUEUEDEBUG) | |
689 | #define QUEUEDEBUG_CIRCLEQ_HEAD(head, field) \ | |
690 | if ((head)->cqh_first != CIRCLEQ_ENDC(head) && \ | |
691 | (head)->cqh_first->field.cqe_prev != CIRCLEQ_ENDC(head)) \ | |
692 | QUEUEDEBUG_ABORT("CIRCLEQ head forw %p %s:%d", (head), \ | |
693 | __FILE__, __LINE__); \ | |
694 | if ((head)->cqh_last != CIRCLEQ_ENDC(head) && \ | |
695 | (head)->cqh_last->field.cqe_next != CIRCLEQ_ENDC(head)) \ | |
696 | QUEUEDEBUG_ABORT("CIRCLEQ head back %p %s:%d", (head), \ | |
697 | __FILE__, __LINE__); | |
698 | #define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field) \ | |
699 | if ((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) { \ | |
700 | if ((head)->cqh_last != (elm)) \ | |
701 | QUEUEDEBUG_ABORT("CIRCLEQ elm last %p %s:%d", \ | |
702 | (elm), __FILE__, __LINE__); \ | |
703 | } else { \ | |
704 | if ((elm)->field.cqe_next->field.cqe_prev != (elm)) \ | |
705 | QUEUEDEBUG_ABORT("CIRCLEQ elm forw %p %s:%d", \ | |
706 | (elm), __FILE__, __LINE__); \ | |
707 | } \ | |
708 | if ((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) { \ | |
709 | if ((head)->cqh_first != (elm)) \ | |
710 | QUEUEDEBUG_ABORT("CIRCLEQ elm first %p %s:%d", \ | |
711 | (elm), __FILE__, __LINE__); \ | |
712 | } else { \ | |
713 | if ((elm)->field.cqe_prev->field.cqe_next != (elm)) \ | |
714 | QUEUEDEBUG_ABORT("CIRCLEQ elm prev %p %s:%d", \ | |
715 | (elm), __FILE__, __LINE__); \ | |
716 | } | |
717 | #define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field) \ | |
718 | (elm)->field.cqe_next = (void *)1L; \ | |
719 | (elm)->field.cqe_prev = (void *)1L; | |
720 | #else | |
721 | #define QUEUEDEBUG_CIRCLEQ_HEAD(head, field) | |
722 | #define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field) | |
723 | #define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field) | |
724 | #endif | |
725 | ||
726 | #define CIRCLEQ_HEAD(name, type) \ | |
727 | struct name { \ | |
728 | struct type *cqh_first; /* first element */ \ | |
729 | struct type *cqh_last; /* last element */ \ | |
730 | } | |
731 | ||
732 | #define CIRCLEQ_HEAD_INITIALIZER(head) \ | |
733 | { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } | |
734 | ||
735 | #define CIRCLEQ_ENTRY(type) \ | |
736 | struct { \ | |
737 | struct type *cqe_next; /* next element */ \ | |
738 | struct type *cqe_prev; /* previous element */ \ | |
739 | } | |
740 | ||
741 | /* | |
742 | * Circular queue functions. | |
743 | */ | |
744 | #define CIRCLEQ_INIT(head) do { \ | |
745 | (head)->cqh_first = CIRCLEQ_END(head); \ | |
746 | (head)->cqh_last = CIRCLEQ_END(head); \ | |
747 | } while (/*CONSTCOND*/0) | |
748 | ||
749 | #define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ | |
750 | QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ | |
751 | QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \ | |
752 | (elm)->field.cqe_next = (listelm)->field.cqe_next; \ | |
753 | (elm)->field.cqe_prev = (listelm); \ | |
754 | if ((listelm)->field.cqe_next == CIRCLEQ_ENDC(head)) \ | |
755 | (head)->cqh_last = (elm); \ | |
756 | else \ | |
757 | (listelm)->field.cqe_next->field.cqe_prev = (elm); \ | |
758 | (listelm)->field.cqe_next = (elm); \ | |
759 | } while (/*CONSTCOND*/0) | |
760 | ||
761 | #define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ | |
762 | QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ | |
763 | QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \ | |
764 | (elm)->field.cqe_next = (listelm); \ | |
765 | (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ | |
766 | if ((listelm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \ | |
767 | (head)->cqh_first = (elm); \ | |
768 | else \ | |
769 | (listelm)->field.cqe_prev->field.cqe_next = (elm); \ | |
770 | (listelm)->field.cqe_prev = (elm); \ | |
771 | } while (/*CONSTCOND*/0) | |
772 | ||
773 | #define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ | |
774 | QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ | |
775 | (elm)->field.cqe_next = (head)->cqh_first; \ | |
776 | (elm)->field.cqe_prev = CIRCLEQ_END(head); \ | |
777 | if ((head)->cqh_last == CIRCLEQ_ENDC(head)) \ | |
778 | (head)->cqh_last = (elm); \ | |
779 | else \ | |
780 | (head)->cqh_first->field.cqe_prev = (elm); \ | |
781 | (head)->cqh_first = (elm); \ | |
782 | } while (/*CONSTCOND*/0) | |
783 | ||
784 | #define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ | |
785 | QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ | |
786 | (elm)->field.cqe_next = CIRCLEQ_END(head); \ | |
787 | (elm)->field.cqe_prev = (head)->cqh_last; \ | |
788 | if ((head)->cqh_first == CIRCLEQ_ENDC(head)) \ | |
789 | (head)->cqh_first = (elm); \ | |
790 | else \ | |
791 | (head)->cqh_last->field.cqe_next = (elm); \ | |
792 | (head)->cqh_last = (elm); \ | |
793 | } while (/*CONSTCOND*/0) | |
794 | ||
795 | #define CIRCLEQ_REMOVE(head, elm, field) do { \ | |
796 | QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ | |
797 | QUEUEDEBUG_CIRCLEQ_ELM((head), (elm), field) \ | |
798 | if ((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) \ | |
799 | (head)->cqh_last = (elm)->field.cqe_prev; \ | |
800 | else \ | |
801 | (elm)->field.cqe_next->field.cqe_prev = \ | |
802 | (elm)->field.cqe_prev; \ | |
803 | if ((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \ | |
804 | (head)->cqh_first = (elm)->field.cqe_next; \ | |
805 | else \ | |
806 | (elm)->field.cqe_prev->field.cqe_next = \ | |
807 | (elm)->field.cqe_next; \ | |
808 | QUEUEDEBUG_CIRCLEQ_POSTREMOVE((elm), field) \ | |
809 | } while (/*CONSTCOND*/0) | |
810 | ||
811 | #define CIRCLEQ_FOREACH(var, head, field) \ | |
812 | for ((var) = ((head)->cqh_first); \ | |
813 | (var) != CIRCLEQ_ENDC(head); \ | |
814 | (var) = ((var)->field.cqe_next)) | |
815 | ||
816 | #define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ | |
817 | for ((var) = ((head)->cqh_last); \ | |
818 | (var) != CIRCLEQ_ENDC(head); \ | |
819 | (var) = ((var)->field.cqe_prev)) | |
820 | ||
821 | /* | |
822 | * Circular queue access methods. | |
823 | */ | |
824 | #define CIRCLEQ_FIRST(head) ((head)->cqh_first) | |
825 | #define CIRCLEQ_LAST(head) ((head)->cqh_last) | |
826 | /* For comparisons */ | |
827 | #define CIRCLEQ_ENDC(head) (__launder_type(head)) | |
828 | /* For assignments */ | |
829 | #define CIRCLEQ_END(head) ((void *)(head)) | |
830 | #define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) | |
831 | #define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) | |
832 | #define CIRCLEQ_EMPTY(head) \ | |
833 | (CIRCLEQ_FIRST(head) == CIRCLEQ_ENDC(head)) | |
834 | ||
835 | #define CIRCLEQ_LOOP_NEXT(head, elm, field) \ | |
836 | (((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) \ | |
837 | ? ((head)->cqh_first) \ | |
838 | : (elm->field.cqe_next)) | |
839 | #define CIRCLEQ_LOOP_PREV(head, elm, field) \ | |
840 | (((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \ | |
841 | ? ((head)->cqh_last) \ | |
842 | : (elm->field.cqe_prev)) | |
843 | #endif /* !_KERNEL */ | |
844 | ||
845 | #endif /* !_SYS_QUEUE_H_ */ |
3 | 3 | INCS= einfo.h |
4 | 4 | VERSION_MAP= einfo.map |
5 | 5 | |
6 | CPPFLAGS+= -I../includes | |
6 | LOCAL_CPPFLAGS+= -I../includes | |
7 | 7 | |
8 | 8 | MK= ../../mk |
9 | 9 | include ${MK}/lib.mk |
47 | 47 | # endif |
48 | 48 | #endif |
49 | 49 | |
50 | __BEGIN_DECLS | |
50 | /* __BEGIN_DECLS */ | |
51 | #ifdef __cplusplus | |
52 | extern "C" { | |
53 | #endif | |
51 | 54 | |
52 | 55 | /*! @brief Color types to use */ |
53 | 56 | typedef enum |
139 | 142 | /*! @brief Prefix each einfo line with something */ |
140 | 143 | void eprefix(const char * EINFO_RESTRICT); |
141 | 144 | |
142 | __END_DECLS | |
145 | /* __END_DECLS */ | |
146 | #ifdef __cplusplus | |
147 | } | |
143 | 148 | #endif |
149 | ||
150 | #endif |
6 | 6 | |
7 | 7 | LDADD+= ${LIBKVM} |
8 | 8 | |
9 | CPPFLAGS+= -I../includes | |
9 | LOCAL_CPPFLAGS+= -I../includes | |
10 | 10 | |
11 | 11 | MK= ../../mk |
12 | 12 | include ${MK}/lib.mk |
27 | 27 | * SUCH DAMAGE. |
28 | 28 | */ |
29 | 29 | |
30 | #include "queue.h" | |
30 | 31 | #include "librc.h" |
31 | 32 | |
32 | #if defined(__linux__) || defined (__GLIBC__) | |
33 | #if defined(__linux__) || (defined (__FreeBSD_kernel__) && defined(__GLIBC__)) | |
33 | 34 | static bool |
34 | 35 | pid_is_exec(pid_t pid, const char *exec) |
35 | 36 | { |
97 | 98 | pid_t p; |
98 | 99 | char buffer[PATH_MAX]; |
99 | 100 | struct stat sb; |
100 | pid_t runscript_pid = 0; | |
101 | pid_t openrc_pid = 0; | |
101 | 102 | char *pp; |
102 | 103 | RC_PIDLIST *pids = NULL; |
103 | 104 | RC_PID *pi; |
106 | 107 | return NULL; |
107 | 108 | |
108 | 109 | /* |
109 | We never match RC_RUNSCRIPT_PID if present so we avoid the below | |
110 | We never match RC_OPENRC_PID if present so we avoid the below | |
110 | 111 | scenario |
111 | 112 | |
112 | 113 | /etc/init.d/ntpd stop does |
116 | 117 | nasty |
117 | 118 | */ |
118 | 119 | |
119 | if ((pp = getenv("RC_RUNSCRIPT_PID"))) { | |
120 | if (sscanf(pp, "%d", &runscript_pid) != 1) | |
121 | runscript_pid = 0; | |
120 | if ((pp = getenv("RC_OPENRC_PID"))) { | |
121 | if (sscanf(pp, "%d", &openrc_pid) != 1) | |
122 | openrc_pid = 0; | |
122 | 123 | } |
123 | 124 | |
124 | 125 | /* |
144 | 145 | while ((entry = readdir(procdir)) != NULL) { |
145 | 146 | if (sscanf(entry->d_name, "%d", &p) != 1) |
146 | 147 | continue; |
147 | if (runscript_pid != 0 && runscript_pid == p) | |
148 | if (openrc_pid != 0 && openrc_pid == p) | |
148 | 149 | continue; |
149 | 150 | if (pid != 0 && pid != p) |
150 | 151 | continue; |
508 | 509 | RC_STRINGLIST *list = NULL; |
509 | 510 | RC_STRING *s; |
510 | 511 | size_t i; |
512 | char *ch_root; | |
513 | char *spidfile; | |
511 | 514 | |
512 | 515 | path += snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s", |
513 | 516 | basename_c(service)); |
551 | 554 | } |
552 | 555 | } |
553 | 556 | fclose(fp); |
557 | ||
558 | ch_root = rc_service_value_get(basename_c(service), "chroot"); | |
559 | spidfile = pidfile; | |
560 | if (ch_root && pidfile) { | |
561 | spidfile = xmalloc(strlen(ch_root) + strlen(pidfile) + 1); | |
562 | strcpy(spidfile, ch_root); | |
563 | strcat(spidfile, pidfile); | |
564 | free(pidfile); | |
565 | pidfile = spidfile; | |
566 | } | |
554 | 567 | |
555 | 568 | pid = 0; |
556 | 569 | if (pidfile) { |
29 | 29 | |
30 | 30 | #include <sys/utsname.h> |
31 | 31 | |
32 | #include "queue.h" | |
32 | 33 | #include "librc.h" |
33 | 34 | |
34 | 35 | #define GENDEP RC_LIBEXECDIR "/sh/gendepends.sh" |
27 | 27 | * SUCH DAMAGE. |
28 | 28 | */ |
29 | 29 | |
30 | #include "queue.h" | |
30 | 31 | #include "librc.h" |
31 | 32 | |
32 | 33 | RC_STRINGLIST * |
29 | 29 | |
30 | 30 | const char librc_copyright[] = "Copyright (c) 2007-2008 Roy Marples"; |
31 | 31 | |
32 | #include "queue.h" | |
32 | 33 | #include "librc.h" |
33 | 34 | #ifdef __FreeBSD__ |
34 | 35 | # include <sys/sysctl.h> |
99 | 100 | continue; |
100 | 101 | } |
101 | 102 | if (options & LS_DIR) { |
102 | if (stat(d->d_name, &buf) == 0 && | |
103 | snprintf(file, sizeof(file), "%s/%s", | |
104 | dir, d->d_name); | |
105 | if (stat(file, &buf) != 0 || | |
103 | 106 | !S_ISDIR(buf.st_mode)) |
104 | 107 | continue; |
105 | 108 | } |
292 | 295 | return RC_SYS_OPENVZ; /* old test */ |
293 | 296 | else if (file_regex("/proc/1/environ", "container=lxc")) |
294 | 297 | return RC_SYS_LXC; |
298 | else if (file_regex("/proc/1/environ", "container=systemd-nspawn")) | |
299 | return RC_SYS_SYSTEMD_NSPAWN; | |
295 | 300 | #endif |
296 | 301 | |
297 | 302 | return NULL; |
56 | 56 | #include <time.h> |
57 | 57 | #include <unistd.h> |
58 | 58 | |
59 | #ifdef BSD | |
59 | #if defined(BSD) && !defined(__GNU__) | |
60 | 60 | #include <sys/param.h> |
61 | 61 | #include <sys/user.h> |
62 | 62 | #include <sys/sysctl.h> |
63 | 63 | #include <kvm.h> |
64 | #else | |
65 | #include <sys/param.h> | |
64 | 66 | #endif |
65 | 67 | |
66 | 68 | #include "rc.h" |
26 | 26 | #define __RC_H__ |
27 | 27 | |
28 | 28 | #include <sys/types.h> |
29 | #include <sys/queue.h> | |
30 | 29 | #include <stdbool.h> |
31 | 30 | #include <stdio.h> |
32 | 31 | |
33 | __BEGIN_DECLS | |
32 | /* __BEGIN_DECLS */ | |
33 | #ifdef __cplusplus | |
34 | extern "C" { | |
35 | #endif | |
34 | 36 | |
35 | 37 | #define RC_PREFIX "@PREFIX@" |
36 | 38 | #define RC_SYSCONFDIR "@SYSCONFDIR@" |
38 | 40 | #define RC_LIBEXECDIR "@LIBEXECDIR@" |
39 | 41 | #if defined(PREFIX) |
40 | 42 | #define RC_SVCDIR RC_LIBEXECDIR "/init.d" |
41 | #elif defined(__linux__) | |
43 | #elif defined(__linux__) || (defined(__FreeBSD_kernel__) && \ | |
44 | defined(__GLIBC__)) || defined(__GNU__) | |
42 | 45 | #define RC_SVCDIR "/run/openrc" |
43 | 46 | #else |
44 | 47 | #define RC_SVCDIR RC_LIBEXECDIR "/init.d" |
72 | 75 | # define RC_LOCAL_INITDIR RC_LOCAL_PREFIX "/etc/init.d" |
73 | 76 | # define RC_LOCAL_CONFDIR RC_LOCAL_PREFIX "/etc/conf.d" |
74 | 77 | #endif |
78 | ||
79 | #ifndef _SYS_QUEUE_H_ | |
80 | ||
81 | /* | |
82 | * The following are copied directly from our imported queue.h. | |
83 | */ | |
84 | ||
85 | /* | |
86 | * List definitions. | |
87 | */ | |
88 | #define LIST_HEAD(name, type) \ | |
89 | struct name { \ | |
90 | struct type *lh_first; /* first element */ \ | |
91 | } | |
92 | ||
93 | #define LIST_HEAD_INITIALIZER(head) \ | |
94 | { NULL } | |
95 | ||
96 | #define LIST_ENTRY(type) \ | |
97 | struct { \ | |
98 | struct type *le_next; /* next element */ \ | |
99 | struct type **le_prev; /* address of previous next element */ \ | |
100 | } | |
101 | ||
102 | /* | |
103 | * Tail queue definitions. | |
104 | */ | |
105 | #define _TAILQ_HEAD(name, type, qual) \ | |
106 | struct name { \ | |
107 | qual type *tqh_first; /* first element */ \ | |
108 | qual type *qual *tqh_last; /* addr of last next element */ \ | |
109 | } | |
110 | #define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,) | |
111 | ||
112 | #define TAILQ_HEAD_INITIALIZER(head) \ | |
113 | { TAILQ_END(head), &(head).tqh_first } | |
114 | ||
115 | #define _TAILQ_ENTRY(type, qual) \ | |
116 | struct { \ | |
117 | qual type *tqe_next; /* next element */ \ | |
118 | qual type *qual *tqe_prev; /* address of previous next element */\ | |
119 | } | |
120 | #define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,) | |
121 | ||
122 | #endif /* _SYS_QUEUE_H_ */ | |
75 | 123 | |
76 | 124 | /* A doubly linked list using queue(3) for ease of use */ |
77 | 125 | typedef struct rc_string { |
283 | 331 | #define RC_SYS_OPENVZ "OPENVZ" |
284 | 332 | #define RC_SYS_LXC "LXC" |
285 | 333 | #define RC_SYS_PREFIX "PREFIX" |
334 | #define RC_SYS_SYSTEMD_NSPAWN "SYSTEMD-NSPAWN" | |
286 | 335 | #define RC_SYS_UML "UML" |
287 | 336 | #define RC_SYS_VSERVER "VSERVER" |
288 | 337 | #define RC_SYS_XEN0 "XEN0" |
562 | 611 | * we have our own */ |
563 | 612 | ssize_t rc_getline(char **, size_t *, FILE *); |
564 | 613 | |
565 | __END_DECLS | |
614 | /* __END_DECLS */ | |
615 | #ifdef __cplusplus | |
616 | } | |
566 | 617 | #endif |
618 | ||
619 | #endif |
0 | 0 | PROG= openrc |
1 | SRCS= checkpath.c fstabinfo.c mountinfo.c start-stop-daemon.c \ | |
1 | SRCS= checkpath.c fstabinfo.c mountinfo.c openrc-run.c \ | |
2 | 2 | rc-applets.c rc-depend.c rc-logger.c \ |
3 | 3 | rc-misc.c rc-plugin.c rc-service.c rc-status.c rc-update.c \ |
4 | runscript.c rc.c swclock.c | |
4 | rc.c start-stop-daemon.c swclock.c | |
5 | 5 | |
6 | 6 | ifeq (${MKSELINUX},yes) |
7 | 7 | SRCS+= rc-selinux.c |
34 | 34 | ALL_LINKS= ${BINLINKS} ${SBINLINKS} ${RC_BINLINKS} ${RC_SBINLINKS} |
35 | 35 | CLEANFILES+= ${ALL_LINKS} |
36 | 36 | |
37 | CPPFLAGS+= -I../includes -I../librc -I../libeinfo | |
38 | LDFLAGS+= -L../librc -L../libeinfo | |
37 | LOCAL_CPPFLAGS=-I../includes -I../librc -I../libeinfo | |
38 | LOCAL_LDFLAGS=-L../librc -L../libeinfo | |
39 | 39 | LDADD+= -lutil -lrc -leinfo |
40 | 40 | |
41 | 41 | include ../../Makefile.inc |
42 | 42 | MK= ../../mk |
43 | 43 | include ${MK}/prog.mk |
44 | include ${MK}/git.mk | |
44 | include ${MK}/gitver.mk | |
45 | 45 | include ${MK}/cc.mk |
46 | 46 | |
47 | 47 | include ${MK}/termcap.mk |
22 | 22 | * SUCH DAMAGE. |
23 | 23 | */ |
24 | 24 | |
25 | #include "queue.h" | |
25 | 26 | #include "rc.h" |
26 | 27 | |
27 | 28 | int checkpath(int, char **); |
44 | 44 | #include "builtins.h" |
45 | 45 | #include "einfo.h" |
46 | 46 | #include "rc-misc.h" |
47 | ||
48 | #ifdef HAVE_SELINUX | |
49 | 47 | #include "rc-selinux.h" |
50 | #endif | |
51 | 48 | |
52 | 49 | typedef enum { |
53 | 50 | inode_unknown = 0, |
67 | 64 | int u; |
68 | 65 | |
69 | 66 | memset(&st, 0, sizeof(st)); |
70 | if (stat(path, &st) || trunc) { | |
67 | if (lstat(path, &st) || trunc) { | |
71 | 68 | if (type == inode_file) { |
72 | 69 | einfo("%s: creating file", path); |
73 | 70 | if (!mode) /* 664 */ |
132 | 129 | } |
133 | 130 | |
134 | 131 | if (mode && (st.st_mode & 0777) != mode) { |
132 | if ((type != inode_dir) && (st.st_nlink > 1)) { | |
133 | eerror("%s: chmod: %s %s", applet, "Too many hard links to", path); | |
134 | return -1; | |
135 | } | |
136 | if (S_ISLNK(st.st_mode)) { | |
137 | eerror("%s: chmod: %s %s", applet, path, " is a symbolic link"); | |
138 | return -1; | |
139 | } | |
135 | 140 | einfo("%s: correcting mode", path); |
136 | 141 | if (chmod(path, mode)) { |
137 | 142 | eerror("%s: chmod: %s", applet, strerror(errno)); |
140 | 145 | } |
141 | 146 | |
142 | 147 | if (chowner && (st.st_uid != uid || st.st_gid != gid)) { |
148 | if ((type != inode_dir) && (st.st_nlink > 1)) { | |
149 | eerror("%s: chown: %s %s", applet, "Too many hard links to", path); | |
150 | return -1; | |
151 | } | |
152 | if (S_ISLNK(st.st_mode)) { | |
153 | eerror("%s: chown: %s %s", applet, path, " is a symbolic link"); | |
154 | return -1; | |
155 | } | |
143 | 156 | einfo("%s: correcting owner", path); |
144 | 157 | if (chown(path, uid, gid)) { |
145 | 158 | eerror("%s: chown: %s", applet, strerror(errno)); |
147 | 160 | } |
148 | 161 | } |
149 | 162 | |
150 | #ifdef HAVE_SELINUX | |
151 | 163 | if (selinux_on) |
152 | 164 | selinux_util_label(path); |
153 | #endif | |
154 | 165 | |
155 | 166 | return 0; |
156 | 167 | } |
279 | 290 | if (gr) |
280 | 291 | gid = gr->gr_gid; |
281 | 292 | |
282 | #ifdef HAVE_SELINUX | |
283 | 293 | if (selinux_util_open() == 1) |
284 | 294 | selinux_on = true; |
285 | #endif | |
286 | 295 | |
287 | 296 | while (optind < argc) { |
288 | 297 | if (writable) |
292 | 301 | optind++; |
293 | 302 | } |
294 | 303 | |
295 | #ifdef HAVE_SELINUX | |
296 | 304 | if (selinux_on) |
297 | 305 | selinux_util_close(); |
298 | #endif | |
299 | 306 | |
300 | 307 | return retval; |
301 | 308 | } |
69 | 69 | |
70 | 70 | #include "builtins.h" |
71 | 71 | #include "einfo.h" |
72 | #include "queue.h" | |
72 | 73 | #include "rc.h" |
73 | 74 | #include "rc-misc.h" |
74 | 75 |
34 | 34 | # include <sys/ucred.h> |
35 | 35 | # include <sys/mount.h> |
36 | 36 | # define F_FLAGS f_flags |
37 | #elif defined(BSD) | |
37 | #elif defined(BSD) && !defined(__GNU__) | |
38 | 38 | # include <sys/statvfs.h> |
39 | 39 | # define statfs statvfs |
40 | 40 | # define F_FLAGS f_flag |
41 | #elif defined (__linux__) || defined (__GLIBC__) | |
41 | #elif defined (__linux__) || (defined(__FreeBSD_kernel__) && \ | |
42 | defined(__GLIBC__)) || defined(__GNU__) | |
42 | 43 | # include <mntent.h> |
43 | 44 | #endif |
44 | 45 | |
52 | 53 | |
53 | 54 | #include "builtins.h" |
54 | 55 | #include "einfo.h" |
56 | #include "queue.h" | |
55 | 57 | #include "rc.h" |
56 | 58 | #include "rc-misc.h" |
57 | 59 | |
167 | 169 | return -1; |
168 | 170 | } |
169 | 171 | |
170 | #ifdef BSD | |
172 | #if defined(BSD) && !defined(__GNU__) | |
171 | 173 | |
172 | 174 | /* Translate the mounted options to english |
173 | 175 | * This is taken directly from FreeBSD mount.c */ |
264 | 266 | return list; |
265 | 267 | } |
266 | 268 | |
267 | #elif defined (__linux__) || defined (__GLIBC__) | |
269 | #elif defined (__linux__) || (defined (__FreeBSD_kernel__) && \ | |
270 | defined(__GLIBC__)) | |
268 | 271 | static struct mntent * |
269 | 272 | getmntfile(const char *file) |
270 | 273 | { |
294 | 297 | int netdev; |
295 | 298 | RC_STRINGLIST *list; |
296 | 299 | |
297 | if ((fp = fopen("/proc/mounts", "r")) == NULL) | |
300 | if ((fp = fopen("/proc/self/mounts", "r")) == NULL) | |
298 | 301 | eerrorx("getmntinfo: %s", strerror(errno)); |
299 | 302 | |
300 | 303 | list = rc_stringlist_new(); |
311 | 314 | if ((ent = getmntfile(to))) { |
312 | 315 | if (strstr(ent->mnt_opts, "_netdev")) |
313 | 316 | netdev = 0; |
317 | else | |
318 | netdev = 1; | |
314 | 319 | } |
315 | 320 | |
316 | 321 | process_mount(list, args, from, to, fst, opts, netdev); |
343 | 348 | |
344 | 349 | #include "_usage.h" |
345 | 350 | #define extraopts "[mount1] [mount2] ..." |
346 | #define getoptstring "f:F:n:N:o:O:p:P:ist" getoptstring_COMMON | |
351 | #define getoptstring "f:F:n:N:o:O:p:P:iste:E:" getoptstring_COMMON | |
347 | 352 | static const struct option longopts[] = { |
348 | 353 | { "fstype-regex", 1, NULL, 'f'}, |
349 | 354 | { "skip-fstype-regex", 1, NULL, 'F'}, |
0 | /* | |
1 | * openrc-run.c | |
2 | * Handle launching of init scripts. | |
3 | */ | |
4 | ||
5 | /* | |
6 | * Copyright (c) 2007-2009 Roy Marples <roy@marples.name> | |
7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | |
16 | * | |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
27 | * SUCH DAMAGE. | |
28 | */ | |
29 | ||
30 | #include <sys/types.h> | |
31 | #include <sys/ioctl.h> | |
32 | #include <sys/file.h> | |
33 | #include <sys/param.h> | |
34 | #include <sys/stat.h> | |
35 | #include <sys/wait.h> | |
36 | ||
37 | #include <ctype.h> | |
38 | #include <errno.h> | |
39 | #include <fcntl.h> | |
40 | #include <fnmatch.h> | |
41 | #include <getopt.h> | |
42 | #include <libgen.h> | |
43 | #include <limits.h> | |
44 | #include <poll.h> | |
45 | #include <signal.h> | |
46 | #include <stdio.h> | |
47 | #include <stdlib.h> | |
48 | #include <string.h> | |
49 | #include <termios.h> | |
50 | #include <time.h> | |
51 | #include <unistd.h> | |
52 | ||
53 | #if defined(__linux__) || (defined(__FreeBSD_kernel__) && \ | |
54 | defined(__GLIBC__)) | |
55 | # include <pty.h> | |
56 | #elif defined(__NetBSD__) || defined(__OpenBSD__) | |
57 | # include <util.h> | |
58 | #else | |
59 | # include <libutil.h> | |
60 | #endif | |
61 | ||
62 | #include "builtins.h" | |
63 | #include "einfo.h" | |
64 | #include "queue.h" | |
65 | #include "rc.h" | |
66 | #include "rc-misc.h" | |
67 | #include "rc-plugin.h" | |
68 | #include "rc-selinux.h" | |
69 | ||
70 | #define PREFIX_LOCK RC_SVCDIR "/prefix.lock" | |
71 | ||
72 | #define WAIT_INTERVAL 20000000 /* usecs to poll the lock file */ | |
73 | #define WAIT_TIMEOUT 60 /* seconds until we timeout */ | |
74 | #define WARN_TIMEOUT 10 /* warn about this every N seconds */ | |
75 | ||
76 | static const char *applet; | |
77 | static char *service, *runlevel, *ibsave, *prefix; | |
78 | static RC_DEPTREE *deptree; | |
79 | static RC_STRINGLIST *applet_list, *services, *tmplist; | |
80 | static RC_STRINGLIST *restart_services, *need_services, *use_services; | |
81 | static RC_HOOK hook_out; | |
82 | static int exclusive_fd = -1, master_tty = -1; | |
83 | static bool sighup, in_background, deps, dry_run; | |
84 | static pid_t service_pid; | |
85 | static int signal_pipe[2] = { -1, -1 }; | |
86 | ||
87 | static RC_STRINGLIST *deptypes_b; | |
88 | static RC_STRINGLIST *deptypes_n; | |
89 | static RC_STRINGLIST *deptypes_nu; | |
90 | static RC_STRINGLIST *deptypes_nua; | |
91 | static RC_STRINGLIST *deptypes_m; | |
92 | static RC_STRINGLIST *deptypes_mua; | |
93 | ||
94 | static void | |
95 | handle_signal(int sig) | |
96 | { | |
97 | int serrno = errno; | |
98 | char signame[10] = { '\0' }; | |
99 | struct winsize ws; | |
100 | ||
101 | switch (sig) { | |
102 | case SIGHUP: | |
103 | sighup = true; | |
104 | break; | |
105 | ||
106 | case SIGCHLD: | |
107 | if (signal_pipe[1] > -1) { | |
108 | if (write(signal_pipe[1], &sig, sizeof(sig)) == -1) | |
109 | eerror("%s: send: %s", | |
110 | service, strerror(errno)); | |
111 | } else | |
112 | rc_waitpid(-1); | |
113 | break; | |
114 | ||
115 | case SIGWINCH: | |
116 | if (master_tty >= 0) { | |
117 | ioctl(fileno(stdout), TIOCGWINSZ, &ws); | |
118 | ioctl(master_tty, TIOCSWINSZ, &ws); | |
119 | } | |
120 | break; | |
121 | ||
122 | case SIGINT: | |
123 | if (!signame[0]) | |
124 | snprintf(signame, sizeof(signame), "SIGINT"); | |
125 | /* FALLTHROUGH */ | |
126 | case SIGTERM: | |
127 | if (!signame[0]) | |
128 | snprintf(signame, sizeof(signame), "SIGTERM"); | |
129 | /* FALLTHROUGH */ | |
130 | case SIGQUIT: | |
131 | if (!signame[0]) | |
132 | snprintf(signame, sizeof(signame), "SIGQUIT"); | |
133 | /* Send the signal to our children too */ | |
134 | if (service_pid > 0) | |
135 | kill(service_pid, sig); | |
136 | eerrorx("%s: caught %s, aborting", applet, signame); | |
137 | /* NOTREACHED */ | |
138 | ||
139 | default: | |
140 | eerror("%s: caught unknown signal %d", applet, sig); | |
141 | } | |
142 | ||
143 | /* Restore errno */ | |
144 | errno = serrno; | |
145 | } | |
146 | ||
147 | static void | |
148 | unhotplug() | |
149 | { | |
150 | char file[PATH_MAX]; | |
151 | ||
152 | snprintf(file, sizeof(file), RC_SVCDIR "/hotplugged/%s", applet); | |
153 | if (exists(file) && unlink(file) != 0) | |
154 | eerror("%s: unlink `%s': %s", applet, file, strerror(errno)); | |
155 | } | |
156 | ||
157 | static void | |
158 | start_services(RC_STRINGLIST *list) | |
159 | { | |
160 | RC_STRING *svc; | |
161 | RC_SERVICE state = rc_service_state (service); | |
162 | ||
163 | if (!list) | |
164 | return; | |
165 | ||
166 | if (state & RC_SERVICE_INACTIVE || | |
167 | state & RC_SERVICE_WASINACTIVE || | |
168 | state & RC_SERVICE_STARTING || | |
169 | state & RC_SERVICE_STARTED) | |
170 | { | |
171 | TAILQ_FOREACH(svc, list, entries) { | |
172 | if (!(rc_service_state(svc->value) & | |
173 | RC_SERVICE_STOPPED)) | |
174 | continue; | |
175 | if (state & RC_SERVICE_INACTIVE || | |
176 | state & RC_SERVICE_WASINACTIVE) | |
177 | { | |
178 | rc_service_schedule_start(service, | |
179 | svc->value); | |
180 | ewarn("WARNING: %s will start when %s has started", | |
181 | svc->value, applet); | |
182 | } else | |
183 | service_start(svc->value); | |
184 | } | |
185 | } | |
186 | } | |
187 | ||
188 | static void | |
189 | restore_state(void) | |
190 | { | |
191 | RC_SERVICE state; | |
192 | ||
193 | if (rc_in_plugin || exclusive_fd == -1) | |
194 | return; | |
195 | state = rc_service_state(applet); | |
196 | if (state & RC_SERVICE_STOPPING) { | |
197 | if (state & RC_SERVICE_WASINACTIVE) | |
198 | rc_service_mark(applet, RC_SERVICE_INACTIVE); | |
199 | else | |
200 | rc_service_mark(applet, RC_SERVICE_STARTED); | |
201 | if (rc_runlevel_stopping()) | |
202 | rc_service_mark(applet, RC_SERVICE_FAILED); | |
203 | } else if (state & RC_SERVICE_STARTING) { | |
204 | if (state & RC_SERVICE_WASINACTIVE) | |
205 | rc_service_mark(applet, RC_SERVICE_INACTIVE); | |
206 | else | |
207 | rc_service_mark(applet, RC_SERVICE_STOPPED); | |
208 | if (rc_runlevel_starting()) | |
209 | rc_service_mark(applet, RC_SERVICE_FAILED); | |
210 | } | |
211 | exclusive_fd = svc_unlock(applet, exclusive_fd); | |
212 | } | |
213 | ||
214 | static void | |
215 | cleanup(void) | |
216 | { | |
217 | restore_state(); | |
218 | ||
219 | if (!rc_in_plugin) { | |
220 | if (hook_out) { | |
221 | rc_plugin_run(hook_out, applet); | |
222 | if (hook_out == RC_HOOK_SERVICE_START_DONE) | |
223 | rc_plugin_run(RC_HOOK_SERVICE_START_OUT, | |
224 | applet); | |
225 | else if (hook_out == RC_HOOK_SERVICE_STOP_DONE) | |
226 | rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, | |
227 | applet); | |
228 | } | |
229 | ||
230 | if (restart_services) | |
231 | start_services(restart_services); | |
232 | } | |
233 | ||
234 | rc_plugin_unload(); | |
235 | ||
236 | #ifdef DEBUG_MEMORY | |
237 | rc_stringlist_free(deptypes_b); | |
238 | rc_stringlist_free(deptypes_n); | |
239 | rc_stringlist_free(deptypes_nu); | |
240 | rc_stringlist_free(deptypes_nua); | |
241 | rc_stringlist_free(deptypes_m); | |
242 | rc_stringlist_free(deptypes_mua); | |
243 | rc_deptree_free(deptree); | |
244 | rc_stringlist_free(restart_services); | |
245 | rc_stringlist_free(need_services); | |
246 | rc_stringlist_free(use_services); | |
247 | rc_stringlist_free(services); | |
248 | rc_stringlist_free(applet_list); | |
249 | rc_stringlist_free(tmplist); | |
250 | free(ibsave); | |
251 | free(service); | |
252 | free(prefix); | |
253 | free(runlevel); | |
254 | #endif | |
255 | } | |
256 | ||
257 | /* Buffer and lock all output messages so that we get readable content */ | |
258 | /* FIXME: Use a dynamic lock file that contains the tty/pts as well. | |
259 | * For example openrc-pts8.lock or openrc-tty1.lock. | |
260 | * Using a static lock file makes no sense, esp. in multi-user environments. | |
261 | * Why don't we use (f)printf, as it is thread-safe through POSIX already? | |
262 | * Bug: 360013 | |
263 | */ | |
264 | static int | |
265 | write_prefix(const char *buffer, size_t bytes, bool *prefixed) | |
266 | { | |
267 | size_t i, j; | |
268 | const char *ec = ecolor(ECOLOR_HILITE); | |
269 | const char *ec_normal = ecolor(ECOLOR_NORMAL); | |
270 | ssize_t ret = 0; | |
271 | int fd = fileno(stdout), lock_fd = -1; | |
272 | ||
273 | /* | |
274 | * Lock the prefix. | |
275 | * open() may fail here when running as user, as RC_SVCDIR may not be writable. | |
276 | */ | |
277 | lock_fd = open(PREFIX_LOCK, O_WRONLY | O_CREAT, 0664); | |
278 | ||
279 | if (lock_fd != -1) { | |
280 | while (flock(lock_fd, LOCK_EX) != 0) { | |
281 | if (errno != EINTR) { | |
282 | ewarnv("flock() failed: %s", strerror(errno)); | |
283 | break; | |
284 | } | |
285 | } | |
286 | } | |
287 | else | |
288 | ewarnv("Couldn't open the prefix lock, please make sure you have enough permissions"); | |
289 | ||
290 | for (i = 0; i < bytes; i++) { | |
291 | /* We don't prefix eend calls (cursor up) */ | |
292 | if (buffer[i] == '\033' && !*prefixed) { | |
293 | for (j = i + 1; j < bytes; j++) { | |
294 | if (buffer[j] == 'A') | |
295 | *prefixed = true; | |
296 | if (isalpha((unsigned int)buffer[j])) | |
297 | break; | |
298 | } | |
299 | } | |
300 | ||
301 | if (!*prefixed) { | |
302 | ret += write(fd, ec, strlen(ec)); | |
303 | ret += write(fd, prefix, strlen(prefix)); | |
304 | ret += write(fd, ec_normal, strlen(ec_normal)); | |
305 | ret += write(fd, "|", 1); | |
306 | *prefixed = true; | |
307 | } | |
308 | ||
309 | if (buffer[i] == '\n') | |
310 | *prefixed = false; | |
311 | ret += write(fd, buffer + i, 1); | |
312 | } | |
313 | ||
314 | /* Release the lock */ | |
315 | close(lock_fd); | |
316 | ||
317 | return ret; | |
318 | } | |
319 | ||
320 | static int | |
321 | svc_exec(const char *arg1, const char *arg2) | |
322 | { | |
323 | int ret, fdout = fileno(stdout); | |
324 | struct termios tt; | |
325 | struct winsize ws; | |
326 | int i; | |
327 | int flags = 0; | |
328 | struct pollfd fd[2]; | |
329 | int s; | |
330 | char *buffer; | |
331 | size_t bytes; | |
332 | bool prefixed = false; | |
333 | int slave_tty; | |
334 | sigset_t sigchldmask; | |
335 | sigset_t oldmask; | |
336 | ||
337 | /* Setup our signal pipe */ | |
338 | if (pipe(signal_pipe) == -1) | |
339 | eerrorx("%s: pipe: %s", service, applet); | |
340 | for (i = 0; i < 2; i++) | |
341 | if ((flags = fcntl(signal_pipe[i], F_GETFD, 0) == -1 || | |
342 | fcntl(signal_pipe[i], F_SETFD, flags | FD_CLOEXEC) == -1)) | |
343 | eerrorx("%s: fcntl: %s", service, strerror(errno)); | |
344 | ||
345 | /* Open a pty for our prefixed output | |
346 | * We do this instead of mapping pipes to stdout, stderr so that | |
347 | * programs can tell if they're attached to a tty or not. | |
348 | * The only loss is that we can no longer tell the difference | |
349 | * between the childs stdout or stderr */ | |
350 | master_tty = slave_tty = -1; | |
351 | if (prefix && isatty(fdout)) { | |
352 | tcgetattr(fdout, &tt); | |
353 | ioctl(fdout, TIOCGWINSZ, &ws); | |
354 | ||
355 | /* If the below call fails due to not enough ptys then we don't | |
356 | * prefix the output, but we still work */ | |
357 | openpty(&master_tty, &slave_tty, NULL, &tt, &ws); | |
358 | if (master_tty >= 0 && | |
359 | (flags = fcntl(master_tty, F_GETFD, 0)) == 0) | |
360 | fcntl(master_tty, F_SETFD, flags | FD_CLOEXEC); | |
361 | ||
362 | if (slave_tty >=0 && | |
363 | (flags = fcntl(slave_tty, F_GETFD, 0)) == 0) | |
364 | fcntl(slave_tty, F_SETFD, flags | FD_CLOEXEC); | |
365 | } | |
366 | ||
367 | service_pid = fork(); | |
368 | if (service_pid == -1) | |
369 | eerrorx("%s: fork: %s", service, strerror(errno)); | |
370 | if (service_pid == 0) { | |
371 | if (slave_tty >= 0) { | |
372 | dup2(slave_tty, STDOUT_FILENO); | |
373 | dup2(slave_tty, STDERR_FILENO); | |
374 | } | |
375 | ||
376 | if (exists(RC_SVCDIR "/openrc-run.sh")) { | |
377 | execl(RC_SVCDIR "/openrc-run.sh", | |
378 | RC_SVCDIR "/openrc-run.sh", | |
379 | service, arg1, arg2, (char *) NULL); | |
380 | eerror("%s: exec `" RC_SVCDIR "/openrc-run.sh': %s", | |
381 | service, strerror(errno)); | |
382 | _exit(EXIT_FAILURE); | |
383 | } else { | |
384 | execl(RC_LIBEXECDIR "/sh/openrc-run.sh", | |
385 | RC_LIBEXECDIR "/sh/openrc-run.sh", | |
386 | service, arg1, arg2, (char *) NULL); | |
387 | eerror("%s: exec `" RC_LIBEXECDIR "/sh/openrc-run.sh': %s", | |
388 | service, strerror(errno)); | |
389 | _exit(EXIT_FAILURE); | |
390 | } | |
391 | } | |
392 | ||
393 | buffer = xmalloc(sizeof(char) * BUFSIZ); | |
394 | fd[0].fd = signal_pipe[0]; | |
395 | fd[0].events = fd[1].events = POLLIN; | |
396 | fd[0].revents = fd[1].revents = 0; | |
397 | if (master_tty >= 0) { | |
398 | fd[1].fd = master_tty; | |
399 | fd[1].events = POLLIN; | |
400 | fd[1].revents = 0; | |
401 | } | |
402 | ||
403 | for (;;) { | |
404 | if ((s = poll(fd, master_tty >= 0 ? 2 : 1, -1)) == -1) { | |
405 | if (errno != EINTR) { | |
406 | eerror("%s: poll: %s", | |
407 | service, strerror(errno)); | |
408 | break; | |
409 | } | |
410 | } | |
411 | ||
412 | if (s > 0) { | |
413 | if (fd[1].revents & (POLLIN | POLLHUP)) { | |
414 | bytes = read(master_tty, buffer, BUFSIZ); | |
415 | write_prefix(buffer, bytes, &prefixed); | |
416 | } | |
417 | ||
418 | /* Only SIGCHLD signals come down this pipe */ | |
419 | if (fd[0].revents & (POLLIN | POLLHUP)) | |
420 | break; | |
421 | } | |
422 | } | |
423 | ||
424 | free(buffer); | |
425 | ||
426 | sigemptyset (&sigchldmask); | |
427 | sigaddset (&sigchldmask, SIGCHLD); | |
428 | sigprocmask (SIG_BLOCK, &sigchldmask, &oldmask); | |
429 | ||
430 | close(signal_pipe[0]); | |
431 | close(signal_pipe[1]); | |
432 | signal_pipe[0] = signal_pipe[1] = -1; | |
433 | ||
434 | sigprocmask (SIG_SETMASK, &oldmask, NULL); | |
435 | ||
436 | if (master_tty >= 0) { | |
437 | /* Why did we do this? */ | |
438 | /* signal (SIGWINCH, SIG_IGN); */ | |
439 | close(master_tty); | |
440 | master_tty = -1; | |
441 | } | |
442 | ||
443 | ret = rc_waitpid(service_pid); | |
444 | ret = WEXITSTATUS(ret); | |
445 | if (ret != 0 && errno == ECHILD) | |
446 | /* killall5 -9 could cause this */ | |
447 | ret = 0; | |
448 | service_pid = 0; | |
449 | ||
450 | return ret; | |
451 | } | |
452 | ||
453 | static bool | |
454 | svc_wait(const char *svc) | |
455 | { | |
456 | char file[PATH_MAX]; | |
457 | int fd; | |
458 | bool forever = false; | |
459 | RC_STRINGLIST *keywords; | |
460 | struct timespec interval, timeout, warn; | |
461 | ||
462 | /* Some services don't have a timeout, like fsck */ | |
463 | keywords = rc_deptree_depend(deptree, svc, "keyword"); | |
464 | if (rc_stringlist_find(keywords, "-timeout") || | |
465 | rc_stringlist_find(keywords, "notimeout")) | |
466 | forever = true; | |
467 | rc_stringlist_free(keywords); | |
468 | ||
469 | snprintf(file, sizeof(file), RC_SVCDIR "/exclusive/%s", | |
470 | basename_c(svc)); | |
471 | ||
472 | interval.tv_sec = 0; | |
473 | interval.tv_nsec = WAIT_INTERVAL; | |
474 | timeout.tv_sec = WAIT_TIMEOUT; | |
475 | timeout.tv_nsec = 0; | |
476 | warn.tv_sec = WARN_TIMEOUT; | |
477 | warn.tv_nsec = 0; | |
478 | for (;;) { | |
479 | fd = open(file, O_RDONLY | O_NONBLOCK); | |
480 | if (fd != -1) { | |
481 | if (flock(fd, LOCK_SH | LOCK_NB) == 0) { | |
482 | close(fd); | |
483 | return true; | |
484 | } | |
485 | close(fd); | |
486 | } | |
487 | if (errno == ENOENT) | |
488 | return true; | |
489 | if (errno != EWOULDBLOCK) | |
490 | eerrorx("%s: open `%s': %s", applet, file, | |
491 | strerror(errno)); | |
492 | if (nanosleep(&interval, NULL) == -1) { | |
493 | if (errno != EINTR) | |
494 | return false; | |
495 | } | |
496 | if (!forever) { | |
497 | timespecsub(&timeout, &interval, &timeout); | |
498 | if (timeout.tv_sec <= 0) | |
499 | return false; | |
500 | timespecsub(&warn, &interval, &warn); | |
501 | if (warn.tv_sec <= 0) { | |
502 | ewarn("%s: waiting for %s (%d seconds)", | |
503 | applet, svc, (int)timeout.tv_sec); | |
504 | warn.tv_sec = WARN_TIMEOUT; | |
505 | warn.tv_nsec = 0; | |
506 | } | |
507 | } | |
508 | } | |
509 | return false; | |
510 | } | |
511 | ||
512 | static void | |
513 | get_started_services(void) | |
514 | { | |
515 | RC_STRINGLIST *tmp = rc_services_in_state(RC_SERVICE_INACTIVE); | |
516 | ||
517 | rc_stringlist_free(restart_services); | |
518 | restart_services = rc_services_in_state(RC_SERVICE_STARTED); | |
519 | TAILQ_CONCAT(restart_services, tmp, entries); | |
520 | free(tmp); | |
521 | } | |
522 | ||
523 | static void | |
524 | setup_deptypes(void) | |
525 | { | |
526 | deptypes_b = rc_stringlist_new(); | |
527 | rc_stringlist_add(deptypes_b, "broken"); | |
528 | ||
529 | deptypes_n = rc_stringlist_new(); | |
530 | rc_stringlist_add(deptypes_n, "ineed"); | |
531 | ||
532 | deptypes_nu = rc_stringlist_new(); | |
533 | rc_stringlist_add(deptypes_nu, "ineed"); | |
534 | rc_stringlist_add(deptypes_nu, "iuse"); | |
535 | ||
536 | deptypes_nua = rc_stringlist_new(); | |
537 | rc_stringlist_add(deptypes_nua, "ineed"); | |
538 | rc_stringlist_add(deptypes_nua, "iuse"); | |
539 | rc_stringlist_add(deptypes_nua, "iafter"); | |
540 | ||
541 | deptypes_m = rc_stringlist_new(); | |
542 | rc_stringlist_add(deptypes_m, "needsme"); | |
543 | ||
544 | deptypes_mua = rc_stringlist_new(); | |
545 | rc_stringlist_add(deptypes_mua, "needsme"); | |
546 | rc_stringlist_add(deptypes_mua, "usesme"); | |
547 | rc_stringlist_add(deptypes_mua, "beforeme"); | |
548 | } | |
549 | ||
550 | static void | |
551 | svc_start_check(void) | |
552 | { | |
553 | RC_SERVICE state; | |
554 | ||
555 | state = rc_service_state(service); | |
556 | ||
557 | if (in_background) { | |
558 | if (!(state & (RC_SERVICE_INACTIVE | RC_SERVICE_STOPPED))) | |
559 | exit(EXIT_FAILURE); | |
560 | if (rc_yesno(getenv("IN_HOTPLUG"))) | |
561 | rc_service_mark(service, RC_SERVICE_HOTPLUGGED); | |
562 | if (strcmp(runlevel, RC_LEVEL_SYSINIT) == 0) | |
563 | ewarnx("WARNING: %s will be started in the" | |
564 | " next runlevel", applet); | |
565 | } | |
566 | ||
567 | if (exclusive_fd == -1) | |
568 | exclusive_fd = svc_lock(applet); | |
569 | if (exclusive_fd == -1) { | |
570 | if (errno == EACCES) | |
571 | eerrorx("%s: superuser access required", applet); | |
572 | if (state & RC_SERVICE_STOPPING) | |
573 | ewarnx("WARNING: %s is stopping", applet); | |
574 | else | |
575 | ewarnx("WARNING: %s is already starting", applet); | |
576 | } | |
577 | fcntl(exclusive_fd, F_SETFD, | |
578 | fcntl(exclusive_fd, F_GETFD, 0) | FD_CLOEXEC); | |
579 | ||
580 | if (state & RC_SERVICE_STARTED) { | |
581 | ewarn("WARNING: %s has already been started", applet); | |
582 | exit(EXIT_SUCCESS); | |
583 | } | |
584 | else if (state & RC_SERVICE_INACTIVE && !in_background) | |
585 | ewarnx("WARNING: %s has already started, but is inactive", | |
586 | applet); | |
587 | ||
588 | rc_service_mark(service, RC_SERVICE_STARTING); | |
589 | hook_out = RC_HOOK_SERVICE_START_OUT; | |
590 | rc_plugin_run(RC_HOOK_SERVICE_START_IN, applet); | |
591 | } | |
592 | ||
593 | static void | |
594 | svc_start_deps(void) | |
595 | { | |
596 | bool first; | |
597 | RC_STRING *svc, *svc2; | |
598 | RC_SERVICE state; | |
599 | int depoptions = RC_DEP_TRACE, n; | |
600 | size_t len; | |
601 | char *p, *tmp; | |
602 | pid_t pid; | |
603 | ||
604 | errno = 0; | |
605 | if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT) | |
606 | depoptions |= RC_DEP_STRICT; | |
607 | ||
608 | if (!deptree && ((deptree = _rc_deptree_load(0, NULL)) == NULL)) | |
609 | eerrorx("failed to load deptree"); | |
610 | if (!deptypes_b) | |
611 | setup_deptypes(); | |
612 | ||
613 | services = rc_deptree_depends(deptree, deptypes_b, applet_list, | |
614 | runlevel, 0); | |
615 | if (TAILQ_FIRST(services)) { | |
616 | eerrorn("ERROR: %s needs service(s) ", applet); | |
617 | first = true; | |
618 | TAILQ_FOREACH(svc, services, entries) { | |
619 | if (first) | |
620 | first = false; | |
621 | else | |
622 | fprintf(stderr, ", "); | |
623 | fprintf(stderr, "%s", svc->value); | |
624 | } | |
625 | fprintf(stderr, "\n"); | |
626 | exit(EXIT_FAILURE); | |
627 | } | |
628 | rc_stringlist_free(services); | |
629 | services = NULL; | |
630 | ||
631 | need_services = rc_deptree_depends(deptree, deptypes_n, | |
632 | applet_list, runlevel, depoptions); | |
633 | use_services = rc_deptree_depends(deptree, deptypes_nu, | |
634 | applet_list, runlevel, depoptions); | |
635 | ||
636 | if (!rc_runlevel_starting()) { | |
637 | TAILQ_FOREACH(svc, use_services, entries) { | |
638 | state = rc_service_state(svc->value); | |
639 | /* Don't stop failed services again. | |
640 | * If you remove this check, ensure that the | |
641 | * exclusive file isn't created. */ | |
642 | if (state & RC_SERVICE_FAILED && | |
643 | rc_runlevel_starting()) | |
644 | continue; | |
645 | if (state & RC_SERVICE_STOPPED) { | |
646 | if (dry_run) { | |
647 | printf(" %s", svc->value); | |
648 | continue; | |
649 | } | |
650 | pid = service_start(svc->value); | |
651 | if (!rc_conf_yesno("rc_parallel")) | |
652 | rc_waitpid(pid); | |
653 | } | |
654 | } | |
655 | } | |
656 | ||
657 | if (dry_run) | |
658 | return; | |
659 | ||
660 | /* Now wait for them to start */ | |
661 | services = rc_deptree_depends(deptree, deptypes_nua, applet_list, | |
662 | runlevel, depoptions); | |
663 | /* We use tmplist to hold our scheduled by list */ | |
664 | tmplist = rc_stringlist_new(); | |
665 | TAILQ_FOREACH(svc, services, entries) { | |
666 | state = rc_service_state(svc->value); | |
667 | if (state & RC_SERVICE_STARTED) | |
668 | continue; | |
669 | ||
670 | /* Don't wait for services which went inactive but are | |
671 | * now in starting state which we are after */ | |
672 | if (state & RC_SERVICE_STARTING && | |
673 | state & RC_SERVICE_WASINACTIVE) | |
674 | { | |
675 | if (!rc_stringlist_find(need_services, svc->value) && | |
676 | !rc_stringlist_find(use_services, svc->value)) | |
677 | continue; | |
678 | } | |
679 | ||
680 | if (!svc_wait(svc->value)) | |
681 | eerror("%s: timed out waiting for %s", | |
682 | applet, svc->value); | |
683 | state = rc_service_state(svc->value); | |
684 | if (state & RC_SERVICE_STARTED) | |
685 | continue; | |
686 | if (rc_stringlist_find(need_services, svc->value)) { | |
687 | if (state & RC_SERVICE_INACTIVE || | |
688 | state & RC_SERVICE_WASINACTIVE) | |
689 | { | |
690 | rc_stringlist_add(tmplist, svc->value); | |
691 | } else if (!TAILQ_FIRST(tmplist)) | |
692 | eerrorx("ERROR: cannot start %s as" | |
693 | " %s would not start", | |
694 | applet, svc->value); | |
695 | } | |
696 | } | |
697 | ||
698 | if (TAILQ_FIRST(tmplist)) { | |
699 | /* Set the state now, then unlink our exclusive so that | |
700 | our scheduled list is preserved */ | |
701 | rc_service_mark(service, RC_SERVICE_STOPPED); | |
702 | ||
703 | rc_stringlist_free(use_services); | |
704 | use_services = NULL; | |
705 | len = 0; | |
706 | n = 0; | |
707 | TAILQ_FOREACH(svc, tmplist, entries) { | |
708 | rc_service_schedule_start(svc->value, service); | |
709 | use_services = rc_deptree_depend(deptree, | |
710 | "iprovide", svc->value); | |
711 | TAILQ_FOREACH(svc2, use_services, entries) | |
712 | rc_service_schedule_start(svc2->value, service); | |
713 | rc_stringlist_free(use_services); | |
714 | use_services = NULL; | |
715 | len += strlen(svc->value) + 2; | |
716 | n++; | |
717 | } | |
718 | ||
719 | len += 5; | |
720 | tmp = p = xmalloc(sizeof(char) * len); | |
721 | TAILQ_FOREACH(svc, tmplist, entries) { | |
722 | if (p != tmp) | |
723 | p += snprintf(p, len, ", "); | |
724 | p += snprintf(p, len - (p - tmp), | |
725 | "%s", svc->value); | |
726 | } | |
727 | rc_stringlist_free(tmplist); | |
728 | tmplist = NULL; | |
729 | ewarnx("WARNING: %s will start when %s has started", applet, tmp); | |
730 | free(tmp); | |
731 | } | |
732 | ||
733 | rc_stringlist_free(tmplist); | |
734 | tmplist = NULL; | |
735 | rc_stringlist_free(services); | |
736 | services = NULL; | |
737 | } | |
738 | ||
739 | static void svc_start_real() | |
740 | { | |
741 | bool started; | |
742 | RC_STRING *svc, *svc2; | |
743 | ||
744 | if (ibsave) | |
745 | setenv("IN_BACKGROUND", ibsave, 1); | |
746 | hook_out = RC_HOOK_SERVICE_START_DONE; | |
747 | rc_plugin_run(RC_HOOK_SERVICE_START_NOW, applet); | |
748 | started = (svc_exec("start", NULL) == 0); | |
749 | if (ibsave) | |
750 | unsetenv("IN_BACKGROUND"); | |
751 | ||
752 | if (rc_service_state(service) & RC_SERVICE_INACTIVE) | |
753 | ewarnx("WARNING: %s has started, but is inactive", applet); | |
754 | else if (!started) | |
755 | eerrorx("ERROR: %s failed to start", applet); | |
756 | ||
757 | rc_service_mark(service, RC_SERVICE_STARTED); | |
758 | exclusive_fd = svc_unlock(applet, exclusive_fd); | |
759 | hook_out = RC_HOOK_SERVICE_START_OUT; | |
760 | rc_plugin_run(RC_HOOK_SERVICE_START_DONE, applet); | |
761 | ||
762 | /* Now start any scheduled services */ | |
763 | services = rc_services_scheduled(service); | |
764 | TAILQ_FOREACH(svc, services, entries) | |
765 | if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) | |
766 | service_start(svc->value); | |
767 | rc_stringlist_free(services); | |
768 | services = NULL; | |
769 | ||
770 | /* Do the same for any services we provide */ | |
771 | if (deptree) { | |
772 | tmplist = rc_deptree_depend(deptree, "iprovide", applet); | |
773 | TAILQ_FOREACH(svc, tmplist, entries) { | |
774 | services = rc_services_scheduled(svc->value); | |
775 | TAILQ_FOREACH(svc2, services, entries) | |
776 | if (rc_service_state(svc2->value) & | |
777 | RC_SERVICE_STOPPED) | |
778 | service_start(svc2->value); | |
779 | rc_stringlist_free(services); | |
780 | services = NULL; | |
781 | } | |
782 | rc_stringlist_free(tmplist); | |
783 | tmplist = NULL; | |
784 | } | |
785 | ||
786 | hook_out = 0; | |
787 | rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); | |
788 | } | |
789 | ||
790 | static void | |
791 | svc_start(void) | |
792 | { | |
793 | if (dry_run) | |
794 | einfon("start:"); | |
795 | else | |
796 | svc_start_check(); | |
797 | if (deps) | |
798 | svc_start_deps(); | |
799 | if (dry_run) | |
800 | printf(" %s\n", applet); | |
801 | else | |
802 | svc_start_real(); | |
803 | } | |
804 | ||
805 | static int | |
806 | svc_stop_check(RC_SERVICE *state) | |
807 | { | |
808 | *state = rc_service_state(service); | |
809 | ||
810 | if (rc_runlevel_stopping() && *state & RC_SERVICE_FAILED) | |
811 | exit(EXIT_FAILURE); | |
812 | ||
813 | if (in_background && | |
814 | !(*state & RC_SERVICE_STARTED) && | |
815 | !(*state & RC_SERVICE_INACTIVE)) | |
816 | exit(EXIT_FAILURE); | |
817 | ||
818 | if (exclusive_fd == -1) | |
819 | exclusive_fd = svc_lock(applet); | |
820 | if (exclusive_fd == -1) { | |
821 | if (errno == EACCES) | |
822 | eerrorx("%s: superuser access required", applet); | |
823 | if (*state & RC_SERVICE_STOPPING) | |
824 | ewarnx("WARNING: %s is already stopping", applet); | |
825 | eerrorx("ERROR: %s stopped by something else", applet); | |
826 | } | |
827 | fcntl(exclusive_fd, F_SETFD, | |
828 | fcntl(exclusive_fd, F_GETFD, 0) | FD_CLOEXEC); | |
829 | ||
830 | if (*state & RC_SERVICE_STOPPED) { | |
831 | ewarn("WARNING: %s is already stopped", applet); | |
832 | return 1; | |
833 | } | |
834 | ||
835 | rc_service_mark(service, RC_SERVICE_STOPPING); | |
836 | hook_out = RC_HOOK_SERVICE_STOP_OUT; | |
837 | rc_plugin_run(RC_HOOK_SERVICE_STOP_IN, applet); | |
838 | ||
839 | if (!rc_runlevel_stopping()) { | |
840 | if (rc_service_in_runlevel(service, RC_LEVEL_SYSINIT)) | |
841 | ewarn("WARNING: you are stopping a sysinit service"); | |
842 | else if (rc_service_in_runlevel(service, RC_LEVEL_BOOT)) | |
843 | ewarn("WARNING: you are stopping a boot service"); | |
844 | } | |
845 | ||
846 | return 0; | |
847 | } | |
848 | ||
849 | static void | |
850 | svc_stop_deps(RC_SERVICE state) | |
851 | { | |
852 | int depoptions = RC_DEP_TRACE; | |
853 | RC_STRING *svc; | |
854 | pid_t pid; | |
855 | ||
856 | if (state & RC_SERVICE_WASINACTIVE) | |
857 | return; | |
858 | ||
859 | errno = 0; | |
860 | if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT) | |
861 | depoptions |= RC_DEP_STRICT; | |
862 | ||
863 | if (!deptree && ((deptree = _rc_deptree_load(0, NULL)) == NULL)) | |
864 | eerrorx("failed to load deptree"); | |
865 | ||
866 | if (!deptypes_m) | |
867 | setup_deptypes(); | |
868 | ||
869 | services = rc_deptree_depends(deptree, deptypes_m, applet_list, | |
870 | runlevel, depoptions); | |
871 | tmplist = rc_stringlist_new(); | |
872 | TAILQ_FOREACH_REVERSE(svc, services, rc_stringlist, entries) { | |
873 | state = rc_service_state(svc->value); | |
874 | /* Don't stop failed services again. | |
875 | * If you remove this check, ensure that the | |
876 | * exclusive file isn't created. */ | |
877 | if (state & RC_SERVICE_FAILED && | |
878 | rc_runlevel_stopping()) | |
879 | continue; | |
880 | if (state & RC_SERVICE_STARTED || | |
881 | state & RC_SERVICE_INACTIVE) | |
882 | { | |
883 | if (dry_run) { | |
884 | printf(" %s", svc->value); | |
885 | continue; | |
886 | } | |
887 | svc_wait(svc->value); | |
888 | state = rc_service_state(svc->value); | |
889 | if (state & RC_SERVICE_STARTED || | |
890 | state & RC_SERVICE_INACTIVE) | |
891 | { | |
892 | pid = service_stop(svc->value); | |
893 | if (!rc_conf_yesno("rc_parallel")) | |
894 | rc_waitpid(pid); | |
895 | rc_stringlist_add(tmplist, svc->value); | |
896 | } | |
897 | } | |
898 | } | |
899 | rc_stringlist_free(services); | |
900 | services = NULL; | |
901 | if (dry_run) | |
902 | return; | |
903 | ||
904 | TAILQ_FOREACH(svc, tmplist, entries) { | |
905 | if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) | |
906 | continue; | |
907 | svc_wait(svc->value); | |
908 | if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) | |
909 | continue; | |
910 | if (rc_runlevel_stopping()) { | |
911 | /* If shutting down, we should stop even | |
912 | * if a dependant failed */ | |
913 | if (runlevel && | |
914 | (strcmp(runlevel, | |
915 | RC_LEVEL_SHUTDOWN) == 0 || | |
916 | strcmp(runlevel, | |
917 | RC_LEVEL_SINGLE) == 0)) | |
918 | continue; | |
919 | rc_service_mark(service, RC_SERVICE_FAILED); | |
920 | } | |
921 | eerrorx("ERROR: cannot stop %s as %s " | |
922 | "is still up", applet, svc->value); | |
923 | } | |
924 | rc_stringlist_free(tmplist); | |
925 | tmplist = NULL; | |
926 | ||
927 | /* We now wait for other services that may use us and are | |
928 | * stopping. This is important when a runlevel stops */ | |
929 | services = rc_deptree_depends(deptree, deptypes_mua, applet_list, | |
930 | runlevel, depoptions); | |
931 | TAILQ_FOREACH(svc, services, entries) { | |
932 | if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) | |
933 | continue; | |
934 | svc_wait(svc->value); | |
935 | } | |
936 | rc_stringlist_free(services); | |
937 | services = NULL; | |
938 | } | |
939 | ||
940 | static void | |
941 | svc_stop_real(void) | |
942 | { | |
943 | bool stopped; | |
944 | ||
945 | /* If we're stopping localmount, set LC_ALL=C so that | |
946 | * bash doesn't load anything blocking the unmounting of /usr */ | |
947 | if (strcmp(applet, "localmount") == 0) | |
948 | setenv("LC_ALL", "C", 1); | |
949 | ||
950 | if (ibsave) | |
951 | setenv("IN_BACKGROUND", ibsave, 1); | |
952 | hook_out = RC_HOOK_SERVICE_STOP_DONE; | |
953 | rc_plugin_run(RC_HOOK_SERVICE_STOP_NOW, applet); | |
954 | stopped = (svc_exec("stop", NULL) == 0); | |
955 | if (ibsave) | |
956 | unsetenv("IN_BACKGROUND"); | |
957 | ||
958 | if (!stopped) | |
959 | eerrorx("ERROR: %s failed to stop", applet); | |
960 | ||
961 | if (in_background) | |
962 | rc_service_mark(service, RC_SERVICE_INACTIVE); | |
963 | else | |
964 | rc_service_mark(service, RC_SERVICE_STOPPED); | |
965 | ||
966 | hook_out = RC_HOOK_SERVICE_STOP_OUT; | |
967 | rc_plugin_run(RC_HOOK_SERVICE_STOP_DONE, applet); | |
968 | hook_out = 0; | |
969 | rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); | |
970 | } | |
971 | ||
972 | static int | |
973 | svc_stop(void) | |
974 | { | |
975 | RC_SERVICE state; | |
976 | ||
977 | state = 0; | |
978 | if (dry_run) | |
979 | einfon("stop:"); | |
980 | else | |
981 | if (svc_stop_check(&state) == 1) | |
982 | return 1; /* Service has been stopped already */ | |
983 | if (deps) | |
984 | svc_stop_deps(state); | |
985 | if (dry_run) | |
986 | printf(" %s\n", applet); | |
987 | else | |
988 | svc_stop_real(); | |
989 | ||
990 | return 0; | |
991 | } | |
992 | ||
993 | static void | |
994 | svc_restart(void) | |
995 | { | |
996 | /* This is hairly and a better way needs to be found I think! | |
997 | * The issue is this - openvpn need net and dns. net can restart | |
998 | * dns via resolvconf, so you could have openvpn trying to restart | |
999 | * dnsmasq which in turn is waiting on net which in turn is waiting | |
1000 | * on dnsmasq. | |
1001 | * The work around is for resolvconf to restart its services with | |
1002 | * --nodeps which means just that. | |
1003 | * The downside is that there is a small window when our status is | |
1004 | * invalid. | |
1005 | * One workaround would be to introduce a new status, | |
1006 | * or status locking. */ | |
1007 | if (!deps) { | |
1008 | RC_SERVICE state = rc_service_state(service); | |
1009 | if (state & RC_SERVICE_STARTED || state & RC_SERVICE_INACTIVE) | |
1010 | svc_exec("stop", "start"); | |
1011 | else | |
1012 | svc_exec("start", NULL); | |
1013 | return; | |
1014 | } | |
1015 | ||
1016 | if (!(rc_service_state(service) & RC_SERVICE_STOPPED)) { | |
1017 | get_started_services(); | |
1018 | svc_stop(); | |
1019 | if (dry_run) | |
1020 | ewarn("Cannot calculate restart start dependencies" | |
1021 | " on a dry-run"); | |
1022 | } | |
1023 | ||
1024 | svc_start(); | |
1025 | start_services(restart_services); | |
1026 | rc_stringlist_free(restart_services); | |
1027 | restart_services = NULL; | |
1028 | } | |
1029 | ||
1030 | static bool | |
1031 | service_plugable(void) | |
1032 | { | |
1033 | char *list, *p, *token; | |
1034 | bool allow = true, truefalse; | |
1035 | char *match = rc_conf_value("rc_hotplug"); | |
1036 | ||
1037 | if (!match) | |
1038 | match = rc_conf_value("rc_plug_services"); | |
1039 | if (!match) | |
1040 | return false; | |
1041 | ||
1042 | list = xstrdup(match); | |
1043 | p = list; | |
1044 | while ((token = strsep(&p, " "))) { | |
1045 | if (token[0] == '!') { | |
1046 | truefalse = false; | |
1047 | token++; | |
1048 | } else | |
1049 | truefalse = true; | |
1050 | ||
1051 | if (fnmatch(token, applet, 0) == 0) { | |
1052 | allow = truefalse; | |
1053 | break; | |
1054 | } | |
1055 | } | |
1056 | #ifdef DEBUG_MEMORY | |
1057 | free(list); | |
1058 | #endif | |
1059 | return allow; | |
1060 | } | |
1061 | ||
1062 | #include "_usage.h" | |
1063 | #define getoptstring "dDsSvl:Z" getoptstring_COMMON | |
1064 | #define extraopts "stop | start | restart | describe | zap" | |
1065 | static const struct option longopts[] = { | |
1066 | { "debug", 0, NULL, 'd'}, | |
1067 | { "dry-run", 0, NULL, 'Z'}, | |
1068 | { "ifstarted", 0, NULL, 's'}, | |
1069 | { "ifstopped", 0, NULL, 'S'}, | |
1070 | { "nodeps", 0, NULL, 'D'}, | |
1071 | { "lockfd", 1, NULL, 'l'}, | |
1072 | longopts_COMMON | |
1073 | }; | |
1074 | static const char *const longopts_help[] = { | |
1075 | "set xtrace when running the script", | |
1076 | "show what would be done", | |
1077 | "only run commands when started", | |
1078 | "only run commands when stopped", | |
1079 | "ignore dependencies", | |
1080 | "fd of the exclusive lock from rc", | |
1081 | longopts_help_COMMON | |
1082 | }; | |
1083 | #include "_usage.c" | |
1084 | ||
1085 | int | |
1086 | openrc_run(int argc, char **argv) | |
1087 | { | |
1088 | bool doneone = false; | |
1089 | int retval, opt, depoptions = RC_DEP_TRACE; | |
1090 | RC_STRING *svc; | |
1091 | char path[PATH_MAX], lnk[PATH_MAX]; | |
1092 | char *dir, *save = NULL, *saveLnk = NULL; | |
1093 | char pidstr[10]; | |
1094 | size_t l = 0, ll; | |
1095 | const char *file; | |
1096 | struct stat stbuf; | |
1097 | ||
1098 | /* Show help if insufficient args */ | |
1099 | if (argc < 2 || !exists(argv[1])) { | |
1100 | fprintf(stderr, "openrc-run should not be run directly\n"); | |
1101 | exit(EXIT_FAILURE); | |
1102 | } | |
1103 | ||
1104 | if (stat(argv[1], &stbuf) != 0) { | |
1105 | fprintf(stderr, "openrc-run `%s': %s\n", | |
1106 | argv[1], strerror(errno)); | |
1107 | exit(EXIT_FAILURE); | |
1108 | } | |
1109 | ||
1110 | atexit(cleanup); | |
1111 | ||
1112 | /* We need to work out the real full path to our service. | |
1113 | * This works fine, provided that we ONLY allow multiplexed services | |
1114 | * to exist in the same directory as the master link. | |
1115 | * Also, the master link as to be a real file in the init dir. */ | |
1116 | if (!realpath(argv[1], path)) { | |
1117 | fprintf(stderr, "realpath: %s\n", strerror(errno)); | |
1118 | exit(EXIT_FAILURE); | |
1119 | } | |
1120 | memset(lnk, 0, sizeof(lnk)); | |
1121 | if (readlink(argv[1], lnk, sizeof(lnk)-1)) { | |
1122 | dir = dirname(path); | |
1123 | if (strchr(lnk, '/')) { | |
1124 | save = xstrdup(dir); | |
1125 | saveLnk = xstrdup(lnk); | |
1126 | dir = dirname(saveLnk); | |
1127 | if (strcmp(dir, save) == 0) | |
1128 | file = basename_c(argv[1]); | |
1129 | else | |
1130 | file = basename_c(lnk); | |
1131 | dir = save; | |
1132 | } else | |
1133 | file = basename_c(argv[1]); | |
1134 | ll = strlen(dir) + strlen(file) + 2; | |
1135 | service = xmalloc(ll); | |
1136 | snprintf(service, ll, "%s/%s", dir, file); | |
1137 | if (stat(service, &stbuf) != 0) { | |
1138 | free(service); | |
1139 | service = xstrdup(lnk); | |
1140 | } | |
1141 | free(save); | |
1142 | free(saveLnk); | |
1143 | } | |
1144 | if (!service) | |
1145 | service = xstrdup(path); | |
1146 | applet = basename_c(service); | |
1147 | ||
1148 | if (argc < 3) | |
1149 | usage(EXIT_FAILURE); | |
1150 | ||
1151 | /* Change dir to / to ensure all init scripts don't use stuff in pwd */ | |
1152 | if (chdir("/") == -1) | |
1153 | eerror("chdir: %s", strerror(errno)); | |
1154 | ||
1155 | if ((runlevel = xstrdup(getenv("RC_RUNLEVEL"))) == NULL) { | |
1156 | env_filter(); | |
1157 | env_config(); | |
1158 | runlevel = rc_runlevel_get(); | |
1159 | } | |
1160 | ||
1161 | setenv("EINFO_LOG", service, 1); | |
1162 | setenv("RC_SVCNAME", applet, 1); | |
1163 | ||
1164 | /* Set an env var so that we always know our pid regardless of any | |
1165 | subshells the init script may create so that our mark_service_* | |
1166 | functions can always instruct us of this change */ | |
1167 | snprintf(pidstr, sizeof(pidstr), "%d", (int) getpid()); | |
1168 | setenv("RC_OPENRC_PID", pidstr, 1); | |
1169 | /* | |
1170 | * RC_RUNSCRIPT_PID is deprecated, but we will keep it for a while | |
1171 | * for safety. | |
1172 | */ | |
1173 | setenv("RC_RUNSCRIPT_PID", pidstr, 1); | |
1174 | ||
1175 | /* eprefix is kinda klunky, but it works for our purposes */ | |
1176 | if (rc_conf_yesno("rc_parallel")) { | |
1177 | /* Get the longest service name */ | |
1178 | services = rc_services_in_runlevel(NULL); | |
1179 | TAILQ_FOREACH(svc, services, entries) { | |
1180 | ll = strlen(svc->value); | |
1181 | if (ll > l) | |
1182 | l = ll; | |
1183 | } | |
1184 | rc_stringlist_free(services); | |
1185 | services = NULL; | |
1186 | ll = strlen(applet); | |
1187 | if (ll > l) | |
1188 | l = ll; | |
1189 | ||
1190 | /* Make our prefix string */ | |
1191 | prefix = xmalloc(sizeof(char) * l + 1); | |
1192 | ll = strlen(applet); | |
1193 | memcpy(prefix, applet, ll); | |
1194 | memset(prefix + ll, ' ', l - ll); | |
1195 | memset(prefix + l, 0, 1); | |
1196 | eprefix(prefix); | |
1197 | } | |
1198 | ||
1199 | /* Ok, we are ready to go, so setup selinux if applicable */ | |
1200 | selinux_setup(argv); | |
1201 | ||
1202 | deps = true; | |
1203 | ||
1204 | /* Punt the first arg as its our service name */ | |
1205 | argc--; | |
1206 | argv++; | |
1207 | ||
1208 | /* Right then, parse any options there may be */ | |
1209 | while ((opt = getopt_long(argc, argv, getoptstring, | |
1210 | longopts, (int *)0)) != -1) | |
1211 | switch (opt) { | |
1212 | case 'd': | |
1213 | setenv("RC_DEBUG", "YES", 1); | |
1214 | break; | |
1215 | case 'l': | |
1216 | exclusive_fd = atoi(optarg); | |
1217 | fcntl(exclusive_fd, F_SETFD, | |
1218 | fcntl(exclusive_fd, F_GETFD, 0) | FD_CLOEXEC); | |
1219 | break; | |
1220 | case 's': | |
1221 | if (!(rc_service_state(service) & RC_SERVICE_STARTED)) | |
1222 | exit(EXIT_FAILURE); | |
1223 | break; | |
1224 | case 'S': | |
1225 | if (!(rc_service_state(service) & RC_SERVICE_STOPPED)) | |
1226 | exit(EXIT_FAILURE); | |
1227 | break; | |
1228 | case 'D': | |
1229 | deps = false; | |
1230 | break; | |
1231 | case 'Z': | |
1232 | dry_run = true; | |
1233 | break; | |
1234 | case_RC_COMMON_GETOPT | |
1235 | } | |
1236 | ||
1237 | /* If we're changing runlevels and not called by rc then we cannot | |
1238 | work with any dependencies */ | |
1239 | if (deps && getenv("RC_PID") == NULL && | |
1240 | (rc_runlevel_starting() || rc_runlevel_stopping())) | |
1241 | deps = false; | |
1242 | ||
1243 | /* Save the IN_BACKGROUND env flag so it's ONLY passed to the service | |
1244 | that is being called and not any dependents */ | |
1245 | if (getenv("IN_BACKGROUND")) { | |
1246 | ibsave = xstrdup(getenv("IN_BACKGROUND")); | |
1247 | in_background = rc_yesno(ibsave); | |
1248 | unsetenv("IN_BACKGROUND"); | |
1249 | } | |
1250 | ||
1251 | if (rc_yesno(getenv("IN_HOTPLUG"))) { | |
1252 | if (!service_plugable()) | |
1253 | eerrorx("%s: not allowed to be hotplugged", applet); | |
1254 | in_background = true; | |
1255 | } | |
1256 | ||
1257 | /* Setup a signal handler */ | |
1258 | signal_setup(SIGHUP, handle_signal); | |
1259 | signal_setup(SIGINT, handle_signal); | |
1260 | signal_setup(SIGQUIT, handle_signal); | |
1261 | signal_setup(SIGTERM, handle_signal); | |
1262 | signal_setup(SIGCHLD, handle_signal); | |
1263 | ||
1264 | /* Load our plugins */ | |
1265 | rc_plugin_load(); | |
1266 | ||
1267 | applet_list = rc_stringlist_new(); | |
1268 | rc_stringlist_add(applet_list, applet); | |
1269 | ||
1270 | /* Now run each option */ | |
1271 | retval = EXIT_SUCCESS; | |
1272 | while (optind < argc) { | |
1273 | optarg = argv[optind++]; | |
1274 | ||
1275 | /* Abort on a sighup here */ | |
1276 | if (sighup) | |
1277 | exit (EXIT_FAILURE); | |
1278 | ||
1279 | /* Export the command we're running. | |
1280 | This is important as we stamp on the restart function now but | |
1281 | some start/stop routines still need to behave differently if | |
1282 | restarting. */ | |
1283 | unsetenv("RC_CMD"); | |
1284 | setenv("RC_CMD", optarg, 1); | |
1285 | ||
1286 | doneone = true; | |
1287 | ||
1288 | if (strcmp(optarg, "describe") == 0 || | |
1289 | strcmp(optarg, "help") == 0 || | |
1290 | strcmp(optarg, "depend") == 0) | |
1291 | { | |
1292 | save = prefix; | |
1293 | eprefix(NULL); | |
1294 | prefix = NULL; | |
1295 | svc_exec(optarg, NULL); | |
1296 | eprefix(save); | |
1297 | prefix = save; | |
1298 | } else if (strcmp(optarg, "ineed") == 0 || | |
1299 | strcmp(optarg, "iuse") == 0 || | |
1300 | strcmp(optarg, "needsme") == 0 || | |
1301 | strcmp(optarg, "usesme") == 0 || | |
1302 | strcmp(optarg, "iafter") == 0 || | |
1303 | strcmp(optarg, "ibefore") == 0 || | |
1304 | strcmp(optarg, "iprovide") == 0) | |
1305 | { | |
1306 | errno = 0; | |
1307 | if (rc_conf_yesno("rc_depend_strict") || | |
1308 | errno == ENOENT) | |
1309 | depoptions |= RC_DEP_STRICT; | |
1310 | ||
1311 | if (!deptree && | |
1312 | ((deptree = _rc_deptree_load(0, NULL)) == NULL)) | |
1313 | eerrorx("failed to load deptree"); | |
1314 | ||
1315 | tmplist = rc_stringlist_new(); | |
1316 | rc_stringlist_add(tmplist, optarg); | |
1317 | services = rc_deptree_depends(deptree, tmplist, | |
1318 | applet_list, | |
1319 | runlevel, depoptions); | |
1320 | rc_stringlist_free(tmplist); | |
1321 | TAILQ_FOREACH(svc, services, entries) | |
1322 | printf("%s ", svc->value); | |
1323 | printf ("\n"); | |
1324 | rc_stringlist_free(services); | |
1325 | services = NULL; | |
1326 | } else if (strcmp (optarg, "status") == 0) { | |
1327 | save = prefix; | |
1328 | eprefix(NULL); | |
1329 | prefix = NULL; | |
1330 | retval = svc_exec("status", NULL); | |
1331 | } else { | |
1332 | if (strcmp(optarg, "conditionalrestart") == 0 || | |
1333 | strcmp(optarg, "condrestart") == 0) | |
1334 | { | |
1335 | if (rc_service_state(service) & | |
1336 | RC_SERVICE_STARTED) | |
1337 | svc_restart(); | |
1338 | } else if (strcmp(optarg, "restart") == 0) { | |
1339 | svc_restart(); | |
1340 | } else if (strcmp(optarg, "start") == 0) { | |
1341 | svc_start(); | |
1342 | } else if (strcmp(optarg, "stop") == 0 || strcmp(optarg, "pause") == 0) { | |
1343 | if (strcmp(optarg, "pause") == 0) { | |
1344 | ewarn("WARNING: 'pause' is deprecated; please use '--nodeps stop'"); | |
1345 | deps = false; | |
1346 | } | |
1347 | if (deps && in_background) | |
1348 | get_started_services(); | |
1349 | if (svc_stop() == 1) | |
1350 | continue; /* Service has been stopped already */ | |
1351 | if (deps) { | |
1352 | if (!in_background && | |
1353 | !rc_runlevel_stopping() && | |
1354 | rc_service_state(service) & | |
1355 | RC_SERVICE_STOPPED) | |
1356 | unhotplug(); | |
1357 | ||
1358 | if (in_background && | |
1359 | rc_service_state(service) & | |
1360 | RC_SERVICE_INACTIVE) | |
1361 | { | |
1362 | TAILQ_FOREACH(svc, | |
1363 | restart_services, | |
1364 | entries) | |
1365 | if (rc_service_state(svc->value) & | |
1366 | RC_SERVICE_STOPPED) | |
1367 | rc_service_schedule_start(service, svc->value); | |
1368 | } | |
1369 | } | |
1370 | } else if (strcmp(optarg, "zap") == 0) { | |
1371 | einfo("Manually resetting %s to stopped state", | |
1372 | applet); | |
1373 | if (!rc_service_mark(applet, | |
1374 | RC_SERVICE_STOPPED)) | |
1375 | eerrorx("rc_service_mark: %s", | |
1376 | strerror(errno)); | |
1377 | unhotplug(); | |
1378 | } else | |
1379 | retval = svc_exec(optarg, NULL); | |
1380 | ||
1381 | /* We should ensure this list is empty after | |
1382 | * an action is done */ | |
1383 | rc_stringlist_free(restart_services); | |
1384 | restart_services = NULL; | |
1385 | } | |
1386 | ||
1387 | if (!doneone) | |
1388 | usage(EXIT_FAILURE); | |
1389 | } | |
1390 | ||
1391 | return retval; | |
1392 | } | |
1393 | ||
1394 | int | |
1395 | runscript(int argc, char **argv) | |
1396 | { | |
1397 | ewarnv("runscript is deprecated; please use openrc-run instead."); | |
1398 | return (openrc_run(argc, argv)); | |
1399 | } |
328 | 328 | bool ok = false; |
329 | 329 | char *svcname = getenv("RC_SVCNAME"); |
330 | 330 | char *service = NULL; |
331 | char *runscript_pid; | |
331 | char *openrc_pid; | |
332 | 332 | /* char *mtime; */ |
333 | 333 | pid_t pid; |
334 | 334 | RC_SERVICE bit; |
349 | 349 | eerrorx("%s: unknown applet", applet); |
350 | 350 | |
351 | 351 | /* If we're marking ourselves then we need to inform our parent |
352 | runscript process so they do not mark us based on our exit code */ | |
352 | openrc-run process so they do not mark us based on our exit code */ | |
353 | 353 | /* |
354 | 354 | * FIXME: svcname and service are almost always equal except called from a |
355 | 355 | * shell with just argv[1] - So that doesn't seem to do what Roy initially |
358 | 358 | * openrc@gentoo.org). |
359 | 359 | */ |
360 | 360 | if (ok && svcname && strcmp(svcname, service) == 0) { |
361 | runscript_pid = getenv("RC_RUNSCRIPT_PID"); | |
362 | if (runscript_pid && sscanf(runscript_pid, "%d", &pid) == 1) | |
361 | openrc_pid = getenv("RC_OPENRC_PID"); | |
362 | if (openrc_pid && sscanf(openrc_pid, "%d", &pid) == 1) | |
363 | 363 | if (kill(pid, SIGHUP) != 0) |
364 | 364 | eerror("%s: failed to signal parent %d: %s", |
365 | 365 | applet, pid, strerror(errno)); |
368 | 368 | in control as well */ |
369 | 369 | /* |
370 | 370 | l = strlen(RC_SVCDIR "/exclusive") + strlen(svcname) + |
371 | strlen(runscript_pid) + 4; | |
371 | strlen(openrc_pid) + 4; | |
372 | 372 | mtime = xmalloc(l); |
373 | 373 | snprintf(mtime, l, RC_SVCDIR "/exclusive/%s.%s", |
374 | svcname, runscript_pid); | |
374 | svcname, openrc_pid); | |
375 | 375 | if (exists(mtime) && unlink(mtime) != 0) |
376 | 376 | eerror("%s: unlink: %s", applet, strerror(errno)); |
377 | 377 | free(mtime); |
45 | 45 | |
46 | 46 | #include "builtins.h" |
47 | 47 | #include "einfo.h" |
48 | #include "queue.h" | |
48 | 49 | #include "rc.h" |
49 | 50 | #include "rc-misc.h" |
50 | 51 |
43 | 43 | #include <time.h> |
44 | 44 | #include <unistd.h> |
45 | 45 | |
46 | #if defined(__linux__) || defined(__GLIBC__) | |
46 | #if defined(__linux__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__)) | |
47 | 47 | # include <pty.h> |
48 | 48 | #elif defined(__NetBSD__) || defined(__OpenBSD__) |
49 | 49 | # include <util.h> |
53 | 53 | |
54 | 54 | #include "einfo.h" |
55 | 55 | #include "rc-logger.h" |
56 | #include "queue.h" | |
56 | 57 | #include "rc.h" |
57 | 58 | #include "rc-misc.h" |
58 | 59 |
46 | 46 | #include <unistd.h> |
47 | 47 | |
48 | 48 | #include "einfo.h" |
49 | #include "queue.h" | |
49 | 50 | #include "rc.h" |
50 | 51 | #include "rc-misc.h" |
51 | 52 | #include "version.h" |
64 | 65 | "LC_MONETARY", "LC_MESSAGES", "LC_PAPER", "LC_NAME", "LC_ADDRESS", |
65 | 66 | "LC_TELEPHONE", "LC_MEASUREMENT", "LC_IDENTIFICATION", "LC_ALL", |
66 | 67 | "IN_HOTPLUG", "IN_BACKGROUND", "RC_INTERFACE_KEEP_CONFIG", |
68 | "EERROR_QUIET", "EINFO_QUIET", | |
67 | 69 | NULL |
68 | 70 | }; |
69 | 71 |
42 | 42 | #include <unistd.h> |
43 | 43 | |
44 | 44 | #include "einfo.h" |
45 | #include "queue.h" | |
45 | 46 | #include "rc.h" |
46 | 47 | #include "rc-misc.h" |
47 | 48 | #include "rc-plugin.h" |
0 | 0 | /* |
1 | rc-selinux.c | |
2 | SELinux helpers to get and set contexts. | |
3 | */ | |
1 | * rc-selinux.c | |
2 | * SELinux helpers to get and set contexts. | |
3 | */ | |
4 | 4 | |
5 | 5 | /* |
6 | 6 | * Copyright (c) 2014 Jason Zaman <jason@perfinion.com> |
30 | 30 | #include <stddef.h> |
31 | 31 | #include <errno.h> |
32 | 32 | #include <dlfcn.h> |
33 | ||
34 | #include <sys/stat.h> | |
33 | #include <ctype.h> | |
34 | #include <limits.h> | |
35 | #include <pwd.h> | |
36 | #include <unistd.h> | |
35 | 37 | |
36 | 38 | #include <selinux/selinux.h> |
37 | 39 | #include <selinux/label.h> |
40 | #include <selinux/get_default_type.h> | |
41 | #include <selinux/context.h> | |
42 | ||
43 | #include <sys/stat.h> | |
44 | #include <sys/types.h> | |
38 | 45 | |
39 | 46 | #include "einfo.h" |
47 | #include "queue.h" | |
40 | 48 | #include "rc.h" |
41 | 49 | #include "rc-misc.h" |
42 | 50 | #include "rc-plugin.h" |
43 | 51 | #include "rc-selinux.h" |
44 | 52 | |
45 | #define SELINUX_LIB RC_LIBDIR "/runscript_selinux.so" | |
46 | ||
47 | static void (*selinux_run_init_old) (void); | |
48 | static void (*selinux_run_init_new) (int argc, char **argv); | |
49 | ||
53 | /* the context files for selinux */ | |
54 | #define RUN_INIT_FILE "run_init_type" | |
55 | #define INITRC_FILE "initrc_context" | |
56 | ||
57 | #ifdef HAVE_AUDIT | |
58 | #include <libaudit.h> | |
59 | #endif | |
60 | ||
61 | /* PAM or shadow for authentication */ | |
62 | #ifdef HAVE_PAM | |
63 | # define PAM_SERVICE_NAME "run_init" /* the name of this program for PAM */ | |
64 | # include <security/pam_appl.h> | |
65 | # include <security/pam_misc.h> | |
66 | #else | |
67 | # define PASSWORD_PROMPT "Password:" | |
68 | # include <crypt.h> | |
69 | # include <shadow.h> | |
70 | # include <string.h> | |
71 | #endif | |
72 | ||
73 | ||
74 | /* The handle for the fcontext lookups */ | |
50 | 75 | static struct selabel_handle *hnd = NULL; |
51 | 76 | |
52 | 77 | int selinux_util_label(const char *path) |
131 | 156 | return 0; |
132 | 157 | } |
133 | 158 | |
134 | void selinux_setup(int argc, char **argv) | |
135 | { | |
136 | void *lib_handle = NULL; | |
137 | ||
138 | if (!exists(SELINUX_LIB)) | |
159 | /* | |
160 | * This will check the users password and return 0 on success or -1 on fail | |
161 | * | |
162 | * We ask for the password to make sure it is intended vs run by malicious software. | |
163 | * Actual authorization is covered by the policy itself. | |
164 | */ | |
165 | static int check_password(char *username) | |
166 | { | |
167 | int ret = 1; | |
168 | #ifdef HAVE_PAM | |
169 | pam_handle_t *pamh; | |
170 | int pam_err = 0; | |
171 | const struct pam_conv pconv = { | |
172 | misc_conv, | |
173 | NULL | |
174 | }; | |
175 | ||
176 | pam_err = pam_start(PAM_SERVICE_NAME, username, &pconv, &pamh); | |
177 | if (pam_err != PAM_SUCCESS) { | |
178 | ret = -1; | |
179 | goto outpam; | |
180 | } | |
181 | ||
182 | pam_err = pam_authenticate(pamh, PAM_DISALLOW_NULL_AUTHTOK); | |
183 | if (pam_err != PAM_SUCCESS) { | |
184 | ret = -1; | |
185 | goto outpam; | |
186 | } | |
187 | ||
188 | ret = 0; | |
189 | outpam: | |
190 | pam_end(pamh, pam_err); | |
191 | pamh = NULL; | |
192 | ||
193 | #else /* authenticating via /etc/shadow instead */ | |
194 | struct spwd *spw; | |
195 | char *password; | |
196 | char *attempt; | |
197 | ||
198 | spw = getspnam(username); | |
199 | if (!spw) { | |
200 | eerror("Failed to read shadow entry"); | |
201 | ret = -1; | |
202 | goto outshadow; | |
203 | } | |
204 | ||
205 | attempt = getpass(PASSWORD_PROMPT); | |
206 | if (!attempt) { | |
207 | ret = -1; | |
208 | goto outshadow; | |
209 | } | |
210 | ||
211 | if (*spw->sp_pwdp == '\0' && *attempt == '\0') { | |
212 | ret = -1; | |
213 | goto outshadow; | |
214 | } | |
215 | ||
216 | /* salt must be at least two characters long */ | |
217 | if (!(spw->sp_pwdp[0] && spw->sp_pwdp[1])) { | |
218 | ret = -1; | |
219 | goto outshadow; | |
220 | } | |
221 | ||
222 | /* encrypt the password attempt */ | |
223 | password = crypt(attempt, spw->sp_pwdp); | |
224 | ||
225 | if (password && strcmp(password, spw->sp_pwdp) == 0) | |
226 | ret = 0; | |
227 | else | |
228 | ret = -1; | |
229 | outshadow: | |
230 | #endif | |
231 | return ret; | |
232 | } | |
233 | ||
234 | /* Authenticates the user, returns 0 on success, 1 on fail */ | |
235 | static int check_auth() | |
236 | { | |
237 | struct passwd *pw; | |
238 | uid_t uid; | |
239 | ||
240 | #ifdef HAVE_AUDIT | |
241 | uid = audit_getloginuid(); | |
242 | if (uid == (uid_t) -1) | |
243 | uid = getuid(); | |
244 | #else | |
245 | uid = getuid(); | |
246 | #endif | |
247 | ||
248 | pw = getpwuid(uid); | |
249 | if (!pw) { | |
250 | eerror("cannot find your entry in the passwd file."); | |
251 | return (-1); | |
252 | } | |
253 | ||
254 | printf("Authenticating %s.\n", pw->pw_name); | |
255 | ||
256 | /* do the actual check */ | |
257 | if (check_password(pw->pw_name) == 0) { | |
258 | return 0; | |
259 | } | |
260 | ||
261 | eerrorx("Authentication failed for %s", pw->pw_name); | |
262 | return 1; | |
263 | } | |
264 | ||
265 | /* | |
266 | * Read the context from the given context file. context must be free'd by the user. | |
267 | */ | |
268 | static int read_context_file(const char *filename, char **context) | |
269 | { | |
270 | int ret = -1; | |
271 | FILE *fp; | |
272 | char filepath[PATH_MAX]; | |
273 | char *line = NULL; | |
274 | char *p; | |
275 | char *p2; | |
276 | size_t len = 0; | |
277 | ssize_t read; | |
278 | ||
279 | memset(filepath, '\0', PATH_MAX); | |
280 | snprintf(filepath, PATH_MAX - 1, "%s/%s", selinux_contexts_path(), filename); | |
281 | ||
282 | fp = fopen(filepath, "r"); | |
283 | if (fp == NULL) { | |
284 | eerror("Failed to open context file: %s", filename); | |
285 | return -1; | |
286 | } | |
287 | ||
288 | while ((read = getline(&line, &len, fp)) != -1) { | |
289 | /* cut off spaces before the string */ | |
290 | p = line; | |
291 | while (isspace(*p) && *p != '\0') | |
292 | p++; | |
293 | ||
294 | /* empty string, skip */ | |
295 | if (*p == '\0') | |
296 | continue; | |
297 | ||
298 | /* cut off spaces after the string */ | |
299 | p2 = p; | |
300 | while (!isspace(*p2) && *p2 != '\0') | |
301 | p2++; | |
302 | *p2 = '\0'; | |
303 | ||
304 | *context = xstrdup(p); | |
305 | ret = 0; | |
306 | break; | |
307 | } | |
308 | ||
309 | free(line); | |
310 | fclose(fp); | |
311 | return ret; | |
312 | } | |
313 | ||
314 | void selinux_setup(char **argv) | |
315 | { | |
316 | char *new_context = NULL; | |
317 | char *curr_context = NULL; | |
318 | context_t curr_con; | |
319 | char *curr_t = NULL; | |
320 | char *run_init_t = NULL; | |
321 | ||
322 | /* Return, if selinux is disabled. */ | |
323 | if (is_selinux_enabled() < 1) { | |
139 | 324 | return; |
140 | ||
141 | lib_handle = dlopen(SELINUX_LIB, RTLD_NOW | RTLD_GLOBAL); | |
142 | if (!lib_handle) { | |
143 | eerror("dlopen: %s", dlerror()); | |
144 | return; | |
145 | } | |
146 | ||
147 | selinux_run_init_old = (void (*)(void)) | |
148 | dlfunc(lib_handle, "selinux_runscript"); | |
149 | selinux_run_init_new = (void (*)(int, char **)) | |
150 | dlfunc(lib_handle, "selinux_runscript2"); | |
151 | ||
152 | /* Use new run_init if it exists, else fall back to old */ | |
153 | if (selinux_run_init_new) | |
154 | selinux_run_init_new(argc, argv); | |
155 | else if (selinux_run_init_old) | |
156 | selinux_run_init_old(); | |
157 | else | |
158 | /* This shouldnt happen... probably corrupt lib */ | |
159 | eerrorx | |
160 | ("run_init is missing from runscript_selinux.so!"); | |
161 | ||
162 | dlclose(lib_handle); | |
163 | } | |
325 | } | |
326 | ||
327 | if (read_context_file(RUN_INIT_FILE, &run_init_t) != 0) { | |
328 | /* assume a reasonable default, rather than bailing out */ | |
329 | run_init_t = xstrdup("run_init_t"); | |
330 | ewarn("Assuming SELinux run_init type is %s", run_init_t); | |
331 | } | |
332 | ||
333 | /* Get our current context. */ | |
334 | if (getcon(&curr_context) < 0) { | |
335 | if (errno == ENOENT) { | |
336 | /* should only hit this if proc is not mounted. this | |
337 | * happens on Gentoo right after init starts, when | |
338 | * the init script processing starts. | |
339 | */ | |
340 | goto out; | |
341 | } else { | |
342 | perror("getcon"); | |
343 | exit(1); | |
344 | } | |
345 | } | |
346 | ||
347 | /* extract the type from the context */ | |
348 | curr_con = context_new(curr_context); | |
349 | curr_t = xstrdup(context_type_get(curr_con)); | |
350 | /* dont need them anymore so free() now */ | |
351 | context_free(curr_con); | |
352 | free(curr_context); | |
353 | ||
354 | /* if we are not in the run_init domain, we should not do anything */ | |
355 | if (strncmp(run_init_t, curr_t, strlen(run_init_t)) != 0) { | |
356 | goto out; | |
357 | } | |
358 | ||
359 | free(curr_t); | |
360 | free(run_init_t); | |
361 | ||
362 | if (check_auth() != 0) { | |
363 | eerrorx("Authentication failed."); | |
364 | } | |
365 | ||
366 | /* Get the context for the script to be run in. */ | |
367 | if (read_context_file(INITRC_FILE, &new_context) != 0) { | |
368 | /* assume a reasonable default, rather than bailing out */ | |
369 | new_context = xstrdup("system_u:system_r:initrc_t"); | |
370 | ewarn("Assuming SELinux initrc context is %s", new_context); | |
371 | } | |
372 | ||
373 | /* Set the new context */ | |
374 | if (setexeccon(new_context) < 0) { | |
375 | eerrorx("Could not set SELinux exec context to %s.", new_context); | |
376 | } | |
377 | ||
378 | free(new_context); | |
379 | ||
380 | /* | |
381 | * exec will recycle ptys so try and use open_init_pty if it exists | |
382 | * which will open the pty with initrc_devpts_t, if it doesnt exist, | |
383 | * fall back to plain exec | |
384 | */ | |
385 | if (access("/usr/sbin/open_init_pty", X_OK)) { | |
386 | if (execvp("/usr/sbin/open_init_pty", argv)) { | |
387 | perror("execvp"); | |
388 | exit(-1); | |
389 | } | |
390 | } else if (execvp(argv[1], argv + 1)) { | |
391 | perror("execvp"); | |
392 | exit(-1); | |
393 | } | |
394 | ||
395 | out: | |
396 | free(run_init_t); | |
397 | free(curr_t); | |
398 | } |
25 | 25 | #ifndef RC_SELINUX_UTIL_H |
26 | 26 | #define RC_SELINUX_UTIL_H |
27 | 27 | |
28 | #ifdef HAVE_SELINUX | |
29 | ||
28 | 30 | int selinux_util_open(void); |
29 | 31 | int selinux_util_label(const char *path); |
30 | 32 | int selinux_util_close(void); |
31 | 33 | |
32 | void selinux_setup(int argc, char **argv); | |
34 | void selinux_setup(char **argv); | |
35 | ||
36 | #else | |
37 | ||
38 | /* always return false for selinux_util_open() */ | |
39 | #define selinux_util_open() (0) | |
40 | #define selinux_util_label(x) do { } while(0) | |
41 | #define selinux_util_close() do { } while(0) | |
42 | ||
43 | #define selinux_setup(x) do { } while(0) | |
33 | 44 | |
34 | 45 | #endif |
46 | ||
47 | ||
48 | #endif |
35 | 35 | |
36 | 36 | #include "builtins.h" |
37 | 37 | #include "einfo.h" |
38 | #include "queue.h" | |
38 | 39 | #include "rc.h" |
39 | 40 | #include "rc-misc.h" |
40 | 41 | |
56 | 57 | }; |
57 | 58 | static const char * const longopts_help[] = { |
58 | 59 | "tests if the service exists or not", |
59 | "if the service exsits then run the command", | |
60 | "if the service exists then run the command", | |
60 | 61 | "list all available services", |
61 | 62 | "resolve the service name to an init script", |
62 | 63 | longopts_help_COMMON |
35 | 35 | |
36 | 36 | #include "builtins.h" |
37 | 37 | #include "einfo.h" |
38 | #include "queue.h" | |
38 | 39 | #include "rc.h" |
39 | 40 | #include "rc-misc.h" |
40 | 41 |
38 | 38 | |
39 | 39 | #include "builtins.h" |
40 | 40 | #include "einfo.h" |
41 | #include "queue.h" | |
41 | 42 | #include "rc.h" |
42 | 43 | #include "rc-misc.h" |
43 | 44 |
59 | 59 | |
60 | 60 | #include "builtins.h" |
61 | 61 | #include "einfo.h" |
62 | #include "queue.h" | |
62 | 63 | #include "rc.h" |
63 | 64 | #include "rc-logger.h" |
64 | 65 | #include "rc-misc.h" |
517 | 518 | } |
518 | 519 | |
519 | 520 | static void |
520 | do_stop_services(const RC_STRINGLIST *types_n, const RC_STRINGLIST *start_services, | |
521 | do_stop_services(RC_STRINGLIST *types_n, RC_STRINGLIST *start_services, | |
521 | 522 | const RC_STRINGLIST *stop_services, const RC_DEPTREE *deptree, |
522 | 523 | const char *newlevel, bool parallel, bool going_down) |
523 | 524 | { |
0 | /* | |
1 | * runscript.c | |
2 | * Handle launching of init scripts. | |
3 | */ | |
4 | ||
5 | /* | |
6 | * Copyright (c) 2007-2009 Roy Marples <roy@marples.name> | |
7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | |
16 | * | |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
27 | * SUCH DAMAGE. | |
28 | */ | |
29 | ||
30 | #include <sys/types.h> | |
31 | #include <sys/ioctl.h> | |
32 | #include <sys/file.h> | |
33 | #include <sys/param.h> | |
34 | #include <sys/stat.h> | |
35 | #include <sys/wait.h> | |
36 | ||
37 | #include <ctype.h> | |
38 | #include <errno.h> | |
39 | #include <fcntl.h> | |
40 | #include <fnmatch.h> | |
41 | #include <getopt.h> | |
42 | #include <libgen.h> | |
43 | #include <limits.h> | |
44 | #include <poll.h> | |
45 | #include <signal.h> | |
46 | #include <stdio.h> | |
47 | #include <stdlib.h> | |
48 | #include <string.h> | |
49 | #include <termios.h> | |
50 | #include <time.h> | |
51 | #include <unistd.h> | |
52 | ||
53 | #if defined(__linux__) || defined(__GLIBC__) | |
54 | # include <pty.h> | |
55 | #elif defined(__NetBSD__) || defined(__OpenBSD__) | |
56 | # include <util.h> | |
57 | #else | |
58 | # include <libutil.h> | |
59 | #endif | |
60 | ||
61 | #include "builtins.h" | |
62 | #include "einfo.h" | |
63 | #include "rc.h" | |
64 | #include "rc-misc.h" | |
65 | #include "rc-plugin.h" | |
66 | ||
67 | #ifdef HAVE_SELINUX | |
68 | #include "rc-selinux.h" | |
69 | #endif | |
70 | ||
71 | #define PREFIX_LOCK RC_SVCDIR "/prefix.lock" | |
72 | ||
73 | #define WAIT_INTERVAL 20000000 /* usecs to poll the lock file */ | |
74 | #define WAIT_TIMEOUT 60 /* seconds until we timeout */ | |
75 | #define WARN_TIMEOUT 10 /* warn about this every N seconds */ | |
76 | ||
77 | static const char *applet; | |
78 | static char *service, *runlevel, *ibsave, *prefix; | |
79 | static RC_DEPTREE *deptree; | |
80 | static RC_STRINGLIST *applet_list, *services, *tmplist; | |
81 | static RC_STRINGLIST *restart_services, *need_services, *use_services; | |
82 | static RC_HOOK hook_out; | |
83 | static int exclusive_fd = -1, master_tty = -1; | |
84 | static bool sighup, in_background, deps, dry_run; | |
85 | static pid_t service_pid; | |
86 | static int signal_pipe[2] = { -1, -1 }; | |
87 | ||
88 | static RC_STRINGLIST *types_b, *types_n, *types_nu, *types_nua, *types_m; | |
89 | static RC_STRINGLIST *types_mua = NULL; | |
90 | ||
91 | static void | |
92 | handle_signal(int sig) | |
93 | { | |
94 | int serrno = errno; | |
95 | char signame[10] = { '\0' }; | |
96 | struct winsize ws; | |
97 | ||
98 | switch (sig) { | |
99 | case SIGHUP: | |
100 | sighup = true; | |
101 | break; | |
102 | ||
103 | case SIGCHLD: | |
104 | if (signal_pipe[1] > -1) { | |
105 | if (write(signal_pipe[1], &sig, sizeof(sig)) == -1) | |
106 | eerror("%s: send: %s", | |
107 | service, strerror(errno)); | |
108 | } else | |
109 | rc_waitpid(-1); | |
110 | break; | |
111 | ||
112 | case SIGWINCH: | |
113 | if (master_tty >= 0) { | |
114 | ioctl(fileno(stdout), TIOCGWINSZ, &ws); | |
115 | ioctl(master_tty, TIOCSWINSZ, &ws); | |
116 | } | |
117 | break; | |
118 | ||
119 | case SIGINT: | |
120 | if (!signame[0]) | |
121 | snprintf(signame, sizeof(signame), "SIGINT"); | |
122 | /* FALLTHROUGH */ | |
123 | case SIGTERM: | |
124 | if (!signame[0]) | |
125 | snprintf(signame, sizeof(signame), "SIGTERM"); | |
126 | /* FALLTHROUGH */ | |
127 | case SIGQUIT: | |
128 | if (!signame[0]) | |
129 | snprintf(signame, sizeof(signame), "SIGQUIT"); | |
130 | /* Send the signal to our children too */ | |
131 | if (service_pid > 0) | |
132 | kill(service_pid, sig); | |
133 | eerrorx("%s: caught %s, aborting", applet, signame); | |
134 | /* NOTREACHED */ | |
135 | ||
136 | default: | |
137 | eerror("%s: caught unknown signal %d", applet, sig); | |
138 | } | |
139 | ||
140 | /* Restore errno */ | |
141 | errno = serrno; | |
142 | } | |
143 | ||
144 | static void | |
145 | unhotplug() | |
146 | { | |
147 | char file[PATH_MAX]; | |
148 | ||
149 | snprintf(file, sizeof(file), RC_SVCDIR "/hotplugged/%s", applet); | |
150 | if (exists(file) && unlink(file) != 0) | |
151 | eerror("%s: unlink `%s': %s", applet, file, strerror(errno)); | |
152 | } | |
153 | ||
154 | static void | |
155 | start_services(RC_STRINGLIST *list) | |
156 | { | |
157 | RC_STRING *svc; | |
158 | RC_SERVICE state = rc_service_state (service); | |
159 | ||
160 | if (!list) | |
161 | return; | |
162 | ||
163 | if (state & RC_SERVICE_INACTIVE || | |
164 | state & RC_SERVICE_WASINACTIVE || | |
165 | state & RC_SERVICE_STARTING || | |
166 | state & RC_SERVICE_STARTED) | |
167 | { | |
168 | TAILQ_FOREACH(svc, list, entries) { | |
169 | if (!(rc_service_state(svc->value) & | |
170 | RC_SERVICE_STOPPED)) | |
171 | continue; | |
172 | if (state & RC_SERVICE_INACTIVE || | |
173 | state & RC_SERVICE_WASINACTIVE) | |
174 | { | |
175 | rc_service_schedule_start(service, | |
176 | svc->value); | |
177 | ewarn("WARNING: %s will start when %s has started", | |
178 | svc->value, applet); | |
179 | } else | |
180 | service_start(svc->value); | |
181 | } | |
182 | } | |
183 | } | |
184 | ||
185 | static void | |
186 | restore_state(void) | |
187 | { | |
188 | RC_SERVICE state; | |
189 | ||
190 | if (rc_in_plugin || exclusive_fd == -1) | |
191 | return; | |
192 | state = rc_service_state(applet); | |
193 | if (state & RC_SERVICE_STOPPING) { | |
194 | if (state & RC_SERVICE_WASINACTIVE) | |
195 | rc_service_mark(applet, RC_SERVICE_INACTIVE); | |
196 | else | |
197 | rc_service_mark(applet, RC_SERVICE_STARTED); | |
198 | if (rc_runlevel_stopping()) | |
199 | rc_service_mark(applet, RC_SERVICE_FAILED); | |
200 | } else if (state & RC_SERVICE_STARTING) { | |
201 | if (state & RC_SERVICE_WASINACTIVE) | |
202 | rc_service_mark(applet, RC_SERVICE_INACTIVE); | |
203 | else | |
204 | rc_service_mark(applet, RC_SERVICE_STOPPED); | |
205 | if (rc_runlevel_starting()) | |
206 | rc_service_mark(applet, RC_SERVICE_FAILED); | |
207 | } | |
208 | exclusive_fd = svc_unlock(applet, exclusive_fd); | |
209 | } | |
210 | ||
211 | static void | |
212 | cleanup(void) | |
213 | { | |
214 | restore_state(); | |
215 | ||
216 | if (!rc_in_plugin) { | |
217 | if (hook_out) { | |
218 | rc_plugin_run(hook_out, applet); | |
219 | if (hook_out == RC_HOOK_SERVICE_START_DONE) | |
220 | rc_plugin_run(RC_HOOK_SERVICE_START_OUT, | |
221 | applet); | |
222 | else if (hook_out == RC_HOOK_SERVICE_STOP_DONE) | |
223 | rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, | |
224 | applet); | |
225 | } | |
226 | ||
227 | if (restart_services) | |
228 | start_services(restart_services); | |
229 | } | |
230 | ||
231 | rc_plugin_unload(); | |
232 | ||
233 | #ifdef DEBUG_MEMORY | |
234 | rc_stringlist_free(types_b); | |
235 | rc_stringlist_free(types_n); | |
236 | rc_stringlist_free(types_nu); | |
237 | rc_stringlist_free(types_nua); | |
238 | rc_stringlist_free(types_m); | |
239 | rc_stringlist_free(types_mua); | |
240 | rc_deptree_free(deptree); | |
241 | rc_stringlist_free(restart_services); | |
242 | rc_stringlist_free(need_services); | |
243 | rc_stringlist_free(use_services); | |
244 | rc_stringlist_free(services); | |
245 | rc_stringlist_free(applet_list); | |
246 | rc_stringlist_free(tmplist); | |
247 | free(ibsave); | |
248 | free(service); | |
249 | free(prefix); | |
250 | free(runlevel); | |
251 | #endif | |
252 | } | |
253 | ||
254 | /* Buffer and lock all output messages so that we get readable content */ | |
255 | /* FIXME: Use a dynamic lock file that contains the tty/pts as well. | |
256 | * For example openrc-pts8.lock or openrc-tty1.lock. | |
257 | * Using a static lock file makes no sense, esp. in multi-user environments. | |
258 | * Why don't we use (f)printf, as it is thread-safe through POSIX already? | |
259 | * Bug: 360013 | |
260 | */ | |
261 | static int | |
262 | write_prefix(const char *buffer, size_t bytes, bool *prefixed) | |
263 | { | |
264 | size_t i, j; | |
265 | const char *ec = ecolor(ECOLOR_HILITE); | |
266 | const char *ec_normal = ecolor(ECOLOR_NORMAL); | |
267 | ssize_t ret = 0; | |
268 | int fd = fileno(stdout), lock_fd = -1; | |
269 | ||
270 | /* | |
271 | * Lock the prefix. | |
272 | * open() may fail here when running as user, as RC_SVCDIR may not be writable. | |
273 | */ | |
274 | lock_fd = open(PREFIX_LOCK, O_WRONLY | O_CREAT, 0664); | |
275 | ||
276 | if (lock_fd != -1) { | |
277 | while (flock(lock_fd, LOCK_EX) != 0) { | |
278 | if (errno != EINTR) { | |
279 | ewarnv("flock() failed: %s", strerror(errno)); | |
280 | break; | |
281 | } | |
282 | } | |
283 | } | |
284 | else | |
285 | ewarnv("Couldn't open the prefix lock, please make sure you have enough permissions"); | |
286 | ||
287 | for (i = 0; i < bytes; i++) { | |
288 | /* We don't prefix eend calls (cursor up) */ | |
289 | if (buffer[i] == '\033' && !*prefixed) { | |
290 | for (j = i + 1; j < bytes; j++) { | |
291 | if (buffer[j] == 'A') | |
292 | *prefixed = true; | |
293 | if (isalpha((unsigned int)buffer[j])) | |
294 | break; | |
295 | } | |
296 | } | |
297 | ||
298 | if (!*prefixed) { | |
299 | ret += write(fd, ec, strlen(ec)); | |
300 | ret += write(fd, prefix, strlen(prefix)); | |
301 | ret += write(fd, ec_normal, strlen(ec_normal)); | |
302 | ret += write(fd, "|", 1); | |
303 | *prefixed = true; | |
304 | } | |
305 | ||
306 | if (buffer[i] == '\n') | |
307 | *prefixed = false; | |
308 | ret += write(fd, buffer + i, 1); | |
309 | } | |
310 | ||
311 | /* Release the lock */ | |
312 | close(lock_fd); | |
313 | ||
314 | return ret; | |
315 | } | |
316 | ||
317 | static int | |
318 | svc_exec(const char *arg1, const char *arg2) | |
319 | { | |
320 | int ret, fdout = fileno(stdout); | |
321 | struct termios tt; | |
322 | struct winsize ws; | |
323 | int i; | |
324 | int flags = 0; | |
325 | struct pollfd fd[2]; | |
326 | int s; | |
327 | char *buffer; | |
328 | size_t bytes; | |
329 | bool prefixed = false; | |
330 | int slave_tty; | |
331 | sigset_t sigchldmask; | |
332 | sigset_t oldmask; | |
333 | ||
334 | /* Setup our signal pipe */ | |
335 | if (pipe(signal_pipe) == -1) | |
336 | eerrorx("%s: pipe: %s", service, applet); | |
337 | for (i = 0; i < 2; i++) | |
338 | if ((flags = fcntl(signal_pipe[i], F_GETFD, 0) == -1 || | |
339 | fcntl(signal_pipe[i], F_SETFD, flags | FD_CLOEXEC) == -1)) | |
340 | eerrorx("%s: fcntl: %s", service, strerror(errno)); | |
341 | ||
342 | /* Open a pty for our prefixed output | |
343 | * We do this instead of mapping pipes to stdout, stderr so that | |
344 | * programs can tell if they're attached to a tty or not. | |
345 | * The only loss is that we can no longer tell the difference | |
346 | * between the childs stdout or stderr */ | |
347 | master_tty = slave_tty = -1; | |
348 | if (prefix && isatty(fdout)) { | |
349 | tcgetattr(fdout, &tt); | |
350 | ioctl(fdout, TIOCGWINSZ, &ws); | |
351 | ||
352 | /* If the below call fails due to not enough ptys then we don't | |
353 | * prefix the output, but we still work */ | |
354 | openpty(&master_tty, &slave_tty, NULL, &tt, &ws); | |
355 | if (master_tty >= 0 && | |
356 | (flags = fcntl(master_tty, F_GETFD, 0)) == 0) | |
357 | fcntl(master_tty, F_SETFD, flags | FD_CLOEXEC); | |
358 | ||
359 | if (slave_tty >=0 && | |
360 | (flags = fcntl(slave_tty, F_GETFD, 0)) == 0) | |
361 | fcntl(slave_tty, F_SETFD, flags | FD_CLOEXEC); | |
362 | } | |
363 | ||
364 | service_pid = fork(); | |
365 | if (service_pid == -1) | |
366 | eerrorx("%s: fork: %s", service, strerror(errno)); | |
367 | if (service_pid == 0) { | |
368 | if (slave_tty >= 0) { | |
369 | dup2(slave_tty, STDOUT_FILENO); | |
370 | dup2(slave_tty, STDERR_FILENO); | |
371 | } | |
372 | ||
373 | if (exists(RC_SVCDIR "/runscript.sh")) { | |
374 | execl(RC_SVCDIR "/runscript.sh", | |
375 | RC_SVCDIR "/runscript.sh", | |
376 | service, arg1, arg2, (char *) NULL); | |
377 | eerror("%s: exec `" RC_SVCDIR "/runscript.sh': %s", | |
378 | service, strerror(errno)); | |
379 | _exit(EXIT_FAILURE); | |
380 | } else { | |
381 | execl(RC_LIBEXECDIR "/sh/runscript.sh", | |
382 | RC_LIBEXECDIR "/sh/runscript.sh", | |
383 | service, arg1, arg2, (char *) NULL); | |
384 | eerror("%s: exec `" RC_LIBEXECDIR "/sh/runscript.sh': %s", | |
385 | service, strerror(errno)); | |
386 | _exit(EXIT_FAILURE); | |
387 | } | |
388 | } | |
389 | ||
390 | buffer = xmalloc(sizeof(char) * BUFSIZ); | |
391 | fd[0].fd = signal_pipe[0]; | |
392 | fd[0].events = fd[1].events = POLLIN; | |
393 | fd[0].revents = fd[1].revents = 0; | |
394 | if (master_tty >= 0) { | |
395 | fd[1].fd = master_tty; | |
396 | fd[1].events = POLLIN; | |
397 | fd[1].revents = 0; | |
398 | } | |
399 | ||
400 | for (;;) { | |
401 | if ((s = poll(fd, master_tty >= 0 ? 2 : 1, -1)) == -1) { | |
402 | if (errno != EINTR) { | |
403 | eerror("%s: poll: %s", | |
404 | service, strerror(errno)); | |
405 | break; | |
406 | } | |
407 | } | |
408 | ||
409 | if (s > 0) { | |
410 | if (fd[1].revents & (POLLIN | POLLHUP)) { | |
411 | bytes = read(master_tty, buffer, BUFSIZ); | |
412 | write_prefix(buffer, bytes, &prefixed); | |
413 | } | |
414 | ||
415 | /* Only SIGCHLD signals come down this pipe */ | |
416 | if (fd[0].revents & (POLLIN | POLLHUP)) | |
417 | break; | |
418 | } | |
419 | } | |
420 | ||
421 | free(buffer); | |
422 | ||
423 | sigemptyset (&sigchldmask); | |
424 | sigaddset (&sigchldmask, SIGCHLD); | |
425 | sigprocmask (SIG_BLOCK, &sigchldmask, &oldmask); | |
426 | ||
427 | close(signal_pipe[0]); | |
428 | close(signal_pipe[1]); | |
429 | signal_pipe[0] = signal_pipe[1] = -1; | |
430 | ||
431 | sigprocmask (SIG_SETMASK, &oldmask, NULL); | |
432 | ||
433 | if (master_tty >= 0) { | |
434 | /* Why did we do this? */ | |
435 | /* signal (SIGWINCH, SIG_IGN); */ | |
436 | close(master_tty); | |
437 | master_tty = -1; | |
438 | } | |
439 | ||
440 | ret = rc_waitpid(service_pid); | |
441 | ret = WEXITSTATUS(ret); | |
442 | if (ret != 0 && errno == ECHILD) | |
443 | /* killall5 -9 could cause this */ | |
444 | ret = 0; | |
445 | service_pid = 0; | |
446 | ||
447 | return ret; | |
448 | } | |
449 | ||
450 | static bool | |
451 | svc_wait(const char *svc) | |
452 | { | |
453 | char file[PATH_MAX]; | |
454 | int fd; | |
455 | bool forever = false; | |
456 | RC_STRINGLIST *keywords; | |
457 | struct timespec interval, timeout, warn; | |
458 | ||
459 | /* Some services don't have a timeout, like fsck */ | |
460 | keywords = rc_deptree_depend(deptree, svc, "keyword"); | |
461 | if (rc_stringlist_find(keywords, "-timeout") || | |
462 | rc_stringlist_find(keywords, "notimeout")) | |
463 | forever = true; | |
464 | rc_stringlist_free(keywords); | |
465 | ||
466 | snprintf(file, sizeof(file), RC_SVCDIR "/exclusive/%s", | |
467 | basename_c(svc)); | |
468 | ||
469 | interval.tv_sec = 0; | |
470 | interval.tv_nsec = WAIT_INTERVAL; | |
471 | timeout.tv_sec = WAIT_TIMEOUT; | |
472 | timeout.tv_nsec = 0; | |
473 | warn.tv_sec = WARN_TIMEOUT; | |
474 | warn.tv_nsec = 0; | |
475 | for (;;) { | |
476 | fd = open(file, O_RDONLY | O_NONBLOCK); | |
477 | if (fd != -1) { | |
478 | if (flock(fd, LOCK_SH | LOCK_NB) == 0) { | |
479 | close(fd); | |
480 | return true; | |
481 | } | |
482 | close(fd); | |
483 | } | |
484 | if (errno == ENOENT) | |
485 | return true; | |
486 | if (errno != EWOULDBLOCK) | |
487 | eerrorx("%s: open `%s': %s", applet, file, | |
488 | strerror(errno)); | |
489 | if (nanosleep(&interval, NULL) == -1) { | |
490 | if (errno != EINTR) | |
491 | return false; | |
492 | } | |
493 | if (!forever) { | |
494 | timespecsub(&timeout, &interval, &timeout); | |
495 | if (timeout.tv_sec <= 0) | |
496 | return false; | |
497 | timespecsub(&warn, &interval, &warn); | |
498 | if (warn.tv_sec <= 0) { | |
499 | ewarn("%s: waiting for %s (%d seconds)", | |
500 | applet, svc, (int)timeout.tv_sec); | |
501 | warn.tv_sec = WARN_TIMEOUT; | |
502 | warn.tv_nsec = 0; | |
503 | } | |
504 | } | |
505 | } | |
506 | return false; | |
507 | } | |
508 | ||
509 | static void | |
510 | get_started_services(void) | |
511 | { | |
512 | RC_STRINGLIST *tmp = rc_services_in_state(RC_SERVICE_INACTIVE); | |
513 | ||
514 | rc_stringlist_free(restart_services); | |
515 | restart_services = rc_services_in_state(RC_SERVICE_STARTED); | |
516 | TAILQ_CONCAT(restart_services, tmp, entries); | |
517 | free(tmp); | |
518 | } | |
519 | ||
520 | static void | |
521 | setup_types(void) | |
522 | { | |
523 | types_b = rc_stringlist_new(); | |
524 | rc_stringlist_add(types_b, "broken"); | |
525 | ||
526 | types_n = rc_stringlist_new(); | |
527 | rc_stringlist_add(types_n, "ineed"); | |
528 | ||
529 | types_nu = rc_stringlist_new(); | |
530 | rc_stringlist_add(types_nu, "ineed"); | |
531 | rc_stringlist_add(types_nu, "iuse"); | |
532 | ||
533 | types_nua = rc_stringlist_new(); | |
534 | rc_stringlist_add(types_nua, "ineed"); | |
535 | rc_stringlist_add(types_nua, "iuse"); | |
536 | rc_stringlist_add(types_nua, "iafter"); | |
537 | ||
538 | types_m = rc_stringlist_new(); | |
539 | rc_stringlist_add(types_m, "needsme"); | |
540 | ||
541 | types_mua = rc_stringlist_new(); | |
542 | rc_stringlist_add(types_mua, "needsme"); | |
543 | rc_stringlist_add(types_mua, "usesme"); | |
544 | rc_stringlist_add(types_mua, "beforeme"); | |
545 | } | |
546 | ||
547 | static void | |
548 | svc_start_check(void) | |
549 | { | |
550 | RC_SERVICE state; | |
551 | ||
552 | state = rc_service_state(service); | |
553 | ||
554 | if (in_background) { | |
555 | if (!(state & (RC_SERVICE_INACTIVE | RC_SERVICE_STOPPED))) | |
556 | exit(EXIT_FAILURE); | |
557 | if (rc_yesno(getenv("IN_HOTPLUG"))) | |
558 | rc_service_mark(service, RC_SERVICE_HOTPLUGGED); | |
559 | if (strcmp(runlevel, RC_LEVEL_SYSINIT) == 0) | |
560 | ewarnx("WARNING: %s will be started in the" | |
561 | " next runlevel", applet); | |
562 | } | |
563 | ||
564 | if (exclusive_fd == -1) | |
565 | exclusive_fd = svc_lock(applet); | |
566 | if (exclusive_fd == -1) { | |
567 | if (errno == EACCES) | |
568 | eerrorx("%s: superuser access required", applet); | |
569 | if (state & RC_SERVICE_STOPPING) | |
570 | ewarnx("WARNING: %s is stopping", applet); | |
571 | else | |
572 | ewarnx("WARNING: %s is already starting", applet); | |
573 | } | |
574 | fcntl(exclusive_fd, F_SETFD, | |
575 | fcntl(exclusive_fd, F_GETFD, 0) | FD_CLOEXEC); | |
576 | ||
577 | if (state & RC_SERVICE_STARTED) { | |
578 | ewarn("WARNING: %s has already been started", applet); | |
579 | exit(EXIT_SUCCESS); | |
580 | } | |
581 | else if (state & RC_SERVICE_INACTIVE && !in_background) | |
582 | ewarnx("WARNING: %s has already started, but is inactive", | |
583 | applet); | |
584 | ||
585 | rc_service_mark(service, RC_SERVICE_STARTING); | |
586 | hook_out = RC_HOOK_SERVICE_START_OUT; | |
587 | rc_plugin_run(RC_HOOK_SERVICE_START_IN, applet); | |
588 | } | |
589 | ||
590 | static void | |
591 | svc_start_deps(void) | |
592 | { | |
593 | bool first; | |
594 | RC_STRING *svc, *svc2; | |
595 | RC_SERVICE state; | |
596 | int depoptions = RC_DEP_TRACE, n; | |
597 | size_t len; | |
598 | char *p, *tmp; | |
599 | pid_t pid; | |
600 | ||
601 | errno = 0; | |
602 | if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT) | |
603 | depoptions |= RC_DEP_STRICT; | |
604 | ||
605 | if (!deptree && ((deptree = _rc_deptree_load(0, NULL)) == NULL)) | |
606 | eerrorx("failed to load deptree"); | |
607 | if (!types_b) | |
608 | setup_types(); | |
609 | ||
610 | services = rc_deptree_depends(deptree, types_b, applet_list, | |
611 | runlevel, 0); | |
612 | if (TAILQ_FIRST(services)) { | |
613 | eerrorn("ERROR: %s needs service(s) ", applet); | |
614 | first = true; | |
615 | TAILQ_FOREACH(svc, services, entries) { | |
616 | if (first) | |
617 | first = false; | |
618 | else | |
619 | fprintf(stderr, ", "); | |
620 | fprintf(stderr, "%s", svc->value); | |
621 | } | |
622 | fprintf(stderr, "\n"); | |
623 | exit(EXIT_FAILURE); | |
624 | } | |
625 | rc_stringlist_free(services); | |
626 | services = NULL; | |
627 | ||
628 | need_services = rc_deptree_depends(deptree, types_n, | |
629 | applet_list, runlevel, depoptions); | |
630 | use_services = rc_deptree_depends(deptree, types_nu, | |
631 | applet_list, runlevel, depoptions); | |
632 | ||
633 | if (!rc_runlevel_starting()) { | |
634 | TAILQ_FOREACH(svc, use_services, entries) { | |
635 | state = rc_service_state(svc->value); | |
636 | /* Don't stop failed services again. | |
637 | * If you remove this check, ensure that the | |
638 | * exclusive file isn't created. */ | |
639 | if (state & RC_SERVICE_FAILED && | |
640 | rc_runlevel_starting()) | |
641 | continue; | |
642 | if (state & RC_SERVICE_STOPPED) { | |
643 | if (dry_run) { | |
644 | printf(" %s", svc->value); | |
645 | continue; | |
646 | } | |
647 | pid = service_start(svc->value); | |
648 | if (!rc_conf_yesno("rc_parallel")) | |
649 | rc_waitpid(pid); | |
650 | } | |
651 | } | |
652 | } | |
653 | ||
654 | if (dry_run) | |
655 | return; | |
656 | ||
657 | /* Now wait for them to start */ | |
658 | services = rc_deptree_depends(deptree, types_nua, applet_list, | |
659 | runlevel, depoptions); | |
660 | /* We use tmplist to hold our scheduled by list */ | |
661 | tmplist = rc_stringlist_new(); | |
662 | TAILQ_FOREACH(svc, services, entries) { | |
663 | state = rc_service_state(svc->value); | |
664 | if (state & RC_SERVICE_STARTED) | |
665 | continue; | |
666 | ||
667 | /* Don't wait for services which went inactive but are | |
668 | * now in starting state which we are after */ | |
669 | if (state & RC_SERVICE_STARTING && | |
670 | state & RC_SERVICE_WASINACTIVE) | |
671 | { | |
672 | if (!rc_stringlist_find(need_services, svc->value) && | |
673 | !rc_stringlist_find(use_services, svc->value)) | |
674 | continue; | |
675 | } | |
676 | ||
677 | if (!svc_wait(svc->value)) | |
678 | eerror("%s: timed out waiting for %s", | |
679 | applet, svc->value); | |
680 | state = rc_service_state(svc->value); | |
681 | if (state & RC_SERVICE_STARTED) | |
682 | continue; | |
683 | if (rc_stringlist_find(need_services, svc->value)) { | |
684 | if (state & RC_SERVICE_INACTIVE || | |
685 | state & RC_SERVICE_WASINACTIVE) | |
686 | { | |
687 | rc_stringlist_add(tmplist, svc->value); | |
688 | } else if (!TAILQ_FIRST(tmplist)) | |
689 | eerrorx("ERROR: cannot start %s as" | |
690 | " %s would not start", | |
691 | applet, svc->value); | |
692 | } | |
693 | } | |
694 | ||
695 | if (TAILQ_FIRST(tmplist)) { | |
696 | /* Set the state now, then unlink our exclusive so that | |
697 | our scheduled list is preserved */ | |
698 | rc_service_mark(service, RC_SERVICE_STOPPED); | |
699 | ||
700 | rc_stringlist_free(use_services); | |
701 | use_services = NULL; | |
702 | len = 0; | |
703 | n = 0; | |
704 | TAILQ_FOREACH(svc, tmplist, entries) { | |
705 | rc_service_schedule_start(svc->value, service); | |
706 | use_services = rc_deptree_depend(deptree, | |
707 | "iprovide", svc->value); | |
708 | TAILQ_FOREACH(svc2, use_services, entries) | |
709 | rc_service_schedule_start(svc2->value, service); | |
710 | rc_stringlist_free(use_services); | |
711 | use_services = NULL; | |
712 | len += strlen(svc->value) + 2; | |
713 | n++; | |
714 | } | |
715 | ||
716 | len += 5; | |
717 | tmp = p = xmalloc(sizeof(char) * len); | |
718 | TAILQ_FOREACH(svc, tmplist, entries) { | |
719 | if (p != tmp) | |
720 | p += snprintf(p, len, ", "); | |
721 | p += snprintf(p, len - (p - tmp), | |
722 | "%s", svc->value); | |
723 | } | |
724 | rc_stringlist_free(tmplist); | |
725 | tmplist = NULL; | |
726 | ewarnx("WARNING: %s will start when %s has started", applet, tmp); | |
727 | free(tmp); | |
728 | } | |
729 | ||
730 | rc_stringlist_free(tmplist); | |
731 | tmplist = NULL; | |
732 | rc_stringlist_free(services); | |
733 | services = NULL; | |
734 | } | |
735 | ||
736 | static void svc_start_real() | |
737 | { | |
738 | bool started; | |
739 | RC_STRING *svc, *svc2; | |
740 | ||
741 | if (ibsave) | |
742 | setenv("IN_BACKGROUND", ibsave, 1); | |
743 | hook_out = RC_HOOK_SERVICE_START_DONE; | |
744 | rc_plugin_run(RC_HOOK_SERVICE_START_NOW, applet); | |
745 | started = (svc_exec("start", NULL) == 0); | |
746 | if (ibsave) | |
747 | unsetenv("IN_BACKGROUND"); | |
748 | ||
749 | if (rc_service_state(service) & RC_SERVICE_INACTIVE) | |
750 | ewarnx("WARNING: %s has started, but is inactive", applet); | |
751 | else if (!started) | |
752 | eerrorx("ERROR: %s failed to start", applet); | |
753 | ||
754 | rc_service_mark(service, RC_SERVICE_STARTED); | |
755 | exclusive_fd = svc_unlock(applet, exclusive_fd); | |
756 | hook_out = RC_HOOK_SERVICE_START_OUT; | |
757 | rc_plugin_run(RC_HOOK_SERVICE_START_DONE, applet); | |
758 | ||
759 | /* Now start any scheduled services */ | |
760 | services = rc_services_scheduled(service); | |
761 | TAILQ_FOREACH(svc, services, entries) | |
762 | if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) | |
763 | service_start(svc->value); | |
764 | rc_stringlist_free(services); | |
765 | services = NULL; | |
766 | ||
767 | /* Do the same for any services we provide */ | |
768 | if (deptree) { | |
769 | tmplist = rc_deptree_depend(deptree, "iprovide", applet); | |
770 | TAILQ_FOREACH(svc, tmplist, entries) { | |
771 | services = rc_services_scheduled(svc->value); | |
772 | TAILQ_FOREACH(svc2, services, entries) | |
773 | if (rc_service_state(svc2->value) & | |
774 | RC_SERVICE_STOPPED) | |
775 | service_start(svc2->value); | |
776 | rc_stringlist_free(services); | |
777 | services = NULL; | |
778 | } | |
779 | rc_stringlist_free(tmplist); | |
780 | tmplist = NULL; | |
781 | } | |
782 | ||
783 | hook_out = 0; | |
784 | rc_plugin_run(RC_HOOK_SERVICE_START_OUT, applet); | |
785 | } | |
786 | ||
787 | static void | |
788 | svc_start(void) | |
789 | { | |
790 | if (dry_run) | |
791 | einfon("start:"); | |
792 | else | |
793 | svc_start_check(); | |
794 | if (deps) | |
795 | svc_start_deps(); | |
796 | if (dry_run) | |
797 | printf(" %s\n", applet); | |
798 | else | |
799 | svc_start_real(); | |
800 | } | |
801 | ||
802 | static int | |
803 | svc_stop_check(RC_SERVICE *state) | |
804 | { | |
805 | *state = rc_service_state(service); | |
806 | ||
807 | if (rc_runlevel_stopping() && *state & RC_SERVICE_FAILED) | |
808 | exit(EXIT_FAILURE); | |
809 | ||
810 | if (in_background && | |
811 | !(*state & RC_SERVICE_STARTED) && | |
812 | !(*state & RC_SERVICE_INACTIVE)) | |
813 | exit(EXIT_FAILURE); | |
814 | ||
815 | if (exclusive_fd == -1) | |
816 | exclusive_fd = svc_lock(applet); | |
817 | if (exclusive_fd == -1) { | |
818 | if (errno == EACCES) | |
819 | eerrorx("%s: superuser access required", applet); | |
820 | if (*state & RC_SERVICE_STOPPING) | |
821 | ewarnx("WARNING: %s is already stopping", applet); | |
822 | eerrorx("ERROR: %s stopped by something else", applet); | |
823 | } | |
824 | fcntl(exclusive_fd, F_SETFD, | |
825 | fcntl(exclusive_fd, F_GETFD, 0) | FD_CLOEXEC); | |
826 | ||
827 | if (*state & RC_SERVICE_STOPPED) { | |
828 | ewarn("WARNING: %s is already stopped", applet); | |
829 | return 1; | |
830 | } | |
831 | ||
832 | rc_service_mark(service, RC_SERVICE_STOPPING); | |
833 | hook_out = RC_HOOK_SERVICE_STOP_OUT; | |
834 | rc_plugin_run(RC_HOOK_SERVICE_STOP_IN, applet); | |
835 | ||
836 | if (!rc_runlevel_stopping()) { | |
837 | if (rc_service_in_runlevel(service, RC_LEVEL_SYSINIT)) | |
838 | ewarn("WARNING: you are stopping a sysinit service"); | |
839 | else if (rc_service_in_runlevel(service, RC_LEVEL_BOOT)) | |
840 | ewarn("WARNING: you are stopping a boot service"); | |
841 | } | |
842 | ||
843 | return 0; | |
844 | } | |
845 | ||
846 | static void | |
847 | svc_stop_deps(RC_SERVICE state) | |
848 | { | |
849 | int depoptions = RC_DEP_TRACE; | |
850 | RC_STRING *svc; | |
851 | pid_t pid; | |
852 | ||
853 | if (state & RC_SERVICE_WASINACTIVE) | |
854 | return; | |
855 | ||
856 | errno = 0; | |
857 | if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT) | |
858 | depoptions |= RC_DEP_STRICT; | |
859 | ||
860 | if (!deptree && ((deptree = _rc_deptree_load(0, NULL)) == NULL)) | |
861 | eerrorx("failed to load deptree"); | |
862 | ||
863 | if (!types_m) | |
864 | setup_types(); | |
865 | ||
866 | services = rc_deptree_depends(deptree, types_m, applet_list, | |
867 | runlevel, depoptions); | |
868 | tmplist = rc_stringlist_new(); | |
869 | TAILQ_FOREACH_REVERSE(svc, services, rc_stringlist, entries) { | |
870 | state = rc_service_state(svc->value); | |
871 | /* Don't stop failed services again. | |
872 | * If you remove this check, ensure that the | |
873 | * exclusive file isn't created. */ | |
874 | if (state & RC_SERVICE_FAILED && | |
875 | rc_runlevel_stopping()) | |
876 | continue; | |
877 | if (state & RC_SERVICE_STARTED || | |
878 | state & RC_SERVICE_INACTIVE) | |
879 | { | |
880 | if (dry_run) { | |
881 | printf(" %s", svc->value); | |
882 | continue; | |
883 | } | |
884 | svc_wait(svc->value); | |
885 | state = rc_service_state(svc->value); | |
886 | if (state & RC_SERVICE_STARTED || | |
887 | state & RC_SERVICE_INACTIVE) | |
888 | { | |
889 | pid = service_stop(svc->value); | |
890 | if (!rc_conf_yesno("rc_parallel")) | |
891 | rc_waitpid(pid); | |
892 | rc_stringlist_add(tmplist, svc->value); | |
893 | } | |
894 | } | |
895 | } | |
896 | rc_stringlist_free(services); | |
897 | services = NULL; | |
898 | if (dry_run) | |
899 | return; | |
900 | ||
901 | TAILQ_FOREACH(svc, tmplist, entries) { | |
902 | if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) | |
903 | continue; | |
904 | svc_wait(svc->value); | |
905 | if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) | |
906 | continue; | |
907 | if (rc_runlevel_stopping()) { | |
908 | /* If shutting down, we should stop even | |
909 | * if a dependant failed */ | |
910 | if (runlevel && | |
911 | (strcmp(runlevel, | |
912 | RC_LEVEL_SHUTDOWN) == 0 || | |
913 | strcmp(runlevel, | |
914 | RC_LEVEL_SINGLE) == 0)) | |
915 | continue; | |
916 | rc_service_mark(service, RC_SERVICE_FAILED); | |
917 | } | |
918 | eerrorx("ERROR: cannot stop %s as %s " | |
919 | "is still up", applet, svc->value); | |
920 | } | |
921 | rc_stringlist_free(tmplist); | |
922 | tmplist = NULL; | |
923 | ||
924 | /* We now wait for other services that may use us and are | |
925 | * stopping. This is important when a runlevel stops */ | |
926 | services = rc_deptree_depends(deptree, types_mua, applet_list, | |
927 | runlevel, depoptions); | |
928 | TAILQ_FOREACH(svc, services, entries) { | |
929 | if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) | |
930 | continue; | |
931 | svc_wait(svc->value); | |
932 | } | |
933 | rc_stringlist_free(services); | |
934 | services = NULL; | |
935 | } | |
936 | ||
937 | static void | |
938 | svc_stop_real(void) | |
939 | { | |
940 | bool stopped; | |
941 | ||
942 | /* If we're stopping localmount, set LC_ALL=C so that | |
943 | * bash doesn't load anything blocking the unmounting of /usr */ | |
944 | if (strcmp(applet, "localmount") == 0) | |
945 | setenv("LC_ALL", "C", 1); | |
946 | ||
947 | if (ibsave) | |
948 | setenv("IN_BACKGROUND", ibsave, 1); | |
949 | hook_out = RC_HOOK_SERVICE_STOP_DONE; | |
950 | rc_plugin_run(RC_HOOK_SERVICE_STOP_NOW, applet); | |
951 | stopped = (svc_exec("stop", NULL) == 0); | |
952 | if (ibsave) | |
953 | unsetenv("IN_BACKGROUND"); | |
954 | ||
955 | if (!stopped) | |
956 | eerrorx("ERROR: %s failed to stop", applet); | |
957 | ||
958 | if (in_background) | |
959 | rc_service_mark(service, RC_SERVICE_INACTIVE); | |
960 | else | |
961 | rc_service_mark(service, RC_SERVICE_STOPPED); | |
962 | ||
963 | hook_out = RC_HOOK_SERVICE_STOP_OUT; | |
964 | rc_plugin_run(RC_HOOK_SERVICE_STOP_DONE, applet); | |
965 | hook_out = 0; | |
966 | rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, applet); | |
967 | } | |
968 | ||
969 | static int | |
970 | svc_stop(void) | |
971 | { | |
972 | RC_SERVICE state; | |
973 | ||
974 | state = 0; | |
975 | if (dry_run) | |
976 | einfon("stop:"); | |
977 | else | |
978 | if (svc_stop_check(&state) == 1) | |
979 | return 1; /* Service has been stopped already */ | |
980 | if (deps) | |
981 | svc_stop_deps(state); | |
982 | if (dry_run) | |
983 | printf(" %s\n", applet); | |
984 | else | |
985 | svc_stop_real(); | |
986 | ||
987 | return 0; | |
988 | } | |
989 | ||
990 | static void | |
991 | svc_restart(void) | |
992 | { | |
993 | /* This is hairly and a better way needs to be found I think! | |
994 | * The issue is this - openvpn need net and dns. net can restart | |
995 | * dns via resolvconf, so you could have openvpn trying to restart | |
996 | * dnsmasq which in turn is waiting on net which in turn is waiting | |
997 | * on dnsmasq. | |
998 | * The work around is for resolvconf to restart its services with | |
999 | * --nodeps which means just that. | |
1000 | * The downside is that there is a small window when our status is | |
1001 | * invalid. | |
1002 | * One workaround would be to introduce a new status, | |
1003 | * or status locking. */ | |
1004 | if (!deps) { | |
1005 | RC_SERVICE state = rc_service_state(service); | |
1006 | if (state & RC_SERVICE_STARTED || state & RC_SERVICE_INACTIVE) | |
1007 | svc_exec("stop", "start"); | |
1008 | else | |
1009 | svc_exec("start", NULL); | |
1010 | return; | |
1011 | } | |
1012 | ||
1013 | if (!(rc_service_state(service) & RC_SERVICE_STOPPED)) { | |
1014 | get_started_services(); | |
1015 | svc_stop(); | |
1016 | if (dry_run) | |
1017 | ewarn("Cannot calculate restart start dependencies" | |
1018 | " on a dry-run"); | |
1019 | } | |
1020 | ||
1021 | svc_start(); | |
1022 | start_services(restart_services); | |
1023 | rc_stringlist_free(restart_services); | |
1024 | restart_services = NULL; | |
1025 | } | |
1026 | ||
1027 | static bool | |
1028 | service_plugable(void) | |
1029 | { | |
1030 | char *list, *p, *token; | |
1031 | bool allow = true, truefalse; | |
1032 | char *match = rc_conf_value("rc_hotplug"); | |
1033 | ||
1034 | if (!match) | |
1035 | match = rc_conf_value("rc_plug_services"); | |
1036 | if (!match) | |
1037 | return false; | |
1038 | ||
1039 | list = xstrdup(match); | |
1040 | p = list; | |
1041 | while ((token = strsep(&p, " "))) { | |
1042 | if (token[0] == '!') { | |
1043 | truefalse = false; | |
1044 | token++; | |
1045 | } else | |
1046 | truefalse = true; | |
1047 | ||
1048 | if (fnmatch(token, applet, 0) == 0) { | |
1049 | allow = truefalse; | |
1050 | break; | |
1051 | } | |
1052 | } | |
1053 | #ifdef DEBUG_MEMORY | |
1054 | free(list); | |
1055 | #endif | |
1056 | return allow; | |
1057 | } | |
1058 | ||
1059 | #include "_usage.h" | |
1060 | #define getoptstring "dDsSvl:Z" getoptstring_COMMON | |
1061 | #define extraopts "stop | start | restart | describe | zap" | |
1062 | static const struct option longopts[] = { | |
1063 | { "debug", 0, NULL, 'd'}, | |
1064 | { "dry-run", 0, NULL, 'Z'}, | |
1065 | { "ifstarted", 0, NULL, 's'}, | |
1066 | { "ifstopped", 0, NULL, 'S'}, | |
1067 | { "nodeps", 0, NULL, 'D'}, | |
1068 | { "lockfd", 1, NULL, 'l'}, | |
1069 | longopts_COMMON | |
1070 | }; | |
1071 | static const char *const longopts_help[] = { | |
1072 | "set xtrace when running the script", | |
1073 | "show what would be done", | |
1074 | "only run commands when started", | |
1075 | "only run commands when stopped", | |
1076 | "ignore dependencies", | |
1077 | "fd of the exclusive lock from rc", | |
1078 | longopts_help_COMMON | |
1079 | }; | |
1080 | #include "_usage.c" | |
1081 | ||
1082 | int | |
1083 | openrc_run(int argc, char **argv) | |
1084 | { | |
1085 | bool doneone = false; | |
1086 | int retval, opt, depoptions = RC_DEP_TRACE; | |
1087 | RC_STRING *svc; | |
1088 | char path[PATH_MAX], lnk[PATH_MAX]; | |
1089 | char *dir, *save = NULL, *saveLnk = NULL; | |
1090 | char pidstr[10]; | |
1091 | size_t l = 0, ll; | |
1092 | const char *file; | |
1093 | struct stat stbuf; | |
1094 | ||
1095 | /* Show help if insufficient args */ | |
1096 | if (argc < 2 || !exists(argv[1])) { | |
1097 | fprintf(stderr, "openrc-run should not be run directly\n"); | |
1098 | exit(EXIT_FAILURE); | |
1099 | } | |
1100 | ||
1101 | if (stat(argv[1], &stbuf) != 0) { | |
1102 | fprintf(stderr, "openrc-run `%s': %s\n", | |
1103 | argv[1], strerror(errno)); | |
1104 | exit(EXIT_FAILURE); | |
1105 | } | |
1106 | ||
1107 | atexit(cleanup); | |
1108 | ||
1109 | /* We need to work out the real full path to our service. | |
1110 | * This works fine, provided that we ONLY allow multiplexed services | |
1111 | * to exist in the same directory as the master link. | |
1112 | * Also, the master link as to be a real file in the init dir. */ | |
1113 | if (!realpath(argv[1], path)) { | |
1114 | fprintf(stderr, "realpath: %s\n", strerror(errno)); | |
1115 | exit(EXIT_FAILURE); | |
1116 | } | |
1117 | memset(lnk, 0, sizeof(lnk)); | |
1118 | if (readlink(argv[1], lnk, sizeof(lnk)-1)) { | |
1119 | dir = dirname(path); | |
1120 | if (strchr(lnk, '/')) { | |
1121 | save = xstrdup(dir); | |
1122 | saveLnk = xstrdup(lnk); | |
1123 | dir = dirname(saveLnk); | |
1124 | if (strcmp(dir, save) == 0) | |
1125 | file = basename_c(argv[1]); | |
1126 | else | |
1127 | file = basename_c(lnk); | |
1128 | dir = save; | |
1129 | } else | |
1130 | file = basename_c(argv[1]); | |
1131 | ll = strlen(dir) + strlen(file) + 2; | |
1132 | service = xmalloc(ll); | |
1133 | snprintf(service, ll, "%s/%s", dir, file); | |
1134 | if (stat(service, &stbuf) != 0) { | |
1135 | free(service); | |
1136 | service = xstrdup(lnk); | |
1137 | } | |
1138 | free(save); | |
1139 | free(saveLnk); | |
1140 | } | |
1141 | if (!service) | |
1142 | service = xstrdup(path); | |
1143 | applet = basename_c(service); | |
1144 | ||
1145 | if (argc < 3) | |
1146 | usage(EXIT_FAILURE); | |
1147 | ||
1148 | /* Change dir to / to ensure all init scripts don't use stuff in pwd */ | |
1149 | if (chdir("/") == -1) | |
1150 | eerror("chdir: %s", strerror(errno)); | |
1151 | ||
1152 | if ((runlevel = xstrdup(getenv("RC_RUNLEVEL"))) == NULL) { | |
1153 | env_filter(); | |
1154 | env_config(); | |
1155 | runlevel = rc_runlevel_get(); | |
1156 | } | |
1157 | ||
1158 | setenv("EINFO_LOG", service, 1); | |
1159 | setenv("RC_SVCNAME", applet, 1); | |
1160 | ||
1161 | /* Set an env var so that we always know our pid regardless of any | |
1162 | subshells the init script may create so that our mark_service_* | |
1163 | functions can always instruct us of this change */ | |
1164 | snprintf(pidstr, sizeof(pidstr), "%d", (int) getpid()); | |
1165 | setenv("RC_RUNSCRIPT_PID", pidstr, 1); | |
1166 | ||
1167 | /* eprefix is kinda klunky, but it works for our purposes */ | |
1168 | if (rc_conf_yesno("rc_parallel")) { | |
1169 | /* Get the longest service name */ | |
1170 | services = rc_services_in_runlevel(NULL); | |
1171 | TAILQ_FOREACH(svc, services, entries) { | |
1172 | ll = strlen(svc->value); | |
1173 | if (ll > l) | |
1174 | l = ll; | |
1175 | } | |
1176 | rc_stringlist_free(services); | |
1177 | services = NULL; | |
1178 | ll = strlen(applet); | |
1179 | if (ll > l) | |
1180 | l = ll; | |
1181 | ||
1182 | /* Make our prefix string */ | |
1183 | prefix = xmalloc(sizeof(char) * l + 1); | |
1184 | ll = strlen(applet); | |
1185 | memcpy(prefix, applet, ll); | |
1186 | memset(prefix + ll, ' ', l - ll); | |
1187 | memset(prefix + l, 0, 1); | |
1188 | eprefix(prefix); | |
1189 | } | |
1190 | ||
1191 | #ifdef HAVE_SELINUX | |
1192 | /* Ok, we are ready to go, so setup selinux if applicable */ | |
1193 | selinux_setup(argc, argv); | |
1194 | #endif | |
1195 | ||
1196 | deps = true; | |
1197 | ||
1198 | /* Punt the first arg as its our service name */ | |
1199 | argc--; | |
1200 | argv++; | |
1201 | ||
1202 | /* Right then, parse any options there may be */ | |
1203 | while ((opt = getopt_long(argc, argv, getoptstring, | |
1204 | longopts, (int *)0)) != -1) | |
1205 | switch (opt) { | |
1206 | case 'd': | |
1207 | setenv("RC_DEBUG", "YES", 1); | |
1208 | break; | |
1209 | case 'l': | |
1210 | exclusive_fd = atoi(optarg); | |
1211 | fcntl(exclusive_fd, F_SETFD, | |
1212 | fcntl(exclusive_fd, F_GETFD, 0) | FD_CLOEXEC); | |
1213 | break; | |
1214 | case 's': | |
1215 | if (!(rc_service_state(service) & RC_SERVICE_STARTED)) | |
1216 | exit(EXIT_FAILURE); | |
1217 | break; | |
1218 | case 'S': | |
1219 | if (!(rc_service_state(service) & RC_SERVICE_STOPPED)) | |
1220 | exit(EXIT_FAILURE); | |
1221 | break; | |
1222 | case 'D': | |
1223 | deps = false; | |
1224 | break; | |
1225 | case 'Z': | |
1226 | dry_run = true; | |
1227 | break; | |
1228 | case_RC_COMMON_GETOPT | |
1229 | } | |
1230 | ||
1231 | /* If we're changing runlevels and not called by rc then we cannot | |
1232 | work with any dependencies */ | |
1233 | if (deps && getenv("RC_PID") == NULL && | |
1234 | (rc_runlevel_starting() || rc_runlevel_stopping())) | |
1235 | deps = false; | |
1236 | ||
1237 | /* Save the IN_BACKGROUND env flag so it's ONLY passed to the service | |
1238 | that is being called and not any dependents */ | |
1239 | if (getenv("IN_BACKGROUND")) { | |
1240 | ibsave = xstrdup(getenv("IN_BACKGROUND")); | |
1241 | in_background = rc_yesno(ibsave); | |
1242 | unsetenv("IN_BACKGROUND"); | |
1243 | } | |
1244 | ||
1245 | if (rc_yesno(getenv("IN_HOTPLUG"))) { | |
1246 | if (!service_plugable()) | |
1247 | eerrorx("%s: not allowed to be hotplugged", applet); | |
1248 | in_background = true; | |
1249 | } | |
1250 | ||
1251 | /* Setup a signal handler */ | |
1252 | signal_setup(SIGHUP, handle_signal); | |
1253 | signal_setup(SIGINT, handle_signal); | |
1254 | signal_setup(SIGQUIT, handle_signal); | |
1255 | signal_setup(SIGTERM, handle_signal); | |
1256 | signal_setup(SIGCHLD, handle_signal); | |
1257 | ||
1258 | /* Load our plugins */ | |
1259 | rc_plugin_load(); | |
1260 | ||
1261 | applet_list = rc_stringlist_new(); | |
1262 | rc_stringlist_add(applet_list, applet); | |
1263 | ||
1264 | /* Now run each option */ | |
1265 | retval = EXIT_SUCCESS; | |
1266 | while (optind < argc) { | |
1267 | optarg = argv[optind++]; | |
1268 | ||
1269 | /* Abort on a sighup here */ | |
1270 | if (sighup) | |
1271 | exit (EXIT_FAILURE); | |
1272 | ||
1273 | /* Export the command we're running. | |
1274 | This is important as we stamp on the restart function now but | |
1275 | some start/stop routines still need to behave differently if | |
1276 | restarting. */ | |
1277 | unsetenv("RC_CMD"); | |
1278 | setenv("RC_CMD", optarg, 1); | |
1279 | ||
1280 | doneone = true; | |
1281 | ||
1282 | if (strcmp(optarg, "describe") == 0 || | |
1283 | strcmp(optarg, "help") == 0 || | |
1284 | strcmp(optarg, "depend") == 0) | |
1285 | { | |
1286 | save = prefix; | |
1287 | eprefix(NULL); | |
1288 | prefix = NULL; | |
1289 | svc_exec(optarg, NULL); | |
1290 | eprefix(save); | |
1291 | prefix = save; | |
1292 | } else if (strcmp(optarg, "ineed") == 0 || | |
1293 | strcmp(optarg, "iuse") == 0 || | |
1294 | strcmp(optarg, "needsme") == 0 || | |
1295 | strcmp(optarg, "usesme") == 0 || | |
1296 | strcmp(optarg, "iafter") == 0 || | |
1297 | strcmp(optarg, "ibefore") == 0 || | |
1298 | strcmp(optarg, "iprovide") == 0) | |
1299 | { | |
1300 | errno = 0; | |
1301 | if (rc_conf_yesno("rc_depend_strict") || | |
1302 | errno == ENOENT) | |
1303 | depoptions |= RC_DEP_STRICT; | |
1304 | ||
1305 | if (!deptree && | |
1306 | ((deptree = _rc_deptree_load(0, NULL)) == NULL)) | |
1307 | eerrorx("failed to load deptree"); | |
1308 | ||
1309 | tmplist = rc_stringlist_new(); | |
1310 | rc_stringlist_add(tmplist, optarg); | |
1311 | services = rc_deptree_depends(deptree, tmplist, | |
1312 | applet_list, | |
1313 | runlevel, depoptions); | |
1314 | rc_stringlist_free(tmplist); | |
1315 | TAILQ_FOREACH(svc, services, entries) | |
1316 | printf("%s ", svc->value); | |
1317 | printf ("\n"); | |
1318 | rc_stringlist_free(services); | |
1319 | services = NULL; | |
1320 | } else if (strcmp (optarg, "status") == 0) { | |
1321 | save = prefix; | |
1322 | eprefix(NULL); | |
1323 | prefix = NULL; | |
1324 | retval = svc_exec("status", NULL); | |
1325 | } else { | |
1326 | if (strcmp(optarg, "conditionalrestart") == 0 || | |
1327 | strcmp(optarg, "condrestart") == 0) | |
1328 | { | |
1329 | if (rc_service_state(service) & | |
1330 | RC_SERVICE_STARTED) | |
1331 | svc_restart(); | |
1332 | } else if (strcmp(optarg, "restart") == 0) { | |
1333 | svc_restart(); | |
1334 | } else if (strcmp(optarg, "start") == 0) { | |
1335 | svc_start(); | |
1336 | } else if (strcmp(optarg, "stop") == 0 || strcmp(optarg, "pause") == 0) { | |
1337 | if (strcmp(optarg, "pause") == 0) { | |
1338 | ewarn("WARNING: 'pause' is deprecated; please use '--nodeps stop'"); | |
1339 | deps = false; | |
1340 | } | |
1341 | if (deps && in_background) | |
1342 | get_started_services(); | |
1343 | if (svc_stop() == 1) | |
1344 | continue; /* Service has been stopped already */ | |
1345 | if (deps) { | |
1346 | if (!in_background && | |
1347 | !rc_runlevel_stopping() && | |
1348 | rc_service_state(service) & | |
1349 | RC_SERVICE_STOPPED) | |
1350 | unhotplug(); | |
1351 | ||
1352 | if (in_background && | |
1353 | rc_service_state(service) & | |
1354 | RC_SERVICE_INACTIVE) | |
1355 | { | |
1356 | TAILQ_FOREACH(svc, | |
1357 | restart_services, | |
1358 | entries) | |
1359 | if (rc_service_state(svc->value) & | |
1360 | RC_SERVICE_STOPPED) | |
1361 | rc_service_schedule_start(service, svc->value); | |
1362 | } | |
1363 | } | |
1364 | } else if (strcmp(optarg, "zap") == 0) { | |
1365 | einfo("Manually resetting %s to stopped state", | |
1366 | applet); | |
1367 | if (!rc_service_mark(applet, | |
1368 | RC_SERVICE_STOPPED)) | |
1369 | eerrorx("rc_service_mark: %s", | |
1370 | strerror(errno)); | |
1371 | unhotplug(); | |
1372 | } else | |
1373 | retval = svc_exec(optarg, NULL); | |
1374 | ||
1375 | /* We should ensure this list is empty after | |
1376 | * an action is done */ | |
1377 | rc_stringlist_free(restart_services); | |
1378 | restart_services = NULL; | |
1379 | } | |
1380 | ||
1381 | if (!doneone) | |
1382 | usage(EXIT_FAILURE); | |
1383 | } | |
1384 | ||
1385 | return retval; | |
1386 | } | |
1387 | ||
1388 | int | |
1389 | runscript(int argc, char **argv) | |
1390 | { | |
1391 | ewarnv("runscript is deprecated; please use openrc-run instead."); | |
1392 | return (openrc_run(argc, argv)); | |
1393 | } |
73 | 73 | |
74 | 74 | #include "builtins.h" |
75 | 75 | #include "einfo.h" |
76 | #include "queue.h" | |
76 | 77 | #include "rc.h" |
77 | 78 | #include "rc-misc.h" |
78 | ||
79 | /* Some libc implementations don't define this */ | |
80 | #ifndef LIST_FOREACH_SAFE | |
81 | #define LIST_FOREACH_SAFE(var, head, field, tvar) \ | |
82 | for ((var) = LIST_FIRST((head)); \ | |
83 | (var) && ((tvar) = LIST_NEXT((var), field), 1); \ | |
84 | (var) = (tvar)) | |
85 | #endif | |
86 | ||
87 | 79 | |
88 | 80 | typedef struct scheduleitem |
89 | 81 | { |
685 | 677 | int tid = 0; |
686 | 678 | char *redirect_stderr = NULL; |
687 | 679 | char *redirect_stdout = NULL; |
680 | int stdin_fd; | |
688 | 681 | int stdout_fd; |
689 | 682 | int stderr_fd; |
690 | 683 | pid_t pid, spid; |
926 | 919 | exec = name; |
927 | 920 | if (name && start) |
928 | 921 | *argv = name; |
929 | } else if (name) | |
922 | } else if (name) { | |
930 | 923 | *--argv = name; |
931 | else if (exec) | |
924 | ++argc; | |
925 | } else if (exec) { | |
932 | 926 | *--argv = exec; |
927 | ++argc; | |
928 | }; | |
933 | 929 | |
934 | 930 | if (stop || sig != -1) { |
935 | 931 | if (sig == -1) |
1082 | 1078 | exit (EXIT_SUCCESS); |
1083 | 1079 | |
1084 | 1080 | einfon("Would start"); |
1085 | while (argc-- >= 0) | |
1081 | while (argc-- > 0) | |
1086 | 1082 | printf(" %s", *argv++); |
1087 | 1083 | printf("\n"); |
1088 | 1084 | eindent(); |
1251 | 1247 | setenv("PATH", newpath, 1); |
1252 | 1248 | } |
1253 | 1249 | |
1250 | stdin_fd = devnull_fd; | |
1254 | 1251 | stdout_fd = devnull_fd; |
1255 | 1252 | stderr_fd = devnull_fd; |
1256 | 1253 | if (redirect_stdout) { |
1270 | 1267 | applet, redirect_stderr, strerror(errno)); |
1271 | 1268 | } |
1272 | 1269 | |
1273 | /* We don't redirect stdin as some daemons may need it */ | |
1270 | if (background) | |
1271 | dup2(stdin_fd, STDIN_FILENO); | |
1274 | 1272 | if (background || redirect_stdout || rc_yesno(getenv("EINFO_QUIET"))) |
1275 | 1273 | dup2(stdout_fd, STDOUT_FILENO); |
1276 | 1274 | if (background || redirect_stderr || rc_yesno(getenv("EINFO_QUIET"))) |