1// +build darwin
2
3package common
4
5import (
6	"context"
7	"os"
8	"os/exec"
9	"strings"
10	"unsafe"
11
12	"golang.org/x/sys/unix"
13)
14
15func DoSysctrlWithContext(ctx context.Context, mib string) ([]string, error) {
16	sysctl, err := exec.LookPath("/usr/sbin/sysctl")
17	if err != nil {
18		return []string{}, err
19	}
20	cmd := exec.CommandContext(ctx, sysctl, "-n", mib)
21	cmd.Env = getSysctrlEnv(os.Environ())
22	out, err := cmd.Output()
23	if err != nil {
24		return []string{}, err
25	}
26	v := strings.Replace(string(out), "{ ", "", 1)
27	v = strings.Replace(string(v), " }", "", 1)
28	values := strings.Fields(string(v))
29
30	return values, nil
31}
32
33func CallSyscall(mib []int32) ([]byte, uint64, error) {
34	miblen := uint64(len(mib))
35
36	// get required buffer size
37	length := uint64(0)
38	_, _, err := unix.Syscall6(
39		unix.SYS___SYSCTL,
40		uintptr(unsafe.Pointer(&mib[0])),
41		uintptr(miblen),
42		0,
43		uintptr(unsafe.Pointer(&length)),
44		0,
45		0)
46	if err != 0 {
47		var b []byte
48		return b, length, err
49	}
50	if length == 0 {
51		var b []byte
52		return b, length, err
53	}
54	// get proc info itself
55	buf := make([]byte, length)
56	_, _, err = unix.Syscall6(
57		unix.SYS___SYSCTL,
58		uintptr(unsafe.Pointer(&mib[0])),
59		uintptr(miblen),
60		uintptr(unsafe.Pointer(&buf[0])),
61		uintptr(unsafe.Pointer(&length)),
62		0,
63		0)
64	if err != 0 {
65		return buf, length, err
66	}
67
68	return buf, length, nil
69}
70