mirror of
https://github.com/troglobit/finit.git
synced 2026-10-12 10:12:32 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d15e28ea6b | ||
|
|
836bfff08b | ||
|
|
59152b557c | ||
|
|
293b0ffa79 | ||
|
|
d5d9cd5645 | ||
|
|
2f281665af | ||
|
|
b00e7394f8 | ||
|
|
d5a5fffa52 | ||
|
|
4d24c34b28 | ||
|
|
355265651e | ||
|
|
41093df2a9 | ||
|
|
0a816d1fa4 | ||
|
|
3bfc0f0fca | ||
|
|
0aa6ee895c | ||
|
|
b1526fb2d6 | ||
|
|
b2624ac160 | ||
|
|
2c340f83ce | ||
|
|
337ee003bb | ||
|
|
791df0c986 | ||
|
|
f29e92be21 | ||
|
|
379a63fce4 | ||
|
|
b1f9a11809 | ||
|
|
2d9c63e48e | ||
|
|
d66455496a | ||
|
|
77cf72cb40 | ||
|
|
6cc587068b | ||
|
|
cc96e8908a | ||
|
|
adb25d52cd | ||
|
|
7d09567ec8 | ||
|
|
9130af1c77 | ||
|
|
cbea83b369 | ||
|
|
42cd8d284b | ||
|
|
72ebc92622 | ||
|
|
06adecaaea | ||
|
|
efc0592961 | ||
|
|
ed88469276 | ||
|
|
cbf96a1de0 | ||
|
|
cc979f27f1 | ||
|
|
fca5ce57ea | ||
|
|
53aa195ad5 | ||
|
|
e60211168e | ||
|
|
dc3ee9e467 | ||
|
|
6918f3b711 | ||
|
|
66020f48ea | ||
|
|
47b0d4cccf | ||
|
|
92c2efa655 | ||
|
|
b69aa8a8bd | ||
|
|
ca90bbfb04 | ||
|
|
0b5c555c7f | ||
|
|
6443995fc9 | ||
|
|
180faf8a40 | ||
|
|
0ebdd32f6b | ||
|
|
60bf858302 | ||
|
|
7c86b40190 | ||
|
|
4f3f140a09 | ||
|
|
10c24b1674 | ||
|
|
2b4f89ecd1 | ||
|
|
c42a6f2869 | ||
|
|
89bb609a7e | ||
|
|
da6298aecd | ||
|
|
576318cc29 | ||
|
|
0d7d331ad4 | ||
|
|
c886ecb5cc | ||
|
|
304a096877 | ||
|
|
064c7682fc | ||
|
|
58239b897b | ||
|
|
5281d82e80 | ||
|
|
5ff28c4dc6 | ||
|
|
f2218836af | ||
|
|
fbb3779d17 | ||
|
|
68f44f7a97 | ||
|
|
50e587f447 | ||
|
|
fb4c560196 | ||
|
|
8b5fa5eeaa | ||
|
|
88ec21e9cc | ||
|
|
84adec4006 | ||
|
|
19b2b2a279 | ||
|
|
e4163b7221 | ||
|
|
eaef302420 | ||
|
|
d5738da307 | ||
|
|
c9f930c7ad | ||
|
|
e2ee372b5d | ||
|
|
7ff7f93364 | ||
|
|
d5a95760ef | ||
|
|
24d1425b74 | ||
|
|
43d9e25ba7 | ||
|
|
f27998ae4f | ||
|
|
c8e0b6b9ef | ||
|
|
f7e8fccb2f | ||
|
|
7bbccb1213 | ||
|
|
d38c333e04 | ||
|
|
095f6b645c | ||
|
|
b4d10cbade | ||
|
|
5d703fd39e | ||
|
|
eaaf8d862e | ||
|
|
2468f11cd8 | ||
|
|
f8a6a119ac | ||
|
|
1889b88aab | ||
|
|
0d70023bfe | ||
|
|
41648a073b | ||
|
|
33cee0ba5f | ||
|
|
2235fb8352 | ||
|
|
eb9e94935e | ||
|
|
fb230f2137 | ||
|
|
6aa48a8b32 | ||
|
|
5b9cebbfd3 | ||
|
|
38791616e0 | ||
|
|
fede3fd2e1 | ||
|
|
a46a33238d | ||
|
|
afe0488bf2 | ||
|
|
ec5e42694d | ||
|
|
2e73563eea | ||
|
|
338521a748 | ||
|
|
6ae1083c99 | ||
|
|
846806747b | ||
|
|
8904ca993e | ||
|
|
efed0db16b | ||
|
|
11946f12d3 | ||
|
|
2ba359ed80 | ||
|
|
fafd524701 | ||
|
|
1ee6c9f46b | ||
|
|
a88eb82a68 | ||
|
|
a436a1c8cb | ||
|
|
7cb91854b0 | ||
|
|
939ae02a6a | ||
|
|
480d29175c | ||
|
|
ea68413512 | ||
|
|
4edfa9859e | ||
|
|
eb6291c943 | ||
|
|
756b7c3fb6 | ||
|
|
263aec292a | ||
|
|
5a946a4ea7 | ||
|
|
c90b4d797b | ||
|
|
6e7a2fb6d5 | ||
|
|
ddedcf77e8 | ||
|
|
924ec2ef80 | ||
|
|
a49f27c191 | ||
|
|
b41b4ce989 | ||
|
|
3d74e93fa2 | ||
|
|
443700a88e | ||
|
|
4701edef4c | ||
|
|
e6da0a22e7 | ||
|
|
7be2bbbc30 | ||
|
|
3e269c632f | ||
|
|
f2507d9fd7 | ||
|
|
e9f403bceb | ||
|
|
c03176c42a | ||
|
|
9707bfb103 | ||
|
|
11430f83c8 | ||
|
|
a22a794f55 | ||
|
|
5556501287 | ||
|
|
ab554568b2 | ||
|
|
b39a4498a3 | ||
|
|
dead2444e2 | ||
|
|
a58002588e | ||
|
|
28e101aaae | ||
|
|
6da8af8136 | ||
|
|
3069e753e1 | ||
|
|
aafd5c1010 | ||
|
|
2f51c8ea0d | ||
|
|
d1130473fc | ||
|
|
b682a5e4fe | ||
|
|
1fc0f36c6c | ||
|
|
5df5b22327 | ||
|
|
4153c7966d | ||
|
|
458d68533f | ||
|
|
63b5db38df | ||
|
|
2135639508 | ||
|
|
9c8cd6c024 | ||
|
|
450f498061 | ||
|
|
5769500afe | ||
|
|
dc61969164 | ||
|
|
6f0d448765 | ||
|
|
0c9b7a67e0 | ||
|
|
5db2fb2c32 | ||
|
|
f4d3ec1a9f | ||
|
|
51befb492c | ||
|
|
7850378e15 | ||
|
|
438d6b4e63 | ||
|
|
712f68f9da | ||
|
|
8a32ec5c92 | ||
|
|
081622a085 | ||
|
|
2526431d8e | ||
|
|
47d8a83668 | ||
|
|
f72f3febf9 | ||
|
|
138546d008 | ||
|
|
cee244d151 | ||
|
|
7af4ad5c24 | ||
|
|
c0d3705ed5 | ||
|
|
5cf2b9a283 | ||
|
|
0e898da6e5 | ||
|
|
d9f13a1e50 | ||
|
|
4fbcd1bbad | ||
|
|
b6c5498f43 | ||
|
|
9a6c68c952 | ||
|
|
e8170e1216 | ||
|
|
059a4c8a86 | ||
|
|
0de9db68a3 | ||
|
|
aeff68b598 | ||
|
|
700c32fd73 | ||
|
|
334d4a708a | ||
|
|
4d472273e1 | ||
|
|
13f1359b3a | ||
|
|
2e5b97c8b2 | ||
|
|
9a962c86c8 | ||
|
|
f954a4cb92 | ||
|
|
feb97bc77c | ||
|
|
e00fda5dc3 | ||
|
|
80191f2fd5 | ||
|
|
42ef3d3cf7 | ||
|
|
1f4acb322a | ||
|
|
c3ba15045b | ||
|
|
8f1d1717f8 | ||
|
|
7703d00e82 | ||
|
|
3bb826b22b | ||
|
|
9ee2be121f | ||
|
|
36c6aa73aa | ||
|
|
13dddb6912 | ||
|
|
bdaf3370d4 | ||
|
|
a24077c4af | ||
|
|
414a49d733 | ||
|
|
be9d54561d | ||
|
|
3ce5a2a965 | ||
|
|
1d03e9aa8b | ||
|
|
5340e47e81 | ||
|
|
98bbf4a1e5 | ||
|
|
d70e2f1ed0 | ||
|
|
ecb5949679 | ||
|
|
e55fd19091 | ||
|
|
19c64e323c | ||
|
|
9354221bdd | ||
|
|
1d7048d3ae | ||
|
|
8251d713e0 | ||
|
|
44d0d87ad3 | ||
|
|
571250a9b9 | ||
|
|
91540fd793 | ||
|
|
2566e00ef0 | ||
|
|
1e5ce38928 | ||
|
|
c679b0a93d | ||
|
|
c4dcf568c8 | ||
|
|
b65773d508 | ||
|
|
e75c1792aa | ||
|
|
0be4838e01 | ||
|
|
b71605c819 | ||
|
|
3bb2eb2a8d | ||
|
|
8ce35771c3 | ||
|
|
67e80ea989 | ||
|
|
f4d8ecfb5b | ||
|
|
2eb3ebb404 | ||
|
|
1e1b3564dd | ||
|
|
7af257cccf | ||
|
|
84ddac65e5 | ||
|
|
62d6b56fd3 | ||
|
|
fa71f97dcf | ||
|
|
ed383eaaa6 | ||
|
|
9cb6a54493 | ||
|
|
f796d59f77 | ||
|
|
97ca450966 | ||
|
|
e0c1c08e68 | ||
|
|
c81b722691 | ||
|
|
11da93b759 | ||
|
|
28a90a793d | ||
|
|
56a89db889 | ||
|
|
a613ee908f | ||
|
|
d3f58b5df0 | ||
|
|
af88b10322 | ||
|
|
966ae9fb0d | ||
|
|
a69cef0a11 | ||
|
|
b396a018c5 | ||
|
|
a4af9ba248 | ||
|
|
6942e38413 | ||
|
|
e03bd093b5 | ||
|
|
d6070a0d10 | ||
|
|
bd4efb59ca | ||
|
|
a90cfd4a75 | ||
|
|
ab5a983bf7 | ||
|
|
f7bacf8b1b | ||
|
|
d363501e21 | ||
|
|
4150fdfe59 | ||
|
|
4d2b97e4cc | ||
|
|
21eda9dd1c | ||
|
|
4f7e726a3e | ||
|
|
74fc16b832 | ||
|
|
7393072120 | ||
|
|
96bb3f5c6c | ||
|
|
c23a867485 | ||
|
|
4f8a5a6531 | ||
|
|
48e1a0b17f | ||
|
|
9c727ed08d | ||
|
|
49cd3a441d | ||
|
|
8b9258aa73 | ||
|
|
82c6e4680f | ||
|
|
a67b2ba9a7 | ||
|
|
a96edf0291 | ||
|
|
c26dded49c | ||
|
|
3bd15a53d6 | ||
|
|
f0a888c0d1 | ||
|
|
b6769356b2 | ||
|
|
5a9cafc2fc | ||
|
|
2e36590bbd | ||
|
|
33e504b928 | ||
|
|
6a4f197cc0 | ||
|
|
4894580e8b | ||
|
|
70997fb4c5 | ||
|
|
e9515971ea | ||
|
|
82dfa002ff | ||
|
|
a664fd7192 | ||
|
|
b62ee0ef6d | ||
|
|
0cfd867816 | ||
|
|
934a4db7d5 | ||
|
|
c9fe9afa61 | ||
|
|
320e91653b | ||
|
|
859d215ca4 | ||
|
|
0a94f3f303 | ||
|
|
e83a26b256 | ||
|
|
2508495b8c | ||
|
|
3ef52d9324 | ||
|
|
05b72281e6 | ||
|
|
a47abfdc16 | ||
|
|
2c9265f8c8 | ||
|
|
56cb6f8613 | ||
|
|
3dd56ed8af | ||
|
|
fddeeb683c | ||
|
|
25835b0edf | ||
|
|
27fcfada66 | ||
|
|
2dd5fb0f77 | ||
|
|
63044a4b81 | ||
|
|
4e74f9783a | ||
|
|
c3c662fe64 | ||
|
|
7c2764790c | ||
|
|
732d500cf5 | ||
|
|
4e1ac726ac | ||
|
|
fba58085c6 | ||
|
|
d1ebb255c6 | ||
|
|
a39ee0b44d | ||
|
|
947d91acd5 | ||
|
|
8c206d52e5 | ||
|
|
0f445dc9f4 | ||
|
|
c71b35e61a | ||
|
|
d20308b7d7 | ||
|
|
e4e54a88d9 | ||
|
|
308b7c5197 | ||
|
|
89772bf6c0 | ||
|
|
077002e647 | ||
|
|
988cdf9878 | ||
|
|
97db2078f5 | ||
|
|
02a110e6c2 | ||
|
|
681ef8de6f | ||
|
|
0147e0e64f | ||
|
|
311c6be9aa | ||
|
|
c22d123ab0 | ||
|
|
96b5991355 | ||
|
|
06bd352863 | ||
|
|
a918f7497a | ||
|
|
8bbae3d414 | ||
|
|
bfd1f36fdd | ||
|
|
6fc702a560 | ||
|
|
40dcc5541b | ||
|
|
5b41c6e327 | ||
|
|
4bd81b4d4c | ||
|
|
c29589c2ca | ||
|
|
73b89430e4 | ||
|
|
2a62fa3d85 | ||
|
|
4542fdb5bb | ||
|
|
525aaf1f66 | ||
|
|
910dac5f3a | ||
|
|
2a5c319084 | ||
|
|
612f4fe288 | ||
|
|
c058c05651 | ||
|
|
0de4578e50 | ||
|
|
b9e94e4695 | ||
|
|
9887003b25 | ||
|
|
f6bfbc86e9 | ||
|
|
4c90b51d80 | ||
|
|
48cfbfe5ed | ||
|
|
f98be8540f | ||
|
|
17c69fef3d | ||
|
|
c586204fc1 | ||
|
|
ff5e3219be | ||
|
|
07c52f1566 | ||
|
|
0e04ffd68f | ||
|
|
8b5435908c | ||
|
|
3a74310aa6 | ||
|
|
180859a429 | ||
|
|
1d92819d92 | ||
|
|
cfa871c548 | ||
|
|
685e0a80a4 | ||
|
|
19847d2997 | ||
|
|
7108b0e789 | ||
|
|
7eac0b0341 | ||
|
|
33ec4e7d19 | ||
|
|
1b78f2b364 | ||
|
|
119363ff75 | ||
|
|
f89b508c01 | ||
|
|
dda8c7c3ac | ||
|
|
e2d9aab70d | ||
|
|
3df154b798 | ||
|
|
3d9cbaf040 | ||
|
|
70c2939596 | ||
|
|
d4ee44e27f | ||
|
|
0498326962 | ||
|
|
c84ababbd4 | ||
|
|
67ea42c87b | ||
|
|
a2ab45cad7 | ||
|
|
f3fcca6150 | ||
|
|
2b65d8f1e9 | ||
|
|
7c2abf69c4 | ||
|
|
457c0a246f | ||
|
|
1a439baf68 | ||
|
|
68ce78b3fe | ||
|
|
72e27e99e5 | ||
|
|
a436382886 | ||
|
|
6bbfc7b1f1 | ||
|
|
006dd12b09 | ||
|
|
d3a0631390 | ||
|
|
9046b6fe2b | ||
|
|
f217794773 | ||
|
|
11e02fabb3 | ||
|
|
8b9bb1c7ce | ||
|
|
2a7abf1db0 | ||
|
|
34b8c5a3ba | ||
|
|
8e056422fc | ||
|
|
94e8b185b4 | ||
|
|
996d3960e1 | ||
|
|
3b19734f63 | ||
|
|
64e7c0cd9e | ||
|
|
4d0c88bd7a | ||
|
|
9e8c601507 | ||
|
|
b26104466a | ||
|
|
bd25bf65ce | ||
|
|
edd3b41adf | ||
|
|
28ca3fcc5c | ||
|
|
3b601d0115 | ||
|
|
1ef9a9f128 | ||
|
|
d612a86c3b | ||
|
|
5d3cd05202 | ||
|
|
726f7ba229 | ||
|
|
61dab8bd75 | ||
|
|
a7e81f45c6 | ||
|
|
be4062f019 | ||
|
|
035f06e137 | ||
|
|
2f91ab5eac | ||
|
|
f6b5b0260b | ||
|
|
bb9bd7e0b0 | ||
|
|
287abd5c7c | ||
|
|
d27f114742 | ||
|
|
505c370898 | ||
|
|
f26009ec3e | ||
|
|
8425bc313b | ||
|
|
f4d3cf2835 | ||
|
|
bd5cf7c9eb | ||
|
|
4709394ae6 | ||
|
|
729002ef82 | ||
|
|
58b075dbf2 | ||
|
|
d679840fa3 | ||
|
|
0e70bdbf6a | ||
|
|
d810ac00bc | ||
|
|
5f74adad06 | ||
|
|
585ac51f45 | ||
|
|
ce36797506 | ||
|
|
a61c2ceb79 | ||
|
|
383339dc4a | ||
|
|
36b46ba134 | ||
|
|
a2d0859bf1 | ||
|
|
d5f542dcca | ||
|
|
fb86042cb3 | ||
|
|
359fb8530e | ||
|
|
5dd1a676ac | ||
|
|
278994781b | ||
|
|
c9f1bff419 | ||
|
|
1f9621cf4b | ||
|
|
9458e4e66b | ||
|
|
ff08038bdc | ||
|
|
ce330e8bf1 | ||
|
|
47d837bf6a | ||
|
|
912a281ee2 | ||
|
|
6e863a7872 | ||
|
|
488e6c2adf | ||
|
|
e177b866a9 | ||
|
|
15dcebd0f1 | ||
|
|
af60d8d3ec | ||
|
|
5a32fdb309 | ||
|
|
19f5cb1d01 | ||
|
|
c5bca5f80a | ||
|
|
d22dea74e3 | ||
|
|
dc547317c9 | ||
|
|
6bf5d98569 | ||
|
|
29dea38f50 | ||
|
|
34567dd244 | ||
|
|
a3584c6ca3 | ||
|
|
165d0633f6 | ||
|
|
9f7ba1ba79 | ||
|
|
03c08d3970 | ||
|
|
37e3be9a0d | ||
|
|
10437887fc | ||
|
|
faf1c6233d | ||
|
|
c36960350c | ||
|
|
51ade57723 | ||
|
|
9d79673cea | ||
|
|
762bf5f031 | ||
|
|
abcb3ceb67 | ||
|
|
0ae5071f94 | ||
|
|
e589c5b269 | ||
|
|
12e341fe73 | ||
|
|
9be3c4cb9a | ||
|
|
433f3ce17e | ||
|
|
2c29ede0da | ||
|
|
7cfbca6d74 | ||
|
|
b30621bb3b | ||
|
|
d6f35903d6 | ||
|
|
a61a8015d7 | ||
|
|
e2f070649d | ||
|
|
f08d375c36 | ||
|
|
1c4bad5b73 | ||
|
|
6c874895dc | ||
|
|
ef1a05425d | ||
|
|
fc3bad2160 | ||
|
|
31ac933d64 | ||
|
|
caa398816d | ||
|
|
0d57a507f3 | ||
|
|
96257cc5c7 | ||
|
|
fbcd7d2384 | ||
|
|
d9dbfa23c7 | ||
|
|
91f077bd08 | ||
|
|
5fb4a6ae8f | ||
|
|
e84333662e | ||
|
|
ddb42fda70 | ||
|
|
621eb21b42 | ||
|
|
6cc44a87c9 | ||
|
|
5f908cae49 | ||
|
|
6de67ed107 | ||
|
|
c129f06195 | ||
|
|
d11dc63bc2 | ||
|
|
d904ec1602 | ||
|
|
2a98b2f055 | ||
|
|
6286ede985 | ||
|
|
4a8ca787d3 | ||
|
|
561c88a868 | ||
|
|
f8dfcdf024 | ||
|
|
f50b5a4ac6 | ||
|
|
59525b80e3 | ||
|
|
0ce028add1 | ||
|
|
75c5c85f07 | ||
|
|
ccb84ced2e | ||
|
|
5ef669fb6c | ||
|
|
96ff9c115c | ||
|
|
83aa6abb1c | ||
|
|
9304024841 | ||
|
|
0de5981948 | ||
|
|
c39106906d | ||
|
|
929a6e7aac | ||
|
|
ceb4d04d23 | ||
|
|
f483a8aeaa | ||
|
|
e3e220ce8e | ||
|
|
fc653e4293 | ||
|
|
94d55cb7dd | ||
|
|
0e84ecf143 | ||
|
|
0e93dfd640 | ||
|
|
4dff8237f1 | ||
|
|
35400f2a8b | ||
|
|
9a76f0862c | ||
|
|
fb8a7caa99 | ||
|
|
f8bed5c7af | ||
|
|
da6fa482e7 | ||
|
|
fdf8e48c99 | ||
|
|
195155a7f5 | ||
|
|
6934ba4dbc | ||
|
|
fdbd25c1b5 | ||
|
|
467f1cca81 | ||
|
|
d6fdf4a806 | ||
|
|
4be9d97e61 | ||
|
|
021d011493 | ||
|
|
e988d38f71 | ||
|
|
8690fc732b | ||
|
|
ceb2945da9 | ||
|
|
1b8a0951f5 | ||
|
|
a27b8462d1 | ||
|
|
edc2d53923 | ||
|
|
4aae3403f5 | ||
|
|
73423699fd | ||
|
|
0cce69892a | ||
|
|
3ca6256f87 | ||
|
|
eca3098c0e | ||
|
|
7af3461e3c | ||
|
|
b62c975dc4 | ||
|
|
b368bd1420 | ||
|
|
060e97d64e | ||
|
|
9b17ce0b7c | ||
|
|
50f2cbf600 | ||
|
|
837bca3947 | ||
|
|
16180675db | ||
|
|
d3c6351ed8 | ||
|
|
7e37ac348e | ||
|
|
30e68658ae | ||
|
|
a179308819 | ||
|
|
4cdd5f8ccc | ||
|
|
7f19474d8d | ||
|
|
a5941165a0 | ||
|
|
181d9556a1 | ||
|
|
bf72e6b9c8 | ||
|
|
8db521d379 | ||
|
|
f46ac20fb0 | ||
|
|
d70d86e9fe | ||
|
|
38db52aa4e | ||
|
|
bf62bee440 | ||
|
|
e50fe3b060 | ||
|
|
d6c55282ef | ||
|
|
1015124530 | ||
|
|
38885aaa67 | ||
|
|
a685b698c2 | ||
|
|
9bce8f9584 | ||
|
|
d04b04d73a | ||
|
|
72125430e6 | ||
|
|
561387ce57 | ||
|
|
e2d1930e6c | ||
|
|
6f2a124240 | ||
|
|
10392e9639 | ||
|
|
605c489937 | ||
|
|
26409bc860 | ||
|
|
b01f9f38f2 | ||
|
|
2ddbb805ca | ||
|
|
ed999d9a80 | ||
|
|
82cc10be88 | ||
|
|
30fb9780d7 | ||
|
|
09f46f62b4 | ||
|
|
bc4e7a8d8d | ||
|
|
e2753d75f8 | ||
|
|
addb8c4019 | ||
|
|
0c4a9b62c2 | ||
|
|
57c97d8190 | ||
|
|
b0d0ca76cf | ||
|
|
5240c0cf19 | ||
|
|
a02f369a89 | ||
|
|
fa2a113cbf | ||
|
|
4c5ac38e2c | ||
|
|
f89ebb91a8 | ||
|
|
477bc064d5 | ||
|
|
96376126b3 | ||
|
|
1c150928cb | ||
|
|
7a8d4e2c6b | ||
|
|
fb956fd2f5 | ||
|
|
e6e4d814f3 | ||
|
|
544d44886a | ||
|
|
cec2d5a4db | ||
|
|
539d215d0e | ||
|
|
10ef0e7de6 | ||
|
|
05e6b3e752 | ||
|
|
3e4be9a122 | ||
|
|
5593372ffb | ||
|
|
05be281301 | ||
|
|
108bbf56dd | ||
|
|
a61aa73419 | ||
|
|
f39626f132 | ||
|
|
c0b6f3af08 | ||
|
|
5d8fcfdf13 | ||
|
|
e4830c5614 | ||
|
|
f33261af6b | ||
|
|
e7516f2b63 | ||
|
|
d18167fe1d | ||
|
|
7d3f95c0a9 | ||
|
|
86c5bbb03d | ||
|
|
7530bb74f6 | ||
|
|
54dd726d16 | ||
|
|
bd9bb92ca0 | ||
|
|
01cb088e51 | ||
|
|
3d91112e0d | ||
|
|
16aef80682 | ||
|
|
fd34914936 | ||
|
|
21a890a04e | ||
|
|
7f5f7e8ef6 | ||
|
|
ff937576ea | ||
|
|
7d831170ae | ||
|
|
6a21ac55ad | ||
|
|
a0820c7f20 | ||
|
|
6d58c9ed0b | ||
|
|
bc2ffbc767 | ||
|
|
4c1fc2410e | ||
|
|
70e1aa889a | ||
|
|
c8c5e4e88a | ||
|
|
86c1398778 | ||
|
|
b37fa2b417 | ||
|
|
a91e197553 | ||
|
|
5adb92ca1b | ||
|
|
cfc99c4e8b | ||
|
|
3e51ed1c55 | ||
|
|
b5df0a6274 | ||
|
|
cbe8d56042 | ||
|
|
a3ec792b44 | ||
|
|
c24855d4d5 | ||
|
|
014e457fda | ||
|
|
21d89c7e24 | ||
|
|
639fb76f5a | ||
|
|
30c189b116 | ||
|
|
e2a8803f7a | ||
|
|
209e140ddd | ||
|
|
2e3fa72924 | ||
|
|
1502838a0d | ||
|
|
377c8bce8c | ||
|
|
a39d958d25 | ||
|
|
7f8a96a73e | ||
|
|
5c2577214d | ||
|
|
f03206a694 | ||
|
|
f0e328edc9 | ||
|
|
13342f2bd9 | ||
|
|
c926160853 | ||
|
|
462d5b22b4 | ||
|
|
b1bfab08f3 | ||
|
|
aeb48ef04b | ||
|
|
b8b200ad75 | ||
|
|
c148d8d783 | ||
|
|
27ba3b27f5 | ||
|
|
b4af86255d | ||
|
|
01a007b388 | ||
|
|
0e28741dcb | ||
|
|
c993feeb44 | ||
|
|
ec17f0aa23 | ||
|
|
6baf2990e8 | ||
|
|
6416e2a1a4 | ||
|
|
7c42986800 | ||
|
|
6f802a7ff1 | ||
|
|
879721839e | ||
|
|
20290a4166 | ||
|
|
ba77e4f217 | ||
|
|
e7b18feca5 | ||
|
|
4a90a3e8ef | ||
|
|
6d14ff84d3 | ||
|
|
89cc6017df | ||
|
|
f6fafdbd23 | ||
|
|
3480e42687 | ||
|
|
053c1643a7 | ||
|
|
2018cac050 | ||
|
|
f9090f535d | ||
|
|
10577f3e48 | ||
|
|
07f7caef0d | ||
|
|
093b3ba467 | ||
|
|
c63279630b | ||
|
|
4755e5206b | ||
|
|
2002157032 | ||
|
|
094e00d405 | ||
|
|
e01836c506 | ||
|
|
685f332c6e | ||
|
|
ae09272bcc | ||
|
|
d16f7e0c88 | ||
|
|
063d645d95 | ||
|
|
f87e9d8880 | ||
|
|
e8099f1bfa | ||
|
|
7dc7f9a968 | ||
|
|
996ab8c6c6 | ||
|
|
16c2198304 | ||
|
|
ecca01dea0 | ||
|
|
bda3cdd3ad | ||
|
|
4811f76294 | ||
|
|
0aba704312 | ||
|
|
57329832d0 | ||
|
|
078a1d0c95 | ||
|
|
0e695aa0c7 | ||
|
|
f7a1514131 | ||
|
|
11bc87ecc3 | ||
|
|
e1c59a2515 | ||
|
|
2faefd44a2 | ||
|
|
6fa3aa41df | ||
|
|
ef9e9ec786 | ||
|
|
d77e3a6113 | ||
|
|
0b1258b44c | ||
|
|
62dad82ba8 | ||
|
|
5423b5b0a2 | ||
|
|
6b10174bcb | ||
|
|
ec94f4d321 | ||
|
|
69800537f2 | ||
|
|
61faedb0b5 | ||
|
|
61014431aa | ||
|
|
49bd63994c | ||
|
|
85b29d9407 | ||
|
|
b83fdea49b | ||
|
|
beec0ee590 | ||
|
|
4121113688 | ||
|
|
62da379472 | ||
|
|
3c9053b055 | ||
|
|
71b07ce2bd | ||
|
|
ebea3d273e | ||
|
|
f3a76b8a63 | ||
|
|
ba93791077 | ||
|
|
b994858907 | ||
|
|
74ad34a0c5 | ||
|
|
1b5b37c06b | ||
|
|
c8e1bd0e9a | ||
|
|
e9c8d3d740 | ||
|
|
f567b866a0 | ||
|
|
3471d3ee2d | ||
|
|
6e197f5751 | ||
|
|
b568c18346 | ||
|
|
1b29876ba8 | ||
|
|
4c6f3d2d69 | ||
|
|
8d3f7eded2 | ||
|
|
0222feeda1 | ||
|
|
f10cf1a9a0 | ||
|
|
85b2089fd3 | ||
|
|
885808c64c | ||
|
|
78069b42e7 | ||
|
|
3e0063e874 | ||
|
|
6ec1ab3d4f | ||
|
|
33b4540ad9 | ||
|
|
a434b51653 | ||
|
|
222d8d3575 | ||
|
|
8e2d006048 | ||
|
|
fd9f204b6d | ||
|
|
f0f358a138 | ||
|
|
cfffcd4513 | ||
|
|
e51587c66e | ||
|
|
f930953e6a | ||
|
|
ebdc10d1c5 | ||
|
|
d12370568f | ||
|
|
176125deca | ||
|
|
cb934ca39f | ||
|
|
4fd95fdcbe | ||
|
|
cb62349054 | ||
|
|
1b72119673 | ||
|
|
add474e825 | ||
|
|
f32e4d4b30 | ||
|
|
eff87b3dc5 | ||
|
|
ea4821fd18 | ||
|
|
6285668dcd | ||
|
|
449bc7d12b | ||
|
|
ee867e7f3b | ||
|
|
b4c7ae9c8c | ||
|
|
95995a45cf | ||
|
|
823bb82b8c | ||
|
|
9a5bb46f78 | ||
|
|
950ca953f5 | ||
|
|
495c8c9eac | ||
|
|
2887795586 | ||
|
|
6a893f50ae | ||
|
|
5d08353284 | ||
|
|
a37037ded4 | ||
|
|
d331b72dfd | ||
|
|
3b21d35f23 | ||
|
|
62a694b8b7 | ||
|
|
eeba2960f9 | ||
|
|
91550c926b | ||
|
|
184525687c | ||
|
|
cdede817fd | ||
|
|
df42c2f6fe | ||
|
|
b53f2f4a60 | ||
|
|
5ff27c4fe2 | ||
|
|
e5fff5117d | ||
|
|
615cd5aac3 | ||
|
|
621d95a89e | ||
|
|
cd383167f9 | ||
|
|
cb2969002c | ||
|
|
1cf204e23d | ||
|
|
393834b253 | ||
|
|
4ca8256e18 | ||
|
|
280d91b9bf | ||
|
|
980152fd53 | ||
|
|
d994420d4d | ||
|
|
38f3ecf01f | ||
|
|
5cd0d05b31 | ||
|
|
62519c3638 | ||
|
|
27bb2deb1a | ||
|
|
a2c8e71f14 | ||
|
|
d1f56e7c2e | ||
|
|
a9fd0cbf02 | ||
|
|
be8c89ec00 | ||
|
|
4f53752693 | ||
|
|
393673222d | ||
|
|
a88f4524d5 | ||
|
|
3a02066a66 | ||
|
|
7e3981d1a3 | ||
|
|
ec2900e4dd | ||
|
|
d718a27abf | ||
|
|
db8027911c | ||
|
|
aef3b4117d | ||
|
|
6728b77aca | ||
|
|
a7c0b42965 | ||
|
|
667b6ecbbd | ||
|
|
b852878a4a | ||
|
|
940f1f7486 | ||
|
|
49c705b5ad | ||
|
|
5163e8a433 | ||
|
|
71e9603e4e | ||
|
|
c71102f44e | ||
|
|
9b9158a765 | ||
|
|
595e2b4e81 | ||
|
|
ae8e205343 | ||
|
|
00b33fbd42 | ||
|
|
841b06df37 | ||
|
|
522a06f864 | ||
|
|
fa14ed1649 | ||
|
|
64e41e066b | ||
|
|
2a71f35005 | ||
|
|
961a337a5e | ||
|
|
f0622a692e | ||
|
|
ef7042dd9d | ||
|
|
046ecfa329 | ||
|
|
47fbe49861 | ||
|
|
2f34315634 | ||
|
|
c8d6ad6546 | ||
|
|
3dfae3074e | ||
|
|
97bebe52c9 | ||
|
|
8e1845f57b | ||
|
|
6cd6769997 | ||
|
|
03884d3566 | ||
|
|
899925e249 | ||
|
|
efefa398ce | ||
|
|
1ee24c69bc | ||
|
|
b16a36980c | ||
|
|
c1b52bbc04 | ||
|
|
9461ad4d4d | ||
|
|
e2ef6e9c34 | ||
|
|
cdc8873f5b | ||
|
|
b82b205d92 | ||
|
|
39d879f240 | ||
|
|
9c1db9cab3 | ||
|
|
2f5c00f2bd | ||
|
|
dc36b313ff | ||
|
|
093fa0107a | ||
|
|
e8f5ec2579 | ||
|
|
62241668df | ||
|
|
ee67c08b64 | ||
|
|
41a14391a2 | ||
|
|
6eccca31b9 | ||
|
|
d497942a9f | ||
|
|
68c7352108 | ||
|
|
0d40e43c4b | ||
|
|
9867fd82df | ||
|
|
1c941fdfbb | ||
|
|
0ba67a72f8 | ||
|
|
09b9e26b2d | ||
|
|
d25c1d5564 | ||
|
|
d4358ed3f7 | ||
|
|
cc6ffa35fc | ||
|
|
55e9cb2f58 | ||
|
|
2641256254 | ||
|
|
473116f603 | ||
|
|
e18d63df4a | ||
|
|
4b1b3f6913 | ||
|
|
f6da5e4136 | ||
|
|
d1d5d39144 | ||
|
|
754358113f | ||
|
|
c24207516d | ||
|
|
2a23bce78d | ||
|
|
a19b82ea5f | ||
|
|
ed9590aef1 | ||
|
|
25683221cc | ||
|
|
9cc9e3ddbb | ||
|
|
654f8aeb19 | ||
|
|
e349abb897 | ||
|
|
3027a6755f | ||
|
|
5404aa6037 | ||
|
|
a319e32438 | ||
|
|
2eaf57fc67 | ||
|
|
88ec4a55cb | ||
|
|
0acbc60ec1 | ||
|
|
4362971c6a | ||
|
|
94c0d1b833 | ||
|
|
1e795d4e16 | ||
|
|
93a027ca23 | ||
|
|
5f3958fab4 | ||
|
|
1351b708fe | ||
|
|
e867e039bb | ||
|
|
1d1087a3b3 | ||
|
|
e91f1ea1b2 | ||
|
|
55d16edadc | ||
|
|
b79245ddb3 | ||
|
|
e706300b6d | ||
|
|
d08cbd77aa | ||
|
|
b070ae73a4 | ||
|
|
2c30eef9a1 | ||
|
|
31cdc113fc | ||
|
|
f6f813498b | ||
|
|
4c8baaf7c0 | ||
|
|
57ca937f27 | ||
|
|
d13e39e345 | ||
|
|
f52c141062 | ||
|
|
40042da8ff | ||
|
|
c251304146 | ||
|
|
c047e37a79 | ||
|
|
d2c57447f0 | ||
|
|
79e9dabc11 | ||
|
|
b04dc4d457 | ||
|
|
f86e7810be | ||
|
|
2018c82ea1 | ||
|
|
c27f3603e6 | ||
|
|
6f82b806ad | ||
|
|
cbb8935660 | ||
|
|
21ebbb942f | ||
|
|
988ecd95e3 | ||
|
|
3f3e70c686 | ||
|
|
073b040981 | ||
|
|
b1a058ccdd | ||
|
|
cbc7b8c3c7 | ||
|
|
13340e4200 | ||
|
|
0076c1f218 | ||
|
|
6fc71b7528 | ||
|
|
b42f1e99e2 | ||
|
|
afd6ad06a6 | ||
|
|
ea0bfaa2f3 | ||
|
|
5c3ec176c2 | ||
|
|
40425ee9ec | ||
|
|
424db825a3 | ||
|
|
b9cc4cd629 | ||
|
|
243b8f025b | ||
|
|
6c60b67588 | ||
|
|
910bb13711 | ||
|
|
add55cfc2a | ||
|
|
565820325b | ||
|
|
6bb4d67d92 | ||
|
|
534d50c03a | ||
|
|
9a42883a96 | ||
|
|
7c77e2c2b6 | ||
|
|
ea8c46cd30 | ||
|
|
fead3b0671 | ||
|
|
081990b49e | ||
|
|
6b89f8c6db | ||
|
|
373097040a | ||
|
|
a4ab75172c | ||
|
|
5cf9958957 | ||
|
|
b137e08e84 | ||
|
|
a1af8e8687 | ||
|
|
53c7ddcb22 | ||
|
|
3872077ff1 |
@@ -9,9 +9,9 @@ For email questions/requests/alerts there is always the risk of memory
|
|||||||
exhaustion on the part of the maintainer(s).
|
exhaustion on the part of the maintainer(s).
|
||||||
|
|
||||||
If you are unsure of what to do, or how to implement an idea or bugfix,
|
If you are unsure of what to do, or how to implement an idea or bugfix,
|
||||||
open an issue with `"[RFC: Unsure if this is a bug ... ?"`, or similar,
|
open an issue with `"[RFC: Unsure if this is a bug ... ?"`, or use the
|
||||||
so we can discuss it. Talking about the code first is the best way to
|
GitHub discussions forum, so we can discuss it. Talking about the code
|
||||||
get started before submitting a pull request.
|
first is the best way to get started before submitting a pull request.
|
||||||
|
|
||||||
Either way, when sending an email, patch, or pull request, start by
|
Either way, when sending an email, patch, or pull request, start by
|
||||||
stating the version the change is made against, what it does, and why.
|
stating the version the change is made against, what it does, and why.
|
||||||
@@ -73,7 +73,6 @@ It is expected of everyone engaging in the project to, in the words of
|
|||||||
Bill & Ted; [be excellent to each other][conduct].
|
Bill & Ted; [be excellent to each other][conduct].
|
||||||
|
|
||||||
|
|
||||||
[github]: https://github.com/troglobit/finit/
|
|
||||||
[KNF]: https://en.wikipedia.org/wiki/Kernel_Normal_Form
|
[KNF]: https://en.wikipedia.org/wiki/Kernel_Normal_Form
|
||||||
[gitbook]: https://git-scm.com/book/ch5-2.html
|
[gitbook]: https://git-scm.com/book/ch5-2.html
|
||||||
[conduct]: CODE-OF-CONDUCT.md
|
[conduct]: CODE-OF-CONDUCT.md
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
name: Bob the Builder
|
||||||
|
|
||||||
|
# Run on all branches, including all pull requests, except the 'dev'
|
||||||
|
# branch since that's where we run Coverity Scan (limited tokens/day)
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
- '!dev'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
# Verify we can build on latest Ubuntu with both gcc and clang
|
||||||
|
name: ${{ matrix.compiler }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
compiler: [gcc, clang]
|
||||||
|
fail-fast: false
|
||||||
|
env:
|
||||||
|
MAKEFLAGS: -j3
|
||||||
|
CC: ${{ matrix.compiler }}
|
||||||
|
steps:
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get -y update
|
||||||
|
sudo apt-get -y install pkg-config tree jq libuev-dev libite-dev
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Static Finit
|
||||||
|
run: |
|
||||||
|
./autogen.sh
|
||||||
|
./configure --prefix= --enable-static
|
||||||
|
make V=1
|
||||||
|
- name: Regular Finit
|
||||||
|
run: |
|
||||||
|
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
||||||
|
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
||||||
|
--with-keventd
|
||||||
|
make clean
|
||||||
|
make V=1
|
||||||
|
- name: Install to /tmp
|
||||||
|
run: |
|
||||||
|
DESTDIR=/tmp make install-strip
|
||||||
|
tree /tmp || true
|
||||||
|
- name: Check dependencies
|
||||||
|
run: |
|
||||||
|
ldd /tmp/sbin/finit
|
||||||
|
size /tmp/sbin/finit
|
||||||
|
ldd /tmp/sbin/initctl
|
||||||
|
size /tmp/sbin/initctl
|
||||||
|
ldd /tmp/sbin/reboot
|
||||||
|
size /tmp/sbin/reboot
|
||||||
|
- name: Verify starting and showing usage text
|
||||||
|
run: |
|
||||||
|
sudo /tmp/sbin/finit -h
|
||||||
|
sudo /tmp/sbin/initctl -h
|
||||||
|
- name: Run Unit Tests
|
||||||
|
run: |
|
||||||
|
make check || (cat test/test-suite.log; false)
|
||||||
|
- name: Upload Test Results
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: finit-test-${{ matrix.compiler }}
|
||||||
|
path: test/*.log
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
name: Coverity Scan
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'dev'
|
||||||
|
|
||||||
|
env:
|
||||||
|
PROJECT_NAME: finit
|
||||||
|
CONTACT_EMAIL: troglobit@gmail.com
|
||||||
|
COVERITY_NAME: troglobit-finit
|
||||||
|
COVERITY_PROJ: troglobit%2Ffinit
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
coverity:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Fetch latest Coverity Scan MD5
|
||||||
|
id: var
|
||||||
|
env:
|
||||||
|
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||||
|
run: |
|
||||||
|
wget -q https://scan.coverity.com/download/cxx/linux64 \
|
||||||
|
--post-data "token=$TOKEN&project=${COVERITY_PROJ}&md5=1" \
|
||||||
|
-O coverity-latest.tar.gz.md5
|
||||||
|
echo "md5=$(cat coverity-latest.tar.gz.md5)" | tee -a $GITHUB_OUTPUT
|
||||||
|
- uses: actions/cache@v3
|
||||||
|
id: cache
|
||||||
|
with:
|
||||||
|
path: coverity-latest.tar.gz
|
||||||
|
key: ${{ runner.os }}-coverity-${{ steps.var.outputs.md5 }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-coverity-${{ steps.var.outputs.md5 }}
|
||||||
|
${{ runner.os }}-coverity-
|
||||||
|
${{ runner.os }}-coverity
|
||||||
|
- name: Download Coverity Scan
|
||||||
|
env:
|
||||||
|
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||||
|
run: |
|
||||||
|
if [ ! -f coverity-latest.tar.gz ]; then
|
||||||
|
wget -q https://scan.coverity.com/download/cxx/linux64 \
|
||||||
|
--post-data "token=$TOKEN&project=${COVERITY_PROJ}" \
|
||||||
|
-O coverity-latest.tar.gz
|
||||||
|
else
|
||||||
|
echo "Latest Coverity Scan available from cache :-)"
|
||||||
|
md5sum coverity-latest.tar.gz
|
||||||
|
fi
|
||||||
|
mkdir coverity
|
||||||
|
tar xzf coverity-latest.tar.gz --strip 1 -C coverity
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get -y update
|
||||||
|
sudo apt-get -y install pkg-config
|
||||||
|
wget https://github.com/troglobit/libuev/releases/download/v2.4.0/libuev-2.4.0.tar.xz
|
||||||
|
wget https://github.com/troglobit/libite/releases/download/v2.5.2/libite-2.5.2.tar.gz
|
||||||
|
tar xf libuev-2.4.0.tar.xz
|
||||||
|
tar xf libite-2.5.2.tar.gz
|
||||||
|
(cd libuev-2.4.0 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||||
|
(cd libite-2.5.2 && ./configure --prefix=/usr && make && sudo make install-strip)
|
||||||
|
sudo ldconfig
|
||||||
|
- name: Configure
|
||||||
|
run: |
|
||||||
|
./autogen.sh
|
||||||
|
./configure --prefix= --enable-x11-common-plugin --with-watchdog --with-keventd
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
export PATH=`pwd`/coverity/bin:$PATH
|
||||||
|
cov-build --dir cov-int make
|
||||||
|
- name: Submit results to Coverity Scan
|
||||||
|
env:
|
||||||
|
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||||
|
run: |
|
||||||
|
tar czvf ${PROJECT_NAME}.tgz cov-int
|
||||||
|
curl \
|
||||||
|
--form project=${COVERITY_NAME} \
|
||||||
|
--form token=$TOKEN \
|
||||||
|
--form email=${CONTACT_EMAIL} \
|
||||||
|
--form file=@${PROJECT_NAME}.tgz \
|
||||||
|
--form version=trunk \
|
||||||
|
--form description="${PROJECT_NAME} $(git rev-parse HEAD)" \
|
||||||
|
https://scan.coverity.com/builds?project=${COVERITY_PROJ}
|
||||||
|
- name: Upload build.log
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: coverity-build.log
|
||||||
|
path: cov-int/build-log.txt
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
name: Release General
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '[0-9]+.[0-9]+*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
name: Build and upload release tarball
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
MAKEFLAGS: -j3
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Installing dependencies ...
|
||||||
|
run: |
|
||||||
|
sudo apt-get -y update
|
||||||
|
sudo apt-get -y install pkg-config jq libuev-dev libite-dev
|
||||||
|
- name: Setting release variables ...
|
||||||
|
id: build
|
||||||
|
run: |
|
||||||
|
ver=${GITHUB_REF#refs/tags/}
|
||||||
|
echo "ver=${ver}" >> $GITHUB_OUTPUT
|
||||||
|
if echo $ver | grep -qE '^[0-9]+\.[0-9]+(\.[0-9]+)?(-alpha|-beta|-rc)[0-9]*$'; then
|
||||||
|
echo "pre=true" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "pre=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
if echo $ver | grep -qE '^[0-9.]+\.[0-9.]+(\.[0-9]+)?$'; then
|
||||||
|
echo "latest=true" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "latest=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
- name: Creating Makefiles ...
|
||||||
|
run: |
|
||||||
|
./autogen.sh
|
||||||
|
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
||||||
|
--enable-x11-common-plugin --enable-testserv-plugin --with-watchdog \
|
||||||
|
--with-keventd
|
||||||
|
- name: Build release ...
|
||||||
|
run: |
|
||||||
|
make release || (cat test/test-suite.log; false)
|
||||||
|
ls -lF ../
|
||||||
|
mkdir -p artifacts/
|
||||||
|
mv ../*.tar.* artifacts/
|
||||||
|
- name: Extract ChangeLog entry ...
|
||||||
|
run: |
|
||||||
|
awk '/-----*/{if (x == 1) exit; x=1;next}x' ChangeLog.md \
|
||||||
|
|head -n -1 > release.md
|
||||||
|
cat release.md
|
||||||
|
- uses: ncipollo/release-action@v1
|
||||||
|
with:
|
||||||
|
name: Finit v${{ github.ref_name }}
|
||||||
|
prerelease: ${{ steps.build.outputs.pre }}
|
||||||
|
makeLatest: ${{ steps.build.outputs.latest }}
|
||||||
|
bodyFile: "release.md"
|
||||||
|
artifacts: "artifacts/*"
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
name: Weekly Distcheck
|
||||||
|
|
||||||
|
# Verify that `make distcheck` works as intended: all tests pass, and
|
||||||
|
# any new files are distributed in the tarballs
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * 0'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
schedule:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
run: ${{ steps.check.outputs.run }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Check for any commits since last week
|
||||||
|
id: schedule
|
||||||
|
run: |
|
||||||
|
commits="$(git log --format=%H --since='1 week ago')"
|
||||||
|
if [ -n "$commits" ]; then
|
||||||
|
echo "run=true" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "run=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
distcheck:
|
||||||
|
needs: schedule
|
||||||
|
if: ${{ needs.schedule.outputs.run == 'true' }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get -y update
|
||||||
|
sudo apt-get -y install pkg-config jq libuev-dev libite-dev
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Base run
|
||||||
|
run: |
|
||||||
|
./autogen.sh
|
||||||
|
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var
|
||||||
|
make -j9 V=1
|
||||||
|
- name: Install to /tmp
|
||||||
|
run: |
|
||||||
|
DESTDIR=/tmp make install-strip
|
||||||
|
- name: Check dist tarball
|
||||||
|
run: |
|
||||||
|
ver=$(/tmp/sbin/initctl -V | awk '/Finit.*/ {print $2;}')
|
||||||
|
dir=finit-$ver/_build/sub
|
||||||
|
make -j1 distcheck || (cat $dir/test/test-suite.log; false)
|
||||||
@@ -14,6 +14,7 @@ GTAGS
|
|||||||
/autom4te.cache
|
/autom4te.cache
|
||||||
/aclocal.m4
|
/aclocal.m4
|
||||||
/ar-lib
|
/ar-lib
|
||||||
|
/backup/
|
||||||
/compile
|
/compile
|
||||||
/config.cache
|
/config.cache
|
||||||
/config.h
|
/config.h
|
||||||
@@ -36,6 +37,9 @@ GTAGS
|
|||||||
/test-driver
|
/test-driver
|
||||||
/test-suite.log
|
/test-suite.log
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
/.gdb_history
|
||||||
|
|
||||||
# TroglOS build system
|
# TroglOS build system
|
||||||
/.config
|
/.config
|
||||||
/.stamp
|
/.stamp
|
||||||
@@ -45,3 +49,6 @@ GTAGS
|
|||||||
/.autoconf
|
/.autoconf
|
||||||
/.automake
|
/.automake
|
||||||
/.built
|
/.built
|
||||||
|
|
||||||
|
# VS Code user settings
|
||||||
|
.vscode
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# GNU Global .conf file, see /etc/gtags/gtags.conf for details.
|
||||||
|
default:\
|
||||||
|
:tc=default@/etc/gtags/gtags.conf:\
|
||||||
|
:tc=common:
|
||||||
|
|
||||||
|
common:\
|
||||||
|
:skip=tags,TAGS,ID,y.tab.c,y.tab.h,gtags.files,cscope.files,cscope.out,cscope.po.out,cscope.in.out,,{arch}/,autom4te.cache/,*.orig,*.rej,*.bak,*~,#*#,*.swp,*.tmp,*_flymake.*,*_flymake,*.o,*.a,*.so,*.lo,*.zip,*.gz,*.bz2,*.xz,*.lzh,*.Z,*.tgz,*.min.js,*min.css,sysroot/:
|
||||||
-62
@@ -1,62 +0,0 @@
|
|||||||
# Travis CI integration -- https://travis-ci.org/troglobit/finit
|
|
||||||
# Defaults to GNU GCC and autotools: ./configure && make && make test
|
|
||||||
language: c
|
|
||||||
|
|
||||||
# Use docker for quicker builds, it now allows https://docs.travis-ci.com/user/apt/
|
|
||||||
sudo: false
|
|
||||||
|
|
||||||
# Test build with both GCC and Clang (LLVM)
|
|
||||||
compiler:
|
|
||||||
- gcc
|
|
||||||
- clang
|
|
||||||
|
|
||||||
# The secure: declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
|
||||||
# via the "travis encrypt" command using the project repo's public key
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- PKG_CONFIG_PATH=/tmp/lib/pkgconfig
|
|
||||||
- CFLAGS="-W -Wall -Wextra"
|
|
||||||
- secure: "eOiuHs02lG2Uv146K9dMqucGTWUJFEhpz1oAtwe+kPrRXsXWc20hYMO+DSpMgD05vSvNeQA6p7h7LdRFQ+/g/Obj27TsOE+RKkUvRAtdwzxnKVyii9C/nmML8cFw7rIA0VS8O9mAkVYeyDxNDupBp3e9DPCibhKPvqCvioTnyy4="
|
|
||||||
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- tree
|
|
||||||
coverity_scan:
|
|
||||||
project:
|
|
||||||
name: "troglobit/finit"
|
|
||||||
description: "finit | Fast & Extensible init for Linux"
|
|
||||||
notification_email: troglobit@gmail.com
|
|
||||||
build_command_prepend: "./autogen.sh && ./configure --prefix= --disable-doc --disable-contrib --with-watchdog"
|
|
||||||
build_command: "make"
|
|
||||||
branch_pattern: dev
|
|
||||||
|
|
||||||
install:
|
|
||||||
- wget https://github.com/troglobit/libuev/releases/download/v2.3.2/libuev-2.3.2.tar.xz
|
|
||||||
- wget https://github.com/troglobit/libite/releases/download/v2.3.1/libite-2.3.1.tar.gz
|
|
||||||
- tar xf libuev-2.3.2.tar.xz
|
|
||||||
- tar xf libite-2.3.1.tar.gz
|
|
||||||
- (cd libuev-2.3.2 && ./configure --prefix=/tmp && make && make install-strip)
|
|
||||||
- (cd libite-2.3.1 && ./configure --prefix=/tmp && make && make install-strip)
|
|
||||||
|
|
||||||
# Custom build script for the time being, no "make test" yet
|
|
||||||
script:
|
|
||||||
- ./autogen.sh
|
|
||||||
- ./configure --prefix= --enable-static
|
|
||||||
- make clean
|
|
||||||
- make V=1 -j5
|
|
||||||
- ./configure --prefix= --enable-x11-common-plugin --with-watchdog
|
|
||||||
- cat config.log
|
|
||||||
- make clean
|
|
||||||
- make V=1 -j5
|
|
||||||
- make install-strip DESTDIR=/tmp/finit
|
|
||||||
- tree /tmp/finit
|
|
||||||
- ldd /tmp/finit/sbin/finit
|
|
||||||
- size /tmp/finit/sbin/finit
|
|
||||||
- size /tmp/finit/sbin/initctl
|
|
||||||
- size /tmp/finit/sbin/reboot
|
|
||||||
- LD_LIBRARY_PATH=/tmp/lib /tmp/finit/sbin/initctl -h
|
|
||||||
- unshare -V
|
|
||||||
- nsenter -V
|
|
||||||
- chroot --version
|
|
||||||
- 'LD_LIBRARY_PATH=/tmp/lib make distcheck || (cat finit-4.0-beta1/_build/sub/test/test-suite.log; exit 1)'
|
|
||||||
+796
-15
@@ -4,6 +4,786 @@ Change Log
|
|||||||
All relevant changes are documented in this file.
|
All relevant changes are documented in this file.
|
||||||
|
|
||||||
|
|
||||||
|
[4.7][] - 2024-01-07
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Silence "not available" messages for run/task/service with `nowarn`
|
||||||
|
- Update docs, `cgroup.root` workaround for `SCHED_RR` tasks
|
||||||
|
- Drop runlevels 0 and 6 from `keventd`, not needed at reboot/poweroff
|
||||||
|
- Mount `/dev/shm` with mode 1777 (sticky bit)
|
||||||
|
- Mount `/dev/mqueue` if available, inspiration from Alpine Linux
|
||||||
|
- Update Alpine Linux installer and configuration files, tested on
|
||||||
|
Alpine v3.19, some assembly still required
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix confusing warning message when tmpfiles.d fails to install symlink
|
||||||
|
- Fix tmpfiles.d legacy `/run/lock/subsys`, ordering
|
||||||
|
- Add missing `/var/tmp` and `/var/lock -> /run/lock` (tmpfiles.d)
|
||||||
|
- Fix #388: log redirection broken unless Finit runs in debug mode.
|
||||||
|
Found and fixed by Ryan Rorison
|
||||||
|
- Fix #389: must libc requires `libgen.h` for `basename()` function.
|
||||||
|
Reported and worked around with new `basenm()` function by Stargirl
|
||||||
|
|
||||||
|
|
||||||
|
[4.6][] - 2023-11-13
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Add support for service `notify:pid` and `readiness none` global
|
||||||
|
option to change how Finit expects readiness notification, issue #386
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix #383: dbus and runparts regression in Finit v4.5. The configure
|
||||||
|
script must expand `FINIT_RUNPATH_` before defining it in `config.h`
|
||||||
|
- Fix #384: service environment variables drop everything but the first
|
||||||
|
argument, e.g., `VAR="foo bar qux"` drops everything but `foo`
|
||||||
|
- Fix #385: internal conditions, e.g., `<int/bootstrap>` turn into flux
|
||||||
|
when leaving bootstrap, causing depending services to stop
|
||||||
|
- Fix #387: global environment variables declared with `set VAR=NAME` do
|
||||||
|
not drop leading `set `, causing `'set VAR'='NAME'` in env.
|
||||||
|
- Sanity check environment variables, for services and globally. Ensure
|
||||||
|
the variable name (key) does not contain spaces, or a leading `set `
|
||||||
|
|
||||||
|
|
||||||
|
[4.5][] - 2023-10-30
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
- Refactor `runparts` and `/etc/rc.local` to no longer block the main
|
||||||
|
loop, allowing `initctl` calls to interact with Finit. Issue #356
|
||||||
|
- Refactor the `run` stanza to no longer block the main loop, issue #362
|
||||||
|
- Allow `sulogin` with a user different from `root`, issue #357
|
||||||
|
- Allow disabling invocation of rescue mode from kernel command line
|
||||||
|
- Add `initctl -f` to force-skip asking Finit for existing services
|
||||||
|
when creating new services during bootstrap, e.g. `/etc/rc.local`
|
||||||
|
- `initctl runlevel` now returns `N S` instead of `N 10` in bootstrap
|
||||||
|
- `initctl runlevel N` during bootstrap is now allowed. It changes
|
||||||
|
the next runlevel to go to when bootstrap has completed. Effectively
|
||||||
|
overriding the `runlevel N` statement in `/etc/finit.conf`
|
||||||
|
- Improved logging on failure to `execvp()` a run/task/service, now
|
||||||
|
with `errno`, e.g., "No such file or directory" when the command
|
||||||
|
is missing from `$PATH`
|
||||||
|
- Add Bash completion support for `initctl`, configurable, issue #360
|
||||||
|
- Handle absolute path to `initctl [enable|disable]`, not supported
|
||||||
|
- Update `finit.conf(5)` man page with the recommended directory
|
||||||
|
hierarchy in `/etc/finit.d/`
|
||||||
|
- The `runparts` code has been split into `/libexec/finit/runparts`
|
||||||
|
- The `runparts` command now takes two options: `sysv` and `progress`.
|
||||||
|
The former ensures only `SNNfoo` and `KNNfoo` scripts are run.
|
||||||
|
- Add SysV Init Compatibility section to documentation
|
||||||
|
- Increased MAX path for commands, and arguments: 64 -> 256
|
||||||
|
- The bundled watchdog daemon no longer tries to log at startup, because
|
||||||
|
syslog is not available yet, any startup message leak to console
|
||||||
|
- Extend `if:` option with runtime evaluation of conditions. E.g., start
|
||||||
|
a task only `if:<run/foo/failure>` (here the run task 'foo' failed)
|
||||||
|
- Document new `if:`, `conflict:`, `nowarn` options for run/task/service
|
||||||
|
first introduced in v4.4
|
||||||
|
- Failure to open fstab should log to console, not just log to `/dev/kmsg`
|
||||||
|
- Rename `/lib/finit/system/*.conf`, added numbered prefix to ensure
|
||||||
|
proper execution order, e.g., `udevd` should always run first
|
||||||
|
- Plugins and bundled services: dbus, keventd, watchdogd, and runparts,
|
||||||
|
are now loaded *after* all services in `/lib/finit/system/`. A new
|
||||||
|
runtime-only path (for inspection) in `/run/finit/system/` is used
|
||||||
|
- Redirect `log*` output to console when `finit.debug` is enabled
|
||||||
|
- Assert `<int/container>` condition if we detect running in container
|
||||||
|
- Add support for mdev's netlink daemon mode, issue #367
|
||||||
|
- Add support for mdevd in `10-hotplug.conf`, preferred over plain mdev
|
||||||
|
- Disable modprobe plugin by default, udevd and mdev/mdevd loads modules
|
||||||
|
- Update documentation for run/task shell limitations, issue #376
|
||||||
|
- Update documentation regarding automount of `/run` and `/tmp`
|
||||||
|
- Update plugin documentation, add section about limited tmpfiles.d(5) support
|
||||||
|
- Skip registering service when `if:!name` matches a known service.
|
||||||
|
This allows conditional loading of alternative services, e.g. if udevd
|
||||||
|
is already loaded we do not need mdevd
|
||||||
|
- Drop `doc/bootstrap.md`, inaccurate and confusing to users
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix #227: believed to have been fixed in v4.3, the root cause was
|
||||||
|
actually that Finit was waiting for a process that was no longer in
|
||||||
|
the system. The fix is to ask the kernel on process-stop-timeout and
|
||||||
|
replay the lost PID so that Finit can continue with reboot/shutdown
|
||||||
|
- Fix #358: fix inotify events for `/etc/finit.conf`, improved log
|
||||||
|
messages and error handling
|
||||||
|
- Fix #361: cgroup move fail if run/task/services start as non-root.
|
||||||
|
Regression in the v4.4 release cycle while adding support for the
|
||||||
|
pre:/post:/ready: scripts. Now the latter scripts also properly run
|
||||||
|
in their correct cgroup
|
||||||
|
- Fix #366: document `fsck.*` kernel command line options and simplify
|
||||||
|
the configure flags `--enable-fsckfix` and `--enable-fastboot` to
|
||||||
|
only adjust the default values for the `fsck.*` options.
|
||||||
|
- Fix #371: swap load order of `/lib/finit/system/*` vs `/etc/finit.d/*`
|
||||||
|
We must run `10-hotplug.conf` first to ensure devices and modules are
|
||||||
|
up and loaded before the user's run/task/services are called. The order
|
||||||
|
at bootstrap is now saved in `/run/finit/conf.order` for inspection,
|
||||||
|
`/run/finit/exec.order` shows the start order of each process
|
||||||
|
- Fix #372: lost `udevadm` calls due to overloading
|
||||||
|
- Adjust final `udevadm settle` timeout: 5 -> 30 sec
|
||||||
|
- Fixed dbus plugin, the function that located `<pidfile> ...` in the
|
||||||
|
`dbus/system.conf` caused spurious line breaks which led to the
|
||||||
|
service not being loaded properly
|
||||||
|
- The `runparts` executor now skips backup files (`foo~`)
|
||||||
|
- The `runparts` stanza now properly appends ` start` to scripts that
|
||||||
|
start with `S[0-9]+`. This has been broken for a very long time.
|
||||||
|
- Fix #377: expand service `env:file` variables, allow constructs like:
|
||||||
|
|
||||||
|
RUNDIR=/var/run/somesvc
|
||||||
|
DAEMON_ARGS=--workdir $RUNDIR --other-args...
|
||||||
|
- Fix #378: warn on console if run/task times out during bootstrap
|
||||||
|
- Fix #378: add run/task support for `<!>` to allow transition from
|
||||||
|
bootstrap to multi-user runlevel even though task has not run yet.
|
||||||
|
- Fix #382: do not clear `<service/foo/STATE>` conditions on reload.
|
||||||
|
Introduced back in v4.3-rc2, 82cc10be8, the support for automatic
|
||||||
|
service conditions have had a weird and unintended behavior. Any
|
||||||
|
change in state (see `doc/svc-machine.png`) caused Finit to clear
|
||||||
|
out *all* previously acquired service conditions.
|
||||||
|
|
||||||
|
However, when moving between RUNNING and PAUSED states, a service
|
||||||
|
should not have its conditions cleared. The PAUSED state, seen
|
||||||
|
also by all conditions moving to FLUX, is only temporary while an
|
||||||
|
`initctl reload` is processed. If a service has no changes to be
|
||||||
|
applied it will move back to RUNNING.
|
||||||
|
|
||||||
|
Also, we cannot clear the service conditions because other run/task
|
||||||
|
or services may depend on it and clearing them would cause Finit to
|
||||||
|
`SIGTERM` these processes (since they are no longer eligible to run).
|
||||||
|
|
||||||
|
|
||||||
|
[4.4][] - 2023-05-15
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
> **Note 1:** this release contains changes to the `.conf` parser. If you
|
||||||
|
> have .conf file statements with comment character (`#`) in the command
|
||||||
|
> options or description, you must now escape them (`\#`). Issue #186
|
||||||
|
>
|
||||||
|
> **Note 2:** prior to this release, runlevel `S` and `0` were after
|
||||||
|
> boot treated as the same runlevel. This caused `task [06] ...` to
|
||||||
|
> also run at bootstrap instead of just at shutdown and reboot. The
|
||||||
|
> changes made to Finit to separate `S` from `0` require you to update
|
||||||
|
> the allowed runlevels for services that are allowed to continue
|
||||||
|
> running at shutdown. I.e., change `[S123456789]` to `[S0123456789]`
|
||||||
|
> for, e.g., `sysklogd`. Issue #352
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
* Add limited tmpfiles.d(5) support
|
||||||
|
|
||||||
|
This change adds very basic `tmpfiles.d/` support to Finit. Most of
|
||||||
|
the basic types are supported, but not all, so for now, please check
|
||||||
|
the code and examples for details on what is working.
|
||||||
|
|
||||||
|
* If a run/task/service command does not exist, skip registering it
|
||||||
|
|
||||||
|
This changes the semantics of Finit a bit by checking for the command
|
||||||
|
to run when registering it, skipping commands that cannot be found in
|
||||||
|
the absolute path provided in the command, or in `$PATH`
|
||||||
|
|
||||||
|
This change includes a new `nowarn` flag that can be used to prevent
|
||||||
|
Finit from warning for missing commands. See below for an example.
|
||||||
|
|
||||||
|
* Add run/task/service support for `conflict:foo` handling
|
||||||
|
* Add run/task/service support for `if:[!]ident` and `if:<[!]cond>`
|
||||||
|
|
||||||
|
Conditional loading of stanza depending on ident is already loaded (or
|
||||||
|
not), or condition satisfied (or not). E.g., do not run `mdev` if we
|
||||||
|
found and registered `udevd`, or load service only if `<boot/testing>`
|
||||||
|
condition is set.
|
||||||
|
|
||||||
|
The optional leading `!` negates the comparison, if NOT foo then ...
|
||||||
|
|
||||||
|
* Add support for static services in `/lib/finit/system/*.conf`
|
||||||
|
|
||||||
|
Slowly migrating away from hard-coded services in plugins. This way
|
||||||
|
it's possible for the user to both inspect and override as needed.
|
||||||
|
|
||||||
|
* Migrate hotplug plugin to a conditional `/lib/finit/system/hotplug.conf`
|
||||||
|
|
||||||
|
This is the first example of the just minted advanced stanza syntax with
|
||||||
|
`if:`-statements, `conflict:` handling, and `nowarn` flags.
|
||||||
|
|
||||||
|
* Initial support for template services, `foo@.conf`, similar to systemd
|
||||||
|
|
||||||
|
$ initctl show avahi-autoipd@
|
||||||
|
service :%i avahi-autoipd --syslog %i -- ZeroConf for %i
|
||||||
|
|
||||||
|
To enable ZeroConf for, e.g., `eth0`, use
|
||||||
|
|
||||||
|
$ initctl enable avahi-autoipd@eth0.conf
|
||||||
|
|
||||||
|
The enabled symlink will be set up to `avahi-autoipd@.conf` and every
|
||||||
|
instance of `%i` will in the instantiated directive be replaced with
|
||||||
|
`eth0`. Inspect the result with:
|
||||||
|
|
||||||
|
$ initctl status avahi-autoipd:eth0
|
||||||
|
|
||||||
|
* Add `devmon`, a `<dev/foo>` condition provider, issue #185
|
||||||
|
* Support for line continuation character `\` in .conf files, issue #186
|
||||||
|
|
||||||
|
service name:sysklogd [S123456789] \
|
||||||
|
env:-/etc/default/sysklogd \
|
||||||
|
syslogd -F $SYSLOGD_ARGS \
|
||||||
|
-- System log daemon
|
||||||
|
|
||||||
|
* `HOOK_BASEFS_UP` has been moved! External plugins that need to call
|
||||||
|
`service_register()`, please use `HOOK_SVC_PLUGIN` from now on.
|
||||||
|
Apologies for any inconveniences this might cause!
|
||||||
|
* getty: add support for `/etc/os-release` to replace `uname` output
|
||||||
|
This change, which has a fallback to `/usr/lib/os-release`, overrides
|
||||||
|
traditional modifiers with the os-release variant. These values were
|
||||||
|
taken from `uname`, which on Linux systems are pretty useless since
|
||||||
|
they always return the kernel name and version instead of the
|
||||||
|
distro/OS values.
|
||||||
|
|
||||||
|
E.g., \s becomes `PRETTY_NAME` instead of 'Linux' and \v becomes the
|
||||||
|
pretty `VERSION`, while \r becomes `VERSION_ID`.
|
||||||
|
* Support for overriding `/etc/finit.conf` and `/etc/finit.d` issue #235
|
||||||
|
New (kernel) command line option `finit.config=PATH` which can be used
|
||||||
|
to redirect Finit to start up with, e.g., `/etc/factory.conf` instead of
|
||||||
|
`/etc/finit.conf`.
|
||||||
|
|
||||||
|
For the complete experience a new top-level configuration file directive
|
||||||
|
`rcsd PATH` has aslo been added. It in turn can be used by `factory.conf`
|
||||||
|
as follows to override `/etc/finit.d`:
|
||||||
|
|
||||||
|
rcsd /etc/factory.d
|
||||||
|
|
||||||
|
* Support for overriding `/etc/finit.d` from the alternate `finit.conf`
|
||||||
|
with a new `rcsd /path/to/dot.d/` .conf file directive
|
||||||
|
* Support for `fsck_mode=[auto,skip,force]` + `fsck_repair=[preen,no,yes]`
|
||||||
|
* Add `set` keyword for environment variables set in `/etc/finit.conf`
|
||||||
|
* Support `finit.cond=foo` cmdline `<boot/foo>` conditions, issue #250
|
||||||
|
* `initctl` JSON output support for status and conditions, issue #273
|
||||||
|
Example:
|
||||||
|
|
||||||
|
root@infix:~$ initctl status -j resolvconf
|
||||||
|
{
|
||||||
|
"identity": "resolvconf",
|
||||||
|
"description": "Update DNS configuration",
|
||||||
|
"type": "task",
|
||||||
|
"forking": false,
|
||||||
|
"status": "done",
|
||||||
|
"exit": { "code": 0 },
|
||||||
|
"origin": "/etc/finit.d/enabled/sysrepo.conf",
|
||||||
|
"command": "resolvconf -u",
|
||||||
|
"restarts": 0,
|
||||||
|
"pidfile": "none",
|
||||||
|
"pid": 0,
|
||||||
|
"user": "root",
|
||||||
|
"group": "root",
|
||||||
|
"uptime": 0,
|
||||||
|
"runlevels": [ 1, 2, 3, 4, 5, 7, 8, 9 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
The excellent tool `jq` can be used to extract parts of the output for
|
||||||
|
further scripting. E.g. `initctl status -j foo | jq .exit.status`
|
||||||
|
|
||||||
|
* Add JSON support to `initctl ls` command
|
||||||
|
|
||||||
|
This allows for easy access to the *disabled* services:
|
||||||
|
|
||||||
|
root@anarchy:~# initctl ls --json |jq '.available - .enabled'
|
||||||
|
[
|
||||||
|
"chronyd.conf",
|
||||||
|
"dnsmasq.conf",
|
||||||
|
"gdbserver.conf",
|
||||||
|
"inadyn.conf",
|
||||||
|
"inetd.conf",
|
||||||
|
"isisd.conf",
|
||||||
|
"lldpd.conf",
|
||||||
|
"mstpd.conf",
|
||||||
|
"ntpd.conf",
|
||||||
|
"ospf6d.conf",
|
||||||
|
"ospfd.conf",
|
||||||
|
"querierd.conf",
|
||||||
|
"ripd.conf",
|
||||||
|
"ripng.conf",
|
||||||
|
"sshd.conf",
|
||||||
|
"syslogd.conf",
|
||||||
|
"telnetd.conf",
|
||||||
|
"uftpd.conf",
|
||||||
|
"wpa_supplicant.conf",
|
||||||
|
"zebra.conf"
|
||||||
|
]
|
||||||
|
|
||||||
|
* Allow `manual:yes` on sysv/service/run/task stanzas, issue #274
|
||||||
|
* Add support for `oncrash:script` to call the `post:script` action, if
|
||||||
|
defined, for a crashing service. The `EXIT_CODE` variable sent to the
|
||||||
|
script is set to `crashed`. Issue #282
|
||||||
|
* Search for plugins in `/usr` and `/usr/local` as well, issue #284
|
||||||
|
* tty: add support for `passenv` flag to `/bin/login`, issue #286
|
||||||
|
* Add reboot/shutdown/poweroff timeout `-t SEC` to initctl, issue #295
|
||||||
|
* Add support for s6 and systemd readiness notification, issue #299.
|
||||||
|
Service readiness notification to support daemons employing systemd
|
||||||
|
and s6 notification. Complementing the native Finit readiness support
|
||||||
|
using PID files that exist already.
|
||||||
|
|
||||||
|
The two have slightly different ways of implementing readiness:
|
||||||
|
|
||||||
|
- https://www.freedesktop.org/software/systemd/man/sd_notify.html
|
||||||
|
- https://skarnet.org/software/s6/notifywhenup.html
|
||||||
|
|
||||||
|
Finit now provides both a `NOTIFY_SOCKET` environment variable, for
|
||||||
|
systemd, and a way to start s6 daemons with a descriptor argument.
|
||||||
|
|
||||||
|
For details on the syntax, see the `service` documentation.
|
||||||
|
|
||||||
|
This change also renames internal states for run/task/services to
|
||||||
|
avoid any confusion with the introduction of `ready:scripts`:
|
||||||
|
|
||||||
|
- `WAITING -> PAUSED`
|
||||||
|
- `READY -> WAITING`
|
||||||
|
|
||||||
|
A service condition that used, e.g., `<service/foo/ready>` should now
|
||||||
|
instead use `<service/foo/waiting>`
|
||||||
|
|
||||||
|
* Add `ready:script` for services, called when daemon is ready, issue #300
|
||||||
|
* Add support for running scripts at shutdown at two new hook points
|
||||||
|
during the shutdown process, issue #302. See doc/plugins.md for details:
|
||||||
|
|
||||||
|
- `HOOK_SVC_DN`: after all services and non-reserved processes have been
|
||||||
|
killed (and collected)
|
||||||
|
- `HOOK_SYS_DN`: after all file systems have been unmounted, *just prior*
|
||||||
|
to Finit calling `reboot()` to shut down or reboot the system
|
||||||
|
|
||||||
|
* The `modules-load` plugin now default to runlevel `[S]`, in previous
|
||||||
|
releases it was `[2345]`. This breaking change is to align it more
|
||||||
|
with what users mostly want (modules loaded before services start) and
|
||||||
|
can be changed back to the old behavior with a per-file setting:
|
||||||
|
|
||||||
|
set runlevel 2345
|
||||||
|
|
||||||
|
* The `modules-load` plugin now adds silent tasks for modprobe. This to
|
||||||
|
prevent confusing `[ OK ]` boot messages when in fact modprobe failed.
|
||||||
|
* The `modules-load` plugin now support `set modprobe /path/to/modprobe`
|
||||||
|
* The header files `finit/conf.h` and `finit/service.h` are now exported
|
||||||
|
for external plugins
|
||||||
|
* Add support for multiple args to `initctl cond set/clr`, issue #329
|
||||||
|
* Silence confusing `[ OK ]` progress from modules-load plugin, issue #332
|
||||||
|
|
||||||
|
This change drops the confusing status progress output, which was always
|
||||||
|
OK since the actual modprobe operation runs in the background. No need
|
||||||
|
to show status of the "added a task to finit, found modprobe" command.
|
||||||
|
|
||||||
|
* dbus plugin: adapt to other operating systems
|
||||||
|
|
||||||
|
Not all Linux systems are based on Debian, and even if they are inspired
|
||||||
|
by Debian (Buildroot), they do not necessarily use the same defaults.
|
||||||
|
Probes the system at runtime for:
|
||||||
|
|
||||||
|
- dbus user and group
|
||||||
|
- dbus PID file
|
||||||
|
|
||||||
|
If the user/group cannot be found we fall back to `root`, if the PID
|
||||||
|
file cannot be determined we ignore PID file readiness.
|
||||||
|
|
||||||
|
* Improve documentation for runparts and hook scripts. Issue #315, #320
|
||||||
|
* Add `HOOK_NETWORK_DN`, called after change to runlevel 6 or 0, issue #319
|
||||||
|
* Use sysklogd `logger` tool instead of legacy `logit` tool, issue #344
|
||||||
|
|
||||||
|
For log redirection Finit has the legacy `logit` tool. This change
|
||||||
|
allows Finit to use the `sysklogd` project's extended `logger` tool
|
||||||
|
instead, when available. Allowing logging with the process' PID.
|
||||||
|
|
||||||
|
* Add `initctl` aliases: `cat -> show`, `kill -> signal`
|
||||||
|
* Add `initctl -n,--noerr` to return OK(0) if services do not exist, for
|
||||||
|
integration with openresolv and scripts with similar requirements
|
||||||
|
* Add `initctl plugins`, list installed plugins
|
||||||
|
* Add timestamp to log messages in fallback and logging to `stderr`.
|
||||||
|
When there is no log daemon, and we are running in a container, or we
|
||||||
|
cannot log to the kernel ring buffer, then we log to `stderr`. This
|
||||||
|
change improves log output by prefixing each message with a timestamp.
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* Fix #254: document limitations in `rc.local` and `runparts` scripts
|
||||||
|
* Fix #269: add compulsory kernel symlinks in `/dev`
|
||||||
|
* Fix #275: `initctl status foo` should list all instances, regression
|
||||||
|
introduced in v4.3
|
||||||
|
* Fix #278: enforce conditions also for running `pre:` scripts
|
||||||
|
* Fix #279: allow `restart:always`, of crashing services. Similar to
|
||||||
|
`respawn` but honors `restart_sec`
|
||||||
|
* Fix #280: allow calling `initctl restart foo` from within foo
|
||||||
|
* Fix #283: too quick timeout at bootstrap of lingering tasks
|
||||||
|
* Fix #285: `initctl restart` should start crashed service
|
||||||
|
* Fix #288: enable built-in `sulogin` in Alpine and Void Linux builds
|
||||||
|
* Fix #293: modprobe plugin: support for coldplugging more devices. It
|
||||||
|
turns out, not all buses in Linux add `modalias` attributes to their
|
||||||
|
devices in sysfs. One notable exception are MDIO buses. The plugin's
|
||||||
|
scan routine would thus not pick them up.
|
||||||
|
* Fix #294: `shutdown --help` mistakenly shuts down system
|
||||||
|
* Fix #310: Always use configured restart delay for crashing services.
|
||||||
|
If no delay is configured, default to an initial 2000 msec for forking
|
||||||
|
daemons and start-stop scripts, and 1 msec for non-forking daemons
|
||||||
|
* Fix #311: document how to combine device tree with conditions
|
||||||
|
* Fix #312: restart services with respawn set, e.g. ttys, immediately
|
||||||
|
* Fix #313: Cancel pending restart timer on stop/start/restart/reload
|
||||||
|
* Fix #314: skip run/task/service restart if conditions are lost
|
||||||
|
* Fix #315: add environment variables to hook scripts
|
||||||
|
|
||||||
|
All hook scripts are called with at least one environment variable
|
||||||
|
set, `FINIT_HOOK_NAME`, useful when reusing the same hook script for
|
||||||
|
multiple hook points. It is set to the string name, also used by the
|
||||||
|
path, e.g., `hook/net/up`
|
||||||
|
|
||||||
|
For all hook points from hook/sys/shutdown and later, `FINIT_SHUTDOWN`
|
||||||
|
is also set, to one of: `halt`, `poweroff`, `reboot`
|
||||||
|
|
||||||
|
* Fix #317: make sure hook scripts don't run twice, also fixes #316
|
||||||
|
* Fix #318: only show `[ OK ] Calling foo` progress for `runparts ...`
|
||||||
|
* Fix #320: the API/IPC socket is closed immediately at shutdown/reboot
|
||||||
|
to protect hook scripts or services calling initctl. There is no way
|
||||||
|
to service these requests safely at that time
|
||||||
|
* Fix #333: consider a service dirty if command line args have changed
|
||||||
|
|
||||||
|
This fixes `initctl reload` correctly restarting all daemons that have
|
||||||
|
new command line arguments.
|
||||||
|
|
||||||
|
Previously command line arguments changes were only acted upon if the
|
||||||
|
service was explicitly reloaded `initctl reload myservice`.
|
||||||
|
|
||||||
|
Found and fixed by Jack Newman
|
||||||
|
|
||||||
|
* Fix #338: ensure shutdown hooks are called properly; `hook/sys/down`
|
||||||
|
and `hook/svc/down` hook scripts, found and fixed by Jack Newman
|
||||||
|
* Fix #339: use absolute path in `/etc/finit.d/enabled/` symlinks, for
|
||||||
|
use-cases when `/etc` is read-only and `/etc/finit.d/enabled ->
|
||||||
|
/mnt/finit.d/enabled`, reported by Jack Newman
|
||||||
|
* Fix #340: Finit ignores deleted/moved `.conf` file sin `/etc/finit.d`
|
||||||
|
* Fix #342: in runlevel S (bootstrap), not all `initctl` commands can be
|
||||||
|
supported, block the following: runlevel, reload, start/stop, restart,
|
||||||
|
reload, halt, poweroff, suspend. Also, prevent `SIGHUP` and `SIGUSR1`
|
||||||
|
signals when in shutdown or reboot
|
||||||
|
* Fix #352: separate runlevel S from runlevel 0
|
||||||
|
* Fix #355: regression in v3.2 stopping a process and its group
|
||||||
|
|
||||||
|
In Finit v3.2 a regression was introduced that affects the way Finit
|
||||||
|
stops a supervised process and its process group.
|
||||||
|
|
||||||
|
Instead of sending SIGTERM to the process, and thus delegating the
|
||||||
|
responsibility to that process to inform any children it may have, as
|
||||||
|
of commit 91a9c83 Finit sends SIGTERM to the entire process group.
|
||||||
|
For SIGKILL this is fine, SIGKILL only runs as cleanup and as a last
|
||||||
|
ditch effort if the process doesn't respond to SIGTERM.
|
||||||
|
|
||||||
|
This regression, introduced in v3.2, directly affects services like
|
||||||
|
`avahi-autoipd` that have forked off children that it needs to tell to
|
||||||
|
exit cleanly before it returns. With the patch in question these
|
||||||
|
children are never allowed to complete, which in turn causes lingering
|
||||||
|
169.254 link-local addresses on interfaces.
|
||||||
|
|
||||||
|
* Fix bootmisc plugin: octal permission on `/run/lock` and `/var/lock`
|
||||||
|
|
||||||
|
* Ensure `initctl cond get` support the flux state (exit code 255)
|
||||||
|
* Fix potential socket leak at bootstrap and shutdown
|
||||||
|
* Fix potential NULL pointer deref in kernel command line parser
|
||||||
|
* Fix lingering condition in service after reload of service with new
|
||||||
|
config that has no condition
|
||||||
|
* Fix wrong path to command in service after reload, may have changed
|
||||||
|
* `logit`: fall back to package name if `$LOGNAME` and `$USER` are
|
||||||
|
unset. **Note:** you should probably not use `logit` in your own
|
||||||
|
scripts, it is only meant for internal use by Finit. We recommend
|
||||||
|
using `logger` from the `bsdutils` or `sysklogd` packages instead
|
||||||
|
* Fix issue where `env:`/`pre:`/`post:`/etc. is removed from a service
|
||||||
|
|
||||||
|
The trick is when reloading a service like this:
|
||||||
|
|
||||||
|
service env:/etc/env serv -np -e foo:bar
|
||||||
|
|
||||||
|
into this:
|
||||||
|
|
||||||
|
service pre:/bin/pre.sh serv -np
|
||||||
|
|
||||||
|
In the second the `env:` has been removed and `pre:` added. Prior to
|
||||||
|
this patch, `env:` was kept leading to unintended behavior.
|
||||||
|
* Fix parse/diff of command line args, e.g., `nginx -g 'daemon off;'`
|
||||||
|
|
||||||
|
Starting a service like this works fine:
|
||||||
|
|
||||||
|
service [2345789] env:-/etc/default/nginx nginx -g 'daemon off;'
|
||||||
|
|
||||||
|
However, on `initctl reload` (and no change to .conf files) the arg
|
||||||
|
list was lost while parsing the .conf files. Leading to a false
|
||||||
|
positive 'diff' in args causing nginx to be unnecessarily restarted.
|
||||||
|
* Fix issue with disabled "linewrap" on the console TTY after login.
|
||||||
|
The root cause is `qemu-system-x86_64 -nographics` disabling it when
|
||||||
|
starting up. The correct `\e[?7h` escape code is now used.
|
||||||
|
|
||||||
|
|
||||||
|
[4.3][] - 2022-05-15
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Critical bug fix release. If you run a 32-bit target with GLIBC 2.34
|
||||||
|
you *need* to upgrade!
|
||||||
|
|
||||||
|
> **Note:** system verbosity on console at start and shutdown has been
|
||||||
|
> increased. Now the output of all commands is logged to the
|
||||||
|
> system logger, for early services `/dev/kmsg` is used.
|
||||||
|
>
|
||||||
|
> **Also:** please notice the updated support for enabling and disabling
|
||||||
|
> kernel and Finit debug messages on the system console. Very
|
||||||
|
> useful when debugging either of them, e.g., a kernel module.
|
||||||
|
> For details, see [cmdline.md](doc/cmdline.md).
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
* Support for overriding default runlevel from kernel command line. Any
|
||||||
|
runlevel `[1-9]` may be selected, except 6 (reboot). Issue #261
|
||||||
|
* New command line option: `finit.fstab=/etc/fstab.custom`, with full
|
||||||
|
support for mounting, mount helpers, fsck, and swapon/off, issue #224
|
||||||
|
* Support for special device `/dev/root`, which may not exist in `/dev`.
|
||||||
|
Finit now looks up the matching block device for `/` in `/sys/block/`
|
||||||
|
* Loading `module`s no longer shows arguments in progress output
|
||||||
|
* Warning messages in progress output now in yellow, not red, issue #214
|
||||||
|
* `initctl`, new command line option `-V,--version` for ease of use
|
||||||
|
* New condition `done` for run task, issue #207 by Ming Liu, Atlas Copco
|
||||||
|
* Refactor parts of shutdown and reboot sequence for PREEMPT-RT kernels,
|
||||||
|
by Robert Andersson, Mathias Thore, and Ming Liu, Atlas Copco
|
||||||
|
* Conditions for run/task/sysv status, e.g. `run/foo/success` and
|
||||||
|
`task/bar/failure`. Issue #232, by Ming Liu, Atlas Copco
|
||||||
|
* Conditions for services, can be used to synchronize other stanzas:
|
||||||
|
- `service/foo/running`
|
||||||
|
- `service/foo/halted`
|
||||||
|
- `service/foo/missing`
|
||||||
|
- `service/foo/crashed`
|
||||||
|
- `service/foo/stopped`
|
||||||
|
- `service/foo/busy`
|
||||||
|
- `service/foo/restart`
|
||||||
|
* `initctl signal` support, by Jörgen Sigvardsson, issue #225
|
||||||
|
* `initctl cond get` support to match `cond [set | clear]`, issue #255
|
||||||
|
* `[WARN]` messages on console now printed in yellow, issue #214
|
||||||
|
* Network services now also stopped when going to runlevel 6 (reboot),
|
||||||
|
not just runlevel 0 (shutdown) or 1 (single-user)
|
||||||
|
* When `ifup` is missing on the system, bring at least `lo` up at boot
|
||||||
|
* Log output from `ifup -a` (and `ifdown -a`), to syslog
|
||||||
|
* Avoid blocking PID 1 when starting SysV init scripts
|
||||||
|
* Allow custom `pid:` for SysV init scripts
|
||||||
|
* Document supported types of forking/non-forking services
|
||||||
|
* Auto-detect running in some common forms of containers
|
||||||
|
* Simplify shutdown/reboot when running in a container
|
||||||
|
* Log to `stderr` when running in a container w/o syslog daemon
|
||||||
|
* Add support for `type:forking` to services, already supported but
|
||||||
|
with a very difficult `pid:` syntax, issue #223. Docs updated
|
||||||
|
* Support for setting global environment variables in `finit.conf`,
|
||||||
|
please note: this also affects Finit itself, be careful!
|
||||||
|
* Extended environment variables for pre/post scripts, issue #189
|
||||||
|
* Document secret service option `respawn`, which bypasses the crash
|
||||||
|
semantics, allowing endless restarts
|
||||||
|
* Document secret `HOOK_BANNER`, the first hook point before the banner
|
||||||
|
* Document slightly confusing `initctl reload foo` command. It does
|
||||||
|
*not* reload the service's `.conf` file! Issue #263
|
||||||
|
* Log changes; all instances where previously the `basename cmd` of a
|
||||||
|
service was used to identify the service, now the proper `name:id` is
|
||||||
|
used instead. Meaning, a service without a custom `:ID` or `name:`
|
||||||
|
will display the same as before, but with any of those customizations
|
||||||
|
the name and name:id will now be shown. **Note:** this may affect any
|
||||||
|
log scrapers out there!
|
||||||
|
* New plugin: `hook-scripts`, allows [run-parts(8)][] style scripts to
|
||||||
|
run on any hook point. Contributed by Tobias Waldekranz
|
||||||
|
* `initctl` (`reboot`) falls back to `-f` when it detects it is in
|
||||||
|
`sulogin` recovery mode, issue #247
|
||||||
|
* The bundled `sulogin` is no longer enabled by default, in favor of
|
||||||
|
distribution versions. Enable with `./configure --with-sulogin`
|
||||||
|
* Support args to sysv-like scripts, e.g. `bridge-stp br0 start`
|
||||||
|
* The `modules-load` plugin now skips all lines starting with `#` and
|
||||||
|
`;`. Furthermore, files in `/etc/modules-load.d/*.conf` are now read
|
||||||
|
in lexicographic order and UNIX backup files (`foo.conf~`) are skipped
|
||||||
|
* The `name:id` tuple is now more consistently used in all log and debug
|
||||||
|
messages instead of the basename of the command
|
||||||
|
* Simplify error output of `initctl start/stop/restart/signal`, no more
|
||||||
|
extra usage help, just a plain error message
|
||||||
|
* Exit codes of `initctl` have changed to use LSB script standard and BSD
|
||||||
|
sysexits.h exit codes. As before, a non-zero exit is error or missing
|
||||||
|
* Add support for `initctl -q` to more commands: stop, start, restart,
|
||||||
|
reload, signal, etc.
|
||||||
|
|
||||||
|
[run-parts(8)]: https://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* Fix nasty 32/64-bit alignment issue between finit and its plugins,
|
||||||
|
applicable to 32-bit targets with GLIBC 2.34 and later. External
|
||||||
|
plugins must make sure to use, at least: `-D_TIME_BITS=64`
|
||||||
|
* Fix #215: disable cgroup support at runtime if kernel lacks support
|
||||||
|
or does not have the required controllers (cpu)
|
||||||
|
* Fix #217: iwatcher initialization issue, by Ming Liu, Atlas Copco
|
||||||
|
* Fix #218: initctl matches too many services, by Ming Liu, Atlas Copco
|
||||||
|
* Fix #219: not all filesystems unmounted at shutdown, by Ming Liu,
|
||||||
|
Mathias Thore, and Robert Andersson, Atlas Copco
|
||||||
|
* Fix #226: initctl shows wrong PID for crashing services
|
||||||
|
* Fix #227: reboot stalls if process stopped with `[WARN]`
|
||||||
|
* Fix #233: initctl shows wrong status for run/task, by Sergio Morlans
|
||||||
|
and Ming Liu, Atlas Copco
|
||||||
|
* Fix #248: source `env:file` also in `pre:` and `post` scripts
|
||||||
|
* Fix #260: drop limit on device name in `Checking filesystem...` output
|
||||||
|
* Fix start/stop and monitoring (restart) of SysV init scripts and
|
||||||
|
forking services, see the updated documentation for details
|
||||||
|
* Fix call to `swapoff` at shutdown, does not support `-e` flag
|
||||||
|
* Fix suspend to RAM issue. Previously `reboot(RB_SW_SUSPEND)` was
|
||||||
|
used, now the modern `/sys/power/state` API is used instead.
|
||||||
|
* Fix nasty run/task/service matcher bug, triggered by stanzas using the
|
||||||
|
same basename of a command but different `:ID`. Caused Finit to match
|
||||||
|
with already registered but different run/task/service
|
||||||
|
|
||||||
|
|
||||||
|
[4.2][] - 2022-01-16
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
* Support for non-root users to use `initctl`, e.g. group wheel
|
||||||
|
* Support for new libite (-lite) header namespace
|
||||||
|
* RTC plugin now reset an invalid RTC time to the kernel default
|
||||||
|
time, 2000-01-01 00:00, prevents errors and is less crazy than
|
||||||
|
some systems coming with with <= Jan 1, 1970
|
||||||
|
* urandom plugin now use RNDADDENTROPY ioctl to seed kernel rng,
|
||||||
|
incrementing entropy count. Also, 32 kiB instead of 512 bytes are
|
||||||
|
now saved (and restored) on reboot. This should greatly improve
|
||||||
|
reliability of systems with none or poor HWRNG
|
||||||
|
* Kernel logging to console (loglevel >= 7, debug, when quiet mode is
|
||||||
|
not used) is now honored by Finit, regardless of the finit.debug
|
||||||
|
command line option
|
||||||
|
* Reduced default log level from `LOG_NOTICE` to `LOG_INFO`
|
||||||
|
* Wrapped all calls to mount(2) to add logging in case of failure
|
||||||
|
* New configure options to control fastboot (no fsck) and fsck fix
|
||||||
|
options, by Ming Liu, Atlas Copco
|
||||||
|
* Support for overriding default `/etc/nologin` file with an external
|
||||||
|
`#define`, by Ming Liu, Atlas Copco
|
||||||
|
* Support for overriding default `/var/run/dbus/pid` file with an
|
||||||
|
external `#define`, by Ming Liu, Atlas Copco
|
||||||
|
* Support for more service options to control respawn behavior of
|
||||||
|
crashing services, by Robert Andersson and Ming Liu, Atlas Copco
|
||||||
|
* Support for `initctl ident [NAME]` which lists all instances of
|
||||||
|
`NAME`, or all enabled system run/tasks and services
|
||||||
|
* Show number of total restarts and current respawn count for a
|
||||||
|
service in `initctl status foo`
|
||||||
|
* Crashing services no longer have the crash/restart counter reset as
|
||||||
|
soon as they have stabilized. Instead, a background timer will
|
||||||
|
slowly (every 300 sec) age (decrement) the counter. This will still
|
||||||
|
catch services that "rage quit", but also those that crash after a
|
||||||
|
longer period of activity
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* Fix #180: user managed (`manual:yes`) services accidentally started
|
||||||
|
by `initctl reload`, regression introduced in Finit v4.0
|
||||||
|
* Fix #181: lots of typos all over the tree, by David Yang, Debian
|
||||||
|
* Fix #187: fix typos, incl. small cleanup, in doc/bootstrap.md
|
||||||
|
* Fix #188: support running on kernels that do not have cgroups v2.
|
||||||
|
When this is detect, all functions related to cgroups support in
|
||||||
|
Finit are disabled, *except* the .conf file parser. Hence, you
|
||||||
|
may get parse error if you have invalid cgroup configuration in
|
||||||
|
your Finit .conf files
|
||||||
|
* Fix #197: `initctl status foo` now shows a focused overview of all
|
||||||
|
matching instances; foo:1, foo:2 -- if only one instance matches the
|
||||||
|
command line argument, or if onle one instance exists, the detailed
|
||||||
|
view is shown, as before
|
||||||
|
* Fix #198: a few typos found by Tim Gates
|
||||||
|
* Fix #199: avoid using C++ reserved keywords
|
||||||
|
* Fix #201: memory leak in usr condition plugin, by Ming Liu, Atlas Copco
|
||||||
|
* Fix #203: ensure all filesystems listed in /proc/mounts are properly
|
||||||
|
unumounted on shutdown/reboot, by Robert Andersson, Atlas Copco
|
||||||
|
* Fix #210: resizing terminal (smaller) after boot causes empty lines
|
||||||
|
to be inserted between boot progress
|
||||||
|
* Fix #211: drop hard-coded 32 character limit in getty, now reads
|
||||||
|
`_SC_LOGIN_NAME_MAX` from `sysconf(3)`
|
||||||
|
* Fix #212: service PID file lost after inictl reload, visible from
|
||||||
|
the output from `initctl status foo`
|
||||||
|
|
||||||
|
|
||||||
|
[4.1][] - 2021-06-06
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Bug fix release. Also disables handlers for `SIGINT` and `SIGPWR`, a
|
||||||
|
new set of `sys` conditions are instead generated which can be used to
|
||||||
|
trigger external programs.
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
* Change behavior on SIGUSR1 to be compatible with sysvinit and systemd.
|
||||||
|
Previously SIGUSR1 caused Finit to halt, like BusyBox init. This had
|
||||||
|
"interesting" side effects on Debian systems when coexisting with
|
||||||
|
sysvinit (upgrading/reinstalling causes scripts to `kill -USR1 1`)
|
||||||
|
* Change how `contrib/debian/install.sh` sets up a Grub boot entry for
|
||||||
|
finit. We now modify the $SUPPORTED_INITS variable in `10_linux`
|
||||||
|
* Disable default kernel ctrl-alt-delete handler and let Finit instead
|
||||||
|
catch `SIGINT` from kernel to be able to perform a proper reboot.
|
||||||
|
There is no default command for this, you need to set up a task that
|
||||||
|
triggers on `<sys/key/ctrlaltdel>` to issue `initctl reboot`
|
||||||
|
* Added keventd to provide `<sys/pwr/ac>` condition to Finit. keventd
|
||||||
|
is currently only responsible for monitoring `/sys/class/power_supply`
|
||||||
|
for changes to active AC mains power online status. Enable keventd
|
||||||
|
with `configure --with-keventd`
|
||||||
|
* For handling power fail events (from UPS and similar) a process may
|
||||||
|
send `SIGPWR` to PID 1. Finit no longer redirects this to `SIGUSR1`
|
||||||
|
(poweroff). There is no default command for this, you need to set up
|
||||||
|
a task that triggers on `<sys/pwr/fail>` to issue `initctl poweroff`
|
||||||
|
* Built-in Finit getty is now a standalone program
|
||||||
|
* Default termios for TTYs now enable `IUTF8` on input
|
||||||
|
* If `/bin/login` is not found, Finit now tries `sulogin` before it
|
||||||
|
falls back to an unauthenticated `/bin/sh`
|
||||||
|
* Dropped (broken) support for multiple consoles. Finit now follows
|
||||||
|
the default console selected by the kernel, `/dev/console`
|
||||||
|
* Dropped signal handlers for SIGSTOP/TSTP and SIGCONT
|
||||||
|
* Added support for `\n`, in addition to `\r`, in "Please press Enter"
|
||||||
|
prompt before starting getty
|
||||||
|
* Finit no longer parses `/proc/cmdline` for its options. Instead all
|
||||||
|
options are by default now read from `argv[]`, like a normal program,
|
||||||
|
this is also what the kernel does by default. Please note, this may
|
||||||
|
not work if your systems boots with an initramfs (ymmv), for such
|
||||||
|
cases, see `configure --enable-kernel-cmdline`
|
||||||
|
* The following plugins are now possible to disable (for containers):
|
||||||
|
`rtc.so`, `urandom.so`, you may also want to disable `hotplug.so`.
|
||||||
|
They are all enabled by default, as in Finit 4.0, but may be moved
|
||||||
|
to external tools or entries in `finit.conf` in Finit 5.0
|
||||||
|
* Added support for reading `PRETTY_NAME` from `/etc/os-release` to use
|
||||||
|
as heading in progress output, unless `--with-heading=GREET` is used.
|
||||||
|
* Added manual pages for finit(8), initctl(8), and finit.conf(5)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* Stricter interface name validation in netlink plugin, modeled after
|
||||||
|
the kernel. Suggested by Coverity Scan
|
||||||
|
* Fix problem of re-registering a service as a task. Previously, if a
|
||||||
|
fundamental change, like type, was made to an active service/run/task
|
||||||
|
it did not take. Only possible workaround was to remove from config
|
||||||
|
* initctl: drop warning when removing a non-existing usr condition
|
||||||
|
* initctl: drop confusing `errno 0` when timing out waiting for reply
|
||||||
|
* Ensure services in plugins and from Finit main belong to a cgroup
|
||||||
|
* Ensure init top-level cgroup remains a leaf group
|
||||||
|
* Fix tty parse error for detecting use of external getty
|
||||||
|
* Fix default `name:` and `:ID` for tty's, e.g. `ttyS0` now gives
|
||||||
|
`tty:S0` as expected. This was default for built-in getty already
|
||||||
|
* Fix max username (32 chars) in bundled Finit getty
|
||||||
|
* The `contrib/*/install.sh` scripts failed to run from tarball
|
||||||
|
* Finit no longer forcibly mounts; `/dev`, `/proc`, or `/sys`, instead
|
||||||
|
it checks first if they are already mounted (devtmpfs or container)
|
||||||
|
* Fix `/etc/fstab` parser to properly check for 'ro' to not remount the
|
||||||
|
root filesystem at boot. The wrong field was read, so a root mounted
|
||||||
|
by an initramfs, or by lxc for a container, had their root remounted
|
||||||
|
* Fix SIGCHLD handler, `waitpd()` may be interrupted by a signal
|
||||||
|
* Reset `starting` flag of services being stopped. When a service
|
||||||
|
is started and then stopped before it has created its pid file,
|
||||||
|
it could be left forever in the stopping state, unless we reset
|
||||||
|
the starting flag.
|
||||||
|
* Fix #170: detect loss of default route when interfaces go down. This
|
||||||
|
emulates the missing kernel netlink message to remove the condition
|
||||||
|
net/default/route to allow stopping dependent services
|
||||||
|
* Fix #171: restore automatic mount of `/dev/shm`, `/dev/pts`, `/run`
|
||||||
|
and `/tmp`, unless mounted already by `/etc/fstab`. This is what most
|
||||||
|
desktop systems expect PID 1 to do. Here we also make sure to mount
|
||||||
|
`/run/lock` as a tmpfs as well, with write perms for regular users,
|
||||||
|
this prevents regular users from filling up `/run` and causing DoS.
|
||||||
|
* Fix #173: netlink plugin runs out of socket buffer space;
|
||||||
|
|
||||||
|
finit[1]: nl_callback():recv(): No buffer space available
|
||||||
|
|
||||||
|
Fixed by adding support for resync with kernel on `ENOBUFS`. See
|
||||||
|
netlink(7) for details. As a spin-off the plugin now supports any
|
||||||
|
number of interfaces and routes on a system. On resync, the following
|
||||||
|
message is now logged, as a warning:
|
||||||
|
|
||||||
|
finit[1]: nl_callback():busy system, resynchronizing with kernel.
|
||||||
|
|
||||||
|
* Fix #174: loss of log messages using combo of prio and facility, e.g.,
|
||||||
|
`logit(LOG_CONSOLE | LOG_NOTICE, ...)`, by Jacques de Laval, Westermo
|
||||||
|
* Fix #175: ensure Finit does not acquire a controlling TTY when checking
|
||||||
|
if a device is a TTY before starting a getty. This fixes an old bug
|
||||||
|
where Ctrl-C after logout from a shell could cause PID 1 to get SIGINT,
|
||||||
|
which in turn could lead to a system reboot
|
||||||
|
|
||||||
|
|
||||||
[4.0][] - 2021-04-26
|
[4.0][] - 2021-04-26
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
@@ -84,7 +864,7 @@ make sure to read the whole change log when upgrading.
|
|||||||
- As long as a stepped service changes state we queue another step all
|
- As long as a stepped service changes state we queue another step all
|
||||||
event, because services may depend on each other
|
event, because services may depend on each other
|
||||||
* Require new libuEv API: `uev_init1()` to reduce event cache so that
|
* Require new libuEv API: `uev_init1()` to reduce event cache so that
|
||||||
the kernel can invalidate deleted events before enqueing to userspace
|
the kernel can invalidate deleted events before enqueuing to userspace
|
||||||
* Rename `hwclock.so` plugin to `rtc.so` since it now is stand-alone
|
* Rename `hwclock.so` plugin to `rtc.so` since it now is stand-alone
|
||||||
from the `hwclock` tool. Note: the kernel can also be set to load
|
from the `hwclock` tool. Note: the kernel can also be set to load
|
||||||
and store RTC to/from system clock at boot/halt as well, issue #110
|
and store RTC to/from system clock at boot/halt as well, issue #110
|
||||||
@@ -406,7 +1186,7 @@ Bug fix release.
|
|||||||
|
|
||||||
* Add support for status/show service by `name:id`
|
* Add support for status/show service by `name:id`
|
||||||
* Enforce terse mode after boot, if verbose mode is disabled
|
* Enforce terse mode after boot, if verbose mode is disabled
|
||||||
* Reenable verbose mode at reboot, if disabled at boot
|
* Re-enable verbose mode at reboot, if disabled at boot
|
||||||
* Update section mentioning BusyBox getty
|
* Update section mentioning BusyBox getty
|
||||||
* Update debugging documentation
|
* Update debugging documentation
|
||||||
* Allow debug to override terse mode
|
* Allow debug to override terse mode
|
||||||
@@ -461,7 +1241,7 @@ handling and reconfiguration at runtime.
|
|||||||
* Clarify how to select different plugins with the configure script
|
* Clarify how to select different plugins with the configure script
|
||||||
* Improve urandom plugin for embedded systems w/o random seed
|
* Improve urandom plugin for embedded systems w/o random seed
|
||||||
* Add `--debug` flag to `initctl`
|
* Add `--debug` flag to `initctl`
|
||||||
* The runlevels listed for services in `initctl show` now hightlight the
|
* The runlevels listed for services in `initctl show` now highlight the
|
||||||
active runlevel.
|
active runlevel.
|
||||||
* Clarify in the README and in `initctl help` that the GW event to
|
* Clarify in the README and in `initctl help` that the GW event to
|
||||||
listen for in service declarations is `GW:UP`
|
listen for in service declarations is `GW:UP`
|
||||||
@@ -493,7 +1273,7 @@ handling and reconfiguration at runtime.
|
|||||||
* Do not use `-Os` use `-O2` as default optimization level. Many cross
|
* Do not use `-Os` use `-O2` as default optimization level. Many cross
|
||||||
compiler toolchains are known to have problems with `-Os`
|
compiler toolchains are known to have problems with `-Os`
|
||||||
* Do not allow build VERSION to be overloaded by an environment variable
|
* Do not allow build VERSION to be overloaded by an environment variable
|
||||||
* Fix too small MAX arguments and too few argments in `svc_t` for
|
* Fix too small MAX arguments and too few arguments in `svc_t` for
|
||||||
reading currently running services with `initctl show`
|
reading currently running services with `initctl show`
|
||||||
* Unblock blocked signals after forking off a child
|
* Unblock blocked signals after forking off a child
|
||||||
|
|
||||||
@@ -593,7 +1373,7 @@ The inetd release.
|
|||||||
### Changes
|
### Changes
|
||||||
* Add support for built-in inetd super server -- launch services on
|
* Add support for built-in inetd super server -- launch services on
|
||||||
demand. Supports filtering per interface and custom Inet ports.
|
demand. Supports filtering per interface and custom Inet ports.
|
||||||
* Upgrade to [libuEv] v1.1.0 to better handle error conditions.
|
* Upgrade to [libuEv][] v1.1.0 to better handle error conditions.
|
||||||
* Allow mixed case config directives in `finit.conf`
|
* Allow mixed case config directives in `finit.conf`
|
||||||
* Add support for RFC 868 (rdate) time plugin, start as inetd service.
|
* Add support for RFC 868 (rdate) time plugin, start as inetd service.
|
||||||
* Load plugins before parsing `finit.conf`, this makes it possible to
|
* Load plugins before parsing `finit.conf`, this makes it possible to
|
||||||
@@ -611,7 +1391,7 @@ The inetd release.
|
|||||||
turned out to not work so well after all. For instance, launching
|
turned out to not work so well after all. For instance, launching
|
||||||
TTYs in a background process completely blocked inetd services from
|
TTYs in a background process completely blocked inetd services from
|
||||||
even starting up listening sockets ... proper fork seems to work fine
|
even starting up listening sockets ... proper fork seems to work fine
|
||||||
though. This is the casue for *yanking* the [1.11] release, below.
|
though. This is the cause for *yanking* the [1.11] release, below.
|
||||||
* Trap segfaults caused by external plugins/callbacks in a sub-process.
|
* Trap segfaults caused by external plugins/callbacks in a sub-process.
|
||||||
This prevents a single programming mistake in by a 3rd party developer
|
This prevents a single programming mistake in by a 3rd party developer
|
||||||
from taking down the entire system.
|
from taking down the entire system.
|
||||||
@@ -624,7 +1404,7 @@ The inetd release.
|
|||||||
[1.11][] - 2015-01-24 [YANKED]
|
[1.11][] - 2015-01-24 [YANKED]
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
The [libuEv] release.
|
The [libuEv][] release.
|
||||||
|
|
||||||
**Note:** This release has been *yanked* from distribution due to a
|
**Note:** This release has been *yanked* from distribution due to a
|
||||||
regression in launching background processes and TTY's. Fixed in
|
regression in launching background processes and TTY's. Fixed in
|
||||||
@@ -707,7 +1487,7 @@ Major bug fix release.
|
|||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
* Show `__FILE__` in `_d()` debug messages, useful for plugins with
|
* Show `__FILE__` in `_d()` debug messages, useful for plugins with
|
||||||
similarily named callbacks. Also, only in debug mode anyway
|
similarly named callbacks. Also, only in debug mode anyway
|
||||||
* Make sure to cleanup recorded PID when a service is lost. Required by
|
* Make sure to cleanup recorded PID when a service is lost. Required by
|
||||||
service plugins for their callbacks to work.
|
service plugins for their callbacks to work.
|
||||||
* Only clear screen when in verbose mode. Maybe this should be removed
|
* Only clear screen when in verbose mode. Maybe this should be removed
|
||||||
@@ -875,7 +1655,14 @@ Major bug fix release.
|
|||||||
|
|
||||||
* Initial release
|
* Initial release
|
||||||
|
|
||||||
[UNRELEASED]: https://github.com/troglobit/finit/compare/3.1...HEAD
|
[UNRELEASED]: https://github.com/troglobit/finit/compare/4.7...HEAD
|
||||||
|
[4.7]: https://github.com/troglobit/finit/compare/4.6...4.7
|
||||||
|
[4.6]: https://github.com/troglobit/finit/compare/4.5...4.6
|
||||||
|
[4.5]: https://github.com/troglobit/finit/compare/4.4...4.5
|
||||||
|
[4.4]: https://github.com/troglobit/finit/compare/4.3...4.4
|
||||||
|
[4.3]: https://github.com/troglobit/finit/compare/4.2...4.3
|
||||||
|
[4.2]: https://github.com/troglobit/finit/compare/4.1...4.2
|
||||||
|
[4.1]: https://github.com/troglobit/finit/compare/4.0...4.1
|
||||||
[4.0]: https://github.com/troglobit/finit/compare/3.1...4.0
|
[4.0]: https://github.com/troglobit/finit/compare/3.1...4.0
|
||||||
[3.1]: https://github.com/troglobit/finit/compare/3.0...3.1
|
[3.1]: https://github.com/troglobit/finit/compare/3.0...3.1
|
||||||
[3.0]: https://github.com/troglobit/finit/compare/2.4...3.0
|
[3.0]: https://github.com/troglobit/finit/compare/2.4...3.0
|
||||||
@@ -907,9 +1694,3 @@ Major bug fix release.
|
|||||||
[0.2]: https://github.com/troglobit/finit/compare/0.1...0.2
|
[0.2]: https://github.com/troglobit/finit/compare/0.1...0.2
|
||||||
[libuEv]: https://github.com/troglobit/libuev
|
[libuEv]: https://github.com/troglobit/libuev
|
||||||
[dea3ae8]: https://github.com/troglobit/finit/commit/dea3ae8
|
[dea3ae8]: https://github.com/troglobit/finit/commit/dea3ae8
|
||||||
|
|
||||||
<!--
|
|
||||||
-- Local Variables:
|
|
||||||
-- mode: markdown
|
|
||||||
-- End:
|
|
||||||
-->
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
|
||||||
Copyright (c) 2008-2021 Joachim Wiberg <troglobit@gmail.com>
|
Copyright (c) 2008-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+10
-1
@@ -1,5 +1,5 @@
|
|||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
SUBDIRS = plugins src test
|
SUBDIRS = man plugins src system test tmpfiles.d
|
||||||
doc_DATA = README.md LICENSE contrib/finit.conf
|
doc_DATA = README.md LICENSE contrib/finit.conf
|
||||||
EXTRA_DIST = README.md LICENSE ChangeLog.md contrib/finit.conf
|
EXTRA_DIST = README.md LICENSE ChangeLog.md contrib/finit.conf
|
||||||
|
|
||||||
@@ -10,6 +10,10 @@ if DOC
|
|||||||
SUBDIRS += doc
|
SUBDIRS += doc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if BASH
|
||||||
|
bashdir = $(BASH_DIR)
|
||||||
|
dist_bash_DATA = initctl
|
||||||
|
endif
|
||||||
# Compat hook
|
# Compat hook
|
||||||
install-dev:
|
install-dev:
|
||||||
@make -C src install-pkgincludeHEADERS
|
@make -C src install-pkgincludeHEADERS
|
||||||
@@ -29,3 +33,8 @@ release: distcheck
|
|||||||
printf "$$file.md5\t"; cat ../$$file.md5 | cut -f1 -d' '; \
|
printf "$$file.md5\t"; cat ../$$file.md5 | cut -f1 -d' '; \
|
||||||
printf "$$file.sha256\t"; cat ../$$file.sha256 | cut -f1 -d' '; \
|
printf "$$file.sha256\t"; cat ../$$file.sha256 | cut -f1 -d' '; \
|
||||||
done
|
done
|
||||||
|
|
||||||
|
DISTCHECK_CONFIGURE_FLAGS = --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
|
||||||
|
--enable-testserv-plugin --enable-x11-common-plugin \
|
||||||
|
--with-watchdog --with-keventd --with-fstab=/etc/fstab \
|
||||||
|
--with-bash-completion-dir=no
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
[![License Badge][]][License] [![Travis Status]][Travis] [![Coverity Status]][Coverity Scan]
|
[![License Badge][]][License] [![GitHub Status][]][GitHub] [![Coverity Status][]][Coverity Scan]
|
||||||
<img align="right" src="img/finit3.png" alt="Finit: Fast Init">
|
<img align="right" src="img/finit3.png" alt="Finit: Fast Init">
|
||||||
|
|
||||||
* [Introduction](#introduction)
|
* [Introduction](#introduction)
|
||||||
* [Features](#features)
|
* [Features](#features)
|
||||||
* [Bootstrap](doc/bootstrap.md#bootstrap)
|
|
||||||
* [Runlevels](#runlevels)
|
* [Runlevels](#runlevels)
|
||||||
* [Syntax](doc/config.md#syntax)
|
* [Syntax](doc/config.md#syntax)
|
||||||
* [Runparts & /etc/rc.local](#runparts--etcrclocal)
|
* [Runparts & /etc/rc.local](#runparts--etcrclocal)
|
||||||
@@ -22,22 +21,25 @@
|
|||||||
Introduction
|
Introduction
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Finit is a simple alternative to [SysV init][4] and [systemd][6]. It
|
Fast init for Linux systems. Reverse engineered from the [EeePC
|
||||||
was reverse engineered from the [EeePC fastinit][] over ten years ago
|
fastinit][] by [Claudio Matsuoka][] — "gaps filled with frog DNA …"
|
||||||
by [Claudio Matsuoka][] — "gaps filled with frog DNA …"
|
|
||||||
|
|
||||||

|

|
||||||
*Figure 1: Screenshot showing Finit booting [Alpine Linux](https://www.alpinelinux.org/).*
|
*Figure 1: Screenshot of Finit booting [Alpine Linux (HowTo)](https://github.com/troglobit/finit/tree/master/contrib/alpine).*
|
||||||
|
|
||||||
Features include:
|
Features include:
|
||||||
|
|
||||||
* Runlevels
|
* Runlevels, defined per service
|
||||||
* One-shot tasks, daemons, or SysV init scripts
|
* One-shot tasks, services (daemons), or [SysV init][4] start/stop scripts
|
||||||
* Runparts and rc.local
|
* Runparts and `/etc/rc.local` support
|
||||||
* Process supervision
|
* Process supervision similar to [systemd][]
|
||||||
* Sourcing environment files
|
* Sourcing environment files
|
||||||
* Conditions for network/process/custom dependencies
|
* Conditions for network/process/custom dependencies
|
||||||
|
* Readiness notification; PID files (native) for synchronizing system
|
||||||
|
startup, support for systemd [sd_notify()][], or [s6 style][] too
|
||||||
|
* Limited support for [tmpfiles.d(5)][] (no aging, attributes, or subvolumes)
|
||||||
* Pre/Post script actions
|
* Pre/Post script actions
|
||||||
|
* Rudimentary [templating support](doc/config.md#templating)
|
||||||
* Tooling to enable/disable services
|
* Tooling to enable/disable services
|
||||||
* Built-in getty
|
* Built-in getty
|
||||||
* Built-in watchdog, with support for hand-over to [watchdogd](https://troglobit.com/watchdogd.html)
|
* Built-in watchdog, with support for hand-over to [watchdogd](https://troglobit.com/watchdogd.html)
|
||||||
@@ -45,14 +47,26 @@ Features include:
|
|||||||
* Cgroups v2, both configuration and monitoring in `initctl top`
|
* Cgroups v2, both configuration and monitoring in `initctl top`
|
||||||
* Plugin support for customization
|
* Plugin support for customization
|
||||||
* Proper rescue mode with bundled `sulogin` for protected maintenance shell
|
* Proper rescue mode with bundled `sulogin` for protected maintenance shell
|
||||||
|
* Integration with [watchdogd][] for full system supervision
|
||||||
|
* Logging to kernel ring buffer before `syslogd` has started, see the
|
||||||
|
recommended [sysklogd][] project for complete logging integration
|
||||||
|
and how to log to the kernel ring buffer from scripts using `logger`
|
||||||
|
|
||||||
Focus is on small and embedded systems, although Finit is fully usable
|
Focus is on small and embedded systems, although Finit is fully usable
|
||||||
on server and desktop systems as well. For working examples, see the
|
on server and desktop systems as well. For working examples, see the
|
||||||
[contrib/](contrib/) section with tutorials for:
|
[contrib/](contrib/) section with tutorials for the following Linux
|
||||||
|
distributions:
|
||||||
|
|
||||||
* [Void Linux](contrib/void/),
|
* [Void Linux](contrib/void/),
|
||||||
* [Alpine Linux](contrib/alpine/), and
|
* [Alpine Linux](contrib/alpine/), and
|
||||||
* [Debian GNU/Linux](contrib/debian/)
|
* [Debian GNU/Linux](contrib/debian/), also works on Ubuntu/Linux Mint
|
||||||
|
|
||||||
|
> **Note:** support for various Linux distributions does not mean Finit
|
||||||
|
> installs easily on all architectures. The bundled install scripts are
|
||||||
|
> examples for standard installations, tested on amd64 (x86_64) systems.
|
||||||
|
> Custom setups, e.g., for embedded systems, can be found in any of the
|
||||||
|
> following [Buildroot][] based examples: [myLinux][], [Infix][], or the
|
||||||
|
> plain [br2-finit-demo](https://github.com/troglobit/br2-finit-demo).
|
||||||
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
@@ -61,14 +75,25 @@ Example
|
|||||||
This example `/etc/finit.conf` can also be split up in multiple `.conf`
|
This example `/etc/finit.conf` can also be split up in multiple `.conf`
|
||||||
files in `/etc/finit.d`. Available, but not yet enabled, services can
|
files in `/etc/finit.d`. Available, but not yet enabled, services can
|
||||||
be placed in `/etc/finit.d/available` and enabled by an operator using
|
be placed in `/etc/finit.d/available` and enabled by an operator using
|
||||||
the [initctl](#commands--status) tool.
|
the [initctl](#commands--status) tool. See the above mentioned Linux
|
||||||
|
distributions, or [myLinux][].
|
||||||
|
|
||||||
|
> **Note:** as of Finit v4.4, .conf lines can be broken up using the
|
||||||
|
> standard UNIX continuation character (`\`), also trailing comments are
|
||||||
|
> now supported. The latter means you need to escape any hashes used in
|
||||||
|
> directives and descriptions (`\#`). For more on this and examples,
|
||||||
|
> see the [finit.conf(5)][] manual or [doc/config.md](doc/config.md).
|
||||||
|
|
||||||
```ApacheConf
|
```ApacheConf
|
||||||
# Fallback if /etc/hostname is missing
|
# Fallback if /etc/hostname is missing
|
||||||
host default
|
host default
|
||||||
|
|
||||||
# Runlevel to start after bootstrap, 'S', default: 2
|
# Runlevel to start after bootstrap, 'S', default: 2
|
||||||
runlevel 2
|
#runlevel 2
|
||||||
|
|
||||||
|
# Support for setting global environment variables, using foo=bar syntax
|
||||||
|
# be careful though with variables like PATH, SHELL, LOGNAME, etc.
|
||||||
|
#PATH=/usr/bin:/bin:/usr/sbin:/sbin
|
||||||
|
|
||||||
# Max file size for each log file: 100 kiB, rotate max 4 copies:
|
# Max file size for each log file: 100 kiB, rotate max 4 copies:
|
||||||
# log => log.1 => log.2.gz => log.3.gz => log.4.gz
|
# log => log.1 => log.2.gz => log.3.gz => log.4.gz
|
||||||
@@ -97,6 +122,11 @@ service :8080 [2345] merecat -n -p 8080 /var/www -- Old web server
|
|||||||
#sysv [S] /etc/init.d/acpid -- Starting ACPI Daemon
|
#sysv [S] /etc/init.d/acpid -- Starting ACPI Daemon
|
||||||
#task [S] /etc/init.d/kbd -- Preparing console
|
#task [S] /etc/init.d/kbd -- Preparing console
|
||||||
|
|
||||||
|
# Hidden from boot progress, using empty `--` description
|
||||||
|
#sysv [S] /etc/init.d/keyboard-setup --
|
||||||
|
#sysv [S] /etc/init.d/acpid --
|
||||||
|
#task [S] /etc/init.d/kbd --
|
||||||
|
|
||||||
# Run start scripts from this directory
|
# Run start scripts from this directory
|
||||||
# runparts /etc/start.d
|
# runparts /etc/start.d
|
||||||
|
|
||||||
@@ -119,10 +149,10 @@ some of the most common components needed to start a UNIX daemon:
|
|||||||
|
|
||||||
```
|
```
|
||||||
service [LVLS] <COND> log env:[-]/etc/default/daemon daemon ARGS -- Daemon daemon
|
service [LVLS] <COND> log env:[-]/etc/default/daemon daemon ARGS -- Daemon daemon
|
||||||
^ ^ ^ ^ ^ ^ ^ ^
|
^ ^ ^ ^ ^ ^ ^ ^
|
||||||
| | | | | | | `-- Optional description
|
| | | | | | | `---------- Optional description
|
||||||
| | | | | | `----------- Daemon arguments
|
| | | | | | `------------------ Daemon arguments
|
||||||
| | | | | `-------------------------- Path to daemon
|
| | | | | `------------------------- Path to daemon
|
||||||
| | | | `---------------------------------------------------- Optional env. file
|
| | | | `---------------------------------------------------- Optional env. file
|
||||||
| | | `-------------------------------------------------------- Redirect output to log
|
| | | `-------------------------------------------------------- Redirect output to log
|
||||||
| | `--------------------------------------------------------------- Optional conditions
|
| | `--------------------------------------------------------------- Optional conditions
|
||||||
@@ -134,13 +164,13 @@ Some components are optional: runlevel(s), condition(s) and description,
|
|||||||
making it easy to create simple start scripts and still possible for more
|
making it easy to create simple start scripts and still possible for more
|
||||||
advanced uses as well:
|
advanced uses as well:
|
||||||
|
|
||||||
service sshd -D
|
service /usr/sbin/sshd -D
|
||||||
|
|
||||||
Dependencies are handled using [conditions](doc/conditions.md). One of
|
Dependencies are handled using [conditions](doc/conditions.md). One of
|
||||||
the most common conditions is to wait for basic networking to become
|
the most common conditions is to wait for basic networking to become
|
||||||
available:
|
available:
|
||||||
|
|
||||||
service <net/route/default> nginx -- High performace HTTP server
|
service <net/route/default> nginx -- High performance HTTP server
|
||||||
|
|
||||||
Here is another example where we instruct Finit to not start BusyBox
|
Here is another example where we instruct Finit to not start BusyBox
|
||||||
`ntpd` until `syslogd` has started properly. Finit waits for `syslogd`
|
`ntpd` until `syslogd` has started properly. Finit waits for `syslogd`
|
||||||
@@ -215,13 +245,50 @@ networking here. The configured `runlevel NUM` from `/etc/finit.conf`
|
|||||||
is what Finit changes to after bootstrap, unless 'single' (or 'S') is
|
is what Finit changes to after bootstrap, unless 'single' (or 'S') is
|
||||||
given on the kernel cmdline, in which case runlevel 1 is started.
|
given on the kernel cmdline, in which case runlevel 1 is started.
|
||||||
|
|
||||||
All services in runlevel S(0) are started first, followed by the desired
|
All services in runlevel S) are started first, followed by the desired
|
||||||
run-time runlevel. Run tasks in runlevel S can be started in sequence
|
run-time runlevel. Run tasks in runlevel S can be started in sequence
|
||||||
by using `run [S] cmd`. Changing runlevels at runtime is done like any
|
by using `run [S] cmd`. Changing runlevels at runtime is done like any
|
||||||
other init, e.g. <kbd>init 4</kbd>, but also using the more advanced
|
other init, e.g. <kbd>init 4</kbd>, but also using the more advanced
|
||||||
`intictl` tool.
|
`intictl` tool.
|
||||||
|
|
||||||
|
|
||||||
|
**Conditions**
|
||||||
|
|
||||||
|
As mentioned previously, Finit has an advanced dependency system to
|
||||||
|
handle synchronization, called [conditions](doc/conditions.md). It can
|
||||||
|
be used in many ways; depend on another service, network availability,
|
||||||
|
etc.
|
||||||
|
|
||||||
|
One *really cool* example useful for embedded systems is to run certain
|
||||||
|
scripts if a board has a certain feature encoded in its device tree. At
|
||||||
|
bootstrap we run the following `ident` script:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
#!/bin/sh
|
||||||
|
conddir=/var/run/finit/cond/hw/model
|
||||||
|
dtmodel=/sys/firmware/devicetree/base/model
|
||||||
|
|
||||||
|
if ! test -e $dtmodel; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
model=$(cat $dtmodel | tr "[A-Z] " "[a-z]-")
|
||||||
|
mkdir -p $conddir && ln -s ../../reconf $conddir/$model
|
||||||
|
```
|
||||||
|
|
||||||
|
Provided the device tree node exists, and is a string, we can then use
|
||||||
|
the condition `<hw/model/foo>` when starting other scripts. Here is an
|
||||||
|
example:
|
||||||
|
|
||||||
|
```
|
||||||
|
run [S] /path/to/ident --
|
||||||
|
task [2] <hw/model/foo> /path/to/foo-init -- Initializing Foo board
|
||||||
|
```
|
||||||
|
|
||||||
|
> Notice the trick with an empty description to hide the call to `ident`
|
||||||
|
> in the Finit progress output.
|
||||||
|
|
||||||
|
|
||||||
**Plugins**
|
**Plugins**
|
||||||
|
|
||||||
Plugins can *extend* the functionality of Finit and *hook into* the
|
Plugins can *extend* the functionality of Finit and *hook into* the
|
||||||
@@ -263,8 +330,8 @@ unnecessary overhead, which can be removed at build-time using:
|
|||||||
|
|
||||||
**Cgroups**
|
**Cgroups**
|
||||||
|
|
||||||
Finit supports cgroups v2 and comes with the following default groups
|
Finit supports cgroups v2 and comes with the following default groups in
|
||||||
in which services and user sessions are placed in:
|
which services and user sessions are placed in:
|
||||||
|
|
||||||
/sys/fs/cgroup
|
/sys/fs/cgroup
|
||||||
|-- init/ # cpu.weight:100
|
|-- init/ # cpu.weight:100
|
||||||
@@ -300,6 +367,10 @@ The `initctl` tool has three commands to help debug and optimize the
|
|||||||
setup and monitoring of cgroups. See the `ps`, `top`, and `cgroup`
|
setup and monitoring of cgroups. See the `ps`, `top`, and `cgroup`
|
||||||
commands for details.
|
commands for details.
|
||||||
|
|
||||||
|
> **Note:** systems that do not support cgroups, specifically version 2,
|
||||||
|
> are automatically detected. On such systems the above functionality
|
||||||
|
> is disabled early at boot.
|
||||||
|
|
||||||
|
|
||||||
Runparts & /etc/rc.local
|
Runparts & /etc/rc.local
|
||||||
------------------------
|
------------------------
|
||||||
@@ -320,8 +391,34 @@ Right after the runlevel change when all services have started properly,
|
|||||||
No configuration stanza in `/etc/finit.conf` is required for `rc.local`.
|
No configuration stanza in `/etc/finit.conf` is required for `rc.local`.
|
||||||
If it exists and is an executable shell script Finit calls it at the very
|
If it exists and is an executable shell script Finit calls it at the very
|
||||||
end of the boot, before calling the `HOOK_SYSTEM_UP`. See more on hooks
|
end of the boot, before calling the `HOOK_SYSTEM_UP`. See more on hooks
|
||||||
in [doc/plugins.md](doc/plugins.md#hooks), and about the system bootstrap
|
in [doc/plugins.md](doc/plugins.md#hooks).
|
||||||
in [doc/bootstrap.md](doc/bootstrap.md).
|
|
||||||
|
|
||||||
|
### Limitations
|
||||||
|
|
||||||
|
It is not possible to call Finit via signals or use `initctl` in any
|
||||||
|
runparts or `/etc/rc.local` script. This because Finit is single
|
||||||
|
threaded and is calling these scripts in a blocking fashion at the end
|
||||||
|
of runlevel S, at which point the event loop has not yet been started.
|
||||||
|
|
||||||
|
The event loop is the whole thing which Finit is built around, except
|
||||||
|
for runlevel S, which remains a slow procession through a lot of set up,
|
||||||
|
with a few hooks and blocking call outs to external scripts.
|
||||||
|
|
||||||
|
However, not all `initctl` commands are prohibited, supported commands:
|
||||||
|
are:
|
||||||
|
|
||||||
|
- `inictl cond`: only operate of files in `/run/finit/cond`
|
||||||
|
- `initctl enable/disable`: enabled run/task/service is activated on
|
||||||
|
the runlevel change from S to 2
|
||||||
|
- `initctl touch/show/create/delete/list`: `create`, provided the
|
||||||
|
non-interactive mode is used, again changes take effect in the
|
||||||
|
runlevel change directly after bootstrap
|
||||||
|
- `initctl -f reboot/poweroff/halt`: provided the `-f` flag is used to
|
||||||
|
force direct kernel commands
|
||||||
|
|
||||||
|
**Example:** you can set a `usr/` condition in `/etc/rc.local` and have
|
||||||
|
a service/task in runlevel 2 depend on it to execute.
|
||||||
|
|
||||||
|
|
||||||
Runlevels
|
Runlevels
|
||||||
@@ -409,24 +506,25 @@ services, called `initctl`. Unlike `telinit` the `initctl` tool does
|
|||||||
not return until the given command has fully completed.
|
not return until the given command has fully completed.
|
||||||
|
|
||||||
```
|
```
|
||||||
alpine:~# initctl help
|
|
||||||
Usage: initctl [OPTIONS] [COMMAND]
|
Usage: initctl [OPTIONS] [COMMAND]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-b, --batch Batch mode, no screen size probing
|
-b, --batch Batch mode, no screen size probing
|
||||||
-c, --create Create missing paths (and files) as needed
|
-c, --create Create missing paths (and files) as needed
|
||||||
-f, --force Ignore missing files and arguments, never prompt
|
-f, --force Ignore missing files and arguments, never prompt
|
||||||
|
-h, --help This help text
|
||||||
|
-j, --json JSON output in 'status' and 'cond' commands
|
||||||
-1, --once Only one lap in commands like 'top'
|
-1, --once Only one lap in commands like 'top'
|
||||||
-p, --plain Use plain table headings, no ctrl chars
|
-p, --plain Use plain table headings, no ctrl chars
|
||||||
-q, --quiet Silent, only return status of command
|
-q, --quiet Silent, only return status of command
|
||||||
-t, --no-heading Skip table headings
|
-t, --no-heading Skip table headings
|
||||||
-v, --verbose Verbose output
|
-v, --verbose Verbose output
|
||||||
-h, --help This help text
|
-V, --version Show program version
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
debug Toggle Finit (daemon) debug
|
debug Toggle Finit (daemon) debug
|
||||||
help This help text
|
help This help text
|
||||||
version Show Finit version
|
version Show program version
|
||||||
|
|
||||||
ls | list List all .conf in /etc/finit.d
|
ls | list List all .conf in /etc/finit.d
|
||||||
create <CONF> Create .conf in /etc/finit.d/available
|
create <CONF> Create .conf in /etc/finit.d/available
|
||||||
@@ -438,16 +536,21 @@ Commands:
|
|||||||
disable <CONF> Disable .conf in /etc/finit.d/enabled
|
disable <CONF> Disable .conf in /etc/finit.d/enabled
|
||||||
reload Reload *.conf in /etc/finit.d (activate changes)
|
reload Reload *.conf in /etc/finit.d (activate changes)
|
||||||
|
|
||||||
cond set <COND> Set (assert) user-defined condition +usr/COND
|
cond set <COND> Set (assert) user-defined conditions +usr/COND
|
||||||
cond clear <COND> Clear (deassert) user-defined condition -usr/COND
|
cond get <COND> Get status of user-defined condition, see $? and -v
|
||||||
|
cond clear <COND> Clear (deassert) user-defined conditions -usr/COND
|
||||||
cond status Show condition status, default cond command
|
cond status Show condition status, default cond command
|
||||||
cond dump Dump all conditions and their status
|
cond dump [TYPE] Dump all, or a type of, conditions and their status
|
||||||
|
|
||||||
log [NAME] Show ten last Finit, or NAME, messages from syslog
|
log [NAME] Show ten last Finit, or NAME, messages from syslog
|
||||||
start <NAME>[:ID] Start service by name, with optional ID
|
start <NAME>[:ID] Start service by name, with optional ID
|
||||||
stop <NAME>[:ID] Stop/Pause a running service by name
|
stop <NAME>[:ID] Stop/Pause a running service by name
|
||||||
reload <NAME>[:ID] Reload service by name (SIGHUP or restart)
|
reload <NAME>[:ID] Reload service as if .conf changed (SIGHUP or restart)
|
||||||
|
This allows restart of run/tasks that have already run
|
||||||
|
Note: Finit .conf file(s) are *not* reloaded!
|
||||||
restart <NAME>[:ID] Restart (stop/start) service by name
|
restart <NAME>[:ID] Restart (stop/start) service by name
|
||||||
|
signal <NAME>[:ID] <S> Send signal S to service by name, with optional ID
|
||||||
|
ident [NAME] Show matching identities for NAME, or all
|
||||||
status <NAME>[:ID] Show service status, by name
|
status <NAME>[:ID] Show service status, by name
|
||||||
status Show status of services, default command
|
status Show status of services, default command
|
||||||
|
|
||||||
@@ -455,14 +558,15 @@ Commands:
|
|||||||
ps List processes based on cgroups
|
ps List processes based on cgroups
|
||||||
top Show top-like listing based on cgroups
|
top Show top-like listing based on cgroups
|
||||||
|
|
||||||
|
plugins List installed plugins
|
||||||
|
|
||||||
runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot
|
runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot
|
||||||
reboot Reboot system
|
reboot Reboot system
|
||||||
halt Halt system
|
halt Halt system
|
||||||
poweroff Halt and power off system
|
poweroff Halt and power off system
|
||||||
suspend Suspend system
|
suspend Suspend system
|
||||||
|
|
||||||
Bug report address: https://github.com/troglobit/finit/issues
|
utmp show Raw dump of UTMP/WTMP db
|
||||||
Project homepage: https://troglobit.com/finit.html
|
|
||||||
```
|
```
|
||||||
|
|
||||||
For services *not* supporting `SIGHUP` the `<!>` notation in the .conf
|
For services *not* supporting `SIGHUP` the `<!>` notation in the .conf
|
||||||
@@ -481,24 +585,24 @@ scripting and documentation:
|
|||||||
|
|
||||||
```
|
```
|
||||||
alpine:~# initctl -p
|
alpine:~# initctl -p
|
||||||
PID IDENT STATUS RUNLEVELS DESCRIPTION
|
PID IDENT STATUS RUNLEVELS DESCRIPTION
|
||||||
======================================================================
|
======================================================================
|
||||||
1506 acpid running [--2345----] ACPI daemon
|
1506 acpid running [---2345----] ACPI daemon
|
||||||
1509 crond running [--2345----] Cron daemon
|
1509 crond running [---2345----] Cron daemon
|
||||||
1489 dropbear running [--2345----] Dropbear SSH daemon
|
1489 dropbear running [---2345----] Dropbear SSH daemon
|
||||||
1511 klogd running [S12345----] Kernel log daemon
|
1511 klogd running [S-12345----] Kernel log daemon
|
||||||
1512 ntpd running [--2345----] NTP daemon
|
1512 ntpd running [---2345----] NTP daemon
|
||||||
1473 syslogd running [S12345----] Syslog daemon
|
1473 syslogd running [S-12345----] Syslog daemon
|
||||||
|
|
||||||
alpine:~# initctl -pv
|
alpine:~# initctl -pv
|
||||||
PID IDENT STATUS RUNLEVELS COMMAND
|
PID IDENT STATUS RUNLEVELS COMMAND
|
||||||
======================================================================
|
======================================================================
|
||||||
1506 acpid running [--2345----] acpid -f
|
1506 acpid running [---2345----] acpid -f
|
||||||
1509 crond running [--2345----] crond -f -S $CRON_OPTS
|
1509 crond running [---2345----] crond -f -S $CRON_OPTS
|
||||||
1489 dropbear running [--2345----] dropbear -R -F $DROPBEAR_OPTS
|
1489 dropbear running [---2345----] dropbear -R -F $DROPBEAR_OPTS
|
||||||
1511 klogd running [S12345----] klogd -n $KLOGD_OPTS
|
1511 klogd running [S-12345----] klogd -n $KLOGD_OPTS
|
||||||
1512 ntpd running [--2345----] ntpd -n $NTPD_OPTS
|
1512 ntpd running [---2345----] ntpd -n $NTPD_OPTS
|
||||||
1473 syslogd running [S12345----] syslogd -n
|
1473 syslogd running [S-12345----] syslogd -n
|
||||||
```
|
```
|
||||||
|
|
||||||
The environment variables to each of the services above are read from,
|
The environment variables to each of the services above are read from,
|
||||||
@@ -523,7 +627,7 @@ Condition(s):
|
|||||||
User : root
|
User : root
|
||||||
Group : root
|
Group : root
|
||||||
Uptime : 2 hour 46 min 56 sec
|
Uptime : 2 hour 46 min 56 sec
|
||||||
Runlevels : [--2345----]
|
Runlevels : [---2345----]
|
||||||
Memory : 1.2M
|
Memory : 1.2M
|
||||||
CGroup : /system/dropbear cpu 0 [100, max] mem [--.--, max]
|
CGroup : /system/dropbear cpu 0 [100, max] mem [--.--, max]
|
||||||
|- 1485 dropbear -R -F
|
|- 1485 dropbear -R -F
|
||||||
@@ -574,36 +678,43 @@ This project is based on the [original finit][] by [Claudio Matsuoka][]
|
|||||||
which was reverse engineered from syscalls of the [EeePC fastinit][] —
|
which was reverse engineered from syscalls of the [EeePC fastinit][] —
|
||||||
"gaps filled with frog DNA …"
|
"gaps filled with frog DNA …"
|
||||||
|
|
||||||
Finit is developed and maintained by [Joachim Wiberg][] at [GitHub][].
|
Finit is developed and maintained by [Joachim Wiberg][] at [GitHub][6].
|
||||||
Please file bug reports, clone it, or send pull requests for bug fixes
|
Please file bug reports, clone it, or send pull requests for bug fixes
|
||||||
and proposed extensions.
|
and proposed extensions.
|
||||||
|
|
||||||
|
|
||||||
[1]: https://en.wikipedia.org/wiki/Process_supervision
|
[1]: https://en.wikipedia.org/wiki/Process_supervision
|
||||||
[2]: http://cr.yp.to/daemontools.html
|
[2]: https://cr.yp.to/daemontools.html
|
||||||
[3]: http://smarden.org/runit/
|
[3]: https://smarden.org/runit/
|
||||||
[4]: http://en.wikipedia.org/wiki/Init
|
[4]: https://en.wikipedia.org/wiki/Init
|
||||||
[5]: http://en.wikipedia.org/wiki/Runlevel
|
[5]: https://en.wikipedia.org/wiki/Runlevel
|
||||||
[6]: https://www.freedesktop.org/wiki/Software/systemd/
|
[6]: https://github.com/troglobit/finit
|
||||||
[9]: https://github.com/troglobit/troglos
|
|
||||||
[RFC862]: https://tools.ietf.org/html/rfc862
|
[RFC862]: https://tools.ietf.org/html/rfc862
|
||||||
[RFC863]: https://tools.ietf.org/html/rfc863
|
[RFC863]: https://tools.ietf.org/html/rfc863
|
||||||
[RFC864]: https://tools.ietf.org/html/rfc864
|
[RFC864]: https://tools.ietf.org/html/rfc864
|
||||||
[RFC867]: https://tools.ietf.org/html/rfc867
|
[RFC867]: https://tools.ietf.org/html/rfc867
|
||||||
[RFC868]: https://tools.ietf.org/html/rfc868
|
[RFC868]: https://tools.ietf.org/html/rfc868
|
||||||
[init]: http://en.wikipedia.org/wiki/Init
|
[init]: https://en.wikipedia.org/wiki/Init
|
||||||
[upstart]: http://upstart.ubuntu.com/
|
[upstart]: https://upstart.ubuntu.com/
|
||||||
[systemd]: http://www.freedesktop.org/wiki/Software/systemd/
|
[systemd]: https://www.freedesktop.org/wiki/Software/systemd/
|
||||||
[openrc]: http://www.gentoo.org/proj/en/base/openrc/
|
[openrc]: https://www.gentoo.org/proj/en/base/openrc/
|
||||||
[run-parts(8)]: http://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
[sd_notify()]: https://www.freedesktop.org/software/systemd/man/sd_notify.html
|
||||||
|
[s6 style]: https://skarnet.org/software/s6/notifywhenup.html
|
||||||
|
[run-parts(8)]: https://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
||||||
|
[tmpfiles.d(5)]: https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html
|
||||||
[original finit]: http://helllabs.org/finit/
|
[original finit]: http://helllabs.org/finit/
|
||||||
[EeePC fastinit]: https://web.archive.org/web/20071208212450/http://wiki.eeeuser.com/boot_process:the_boot_process
|
[EeePC fastinit]: https://web.archive.org/web/20071208212450/http://wiki.eeeuser.com/boot_process:the_boot_process
|
||||||
[Claudio Matsuoka]: https://github.com/cmatsuoka
|
[Claudio Matsuoka]: https://github.com/cmatsuoka
|
||||||
[Joachim Wiberg]: http://troglobit.com
|
[Joachim Wiberg]: https://troglobit.com
|
||||||
[GitHub]: https://github.com/troglobit/finit
|
[Buildroot]: https://buildroot.org
|
||||||
|
[Infix]: https://kernelkit.github.io
|
||||||
|
[finit.conf(5)]: https://man.troglobit.com/man5/finit.conf.5.html
|
||||||
[License]: https://en.wikipedia.org/wiki/MIT_License
|
[License]: https://en.wikipedia.org/wiki/MIT_License
|
||||||
[License Badge]: https://img.shields.io/badge/License-MIT-teal.svg
|
[License Badge]: https://img.shields.io/badge/License-MIT-teal.svg
|
||||||
[Travis]: https://travis-ci.org/troglobit/finit
|
[myLinux]: https://github.com/troglobit/myLinux/
|
||||||
[Travis Status]: https://travis-ci.org/troglobit/finit.svg?branch=master
|
[watchdogd]: https://github.com/troglobit/watchdogd/
|
||||||
|
[sysklogd]: https://github.com/troglobit/sysklogd/
|
||||||
|
[GitHub]: https://github.com/troglobit/finit/actions/workflows/build.yml/
|
||||||
|
[GitHub Status]: https://github.com/troglobit/finit/actions/workflows/build.yml/badge.svg
|
||||||
[Coverity Scan]: https://scan.coverity.com/projects/3545
|
[Coverity Scan]: https://scan.coverity.com/projects/3545
|
||||||
[Coverity Status]: https://scan.coverity.com/projects/3545/badge.svg
|
[Coverity Status]: https://scan.coverity.com/projects/3545/badge.svg
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Run test suite with the correct configure params
|
||||||
|
|
||||||
|
make distclean
|
||||||
|
./configure --prefix=/usr --exec-prefix= --sysconfdir=/etc --localstatedir=/var \
|
||||||
|
--enable-x11-common-plugin --with-watchdog --with-keventd
|
||||||
|
make -j17 clean check
|
||||||
+173
-23
@@ -1,20 +1,24 @@
|
|||||||
AC_INIT(Finit, 4.0, https://github.com/troglobit/finit/issues, finit, https://troglobit.com/finit.html)
|
AC_INIT([Finit], [4.7], [https://github.com/troglobit/finit/issues],
|
||||||
|
[finit], [https://troglobit.com/projects/finit/])
|
||||||
AC_CONFIG_AUX_DIR(aux)
|
AC_CONFIG_AUX_DIR(aux)
|
||||||
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects])
|
AM_INIT_AUTOMAKE([1.11 foreign dist-xz subdir-objects])
|
||||||
AM_SILENT_RULES([yes])
|
AM_SILENT_RULES([yes])
|
||||||
|
|
||||||
AC_CONFIG_SRCDIR([src/finit.c])
|
AC_CONFIG_SRCDIR([src/finit.c])
|
||||||
AC_CONFIG_HEADER([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
contrib/Makefile
|
contrib/Makefile
|
||||||
contrib/alpine/Makefile contrib/alpine/finit.d/Makefile contrib/alpine/finit.d/available/Makefile
|
contrib/alpine/Makefile contrib/alpine/finit.d/Makefile contrib/alpine/finit.d/available/Makefile
|
||||||
contrib/debian/Makefile contrib/debian/finit.d/Makefile contrib/debian/finit.d/available/Makefile contrib/debian/grub.d/Makefile
|
contrib/debian/Makefile contrib/debian/finit.d/Makefile contrib/debian/finit.d/available/Makefile
|
||||||
contrib/void/Makefile contrib/void/finit.d/Makefile contrib/void/finit.d/available/Makefile
|
contrib/void/Makefile contrib/void/finit.d/Makefile contrib/void/finit.d/available/Makefile
|
||||||
doc/Makefile
|
doc/Makefile
|
||||||
|
man/Makefile
|
||||||
plugins/Makefile
|
plugins/Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
test/test.env
|
system/Makefile system/10-hotplug.conf
|
||||||
test/Makefile])
|
test/test.env test/Makefile
|
||||||
|
test/lib/Makefile test/src/Makefile
|
||||||
|
tmpfiles.d/Makefile])
|
||||||
|
|
||||||
# Older versions of autoconf (<2.58) do not have AC_CONFIG_MACRO_DIR()
|
# Older versions of autoconf (<2.58) do not have AC_CONFIG_MACRO_DIR()
|
||||||
#m4_include([m4/plugin.m4])
|
#m4_include([m4/plugin.m4])
|
||||||
@@ -31,9 +35,8 @@ AC_PROG_INSTALL
|
|||||||
AC_PROG_MKDIR_P
|
AC_PROG_MKDIR_P
|
||||||
|
|
||||||
# Configuration.
|
# Configuration.
|
||||||
AC_HEADER_STDC
|
AC_CHECK_HEADERS([termios.h sys/ioctl.h mntent.h sys/sysmacros.h])
|
||||||
AC_CHECK_HEADERS([fstaby.h termios.h sys/ioctl.h])
|
AC_CHECK_FUNCS([strstr getopt getmntent getmntent_r])
|
||||||
AC_CHECK_FUNCS([strstr getopt getfsenty])
|
|
||||||
|
|
||||||
# Check for uint[8,16,32]_t
|
# Check for uint[8,16,32]_t
|
||||||
AC_TYPE_UINT8_T
|
AC_TYPE_UINT8_T
|
||||||
@@ -52,12 +55,24 @@ AC_ARG_ENABLE(auto_reload,
|
|||||||
AS_HELP_STRING([--enable-auto-reload], [Automatic reload on any .conf change]),,[
|
AS_HELP_STRING([--enable-auto-reload], [Automatic reload on any .conf change]),,[
|
||||||
enable_auto_reload=no])
|
enable_auto_reload=no])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(kernel_cmdline,
|
||||||
|
AS_HELP_STRING([--enable-kernel-cmdline], [Parse init args from /proc/cmdline (don't use!)]),,[
|
||||||
|
enable_kernel_cmdline=no])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(fastboot,
|
||||||
|
AS_HELP_STRING([--enable-fastboot], [Skip fsck check on filesystems listed in /etc/fstab]),,[
|
||||||
|
enable_fastboot=no])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(fsckfix,
|
||||||
|
AS_HELP_STRING([--enable-fsckfix], [Run fsck fix mode (options: -yf) on filesystems listed in /etc/fstab]),,[
|
||||||
|
enable_fsckfix=no])
|
||||||
|
|
||||||
AC_ARG_ENABLE(redirect,
|
AC_ARG_ENABLE(redirect,
|
||||||
AS_HELP_STRING([--disable-redirect], [Disable redirection of service output to /dev/null]),,[
|
AS_HELP_STRING([--disable-redirect], [Disable redirection of service output to /dev/null]),,[
|
||||||
enable_redirect=yes])
|
enable_redirect=yes])
|
||||||
|
|
||||||
AC_ARG_ENABLE(logrotate,
|
AC_ARG_ENABLE(logrotate,
|
||||||
AS_HELP_STRING([--disable-logrotate], [Disable built-in rotation of /var/log/wtmp, default enabled]),,[
|
AS_HELP_STRING([--disable-logrotate], [Disable built-in rotation of /var/log/wtmp]),,[
|
||||||
enable_logrotate=yes])
|
enable_logrotate=yes])
|
||||||
|
|
||||||
AC_ARG_ENABLE(doc,
|
AC_ARG_ENABLE(doc,
|
||||||
@@ -68,19 +83,39 @@ AC_ARG_ENABLE(contrib,
|
|||||||
AS_HELP_STRING([--disable-contrib], [Disable build and install of contrib section]),,[
|
AS_HELP_STRING([--disable-contrib], [Disable build and install of contrib section]),,[
|
||||||
enable_contrib=yes])
|
enable_contrib=yes])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([rescue],
|
||||||
|
AS_HELP_STRING([--disable-rescue], [Disable potentially unsafe rescue mode]),,
|
||||||
|
[enable_rescue=yes])
|
||||||
|
|
||||||
# Check for extra plugins to enable
|
# Check for extra plugins to enable
|
||||||
enable_all_plugins=auto
|
AC_ARG_ENABLE(all_plugins,
|
||||||
|
AS_HELP_STRING([--enable-all-plugins], [Enable all plugins, default: auto]),
|
||||||
|
enable_all_plugins=$enableval, enable_all_plugins=auto)
|
||||||
AC_PLUGIN([alsa-utils], [no], [Save and restore ALSA sound settings using alsactl])
|
AC_PLUGIN([alsa-utils], [no], [Save and restore ALSA sound settings using alsactl])
|
||||||
AC_PLUGIN([dbus], [no], [Setup and start system message bus, D-Bus])
|
AC_PLUGIN([dbus], [no], [Setup and start system message bus, D-Bus])
|
||||||
AC_PLUGIN([modules-load], [no], [Scans /etc/modules-load.d for modules to load])
|
AC_PLUGIN([modules-load], [no], [Scans /etc/modules-load.d for modules to load])
|
||||||
|
AC_PLUGIN([modprobe], [no], [Coldplug modules using modalias magic])
|
||||||
AC_PLUGIN([resolvconf], [no], [Setup necessary files for resolvconf])
|
AC_PLUGIN([resolvconf], [no], [Setup necessary files for resolvconf])
|
||||||
AC_PLUGIN([x11-common], [no], [Console setup (for X)])
|
AC_PLUGIN([x11-common], [no], [Console setup (for X)])
|
||||||
AC_PLUGIN([netlink], [yes], [Basic netlink plugin for IFUP/IFDN and GW events. Can be replaced with externally built plugin that links with libnl or similar.])
|
AC_PLUGIN([netlink], [yes], [Basic netlink plugin for IFUP/IFDN and GW events. Can be replaced with externally built plugin that links with libnl or similar.])
|
||||||
AC_PLUGIN([hotplug], [yes], [Setup and start udev or mdev hotplug daemon])
|
AC_PLUGIN([hook-scripts], [no], [Trigger script execution from hook points])
|
||||||
|
AC_PLUGIN([hotplug], [yes], [Start udevd or mdev kernel event datamon])
|
||||||
|
AC_PLUGIN([rtc], [yes], [Save and restore RTC using hwclock])
|
||||||
|
AC_PLUGIN([tty], [yes], [Automatically activate new TTYs, e.g. USB-to-serial])
|
||||||
|
AC_PLUGIN([urandom], [yes], [Setup and save random seed at boot/shutdown])
|
||||||
|
AC_PLUGIN([testserv], [no], [Test plugin to start test serv daemon])
|
||||||
|
|
||||||
# Check for extra arguments or packages
|
# Check for extra arguments or packages
|
||||||
|
AC_ARG_WITH([bash-completion-dir],
|
||||||
|
AS_HELP_STRING([--with-bash-completion-dir[=PATH]], [Directory to install Bash completion, default: auto]),
|
||||||
|
[bash_dir=$withval], [bash_dir=yes])
|
||||||
|
|
||||||
|
AC_ARG_WITH(fstab,
|
||||||
|
AS_HELP_STRING([--with-fstab=FILE], [System default fstab, default $sysconfdir/fstab]),
|
||||||
|
[fstab=$withval], [fstab=yes])
|
||||||
|
|
||||||
AC_ARG_WITH(heading,
|
AC_ARG_WITH(heading,
|
||||||
AS_HELP_STRING([--with-heading=GREET], [Display GREET instead of Finit version at boot]),
|
AS_HELP_STRING([--with-heading=GREET], [Heading for boot progress. Default: PRETTY_NAME from /etc/os-release, fallback to "Finit vX.YY"]),
|
||||||
[heading=$withval], [heading=yes])
|
[heading=$withval], [heading=yes])
|
||||||
|
|
||||||
AC_ARG_WITH(config,
|
AC_ARG_WITH(config,
|
||||||
@@ -99,28 +134,59 @@ AC_ARG_WITH(sysconfig,
|
|||||||
AS_HELP_STRING([--with-sysconfig=DIR], [System environment directory, sourced by .conf files, default /etc/default & /etc/conf.d]),
|
AS_HELP_STRING([--with-sysconfig=DIR], [System environment directory, sourced by .conf files, default /etc/default & /etc/conf.d]),
|
||||||
[sysconfig=$withval], [sysconfig=default])
|
[sysconfig=$withval], [sysconfig=default])
|
||||||
|
|
||||||
|
AC_ARG_WITH(group,
|
||||||
|
AS_HELP_STRING([--with-group=NAME], [Group for /run/finit/socket (initctl), default: root]),
|
||||||
|
[group=$withval], [group=root])
|
||||||
|
|
||||||
AC_ARG_WITH(hostname,
|
AC_ARG_WITH(hostname,
|
||||||
AS_HELP_STRING([--with-hostname=NAME], [If /etc/hostname is missing, default: noname]),
|
AS_HELP_STRING([--with-hostname=NAME], [If /etc/hostname is missing, default: noname]),
|
||||||
[hostname=$withval], [hostname=yes])
|
[hostname=$withval], [hostname=yes])
|
||||||
|
|
||||||
AC_ARG_WITH(runlevel,
|
AC_ARG_WITH(runlevel,
|
||||||
AS_HELP_STRING([--with-runlevel=N], [Runlevel to switch to after bootstrap, default: 2]),
|
AS_HELP_STRING([--with-runlevel=N], [Runlevel to switch to after bootstrap [1-9], default: 2]),
|
||||||
[runlevel=$withval], [runlevel=yes])
|
[runlevel=$withval], [runlevel=yes])
|
||||||
|
|
||||||
AC_ARG_WITH(random-seed,
|
AC_ARG_WITH(random-seed,
|
||||||
AS_HELP_STRING([--with-random-seed=FILE], [Save a random seed for /dev/urandom across reboots, default /var/lib/misc/random-seed]),
|
AS_HELP_STRING([--with-random-seed=FILE], [Save a random seed for /dev/urandom across reboots, default /var/lib/misc/random-seed]),
|
||||||
[random_seed=$withval], [random_seed=yes])
|
[random_seed=$withval], [random_seed=yes])
|
||||||
|
|
||||||
|
AC_ARG_WITH(keventd,
|
||||||
|
AS_HELP_STRING([--with-keventd], [Enable built-in keventd, default: no]),, [with_keventd=no])
|
||||||
|
|
||||||
|
AC_ARG_WITH(sulogin,
|
||||||
|
AS_HELP_STRING([--with-sulogin@<:@=USER@:>@], [Enable built-in sulogin, optional USER to request password for (default root), default: no.]),[sulogin=$withval],[with_sulogin=no])
|
||||||
|
|
||||||
AC_ARG_WITH(watchdog,
|
AC_ARG_WITH(watchdog,
|
||||||
AS_HELP_STRING([--with-watchdog=[DEV]], [Enable built-in watchdog, default: /dev/watchdog]),
|
AS_HELP_STRING([--with-watchdog@<:@=DEV@:>@], [Enable built-in watchdog, default: /dev/watchdog]),
|
||||||
[watchdog=$withval], [with_watchdog=no watchdog=])
|
[watchdog=$withval], [with_watchdog=no watchdog=])
|
||||||
|
|
||||||
|
AC_ARG_WITH(hook-scripts-path,
|
||||||
|
AS_HELP_STRING([--with-hook-scripts-path=DIR], [Base directory for hook scripts, default $libexecdir/finit/hook]),
|
||||||
|
[hook_scripts_path=$withval], [hook_scripts_path=yes])
|
||||||
|
|
||||||
|
AC_ARG_WITH(plugin-path,
|
||||||
|
AS_HELP_STRING([--with-plugin-path=DIR], [Search path for external plugins, default /usr/lib/finit/plugins:/usr/local/lib/finit/plugins]),
|
||||||
|
[plugin_path=$withval], [plugin_path=yes])
|
||||||
|
|
||||||
|
AC_ARG_WITH(rtc-date,
|
||||||
|
AS_HELP_STRING([--with-rtc-date=DATE], [If RTC date/time is too old, restore to DATE, format "YYYY-MM-DD HH:MM", default "2000-01-01 00:00"]),
|
||||||
|
[rtc_date=$withval], [rtc_date=no])
|
||||||
|
|
||||||
### Enable features ###########################################################################
|
### Enable features ###########################################################################
|
||||||
|
|
||||||
# Create config.h from selected features and fallback defaults
|
# Create config.h from selected features and fallback defaults
|
||||||
AS_IF([test "x$enable_auto_reload" = "xyes"], [
|
AS_IF([test "x$enable_auto_reload" = "xyes"], [
|
||||||
AC_DEFINE(AUTO_RELOAD, 1, [Finit automatically does `initctl reload` on any .conf change])])
|
AC_DEFINE(AUTO_RELOAD, 1, [Finit automatically does `initctl reload` on any .conf change])])
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_kernel_cmdline" = "xyes"], [
|
||||||
|
AC_DEFINE(KERNEL_CMDLINE, 1, [Dumpster diving after init args from /proc/cmdline])])
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_fastboot" = "xyes"], [
|
||||||
|
AC_DEFINE(FAST_BOOT, 1, [Skip fsck check on filesystems listed in /etc/fstab])])
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_fsckfix" = "xyes"], [
|
||||||
|
AC_DEFINE(FSCK_FIX, 1, [Run fsck fix mode (options: -yf) on filesystems listed in /etc/fstab])])
|
||||||
|
|
||||||
AS_IF([test "x$enable_redirect" = "xyes"], [
|
AS_IF([test "x$enable_redirect" = "xyes"], [
|
||||||
AC_DEFINE(REDIRECT_OUTPUT, 1, [Enable redirection of service output to /dev/null])])
|
AC_DEFINE(REDIRECT_OUTPUT, 1, [Enable redirection of service output to /dev/null])])
|
||||||
|
|
||||||
@@ -128,9 +194,24 @@ AS_IF([test "x$enable_redirect" = "xyes"], [
|
|||||||
AS_IF([test "x$enable_logrotate" != "xno"], [
|
AS_IF([test "x$enable_logrotate" != "xno"], [
|
||||||
AC_DEFINE(LOGROTATE_ENABLED, 1, [Enable built-in rotation of /var/log/wtmp et al.])])
|
AC_DEFINE(LOGROTATE_ENABLED, 1, [Enable built-in rotation of /var/log/wtmp et al.])])
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_rescue" != "xno"], [
|
||||||
|
AC_DEFINE([RESCUE_MODE], 1, [Define to enable support for rescue mode.])])
|
||||||
|
|
||||||
AM_CONDITIONAL(LOGROTATE, [test "x$enable_logrotate" = "xyes"])
|
AM_CONDITIONAL(LOGROTATE, [test "x$enable_logrotate" = "xyes"])
|
||||||
|
|
||||||
### With features ##############################################################################
|
### With features ##############################################################################
|
||||||
|
AS_IF([test "x$bash_dir" = "xyes"], [
|
||||||
|
PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0],
|
||||||
|
[BASH_DIR="$(pkg-config --variable=completionsdir bash-completion)"],
|
||||||
|
[BASH_DIR="$datadir/bash-completion/completions"])], [
|
||||||
|
BASH_DIR="$bash_dir"])
|
||||||
|
|
||||||
|
AS_IF([test "x$with_fstab" != "xno"], [
|
||||||
|
AS_IF([test "x$fstab" = "xyes"], [fstab=$sysconfdir/fstab])
|
||||||
|
AC_EXPAND_DIR(fstab_path, "$fstab")
|
||||||
|
AC_DEFINE_UNQUOTED(FINIT_FSTAB, "$fstab_path", [Built-in default: /etc/fstab])],[
|
||||||
|
AC_DEFINE_UNQUOTED(FINIT_FSTAB, NULL, [No built-in default fstab])])
|
||||||
|
|
||||||
AS_IF([test "x$with_config" != "xno"], [
|
AS_IF([test "x$with_config" != "xno"], [
|
||||||
AS_IF([test "x$conf" = "xyes"], [
|
AS_IF([test "x$conf" = "xyes"], [
|
||||||
conf=$sysconfdir/finit.conf])])
|
conf=$sysconfdir/finit.conf])])
|
||||||
@@ -158,9 +239,13 @@ AS_IF([test "x$with_sysconfig" != "xno"], [
|
|||||||
[System environment, default /etc/default & /etc/conf.d])])])
|
[System environment, default /etc/default & /etc/conf.d])])])
|
||||||
|
|
||||||
AS_IF([test "x$with_heading" != "xno"], [
|
AS_IF([test "x$with_heading" != "xno"], [
|
||||||
AS_IF([test "x$heading" = "xyes"], [
|
AS_IF([test "x$heading" = "xyes"], [heading=""])
|
||||||
heading="$PACKAGE_NAME v$PACKAGE_VERSION"])])
|
AC_DEFINE_UNQUOTED(INIT_OSHEADING, "$heading", [Displayed by Finit at boot, defaults to /etc/os-release PRETTY_NAME])])
|
||||||
AC_DEFINE_UNQUOTED(INIT_HEADING, "$heading", [Displayed by Finit at boot])
|
|
||||||
|
AS_IF([test "x$with_group" != "xno"], [
|
||||||
|
AS_IF([test "x$group" = "xyes"], [
|
||||||
|
group=root])])
|
||||||
|
AC_DEFINE_UNQUOTED(DEFGROUP, "$group", [For /run/finit/socket])
|
||||||
|
|
||||||
AS_IF([test "x$with_hostname" != "xno"], [
|
AS_IF([test "x$with_hostname" != "xno"], [
|
||||||
AS_IF([test "x$hostname" = "xyes"], [
|
AS_IF([test "x$hostname" = "xyes"], [
|
||||||
@@ -179,6 +264,19 @@ AS_IF([test "x$with_random_seed" != "xno"], [
|
|||||||
AC_EXPAND_DIR(random_path, "$random_seed")
|
AC_EXPAND_DIR(random_path, "$random_seed")
|
||||||
AC_DEFINE_UNQUOTED(RANDOMSEED, "$random_path", [Improve random at boot by seeding it with sth from before.])])
|
AC_DEFINE_UNQUOTED(RANDOMSEED, "$random_path", [Improve random at boot by seeding it with sth from before.])])
|
||||||
|
|
||||||
|
AS_IF([test "x$rtc_date" != "xno"], [
|
||||||
|
AC_DEFINE(RTC_TIMESTAMP_CUSTOM, "$rtc_date", [Custom RTC restore date, default: 2000-01-01 00:00])], [
|
||||||
|
rtc_date=""])
|
||||||
|
|
||||||
|
AS_IF([test "x$with_keventd" != "xno"], [with_keventd=yes])
|
||||||
|
|
||||||
|
AS_IF([test "x$with_sulogin" != "xno"], [
|
||||||
|
AS_IF([test "x$sulogin" = "xyes"], [
|
||||||
|
sulogin=root])
|
||||||
|
with_sulogin=yes
|
||||||
|
AC_DEFINE_UNQUOTED(SULOGIN_USER, "$sulogin", [Built-in sulogin user, default: root])], [
|
||||||
|
sulogin=])
|
||||||
|
|
||||||
AS_IF([test "x$with_watchdog" != "xno"], [
|
AS_IF([test "x$with_watchdog" != "xno"], [
|
||||||
AS_IF([test "x$watchdog" = "xyes"], [
|
AS_IF([test "x$watchdog" = "xyes"], [
|
||||||
watchdog=/dev/watchdog])
|
watchdog=/dev/watchdog])
|
||||||
@@ -186,27 +284,70 @@ AS_IF([test "x$with_watchdog" != "xno"], [
|
|||||||
AC_DEFINE_UNQUOTED(WDT_DEVNODE, "$watchdog", [Built-in watchdog device node])], [
|
AC_DEFINE_UNQUOTED(WDT_DEVNODE, "$watchdog", [Built-in watchdog device node])], [
|
||||||
watchdog=])
|
watchdog=])
|
||||||
|
|
||||||
|
AS_IF([test "x$enable_hook_scripts_plugin" != "xno"], [
|
||||||
|
AS_IF([test "x$hook_scripts_path" = "xyes"], [hook_scripts_path=$libexecdir/finit/hook])
|
||||||
|
AC_EXPAND_DIR(hook_scripts_path, "$hook_scripts_path")
|
||||||
|
AC_DEFINE_UNQUOTED(PLUGIN_HOOK_SCRIPTS_PATH, "$hook_scripts_path", [Built-in default: $libexecdir/finit])])
|
||||||
|
|
||||||
|
AS_IF([test "x$with_plugin_path" != "xno"], [
|
||||||
|
AS_IF([test "x$plugin_path" = "xyes"], [plugin_path=/usr/lib/finit/plugins:/usr/local/lib/finit/plugins])
|
||||||
|
AC_EXPAND_DIR(plugin_path, "$plugin_path")
|
||||||
|
AC_DEFINE_UNQUOTED(EXTERNAL_PLUGIN_PATH, "$plugin_path", [Built-in default: /usr/lib/finit/plugins:/usr/local/lib/finit/plugins])])
|
||||||
|
|
||||||
# Control build with automake flags
|
# Control build with automake flags
|
||||||
AM_CONDITIONAL(STATIC, [test "x$enable_static" = "xyes"])
|
AM_CONDITIONAL(BASH, [test "x$bash_dir" != "xno"])
|
||||||
|
AM_CONDITIONAL(STATIC, [test "x$enable_static" = "xyes"])
|
||||||
|
AM_CONDITIONAL(KEVENTD, [test "x$with_keventd" != "xno"])
|
||||||
|
AM_CONDITIONAL(SULOGIN, [test "x$with_sulogin" != "xno"])
|
||||||
AM_CONDITIONAL(WATCHDOGD, [test "x$with_watchdog" != "xno"])
|
AM_CONDITIONAL(WATCHDOGD, [test "x$with_watchdog" != "xno"])
|
||||||
AM_CONDITIONAL(DOC, [test "x$enable_doc" = "xyes"])
|
AM_CONDITIONAL(DOC, [test "x$enable_doc" = "xyes"])
|
||||||
AM_CONDITIONAL(CONTRIB, [test "x$enable_contrib" = "xyes"])
|
AM_CONDITIONAL(CONTRIB, [test "x$enable_contrib" = "xyes"])
|
||||||
|
AM_CONDITIONAL(TESTSERV, [test "x$enable_testserv_plugin" = "xyes"])
|
||||||
|
|
||||||
|
# Workaround for as-of-yet unreleased runstatedir support, planned for
|
||||||
|
# autoconf 2.70, which some major distros have backported.
|
||||||
|
AS_IF([test -z "$runstatedir"], runstatedir="$localstatedir/run")
|
||||||
|
AC_SUBST(runstatedir)
|
||||||
|
|
||||||
# Override default libdir, used for plugins and rescue.conf
|
# Override default libdir, used for plugins and rescue.conf
|
||||||
pkglibdir=$libdir/finit
|
pkglibdir=$libdir/finit
|
||||||
AC_SUBST(pkglibexecdir)
|
AC_SUBST(pkglibexecdir)
|
||||||
AC_EXPAND_DIR(pkglibexecdir, "$libexecdir/finit")
|
AC_EXPAND_DIR(pkglibexecdir, "$libexecdir/finit")
|
||||||
AC_DEFINE_UNQUOTED(FINIT_LIBPATH_, "$pkglibexecdir", [Finit libexec path])
|
AC_DEFINE_UNQUOTED(FINIT_EXECPATH_, "$pkglibexecdir", [Finit libexec path])
|
||||||
|
AC_EXPAND_DIR(finit_runpath, "$runstatedir/finit/system")
|
||||||
|
AC_DEFINE_UNQUOTED(FINIT_RUNPATH_, "$finit_runpath", [Finit runtime dynamic system services])
|
||||||
|
|
||||||
AC_EXPAND_DIR(plugin_path, "$libdir/finit/plugins")
|
AC_EXPAND_DIR(plugin_path, "$pkglibdir/plugins")
|
||||||
AC_SUBST(plugin_path)
|
AC_SUBST(plugin_path)
|
||||||
AC_DEFINE_UNQUOTED(PLUGIN_PATH, "$plugin_path", [Finit plugin path])
|
AC_DEFINE_UNQUOTED(PLUGIN_PATH, "$plugin_path", [Finit plugin path])
|
||||||
|
|
||||||
AC_EXPAND_DIR(rescue_conf, "$libdir/finit/rescue.conf")
|
AC_EXPAND_DIR(tmpfiles_path, "$libdir/tmpfiles.d")
|
||||||
|
AC_SUBST(tmpfiles_path)
|
||||||
|
AC_DEFINE_UNQUOTED(TMPFILES_PATH_, "$tmpfiles_path", [Main tmpfiles.d/, override in /etc])
|
||||||
|
|
||||||
|
AC_EXPAND_DIR(finit_tmpfiles, "$pkglibdir/tmpfiles.d")
|
||||||
|
AC_SUBST(finit_tmpfiles)
|
||||||
|
AC_DEFINE_UNQUOTED(FINIT_TMPFILES, "$finit_tmpfiles", [Finit tmpfiles.d/ .conf path])
|
||||||
|
|
||||||
|
AC_EXPAND_DIR(system_path, "$pkglibdir/system")
|
||||||
|
AC_SUBST(system_path)
|
||||||
|
AC_DEFINE_UNQUOTED(FINIT_SYSPATH_, "$system_path", [Static services, previously generated at runtime by plugins])
|
||||||
|
|
||||||
|
AC_EXPAND_DIR(rescue_conf, "$pkglibdir/rescue.conf")
|
||||||
AC_DEFINE_UNQUOTED(RESCUE_CONF, "$rescue_conf", [Finit rescue mode .conf])
|
AC_DEFINE_UNQUOTED(RESCUE_CONF, "$rescue_conf", [Finit rescue mode .conf])
|
||||||
AC_EXPAND_DIR(sample_conf, "$libdir/finit/sample.conf")
|
AC_EXPAND_DIR(sample_conf, "$pkglibdir/sample.conf")
|
||||||
AC_DEFINE_UNQUOTED(SAMPLE_CONF, "$sample_conf", [Finit sameple.conf for initctl create])
|
AC_DEFINE_UNQUOTED(SAMPLE_CONF, "$sample_conf", [Finit sameple.conf for initctl create])
|
||||||
|
|
||||||
|
AC_EXPAND_DIR(bash_completion_dir, "$BASH_DIR")
|
||||||
|
AC_SUBST(BASH_DIR, "$bash_completion_dir")
|
||||||
|
|
||||||
|
AS_IF([test "$heading" = ""], [heading="<DEFAULT>"])
|
||||||
|
AS_IF([test "$heading" = "no"], [heading="<NONE>"])
|
||||||
|
|
||||||
|
RTC_DATE=$rtc_date
|
||||||
|
AS_IF([test "$rtc_date" = ""], [RTC_DATE="<DEFAULT>"])
|
||||||
|
AS_IF([test "$rtc_date" = "no"], [RTC_DATE="<DEFAULT>"])
|
||||||
|
|
||||||
# Generate all files
|
# Generate all files
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
||||||
@@ -218,6 +359,7 @@ cat <<EOF
|
|||||||
Exec prefix...........: $eprefix
|
Exec prefix...........: $eprefix
|
||||||
Sysconfdir............: `eval echo $sysconfdir`
|
Sysconfdir............: `eval echo $sysconfdir`
|
||||||
Localstatedir.........: `eval echo $localstatedir`
|
Localstatedir.........: `eval echo $localstatedir`
|
||||||
|
Default fstab.........: `eval echo $fstab`
|
||||||
Finit config file.....: $conf_path
|
Finit config file.....: $conf_path
|
||||||
Finit config.d path...: $rcsd_path
|
Finit config.d path...: $rcsd_path
|
||||||
Finit plugin path.....: $plugin_path
|
Finit plugin path.....: $plugin_path
|
||||||
@@ -230,14 +372,22 @@ cat <<EOF
|
|||||||
Behavior:
|
Behavior:
|
||||||
Boot heading..........: $heading
|
Boot heading..........: $heading
|
||||||
Plugins...............: $plugins
|
Plugins...............: $plugins
|
||||||
|
RTC restore date......: $RTC_DATE
|
||||||
|
|
||||||
Optional features:
|
Optional features:
|
||||||
Install doc/..........: $enable_doc
|
Install doc/..........: $enable_doc
|
||||||
Install contrib/......: $enable_contrib
|
Install contrib/......: $enable_contrib
|
||||||
|
Bash completion.......: $bash_completion_dir
|
||||||
|
Built-in keventd......: $with_keventd
|
||||||
|
Built-in sulogin......: $with_sulogin $sulogin
|
||||||
Built-in watchdogd....: $with_watchdog $watchdog
|
Built-in watchdogd....: $with_watchdog $watchdog
|
||||||
Built-in logrotate....: $enable_logrotate
|
Built-in logrotate....: $enable_logrotate
|
||||||
|
Skip fsck check.......: $enable_fastboot
|
||||||
|
Run fsck fix mode.....: $enable_fsckfix
|
||||||
Redirect output.......: $enable_redirect
|
Redirect output.......: $enable_redirect
|
||||||
|
Rescue mode...........: $enable_rescue
|
||||||
Default hostname......: $hostname
|
Default hostname......: $hostname
|
||||||
|
Default group.........: $group
|
||||||
Default runlevel......: $runlevel
|
Default runlevel......: $runlevel
|
||||||
|
|
||||||
------------- Compiler version --------------
|
------------- Compiler version --------------
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
SUBDIRS = finit.d
|
SUBDIRS = finit.d
|
||||||
docsdir := @docdir@/contrib/alpine
|
docsdir := @docdir@/contrib/alpine
|
||||||
docs_DATA = README.md finit.conf alpine-release build.sh install.sh rc.local
|
docs_DATA = README.md finit.conf build.sh install.sh rc.local
|
||||||
EXTRA_DIST = $(docs_DATA)
|
EXTRA_DIST = $(docs_DATA)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
HowTo: Finit on Alpine Linux 3.4-3.6
|
HowTo: Finit on Alpine Linux 3.4...3.19
|
||||||
====================================
|
=======================================
|
||||||
|
|
||||||
HowTo use Finit to boot an [Alpine Linux][] system. It is assumed that
|
HowTo use Finit to boot an [Alpine Linux][] system. It is assumed that
|
||||||
the user has already installed make, a compiler, C library header files,
|
the user has already installed make, a compiler, C library header files,
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
3.6.2
|
|
||||||
@@ -17,8 +17,8 @@ PKG_CONFIG_LIBDIR=/usr/lib/pkgconfig:/usr/local/lib/pkgconfig ./configure \
|
|||||||
--prefix=/usr --exec-prefix= \
|
--prefix=/usr --exec-prefix= \
|
||||||
--sysconfdir=/etc --localstatedir=/var \
|
--sysconfdir=/etc --localstatedir=/var \
|
||||||
--enable-dbus-plugin --enable-x11-common-plugin \
|
--enable-dbus-plugin --enable-x11-common-plugin \
|
||||||
--enable-alsa-utils-plugin --with-watchdog \
|
--enable-alsa-utils-plugin --without-watchdog \
|
||||||
--with-heading="Alpine Linux 3.13"
|
--with-keventd --with-sulogin
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "*** Building ..."
|
echo "*** Building ..."
|
||||||
@@ -35,4 +35,3 @@ fi
|
|||||||
echo
|
echo
|
||||||
echo "*** Done"
|
echo "*** Done"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,22 @@
|
|||||||
# Default is 2
|
# Default is 2
|
||||||
#runlevel 2
|
#runlevel 2
|
||||||
|
|
||||||
|
# Top-level cgroups and their default settings. All groups mandatory
|
||||||
|
# but more can be added, max 8 groups in total currently. The cgroup
|
||||||
|
# 'root' is also available, reserved for RT processes. Settings are
|
||||||
|
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
||||||
|
# cgroup v2 controller default names.
|
||||||
|
#cgroup init cpu.weight:100
|
||||||
|
#cgroup user cpu.weight:100
|
||||||
|
#cgroup system cpu.weight:9700
|
||||||
|
|
||||||
|
# Task to run if ctrl-alt-del is pressed. This condition is asserted by
|
||||||
|
# Finit upon receiving SIGINT (from the kernel).
|
||||||
|
#task <sys/key/ctrlaltdel> [12345789] initctl reboot -- Rebooting system
|
||||||
|
|
||||||
|
# Task to run if the kernel gets a power fail condition is pressed.
|
||||||
|
# Asserted by Finit upon receiving SIGPWR (from the kernel).
|
||||||
|
#task <sys/pwr/fail> [12345789] initctl poweroff -- Shutting down system
|
||||||
|
|
||||||
## Bootstrap services and tasks
|
## Bootstrap services and tasks
|
||||||
# Can be listed here or in /etc/finit.d/*.conf
|
# Can be listed here or in /etc/finit.d/*.conf
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
SUBDIRS = available
|
SUBDIRS = available
|
||||||
docsdir := @docdir@/contrib/alpine/finit.d
|
docsdir := @docdir@/contrib/alpine/finit.d
|
||||||
d_LINKS = acpid.conf crond.conf dropbear.conf getty.conf \
|
d_LINKS = acpid.conf crond.conf dropbear.conf getty.conf \
|
||||||
keymap.conf modules.conf ntpd.conf \
|
keymap.conf modules.conf ntpd.conf syslogd.conf
|
||||||
klogd.conf syslogd.conf
|
|
||||||
|
|
||||||
install-exec-hook:
|
install-exec-hook:
|
||||||
@$(MKDIR_P) $(DESTDIR)$(docsdir)/available
|
@$(MKDIR_P) $(DESTDIR)$(docsdir)/available
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
docsdir := @docdir@/contrib/alpine/finit.d/available
|
docsdir := @docdir@/contrib/alpine/finit.d/available
|
||||||
docs_DATA = acpid.conf crond.conf dropbear.conf getty.conf keymap.conf \
|
docs_DATA = acpid.conf crond.conf dropbear.conf getty.conf keymap.conf \
|
||||||
lxdm.conf modules.conf ntpd.conf syslog.conf watchdog.conf
|
lxdm.conf modules.conf ntpd.conf syslogd.conf watchdog.conf
|
||||||
EXTRA_DIST = $(docs_DATA)
|
EXTRA_DIST = $(docs_DATA)
|
||||||
|
|||||||
@@ -4,4 +4,4 @@
|
|||||||
#module evdev
|
#module evdev
|
||||||
#module mousedev
|
#module mousedev
|
||||||
#module 8139cp
|
#module 8139cp
|
||||||
module softdog
|
#module softdog
|
||||||
|
|||||||
+35
-28
@@ -1,44 +1,53 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
if [ "x`id -u`" != "x0" ]; then
|
if [ "$(id -u)" != "0" ]; then
|
||||||
echo
|
printf "\n\e[1m*** This script must run as root\e[0m\n\n"
|
||||||
echo "*** This script must run as root"
|
|
||||||
echo
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# shellcheck disable=SC3037,SC3045,SC2154
|
||||||
|
yorn()
|
||||||
|
{
|
||||||
|
printf "\e[1m> %s (y/N)?\e[0m " "$*"
|
||||||
|
read -rn1 yorn
|
||||||
|
echo
|
||||||
|
|
||||||
|
if [ "$yorn" = "y" ] || [ "$yorn" = "Y" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
# Adjust base directory
|
# Adjust base directory
|
||||||
if [ -e alpine-release ]; then
|
if grep -q contrib/alpine Makefile 2>/dev/null; then
|
||||||
cd ../..
|
cd ../..
|
||||||
elif [ ! -e autogen.sh ]; then
|
fi
|
||||||
echo "*** Please run this script from the Finit base directory."
|
|
||||||
|
if [ ! -e configure.ac ]; then
|
||||||
|
printf "\n\e[1m*** Please run this script from the Finit base directory.\e[0m\n"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo
|
printf "\n\e[1mInstall Finit on Alpine Linux\n"
|
||||||
echo "*** Install Finit on Alpine Linux"
|
printf "========================================================================\e[0m\n"
|
||||||
echo "========================================================================"
|
printf "/sbin/finit - PID 1\n"
|
||||||
echo "/sbin/finit - PID 1"
|
printf "/lib/finit/plugins/* - All enabled Finit plugins\n"
|
||||||
echo "/lib/finit/plugins/* - All enabled Finit plugins"
|
printf "/etc/finit.conf - Finit configuration file\n"
|
||||||
echo "/etc/finit.conf - Finit configuration file"
|
printf "/etc/finit.d/ - Finit services\n"
|
||||||
echo "/etc/finit.d/ - Finit services"
|
|
||||||
echo
|
|
||||||
read -p "Do you want to continue (y/N)? " yorn
|
|
||||||
|
|
||||||
if [ "x$yorn" = "xy" -o "x$yorn" = "xY" ]; then
|
if yorn "Do you want to continue"; then
|
||||||
echo
|
printf "\n\e[1m*** Installing Finit files ...\e[0m\n"
|
||||||
echo "*** Installing Finit files ..."
|
|
||||||
make install
|
make install
|
||||||
cd /usr/share/doc/finit/contrib/alpine
|
cd /usr/share/doc/finit/contrib/alpine || exit 1
|
||||||
for file in finit.conf rc.local; do
|
for file in finit.conf rc.local; do
|
||||||
install -vbD $file /etc/$file
|
install -vbD $file /etc/$file
|
||||||
done
|
done
|
||||||
cp -va finit.d /etc/
|
cp -va finit.d /etc/
|
||||||
|
|
||||||
read -p "*** Install Finit as the system default Init (y/N)? " yorn
|
if yorn "Install Finit as the system default Init"; then
|
||||||
if [ "x$yorn" = "xy" -o "x$yorn" = "xY" ]; then
|
printf "\e[1m*** Updating /sbin/init symlink --> finit ...\e[0m\n"
|
||||||
echo "*** Updating /sbin/init symlink --> finit ..."
|
cd /sbin || exit 1
|
||||||
cd /sbin
|
|
||||||
rm init
|
rm init
|
||||||
ln -s finit init
|
ln -s finit init
|
||||||
|
|
||||||
@@ -47,10 +56,8 @@ if [ "x$yorn" = "xy" -o "x$yorn" = "xY" ]; then
|
|||||||
ln -s reboot shutdown
|
ln -s reboot shutdown
|
||||||
ln -s reboot suspend
|
ln -s reboot suspend
|
||||||
fi
|
fi
|
||||||
echo "*** Done"
|
printf "\n\e[1m*** Done\e[0m\n"
|
||||||
echo
|
echo
|
||||||
else
|
else
|
||||||
echo
|
printf "\n\e[1m*** Aborting install.\e[0m\n\n"
|
||||||
echo "*** Aborting install."
|
|
||||||
echo
|
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -4,5 +4,5 @@
|
|||||||
#
|
#
|
||||||
# Each line is run in sequence.
|
# Each line is run in sequence.
|
||||||
#
|
#
|
||||||
# NOTE: Remeber to set the executable bit!
|
# NOTE: Remember to set the executable bit!
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SUBDIRS = finit.d grub.d
|
SUBDIRS = finit.d
|
||||||
docsdir := @docdir@/contrib/debian
|
docsdir := @docdir@/contrib/debian
|
||||||
docs_DATA = README.md finit.conf os-release build.sh install.sh
|
docs_DATA = README.md finit.conf build.sh install.sh
|
||||||
EXTRA_DIST = $(docs_DATA)
|
EXTRA_DIST = $(docs_DATA)
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ set up your system to run Finit:
|
|||||||
user@debian:~/finit$ contrib/debian/build.sh
|
user@debian:~/finit$ contrib/debian/build.sh
|
||||||
|
|
||||||
However, since `/sbin/init` already exists on your system, the script
|
However, since `/sbin/init` already exists on your system, the script
|
||||||
creates another entry in your GRUB config, in `/etc/grub.d/40_custom`,
|
creates another entry in your GRUB config by updating `$SUPPORTED_INITS`
|
||||||
where `init=/sbin/finit` is added to your kernel line. It is of course
|
in `/etc/grub.d/10_inux` and run `update-grub`. On reboot you will find
|
||||||
also possible to change the default init to Finit, if you do you can
|
a (finit) entry in the "Advanced options for Debian GNU/Linux" section.
|
||||||
remove the custom Grub entry:
|
It is of course also possible to change the default init to Finit:
|
||||||
|
|
||||||
user@debian:~/finit# cd /sbin
|
user@debian:~/finit# cd /sbin
|
||||||
user@debian:/sbin# sudo mv init oldinit
|
user@debian:/sbin# sudo mv init oldinit
|
||||||
@@ -47,11 +47,13 @@ comands to `initctl`, followed by `reload` to activate your changes.
|
|||||||
You can also use a standard [/etc/rc.local](rc.local) for one-shot tasks
|
You can also use a standard [/etc/rc.local](rc.local) for one-shot tasks
|
||||||
and initialization like keyboard language etc.
|
and initialization like keyboard language etc.
|
||||||
|
|
||||||
If you want to use the X Window system, `sudo apt install elogind`
|
> **NOTE:** X Window system, you may need to `sudo apt install elogind`
|
||||||
(Bullseye and later). Followed by `initctl reload` (enabled by default)
|
> (Bullseye and later), followed by `initctl reload` to activate it (it
|
||||||
and logout/login again. The elogind daemon ensures a regular non-root
|
> is enabled by default), and logout/login again. The elogind daemon
|
||||||
user can start and interact with an X session, otherwise keyboard and
|
> ensures a regular non-root user can start and interact with an X
|
||||||
mouse won't work.
|
> session, otherwise keyboard and mouse won't work. When you're happy,
|
||||||
|
> you can enable the lightdm.conf, change the default runlevel to 3, and
|
||||||
|
> presto! you have a desktop again.
|
||||||
|
|
||||||
|
|
||||||
Have fun!
|
Have fun!
|
||||||
|
|||||||
@@ -25,9 +25,8 @@ echo
|
|||||||
--prefix=/usr --exec-prefix= \
|
--prefix=/usr --exec-prefix= \
|
||||||
--sysconfdir=/etc --localstatedir=/var \
|
--sysconfdir=/etc --localstatedir=/var \
|
||||||
--enable-dbus-plugin --enable-x11-common-plugin \
|
--enable-dbus-plugin --enable-x11-common-plugin \
|
||||||
--enable-alsa-utils-plugin \
|
--enable-alsa-utils-plugin --with-keventd \
|
||||||
--with-random-seed=/var/lib/urandom/random-seed \
|
--with-random-seed=/var/lib/urandom/random-seed
|
||||||
--with-heading="Debian GNU/Linux"
|
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo
|
echo
|
||||||
@@ -60,6 +59,3 @@ else
|
|||||||
echo "*** Use 'sudo contrib/debian/install.sh' later to install Finit"
|
echo "*** Use 'sudo contrib/debian/install.sh' later to install Finit"
|
||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,22 @@
|
|||||||
# Default is 2
|
# Default is 2
|
||||||
#runlevel 2
|
#runlevel 2
|
||||||
|
|
||||||
|
# Top-level cgroups and their default settings. All groups mandatory
|
||||||
|
# but more can be added, max 8 groups in total currently. The cgroup
|
||||||
|
# 'root' is also available, reserved for RT processes. Settings are
|
||||||
|
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
||||||
|
# cgroup v2 controller default names.
|
||||||
|
#cgroup init cpu.weight:100
|
||||||
|
#cgroup user cpu.weight:100
|
||||||
|
#cgroup system cpu.weight:9700
|
||||||
|
|
||||||
|
# Task to run if ctrl-alt-del is pressed. This condition is asserted by
|
||||||
|
# Finit upon receiving SIGINT (from the kernel).
|
||||||
|
#task <sys/key/ctrlaltdel> [12345789] initctl reboot -- Rebooting system
|
||||||
|
|
||||||
|
# Task to run if the kernel gets a power fail condition is pressed.
|
||||||
|
# Asserted by Finit upon receiving SIGPWR (from the kernel).
|
||||||
|
#task <sys/pwr/fail> [12345789] initctl poweroff -- Shutting down system
|
||||||
|
|
||||||
## Bootstrap services and tasks
|
## Bootstrap services and tasks
|
||||||
# Can be listed here or in /etc/finit.d/*.conf
|
# Can be listed here or in /etc/finit.d/*.conf
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
SUBDIRS = available
|
SUBDIRS = available
|
||||||
docsdir := @docdir@/contrib/debian/finit.d
|
docsdir := @docdir@/contrib/debian/finit.d
|
||||||
d_LINKS = console-setup.conf elogind.conf getty.conf \
|
d_LINKS = acpid.conf apparmor.conf avahi-daemon.conf \
|
||||||
keyboard-setup.conf modules.conf rsyslogd.conf \
|
bluetooth.conf console-setup.conf elogind.conf \
|
||||||
sshd.conf
|
getty.conf keyboard-setup.conf modules.conf \
|
||||||
|
plymouth-quit.conf rsyslogd.conf sshd.conf
|
||||||
|
|
||||||
install-exec-hook:
|
install-exec-hook:
|
||||||
@$(MKDIR_P) $(DESTDIR)$(docsdir)/available
|
@$(MKDIR_P) $(DESTDIR)$(docsdir)/available
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
docsdir := @docdir@/contrib/debian/finit.d/available
|
docsdir := @docdir@/contrib/debian/finit.d/available
|
||||||
docs_DATA = acpid.conf console-setup.conf elogind.conf getty.conf \
|
docs_DATA = acpid.conf apparmor.conf avahi-daemon.conf bluetooth.conf \
|
||||||
|
console-setup.conf elogind.conf getty.conf \
|
||||||
keyboard-setup.conf lightdm.conf modules.conf sntpd.conf \
|
keyboard-setup.conf lightdm.conf modules.conf sntpd.conf \
|
||||||
rsyslogd.conf sshd.conf syslogd.conf xdm.conf
|
plymouth-quit.conf rsyslogd.conf sshd.conf syslogd.conf \
|
||||||
|
xdm.conf
|
||||||
EXTRA_DIST = $(docs_DATA)
|
EXTRA_DIST = $(docs_DATA)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
task [2345] <sys/pwr/ac,pid/syslogd> halt:usr1 env:-/etc/default/anacron anacron -d -q $ANACRON_ARGS -- Anacron jobs
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
sysv [S] /etc/init.d/apparmor -- AppArmor initialization
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
service [2345] env:-/etc/default/avahi-daemon avahi-daemon -s $AVAHI_DAEMON_OPTS -- Avahi mDNS/DNS-SD Stack
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# To ignore errors like "org.freedesktop.hostname1", update the env file with
|
||||||
|
# "--noplugin=hostname", i.e. append to BLUETOOTHD_OPTS
|
||||||
|
service [2345] log:null env:-/etc/default/bluetooth /usr/libexec/bluetooth/bluetoothd -n $BLUETOOTHD_OPTS -- Bluetooth service
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
service [2345] <sys/pwr/ac,pid/syslogd> env:-/etc/default/cron cron -f $EXTRA_OPTS -- Background job processing daemon
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
# Consoles to start getty on when system is up
|
# Consoles to start getty on when system is up
|
||||||
tty [12345] /dev/tty1 linux noclear nowait
|
tty [12345] /dev/tty1 linux noclear nowait
|
||||||
tty [2345] /dev/tty2 linux noclear nowait
|
tty [2345] /dev/tty2 linux nowait
|
||||||
tty [2345] /dev/tty3 linux noclear nowait
|
tty [2345] /dev/tty3 linux nowait
|
||||||
|
tty [2345] /dev/tty4 linux nowait
|
||||||
|
tty [2345] /dev/tty5 linux nowait
|
||||||
|
tty [2345] /dev/tty6 linux nowait
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
# Need to stop plymouth, or it'll block stdin on tty1
|
||||||
|
task [S] /usr/bin/plymouth quit -- Stopping Plymouth Boot Screen
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
exec tail -n +3 $0
|
|
||||||
# This file provides an easy way to add custom menu entries. Simply type the
|
|
||||||
# menu entries you want to add after this comment. Be careful not to change
|
|
||||||
# the 'exec tail' line above.
|
|
||||||
|
|
||||||
menuentry '$MENU with Finit' --class $TYPE --class gnu-linux --class gnu --class os --user {
|
|
||||||
insmod gzio
|
|
||||||
insmod part_msdos
|
|
||||||
insmod ext2
|
|
||||||
search --no-floppy --fs-uuid --set=root $BOOT
|
|
||||||
linux /vmlinuz root=UUID=$ROOT ro quiet init=/sbin/finit
|
|
||||||
initrd /initrd.img
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
docsdir := @docdir@/contrib/debian/grub.d
|
|
||||||
docs_DATA = 40_custom
|
|
||||||
EXTRA_DIST = $(docs_DATA)
|
|
||||||
@@ -8,10 +8,10 @@ if [ "x`id -u`" != "x0" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Adjust base directory
|
# Adjust base directory
|
||||||
grep -q Debian os-release 2>/dev/null
|
grep -q debian Makefile 2>/dev/null
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
cd ../..
|
cd ../..
|
||||||
elif [ ! -e autogen.sh ]; then
|
elif [ ! -e configure.ac ]; then
|
||||||
echo "*** Please run this script from the Finit base directory."
|
echo "*** Please run this script from the Finit base directory."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -23,7 +23,7 @@ echo "/sbin/finit - PID 1"
|
|||||||
echo "/lib/finit/plugins/* - All enabled Finit plugins"
|
echo "/lib/finit/plugins/* - All enabled Finit plugins"
|
||||||
echo "/etc/finit.conf - Finit configuration file"
|
echo "/etc/finit.conf - Finit configuration file"
|
||||||
echo "/etc/finit.d/ - Finit services"
|
echo "/etc/finit.d/ - Finit services"
|
||||||
echo "/etc/grub.d/40_custom - Add menu entry to the Grub boot loader"
|
echo "/etc/grub.d/10_linux - Add Finit to Grub's SUPPORTED_INITS"
|
||||||
echo
|
echo
|
||||||
read -p "Do you want to continue (y/N)? " yorn
|
read -p "Do you want to continue (y/N)? " yorn
|
||||||
echo
|
echo
|
||||||
@@ -38,12 +38,18 @@ if [ "x$yorn" = "xy" -o "x$yorn" = "xY" ]; then
|
|||||||
cp -va finit.d /etc/
|
cp -va finit.d /etc/
|
||||||
|
|
||||||
echo "*** Setting up a GRUB boot entry ..."
|
echo "*** Setting up a GRUB boot entry ..."
|
||||||
MENU=`grep gnu-linux /boot/grub/grub.cfg |head -1 |sed "s/menuentry '\([^']*\).*/\1/"`
|
fn=/etc/grub.d/10_linux
|
||||||
TYPE=`grep gnu-linux /boot/grub/grub.cfg |head -1 |sed "s/.*' --class \([a-z]*\).*/\1/"`
|
if [ -e $fn ]; then
|
||||||
BOOT=`grep set=root /boot/grub/grub.cfg |head -1 |sed 's/.* \([a-f0-9]*-[a-f0-9]*-[a-f0-9]*-[a-f0-9]*-[a-f0-9]*\).*/\1/'`
|
if `grep SUPPORTED_INITS $fn |head -1 |grep -q finit`; then
|
||||||
ROOT=`grep root=UUID /boot/grub/grub.cfg |head -1 |sed 's/.*UUID=\([a-f0-9]*-[a-f0-9]*-[a-f0-9]*-[a-f0-9]*-[a-f0-9]*\).*/\1/'`
|
echo "Already installed, done."
|
||||||
cat grub.d/40_custom | sed "s,\$BOOT,$BOOT,;s,\$ROOT,$ROOT,;s,\$TYPE,$TYPE,;s,\$MENU,$MENU," >/etc/grub.d/40_custom
|
else
|
||||||
update-grub
|
echo "Adding Finit to list of SUPPORTED_INITS ..."
|
||||||
|
sed -i 's/SUPPORTED_INITS="[^"]*/& finit:\/sbin\/finit/' $fn
|
||||||
|
update-grub
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Cannot find $fn, you'll have to set up your bootloader on your own."
|
||||||
|
fi
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "*** Done"
|
echo "*** Done"
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
PRETTY_NAME="Debian GNU/Linux 8 (jessie)"
|
|
||||||
NAME="Debian GNU/Linux"
|
|
||||||
VERSION_ID="8"
|
|
||||||
VERSION="8 (jessie)"
|
|
||||||
ID=debian
|
|
||||||
HOME_URL="http://www.debian.org/"
|
|
||||||
SUPPORT_URL="http://www.debian.org/support"
|
|
||||||
BUG_REPORT_URL="https://bugs.debian.org/"
|
|
||||||
@@ -35,6 +35,14 @@ tty /dev/tty1
|
|||||||
tty /dev/tty2
|
tty /dev/tty2
|
||||||
tty /dev/tty3
|
tty /dev/tty3
|
||||||
|
|
||||||
|
# Task to run if ctrl-alt-del is pressed. This condition is asserted by
|
||||||
|
# Finit upon receiving SIGINT (from the kernel).
|
||||||
|
task <sys/key/ctrlaltdel> [12345789] initctl reboot -- Rebooting system
|
||||||
|
|
||||||
|
# Task to run if the kernel gets a power fail condition is pressed.
|
||||||
|
# Asserted by Finit upon receiving SIGPWR (from the kernel).
|
||||||
|
task <sys/pwr/fail> [12345789] initctl poweroff -- Shutting down system
|
||||||
|
|
||||||
# Alternative method instead of runparts
|
# Alternative method instead of runparts
|
||||||
#task [S] /etc/init.d/keyboard-setup start -- Setting up preliminary keymap
|
#task [S] /etc/init.d/keyboard-setup start -- Setting up preliminary keymap
|
||||||
#task [S] /etc/init.d/acpid start -- Starting ACPI Daemon
|
#task [S] /etc/init.d/acpid start -- Starting ACPI Daemon
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
In Finit issue #196 we were reminded [1] of a missing inotify flag in
|
||||||
|
Linux older kernels, IN_MASK_CREATE. Finit makes use of this internally
|
||||||
|
for monitoring PID conditions, and more. This is a central mechanism to
|
||||||
|
synchronize services at boot and reload at runtime.
|
||||||
|
|
||||||
|
The following patch for Linux 4.9.0, was provided by Andy Savage for
|
||||||
|
other people that may want to run Finit on slightly older kernels.
|
||||||
|
|
||||||
|
[1]: https://github.com/troglobit/finit/issues/196
|
||||||
|
|
||||||
|
Index: fs/notify/inotify/inotify_user.c
|
||||||
|
===================================================================
|
||||||
|
--- fs.orig/notify/inotify/inotify_user.c
|
||||||
|
+++ fs/notify/inotify/inotify_user.c
|
||||||
|
@@ -522,6 +522,7 @@ static int inotify_update_existing_watch
|
||||||
|
__u32 old_mask, new_mask;
|
||||||
|
__u32 mask;
|
||||||
|
int add = (arg & IN_MASK_ADD);
|
||||||
|
+ int create = (arg & IN_MASK_CREATE);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mask = inotify_arg_to_mask(arg);
|
||||||
|
@@ -529,6 +530,8 @@ static int inotify_update_existing_watch
|
||||||
|
fsn_mark = fsnotify_find_inode_mark(group, inode);
|
||||||
|
if (!fsn_mark)
|
||||||
|
return -ENOENT;
|
||||||
|
+ else if (create)
|
||||||
|
+ return -EEXIST;
|
||||||
|
|
||||||
|
i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
|
||||||
|
|
||||||
|
@@ -726,6 +729,10 @@ SYSCALL_DEFINE3(inotify_add_watch, int,
|
||||||
|
if (unlikely(!f.file))
|
||||||
|
return -EBADF;
|
||||||
|
|
||||||
|
+ /* IN_MASK_ADD and IN_MASK_CREATE don't make sense together */
|
||||||
|
+ if (unlikely((mask & IN_MASK_ADD) && (mask & IN_MASK_CREATE)))
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
/* verify that this is indeed an inotify instance */
|
||||||
|
if (unlikely(f.file->f_op != &inotify_fops)) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
@@ -814,7 +821,7 @@ static int __init inotify_user_setup(voi
|
||||||
|
BUILD_BUG_ON(IN_ISDIR != FS_ISDIR);
|
||||||
|
BUILD_BUG_ON(IN_ONESHOT != FS_IN_ONESHOT);
|
||||||
|
|
||||||
|
- BUG_ON(hweight32(ALL_INOTIFY_BITS) != 21);
|
||||||
|
+ BUG_ON(hweight32(ALL_INOTIFY_BITS) != 22);
|
||||||
|
|
||||||
|
inotify_inode_mark_cachep = KMEM_CACHE(inotify_inode_mark, SLAB_PANIC);
|
||||||
|
|
||||||
|
Index: include/linux/inotify.h
|
||||||
|
===================================================================
|
||||||
|
--- include.orig/linux/inotify.h
|
||||||
|
+++ include/linux/inotify.h
|
||||||
|
@@ -17,6 +17,6 @@ extern struct ctl_table inotify_table[];
|
||||||
|
IN_DELETE_SELF | IN_MOVE_SELF | IN_UNMOUNT | \
|
||||||
|
IN_Q_OVERFLOW | IN_IGNORED | IN_ONLYDIR | \
|
||||||
|
IN_DONT_FOLLOW | IN_EXCL_UNLINK | IN_MASK_ADD | \
|
||||||
|
- IN_ISDIR | IN_ONESHOT)
|
||||||
|
+ IN_MASK_CREATE | IN_ISDIR | IN_ONESHOT)
|
||||||
|
|
||||||
|
#endif /* _LINUX_INOTIFY_H */
|
||||||
|
Index: include/uapi/linux/inotify.h
|
||||||
|
===================================================================
|
||||||
|
--- include.orig/uapi/linux/inotify.h
|
||||||
|
+++ include/uapi/linux/inotify.h
|
||||||
|
@@ -52,6 +52,7 @@ struct inotify_event {
|
||||||
|
#define IN_ONLYDIR 0x01000000 /* only watch the path if it is a directory */
|
||||||
|
#define IN_DONT_FOLLOW 0x02000000 /* don't follow a sym link */
|
||||||
|
#define IN_EXCL_UNLINK 0x04000000 /* exclude events on unlinked objects */
|
||||||
|
+#define IN_MASK_CREATE 0x10000000 /* only create watches */
|
||||||
|
#define IN_MASK_ADD 0x20000000 /* add to the mask of an already existing watch */
|
||||||
|
#define IN_ISDIR 0x40000000 /* event occurred against dir */
|
||||||
|
#define IN_ONESHOT 0x80000000 /* only send event once */
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
SUBDIRS = finit.d
|
SUBDIRS = finit.d
|
||||||
docsdir := @docdir@/contrib/void
|
docsdir := @docdir@/contrib/void
|
||||||
docs_DATA = README.md finit.conf build.sh install.sh rc.local xbps
|
docs_DATA = README.md finit.conf build.sh install.sh rc.local
|
||||||
EXTRA_DIST = $(docs_DATA)
|
EXTRA_DIST = $(docs_DATA)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ PKG_CONFIG_LIBDIR=/usr/lib/pkgconfig:/usr/local/lib/pkgconfig ./configure \
|
|||||||
--sysconfdir=/etc --localstatedir=/var \
|
--sysconfdir=/etc --localstatedir=/var \
|
||||||
--enable-dbus-plugin --enable-x11-common-plugin \
|
--enable-dbus-plugin --enable-x11-common-plugin \
|
||||||
--enable-alsa-utils-plugin --with-watchdog \
|
--enable-alsa-utils-plugin --with-watchdog \
|
||||||
--with-heading="Void Linux"
|
--with-keventd --with-sulogin
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "*** Building ..."
|
echo "*** Building ..."
|
||||||
@@ -35,4 +35,3 @@ fi
|
|||||||
echo
|
echo
|
||||||
echo "*** Done"
|
echo "*** Done"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
|||||||
@@ -5,5 +5,22 @@
|
|||||||
# Default is 2
|
# Default is 2
|
||||||
#runlevel 2
|
#runlevel 2
|
||||||
|
|
||||||
|
# Top-level cgroups and their default settings. All groups mandatory
|
||||||
|
# but more can be added, max 8 groups in total currently. The cgroup
|
||||||
|
# 'root' is also available, reserved for RT processes. Settings are
|
||||||
|
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
||||||
|
# cgroup v2 controller default names.
|
||||||
|
#cgroup init cpu.weight:100
|
||||||
|
#cgroup user cpu.weight:100
|
||||||
|
#cgroup system cpu.weight:9700
|
||||||
|
|
||||||
|
# Task to run if ctrl-alt-del is pressed. This condition is asserted by
|
||||||
|
# Finit upon receiving SIGINT (from the kernel).
|
||||||
|
#task <sys/key/ctrlaltdel> [12345789] initctl reboot -- Rebooting system
|
||||||
|
|
||||||
|
# Task to run if the kernel gets a power fail condition is pressed.
|
||||||
|
# Asserted by Finit upon receiving SIGPWR (from the kernel).
|
||||||
|
#task <sys/pwr/fail> [12345789] initctl poweroff -- Shutting down system
|
||||||
|
|
||||||
## Bootstrap services and tasks
|
## Bootstrap services and tasks
|
||||||
# Can be listed here or in /etc/finit.d/*.conf
|
# Can be listed here or in /etc/finit.d/*.conf
|
||||||
|
|||||||
@@ -8,9 +8,10 @@ if [ "x`id -u`" != "x0" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Adjust base directory
|
# Adjust base directory
|
||||||
if [ -e xbps ]; then
|
grep -q void Makefile 2>/dev/null
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
cd ../..
|
cd ../..
|
||||||
elif [ ! -e autogen.sh ]; then
|
elif [ ! -e configure.ac ]; then
|
||||||
echo "*** Please run this script from the Finit base directory."
|
echo "*** Please run this script from the Finit base directory."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -4,4 +4,4 @@
|
|||||||
#
|
#
|
||||||
# Each line is run in sequence.
|
# Each line is run in sequence.
|
||||||
#
|
#
|
||||||
# NOTE: Remeber to set the executable bit!
|
# NOTE: Remember to set the executable bit!
|
||||||
|
|||||||
+14
-2
@@ -21,17 +21,29 @@ Some of these are also registered in the issue tracker on GitHub.
|
|||||||
* Allow running as non-pid1 => read .conf and RCSD form cmdline
|
* Allow running as non-pid1 => read .conf and RCSD form cmdline
|
||||||
* Add `finit.conf` support for UPS notification (SIGPWR) to start a task
|
* Add `finit.conf` support for UPS notification (SIGPWR) to start a task
|
||||||
using, e.g. <sys/power/{ok,fail,low}> conditions. More info in sig.c
|
using, e.g. <sys/power/{ok,fail,low}> conditions. More info in sig.c
|
||||||
|
|
||||||
|
As of Finit v4.1 SIGPWR generates <sys/power/fail> condition and it
|
||||||
|
is up to a task to check why and take appropriate action.
|
||||||
* Add `finit.conf` support for ctrl-alt-delete (SIGINT) and kbrequest,
|
* Add `finit.conf` support for ctrl-alt-delete (SIGINT) and kbrequest,
|
||||||
i.e. KeyboardSignal, (SIGWINCH) behavior. Using conditions to a task,
|
i.e. KeyboardSignal, (SIGWINCH) behavior. Using conditions to a task,
|
||||||
e.g, <sys/key/ctrlaltdel> and <sys/key/signal> like SIGPWR handling.
|
e.g, <sys/key/ctrlaltdel> and <sys/key/signal> like SIGPWR handling.
|
||||||
* Write man pages for finit and `finit.conf`, steal from the excellent
|
|
||||||
`pimd` man pages ...
|
As of Finit v4.1 SIGINT generates <sys/key/ctrlaltdel>, but there is
|
||||||
|
no check if the signal actually originates from the kernel. To get
|
||||||
|
this verification, a new libuEv release is needed. As of June 6 -21
|
||||||
|
that functionality is not yet released.
|
||||||
|
|
||||||
|
|
||||||
|
Initctl
|
||||||
|
-------
|
||||||
|
|
||||||
* Add support for timed shutdown in Finit, including cancelled shutdown:
|
* Add support for timed shutdown in Finit, including cancelled shutdown:
|
||||||
|
|
||||||
shutdown -h 03:35 "foobar was here"
|
shutdown -h 03:35 "foobar was here"
|
||||||
|
|
||||||
* Add support for JSON output, or similar, from `initctl show`, e.g.
|
* Add support for JSON output, or similar, from `initctl show`, e.g.
|
||||||
`initctl show --json`
|
`initctl show --json`
|
||||||
|
* Add support for `-s` to redirect all output to syslog, for scripting
|
||||||
|
|
||||||
|
|
||||||
Init
|
Init
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
Bootstrap
|
|
||||||
=========
|
|
||||||
|
|
||||||
1. Prepare emergency shell, if enabled
|
|
||||||
2. Set up initial signal handlers
|
|
||||||
3. Set up default $PATH early
|
|
||||||
4. Mount `/proc` and `/sys`
|
|
||||||
5. Check kernel command line for `debug` to figure out log level
|
|
||||||
6. Load all `.so` plugins
|
|
||||||
7. Call `fsck` on file systems listed in `/etc/fstab`
|
|
||||||
8. Populate `/dev` using either udev or mdev, depending on system type
|
|
||||||
9. Parse `/etc/finit.conf`
|
|
||||||
10. Start built-in watchdog, if enabled and `WDT_DEVNODE` exists. This
|
|
||||||
means any WDT that requires a kernel module need to be either
|
|
||||||
compiled into the kernel, or insmod'ed in `/etc/finit.conf`
|
|
||||||
11. Load all `/etc/finit.d/*.conf` files and set hostname
|
|
||||||
12. Remount `/` read-write if `/` is listed in `/etc/fstab` without `ro`
|
|
||||||
13. Call 1st level hooks, `HOOK_ROOTFS_UP`
|
|
||||||
14. Mount all file systems listed in `/etc/fstab` and swap, if available
|
|
||||||
15. Enable SysV init signals
|
|
||||||
16. Call 2nd level hooks, `HOOK_BASEFS_UP`
|
|
||||||
17. Cleanup stale files from `/tmp/*` et al, handled by `bootmisc` plugin
|
|
||||||
18. Load kernel params from `/etc/sysctl.d/*.conf`, `/etc/sysctl.conf`
|
|
||||||
et al. (Supports all locations that SysV init does.), handled by
|
|
||||||
`procps` plugin
|
|
||||||
19. Start all 'S' runlevel tasks and services
|
|
||||||
20. Bring up loopback interface and all `/etc/network/interfaces`, if
|
|
||||||
the `.conf` setting `network <SCRIPT>` is set, it is called instead
|
|
||||||
21. Call 3rd level hooks, `HOOK_NETWORK_UP`
|
|
||||||
22. If `runparts <DIR>` is set, [run-parts(8)][] is called on `<DIR>`
|
|
||||||
23. Switch to the configured runlevel from `/etc/finit.conf`, default 2.
|
|
||||||
At every runlevel change all `*.conf` files in `/etc/finit.d/` are
|
|
||||||
(re)loaded and new services, tasks, and blocking run commands are
|
|
||||||
started. Provided they are allowed in the new runlevel and all of
|
|
||||||
their conditions, if any, are set.
|
|
||||||
24. Call 4th level hooks, `HOOK_SVC_UP`
|
|
||||||
25. Call `/etc/rc.local`, if it exists and is an executable shell script
|
|
||||||
26. Call 5th level (last) hooks, `HOOK_SYSTEM_UP`
|
|
||||||
27. Start all configured TTYs
|
|
||||||
|
|
||||||
In (19) and (22) tasks and services defined in `/etc/finit.conf` and
|
|
||||||
`/etc/sysctl.d/*.conf` are started. Remember, all `service` and `task`
|
|
||||||
stanzas are started in parallel and `run` in sequence, and in the order
|
|
||||||
listed. Hence, to emulate a SysV `/etc/init.d/rcS` one could write a
|
|
||||||
long `finit.conf` with only `run` statements.
|
|
||||||
|
|
||||||
Notice the five hook points that are called at various point in the
|
|
||||||
bootstrap process. This is where plugins can extend the boot in any way
|
|
||||||
they please. There are other hook points, e.g. `HOOK_MOUNT_ERROR`, for
|
|
||||||
more on this see [plugins.md](plugins.md).
|
|
||||||
|
|
||||||
For instance, at `HOOK_BASEFS_UP` a plugin could read an XML file from a
|
|
||||||
USB stick, convert/copy its contents to the system's `/etc/` directory,
|
|
||||||
well before all 'S' runlevel tasks are started. This could be used with
|
|
||||||
system images that are created read-only and all configuration is stored
|
|
||||||
on external media.
|
|
||||||
|
|
||||||
[run-parts(8)]: http://manpages.debian.org/cgi-bin/man.cgi?query=run-parts
|
|
||||||
+33
-13
@@ -27,10 +27,10 @@ optional plugins to enable. It depends on two external libraries:
|
|||||||
PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig ./configure
|
PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig ./configure
|
||||||
|
|
||||||
The configure script checks for all dependencies, including the correct
|
The configure script checks for all dependencies, including the correct
|
||||||
version of the above mentioned libraries. Currently requried versions:
|
version of the above mentioned libraries. Currently required versions:
|
||||||
|
|
||||||
- libite v2.2.0
|
- libite v2.2.0, or later
|
||||||
- libuEv v2.2.0
|
- libuEv v2.2.0, or later
|
||||||
|
|
||||||
|
|
||||||
Configure
|
Configure
|
||||||
@@ -53,6 +53,10 @@ Below are a few of the main switches to configure:
|
|||||||
built-ins (.o files) and all external libraries, except the C library
|
built-ins (.o files) and all external libraries, except the C library
|
||||||
will be linked statically.
|
will be linked statically.
|
||||||
|
|
||||||
|
* `--enable-kernel-cmdline`: Enable Finit pre-4.1 parsing of init args from
|
||||||
|
`/proc/cmdline`, this is *not recommended* since Finit may be running as the
|
||||||
|
init for container apps that can see the host's `/proc` filesystem
|
||||||
|
|
||||||
* `--enable-alsa-utils-plugin`: Enable the optional `alsa-utils.so` sound plugin.
|
* `--enable-alsa-utils-plugin`: Enable the optional `alsa-utils.so` sound plugin.
|
||||||
|
|
||||||
* `--enable-dbus-plugin`: Enable the optional D-Bus `dbus.so` plugin.
|
* `--enable-dbus-plugin`: Enable the optional D-Bus `dbus.so` plugin.
|
||||||
@@ -61,8 +65,19 @@ Below are a few of the main switches to configure:
|
|||||||
|
|
||||||
* `--enable-x11-common-plugin`: Enable the optional X Window `x11-common.so` plugin.
|
* `--enable-x11-common-plugin`: Enable the optional X Window `x11-common.so` plugin.
|
||||||
|
|
||||||
|
* `--with-sulogin`: Enable bundled `sulogin` program. Default is to use the
|
||||||
|
system `sulogin(8)`. The sulogin shipped with Finit *allows password-less*
|
||||||
|
login if the `root` user is disabled or has no password at all.
|
||||||
|
|
||||||
For more configure flags, see <kbd>./configure --help</kbd>
|
For more configure flags, see <kbd>./configure --help</kbd>
|
||||||
|
|
||||||
|
> **Note:** the configure script is not available in the GIT sources. It is
|
||||||
|
> however included in (officially supported) released tarballs. The
|
||||||
|
> idea is that you should not need GNU autotools to build, only the
|
||||||
|
> above mentioned dependencies, a POSIX shell, a C compiler and make.
|
||||||
|
> Any contributing to Finit can generate it from `configure.ac` using
|
||||||
|
> the `autogen.sh` script.
|
||||||
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
-------
|
-------
|
||||||
@@ -70,16 +85,16 @@ Example
|
|||||||
First, unpack the archive:
|
First, unpack the archive:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ tar xf finit-3.0.tar.xz
|
$ tar xf finit-4.3.tar.gz
|
||||||
$ cd finit-3.0/
|
$ cd finit-4.3/
|
||||||
```
|
```
|
||||||
|
|
||||||
Then configure, build and install:
|
Then configure, build and install:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ ./configure --prefix=/usr --exec-prefix= \
|
$ ./configure --prefix=/usr --exec-prefix= \
|
||||||
--sysconfdir=/etc --localstatedir=/var \
|
--sysconfdir=/etc --localstatedir=/var \
|
||||||
--with-heading="Alpine Linux 3.13" --with-hostname=alpine
|
--with-keventd --with-watchdog
|
||||||
$ make
|
$ make
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
@@ -87,13 +102,13 @@ $ make
|
|||||||
$ DESTDIR=/tmp/finit make install
|
$ DESTDIR=/tmp/finit make install
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example the [finit-3.0.tar.xz][1] archive is unpacked to the
|
In this example the [finit-4.3.tar.gz][1] archive is unpacked to the
|
||||||
user's home directory, configured, built and installed to a temporary
|
user's home directory, configured, built and installed to a temporary
|
||||||
staging directory. The environment variable `DESTDIR` controls the
|
staging directory. The environment variable `DESTDIR` controls the
|
||||||
destination directory when installing, very useful for building binary
|
destination directory when installing, very useful for building binary
|
||||||
standalone packages.
|
standalone packages.
|
||||||
|
|
||||||
Finit 3.0 and later can detect if it runs on an embedded system, or a
|
Finit 4.1 and later can detect if it runs on an embedded system, or a
|
||||||
system that use BusyBox tools instead of udev & C:o. On such systems
|
system that use BusyBox tools instead of udev & C:o. On such systems
|
||||||
`mdev` instead of `udev` is used. However, remember to also change the
|
`mdev` instead of `udev` is used. However, remember to also change the
|
||||||
Linux config to:
|
Linux config to:
|
||||||
@@ -142,17 +157,22 @@ enabled. The default Finit rescue mode configuration is installed into
|
|||||||
|
|
||||||
By default the a root shell, without login, is started.
|
By default the a root shell, without login, is started.
|
||||||
|
|
||||||
|
> **Note:** in this mode `initctl` will not work. Use the `-f` flag to
|
||||||
|
> force `reboot`, `shutdown`, or `poweroff`.
|
||||||
|
|
||||||
|
|
||||||
Debugging
|
Debugging
|
||||||
---------
|
---------
|
||||||
|
|
||||||
Edit, or append to, the kernel command line: remove `quiet` to enable
|
Edit, or append to, the kernel command line: remove `quiet` to enable
|
||||||
kernel messages and add `debug` to enable Finit debug messages.
|
kernel messages and add `finit.debug` to enable Finit debug messages.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
append="init=/sbin/finit debug"
|
append="init=/sbin/finit -- finit.debug"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Notice the `--` separator.
|
||||||
|
|
||||||
To debug startup issues, in particular issues with getty/login, add
|
To debug startup issues, in particular issues with getty/login, add
|
||||||
the following to your Finit .conf file:
|
the following to your Finit .conf file:
|
||||||
|
|
||||||
@@ -171,6 +191,6 @@ it only for debugging start up issues when Finit crashes.
|
|||||||
systems since they can potentially give a user root access.
|
systems since they can potentially give a user root access.
|
||||||
|
|
||||||
|
|
||||||
[1]: ftp://troglobit.com/finit/finit-3.0.tar.xz
|
[1]: ftp://troglobit.com/finit/finit-4.3.tar.gz
|
||||||
[libuEv]: https://github.com/troglobit/libuev
|
[libuEv]: https://github.com/troglobit/libuev
|
||||||
[libite]: https://github.com/troglobit/libite
|
[libite]: https://github.com/troglobit/libite
|
||||||
|
|||||||
+82
-12
@@ -6,15 +6,66 @@ passed on the Linux kernel command line. Not limited to Finit.
|
|||||||
|
|
||||||
The `bool` setting is one of `on, off, true false, 1, 0`.
|
The `bool` setting is one of `on, off, true false, 1, 0`.
|
||||||
|
|
||||||
|
> **NOTE:** remember to use `--` to separate kernel parameters from
|
||||||
|
> parameters to init. E.g., `init=/sbin/finit -- finit.debug rescue`
|
||||||
|
|
||||||
* `debug`: Enable kernel debug. Debug messages are printed to the
|
* `debug`: Enable kernel debug. Debug messages are printed to the
|
||||||
console until Finit starts up.
|
console until Finit starts up, unless `loglevel=7` (below) is used.
|
||||||
|
|
||||||
|
* `fsck.mode=<auto,force,skip>`, default: `auto`, unless built with
|
||||||
|
`configure --enable-fastboot`, in which case the default is `skip`
|
||||||
|
|
||||||
|
* `fsck.repair=<preen,yes,no>`, default: `preen`, unless built with
|
||||||
|
`configure --enable-fsckfix`, in which case the default is `yes`.
|
||||||
|
This configure option also sets `fsck.mode=force`, unless fastboot
|
||||||
|
is selected at the same time. I.e., the `--enable-fastboot` build
|
||||||
|
option overrides the `fsck.mode` default value.
|
||||||
|
|
||||||
|
* `finit.cond=foo[,bar[,baz]]`: set `<boot/foo>` condition, optionally
|
||||||
|
multiple conditions can be set using the same option, separated with a
|
||||||
|
comma. Alternatively, multiple `foo.cond=arg` can be given. Each will
|
||||||
|
result in a `<boot/arg>` condition being set to control the rest of the
|
||||||
|
system bootstrap.
|
||||||
|
|
||||||
|
Very useful for selecting different boot modes, e.g. manufacturing test,
|
||||||
|
firmware upgrade, or rescue mode.
|
||||||
|
|
||||||
|
> Note: `<boot/...>` conditions cannot be cleared with `initctl`!
|
||||||
|
|
||||||
|
* `finit.config=/path/to/alternative/finit.conf`: override the
|
||||||
|
compile-time bootstrap config file, default:
|
||||||
|
|
||||||
|
./configure --with-config=/etc/finit.conf
|
||||||
|
|
||||||
|
Useful when starting up in various rescue mode, factory, or
|
||||||
|
production test setups. Use the top-level configuration file
|
||||||
|
directive `rcsd /path/to/finit.d` to override the default
|
||||||
|
rcS.d directory.
|
||||||
|
|
||||||
* `finit.debug[=bool]`: Enable finit debug. This is operated
|
* `finit.debug[=bool]`: Enable finit debug. This is operated
|
||||||
independently of the kernel debug setting. New as of Finit v4.
|
independently of the kernel `debug` setting. New as of Finit v4.
|
||||||
|
|
||||||
* `finit.show_status[=bool]`: Control finit boot progress, including
|
* `finit.fstab=</path/to/etc/fstab.alternative>`: Tell Finit to use an
|
||||||
banner.
|
alternate `fstab` to mount the file system from. Remember, this file
|
||||||
|
must be on the `root=...` file system provided to Finit from the
|
||||||
|
kernel. By default the built-in fstab is used, which itself defaults
|
||||||
|
to `/etc/fstab`, but can be changed at build time with:
|
||||||
|
|
||||||
|
./configure --with-fstab=/path/to/fstab
|
||||||
|
|
||||||
|
It is even possible to disable a built-in default using:
|
||||||
|
|
||||||
|
./configure --without-fstab
|
||||||
|
|
||||||
|
Making `finit.fstab=/path/to/fstab` a *mandatory* command line option.
|
||||||
|
Note, if the command line fstab is missing, Finit falls back to the
|
||||||
|
built-in fstab, and if both are missing, the system treats this as a
|
||||||
|
bad `fsck` and thus calls `sulogin`. If, in turn, `sulogin` is not
|
||||||
|
available on the system, Finit calls reboot, which is also what will
|
||||||
|
happen when a user exits from `sulogin`.
|
||||||
|
|
||||||
|
* `finit.status[=bool]`: Control finit boot progress, including banner.
|
||||||
|
(Used to be `finit.show_status`, which works but is deprecated.)
|
||||||
|
|
||||||
* `finit.status_style=<classic,modern>`: Set Finit boot progress style,
|
* `finit.status_style=<classic,modern>`: Set Finit boot progress style,
|
||||||
when enabled.
|
when enabled.
|
||||||
@@ -24,25 +75,44 @@ The `bool` setting is one of `on, off, true false, 1, 0`.
|
|||||||
signals and has no job control. Recommend using, and modifying,
|
signals and has no job control. Recommend using, and modifying,
|
||||||
`rescue` mode instead.
|
`rescue` mode instead.
|
||||||
|
|
||||||
|
* `loglevel=<0-7>`, sets the kernel's log level, which is more granular
|
||||||
|
than `debug`. Also, when `loglevel=7`, Finit will *not disable*
|
||||||
|
kernel logs to the console. This is very useful when debugging the
|
||||||
|
kernel at system bring-up. Since `loglevel=7` is the same as `debug`
|
||||||
|
this means you have to use `quiet` for a quiet boot, until sysklogd
|
||||||
|
takes over logging of kernel events.
|
||||||
|
|
||||||
* `panic=SEC`: By default the kernel does not reboot after a kernel
|
* `panic=SEC`: By default the kernel does not reboot after a kernel
|
||||||
panic. This setting will cause a kernel reboot after SEC seconds.
|
panic. This setting will cause a kernel reboot after SEC seconds.
|
||||||
|
|
||||||
* `quiet`: Suppress kernel logging to console, except for warnings and
|
* `quiet`: Suppress kernel logging to console, except for warnings and
|
||||||
errors.
|
errors. Also, see `loglevel` and `quiet` above.
|
||||||
|
|
||||||
* `rescue`: Start rescue/maintenance mode. If your system comes with
|
* `rescue`: Start rescue/maintenance mode. If your system comes with
|
||||||
the bundled `sulogin` program (Finit, or from util-linux/Busybox),
|
the bundled `sulogin` program (Finit, or from util-linux/Busybox),
|
||||||
you will be given a root login to a maintenance shell. However, if
|
you will be given a root login to a maintenance shell. However, if
|
||||||
`sulogin` is missing, the file `/lib/finit/rescue.conf` is read and
|
`sulogin` is missing, the file `/lib/finit/rescue.conf` is read and
|
||||||
the system booted in a limited fallback mode. See [config.md][]
|
the system booted in a limited fallback mode. See [config.md][]
|
||||||
for more information.
|
for more information.
|
||||||
|
|
||||||
* `single`, or `S`: Single user mode, runlevel 1, in Finit. Useful to
|
This option can be disabled with `configure --without-rescue`
|
||||||
debug problems with the regular runlevel. All services and TTYs in
|
|
||||||
`[1]` will be started, so a `tty [1] @console nologin` configuration
|
|
||||||
presents you with a root console without login.
|
|
||||||
|
|
||||||
For more on kernel boot paramaters, see the man page [bootparam(7)][].
|
**Note:** in this mode `initctl` will not work. Correct the problem
|
||||||
|
and use `reboot -f` to force reboot.
|
||||||
|
|
||||||
[config.md][]: config.md#rescue-mode
|
* `single`, or `S`: Overrides the configured runlevel (default: 2) to go
|
||||||
|
to after bootstrap by forcing it to runlevel 1, this is also known
|
||||||
|
as single user mode. Useful to debug startup problems. All services
|
||||||
|
and TTYs in `[1]` will be started, so a `tty [1] @console nologin`
|
||||||
|
configuration presents you with a root console without login.
|
||||||
|
|
||||||
|
* `1-9`, except `6`: override the configured `runlevel`. Like the `S`
|
||||||
|
and `rescue`, giving a single number on the kernel command line tells
|
||||||
|
Finit to ignore any `runlevel` in `/etc/finit.conf` as well as the
|
||||||
|
configure fallback `--with-runlevel=N` setting. Remember, `6` is the
|
||||||
|
reboot runlevel and is not permitted. Any other values are ignored.
|
||||||
|
|
||||||
|
For more on kernel boot parameters, see the man page [bootparam(7)][].
|
||||||
|
|
||||||
|
[config.md]: config.md#rescue-mode
|
||||||
[bootparam(7)]: https://www.man7.org/linux/man-pages/man7/bootparam.7.html
|
[bootparam(7)]: https://www.man7.org/linux/man-pages/man7/bootparam.7.html
|
||||||
|
|||||||
+78
-17
@@ -13,9 +13,9 @@ Finit Conditions
|
|||||||
Introduction
|
Introduction
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Conditions are a new addition to Finit, introduced in v3, with the
|
Conditions are a relatively new addition to Finit, introduced in v3,
|
||||||
intention of providing a mechanism for common synchronization problems.
|
with the intention of providing a mechanism for common synchronization
|
||||||
For example:
|
problems. For example:
|
||||||
|
|
||||||
- *"wait for service A to start before starting service B"*, or
|
- *"wait for service A to start before starting service B"*, or
|
||||||
- *"wait for basic network access to be available"*
|
- *"wait for basic network access to be available"*
|
||||||
@@ -27,6 +27,16 @@ specified separated by comma. Multiple conditions are logically AND'ed
|
|||||||
during evaluation, i.e. all conditions must be satisfied in order for a
|
during evaluation, i.e. all conditions must be satisfied in order for a
|
||||||
service to run.
|
service to run.
|
||||||
|
|
||||||
|
A special syntax, using a leading `!` in run/task/service conditions,
|
||||||
|
denote if a:
|
||||||
|
|
||||||
|
- service does not support `SIGHUP`
|
||||||
|
- run/task should not block runlevel changes (i.e., bootstrap)
|
||||||
|
|
||||||
|
Finit guarantees by default that all run/tasks run (at least) once
|
||||||
|
per runlevel. For most tasks this is a good default, for example
|
||||||
|
checking SSH host keys or loading keymap. However, for conditions
|
||||||
|
that are unlikely to happen it is not. (See example below.)
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
@@ -35,22 +45,40 @@ service to run.
|
|||||||
In this example the Network monitor daemon `netd` is not started until
|
In this example the Network monitor daemon `netd` is not started until
|
||||||
both the `pid/setupd` *and* `pid/zebra` conditions are satisfied. A
|
both the `pid/setupd` *and* `pid/zebra` conditions are satisfied. A
|
||||||
`pid/` condition is satisfied by the corresponding service's PID file
|
`pid/` condition is satisfied by the corresponding service's PID file
|
||||||
being created.
|
being created, i.e., the service's default readiness notification.
|
||||||
|
|
||||||
**NOTE:** Conditions also stop services when a condition is no longer
|
**NOTE:** Conditions also stop services when a condition is no longer
|
||||||
asserted. I.e., if the Zebra process above stops or restarts, netd
|
asserted. I.e., if the Zebra process above stops or restarts, netd
|
||||||
will also stop or restart.
|
will also stop or restart.
|
||||||
|
|
||||||
|
Another example is `dropbear`, it does not support `SIGHUP`, but we can
|
||||||
|
also see optional sourcing of arguments from an environment file:
|
||||||
|
|
||||||
|
service [2345789] <!> env:-/etc/default/dropbear dropbear -F -R $DROPBEAR_ARGS -- Dropbear SSH daemon
|
||||||
|
|
||||||
|
Finally, the weird "block runlevel changes" example. Here we see what
|
||||||
|
happens when Finit receives `SIGPWR`, sent from a power daemon like
|
||||||
|
[powstatd(8)][]. A condition is asserted and a user can set up their
|
||||||
|
own task to act on it. We do not want this task to block Finit from
|
||||||
|
moving to the next runlevel after bootstrap, so we set `<!>`:
|
||||||
|
|
||||||
|
task [S0123456789] <!sys/pwr/fail> name:pwrfail initctl poweroff -- Power failure, shutting down
|
||||||
|
|
||||||
|
|
||||||
Triggering
|
Triggering
|
||||||
----------
|
----------
|
||||||
|
|
||||||
Conditions are mainly triggered (asserted) by built-in plugins, e.g.,
|
Conditions are mainly triggered (asserted) by built-in plugins, e.g.,
|
||||||
`netlink.so` and `pidfile.so`, see below for built-in conditions. Finit
|
|
||||||
also supports user-defined conditions, sometimes referred to as static
|
- `netlink.so`: provides `<net/...>`
|
||||||
or one-shot conditions. They live in the `<usr/...` namespace and are
|
- `pidfile.so`: provides `<pid/...>`
|
||||||
constrained to a flat hierarchy without any sub-directories, unlike the
|
- Cmdline `finit.cond=arg`: provides `<boot/arg>`
|
||||||
pidfile plugin, for instance.
|
|
||||||
|
See below for built-in conditions. Finit also supports user-defined
|
||||||
|
conditions, sometimes referred to as static or one-shot conditions.
|
||||||
|
They live in the `<usr/...>` namespace and are constrained to a flat
|
||||||
|
hierarchy without any sub-directories, unlike the pidfile plugin, for
|
||||||
|
instance.
|
||||||
|
|
||||||
User-defined conditions are controlled using the `initctl cond set` and
|
User-defined conditions are controlled using the `initctl cond set` and
|
||||||
`initctl cond clear` commands:
|
`initctl cond clear` commands:
|
||||||
@@ -87,12 +115,35 @@ Static (one-shot) conditions, like `usr/`, never enter the `flux` state.
|
|||||||
Built-in Conditions
|
Built-in Conditions
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Finit comes with a `pidfile` and `netlink` plugin. When enabled, the
|
Finit comes with a set of plugins for conditions:
|
||||||
`pidfile` plugin watches `/var/run/` (recursively) for PID files created
|
|
||||||
by the monitored services, and sets a corresponding condition in the
|
- `devmon` (built-in)
|
||||||
`pid/` namespace. Similarily, the `netlink` plugin provides basic
|
- `netlink`
|
||||||
conditions for when an interface is brought up/down and when a default
|
- `pidfile`
|
||||||
route (gateway) is set, in the `net/` namespace.
|
- `sys`
|
||||||
|
- `usr`
|
||||||
|
|
||||||
|
The `devmon` (built-in) plugin monitors `/dev` and `/dev/dir` for device
|
||||||
|
nodes being created and removed. It is active only when a run, task, or
|
||||||
|
service has declared a `<dev/foo>` or `<dev/dir/bar>` condition.
|
||||||
|
|
||||||
|
The `pidfile` plugin (recursively) watches `/run/` (recursively) for PID
|
||||||
|
files created by the monitored services, and sets a corresponding
|
||||||
|
condition in the `pid/` namespace.
|
||||||
|
|
||||||
|
Similarly, the `netlink` plugin provides basic conditions for when an
|
||||||
|
interface is brought up/down and when a default route (gateway) is set,
|
||||||
|
in the `net/` namespace.
|
||||||
|
|
||||||
|
The `sys` and `usr` plugins monitor are passive condition monitors where
|
||||||
|
the action is provided by `keventd`, signal handlers, and in the case of
|
||||||
|
`usr`, the end-user via the `initctl` tool.
|
||||||
|
|
||||||
|
Additionally, the various states of a run/task/sysv/service can also be
|
||||||
|
used as conditions, the image above shows the state names. The syntax
|
||||||
|
for a `service` type process: `<service/foo/STATE>`. The other types,
|
||||||
|
in particular run/task/sysv, there are the additional states `success`
|
||||||
|
and `failure`.
|
||||||
|
|
||||||
With the example listed above, finit does not start the `/sbin/netd`
|
With the example listed above, finit does not start the `/sbin/netd`
|
||||||
daemon until `setupd` and `zebra` has started *and* created their PID
|
daemon until `setupd` and `zebra` has started *and* created their PID
|
||||||
@@ -111,6 +162,14 @@ Built-in conditions:
|
|||||||
- `net/<IFNAME>/exist`
|
- `net/<IFNAME>/exist`
|
||||||
- `net/<IFNAME>/up`
|
- `net/<IFNAME>/up`
|
||||||
- `net/<IFNAME>/running`
|
- `net/<IFNAME>/running`
|
||||||
|
- `service/<NAME[:ID]>/<STATE>`
|
||||||
|
- `{run, task, sysv}/<NAME[:ID]>/{<STATE>, success, failure}`
|
||||||
|
- `sys/pwr/ac`
|
||||||
|
- `sys/pwr/fail`
|
||||||
|
- `sys/key/ctrlaltdel`
|
||||||
|
- `usr/foo`
|
||||||
|
- `boot/arg`
|
||||||
|
- `dev/node` and `dev/dir/node`
|
||||||
|
|
||||||
**Note:** `up` means administratively up, the interface flag `IFF_UP`.
|
**Note:** `up` means administratively up, the interface flag `IFF_UP`.
|
||||||
`running` is the `IFF_RUNNING` flag, meaning operatively up. The
|
`running` is the `IFF_RUNNING` flag, meaning operatively up. The
|
||||||
@@ -156,7 +215,7 @@ Debugging
|
|||||||
If a service is not being started as it should, the problem might be
|
If a service is not being started as it should, the problem might be
|
||||||
that one of its conditions is not in the expected state. Use the
|
that one of its conditions is not in the expected state. Use the
|
||||||
command `initctl status` to inspect service status. Services in the
|
command `initctl status` to inspect service status. Services in the
|
||||||
`ready` state are pending a condition.
|
`waiting` state are pending a condition.
|
||||||
|
|
||||||
In that situation, running `initctl cond show` reveals which of the
|
In that situation, running `initctl cond show` reveals which of the
|
||||||
conditions that are not satisfied. Listed as `off` below.
|
conditions that are not satisfied. Listed as `off` below.
|
||||||
@@ -173,7 +232,7 @@ PID IDENT STATUS CONDITION (+ ON, ~ FLUX, - OFF)
|
|||||||
|
|
||||||
Here we can see that `netd` is allowed to run since both its conditions
|
Here we can see that `netd` is allowed to run since both its conditions
|
||||||
are in the `on` state, as indicated by the `+`-prefix. `udhcpc` however
|
are in the `on` state, as indicated by the `+`-prefix. `udhcpc` however
|
||||||
is not allowed to run since `net/vlan1/exist` condition is not satsifed.
|
is not allowed to run since `net/vlan1/exist` condition is not satisfied.
|
||||||
As indicated by the `-`-prefix.
|
As indicated by the `-`-prefix.
|
||||||
|
|
||||||
To fake interface `vlan1` suddenly appearing, and test what happens to
|
To fake interface `vlan1` suddenly appearing, and test what happens to
|
||||||
@@ -224,3 +283,5 @@ Therefore, any plugin that supplies Finit with conditions must ensure
|
|||||||
that their state is updated after each reconfiguration. This can be
|
that their state is updated after each reconfiguration. This can be
|
||||||
done by binding to the `HOOK_SVC_RECONF` hook. For an example of how
|
done by binding to the `HOOK_SVC_RECONF` hook. For an example of how
|
||||||
to do this, see `plugins/pidfile.c`.
|
to do this, see `plugins/pidfile.c`.
|
||||||
|
|
||||||
|
[powstatd(8)]: https://manpages.ubuntu.com/manpages/trusty/en/man8/powstatd.8.html
|
||||||
|
|||||||
+796
-93
File diff suppressed because it is too large
Load Diff
+154
-29
@@ -8,7 +8,8 @@ Hooks & Plugins
|
|||||||
* [Shutdown Hooks](#shutdown-hooks)
|
* [Shutdown Hooks](#shutdown-hooks)
|
||||||
|
|
||||||
Finit can be extended to add general functionality in the form of I/O
|
Finit can be extended to add general functionality in the form of I/O
|
||||||
monitors, or hook plugins.
|
monitors, or hook plugins. It is even possible to run scripts at these
|
||||||
|
hook points, see below.
|
||||||
|
|
||||||
The following sections detail existing plugins and hook points. For
|
The following sections detail existing plugins and hook points. For
|
||||||
more information, see the plugins listed below.
|
more information, see the plugins listed below.
|
||||||
@@ -27,33 +28,92 @@ For your convenience a set of *optional* plugins are available:
|
|||||||
system and runs at `HOOK_BASEFS_UP`. The `/var`, `/run`, and `/dev`
|
system and runs at `HOOK_BASEFS_UP`. The `/var`, `/run`, and `/dev`
|
||||||
file systems must be writable for this plugin to work.
|
file systems must be writable for this plugin to work.
|
||||||
|
|
||||||
Note: On an embedded system both `/var` and `/run` can be `tmpfs` RAM
|
This plugin is a wrapper for the [tmpfiles.d(5)][] implementation that
|
||||||
disks and `/dev` is usually a `devtmpfs`. This must be defined in the
|
Finit has. Capable but limited: no aging, attributes, or subvolumes.
|
||||||
`/etc/fstab` file and in the Linux kernel config.
|
|
||||||
|
By default, `/lib/finit/tmpfiles.d` carries all the default .conf
|
||||||
|
files distributed with Finit. It is read first but can be overridden
|
||||||
|
by any of the standard tmpfiles.d directories, e.g. `/etc/tmpfiles.d`.
|
||||||
|
|
||||||
|
> **Note:** On an embedded system both `/var` and `/run` can be `tmpfs`
|
||||||
|
> RAM disks and `/dev` is usually a `devtmpfs`. This must be defined
|
||||||
|
> in the `/etc/fstab` file and in the Linux kernel config.
|
||||||
|
|
||||||
* *dbus.so*: Setup and start system message bus, D-Bus, at boot.
|
* *dbus.so*: Setup and start system message bus, D-Bus, at boot.
|
||||||
_Optional plugin._
|
_Optional plugin._
|
||||||
|
|
||||||
* *hotplug.so*: Setup and start either udev or mdev hotplug daemon, if
|
* *hook-scripts.so*: Trigger the execution of scripts from plugin hook
|
||||||
available.
|
points (see [Hooks](#hooks)). _Optional plugin._
|
||||||
|
|
||||||
|
This plugin is particularly useful for early boot debugging that needs
|
||||||
|
to take place before regular services are available.
|
||||||
|
|
||||||
|
For example, say that you want to enable some kernel tracing before
|
||||||
|
modules are loaded. With hook scripts, you can just drop in a shell
|
||||||
|
script in `/libexec/finit/hook/mount/all/` that will poke the right
|
||||||
|
control files in tracefs.
|
||||||
|
|
||||||
|
Scripts are located in `/libexec/finit/hook` by default, this can be
|
||||||
|
customized at build-time using the `--with-hook-scripts-path=PATH`
|
||||||
|
argument to `configure`.
|
||||||
|
|
||||||
|
* *hotplug.so*: Replaced with `/lib/finit/system/10-hotplug.conf`, which
|
||||||
|
checks for `udevd` and `mdev` at boot. This file can be overridden by a
|
||||||
|
file in `/etc/finit.d/10-hotplug.conf`.
|
||||||
|
|
||||||
|
Enabled by default.
|
||||||
|
|
||||||
|
> See the [Services](config.md#services) section in the configuration
|
||||||
|
> guide for an example how to run `mdevd`, alternative to plain mdev.
|
||||||
|
|
||||||
* *rtc.so*: Restore and save system clock from/to RTC on boot/halt.
|
* *rtc.so*: Restore and save system clock from/to RTC on boot/halt.
|
||||||
|
Enabled by default.
|
||||||
|
|
||||||
* *modules-load.so*: Scans /etc/modules-load.d for modules to modprobe.
|
* *modules-load.so*: Scans `/etc/modules-load.d/*.conf` for modules to
|
||||||
|
load using `modprobe`. Each file can contain multiple lines with the
|
||||||
|
name of the module to load. Any line starting with the standard UNIX
|
||||||
|
comment character, `#`, or `;`, is skipped.
|
||||||
|
|
||||||
|
Modules are by default loaded in runlevel `S` using the `task` stanza.
|
||||||
|
Each module gets a unique `name:modprobe.foo`, and optional`:ID`. The
|
||||||
|
runlevel can be changed per file using:
|
||||||
|
|
||||||
|
set runlevel 2345
|
||||||
|
|
||||||
|
The `:ID` is a globally incremented index, which can be disabled per
|
||||||
|
file (anywhere) using the following config line:
|
||||||
|
|
||||||
|
set noindex
|
||||||
|
|
||||||
|
To change the index used by the plugin:
|
||||||
|
|
||||||
|
set index 1234
|
||||||
|
|
||||||
|
**Note:** unlike the traditional .conf `module` directive, which load
|
||||||
|
any listed module immediately, this plugin creates a background `task`
|
||||||
|
which load the module(s) in the background. The program is modprobe,
|
||||||
|
`/sbin/modprobe`, which you can override per .conf file:
|
||||||
|
|
||||||
|
set modprobe /path/to/maybe-a-modprobe-wrapper
|
||||||
|
|
||||||
|
Since these tasks run in the background, they usually return `[ OK ]`
|
||||||
|
at boot, unless the modprobe tool does not exist. Check syslog for
|
||||||
|
warnings and the actual status of the operation using `initctl`.
|
||||||
|
|
||||||
* *netlink.so*: Listens to Linux kernel Netlink events for gateway and
|
* *netlink.so*: Listens to Linux kernel Netlink events for gateway and
|
||||||
interfaces. These events are then sent to the Finit service monitor
|
interfaces. These events are then sent to the Finit service monitor
|
||||||
for services that may want to be SIGHUP'ed on new default route or
|
for services that may want to be SIGHUP'ed on new default route or
|
||||||
interfaces going up/down.
|
interfaces going up/down. Enabled by default.
|
||||||
|
|
||||||
* *resolvconf.so*: Setup necessary files for `resolvconf` at startup.
|
* *resolvconf.so*: Setup necessary files for `resolvconf` at startup.
|
||||||
_Optional plugin._
|
_Optional plugin._
|
||||||
|
|
||||||
* *tty.so*: Watches `/dev`, using inotify, for new device nodes (TTY's)
|
* *tty.so*: Watches `/dev`, using inotify, for new device nodes (TTY's)
|
||||||
to start/stop getty consoles on them on demand. Useful when plugging
|
to start/stop getty consoles on them on demand. Useful when plugging
|
||||||
in a usb2serial converter to login to your embedded device.
|
in a usb2serial converter to login to your embedded device. Enabled
|
||||||
|
by default.
|
||||||
|
|
||||||
* *urandom.so*: Setup random seed at startup.
|
* *urandom.so*: Setup random seed at startup. Enabled by default.
|
||||||
|
|
||||||
* *x11-common.so*: Setup necessary files for X-Window. _Optional plugin._
|
* *x11-common.so*: Setup necessary files for X-Window. _Optional plugin._
|
||||||
|
|
||||||
@@ -67,40 +127,105 @@ state, etc. Available hook points are:
|
|||||||
Hooks
|
Hooks
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
In the below listings, the first label is the hook point for a C plugin,
|
||||||
|
the second is the condition name and hook script path. A hook script is
|
||||||
|
a plain shell script, or program, that does a very small dedicated job
|
||||||
|
at the below hook points.
|
||||||
|
|
||||||
|
See [Run-parts Scripts](config.md#run-parts-scripts) for details on the
|
||||||
|
requirements, possibilities, and *limitations* of hook scripts.
|
||||||
|
|
||||||
|
All hook scripts are called with at least one environment variable set,
|
||||||
|
the hook name, useful when reusing the same hook script for multiple
|
||||||
|
hook points:
|
||||||
|
|
||||||
|
- `FINIT_HOOK_NAME`: set to the second label, e.g., `hook/net/up`
|
||||||
|
- `FINIT_SHUTDOWN`: set for `hook/sys/shutdown` and later to one
|
||||||
|
of `halt`, `poweroff`, or `reboot`.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
$ mkdir -p /libexec/finit/hook/sys/down
|
||||||
|
$ cat <<EOF >/libexec/finit/hook/sys/down/foo.sh
|
||||||
|
#!/bin/sh
|
||||||
|
echo 'I run just before the reboot() syscall at shutdown/reboot'
|
||||||
|
echo 'I have access to /dev since devtmpfs is exempt from umount'
|
||||||
|
echo "FINIT_HOOK_NAME: $FINIT_HOOK_NAME"
|
||||||
|
if [ -n "$FINIT_SHUTDOWN" ]; then
|
||||||
|
echo "FINIT_SHUTDOWN: $FINIT_SHUTDOWN"
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
EOF
|
||||||
|
$ chmod +x /libexec/finit/hook/sys/down/foo.sh
|
||||||
|
|
||||||
|
> **Note:** to use hook scripts, even for pre-bootstrap and pre-shutdown
|
||||||
|
> tasks, you must build with `configure --enable-hook-scripts-plugin`.
|
||||||
|
|
||||||
### Bootstrap Hooks
|
### Bootstrap Hooks
|
||||||
|
|
||||||
* `HOOK_ROOTFS_UP`: When `finit.conf` has been read and `/` has is
|
* `HOOK_BANNER`, `hook/sys/banner`: The very first point at which a
|
||||||
mounted — very early
|
plugin can run. Intended to be used as a banner replacement.
|
||||||
|
Essentially this runs just before entering runlevel S. Assume nothing
|
||||||
|
is available, so be prepared to use absolute paths, etc.
|
||||||
|
|
||||||
* `HOOK_BASEFS_UP`: All of `/etc/fstab` is mounted, swap is available
|
* `HOOK_ROOTFS_UP`, `hook/mount/root`: When `finit.conf` has been read
|
||||||
and default init signals are setup
|
and `/` has is mounted — very early
|
||||||
|
|
||||||
* `HOOK_NETWORK_UP`: System bootstrap, runlevel S, has completed and
|
* `HOOK_MOUNT_ERROR`, `hook/mount/error`: executed if `mount -a` fails
|
||||||
networking is up (`lo` is up and the `network` script has run)
|
|
||||||
|
|
||||||
* `HOOK_SVC_UP`: All services in the active runlevel has been launched
|
* `HOOK_MOUNT_POST`, `hook/mount/post`: always executed after `mount -a`
|
||||||
|
|
||||||
* `HOOK_SYSTEM_UP`: All services *and* everything in `/etc/finit.d`
|
* `HOOK_BASEFS_UP`, `hook/mount/all`: All of `/etc/fstab` is mounted,
|
||||||
has been launched
|
swap is available and default init signals are setup
|
||||||
|
|
||||||
|
* `HOOK_SVC_PLUGIN`, `hook/svc/plugin`: Called in `conf_init()` right
|
||||||
|
before loading `/etc/finit.conf`. For plugins to register any early
|
||||||
|
run/task/services, please do NOT use any earlier hook point. That
|
||||||
|
will cause uninitialized rlimits that lead to unpredictable results
|
||||||
|
when Finit later tries to start the run/task/service.
|
||||||
|
|
||||||
|
* `HOOK_NETWORK_UP`, `hook/net/up`: System bootstrap, runlevel S, has
|
||||||
|
completed and networking is up (`lo` is up and the `network` script
|
||||||
|
has run)
|
||||||
|
|
||||||
|
* `HOOK_SVC_UP`, `hook/svc/up`: All services in the active runlevel have
|
||||||
|
been launched
|
||||||
|
|
||||||
|
* `HOOK_SYSTEM_UP`, `hook/sys/up`: All services *and* everything in
|
||||||
|
`/etc/finit.d` has been launched
|
||||||
|
|
||||||
### Runtime Hooks
|
### Runtime Hooks
|
||||||
|
|
||||||
* `HOOK_SVC_RECONF`: Called when the user has changed something in the
|
* `HOOK_SVC_RECONF`, N/A: Called when the user has changed something in
|
||||||
`/etc/finit.d` directory and issued `SIGHUP`. The hook is called when
|
the `/etc/finit.d` directory and issued `SIGHUP`. The hook is called
|
||||||
all modified/removed services have been stopped. When the hook has
|
when all modified/removed services have been stopped. When the hook
|
||||||
completed, Finit continues to start all modified and new services.
|
has completed, Finit continues to start all modified and new services.
|
||||||
|
|
||||||
* `HOOK_RUNLEVEL_CHANGE`: Called when the user has issued a runlevel
|
* `HOOK_RUNLEVEL_CHANGE`, N/A: Called when the user has issued a
|
||||||
change. The hook is called when services not matching the new
|
runlevel change. The hook is called when services not matching the
|
||||||
runlevel have been been stopped. When the hook has completed, Finit
|
new runlevel have been been stopped. When the hook has completed,
|
||||||
continues to start all services in the new runlevel.
|
Finit continues to start all services in the new runlevel.
|
||||||
|
|
||||||
### Shutdown Hooks
|
### Shutdown Hooks
|
||||||
|
|
||||||
* `HOOK_SHUTDOWN`: Called at shutdown/reboot, right before all
|
* `HOOK_NETWORK_DN`, `hook/net/down`: Called right after having changed
|
||||||
services are sent `SIGTERM`
|
to runlevel 6, or 0, when all services have received their 'stop' signal.
|
||||||
|
|
||||||
|
* `HOOK_SHUTDOWN`, `hook/sys/shutdown`: Called at shutdown/reboot, right
|
||||||
|
before all services are sent `SIGTERM`
|
||||||
|
|
||||||
|
* `HOOK_SVC_DN`, `hook/svc/down`: In shutdown/reboot, all services and
|
||||||
|
non-reserved processes have been killed. **Note:** only hook scripts
|
||||||
|
can run here!
|
||||||
|
|
||||||
|
* `HOOK_SYSTEM_DN`, `hook/sys/down`: In shutdown/reboot, called after
|
||||||
|
all non-reserved file systems have been unmounted, just before Finit
|
||||||
|
tells the kernel to reboot or shut down. **Note:** only hook scripts
|
||||||
|
can run here!
|
||||||
|
|
||||||
Plugins like `tty.so` extend finit by acting on events, they are called
|
Plugins like `tty.so` extend finit by acting on events, they are called
|
||||||
I/O plugins and are called from the finit main loop when `poll()`
|
I/O plugins and are called from the finit main loop when `poll()`
|
||||||
detects an event. See the source code for `plugins/*.c` for more help
|
detects an event. See the source code for `plugins/*.c` for more help
|
||||||
and ideas.
|
and ideas.
|
||||||
|
|
||||||
|
[tmpfiles.d(5)]: https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html
|
||||||
|
|||||||
+55
-1
@@ -1,7 +1,59 @@
|
|||||||
Finit Services
|
Finit Services
|
||||||
==============
|
==============
|
||||||
|
|
||||||

|
Starting & Monitoring
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Finit can start and monitor the following types of daemons:
|
||||||
|
|
||||||
|
* Forks to background, creates a PID file
|
||||||
|
* Runs in foreground:
|
||||||
|
- creates a PID file
|
||||||
|
- does not create a PID file -- Finit can create it for you (optional)
|
||||||
|
|
||||||
|
Finit can *not* start and monitor a daemon that:
|
||||||
|
|
||||||
|
* Forks to background and does *not* create a PID file
|
||||||
|
|
||||||
|
| | Forking | Creates PID File | Finit creates PID File |
|
||||||
|
|---|---------|------------------|------------------------|
|
||||||
|
| ✔ | Yes | Yes | No |
|
||||||
|
| ✔ | No | Yes | No |
|
||||||
|
| ✔ | No | No | Yes, optionally |
|
||||||
|
| ✘ | Yes | No | No |
|
||||||
|
|
||||||
|
> **Note:** PID files is one mechanism used to assert conditions to
|
||||||
|
> synchronize the start and stop of other, dependent, services.
|
||||||
|
|
||||||
|
### Forks to Background w/ PID File
|
||||||
|
|
||||||
|
There are two syntax variants, type 1 and type 2. The former is the
|
||||||
|
traditional one used also for `sysv` start/stop scripts, and the latter
|
||||||
|
is inspired by systemd, with a twist -- it lets Finit guess the pifdile
|
||||||
|
to look for based on the standard path and the basename of the command.
|
||||||
|
|
||||||
|
service pid:!/run/serv.pid serv -- Forking service, type 1
|
||||||
|
service type:forking serv -- Forking service, type 2
|
||||||
|
|
||||||
|
In this example the resulting files to watch for are `/run/serv.pid` and
|
||||||
|
`/var/run/serv.pid`, respectively. On most modern Linux systems this is
|
||||||
|
the same directory (`/var/run` is a symlink to `../run`).
|
||||||
|
|
||||||
|
### Runs in Foreground w/ PID File
|
||||||
|
|
||||||
|
service serv -n -p -- Foreground service w/ PID file
|
||||||
|
|
||||||
|
### Runs in Foreground w/o PID File
|
||||||
|
|
||||||
|
Same as previous, but we tell Finit to create the PID file, because we
|
||||||
|
need it to synchronize start/stop of a dependent service.
|
||||||
|
|
||||||
|
service pid:/run/serv.pid serv -n -- Foreground service w/o PID file
|
||||||
|
|
||||||
|
### Runs in Foreground w/ Custom PID File
|
||||||
|
|
||||||
|
service pid:/run/servy.pid serv -n -p -P /run/servy.pid -- Foreground service w/ custom PID file
|
||||||
|
|
||||||
|
|
||||||
State Machine
|
State Machine
|
||||||
-------------
|
-------------
|
||||||
@@ -11,6 +63,8 @@ For `run`s and `task`s there is an additional end state called `DONE`,
|
|||||||
not shown in the diagram for brevity. Services start in the `HALTED`
|
not shown in the diagram for brevity. Services start in the `HALTED`
|
||||||
state.
|
state.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
The current state depends on the two following conditions:
|
The current state depends on the two following conditions:
|
||||||
|
|
||||||
* `E`: Service enabled. In order for `E` to be satisfied, the service
|
* `E`: Service enabled. In order for `E` to be satisfied, the service
|
||||||
|
|||||||
+17
-9
@@ -12,28 +12,36 @@ have been adopted:
|
|||||||
Same effect as `finit q`, `init q`, or `initctl reload`, reloads all
|
Same effect as `finit q`, `init q`, or `initctl reload`, reloads all
|
||||||
*.conf files in `/etc/finit.d/`
|
*.conf files in `/etc/finit.d/`
|
||||||
|
|
||||||
|
This also restarts the API (initctl) socket, like SysV init and systemd
|
||||||
|
does on USR1 with their FIFO/D-Bus.
|
||||||
|
|
||||||
|
|
||||||
`SIGUSR1`
|
`SIGUSR1`
|
||||||
---------
|
---------
|
||||||
|
|
||||||
Calls shutdown hooks, including `HOOK_SHUTDOWN`, stopping all running
|
Since Finit 4.1 this signal causes Finit to restart its API (initctl)
|
||||||
processes, and unmounts all file systems. Then tells kernel to halt.
|
socket, like SysV init and systemd does on USR1 with their FIFO/D-Bus.
|
||||||
Most people these days want `SIGUSR2` though.
|
|
||||||
|
Finit <= 4.0 performed a system halt (like USR2 without power-off), but
|
||||||
|
this caused compatibility problems with systemd and sysvinit on desktop
|
||||||
|
systems. Hence, since Finit 4.1 it is no longer possible to halt a
|
||||||
|
system with a signal.
|
||||||
|
|
||||||
SysV init and systemd use this to re-open their FIFO/D-Bus.
|
|
||||||
|
|
||||||
`SIGUSR2`
|
`SIGUSR2`
|
||||||
---------
|
---------
|
||||||
|
|
||||||
Like SIGUSR1, but tell kernel to power-off the system, if ACPI or
|
Calls shutdown hooks, including `HOOK_SHUTDOWN`, stopping all running
|
||||||
similar exists to actually do this. If the kernel fails power-off,
|
processes, and unmounts all file systems. Then tells kernel to power
|
||||||
Finit falls back to halt.
|
off the system, if ACPI or similar exists to actually do this. If the
|
||||||
|
kernel fails power-off, Finit falls back to halt.
|
||||||
|
|
||||||
SysV init N/A, systemd dumps its internal state to log.
|
SysV init N/A, systemd dumps its internal state to log.
|
||||||
|
|
||||||
`SIGTERM`
|
`SIGTERM`
|
||||||
---------
|
---------
|
||||||
|
|
||||||
Like `SIGUSR1`, but tell kernel to reboot the system when done.
|
Like `SIGUSR2`, but tell kernel to reboot the system when done.
|
||||||
|
|
||||||
SysV init N/A, systemd rexecutes itself.
|
SysV init N/A, systemd rexecutes itself.
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 230 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 164 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,141 @@
|
|||||||
|
_cond()
|
||||||
|
{
|
||||||
|
initctl -pt cond dump | awk '{print $4}' | sed 's/<\(.*\)>/\1/'
|
||||||
|
}
|
||||||
|
|
||||||
|
_ident()
|
||||||
|
{
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
initctl ident | grep -q $1
|
||||||
|
else
|
||||||
|
initctl ident
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_svc()
|
||||||
|
{
|
||||||
|
initctl ls -pt | grep $1 | sed "s/.*\/\(.*\)/\1/g" | sort -u
|
||||||
|
}
|
||||||
|
|
||||||
|
_enabled()
|
||||||
|
{
|
||||||
|
echo "$(_svc enabled)"
|
||||||
|
}
|
||||||
|
|
||||||
|
_available()
|
||||||
|
{
|
||||||
|
all=$(mktemp)
|
||||||
|
ena=$(mktemp)
|
||||||
|
echo "$(_svc available)" >$all
|
||||||
|
echo "$(_svc enabled)" >$ena
|
||||||
|
grep -v -f $ena $all
|
||||||
|
rm $all $ena
|
||||||
|
}
|
||||||
|
|
||||||
|
# Determine first non-option word. Usually the command
|
||||||
|
_firstword() {
|
||||||
|
local firstword i
|
||||||
|
|
||||||
|
firstword=
|
||||||
|
for ((i = 1; i < ${#COMP_WORDS[@]}; ++i)); do
|
||||||
|
if [[ ${COMP_WORDS[i]} != -* ]]; then
|
||||||
|
firstword=${COMP_WORDS[i]}
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo $firstword
|
||||||
|
}
|
||||||
|
|
||||||
|
# Determine last non-option word. Uusally a sub-command
|
||||||
|
_lastword() {
|
||||||
|
local lastword i
|
||||||
|
|
||||||
|
lastword=
|
||||||
|
for ((i = 1; i < ${#COMP_WORDS[@]}; ++i)); do
|
||||||
|
if [[ ${COMP_WORDS[i]} != -* ]] && [[ -n ${COMP_WORDS[i]} ]] && [[ ${COMP_WORDS[i]} != $cur ]]; then
|
||||||
|
lastword=${COMP_WORDS[i]}
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo $lastword
|
||||||
|
}
|
||||||
|
|
||||||
|
_initctl()
|
||||||
|
{
|
||||||
|
local cur command
|
||||||
|
|
||||||
|
cur=${COMP_WORDS[COMP_CWORD]}
|
||||||
|
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||||
|
firstword=$(_firstword)
|
||||||
|
lastword=$(_lastword)
|
||||||
|
|
||||||
|
commands="status cond debug help kill ls log version list enable \
|
||||||
|
disable touch show cat edit create delete reload start \
|
||||||
|
stop restart signal cgroup ps top plugins runlevel reboot \
|
||||||
|
halt poweroff suspend utmp"
|
||||||
|
cond_cmds="set get clear status dump"
|
||||||
|
cond_types="hook net pid service task usr"
|
||||||
|
signals="int term hup stop tstp cont usr1 usr2 pwr"
|
||||||
|
options="-b --batch \
|
||||||
|
-c --create \
|
||||||
|
-d --debug \
|
||||||
|
-f --force \
|
||||||
|
-h --help \
|
||||||
|
-j --json \
|
||||||
|
-n --noerr \
|
||||||
|
-1 --once \
|
||||||
|
-p --plain \
|
||||||
|
-q --quiet \
|
||||||
|
-t --no-heading \
|
||||||
|
-v --verbose \
|
||||||
|
-V --version"
|
||||||
|
|
||||||
|
case "${firstword}" in
|
||||||
|
enable)
|
||||||
|
COMPREPLY=($(compgen -W "$(_available)" -- $cur))
|
||||||
|
;;
|
||||||
|
disable|touch)
|
||||||
|
COMPREPLY=($(compgen -W "$(_enabled)" -- $cur))
|
||||||
|
;;
|
||||||
|
show|cat|edit|delete)
|
||||||
|
COMPREPLY=($(compgen -W "$(_svc .)" -- $cur))
|
||||||
|
;;
|
||||||
|
start|stop|restart|log|status)
|
||||||
|
COMPREPLY=($(compgen -W "$(_ident)" -- $cur))
|
||||||
|
;;
|
||||||
|
signal|kill)
|
||||||
|
if $(_ident "${prev}"); then
|
||||||
|
COMPREPLY=($(compgen -W "$signals" -- $cur))
|
||||||
|
else
|
||||||
|
COMPREPLY=($(compgen -W "$(_ident)" -- $cur))
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
cond)
|
||||||
|
case "${lastword}" in
|
||||||
|
set|clear)
|
||||||
|
compopt -o nospace
|
||||||
|
COMPREPLY=($(compgen -W "usr/" -- $cur))
|
||||||
|
;;
|
||||||
|
get)
|
||||||
|
COMPREPLY=($(compgen -W "$(_cond)" -- $cur))
|
||||||
|
;;
|
||||||
|
dump)
|
||||||
|
COMPREPLY=($(compgen -W "$cond_types" -- $cur))
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
COMPREPLY=($(compgen -W "$cond_cmds" -- $cur))
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
COMPREPLY=($(compgen -W "$commands" -- $cur))
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [[ $cur == -* ]]; then
|
||||||
|
COMPREPLY=($(compgen -W "$options" -- $cur))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
complete -F _initctl initctl
|
||||||
+19
-23
@@ -1,8 +1,6 @@
|
|||||||
# From https://github.com/collectd/collectd/blob/master/configure.ac
|
# From https://github.com/collectd/collectd/blob/master/configure.ac
|
||||||
# Dependency handling currently unused
|
# Dependency handling currently unused
|
||||||
|
|
||||||
define([toupper], [translit([$1], [a-z], [A-Z])])
|
|
||||||
define([sanitize], [translit([$1], [-], [_])])
|
|
||||||
define([enadis], [ifelse([$1], [yes], [disable], [enable])])
|
define([enadis], [ifelse([$1], [yes], [disable], [enable])])
|
||||||
|
|
||||||
# AC_PLUGIN(name, default, info)
|
# AC_PLUGIN(name, default, info)
|
||||||
@@ -10,27 +8,25 @@ define([enadis], [ifelse([$1], [yes], [disable], [enable])])
|
|||||||
AC_DEFUN([AC_PLUGIN],[
|
AC_DEFUN([AC_PLUGIN],[
|
||||||
m4_divert_once([HELP_ENABLE], [
|
m4_divert_once([HELP_ENABLE], [
|
||||||
Optional Plugins:])
|
Optional Plugins:])
|
||||||
|
define(PLUGGY, m4_translit([$1],[a-z-][A-Z-]))dnl
|
||||||
|
AC_ARG_ENABLE([$1-plugin], AS_HELP_STRING([--enadis($2)-$1-plugin], [$3]), [
|
||||||
|
if test "x$enableval" = "xyes"; then
|
||||||
|
enable_plugin="yes"
|
||||||
|
else
|
||||||
enable_plugin="no"
|
enable_plugin="no"
|
||||||
define(pluggy, sanitize($1))
|
fi], [
|
||||||
define(PLUGGY, toupper(pluggy))
|
if test "x$enable_all_plugins" = "xauto"; then
|
||||||
AC_ARG_ENABLE([$1-plugin], AS_HELP_STRING([--enadis($2)-$1-plugin], [$3]), [
|
if test "x$2" = "xyes"; then
|
||||||
if test "x$enableval" = "xyes"; then
|
enable_plugin="yes"
|
||||||
enable_plugin="yes"
|
|
||||||
else
|
else
|
||||||
enable_plugin="no"
|
enable_plugin="no"
|
||||||
fi], [
|
|
||||||
if test "x$enable_all_plugins" = "xauto"; then
|
|
||||||
if test "x$2" = "xyes"; then
|
|
||||||
enable_plugin="yes"
|
|
||||||
else
|
|
||||||
enable_plugin="no"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
enable_plugin="$enable_all_plugins"
|
|
||||||
fi])
|
|
||||||
if test "x$enable_plugin" = "xyes"; then
|
|
||||||
AC_DEFINE([HAVE_]PLUGGY[_PLUGIN], 1, [Define to 1 if the $1 plugin is enabled.])
|
|
||||||
plugins="$1 $plugins"
|
|
||||||
fi
|
fi
|
||||||
AM_CONDITIONAL([BUILD_]PLUGGY[_PLUGIN], test "x$enable_plugin" = "xyes")
|
else
|
||||||
enable_pluggy="$enable_plugin"])
|
enable_plugin="$enable_all_plugins"
|
||||||
|
fi])
|
||||||
|
if test "x$enable_plugin" = "xyes"; then
|
||||||
|
AC_DEFINE(HAVE_[]m4_translit($1,[-a-z],[_A-Z])_PLUGIN, 1, [Define to 1 if the $1 plugin is enabled.])
|
||||||
|
plugins="$1 $plugins"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AM_CONDITIONAL(BUILD_[]m4_translit($1,[-a-z],[_A-Z])_PLUGIN, test "x$enable_plugin" = "xyes")])
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
dist_man8_MANS = finit.8 initctl.8
|
||||||
|
dist_man5_MANS = finit.conf.5
|
||||||
+348
@@ -0,0 +1,348 @@
|
|||||||
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
|
.\" First parameter, NAME, should be all caps
|
||||||
|
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||||
|
.\" other parameters are allowed: see man(7), man(1)
|
||||||
|
.Dd Apr 22, 2023
|
||||||
|
.\" Please adjust this date whenever revising the manpage.
|
||||||
|
.Dt FINIT 8 SMM
|
||||||
|
.Os Linux
|
||||||
|
.Sh NAME
|
||||||
|
.Nm finit
|
||||||
|
.Nd Fast init for Linux systems
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm /sbin/finit
|
||||||
|
.Op --
|
||||||
|
.Op debug
|
||||||
|
.Op finit.cond=foo[,bar[,baz]]
|
||||||
|
.Op finit.config=/path/to/alt/finit.conf
|
||||||
|
.Op finit.debug
|
||||||
|
.Op finit.fstab=/etc/fstab.alt
|
||||||
|
.Op finit.status=<on,off>
|
||||||
|
.Op finit.status_style=<classic,modern>
|
||||||
|
.Op loglevel=<0-7>
|
||||||
|
.Op panic=SEC
|
||||||
|
.Op quiet
|
||||||
|
.Op rescue | recover
|
||||||
|
.Op single | S
|
||||||
|
.Nm /sbin/telinit
|
||||||
|
.Op Fl hv
|
||||||
|
.Op q | Q | 0-9
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
Fast init for Linux systems. Reverse engineered from the EeePC
|
||||||
|
fastinit, 10+ years ago by Claudio Matsuoka, "gaps filled with frog
|
||||||
|
DNA ...". Focus is on small and embedded systems, although Finit is
|
||||||
|
fully usable on server and desktop systems as well.
|
||||||
|
.Pp
|
||||||
|
Features include:
|
||||||
|
.Bl -bullet -width 1n -compact
|
||||||
|
.It
|
||||||
|
Runlevels, defined per service
|
||||||
|
.It
|
||||||
|
One-shot tasks, services (daemons), or SysV init start/stop scripts
|
||||||
|
.It
|
||||||
|
Runparts and
|
||||||
|
.Pa /etc/rc.local
|
||||||
|
support
|
||||||
|
.It
|
||||||
|
Process supervision similar to
|
||||||
|
.Xr systemd 8
|
||||||
|
.It
|
||||||
|
Sourcing environment files
|
||||||
|
.It
|
||||||
|
Conditions for network/process/custom dependencies
|
||||||
|
.It
|
||||||
|
Process readiness notification for synchronizing system startup as well
|
||||||
|
as reconfiguration at runtime. Natively PID files are used, but systemd
|
||||||
|
.Cm sd_notify()
|
||||||
|
and s6 notification is also supported.
|
||||||
|
.It
|
||||||
|
Limited support for
|
||||||
|
.Xr tmpfiles.d 5 ,
|
||||||
|
no aging, attributes, or subvolumes
|
||||||
|
.It
|
||||||
|
Pre/Post script actions
|
||||||
|
.It
|
||||||
|
Tooling to enable/disable services
|
||||||
|
.It
|
||||||
|
Built-in getty
|
||||||
|
.It
|
||||||
|
Built-in watchdog, with support for hand-over to
|
||||||
|
.Lk https://troglobit.com/watchdogd.html watchdogd
|
||||||
|
.It
|
||||||
|
Built-in support for Debian/BusyBox
|
||||||
|
.Pa /etc/network/interfaces
|
||||||
|
.It
|
||||||
|
Cgroups v2, both configuration and monitoring in `initctl top`
|
||||||
|
.It
|
||||||
|
Plugin support for customization
|
||||||
|
.It
|
||||||
|
Proper rescue mode with bundled `sulogin` for protected maintenance shell
|
||||||
|
.El
|
||||||
|
.Sh BOOTPARAM
|
||||||
|
.Nm
|
||||||
|
support the following command line parameters to alter the behavior
|
||||||
|
at boot. Notice the
|
||||||
|
.Cm --
|
||||||
|
separator needed to tell the kernel which paramters should be given to
|
||||||
|
PID 1. For more information on this, and available kernel command line
|
||||||
|
options, see
|
||||||
|
.Xr bootparam 7 .
|
||||||
|
.Bl -tag -width pid -offset indent
|
||||||
|
.It Cm debug
|
||||||
|
Enable kernel debug. Debug messages are printed to the console until
|
||||||
|
Finit starts up, unless
|
||||||
|
.Cm loglevel=7
|
||||||
|
(below) is used.
|
||||||
|
.It Cm finit.cond=foo[,bar[,baz]]
|
||||||
|
set
|
||||||
|
.Cm <boot/foo>
|
||||||
|
condition, optionally multiple conditions can be set using the same
|
||||||
|
option, separated with a comma. Alternatively, multiple
|
||||||
|
.Cm foo.cond=arg
|
||||||
|
can be given. Each will result in a
|
||||||
|
.Cm <boot/arg>
|
||||||
|
condition being set to control the rest of the system bootstrap.
|
||||||
|
.Pp
|
||||||
|
Very useful for selecting different boot modes, e.g. manufacturing test,
|
||||||
|
firmware upgrade, or rescue mode.
|
||||||
|
.Pp
|
||||||
|
.Sy Note:
|
||||||
|
.Cm <boot/...>
|
||||||
|
conditions cannot be cleared with
|
||||||
|
.Nm initctl !
|
||||||
|
.It Cm finit.config=/path/to/alternative/finit.conf
|
||||||
|
override the compile-time bootstrap config file, default:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
./configure --with-config=/etc/finit.conf
|
||||||
|
.Ed
|
||||||
|
Useful when starting up in various rescue mode, factory, or
|
||||||
|
production test setups. Use the top-level configuration file
|
||||||
|
directive
|
||||||
|
.Cm rcsd Ar /path/to/finit.d
|
||||||
|
to override the default rcS.d directory.
|
||||||
|
.It Cm finit.debug
|
||||||
|
Enable Finit debug messages on system console and log. Sometimes useful
|
||||||
|
when doing board bringup. Before the system log daemon has started,
|
||||||
|
Finit use the kernel ring buffer,
|
||||||
|
.Pa /dev/kmsg .
|
||||||
|
.It Cm finit.fstab=/path/to/fstab.alt
|
||||||
|
Tell
|
||||||
|
.Nm
|
||||||
|
to use an alternate
|
||||||
|
.Cm fstab
|
||||||
|
to mount the file system from. Remember, this file must be on the
|
||||||
|
.Cm root=...
|
||||||
|
file system provided to Finit from the kernel. If this file is missing,
|
||||||
|
.Nm
|
||||||
|
falls back to its built-in default, which can be changed at build time
|
||||||
|
using the
|
||||||
|
.Cm --with-fstab=/path/to/footab
|
||||||
|
configure option. It is even possible to completely disable the
|
||||||
|
built-in using
|
||||||
|
.Cm --without-fstab ,
|
||||||
|
meaning
|
||||||
|
.Nm
|
||||||
|
.Sy must
|
||||||
|
be started with the
|
||||||
|
.Cm finit.fstab
|
||||||
|
option.
|
||||||
|
.Pp
|
||||||
|
Should
|
||||||
|
.Nm
|
||||||
|
discover that there is no fstab file available, including the fallback,
|
||||||
|
it triggers the same failure mode as when
|
||||||
|
.Cm fsck
|
||||||
|
fails, starting
|
||||||
|
.Xr sulogin 8 ,
|
||||||
|
if that is availble. When
|
||||||
|
.Cm sulogin
|
||||||
|
is missing, or when the user exits from
|
||||||
|
.Cm sulogin ,
|
||||||
|
the system is rebooted.
|
||||||
|
.Pp
|
||||||
|
Default fstab, unless changed at build-time:
|
||||||
|
.Pa /etc/fstab
|
||||||
|
.It Cm finit.status=<on,off>
|
||||||
|
Control finit boot progress, including banner. This used to be called
|
||||||
|
.Cm finit.show_status ,
|
||||||
|
which still works but is deprecated.
|
||||||
|
.It Cm finit.status_style=<classic,modern>
|
||||||
|
Set Finit boot progress style, when enabled.
|
||||||
|
.It Cm loglevel=<0-7>
|
||||||
|
set the kernel's log level, which is more granular than
|
||||||
|
.Cm debug .
|
||||||
|
Also, when
|
||||||
|
.Cm loglevel=7 ,
|
||||||
|
Finit will
|
||||||
|
.Em not disable
|
||||||
|
kernel logs to the console. This is very useful when debugging the
|
||||||
|
kernel at system bring-up. Since
|
||||||
|
.Cm loglevel=7
|
||||||
|
is the same as
|
||||||
|
.Cm debug
|
||||||
|
this means you have to use
|
||||||
|
.Cm quiet
|
||||||
|
for a quiet boot, until sysklogd takes over logging of kernel events.
|
||||||
|
.It Cm panic=SEC
|
||||||
|
By default the kernel does not reboot after a kernel panic. This
|
||||||
|
setting will cause a kernel reboot after
|
||||||
|
.Ar SEC
|
||||||
|
seconds.
|
||||||
|
.It Cm quiet
|
||||||
|
Suppress kernel logging to console, except for warnings and errors.
|
||||||
|
Also, see
|
||||||
|
.Cm loglevel
|
||||||
|
and
|
||||||
|
.Cm quiet
|
||||||
|
above.
|
||||||
|
.It Cm rescue | recover
|
||||||
|
Start rescue/maintenance mode. If your system comes with the bundled
|
||||||
|
.Cm sulogin
|
||||||
|
program (Finit, or from util-linux/Busybox), you will be given a root
|
||||||
|
login to a maintenance shell. However, if
|
||||||
|
.Cm sulogin
|
||||||
|
is missing, the file
|
||||||
|
.Pa /lib/finit/rescue.conf
|
||||||
|
is read and the system booted in a limited fallback mode. See
|
||||||
|
.Xr finit.conf 5
|
||||||
|
for more information.
|
||||||
|
.It Cm single | S
|
||||||
|
Single user mode, runlevel 1, in Finit. Useful to debug problems with
|
||||||
|
the regular runlevel. All services and TTYs in
|
||||||
|
.Cm [1]
|
||||||
|
will be started, e.g., a
|
||||||
|
.Cm tty [1] @console nologin
|
||||||
|
configuration presents you with a root console without login.
|
||||||
|
.Pp
|
||||||
|
.Sy Note:
|
||||||
|
by definition, single user mode does not have networking enabled. This
|
||||||
|
is also true for runlevel 1.
|
||||||
|
.El
|
||||||
|
.Sh BOOTING
|
||||||
|
.Pp
|
||||||
|
Before laucnhing services, the system needs to be bootstrapped. This
|
||||||
|
involves mounting all filesystems (not already mounted by an initramfs)
|
||||||
|
in
|
||||||
|
.Pa /etc/fstab ,
|
||||||
|
or any alternate
|
||||||
|
.Pa fstab
|
||||||
|
file provided on the Finit command line using
|
||||||
|
.Cm finit.fstab ,
|
||||||
|
ensuring that necessary filesystems like:
|
||||||
|
.Pa /dev ,
|
||||||
|
.Pa /proc ,
|
||||||
|
.Pa /sys ,
|
||||||
|
and
|
||||||
|
.Pa /run
|
||||||
|
are available and can provide the system with the services required.
|
||||||
|
.Pp
|
||||||
|
With that out of the way, a set of plugins take over:
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width bootmisc.so -offset indent
|
||||||
|
.It Cm bootmisc.so
|
||||||
|
Cleans up stale files from previous boots and default directories are
|
||||||
|
created in tmpfs filesystems
|
||||||
|
.It Cm modprobe.so
|
||||||
|
Probes kernel modules required by the system
|
||||||
|
.It Cm procps.so
|
||||||
|
Set kernel variables from
|
||||||
|
.Pa /etc/sysctl.conf
|
||||||
|
et al
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
When the plugins are done, finit reads
|
||||||
|
.Pa /etc/finit.conf
|
||||||
|
and all other enabled services in
|
||||||
|
.Pa /etc/finit.d/* .
|
||||||
|
First all services, run/tasks in runlevel S (bootStrap) are started,
|
||||||
|
When all run/tasks have completed, Finit changes to the configured
|
||||||
|
runlevel (default 2), Processes are started in parallel, in dependency
|
||||||
|
order according to their conditions.
|
||||||
|
.Pp
|
||||||
|
When all services and run/tasks have been started, the console progress
|
||||||
|
is disabled and all configured getty services are started.
|
||||||
|
.Sh CONDITIONS
|
||||||
|
The condition subysystem in Finit was initially created to track PID
|
||||||
|
files of daemons. If service/task B requires service A to have started,
|
||||||
|
Finit waits for the PID file of service A to be created/updated before
|
||||||
|
it starts service B. Conversely, if service A is stopped and its PID
|
||||||
|
file removed, service B is also stopped.
|
||||||
|
.Pp
|
||||||
|
The following condition families are available today:
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width service -offset indent
|
||||||
|
.It Cm net
|
||||||
|
Linux netlink events, e.g. net/route/default, net/eth0/up, and
|
||||||
|
net/et0/running
|
||||||
|
.It Cm pid
|
||||||
|
PID files based on the service declaration
|
||||||
|
.Cm name:id ,
|
||||||
|
gives the condition pid/name:id
|
||||||
|
.It Cm service
|
||||||
|
Tracks run/task/service state stansitions, including readiness. E.g.,
|
||||||
|
.Cm service/foo/ready
|
||||||
|
can be used as a condition for service
|
||||||
|
.Cm bar ,
|
||||||
|
provided
|
||||||
|
.Cm foo
|
||||||
|
properly signals its readiness to Finit.
|
||||||
|
.It Cm sys
|
||||||
|
System conditions, e.g. sys/key/ctrlaltdel and sys/pwr/fail
|
||||||
|
.It Cm usr
|
||||||
|
User conditions, assert and deassert using
|
||||||
|
.Cm initctl cond [set|clr] foo
|
||||||
|
.El
|
||||||
|
.Sh SIGNALS
|
||||||
|
PID 1 is the only process that by default blocks all signals. Finit
|
||||||
|
allows for the following signals to control operation, but recommends
|
||||||
|
instead using the
|
||||||
|
.Xr initctl 8
|
||||||
|
tool.
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width TERM
|
||||||
|
.It HUP
|
||||||
|
Tell
|
||||||
|
.Nm
|
||||||
|
to reload its configuration file(s), same as
|
||||||
|
.Cm initctl reload
|
||||||
|
.It USR1
|
||||||
|
Restart API
|
||||||
|
.Cm ( initctl )
|
||||||
|
socket.
|
||||||
|
.It USR2
|
||||||
|
Tell
|
||||||
|
.Nm
|
||||||
|
to perform a system shutdown, same as
|
||||||
|
.Cm initctl poweroff
|
||||||
|
.It TERM
|
||||||
|
Like SIGUSR2 but performs a reboot, same as
|
||||||
|
.Cm initctl reboot
|
||||||
|
.It INT
|
||||||
|
Sent from kernel when Ctrl-Alt-Del is pressed (on the console), this
|
||||||
|
asserts the sys/key/ctrlaltdel condition, which can be used to start
|
||||||
|
tasks or services
|
||||||
|
.It PWR
|
||||||
|
Sent from a a power daemon on changes to UPS status, Finit asserts
|
||||||
|
the sys/pwr/fail condition
|
||||||
|
.El
|
||||||
|
.Sh FILES
|
||||||
|
.Bl -tag -width /etc/finit.d/available/*.conf -compact
|
||||||
|
.It Pa /etc/finit.conf
|
||||||
|
Main configuration file
|
||||||
|
.It Pa /etc/finit.d/*.conf
|
||||||
|
Static service definitions
|
||||||
|
.It Pa /etc/finit.d/available/*.conf
|
||||||
|
Available services
|
||||||
|
.It Pa /etc/finit.d/enabled/*.conf
|
||||||
|
Symlinks from available
|
||||||
|
.It Pa /run/finit/
|
||||||
|
Runtime files, including the condition subsystem
|
||||||
|
.El
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr finit.conf 5
|
||||||
|
.Xr initctl 8
|
||||||
|
.Xr tmpfiles.d 5
|
||||||
|
.Sh AUTHORS
|
||||||
|
.Nm
|
||||||
|
was conceived and reverse engineered by Claudio Matsuoka. Since v1.0,
|
||||||
|
maintained by Joachim Wiberg, with contributions by many others.
|
||||||
@@ -0,0 +1,989 @@
|
|||||||
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
|
.\" First parameter, NAME, should be all caps
|
||||||
|
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||||
|
.\" other parameters are allowed: see man(7), man(1)
|
||||||
|
.Dd July 11, 2023
|
||||||
|
.Dt FINIT.CONF 5 SMM
|
||||||
|
.Os Linux
|
||||||
|
.Sh NAME
|
||||||
|
.Nm finit.conf
|
||||||
|
.Nd Finit configuration file format
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm /etc/finit.conf
|
||||||
|
.Nm /etc/finit.d/*.conf
|
||||||
|
.Nm /etc/finit.d/available/*.conf
|
||||||
|
.Nm /etc/finit.d/enabled/*.conf
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Nm Finit
|
||||||
|
based systems can be set up with a single file:
|
||||||
|
.Pa /etc/finit.conf .
|
||||||
|
This is the traditional way of doing it which can be ideal for some
|
||||||
|
setups since it gives a great overview of the system configuration.
|
||||||
|
.Pp
|
||||||
|
More comprehensive setups, however, require more careful planning.
|
||||||
|
The recommendation is per-package
|
||||||
|
.Cm *.conf
|
||||||
|
files in
|
||||||
|
.Pa /etc/finit.d/available/ .
|
||||||
|
This allows end users to enable and disable parts of the system
|
||||||
|
configuration at runtime. Finit tracks which tasks and services belong
|
||||||
|
to a given file, so that when the user calls
|
||||||
|
.Cm initctl reload
|
||||||
|
to activate the changes they have made, only the affected tasks and
|
||||||
|
services are stopped, started, or restarted. Hence, this approach is
|
||||||
|
useful for modern package-based Linux distributions.
|
||||||
|
.Pp
|
||||||
|
The following sections describe the more of this in detail, starting
|
||||||
|
with files, the file format, and available directives. Remember to
|
||||||
|
also visit the other manual pages (references at the bottom).
|
||||||
|
.Sh FILES
|
||||||
|
.Bl -tag -width /etc/finit.d/available/*.conf -compact
|
||||||
|
.It Pa /etc/finit.conf
|
||||||
|
Main configuration file, optional
|
||||||
|
.It Pa /etc/finit.d/*.conf
|
||||||
|
Static (system) service definitions
|
||||||
|
.It Pa /etc/finit.d/available/*.conf
|
||||||
|
Available (installed) services
|
||||||
|
.It Pa /etc/finit.d/enabled/*.conf
|
||||||
|
Enabled services (symlink back)
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
Static services,
|
||||||
|
.Cm .conf
|
||||||
|
files in
|
||||||
|
.Pa /etc/finit.d/ ,
|
||||||
|
cannot be enabled or disabled using
|
||||||
|
.Cm initctl [enable | disable] service[.conf] .
|
||||||
|
An enabled service is a symlink back to the corresponding
|
||||||
|
.Cm ../available/
|
||||||
|
service
|
||||||
|
.Cm .conf
|
||||||
|
file. Please use the
|
||||||
|
.Cm initctl
|
||||||
|
tool to manage these symlinks to ensure proper operation.
|
||||||
|
.Pp
|
||||||
|
.Sy NOTE:
|
||||||
|
Previous versions of
|
||||||
|
.Nm Finit
|
||||||
|
created symlinks in
|
||||||
|
.Pa /etc/finit.d/
|
||||||
|
if
|
||||||
|
.Pa /etc/finit.d/enabled/
|
||||||
|
was missing, this is as of v4.4 not supported.
|
||||||
|
.Sh FILE FORMAT
|
||||||
|
The file format is line based, empty lines and comments, lines starting
|
||||||
|
with `#', are ignored. A configuration directive starts with a keyword
|
||||||
|
followed by a space and the rest of the line is treated as the value.
|
||||||
|
.Pp
|
||||||
|
As of Finit v4.4, configuration directives can be broken up in multiple
|
||||||
|
lines using the continuation character `\\', and trailing comments are
|
||||||
|
also allowed. Example:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
# Escape \\# chars if you want them literal in, e.g., descriptions
|
||||||
|
service name:sysklogd [S123456789] \\
|
||||||
|
env:-/etc/default/sysklogd \\
|
||||||
|
syslogd -F $SYSLOGD_ARGS \\
|
||||||
|
-- System log daemon \\# 1 # Comments allowed now
|
||||||
|
.Ed
|
||||||
|
.Sh DIRECTIVES
|
||||||
|
This section lists all supported configuration directives. There also exist
|
||||||
|
deprecated directives, see the Markdown documentation for details on these.
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width 1n
|
||||||
|
.It Cm rlimit Oo hard|soft Oc Ar RESOURCE Aq LIMIT | unlimited
|
||||||
|
.Pp
|
||||||
|
Set the hard or soft limit for a resource, or both if that argument is
|
||||||
|
omitted.
|
||||||
|
.Ar RESOURCE
|
||||||
|
is the lower-case
|
||||||
|
.Cm RLIMIT_
|
||||||
|
string constants from
|
||||||
|
.Xr setrlimit 2 ,
|
||||||
|
without prefix. E.g. to set
|
||||||
|
.Cm RLIMIT_CPU ,
|
||||||
|
use
|
||||||
|
.Cm cpu .
|
||||||
|
.Pp
|
||||||
|
.Ar LIMIT
|
||||||
|
is an integer that depends on the resource being modified, see
|
||||||
|
the man page, or the kernel
|
||||||
|
.Pa /proc/PID/limits
|
||||||
|
file, for details.
|
||||||
|
Finit versions before v3.1 used
|
||||||
|
.Cm infinity
|
||||||
|
for
|
||||||
|
.Cm unlimited ,
|
||||||
|
which is still supported, albeit deprecated.
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
# No process is allowed more than 8MB of address space
|
||||||
|
rlimit hard as 8388608
|
||||||
|
|
||||||
|
# Core dumps may be arbitrarily large
|
||||||
|
rlimit soft core infinity
|
||||||
|
|
||||||
|
# CPU limit for all services, soft & hard = 10 sec
|
||||||
|
rlimit cpu 10
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
.Cm rlimit
|
||||||
|
can be set globally, in
|
||||||
|
.Pa /etc/finit.conf ,
|
||||||
|
or locally per each
|
||||||
|
.Pa /etc/finit.d/*.conf
|
||||||
|
read. I.e., a set of task/run/service stanzas can share the same
|
||||||
|
rlimits if they are in the same .conf.
|
||||||
|
.It Cm runlevel Aq N
|
||||||
|
The system runlevel to go to after bootstrap (S) has completed.
|
||||||
|
.Cm N
|
||||||
|
is the runlevel number 0-9, where 6 is reserved for reboot and 0 for
|
||||||
|
halt. All other can be used by operating system administrators.
|
||||||
|
Default: 2
|
||||||
|
.Pp
|
||||||
|
It s recommended to keep runlevel 1 as single-user mode, because
|
||||||
|
.Nm
|
||||||
|
disables networking in this mode.
|
||||||
|
.Pp
|
||||||
|
.Sy Note:
|
||||||
|
only read and executed in runlevel S (bootstrap).
|
||||||
|
.It Cm run Oo LVLS Oc Ao COND Ac Ar /path/to/cmd ARGS Op -- Optional description
|
||||||
|
One-shot command to run in sequence when entering a runlevel, with
|
||||||
|
optional arguments and description.
|
||||||
|
.Pp
|
||||||
|
.Cm run
|
||||||
|
commands are guaranteed to be completed before running the next
|
||||||
|
command. Highly useful if true serialization is needed. Usually
|
||||||
|
only used in the bootstrap (S) runlevel.
|
||||||
|
.Pp
|
||||||
|
.Cm Aq COND
|
||||||
|
conditions are described in
|
||||||
|
.Xr finit 8 ,
|
||||||
|
see also the
|
||||||
|
.Sx Examples
|
||||||
|
section below.
|
||||||
|
.It Cm task Oo LVLS Oc Ao COND Ac Ar /path/to/cmd ARGS Op -- Optional description
|
||||||
|
One-shot like
|
||||||
|
.Cm run ,
|
||||||
|
but starts in parallel with the next command.
|
||||||
|
.Pp
|
||||||
|
Both
|
||||||
|
.Cm run
|
||||||
|
and
|
||||||
|
.Cm task
|
||||||
|
commands are run in a shell, so pipes and redirects can be freely used:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
task [s] echo "foo" | cat >/tmp/bar
|
||||||
|
.Ed
|
||||||
|
.It Cm sysv Oo LVLS Oc Ao COND Ac Ar /path/to/script ARGS Op -- Optional description
|
||||||
|
Similar to
|
||||||
|
.Cm task
|
||||||
|
is the
|
||||||
|
.Cm sysv
|
||||||
|
stanza, which can be used to call SysV style start/stop scripts. The
|
||||||
|
primary intention for this command is to be able to re-use much of
|
||||||
|
existing setup and init scripts in Linux distributions.
|
||||||
|
.Pp
|
||||||
|
When entering an allowed runlevel, Finit calls
|
||||||
|
.Cm init-script start ,
|
||||||
|
when entering a disallowed runlevel, Finit calls
|
||||||
|
.Cm init-script stop ,
|
||||||
|
and if the Finit .conf, where the
|
||||||
|
.Cm sysv
|
||||||
|
stanza is declared, is modified, Finit calls
|
||||||
|
.Cm init-script restart
|
||||||
|
on
|
||||||
|
.Cm initctl reload .
|
||||||
|
Similar to how
|
||||||
|
.Cm service
|
||||||
|
stanzas work.
|
||||||
|
.Pp
|
||||||
|
Forking services started with
|
||||||
|
.Cm sysv
|
||||||
|
scripts can be monitored by Finit by declaring the PID file to look for:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
sysv pid:!/path/to/pidfile.pid /path/to/script ...
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The leading '!' is to prevent Finit from managing the PID file, which is
|
||||||
|
the default behavior for the
|
||||||
|
.Cm pid:
|
||||||
|
command modifier.
|
||||||
|
.It Cm service Oo LVLS Oc Ao COND Ac Ar /path/to/daemon ARGS Op -- Optional description
|
||||||
|
Service, or daemon, to be monitored and automatically restarted if it
|
||||||
|
exits prematurely. Finit tries to restart services that die, by
|
||||||
|
default 10 times, before giving up and marking them as
|
||||||
|
.Em crashed .
|
||||||
|
After which they have to be restarted manually using
|
||||||
|
.Cm initctl restart NAME .
|
||||||
|
The number of restarts, the delay between each restart, and more is
|
||||||
|
configurable, see the options below.
|
||||||
|
.Pp
|
||||||
|
.Bd -filled -offset indent
|
||||||
|
.Sy Tip:
|
||||||
|
to allow endless restarts, see below option
|
||||||
|
.Cm respawn
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
For daemons that support it, we recommend appending
|
||||||
|
.Cm --foreground , --no-background , -n , -F ,
|
||||||
|
or similar command line argument to prevent them from forking off a
|
||||||
|
sub-process in the background. This is the most reliable way to monitor
|
||||||
|
a service.
|
||||||
|
.Pp
|
||||||
|
However, not all daemons support running in the foreground, or they may
|
||||||
|
start logging to the foreground as well, these are called forking
|
||||||
|
services and are supported using the same syntax as forking
|
||||||
|
.Cm sysv
|
||||||
|
services, using the
|
||||||
|
.Cm pid:!/path/to/pidfile.pid
|
||||||
|
command modifier syntax. There is an alternative syntax that may be
|
||||||
|
more intuitive, where Finit can also guess the PID file based on the
|
||||||
|
daemon's command name:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
service type:forking ntpd -- NTP daemon
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
Here we let BusyBox
|
||||||
|
.Nm ntpd
|
||||||
|
daemonize itself. Finit uses the basename of the binary to guess the
|
||||||
|
PID file to watch for the PID:
|
||||||
|
.Pa /var/run/ntpd.pid .
|
||||||
|
If Finit guesses wrong, you have to submit the full
|
||||||
|
.Cm pid:!/path/to/file.pid
|
||||||
|
option to your service stanza.
|
||||||
|
.Pp
|
||||||
|
.Sy Example: in the case of
|
||||||
|
.Cm ospfd
|
||||||
|
(below), we omit the
|
||||||
|
.Cm -d
|
||||||
|
flag (daemonize) to prevent it from forking to the background:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
service [2345] <pid/zebra> /sbin/ospfd -- OSPF daemon
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
.Cm [2345]
|
||||||
|
denote the runlevels
|
||||||
|
.Cm ospfd
|
||||||
|
is allowed to run in, they are optional and default to runlevel 2-5 if
|
||||||
|
omitted.
|
||||||
|
.Pp
|
||||||
|
.Cm <pid/zebra>
|
||||||
|
is the condition for starting
|
||||||
|
.Cm ospfd .
|
||||||
|
In this example Finit waits for another service,
|
||||||
|
.Cm zebra ,
|
||||||
|
to have created its PID file in
|
||||||
|
.Pa /var/run/quagga/zebra.pid
|
||||||
|
before starting
|
||||||
|
.Cm ospfd .
|
||||||
|
Finit watches *all* files in
|
||||||
|
.Pa /var/run ,
|
||||||
|
for each file named
|
||||||
|
.Cm *.pid ,
|
||||||
|
.Cm */pid ,
|
||||||
|
Finit opens it and find the matching
|
||||||
|
.Cm NAME:ID
|
||||||
|
using the PID.
|
||||||
|
.Pp
|
||||||
|
Some services do not maintain a PID file and rather than patching each
|
||||||
|
application Finit provides a workaround. A
|
||||||
|
.Cm pid
|
||||||
|
modifier keyword can be set to have Finit automatically create (when
|
||||||
|
starting) and later remove (when stopping) the PID file. The file is
|
||||||
|
created in the
|
||||||
|
.Pa /var/run
|
||||||
|
directory using the
|
||||||
|
.Xr basename 3
|
||||||
|
of the service. The full syntax of the
|
||||||
|
.Cm pid
|
||||||
|
modifier is:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
pid[:[!][/path/to/]filename[.pid]]
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
For example, by adding
|
||||||
|
.Cm pid:/run/foo.pid
|
||||||
|
to the service
|
||||||
|
.Cm /sbin/bar ,
|
||||||
|
that PID file will, not only be created and removed automatically, but
|
||||||
|
also be used by the Finit condition subsystem. So a service/run/task
|
||||||
|
can depend on the
|
||||||
|
.Cm <pid/bar>
|
||||||
|
condition.
|
||||||
|
.Pp
|
||||||
|
As an alternative "readiness" notification, Finit supports both systemd
|
||||||
|
and s6 style notification. This can be enabled by using the `notify`
|
||||||
|
option:
|
||||||
|
.Bl -tag -width 1n
|
||||||
|
.It Cm notify:systemd
|
||||||
|
tells Finit the service uses the
|
||||||
|
.Cm sd_notify()
|
||||||
|
API to signal PID 1 when it has completed its startup and is ready
|
||||||
|
to service events. This API expects
|
||||||
|
the environment variable
|
||||||
|
.Cm NOTIFY_SOCKET
|
||||||
|
to be set to the socket where the application can send
|
||||||
|
.Cm "READY=1\n"
|
||||||
|
when it is starting up or has processed a
|
||||||
|
.Cm SIGHUP .
|
||||||
|
For details, see:
|
||||||
|
.Pp
|
||||||
|
.Lk https://www.freedesktop.org/software/systemd/man/sd_notify.html
|
||||||
|
.It Cm notify:s6
|
||||||
|
puts Finit in s6 compatibility mode. Compared to the systemd
|
||||||
|
notification, s6 expect compliant daemons to send
|
||||||
|
.Cm "\\n"
|
||||||
|
and then close their socket. For details, see:
|
||||||
|
.Pp
|
||||||
|
.Lk https://skarnet.org/software/s6/notifywhenup.html
|
||||||
|
.Pp
|
||||||
|
Finit takes care of "hard-wiring" the READY state as long as the
|
||||||
|
application is running, events across any `SIGHUP`. Since s6 can give
|
||||||
|
its applications the descriptor number (must be >3) on then command
|
||||||
|
line, Finit provides the following syntax (
|
||||||
|
.Cm %n
|
||||||
|
is replaced by Finit with then descriptor number):
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
service notify:s6 mdevd -C -O 4 -D %n
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
When a service is ready, either by Finit detecting its PID file, or
|
||||||
|
their respective readiness mechanism has been triggered, Finit creates
|
||||||
|
then service's ready condition which other services can depend on:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
$ initctl -v cond get service/mdevd/ready
|
||||||
|
on
|
||||||
|
.Ed
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
If a service should not be automatically started, it can be configured
|
||||||
|
as manual with the
|
||||||
|
.Cm manual:yes
|
||||||
|
command modifier. The service can then be started at any time by
|
||||||
|
running
|
||||||
|
.Cm initctl start NAME
|
||||||
|
.Pp
|
||||||
|
The name of a service, shown by the
|
||||||
|
.Cm initctl
|
||||||
|
tool, defaults to the basename of the service executable. It can be
|
||||||
|
changed with the
|
||||||
|
.Cm name:foo
|
||||||
|
command modifier.
|
||||||
|
.Pp
|
||||||
|
As mentioned previously, services are automatically restarted should
|
||||||
|
they crash, this is configurable with the following options:
|
||||||
|
.Bl -tag -width 1n
|
||||||
|
.It Cm restart:NUM
|
||||||
|
number of times Finit tries to restart a crashing
|
||||||
|
service, default: 10. When this limit is reached the service is
|
||||||
|
marked
|
||||||
|
.Em crashed
|
||||||
|
and must be restarted manually with
|
||||||
|
.Xr initctl 8 .
|
||||||
|
.It Cm restart_sec:SEC
|
||||||
|
number of seconds before Finit tries to restart
|
||||||
|
a crashing service, default: 2 seconds for the first five retries,
|
||||||
|
then back-off to 5 seconds. The maximum of this configured value
|
||||||
|
and the above (2 and 5) will be used
|
||||||
|
.It Cm restart:always
|
||||||
|
no upper limit on the number of times Finit tries to restart a crashing
|
||||||
|
service. Same as
|
||||||
|
.Cm restart:-1
|
||||||
|
.It Cm norestart
|
||||||
|
dont restart on failures, same as
|
||||||
|
.Cm restart:0
|
||||||
|
.It Cm respawn
|
||||||
|
bypasses the
|
||||||
|
.Cm restart
|
||||||
|
mechanism completely, allows endless restarts. Useful in many
|
||||||
|
use-cases, but not what
|
||||||
|
.Cm service
|
||||||
|
was originally designed for so not the default behavior.
|
||||||
|
.It Cm oncrash:reboot
|
||||||
|
when all retries have failed, and the service
|
||||||
|
has
|
||||||
|
.Em crashed ,
|
||||||
|
if this option is set the system is rebooted.
|
||||||
|
.It Cm oncrash:script
|
||||||
|
Similar to
|
||||||
|
.Cm oncrash:reboot ,
|
||||||
|
but instead of rebooting this action calls the
|
||||||
|
.Cm post:script
|
||||||
|
(see below) to let the operator decide the best course of action. If
|
||||||
|
the post:script option is not set, this is a no-op.
|
||||||
|
.Pp
|
||||||
|
The post:script is called with the same environment variables
|
||||||
|
.Sy except
|
||||||
|
for the
|
||||||
|
.Cm EXIT_CODE
|
||||||
|
variable which is set to
|
||||||
|
.Cm "crashed" .
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
When stopping a service (run/task/sysv/service), either manually or when
|
||||||
|
moving to another runlevel, Finit starts by sending SIGTERM, to allow
|
||||||
|
the process to shut down gracefully. If the process has not been
|
||||||
|
collected within 3 seconds, Finit sends SIGKILL. To halt the process
|
||||||
|
using a different signal, use the command modifier
|
||||||
|
.Cm halt:SIGNAL ,
|
||||||
|
e.g.,
|
||||||
|
.Cm halt:SIGPWR .
|
||||||
|
To change the delay between your halt signal and KILL, use the command
|
||||||
|
modifier
|
||||||
|
.Cm kill:SEC ,
|
||||||
|
e.g.,
|
||||||
|
.Cm kill:10
|
||||||
|
to wait 10 seconds before sending SIGKILL.
|
||||||
|
.Pp
|
||||||
|
Services support the
|
||||||
|
.Cm pre:script
|
||||||
|
and
|
||||||
|
.Cm post:script
|
||||||
|
command actions as well. These run as the same
|
||||||
|
.Cm @USER:GROUP
|
||||||
|
as the service itself, with any
|
||||||
|
.Cm env:file
|
||||||
|
sourced. The scripts must use an absolute path, but are executed from
|
||||||
|
the
|
||||||
|
.Cm $HOME
|
||||||
|
of the given user. The scripts are not called with any argument
|
||||||
|
(currently), but both get the
|
||||||
|
.Cm SERVICE_IDENT=foo
|
||||||
|
environment variable set. Here
|
||||||
|
.Cm foo
|
||||||
|
denotes the identity of the service, which if there are multiple
|
||||||
|
services named
|
||||||
|
.Cm foo ,
|
||||||
|
may be
|
||||||
|
.Cm foo:1 ,
|
||||||
|
or any unique identifier specified in the .conf file. The
|
||||||
|
.Cm post:script
|
||||||
|
is called with an additional set of environment variables:
|
||||||
|
.Bl -tag -offset indent -width 1n
|
||||||
|
.It Cm EXIT_CODE=[exited,signal,crashed]
|
||||||
|
set to one of
|
||||||
|
.Cm exited ,
|
||||||
|
.Cm signal ,
|
||||||
|
or
|
||||||
|
.Cm crashed
|
||||||
|
(see above).
|
||||||
|
.It Cm EXIT_STATUS=[num,SIGNAME]
|
||||||
|
set to one of exit status code from the program, if it exited normally,
|
||||||
|
or the signal name (HUP, TERM, etc.) if it exited due to signal
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The scripts have a default execution time of 3 seconds before they are
|
||||||
|
SIGKILLed, this can be adjusted using the
|
||||||
|
.Cm kill:SEC
|
||||||
|
modifier syntax.
|
||||||
|
.It Cm runparts Aq DIR
|
||||||
|
Call
|
||||||
|
.Xr run-parts 8
|
||||||
|
on
|
||||||
|
.Cm DIR
|
||||||
|
to run start scripts. All executable files, or scripts, in the
|
||||||
|
directory are called, in alphabetic order. The scripts in this
|
||||||
|
directory are executed at the very end of bootstrap, runlevel S.
|
||||||
|
.Pp
|
||||||
|
It can be beneficial to use
|
||||||
|
.Cm S01name ,
|
||||||
|
.Cm S02othername ,
|
||||||
|
etc. if there is a dependency order between the scripts. Symlinks to
|
||||||
|
existing daemons can talso be used, but make sure they daemonize by
|
||||||
|
default.
|
||||||
|
.Pp
|
||||||
|
Similar to the
|
||||||
|
.Pa /etc/rc.local
|
||||||
|
shell script, make sure that all your services and programs either
|
||||||
|
terminate or start in the background or you will block Finit.
|
||||||
|
.Sy Note:
|
||||||
|
only read and executed in runlevel S (bootstrap).
|
||||||
|
.It Cm include Aq CONF
|
||||||
|
Include another configuration file. Absolute path required.
|
||||||
|
.It Cm log size:BYTES count:NUM
|
||||||
|
Log rotation for run/task/services using the
|
||||||
|
.Cm log
|
||||||
|
command modifier with redirection to a log file. Global setting,
|
||||||
|
applies to all services.
|
||||||
|
.Pp
|
||||||
|
The size can be given as bytes, without a specifier, or in `k`, `M`,
|
||||||
|
or `G`, e.g.
|
||||||
|
.Cm size:10M ,
|
||||||
|
or
|
||||||
|
.Cm size:3G .
|
||||||
|
A value of
|
||||||
|
.Cm size:0
|
||||||
|
disables log rotation. The default is
|
||||||
|
.Cm size:200k .
|
||||||
|
.Pp
|
||||||
|
The count value is recommended to be between 1-5, with a default 5.
|
||||||
|
Setting count to 0 means the logfile will be truncated when the MAX
|
||||||
|
size limit is reached.
|
||||||
|
.It Cm tty Oo LVLS Oc Ao COND Ac Ar DEV Oo BAUD Oc Oo noclear Oc Oo nowait Oc Oo nologin Oc Oo TERM Oc
|
||||||
|
This form of the
|
||||||
|
.Cm tty
|
||||||
|
stanza uses the built-in getty on the given TTY device
|
||||||
|
.Ar DEV ,
|
||||||
|
in the given runlevels.
|
||||||
|
.Ar DEV may be the special keyword
|
||||||
|
.Cm @console ,
|
||||||
|
or `console`, which is expanded from `/sys/class/tty/console/active`,
|
||||||
|
useful on embedded systems.
|
||||||
|
.Pp
|
||||||
|
The default baud rate is 0, i.e., keep kernel default.
|
||||||
|
.Pp
|
||||||
|
The `tty` stanza inherits runlevel, condition (and other feature)
|
||||||
|
parsing from the `service` stanza. So TTYs can run in one or many
|
||||||
|
runlevels and depend on any condition supported by Finit. This is
|
||||||
|
useful e.g. to depend on `<pid/elogind>` before starting a TTY.
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
tty [12345] /dev/ttyAMA0 115200 noclear vt220
|
||||||
|
.Ed
|
||||||
|
.It Cm tty Oo LVLS Oc Ao COND Ac Ar CMD DEV Oo noclear Oc Oo nowait Oc
|
||||||
|
This form of the
|
||||||
|
.Cm tty
|
||||||
|
stanza is for using an external getty, like agetty or the BusyBox getty.
|
||||||
|
.Pp
|
||||||
|
By default, these first two syntax variants
|
||||||
|
.Em clear
|
||||||
|
the TTY and
|
||||||
|
.Em wait
|
||||||
|
for the user to press enter before starting getty.
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
tty [12345] /sbin/getty -L 115200 /dev/ttyAMA0 vt100
|
||||||
|
tty [12345] /sbin/agetty -L ttyAMA0 115200 vt100 nowait
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Cm noclear
|
||||||
|
option disables clearing the TTY after each session. Clearing the TTY
|
||||||
|
when a user logs out is usually preferable.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Cm nowait
|
||||||
|
option disables the
|
||||||
|
.Cm Please press Enter to activate console
|
||||||
|
message before actually starting the getty program. On small and
|
||||||
|
embedded systems running multiple unused getty wastes both memory and
|
||||||
|
CPU cycles, so `wait` is the preferred default.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Cm nologin
|
||||||
|
option disables getty and
|
||||||
|
.Pa /bin/login ,
|
||||||
|
and gives the user a root (login) shell on the given TTY
|
||||||
|
.Cm DEV
|
||||||
|
immediately. Needless to say, this is a rather insecure option, but can
|
||||||
|
be very useful for developer builds, during board bringup, or similar.
|
||||||
|
.Pp
|
||||||
|
Notice the ordering, the
|
||||||
|
.Cm TERM
|
||||||
|
option to the built-in getty must be the last argument.
|
||||||
|
.Pp
|
||||||
|
Embedded systems may want to enable automatic `DEV` by supplying the
|
||||||
|
special
|
||||||
|
.Cm @console
|
||||||
|
device. This works regardless weather the system uses
|
||||||
|
.Cm ttyS0 , ttyAMA0 , ttyMXC0 ,
|
||||||
|
or anything else. Finit figures it out by querying sysfs:
|
||||||
|
.Pa /sys/class/tty/console/active .
|
||||||
|
The speed can be omitted to keep the kernel default.
|
||||||
|
.Pp
|
||||||
|
Most systems get by fine by just using `console`, which will evaluate
|
||||||
|
to
|
||||||
|
.Pa /dev/console .
|
||||||
|
If you have to use
|
||||||
|
.Cm @console
|
||||||
|
to get any output, you may have some issue with your kernel config.
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
tty [12345] @console noclear vt220
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
On really bare bones systems, or for board bringup, Finit can give you a
|
||||||
|
shell prompt as soon as bootstrap is done, without opening any device
|
||||||
|
node:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
tty [12345789] notty
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
This should of course not be enabled on production systems. Because it
|
||||||
|
may give a user root access without having to log in. However, for
|
||||||
|
board bringup and system debugging it can come in handy.
|
||||||
|
.Pp
|
||||||
|
One can also use the
|
||||||
|
.Cm service
|
||||||
|
stanza to start a stand-alone shell:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
service [12345] /bin/sh -l
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
.It Cm tty Oo LVLS Oc Ao COND Ac Oo notty Oc Oo rescue Oc
|
||||||
|
The third
|
||||||
|
.Cm tty
|
||||||
|
form is for board bringup and the
|
||||||
|
.Cm rescue
|
||||||
|
boot mode. No device node is required in this variant, the same output
|
||||||
|
that the kernel uses is reused for stdio. If the
|
||||||
|
.Cm rescue
|
||||||
|
option is omitted, a shell is started. The flags
|
||||||
|
.Cm nologin , noclear ,
|
||||||
|
and
|
||||||
|
.Cm nowait
|
||||||
|
are implied. If the
|
||||||
|
.Cm rescue
|
||||||
|
option is set the bundled
|
||||||
|
.Pa /libexec/finit/sulogin
|
||||||
|
is started to present a bare-bones root login prompt. If the root
|
||||||
|
(uid:0, gid:0) user does not have a password set, no rescue is possible.
|
||||||
|
.El
|
||||||
|
.Sh COMMAND MODIFIERS
|
||||||
|
The run/task/tty/service/sysv stanzas take modifiers, or options, to
|
||||||
|
control their behavior. This section lists them with their limitations.
|
||||||
|
All modifiers must be placed between the stanza and its command.
|
||||||
|
.Bl -tag -width 1n
|
||||||
|
.It Cm @user:group
|
||||||
|
Every
|
||||||
|
.Cm run , task ,
|
||||||
|
or
|
||||||
|
.Cm service
|
||||||
|
can also list the privileges the
|
||||||
|
.Cm /path/to/cmd
|
||||||
|
should be executed with. Prefix the command with
|
||||||
|
.Cm @USR[:GRP] ,
|
||||||
|
group is optional, like this:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
run [2345] @joe:users logger "Hello world"
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
For multiple instances of the same command, e.g. a DHCP client or
|
||||||
|
multiple web servers, add
|
||||||
|
.Cm :ID
|
||||||
|
somewhere between the
|
||||||
|
.Cm run , task , service
|
||||||
|
keyword and the command, like this:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
service :80 [2345] httpd -f -h /http -p 80 -- Web server
|
||||||
|
service :8080[2345] httpd -f -h /http -p 8080 -- Old web server
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
Without the
|
||||||
|
.Cm :ID
|
||||||
|
to the service the latter will overwrite the former and only the old web
|
||||||
|
server would be started and supervised.
|
||||||
|
.It Cm log:/path/to/file
|
||||||
|
Redirect stdout/stderr of a command to the given log file. See the
|
||||||
|
global log directive, above, for details on log rotation.
|
||||||
|
.It Cm log:console
|
||||||
|
Redirect stdout/stderr of a command to
|
||||||
|
.Pa /dev/console ,
|
||||||
|
only use this for debugging or bringup.
|
||||||
|
.It Cm log:null
|
||||||
|
Redirect stdout/stderr of a command to
|
||||||
|
.Pa /dev/null .
|
||||||
|
.It Cm log:prio:facility.level,tag:ident
|
||||||
|
Redirect stdout/stderr of a command to syslog using the given priority
|
||||||
|
and tag identity.
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
service log:prio:user.warn,tag:ntpd /sbin/ntpd pool.ntp.org -- NTP daemon
|
||||||
|
.Ed
|
||||||
|
.It Cm log
|
||||||
|
Default
|
||||||
|
.Cm prio
|
||||||
|
is
|
||||||
|
.Cm daemon.info
|
||||||
|
and the default
|
||||||
|
.Cm tag
|
||||||
|
identity is the basename of the service or run/task command.
|
||||||
|
.El
|
||||||
|
.Sh RESCUE MODE
|
||||||
|
Finit supports a rescue mode which is activated by the
|
||||||
|
.Cm rescue
|
||||||
|
option on the kernel command line. The rescue mode comes in two
|
||||||
|
flavors:
|
||||||
|
.Em traditional
|
||||||
|
and
|
||||||
|
.Em fallback .
|
||||||
|
.Ss Traditional
|
||||||
|
This is what most users expect. A very early maintenance login prompt,
|
||||||
|
served by the bundled
|
||||||
|
.Pa /libexec/finit/sulogin
|
||||||
|
program, or the standard
|
||||||
|
.Cm sulogin
|
||||||
|
from util-linux or BusyBox is searched for in the UNIX default
|
||||||
|
.Cm $PATH .
|
||||||
|
If a successful login is made, or the user exits (Ctrl-D), the rescue
|
||||||
|
mode is ended and the system boots up normally.
|
||||||
|
.Pp
|
||||||
|
.Sy Note:
|
||||||
|
if the user (UID 0 and GID 0) does not have a password, or
|
||||||
|
.Em the account is locked ,
|
||||||
|
the user is presented with a password-less prompt:
|
||||||
|
.Cm "Press enter to enter maintenance mode." ,
|
||||||
|
which opens up a root shell.
|
||||||
|
.Ss Fallback
|
||||||
|
If no
|
||||||
|
.Cm sulogin
|
||||||
|
program is found, Finit tries to bring up as much of its own
|
||||||
|
functionality as possible, yet limiting many aspects, meaning; no
|
||||||
|
network, no`fsck` of file systems in
|
||||||
|
.Pa /etc/fstab ,
|
||||||
|
no
|
||||||
|
.Pa /etc/rc.local ,
|
||||||
|
no
|
||||||
|
.Cm runparts ,
|
||||||
|
and most plugins are skipped (except those that provide functionality
|
||||||
|
for the condition subsystem).
|
||||||
|
.Pp
|
||||||
|
Instead of reading
|
||||||
|
.Pa /etc/finit.conf
|
||||||
|
et al, system configuration is read from
|
||||||
|
.Pa /lib/finit/rescue.conf ,
|
||||||
|
which can be freely modified by the system administrator.
|
||||||
|
.Pp
|
||||||
|
The bundled default `rescue.conf` contains nothing more than:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
runlevel 1
|
||||||
|
tty [12345] rescue
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Cm tty
|
||||||
|
has the
|
||||||
|
.Cm rescue
|
||||||
|
option set, which works similar to the board bring-up tty option
|
||||||
|
.Cm notty .
|
||||||
|
The major difference being that `sulogin` is started to query for
|
||||||
|
root/admin password. If
|
||||||
|
.Cm sulogin
|
||||||
|
is not found,
|
||||||
|
.Cm rescue
|
||||||
|
behaves like
|
||||||
|
.Cm notty
|
||||||
|
and gives a plain root shell prompt.
|
||||||
|
.Pp
|
||||||
|
If Finit cannot find
|
||||||
|
.Pa /lib/finit/rescue.conf
|
||||||
|
it defaults to:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
tty [12345] rescue
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
There is no way to exit the
|
||||||
|
.Em fallback
|
||||||
|
rescue mode.
|
||||||
|
.Sh SERVICE ENVIRONMENT
|
||||||
|
Finit supports sourcing environment variables from
|
||||||
|
.Pa /etc/default/* ,
|
||||||
|
or similar. This is a common pattern from SysV init scripts, where the
|
||||||
|
start/stop script is a generic script for the given service,
|
||||||
|
.Cm foo ,
|
||||||
|
and the options for the service are sourced from the file
|
||||||
|
.Pa /etc/default/foo .
|
||||||
|
Like this:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
/etc/default/foo:
|
||||||
|
|
||||||
|
FOO_OPTIONS=--extra-arg="bar" -s -x
|
||||||
|
|
||||||
|
/etc/finit.conf:
|
||||||
|
|
||||||
|
service [2345] env:-/etc/default/foo foo -n $FOO_OPTIONS -- Example foo daemon
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
Here the service
|
||||||
|
.Cm foo
|
||||||
|
is started with
|
||||||
|
.Op Fl -n ,
|
||||||
|
to make sure it runs in the foreground, and the with the options found
|
||||||
|
in the environment file. With the
|
||||||
|
.Cm ps
|
||||||
|
command we can see that the process is started with:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
foo -n --extra-arg=bar -s -x
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
.Sy Note:
|
||||||
|
the leading `-` determines if Finit should treat a missing environment
|
||||||
|
file as blocking the start of the service or not. When `-` is used, a
|
||||||
|
missing environment file does
|
||||||
|
.Em not
|
||||||
|
block the start.
|
||||||
|
.Sh SERVICE WRAPPER SCRIPTS
|
||||||
|
If your service requires to run additional commands, executed before the
|
||||||
|
service is actually started, like the systemd `ExecStartPre`, you can
|
||||||
|
use a wrapper shell script to start your service.
|
||||||
|
.Pp
|
||||||
|
The Finit service
|
||||||
|
.Cm .conf
|
||||||
|
file can be put into
|
||||||
|
.Pa /etc/finit.d/available ,
|
||||||
|
so you can control the service using
|
||||||
|
.Cm initctl .
|
||||||
|
Then use the path to the wrapper script in the Finit
|
||||||
|
.Cm .conf
|
||||||
|
service stanza. The following example employs a wrapper script in
|
||||||
|
.Pa /etc/start.d .
|
||||||
|
.Bd -unfilled
|
||||||
|
/etc/finit.d/available/program.conf:
|
||||||
|
|
||||||
|
service [235] <!> /etc/start.d/program -- Example Program
|
||||||
|
|
||||||
|
/etc/start.d/program:
|
||||||
|
|
||||||
|
#!/bin/sh
|
||||||
|
# Prepare the command line options
|
||||||
|
OPTIONS="-u $(cat /etc/username)"
|
||||||
|
|
||||||
|
# Execute the program
|
||||||
|
exec /usr/bin/program $OPTIONS
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
.Sy Note:
|
||||||
|
the example sets
|
||||||
|
.Cm <!>
|
||||||
|
to denote that it doesn't support SIGHUP. That way Finit will
|
||||||
|
stop/start the service instead of sending SIGHUP at restart/reload
|
||||||
|
events.
|
||||||
|
.Sh TEMPLATING
|
||||||
|
Finit comes with rudimentary support for templating, similar to that of
|
||||||
|
systemd. Best illustrated with an example:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
$ initctl show avahi-autoipd@
|
||||||
|
service :%i avahi-autoipd --syslog %i -- ZeroConf for %i
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
To enable ZeroConf for, e.g.,
|
||||||
|
.Cm eth0 ,
|
||||||
|
use
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
$ initctl enable avahi-autoipd@eth0.conf
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The enabled symlink will be set up to
|
||||||
|
.Cm avahi-autoipd@.conf
|
||||||
|
and every instance of
|
||||||
|
.Cm %i
|
||||||
|
will in the instantiated directive be replaced with
|
||||||
|
.Cm eth0 .
|
||||||
|
Inspect the result with:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
$ initctl status avahi-autoipd:eth0
|
||||||
|
.Ed
|
||||||
|
.Sh CGROUPS
|
||||||
|
There are three major cgroup configuration directives:
|
||||||
|
.Pp
|
||||||
|
.Bl -enum -offset indent -compact
|
||||||
|
.It
|
||||||
|
Global top-level group: init, system, user, or a custom group
|
||||||
|
.It
|
||||||
|
Selecting a top-level group for a set of run/task/services
|
||||||
|
.It
|
||||||
|
Per run/task/service limits
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
Top-level group configuration.
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
# Top-level cgroups and their default settings. All groups mandatory
|
||||||
|
# but more can be added, max 8 groups in total currently. The cgroup
|
||||||
|
# 'root' is also available, reserved for RT processes. Settings are
|
||||||
|
# as-is, only one shorthand 'mem.' exists, other than that it's the
|
||||||
|
# cgroup v2 controller default names.
|
||||||
|
cgroup init cpu.weight:100
|
||||||
|
cgroup user cpu.weight:100
|
||||||
|
cgroup system cpu.weight:9800
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
Adding an extra cgroup
|
||||||
|
.Cm maint/
|
||||||
|
will require you to adjust the weight of the above three. We leave
|
||||||
|
.Cm init/
|
||||||
|
and
|
||||||
|
.Cm user/
|
||||||
|
as-is reducing weight of
|
||||||
|
.Cm system/
|
||||||
|
to 9700.
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
cgroup system cpu.weight:9700
|
||||||
|
|
||||||
|
# Example extra cgroup 'maint'
|
||||||
|
cgroup maint cpu.weight:100
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
By default, the
|
||||||
|
.Cm system/
|
||||||
|
cgroup is selected for almost everything. The
|
||||||
|
.Cm init/
|
||||||
|
cgroup is reserved for PID 1 itself and its closest relatives. The
|
||||||
|
.Cm user/
|
||||||
|
cgroup is for local TTY logins spawned by getty.
|
||||||
|
.Pp
|
||||||
|
To select a different top-level cgroup, e.g.
|
||||||
|
.Cm maint/ ,
|
||||||
|
one can either define it for a group of run/task/service directives in a
|
||||||
|
.Cm .conf
|
||||||
|
or per each stanza:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
cgroup.maint
|
||||||
|
service [...] <...> /path/to/foo args -- description
|
||||||
|
service [...] <...> /path/to/bar args -- description
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
or
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
service [...] <...> cgroup.maint /path/to/foo args -- description
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The latter form also allows per-stanza limits on the form:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
service [...] <...> cgroup.maint:cpu.max:10000,mem.max:655360 /path/to/foo args -- description
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
Notice the comma separation and the
|
||||||
|
.Cm mem.
|
||||||
|
exception to the rule: every cgroup setting maps directly to cgroup v2
|
||||||
|
syntax. I.e.,
|
||||||
|
.Cm cpu.max
|
||||||
|
maps to the file
|
||||||
|
.Pm /sys/fs/cgroup/maint/foo/cpu.max .
|
||||||
|
There is no filtering, except for expanding the shorthand
|
||||||
|
.Cm mem.
|
||||||
|
to
|
||||||
|
.Cm memory. ,
|
||||||
|
if the file is not available, either the cgroup controller is not
|
||||||
|
available in your Linux kernel, or the name is misspelled.
|
||||||
|
.Pp
|
||||||
|
Linux cgroups and details surrounding values are not explained in the
|
||||||
|
Finit documentation. The Linux admin-guide cover this well:
|
||||||
|
.Lk https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html
|
||||||
|
.Sh LIMITATIONS
|
||||||
|
As of Finit v4 there are no limitations to where
|
||||||
|
.Cm .conf
|
||||||
|
settings can be placed. Except for the system/global
|
||||||
|
.Cm rlimit
|
||||||
|
and
|
||||||
|
.Cm cgroup
|
||||||
|
top-level group declarations, which can only be set from
|
||||||
|
.Pa /etc/finit.conf ,
|
||||||
|
since it is the first
|
||||||
|
.Cm .conf
|
||||||
|
file Finit reads.
|
||||||
|
.Pp
|
||||||
|
Originally,
|
||||||
|
.Pp /etc/finit.conf
|
||||||
|
was the only way to set up a Finit system. Today it is mainly used for
|
||||||
|
bootstrap settings like system hostname, early module loading for
|
||||||
|
watchdogd, network bringup and system shutdown. These can now also be
|
||||||
|
set in any
|
||||||
|
.Cm .conf
|
||||||
|
file in
|
||||||
|
.Pa /etc/finit.d .
|
||||||
|
.Pp
|
||||||
|
There is, however, nothing preventing you from having all configuration
|
||||||
|
settings in
|
||||||
|
.Pa /etc/finit.conf .
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr finit 8 ,
|
||||||
|
.Xr initctl 8
|
||||||
|
.Sh AUTHORS
|
||||||
|
.Nm Finit
|
||||||
|
was conceived and reverse engineered by Claudio Matsuoka. Since v1.0,
|
||||||
|
maintained by Joachim Wiberg, with contributions by many others.
|
||||||
+277
@@ -0,0 +1,277 @@
|
|||||||
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
|
.\" First parameter, NAME, should be all caps
|
||||||
|
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||||
|
.\" other parameters are allowed: see man(7), man(1)
|
||||||
|
.Dd June 6, 2021
|
||||||
|
.\" Please adjust this date whenever revising the manpage.
|
||||||
|
.Dt INITCTL 8 SMM
|
||||||
|
.Os Linux
|
||||||
|
.Sh NAME
|
||||||
|
.Nm initctl
|
||||||
|
.Nd Control tool for Finit
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm /sbin/initctl
|
||||||
|
.Op Fl bcfhjlpqtvV
|
||||||
|
.Op COMMAND
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Nm
|
||||||
|
is the official tool for interacting with
|
||||||
|
.Xr finit 8 .
|
||||||
|
It comes with functions for showing status, querying health of services,
|
||||||
|
as well as editing, enabling and disabling services.
|
||||||
|
.Sh OPTIONS
|
||||||
|
This program follows the usual UNIX command line syntax, with long
|
||||||
|
options starting with two dashes (`-'). The options are as follows:
|
||||||
|
.Bl -tag -width Ds
|
||||||
|
.It Fl b, -batch
|
||||||
|
Batch mode, no screen size probing. Useful for scripting.
|
||||||
|
.It Fl c, -create
|
||||||
|
Create missing paths (and files) as needed. Useful with the
|
||||||
|
.Cm edit
|
||||||
|
command.
|
||||||
|
.It Fl f, -force
|
||||||
|
Ignore missing files and arguments, never prompt.
|
||||||
|
.It Fl h, -help
|
||||||
|
Show built-in help text.
|
||||||
|
.It Fl j, -json
|
||||||
|
JSON output in
|
||||||
|
.Ar status
|
||||||
|
and
|
||||||
|
.Ar cond
|
||||||
|
commands.
|
||||||
|
.It Fl n, -noerr
|
||||||
|
When scripting
|
||||||
|
.Nm
|
||||||
|
to stop, start, restart, or signal a task or service, this option can be
|
||||||
|
used to ignore error 69 (no such task or service) and instead return 0
|
||||||
|
(OK).
|
||||||
|
.It Fl 1, -once
|
||||||
|
Only one lap in commands like top.
|
||||||
|
.It Fl p, -plain
|
||||||
|
Use plain table headings, no ANSI control characters.
|
||||||
|
.It Fl q, -quiet
|
||||||
|
Silent, only return status of command.
|
||||||
|
.It Fl t, -no-heading
|
||||||
|
Skip table headings.
|
||||||
|
.It Fl v, -verbose
|
||||||
|
Verbose output, where applicable.
|
||||||
|
.It Fl V, -version
|
||||||
|
Show program version.
|
||||||
|
.El
|
||||||
|
.Sh COMMANDS
|
||||||
|
.Bl -tag -width Ds
|
||||||
|
.It Nm Ar debug
|
||||||
|
Toggle
|
||||||
|
.Nm finit
|
||||||
|
(daemon) debug to
|
||||||
|
.Pa /dev/console
|
||||||
|
.It Nm Ar help
|
||||||
|
Show built-in help text.
|
||||||
|
.It Nm Ar version
|
||||||
|
Show program version.
|
||||||
|
.It Nm Ar ls | list
|
||||||
|
List all
|
||||||
|
.Cm *.conf
|
||||||
|
files in
|
||||||
|
.Pa /etc/finit.d
|
||||||
|
.It Nm Ar create Ar CONF
|
||||||
|
Create
|
||||||
|
.Cm .conf
|
||||||
|
in
|
||||||
|
.Pa /etc/finit.d/available .
|
||||||
|
.Pp
|
||||||
|
Piping the contents into
|
||||||
|
.Nm
|
||||||
|
works as one would expect:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
echo "task name:foo /tmp/foo.sh -- Foo logger" | initctl create foo
|
||||||
|
initctl enable foo
|
||||||
|
initctl reload
|
||||||
|
.Ed
|
||||||
|
.It Nm Ar delete Ar CONF
|
||||||
|
Delete
|
||||||
|
.Cm .conf
|
||||||
|
in
|
||||||
|
.Pa /etc/finit.d/available
|
||||||
|
.It Nm Ar show Ar CONF
|
||||||
|
Show
|
||||||
|
.Cm .conf
|
||||||
|
in
|
||||||
|
.Pa /etc/finit.d/available
|
||||||
|
.It Nm Ar edit Ar CONF
|
||||||
|
Edit
|
||||||
|
.Cm .conf
|
||||||
|
in
|
||||||
|
.Pa /etc/finit.d/available
|
||||||
|
.It Nm Ar touch Ar CONF
|
||||||
|
Change (mark as modified)
|
||||||
|
.Cm .conf
|
||||||
|
in
|
||||||
|
.Pa /etc/finit.d/available ,
|
||||||
|
like
|
||||||
|
.Ar edit
|
||||||
|
this tells
|
||||||
|
.Nm finit
|
||||||
|
that a configuration has been changed and is a candidate to be restarted
|
||||||
|
(or SIGHUP'ed) on
|
||||||
|
.Cm initctl reload
|
||||||
|
.It Nm Ar enable Ar CONF
|
||||||
|
Enable
|
||||||
|
.Cm .conf
|
||||||
|
in
|
||||||
|
.Pa /etc/finit.d/available ,
|
||||||
|
i.e., add symlink in
|
||||||
|
.Pa /etc/finit.d/enabled
|
||||||
|
.It Nm Ar disable Ar CONF
|
||||||
|
Disable
|
||||||
|
.Cm .conf
|
||||||
|
in
|
||||||
|
.Pa /etc/finit.d/enabled ,
|
||||||
|
i.e., removes symlink.
|
||||||
|
.It Nm Ar reload
|
||||||
|
Reload
|
||||||
|
.Cm *.conf in
|
||||||
|
.Pa /etc/finit.d ,
|
||||||
|
i.e., activates changes.
|
||||||
|
.It Nm Ar cond set Ar COND Op COND ...
|
||||||
|
Set (assert) user-defined condition,
|
||||||
|
.Cm +usr/COND
|
||||||
|
.It Nm Ar cond get Ar COND
|
||||||
|
Get (quietly) the status of any condition. Defaults to user-defined
|
||||||
|
condions, but if a slash is detected, e.g.,
|
||||||
|
.Cm pid/foo
|
||||||
|
or
|
||||||
|
.Cm net/eth0/exist ,
|
||||||
|
then any condition can be read.
|
||||||
|
.Pp
|
||||||
|
The command is geared for scripting, check the exit code to get the
|
||||||
|
status of the condition: 0 - on, 1 - off, 255 - flux. For a more
|
||||||
|
verbose output, use the
|
||||||
|
.Fl v
|
||||||
|
option.
|
||||||
|
.It Nm Ar cond clr | clear Ar COND Op COND ...
|
||||||
|
Clear (deassert) user-defined condition,
|
||||||
|
.Cm -usr/COND
|
||||||
|
.It Nm Ar cond status
|
||||||
|
Show condition status, default
|
||||||
|
.Cm cond
|
||||||
|
command. Also supports the
|
||||||
|
.Fl j
|
||||||
|
option for detailed JSON output.
|
||||||
|
.It Nm Ar cond dump Op Cm TYPE
|
||||||
|
Dump all, or a given type of, conditions and their status. Also
|
||||||
|
supports the
|
||||||
|
.Fl j
|
||||||
|
option for detailed JSON output.
|
||||||
|
.It Nm Ar ident Op Cm NAME
|
||||||
|
Display indentities of all run/task/services, or only instances
|
||||||
|
matching
|
||||||
|
.Cm NAME .
|
||||||
|
A partial string, e.g.,
|
||||||
|
.Cm NAM ,
|
||||||
|
will not match anything.
|
||||||
|
.It Nm Ar log Op Cm NAME
|
||||||
|
Show ten last Finit, or
|
||||||
|
.Cm NAME ,
|
||||||
|
messages from syslog.
|
||||||
|
.It Nm Ar start Cm NAME[:ID]
|
||||||
|
Start service by name, with optional ID, e.g.,
|
||||||
|
.Cm initctl start tty:1
|
||||||
|
.It Nm Ar stop Cm NAME[:ID]
|
||||||
|
Stop/Pause a running service by name.
|
||||||
|
.It Nm Ar reload Cm NAME[:ID]
|
||||||
|
Reload service as if its configuration had changed. Internally,
|
||||||
|
.Nm finit
|
||||||
|
marks the named service as "dirty" and turns the state machine,
|
||||||
|
resulting in a SIGHUP or restart of (at least) the named service.
|
||||||
|
Any dependant services are also restarted.
|
||||||
|
.Pp
|
||||||
|
.Sy Note:
|
||||||
|
no .conf file is reloaded with this variant of the command. Essentially
|
||||||
|
it is the same as calling
|
||||||
|
.Cm restart .
|
||||||
|
Except for two things:
|
||||||
|
.Bl -enum -offset indent -compact
|
||||||
|
.It
|
||||||
|
if the service supports HUP, it's signaled instead of stop-started, and
|
||||||
|
.It
|
||||||
|
it allows restarting run/task in the same runlevel -- which is otherwise
|
||||||
|
restricted.
|
||||||
|
.El
|
||||||
|
.It Nm Ar signal Cm NAME:[ID] S
|
||||||
|
Send signal S to service, by name.
|
||||||
|
.Cm S
|
||||||
|
may be a complete signal name such as SIGHUP, or short name such as HUP, or the signal number such as 1 (SIGHUP).
|
||||||
|
.It Nm Ar restart Cm NAME[:ID]
|
||||||
|
Restart (stop/start) service by name.
|
||||||
|
.It Nm Ar status Cm NAME[:ID]
|
||||||
|
Show service status, by name. If only
|
||||||
|
.Cm NAME
|
||||||
|
is given and multiple instances exits, a summary of all matching
|
||||||
|
instances are shown. Only an exact match displays detailed status
|
||||||
|
for a given instance.
|
||||||
|
.Pp
|
||||||
|
With the
|
||||||
|
.Fl q
|
||||||
|
option this command is silent, provided the
|
||||||
|
.Ar NAME[:ID]
|
||||||
|
selection matches a single run/task/service. The exit code of
|
||||||
|
.Nm
|
||||||
|
is non-zero if there is a problem. Zero is returned if a run/task has
|
||||||
|
run (at least) once in the current runlevel, and when a service is running
|
||||||
|
(as expected). See the
|
||||||
|
.Fl j
|
||||||
|
option for detailed JSON output suitable for machine parsing.
|
||||||
|
.Pp
|
||||||
|
.Sy Tip:
|
||||||
|
.Xr jq 1
|
||||||
|
is a useful scripting tool in combination with JSON output.
|
||||||
|
.It Nm Ar status
|
||||||
|
Show status of all services, default command. Also supports the
|
||||||
|
.Fl j
|
||||||
|
option for detailed JSON output.
|
||||||
|
.It Nm Ar cgroup
|
||||||
|
List cgroup config overview.
|
||||||
|
.It Nm Ar ps
|
||||||
|
List processes based on cgroups.
|
||||||
|
.It Nm Ar top
|
||||||
|
Show top-like listing based on cgroups.
|
||||||
|
.It Nm Ar plugins
|
||||||
|
List installed plugins.
|
||||||
|
.It Nm Ar runlevel Op Ar 0-9
|
||||||
|
Show or set runlevel: 0 halt, 6 reboot.
|
||||||
|
.Pp
|
||||||
|
If called at boot (runlevel S) to set the runlevel, Finit only schedules
|
||||||
|
the change, effectively overriding the configured runlevel from
|
||||||
|
.Pa /etc/finit.conf .
|
||||||
|
Useful to trigger a fail-safe mode, or similar.
|
||||||
|
.It Nm Ar reboot
|
||||||
|
Reboot system, default if
|
||||||
|
.Cm reboot
|
||||||
|
is symlinked to
|
||||||
|
.Nm .
|
||||||
|
.It Nm Ar halt
|
||||||
|
Halt system, default if
|
||||||
|
.Cm halt
|
||||||
|
is symlinked to
|
||||||
|
.Nm .
|
||||||
|
.It Nm Ar poweroff
|
||||||
|
Power-off system, default if
|
||||||
|
.Cm poweroff
|
||||||
|
is symlinked to
|
||||||
|
.Nm .
|
||||||
|
.It Nm Ar suspend
|
||||||
|
Suspend system, default if
|
||||||
|
.Cm suspend
|
||||||
|
is symlinked to
|
||||||
|
.Nm .
|
||||||
|
.It Nm Ar utmp show
|
||||||
|
Raw dump of UTMP/WTMP db.
|
||||||
|
.El
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr finit.conf 5
|
||||||
|
.Xr finit 8
|
||||||
|
.Sh AUTHORS
|
||||||
|
.Nm finit
|
||||||
|
was conceived and reverse engineered by Claudio Matsuoka. Since v1.0,
|
||||||
|
maintained by Joachim Wiberg, with contributions by many others.
|
||||||
+42
-10
@@ -1,13 +1,13 @@
|
|||||||
pkglibdir = $(plugin_path)
|
pkglibdir = $(plugin_path)
|
||||||
AM_LDFLAGS = -module -avoid-version -shared
|
AM_LDFLAGS = -module -avoid-version -shared
|
||||||
AM_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
AM_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
||||||
AM_CPPFLAGS = -I$(top_srcdir)/src -U_FORTIFY_SOURCE
|
AM_CPPFLAGS = -I$(top_srcdir)/src
|
||||||
AM_CPPFLAGS += -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_GNU_SOURCE -D_DEFAULT_SOURCE
|
AM_CPPFLAGS += -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_GNU_SOURCE -D_DEFAULT_SOURCE
|
||||||
AM_CPPFLAGS += $(lite_CFLAGS)
|
AM_CPPFLAGS += -D__FINIT__ $(lite_CFLAGS) $(uev_CFLAGS)
|
||||||
|
|
||||||
if STATIC
|
if STATIC
|
||||||
noinst_LTLIBRARIES = libplug.la
|
noinst_LTLIBRARIES = libplug.la
|
||||||
libplug_la_SOURCES = bootmisc.c modprobe.c rtc.c pidfile.c procps.c tty.c urandom.c usr.c
|
libplug_la_SOURCES = bootmisc.c pidfile.c procps.c sys.c usr.c
|
||||||
|
|
||||||
if BUILD_ALSA_UTILS_PLUGIN
|
if BUILD_ALSA_UTILS_PLUGIN
|
||||||
libplug_la_SOURCES += alsa-utils.c
|
libplug_la_SOURCES += alsa-utils.c
|
||||||
@@ -17,14 +17,14 @@ if BUILD_DBUS_PLUGIN
|
|||||||
libplug_la_SOURCES += dbus.c
|
libplug_la_SOURCES += dbus.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_HOTPLUG_PLUGIN
|
|
||||||
libplug_la_SOURCES += hotplug.c
|
|
||||||
endif
|
|
||||||
|
|
||||||
if BUILD_MODULES_LOAD_PLUGIN
|
if BUILD_MODULES_LOAD_PLUGIN
|
||||||
libplug_la_SOURCES += modules-load.c
|
libplug_la_SOURCES += modules-load.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if BUILD_MODPROBE_PLUGIN
|
||||||
|
libplug_la_SOURCES += modprobe.c
|
||||||
|
endif
|
||||||
|
|
||||||
if BUILD_NETLINK_PLUGIN
|
if BUILD_NETLINK_PLUGIN
|
||||||
libplug_la_SOURCES += netlink.c
|
libplug_la_SOURCES += netlink.c
|
||||||
endif
|
endif
|
||||||
@@ -33,8 +33,24 @@ if BUILD_RESOLVCONF_PLUGIN
|
|||||||
libplug_la_SOURCES += resolvconf.c
|
libplug_la_SOURCES += resolvconf.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if BUILD_RTC_PLUGIN
|
||||||
|
libplug_la_SOURCES += rtc.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
if BUILD_TTY_PLUGIN
|
||||||
|
libplug_la_SOURCES += tty.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
if BUILD_URANDOM_PLUGIN
|
||||||
|
libplug_la_SOURCES += urandom.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
if BUILD_X11_COMMON_PLUGIN
|
||||||
|
libplug_la_SOURCES += x11-common.c
|
||||||
|
endif
|
||||||
|
|
||||||
else
|
else
|
||||||
pkglib_LTLIBRARIES = bootmisc.la modprobe.la rtc.la pidfile.la procps.la tty.la urandom.la usr.la
|
pkglib_LTLIBRARIES = bootmisc.la pidfile.la procps.la sys.la usr.la
|
||||||
|
|
||||||
if BUILD_ALSA_UTILS_PLUGIN
|
if BUILD_ALSA_UTILS_PLUGIN
|
||||||
pkglib_LTLIBRARIES += alsa-utils.la
|
pkglib_LTLIBRARIES += alsa-utils.la
|
||||||
@@ -44,14 +60,18 @@ if BUILD_DBUS_PLUGIN
|
|||||||
pkglib_LTLIBRARIES += dbus.la
|
pkglib_LTLIBRARIES += dbus.la
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_HOTPLUG_PLUGIN
|
if BUILD_HOOK_SCRIPTS_PLUGIN
|
||||||
pkglib_LTLIBRARIES += hotplug.la
|
pkglib_LTLIBRARIES += hook-scripts.la
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_MODULES_LOAD_PLUGIN
|
if BUILD_MODULES_LOAD_PLUGIN
|
||||||
pkglib_LTLIBRARIES += modules-load.la
|
pkglib_LTLIBRARIES += modules-load.la
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if BUILD_MODPROBE_PLUGIN
|
||||||
|
pkglib_LTLIBRARIES += modprobe.la
|
||||||
|
endif
|
||||||
|
|
||||||
if BUILD_NETLINK_PLUGIN
|
if BUILD_NETLINK_PLUGIN
|
||||||
pkglib_LTLIBRARIES += netlink.la
|
pkglib_LTLIBRARIES += netlink.la
|
||||||
endif
|
endif
|
||||||
@@ -60,6 +80,18 @@ if BUILD_RESOLVCONF_PLUGIN
|
|||||||
pkglib_LTLIBRARIES += resolvconf.la
|
pkglib_LTLIBRARIES += resolvconf.la
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if BUILD_RTC_PLUGIN
|
||||||
|
pkglib_LTLIBRARIES += rtc.la
|
||||||
|
endif
|
||||||
|
|
||||||
|
if BUILD_TTY_PLUGIN
|
||||||
|
pkglib_LTLIBRARIES += tty.la
|
||||||
|
endif
|
||||||
|
|
||||||
|
if BUILD_URANDOM_PLUGIN
|
||||||
|
pkglib_LTLIBRARIES += urandom.la
|
||||||
|
endif
|
||||||
|
|
||||||
if BUILD_X11_COMMON_PLUGIN
|
if BUILD_X11_COMMON_PLUGIN
|
||||||
pkglib_LTLIBRARIES += x11-common.la
|
pkglib_LTLIBRARIES += x11-common.la
|
||||||
endif
|
endif
|
||||||
|
|||||||
+11
-6
@@ -1,6 +1,6 @@
|
|||||||
/* Save and restore ALSA sound settings using alsactl
|
/* Save and restore ALSA sound settings using alsactl
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -21,7 +21,12 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <lite/lite.h>
|
#ifdef _LIBITE_LITE
|
||||||
|
# include <libite/lite.h>
|
||||||
|
#else
|
||||||
|
# include <lite/lite.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
@@ -31,12 +36,12 @@
|
|||||||
static void save(void *arg)
|
static void save(void *arg)
|
||||||
{
|
{
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
_d("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (whichp(ALSACTL)) {
|
if (whichp(ALSACTL)) {
|
||||||
_d("Saving sound settings ...");
|
dbg("Saving sound settings ...");
|
||||||
run_interactive(ALSACTL " -g store", "Saving sound settings");
|
run_interactive(ALSACTL " -g store", "Saving sound settings");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,12 +49,12 @@ static void save(void *arg)
|
|||||||
static void restore(void *arg)
|
static void restore(void *arg)
|
||||||
{
|
{
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
_d("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (whichp(ALSACTL)) {
|
if (whichp(ALSACTL)) {
|
||||||
_d("Restoring sound settings ...");
|
dbg("Restoring sound settings ...");
|
||||||
run_interactive(ALSACTL " -g restore", "Restoring sound settings");
|
run_interactive(ALSACTL " -g restore", "Restoring sound settings");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+59
-74
@@ -1,6 +1,6 @@
|
|||||||
/* Setup necessary system files for, e.g. UTMP (tracking logins)
|
/* Setup necessary system files for, e.g. UTMP (tracking logins)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -21,24 +21,35 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "config.h" /* Generated by configure script */
|
||||||
|
|
||||||
#include <ftw.h>
|
#include <ftw.h>
|
||||||
|
#ifdef HAVE_MNTENT_H
|
||||||
#include <mntent.h>
|
#include <mntent.h>
|
||||||
|
#endif
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <lite/lite.h>
|
#ifdef _LIBITE_LITE
|
||||||
|
# include <libite/lite.h>
|
||||||
|
#else
|
||||||
|
# include <lite/lite.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "tmpfiles.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utmp-api.h"
|
#include "utmp-api.h"
|
||||||
|
|
||||||
static int is_tmpfs(char *path)
|
static int is_tmpfs(char *path)
|
||||||
{
|
{
|
||||||
|
struct mntent mount;
|
||||||
|
struct mntent *mnt;
|
||||||
|
char buf[256];
|
||||||
int tmpfs = 0;
|
int tmpfs = 0;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *dir;
|
char *dir;
|
||||||
struct mntent *mnt;
|
|
||||||
|
|
||||||
/* If path is a symlink, check what it resolves to */
|
/* If path is a symlink, check what it resolves to */
|
||||||
dir = realpath(path, NULL);
|
dir = realpath(path, NULL);
|
||||||
@@ -51,7 +62,7 @@ static int is_tmpfs(char *path)
|
|||||||
return 0; /* Dunno, maybe not */
|
return 0; /* Dunno, maybe not */
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((mnt = getmntent(fp))) {
|
while ((mnt = getmntent_r(fp, &mount, buf, sizeof(buf)))) {
|
||||||
if (!strcmp(dir, mnt->mnt_dir))
|
if (!strcmp(dir, mnt->mnt_dir))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -70,7 +81,7 @@ static int bootclean(const char *fpath, const struct stat *sb, int tflag, struct
|
|||||||
if (ftw->level == 0)
|
if (ftw->level == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
_d("Removing %s ...", fpath);
|
dbg("Removing %s ...", fpath);
|
||||||
(void)remove(fpath);
|
(void)remove(fpath);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -100,6 +111,45 @@ static void clean(void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Kernel defines the following compulsory and recommended links
|
||||||
|
* https://github.com/torvalds/linux/blob/v5.18/Documentation/admin-guide/devices.rst#compulsory-links
|
||||||
|
*/
|
||||||
|
static void kernel_links(void)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
char *tgt, *lnk;
|
||||||
|
int optional;
|
||||||
|
} k[] = {
|
||||||
|
{ "/proc/self/fd", "/dev/fd", 0 },
|
||||||
|
{ "fd/0", "/dev/stdin", 0 },
|
||||||
|
{ "fd/1", "/dev/stdout", 0 },
|
||||||
|
{ "fd/2", "/dev/stderr", 0 },
|
||||||
|
{ "socksys", "/dev/nfsd", 0 },
|
||||||
|
{ "null", "/dev/X0R", 0 },
|
||||||
|
{ "/proc/kcore", "/dev/core", 1 },
|
||||||
|
{ "ram0", "/dev/ramdisk", 1 },
|
||||||
|
{ "qft0", "/dev/ftape", 1 },
|
||||||
|
{ "video0", "/dev/bttv0", 1 },
|
||||||
|
{ "radio0", "/dev/radio", 1 },
|
||||||
|
};
|
||||||
|
char *fn, buf[80];
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < NELEMS(k); i++) {
|
||||||
|
fn = k[i].tgt;
|
||||||
|
|
||||||
|
if (k[i].optional) {
|
||||||
|
if (fn[0] != '/') {
|
||||||
|
snprintf(buf, sizeof(buf), "/dev/%s", k[i].tgt);
|
||||||
|
fn = buf;
|
||||||
|
}
|
||||||
|
if (!fexist(fn))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ln(k[i].tgt, k[i].lnk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup standard FHS 2.3 structure in /var, and write runlevel to UTMP
|
* Setup standard FHS 2.3 structure in /var, and write runlevel to UTMP
|
||||||
*/
|
*/
|
||||||
@@ -109,80 +159,15 @@ static void setup(void *arg)
|
|||||||
|
|
||||||
prev = umask(0);
|
prev = umask(0);
|
||||||
|
|
||||||
_d("Setting up FHS structure in /var ...");
|
/* Kernel symlinks, e.g. /proc/self/fd -> /dev/fd */
|
||||||
makedir("/var/cache", 0755);
|
kernel_links();
|
||||||
makedir("/var/db", 0755); /* _PATH_VARDB on some systems */
|
|
||||||
makedir("/var/games", 0755);
|
|
||||||
makedir("/var/lib", 0755);
|
|
||||||
makedir("/var/lib/misc", 0755); /* _PATH_VARDB on some systems */
|
|
||||||
makedir("/var/lib/alarm", 0755);
|
|
||||||
makedir("/var/lib/urandom",0755);
|
|
||||||
if (fisdir("/run")) {
|
|
||||||
_d("System with new /run tmpfs ...");
|
|
||||||
makedir("/run/lock", 1777);
|
|
||||||
symlink("/run/lock", "/var/lock");
|
|
||||||
symlink("/dev/shm", "/run/shm");
|
|
||||||
|
|
||||||
/* compat only, should really be set up by OS/dist */
|
/* Create all system tmpfiles.d(5) */
|
||||||
symlink("/run", "/var/run");
|
tmpfilesd();
|
||||||
} else {
|
|
||||||
makedir("/var/lock", 1777);
|
|
||||||
makedir("/var/run", 0755);
|
|
||||||
}
|
|
||||||
makedir("/var/log", 0755);
|
|
||||||
makedir("/var/mail", 0755);
|
|
||||||
makedir("/var/opt", 0755);
|
|
||||||
makedir("/var/spool", 0755);
|
|
||||||
makedir("/var/spool/cron", 0755);
|
|
||||||
makedir("/var/tmp", 0755);
|
|
||||||
makedir("/var/empty", 0755);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* UTMP actually needs multiple db files
|
|
||||||
*/
|
|
||||||
if (has_utmp()) {
|
|
||||||
int gid;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If /etc/group or "utmp" group is missing, default to
|
|
||||||
* "root", or "wheel", group.
|
|
||||||
*/
|
|
||||||
_d("Setting up necessary UTMP files ...");
|
|
||||||
gid = getgroup("utmp");
|
|
||||||
if (gid < 0)
|
|
||||||
gid = 0;
|
|
||||||
|
|
||||||
create("/var/run/utmp", 0644, 0, gid); /* Currently logged in */
|
|
||||||
create("/var/log/wtmp", 0644, 0, gid); /* Login history */
|
|
||||||
create("/var/log/btmp", 0600, 0, gid); /* Failed logins */
|
|
||||||
create("/var/log/lastlog", 0644, 0, gid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set BOOT_TIME UTMP entry */
|
/* Set BOOT_TIME UTMP entry */
|
||||||
utmp_set_boot();
|
utmp_set_boot();
|
||||||
|
|
||||||
#ifdef TOUCH_ETC_NETWORK_RUN_IFSTATE
|
|
||||||
touch("/etc/network/run/ifstate");
|
|
||||||
#else
|
|
||||||
erase("/etc/network/run/ifstate");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
_d("Setting up misc files ...");
|
|
||||||
makedir("/var/run/network",0755); /* Needed by Debian/Ubuntu ifupdown */
|
|
||||||
makedir("/var/run/lldpd", 0755); /* Needed by lldpd */
|
|
||||||
makedir("/var/run/pluto", 0755); /* Needed by Openswan */
|
|
||||||
mksubsys("/var/run/quagga", 0755, "quagga", "quagga");
|
|
||||||
mksubsys("/var/log/quagga", 0755, "quagga", "quagga");
|
|
||||||
mksubsys("/var/run/frr", 0755, "frr", "frr");
|
|
||||||
mksubsys("/var/log/frr", 0755, "frr", "frr");
|
|
||||||
makedir("/var/run/sshd", 01755); /* OpenSSH */
|
|
||||||
|
|
||||||
if (!fexist("/etc/mtab"))
|
|
||||||
symlink("../proc/self/mounts", "/etc/mtab");
|
|
||||||
|
|
||||||
/* Void Linux has a uuidd that runs as uuid:uuid and needs /run/uuid */
|
|
||||||
mksubsys("/var/run/uuidd", 0755, "uuidd", "uuidd");
|
|
||||||
|
|
||||||
umask(prev);
|
umask(prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+111
-26
@@ -1,6 +1,6 @@
|
|||||||
/* Setup and start system message bus, D-Bus
|
/* Setup and start system message bus, D-Bus
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -22,7 +22,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <lite/lite.h>
|
#ifdef _LIBITE_LITE
|
||||||
|
# include <libite/lite.h>
|
||||||
|
#else
|
||||||
|
# include <lite/lite.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@@ -31,54 +35,135 @@
|
|||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
|
||||||
#define DAEMON "dbus-daemon"
|
#define DBUS_DAEMON "dbus-daemon"
|
||||||
#define ARGS "--nofork --system --syslog-only"
|
#define DBUS_ARGS "--nofork --system --syslog-only"
|
||||||
#define DESC "D-Bus message bus daemon"
|
#define DBUS_DESC "D-Bus message bus daemon"
|
||||||
|
|
||||||
#define DAEMONUSER "messagebus"
|
#ifndef DBUS_DAEMONUSER
|
||||||
|
#define DBUS_DAEMONUSER "messagebus"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DBUS_DAEMONGROUP
|
||||||
|
#define DBUS_DAEMONGROUP "messagebus"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dumnpster diving for the D-Bus main configuration file
|
||||||
|
* where <pidfile> is defined.
|
||||||
|
*/
|
||||||
|
static char *dbus_pidfn(void)
|
||||||
|
{
|
||||||
|
char *alt[] = {
|
||||||
|
"/usr/share/dbus-1/system.conf",
|
||||||
|
"/etc/dbus-1/system.conf",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; alt[i]; i++) {
|
||||||
|
char *fn = alt[i];
|
||||||
|
char buf[256];
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
fp = fopen(fn, "r");
|
||||||
|
if (!fp)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fn = NULL;
|
||||||
|
while (fgets(buf, sizeof(buf), fp)) {
|
||||||
|
char *pos;
|
||||||
|
|
||||||
|
pos = strstr(buf, "<pidfile>");
|
||||||
|
if (!pos)
|
||||||
|
continue;
|
||||||
|
fn = pos + strlen("<pidfile>");
|
||||||
|
pos = strstr(fn, "</pidfile>");
|
||||||
|
if (!pos) {
|
||||||
|
fn = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*pos = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
if (fn)
|
||||||
|
return strdup(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void setup(void *arg)
|
static void setup(void *arg)
|
||||||
{
|
{
|
||||||
|
char *group = DBUS_DAEMONGROUP;
|
||||||
|
char *user = DBUS_DAEMONUSER;
|
||||||
char line[256];
|
char line[256];
|
||||||
|
char *pidfn;
|
||||||
mode_t prev;
|
mode_t prev;
|
||||||
char *cmd;
|
char *cmd;
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
_d("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = which(DAEMON);
|
cmd = which(DBUS_DAEMON);
|
||||||
if (!cmd) {
|
if (!cmd) {
|
||||||
_d("Skipping plugin, %s is not installed.", DAEMON);
|
dbg("Skipping plugin, %s is not installed.", DBUS_DAEMON);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev =umask(0);
|
if (getuser(user, NULL) == -1) {
|
||||||
|
if (getuser("dbus", NULL) == -1)
|
||||||
|
user = "root"; /* fallback */
|
||||||
|
else
|
||||||
|
user = "dbus"; /* e.g., Buildroot */
|
||||||
|
}
|
||||||
|
|
||||||
mksubsys("/var/run/dbus", 0755, DAEMONUSER, DAEMONUSER);
|
if (getgroup(group) == -1) {
|
||||||
if (whichp("dbus-uuidgen"))
|
if (getgroup("dbus") == -1)
|
||||||
run_interactive("dbus-uuidgen --ensure", "Creating machine UUID for D-Bus");
|
group = "root"; /* fallback */
|
||||||
|
else
|
||||||
|
group = "dbus"; /* e.g., Buildroot */
|
||||||
|
}
|
||||||
|
|
||||||
/* Clean up from any previous pre-bootstrap run */
|
/* Clean up from any previous pre-bootstrap run */
|
||||||
remove("/var/run/dbus/pid");
|
pidfn = dbus_pidfn();
|
||||||
|
if (pidfn)
|
||||||
/* Register service with Finit */
|
remove(pidfn);
|
||||||
snprintf(line, sizeof(line), "[S12345789] @%s:%s %s %s -- %s",
|
|
||||||
DAEMONUSER, DAEMONUSER, cmd, ARGS, DESC);
|
|
||||||
if (service_register(SVC_TYPE_SERVICE, line, global_rlimit, NULL))
|
|
||||||
_pe("Failed registering %s", DAEMON);
|
|
||||||
free(cmd);
|
|
||||||
|
|
||||||
|
dbg("Creating D-Bus Required Directories ...");
|
||||||
|
prev = umask(0);
|
||||||
|
mksubsys("/var/run/dbus", 0755, user, group);
|
||||||
|
mksubsys("/var/run/lock/subsys", 0755, user, group);
|
||||||
|
mksubsys("/var/lib/dbus", 0755, user, group);
|
||||||
|
mksubsys("/tmp/dbus", 0755, user, group);
|
||||||
umask(prev);
|
umask(prev);
|
||||||
|
|
||||||
|
/* Generate machine id for dbus */
|
||||||
|
if (whichp("dbus-uuidgen"))
|
||||||
|
run_interactive("dbus-uuidgen --ensure", "Verifying D-Bus machine UUID");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register service with Finit
|
||||||
|
* Note: dbus drops privs after starting up.
|
||||||
|
*/
|
||||||
|
if (pidfn) {
|
||||||
|
snprintf(line, sizeof(line), "[S123456789] cgroup.system notify:none name:dbus pid:!%s %s %s -- %s",
|
||||||
|
pidfn, cmd, DBUS_ARGS, DBUS_DESC);
|
||||||
|
free(pidfn);
|
||||||
|
} else
|
||||||
|
snprintf(line, sizeof(line), "[S123456789] cgroup.system notify:none name:dbus %s %s -- %s",
|
||||||
|
cmd, DBUS_ARGS, DBUS_DESC);
|
||||||
|
|
||||||
|
conf_save_service(SVC_TYPE_SERVICE, line, "dbus.conf");
|
||||||
|
free(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = __FILE__,
|
||||||
.hook[HOOK_BASEFS_UP] = {
|
.hook[HOOK_SVC_PLUGIN] = { .cb = setup },
|
||||||
.cb = setup
|
|
||||||
},
|
|
||||||
.depends = { "bootmisc", },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(plugin_init)
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
/* Trigger scripts to run from finit's hooks
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Tobias Waldekranz <tobias@waldekranz.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "finit.h"
|
||||||
|
#include "helpers.h"
|
||||||
|
#include "plugin.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
extern void plugin_script_run(hook_point_t no);
|
||||||
|
|
||||||
|
static void hscript_run_parts(hook_point_t no)
|
||||||
|
{
|
||||||
|
plugin_script_run(no);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hscript_banner(void *arg)
|
||||||
|
{
|
||||||
|
hscript_run_parts(HOOK_BANNER);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hscript_rootfs_up(void *arg)
|
||||||
|
{
|
||||||
|
hscript_run_parts(HOOK_ROOTFS_UP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hscript_mount_error(void *arg)
|
||||||
|
{
|
||||||
|
hscript_run_parts(HOOK_MOUNT_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hscript_mount_post(void *arg)
|
||||||
|
{
|
||||||
|
hscript_run_parts(HOOK_MOUNT_POST);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hscript_basefs_up(void *arg)
|
||||||
|
{
|
||||||
|
hscript_run_parts(HOOK_BASEFS_UP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hscript_network_up(void *arg)
|
||||||
|
{
|
||||||
|
hscript_run_parts(HOOK_NETWORK_UP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hscript_svc_up(void *arg)
|
||||||
|
{
|
||||||
|
hscript_run_parts(HOOK_SVC_UP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hscript_system_up(void *arg)
|
||||||
|
{
|
||||||
|
hscript_run_parts(HOOK_SYSTEM_UP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hscript_shutdown(void *arg)
|
||||||
|
{
|
||||||
|
hscript_run_parts(HOOK_SHUTDOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_t plugin = {
|
||||||
|
.name = __FILE__,
|
||||||
|
.hook[HOOK_BANNER] = { .cb = hscript_banner },
|
||||||
|
.hook[HOOK_ROOTFS_UP] = { .cb = hscript_rootfs_up },
|
||||||
|
.hook[HOOK_MOUNT_ERROR] = { .cb = hscript_mount_error },
|
||||||
|
.hook[HOOK_MOUNT_POST] = { .cb = hscript_mount_post },
|
||||||
|
.hook[HOOK_BASEFS_UP] = { .cb = hscript_basefs_up },
|
||||||
|
.hook[HOOK_NETWORK_UP] = { .cb = hscript_network_up },
|
||||||
|
.hook[HOOK_SVC_UP] = { .cb = hscript_svc_up },
|
||||||
|
.hook[HOOK_SYSTEM_UP] = { .cb = hscript_system_up },
|
||||||
|
.hook[HOOK_SHUTDOWN] = { .cb = hscript_shutdown },
|
||||||
|
/*
|
||||||
|
* We have exited here, so these are handled a bit differently by Finit,
|
||||||
|
* when hook scripts are enabled, just to provide the user with the same
|
||||||
|
* interface:
|
||||||
|
*
|
||||||
|
* .hook[HOOK_SVC_DN] = { .cb = hscript_svc_down },
|
||||||
|
* .hook[HOOK_SYS_DN] = { .cb = hscript_system_down },
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
PLUGIN_INIT(plugin_init)
|
||||||
|
{
|
||||||
|
plugin_register(&plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
PLUGIN_EXIT(plugin_exit)
|
||||||
|
{
|
||||||
|
plugin_unregister(&plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local Variables:
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* c-file-style: "linux"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
/* Heuristically find and initialize a suitable hotplug daemon
|
|
||||||
*
|
|
||||||
* Copyright (c) 2012-2021 Joachim Wiberg <troglobit@gmail.com>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "conf.h"
|
|
||||||
#include "finit.h"
|
|
||||||
#include "helpers.h"
|
|
||||||
#include "plugin.h"
|
|
||||||
#include "service.h"
|
|
||||||
|
|
||||||
static void setup(void *arg)
|
|
||||||
{
|
|
||||||
char cmd[256];
|
|
||||||
char *path;
|
|
||||||
|
|
||||||
if (rescue) {
|
|
||||||
_d("Skipping %s plugin in rescue mode.", __FILE__);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Populate /dev and prepare for runtime events from kernel.
|
|
||||||
* Prefer udev if mdev is also available on the system.
|
|
||||||
*/
|
|
||||||
path = which("udevd");
|
|
||||||
if (!path)
|
|
||||||
path = which("/lib/systemd/systemd-udevd");
|
|
||||||
if (path) {
|
|
||||||
/* Register udevd as a monitored service */
|
|
||||||
snprintf(cmd, sizeof(cmd), "[S12345789] pid:udevd name:udevd log %s "
|
|
||||||
"-- Device event managing daemon", path);
|
|
||||||
if (service_register(SVC_TYPE_SERVICE, cmd, global_rlimit, NULL)) {
|
|
||||||
_pe("Failed registering %s", path);
|
|
||||||
} else {
|
|
||||||
snprintf(cmd, sizeof(cmd), ":1 [S] <pid/udevd> log "
|
|
||||||
"udevadm trigger -c add -t devices "
|
|
||||||
"-- Requesting device events");
|
|
||||||
service_register(SVC_TYPE_RUN, cmd, global_rlimit, NULL);
|
|
||||||
|
|
||||||
snprintf(cmd, sizeof(cmd), ":2 [S] <pid/udevd> log "
|
|
||||||
"udevadm trigger -c add -t subsystems "
|
|
||||||
"-- Requesting subsystem events");
|
|
||||||
service_register(SVC_TYPE_RUN, cmd, global_rlimit, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(path);
|
|
||||||
|
|
||||||
/* Debian has this little script to copy generated
|
|
||||||
* rules while the system was read-only. TODO: When
|
|
||||||
* this functionality was hardcoded in finit.c, this
|
|
||||||
* call was made in crank_worker(). Now that
|
|
||||||
* filesystems are mounted earlier we should be able
|
|
||||||
* to make this call directly after the triggers have
|
|
||||||
* run, but this has not been tested AT ALL. */
|
|
||||||
if (fexist("/lib/udev/udev-finish"))
|
|
||||||
run_interactive("/lib/udev/udev-finish", "Finalizing udev");
|
|
||||||
} else {
|
|
||||||
path = which("mdev");
|
|
||||||
if (path) {
|
|
||||||
/* Embedded Linux systems usually have BusyBox mdev */
|
|
||||||
if (debug)
|
|
||||||
touch("/dev/mdev.log");
|
|
||||||
|
|
||||||
snprintf(cmd, sizeof(cmd), "%s -s", path);
|
|
||||||
free(path);
|
|
||||||
|
|
||||||
run_interactive(cmd, "Populating device tree");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static plugin_t plugin = {
|
|
||||||
.name = __FILE__,
|
|
||||||
.hook[HOOK_BASEFS_UP] = {
|
|
||||||
.cb = setup
|
|
||||||
},
|
|
||||||
.depends = { "bootmisc" },
|
|
||||||
};
|
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
|
||||||
{
|
|
||||||
plugin_register(&plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
|
||||||
{
|
|
||||||
plugin_unregister(&plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Local Variables:
|
|
||||||
* indent-tabs-mode: t
|
|
||||||
* c-file-style: "linux"
|
|
||||||
* End:
|
|
||||||
*/
|
|
||||||
+78
-15
@@ -1,6 +1,6 @@
|
|||||||
/* Coldplug modules using modalias magic
|
/* Coldplug modules using modalias magic
|
||||||
*
|
*
|
||||||
* Copyright (c) 2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -40,11 +40,15 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h> /* gettimeofday() */
|
#include <sys/time.h> /* gettimeofday() */
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <lite/lite.h>
|
#ifdef _LIBITE_LITE
|
||||||
|
# include <libite/lite.h>
|
||||||
|
#else
|
||||||
|
# include <lite/lite.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "util.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
|
||||||
struct module {
|
struct module {
|
||||||
@@ -67,14 +71,14 @@ static int modprobe(char *alias)
|
|||||||
pid = fork();
|
pid = fork();
|
||||||
switch (pid) {
|
switch (pid) {
|
||||||
case -1:
|
case -1:
|
||||||
_pe("Failed forking modprobe child");
|
err(1, "Failed forking modprobe child");
|
||||||
return 1;
|
return 1;
|
||||||
case 0:
|
case 0:
|
||||||
execvp(args[0], args);
|
execvp(args[0], args);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (!complete(args[0], pid))
|
if (!complete(args[0], pid))
|
||||||
_d("Successful modprobe of %s", alias);
|
dbg("Successful modprobe of %s", alias);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +106,7 @@ static void alias_remove(struct module *m)
|
|||||||
TAILQ_REMOVE(&modules, m, link);
|
TAILQ_REMOVE(&modules, m, link);
|
||||||
free(m->alias);
|
free(m->alias);
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int alias_exist(char *alias)
|
static int alias_exist(char *alias)
|
||||||
{
|
{
|
||||||
@@ -116,27 +120,86 @@ static int alias_exist(char *alias)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int scan_alias(const char *path, const struct stat *st, int flag, struct FTW *unused)
|
static void alias_add_uniq(char *alias)
|
||||||
|
{
|
||||||
|
if (alias_exist(alias))
|
||||||
|
return;
|
||||||
|
|
||||||
|
alias_add(alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FILE *maybe_fopen_alias(const char *file, const char *path)
|
||||||
|
{
|
||||||
|
const char *basename;
|
||||||
|
|
||||||
|
basename = basenm(path);
|
||||||
|
if (!strcmp(basename, path))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (strcmp(file, basename))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return fopen(path, "r");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int scan_modalias(const char *path)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
|
||||||
char buf[256];
|
char buf[256];
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
if (fnmatch("*/modalias", path, 0))
|
fp = maybe_fopen_alias("modalias", path);
|
||||||
return 0;
|
|
||||||
|
|
||||||
fp = fopen(path, "r");
|
|
||||||
if (!fp)
|
if (!fp)
|
||||||
return 0;
|
return 1;
|
||||||
|
|
||||||
if (fgets(buf, sizeof(buf), fp)) {
|
if (fgets(buf, sizeof(buf), fp)) {
|
||||||
chomp(buf);
|
chomp(buf);
|
||||||
if (!alias_exist(buf))
|
alias_add_uniq(buf);
|
||||||
alias_add(buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int scan_uevent(const char *path)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
fp = maybe_fopen_alias("uevent", path);
|
||||||
|
if (!fp)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
while (fgets(buf, sizeof(buf), fp)) {
|
||||||
|
if (strstr(buf, "MODALIAS=") != buf)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
chomp(buf);
|
||||||
|
|
||||||
|
alias_add_uniq(buf + strlen("MODALIAS="));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int scan_alias(const char *path, const struct stat *st,
|
||||||
|
int flag, struct FTW *unused)
|
||||||
|
{
|
||||||
|
/* Sanity check: is this a regular file we can read? */
|
||||||
|
if (!(S_ISREG(st->st_mode) && (st->st_mode & S_IRUSR)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!scan_uevent(path))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
scan_modalias(path);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void coldplug(void *arg)
|
static void coldplug(void *arg)
|
||||||
{
|
{
|
||||||
struct module *m, *tmp;
|
struct module *m, *tmp;
|
||||||
|
|||||||
+169
-44
@@ -21,10 +21,37 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <lite/lite.h>
|
/*
|
||||||
|
* This plugin scans files in /etc/modules-load.d/, for each line in the
|
||||||
|
* file it assumes the name of a kernel module, with optional arguments.
|
||||||
|
* Each module is loaded when entering runlevel 2, 3, 4, or 5, using the
|
||||||
|
* modprobe tool.
|
||||||
|
*
|
||||||
|
* Loading is done by inserting a `task` stanza in Finit, ensuring all
|
||||||
|
* modules are loaded in parallel, with other modules and programs.
|
||||||
|
* Each `task` stanza is by default given the name:modprobe.module and
|
||||||
|
* indexed with `:ID`, starting with 1.
|
||||||
|
*
|
||||||
|
* Indexing can be disabled per file in /etc/modules-load.d/, anywwhere
|
||||||
|
* in a file, by putting the keyword `noindex` on a line of its own. A
|
||||||
|
* noindex command can appear anywhere in the file, and up to the point
|
||||||
|
* it is read, tasks will be indexed with an incrementing `:ID`. When
|
||||||
|
* `noindex` is read indexing is disabled and all subseequent tasks will
|
||||||
|
* not have any `:ID` at all.
|
||||||
|
*
|
||||||
|
* Please note, the :ID is there for your benefit, it ensures that tasks
|
||||||
|
* in Finit are unique. If you have two tasks with the same name and ID
|
||||||
|
* (or no ID), the last one read replaces any preceeding one!
|
||||||
|
*/
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#ifdef _LIBITE_LITE
|
||||||
|
# include <libite/lite.h>
|
||||||
|
#else
|
||||||
|
# include <lite/lite.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
@@ -35,60 +62,158 @@
|
|||||||
#ifndef MODULES_LOAD_PATH
|
#ifndef MODULES_LOAD_PATH
|
||||||
#define MODULES_LOAD_PATH "/etc/modules-load.d"
|
#define MODULES_LOAD_PATH "/etc/modules-load.d"
|
||||||
#endif
|
#endif
|
||||||
|
#define MODPROBE_PATH "/sbin/modprobe"
|
||||||
#define SERVICE_LINE \
|
#define SERVICE_LINE \
|
||||||
":%d name:modprobe.%s [2345] /sbin/modprobe %s %s -- Kernel module: %s"
|
"cgroup.init name:modprobe.%s :%d [%s] %s %s %s --"
|
||||||
|
#define SERVICE_LINE_NOINDEX \
|
||||||
|
"cgroup.init name:modprobe.%s [%s] %s %s %s --"
|
||||||
|
|
||||||
|
static int modules_load(const char *file, int index)
|
||||||
|
{
|
||||||
|
char module_path[PATH_MAX];
|
||||||
|
char *modprobe_path;
|
||||||
|
int num = 0;
|
||||||
|
char *line;
|
||||||
|
char *lvl;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
strlcpy(module_path, MODULES_LOAD_PATH "/", sizeof(module_path));
|
||||||
|
strlcat(module_path, file, sizeof(module_path));
|
||||||
|
|
||||||
|
fp = fopen(module_path, "r");
|
||||||
|
if (!fp) {
|
||||||
|
warnx("failed opening %s for reading, skipping ...", module_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
modprobe_path = strdup(MODPROBE_PATH);
|
||||||
|
if (!modprobe_path) {
|
||||||
|
fail:
|
||||||
|
warnx("failed allocating memory in modules-load plugin.");
|
||||||
|
fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lvl = strdup("S");
|
||||||
|
if (!lvl) {
|
||||||
|
free(modprobe_path);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((line = fparseln(fp, NULL, NULL, NULL, 0))) {
|
||||||
|
char cmd[CMD_SIZE], *mod, *args, *set;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fparseln() skips regular UNIX comments only.
|
||||||
|
* This is for modules-load.d(5) compat.
|
||||||
|
*/
|
||||||
|
if (line[0] == ';')
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
/* trim whitespace */
|
||||||
|
mod = strip_line(line);
|
||||||
|
if (!mod[0])
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
/* Finit extension 'set foo bar' */
|
||||||
|
if ((set = fgetval(mod, "set", "= \t"))) {
|
||||||
|
char *val = mod;
|
||||||
|
|
||||||
|
if (!strcmp(set, "noindex")) {
|
||||||
|
index = 0;
|
||||||
|
free(set);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((val = fgetval(set, "index", "= \t"))) {
|
||||||
|
index = atoi(val);
|
||||||
|
free(set);
|
||||||
|
free(val);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((val = fgetval(set, "runlevel", "= \t"))) {
|
||||||
|
free(lvl);
|
||||||
|
lvl = val;
|
||||||
|
free(set);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((val = fgetval(set, "modprobe", "= \t"))) {
|
||||||
|
if (access(val, X_OK)) {
|
||||||
|
warn("%s: cannot use %s", module_path, val);
|
||||||
|
free(set);
|
||||||
|
free(val);
|
||||||
|
free(line);
|
||||||
|
goto skip;
|
||||||
|
} else {
|
||||||
|
free(modprobe_path);
|
||||||
|
modprobe_path = val;
|
||||||
|
}
|
||||||
|
free(set);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unknown 'set' command, ignore. */
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
mod = strtok_r(mod, " ", &args);
|
||||||
|
if (!mod)
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
if (!index)
|
||||||
|
snprintf(cmd, sizeof(cmd), SERVICE_LINE_NOINDEX, mod, lvl, modprobe_path, mod, args);
|
||||||
|
else
|
||||||
|
snprintf(cmd, sizeof(cmd), SERVICE_LINE, mod, index++, lvl, modprobe_path, mod, args);
|
||||||
|
|
||||||
|
dbg("task %s", cmd);
|
||||||
|
service_register(SVC_TYPE_TASK, cmd, global_rlimit, NULL);
|
||||||
|
num++;
|
||||||
|
next:
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
skip:
|
||||||
|
free(modprobe_path);
|
||||||
|
free(lvl);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX: check here for .conf only? */
|
||||||
|
static int module_filter(const struct dirent *d)
|
||||||
|
{
|
||||||
|
if (d->d_type == DT_DIR)
|
||||||
|
return 0;
|
||||||
|
if (d->d_name[0] == '.')
|
||||||
|
return 0; /* skip dot files */
|
||||||
|
if (d->d_name[strlen(d->d_name) - 1] == '~')
|
||||||
|
return 0; /* skip backup files */
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void load(void *arg)
|
static void load(void *arg)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
struct dirent **dentry;
|
||||||
DIR *dirp;
|
|
||||||
struct dirent *direntp;
|
|
||||||
char line[256];
|
|
||||||
int index = 1;
|
int index = 1;
|
||||||
|
int i, num;
|
||||||
|
|
||||||
_d("Scanning " MODULES_LOAD_PATH " for config files ...");
|
dbg("Scanning " MODULES_LOAD_PATH " for config files ...");
|
||||||
|
num = scandir(MODULES_LOAD_PATH, &dentry, module_filter, alphasort);
|
||||||
dirp = opendir(MODULES_LOAD_PATH);
|
if (num > 0) {
|
||||||
if (!dirp) return;
|
for (i = 0; i < num; i++) {
|
||||||
|
index += modules_load(dentry[i]->d_name, index);
|
||||||
while ((direntp = readdir(dirp)))
|
free(dentry[i]);
|
||||||
{
|
|
||||||
char module_path[PATH_MAX];
|
|
||||||
strlcpy(module_path, MODULES_LOAD_PATH "/", sizeof(module_path));
|
|
||||||
strlcat(module_path, direntp->d_name, sizeof(module_path));
|
|
||||||
|
|
||||||
fp = fopen(module_path, "r");
|
|
||||||
if (!fp) continue;
|
|
||||||
|
|
||||||
while (fgets(line, sizeof(line), fp)) {
|
|
||||||
char cmd[CMD_SIZE], *mod, *args;
|
|
||||||
|
|
||||||
mod = strip_line(line);
|
|
||||||
if (!*mod) continue;
|
|
||||||
|
|
||||||
mod = chomp(mod);
|
|
||||||
if (!mod || !*mod) continue;
|
|
||||||
|
|
||||||
mod = strtok_r(mod, " ", &args);
|
|
||||||
|
|
||||||
snprintf(cmd, sizeof(cmd), SERVICE_LINE,
|
|
||||||
index, mod, mod, args, mod);
|
|
||||||
service_register(SVC_TYPE_TASK, cmd, global_rlimit, NULL);
|
|
||||||
|
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
|
free(dentry);
|
||||||
fclose(fp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(dirp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = __FILE__,
|
||||||
.hook[HOOK_BASEFS_UP] = {
|
.hook[HOOK_SVC_PLUGIN] = { .cb = load },
|
||||||
.cb = load
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(plugin_init)
|
||||||
|
|||||||
+245
-57
@@ -1,7 +1,8 @@
|
|||||||
|
|
||||||
/* Netlink plugin for IFUP/IFDN and GW events
|
/* Netlink plugin for IFUP/IFDN and GW events
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009-2011 Mårten Wikström <marten.wikstrom@keystream.se>
|
* Copyright (C) 2009-2011 Mårten Wikström <marten.wikstrom@keystream.se>
|
||||||
* Copyright (C) 2009-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (C) 2009-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -30,34 +31,38 @@
|
|||||||
#include "cond.h"
|
#include "cond.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
#include "service.h"
|
||||||
|
|
||||||
static int nlmsg_validate(struct nlmsghdr *nh, size_t len)
|
#define NL_BUFSZ 4096
|
||||||
{
|
|
||||||
if (!NLMSG_OK(nh, len))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (nh->nlmsg_type == NLMSG_DONE) {
|
struct nl_request {
|
||||||
_d("Done with netlink messages.");
|
struct nlmsghdr nh;
|
||||||
return 1;
|
union {
|
||||||
}
|
struct rtmsg rtm;
|
||||||
|
struct ifinfomsg ifi;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
if (nh->nlmsg_type == NLMSG_ERROR) {
|
static int nl_defidx;
|
||||||
_d("Netlink reports error.");
|
static int nl_ifdown;
|
||||||
return 1;
|
static char *nl_buf;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nl_route(struct nlmsghdr *nlmsg, ssize_t len)
|
static void nl_route(struct nlmsghdr *nlmsg, ssize_t len)
|
||||||
{
|
{
|
||||||
|
char daddr[INET_ADDRSTRLEN];
|
||||||
|
char gaddr[INET_ADDRSTRLEN];
|
||||||
|
struct in_addr ind, ing;
|
||||||
struct rtmsg *r;
|
struct rtmsg *r;
|
||||||
struct rtattr *a;
|
struct rtattr *a;
|
||||||
|
int plen = 0;
|
||||||
|
int dst = 0;
|
||||||
|
int idx = 0;
|
||||||
|
int gw = 0;
|
||||||
int la;
|
int la;
|
||||||
int gw = 0, dst = 0, mask = 0, idx = 0;
|
|
||||||
|
|
||||||
if (nlmsg->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg))) {
|
if (nlmsg->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg))) {
|
||||||
_e("Packet too small or truncated!");
|
errx(1, "Packet too small or truncated!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +70,7 @@ static void nl_route(struct nlmsghdr *nlmsg, ssize_t len)
|
|||||||
a = RTM_RTA(r);
|
a = RTM_RTA(r);
|
||||||
la = RTM_PAYLOAD(nlmsg);
|
la = RTM_PAYLOAD(nlmsg);
|
||||||
if (la >= len) {
|
if (la >= len) {
|
||||||
_e("Packet too large!");
|
errx(1, "Packet too large!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,29 +80,38 @@ static void nl_route(struct nlmsghdr *nlmsg, ssize_t len)
|
|||||||
switch (a->rta_type) {
|
switch (a->rta_type) {
|
||||||
case RTA_GATEWAY:
|
case RTA_GATEWAY:
|
||||||
gw = *((int *)data);
|
gw = *((int *)data);
|
||||||
//_d("GW: 0x%04x", gw);
|
//dbg("GW: 0x%04x", gw);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RTA_DST:
|
case RTA_DST:
|
||||||
dst = *((int *)data);
|
dst = *((int *)data);
|
||||||
mask = r->rtm_dst_len;
|
plen = r->rtm_dst_len;
|
||||||
//_d("MASK: 0x%04x", mask);
|
//dbg("Prefix LEN: 0x%04x", plen);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RTA_OIF:
|
case RTA_OIF:
|
||||||
idx = *((int *)data);
|
idx = *((int *)data);
|
||||||
//_d("IDX: 0x%04x", idx);
|
//dbg("IDX: 0x%04x", idx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
a = RTA_NEXT(a, la);
|
a = RTA_NEXT(a, la);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!dst && !mask) && (gw || idx)) {
|
ind.s_addr = dst;
|
||||||
if (nlmsg->nlmsg_type == RTM_DELROUTE)
|
ing.s_addr = gw;
|
||||||
|
inet_ntop(AF_INET, &ind, daddr, sizeof(daddr));
|
||||||
|
inet_ntop(AF_INET, &ing, gaddr, sizeof(gaddr));
|
||||||
|
dbg("Got gw %s dst/len %s/%d ifindex %d", gaddr, daddr, plen, idx);
|
||||||
|
|
||||||
|
if ((!dst && !plen) && (gw || idx)) {
|
||||||
|
if (nlmsg->nlmsg_type == RTM_DELROUTE) {
|
||||||
cond_clear("net/route/default");
|
cond_clear("net/route/default");
|
||||||
else
|
nl_defidx = 0;
|
||||||
|
} else {
|
||||||
cond_set("net/route/default");
|
cond_set("net/route/default");
|
||||||
|
nl_defidx = idx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,14 +131,14 @@ static int validate_ifname(const char *ifname)
|
|||||||
if (!ifname || !ifname[0])
|
if (!ifname || !ifname[0])
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (strlen(ifname) >= IFNAMSIZ)
|
if (strnlen(ifname, IFNAMSIZ) == IFNAMSIZ)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (strstr(ifname, ".."))
|
if (!strcmp(ifname, ".") || !strcmp(ifname, ".."))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
while (*ifname) {
|
while (*ifname) {
|
||||||
if (*ifname == '/' || isspace(*ifname))
|
if (*ifname == '/' || *ifname == ':' || isspace(*ifname))
|
||||||
return 1;
|
return 1;
|
||||||
ifname++;
|
ifname++;
|
||||||
}
|
}
|
||||||
@@ -132,15 +146,28 @@ static int validate_ifname(const char *ifname)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if this interface was associated with the default route
|
||||||
|
* previously, or if it's been removed. If so, trigger a recheck
|
||||||
|
* of the system default route.
|
||||||
|
*/
|
||||||
|
static void nl_check_default(char *ifname)
|
||||||
|
{
|
||||||
|
int idx = (int)if_nametoindex(ifname);
|
||||||
|
|
||||||
|
if ((nl_defidx > 0 && nl_defidx == idx) || (idx == 0 && errno == ENODEV))
|
||||||
|
nl_ifdown = 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void nl_link(struct nlmsghdr *nlmsg, ssize_t len)
|
static void nl_link(struct nlmsghdr *nlmsg, ssize_t len)
|
||||||
{
|
{
|
||||||
int la;
|
|
||||||
char ifname[IFNAMSIZ + 1];
|
char ifname[IFNAMSIZ + 1];
|
||||||
struct rtattr *a;
|
|
||||||
struct ifinfomsg *i;
|
struct ifinfomsg *i;
|
||||||
|
struct rtattr *a;
|
||||||
|
int la;
|
||||||
|
|
||||||
if (nlmsg->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg))) {
|
if (nlmsg->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg))) {
|
||||||
_e("Packet too small or truncated!");
|
errx(1, "Packet too small or truncated!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +175,7 @@ static void nl_link(struct nlmsghdr *nlmsg, ssize_t len)
|
|||||||
a = (struct rtattr *)((char *)i + NLMSG_ALIGN(sizeof(struct ifinfomsg)));
|
a = (struct rtattr *)((char *)i + NLMSG_ALIGN(sizeof(struct ifinfomsg)));
|
||||||
la = NLMSG_PAYLOAD(nlmsg, sizeof(struct ifinfomsg));
|
la = NLMSG_PAYLOAD(nlmsg, sizeof(struct ifinfomsg));
|
||||||
if (la >= len) {
|
if (la >= len) {
|
||||||
_e("Packet too large!");
|
errx(1, "Packet too large!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +185,7 @@ static void nl_link(struct nlmsghdr *nlmsg, ssize_t len)
|
|||||||
|
|
||||||
strlcpy(ifname, RTA_DATA(a), sizeof(ifname));
|
strlcpy(ifname, RTA_DATA(a), sizeof(ifname));
|
||||||
if (validate_ifname(ifname)) {
|
if (validate_ifname(ifname)) {
|
||||||
_d("Invalid interface name '%s', skipping ...", ifname);
|
dbg("Invalid interface name '%s', skipping ...", ifname);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,55 +195,208 @@ static void nl_link(struct nlmsghdr *nlmsg, ssize_t len)
|
|||||||
* New interface has appeared, or interface flags has changed.
|
* New interface has appeared, or interface flags has changed.
|
||||||
* Check ifi_flags here to see if the interface is UP/DOWN
|
* Check ifi_flags here to see if the interface is UP/DOWN
|
||||||
*/
|
*/
|
||||||
_d("%s: New link, flags 0x%x, change 0x%x", ifname, i->ifi_flags, i->ifi_change);
|
dbg("%s: New link, flags 0x%x, change 0x%x", ifname, i->ifi_flags, i->ifi_change);
|
||||||
net_cond_set(ifname, "exist", 1);
|
net_cond_set(ifname, "exist", 1);
|
||||||
net_cond_set(ifname, "up", i->ifi_flags & IFF_UP);
|
net_cond_set(ifname, "up", i->ifi_flags & IFF_UP);
|
||||||
net_cond_set(ifname, "running", i->ifi_flags & IFF_RUNNING);
|
net_cond_set(ifname, "running", i->ifi_flags & IFF_RUNNING);
|
||||||
|
if (!(i->ifi_flags & IFF_UP) || !(i->ifi_flags & IFF_RUNNING))
|
||||||
|
nl_check_default(ifname);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RTM_DELLINK:
|
case RTM_DELLINK:
|
||||||
/* NOTE: Interface has disappeared, not link down ... */
|
/* NOTE: Interface has disappeared, not link down ... */
|
||||||
_d("%s: Delete link", ifname);
|
dbg("%s: Delete link", ifname);
|
||||||
net_cond_set(ifname, "exist", 0);
|
net_cond_set(ifname, "exist", 0);
|
||||||
net_cond_set(ifname, "up", 0);
|
net_cond_set(ifname, "up", 0);
|
||||||
net_cond_set(ifname, "running", 0);
|
net_cond_set(ifname, "running", 0);
|
||||||
|
nl_check_default(ifname);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RTM_NEWADDR:
|
case RTM_NEWADDR:
|
||||||
_d("%s: New Address", ifname);
|
dbg("%s: New Address", ifname);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RTM_DELADDR:
|
case RTM_DELADDR:
|
||||||
_d("%s: Deconfig Address", ifname);
|
dbg("%s: Deconfig Address", ifname);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_d("%s: Msg 0x%x", ifname, nlmsg->nlmsg_type);
|
dbg("%s: Msg 0x%x", ifname, nlmsg->nlmsg_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nl_callback(void *arg, int sd, int events)
|
static int nl_parse(int sd)
|
||||||
{
|
{
|
||||||
static char buf[4096];
|
while (1) {
|
||||||
struct nlmsghdr *nh;
|
struct nlmsghdr *nh;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
size_t l;
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
while ((len = recv(sd, nl_buf, NL_BUFSZ, 0)) < 0) {
|
||||||
len = recv(sd, buf, sizeof(buf), 0);
|
switch (errno) {
|
||||||
if (len < 0) {
|
case EAGAIN: /* Nothing more right now. */
|
||||||
if (errno != EINTR) /* Signal */
|
return 0;
|
||||||
_pe("recv()");
|
|
||||||
|
case EINTR: /* Signal */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case ENOBUFS: /* netlink(7) */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
err(1, "recv()");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// dbg("recv %zd bytes", len);
|
||||||
|
l = (size_t)len;
|
||||||
|
for (nh = (struct nlmsghdr *)nl_buf; NLMSG_OK(nh, l); nh = NLMSG_NEXT(nh, l)) {
|
||||||
|
struct nlmsgerr *nle;
|
||||||
|
|
||||||
|
switch (nh->nlmsg_type) {
|
||||||
|
case NLMSG_DONE:
|
||||||
|
// dbg("Done with netlink messages.");
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case NLMSG_ERROR:
|
||||||
|
// dbg("Kernel netlink comm. error.");
|
||||||
|
nle = NLMSG_DATA(nh);
|
||||||
|
if (nle) {
|
||||||
|
errno = -nle->error;
|
||||||
|
err(1, "Kernel netlink error %d", errno);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case RTM_NEWROUTE:
|
||||||
|
case RTM_DELROUTE:
|
||||||
|
// dbg("Netlink route ...");
|
||||||
|
nl_route(nh, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTM_NEWLINK:
|
||||||
|
case RTM_DELLINK:
|
||||||
|
// dbg("Netlink link ...");
|
||||||
|
nl_link(nh, len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
warnx("unhandled netlink message, type %d", nh->nlmsg_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nl_request(int sd, unsigned int seq, int type)
|
||||||
|
{
|
||||||
|
struct nl_request *nlr = (struct nl_request *)nl_buf;
|
||||||
|
|
||||||
|
memset(nlr, 0, sizeof(struct nl_request));
|
||||||
|
nlr->nh.nlmsg_type = type;
|
||||||
|
nlr->nh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
|
||||||
|
nlr->nh.nlmsg_seq = seq;
|
||||||
|
nlr->nh.nlmsg_pid = 1;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case RTM_GETROUTE:
|
||||||
|
// dbg("RTM_GETROUTE");
|
||||||
|
nlr->rtm.rtm_family = AF_INET;
|
||||||
|
nlr->rtm.rtm_table = RT_TABLE_MAIN;
|
||||||
|
nlr->nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RTM_GETLINK:
|
||||||
|
// dbg("RTM_GETLINK");
|
||||||
|
nlr->ifi.ifi_family = AF_UNSPEC;
|
||||||
|
nlr->ifi.ifi_change = 0xFFFFFFFF;
|
||||||
|
nlr->nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
warnx("Cannot resync, unhandled message type %d", type);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (send(sd, nlr, nlr->nh.nlmsg_len, 0) < 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return nl_parse(sd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nl_resync_routes(int sd, unsigned int seq)
|
||||||
|
{
|
||||||
|
if (nl_request(sd, seq, RTM_GETROUTE))
|
||||||
|
err(1, "Failed netlink route request");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nl_resync_ifaces(int sd, unsigned int seq)
|
||||||
|
{
|
||||||
|
if (nl_request(sd, seq, RTM_GETLINK))
|
||||||
|
err(1, "Failed netlink link request");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We've potentially lost netlink events, let's resync with kernel.
|
||||||
|
*/
|
||||||
|
static void nl_resync(int all)
|
||||||
|
{
|
||||||
|
unsigned int seq = 0;
|
||||||
|
int sd;
|
||||||
|
|
||||||
|
sd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
|
||||||
|
if (sd < 0) {
|
||||||
|
err(1, "netlink socket");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (nh = (struct nlmsghdr *)buf; !nlmsg_validate(nh, len); nh = NLMSG_NEXT(nh, len)) {
|
if (all) {
|
||||||
//_d("Well formed netlink message received. type %d ...", nh->nlmsg_type);
|
dbg("============================ RESYNC =================================");
|
||||||
if (nh->nlmsg_type == RTM_NEWROUTE || nh->nlmsg_type == RTM_DELROUTE)
|
/* this doesn't update conditions, and thus does not stop services */
|
||||||
nl_route(nh, len);
|
cond_deassert("net/");
|
||||||
else
|
|
||||||
nl_link(nh, len);
|
nl_resync_ifaces(sd, seq++);
|
||||||
|
nl_resync_routes(sd, seq++);
|
||||||
|
|
||||||
|
/* delayed update after we've corrected things */
|
||||||
|
service_step_all(SVC_TYPE_ANY);
|
||||||
|
dbg("=========================== RESYNCED ================================");
|
||||||
|
} else
|
||||||
|
nl_resync_routes(sd, seq++);
|
||||||
|
|
||||||
|
close(sd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nl_callback(void *arg, int sd, int events)
|
||||||
|
{
|
||||||
|
if (nl_parse(sd) < 0) {
|
||||||
|
if (errno == ENOBUFS) { /* netlink(7) */
|
||||||
|
warnx("busy system, resynchronizing with kernel.");
|
||||||
|
nl_resync(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Linux doesn't send route changes when interfaces go down, so
|
||||||
|
* we need to check ourselves, e.g. for loss of default route.
|
||||||
|
*/
|
||||||
|
if (nl_ifdown) {
|
||||||
|
dbg("interface down, checking default route.");
|
||||||
|
if (nl_defidx > 0) {
|
||||||
|
nl_defidx = 0;
|
||||||
|
nl_resync(0);
|
||||||
|
if (nl_defidx <= 0) {
|
||||||
|
cond_clear("net/route/default");
|
||||||
|
nl_defidx = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nl_ifdown = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,22 +416,29 @@ static plugin_t plugin = {
|
|||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(plugin_init)
|
||||||
{
|
{
|
||||||
int sd;
|
|
||||||
struct sockaddr_nl sa;
|
struct sockaddr_nl sa;
|
||||||
|
int sd;
|
||||||
|
|
||||||
sd = socket(AF_NETLINK, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, NETLINK_ROUTE);
|
sd = socket(AF_NETLINK, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, NETLINK_ROUTE);
|
||||||
if (sd < 0) {
|
if (sd < 0) {
|
||||||
_pe("socket()");
|
err(1, "socket()");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&sa, 0, sizeof(sa));
|
memset(&sa, 0, sizeof(sa));
|
||||||
sa.nl_family = AF_NETLINK;
|
sa.nl_family = AF_NETLINK;
|
||||||
sa.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_LINK; // | RTMGRP_NOTIFY | RTMGRP_IPV4_IFADDR;
|
sa.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_LINK;
|
||||||
sa.nl_pid = getpid();
|
sa.nl_pid = getpid();
|
||||||
|
|
||||||
if (bind(sd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
|
if (bind(sd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
|
||||||
_pe("bind()");
|
err(1, "bind()");
|
||||||
|
close(sd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nl_buf = malloc(NL_BUFSZ);
|
||||||
|
if (!nl_buf) {
|
||||||
|
err(1, "malloc()");
|
||||||
close(sd);
|
close(sd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -263,6 +450,7 @@ PLUGIN_INIT(plugin_init)
|
|||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(plugin_exit)
|
||||||
{
|
{
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
|
close(plugin.io.fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+54
-28
@@ -1,7 +1,7 @@
|
|||||||
/* Simple pidfile event monitor for the Finit condition engine
|
/* Simple pidfile event monitor for the Finit condition engine
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2016 Tobias Waldekranz <tobias@waldekranz.com>
|
* Copyright (c) 2015-2016 Tobias Waldekranz <tobias@waldekranz.com>
|
||||||
* Copyright (c) 2016-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -52,7 +52,7 @@ static int pidfile_add_path(struct iwatch *iw, char *path)
|
|||||||
ptr = slash++;
|
ptr = slash++;
|
||||||
slash = strchr(ptr, '/');
|
slash = strchr(ptr, '/');
|
||||||
if (slash) {
|
if (slash) {
|
||||||
_d("Path too deep, skipping.");
|
dbg("Path too deep, skipping.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,41 +71,64 @@ static void pidfile_update_conds(char *dir, char *name, uint32_t mask)
|
|||||||
if (fnmatch("*\\.pid", fn, 0) && fnmatch("*/pid", fn, 0))
|
if (fnmatch("*\\.pid", fn, 0) && fnmatch("*/pid", fn, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_d("path: %s, mask: %08x", fn, mask);
|
dbg("path: %s, mask: %08x", fn, mask);
|
||||||
|
|
||||||
svc = svc_find_by_pidfile(fn);
|
svc = svc_find_by_pidfile(fn);
|
||||||
if (!svc) {
|
if (!svc) {
|
||||||
_d("No matching svc for %s", fn);
|
dbg("No matching svc for %s", fn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_d("Found svc %s for %s with pid %d", svc->name, fn, svc->pid);
|
dbg("Found svc %s for %s with pid %d", svc_ident(svc, NULL, 0), fn, svc->pid);
|
||||||
|
|
||||||
mkcond(svc, cond, sizeof(cond));
|
mkcond(svc, cond, sizeof(cond));
|
||||||
|
|
||||||
if (mask & (IN_CLOSE_WRITE | IN_ATTRIB | IN_MODIFY | IN_MOVED_TO)) {
|
if (mask & (IN_CLOSE_WRITE | IN_ATTRIB | IN_MODIFY | IN_MOVED_TO)) {
|
||||||
svc_started(svc);
|
/*
|
||||||
if (!svc_has_pidfile(svc))
|
* only mark native services as started, the s6 and
|
||||||
|
* systemd style services rely on their respective
|
||||||
|
* readiness notification. Issue #343
|
||||||
|
*/
|
||||||
|
if (svc->notify == SVC_NOTIFY_PID)
|
||||||
|
svc_started(svc);
|
||||||
|
|
||||||
|
if (!svc_has_pidfile(svc)) {
|
||||||
|
dbg("Setting %s PID file to %s", svc->name, fn);
|
||||||
pid_file_set(svc, fn, 1);
|
pid_file_set(svc, fn, 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (svc_is_forking(svc)) {
|
if (svc_is_forking(svc)) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
pid = pid_file_read(pid_file(svc));
|
pid = pid_file_read(fn);
|
||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
cond_clear(cond);
|
/* handle case when service dies immediately */
|
||||||
|
if (!fexist(fn))
|
||||||
|
cond_clear(cond);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Service is not crashing, let's tell state machine! */
|
||||||
|
service_forked(svc);
|
||||||
|
|
||||||
if (pid != svc->pid) {
|
if (pid != svc->pid) {
|
||||||
_d("Forking service %s changed PID from %d to %d",
|
dbg("Forking service %s (cmd %s) changed PID from %d to %d",
|
||||||
svc->cmd, svc->pid, pid);
|
svc_ident(svc, NULL, 0), svc->cmd, svc->pid, pid);
|
||||||
svc->pid = pid;
|
svc->pid = pid;
|
||||||
|
|
||||||
|
/* Complement log in service.c for non-forking services */
|
||||||
|
logit(LOG_CONSOLE | LOG_NOTICE, "Started %s[%d]", svc_ident(svc, NULL, 0), pid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cond_set(cond);
|
if (svc->notify == SVC_NOTIFY_PID)
|
||||||
} else if (mask & IN_DELETE)
|
cond_set(cond);
|
||||||
|
if (svc->notify == SVC_NOTIFY_PID || svc->notify == SVC_NOTIFY_NONE)
|
||||||
|
service_ready(svc, 1);
|
||||||
|
} else if (mask & IN_DELETE) {
|
||||||
cond_clear(cond);
|
cond_clear(cond);
|
||||||
|
if (svc->notify == SVC_NOTIFY_PID)
|
||||||
|
service_ready(svc, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* synthesize events in case of new run dirs */
|
/* synthesize events in case of new run dirs */
|
||||||
@@ -127,7 +150,7 @@ static void pidfile_scandir(struct iwatch *iw, char *dir, int len)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < gl.gl_pathc; i++) {
|
for (i = 0; i < gl.gl_pathc; i++) {
|
||||||
_d("scan found %s", gl.gl_pathv[i]);
|
dbg("scan found %s", gl.gl_pathv[i]);
|
||||||
pidfile_update_conds(dir, gl.gl_pathv[i], IN_CREATE);
|
pidfile_update_conds(dir, gl.gl_pathv[i], IN_CREATE);
|
||||||
}
|
}
|
||||||
globfree(&gl);
|
globfree(&gl);
|
||||||
@@ -142,7 +165,7 @@ static void pidfile_handle_dir(struct iwatch *iw, char *dir, char *name, int mas
|
|||||||
struct iwatch_path *iwp;
|
struct iwatch_path *iwp;
|
||||||
|
|
||||||
paste(path, sizeof(path), dir, name);
|
paste(path, sizeof(path), dir, name);
|
||||||
_d("path: %s", path);
|
dbg("path: %s", path);
|
||||||
|
|
||||||
iwp = iwatch_find_by_path(iw, path);
|
iwp = iwatch_find_by_path(iw, path);
|
||||||
|
|
||||||
@@ -166,7 +189,7 @@ static void pidfile_callback(void *arg, int fd, int events)
|
|||||||
|
|
||||||
sz = read(fd, ev_buf, sizeof(ev_buf) - 1);
|
sz = read(fd, ev_buf, sizeof(ev_buf) - 1);
|
||||||
if (sz <= 0) {
|
if (sz <= 0) {
|
||||||
_pe("invalid inotify event");
|
err(1, "invalid inotify event");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ev_buf[sz] = 0;
|
ev_buf[sz] = 0;
|
||||||
@@ -218,6 +241,9 @@ static void pidfile_reconf(void *arg)
|
|||||||
if (svc_is_changed(svc) || svc_is_starting(svc))
|
if (svc_is_changed(svc) || svc_is_starting(svc))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (svc->notify == SVC_NOTIFY_PID)
|
||||||
|
service_ready(svc, 1);
|
||||||
|
|
||||||
mkcond(svc, cond, sizeof(cond));
|
mkcond(svc, cond, sizeof(cond));
|
||||||
if (cond_get(cond) == COND_ON)
|
if (cond_get(cond) == COND_ON)
|
||||||
continue;
|
continue;
|
||||||
@@ -226,9 +252,9 @@ static void pidfile_reconf(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This will call service_step(), which in turn will schedule itself
|
* This calls service_step(), which in turn schedules itself as
|
||||||
* as long as stepped services change state. Services going from
|
* long as stepped services change state. Services going from
|
||||||
* WAITING to RUNNING will reassert their conditions in that loop,
|
* PAUSED to RUNNING reassert their conditions in that loop,
|
||||||
* which in turn may unlock other services, and so on.
|
* which in turn may unlock other services, and so on.
|
||||||
*/
|
*/
|
||||||
service_step_all(SVC_TYPE_SERVICE | SVC_TYPE_RUNTASK);
|
service_step_all(SVC_TYPE_SERVICE | SVC_TYPE_RUNTASK);
|
||||||
@@ -240,7 +266,7 @@ static void pidfile_init(void *arg)
|
|||||||
char *path;
|
char *path;
|
||||||
|
|
||||||
if (mkpath(pid_runpath(_PATH_CONDPID, piddir, sizeof(piddir)), 0755) && errno != EEXIST) {
|
if (mkpath(pid_runpath(_PATH_CONDPID, piddir, sizeof(piddir)), 0755) && errno != EEXIST) {
|
||||||
_pe("Failed creating %s condition directory, %s", COND_PID, _PATH_CONDPID);
|
err(1, "Failed creating %s condition directory, %s", COND_PID, _PATH_CONDPID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,10 +277,10 @@ static void pidfile_init(void *arg)
|
|||||||
*/
|
*/
|
||||||
path = realpath(_PATH_VARRUN, NULL);
|
path = realpath(_PATH_VARRUN, NULL);
|
||||||
if (!path) {
|
if (!path) {
|
||||||
_d("Failed querying realpath(%s): %s", _PATH_VARRUN, strerror(errno));
|
dbg("Failed querying realpath(%s): %s", _PATH_VARRUN, strerror(errno));
|
||||||
path = realpath("/run", NULL);
|
path = realpath("/run", NULL);
|
||||||
if (!path) {
|
if (!path) {
|
||||||
_e("System does not have %s or /run, aborting.", _PATH_VARRUN);
|
errx(1, "System does not have %s or /run, aborting.", _PATH_VARRUN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,15 +301,15 @@ static void pidfile_init(void *arg)
|
|||||||
*
|
*
|
||||||
* service <net/iface/lo> /sbin/dropbear ...
|
* service <net/iface/lo> /sbin/dropbear ...
|
||||||
*
|
*
|
||||||
* Which provides the <pid/dropbear> condition, will not be set by
|
* This service provides the <pid/dropbear> condition, which will not be
|
||||||
* pidfile.so during `initctl reload` because dropbear is still
|
* set by pidfile.so during `initctl reload` because dropbear is still
|
||||||
* SIGSTP:ed waiting for <net/iface/lo>.
|
* SIGSTP:ed (in state PAUSED) waiting for <net/iface/lo>.
|
||||||
*/
|
*/
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = __FILE__,
|
||||||
.hook[HOOK_BASEFS_UP] = { .cb = pidfile_init },
|
.hook[HOOK_BASEFS_UP] = { .cb = pidfile_init },
|
||||||
.hook[HOOK_SVC_RECONF] = { .cb = pidfile_reconf },
|
.hook[HOOK_SVC_RECONF] = { .cb = pidfile_reconf },
|
||||||
.depends = { "netlink" },
|
.depends = { "netlink" }, /* bootmisc depends on us */
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(plugin_init)
|
||||||
@@ -303,8 +329,8 @@ PLUGIN_INIT(plugin_init)
|
|||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(plugin_exit)
|
||||||
{
|
{
|
||||||
iwatch_exit(&iw_pidfile);
|
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
|
iwatch_exit(&iw_pidfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+13
-7
@@ -1,6 +1,6 @@
|
|||||||
/* Set kernel variables from /etc/sysctl.conf et al
|
/* Set kernel variables from /etc/sysctl.conf et al
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2016-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -22,7 +22,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
#include <lite/lite.h>
|
#ifdef _LIBITE_LITE
|
||||||
|
# include <libite/lite.h>
|
||||||
|
#else
|
||||||
|
# include <lite/lite.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
@@ -30,12 +34,10 @@
|
|||||||
|
|
||||||
static void setup(void *arg)
|
static void setup(void *arg)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
glob_t gl;
|
glob_t gl;
|
||||||
char buf[160];
|
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
_d("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,9 +49,13 @@ static void setup(void *arg)
|
|||||||
glob("/mnt/sysctl.d/*.conf", GLOB_APPEND, NULL, &gl);
|
glob("/mnt/sysctl.d/*.conf", GLOB_APPEND, NULL, &gl);
|
||||||
glob("/etc/sysctl.conf", GLOB_APPEND, NULL, &gl);
|
glob("/etc/sysctl.conf", GLOB_APPEND, NULL, &gl);
|
||||||
if (gl.gl_pathc > 0) {
|
if (gl.gl_pathc > 0) {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < gl.gl_pathc; i++) {
|
for (i = 0; i < gl.gl_pathc; i++) {
|
||||||
snprintf(buf, sizeof(buf), "/sbin/sysctl -e -p %s >/dev/null", gl.gl_pathv[i]);
|
char cmd[160];
|
||||||
run(buf);
|
|
||||||
|
snprintf(cmd, sizeof(cmd), "/sbin/sysctl -e -p %s >/dev/null", gl.gl_pathv[i]);
|
||||||
|
run(cmd, "sysctl");
|
||||||
}
|
}
|
||||||
globfree(&gl);
|
globfree(&gl);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* Setup necessary files for resolvconf
|
/* Setup necessary files for resolvconf
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -21,7 +21,11 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <lite/lite.h>
|
#ifdef _LIBITE_LITE
|
||||||
|
# include <libite/lite.h>
|
||||||
|
#else
|
||||||
|
# include <lite/lite.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
@@ -33,7 +37,7 @@
|
|||||||
*/
|
*/
|
||||||
static void setup(void *arg)
|
static void setup(void *arg)
|
||||||
{
|
{
|
||||||
_d("Setting up the resolver ...");
|
dbg("Setting up the resolver ...");
|
||||||
mkpath("/etc/resolvconf", 0755);
|
mkpath("/etc/resolvconf", 0755);
|
||||||
mkpath("/etc/resolvconf/run", 0755);
|
mkpath("/etc/resolvconf/run", 0755);
|
||||||
mkpath("/var/run/resolvconf", 0755);
|
mkpath("/var/run/resolvconf", 0755);
|
||||||
@@ -41,7 +45,7 @@ static void setup(void *arg)
|
|||||||
|
|
||||||
touch("/etc/resolvconf/run/enable-updates");
|
touch("/etc/resolvconf/run/enable-updates");
|
||||||
chdir("/etc/resolvconf/run/interface");
|
chdir("/etc/resolvconf/run/interface");
|
||||||
run_parts("/etc/resolvconf/update.d", "-i");
|
run_parts("/etc/resolvconf/update.d", "-i", NULL, 0, 0);
|
||||||
chdir("/");
|
chdir("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+42
-11
@@ -1,6 +1,6 @@
|
|||||||
/* Save and restore RTC using hwclock
|
/* Save and restore RTC using hwclock
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -21,17 +21,29 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <linux/rtc.h>
|
#include <linux/rtc.h>
|
||||||
#include <lite/lite.h>
|
#ifdef _LIBITE_LITE
|
||||||
|
# include <libite/lite.h>
|
||||||
|
#else
|
||||||
|
# include <lite/lite.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
|
||||||
/* Kernel RTC driver validates against this date for sanity check */
|
/* Kernel RTC driver validates against this date for sanity check */
|
||||||
#define RTC_TIMESTAMP_BEGIN_2000 946684800LL /* 2000-01-01 00:00:00 */
|
#define RTC_TIMESTAMP_BEGIN_2000 "2000-01-01 00:00:00"
|
||||||
|
#ifdef RTC_TIMESTAMP_CUSTOM
|
||||||
|
static char *rtc_timestamp = RTC_TIMESTAMP_CUSTOM;
|
||||||
|
#else
|
||||||
|
static char *rtc_timestamp = RTC_TIMESTAMP_BEGIN_2000;
|
||||||
|
#endif
|
||||||
|
static time_t rtc_date_fallback = 946684800LL;
|
||||||
|
|
||||||
static void tz_set(char *tz, size_t len)
|
static void tz_set(char *tz, size_t len)
|
||||||
{
|
{
|
||||||
@@ -85,7 +97,7 @@ static void rtc_save(void *arg)
|
|||||||
char tz[128];
|
char tz[128];
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
_d("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,10 +107,10 @@ static void rtc_save(void *arg)
|
|||||||
|
|
||||||
tz_set(tz, sizeof(tz));
|
tz_set(tz, sizeof(tz));
|
||||||
rc = gettimeofday(&tv, NULL);
|
rc = gettimeofday(&tv, NULL);
|
||||||
if (rc < 0 || tv.tv_sec < RTC_TIMESTAMP_BEGIN_2000) {
|
if (rc < 0 || tv.tv_sec < rtc_date_fallback) {
|
||||||
print_desc(NULL, "System clock invalid, not saving to RTC");
|
print_desc(NULL, "System clock invalid, not saving to RTC");
|
||||||
invalid:
|
invalid:
|
||||||
logit(LOG_ERR, "System clock invalid, before 2000-01-01 00:00, not saving to RTC");
|
logit(LOG_ERR, "System clock invalid, before %s, not saving to RTC", rtc_timestamp);
|
||||||
rc = 2;
|
rc = 2;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -127,13 +139,15 @@ static void rtc_restore(void *arg)
|
|||||||
char tz[128];
|
char tz[128];
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
_d("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = rtc_open();
|
fd = rtc_open();
|
||||||
if (fd < 0)
|
if (fd < 0) {
|
||||||
|
logit(LOG_NOTICE, "System has no RTC (missing driver?), skipping restore.");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
tz_set(tz, sizeof(tz));
|
tz_set(tz, sizeof(tz));
|
||||||
if (ioctl(fd, RTC_RD_TIME, &tm) < 0) {
|
if (ioctl(fd, RTC_RD_TIME, &tm) < 0) {
|
||||||
@@ -147,19 +161,29 @@ static void rtc_restore(void *arg)
|
|||||||
invalid:
|
invalid:
|
||||||
logit(LOG_ERR, "Failed restoring system clock from RTC.");
|
logit(LOG_ERR, "Failed restoring system clock from RTC.");
|
||||||
if (EINVAL == errno)
|
if (EINVAL == errno)
|
||||||
logit(LOG_ERR, "RTC time is too old (before 2000-01-01 00:00)");
|
logit(LOG_ERR, "RTC time is too old (before %s)", rtc_timestamp);
|
||||||
else if (ENOENT == errno)
|
else if (ENOENT == errno)
|
||||||
logit(LOG_ERR, "RTC has no previously saved (valid) time.");
|
logit(LOG_ERR, "RTC has no previously saved (valid) time.");
|
||||||
else
|
else
|
||||||
logit(LOG_ERR, "RTC error code %d: %s", errno, strerror(errno));
|
logit(LOG_ERR, "RTC error code %d: %s", errno, strerror(errno));
|
||||||
|
|
||||||
|
/* Been here already? */
|
||||||
|
if (rc)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Attempt to set RTC to a sane value ... */
|
||||||
|
tv.tv_sec = rtc_date_fallback;
|
||||||
|
if (!gmtime_r(&tv.tv_sec, &tm))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
logit(LOG_NOTICE, "Resetting RTC to kernel default, %s.", rtc_timestamp);
|
||||||
rc = 2;
|
rc = 2;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
print_desc(NULL, "Restoring system clock (UTC) from RTC");
|
print_desc(NULL, "Restoring system clock (UTC) from RTC");
|
||||||
tm.tm_isdst = -1; /* Use tzdata to figure it out, please. */
|
tm.tm_isdst = -1; /* Use tzdata to figure it out, please. */
|
||||||
tv.tv_sec = mktime(&tm);
|
tv.tv_sec = mktime(&tm);
|
||||||
if (tv.tv_sec < RTC_TIMESTAMP_BEGIN_2000) {
|
if (tv.tv_sec == (time_t)-1 || tv.tv_sec < rtc_date_fallback) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
@@ -185,6 +209,13 @@ static plugin_t plugin = {
|
|||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(plugin_init)
|
||||||
{
|
{
|
||||||
|
struct tm tm = { 0 };
|
||||||
|
|
||||||
|
if (!strptime(rtc_timestamp, "%Y-%m-%d %H:%M", &tm))
|
||||||
|
rtc_date_fallback = mktime(&tm);
|
||||||
|
else
|
||||||
|
rtc_timestamp = RTC_TIMESTAMP_BEGIN_2000;
|
||||||
|
|
||||||
plugin_register(&plugin);
|
plugin_register(&plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+213
@@ -0,0 +1,213 @@
|
|||||||
|
/* System condition event monitor for the Finit condition engine
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fnmatch.h>
|
||||||
|
#include <glob.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <paths.h>
|
||||||
|
|
||||||
|
#include "finit.h"
|
||||||
|
#include "cond.h"
|
||||||
|
#include "pid.h"
|
||||||
|
#include "plugin.h"
|
||||||
|
#include "iwatch.h"
|
||||||
|
|
||||||
|
static struct iwatch iw_sys;
|
||||||
|
|
||||||
|
|
||||||
|
static int sys_add_path(struct iwatch *iw, char *path)
|
||||||
|
{
|
||||||
|
return iwatch_add(iw, path, IN_ONLYDIR | IN_CLOSE_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unlink conditions with no active task/service, otherwise they may
|
||||||
|
* trigger inadvertently when calling `initctl reload` to activate
|
||||||
|
* a new configuration.
|
||||||
|
*/
|
||||||
|
static void sys_update_conds(char *dir, char *name, uint32_t mask)
|
||||||
|
{
|
||||||
|
char path[256];
|
||||||
|
char *cond;
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
ptr = strrchr(name, '/');
|
||||||
|
if (ptr)
|
||||||
|
snprintf(path, sizeof(path), "%s/%s", dir, ++ptr);
|
||||||
|
else
|
||||||
|
snprintf(path, sizeof(path), "%s/%s", dir, name);
|
||||||
|
|
||||||
|
cond = strstr(path, COND_BASE);
|
||||||
|
if (!cond)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cond += strlen(COND_BASE) + 1;
|
||||||
|
dbg("cond: %s set: %d", cond, (mask & IN_CREATE) ? 1 : 0);
|
||||||
|
if (!cond_update(cond))
|
||||||
|
unlink(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* synthesize events in case of new run dirs */
|
||||||
|
static void sys_scandir(struct iwatch *iw, char *dir, int len)
|
||||||
|
{
|
||||||
|
glob_t gl;
|
||||||
|
size_t i;
|
||||||
|
char path[len + 6];
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "%s/*", dir);
|
||||||
|
rc = glob(path, GLOB_NOSORT, NULL, &gl);
|
||||||
|
if (rc && rc != GLOB_NOMATCH)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < gl.gl_pathc; i++) {
|
||||||
|
dbg("scan found %s", gl.gl_pathv[i]);
|
||||||
|
sys_update_conds(dir, gl.gl_pathv[i], IN_CREATE);
|
||||||
|
}
|
||||||
|
globfree(&gl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* create/remove sub-directory in monitored directory
|
||||||
|
*/
|
||||||
|
static void sys_handle_dir(struct iwatch *iw, char *dir, char *name, int mask)
|
||||||
|
{
|
||||||
|
char path[strlen(dir) + strlen(name) + 2];
|
||||||
|
struct iwatch_path *iwp;
|
||||||
|
|
||||||
|
paste(path, sizeof(path), dir, name);
|
||||||
|
dbg("path: %s", path);
|
||||||
|
|
||||||
|
iwp = iwatch_find_by_path(iw, path);
|
||||||
|
|
||||||
|
if (mask & IN_CREATE) {
|
||||||
|
if (!iwp) {
|
||||||
|
if (!sys_add_path(iw, path))
|
||||||
|
sys_scandir(iw, path, sizeof(path));
|
||||||
|
}
|
||||||
|
} else if (mask & IN_DELETE) {
|
||||||
|
if (iwp)
|
||||||
|
iwatch_del(&iw_sys, iwp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sys_callback(void *arg, int fd, int events)
|
||||||
|
{
|
||||||
|
static char ev_buf[8 *(sizeof(struct inotify_event) + NAME_MAX + 1) + 1];
|
||||||
|
struct inotify_event *ev;
|
||||||
|
ssize_t sz;
|
||||||
|
size_t off;
|
||||||
|
|
||||||
|
sz = read(fd, ev_buf, sizeof(ev_buf) - 1);
|
||||||
|
if (sz <= 0) {
|
||||||
|
err(1, "invalid inotify event");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ev_buf[sz] = 0;
|
||||||
|
|
||||||
|
for (off = 0; off < (size_t)sz; off += sizeof(*ev) + ev->len) {
|
||||||
|
struct iwatch_path *iwp;
|
||||||
|
|
||||||
|
if (off + sizeof(*ev) > (size_t)sz)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ev = (struct inotify_event *)&ev_buf[off];
|
||||||
|
if (off + sizeof(*ev) + ev->len > (size_t)sz)
|
||||||
|
break;
|
||||||
|
|
||||||
|
dbg("name %s, event: 0x%08x", ev->name, ev->mask);
|
||||||
|
if (!ev->mask)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Find base path for this event */
|
||||||
|
iwp = iwatch_find_by_wd(&iw_sys, ev->wd);
|
||||||
|
if (!iwp)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ev->mask & IN_ISDIR) {
|
||||||
|
sys_handle_dir(&iw_sys, iwp->path, ev->name, ev->mask);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev->mask & (IN_CREATE | IN_DELETE))
|
||||||
|
sys_update_conds(iwp->path, ev->name, ev->mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sys_init(void *arg)
|
||||||
|
{
|
||||||
|
char sysdir[MAX_ARG_LEN];
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
mkpath(_PATH_COND, 0755);
|
||||||
|
if (mkpath(pid_runpath(_PATH_CONDSYS, sysdir, sizeof(sysdir)), 0755) && errno != EEXIST) {
|
||||||
|
err(1, "Failed creating %s condition directory, %s", COND_SYS, _PATH_CONDSYS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = realpath(_PATH_CONDSYS, NULL);
|
||||||
|
if (!path) {
|
||||||
|
err(1, "Cannot figure out real path to %s, aborting", _PATH_CONDSYS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iwatch_add(&iw_sys, path, IN_ONLYDIR))
|
||||||
|
iwatch_exit(&iw_sys);
|
||||||
|
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugin_t plugin = {
|
||||||
|
.name = __FILE__,
|
||||||
|
.hook[HOOK_BASEFS_UP] = { .cb = sys_init },
|
||||||
|
.depends = { "bootmisc", },
|
||||||
|
};
|
||||||
|
|
||||||
|
PLUGIN_INIT(plugin_init)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = iwatch_init(&iw_sys);
|
||||||
|
if (fd < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
plugin.io.fd = fd;
|
||||||
|
plugin.io.cb = sys_callback;
|
||||||
|
plugin.io.flags = PLUGIN_IO_READ;
|
||||||
|
|
||||||
|
plugin_register(&plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
PLUGIN_EXIT(plugin_exit)
|
||||||
|
{
|
||||||
|
plugin_unregister(&plugin);
|
||||||
|
iwatch_exit(&iw_sys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local Variables:
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* c-file-style: "linux"
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
+12
-9
@@ -1,7 +1,7 @@
|
|||||||
/* Optional TTY Watcher, used to catch new TTYs that are discovered, e.g., USB
|
/* Optional TTY Watcher, used to catch new TTYs that are discovered, e.g., USB
|
||||||
*
|
*
|
||||||
* Copyright (c) 2013 Mattias Walström <lazzer@gmail.com>
|
* Copyright (c) 2013 Mattias Walström <lazzer@gmail.com>
|
||||||
* Copyright (c) 2013-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2013-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -27,7 +27,11 @@
|
|||||||
#include <unistd.h> /* read() */
|
#include <unistd.h> /* read() */
|
||||||
#include <sys/inotify.h>
|
#include <sys/inotify.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <lite/lite.h>
|
#ifdef _LIBITE_LITE
|
||||||
|
# include <libite/lite.h>
|
||||||
|
#else
|
||||||
|
# include <lite/lite.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
@@ -51,7 +55,7 @@ static void setup(void)
|
|||||||
|
|
||||||
plugin.io.fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
plugin.io.fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||||
if (-1 == plugin.io.fd || inotify_add_watch(plugin.io.fd, "/dev", IN_CREATE | IN_DELETE) < 0)
|
if (-1 == plugin.io.fd || inotify_add_watch(plugin.io.fd, "/dev", IN_CREATE | IN_DELETE) < 0)
|
||||||
_pe("Failed starting TTY watcher");
|
err(1, "Failed starting TTY watcher");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_tty(char *tty, size_t len, int creat)
|
static void do_tty(char *tty, size_t len, int creat)
|
||||||
@@ -63,10 +67,10 @@ static void do_tty(char *tty, size_t len, int creat)
|
|||||||
svc = svc_find_by_tty(name);
|
svc = svc_find_by_tty(name);
|
||||||
if (svc) {
|
if (svc) {
|
||||||
if (svc_is_blocked(svc) && creat) {
|
if (svc_is_blocked(svc) && creat) {
|
||||||
_d("%s: blocked, re-enabling", svc_ident(svc, NULL, 0));
|
dbg("%s: blocked, re-enabling", svc_ident(svc, NULL, 0));
|
||||||
svc_start(svc);
|
svc_start(svc);
|
||||||
} else if (svc->pid) {
|
} else if (svc->pid) {
|
||||||
_d("%s: missing ...", svc_ident(svc, NULL, 0));
|
dbg("%s: missing ...", svc_ident(svc, NULL, 0));
|
||||||
svc_missing(svc);
|
svc_missing(svc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +87,7 @@ static void tty_watcher(void *arg, int fd, int events)
|
|||||||
|
|
||||||
sz = read(fd, ev_buf, sizeof(ev_buf) - 1);
|
sz = read(fd, ev_buf, sizeof(ev_buf) - 1);
|
||||||
if (sz <= 0) {
|
if (sz <= 0) {
|
||||||
_pe("invalid inotify event");
|
err(1, "invalid inotify event");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ev_buf[sz] = 0;
|
ev_buf[sz] = 0;
|
||||||
@@ -99,7 +103,7 @@ static void tty_watcher(void *arg, int fd, int events)
|
|||||||
if (!ev->mask)
|
if (!ev->mask)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_d("tty %s, event: 0x%08x", ev->name, ev->mask);
|
dbg("tty %s, event: 0x%08x", ev->name, ev->mask);
|
||||||
do_tty(ev->name, ev->len, ev->mask & IN_CREATE);
|
do_tty(ev->name, ev->len, ev->mask & IN_CREATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,10 +116,9 @@ PLUGIN_INIT(plugin_init)
|
|||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(plugin_exit)
|
||||||
{
|
{
|
||||||
|
plugin_unregister(&plugin);
|
||||||
if (plugin.io.fd)
|
if (plugin.io.fd)
|
||||||
close(plugin.io.fd);
|
close(plugin.io.fd);
|
||||||
|
|
||||||
plugin_unregister(&plugin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+75
-8
@@ -1,6 +1,6 @@
|
|||||||
/* Setup random seed
|
/* Setup and save random seed at boot/shutdown
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -22,21 +22,36 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h> /* gettimeofday() */
|
#include <sys/time.h> /* gettimeofday() */
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <lite/lite.h>
|
#ifdef _LIBITE_LITE
|
||||||
|
# include <libite/lite.h>
|
||||||
|
#else
|
||||||
|
# include <lite/lite.h>
|
||||||
|
#endif
|
||||||
|
#include <linux/random.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
|
||||||
|
#ifndef RANDOM_BYTES
|
||||||
|
#define RANDOM_BYTES (32*1024)
|
||||||
|
#endif
|
||||||
|
|
||||||
static void setup(void *arg)
|
static void setup(void *arg)
|
||||||
{
|
{
|
||||||
#ifdef RANDOMSEED
|
#ifdef RANDOMSEED
|
||||||
|
struct rand_pool_info *rpi;
|
||||||
|
ssize_t len = 0;
|
||||||
|
int rc = -1;
|
||||||
|
int fd, err;
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
_d("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,8 +81,60 @@ static void setup(void *arg)
|
|||||||
umask(prev);
|
umask(prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
print_desc("Initializing random number generator", NULL);
|
print_desc("Seeding random number generator", NULL);
|
||||||
print_result(512 != copyfile(RANDOMSEED, "/dev/urandom", 0, 0));
|
|
||||||
|
/*
|
||||||
|
* Simply copying our saved entropy to /dev/urandom doesn't
|
||||||
|
* increment the kernel "entropy count", instead we must use
|
||||||
|
* the ioctl below.
|
||||||
|
*/
|
||||||
|
fd = open(RANDOMSEED, O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
goto fallback;
|
||||||
|
|
||||||
|
rpi = malloc(sizeof(*rpi) + RANDOM_BYTES);
|
||||||
|
if (!rpi) {
|
||||||
|
close(fd);
|
||||||
|
goto fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
ssize_t num;
|
||||||
|
|
||||||
|
num = read(fd, &rpi->buf[len], RANDOM_BYTES - len);
|
||||||
|
if (num <= 0) {
|
||||||
|
if (num == -1 && errno == EINTR)
|
||||||
|
continue;
|
||||||
|
if (len > 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
free(rpi);
|
||||||
|
goto fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
len += num;
|
||||||
|
} while (len < RANDOM_BYTES);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
fd = open("/dev/urandom", O_WRONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
free(rpi);
|
||||||
|
goto fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
rpi->buf_size = len;
|
||||||
|
rpi->entropy_count = len * 8;
|
||||||
|
rc = ioctl(fd, RNDADDENTROPY, rpi);
|
||||||
|
err = errno;
|
||||||
|
close(fd);
|
||||||
|
free(rpi);
|
||||||
|
if (rc < 0)
|
||||||
|
logit(LOG_ERR, "Failed adding entropy to kernel random pool: %s", strerror(err));
|
||||||
|
print_result(rc < 0);
|
||||||
|
return;
|
||||||
|
fallback:
|
||||||
|
print_result(512 > copyfile(RANDOMSEED, "/dev/urandom", 0, 0));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,14 +144,14 @@ static void save(void *arg)
|
|||||||
mode_t prev;
|
mode_t prev;
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
_d("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = umask(077);
|
prev = umask(077);
|
||||||
|
|
||||||
print_desc("Saving random seed", NULL);
|
print_desc("Saving random seed", NULL);
|
||||||
print_result(512 != copyfile("/dev/urandom", RANDOMSEED, 512, 0));
|
print_result(RANDOM_BYTES != copyfile("/dev/urandom", RANDOMSEED, RANDOM_BYTES, 0));
|
||||||
|
|
||||||
umask(prev);
|
umask(prev);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+11
-7
@@ -1,6 +1,6 @@
|
|||||||
/* User-defined condtion event monitor for the Finit condition engine
|
/* User-defined condition event monitor for the Finit condition engine
|
||||||
*
|
*
|
||||||
* Copyright (c) 2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2021-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -52,7 +52,7 @@ static void usr_callback(void *arg, int fd, int events)
|
|||||||
|
|
||||||
sz = read(fd, ev_buf, sizeof(ev_buf) - 1);
|
sz = read(fd, ev_buf, sizeof(ev_buf) - 1);
|
||||||
if (sz <= 0) {
|
if (sz <= 0) {
|
||||||
_pe("invalid inotify event");
|
err(1, "invalid inotify event");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ev_buf[sz] = 0;
|
ev_buf[sz] = 0;
|
||||||
@@ -65,7 +65,7 @@ static void usr_callback(void *arg, int fd, int events)
|
|||||||
if (off + sizeof(*ev) + ev->len > (size_t)sz)
|
if (off + sizeof(*ev) + ev->len > (size_t)sz)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
_d("name %s, event: 0x%08x", ev->name, ev->mask);
|
dbg("name %s, event: 0x%08x", ev->name, ev->mask);
|
||||||
if (!ev->mask)
|
if (!ev->mask)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -84,24 +84,28 @@ static void usr_init(void *arg)
|
|||||||
char usrdir[MAX_ARG_LEN];
|
char usrdir[MAX_ARG_LEN];
|
||||||
char *path;
|
char *path;
|
||||||
|
|
||||||
|
mkpath(_PATH_COND, 0755);
|
||||||
if (mkpath(pid_runpath(_PATH_CONDUSR, usrdir, sizeof(usrdir)), 0755) && errno != EEXIST) {
|
if (mkpath(pid_runpath(_PATH_CONDUSR, usrdir, sizeof(usrdir)), 0755) && errno != EEXIST) {
|
||||||
_pe("Failed creating %s condition directory, %s", COND_USR, _PATH_CONDUSR);
|
err(1, "Failed creating %s condition directory, %s", COND_USR, _PATH_CONDUSR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
path = realpath(_PATH_CONDUSR, NULL);
|
path = realpath(_PATH_CONDUSR, NULL);
|
||||||
if (!path) {
|
if (!path) {
|
||||||
_pe("Cannot figure out real path to %s, aborting", _PATH_CONDUSR);
|
err(1, "Cannot figure out real path to %s, aborting", _PATH_CONDUSR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iwatch_add(&iw_usr, path, IN_ONLYDIR))
|
if (iwatch_add(&iw_usr, path, IN_ONLYDIR))
|
||||||
iwatch_exit(&iw_usr);
|
iwatch_exit(&iw_usr);
|
||||||
|
|
||||||
|
free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = __FILE__,
|
||||||
.hook[HOOK_BASEFS_UP] = { .cb = usr_init },
|
.hook[HOOK_BASEFS_UP] = { .cb = usr_init },
|
||||||
|
.depends = { "bootmisc", },
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(plugin_init)
|
||||||
@@ -121,8 +125,8 @@ PLUGIN_INIT(plugin_init)
|
|||||||
|
|
||||||
PLUGIN_EXIT(plugin_exit)
|
PLUGIN_EXIT(plugin_exit)
|
||||||
{
|
{
|
||||||
iwatch_exit(&iw_usr);
|
|
||||||
plugin_unregister(&plugin);
|
plugin_unregister(&plugin);
|
||||||
|
iwatch_exit(&iw_usr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+10
-35
@@ -1,6 +1,6 @@
|
|||||||
/* Console setup (for X)
|
/* Console setup (for X)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2012-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -24,7 +24,11 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <lite/lite.h>
|
#ifdef _LIBITE_LITE
|
||||||
|
# include <libite/lite.h>
|
||||||
|
#else
|
||||||
|
# include <lite/lite.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
@@ -32,47 +36,18 @@
|
|||||||
|
|
||||||
static void setup(void *arg)
|
static void setup(void *arg)
|
||||||
{
|
{
|
||||||
const char *username = "nobody";
|
|
||||||
char line[LINE_SIZE];
|
|
||||||
mode_t prev;
|
|
||||||
#ifdef PAM_CONSOLE
|
|
||||||
int fd;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (rescue) {
|
if (rescue) {
|
||||||
_d("Skipping %s plugin in rescue mode.", __FILE__);
|
dbg("Skipping %s plugin in rescue mode.", __FILE__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = umask(0);
|
if (fexist("/var/run/console/console.lock") && which("pam_console_apply"))
|
||||||
|
run("pam_console_apply", "pam-console");
|
||||||
makedir("/var/run/console", 01777);
|
|
||||||
snprintf(line, sizeof(line), "/var/run/console/%s", username);
|
|
||||||
touch(line);
|
|
||||||
|
|
||||||
#ifdef PAM_CONSOLE
|
|
||||||
if ((fd = open("/var/run/console/console.lock", O_CREAT|O_WRONLY|O_TRUNC, 0644)) >= 0) {
|
|
||||||
write(fd, username, strlen(username));
|
|
||||||
close(fd);
|
|
||||||
run("pam_console_apply");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
makedir("/tmp/.X11-unix", 01777);
|
|
||||||
makedir("/tmp/.ICE-unix", 01777);
|
|
||||||
|
|
||||||
if (whichp("restorecon"))
|
|
||||||
run("restorecon /tmp/.ICE-unix /tmp/.X11-unix");
|
|
||||||
|
|
||||||
umask(prev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static plugin_t plugin = {
|
static plugin_t plugin = {
|
||||||
.name = __FILE__,
|
.name = __FILE__,
|
||||||
.hook[HOOK_NETWORK_UP] = {
|
.hook[HOOK_SVC_PLUGIN] = { .cb = setup },
|
||||||
.cb = setup
|
|
||||||
},
|
|
||||||
.depends = { "bootmisc", }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PLUGIN_INIT(plugin_init)
|
PLUGIN_INIT(plugin_init)
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
.deps/*
|
.deps/*
|
||||||
finit
|
finit
|
||||||
|
getty
|
||||||
initctl
|
initctl
|
||||||
|
keventd
|
||||||
logit
|
logit
|
||||||
reboot
|
reboot
|
||||||
|
runparts
|
||||||
sulogin
|
sulogin
|
||||||
watchdogd
|
watchdogd
|
||||||
Makefile
|
Makefile
|
||||||
|
|||||||
+37
-9
@@ -8,39 +8,65 @@ AM_LDFLAGS = -export-dynamic
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
sbin_PROGRAMS = finit initctl
|
sbin_PROGRAMS = finit initctl
|
||||||
pkglibexec_PROGRAMS = logit sulogin
|
pkglibexec_PROGRAMS = getty logit runparts
|
||||||
|
if SULOGIN
|
||||||
|
pkglibexec_PROGRAMS += sulogin
|
||||||
|
endif
|
||||||
|
if KEVENTD
|
||||||
|
pkglibexec_PROGRAMS += keventd
|
||||||
|
endif
|
||||||
|
if WATCHDOGD
|
||||||
|
pkglibexec_PROGRAMS += watchdogd
|
||||||
|
endif
|
||||||
|
|
||||||
|
dist_pkglibexec_SCRIPTS = coldplug
|
||||||
|
|
||||||
finit_pkglibdir = $(pkglibdir)
|
finit_pkglibdir = $(pkglibdir)
|
||||||
finit_pkglib_SCRIPTS = rescue.conf sample.conf
|
finit_pkglib_SCRIPTS = rescue.conf sample.conf
|
||||||
|
|
||||||
|
getty_SOURCES = finit.h getty.c helpers.h logrotate.c stty.c utmp-api.c utmp-api.h
|
||||||
|
getty_CFLAGS = -W -Wall -Wextra -std=gnu99
|
||||||
|
getty_CFLAGS += $(lite_CFLAGS)
|
||||||
|
getty_LDADD = $(lite_LIBS)
|
||||||
|
|
||||||
|
keventd_SOURCES = keventd.c iwatch.c iwatch.h util.c util.h
|
||||||
|
keventd_CFLAGS = -W -Wall -Wextra -std=gnu99
|
||||||
|
keventd_CFLAGS += $(lite_CFLAGS)
|
||||||
|
keventd_LDADD = $(lite_LIBS)
|
||||||
|
|
||||||
|
runparts_SOURCES = runparts.c
|
||||||
|
runparts_CFLAGS = -W -Wall -Wextra -std=gnu99
|
||||||
|
runparts_CFLAGS += $(lite_CFLAGS)
|
||||||
|
runparts_LDADD = $(lite_LIBS)
|
||||||
|
|
||||||
sulogin_SOURCES = sulogin.c
|
sulogin_SOURCES = sulogin.c
|
||||||
sulogin_CFLAGS = -W -Wall -Wextra -std=gnu99
|
sulogin_CFLAGS = -W -Wall -Wextra -std=gnu99
|
||||||
sulogin_LDADD = -lcrypt
|
sulogin_LDADD = -lcrypt
|
||||||
|
|
||||||
if WATCHDOGD
|
|
||||||
pkglibexec_PROGRAMS += watchdogd
|
|
||||||
endif
|
|
||||||
|
|
||||||
logit_SOURCES = logit.c logrotate.c
|
logit_SOURCES = logit.c logrotate.c
|
||||||
logit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
logit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
||||||
logit_CFLAGS += $(lite_CFLAGS)
|
logit_CFLAGS += $(lite_CFLAGS)
|
||||||
logit_LDADD = $(lite_LIBS)
|
logit_LDADD = $(lite_LIBS)
|
||||||
|
|
||||||
finit_SOURCES = api.c cgroup.c cgroup.h \
|
finit_SOURCES = api.c cgroup.c cgroup.h \
|
||||||
|
client.c client.h \
|
||||||
cond.c cond-w.c cond.h \
|
cond.c cond-w.c cond.h \
|
||||||
conf.c conf.h \
|
conf.c conf.h \
|
||||||
|
devmon.c devmon.h \
|
||||||
exec.c finit.c finit.h \
|
exec.c finit.c finit.h \
|
||||||
getty.c stty.c \
|
stty.c \
|
||||||
helpers.c helpers.h \
|
helpers.c helpers.h \
|
||||||
iwatch.c iwatch.h \
|
iwatch.c iwatch.h \
|
||||||
log.c log.h \
|
log.c log.h \
|
||||||
mdadm.c mount.c \
|
mdadm.c mount.c \
|
||||||
pid.c pid.h \
|
pid.c pid.h \
|
||||||
plugin.c plugin.h private.h \
|
plugin.c plugin.h private.h \
|
||||||
schedule.c schedule.h \
|
runparts.c schedule.c schedule.h \
|
||||||
service.c service.h \
|
service.c service.h \
|
||||||
sig.c sig.h \
|
sig.c sig.h \
|
||||||
sm.c sm.h \
|
sm.c sm.h \
|
||||||
svc.c svc.h \
|
svc.c svc.h \
|
||||||
|
tmpfiles.c tmpfiles.h \
|
||||||
tty.c tty.h \
|
tty.c tty.h \
|
||||||
util.c util.h \
|
util.c util.h \
|
||||||
utmp-api.c utmp-api.h
|
utmp-api.c utmp-api.h
|
||||||
@@ -48,8 +74,10 @@ if LOGROTATE
|
|||||||
finit_SOURCES += logrotate.c
|
finit_SOURCES += logrotate.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
pkginclude_HEADERS = cgroup.h cond.h finit.h helpers.h log.h plugin.h svc.h
|
pkginclude_HEADERS = cgroup.h cond.h conf.h finit.h helpers.h log.h \
|
||||||
|
plugin.h svc.h service.h
|
||||||
|
|
||||||
|
finit_CPPFLAGS = $(AM_CPPFLAGS) -D__FINIT__
|
||||||
finit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
finit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
||||||
finit_CFLAGS += $(lite_CFLAGS) $(uev_CFLAGS)
|
finit_CFLAGS += $(lite_CFLAGS) $(uev_CFLAGS)
|
||||||
finit_LDADD = $(lite_LIBS) $(uev_LIBS)
|
finit_LDADD = $(lite_LIBS) $(uev_LIBS)
|
||||||
@@ -61,7 +89,7 @@ endif
|
|||||||
|
|
||||||
initctl_SOURCES = initctl.c initctl.h cgutil.c cgutil.h \
|
initctl_SOURCES = initctl.c initctl.h cgutil.c cgutil.h \
|
||||||
client.c client.h cond.c cond.h reboot.c \
|
client.c client.h cond.c cond.h reboot.c \
|
||||||
serv.c serv.h svc.h util.c util.h
|
serv.c serv.h svc.h util.c util.h log.h
|
||||||
initctl_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
initctl_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99
|
||||||
initctl_CFLAGS += $(lite_CFLAGS) $(uev_CFLAGS)
|
initctl_CFLAGS += $(lite_CFLAGS) $(uev_CFLAGS)
|
||||||
initctl_LDADD = $(lite_LIBS) $(uev_LIBS)
|
initctl_LDADD = $(lite_LIBS) $(uev_LIBS)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* External client API, using UNIX domain socket.
|
/* External client API, using UNIX domain socket.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -21,6 +21,8 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "config.h" /* Generated by configure script */
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -29,10 +31,13 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <lite/lite.h>
|
#ifdef _LIBITE_LITE
|
||||||
|
# include <libite/lite.h>
|
||||||
|
#else
|
||||||
|
# include <lite/lite.h>
|
||||||
|
#endif
|
||||||
#include <uev/uev.h>
|
#include <uev/uev.h>
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "cond.h"
|
#include "cond.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
@@ -40,36 +45,40 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
#include "sig.h"
|
#include "schedule.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
|
#include "sig.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
extern svc_t *wdog;
|
|
||||||
static uev_t api_watcher;
|
static uev_t api_watcher;
|
||||||
|
|
||||||
static int call(int (*action)(svc_t *), char *buf, size_t len)
|
static int call(int (*action)(svc_t *, void *), char *buf, size_t len)
|
||||||
{
|
{
|
||||||
return svc_parse_jobstr(buf, len, action, NULL);
|
return svc_parse_jobstr(buf, len, NULL, action, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stop(svc_t *svc)
|
static int stop(svc_t *svc, void *user_data)
|
||||||
{
|
{
|
||||||
if (!svc)
|
if (!svc)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
service_timeout_cancel(svc);
|
||||||
svc_stop(svc);
|
svc_stop(svc);
|
||||||
service_step(svc);
|
service_step(svc);
|
||||||
|
service_step_all(SVC_TYPE_ANY);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int start(svc_t *svc)
|
static int start(svc_t *svc, void *user_data)
|
||||||
{
|
{
|
||||||
if (!svc)
|
if (!svc)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
service_timeout_cancel(svc);
|
||||||
svc_start(svc);
|
svc_start(svc);
|
||||||
service_step(svc);
|
service_step(svc);
|
||||||
|
service_step_all(SVC_TYPE_ANY);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -79,25 +88,30 @@ static int start(svc_t *svc)
|
|||||||
* responsibility of initctl to do. Otherwise we'd block PID 1,
|
* responsibility of initctl to do. Otherwise we'd block PID 1,
|
||||||
* or introduce some nasty race conditions.
|
* or introduce some nasty race conditions.
|
||||||
*/
|
*/
|
||||||
static int restart(svc_t *svc)
|
static int restart(svc_t *svc, void *user_data)
|
||||||
{
|
{
|
||||||
if (!svc)
|
if (!svc)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
svc_mark_dirty(svc);
|
if (!svc_is_running(svc))
|
||||||
svc_start(svc);
|
return start(svc, user_data);
|
||||||
|
|
||||||
|
service_timeout_cancel(svc);
|
||||||
|
service_stop(svc);
|
||||||
service_step(svc);
|
service_step(svc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int reload(svc_t *svc)
|
static int reload(svc_t *svc, void *user_data)
|
||||||
{
|
{
|
||||||
if (!svc)
|
if (!svc)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (svc_is_blocked(svc))
|
if (svc_is_blocked(svc))
|
||||||
svc_start(svc);
|
svc_start(svc);
|
||||||
|
else
|
||||||
|
service_timeout_cancel(svc);
|
||||||
|
|
||||||
svc_mark_dirty(svc);
|
svc_mark_dirty(svc);
|
||||||
service_step(svc);
|
service_step(svc);
|
||||||
@@ -110,8 +124,28 @@ static int do_start (char *buf, size_t len) { return call(start, buf, len); }
|
|||||||
static int do_restart(char *buf, size_t len) { return call(restart, buf, len); }
|
static int do_restart(char *buf, size_t len) { return call(restart, buf, len); }
|
||||||
static int do_reload (char *buf, size_t len) { return call(reload, buf, len); }
|
static int do_reload (char *buf, size_t len) { return call(reload, buf, len); }
|
||||||
|
|
||||||
|
static int do_signal_svc(svc_t *svc, void *user_data)
|
||||||
|
{
|
||||||
|
int signo;
|
||||||
|
|
||||||
|
if (!svc || !user_data || !svc_is_running(svc))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
signo = *(int *)user_data;
|
||||||
|
return !!kill(svc->pid, signo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_signal(char *buf, size_t len, int sig)
|
||||||
|
{
|
||||||
|
/* Sanity check: do we know this signal? */
|
||||||
|
if (!*sig2str(sig))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return svc_parse_jobstr(buf, len, &sig, do_signal_svc, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static char query_buf[368];
|
static char query_buf[368];
|
||||||
static int missing(char *job, char *id)
|
static int missing(char *job, char *id, void *user_data)
|
||||||
{
|
{
|
||||||
char buf[20];
|
char buf[20];
|
||||||
|
|
||||||
@@ -129,7 +163,7 @@ static int missing(char *job, char *id)
|
|||||||
static int do_query(char *buf, size_t len)
|
static int do_query(char *buf, size_t len)
|
||||||
{
|
{
|
||||||
query_buf[0] = 0;
|
query_buf[0] = 0;
|
||||||
if (svc_parse_jobstr(buf, len, NULL, missing)) {
|
if (svc_parse_jobstr(buf, len, NULL, NULL, missing)) {
|
||||||
memcpy(buf, query_buf, len);
|
memcpy(buf, query_buf, len);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -173,70 +207,93 @@ static svc_t *do_find(char *buf, size_t len)
|
|||||||
if (!id)
|
if (!id)
|
||||||
return svc_named_iterator(&iter, 1, input);
|
return svc_named_iterator(&iter, 1, input);
|
||||||
|
|
||||||
return svc_find_by_nameid(input, id);
|
return svc_find(input, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static svc_t *do_find_byc(char *buf, size_t len)
|
static svc_t *do_find_byc(char *buf, size_t len)
|
||||||
{
|
{
|
||||||
svc_t *svc, *iter = NULL;
|
|
||||||
char *input;
|
char *input;
|
||||||
|
|
||||||
input = sanitize(buf, len);
|
input = sanitize(buf, len);
|
||||||
if (!input) {
|
if (!input) {
|
||||||
_d("Invalid input");
|
dbg("Invalid input");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
|
return svc_find_by_cond(input);
|
||||||
char cond[MAX_COND_LEN];
|
|
||||||
|
|
||||||
mkcond(svc, cond, sizeof(cond));
|
|
||||||
_d("Comparing input %s with cond %s", input, cond);
|
|
||||||
if (string_compare(cond, input))
|
|
||||||
return svc;
|
|
||||||
}
|
|
||||||
|
|
||||||
_d("None found");
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_reboot(int cmd, char *buf, size_t len)
|
static void bypass_shutdown(void *);
|
||||||
|
struct wq emergency = { .cb = bypass_shutdown };
|
||||||
|
|
||||||
|
static void bypass_shutdown(void *unused)
|
||||||
|
{
|
||||||
|
cprintf("TIMEOUT TIMEOUT SHUTTING DOWN NOW!!\n");
|
||||||
|
do_shutdown(halt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_reboot(int cmd, int timeout, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
int rc = 1;
|
int rc = 1;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case INIT_CMD_REBOOT:
|
case INIT_CMD_REBOOT:
|
||||||
_d("reboot");
|
halt = SHUT_REBOOT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INIT_CMD_HALT:
|
||||||
|
halt = SHUT_HALT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INIT_CMD_POWEROFF:
|
||||||
|
halt = SHUT_OFF;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INIT_CMD_SUSPEND:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout > 0) {
|
||||||
|
emergency.delay = timeout * 1000;
|
||||||
|
schedule_work(&emergency);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case INIT_CMD_REBOOT:
|
||||||
|
dbg("reboot");
|
||||||
halt = SHUT_REBOOT;
|
halt = SHUT_REBOOT;
|
||||||
service_runlevel(6);
|
service_runlevel(6);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_HALT:
|
case INIT_CMD_HALT:
|
||||||
_d("halt");
|
dbg("halt");
|
||||||
halt = SHUT_HALT;
|
halt = SHUT_HALT;
|
||||||
service_runlevel(0);
|
service_runlevel(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_POWEROFF:
|
case INIT_CMD_POWEROFF:
|
||||||
_d("poweroff");
|
dbg("poweroff");
|
||||||
halt = SHUT_OFF;
|
halt = SHUT_OFF;
|
||||||
service_runlevel(0);
|
service_runlevel(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_SUSPEND:
|
case INIT_CMD_SUSPEND:
|
||||||
_d("suspend");
|
dbg("suspend");
|
||||||
sync();
|
sync();
|
||||||
rc = reboot(RB_SW_SUSPEND);
|
rc = suspend();
|
||||||
if (rc) {
|
if (rc) {
|
||||||
if (errno == EINVAL)
|
if (errno == EINVAL)
|
||||||
snprintf(buf, len, "Kernel does not support suspend.");
|
snprintf(buf, len, "Kernel does not support suspend to RAM.");
|
||||||
else
|
else
|
||||||
snprintf(buf, len, "Failed: %s", strerror(errno));
|
snprintf(buf, len, "Failed: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
rc = 255;
|
/* Handled previously */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +322,7 @@ static void send_svc(int sd, svc_t *svc)
|
|||||||
|
|
||||||
len = write(sd, svc, sizeof(*svc));
|
len = write(sd, svc, sizeof(*svc));
|
||||||
if (len != sizeof(*svc))
|
if (len != sizeof(*svc))
|
||||||
_d("Failed sending svc_t to client");
|
dbg("Failed sending svc_t to client");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void api_cb(uev_t *w, void *arg, int events)
|
static void api_cb(uev_t *w, void *arg, int events)
|
||||||
@@ -277,7 +334,7 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
|
|
||||||
sd = accept(w->fd, NULL, NULL);
|
sd = accept(w->fd, NULL, NULL);
|
||||||
if (sd < 0) {
|
if (sd < 0) {
|
||||||
_pe("Failed serving API request");
|
err(1, "Failed serving API request");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,19 +351,49 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
if (EAGAIN == errno)
|
if (EAGAIN == errno)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
_e("Failed reading initctl request, error %d: %s", errno, strerror(errno));
|
/* we get here when client restarts itself */
|
||||||
|
if (ECONNRESET == errno)
|
||||||
|
break;
|
||||||
|
|
||||||
|
errx(1, "Failed reading initctl request, error %d: %s", errno, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rq.magic != INIT_MAGIC || len != sizeof(rq)) {
|
if (rq.magic != INIT_MAGIC || len != sizeof(rq)) {
|
||||||
_e("Invalid initctl request");
|
errx(1, "Invalid initctl request");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (rq.cmd) {
|
||||||
|
case INIT_CMD_RELOAD:
|
||||||
|
case INIT_CMD_START_SVC:
|
||||||
|
case INIT_CMD_RESTART_SVC:
|
||||||
|
case INIT_CMD_STOP_SVC:
|
||||||
|
case INIT_CMD_RELOAD_SVC:
|
||||||
|
case INIT_CMD_REBOOT:
|
||||||
|
case INIT_CMD_HALT:
|
||||||
|
case INIT_CMD_POWEROFF:
|
||||||
|
case INIT_CMD_SUSPEND:
|
||||||
|
if (IS_RESERVED_RUNLEVEL(runlevel)) {
|
||||||
|
warnx("Unsupported command in runlevel S and 6/0.");
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (rq.cmd) {
|
switch (rq.cmd) {
|
||||||
case INIT_CMD_RUNLVL:
|
case INIT_CMD_RUNLVL:
|
||||||
|
/* Allow changing cfglevel in runlevel S */
|
||||||
|
if (IS_RESERVED_RUNLEVEL(runlevel)) {
|
||||||
|
if (runlevel != INIT_LEVEL) {
|
||||||
|
warnx("Cannot abort runlevel 6/0.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (rq.runlevel) {
|
switch (rq.runlevel) {
|
||||||
case 's':
|
case 's':
|
||||||
case 'S':
|
case 'S':
|
||||||
@@ -314,57 +401,70 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
|
|
||||||
case '0'...'9':
|
case '0'...'9':
|
||||||
_d("Setting new runlevel %c", rq.runlevel);
|
dbg("Setting new runlevel %c", rq.runlevel);
|
||||||
lvl = rq.runlevel - '0';
|
lvl = rq.runlevel - '0';
|
||||||
if (lvl == 0)
|
if (lvl == 0)
|
||||||
halt = SHUT_OFF;
|
halt = SHUT_OFF;
|
||||||
if (lvl == 6)
|
if (lvl == 6)
|
||||||
halt = SHUT_REBOOT;
|
halt = SHUT_REBOOT;
|
||||||
service_runlevel(lvl);
|
|
||||||
|
/* User requested change in next runlevel */
|
||||||
|
if (runlevel == INIT_LEVEL)
|
||||||
|
cfglevel = lvl;
|
||||||
|
else
|
||||||
|
service_runlevel(lvl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_d("Unsupported runlevel: %d", rq.runlevel);
|
dbg("Unsupported runlevel: %d", rq.runlevel);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_DEBUG:
|
case INIT_CMD_DEBUG:
|
||||||
_d("debug");
|
dbg("debug");
|
||||||
log_debug();
|
log_debug();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_RELOAD: /* 'init q' and 'initctl reload' */
|
case INIT_CMD_RELOAD: /* 'init q' and 'initctl reload' */
|
||||||
_d("reload");
|
dbg("reload");
|
||||||
service_reload_dynamic();
|
service_reload_dynamic();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_START_SVC:
|
case INIT_CMD_START_SVC:
|
||||||
_d("start %s", rq.data);
|
dbg("start %s", rq.data);
|
||||||
strterm(rq.data, sizeof(rq.data));
|
strterm(rq.data, sizeof(rq.data));
|
||||||
result = do_start(rq.data, sizeof(rq.data));
|
result = do_start(rq.data, sizeof(rq.data));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_RESTART_SVC:
|
case INIT_CMD_RESTART_SVC:
|
||||||
_d("restart %s", rq.data);
|
dbg("restart %s", rq.data);
|
||||||
strterm(rq.data, sizeof(rq.data));
|
strterm(rq.data, sizeof(rq.data));
|
||||||
result = do_restart(rq.data, sizeof(rq.data));
|
result = do_restart(rq.data, sizeof(rq.data));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_STOP_SVC:
|
case INIT_CMD_STOP_SVC:
|
||||||
_d("stop %s", rq.data);
|
dbg("stop %s", rq.data);
|
||||||
strterm(rq.data, sizeof(rq.data));
|
strterm(rq.data, sizeof(rq.data));
|
||||||
result = do_stop(rq.data, sizeof(rq.data));
|
result = do_stop(rq.data, sizeof(rq.data));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_RELOAD_SVC:
|
case INIT_CMD_RELOAD_SVC:
|
||||||
_d("reload %s", rq.data);
|
dbg("reload %s", rq.data);
|
||||||
strterm(rq.data, sizeof(rq.data));
|
strterm(rq.data, sizeof(rq.data));
|
||||||
result = do_reload(rq.data, sizeof(rq.data));
|
result = do_reload(rq.data, sizeof(rq.data));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case INIT_CMD_GET_PLUGINS:
|
||||||
|
result = plugin_list(rq.data, sizeof(rq.data));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INIT_CMD_PLUGIN_DEPS:
|
||||||
|
result = plugin_deps(rq.data, sizeof(rq.data));
|
||||||
|
break;
|
||||||
|
|
||||||
case INIT_CMD_GET_RUNLEVEL:
|
case INIT_CMD_GET_RUNLEVEL:
|
||||||
_d("get runlevel");
|
dbg("get runlevel");
|
||||||
rq.runlevel = runlevel;
|
rq.runlevel = runlevel;
|
||||||
rq.sleeptime = prevlevel;
|
rq.sleeptime = prevlevel;
|
||||||
break;
|
break;
|
||||||
@@ -373,21 +473,21 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
case INIT_CMD_HALT:
|
case INIT_CMD_HALT:
|
||||||
case INIT_CMD_POWEROFF:
|
case INIT_CMD_POWEROFF:
|
||||||
case INIT_CMD_SUSPEND:
|
case INIT_CMD_SUSPEND:
|
||||||
result = do_reboot(rq.cmd, rq.data, sizeof(rq.data));
|
result = do_reboot(rq.cmd, rq.sleeptime, rq.data, sizeof(rq.data));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_ACK:
|
case INIT_CMD_ACK:
|
||||||
_d("Client failed reading ACK");
|
dbg("Client failed reading ACK");
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
case INIT_CMD_WDOG_HELLO:
|
case INIT_CMD_WDOG_HELLO:
|
||||||
_d("wdog hello");
|
dbg("wdog hello");
|
||||||
if (rq.runlevel <= 0) {
|
if (rq.runlevel <= 0) {
|
||||||
result = 1;
|
result = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_e("Request to hand-over wdog ... to PID %d", rq.runlevel);
|
dbg("Request to hand-over wdog ... to PID %d", rq.runlevel);
|
||||||
svc = svc_find_by_pid(rq.runlevel);
|
svc = svc_find_by_pid(rq.runlevel);
|
||||||
if (!svc) {
|
if (!svc) {
|
||||||
logit(LOG_ERR, "Cannot find PID %d, not registered.", rq.runlevel);
|
logit(LOG_ERR, "Cannot find PID %d, not registered.", rq.runlevel);
|
||||||
@@ -403,7 +503,7 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
|
|
||||||
if (wdog->protect) {
|
if (wdog->protect) {
|
||||||
logit(LOG_NOTICE, "Stopping and deleting built-in watchdog.");
|
logit(LOG_NOTICE, "Stopping and deleting built-in watchdog.");
|
||||||
stop(wdog);
|
stop(wdog, NULL);
|
||||||
svc_del(wdog);
|
svc_del(wdog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -411,9 +511,9 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_SVC_ITER:
|
case INIT_CMD_SVC_ITER:
|
||||||
// _d("svc iter, first: %d", rq.runlevel);
|
// dbg("svc iter, first: %d", rq.runlevel);
|
||||||
/*
|
/*
|
||||||
* XXX: This severly limits the number of
|
* XXX: This severely limits the number of
|
||||||
* simultaneous client connections, but will
|
* simultaneous client connections, but will
|
||||||
* have to do for now.
|
* have to do for now.
|
||||||
*/
|
*/
|
||||||
@@ -422,25 +522,46 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
case INIT_CMD_SVC_QUERY:
|
case INIT_CMD_SVC_QUERY:
|
||||||
_d("svc query: %s", rq.data);
|
dbg("svc query: %s", rq.data);
|
||||||
strterm(rq.data, sizeof(rq.data));
|
strterm(rq.data, sizeof(rq.data));
|
||||||
result = do_query(rq.data, sizeof(rq.data));
|
result = do_query(rq.data, sizeof(rq.data));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INIT_CMD_SVC_FIND:
|
case INIT_CMD_SVC_FIND:
|
||||||
_d("svc find: %s", rq.data);
|
dbg("svc find: %s", rq.data);
|
||||||
strterm(rq.data, sizeof(rq.data));
|
strterm(rq.data, sizeof(rq.data));
|
||||||
send_svc(sd, do_find(rq.data, sizeof(rq.data)));
|
send_svc(sd, do_find(rq.data, sizeof(rq.data)));
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
case INIT_CMD_SVC_FIND_BYC:
|
case INIT_CMD_SVC_FIND_BYC:
|
||||||
_d("svc find by cond: %s", rq.data);
|
dbg("svc find by cond: %s", rq.data);
|
||||||
strterm(rq.data, sizeof(rq.data));
|
strterm(rq.data, sizeof(rq.data));
|
||||||
send_svc(sd, do_find_byc(rq.data, sizeof(rq.data)));
|
send_svc(sd, do_find_byc(rq.data, sizeof(rq.data)));
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
|
case INIT_CMD_SIGNAL:
|
||||||
|
/* runlevel is reused for signal */
|
||||||
|
dbg("svc signal %d: %s", rq.runlevel, rq.data);
|
||||||
|
strterm(rq.data, sizeof(rq.data));
|
||||||
|
result = do_signal(rq.data, sizeof(rq.data), rq.runlevel);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case INIT_CMD_NOTIFY_SOCKET:
|
||||||
|
svc = svc_find_by_pid(rq.runlevel);
|
||||||
|
if (!svc) {
|
||||||
|
errx(1, "Unknown PID, cannot register notify socket");
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uev_io_init(ctx, &svc->notify_watcher, service_notify_cb, svc, sd, UEV_READ)) {
|
||||||
|
err(1, "Falied initializing %s readiness notifier", svc_ident(svc, NULL, 0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return; /* Don't close sd, used for notify */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_d("Unsupported cmd: %d", rq.cmd);
|
dbg("Unsupported cmd: %d", rq.cmd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,7 +571,7 @@ static void api_cb(uev_t *w, void *arg, int events)
|
|||||||
rq.cmd = INIT_CMD_ACK;
|
rq.cmd = INIT_CMD_ACK;
|
||||||
len = write(sd, &rq, sizeof(rq));
|
len = write(sd, &rq, sizeof(rq));
|
||||||
if (len != sizeof(rq))
|
if (len != sizeof(rq))
|
||||||
_d("Failed sending ACK/NACK back to client");
|
dbg("Failed sending ACK/NACK back to client");
|
||||||
}
|
}
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
@@ -461,39 +582,46 @@ leave:
|
|||||||
error:
|
error:
|
||||||
api_exit();
|
api_exit();
|
||||||
if (api_init(w->ctx))
|
if (api_init(w->ctx))
|
||||||
_e("Unrecoverable error on API socket");
|
errx(1, "Unrecoverable error on API socket");
|
||||||
}
|
}
|
||||||
|
|
||||||
int api_init(uev_ctx_t *ctx)
|
int api_init(uev_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
int sd;
|
|
||||||
mode_t oldmask;
|
|
||||||
struct sockaddr_un sun = {
|
struct sockaddr_un sun = {
|
||||||
.sun_family = AF_UNIX,
|
.sun_family = AF_UNIX,
|
||||||
.sun_path = INIT_SOCKET,
|
.sun_path = INIT_SOCKET,
|
||||||
};
|
};
|
||||||
|
mode_t oldmask;
|
||||||
|
int uid, gid;
|
||||||
|
int sd;
|
||||||
|
|
||||||
_d("Setting up external API socket ...");
|
dbg("Setting up external API socket ...");
|
||||||
sd = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
|
sd = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
|
||||||
if (-1 == sd) {
|
if (-1 == sd) {
|
||||||
_pe("Failed starting external API socket");
|
err(1, "Failed starting external API socket");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uid = geteuid();
|
||||||
|
gid = getgroup(DEFGROUP);
|
||||||
|
|
||||||
erase(INIT_SOCKET);
|
erase(INIT_SOCKET);
|
||||||
oldmask = umask(0077);
|
oldmask = umask(0117);
|
||||||
if (-1 == bind(sd, (struct sockaddr*)&sun, sizeof(sun)))
|
if (-1 == bind(sd, (struct sockaddr*)&sun, sizeof(sun)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (-1 == listen(sd, 10))
|
if (-1 == listen(sd, 10))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
if (chown(INIT_SOCKET, uid, gid))
|
||||||
|
err(1, "Failed setting group %s on %s", DEFGROUP, INIT_SOCKET);
|
||||||
|
|
||||||
umask(oldmask);
|
umask(oldmask);
|
||||||
if (!uev_io_init(ctx, &api_watcher, api_cb, NULL, sd, UEV_READ))
|
if (!uev_io_init(ctx, &api_watcher, api_cb, NULL, sd, UEV_READ))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
_pe("Failed intializing API socket");
|
err(1, "Failed initializing API socket");
|
||||||
umask(oldmask);
|
umask(oldmask);
|
||||||
close(sd);
|
close(sd);
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
+99
-41
@@ -1,6 +1,6 @@
|
|||||||
/* Finit control group support functions
|
/* Finit control group support functions
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -24,8 +24,13 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <lite/lite.h>
|
#ifdef _LIBITE_LITE
|
||||||
#include <lite/queue.h>
|
# include <libite/lite.h>
|
||||||
|
# include <libite/queue.h> /* BSD sys/queue.h API */
|
||||||
|
#else
|
||||||
|
# include <lite/lite.h>
|
||||||
|
# include <lite/queue.h> /* BSD sys/queue.h API */
|
||||||
|
#endif
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <sys/sysinfo.h> /* get_nprocs_conf() */
|
#include <sys/sysinfo.h> /* get_nprocs_conf() */
|
||||||
|
|
||||||
@@ -42,7 +47,7 @@ struct cg {
|
|||||||
char *cfg; /* kernel settings */
|
char *cfg; /* kernel settings */
|
||||||
|
|
||||||
int active; /* for mark & sweep */
|
int active; /* for mark & sweep */
|
||||||
int protected; /* for init/, user/, & system/ */
|
int is_protected; /* for init/, user/, & system/ */
|
||||||
};
|
};
|
||||||
|
|
||||||
static TAILQ_HEAD(, cg) cgroups = TAILQ_HEAD_INITIALIZER(cgroups);
|
static TAILQ_HEAD(, cg) cgroups = TAILQ_HEAD_INITIALIZER(cgroups);
|
||||||
@@ -51,22 +56,23 @@ static char controllers[256];
|
|||||||
|
|
||||||
static struct iwatch iw_cgroup;
|
static struct iwatch iw_cgroup;
|
||||||
static uev_t cgw;
|
static uev_t cgw;
|
||||||
|
static int avail;
|
||||||
|
|
||||||
|
|
||||||
static void cgset(const char *path, char *ctrl, char *prop)
|
static void cgset(const char *path, char *ctrl, char *prop)
|
||||||
{
|
{
|
||||||
char *val;
|
char *val;
|
||||||
|
|
||||||
_d("path %s, ctrl %s, prop %s", path ?: "NIL", ctrl ?: "NIL", prop ?: "NIL");
|
dbg("path %s, ctrl %s, prop %s", path ?: "NIL", ctrl ?: "NIL", prop ?: "NIL");
|
||||||
if (!path || !ctrl) {
|
if (!path || !ctrl) {
|
||||||
_e("Missing path or controller, skipping!");
|
errx(1, "Missing path or controller, skipping!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prop) {
|
if (!prop) {
|
||||||
prop = strchr(ctrl, '.');
|
prop = strchr(ctrl, '.');
|
||||||
if (!prop) {
|
if (!prop) {
|
||||||
_e("Invalid cgroup ctrl syntax: %s", ctrl);
|
errx(1, "Invalid cgroup ctrl syntax: %s", ctrl);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,20 +81,20 @@ static void cgset(const char *path, char *ctrl, char *prop)
|
|||||||
|
|
||||||
val = strchr(prop, ':');
|
val = strchr(prop, ':');
|
||||||
if (!val) {
|
if (!val) {
|
||||||
_e("Missing cgroup ctrl value, prop %s", prop);
|
errx(1, "Missing cgroup ctrl value, prop %s", prop);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*val++ = 0;
|
*val++ = 0;
|
||||||
|
|
||||||
/* disallow sneaky relative paths */
|
/* disallow sneaky relative paths */
|
||||||
if (strstr(ctrl, "..") || strstr(prop, "..")) {
|
if (strstr(ctrl, "..") || strstr(prop, "..")) {
|
||||||
_e("Possible security violation; '..' not allowed in cgroup config!");
|
errx(1, "Possible security violation; '..' not allowed in cgroup config!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_d("%s/%s.%s <= %s", path, ctrl, prop, val);
|
dbg("%s/%s.%s <= %s", path, ctrl, prop, val);
|
||||||
if (fnwrite(val, "%s/%s.%s", path, ctrl, prop))
|
if (fnwrite(val, "%s/%s.%s", path, ctrl, prop))
|
||||||
_pe("Failed setting %s/%s.%s = %s", path, ctrl, prop, val);
|
err(1, "Failed setting %s/%s.%s = %s", path, ctrl, prop, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -100,16 +106,16 @@ static void group_init(char *path, int leaf, const char *cfg)
|
|||||||
{
|
{
|
||||||
char *ptr, *s;
|
char *ptr, *s;
|
||||||
|
|
||||||
_d("path %s, leaf %d, cfg %s", path, leaf, cfg ?: "NIL");
|
dbg("path %s, leaf %d, cfg %s", path, leaf, cfg ?: "NIL");
|
||||||
if (!fisdir(path)) {
|
if (!fisdir(path)) {
|
||||||
if (mkdir(path, 0755)) {
|
if (mkdir(path, 0755)) {
|
||||||
_pe("Failed creating cgroup %s", path);
|
err(1, "Failed creating cgroup %s", path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enable detected controllers on domain groups */
|
/* enable detected controllers on domain groups */
|
||||||
if (!leaf && fnwrite(controllers, "%s/cgroup.subtree_control", path))
|
if (!leaf && fnwrite(controllers, "%s/cgroup.subtree_control", path))
|
||||||
_pe("Failed enabling %s for %s", controllers, path);
|
err(1, "Failed enabling %s for %s", controllers, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cfg || !cfg[0])
|
if (!cfg || !cfg[0])
|
||||||
@@ -117,14 +123,14 @@ static void group_init(char *path, int leaf, const char *cfg)
|
|||||||
|
|
||||||
s = strdupa(cfg);
|
s = strdupa(cfg);
|
||||||
if (!s) {
|
if (!s) {
|
||||||
_pe("Failed activating cgroup cfg for %s", path);
|
err(1, "Failed activating cgroup cfg for %s", path);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_d("%s <=> %s", path, s);
|
dbg("%s <=> %s", path, s);
|
||||||
ptr = strtok(s, ",");
|
ptr = strtok(s, ",");
|
||||||
while (ptr) {
|
while (ptr) {
|
||||||
_d("ptr: %s", ptr);
|
dbg("ptr: %s", ptr);
|
||||||
if (!strncmp("mem.", ptr, 4))
|
if (!strncmp("mem.", ptr, 4))
|
||||||
cgset(path, "memory", &ptr[4]);
|
cgset(path, "memory", &ptr[4]);
|
||||||
else
|
else
|
||||||
@@ -138,7 +144,7 @@ static int cgroup_leaf_init(char *group, char *name, int pid, const char *cfg)
|
|||||||
{
|
{
|
||||||
char path[256];
|
char path[256];
|
||||||
|
|
||||||
_d("group %s, name %s, pid %d, cfg %s", group, name, pid, cfg ?: "NIL");
|
dbg("group %s, name %s, pid %d, cfg %s", group, name, pid, cfg ?: "NIL");
|
||||||
if (pid < 0 || pid == 1) {
|
if (pid < 0 || pid == 1) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return 1;
|
return 1;
|
||||||
@@ -150,7 +156,7 @@ static int cgroup_leaf_init(char *group, char *name, int pid, const char *cfg)
|
|||||||
|
|
||||||
/* move process to new group */
|
/* move process to new group */
|
||||||
if (fnwrite(str("%d", pid), "%s/cgroup.procs", path))
|
if (fnwrite(str("%d", pid), "%s/cgroup.procs", path))
|
||||||
_pe("Failed moving pid %d to group %s", pid, path);
|
err(1, "Failed moving pid %d to group %s", pid, path);
|
||||||
|
|
||||||
strlcat(path, "/cgroup.events", sizeof(path));
|
strlcat(path, "/cgroup.events", sizeof(path));
|
||||||
|
|
||||||
@@ -159,6 +165,9 @@ static int cgroup_leaf_init(char *group, char *name, int pid, const char *cfg)
|
|||||||
|
|
||||||
int cgroup_user(char *name, int pid)
|
int cgroup_user(char *name, int pid)
|
||||||
{
|
{
|
||||||
|
if (!avail)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return cgroup_leaf_init("user", name, pid, NULL);
|
return cgroup_leaf_init("user", name, pid, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,12 +175,18 @@ int cgroup_service(char *name, int pid, struct cgroup *cg)
|
|||||||
{
|
{
|
||||||
char *group = "system";
|
char *group = "system";
|
||||||
|
|
||||||
|
if (!avail)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (cg && cg->name[0]) {
|
if (cg && cg->name[0]) {
|
||||||
char path[256];
|
char path[256];
|
||||||
|
|
||||||
if (!strcmp(cg->name, "root"))
|
if (!strcmp(cg->name, "root"))
|
||||||
return fnwrite(str("%d", pid), FINIT_CGPATH "/cgroup.procs");
|
return fnwrite(str("%d", pid), FINIT_CGPATH "/cgroup.procs");
|
||||||
|
|
||||||
|
if (!strcmp(cg->name, "init"))
|
||||||
|
return fnwrite(str("%d", pid), FINIT_CGPATH "/init/cgroup.procs");
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "/sys/fs/cgroup/%s", cg->name);
|
snprintf(path, sizeof(path), "/sys/fs/cgroup/%s", cg->name);
|
||||||
if (fisdir(path))
|
if (fisdir(path))
|
||||||
group = cg->name;
|
group = cg->name;
|
||||||
@@ -196,13 +211,13 @@ static void cgroup_handle_event(char *event, uint32_t mask)
|
|||||||
char *ptr;
|
char *ptr;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
_d("event: '%s', mask: %08x", event, mask);
|
dbg("event: '%s', mask: %08x", event, mask);
|
||||||
if (!(mask & IN_MODIFY))
|
if (!(mask & IN_MODIFY))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fp = fopen(event, "r");
|
fp = fopen(event, "r");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
_d("Failed opening %s, skipping ...", event);
|
dbg("Failed opening %s, skipping ...", event);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +261,7 @@ static void cgroup_events_cb(uev_t *w, void *arg, int events)
|
|||||||
|
|
||||||
sz = read(w->fd, ev_buf, sizeof(ev_buf) - 1);
|
sz = read(w->fd, ev_buf, sizeof(ev_buf) - 1);
|
||||||
if (sz <= 0) {
|
if (sz <= 0) {
|
||||||
_pe("invalid inotify event");
|
err(1, "invalid inotify event");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ev_buf[sz] = 0;
|
ev_buf[sz] = 0;
|
||||||
@@ -272,7 +287,7 @@ static void cgroup_events_cb(uev_t *w, void *arg, int events)
|
|||||||
cgroup_handle_event(iwp->path, ev->mask);
|
cgroup_handle_event(iwp->path, ev->mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_AUTO_RELOAD
|
#ifdef AUTO_RELOAD
|
||||||
if (conf_any_change())
|
if (conf_any_change())
|
||||||
service_reload_dynamic();
|
service_reload_dynamic();
|
||||||
#endif
|
#endif
|
||||||
@@ -299,8 +314,11 @@ void cgroup_mark_all(void)
|
|||||||
{
|
{
|
||||||
struct cg *cg;
|
struct cg *cg;
|
||||||
|
|
||||||
|
if (!avail)
|
||||||
|
return;
|
||||||
|
|
||||||
TAILQ_FOREACH(cg, &cgroups, link) {
|
TAILQ_FOREACH(cg, &cgroups, link) {
|
||||||
if (cg->protected)
|
if (cg->is_protected)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
cg->active = 0;
|
cg->active = 0;
|
||||||
@@ -315,6 +333,9 @@ void cgroup_cleanup(void)
|
|||||||
struct cg *cg, *tmp;
|
struct cg *cg, *tmp;
|
||||||
char path[256];
|
char path[256];
|
||||||
|
|
||||||
|
if (!avail)
|
||||||
|
return;
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(cg, &cgroups, link, tmp) {
|
TAILQ_FOREACH_SAFE(cg, &cgroups, link, tmp) {
|
||||||
if (cg->active)
|
if (cg->active)
|
||||||
continue;
|
continue;
|
||||||
@@ -327,10 +348,13 @@ void cgroup_cleanup(void)
|
|||||||
/*
|
/*
|
||||||
* Add, or update, settings for top-level cgroup
|
* Add, or update, settings for top-level cgroup
|
||||||
*/
|
*/
|
||||||
int cgroup_add(char *name, char *cfg, int protected)
|
int cgroup_add(char *name, char *cfg, int is_protected)
|
||||||
{
|
{
|
||||||
struct cg *cg;
|
struct cg *cg;
|
||||||
|
|
||||||
|
if (!avail)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!name)
|
if (!name)
|
||||||
return -1;
|
return -1;
|
||||||
if (!cfg)
|
if (!cfg)
|
||||||
@@ -340,12 +364,12 @@ int cgroup_add(char *name, char *cfg, int protected)
|
|||||||
if (!cg) {
|
if (!cg) {
|
||||||
cg = malloc(sizeof(struct cg));
|
cg = malloc(sizeof(struct cg));
|
||||||
if (!cg) {
|
if (!cg) {
|
||||||
_pe("Failed allocating 'struct cg' for %s", name);
|
err(1, "Failed allocating 'struct cg' for %s", name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
cg->name = strdup(name);
|
cg->name = strdup(name);
|
||||||
if (!cg->name) {
|
if (!cg->name) {
|
||||||
_pe("Failed setting cgroup name %s", name);
|
err(1, "Failed setting cgroup name %s", name);
|
||||||
free(cg);
|
free(cg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -355,13 +379,13 @@ int cgroup_add(char *name, char *cfg, int protected)
|
|||||||
|
|
||||||
cg->cfg = strdup(cfg);
|
cg->cfg = strdup(cfg);
|
||||||
if (!cg->cfg) {
|
if (!cg->cfg) {
|
||||||
_pe("Failed add/update of cgroup %s", name);
|
err(1, "Failed add/update of cgroup %s", name);
|
||||||
TAILQ_REMOVE(&cgroups, cg, link);
|
TAILQ_REMOVE(&cgroups, cg, link);
|
||||||
free(cg->name);
|
free(cg->name);
|
||||||
free(cg);
|
free(cg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
cg->protected = protected;
|
cg->is_protected = is_protected;
|
||||||
cg->active = 1;
|
cg->active = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -375,6 +399,9 @@ int cgroup_del(char *dir)
|
|||||||
struct cg *cg;
|
struct cg *cg;
|
||||||
char path[256];
|
char path[256];
|
||||||
|
|
||||||
|
if (!avail)
|
||||||
|
return 0;
|
||||||
|
|
||||||
TAILQ_FOREACH(cg, &cgroups, link) {
|
TAILQ_FOREACH(cg, &cgroups, link) {
|
||||||
snprintf(path, sizeof(path), FINIT_CGPATH "/%s", cg->name);
|
snprintf(path, sizeof(path), FINIT_CGPATH "/%s", cg->name);
|
||||||
if (strcmp(path, dir))
|
if (strcmp(path, dir))
|
||||||
@@ -387,7 +414,7 @@ int cgroup_del(char *dir)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rmdir(dir) && errno != ENOENT) {
|
if (rmdir(dir) && errno != ENOENT) {
|
||||||
_d("Failed removing %s: %s", dir, strerror(errno));
|
dbg("Failed removing %s: %s", dir, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,6 +433,9 @@ void cgroup_config(void)
|
|||||||
{
|
{
|
||||||
struct cg *cg;
|
struct cg *cg;
|
||||||
|
|
||||||
|
if (!avail)
|
||||||
|
return;
|
||||||
|
|
||||||
TAILQ_FOREACH(cg, &cgroups, link) {
|
TAILQ_FOREACH(cg, &cgroups, link) {
|
||||||
char path[256];
|
char path[256];
|
||||||
int leaf = 0;
|
int leaf = 0;
|
||||||
@@ -434,14 +464,24 @@ void cgroup_init(uev_ctx_t *ctx)
|
|||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (mount("none", FINIT_CGPATH, "cgroup2", opts, NULL)) {
|
if (mount("none", FINIT_CGPATH, "cgroup2", opts, NULL)) {
|
||||||
_pe("Failed mounting cgroup v2");
|
if (errno == ENOENT)
|
||||||
|
logit(LOG_INFO, "Kernel does not support cgroups v2, disabling.");
|
||||||
|
else if (errno == EPERM) /* Probably inside an unpriviliged container */
|
||||||
|
logit(LOG_INFO, "Not allowed to mount cgroups v2, disabling.");
|
||||||
|
else
|
||||||
|
err(1, "Failed mounting cgroup v2");
|
||||||
|
avail = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
avail = 1;
|
||||||
|
|
||||||
/* Find available controllers */
|
/* Find available controllers */
|
||||||
fp = fopen(FINIT_CGPATH "/cgroup.controllers", "r");
|
fp = fopen(FINIT_CGPATH "/cgroup.controllers", "r");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
_pe("Failed opening %s", FINIT_CGPATH "/cgroup.controllers");
|
err(1, "Failed opening %s", FINIT_CGPATH "/cgroup.controllers");
|
||||||
|
abort:
|
||||||
|
umount(FINIT_CGPATH);
|
||||||
|
avail = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,9 +497,29 @@ void cgroup_init(uev_ctx_t *ctx)
|
|||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
|
/* Check for cpu controller, abort if missing */
|
||||||
|
if (!strstr(controllers, "+cpu")) {
|
||||||
|
logit(LOG_NOTICE, "Missing CPU controller, disabling cgroup support.");
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
|
||||||
/* Enable all controllers */
|
/* Enable all controllers */
|
||||||
if (fnwrite(controllers, FINIT_CGPATH "/cgroup.subtree_control"))
|
if (fnwrite(controllers, FINIT_CGPATH "/cgroup.subtree_control")) {
|
||||||
_pe("Failed enabling %s for %s", controllers, FINIT_CGPATH "/cgroup.subtree_control");
|
err(1, "Failed enabling %s for %s", controllers, FINIT_CGPATH "/cgroup.subtree_control");
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* prepare cgroup.events watcher */
|
||||||
|
fd = iwatch_init(&iw_cgroup);
|
||||||
|
if (fd == -1)
|
||||||
|
goto abort;
|
||||||
|
|
||||||
|
if (uev_io_init(ctx, &cgw, cgroup_events_cb, NULL, fd, UEV_READ)) {
|
||||||
|
err(1, "Failed setting up cgroup.events watcher");
|
||||||
|
iwatch_exit(&iw_cgroup);
|
||||||
|
close(fd);
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
|
||||||
/* Default (protected) groups, PID 1, services, and user/login processes */
|
/* Default (protected) groups, PID 1, services, and user/login processes */
|
||||||
cgroup_add("init", "cpu.weight:100", 1);
|
cgroup_add("init", "cpu.weight:100", 1);
|
||||||
@@ -468,14 +528,12 @@ void cgroup_init(uev_ctx_t *ctx)
|
|||||||
cgroup_config();
|
cgroup_config();
|
||||||
|
|
||||||
/* Move ourselves to init (best effort, otherwise run in 'root' group */
|
/* Move ourselves to init (best effort, otherwise run in 'root' group */
|
||||||
if (fnwrite("1", FINIT_CGPATH "/init/cgroup.procs"))
|
if (fnwrite("1", FINIT_CGPATH "/init/cgroup.procs")) {
|
||||||
_pe("Failed moving PID 1 to cgroup ", FINIT_CGPATH "/init");
|
err(1, "Failed moving PID 1 to cgroup %s", FINIT_CGPATH "/init");
|
||||||
|
uev_io_stop(&cgw);
|
||||||
/* prepare cgroup.events watcher */
|
iwatch_exit(&iw_cgroup);
|
||||||
fd = iwatch_init(&iw_cgroup);
|
|
||||||
if (uev_io_init(ctx, &cgw, cgroup_events_cb, NULL, fd, UEV_READ)) {
|
|
||||||
_pe("Failed setting up cgroup.events watcher");
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
goto abort;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
/* Finit control group support functions
|
/* Finit control group support functions
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -34,7 +34,7 @@ struct cgroup {
|
|||||||
void cgroup_mark_all(void);
|
void cgroup_mark_all(void);
|
||||||
void cgroup_cleanup (void);
|
void cgroup_cleanup (void);
|
||||||
|
|
||||||
int cgroup_add (char *name, char *cfg, int protected);
|
int cgroup_add (char *name, char *cfg, int is_protected);
|
||||||
int cgroup_del (char *dir);
|
int cgroup_del (char *dir);
|
||||||
void cgroup_config (void);
|
void cgroup_config (void);
|
||||||
|
|
||||||
|
|||||||
+20
-10
@@ -1,6 +1,6 @@
|
|||||||
/* New client tool, replaces old /dev/initctl API and telinit tool
|
/* New client tool, replaces old /dev/initctl API and telinit tool
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -23,18 +23,22 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <err.h>
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <search.h>
|
#include <search.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <lite/lite.h>
|
#ifdef _LIBITE_LITE
|
||||||
|
# include <libite/lite.h>
|
||||||
|
#else
|
||||||
|
# include <lite/lite.h>
|
||||||
|
#endif
|
||||||
#include <sys/sysinfo.h> /* sysinfo() */
|
#include <sys/sysinfo.h> /* sysinfo() */
|
||||||
|
|
||||||
#include "cgutil.h"
|
#include "cgutil.h"
|
||||||
#include "initctl.h"
|
#include "initctl.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#define CDIM plain ? "" : "\e[2m"
|
#define CDIM plain ? "" : "\e[2m"
|
||||||
#define CRST plain ? "" : "\e[0m"
|
#define CRST plain ? "" : "\e[0m"
|
||||||
@@ -49,6 +53,10 @@ uint64_t total_ram; /* From sysinfo() */
|
|||||||
struct cg dummy; /* empty result "NULL" */
|
struct cg dummy; /* empty result "NULL" */
|
||||||
struct cg *list;
|
struct cg *list;
|
||||||
|
|
||||||
|
int cgroup_avail(void)
|
||||||
|
{
|
||||||
|
return fismnt(FINIT_CGPATH);
|
||||||
|
}
|
||||||
|
|
||||||
char *pid_cmdline(int pid, char *buf, size_t len)
|
char *pid_cmdline(int pid, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
@@ -236,7 +244,7 @@ static float cgroup_cpuload(struct cg *cg)
|
|||||||
snprintf(fn, sizeof(fn), "%s/cpu.stat", cg->cg_path);
|
snprintf(fn, sizeof(fn), "%s/cpu.stat", cg->cg_path);
|
||||||
fp = fopen(fn, "r");
|
fp = fopen(fn, "r");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
err(1, "Cannot open %s", fn);
|
ERR(72, "Cannot open %s", fn);
|
||||||
|
|
||||||
while (fgets(buf, sizeof(buf), fp)) {
|
while (fgets(buf, sizeof(buf), fp)) {
|
||||||
uint64_t curr;
|
uint64_t curr;
|
||||||
@@ -272,13 +280,13 @@ static struct cg *append(char *path)
|
|||||||
if (access(fn, F_OK)) {
|
if (access(fn, F_OK)) {
|
||||||
/* older kernels, 4.19, don't have summary cpu.stat in root */
|
/* older kernels, 4.19, don't have summary cpu.stat in root */
|
||||||
if (strcmp(path, FINIT_CGPATH))
|
if (strcmp(path, FINIT_CGPATH))
|
||||||
warn("not a cgroup path with cpu controller, %s", path);
|
WARN("not a cgroup path with cpu controller, %s", path);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cg = calloc(1, sizeof(struct cg));
|
cg = calloc(1, sizeof(struct cg));
|
||||||
if (!cg)
|
if (!cg)
|
||||||
err(1, "failed allocating struct cg");
|
ERR(71, "failed allocating struct cg");
|
||||||
|
|
||||||
cg->cg_path = strdup(path);
|
cg->cg_path = strdup(path);
|
||||||
if (list)
|
if (list)
|
||||||
@@ -288,7 +296,7 @@ static struct cg *append(char *path)
|
|||||||
item.key = cg->cg_path;
|
item.key = cg->cg_path;
|
||||||
item.data = cg;
|
item.data = cg;
|
||||||
if (!hsearch(item, ENTER))
|
if (!hsearch(item, ENTER))
|
||||||
err(1, "failed adding to hash table");
|
ERR(70, "failed adding to hash table");
|
||||||
|
|
||||||
return cg;
|
return cg;
|
||||||
}
|
}
|
||||||
@@ -426,7 +434,6 @@ int cgroup_tree(char *path, char *pfx, int mode, int pos)
|
|||||||
pid_comm(pid, comm, sizeof(comm));
|
pid_comm(pid, comm, sizeof(comm));
|
||||||
if (pid_cmdline(pid, buf, sizeof(buf))) {
|
if (pid_cmdline(pid, buf, sizeof(buf))) {
|
||||||
char proc[ttcols];
|
char proc[ttcols];
|
||||||
int len;
|
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 1:
|
case 1:
|
||||||
@@ -448,6 +455,8 @@ int cgroup_tree(char *path, char *pfx, int mode, int pos)
|
|||||||
if (plain) {
|
if (plain) {
|
||||||
strlcat(row, proc, rplen);
|
strlcat(row, proc, rplen);
|
||||||
} else {
|
} else {
|
||||||
|
int len;
|
||||||
|
|
||||||
strlcat(row, CDIM, rlen);
|
strlcat(row, CDIM, rlen);
|
||||||
strlcat(row, proc, rlen);
|
strlcat(row, proc, rlen);
|
||||||
|
|
||||||
@@ -592,7 +601,6 @@ int show_cgtop(char *arg)
|
|||||||
uev_t timer, input, sigint, sigterm, sigquit;
|
uev_t timer, input, sigint, sigterm, sigquit;
|
||||||
char path[512];
|
char path[512];
|
||||||
uev_ctx_t ctx;
|
uev_ctx_t ctx;
|
||||||
int flags;
|
|
||||||
|
|
||||||
if (!arg)
|
if (!arg)
|
||||||
arg = FINIT_CGPATH;
|
arg = FINIT_CGPATH;
|
||||||
@@ -602,7 +610,7 @@ int show_cgtop(char *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!hcreate(ttrows + 25))
|
if (!hcreate(ttrows + 25))
|
||||||
err(1, "failed creating hash table");
|
ERR(70, "failed creating hash table");
|
||||||
|
|
||||||
sysinfo(&si);
|
sysinfo(&si);
|
||||||
total_ram = si.totalram * si.mem_unit;
|
total_ram = si.totalram * si.mem_unit;
|
||||||
@@ -611,6 +619,8 @@ int show_cgtop(char *arg)
|
|||||||
uev_timer_init(&ctx, &timer, cgtop, arg, 1, ionce ? 0 : 1000);
|
uev_timer_init(&ctx, &timer, cgtop, arg, 1, ionce ? 0 : 1000);
|
||||||
|
|
||||||
if (!ionce && !plain) {
|
if (!ionce && !plain) {
|
||||||
|
int flags;
|
||||||
|
|
||||||
atexit(cleanup);
|
atexit(cleanup);
|
||||||
ttraw();
|
ttraw();
|
||||||
hidecursor();
|
hidecursor();
|
||||||
|
|||||||
+3
-1
@@ -1,6 +1,6 @@
|
|||||||
/* Cgroup utility functions for initctl
|
/* Cgroup utility functions for initctl
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2019-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -52,6 +52,8 @@ struct cg {
|
|||||||
} cg_cpu;
|
} cg_cpu;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int cgroup_avail(void);
|
||||||
|
|
||||||
char *pid_cmdline (int pid, char *buf, size_t len);
|
char *pid_cmdline (int pid, char *buf, size_t len);
|
||||||
char *pid_comm (int pid, char *buf, size_t len);
|
char *pid_comm (int pid, char *buf, size_t len);
|
||||||
char *pid_cgroup (int pid, char *buf, size_t len);
|
char *pid_cgroup (int pid, char *buf, size_t len);
|
||||||
|
|||||||
+74
-34
@@ -1,6 +1,6 @@
|
|||||||
/* External client API, using UNIX domain socket.
|
/* External client API, using UNIX domain socket.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -21,13 +21,13 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <err.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
static int sd = -1;
|
static int sd = -1;
|
||||||
|
|
||||||
@@ -39,11 +39,17 @@ int client_connect(void)
|
|||||||
};
|
};
|
||||||
|
|
||||||
sd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
|
sd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
|
||||||
if (-1 == sd)
|
if (-1 == sd) {
|
||||||
err(1, "Failed creating UNIX domain socket");
|
warn("Failed creating UNIX domain socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (connect(sd, (struct sockaddr*)&sun, sizeof(sun)) == -1)
|
if (connect(sd, (struct sockaddr*)&sun, sizeof(sun)) == -1) {
|
||||||
err(1, "Failed connecting to finit");
|
if (errno != ENOENT)
|
||||||
|
warnx("Failed connecting to finit");
|
||||||
|
close(sd);
|
||||||
|
sd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
return sd;
|
return sd;
|
||||||
}
|
}
|
||||||
@@ -63,60 +69,97 @@ int client_disconnect(void)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int client_send(struct init_request *rq, ssize_t len)
|
/* Only valid after client_connect() */
|
||||||
|
int client_socket(void)
|
||||||
|
{
|
||||||
|
return sd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int client_request(struct init_request *rq, ssize_t len)
|
||||||
{
|
{
|
||||||
struct pollfd pfd = { 0 };
|
struct pollfd pfd = { 0 };
|
||||||
int sd, result = 255;
|
int rc;
|
||||||
|
|
||||||
sd = client_connect();
|
if (client_connect() == -1)
|
||||||
if (-1 == sd)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
pfd.fd = sd;
|
pfd.fd = sd;
|
||||||
pfd.events = POLLOUT;
|
pfd.events = POLLOUT;
|
||||||
if (poll(&pfd, 1, 2000) <= 0) {
|
if (poll(&pfd, 1, 2000) <= 0) {
|
||||||
warn("Timed out waiting for Finit, errno %d", errno);
|
warn("Timed out waiting for Finit, errno %d", errno);
|
||||||
goto exit;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write(sd, rq, len) != len) {
|
if (write(sd, rq, len) != len) {
|
||||||
warn("Failed communicating with Finit, errno %d", errno);
|
warn("Failed communicating with Finit, errno %d", errno);
|
||||||
goto exit;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exception, only command that don't need to wait for a
|
||||||
|
* response from Finit. Registers the client socket as a
|
||||||
|
* readiness notification socket with Finit
|
||||||
|
*/
|
||||||
|
if (rq->cmd == INIT_CMD_NOTIFY_SOCKET) {
|
||||||
|
rq->cmd = INIT_CMD_ACK;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pfd.fd = sd;
|
pfd.fd = sd;
|
||||||
pfd.events = POLLIN;
|
pfd.events = POLLIN | POLLERR | POLLHUP;
|
||||||
if (poll(&pfd, 1, 2000) <= 0) {
|
if ((rc = poll(&pfd, 1, 2000)) <= 0) {
|
||||||
warn("Timed out waiting for reply from Finit, errno %d", errno);
|
if (rc) {
|
||||||
goto exit;
|
if (errno == EINTR) /* shutdown/reboot */
|
||||||
|
return -1;
|
||||||
|
warn("poll(), errno %d", errno);
|
||||||
|
} else
|
||||||
|
warnx("Timed out waiting for reply from Finit.");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read(sd, rq, len) != len) {
|
if (read(sd, rq, len) != len) {
|
||||||
warn("Failed reading reply from Finit, errno %d", errno);
|
warn("Failed reading reply from Finit, errno %d", errno);
|
||||||
goto exit;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rq->cmd == INIT_CMD_NACK)
|
if (rq->cmd == INIT_CMD_NACK)
|
||||||
result = 1;
|
return -1;
|
||||||
else
|
|
||||||
result = 0;
|
return 0;
|
||||||
exit:
|
}
|
||||||
|
|
||||||
|
int client_send(struct init_request *rq, ssize_t len)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (client_request(rq, len))
|
||||||
|
rc = 255;
|
||||||
|
|
||||||
client_disconnect();
|
client_disconnect();
|
||||||
|
|
||||||
return result;
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int client_command(int cmd)
|
||||||
|
{
|
||||||
|
struct init_request rq = {
|
||||||
|
.magic = INIT_MAGIC,
|
||||||
|
.runlevel = getpid(),
|
||||||
|
.cmd = cmd,
|
||||||
|
};
|
||||||
|
|
||||||
|
return client_request(&rq, sizeof(rq));
|
||||||
}
|
}
|
||||||
|
|
||||||
svc_t *client_svc_iterator(int first)
|
svc_t *client_svc_iterator(int first)
|
||||||
{
|
{
|
||||||
int sd = -1;
|
|
||||||
struct init_request rq = {
|
struct init_request rq = {
|
||||||
.magic = INIT_MAGIC,
|
.magic = INIT_MAGIC,
|
||||||
.cmd = INIT_CMD_SVC_ITER,
|
.cmd = INIT_CMD_SVC_ITER,
|
||||||
};
|
};
|
||||||
static svc_t svc;
|
static svc_t svc;
|
||||||
|
|
||||||
sd = client_connect();
|
if (client_connect() == -1)
|
||||||
if (sd == -1)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
@@ -135,24 +178,22 @@ svc_t *client_svc_iterator(int first)
|
|||||||
|
|
||||||
return &svc;
|
return &svc;
|
||||||
error:
|
error:
|
||||||
perror("Failed communicating with finit");
|
warn("Failed communicating with finit, error %d", errno);
|
||||||
client_disconnect();
|
client_disconnect();
|
||||||
sd = -1;
|
sd = -1;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
svc_t *do_cmd(int cmd, const char *arg)
|
static svc_t *do_find(int cmd, const char *arg)
|
||||||
{
|
{
|
||||||
struct init_request rq = {
|
struct init_request rq = {
|
||||||
.magic = INIT_MAGIC,
|
.magic = INIT_MAGIC,
|
||||||
.cmd = cmd,
|
.cmd = cmd,
|
||||||
};
|
};
|
||||||
static svc_t svc;
|
static svc_t svc;
|
||||||
int sd = -1;
|
|
||||||
|
|
||||||
sd = client_connect();
|
if (client_connect() == -1)
|
||||||
if (sd == -1)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
strlcpy(rq.data, arg, sizeof(rq.data));
|
strlcpy(rq.data, arg, sizeof(rq.data));
|
||||||
@@ -168,20 +209,19 @@ svc_t *do_cmd(int cmd, const char *arg)
|
|||||||
return &svc;
|
return &svc;
|
||||||
error:
|
error:
|
||||||
client_disconnect();
|
client_disconnect();
|
||||||
perror("Failed communicating with finit");
|
warn("Failed communicating with finit, error %d", errno);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
svc_t *client_svc_find(const char *arg)
|
svc_t *client_svc_find(const char *arg)
|
||||||
{
|
{
|
||||||
return do_cmd(INIT_CMD_SVC_FIND, arg);
|
return do_find(INIT_CMD_SVC_FIND, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
svc_t *client_svc_find_by_cond(const char *arg)
|
svc_t *client_svc_find_by_cond(const char *arg)
|
||||||
{
|
{
|
||||||
return do_cmd(INIT_CMD_SVC_FIND_BYC, arg);
|
return do_find(INIT_CMD_SVC_FIND_BYC, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+5
-1
@@ -1,6 +1,6 @@
|
|||||||
/* External client API, using UNIX domain socket.
|
/* External client API, using UNIX domain socket.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015-2021 Joachim Wiberg <troglobit@gmail.com>
|
* Copyright (c) 2015-2024 Joachim Wiberg <troglobit@gmail.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -29,8 +29,12 @@
|
|||||||
|
|
||||||
int client_connect (void);
|
int client_connect (void);
|
||||||
int client_disconnect (void);
|
int client_disconnect (void);
|
||||||
|
int client_socket (void);
|
||||||
|
|
||||||
|
int client_request (struct init_request *rq, ssize_t len);
|
||||||
int client_send (struct init_request *rq, ssize_t len);
|
int client_send (struct init_request *rq, ssize_t len);
|
||||||
|
int client_command (int cmd);
|
||||||
|
|
||||||
svc_t *client_svc_iterator (int first);
|
svc_t *client_svc_iterator (int first);
|
||||||
svc_t *client_svc_find (const char *arg);
|
svc_t *client_svc_find (const char *arg);
|
||||||
svc_t *client_svc_find_by_cond (const char *arg);
|
svc_t *client_svc_find_by_cond (const char *arg);
|
||||||
|
|||||||
Executable
+11
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# With the daemon mode ('mdev -df') we no longer need the hotplug helper
|
||||||
|
echo "" > /proc/sys/kernel/hotplug
|
||||||
|
|
||||||
|
# Wait for 'mdev -df' to set up its event queue.
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
# Trigger 'add' event for all devices and subsystems to load all modules
|
||||||
|
# and any firmware needed by the hardware.
|
||||||
|
find /sys/devices -name uevent -print | while IFS='' read X; do echo add > $X; done
|
||||||
+235
-43
@@ -21,16 +21,85 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
#include <ftw.h>
|
#include <ftw.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <lite/lite.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#ifdef _LIBITE_LITE
|
||||||
|
# include <libite/lite.h>
|
||||||
|
#else
|
||||||
|
# include <lite/lite.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "cond.h"
|
#include "cond.h"
|
||||||
#include "pid.h"
|
#include "pid.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
|
|
||||||
|
struct cond_boot {
|
||||||
|
TAILQ_ENTRY(cond_boot) link;
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
static TAILQ_HEAD(, cond_boot) cond_boot_list = TAILQ_HEAD_INITIALIZER(cond_boot_list);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse finit.cond=cond[,cond[,...]] from command line. It creates a
|
||||||
|
* temporary linked list of conds which are freed when finit reaches
|
||||||
|
* cond_init(), which calls cond_boot_strap() to realize the conditions
|
||||||
|
* in the file system as regular static conditions. Policy, however,
|
||||||
|
* dictates that these are read-only and should not be possible to
|
||||||
|
* manage from initctl.
|
||||||
|
*/
|
||||||
|
void cond_boot_parse(char *arg)
|
||||||
|
{
|
||||||
|
struct cond_boot *node;
|
||||||
|
|
||||||
|
if (!arg)
|
||||||
|
return;
|
||||||
|
|
||||||
|
node = malloc(sizeof(*node));
|
||||||
|
if (!node) {
|
||||||
|
err(1, "Out of memory cannot track boot conditions");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->name = strdup(arg);
|
||||||
|
TAILQ_INSERT_HEAD(&cond_boot_list, node, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert all conditions read from the kernel command line (above) into
|
||||||
|
* proper finit conditions.
|
||||||
|
*/
|
||||||
|
static void cond_boot_strap(void)
|
||||||
|
{
|
||||||
|
struct cond_boot *node, *tmp;
|
||||||
|
|
||||||
|
TAILQ_FOREACH_SAFE(node, &cond_boot_list, link, tmp) {
|
||||||
|
TAILQ_REMOVE(&cond_boot_list, node, link);
|
||||||
|
if (node->name) {
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
ptr = strtok(node->name, ",");
|
||||||
|
while (ptr) {
|
||||||
|
char cond[strlen(ptr) + 6];
|
||||||
|
|
||||||
|
if (strncmp(ptr, "boot/", 5))
|
||||||
|
snprintf(cond, sizeof(cond), "boot/%s", ptr);
|
||||||
|
else
|
||||||
|
snprintf(cond, sizeof(cond), "%s", ptr);
|
||||||
|
cond_set_oneshot_noupdate(cond);
|
||||||
|
|
||||||
|
ptr = strtok(NULL, ",");
|
||||||
|
}
|
||||||
|
|
||||||
|
free(node->name);
|
||||||
|
}
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The service condition name is constructed from the 'pid/' prefix and
|
* The service condition name is constructed from the 'pid/' prefix and
|
||||||
* the unique NAME:ID tuple that identify each process in Finit. Here
|
* the unique NAME:ID tuple that identify each process in Finit. Here
|
||||||
@@ -106,7 +175,7 @@ static void cond_bump_reconf(void)
|
|||||||
rgen++;
|
rgen++;
|
||||||
|
|
||||||
if (cond_set_gen(_PATH_RECONF, rgen))
|
if (cond_set_gen(_PATH_RECONF, rgen))
|
||||||
_pe("Failed setting %s to gen %d", _PATH_RECONF, rgen);
|
err(1, "Failed setting %s to gen %d", _PATH_RECONF, rgen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cond_checkpath(const char *path)
|
static int cond_checkpath(const char *path)
|
||||||
@@ -116,105 +185,191 @@ static int cond_checkpath(const char *path)
|
|||||||
strlcpy(buf, path, sizeof(buf));
|
strlcpy(buf, path, sizeof(buf));
|
||||||
dir = dirname(buf);
|
dir = dirname(buf);
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
_e("Invalid path '%s' for condition", path);
|
errx(1, "Invalid path '%s' for condition", path);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mkpath(dir, 0755) && errno != EEXIST) {
|
if (mkpath(dir, 0755) && errno != EEXIST) {
|
||||||
_pe("Failed creating dir '%s' for condition '%s'", dir, path);
|
err(1, "Failed creating dir '%s' for condition '%s'", dir, path);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_delete(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftw)
|
||||||
|
{
|
||||||
|
const char *cond, *ptr;
|
||||||
|
|
||||||
|
if (ftw->level == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
ptr = strstr(fpath, COND_BASE);
|
||||||
|
if (!ptr) {
|
||||||
|
warnx("%s does not seem to be a Finit condition, skipping", fpath);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remove(fpath))
|
||||||
|
err(1, "Failed removing condition %s", fpath);
|
||||||
|
|
||||||
|
cond = ptr + strlen(COND_BASE) + 1;
|
||||||
|
cond_update(cond);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cond_delpath(const char *path)
|
||||||
|
{
|
||||||
|
nftw(path, do_delete, 20, FTW_DEPTH);
|
||||||
|
if (remove(path)) {
|
||||||
|
switch (errno) {
|
||||||
|
case ENOENT: /* Ignore */
|
||||||
|
case ENOTEMPTY: /* Only at shutdown and for directories */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err(1, "Failed removing condition path %s", path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int cond_set_path(const char *path, enum cond_state next)
|
int cond_set_path(const char *path, enum cond_state next)
|
||||||
{
|
{
|
||||||
enum cond_state prev;
|
enum cond_state prev;
|
||||||
unsigned int rgen;
|
unsigned int rgen;
|
||||||
|
|
||||||
_d("%s <= %d", path, next);
|
dbg("%s <= %d", path, next);
|
||||||
|
|
||||||
rgen = cond_get_gen(_PATH_RECONF);
|
|
||||||
if (!rgen) {
|
|
||||||
_e("Unable to read configuration generation (%s)", path);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
prev = cond_get_path(path);
|
prev = cond_get_path(path);
|
||||||
|
|
||||||
switch (next) {
|
switch (next) {
|
||||||
case COND_ON:
|
case COND_ON:
|
||||||
if (cond_checkpath(path))
|
if (cond_checkpath(path))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
rgen = cond_get_gen(_PATH_RECONF);
|
||||||
|
if (!rgen) {
|
||||||
|
errx(1, "Unable to read configuration generation (%s)", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
cond_set_gen(path, rgen);
|
cond_set_gen(path, rgen);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COND_OFF:
|
case COND_OFF:
|
||||||
if (unlink(path) && errno != ENOENT)
|
if (unlink(path)) {
|
||||||
_pe("Failed removing condition '%s'", path);
|
switch (errno) {
|
||||||
|
case ENOENT:
|
||||||
|
break;
|
||||||
|
case EISDIR:
|
||||||
|
cond_delpath(path);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err(1, "Failed removing condition '%s'", path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_e("Invalid condition state");
|
errx(1, "Invalid condition state");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return next != prev;
|
return next != prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Should only be used by cond_set*(), cond_clear(), and usr plugin! */
|
/* Should only be used by cond_set*(), cond_clear(), and usr/sys plugins! */
|
||||||
void cond_update(const char *name)
|
int cond_update(const char *name)
|
||||||
{
|
{
|
||||||
svc_t *svc, *iter = NULL;
|
svc_t *svc, *iter = NULL;
|
||||||
|
int affects = 0;
|
||||||
|
|
||||||
_d("%s", name);
|
dbg("%s", name);
|
||||||
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
|
for (svc = svc_iterator(&iter, 1); svc; svc = svc_iterator(&iter, 0)) {
|
||||||
if (!svc_has_cond(svc) || !cond_affects(name, svc->cond))
|
if (!svc_has_cond(svc) || !cond_affects(name, svc->cond))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_d("%s: match <%s> %s(%s)", name ?: "nil", svc->cond, svc->desc, svc->cmd);
|
affects++;
|
||||||
|
dbg("%s: match <%s> %s(%s)", name ?: "nil", svc->cond, svc->desc, svc->cmd);
|
||||||
|
/* Fix bug #314: race condition between crashing services and conditions */
|
||||||
|
if (svc_is_restart(svc) && cond_get_agg(svc->cond) == COND_OFF) {
|
||||||
|
dbg("%s: cancel timer & unblock => WAITING state.", name ?: "nil");
|
||||||
|
service_timeout_cancel(svc);
|
||||||
|
svc_unblock(svc);
|
||||||
|
}
|
||||||
service_step(svc);
|
service_step(svc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return affects;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cond_set_noupdate(const char *name)
|
||||||
|
{
|
||||||
|
dbg("%s", name);
|
||||||
|
if (string_compare(name, "nop"))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!cond_set_path(cond_path(name), COND_ON))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cond_set(const char *name)
|
void cond_set(const char *name)
|
||||||
{
|
{
|
||||||
_d("%s", name);
|
dbg("%s", name);
|
||||||
if (string_compare(name, "nop"))
|
if (cond_set_noupdate(name))
|
||||||
return;
|
|
||||||
|
|
||||||
if (!cond_set_path(cond_path(name), COND_ON))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cond_update(name);
|
cond_update(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cond_set_oneshot(const char *name)
|
int cond_set_oneshot_noupdate(const char *name)
|
||||||
{
|
{
|
||||||
const char *path;
|
const char *path;
|
||||||
|
|
||||||
if (string_compare(name, "nop"))
|
if (string_compare(name, "nop"))
|
||||||
return;
|
return 1;
|
||||||
|
|
||||||
path = cond_path(name);
|
path = cond_path(name);
|
||||||
_d("%s => %s", name, path);
|
dbg("%s => %s", name, path);
|
||||||
|
|
||||||
if (cond_checkpath(path))
|
if (cond_checkpath(path))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (symlink(_PATH_RECONF, path) && errno != EEXIST) {
|
||||||
|
err(1, "Failed creating onshot cond %s", name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cond_set_oneshot(const char *name)
|
||||||
|
{
|
||||||
|
dbg("%s", name);
|
||||||
|
if (cond_set_oneshot_noupdate(name))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (symlink(_PATH_RECONF, path) && errno != EEXIST)
|
|
||||||
_pe("Failed creating onshot cond %s", name);
|
|
||||||
cond_update(name);
|
cond_update(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cond_clear_noupdate(const char *name)
|
||||||
|
{
|
||||||
|
dbg("%s", name);
|
||||||
|
if (string_compare(name, "nop"))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!cond_set_path(cond_path(name), COND_OFF))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void cond_clear(const char *name)
|
void cond_clear(const char *name)
|
||||||
{
|
{
|
||||||
_d("%s", name);
|
dbg("%s", name);
|
||||||
if (string_compare(name, "nop"))
|
if (cond_clear_noupdate(name))
|
||||||
return;
|
|
||||||
|
|
||||||
if (!cond_set_path(cond_path(name), COND_OFF))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cond_update(name);
|
cond_update(name);
|
||||||
@@ -222,12 +377,12 @@ void cond_clear(const char *name)
|
|||||||
|
|
||||||
void cond_reload(void)
|
void cond_reload(void)
|
||||||
{
|
{
|
||||||
_d("");
|
dbg("");
|
||||||
|
|
||||||
cond_bump_reconf();
|
cond_bump_reconf();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int reassert(const char *fpath, const struct stat *sb, int tflg, struct FTW *ftw)
|
static int do_assert(const char *fpath, const struct stat *sb, int tflg, struct FTW *ftw, int set)
|
||||||
{
|
{
|
||||||
char *nm;
|
char *nm;
|
||||||
|
|
||||||
@@ -239,25 +394,56 @@ static int reassert(const char *fpath, const struct stat *sb, int tflg, struct F
|
|||||||
|
|
||||||
nm = strstr((char *)fpath, COND_BASE);
|
nm = strstr((char *)fpath, COND_BASE);
|
||||||
if (!nm) {
|
if (!nm) {
|
||||||
_e("Incorrect condtion path %s, cannot reassert", fpath);
|
errx(1, "Incorrect condition path %s, cannot %sassert", fpath, set ? "re" : "de");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
nm += strlen(COND_BASE);
|
nm += strlen(COND_BASE);
|
||||||
_d("Reasserting %s => %s", fpath, nm);
|
dbg("%sasserting %s => %s", set ? "Re" : "De", fpath, nm);
|
||||||
cond_set(nm);
|
if (set)
|
||||||
|
cond_set(nm);
|
||||||
|
else
|
||||||
|
cond_clear_noupdate(nm); /* important, see netlink plugin! */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int reassert(const char *fpath, const struct stat *sb, int tflg, struct FTW *ftw)
|
||||||
|
{
|
||||||
|
return do_assert(fpath, sb, tflg, ftw, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int deassert(const char *fpath, const struct stat *sb, int tflg, struct FTW *ftw)
|
||||||
|
{
|
||||||
|
return do_assert(fpath, sb, tflg, ftw, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Used only by netlink plugin atm.
|
* Used only by netlink plugin atm.
|
||||||
* type: is a one of pid/, net/, etc.
|
* type: is a one of pid/, net/, etc.
|
||||||
*/
|
*/
|
||||||
void cond_reassert(const char *type)
|
void cond_reassert(const char *pat)
|
||||||
{
|
{
|
||||||
_d("%s", type);
|
dbg("%s", pat);
|
||||||
nftw(cond_path(type), reassert, 20, FTW_DEPTH);
|
nftw(cond_path(pat), reassert, 20, FTW_DEPTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used only by netlink plugin atm.
|
||||||
|
*/
|
||||||
|
void cond_deassert(const char *pat)
|
||||||
|
{
|
||||||
|
dbg("%s", pat);
|
||||||
|
nftw(cond_path(pat), deassert, 20, FTW_DEPTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if we have bootstrapped enough of the system to use conditions.
|
||||||
|
* Will answer 'No' before bootstrap done *and* at shutdown/reboot.
|
||||||
|
*/
|
||||||
|
int cond_is_available(void)
|
||||||
|
{
|
||||||
|
return fisdir(_PATH_COND);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cond_init(void)
|
void cond_init(void)
|
||||||
@@ -265,11 +451,17 @@ void cond_init(void)
|
|||||||
char path[MAX_ARG_LEN];
|
char path[MAX_ARG_LEN];
|
||||||
|
|
||||||
if (mkpath(pid_runpath(_PATH_COND, path, sizeof(path)), 0755) && errno != EEXIST) {
|
if (mkpath(pid_runpath(_PATH_COND, path, sizeof(path)), 0755) && errno != EEXIST) {
|
||||||
_pe("Failed creating condition base directory '%s'", _PATH_COND);
|
err(1, "Failed creating condition base directory '%s'", _PATH_COND);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cond_bump_reconf();
|
cond_bump_reconf();
|
||||||
|
cond_boot_strap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cond_exit(void)
|
||||||
|
{
|
||||||
|
cond_delpath(_PATH_COND);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+6
-2
@@ -21,8 +21,12 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <lite/lite.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#ifdef _LIBITE_LITE
|
||||||
|
# include <libite/lite.h>
|
||||||
|
#else
|
||||||
|
# include <lite/lite.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "finit.h"
|
#include "finit.h"
|
||||||
#include "cond.h"
|
#include "cond.h"
|
||||||
@@ -108,7 +112,7 @@ enum cond_state cond_get_agg(const char *names)
|
|||||||
|
|
||||||
int cond_affects(const char *name, const char *names)
|
int cond_affects(const char *name, const char *names)
|
||||||
{
|
{
|
||||||
static char conds[MAX_COND_LEN];
|
char conds[MAX_COND_LEN];
|
||||||
char *cond;
|
char *cond;
|
||||||
|
|
||||||
if (!name || !names)
|
if (!name || !names)
|
||||||
|
|||||||
+20
-4
@@ -2,15 +2,20 @@
|
|||||||
#define FINIT_COND_H_
|
#define FINIT_COND_H_
|
||||||
|
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
#include <svc.h>
|
|
||||||
|
#include "svc.h"
|
||||||
|
|
||||||
#define COND_BASE "finit/cond"
|
#define COND_BASE "finit/cond"
|
||||||
#define COND_USR "usr/"
|
#define COND_DEV "dev/"
|
||||||
#define COND_PID "pid/"
|
#define COND_PID "pid/"
|
||||||
|
#define COND_SYS "sys/"
|
||||||
|
#define COND_USR "usr/"
|
||||||
|
|
||||||
#define _PATH_COND _PATH_VARRUN COND_BASE "/"
|
#define _PATH_COND _PATH_VARRUN COND_BASE "/"
|
||||||
#define _PATH_CONDUSR _PATH_COND COND_USR
|
#define _PATH_CONDDEV _PATH_COND COND_DEV
|
||||||
#define _PATH_CONDPID _PATH_COND COND_PID
|
#define _PATH_CONDPID _PATH_COND COND_PID
|
||||||
|
#define _PATH_CONDSYS _PATH_COND COND_SYS
|
||||||
|
#define _PATH_CONDUSR _PATH_COND COND_USR
|
||||||
#define _PATH_RECONF _PATH_COND "reconf"
|
#define _PATH_RECONF _PATH_COND "reconf"
|
||||||
|
|
||||||
typedef enum cond_state {
|
typedef enum cond_state {
|
||||||
@@ -28,14 +33,25 @@ enum cond_state cond_get (const char *name);
|
|||||||
enum cond_state cond_get_agg (const char *names);
|
enum cond_state cond_get_agg (const char *names);
|
||||||
int cond_affects (const char *name, const char *names);
|
int cond_affects (const char *name, const char *names);
|
||||||
|
|
||||||
void cond_update (const char *name);
|
void cond_boot_parse (char *arg);
|
||||||
|
int cond_update (const char *name);
|
||||||
int cond_set_path (const char *path, enum cond_state new);
|
int cond_set_path (const char *path, enum cond_state new);
|
||||||
void cond_set (const char *name);
|
void cond_set (const char *name);
|
||||||
void cond_set_oneshot (const char *name);
|
void cond_set_oneshot (const char *name);
|
||||||
void cond_clear (const char *name);
|
void cond_clear (const char *name);
|
||||||
void cond_reload (void);
|
void cond_reload (void);
|
||||||
|
|
||||||
|
int cond_set_noupdate(const char *name);
|
||||||
|
int cond_set_oneshot_noupdate(const char *name);
|
||||||
|
int cond_clear_noupdate(const char *name);
|
||||||
|
|
||||||
void cond_reassert (const char *pat);
|
void cond_reassert (const char *pat);
|
||||||
|
void cond_deassert (const char *pat);
|
||||||
|
|
||||||
|
int cond_is_available(void);
|
||||||
|
|
||||||
void cond_init (void);
|
void cond_init (void);
|
||||||
|
void cond_exit (void);
|
||||||
|
|
||||||
#endif /* FINIT_COND_H_ */
|
#endif /* FINIT_COND_H_ */
|
||||||
|
|
||||||
|
|||||||
+851
-165
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user