|
|
|
@ -8,6 +8,7 @@ import ( |
|
|
|
"sync" |
|
|
|
"sync" |
|
|
|
|
|
|
|
|
|
|
|
"github.com/curusarn/resh/pkg/histfile" |
|
|
|
"github.com/curusarn/resh/pkg/histfile" |
|
|
|
|
|
|
|
"github.com/curusarn/resh/pkg/histlist" |
|
|
|
"github.com/curusarn/resh/pkg/records" |
|
|
|
"github.com/curusarn/resh/pkg/records" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
@ -39,7 +40,7 @@ func (s *Dispatch) sessionInitializer(sessionsToInit chan records.Record) { |
|
|
|
for { |
|
|
|
for { |
|
|
|
record := <-sessionsToInit |
|
|
|
record := <-sessionsToInit |
|
|
|
log.Println("sesshist: got session to init - " + record.SessionID) |
|
|
|
log.Println("sesshist: got session to init - " + record.SessionID) |
|
|
|
s.initSession(record.SessionID) |
|
|
|
s.initSession(record.SessionID, record.Shell) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -57,13 +58,28 @@ func (s *Dispatch) recordAdder(recordsToAdd chan records.Record) { |
|
|
|
if record.PartOne { |
|
|
|
if record.PartOne { |
|
|
|
log.Println("sesshist: got record to add - " + record.CmdLine) |
|
|
|
log.Println("sesshist: got record to add - " + record.CmdLine) |
|
|
|
s.addRecentRecord(record.SessionID, record) |
|
|
|
s.addRecentRecord(record.SessionID, record) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// this inits session on RESH update
|
|
|
|
|
|
|
|
s.checkSession(record.SessionID, record.Shell) |
|
|
|
} |
|
|
|
} |
|
|
|
// TODO: we will need to handle part2 as well eventually
|
|
|
|
// TODO: we will need to handle part2 as well eventually
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (s *Dispatch) checkSession(sessionID, shell string) { |
|
|
|
|
|
|
|
s.mutex.RLock() |
|
|
|
|
|
|
|
_, found := s.sessions[sessionID] |
|
|
|
|
|
|
|
s.mutex.RUnlock() |
|
|
|
|
|
|
|
if found == false { |
|
|
|
|
|
|
|
err := s.initSession(sessionID, shell) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
log.Println("sesshist: Error while checking session:", err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// InitSession struct
|
|
|
|
// InitSession struct
|
|
|
|
func (s *Dispatch) initSession(sessionID string) error { |
|
|
|
func (s *Dispatch) initSession(sessionID, shell string) error { |
|
|
|
log.Println("sesshist: initializing session - " + sessionID) |
|
|
|
log.Println("sesshist: initializing session - " + sessionID) |
|
|
|
s.mutex.RLock() |
|
|
|
s.mutex.RLock() |
|
|
|
_, found := s.sessions[sessionID] |
|
|
|
_, found := s.sessions[sessionID] |
|
|
|
@ -74,14 +90,13 @@ func (s *Dispatch) initSession(sessionID string) error { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
log.Println("sesshist: loading history to populate session - " + sessionID) |
|
|
|
log.Println("sesshist: loading history to populate session - " + sessionID) |
|
|
|
historyCmdLines := s.history.GetRecentCmdLines(s.historyInitSize) |
|
|
|
historyCmdLines := s.history.GetRecentCmdLines(shell, s.historyInitSize) |
|
|
|
|
|
|
|
|
|
|
|
s.mutex.Lock() |
|
|
|
s.mutex.Lock() |
|
|
|
defer s.mutex.Unlock() |
|
|
|
defer s.mutex.Unlock() |
|
|
|
// init sesshist and populate it with history loaded from file
|
|
|
|
// init sesshist and populate it with history loaded from file
|
|
|
|
s.sessions[sessionID] = &sesshist{ |
|
|
|
s.sessions[sessionID] = &sesshist{ |
|
|
|
recentCmdLines: historyCmdLines, |
|
|
|
recentCmdLines: historyCmdLines, |
|
|
|
cmdLinesLastIndex: map[string]int{}, |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
log.Println("sesshist: session init done - " + sessionID) |
|
|
|
log.Println("sesshist: session init done - " + sessionID) |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
@ -105,35 +120,33 @@ func (s *Dispatch) dropSession(sessionID string) error { |
|
|
|
|
|
|
|
|
|
|
|
// AddRecent record to session
|
|
|
|
// AddRecent record to session
|
|
|
|
func (s *Dispatch) addRecentRecord(sessionID string, record records.Record) error { |
|
|
|
func (s *Dispatch) addRecentRecord(sessionID string, record records.Record) error { |
|
|
|
|
|
|
|
log.Println("sesshist: Adding a record, RLocking main lock ...") |
|
|
|
s.mutex.RLock() |
|
|
|
s.mutex.RLock() |
|
|
|
|
|
|
|
log.Println("sesshist: Getting a session ...") |
|
|
|
session, found := s.sessions[sessionID] |
|
|
|
session, found := s.sessions[sessionID] |
|
|
|
|
|
|
|
log.Println("sesshist: RUnlocking main lock ...") |
|
|
|
s.mutex.RUnlock() |
|
|
|
s.mutex.RUnlock() |
|
|
|
|
|
|
|
|
|
|
|
if found == false { |
|
|
|
if found == false { |
|
|
|
log.Println("sesshist ERROR: addRecontRecord(): No session history for SessionID " + sessionID + " - creating session history.") |
|
|
|
log.Println("sesshist ERROR: addRecentRecord(): No session history for SessionID " + sessionID + " - creating session history.") |
|
|
|
s.initSession(sessionID) |
|
|
|
s.initSession(sessionID, record.Shell) |
|
|
|
return s.addRecentRecord(sessionID, record) |
|
|
|
return s.addRecentRecord(sessionID, record) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
log.Println("sesshist: RLocking session lock (w/ defer) ...") |
|
|
|
session.mutex.Lock() |
|
|
|
session.mutex.Lock() |
|
|
|
defer session.mutex.Unlock() |
|
|
|
defer session.mutex.Unlock() |
|
|
|
session.recentRecords = append(session.recentRecords, record) |
|
|
|
session.recentRecords = append(session.recentRecords, record) |
|
|
|
// remove previous occurance of record
|
|
|
|
session.recentCmdLines.AddCmdLine(record.CmdLine) |
|
|
|
cmdLine := record.CmdLine |
|
|
|
|
|
|
|
idx, found := session.cmdLinesLastIndex[cmdLine] |
|
|
|
|
|
|
|
if found { |
|
|
|
|
|
|
|
session.recentCmdLines = append(session.recentCmdLines[:idx], session.recentCmdLines[idx+1:]...) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
session.cmdLinesLastIndex[cmdLine] = len(session.recentCmdLines) |
|
|
|
|
|
|
|
// append new record
|
|
|
|
|
|
|
|
session.recentCmdLines = append(session.recentCmdLines, cmdLine) |
|
|
|
|
|
|
|
log.Println("sesshist: record:", record.CmdLine, "; added to session:", sessionID, |
|
|
|
log.Println("sesshist: record:", record.CmdLine, "; added to session:", sessionID, |
|
|
|
"; session len:", len(session.recentCmdLines), "; session len w/ dups:", len(session.recentRecords)) |
|
|
|
"; session len:", len(session.recentCmdLines.List), "; session len (records):", len(session.recentRecords)) |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Recall command from recent session history
|
|
|
|
// Recall command from recent session history
|
|
|
|
func (s *Dispatch) Recall(sessionID string, histno int, prefix string) (string, error) { |
|
|
|
func (s *Dispatch) Recall(sessionID string, histno int, prefix string) (string, error) { |
|
|
|
|
|
|
|
log.Println("sesshist - recall: RLocking main lock ...") |
|
|
|
s.mutex.RLock() |
|
|
|
s.mutex.RLock() |
|
|
|
|
|
|
|
log.Println("sesshist - recall: Getting session history struct ...") |
|
|
|
session, found := s.sessions[sessionID] |
|
|
|
session, found := s.sessions[sessionID] |
|
|
|
s.mutex.RUnlock() |
|
|
|
s.mutex.RUnlock() |
|
|
|
|
|
|
|
|
|
|
|
@ -141,21 +154,49 @@ func (s *Dispatch) Recall(sessionID string, histno int, prefix string) (string, |
|
|
|
// go s.initSession(sessionID)
|
|
|
|
// go s.initSession(sessionID)
|
|
|
|
return "", errors.New("sesshist ERROR: No session history for SessionID " + sessionID + " - should we create one?") |
|
|
|
return "", errors.New("sesshist ERROR: No session history for SessionID " + sessionID + " - should we create one?") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
log.Println("sesshist - recall: Locking session lock ...") |
|
|
|
|
|
|
|
session.mutex.Lock() |
|
|
|
|
|
|
|
defer session.mutex.Unlock() |
|
|
|
if prefix == "" { |
|
|
|
if prefix == "" { |
|
|
|
session.mutex.Lock() |
|
|
|
log.Println("sesshist - recall: Getting records by histno ...") |
|
|
|
defer session.mutex.Unlock() |
|
|
|
|
|
|
|
return session.getRecordByHistno(histno) |
|
|
|
return session.getRecordByHistno(histno) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
log.Println("sesshist - recall: Searching for records by prefix ...") |
|
|
|
|
|
|
|
return session.searchRecordByPrefix(prefix, histno) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Inspect commands in recent session history
|
|
|
|
|
|
|
|
func (s *Dispatch) Inspect(sessionID string, count int) ([]string, error) { |
|
|
|
|
|
|
|
prefix := "" |
|
|
|
|
|
|
|
log.Println("sesshist - inspect: RLocking main lock ...") |
|
|
|
|
|
|
|
s.mutex.RLock() |
|
|
|
|
|
|
|
log.Println("sesshist - inspect: Getting session history struct ...") |
|
|
|
|
|
|
|
session, found := s.sessions[sessionID] |
|
|
|
|
|
|
|
s.mutex.RUnlock() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if found == false { |
|
|
|
|
|
|
|
// go s.initSession(sessionID)
|
|
|
|
|
|
|
|
return nil, errors.New("sesshist ERROR: No session history for SessionID " + sessionID + " - should we create one?") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
log.Println("sesshist - inspect: Locking session lock ...") |
|
|
|
session.mutex.Lock() |
|
|
|
session.mutex.Lock() |
|
|
|
defer session.mutex.Unlock() |
|
|
|
defer session.mutex.Unlock() |
|
|
|
return session.searchRecordByPrefix(prefix, histno) |
|
|
|
if prefix == "" { |
|
|
|
|
|
|
|
log.Println("sesshist - inspect: Getting records by histno ...") |
|
|
|
|
|
|
|
idx := len(session.recentCmdLines.List) - count |
|
|
|
|
|
|
|
if idx < 0 { |
|
|
|
|
|
|
|
idx = 0 |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return session.recentCmdLines.List[idx:], nil |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
log.Println("sesshist - inspect: Searching for records by prefix ... ERROR - Not implemented") |
|
|
|
|
|
|
|
return nil, errors.New("sesshist ERROR: Inspect - Searching for records by prefix Not implemented yet") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
type sesshist struct { |
|
|
|
type sesshist struct { |
|
|
|
recentRecords []records.Record |
|
|
|
mutex sync.Mutex |
|
|
|
recentCmdLines []string // deduplicated
|
|
|
|
recentRecords []records.Record |
|
|
|
cmdLinesLastIndex map[string]int |
|
|
|
recentCmdLines histlist.Histlist |
|
|
|
mutex sync.Mutex |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s *sesshist) getRecordByHistno(histno int) (string, error) { |
|
|
|
func (s *sesshist) getRecordByHistno(histno int) (string, error) { |
|
|
|
@ -167,11 +208,11 @@ func (s *sesshist) getRecordByHistno(histno int) (string, error) { |
|
|
|
if histno < 0 { |
|
|
|
if histno < 0 { |
|
|
|
return "", errors.New("sesshist ERROR: 'histno < 0' is a command from future (not supperted yet)") |
|
|
|
return "", errors.New("sesshist ERROR: 'histno < 0' is a command from future (not supperted yet)") |
|
|
|
} |
|
|
|
} |
|
|
|
index := len(s.recentCmdLines) - histno |
|
|
|
index := len(s.recentCmdLines.List) - histno |
|
|
|
if index < 0 { |
|
|
|
if index < 0 { |
|
|
|
return "", errors.New("sesshist ERROR: 'histno > number of commands in the session' (" + strconv.Itoa(len(s.recentCmdLines)) + ")") |
|
|
|
return "", errors.New("sesshist ERROR: 'histno > number of commands in the session' (" + strconv.Itoa(len(s.recentCmdLines.List)) + ")") |
|
|
|
} |
|
|
|
} |
|
|
|
return s.recentCmdLines[index], nil |
|
|
|
return s.recentCmdLines.List[index], nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s *sesshist) searchRecordByPrefix(prefix string, histno int) (string, error) { |
|
|
|
func (s *sesshist) searchRecordByPrefix(prefix string, histno int) (string, error) { |
|
|
|
@ -181,14 +222,14 @@ func (s *sesshist) searchRecordByPrefix(prefix string, histno int) (string, erro |
|
|
|
if histno < 0 { |
|
|
|
if histno < 0 { |
|
|
|
return "", errors.New("sesshist ERROR: 'histno < 0' is a command from future (not supperted yet)") |
|
|
|
return "", errors.New("sesshist ERROR: 'histno < 0' is a command from future (not supperted yet)") |
|
|
|
} |
|
|
|
} |
|
|
|
index := len(s.recentCmdLines) - histno |
|
|
|
index := len(s.recentCmdLines.List) - histno |
|
|
|
if index < 0 { |
|
|
|
if index < 0 { |
|
|
|
return "", errors.New("sesshist ERROR: 'histno > number of commands in the session' (" + strconv.Itoa(len(s.recentCmdLines)) + ")") |
|
|
|
return "", errors.New("sesshist ERROR: 'histno > number of commands in the session' (" + strconv.Itoa(len(s.recentCmdLines.List)) + ")") |
|
|
|
} |
|
|
|
} |
|
|
|
cmdLines := []string{} |
|
|
|
cmdLines := []string{} |
|
|
|
for i := len(s.recentCmdLines) - 1; i >= 0; i-- { |
|
|
|
for i := len(s.recentCmdLines.List) - 1; i >= 0; i-- { |
|
|
|
if strings.HasPrefix(s.recentCmdLines[i], prefix) { |
|
|
|
if strings.HasPrefix(s.recentCmdLines.List[i], prefix) { |
|
|
|
cmdLines = append(cmdLines, s.recentCmdLines[i]) |
|
|
|
cmdLines = append(cmdLines, s.recentCmdLines.List[i]) |
|
|
|
if len(cmdLines) >= histno { |
|
|
|
if len(cmdLines) >= histno { |
|
|
|
break |
|
|
|
break |
|
|
|
} |
|
|
|
} |
|
|
|
|