Codebase list openrc / 0ef8014
Merge tag '0.18.3' into debian New upstream release 0.18.3 Benda Xu 8 years ago
124 changed file(s) with 5885 addition(s) and 2442 deletion(s). Raw diff Collapse all Expand all
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
-72
FEATURE-REMOVAL-SCHEDULE less more
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
11 # Copyright (c) 2007-2009 Roy Marples <roy@marples.name>
22 # Released under the 2-clause BSD license.
33
4 include Makefile.inc
4 TOP:= ${dir ${realpath ${firstword ${MAKEFILE_LIST}}}}
5 MK= ${TOP}/mk
6
7 include ${TOP}/Makefile.inc
58
69 SUBDIR= conf.d etc init.d local.d man scripts sh src sysctl.d
710
1619
1720 INSTALLAFTER= _installafter
1821
19 MK= mk
2022 include ${MK}/sys.mk
2123 include ${MK}/os.mk
2224 include ${MK}/subdir.mk
2325 include ${MK}/dist.mk
24 include ${MK}/git.mk
26 include ${MK}/gitver.mk
2527
2628 _installafter:
2729 ifeq (${MKPREFIX},yes)
00 NAME= openrc
1 VERSION= 0.13.1
1 VERSION= 0.18.3
22 PKG= ${NAME}-${VERSION}
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
-94
README less more
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
-31
README.busybox less more
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
-55
README.history less more
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
-85
STYLE less more
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
1414
1515 CONF-FreeBSD= ipfw moused powerd rarpd savecore syscons
1616
17 CONF-Linux= consolefont devfs dmesg hwclock keymaps killprocs modules
17 CONF-Linux= consolefont devfs dmesg hwclock keymaps killprocs modules mtab
1818
1919 CONF-NetBSD= moused rarpd savecore
2020
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="192.168.0.1"
3 #defaultroute6="2001:a:b:c"
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?
11 # LINUX SPECIFIC OPTIONS
22
33 # 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
1213 # If this is commented out, automatic detection will be used.
1314 #
1415 # This should be set to the value representing the environment this file is
6061 # Set the devices controller settings for this service.
6162 #rc_cgroup_devices=""
6263
64 # Set the hugetlb controller settings for this service.
65 #rc_cgroup_hugetlb=""
66
6367 # Set the memory controller settings for this service.
6468 #rc_cgroup_memory=""
6569
70 # Set the net_cls controller settings for this service.
71 #rc_cgroup_net_cls=""
72
6673 # Set the net_prio controller settings for this service.
6774 #rc_cgroup_net_prio=""
75
76 # Set the pids controller settings for this service.
77 #rc_cgroup_pids=""
6878
6979 # Set this to YES if yu want all of the processes in a service's cgroup
7080 # killed when the service is stopped or restarted.
115115 #SSD_NICELEVEL="-19"
116116
117117 # 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
118121 #rc_ulimit="-u 30"
119122
120123 # It's possible to define extra dependencies for services like so
99 trap : SIGINT
1010 trap "echo 'Boot interrupted'; exit 1" SIGQUIT
1111
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
1515
1616 # We don't actually care if rc default worked or not, we should exit 0
1717 # to allow logins
1313 [ -z "$TERM" -o "$TERM" = "dumb" ] && TERM="@TERM@" && export TERM
1414
1515 action=${1:-shutdown}
16 exec /sbin/rc "${action}"
16 exec /sbin/openrc "${action}"
2222 mount-ro
2323 mtab
2424 numlock
25 osclock
2526 procfs
2627 staticroute
2728 sysfs
11
22 DIR= ${INITDIR}
33 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}}
66 BIN= ${OBJS}
77
88 # Are we installing our network scripts?
2020 SRCS-FreeBSD+= adjkerntz.in devd.in dumpon.in encswap.in ipfw.in \
2121 mixer.in nscd.in powerd.in syscons.in
2222
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 \
2424 killprocs.in modules.in mount-ro.in mtab.in numlock.in \
2525 procfs.in sysfs.in termencoding.in tmpfiles.dev.in
2626
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 }
118118 {
119119 [ "$RC_SYS" = VSERVER -o "$RC_SYS" = LXC ] && return 0
120120 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
121135 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
126146 }
127147
128148 start()
192212 if yesno $log_dmesg; then
193213 if $logw || checkpath -W /var/log; then
194214 # 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
199222 fi
200223 fi
201224
77 {
88 need localmount termencoding
99 after hotplug bootmisc
10 keyword -openvz -prefix -uml -vserver -xenu -lxc
10 keyword -openvz -prefix -systemd-nspawn -uml -vserver -xenu -lxc
1111 }
1212
1313 start()
77 {
88 provide dev-mount
99 before dev
10 keyword -prefix -vserver -lxc
10 keyword -prefix -systemd-nspawn -vserver -lxc
1111 }
1212
1313 mount_dev()
6868 # so udev can add its start-message to dmesg
6969 [ -c /dev/kmsg ] || mknod -m 660 /dev/kmsg c 1 11
7070
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
7279 for x in \
7380 "mqueue /dev/mqueue 1777 ,nodev mqueue" \
7481 "devpts /dev/pts 0755 ,gid=5,mode=0620 devpts" \
66 depend()
77 {
88 before dev modules
9 keyword -lxc -prefix -vserver
9 keyword -lxc -prefix -systemd-nspawn -vserver
1010 }
1111
1212 start()
88 depend()
99 {
1010 use dev clock modules
11 keyword -jail -openvz -prefix -timeout -vserver -lxc -uml
11 keyword -jail -openvz -prefix -systemd-nspawn -timeout -vserver -lxc -uml
1212 }
1313
1414 _abort() {
44 description="Sets the hostname of the machine."
55
66 depend() {
7 keyword -prefix -lxc
7 keyword -prefix -systemd-nspawn -lxc
88 }
99
1010 start()
2727 else
2828 before *
2929 fi
30 keyword -openvz -prefix -uml -vserver -xenu -lxc
30 keyword -openvz -prefix -systemd-nspawn -uml -vserver -xenu -lxc
3131 }
3232
3333 setupopts()
77 {
88 need localmount termencoding
99 after bootmisc
10 keyword -openvz -prefix -uml -vserver -xenu -lxc
10 keyword -openvz -prefix -systemd-nspawn -uml -vserver -xenu -lxc
1111 }
1212
1313 start()
1313 {
1414 ebegin "Starting local"
1515
16 local file has_errors=0 retval
16 local file has_errors=0 redirect retval
17 yesno $rc_verbose || redirect='> /dev/null 2>&1'
1718 eindent
1819 for file in @SYSCONFDIR@/local.d/*.start; do
1920 if [ -x "${file}" ]; then
2021 vebegin "Executing \"${file}\""
21 "${file}" 2>&1 >/dev/null
22 eval "${file}" $redirect
2223 retval=$?
2324 if [ ${retval} -ne 0 ]; then
2425 has_errors=1
5152 {
5253 ebegin "Stopping local"
5354
54 local file has_errors=0 retval
55 local file has_errors=0 redirect retval
56 yesno $rc_verbose || redirect='> /dev/null 2>&1'
5557 eindent
5658 for file in @SYSCONFDIR@/local.d/*.stop; do
5759 if [ -x "${file}" ]; then
5860 vebegin "Executing \"${file}\""
59 "${file}" 2>&1 >/dev/null
61 eval "${file}" $redirect
6062 retval=$?
6163 if [ ${retval} -ne 0 ]; then
6264 has_errors=1
88 need fsck
99 use lvm modules mtab
1010 after lvm modules
11 keyword -jail -prefix -vserver -lxc
11 keyword -jail -prefix -systemd-nspawn -vserver -lxc
1212 }
1313
1414 start()
1515 {
1616 # Mount local filesystems in /etc/fstab.
17 local types="noproc" x= no_netdev=
17 local types="noproc" x= no_netdev= rc=
1818 for x in $net_fs_list $extra_net_fs_list; do
1919 types="${types},no${x}"
2020 done
2828 ebegin "Mounting local filesystems"
2929 mount -at "$types" $no_netdev
3030 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
3436 }
3537
3638 stop()
6264
6365 . "$RC_LIBEXECDIR"/sh/rc-mount.sh
6466
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
6594 # Umount loop devices
6695 einfo "Unmounting loop devices"
6796 eindent
55
66 depend()
77 {
8 keyword -jail -prefix -vserver
8 keyword -jail -prefix -systemd-nspawn -vserver
99 }
1010
1111 start()
66 depend()
77 {
88 use isapnp
9 keyword -openvz -prefix -vserver -lxc
9 keyword -openvz -prefix -systemd-nspawn -vserver -lxc
1010 }
1111
1212 start()
66 depend()
77 {
88 need killprocs savecache
9 keyword -openvz -prefix -vserver -lxc
9 keyword -openvz -prefix -systemd-nspawn -vserver -lxc
1010 }
1111
1212 start()
66 depend()
77 {
88 need root
9 keyword -prefix
9 keyword -prefix -systemd-nspawn
1010 }
1111
1212 start()
1313 {
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~~
1635 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
3838 }
11 # Copyright (c) 2007-2009 Roy Marples <roy@marples.name>
22 # Released under the 2-clause BSD license.
33
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."
85
96 depend()
107 {
118 config /etc/fstab
12 use afc-client amd autofs openvpn
9 use afc-client amd nfsclient autofs openvpn
1310 use dns
14 keyword -jail -prefix -vserver -lxc
11 keyword -jail -prefix -systemd-nspawn -vserver -lxc
1512 }
1613
1714 start()
1815 {
1916 local x= fs= rc=
2017 for x in $net_fs_list $extra_net_fs_list; do
21 case "$x" in
22 nfs|nfs4)
23 continue
24 ;;
25 esac
2618 fs="$fs${fs:+,}$x"
2719 done
2820
3426 rc=$?
3527 fi
3628 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
3833 }
3934
4035 stop()
4540 . "$RC_LIBEXECDIR"/sh/rc-mount.sh
4641
4742 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"
5644 done
5745 if [ -n "$fs" ]; then
5846 umount -at $fs || eerror "Failed to simply unmount filesystems"
6149 eindent
6250 fs=
6351 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"
7253 done
7354 [ -n "$fs" ] && fs="^($fs)$"
7455 do_unmount umount ${fs:+--fstype-regex} $fs --netdev
88 depend()
99 {
1010 need localmount
11 keyword -openvz -prefix -vserver -lxc
11 keyword -openvz -prefix -systemd-nspawn -vserver -lxc
1212 }
1313
1414 _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 }
77 {
88 use modules devfs
99 need localmount
10 keyword -openvz -prefix -vserver -lxc
10 keyword -openvz -prefix -systemd-nspawn -vserver -lxc
1111 }
1212
1313 start()
1414 {
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
2215 # Setup Kernel Support for miscellaneous Binary Formats
2316 if [ -d /proc/sys/fs/binfmt_misc -a ! -e /proc/sys/fs/binfmt_misc/register ]; then
17 modprobe -q binfmt-misc
2418 if grep -qs binfmt_misc /proc/filesystems; then
2519 ebegin "Mounting misc binary format filesystem"
2620 mount -t binfmt_misc -o nodev,noexec,nosuid \
2721 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
3822 eend $?
39 fi
4023 fi
4124 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
7125 return 0
7226 }
66 depend()
77 {
88 need fsck
9 keyword -jail -openvz -prefix -vserver -lxc
9 keyword -jail -openvz -prefix -systemd-nspawn -vserver -lxc
1010 }
1111
1212 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 }
66 start()
77 {
88 if [ -e "$RC_SVCDIR"/clock-skewed ]; then
9 ewarn "WARNING: clock skew detected!"
9 ewarn "Clock skew detected!"
1010 if ! yesno "${RC_GOINGDOWN}"; then
1111 eerror "Not saving deptree cache"
1212 return 1
1313 fi
1414 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
1922 return 1
2023 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
2241 fi
2342 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=
3744 for x in deptree depconfig shutdowntime softlevel nettree rc.log; do
3845 [ -e "$RC_SVCDIR/$x" ] && save="$save $RC_SVCDIR/$x"
3946 done
4047 if [ -n "$save" ]; then
41 cp -p $save "$RC_LIBEXECDIR"/cache 2>/dev/null
48 cp -p $save "$RC_LIBEXECDIR"/cache
49 rc=$?
4250 fi
43 rc=$?
4451 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
4656 fi
47 eend $rc
57 eend $rc "Unable to save dependency cache"
4858 }
2222 # Don't quote ${dump_device}, so that if it's unset,
2323 # savecore will check on the partitions listed in fstab
2424 # without errors in the output
25 savecore -C "$dump_dir" $dump_device >/dev/null
25 savecore -C $dump_device >/dev/null
2626 else
2727 ls "$dump_dir"/bsd* > /dev/null 2>&1
2828 fi
44 depend()
55 {
66 before localmount
7 keyword -jail -openvz -prefix -vserver -lxc
7 keyword -jail -openvz -prefix -systemd-nspawn -vserver -lxc
88 }
99
1010 start()
44 depend()
55 {
66 need localmount
7 keyword -jail -openvz -prefix -vserver -lxc
7 keyword -jail -openvz -prefix -systemd-nspawn -vserver -lxc
88 }
99
1010 start()
77 {
88 before *
99 provide clock
10 keyword -openvz -prefix -uml -vserver -xenu -lxc
10 keyword -openvz -prefix -systemd-nspawn -uml -vserver -xenu -lxc
1111 }
1212
1313 # 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 }
44 depend()
55 {
66 before bootmisc logger
7 keyword -prefix -vserver
7 keyword -prefix -systemd-nspawn -vserver
88 }
99
1010 start()
1111 {
12 local quiet
13 yesno $rc_verbose || quiet=-q
14
1215 ebegin "Configuring kernel parameters"
13 sysctl --system
16 sysctl ${quiet} --system
1417 eend $? "Unable to configure some kernel parameters"
1518 }
77
88 depend()
99 {
10 keyword -lxc -prefix -vserver
10 keyword -lxc -prefix -systemd-nspawn -vserver
1111 }
1212
1313 mount_sys()
8181 fi
8282 fi
8383
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
8493 # setup up kernel support for efivarfs
8594 # slightly complicated, as if it's build as a module but NOT yet loaded,
8695 # it will NOT appear in /proc/filesystems yet
106115 mount -n -t cgroup \
107116 -o none,${sysfs_opts},name=openrc,release_agent="$agent" \
108117 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
110119 fi
111120
112121 yesno ${rc_controller_cgroups:-YES} && [ -e /proc/cgroups ] || return 0
113122 while read name hier groups enabled rest; do
114123 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}
116126 mount -n -t cgroup -o ${sysfs_opts},${name} \
117127 ${name} /sys/fs/cgroup/${name}
118128 ;;
128138 restorecon -rF /sys/fs/cgroup >/dev/null 2>&1
129139 eend $?
130140 fi
131
132 return 0
133141 }
134142
135143 start()
136144 {
137 local retval
138145 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
149148 restorecon_sys
150
151 return $retval
149 return 0
152150 }
88
99 depend()
1010 {
11 keyword -lxc -openvz -prefix -uml -vserver -xenu
11 keyword -lxc -openvz -prefix -systemd-nspawn -uml -vserver -xenu
1212 use root
1313 after bootmisc
1414 }
11 # Copyright 1999-2012 Gentoo Foundation
22 # Released under the 2-clause BSD license.
33
4 description="set up tmpfiles.d entries"
4 description="Set up tmpfiles.d entries"
55
66 depend()
77 {
1212
1313 start()
1414 {
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}
1717 eend $?
1818 return 0
1919 }
11 # Copyright 1999-2012 Gentoo Foundation
22 # Released under the 2-clause BSD license.
33
4 description="set up tmpfiles.d entries"
4 description="Set up tmpfiles.d entries"
55
66 depend()
77 {
1010
1111 start()
1212 {
13 ebegin "setting up tmpfiles.d entries"
13 ebegin "Setting up tmpfiles.d entries"
1414 @LIBEXECDIR@/sh/tmpfiles.sh --exclude-prefix=/dev --create --remove --boot \
1515 ${tmpfiles_opts}
1616 eend $?
77 depend()
88 {
99 need localmount
10 keyword -jail -lxc -openvz -prefix
10 keyword -jail -lxc -openvz -prefix -systemd-nspawn
1111 }
1212
1313 save_seed()
0 MK= ../mk
1 include ${MK}/sys.mk
2 include ${MK}/os.mk
3
04 MAN3= einfo.3 \
15 rc_config.3 rc_deptree.3 rc_find_pids.3 rc_plugin_hook.3 \
26 rc_runlevel.3 rc_service.3 rc_stringlist.3
37 MAN8= rc-service.8 rc-status.8 rc-update.8 openrc.8 openrc-run.8 \
48 service.8 start-stop-daemon.8
9
10 ifeq (${OS},Linux)
11 MAN8 += rc-sstat.8
12 endif
513
614 # Handy macro to create symlinks
715 # This does rely on correctly formatting our manpages!
1523 fi; \
1624 done;
1725
18 MK= ../mk
19 include ${MK}/sys.mk
2026 include ${MK}/gitignore.mk
2127
2228 all:
106106 String describing the service.
107107 .It Ar description_$command
108108 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.
109122 .It Ar start_stop_daemon_args
110123 List of arguments passed to start-stop-daemon when starting the daemon.
111124 .It Ar command
113126 .Nm start-stop-daemon
114127 if no start or stop function is defined by the service.
115128 .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 .
117131 .It Ar command_background
118132 Set this to "true", "yes" or "1" (case-insensitive) to force the daemon into
119133 the background. This implies the "--make-pidfile" and "--pidfile" option of
120134 .Xr start-stop-daemon 8
121135 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.
122139 .It Ar pidfile
123140 Pidfile to use for the above defined command.
124141 .It Ar name
125142 Display name used for the above defined command.
143 .It Ar stopsig
144 Signal to send when stopping the daemon.
126145 .It Ar retry
127146 Retry schedule to use when stopping the daemon. It can either be a
128147 timeout in seconds or multiple signal/timeout pairs (like SIGTERM/5).
130149 A list of directories which must exist for the service to start.
131150 .It Ar required_files
132151 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.
133158 .El
134159 .Sh DEPENDENCIES
135160 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>
8686 .Fl s , -stack
8787 option is given then we either add or remove the runlevel from the runlevel.
8888 This allows inheritance of runlevels.
89
89 .Pp
9090 If the
9191 .Fl a, -all
9292 option is given, we remove the service from all runlevels. This is
55
66 .depend: ${SRCS}
77 rm -f .depend
8 ${CC} ${CPPFLAGS} -MM ${SRCS} > .depend
8 ${CC} ${LOCAL_CPPFLAGS} ${CPPFLAGS} -MM ${SRCS} > .depend
99
1010 depend: .depend extra_depend
1111
11 # Copyright (c) 2008 Roy Marples <roy@marples.name>
22 # Released under the 2-clause BSD license.
33
4 GITREF?= HEAD
4 GITREF?= ${VERSION}
55 DISTPREFIX?= ${NAME}-${VERSION}
66 DISTFILE?= ${DISTPREFIX}.tar.bz2
77
88 CLEANFILES+= ${NAME}-*.tar.bz2
9
10 CHANGELOG_LIMIT?= --after="1 year ago"
911
1012 _SNAP_SH= date -u +%Y%m%d%H%M
1113 _SNAP:= $(shell ${_SNAP_SH})
1214 SNAP= ${_SNAP}
1315 SNAPDIR= ${DISTPREFIX}-${SNAP}
1416 SNAPFILE= ${SNAPDIR}.tar.bz2
17
18 changelog:
19 git log ${CHANGELOG_LIMIT} --format=full > ChangeLog
1520
1621 dist:
1722 git archive --prefix=${DISTPREFIX}/ ${GITREF} | bzip2 > ${DISTFILE}
2833 mkdir /tmp/${SNAPDIR}
2934 cp -RPp * /tmp/${SNAPDIR}
3035 (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
3237 tar -cvjpf ${SNAPFILE} -C /tmp ${SNAPDIR}
3338 rm -rf /tmp/${SNAPDIR}
3439 ls -l ${SNAPFILE}
+0
-8
mk/git.mk less more
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}
2020 CLEANFILES+= ${OBJS} ${SOBJS} ${_LIBS} ${SHLIB_LINK}
2121
2222 %.o: %.c
23 ${CC} ${CFLAGS} ${CPPFLAGS} -c $< -o $@
23 ${CC} ${LOCAL_CFLAGS} ${LOCAL_CPPFLAGS} ${CFLAGS} ${CPPFLAGS} -c $< -o $@
2424
2525 %.So: %.c
26 ${CC} ${PICFLAG} -DPIC ${CPPFLAGS} ${CFLAGS} -c $< -o $@
26 ${CC} ${PICFLAG} -DPIC ${LOCAL_CFLAGS} ${LOCAL_CPPFLAGS} ${CPPFLAGS} ${CFLAGS} -c $< -o $@
2727
2828 all: depend ${_LIBS}
2929
3939 @${ECHO} building shared library $@
4040 @rm -f $@ ${SHLIB_LINK}
4141 @ln -fs $@ ${SHLIB_LINK}
42 ${CC} ${CFLAGS} ${LDFLAGS} -shared -Wl,-x \
42 ${CC} ${LOCAL_CFLAGS} ${CFLAGS} ${LOCAL_LDFLAGS} ${LDFLAGS} -shared -Wl,-x \
4343 -o $@ -Wl,-soname,${SONAME} \
4444 ${SOBJS} ${LDADD}
4545
22
33 # Generic definitions
44
5 SFX= .GNU-kFreeBSD.in
6 PKG_PREFIX?= /usr
7
58 CPPFLAGS+= -D_BSD_SOURCE -D_XOPEN_SOURCE=700
69 LIBDL= -Wl,-Bdynamic -ldl
710 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
33 SFX= .Linux.in
44 PKG_PREFIX?= /usr
55
6 CPPFLAGS+= -D_BSD_SOURCE -D_XOPEN_SOURCE=700
6 CPPFLAGS+= -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700
77 LIBDL= -Wl,-Bdynamic -ldl
88
99 ifeq (${MKSELINUX},yes)
1010 CPPFLAGS+= -DHAVE_SELINUX
11 LIBSELINUX= -lselinux
11 LIBSELINUX?= -lselinux
1212 LDADD += $(LIBSELINUX)
13
14 ifneq (${MKPAM},pam)
15 # if using selinux but not pam then we need crypt
16 LIBCRYPT?= -lcrypt
17 LDADD += $(LIBCRYPT)
1318 endif
19
20 endif
21
22 ifeq (${MKAUDIT},yes)
23 LIBAUDIT?= -laudit
24 CPPFLAGS+= -DHAVE_AUDIT
25 LDADD+= ${LIBAUDIT}
26 endif
11 LIBPAM?= -lpam
22 CPPFLAGS+= -DHAVE_PAM
33 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
410
511 PAMDIR?= /etc/pam.d
612 PAMMODE?= 0644
0 # rules to build a library
0 # rules to build a program
11 # based on FreeBSD's bsd.prog.mk
22
33 # Copyright (c) 2008 Roy Marples <roy@marples.name>
2424 all: depend ${PROG}
2525
2626 %.o: %.c
27 ${CC} ${CFLAGS} ${CPPFLAGS} -c $< -o $@
27 ${CC} ${LOCAL_CFLAGS} ${LOCAL_CPPFLAGS} ${CFLAGS} ${CPPFLAGS} -c $< -o $@
2828
2929 ${PROG}: ${SCRIPTS} ${OBJS}
30 ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${OBJS} ${LDADD}
30 ${CC} ${LOCAL_CFLAGS} ${LOCAL_LDFLAGS} ${CFLAGS} ${LDFLAGS} -o $@ ${OBJS} ${LDADD}
3131
3232 clean:
3333 rm -f ${CLEANFILES}
00 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)
23 ifeq ($(LTERMCAP),)
34 LIBTERMCAP?= -lncurses
45 else
56 LIBTERMCAP?= $(LTERMCAP)
67 endif
7 CPPFLAGS+= -DHAVE_TERMCAP
8 CPPFLAGS+= -DHAVE_TERMCAP ${TERMCAP_CFLAGS}
89 LDADD+= ${LIBTERMCAP}
910 else ifeq (${MKTERMCAP},termcap)
1011 LIBTERMCAP?= -ltermcap
3333 # FreeBSD specific stuff
3434 BOOT-FreeBSD+= adjkerntz dumpon syscons
3535
36 BOOT-Linux+= hwclock keymaps modules mtab procfs termencoding tmpfiles.setup
36 BOOT-Linux+= binfmt hwclock keymaps modules mtab procfs termencoding \
37 tmpfiles.setup
3738 SHUTDOWN-Linux= killprocs mount-ro
3839 SYSINIT-Linux= devfs dmesg sysfs tmpfiles.dev
3940
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 MK= ../mk
1 include ${MK}/os.mk
2
03 DIR= ${LIBEXECDIR}/bin
14 BIN= on_ac_power
5 INSTALLAFTER = _installafter
26
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
418 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
00 functions.sh
11 gendepends.sh
22 rc-functions.sh
3 runscript.sh
3 openrc-run.sh
44 cgroup-release-agent.sh
55 init.sh
66 init-early.sh
77 rc-cgroup.sh
88 tmpfiles.sh
99 migrate-to-run.sh
10 binfmt.sh
00 DIR= ${LIBEXECDIR}/sh
11 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}}
55
66 INSTALLAFTER= _installafter
77
1111 SRCS-FreeBSD=
1212 BIN-FreeBSD=
1313
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 \
1717 rc-cgroup.sh
1818
1919 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
00 #!@SHELL@
11 # Copyright (c) 2012 Alexander Vershilov <qnikst@gentoo.org>
22 # Released under the 2-clause BSD license.
3
34 extra_stopped_commands="${extra_stopped_commands} cgroup_cleanup"
5 description_cgroup_cleanup="Kill all processes in the cgroup"
46
57 cgroup_find_path()
68 {
4547 $controller.*)
4648 if [ -n "$name" -a -f "$cgroup/$name" -a -n "$val" ]; then
4749 veinfo "$RC_SVCNAME: Setting $cgroup/$name to $val"
48 echo $val > "$cgroup/$name"
50 printf "%s" "$val" > "$cgroup/$name"
4951 fi
5052 name=$1
5153 val=
5254 ;;
5355 *)
54 val="$val $1"
56 [ -n "$val" ] &&
57 val="$val $1" ||
58 val="$1"
5559 ;;
5660 esac
5761 shift
5862 done
5963 if [ -n "$name" -a -f "$cgroup/$name" -a -n "$val" ]; then
6064 veinfo "$RC_SVCNAME: Setting $cgroup/$name to $val"
61 echo $val > "$cgroup/$name"
65 printf "%s" "$val" > "$cgroup/$name"
6266 fi
6367
6468 if [ -f "$cgroup/tasks" ]; then
6569 veinfo "$RC_SVCNAME: adding to $cgroup/tasks"
66 echo 0 > "$cgroup/tasks"
70 printf "%d" 0 > "$cgroup/tasks"
6771 fi
6872
6973 return 0
7680 # cgroups. But may lead to a problems where that inheriting
7781 # is needed.
7882 for d in /sys/fs/cgroup/* ; do
79 [ -f "${d}"/tasks ] && echo 0 > "${d}"/tasks
83 [ -f "${d}"/tasks ] && printf "%d" 0 > "${d}"/tasks
8084 done
8185
8286 openrc_cgroup=/sys/fs/cgroup/openrc
8387 if [ -d "$openrc_cgroup" ]; then
8488 cgroup="$openrc_cgroup/$RC_SVCNAME"
8589 mkdir -p "$cgroup"
86 [ -f "$cgroup/tasks" ] && echo 0 > "$cgroup/tasks"
90 [ -f "$cgroup/tasks" ] && printf "%d" 0 > "$cgroup/tasks"
8791 fi
8892 }
8993
104108 local devices="${rc_cgroup_devices:-$RC_CGROUP_DEVICES}"
105109 [ -n "$devices" ] && cgroup_set_values devices "$devices"
106110
111 local hugetlb="${rc_cgroup_hugetlb:-$RC_CGROUP_HUGETLB}"
112 [ -n "$hugetlb" ] && cgroup_set_values hugetlb "$hugetlb"
113
107114 local memory="${rc_cgroup_memory:-$RC_CGROUP_MEMORY}"
108115 [ -n "$memory" ] && cgroup_set_values memory "$memory"
109116
117 local net_cls="${rc_cgroup_net_cls:-$RC_CGROUP_NET_CLS}"
118 [ -n "$net_cls" ] && cgroup_set_values net_cls "$net_cls"
119
110120 local net_prio="${rc_cgroup_net_prio:-$RC_CGROUP_NET_PRIO}"
111121 [ -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"
112125
113126 return 0
114127 }
8484 return 1
8585 }
8686
87 # Called from runscript.sh or gendepends.sh
87 # Called from openrc-run.sh or gendepends.sh
8888 _depend() {
8989 depend
9090 local _rc_svcname=$(shell_var "$RC_SVCNAME") _deptype= _depends=
+0
-339
sh/runscript.sh.in less more
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 }
5252 done
5353 }
5454
55 splitpath() {
56 local path=$1
57 while [ -n "$path" ]; do
58 echo $path
59 path=${path%/*}
60 done
61 }
62
5563 _restorecon() {
5664 local path=$1
5765 if [ -x /sbin/restorecon ]; then
58 dryrun_or_real restorecon -F "$path"
66 dryrun_or_real restorecon -F $(splitpath "$path")
5967 fi
6068 }
6169
7987 fi
8088 }
8189
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 }
82101
83102 _f() {
84103 # Create a file if it doesn't exist yet
110129
111130 if [ ! -d "$path" ]; then
112131 dryrun_or_real mkdir -p "$path" 2>/dev/null
132 _restorecon "$path"
113133 dryrun_or_real $CHECKPATH -dq -m "$mode" -o "$uid:$gid" "$path"
114134 fi
115135 }
125145
126146 if [ $CREATE -gt 0 ]; then
127147 dryrun_or_real mkdir -p "$path" 2>/dev/null
148 _restorecon "$path"
128149 dryrun_or_real $CHECKPATH -Dq -m "$mode" -o "$uid:$gid" "$path"
129150 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 "$@"
130158 }
131159
132160 _L() {
233261 FILE=
234262 fragments=
235263 # 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/'
237265 tmpfiles_basenames=''
238266 tmpfiles_d=''
239267 # Build a list of sorted unique basenames
303331 # But IS allowed when globs are expanded for the x/r/R/z/Z types.
304332 while read cmd path mode uid gid age arg; do
305333 LINENUM=$(( LINENUM+1 ))
334 FORCE=0
306335
307336 # Unless we have both command and path, skip this line.
308337 if [ -z "$cmd" -o -z "$path" ]; then
310339 fi
311340
312341 case $cmd in
313 *!) [ "$BOOT" -eq "1" ] || continue; cmd=${cmd%!} ;;
342 \#*) continue ;;
314343 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
315352
316353 # whine about invalid entries
317354 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) ;;
320356 *) warninvalid ; continue ;;
321357 esac
322358
324360 if [ "$mode" = '-' -o "$mode" = '' ]; then
325361 case "$cmd" in
326362 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) ;;
329365 esac
330366 fi
331367
337373
338374 [ -n "$EXCLUDE" ] && checkprefix $path $EXCLUDE && continue
339375 [ -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
340383 [ "$VERBOSE" -eq "1" ] && echo _$cmd "$@"
341384 _$cmd "$@"
342385 rc=$?
4646 #endif
4747
4848 #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
6849
6950 #ifdef __GLIBC__
7051 # 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_ */
33 INCS= einfo.h
44 VERSION_MAP= einfo.map
55
6 CPPFLAGS+= -I../includes
6 LOCAL_CPPFLAGS+= -I../includes
77
88 MK= ../../mk
99 include ${MK}/lib.mk
4747 # endif
4848 #endif
4949
50 __BEGIN_DECLS
50 /* __BEGIN_DECLS */
51 #ifdef __cplusplus
52 extern "C" {
53 #endif
5154
5255 /*! @brief Color types to use */
5356 typedef enum
139142 /*! @brief Prefix each einfo line with something */
140143 void eprefix(const char * EINFO_RESTRICT);
141144
142 __END_DECLS
145 /* __END_DECLS */
146 #ifdef __cplusplus
147 }
143148 #endif
149
150 #endif
66
77 LDADD+= ${LIBKVM}
88
9 CPPFLAGS+= -I../includes
9 LOCAL_CPPFLAGS+= -I../includes
1010
1111 MK= ../../mk
1212 include ${MK}/lib.mk
2727 * SUCH DAMAGE.
2828 */
2929
30 #include "queue.h"
3031 #include "librc.h"
3132
32 #if defined(__linux__) || defined (__GLIBC__)
33 #if defined(__linux__) || (defined (__FreeBSD_kernel__) && defined(__GLIBC__))
3334 static bool
3435 pid_is_exec(pid_t pid, const char *exec)
3536 {
9798 pid_t p;
9899 char buffer[PATH_MAX];
99100 struct stat sb;
100 pid_t runscript_pid = 0;
101 pid_t openrc_pid = 0;
101102 char *pp;
102103 RC_PIDLIST *pids = NULL;
103104 RC_PID *pi;
106107 return NULL;
107108
108109 /*
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
110111 scenario
111112
112113 /etc/init.d/ntpd stop does
116117 nasty
117118 */
118119
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;
122123 }
123124
124125 /*
144145 while ((entry = readdir(procdir)) != NULL) {
145146 if (sscanf(entry->d_name, "%d", &p) != 1)
146147 continue;
147 if (runscript_pid != 0 && runscript_pid == p)
148 if (openrc_pid != 0 && openrc_pid == p)
148149 continue;
149150 if (pid != 0 && pid != p)
150151 continue;
508509 RC_STRINGLIST *list = NULL;
509510 RC_STRING *s;
510511 size_t i;
512 char *ch_root;
513 char *spidfile;
511514
512515 path += snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
513516 basename_c(service));
551554 }
552555 }
553556 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 }
554567
555568 pid = 0;
556569 if (pidfile) {
2929
3030 #include <sys/utsname.h>
3131
32 #include "queue.h"
3233 #include "librc.h"
3334
3435 #define GENDEP RC_LIBEXECDIR "/sh/gendepends.sh"
2727 * SUCH DAMAGE.
2828 */
2929
30 #include "queue.h"
3031 #include "librc.h"
3132
3233 bool
2727 * SUCH DAMAGE.
2828 */
2929
30 #include "queue.h"
3031 #include "librc.h"
3132
3233 RC_STRINGLIST *
2929
3030 const char librc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
3131
32 #include "queue.h"
3233 #include "librc.h"
3334 #ifdef __FreeBSD__
3435 # include <sys/sysctl.h>
99100 continue;
100101 }
101102 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 ||
103106 !S_ISDIR(buf.st_mode))
104107 continue;
105108 }
292295 return RC_SYS_OPENVZ; /* old test */
293296 else if (file_regex("/proc/1/environ", "container=lxc"))
294297 return RC_SYS_LXC;
298 else if (file_regex("/proc/1/environ", "container=systemd-nspawn"))
299 return RC_SYS_SYSTEMD_NSPAWN;
295300 #endif
296301
297302 return NULL;
5656 #include <time.h>
5757 #include <unistd.h>
5858
59 #ifdef BSD
59 #if defined(BSD) && !defined(__GNU__)
6060 #include <sys/param.h>
6161 #include <sys/user.h>
6262 #include <sys/sysctl.h>
6363 #include <kvm.h>
64 #else
65 #include <sys/param.h>
6466 #endif
6567
6668 #include "rc.h"
2626 #define __RC_H__
2727
2828 #include <sys/types.h>
29 #include <sys/queue.h>
3029 #include <stdbool.h>
3130 #include <stdio.h>
3231
33 __BEGIN_DECLS
32 /* __BEGIN_DECLS */
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
3436
3537 #define RC_PREFIX "@PREFIX@"
3638 #define RC_SYSCONFDIR "@SYSCONFDIR@"
3840 #define RC_LIBEXECDIR "@LIBEXECDIR@"
3941 #if defined(PREFIX)
4042 #define RC_SVCDIR RC_LIBEXECDIR "/init.d"
41 #elif defined(__linux__)
43 #elif defined(__linux__) || (defined(__FreeBSD_kernel__) && \
44 defined(__GLIBC__)) || defined(__GNU__)
4245 #define RC_SVCDIR "/run/openrc"
4346 #else
4447 #define RC_SVCDIR RC_LIBEXECDIR "/init.d"
7275 # define RC_LOCAL_INITDIR RC_LOCAL_PREFIX "/etc/init.d"
7376 # define RC_LOCAL_CONFDIR RC_LOCAL_PREFIX "/etc/conf.d"
7477 #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_ */
75123
76124 /* A doubly linked list using queue(3) for ease of use */
77125 typedef struct rc_string {
283331 #define RC_SYS_OPENVZ "OPENVZ"
284332 #define RC_SYS_LXC "LXC"
285333 #define RC_SYS_PREFIX "PREFIX"
334 #define RC_SYS_SYSTEMD_NSPAWN "SYSTEMD-NSPAWN"
286335 #define RC_SYS_UML "UML"
287336 #define RC_SYS_VSERVER "VSERVER"
288337 #define RC_SYS_XEN0 "XEN0"
562611 * we have our own */
563612 ssize_t rc_getline(char **, size_t *, FILE *);
564613
565 __END_DECLS
614 /* __END_DECLS */
615 #ifdef __cplusplus
616 }
566617 #endif
618
619 #endif
00 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 \
22 rc-applets.c rc-depend.c rc-logger.c \
33 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
55
66 ifeq (${MKSELINUX},yes)
77 SRCS+= rc-selinux.c
3434 ALL_LINKS= ${BINLINKS} ${SBINLINKS} ${RC_BINLINKS} ${RC_SBINLINKS}
3535 CLEANFILES+= ${ALL_LINKS}
3636
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
3939 LDADD+= -lutil -lrc -leinfo
4040
4141 include ../../Makefile.inc
4242 MK= ../../mk
4343 include ${MK}/prog.mk
44 include ${MK}/git.mk
44 include ${MK}/gitver.mk
4545 include ${MK}/cc.mk
4646
4747 include ${MK}/termcap.mk
2222 * SUCH DAMAGE.
2323 */
2424
25 #include "queue.h"
2526 #include "rc.h"
2627
2728 int checkpath(int, char **);
4444 #include "builtins.h"
4545 #include "einfo.h"
4646 #include "rc-misc.h"
47
48 #ifdef HAVE_SELINUX
4947 #include "rc-selinux.h"
50 #endif
5148
5249 typedef enum {
5350 inode_unknown = 0,
6764 int u;
6865
6966 memset(&st, 0, sizeof(st));
70 if (stat(path, &st) || trunc) {
67 if (lstat(path, &st) || trunc) {
7168 if (type == inode_file) {
7269 einfo("%s: creating file", path);
7370 if (!mode) /* 664 */
132129 }
133130
134131 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 }
135140 einfo("%s: correcting mode", path);
136141 if (chmod(path, mode)) {
137142 eerror("%s: chmod: %s", applet, strerror(errno));
140145 }
141146
142147 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 }
143156 einfo("%s: correcting owner", path);
144157 if (chown(path, uid, gid)) {
145158 eerror("%s: chown: %s", applet, strerror(errno));
147160 }
148161 }
149162
150 #ifdef HAVE_SELINUX
151163 if (selinux_on)
152164 selinux_util_label(path);
153 #endif
154165
155166 return 0;
156167 }
279290 if (gr)
280291 gid = gr->gr_gid;
281292
282 #ifdef HAVE_SELINUX
283293 if (selinux_util_open() == 1)
284294 selinux_on = true;
285 #endif
286295
287296 while (optind < argc) {
288297 if (writable)
292301 optind++;
293302 }
294303
295 #ifdef HAVE_SELINUX
296304 if (selinux_on)
297305 selinux_util_close();
298 #endif
299306
300307 return retval;
301308 }
6969
7070 #include "builtins.h"
7171 #include "einfo.h"
72 #include "queue.h"
7273 #include "rc.h"
7374 #include "rc-misc.h"
7475
3434 # include <sys/ucred.h>
3535 # include <sys/mount.h>
3636 # define F_FLAGS f_flags
37 #elif defined(BSD)
37 #elif defined(BSD) && !defined(__GNU__)
3838 # include <sys/statvfs.h>
3939 # define statfs statvfs
4040 # define F_FLAGS f_flag
41 #elif defined (__linux__) || defined (__GLIBC__)
41 #elif defined (__linux__) || (defined(__FreeBSD_kernel__) && \
42 defined(__GLIBC__)) || defined(__GNU__)
4243 # include <mntent.h>
4344 #endif
4445
5253
5354 #include "builtins.h"
5455 #include "einfo.h"
56 #include "queue.h"
5557 #include "rc.h"
5658 #include "rc-misc.h"
5759
167169 return -1;
168170 }
169171
170 #ifdef BSD
172 #if defined(BSD) && !defined(__GNU__)
171173
172174 /* Translate the mounted options to english
173175 * This is taken directly from FreeBSD mount.c */
264266 return list;
265267 }
266268
267 #elif defined (__linux__) || defined (__GLIBC__)
269 #elif defined (__linux__) || (defined (__FreeBSD_kernel__) && \
270 defined(__GLIBC__))
268271 static struct mntent *
269272 getmntfile(const char *file)
270273 {
294297 int netdev;
295298 RC_STRINGLIST *list;
296299
297 if ((fp = fopen("/proc/mounts", "r")) == NULL)
300 if ((fp = fopen("/proc/self/mounts", "r")) == NULL)
298301 eerrorx("getmntinfo: %s", strerror(errno));
299302
300303 list = rc_stringlist_new();
311314 if ((ent = getmntfile(to))) {
312315 if (strstr(ent->mnt_opts, "_netdev"))
313316 netdev = 0;
317 else
318 netdev = 1;
314319 }
315320
316321 process_mount(list, args, from, to, fst, opts, netdev);
343348
344349 #include "_usage.h"
345350 #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
347352 static const struct option longopts[] = {
348353 { "fstype-regex", 1, NULL, 'f'},
349354 { "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 }
328328 bool ok = false;
329329 char *svcname = getenv("RC_SVCNAME");
330330 char *service = NULL;
331 char *runscript_pid;
331 char *openrc_pid;
332332 /* char *mtime; */
333333 pid_t pid;
334334 RC_SERVICE bit;
349349 eerrorx("%s: unknown applet", applet);
350350
351351 /* 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 */
353353 /*
354354 * FIXME: svcname and service are almost always equal except called from a
355355 * shell with just argv[1] - So that doesn't seem to do what Roy initially
358358 * openrc@gentoo.org).
359359 */
360360 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)
363363 if (kill(pid, SIGHUP) != 0)
364364 eerror("%s: failed to signal parent %d: %s",
365365 applet, pid, strerror(errno));
368368 in control as well */
369369 /*
370370 l = strlen(RC_SVCDIR "/exclusive") + strlen(svcname) +
371 strlen(runscript_pid) + 4;
371 strlen(openrc_pid) + 4;
372372 mtime = xmalloc(l);
373373 snprintf(mtime, l, RC_SVCDIR "/exclusive/%s.%s",
374 svcname, runscript_pid);
374 svcname, openrc_pid);
375375 if (exists(mtime) && unlink(mtime) != 0)
376376 eerror("%s: unlink: %s", applet, strerror(errno));
377377 free(mtime);
4545
4646 #include "builtins.h"
4747 #include "einfo.h"
48 #include "queue.h"
4849 #include "rc.h"
4950 #include "rc-misc.h"
5051
4343 #include <time.h>
4444 #include <unistd.h>
4545
46 #if defined(__linux__) || defined(__GLIBC__)
46 #if defined(__linux__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
4747 # include <pty.h>
4848 #elif defined(__NetBSD__) || defined(__OpenBSD__)
4949 # include <util.h>
5353
5454 #include "einfo.h"
5555 #include "rc-logger.h"
56 #include "queue.h"
5657 #include "rc.h"
5758 #include "rc-misc.h"
5859
4646 #include <unistd.h>
4747
4848 #include "einfo.h"
49 #include "queue.h"
4950 #include "rc.h"
5051 #include "rc-misc.h"
5152 #include "version.h"
6465 "LC_MONETARY", "LC_MESSAGES", "LC_PAPER", "LC_NAME", "LC_ADDRESS",
6566 "LC_TELEPHONE", "LC_MEASUREMENT", "LC_IDENTIFICATION", "LC_ALL",
6667 "IN_HOTPLUG", "IN_BACKGROUND", "RC_INTERFACE_KEEP_CONFIG",
68 "EERROR_QUIET", "EINFO_QUIET",
6769 NULL
6870 };
6971
4242 #include <unistd.h>
4343
4444 #include "einfo.h"
45 #include "queue.h"
4546 #include "rc.h"
4647 #include "rc-misc.h"
4748 #include "rc-plugin.h"
00 /*
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 */
44
55 /*
66 * Copyright (c) 2014 Jason Zaman <jason@perfinion.com>
3030 #include <stddef.h>
3131 #include <errno.h>
3232 #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>
3537
3638 #include <selinux/selinux.h>
3739 #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>
3845
3946 #include "einfo.h"
47 #include "queue.h"
4048 #include "rc.h"
4149 #include "rc-misc.h"
4250 #include "rc-plugin.h"
4351 #include "rc-selinux.h"
4452
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 */
5075 static struct selabel_handle *hnd = NULL;
5176
5277 int selinux_util_label(const char *path)
131156 return 0;
132157 }
133158
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) {
139324 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 }
2525 #ifndef RC_SELINUX_UTIL_H
2626 #define RC_SELINUX_UTIL_H
2727
28 #ifdef HAVE_SELINUX
29
2830 int selinux_util_open(void);
2931 int selinux_util_label(const char *path);
3032 int selinux_util_close(void);
3133
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)
3344
3445 #endif
46
47
48 #endif
3535
3636 #include "builtins.h"
3737 #include "einfo.h"
38 #include "queue.h"
3839 #include "rc.h"
3940 #include "rc-misc.h"
4041
5657 };
5758 static const char * const longopts_help[] = {
5859 "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",
6061 "list all available services",
6162 "resolve the service name to an init script",
6263 longopts_help_COMMON
3535
3636 #include "builtins.h"
3737 #include "einfo.h"
38 #include "queue.h"
3839 #include "rc.h"
3940 #include "rc-misc.h"
4041
3838
3939 #include "builtins.h"
4040 #include "einfo.h"
41 #include "queue.h"
4142 #include "rc.h"
4243 #include "rc-misc.h"
4344
5959
6060 #include "builtins.h"
6161 #include "einfo.h"
62 #include "queue.h"
6263 #include "rc.h"
6364 #include "rc-logger.h"
6465 #include "rc-misc.h"
517518 }
518519
519520 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,
521522 const RC_STRINGLIST *stop_services, const RC_DEPTREE *deptree,
522523 const char *newlevel, bool parallel, bool going_down)
523524 {
+0
-1394
src/rc/runscript.c less more
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 }
7373
7474 #include "builtins.h"
7575 #include "einfo.h"
76 #include "queue.h"
7677 #include "rc.h"
7778 #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
8779
8880 typedef struct scheduleitem
8981 {
685677 int tid = 0;
686678 char *redirect_stderr = NULL;
687679 char *redirect_stdout = NULL;
680 int stdin_fd;
688681 int stdout_fd;
689682 int stderr_fd;
690683 pid_t pid, spid;
926919 exec = name;
927920 if (name && start)
928921 *argv = name;
929 } else if (name)
922 } else if (name) {
930923 *--argv = name;
931 else if (exec)
924 ++argc;
925 } else if (exec) {
932926 *--argv = exec;
927 ++argc;
928 };
933929
934930 if (stop || sig != -1) {
935931 if (sig == -1)
10821078 exit (EXIT_SUCCESS);
10831079
10841080 einfon("Would start");
1085 while (argc-- >= 0)
1081 while (argc-- > 0)
10861082 printf(" %s", *argv++);
10871083 printf("\n");
10881084 eindent();
12511247 setenv("PATH", newpath, 1);
12521248 }
12531249
1250 stdin_fd = devnull_fd;
12541251 stdout_fd = devnull_fd;
12551252 stderr_fd = devnull_fd;
12561253 if (redirect_stdout) {
12701267 applet, redirect_stderr, strerror(errno));
12711268 }
12721269
1273 /* We don't redirect stdin as some daemons may need it */
1270 if (background)
1271 dup2(stdin_fd, STDIN_FILENO);
12741272 if (background || redirect_stdout || rc_yesno(getenv("EINFO_QUIET")))
12751273 dup2(stdout_fd, STDOUT_FILENO);
12761274 if (background || redirect_stderr || rc_yesno(getenv("EINFO_QUIET")))