From d5ccecf0384a51f3b6c0a2c4c952d9100d30edeb Mon Sep 17 00:00:00 2001
From: Daniel Barlow <dan@telent.net>
Date: Mon, 26 Sep 2022 14:13:23 +0100
Subject: [PATCH] make "shutdown" work

create a package for the s6-compatible shutdown/halt/poweroff
commands and put it on the path ahead of busybox
---
 THOUGHTS.txt                   |  4 ++--
 make-image.nix                 |  4 ++--
 overlay.nix                    |  2 ++
 pkgs/s6-init-bin/default.nix   | 33 +++++++++++++++++++++++++++++++++
 pkgs/s6-init-files/default.nix | 14 +-------------
 5 files changed, 40 insertions(+), 17 deletions(-)
 create mode 100644 pkgs/s6-init-bin/default.nix

diff --git a/THOUGHTS.txt b/THOUGHTS.txt
index c1c4cfe50..1585c4cec 100644
--- a/THOUGHTS.txt
+++ b/THOUGHTS.txt
@@ -75,7 +75,7 @@ Sun Sep 25 20:56:28 BST 2022
 
 TODO - bugs, missing bits, other infelicities as they occur to me:
 
-1) shutdown doesn't work as its using the busybox one not s6.
+DONE 1) shutdown doesn't work as its using the busybox one not s6.
 
 2) perhaps we shouldn't have process-based services like dhcp, ppp
 implement "address provider interface" - instead have a separate
@@ -120,7 +120,7 @@ we want to change the pseudofiles in an overlay?
 is that specified or fluke?
 
 16) tighten up the module specs. (DONE) services.foo should be a s6-rc
-service, kernel config should be checked in some way
+service, (DONE) kernel config should be checked in some way
 
 DONE 17) rename nixwrt references in kernel builder
 
diff --git a/make-image.nix b/make-image.nix
index 4b6249b0c..1ba202127 100644
--- a/make-image.nix
+++ b/make-image.nix
@@ -39,7 +39,7 @@ let
   };
   s6-pseudofiles = pkgs.s6-init-files;
   profile  = writeScript ".profile" ''
-    PATH=${lib.makeBinPath (with pkgs; [busybox execline s6-linux-init s6-rc])}
+    PATH=${lib.makeBinPath (with pkgs; [ s6-init-bin busybox execline s6-linux-init s6-rc])}
     export PATH
   '';
   pseudofiles = writeText "pseudofiles" ''
@@ -60,7 +60,7 @@ let
      /sys d 0555 root root
      /dev/pts d 0755 0 0
      /etc/init.d d 0755 0 0
-     /bin/init s 0755 0 0 /etc/s6-linux-init/current/bin/init
+     /bin/init s 0755 0 0 ${pkgs.s6-init-bin}/bin/init
      /bin/sh s 0755 0 0 ${pkgs.pkgsStatic.busybox}/bin/sh
      /bin/busybox s 0755 0 0 ${pkgs.busybox}/bin/busybox
      /etc/s6-rc d 0755 0 0
diff --git a/overlay.nix b/overlay.nix
index d8dd4735c..22c984466 100644
--- a/overlay.nix
+++ b/overlay.nix
@@ -8,6 +8,8 @@ final: prev: {
   };
   writeAshScript = final.callPackage ./pkgs/write-ash-script {};
 
+  s6-init-bin =  final.callPackage ./pkgs/s6-init-bin {};
+
   pppoe = prev.rpPPPoE.overrideAttrs (o: {
     # use newer rp-pppoe, it builds cleanly
     src = final.fetchFromGitHub {
diff --git a/pkgs/s6-init-bin/default.nix b/pkgs/s6-init-bin/default.nix
new file mode 100644
index 000000000..3feed9124
--- /dev/null
+++ b/pkgs/s6-init-bin/default.nix
@@ -0,0 +1,33 @@
+{
+  s6-linux-init
+, execline
+, writeScript
+, stdenvNoCC
+, lib
+, busybox
+, s6-rc
+}:
+let
+  hpr = name: arg: writeScript name ''
+    #!${execline}/bin/execlineb -S0
+    ${s6-linux-init}/bin/s6-linux-init-hpr ${arg} \$@
+  '';
+  init = writeScript "init" ''
+    #!${execline}/bin/execlineb -S0
+    ${s6-linux-init}/bin/s6-linux-init -c /etc/s6-linux-init/current -m 0022 -p ${lib.makeBinPath [busybox execline s6-linux-init s6-rc]}:/usr/bin:/bin -d /dev -- "\$@"
+  '';
+in stdenvNoCC.mkDerivation {
+  name = "s6-init-bin";
+  phases = ["installPhase"];
+  installPhase = ''
+    bin=$out/bin
+    mkdir -p $bin
+    cd $bin
+    ln -s ${s6-linux-init}/bin/s6-linux-init-shutdown shutdown
+    ln -s ${s6-linux-init}/bin/s6-linux-init-telinit telinit
+    ln -s ${hpr "reboot" "-r"} reboot
+    ln -s ${hpr "poweroff" "-p"} poweroff
+    ln -s ${hpr "halt" "-h"} halt
+    ln -s ${init} init
+  '';
+}
diff --git a/pkgs/s6-init-files/default.nix b/pkgs/s6-init-files/default.nix
index 0d5f51428..f4ac72d37 100644
--- a/pkgs/s6-init-files/default.nix
+++ b/pkgs/s6-init-files/default.nix
@@ -23,18 +23,6 @@ let
   };
   dir = contents: { type = "d"; inherit contents; };
   symlink = target: { type = "s"; inherit target; };
-  hpr = arg: "#!${execline}/bin/execlineb -S0\n${s6-linux-init}/bin/s6-linux-init-hpr ${arg} \$@";
-  bin = dir {
-    shutdown = symlink "${s6-linux-init}/bin/s6-linux-init-shutdown";
-    telinit = symlink "${s6-linux-init}/bin/s6-linux-init-telinit";
-    reboot = { type="f"; file = hpr "-r"; mode="0755"; };
-    poweroff = { type="f"; file = hpr "-p"; mode="0755"; };
-    halt = { type="f"; file = hpr "-h"; mode="0755"; };
-    init = {
-      type="f"; mode="0755";
-      file = "#!${execline}/bin/execlineb -S0\n${s6-linux-init}/bin/s6-linux-init -c /etc/s6-linux-init/current -m 0022 -p ${lib.makeBinPath [busybox execline s6-linux-init s6-rc]}:/usr/bin:/bin -d /dev -- \"\\$@\"";
-    };
-  };
   scripts = symlink "${initscripts}/scripts";
   env = dir {};
   run-image = dir {
@@ -150,7 +138,7 @@ let
     uncaught-logs = (dir {}) // {mode = "2750";};
   };
   structure = { etc = dir { s6-linux-init = dir { current = dir {
-    inherit bin scripts env run-image;
+    inherit scripts env run-image;
   };};};};
 
 in pseudofile "pseudo.s6-init" structure