func()

in providers/aix/process_aix_ppc64.go [105:192]


func (p *process) Info() (types.ProcessInfo, error) {
	if p.info != nil {
		return *p.info, nil
	}

	p.info = &types.ProcessInfo{
		PID: p.pid,
	}

	// Retrieve PPID and StartTime
	info := C.struct_procsinfo64{}
	cpid := C.pid_t(p.pid)

	num, err := C.getprocs(unsafe.Pointer(&info), C.sizeof_struct_procsinfo64, nil, 0, &cpid, 1)
	if num != 1 {
		err = syscall.ESRCH
	}
	if err != nil {
		return types.ProcessInfo{}, fmt.Errorf("error while calling getprocs: %w", err)
	}

	p.info.PPID = int(info.pi_ppid)
	// pi_start is the time in second since the process have started.
	p.info.StartTime = time.Unix(0, int64(uint64(info.pi_start)*1000*uint64(time.Millisecond)))

	// Retrieve arguments and executable name
	// If buffer is not large enough, args are truncated
	buf := make([]byte, 8192)
	var args []string
	if _, err := C.getargs(unsafe.Pointer(&info), C.sizeof_struct_procsinfo64, (*C.char)(&buf[0]), 8192); err != nil {
		return types.ProcessInfo{}, fmt.Errorf("error while calling getargs: %w", err)
	}

	bbuf := bytes.NewBuffer(buf)
	for {
		arg, err := bbuf.ReadBytes(0)
		if err == io.EOF || arg[0] == 0 {
			break
		}
		if err != nil {
			return types.ProcessInfo{}, fmt.Errorf("error while reading arguments: %w", err)
		}

		args = append(args, string(chop(arg)))
	}

	// For some special programs, getargs might return an empty buffer.
	if len(args) == 0 {
		args = append(args, "")
	}

	// The first element of the arguments list is the executable path.
	// There are some exceptions which don't have an executable path
	// but rather a special name directly in args[0].
	if strings.Contains(args[0], "sshd: ") {
		// ssh connections can be named "sshd: root@pts/11".
		// If we are using filepath.Base, the result will only
		// be 11 because of the last "/".
		p.info.Name = args[0]
	} else {
		p.info.Name = filepath.Base(args[0])
	}

	// The process was launched using its absolute path, so we can retrieve
	// the executable path from its "name".
	if filepath.IsAbs(args[0]) {
		p.info.Exe = filepath.Clean(args[0])
	} else {
		// TODO: improve this case. The executable full path can still
		// be retrieve in some cases. Look at os/executable_path.go
		// in the stdlib.
		// For the moment, let's "exe" be the same as "name"
		p.info.Exe = p.info.Name
	}
	p.info.Args = args

	// Get CWD
	cwd, err := os.Readlink("/proc/" + strconv.Itoa(p.pid) + "/cwd")
	if err != nil {
		if !os.IsNotExist(err) {
			return types.ProcessInfo{}, fmt.Errorf("error while reading /proc/%s/cwd: %w", strconv.Itoa(p.pid), err)
		}
	}

	p.info.CWD = strings.TrimSuffix(cwd, "/")

	return *p.info, nil
}