commit 5d7802cdfdb06df1e48852487cdc922da0148c61 Author: RGBCube Date: Wed May 15 13:02:25 2024 +0300 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9bb20ad --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +* + +!src/ + +!.gitignore + +!*.lock +!*.nix +!*.zig +!*.zon diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..c88cc53 --- /dev/null +++ b/build.zig @@ -0,0 +1,41 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const exe = b.addExecutable(.{ + .name = "crash", + .root_source_file = b.path("src/main.zig"), + .target = target, + .optimize = optimize, + }); + + const opts = b.addOptions(); + opts.addOption(?[]const u8, "fallback_shell", b.option([]const u8, "fallback_shell", "The fallback shell crash will use if it can't read the environment or the variable isn't found")); + exe.root_module.addOptions("build_options", opts); + + b.installArtifact(exe); + + const run_cmd = b.addRunArtifact(exe); + + run_cmd.step.dependOn(b.getInstallStep()); + + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const run_step = b.step("run", "Run the program"); + run_step.dependOn(&run_cmd.step); + + const exe_unit_tests = b.addTest(.{ + .root_source_file = b.path("src/main.zig"), + .target = target, + .optimize = optimize, + }); + + const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests); + + const test_step = b.step("test", "Run unit tests"); + test_step.dependOn(&run_exe_unit_tests.step); +} diff --git a/build.zig.zon b/build.zig.zon new file mode 100644 index 0000000..efa94ad --- /dev/null +++ b/build.zig.zon @@ -0,0 +1,10 @@ +.{ + .name = "crash", + .version = "0.0.1", + + .minimum_zig_version = "0.12.0", + + .paths = .{ + "", + }, +} diff --git a/build.zig.zon.nix b/build.zig.zon.nix new file mode 100644 index 0000000..441b465 --- /dev/null +++ b/build.zig.zon.nix @@ -0,0 +1,6 @@ +# generated by zon2nix (https://github.com/nix-community/zon2nix) + +{ linkFarm, fetchzip }: + +linkFarm "zig-packages" [ +] diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..f90f977 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1715653339, + "narHash": "sha256-7lR9tpVXviSccl07GXI0+ve/natd24HAkuy1sQp0OlI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "abd6d48f8c77bea7dc51beb2adfa6ed3950d2585", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..eb7b337 --- /dev/null +++ b/flake.nix @@ -0,0 +1,28 @@ +{ + description = "Crash"; + + nixConfig = { + extra-substituters = "https://cache.garnix.io/"; + extra-trusted-public-keys = "cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g="; + }; + + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + + outputs = { nixpkgs, ... }: with nixpkgs.lib; foldl' recursiveUpdate {} (map (system: let + pkgs = import nixpkgs { inherit system; }; + in { + devShell.${system} = pkgs.mkShell { + packages = with pkgs; [ + zig_0_12 + zls + zon2nix + ]; + }; + + packages.${system} = rec { + crash = pkgs.callPackage ./package.nix {}; + default = crash; + }; + + }) [ "x86_64-linux" "aarch64-linux" "riscv64-linux" ]); +} diff --git a/package.nix b/package.nix new file mode 100644 index 0000000..da12f22 --- /dev/null +++ b/package.nix @@ -0,0 +1,41 @@ +{ + lib, + stdenvNoCC, + callPackage, + + zig_0_12, + optimize ? "ReleaseFast", + + bash, + fallbackShell ? bash, +}: + +stdenvNoCC.mkDerivation { + name = "crash"; + version = lib.head (lib.strings.match ''.*\.version = "([^"]*)".*'' (lib.readFile ./build.zig.zon)); + + src = ./.; + + nativeBuildInputs = [ zig_0_12 ]; + + dontConfigure = true; + dontInstall = true; + + preBuild = '' + mkdir -p .cache + ln -s ${callPackage ./build.zig.zon.nix {}} .cache/p + ''; + + buildPhase = '' + runHook preBuild + + zig build install \ + --cache-dir $(pwd)/zig-cache \ + --global-cache-dir $(pwd)/.cache \ + --prefix $out \ + -Doptimize=${optimize} \ + -Dfallback_shell=${lib.getExe fallbackShell} + + runHook postBuild + ''; +} diff --git a/src/main.zig b/src/main.zig new file mode 100644 index 0000000..c958a89 --- /dev/null +++ b/src/main.zig @@ -0,0 +1,26 @@ +const std = @import("std"); +const fallback_shell = @import("build_options").fallback_shell orelse @compileError("fallback shell was not specified"); + +pub fn fallback(alloc: std.mem.Allocator) noreturn { + const err = std.process.execv(alloc, &[_][]const u8{fallback_shell}); + std.process.exit(@intCast(@intFromError(err))); +} + +pub fn main() noreturn { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + const alloc = gpa.allocator(); + + const shells = std.posix.getenv("SHELLS") orelse fallback(alloc); + + var it = std.mem.split(u8, shells, ":"); + while (it.next()) |shell| { + var child = std.process.Child.init(&[_][]const u8{shell}, alloc); + + switch (child.spawnAndWait() catch fallback(alloc)) { + std.process.Child.Term.Exited => |exit_code| if (exit_code == 0) std.process.exit(0), + else => continue, + } + } + + fallback(alloc); +}