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
77package osext
88
99import (
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 ] != '/' {
0 commit comments