Skip to content

Commit 111ad8d

Browse files
committed
Add tail like functionality to watch command Closes #143
1 parent d78ba7f commit 111ad8d

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed

internal/server/commands/watch.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"log"
99
"os"
1010
"path/filepath"
11+
"strconv"
1112

1213
"github.com/NHAS/reverse_ssh/internal/server/observers"
1314
"github.com/NHAS/reverse_ssh/internal/terminal"
@@ -40,6 +41,81 @@ func (w *watch) Run(tty io.ReadWriter, line terminal.ParsedLine) error {
4041
return sc.Err()
4142
}
4243

44+
if numberOfLinesStr, err := line.GetArgString("l"); err == nil {
45+
46+
f, err := os.Open(filepath.Join(w.datadir, "watch.log"))
47+
if err != nil {
48+
log.Println("unable to open watch.log:", err)
49+
return err
50+
}
51+
defer f.Close()
52+
53+
info, err := f.Stat()
54+
if err != nil {
55+
return err
56+
}
57+
58+
numberOfLines, err := strconv.Atoi(numberOfLinesStr)
59+
if err != nil {
60+
return err
61+
}
62+
63+
readStartIndex := info.Size()
64+
65+
i := 0
66+
outer:
67+
for {
68+
readStartIndex -= 128
69+
if readStartIndex < 0 {
70+
readStartIndex = 0
71+
}
72+
73+
buffer := make([]byte, 128)
74+
n, err := f.ReadAt(buffer, readStartIndex)
75+
if err != nil {
76+
if err == io.EOF {
77+
break outer
78+
}
79+
return err
80+
}
81+
82+
for ii := n - 1; ii > 0; ii-- {
83+
if buffer[ii] == '\n' {
84+
i++
85+
}
86+
87+
// Since we are reading backwards, we have to read towards the previous lines newline
88+
if i == numberOfLines+1 {
89+
// Ignore the previous lines new line
90+
readStartIndex += int64(ii) + 1
91+
break outer
92+
}
93+
}
94+
95+
if readStartIndex == 0 {
96+
// If we've regressed to the file start, and not exited the loop jump out now
97+
break
98+
}
99+
}
100+
101+
_, err = f.Seek(readStartIndex, 0)
102+
if err != nil {
103+
return err
104+
}
105+
106+
scanner := bufio.NewScanner(f)
107+
// optionally, resize scanner's capacity for lines over 64K, see next example
108+
for scanner.Scan() {
109+
fmt.Fprintf(tty, "%s\n\r", scanner.Text())
110+
}
111+
112+
if err := scanner.Err(); err != nil {
113+
return err
114+
}
115+
116+
return nil
117+
}
118+
43119
messages := make(chan string)
44120

45121
observerId := observers.ConnectionState.Register(func(m observer.Message) {
@@ -95,6 +171,7 @@ func (w *watch) Help(explain bool) string {
95171
"watch [OPTIONS]",
96172
"Watch shows continuous connection status of clients (prints the joining and leaving of clients)",
97173
"Defaultly waits for new connection events",
174+
"\t-a\tLists all previous connection events",
98175
"\t-l\tList previous n number of connection events, e.g watch -l 10 shows last 10 connections",
99176
)
100177
}

0 commit comments

Comments
 (0)