Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/completions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ _u7_complete_entities() {
local verb="$1" cur="$2"
case "$verb" in
show|sh)
COMPREPLY=($(compgen -W "ip csv json line ssl files diff cpu memory disk processes port usage network git env log http docker system definition functions --help" -- "$cur"))
COMPREPLY=($(compgen -W "ip csv json line ssl files diff cpu memory disk processes ports port usage network git env log http docker system definition functions --help" -- "$cur"))
;;
make|mk)
COMPREPLY=($(compgen -W "dir file password user copy link archive clone template sequence --help" -- "$cur"))
Expand Down Expand Up @@ -38,6 +38,7 @@ _u7_complete_args() {
env) COMPREPLY=($(compgen -W "match" -- "$cur")) ;;
http) COMPREPLY=($(compgen -W "get head headers" -- "$cur")) ;;
docker) COMPREPLY=($(compgen -W "containers images volumes networks all" -- "$cur")) ;;
ports) COMPREPLY=($(compgen -W "match" -- "$cur")) ;;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 log subcommand completion missing

ports got argument completion, but log (also added in this PR) has no completion case for its subcommands (limit, match, follow). Add a log case alongside the new ports case:

Suggested change
ports) COMPREPLY=($(compgen -W "match" -- "$cur")) ;;
ports) COMPREPLY=($(compgen -W "match" -- "$cur")) ;;
log) COMPREPLY=($(compgen -W "limit match follow" -- "$cur")) ;;
Prompt To Fix With AI
This is a comment left during a code review.
Path: lib/completions.sh
Line: 41

Comment:
**`log` subcommand completion missing**

`ports` got argument completion, but `log` (also added in this PR) has no completion case for its subcommands (`limit`, `match`, `follow`). Add a `log` case alongside the new `ports` case:

```suggestion
        ports) COMPREPLY=($(compgen -W "match" -- "$cur")) ;;
        log) COMPREPLY=($(compgen -W "limit match follow" -- "$cur")) ;;
```

How can I resolve this? If you propose a fix, please make it concise.

log) COMPREPLY=($(compgen -W "limit match follow" -- "$cur")) ; _filedir ;;
*) _filedir ;;
esac
Expand Down
24 changes: 24 additions & 0 deletions lib/show.sh
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,30 @@ _u7_show() {
esac
;;

ports)
case "$1" in
match)
if [[ -z "$2" ]]; then
echo "Usage: u7 sh ports match <pattern>"
return 1
fi
if command -v ss &>/dev/null; then
ss -tlnp | grep -i "$2"
else
netstat -tlnp 2>/dev/null | grep -i "$2"
fi
Comment on lines +158 to +162

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 grep pattern not protected from flag injection

grep -i "$2" will interpret any pattern beginning with - as a grep flag (e.g. u7 sh ports match -v would invert the match silently). The log match handler added in the same PR correctly uses grep -- "$3" to terminate flag parsing. Apply the same protection here:

Suggested change
if command -v ss &>/dev/null; then
ss -tlnp | grep -i "$2"
else
netstat -tlnp 2>/dev/null | grep -i "$2"
fi
if command -v ss &>/dev/null; then
ss -tlnp | grep -i -- "$2"
else
netstat -tlnp 2>/dev/null | grep -i -- "$2"
fi
Prompt To Fix With AI
This is a comment left during a code review.
Path: lib/show.sh
Line: 158-162

Comment:
**`grep` pattern not protected from flag injection**

`grep -i "$2"` will interpret any pattern beginning with `-` as a grep flag (e.g. `u7 sh ports match -v` would invert the match silently). The `log match` handler added in the same PR correctly uses `grep -- "$3"` to terminate flag parsing. Apply the same protection here:

```suggestion
          if command -v ss &>/dev/null; then
            ss -tlnp | grep -i -- "$2"
          else
            netstat -tlnp 2>/dev/null | grep -i -- "$2"
          fi
```

How can I resolve this? If you propose a fix, please make it concise.

;;
"")
if command -v ss &>/dev/null; then
ss -tlnp
else
netstat -tlnp 2>/dev/null
fi
;;
*) echo "Usage: u7 sh ports [match <pattern>]" ; return 1 ;;
esac
;;
Comment on lines +151 to +173

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for choosing between ss and netstat is duplicated for the match case and the default case. You can refactor this to be more DRY (Don't Repeat Yourself) by extracting this logic into a helper function. This will improve the maintainability of the code. I've also added -- to grep as a good practice to prevent patterns starting with a hyphen from being interpreted as options.

    ports)
      _list_ports() {
        if command -v ss &>/dev/null; then
          ss -tlnp
        else
          netstat -tlnp 2>/dev/null
        fi
      }
      case "$1" in
        match)
          if [[ -z "$2" ]]; then
            echo "Usage: u7 sh ports match <pattern>"
            return 1
          fi
          _list_ports | grep -i -- "$2"
          ;;
        "")
          _list_ports
          ;;
        *) echo "Usage: u7 sh ports [match <pattern>]" ; return 1 ;;
      esac
      ;;

Comment on lines +151 to +173

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for choosing between ss and netstat is duplicated for both the plain ports command and ports match. You can refactor this to avoid repetition and improve maintainability by determining the base command first.

    ports)
      local list_cmd
      if command -v ss &>/dev/null; then
        list_cmd="ss -tlnp"
      else
        list_cmd="netstat -tlnp 2>/dev/null"
      fi

      case "$1" in
        match)
          if [[ -z "$2" ]]; then
            echo "Usage: u7 sh ports match <pattern>"
            return 1
          fi
          eval "$list_cmd" | grep -i -- "$2"
          ;;
        "")
          eval "$list_cmd"
          ;;
        *) echo "Usage: u7 sh ports [match <pattern>]" ; return 1 ;;
      esac
      ;;


port)
lsof -i tcp:"$1"
;;
Expand Down
34 changes: 34 additions & 0 deletions test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,40 @@ assert_contains "sh system shows uptime" "Uptime:" "$result"
assert_contains "sh system shows shell" "Shell:" "$result"
assert_contains "sh system shows user" "User:" "$result"

# Test: sh ports lists listening ports
if command -v ss &>/dev/null || command -v netstat &>/dev/null; then
result=$(u7 sh ports 2>&1)
if [[ $? -eq 0 ]]; then
echo -e "${GREEN}✓${NC} sh ports runs without error"
((PASSED++))
else
echo -e "${RED}✗${NC} sh ports runs without error"
echo " Got: $result"
((FAILED++))
fi
else
echo -e "${GREEN}✓${NC} sh ports runs without error (skipped - ss/netstat not installed)"
((PASSED++))
fi

# Test: sh ports shows usage on invalid arg
result=$(u7 sh ports badarg 2>&1)
assert_contains "sh ports rejects invalid arg" "Usage:" "$result"

# Test: sh ports match requires pattern
result=$(u7 sh ports match 2>&1)
assert_contains "sh ports match requires pattern" "Usage:" "$result"

# Test: sh ports match filters output (may return nothing, just check it runs)
if command -v ss &>/dev/null || command -v netstat &>/dev/null; then
u7 sh ports match ssh 2>&1
echo -e "${GREEN}✓${NC} sh ports match runs without crash"
((PASSED++))
else
echo -e "${GREEN}✓${NC} sh ports match runs without crash (skipped - ss/netstat not installed)"
((PASSED++))
fi

# Cleanup
cd /
rm -rf "$TEST_DIR"
Expand Down
Loading