diff --git a/onf/internal/tasklist/tasklist.go b/onf/internal/tasklist/tasklist.go deleted file mode 100644 index f2da8ce..0000000 --- a/onf/internal/tasklist/tasklist.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright © 2019 Jecoz -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package tasklist - -import ( - "bytes" - "fmt" - "io" - "log" - "strconv" - "strings" - - "github.com/jecoz/lsaddr/onf/internal" -) - -type Task struct { - Pid int - Image string -} - -// ParseOutput expects "r" to contain the output of -// a ``tasklist'' call. The output is splitted into lines, and -// each line that ``UnmarshakTasklistLine'' is able to Unmarshal is -// appended to the final output, with the expections of the first lines -// that come before the separator line composed by only "=". Those lines -// are considered part of the "header". -// -// As of ``ParseTask'', this function returns an error only -// if reading from "r" produces an error different from ``io.EOF''. -func ParseOutput(r io.Reader) ([]Task, error) { - ll := []Task{} - delim := "=" - headerTrimmed := false - segLengths := []int{} - err := internal.ScanLines(r, func(line string) error { - if !headerTrimmed { - if strings.HasPrefix(line, delim) && strings.HasSuffix(line, delim) { - headerTrimmed = true - // This is the header delimiter! - chunks, err := internal.ChunkLine(line, " ", 5) - if err != nil { - return fmt.Errorf("unexpected header format: %w", err) - } - for _, v := range chunks { - segLengths = append(segLengths, len(v)) - } - } - // Still in the header - return nil - } - - t, err := ParseTask(line, segLengths) - if err != nil { - log.Printf("skipping tasklist line \"%s\": %v", line, err) - return nil - } - ll = append(ll, *t) - return nil - }) - return ll, err -} - -// ParseTask expectes "line" to be a single line output from -// ``tasklist'' call. The line is unmarshaled into a ``Task'' and the operation -// is performed by readying bytes equal to "segLengths"[i], in order. "segLengths" -// should be computed using the header delimitator and counting the number of -// "=" in each segment of the header (split it by " ") -// -// "line" should not end with a "\n" delimitator, otherwise it will end up in the last -// unmarshaled item. -// The "header" lines (see below) should not be passed to this function. -// -// Example header: -// Image Name PID Session Name Session# Mem Usage -// ========================= ======== ================ =========== ============ -// -// Example line: -// svchost.exe 940 Services 0 52,336 K -func ParseTask(line string, segLengths []int) (*Task, error) { - buf := bytes.NewBufferString(line) - p := make([]byte, 32) - - var image, pidRaw string - for i, v := range segLengths[:2] { - n, err := buf.Read(p[:v+1]) - if err != nil { - return nil, fmt.Errorf("unable to read tasklist chunk: %w", err) - } - s := strings.Trim(string(p[:n]), " ") - switch i { - case 0: - image = s - case 1: - pidRaw = s - default: - } - } - if image == "" { - return nil, fmt.Errorf("couldn't decode image from line") - } - if pidRaw == "" { - return nil, fmt.Errorf("couldn't decode pid from line") - } - pid, err := strconv.Atoi(pidRaw) - if err != nil { - return nil, fmt.Errorf("error parsing pid: %w", err) - } - - return &Task{ - Image: image, - Pid: pid, - }, nil -} diff --git a/onf/internal/tasklist/tasklist_test.go b/onf/internal/tasklist/tasklist_test.go deleted file mode 100644 index 64954f1..0000000 --- a/onf/internal/tasklist/tasklist_test.go +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright © 2019 Jecoz -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package tasklist - -import ( - "bytes" - "reflect" - "testing" -) - -const tasklistExample = ` -Image Name PID Session Name Session# Mem Usage -========================= ======== ================ =========== ============ -System Idle Process 0 Services 0 4 K -System 4 Services 0 15,376 K -smss.exe 296 Services 0 1,008 K -csrss.exe 380 Services 0 4,124 K -wininit.exe 452 Services 0 4,828 K -services.exe 588 Services 0 6,284 K -lsass.exe 596 Services 0 12,600 K -svchost.exe 688 Services 0 17,788 K -svchost.exe 748 Services 0 8,980 K -svchost.exe 888 Services 0 21,052 K -svchost.exe 904 Services 0 21,200 K -svchost.exe 940 Services 0 52,336 K -WUDFHost.exe 464 Services 0 6,128 K -svchost.exe 1036 Services 0 14,524 K -svchost.exe 1044 Services 0 27,488 K -svchost.exe 1104 Services 0 28,428 K -WUDFHost.exe 1240 Services 0 6,888 K -` - -func TestParseOutput(t *testing.T) { - t.Parallel() - buf := bytes.NewBufferString(tasklistExample) - ll, err := ParseOutput(buf) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if len(ll) != 17 { - t.Fatalf("Unexpected ll length: wanted 17, found: %d: %v", len(ll), ll) - } -} - -func TestParseTask(t *testing.T) { - t.Parallel() - tt := []struct { - line string - segs []int - image string - pid int - }{ - { - line: "svchost.exe 940 Services 0 52,336 K", - segs: []int{25, 8, 16, 11, 12}, - image: "svchost.exe", - pid: 940, - }, - { - line: "System Idle Process 0 Services 0 4 K", - segs: []int{25, 8, 16, 11, 12}, - image: "System Idle Process", - pid: 0, - }, - } - - for i, v := range tt { - task, err := ParseTask(v.line, v.segs) - if err != nil { - t.Fatalf("%d: unexpected error: %v", i, err) - } - assert(t, v.image, task.Image) - assert(t, v.pid, task.Pid) - } -} - -func assert(t *testing.T, exp, x interface{}) { - if !reflect.DeepEqual(exp, x) { - t.Fatalf("Assert failed: expected %v, found %v", exp, x) - } -}