diff --git a/reexec/MAINTAINERS b/reexec/MAINTAINERS new file mode 100644 index 0000000..e48a0c7 --- /dev/null +++ b/reexec/MAINTAINERS @@ -0,0 +1 @@ +Michael Crosby (@crosbymichael) diff --git a/reexec/README.md b/reexec/README.md new file mode 100644 index 0000000..45592ce --- /dev/null +++ b/reexec/README.md @@ -0,0 +1,5 @@ +## reexec + +The `reexec` package facilitates the busybox style reexec of the docker binary that we require because +of the forking limitations of using Go. Handlers can be registered with a name and the argv 0 of +the exec of the binary will be used to find and execute custom init paths. diff --git a/reexec/reexec.go b/reexec/reexec.go new file mode 100644 index 0000000..136b905 --- /dev/null +++ b/reexec/reexec.go @@ -0,0 +1,45 @@ +package reexec + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" +) + +var registeredInitializers = make(map[string]func()) + +// Register adds an initialization func under the specified name +func Register(name string, initializer func()) { + if _, exists := registeredInitializers[name]; exists { + panic(fmt.Sprintf("reexec func already registred under name %q", name)) + } + + registeredInitializers[name] = initializer +} + +// Init is called as the first part of the exec process and returns true if an +// initialization function was called. +func Init() bool { + initializer, exists := registeredInitializers[os.Args[0]] + if exists { + initializer() + + return true + } + + return false +} + +// Self returns the path to the current processes binary +func Self() string { + name := os.Args[0] + + if filepath.Base(name) == name { + if lp, err := exec.LookPath(name); err == nil { + name = lp + } + } + + return name +}