|
|
@@ -1,126 +0,0 @@
|
|
|
-// Copyright 2012 The Go Authors. All rights reserved.
|
|
|
-// Use of this source code is governed by a BSD-style
|
|
|
-// license that can be found in the LICENSE file.
|
|
|
-
|
|
|
-// +build !go1.8,darwin !go1.8,freebsd openbsd
|
|
|
-
|
|
|
-package osext
|
|
|
-
|
|
|
-import (
|
|
|
- "os"
|
|
|
- "os/exec"
|
|
|
- "path/filepath"
|
|
|
- "runtime"
|
|
|
- "syscall"
|
|
|
- "unsafe"
|
|
|
-)
|
|
|
-
|
|
|
-var initCwd, initCwdErr = os.Getwd()
|
|
|
-
|
|
|
-func executable() (string, error) {
|
|
|
- var mib [4]int32
|
|
|
- switch runtime.GOOS {
|
|
|
- case "freebsd":
|
|
|
- mib = [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1}
|
|
|
- case "darwin":
|
|
|
- mib = [4]int32{1 /* CTL_KERN */, 38 /* KERN_PROCARGS */, int32(os.Getpid()), -1}
|
|
|
- case "openbsd":
|
|
|
- mib = [4]int32{1 /* CTL_KERN */, 55 /* KERN_PROC_ARGS */, int32(os.Getpid()), 1 /* KERN_PROC_ARGV */}
|
|
|
- }
|
|
|
-
|
|
|
- n := uintptr(0)
|
|
|
- // Get length.
|
|
|
- _, _, errNum := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
|
|
|
- if errNum != 0 {
|
|
|
- return "", errNum
|
|
|
- }
|
|
|
- if n == 0 { // This shouldn't happen.
|
|
|
- return "", nil
|
|
|
- }
|
|
|
- buf := make([]byte, n)
|
|
|
- _, _, errNum = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0)
|
|
|
- if errNum != 0 {
|
|
|
- return "", errNum
|
|
|
- }
|
|
|
- if n == 0 { // This shouldn't happen.
|
|
|
- return "", nil
|
|
|
- }
|
|
|
-
|
|
|
- var execPath string
|
|
|
- switch runtime.GOOS {
|
|
|
- case "openbsd":
|
|
|
- // buf now contains **argv, with pointers to each of the C-style
|
|
|
- // NULL terminated arguments.
|
|
|
- var args []string
|
|
|
- argv := uintptr(unsafe.Pointer(&buf[0]))
|
|
|
- Loop:
|
|
|
- for {
|
|
|
- argp := *(**[1 << 20]byte)(unsafe.Pointer(argv))
|
|
|
- if argp == nil {
|
|
|
- break
|
|
|
- }
|
|
|
- for i := 0; uintptr(i) < n; i++ {
|
|
|
- // we don't want the full arguments list
|
|
|
- if string(argp[i]) == " " {
|
|
|
- break Loop
|
|
|
- }
|
|
|
- if argp[i] != 0 {
|
|
|
- continue
|
|
|
- }
|
|
|
- args = append(args, string(argp[:i]))
|
|
|
- n -= uintptr(i)
|
|
|
- break
|
|
|
- }
|
|
|
- if n < unsafe.Sizeof(argv) {
|
|
|
- break
|
|
|
- }
|
|
|
- argv += unsafe.Sizeof(argv)
|
|
|
- n -= unsafe.Sizeof(argv)
|
|
|
- }
|
|
|
- execPath = args[0]
|
|
|
- // There is no canonical way to get an executable path on
|
|
|
- // OpenBSD, so check PATH in case we are called directly
|
|
|
- if execPath[0] != '/' && execPath[0] != '.' {
|
|
|
- execIsInPath, err := exec.LookPath(execPath)
|
|
|
- if err == nil {
|
|
|
- execPath = execIsInPath
|
|
|
- }
|
|
|
- }
|
|
|
- default:
|
|
|
- for i, v := range buf {
|
|
|
- if v == 0 {
|
|
|
- buf = buf[:i]
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
- execPath = string(buf)
|
|
|
- }
|
|
|
-
|
|
|
- var err error
|
|
|
- // execPath will not be empty due to above checks.
|
|
|
- // Try to get the absolute path if the execPath is not rooted.
|
|
|
- if execPath[0] != '/' {
|
|
|
- execPath, err = getAbs(execPath)
|
|
|
- if err != nil {
|
|
|
- return execPath, err
|
|
|
- }
|
|
|
- }
|
|
|
- // For darwin KERN_PROCARGS may return the path to a symlink rather than the
|
|
|
- // actual executable.
|
|
|
- if runtime.GOOS == "darwin" {
|
|
|
- if execPath, err = filepath.EvalSymlinks(execPath); err != nil {
|
|
|
- return execPath, err
|
|
|
- }
|
|
|
- }
|
|
|
- return execPath, nil
|
|
|
-}
|
|
|
-
|
|
|
-func getAbs(execPath string) (string, error) {
|
|
|
- if initCwdErr != nil {
|
|
|
- return execPath, initCwdErr
|
|
|
- }
|
|
|
- // The execPath may begin with a "../" or a "./" so clean it first.
|
|
|
- // Join the two paths, trailing and starting slashes undetermined, so use
|
|
|
- // the generic Join function.
|
|
|
- return filepath.Join(initCwd, filepath.Clean(execPath)), nil
|
|
|
-}
|