From 65fa944df875fbf6828d05406de32996f2199538 Mon Sep 17 00:00:00 2001 From: yukkop Date: Fri, 10 Oct 2025 13:13:03 +0000 Subject: [PATCH] refactor: legacyPackages --- flake.nix | 4 +- legacy/default.nix | 4 + legacy/writer/default.nix | 51 +++++++ legacy/writer/writeDashApplication.nix | 150 +++++++++++++++++++++ nixos/module/hectic/service/sentinèlla.nix | 14 +- nixos/system/devvm-hemar/default.nix | 5 +- nixos/system/devvm-manual/default.nix | 5 +- nixos/system/yukkop/default.nix | 5 +- overlay/default.nix | 85 +++--------- overlay/writeDashApplication.nix | 150 +++++++++++++++++++++ package/default.nix | 4 +- package/printobstacle.nix | 6 - package/printprogress.nix | 6 - package/sentinèlla/base64.sh | 81 +++++++++++ package/sentinèlla/default.nix | 8 +- package/sentinèlla/probe-loop.sh | 85 ------------ package/sentinèlla/sentinel.sh | 8 ++ plot.png | Bin 21508 -> 0 bytes 18 files changed, 497 insertions(+), 174 deletions(-) create mode 100644 legacy/default.nix create mode 100644 legacy/writer/default.nix create mode 100644 legacy/writer/writeDashApplication.nix create mode 100644 overlay/writeDashApplication.nix delete mode 100644 package/printobstacle.nix delete mode 100644 package/printprogress.nix create mode 100644 package/sentinèlla/base64.sh delete mode 100644 plot.png diff --git a/flake.nix b/flake.nix index 26799c7..4e11fbe 100644 --- a/flake.nix +++ b/flake.nix @@ -49,8 +49,8 @@ pkgs, }: { packages.${system} = import ./package { inherit system pkgs self; }; - legacyPackages.${system} = import nixpkgs { inherit system overlays; }; - devShells.${system} = import ./devshell { inherit self system pkgs; }; + legacyPackages.${system} = import ./legacy { inherit system pkgs self; }; + devShells.${system} = import ./devshell { inherit system pkgs self; }; nixosConfigurations = { "devvm-manual|${system}" = import ./nixos/system/devvm-manual/default.nix { inherit flake self inputs system; }; diff --git a/legacy/default.nix b/legacy/default.nix new file mode 100644 index 0000000..6a3dda3 --- /dev/null +++ b/legacy/default.nix @@ -0,0 +1,4 @@ +{ self, system, pkgs }: +{ + writers = pkgs.callPackage ./writer { }; +} diff --git a/legacy/writer/default.nix b/legacy/writer/default.nix new file mode 100644 index 0000000..4a9c488 --- /dev/null +++ b/legacy/writer/default.nix @@ -0,0 +1,51 @@ +{ + lib, + writers, + gcc, +}: let + writeC = name: argsOrScript: + if lib.isAttrs argsOrScript && !lib.isDerivation argsOrScript + then + writers.makeBinWriter ( + argsOrScript + // { + compileScript = '' + # Force gcc to treat the input file as C code + ${gcc}/bin/gcc -fsyntax-only -xc $contentPath + if [ $? -ne 0 ]; then + echo "Syntax check failed" + exit 1 + fi + ${gcc}/bin/gcc -xc -o $out $contentPath + ''; + } + ) + name + else + writers.makeBinWriter { + compileScript = '' + # Force gcc to treat the input file as C code + ${gcc}/bin/gcc -fsyntax-only -xc $contentPath + if [ $? -ne 0 ]; then + echo "Syntax check failed" + exit 1 + fi + ${gcc}/bin/gcc -xc -o $out $contentPath + ''; + } + name + argsOrScript; + writeMinC = name: includes: body: + writeC name '' + ${builtins.concatStringsSep "\n" (map (h: "#include " + h) includes)} + + int main(int argc, char *argv[]) { + ${body} + } + ''; +in { + writeCBin = name: writeC "/bin/${name}"; + writeC = writeC; + writeMinCBin = name: includes: body: writeMinC "/bin/${name}" includes body; + writeMinC = writeMinC; +} diff --git a/legacy/writer/writeDashApplication.nix b/legacy/writer/writeDashApplication.nix new file mode 100644 index 0000000..1d7dbd4 --- /dev/null +++ b/legacy/writer/writeDashApplication.nix @@ -0,0 +1,150 @@ +{ + /* + The name of the script to write. + + Type: String + */ + name, + /* + The shell script's text, not including a shebang. + + Type: String + */ + text, + /* + Inputs to add to the shell script's `$PATH` at runtime. + + Type: [String|Derivation] + */ + runtimeInputs ? [ ], + /* + Extra environment variables to set at runtime. + + Type: AttrSet + */ + runtimeEnv ? null, + /* + `stdenv.mkDerivation`'s `meta` argument. + + Type: AttrSet + */ + meta ? { }, + /* + `stdenv.mkDerivation`'s `passthru` argument. + + Type: AttrSet + */ + passthru ? { }, + /* + The `checkPhase` to run. Defaults to `shellcheck` on supported + platforms and `bash -n`. + + The script path will be given as `$target` in the `checkPhase`. + + Type: String + */ + checkPhase ? null, + /* + Checks to exclude when running `shellcheck`, e.g. `[ "SC2016" ]`. + + See for a list of checks. + + Type: [String] + */ + excludeShellChecks ? [ ], + /* + Extra command-line flags to pass to ShellCheck. + + Type: [String] + */ + extraShellCheckFlags ? [ ], + /* + Bash options to activate with `set -o` at the start of the script. + + Defaults to `[ "errexit" "nounset" "pipefail" ]`. + + Type: [String] + */ + bashOptions ? [ + "errexit" + "nounset" + "pipefail" + ], + /* + Extra arguments to pass to `stdenv.mkDerivation`. + + :::{.caution} + Certain derivation attributes are used internally, + overriding those could cause problems. + ::: + + Type: AttrSet + */ + derivationArgs ? { }, + /* + Whether to inherit the current `$PATH` in the script. + + Type: Bool + */ + inheritPath ? true, +}: +writeTextFile { + inherit + name + meta + passthru + derivationArgs + ; + executable = true; + destination = "/bin/${name}"; + allowSubstitutes = true; + preferLocalBuild = false; + text = + '' + #!${dash}/bin/dash + ${lib.concatMapStringsSep "\n" (option: "set -o ${option}") bashOptions} + '' + + lib.optionalString (runtimeEnv != null) ( + lib.concatStrings ( + lib.mapAttrsToList (name: value: '' + ${lib.toShellVar name value} + export ${name} + '') runtimeEnv + ) + ) + + lib.optionalString (runtimeInputs != [ ]) '' + + export PATH="${lib.makeBinPath runtimeInputs}${lib.optionalString inheritPath ":$PATH"}" + '' + + '' + + ${text} + ''; + + checkPhase = + let + excludeFlags = lib.optionals (excludeShellChecks != [ ]) [ + "--exclude" + (lib.concatStringsSep "," excludeShellChecks) + ]; + # GHC (=> shellcheck) isn't supported on some platforms (such as risc-v) + # but we still want to use writeShellApplication on those platforms + shellcheckCommand = lib.optionalString shellcheck-minimal.compiler.bootstrapAvailable '' + # use shellcheck which does not include docs + # pandoc takes long to build and documentation isn't needed for just running the cli + ${lib.getExe shellcheck-minimal} ${ + lib.escapeShellArgs (excludeFlags ++ extraShellCheckFlags) + } "$target" + ''; + in + if checkPhase == null then + '' + runHook preCheck + #dryrun + ${dash}/bin/dash -n -O extglob "$target" + ${shellcheckCommand} + runHook postCheck + '' + else + checkPhase; +}; diff --git a/nixos/module/hectic/service/sentinèlla.nix b/nixos/module/hectic/service/sentinèlla.nix index 8107023..813c677 100644 --- a/nixos/module/hectic/service/sentinèlla.nix +++ b/nixos/module/hectic/service/sentinèlla.nix @@ -24,6 +24,15 @@ in { urls to check ''; }; + authFile = lib.mkOption { + type = lib.types.path; + example = '' + config.sops.secrets."name-of-service/sentinèlla-probe".path + ''; + description = '' + file with lines: user:pass + ''; + }; volumes = lib.mkOption { type = lib.types.port; description = '' @@ -44,9 +53,10 @@ in { description = '' in case when you do not want show configurations in repository ``` - VOLUMES= - URLS= + VOLUMES= # default: none + URLS= # default: all from df -P PORT= + AUTH_FILE= # lines: user:pass ``` ''; }; diff --git a/nixos/system/devvm-hemar/default.nix b/nixos/system/devvm-hemar/default.nix index f2215b7..b38830b 100644 --- a/nixos/system/devvm-hemar/default.nix +++ b/nixos/system/devvm-hemar/default.nix @@ -9,7 +9,10 @@ name = builtins.baseNameOf ./.; in self.lib.nixpkgs-lib.nixosSystem { - inherit (self.legacyPackages."${system}") pkgs; + pkgs = import inputs.nixpkgs-25-05 { + inherit system; + overlays = [ self.overlays.default ]; + }; modules = [ { networking.hostName = name; } (import ./${name}.nix { inherit flake self inputs; }) diff --git a/nixos/system/devvm-manual/default.nix b/nixos/system/devvm-manual/default.nix index f2215b7..b38830b 100644 --- a/nixos/system/devvm-manual/default.nix +++ b/nixos/system/devvm-manual/default.nix @@ -9,7 +9,10 @@ name = builtins.baseNameOf ./.; in self.lib.nixpkgs-lib.nixosSystem { - inherit (self.legacyPackages."${system}") pkgs; + pkgs = import inputs.nixpkgs-25-05 { + inherit system; + overlays = [ self.overlays.default ]; + }; modules = [ { networking.hostName = name; } (import ./${name}.nix { inherit flake self inputs; }) diff --git a/nixos/system/yukkop/default.nix b/nixos/system/yukkop/default.nix index f2215b7..b38830b 100644 --- a/nixos/system/yukkop/default.nix +++ b/nixos/system/yukkop/default.nix @@ -9,7 +9,10 @@ name = builtins.baseNameOf ./.; in self.lib.nixpkgs-lib.nixosSystem { - inherit (self.legacyPackages."${system}") pkgs; + pkgs = import inputs.nixpkgs-25-05 { + inherit system; + overlays = [ self.overlays.default ]; + }; modules = [ { networking.hostName = name; } (import ./${name}.nix { inherit flake self inputs; }) diff --git a/overlay/default.nix b/overlay/default.nix index 0fa4f7d..0343fc9 100644 --- a/overlay/default.nix +++ b/overlay/default.nix @@ -2,78 +2,31 @@ lib = nixpkgs.lib; in final: prev: ( let - hectic-packages = self.packages.${prev.system}; + packages = self.packages.${prev.system}; + legacyPackages = self.legacyPackages.${prev.system}; in { - hectic = hectic-packages; + hectic = packages; postgresql_17 = prev.postgresql_17 // {pkgs = prev.postgresql_17.pkgs // { - http = hectic-packages.pg-17-ext-http; - pg_smtp_client = hectic-packages.pg-17-ext-smtp-client; - plhaskell = hectic-packages.pg-17-ext-plhaskell; - plsh = hectic-packages.pg-17-ext-plsh; - hemar = hectic-packages.pg-17-ext-hemar; + http = packages.pg-17-ext-http; + pg_smtp_client = packages.pg-17-ext-smtp-client; + plhaskell = packages.pg-17-ext-plhaskell; + plsh = packages.pg-17-ext-plsh; + hemar = packages.pg-17-ext-hemar; };}; postgresql_16 = prev.postgresql_16 // {pkgs = prev.postgresql_16.pkgs // { - http = hectic-packages.pg-16-ext-http; - pg_smtp_client = hectic-packages.pg-16-ext-smtp-client; - plhaskell = hectic-packages.pg-16-ext-plhaskell; - plsh = hectic-packages.pg-16-ext-plsh; - hemar = hectic-packages.pg-16-ext-hemar; + http = packages.pg-16-ext-http; + pg_smtp_client = packages.pg-16-ext-smtp-client; + plhaskell = packages.pg-16-ext-plhaskell; + plsh = packages.pg-16-ext-plsh; + hemar = packages.pg-16-ext-hemar; };}; postgresql_15 = prev.postgresql_15 // {pkgs = prev.postgresql_15.pkgs // { - http = hectic-packages.pg-15-ext-http; - pg_smtp_client = hectic-packages.pg-15-ext-smtp-client; - plhaskell = hectic-packages.pg-15-ext-plhaskell; - plsh = hectic-packages.pg-15-ext-plsh; - hemar = hectic-packages.pg-15-ext-hemar; + http = packages.pg-15-ext-http; + pg_smtp_client = packages.pg-15-ext-smtp-client; + plhaskell = packages.pg-15-ext-plhaskell; + plsh = packages.pg-15-ext-plsh; + hemar = packages.pg-15-ext-hemar; };}; - writers = let - writeC = name: argsOrScript: - if lib.isAttrs argsOrScript && !lib.isDerivation argsOrScript - then - prev.writers.makeBinWriter ( - argsOrScript - // { - compileScript = '' - # Force gcc to treat the input file as C code - ${prev.gcc}/bin/gcc -fsyntax-only -xc $contentPath - if [ $? -ne 0 ]; then - echo "Syntax check failed" - exit 1 - fi - ${prev.gcc}/bin/gcc -xc -o $out $contentPath - ''; - } - ) - name - else - prev.writers.makeBinWriter { - compileScript = '' - # Force gcc to treat the input file as C code - ${prev.gcc}/bin/gcc -fsyntax-only -xc $contentPath - if [ $? -ne 0 ]; then - echo "Syntax check failed" - exit 1 - fi - ${prev.gcc}/bin/gcc -xc -o $out $contentPath - ''; - } - name - argsOrScript; - writeMinC = name: includes: body: - writeC name '' - ${builtins.concatStringsSep "\n" (map (h: "#include " + h) includes)} - - int main(int argc, char *argv[]) { - ${body} - } - ''; - in - prev.writers - // { - writeCBin = name: writeC "/bin/${name}"; - writeC = writeC; - writeMinCBin = name: includes: body: writeMinC "/bin/${name}" includes body; - writeMinC = writeMinC; - }; + writers = prev.writers // legacyPackages.writers; } ) diff --git a/overlay/writeDashApplication.nix b/overlay/writeDashApplication.nix new file mode 100644 index 0000000..1d7dbd4 --- /dev/null +++ b/overlay/writeDashApplication.nix @@ -0,0 +1,150 @@ +{ + /* + The name of the script to write. + + Type: String + */ + name, + /* + The shell script's text, not including a shebang. + + Type: String + */ + text, + /* + Inputs to add to the shell script's `$PATH` at runtime. + + Type: [String|Derivation] + */ + runtimeInputs ? [ ], + /* + Extra environment variables to set at runtime. + + Type: AttrSet + */ + runtimeEnv ? null, + /* + `stdenv.mkDerivation`'s `meta` argument. + + Type: AttrSet + */ + meta ? { }, + /* + `stdenv.mkDerivation`'s `passthru` argument. + + Type: AttrSet + */ + passthru ? { }, + /* + The `checkPhase` to run. Defaults to `shellcheck` on supported + platforms and `bash -n`. + + The script path will be given as `$target` in the `checkPhase`. + + Type: String + */ + checkPhase ? null, + /* + Checks to exclude when running `shellcheck`, e.g. `[ "SC2016" ]`. + + See for a list of checks. + + Type: [String] + */ + excludeShellChecks ? [ ], + /* + Extra command-line flags to pass to ShellCheck. + + Type: [String] + */ + extraShellCheckFlags ? [ ], + /* + Bash options to activate with `set -o` at the start of the script. + + Defaults to `[ "errexit" "nounset" "pipefail" ]`. + + Type: [String] + */ + bashOptions ? [ + "errexit" + "nounset" + "pipefail" + ], + /* + Extra arguments to pass to `stdenv.mkDerivation`. + + :::{.caution} + Certain derivation attributes are used internally, + overriding those could cause problems. + ::: + + Type: AttrSet + */ + derivationArgs ? { }, + /* + Whether to inherit the current `$PATH` in the script. + + Type: Bool + */ + inheritPath ? true, +}: +writeTextFile { + inherit + name + meta + passthru + derivationArgs + ; + executable = true; + destination = "/bin/${name}"; + allowSubstitutes = true; + preferLocalBuild = false; + text = + '' + #!${dash}/bin/dash + ${lib.concatMapStringsSep "\n" (option: "set -o ${option}") bashOptions} + '' + + lib.optionalString (runtimeEnv != null) ( + lib.concatStrings ( + lib.mapAttrsToList (name: value: '' + ${lib.toShellVar name value} + export ${name} + '') runtimeEnv + ) + ) + + lib.optionalString (runtimeInputs != [ ]) '' + + export PATH="${lib.makeBinPath runtimeInputs}${lib.optionalString inheritPath ":$PATH"}" + '' + + '' + + ${text} + ''; + + checkPhase = + let + excludeFlags = lib.optionals (excludeShellChecks != [ ]) [ + "--exclude" + (lib.concatStringsSep "," excludeShellChecks) + ]; + # GHC (=> shellcheck) isn't supported on some platforms (such as risc-v) + # but we still want to use writeShellApplication on those platforms + shellcheckCommand = lib.optionalString shellcheck-minimal.compiler.bootstrapAvailable '' + # use shellcheck which does not include docs + # pandoc takes long to build and documentation isn't needed for just running the cli + ${lib.getExe shellcheck-minimal} ${ + lib.escapeShellArgs (excludeFlags ++ extraShellCheckFlags) + } "$target" + ''; + in + if checkPhase == null then + '' + runHook preCheck + #dryrun + ${dash}/bin/dash -n -O extglob "$target" + ${shellcheckCommand} + runHook postCheck + '' + else + checkPhase; +}; diff --git a/package/default.nix b/package/default.nix index 7b922db..40aba2c 100644 --- a/package/default.nix +++ b/package/default.nix @@ -241,8 +241,6 @@ in { nvim-alias = pkgs.callPackage ./nvim-alias.nix {}; bolt-unpack = pkgs.callPackage ./bolt-unpack.nix {}; nvim-pager = pkgs.callPackage ./nvim-pager.nix {}; - printobstacle = pkgs.callPackage ./printobstacle.nix {}; - printprogress = pkgs.callPackage ./printprogress.nix {}; colorize = pkgs.callPackage ./colorize.nix {}; github-gh-tl = pkgs.callPackage ./github/gh-tl.nix {}; supabase-with-env-collection = pkgs.callPackage ./supabase-with-env-collection.nix {}; @@ -261,7 +259,7 @@ in { "sentinèlla" = pkgs.callPackage (./. + "/sentinèlla") {}; shellplot = pkgs.callPackage ./shellplot {}; sops = pkgs.callPackage ./sops.nix {}; - onlinepubs2man = pkgs.callPackage ./onlinepubs2man {}; + onlinepubs2man = pkgs.callPackage ./onlinepubs2man {}; pg-17-ext-hemar = buildHemarExt pkgs "17"; pg-17-ext-http = buildHttpExt pkgs "17"; pg-17-ext-smtp-client = buildSmtpExt pkgs "17"; diff --git a/package/printobstacle.nix b/package/printobstacle.nix deleted file mode 100644 index 9b5fe2d..0000000 --- a/package/printobstacle.nix +++ /dev/null @@ -1,6 +0,0 @@ -{pkgs, ...}: let - name = "printobstacle"; -in - pkgs.writeShellScriptBin "${name}" '' - printf "%s%s%s\n" "''${RED}" "$*" "''${RESET}" - '' diff --git a/package/printprogress.nix b/package/printprogress.nix deleted file mode 100644 index dd84a95..0000000 --- a/package/printprogress.nix +++ /dev/null @@ -1,6 +0,0 @@ -{pkgs, ...}: let - name = "printprogress"; -in - pkgs.writeShellScriptBin "${name}" '' - printf "%s%s%s\n" "''${YELLOW}" "$*" "''${RESET}" - '' diff --git a/package/sentinèlla/base64.sh b/package/sentinèlla/base64.sh new file mode 100644 index 0000000..e133626 --- /dev/null +++ b/package/sentinèlla/base64.sh @@ -0,0 +1,81 @@ +mod="${1:?}" + +case "$mod" in + encode) + printf '%s' "${2:?}" | od -An -t u1 | tr -s ' ' | tr -d '\n' | awk ' + BEGIN { + A="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + } + function dec2bin(n, r,len,pad) { + if (n==0) return "00000000" + while (n>0) { + r = (n%2) r + n = int(n/2) + } + return sprintf("%08s", r) + } + function bin2dec(s, i,d,r) { + r=0 + for(i=1;i<=length(s);i++) { + d=substr(s,i,1) + r = r*2 + d + } + return r + } + function buildbin(t, r) { + for(i=1;i<=NF;i+=1) { + #printf("%s | %s\n", dec2bin($i), $i) + r = sprintf("%s%s", r, dec2bin($i)) + } + return r + } + function base64(b, r,c) { + for(i=1;i<=length(b);i+=6) { + #printf("%s | %s\n", substr(b,i,6), bin2dec(substr(b,i,6))) + c = substr(A, bin2dec(substr(b,i,6))+1, 1) + r = sprintf("%s%s", r, c) + } + return r + } + { + b=buildbin($1) + l=length(b) + lack = (6 - l % 6) % 6 + for(i=1;i<=lack;i+=1) { + b = sprintf("%s0", b) + } + r = base64(b) + for(i=1;i<=lack/2;i+=1) { + r = sprintf("%s=", r) + } + print r + } + ' + ;; + decode) + printf '%b\n' "$(printf '%s' "${2:?}" | awk ' BEGIN { + A="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + } + function dec2bin(n, r,len,pad) { + if (n==0) return "000000" + while (n>0) { + r = (n%2) r + n = int(n/2) + } + r = sprintf("%6s", r) + gsub(/ /,"0",r) + return r + } + { + for(i=1;i<=length($1);i+=1) { + b=sprintf("%s%s", b, dec2bin(index(A, substr($1,i,1))-1)) + } + for(i=1; i<=length(b); i+=8){ + n=0 + for(j=0;j<8;j++) n = n*2 + (substr(b,i+j,1)=="1") + printf "\\x%02X", n + } + } + ')" + ;; +esac diff --git a/package/sentinèlla/default.nix b/package/sentinèlla/default.nix index 2fd7b3a..92e0ca4 100644 --- a/package/sentinèlla/default.nix +++ b/package/sentinèlla/default.nix @@ -1,5 +1,11 @@ { symlinkJoin, writeShellApplication, socat, dash, hectic, curl }: let + base64 = writeShellApplication { + name = "base64"; + runtimeInputs = [ ]; + text = builtins.readFile ./base64.sh; + }; + # TODO: writeDashApplication probe = writeShellApplication { name = "probe"; @@ -9,7 +15,7 @@ let probe-loop = writeShellApplication { name = "probe-loop"; - runtimeInputs = [ ]; + runtimeInputs = [ base64 ]; text = builtins.readFile ./probe-loop.sh; }; diff --git a/package/sentinèlla/probe-loop.sh b/package/sentinèlla/probe-loop.sh index 1a4e801..66143e8 100644 --- a/package/sentinèlla/probe-loop.sh +++ b/package/sentinèlla/probe-loop.sh @@ -11,91 +11,6 @@ # TIMEOUT=5 # AUTH_FILE="/path/htpasswd-like" # lines: user:pass -base64() { - local mod - mod="${1:?}" - - case "$mod" in - encode) - printf '%s' "${2:?}" | od -An -t u1 | tr -s ' ' | tr -d '\n' | awk ' - BEGIN { - A="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" - } - function dec2bin(n, r,len,pad) { - if (n==0) return "00000000" - while (n>0) { - r = (n%2) r - n = int(n/2) - } - return sprintf("%08s", r) - } - function bin2dec(s, i,d,r) { - r=0 - for(i=1;i<=length(s);i++) { - d=substr(s,i,1) - r = r*2 + d - } - return r - } - function buildbin(t, r) { - for(i=1;i<=NF;i+=1) { - #printf("%s | %s\n", dec2bin($i), $i) - r = sprintf("%s%s", r, dec2bin($i)) - } - return r - } - function base64(b, r,c) { - for(i=1;i<=length(b);i+=6) { - #printf("%s | %s\n", substr(b,i,6), bin2dec(substr(b,i,6))) - c = substr(A, bin2dec(substr(b,i,6))+1, 1) - r = sprintf("%s%s", r, c) - } - return r - } - { - b=buildbin($1) - l=length(b) - lack = (6 - l % 6) % 6 - for(i=1;i<=lack;i+=1) { - b = sprintf("%s0", b) - } - r = base64(b) - for(i=1;i<=lack/2;i+=1) { - r = sprintf("%s=", r) - } - print r - } - ' - ;; - decode) - printf '%b\n' "$(printf '%s' "${2:?}" | awk ' BEGIN { - A="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" - } - function dec2bin(n, r,len,pad) { - if (n==0) return "000000" - while (n>0) { - r = (n%2) r - n = int(n/2) - } - r = sprintf("%6s", r) - gsub(/ /,"0",r) - return r - } - { - for(i=1;i<=length($1);i+=1) { - b=sprintf("%s%s", b, dec2bin(index(A, substr($1,i,1))-1)) - } - for(i=1; i<=length(b); i+=8){ - n=0 - for(j=0;j<8;j++) n = n*2 + (substr(b,i+j,1)=="1") - printf "\\x%02X", n - } - } - ')" - ;; - esac -} - : "${TIMEOUT:=5}" : "${VOLUMES:=$(df -P | awk 'NR>1{print $6}')}" diff --git a/package/sentinèlla/sentinel.sh b/package/sentinèlla/sentinel.sh index 5619f5a..89ea249 100644 --- a/package/sentinèlla/sentinel.sh +++ b/package/sentinèlla/sentinel.sh @@ -1,3 +1,11 @@ #!/bin/dash +TOKEN=8448534574:AAEvsdQqhUDu3RVRJWDGIVeqRmXlB0Dqn1Q +CHAT_ID=380055934 +POLLING_INTERVAL_SEC=${POLLING_INTERVAL_SEC:-3} +while true; do + curl -s -X POST "https://api.telegram.org/bot${TOKEN}/sendMessage" \ + -d "chat_id=${CHAT_ID}" \ + -d text="your message" +done diff --git a/plot.png b/plot.png deleted file mode 100644 index 92bfa0e492c11117ebc7a9777999768dd70ca8ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21508 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