in metric/system/process/process_darwin.go [172:247]
func getProcArgs(pid int, filter func(string) bool) ([]string, string, mapstr.M, error) {
mib := []C.int{C.CTL_KERN, C.KERN_PROCARGS2, C.int(pid)}
argmax := uintptr(C.ARG_MAX)
buf := make([]byte, argmax)
err := sysctl(mib, &buf[0], &argmax, nil, 0)
if err != nil {
return nil, "", nil, fmt.Errorf("error in sysctl: %w", err)
}
bbuf := bytes.NewBuffer(buf)
bbuf.Truncate(int(argmax))
var argc int32 // raw buffer
_ = binary.Read(bbuf, binary.LittleEndian, &argc) // read length
path, err := bbuf.ReadBytes(0)
if err != nil {
return nil, "", nil, fmt.Errorf("error reading the executable name: %w", err)
}
exeName := stripNullByte(path)
// skip trailing nul bytes
for {
c, err := bbuf.ReadByte()
if err != nil {
return nil, "", nil, fmt.Errorf("error skipping nul values in KERN_PROCARGS2 buffer: %w", err)
}
if c != 0 {
_ = bbuf.UnreadByte()
break
}
}
// read CLI args
argv := make([]string, 0, argc)
for i := 0; i < int(argc); i++ {
arg, err := bbuf.ReadBytes(0)
if err == io.EOF {
break
}
if err != nil {
return nil, exeName, nil, fmt.Errorf("error reading args from KERN_PROCARGS2: %w", err)
}
argv = append(argv, stripNullByte(arg))
}
delim := []byte{61} // "=" for key value pairs
envVars := mapstr.M{}
var envErr error
for {
line, err := bbuf.ReadBytes(0)
if err == io.EOF || line[0] == 0 {
break
}
if err != nil {
return argv, exeName, nil, fmt.Errorf("error reading args from KERN_PROCARGS2 buffer: %w", err)
}
pair := bytes.SplitN(stripNullByteRaw(line), delim, 2)
if len(pair) != 2 {
// invalid k-v pair encountered, return non-fatal error so that we can continue
err := fmt.Errorf("error reading process information from KERN_PROCARGS2: encountered invalid env pair for pid %d", pid)
envErr = errors.Join(envErr, NonFatalErr{Err: err})
continue
}
eKey := string(pair[0])
if filter == nil || filter(eKey) {
envVars[string(pair[0])] = string(pair[1])
}
}
return argv, exeName, envVars, envErr
}