Commit graph

370 commits

Author SHA1 Message Date
Daniel Barlow
b5722a0153 gl-ar750: ath10k wireless depends on firmware
so make sure the firmware is present _first_

the ath10k is still broken anyway, looking into why
2024-02-16 00:38:36 +00:00
Daniel Barlow
3c950704e1 rename /run/service-state to /run/services/outputs 2024-02-13 21:41:43 +00:00
Daniel Barlow
16e4b05653 dhcp6c: set preferred and valid address lifetimes
also workaround a bug in rebinding/updates where we get an error
from "ip addr add" trying to add an address that's already present
2024-02-13 13:49:12 +00:00
Daniel Barlow
79926c6fe7 remove call to deleted package 2024-02-12 14:56:12 +00:00
Daniel Barlow
b9c0d93670 build modules at same time as main kernel vmlinux
This changes the practice for building kernel modules: now we expect
that the appropriate Kconfig symbols are set to =m in
config.kernel.config, and then use pkgs.kmodloader to create
a service that loads and unloads all the modules depended on by
a particular requirement.

Note that modules won't be installed on the target device just by
virue of having been built: only the modules that are referenced by a
kmodloader package will be in the closure.

An example may make this clearer: see modules/firewall/default.nix
in this commit.

Why?

If you have a compiled Linux kernel source tree and you change some
symbol from "is not set" to m and then run make modules, you cannot in
general expect that newly compiled module to work. This is because
there are places in the build of the main kernel where it looks to see
which modules _may_ be defined and uses that information to
accommodate them.

For example in an in-kernel build of

  https://github.com/torvalds/linux/blob/master/net/netfilter/core.c#L689

some symbols are defined only if CONFIG_NF_CONNTRACK is set, meaning
this code won't work if we have it unset initially then try later to
enable it and build modules only. Or see

  https://github.com/torvalds/linux/blob/master/include/linux/netdevice.h#L160
2024-02-11 23:47:11 +00:00
Daniel Barlow
812f497660 add kernel.version param to allow for version-specific patches
default to 5.15.137 to avoid breaking the devices that don't declare it
2024-02-11 16:19:52 +00:00
dan
273c66b2d3 Merge pull request 'Add support for TP-Link Archer AX23' (#6) from raboof/liminix:add-archer-ax23-v1-bak into main
Reviewed-on: https://gti.telent.net/dan/liminix/pulls/6
2024-02-08 17:47:46 +00:00
Daniel Barlow
82537bbe68 delete commented-out code 2024-02-07 23:47:38 +00:00
Daniel Barlow
c9e4c1b0da kernel-modules: use linuxArch instead of case expression 2024-02-07 16:20:34 +00:00
Arnout Engelen
61494fdc0c
Add tplink module for creating 'safeloader' images 2024-02-06 17:59:38 +01:00
Daniel Barlow
b0709a6443 systemconfig: fix missing backslashes on env vars 2024-02-04 17:19:03 +00:00
Daniel Barlow
86f5c9b568 schnapps needs util-linux for mount
specifically, it expects mount /dev/foo -o blah /dest to work,
but busybox mount expects options to precede all the other
command line args
2024-02-04 15:50:25 +00:00
Arnout Engelen
04895f9cf6
openwrt: update to v23.05.2 2024-01-25 12:29:03 +01:00
Daniel Barlow
83ee488e4c systemconfig: /boot needs to go inside /persist 2024-01-09 13:10:02 +00:00
Daniel Barlow
c1101d3af5 make extlinux work with liminix-rebuild
add /boot to the systemConfiguration closure
2024-01-08 18:58:07 +00:00
Daniel Barlow
228c0a1668 pass rootOptions config as rootflags= kernel cmdline opt 2024-01-08 18:54:49 +00:00
Daniel Barlow
63f034e362 preinit: parse rootflags= in kernel command line 2024-01-08 00:35:13 +00:00
Daniel Barlow
6971d03520 preinit: check return from write() 2024-01-07 21:24:16 +00:00
Daniel Barlow
c0c4752350 systemconfig "install" cmd honours prefix on source 2024-01-07 16:54:44 +00:00
Daniel Barlow
45e8db09e1 liminix-rebuild: escape brackets in usage message 2024-01-07 14:18:19 +00:00
Daniel Barlow
2a93f24a58 add turris "schnapps" tool
in its current state this is useful for turris omnia only, but will
allow us to do installs and rollback to turris os if needed.
2024-01-05 00:07:01 +00:00
Daniel Barlow
136c5e6f32 alphabetize package list 2024-01-04 10:15:23 +00:00
Daniel Barlow
9369fdf314 use patched qemu only for run-liminix-vm 2024-01-03 17:53:30 +00:00
Daniel Barlow
ff991508ae build kernel only once for multiple outputs
e.g. vmlinux + zImage
2024-01-02 19:40:57 +00:00
Daniel Barlow
d6f96c0448 add libubootenv package 2024-01-02 17:44:56 +00:00
Daniel Barlow
2152a3f207 a test for liminix-rebuild
it's hacky as Selby, but it's better than no test
2023-12-29 22:11:04 +00:00
Daniel Barlow
1a041392aa liminix-rebuild: add --no-reboot param 2023-12-27 17:47:42 +00:00
Daniel Barlow
6469408d5f run-liminix-vm: don't reverse order of --flags params 2023-12-26 21:59:00 +00:00
Daniel Barlow
e5cbc2b86b WIP add systemConfiguration "install" command
which copies the init stuff (whatever it is) from store to /persist
instead of making liminix-rebuild have to know what the files are.

This is principally to ease making a system configuration in /mnt or
similar when operating in a rescue/recovery scenario, and we
don't want to liminix-rebuild because it will reboot
2023-12-23 23:53:47 +00:00
Daniel Barlow
29f35cb902 min-copy-closure: add --root to copy to non-standard place 2023-12-23 23:12:40 +00:00
Daniel Barlow
aecc44aaa0 run-liminix-vm: --flag parameter passes arg straight to qemu 2023-12-23 15:32:59 +00:00
Daniel Barlow
9f851b229c inadvertently committed, remove 2023-12-22 16:25:54 +00:00
Daniel Barlow
4a606a4b19 tidy up kernel patch 2023-12-21 21:12:55 +00:00
Daniel Barlow
9c894bdabf add tftpboot test for mips 2023-12-21 19:25:45 +00:00
Daniel Barlow
a962f18369 run-liminix-vm: map rootfs file iff --phram-address supplied 2023-12-21 19:25:45 +00:00
Daniel Barlow
9a29a042e8 fix tftpboot test on boards without autoboot, swap wan/lan
This is for MIPS.  I spent a while investigating why the second virtio
net device doesn't function in qemu mips malta u-boot, but with no
success. Use the first one instead.
2023-12-21 19:25:16 +00:00
Daniel Barlow
ab0631c555 qemu mips expects different file size for u-boot 2023-12-19 18:48:28 +00:00
Daniel Barlow
32c13c46bb support aarch64 in tftpboot test 2023-12-19 12:12:12 +00:00
Daniel Barlow
ebaa7b2bcb unbreak fennel test 2023-12-09 17:10:41 +00:00
Daniel Barlow
07e66c462b use virtio-bk-pci instead of virtio-bk-device
u-boot is happy with either but Linux can autodetect the PCI-based
hardware
2023-12-09 15:53:40 +00:00
Daniel Barlow
03b17fa3ed add zImage output 2023-12-07 22:31:26 +00:00
Daniel Barlow
a8891461aa use devtmpfs in initramfs
static device nodes don't work with virtio
2023-12-07 20:03:03 +00:00
Daniel Barlow
5adfb0230f WIP generate bootable disk image with partition table 2023-12-05 23:54:09 +00:00
Daniel Barlow
b519bd15df pretty-print the qemu command line
well, pretty-ish
2023-12-05 17:32:18 +00:00
Daniel Barlow
f2daa0b669 exclude rootfs region from kernel-visible ram 2023-12-05 17:32:18 +00:00
Daniel Barlow
f08c10c8ba patch u-boot to add ubifs support
not that we're using it yet
2023-12-04 23:39:27 +00:00
Daniel Barlow
0242cec977 run-liminix-vm: remove unneeded second copy of pad code 2023-12-04 23:37:39 +00:00
Raito Bezarius
644f42c35e kernel: make the build FSAT on FSAT computers
I have 128 threads, builds should take only but a moment!
2023-12-03 23:05:12 +00:00
Daniel Barlow
98d3336926 rewrite run-liminix-vm as a fennel program
the effect of shell quoting/word splitting rules was reaching
completely unreasonable, insofar as I was unable to reason about it
2023-12-03 22:51:39 +00:00
Daniel Barlow
e35b61b68c mac80211: support ath9k pci variant
if you ask for "ath9k" you get AHB, but if you ask for "atk9k_pci"
now you get PCI. Note that the kernel module name is the same in
both cases.
2023-11-25 18:39:15 +00:00
Daniel Barlow
a8f98ccfe7 use linuxArch instead of case statement 2023-11-25 18:16:20 +00:00
Daniel Barlow
3f0f621809 openwrt patches for mvebu (armv7l) 2023-11-24 22:43:58 +00:00
Daniel Barlow
5ba14fd915 add levitate package
sets up a chroot system in tmpfs that will be executed on the next
reboot to enable system maintenance without the regular filesystems
mounted
2023-11-23 22:21:03 +00:00
Daniel Barlow
c8b2d58dd3 exit 0 on service down even if no outputs to delete 2023-11-21 17:25:50 +00:00
Daniel Barlow
f9f4d97bb8 convert flash params to int 2023-11-12 20:39:06 +00:00
Daniel Barlow
abfb35a231 and entryPoint 2023-11-12 18:50:47 +00:00
Daniel Barlow
315907de98 convert hardware loadAddress to int 2023-11-12 18:47:31 +00:00
Daniel Barlow
6489a39424 qemu armv7 2023-11-05 23:19:11 +00:00
Daniel Barlow
c40eef25d6 qemu: use phram instead of block2mtd 2023-11-05 19:13:51 +00:00
Daniel Barlow
c5c5f1687a patch qemu to load uncompressed ARM kernels at correct offset 2023-11-05 11:32:47 +00:00
Daniel Barlow
824536f9b3 in uimage FIT, honour ${arch} 2023-11-05 11:31:28 +00:00
Daniel Barlow
c3ccee6506 preinit: print errno (in hex, it's easier) for failures 2023-11-05 11:27:57 +00:00
Daniel Barlow
6db982f25f preinit: pause before exiting
as explained in the comment, this is to give us a
chance to see error messages before the kernel panics
2023-11-05 11:27:57 +00:00
Daniel Barlow
86a5224f3c preinit: fix compiler warnings 2023-11-05 11:27:43 +00:00
Daniel Barlow
155a29d9b3 preinit: strip trailing newline(s) on /proc/cmdline 2023-11-05 11:27:34 +00:00
Daniel Barlow
d2f517a4e9 preinit.c: reindent 2023-10-19 21:02:18 +01:00
Daniel Barlow
0f38ee0e9c remove PREINIT_USE_LIBC option as it is now the only option 2023-10-19 18:59:02 +01:00
Daniel Barlow
61dc5beca8 preinit: parse rootfstype from kernel command line 2023-10-19 18:56:09 +01:00
Daniel Barlow
8798ee9830 partial fix for timeout handling
1) "Unknown transfer id" message was because the local variable "tid"
is not a transfer id, it is a sequence number  - so the check was
actually comparing expected vs actual acknowledged sequence number,
not TID.  It's still a problem if we get the wrong one, but it
indicates a lost packet (so we should resend) not a packet that was
sent from somewhere else.

2) if the ACK packet has not been received, our retry should involve
_resending_ it, not just trying to wait for it again.

3) I have removed the timeout condition for terminating the resend
loop, because in practice (assuming both ends have the same timeout
setting) all it did was ensure that the loop only ran once. The
timeout is supposed to regulate how long we wait for before retrying
(it doesn't do this, we wait indefinitely), not how long we wait for
before giving up.
2023-10-18 23:35:23 +01:00
Daniel Barlow
629914f65e initial support for ubifs 2023-10-16 19:55:17 +01:00
Daniel Barlow
0693cf23d8 preinit: improve error logging for fork_exec 2023-10-12 19:00:57 +01:00
Daniel Barlow
c341eb46b6 use hostPlatform.linuxArch in kernel derivation 2023-10-12 18:59:45 +01:00
Daniel Barlow
1a369ff3bf preinit: remove no-longer-used mips assembly 2023-10-12 18:57:54 +01:00
Daniel Barlow
bd20f3e419 uimage: make fit optional 2023-10-09 19:47:57 +01:00
Daniel Barlow
c18f07f02f aarch64: make tftpboot work
- patch dtb to add reserved-memory stanza for the phram device to use
  (aarch64 does not accept memmap= command line option)

- patch phram driver to use memremap() instead of ioremap() as
  ioremap can't be used for system ram on arm devices
2023-10-09 19:47:57 +01:00
Daniel Barlow
269e972970 use FIT images not appended DTB for aarch64 uimage 2023-10-07 22:52:09 +01:00
Daniel Barlow
2a5669c2cd enable openwrt mediatek family patches 2023-10-07 22:42:31 +01:00
Daniel Barlow
b01840fa7f add support for mt7915, mt7615 in mac80211 package
mt7915 additionally requires working MTD, so that it can
read calibration data from flash
2023-10-07 22:29:38 +01:00
Daniel Barlow
abd01a7809 apply mtdpslit patch only for openwrt kernel
it doesn't apply to mainline because there's no mtdsplit
in mainline
2023-09-26 18:40:22 +01:00
Daniel Barlow
dfe7228b99 fix jffs2 mtd partition splitting on little-endian CPU 2023-09-26 16:43:03 +01:00
Daniel Barlow
3205a38ac9 mac80211 use correct arch 2023-09-24 00:17:32 +01:00
Daniel Barlow
119d6ad379 pkgconfig is now pkg-config 2023-09-21 12:25:35 +01:00
Daniel Barlow
be22fbbb0a bootable aarch64 liminux with qemu
I may have broken the run-liminix-vm command a bit for MIPS due to
necessary changes in how we pass the command line.  If CI isn't green
for this commit and youre trying the worked examples, I suggest
reverting to the commit before this one.
2023-09-20 22:55:51 +01:00
Daniel Barlow
57eb55de58 found another mips-vm to rename 2023-09-20 19:13:04 +01:00
Daniel Barlow
4389fa15f7 rename mips-vm as run-liminix-vm 2023-09-20 18:33:20 +01:00
Daniel Barlow
4f29bdd3ed detect arch in kernel and uimage
also move kernel builder to pkgs/

FIXME we need to straighten out the mess in calling
dtb.nix/uimage.nix
2023-09-20 18:26:33 +01:00
Daniel Barlow
f7b30939b5 remove service-state when service exits 2023-09-13 22:49:00 +01:00
Daniel Barlow
106a429b3d odhcp-script only write addresses if there are any 2023-09-13 17:51:07 +01:00
Daniel Barlow
b3e505abf4 anoia.system print command if it failed 2023-09-13 17:50:40 +01:00
Daniel Barlow
8f97c5bf3c anoia service :events method behaves as iterator 2023-09-12 20:46:52 +01:00
Daniel Barlow
7904c6bfe9 anoia users now need lfs
... and we need to figure out how to do transitive
dependencies, because this is not a great experience
2023-09-12 18:46:04 +01:00
Daniel Barlow
343d3b6508 writeFennel is writeFennelScript with knobs on
The second parameter is now an options attrset, wherein we will pile
all kinds of cool stuff.

Right now the only cool bit is `mainFunction`, which allows you to
compile a fennel module into a lua script and name the function that
should be executed when the script runs. This makes it easier to
write testable Fennel code, because the test script can require the
module and call stuff in it.
2023-09-12 17:45:18 +01:00
Daniel Barlow
96e19767e9 odhcpc-script don't require fennel at runtime 2023-09-12 17:39:06 +01:00
Daniel Barlow
d49cbbb8ed test for acquire-wan-address 2023-09-11 00:07:49 +01:00
Daniel Barlow
3ff55d3aad odhcp-script: unique subdirectory names for each parsed address 2023-09-10 12:15:34 +01:00
Daniel Barlow
22275f311c anoia: add simple hash function and base64 encoder 2023-09-10 12:14:39 +01:00
Daniel Barlow
870da62a1e anoia.svc outputs may be directories (read as table) 2023-09-09 00:30:02 +01:00
Daniel Barlow
0312f7a999 fennelrepl look for .fnl before .lua
this means fennelrepl in nix-shell will prefer local
source files to generated lua files, making it easier
to change library code without restarting the shell
2023-09-09 00:11:35 +01:00
Daniel Barlow
9dd3cf23b4 anoia.fs.mktree replaces mkdir
This uses lfs to make the tree in-process instead of
shelling out to the mkdir command
2023-09-08 21:17:42 +01:00
Daniel Barlow
4e9227dff3 move rmtree to anoia library 2023-09-08 21:03:18 +01:00
Daniel Barlow
eaa45906ff fennelrepl runs with --correlate
this is so that error message line numbers match up
2023-09-08 21:02:26 +01:00
Daniel Barlow
12e25722fa odhcp-script: delete stale dirs from previous runs
This requires adding LFS as a dependency because native Lua has
no way to iterate a directory, but it seems to be Not Huge and
hopefully we'll have other uses for it
2023-09-08 20:48:01 +01:00
Daniel Barlow
09fe21260e rename fn 2023-09-08 20:48:01 +01:00
Daniel Barlow
4bd3ccc8fd inline write-{addresses,prefixes} 2023-09-08 20:48:01 +01:00
Daniel Barlow
3e163d4253 remove unused fn 2023-09-08 20:47:55 +01:00
Daniel Barlow
9487cb2567 DRY near-duplicate code between parse-{addresses,prefixces} 2023-09-08 20:47:55 +01:00
Daniel Barlow
b25103be2e test script for odhcp6-script 2023-09-08 20:47:55 +01:00
Daniel Barlow
353a199ab2 odhcpc script: parse ADDRESSES and PREFIXES
so downstream doesn't have to
2023-09-05 22:42:25 +01:00
Daniel Barlow
535eb70bb9 convert all route defns to module-based-service 2023-08-31 23:52:59 +01:00
Daniel Barlow
44c1fb7632 delete now-unused (pkgs.liminix.network) interface address 2023-08-31 18:30:22 +01:00
Daniel Barlow
aecbe08f08 add o+x permission on service-state directories
this is needed for resolvconf, which writes resolv.conf as
an output and wants to make it world-readable
2023-08-28 22:02:28 +01:00
Daniel Barlow
1580857fde extract common "interface up" code to a string
so that bridge service can use it
2023-08-28 22:02:28 +01:00
Daniel Barlow
540a1dfd76 remove interface.device
build-time uses can mostly be replaced with interface.name

for runtime uses, switch to $(output ${interface} name)
2023-08-28 22:02:28 +01:00
Daniel Barlow
6da0e67621 create outputs for network interface 2023-08-27 22:41:26 +01:00
Daniel Barlow
485ecc03b0 serviceDefn build function handles dependencies
in a bit of a hacky way, we culd clean this up
2023-08-27 22:40:54 +01:00
Daniel Barlow
81b56fb6a3 new type for interface (presently just alias to service) 2023-08-27 22:39:37 +01:00
Daniel Barlow
2ad203ce1f delete unused functoins in liminix-tools 2023-08-21 19:29:00 +01:00
Daniel Barlow
6f92f8fa8b merge bridge services into one 2023-08-16 23:29:53 +01:00
Daniel Barlow
fbb2c04132 move module-based-service parameter types into service
This is in preparation for writing something that extracts them
into documentation.

user configurations now call config.system.service.foo.build { ...params }
instead of config.system.service.foo

the parameter type definitions themselves now move into the
config stanza of the module referencing the service

new helper function  liminix.callService

The only service moved so far is dnsmasq
2023-08-04 20:39:29 +01:00
Daniel Barlow
648ea5613b use module-based-service for hostapd 2023-07-16 17:51:50 +01:00
Daniel Barlow
669af24247 make a module for dnsmasq 2023-07-14 23:18:21 +01:00
Daniel Barlow
df6cfe1cd5 move pppoe service derivation into ppp module dir 2023-07-14 21:35:59 +01:00
Daniel Barlow
682183a88d move typeChecked into pkgs.liminix.lib 2023-07-14 20:22:29 +01:00
Daniel Barlow
69e6eb5a89 accept attr args to pppoe service, and typecheck them
We use (abuse, arguably) the nixos module system for typechecking.  Un
the plus side, it gives us documentation of the options and their
expected types. On the downside, the error message doesn't tell us
the file in which the error was encountered.

(This is subject to change, if I can find a better way)
2023-07-14 16:53:36 +01:00
Daniel Barlow
a19d12d6d7 fennelrepl add PREFIX/?/init.lua to lua load path 2023-07-08 23:08:25 +01:00
Daniel Barlow
b5cd0cc2d5 fennelrepl: fix bug which introduced whitespace in package.path 2023-07-08 23:08:24 +01:00
Daniel Barlow
0c41e9305c extract service output watcher to fennel module 2023-07-08 23:08:24 +01:00
Daniel Barlow
708350711b allow running scripts using fennelrepl
e.g.

FENNEL_PATH=pkgs/?/init.fnl\;pkgs/?.fnl nix-shell --run "fennelrepl ./examples/acquire-delegated-prefix.fnl /tmp/boo eth1"
2023-07-08 23:08:24 +01:00
Daniel Barlow
2de4d7a8f9 fennel: extract some common functions into a shareable module 2023-07-05 20:23:27 +01:00
Daniel Barlow
c3bb33c9ce add fennelrepl package
Runs fennel using a Lua compiled with the same options as the
host system, and with packages set up so it can find all the local
Lua packages

To shorten the dev feedback loop further, allows FENNEL_PATH to be set
on the command line so you can point directly it at the Fennel sources
for some library you're working against instead of having to run
nix-build and compile them to Lua
2023-07-04 22:58:51 +01:00
Daniel Barlow
24befe6bf7 install fennel from source as a package
nixos lua packaging is giving me a headache
2023-07-04 22:56:17 +01:00
Daniel Barlow
41687e916d rename luaSmall package to lua 2023-07-02 18:19:54 +01:00
Daniel Barlow
3900683413 simplify protocol for watchers of service output directories
Previously: the service wrote a timestamp and the receiver
read and parsed it to see if there was new data

Now: the service writes and removes a .lock file to prevent
the receiver reading partial data. The receiver is responsible
for remembering the *previous* state and only updating if it's changed
2023-07-02 12:09:13 +01:00
Daniel Barlow
9aa5ff6ed1 make a package for odhcpc-script 2023-06-30 20:02:03 +01:00
Daniel Barlow
b6e72504d6 ipv6 default route
needs to specify the ppp0 *peer* address not the local address
2023-06-30 10:17:33 +01:00
Daniel Barlow
c595ae0ccb firewallgen: make nft shebang work 2023-06-27 21:26:23 +01:00
Daniel Barlow
6101f3f3d8 load necessary kernel modules for firewall 2023-06-27 21:18:09 +01:00
Daniel Barlow
591bd78509 extract writeKconfig to its own file 2023-06-26 20:49:43 +01:00
Daniel Barlow
6bc45c2b55 preinit: null-terminate argv array for execve 2023-06-22 09:29:44 +01:00
Daniel Barlow
d79a1e15bb get fennel from source instead of luarocks 2023-06-20 20:19:11 +01:00
Daniel Barlow
a7e7146887 preinit: disable nolibc
- it stopped working with 22.11->23.05
- linking statically against musl is about 17k, so
  this is costing us 11k or so
2023-06-18 23:04:26 +01:00
Daniel Barlow
d66f5901a2 fix nftables syntax 2023-06-18 22:18:44 +01:00
Daniel Barlow
80639a7256 add firewallgen package, which creates an nft script 2023-06-18 17:40:16 +01:00
Daniel Barlow
3f4dbfcfd3 ipv6 prefix delegation for rotuer
much tidying needed, but it works
2023-05-31 23:29:05 +01:00
Daniel Barlow
fdffdbb22a add writeFennelScript function, make ifwait use it 2023-05-29 20:20:12 +01:00
Daniel Barlow
447f068569 partly support getting IPv6 addresses
- gets interface id from ppp
- runs odhcpc to get RA and prefix delegation
- doesn't do anything useful with the data yet
2023-05-24 23:01:50 +01:00
Daniel Barlow
339c2d9873 upgrade to ppp 2.5.0 2023-05-22 23:31:57 +01:00
Daniel Barlow
39b09df4d7 liminix-rebuild: test if nix-build succeeds 2023-05-20 22:30:22 +01:00
Daniel Barlow
ea2f48cfc9 liminix-rebuild copy nix-store-paths to /persist 2023-05-20 21:55:37 +01:00
Daniel Barlow
b0098f1c8e move min-list-garbage into min-collect-garbage pkg
we don't want it in the same package as min-copy-closure as
that depends on bash
2023-05-20 21:55:23 +01:00