Skip to content

Instantly share code, notes, and snippets.

@edef1c
Last active January 22, 2016 22:43
Show Gist options
  • Save edef1c/a8118bf5b047f5f77c6c to your computer and use it in GitHub Desktop.
Save edef1c/a8118bf5b047f5f77c6c to your computer and use it in GitHub Desktop.
NixOS module: dispatch PE execution to either WINE or Mono based on whether it is a CLR executable
package main
import (
"debug/pe"
"errors"
"fmt"
"os"
"syscall"
)
func main() {
args := os.Args[1:]
f, err := pe.Open(args[0])
if err == nil {
err = f.Close()
}
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(-1)
}
var dataDirectories *[16]pe.DataDirectory
switch hdr := f.OptionalHeader.(type) {
default:
panic(fmt.Errorf("unexpected OptionalHeader type: %T", hdr))
case nil:
case *pe.OptionalHeader32:
dataDirectories = &hdr.DataDirectory
case *pe.OptionalHeader64:
dataDirectories = &hdr.DataDirectory
}
isCLR := dataDirectories != nil && dataDirectories[14].Size != 0
execute := "@executorWIN@"
if isCLR {
execute = "@executorCLR@"
}
err = syscall.Exec(execute, append([]string{execute}, args...), os.Environ())
if err == nil {
err = errors.New("unexpected return from syscall.Exec")
}
fmt.Fprintln(os.Stderr, err)
os.Exit(-1)
}
{ pkgs, ... }:
let
executorWIN = "${pkgs.wine}/bin/wine";
executorCLR = "${pkgs.mono}/bin/mono";
dispatch = (pkgs.goPackages.buildGoPackage rec {
name = "binfmt_dispatch";
goPackagePath = name;
preferLocalBuild = true;
src = pkgs.substituteAll {
name = "binfmt_dispatch.go";
src = ./binfmt_dispatch.go;
dir = ".";
inherit executorWIN executorCLR;
};
}).bin;
in {
environment.systemPackages = [ dispatch pkgs.wine pkgs.mono ];
environment.etc."binfmt.d/pe.conf" = {
text = ":DOSWin:M::MZ::${dispatch}/bin/binfmt_dispatch:\n";
};
systemd.additionalUpstreamSystemUnits = [ "systemd-binfmt.service" ];
systemd.services.systemd-binfmt.wants = [ "proc-sys-fs-binfmt_misc.automount" ];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment