<!DOCTYPE html>
<html>
<head>
<meta http-equiv='content-type' content='text/html;charset=utf8'>
<meta name='generator' content='Ronn-NG/v0.9.1 (http://github.com/apjanke/ronn-ng/tree/0.9.1)'>
<title>klapki(8) - EFI boot manager; or, well, an EFI bootorder compiler.</title>
<style type='text/css' media='all'>
/* style: man */
body#manpage {margin:0}
.mp {max-width:100ex;padding:0 9ex 1ex 4ex}
.mp p,.mp pre,.mp ul,.mp ol,.mp dl {margin:0 0 20px 0}
.mp h2 {margin:10px 0 0 0}
.mp > p,.mp > pre,.mp > ul,.mp > ol,.mp > dl {margin-left:8ex}
.mp h3 {margin:0 0 0 4ex}
.mp dt {margin:0;clear:left}
.mp dt.flush {float:left;width:8ex}
.mp dd {margin:0 0 0 9ex}
.mp h1,.mp h2,.mp h3,.mp h4 {clear:left}
.mp pre {margin-bottom:20px}
.mp pre+h2,.mp pre+h3 {margin-top:22px}
.mp h2+pre,.mp h3+pre {margin-top:5px}
.mp img {display:block;margin:auto}
.mp h1.man-title {display:none}
.mp,.mp code,.mp pre,.mp tt,.mp kbd,.mp samp,.mp h3,.mp h4 {font-family:monospace;font-size:14px;line-height:1.42857142857143}
.mp h2 {font-size:16px;line-height:1.25}
.mp h1 {font-size:20px;line-height:2}
.mp {text-align:justify;background:#fff}
.mp,.mp code,.mp pre,.mp pre code,.mp tt,.mp kbd,.mp samp {color:#131211}
.mp h1,.mp h2,.mp h3,.mp h4 {color:#030201}
.mp u {text-decoration:underline}
.mp code,.mp strong,.mp b {font-weight:bold;color:#131211}
.mp em,.mp var {font-style:italic;color:#232221;text-decoration:none}
.mp a,.mp a:link,.mp a:hover,.mp a code,.mp a pre,.mp a tt,.mp a kbd,.mp a samp {color:#0000ff}
.mp b.man-ref {font-weight:normal;color:#434241}
.mp pre {padding:0 4ex}
.mp pre code {font-weight:normal;color:#434241}
.mp h2+pre,h3+pre {padding-left:0}
ol.man-decor,ol.man-decor li {margin:3px 0 10px 0;padding:0;float:left;width:33%;list-style-type:none;text-transform:uppercase;color:#999;letter-spacing:1px}
ol.man-decor {width:100%}
ol.man-decor li.tl {text-align:left}
ol.man-decor li.tc {text-align:center;letter-spacing:4px}
ol.man-decor li.tr {text-align:right;float:right}
</style>
</head>
<!--
The following styles are deprecated and will be removed at some point:
div#man, div#man ol.man, div#man ol.head, div#man ol.man.
The .man-page, .man-decor, .man-head, .man-foot, .man-title, and
.man-navigation should be used instead.
-->
<body id='manpage'>
<div class='mp' id='man'>
<div class='man-navigation' style='display:none'>
<a href="#NAME">NAME</a>
<a href="#SYNOPSIS">SYNOPSIS</a>
<a href="#DESCRIPTION">DESCRIPTION</a>
<a href="#OPTIONS">OPTIONS</a>
<a href="#ENVIRONMENT">ENVIRONMENT</a>
<a href="#OPS">OPS</a>
<a href="#WISDOM">WISDOM</a>
<a href="#UNINSTALLATION">UNINSTALLATION</a>
<a href="#EXIT-VALUES">EXIT VALUES</a>
<a href="#EXAMPLES">EXAMPLES</a>
<a href="#AUTHOR">AUTHOR</a>
<a href="#SPECIAL-THANKS">SPECIAL THANKS</a>
<a href="#REPORTING-BUGS">REPORTING BUGS</a>
<a href="#SEE-ALSO">SEE ALSO</a>
</div>
<ol class='man-decor man-head man head'>
<li class='tl'>klapki(8)</li>
<li class='tc'></li>
<li class='tr'>klapki(8)</li>
</ol>
<h2 id="NAME">NAME</h2>
<p class="man-name">
<code>klapki</code> - <span class="man-whatis">EFI boot manager; or, well, an EFI bootorder compiler.</span>
</p>
<h2 id="SYNOPSIS">SYNOPSIS</h2>
<p><code>klapki</code> [<code>-nvVEh</code>]… [<code>op</code> [<code>arg</code>…]]…</p>
<h2 id="DESCRIPTION">DESCRIPTION</h2>
<p><a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> generates and manages EFI boot entries on platforms compatible therewith.</p>
<p>This command-line interface is based on running a set of operations (see <a href="#OPS" title="OPS" data-bare-link="true">OPS</a>) which modify the state and context,
then settling the new set-up, then committing it; this means that, barring I/O errors,
<code>{dump}</code>ing after the last operation with <code>-n</code> is an accurate representation of what would be committed without it.</p>
<p>Care is taken to only write what is needed and only when it's needed –
files and wanted entries are hashed with <a class="man-ref" href="https://manpages.debian.org/buster/libssl-doc/SHA1.3ssl.en.html">SHA1<span class="s">(3ssl)</span></a> and only updated on mismatch;
foreign entries are never touched, and <a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> prefers to abandon entries it doesn't understand than to accidentally mangle them.</p>
<p>Minimal state is stored, and it's only supplementary (see <a href="#UNINSTALLATION" title="UNINSTALLATION" data-bare-link="true">UNINSTALLATION</a>).
This means that removing all instances of a kernel boot entry with tools such as <a class="man-ref" href="https://manpages.debian.org/buster/efibootmgr/efibootmgr.8.en.html">efibootmgr<span class="s">(8)</span></a>, the EFI Shell,
or the platform UI will make <a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> forget about the kernel entirely, after minor complaints.</p>
<p><a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a>'s entries <em>can</em> be moved across <code>BootNNNN</code> entries, however, so long as they are kept identical.</p>
<p>The entry description and kernel cmdline are controlled via small executable files, see <a href="#WISDOM" title="WISDOM" data-bare-link="true">WISDOM</a>.</p>
<h2 id="OPTIONS">OPTIONS</h2>
<dl>
<dt><code>-n</code></dt>
<dd>Don't commit – nothing will be written to the filesystem or the firmware.</dd>
<dt><code>-v</code></dt>
<dd>Verbose operation.</dd>
<dt><code>-V</code></dt>
<dd>Very verbose – adds a <code>{dump}</code> op in-between each specified op.</dd>
<dt><code>-E</code></dt>
<dd>Increase libefivar verbosity level.
<p>At time of writing, libefivar supports <code>LOG_VERBOSE</code> and <code>LOG_DEBUG</code>,
which require <code>-E</code> to be specified one and two times, respectively.</p>
<p>See the <a href="#SEE-ALSO" title="SEE ALSO" data-bare-link="true">SEE ALSO</a> sexion for details.</p>
</dd>
<dt><code>-h</code></dt>
<dd>Show a help message with these flags, recognised environment variables (see <a href="#ENVIRONMENT" title="ENVIRONMENT" data-bare-link="true">ENVIRONMENT</a>) and ops (see <a href="#OPS" title="OPS" data-bare-link="true">OPS</a>).</dd>
<dt>
<code>op</code> [<code>arg</code>…]</dt>
<dd>Specify an operation to run and arguments to pass to it.
<p>See <a href="#OPS" title="OPS" data-bare-link="true">OPS</a> for more detail.</p>
</dd>
</dl>
<h2 id="ENVIRONMENT">ENVIRONMENT</h2>
<dl>
<dt>
<code>KLAPKI_HOST</code>=</dt>
<dd>By default, <a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> uses the value found in <code>/etc/machine-id</code>
(or, failing that, the current hostname, as obtained with <a class="man-ref" href="https://manpages.debian.org/buster/manpages-dev/gethostname.2.en.html">gethostname<span class="s">(2)</span></a>)
as the identifier for the host.
<p>If this environment variable is present, it will be used instead;
note, that the host identifier is used verbatim as an EFI variable name
under klapki's GUID (a8a9ad3a-f831-11ea-946d-674ccd7415cc).</p>
</dd>
<dt>
<code>KLAPKI_WISDOM</code>=</dt>
<dd>To obtain the description and cmdline, <a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> invokes respectively-named files under the wisdom root via <a class="man-ref" href="https://manpages.debian.org/buster/manpages-dev/execl.3.en.html">execl<span class="s">(3)</span></a>,
which is <code>/etc/klapki</code> by default. This value overrides that path. If not empty, a '/' is additionally appended before the executable name.
<p>See also <a href="#WISDOM" title="WISDOM" data-bare-link="true">WISDOM</a> below.</p>
</dd>
<dt>
<code>KLAPKI_EFI_ROOT</code>=</dt>
<dd>By default, <a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> puts newly-installed files in <code>\klapki\{host}\{version}</code> under the ESP.
<p>If present, this overrides the constant prefix.
Par exemple, setting <code>KLAPKI_EFI_ROOT</code>= when adding a kernel will put it and the initrds directly under <code>\{host}\{version}</code>
(note that by default this collides with <a class="man-ref" href="https://www.freedesktop.org/software/systemd/man/kernel-install.html">kernel-install<span class="s">(8)</span></a>).</p>
</dd>
</dl>
<h2 id="OPS">OPS</h2>
<dl>
<dt><code>dump</code></dt>
<dd>Write some state (boot order, total boot entries, boot position, each wanted entry, boot variants)
and context (our kernels, fresh kernels, deleted files) to the standard output.</dd>
<dt>
<code>bootpos</code> <<code>position</code>></dt>
<dd>Change the boot position to 0-based <<code>position</code>>.
<p>The cluster of entries for the current host can be placed at any point in the boot order;
it's 0 (i.e. at the beginning) by default, but if you have another operating system or boot-loader and wish to have it be the default,
you can simply move <a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> down the required amount of entries.</p>
<p>See description of addvariant below for sorting inside the cluster.</p>
</dd>
<dt>
<code>addkernel</code> <<code>version</code>> <<code>image</code>> [<code>initrd</code>…] <<code>""</code>></dt>
<dd>Allocate entries for the kernel with version <<code>version</code>> whose image resides at <<code>image</code>> and initrds at [<code>initrd</code>]….
The list of initrds is terminated with an empty argument.
<p>This directive is ignored if a kernel with version <<code>version</code>> is already known. See delkernel below.</p>
<p>The kernel image and initrds will be copied to the ESP (see <code>KLAPKI_EFI_ROOT</code>= in <a href="#ENVIRONMENT" title="ENVIRONMENT" data-bare-link="true">ENVIRONMENT</a>) during context commit.</p>
</dd>
<dt>
<code>delkernel</code> <<code>version</code>></dt>
<dd>Purge all entries for which the version is <<code>version</code>>.
<p>The kernel image, initrds and containing folder will, if not used, be removed from the ESP during context commit.</p>
</dd>
<dt>
<code>addvariant</code> <<code>variant</code>></dt>
<dd>Add an explicit variant <<code>variant</code>> to the end, if not already known. Accompanying boot entries will be allocated in the derivation phase as needed.
<p>Variants are a global property, and a boot entry is generated for each variant
(that is: for the implicit variant, represented by the empty string, in addition to any configured explicit variants).</p>
<p>The order of explicit variants is preserved within each version group, which are sorted highest-to-lowest.
For example: a host with two kernels (<em>5.8.0-[12]-amd64</em>) and two explicit variants (<em>debug</em>, <em>silent</em>) will produce the following entries
(assume <code>$KLAPKI_WISDOM/description</code> linked to <code>/bin/echo</code>); note how the highest kernel version is at the top:<br>
5.8.0-2-amd64<br>
5.8.0-2-amd64 debug<br>
5.8.0-2-amd64 silent<br>
5.8.0-1-amd64<br>
5.8.0-1-amd64 debug<br>
5.8.0-1-amd64 silent</p>
<p>After running <a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> with "<em>delvariant debug addvariant debug</em>", the two explicit variants are now ordered differently (<em>silent</em>, <em>debug</em>),
and this is reflected in the boot order; note also how the implicit variant always sorts earlier than any explicit ones:<br>
5.8.0-2-amd64<br>
5.8.0-2-amd64 silent<br>
5.8.0-2-amd64 debug<br>
5.8.0-1-amd64<br>
5.8.0-1-amd64 silent<br>
5.8.0-1-amd64 debug</p>
</dd>
<dt>
<code>delvariant</code> <<code>variant</code>></dt>
<dd>Remove explicit variant <<code>variant</code>>, if any; accompanying boot entries will purged in the derivation phase as needed.</dd>
</dl>
<h2 id="WISDOM">WISDOM</h2>
<p>The entry description and kernel cmdline are acquired by executing <code>description</code> and <code>cmdline</code> in <code>/etc/klapki</code> (or <code>KLAPKI_WISDOM=</code>, see <a href="#ENVIRONMENT" title="ENVIRONMENT" data-bare-link="true">ENVIRONMENT</a>)
with the following arguments:<br>
0: "description" or "cmdline"<br>
1: kernel version<br>
2: boot variant</p>
<p>And the standard output tied to a memfd (see <a class="man-ref" href="https://manpages.debian.org/buster/manpages-dev/memfd_create.2.en.html">memfd_create<span class="s">(2)</span></a>), which is then trimmed, and all newlines are replaced with a single space.</p>
<p><a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> stops processing if the child exits with a non-zero status or is killed by a signal.
The special exit value 0x6B (107, ASCII 'k') is used to signal an error in <a class="man-ref" href="https://manpages.debian.org/buster/manpages-dev/execl.3.en.html">execl<span class="s">(3)</span></a>ing the wisdom binary.</p>
<p>Additional <code>initrd=</code> statements <em>should</em> work (with warnings, since the should.
Please report on the bug tracker/mailing list (see <a href="#REPORTING-BUGS" title="REPORTING BUGS" data-bare-link="true">REPORTING BUGS</a>) if you use them successfully!) and will not be managed by <a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a>,</p>
<p>The simplest <code>/etc/klapki/description</code> would be a link to <code>/bin/echo</code>.
A simple <code>cmdline</code> is a <code>/bin/sh</code> shebang + <code>echo</code> command.
A cursed <code>cmdline</code> would be a <code>/bin/sh</code> shebang and an <code>awk '{gsub(/initrd=[^ ]+ ?/, ""); print}' /proc/cmdline</code> command.</p>
<h2 id="UNINSTALLATION">UNINSTALLATION</h2>
<p>Remove the EFI variable corresponding to the host (see <a href="#ENVIRONMENT" title="ENVIRONMENT" data-bare-link="true">ENVIRONMENT</a>) under klapki's GUID (a8a9ad3a-f831-11ea-946d-674ccd7415cc).
This will purge the state for the host and hence abandon any entries left over, which remain bootable;
to remove all klapki entries run <code>{delkernel}</code> first (see <a href="#OPS" title="OPS" data-bare-link="true">OPS</a>), or remove them manually from the ESP and firmware afterward.</p>
<p>On Linux this involves running <code>chattr -i</code>, then <code>rm</code> on <code>/sys/firmware/efi/efivars/{KLAPKI_HOST}-a8a9ad3a-f831-11ea-946d-674ccd7415cc</code>.</p>
<h2 id="EXIT-VALUES">EXIT VALUES</h2>
<pre><code>1 - error reading configuration,
2 - error loading state,
3 - error resolving state,
4 - error running an op,
5 - error in propagation phase,
6 - error in aging phase,
7 - error in wisening phase,
8 - error in saving phase,
9 - error committing context,
10 - error committing state.
</code></pre>
<h2 id="EXAMPLES">EXAMPLES</h2>
<p>A simple set-up:</p>
<pre><code>root@zoot:~# ls -l description cmdline
-rwxr-xr-x 1 root root 79 Sep 21 03:30 cmdline
lrwxrwxrwx 1 root root 9 Sep 20 04:30 description -> /bin/echo
root@zoot:~# cat cmdline
#!/bin/sh
echo root=ZFS=zoot/root console=ttyS0
</code></pre>
<p>Add a kernel with a single initrd and a variant:</p>
<pre><code>root@zoot:~# KLAPKI_HOST=zoot klapki addkernel 5.8.0-2-amd64 /boot/vmlinuz-5.8.0-2-amd64 /boot/initrd.img-5.8.0-2-amd64 "" addvariant debug
EFI load: no config for this host (zoot) found; going to the top
Entry 000B changed
Entry 000D changed
Entry 000B: copied vmlinuz-5.8.0-2-amd64 from /boot to \klapki\zoot\5.8.0-2-amd64\
Entry 000B: copied initrd.img-5.8.0-2-amd64 from /boot to \klapki\zoot\5.8.0-2-amd64\
Updating state config
Updating boot order
Writing entry 000B
Writing entry 000D
</code></pre>
<p>Success! But the new "debug" entry doesn't really do much:</p>
<pre><code>root@zoot:~# efibootmgr
BootCurrent: 000D
Timeout: 0 seconds
BootOrder: 000B,000D,000C,000A,0000,0001,0002,0003,0004,0005,0006,0007,0008,0009
Boot0000 through Boot0008 omitted
Boot0009* EFI Internal Shell FvVol(7cb8bdc9-f8eb-4f34-aaea-3ee4af6516a1)/FvFile(7c04a583-9e3e-4f1c-ad65-e05268d0b4d1)
Boot000A* Linux Boot Manager HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\EFI\systemd\systemd-bootx64.efi)
Boot000B* 5.8.0-2-amd64 HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\klapki\zoot\5.8.0-2-amd64\vmlinuz-5.8.0-2-amd64)i.n.i.t.r.d.=.\.k.l.a.p.k.i.\.z.o.o.t.\.5...8...0.-.2.-.a.m.d.6.4.\.i.n.i.t.r.d...i.m.g.-.5...8...0.-.2.-.a.m.d.6.4. .r.o.o.t.=.Z.F.S.=.z.o.o.t./.r.o.o.t. .c.o.n.s.o.l.e.=.t.t.y.S.0.
Boot000C* zoot 5.8.0-1-amd64 HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\62dd03a4928c412180b3024ac6c03a90\5.8.0-1-amd64\linux)i.n.i.t.r.d.=.\.6.2.d.d.0.3.a.4.9.2.8.c.4.1.2.1.8.0.b.3.0.2.4.a.c.6.c.0.3.a.9.0.\.5...8...0.-.1.-.a.m.d.6.4.\.i.n.i.t.r.d...i.m.g.-.5...8...0.-.1.-.a.m.d.6.4. .r.o.o.t.=.Z.F.S.=.z.o.o.t./.r.o.o.t. .c.o.n.s.o.l.e.=.t.t.y.S.0.
Boot000D* 5.8.0-2-amd64 debug HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\klapki\zoot\5.8.0-2-amd64\vmlinuz-5.8.0-2-amd64)i.n.i.t.r.d.=.\.k.l.a.p.k.i.\.z.o.o.t.\.5...8...0.-.2.-.a.m.d.6.4.\.i.n.i.t.r.d...i.m.g.-.5...8...0.-.2.-.a.m.d.6.4. .r.o.o.t.=.Z.F.S.=.z.o.o.t./.r.o.o.t. .c.o.n.s.o.l.e.=.t.t.y.S.0.
</code></pre>
<p>Uncontrivedly, adding a conditional with another argument to enable debugging in the Intel PRO/100 driver and re-running <a class="man-ref" href="klapki.8.html">klapki<span class="s">(8)</span></a> will work:</p>
<pre><code>root@zoot:~# cat cmdline
#!/bin/sh
echo root=ZFS=zoot/root console=ttyS0
[ "$2" = "debug" ] && echo e100.debug=16 || :
root@zoot:~# KLAPKI_WISDOM=. KLAPKI_HOST=zoot klapki
Entry 000D changed
Updating state config
Updating entry 000D
</code></pre>
<p>Note, that, as expected, only the state configuration (which stores the hash of the wanted entry) and the debug entry itself was updated:</p>
<pre><code>root@zoot:~# efibootmgr -v
BootCurrent: 000D
Timeout: 0 seconds
BootOrder: 000B,000D,000C,000A,0000,0001,0002,0003,0004,0005,0006,0007,0008,0009
Boot0000 through Boot000A and Boot000C omitted
Boot000B* 5.8.0-2-amd64 HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\klapki\zoot\5.8.0-2-amd64\vmlinuz-5.8.0-2-amd64)i.n.i.t.r.d.=.\.k.l.a.p.k.i.\.z.o.o.t.\.5...8...0.-.2.-.a.m.d.6.4.\.i.n.i.t.r.d...i.m.g.-.5...8...0.-.2.-.a.m.d.6.4. .r.o.o.t.=.Z.F.S.=.z.o.o.t./.r.o.o.t. .c.o.n.s.o.l.e.=.t.t.y.S.0.
Boot000D* 5.8.0-2-amd64 debug HD(1,GPT,0655a4fb-e2e9-4fa6-b37b-a52633aed855,0x800,0x76800)/File(\klapki\zoot\5.8.0-2-amd64\vmlinuz-5.8.0-2-amd64)i.n.i.t.r.d.=.\.k.l.a.p.k.i.\.z.o.o.t.\.5...8...0.-.2.-.a.m.d.6.4.\.i.n.i.t.r.d...i.m.g.-.5...8...0.-.2.-.a.m.d.6.4. .r.o.o.t.=.Z.F.S.=.z.o.o.t./.r.o.o.t. .c.o.n.s.o.l.e.=.t.t.y.S.0. .e.1.0.0...d.e.b.u.g.=.1.6.
</code></pre>
<h2 id="AUTHOR">AUTHOR</h2>
<p>Written by наб <<a href="mailto:nabijaczleweli@nabijaczleweli.xyz" data-bare-link="true">nabijaczleweli@nabijaczleweli.xyz</a>></p>
<h2 id="SPECIAL-THANKS">SPECIAL THANKS</h2>
<p>To all who support further development, in particular:</p>
<ul>
<li>ThePhD</li>
<li>Embark Studios</li>
</ul>
<h2 id="REPORTING-BUGS">REPORTING BUGS</h2>
<p><<a href="https://todo.sr.ht/~nabijaczleweli/klapki" data-bare-link="true">https://todo.sr.ht/~nabijaczleweli/klapki</a>></p>
<p><<a href="mailto:~nabijaczleweli/klapki@lists.sr.ht" data-bare-link="true">~nabijaczleweli/klapki@lists.sr.ht</a>>, archived at <<a href="https://lists.sr.ht/~nabijaczleweli/klapki" data-bare-link="true">https://lists.sr.ht/~nabijaczleweli/klapki</a>></p>
<h2 id="SEE-ALSO">SEE ALSO</h2>
<p><<a href="https://git.sr.ht/~nabijaczleweli/klapki" data-bare-link="true">https://git.sr.ht/~nabijaczleweli/klapki</a>></p>
<p>UEFI specification, Sexion 3.1.3 Load Options and related:
<<a href="https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf" data-bare-link="true">https://uefi.org/sites/default/files/resources/UEFI_Spec_2_8_final.pdf</a>></p>
<p>libefivar verbosity levels:
<<a href="https://github.com/rhboot/efivar/blob/36297adcb266f07bb06e725a0da377bc6e6aedd0/src/util.h#L328" data-bare-link="true">https://github.com/rhboot/efivar/blob/36297adcb266f07bb06e725a0da377bc6e6aedd0/src/util.h#L328</a>></p>
<ol class='man-decor man-foot man foot'>
<li class='tl'></li>
<li class='tc'>September 2020</li>
<li class='tr'>klapki(8)</li>
</ol>
</div>
</body>
</html>