From 2b4e378dd3a5bc17e774a12d7fb96afb2e80c209 Mon Sep 17 00:00:00 2001 From: rsteube Date: Thu, 19 Oct 2023 15:40:54 +0200 Subject: [PATCH] ActionUsedPorts: support windows --- pkg/actions/net/port.go | 69 ++++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/pkg/actions/net/port.go b/pkg/actions/net/port.go index 2791583924..fc6d4a9b70 100644 --- a/pkg/actions/net/port.go +++ b/pkg/actions/net/port.go @@ -1,7 +1,7 @@ package net import ( - "os/exec" + "runtime" "strings" "github.com/rsteube/carapace" @@ -52,26 +52,59 @@ func ActionKnownPorts() carapace.Action { // 8000 (used by: python) func ActionUsedPorts() carapace.Action { return carapace.ActionCallback(func(c carapace.Context) carapace.Action { - // TODO support other tools - if _, err := exec.LookPath("lsof"); err == nil { - return carapace.ActionExecCommand("lsof", "-i", "-P", "-n")(func(output []byte) carapace.Action { - lines := strings.Split(string(output), "\n") + switch runtime.GOOS { + case "darwin", "linux": + return actionUsedPortsLsof() + case "windows": + return actionUsedPortsNetstat() + default: + return carapace.ActionValues() + } + }).Tag("used ports") +} + +func actionUsedPortsLsof() carapace.Action { + return carapace.ActionExecCommand("lsof", "-i", "-P", "-n")(func(output []byte) carapace.Action { + lines := strings.Split(string(output), "\n") + + vals := make([]string, 0) + for _, line := range lines { + if fields := strings.Fields(line); len(fields) > 9 { + if fields[len(fields)-1] != "(LISTEN)" { + continue + } - vals := make([]string, 0) - for _, line := range lines { - if fields := strings.Fields(line); len(fields) > 9 { - if fields[len(fields)-1] != "(LISTEN)" { - continue - } + if splitted := strings.Split(fields[len(fields)-2], ":"); len(splitted) > 1 { + vals = append(vals, splitted[len(splitted)-1], "used by: "+fields[0]) + } + } + } + return carapace.ActionValuesDescribed(vals...).Style(style.Carapace.KeywordNegative) + }) +} - if splitted := strings.Split(fields[len(fields)-2], ":"); len(splitted) > 1 { - vals = append(vals, splitted[len(splitted)-1], "used by: "+fields[0]) - } +func actionUsedPortsNetstat() carapace.Action { + return carapace.ActionExecCommand("netstat", "-abon")(func(output []byte) carapace.Action { + lines := strings.Split(string(output), "\r\n") + vals := make([]string, 0) + for index, line := range lines[:len(lines)-1] { + if fields := strings.Fields(line); len(fields) > 3 { + switch { + case fields[3] != "LISTENING": + continue + case fields[0] != "TCP" && fields[0] != "UDP": + continue + } + + if splitted := strings.Split(fields[1], ":"); len(splitted) > 1 { + service := strings.TrimSpace(lines[index+1]) + if strings.HasPrefix(service, "[") { + service = service[1 : len(service)-1] } + vals = append(vals, splitted[len(splitted)-1], "used by: "+service) } - return carapace.ActionValuesDescribed(vals...).Style(style.Carapace.KeywordNegative) - }) + } } - return carapace.ActionValues() - }).Tag("used ports") + return carapace.ActionValuesDescribed(vals...).Style(style.Carapace.KeywordNegative) + }) }