internal/psscanner/proclist.go
package psscanner
import (
"fmt"
"io"
"os"
"strconv"
)
type procList map[int]struct{}
type pidProcessor interface {
processNewPid(pid int)
}
func (pl procList) refresh(p pidProcessor) error {
pids, err := getPIDs()
if err != nil {
return err
}
for i := len(pids) - 1; i >= 0; i-- {
pid := pids[i]
_, ok := pl[pid]
if !ok {
p.processNewPid(pid)
pl[pid] = struct{}{}
}
}
return nil
}
func getPIDs() ([]int, error) {
f, err := dirOpen("/proc")
if err != nil {
return nil, fmt.Errorf("opening proc dir: %v", err)
}
defer f.Close()
names, err := f.Readdirnames(-1)
if err != nil {
return nil, fmt.Errorf("reading proc dir: %v", err)
}
pids := make([]int, 0)
for _, f := range names {
pid, err := strconv.Atoi(f)
if err != nil || pid <= 0 {
continue
}
pids = append(pids, pid)
}
return pids, nil
}
type readDirNamesCloser interface {
Readdirnames(n int) (names []string, err error)
io.Closer
}
var dirOpen func(string) (readDirNamesCloser, error) = func(s string) (readDirNamesCloser, error) {
return os.Open(s)
}