Skip to content

Commit b4814f4

Browse files
committed
Unbreak support for OpenBSD.
OpenBSD does not have procfs and tere's no canonical way to get an executable path so this implementation is a best effort.
1 parent 6e7f843 commit b4814f4

3 files changed

Lines changed: 56 additions & 9 deletions

File tree

osext_procfs.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build linux netbsd openbsd solaris dragonfly
5+
// +build linux netbsd solaris dragonfly
66

77
package osext
88

@@ -27,7 +27,7 @@ func executable() (string, error) {
2727
return execpath, nil
2828
case "netbsd":
2929
return os.Readlink("/proc/curproc/exe")
30-
case "openbsd", "dragonfly":
30+
case "dragonfly":
3131
return os.Readlink("/proc/curproc/file")
3232
case "solaris":
3333
return os.Readlink(fmt.Sprintf("/proc/%d/path/a.out", os.Getpid()))

osext_sysctl.go

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build darwin freebsd
5+
// +build darwin freebsd openbsd
66

77
package osext
88

99
import (
1010
"os"
11+
"os/exec"
1112
"path/filepath"
1213
"runtime"
1314
"syscall"
@@ -23,6 +24,8 @@ func executable() (string, error) {
2324
mib = [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1}
2425
case "darwin":
2526
mib = [4]int32{1 /* CTL_KERN */, 38 /* KERN_PROCARGS */, int32(os.Getpid()), -1}
27+
case "openbsd":
28+
mib = [4]int32{1 /* CTL_KERN */, 55 /* KERN_PROC_ARGS */, int32(os.Getpid()), 1 /* KERN_PROC_ARGV */}
2629
}
2730

2831
n := uintptr(0)
@@ -42,14 +45,58 @@ func executable() (string, error) {
4245
if n == 0 { // This shouldn't happen.
4346
return "", nil
4447
}
45-
for i, v := range buf {
46-
if v == 0 {
47-
buf = buf[:i]
48-
break
48+
49+
var execPath string
50+
switch runtime.GOOS {
51+
case "openbsd":
52+
// buf now contains **argv, with pointers to each of the C-style
53+
// NULL terminated arguments.
54+
var args []string
55+
argv := uintptr(unsafe.Pointer(&buf[0]))
56+
Loop:
57+
for {
58+
argp := *(**[1<<20]byte)(unsafe.Pointer(argv))
59+
if argp == nil {
60+
break
61+
}
62+
for i := 0; uintptr(i) < n; i++ {
63+
// we don't want the full arguments list
64+
if string(argp[i]) == " " {
65+
break Loop
66+
}
67+
if argp[i] != 0 {
68+
continue
69+
}
70+
args = append(args, string(argp[:i]))
71+
n -= uintptr(i)
72+
break
73+
}
74+
if n < unsafe.Sizeof(argv) {
75+
break
76+
}
77+
argv += unsafe.Sizeof(argv)
78+
n -= unsafe.Sizeof(argv)
79+
}
80+
execPath = args[0]
81+
// There is no canonical way to get an executable path on
82+
// OpenBSD, so check PATH in case we are called directly
83+
if execPath[0] != '/' && execPath[0] != '.' {
84+
execIsInPath, err := exec.LookPath(execPath)
85+
if err == nil {
86+
execPath = execIsInPath
87+
}
4988
}
89+
default:
90+
for i, v := range buf {
91+
if v == 0 {
92+
buf = buf[:i]
93+
break
94+
}
95+
}
96+
execPath = string(buf)
5097
}
98+
5199
var err error
52-
execPath := string(buf)
53100
// execPath will not be empty due to above checks.
54101
// Try to get the absolute path if the execPath is not rooted.
55102
if execPath[0] != '/' {

osext_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build darwin linux freebsd netbsd windows
5+
// +build darwin linux freebsd netbsd windows openbsd
66

77
package osext
88

0 commit comments

Comments
 (0)