227 lines
6.0 KiB
Go
227 lines
6.0 KiB
Go
/*
|
|
Copyright (c) 2018 Rasmus Moorats (nns)
|
|
|
|
This file is part of iopshell.
|
|
|
|
iopshell is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
iopshell 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with iopshell. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package setting
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/chzyer/readline"
|
|
"github.com/nnsee/iopshell/internal/cmd"
|
|
"github.com/nnsee/iopshell/internal/connection"
|
|
"github.com/nnsee/iopshell/internal/textmutate"
|
|
)
|
|
|
|
var (
|
|
// ConnChannel listens for connection requests
|
|
ConnChannel = make(chan []string)
|
|
// ScriptIn listens for script run requests
|
|
ScriptIn = make(chan []string)
|
|
// ScriptRet houses return codes from scripts
|
|
ScriptRet = make(chan error)
|
|
// In receives incoming messages
|
|
In = make(chan interface{})
|
|
// Out houses outgoing messages
|
|
Out = make(chan interface{})
|
|
// PassBack returns a response to a command if requested
|
|
PassBack = make(chan connection.Response)
|
|
// PassBackID houses ID waiting for a response
|
|
PassBackID = -1
|
|
)
|
|
|
|
// Opt houses some options
|
|
type Opt struct {
|
|
Description string
|
|
Val interface{}
|
|
}
|
|
|
|
// ShellVars house some important structs, so they can be accessed elsewhere
|
|
type ShellVars struct {
|
|
Conn *connection.Connection
|
|
Completer readline.PrefixCompleter
|
|
Instance *readline.Instance
|
|
Opts map[string]*Opt
|
|
}
|
|
|
|
// Set sets opt to val
|
|
func (s *ShellVars) Set(opt string, val interface{}) bool {
|
|
if o, ok := s.Opts[opt]; ok {
|
|
o.Val = val
|
|
if opt == "verbose" { // there's got to be a better way to do this
|
|
textmutate.Verbose = val.(bool)
|
|
}
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Get returns the specified option's pointer, or false if it doesn't exist
|
|
func (s *ShellVars) Get(opt string) (*Opt, bool) {
|
|
if o, ok := s.Opts[opt]; ok {
|
|
return o, true
|
|
}
|
|
return &Opt{}, false
|
|
}
|
|
|
|
// GetS returns the specified option's value as a string, or false if it doesn't exist
|
|
func (s *ShellVars) GetS(opt string) (string, bool) {
|
|
if o, ok := s.Opts[opt]; ok {
|
|
val, err := o.Val.(string)
|
|
return val, err
|
|
}
|
|
return "", false
|
|
}
|
|
|
|
// GetB returns the specified option's value as a bool, or false if it doesn't exist
|
|
func (s *ShellVars) GetB(opt string) (bool, bool) {
|
|
if o, ok := s.Opts[opt]; ok {
|
|
val, err := o.Val.(bool)
|
|
return val, err
|
|
}
|
|
return false, false
|
|
}
|
|
|
|
// GetF returns the specified option's value as an float64, or false if it doesn't exist
|
|
func (s *ShellVars) GetF(opt string) (float64, bool) {
|
|
if o, ok := s.Opts[opt]; ok {
|
|
val, err := o.Val.(float64)
|
|
return val, err
|
|
}
|
|
return 0, false
|
|
}
|
|
|
|
// GetResponse can be used by commands to get a response
|
|
func GetResponse(id int) connection.Response {
|
|
var placeholder connection.Response
|
|
if id == -1 {
|
|
// call failed
|
|
return placeholder
|
|
}
|
|
PassBackID = id
|
|
return <-PassBack
|
|
}
|
|
|
|
// UpdatePrompt refreshes the prompt and sets it according to current status
|
|
func (s *ShellVars) UpdatePrompt() {
|
|
var prompt string
|
|
prompt = "\033[91miop\033[0;1m$\033[0m "
|
|
|
|
if s.Conn.Ws != nil {
|
|
if s.Conn.User == "" {
|
|
// Connected but not authenticated
|
|
prompt = "\033[32miop\033[0;1m$\033[0m "
|
|
} else {
|
|
// Connected and authenticated
|
|
prompt = fmt.Sprintf("\033[32miop\033[0m %s\033[0;1m$\033[0m ", s.Conn.User)
|
|
}
|
|
}
|
|
|
|
if s.Instance != nil {
|
|
s.Instance.SetPrompt(prompt)
|
|
s.Instance.Refresh()
|
|
}
|
|
}
|
|
|
|
// Helper item for call item completion
|
|
func callCompleterItem(name string) *readline.PrefixCompleter {
|
|
name += ":"
|
|
return &readline.PrefixCompleter{
|
|
Name: []rune(name),
|
|
Dynamic: false,
|
|
Children: nil,
|
|
}
|
|
}
|
|
|
|
// UpdateCompleter adds commands registered with .Register() to the autocompleter
|
|
func (s *ShellVars) UpdateCompleter(cmdlist map[string]cmd.Command) {
|
|
s.Completer = *readline.NewPrefixCompleter()
|
|
s.Completer.SetChildren(*new([]readline.PrefixCompleterInterface))
|
|
|
|
for _, c := range cmdlist {
|
|
s.Completer.Children = append(s.Completer.Children,
|
|
readline.PcItem(c.Name))
|
|
}
|
|
}
|
|
|
|
// UpdateCallCompleter generates the completer for the "call" command
|
|
// supplied via a map generated by the "list" method
|
|
func (s *ShellVars) UpdateCallCompleter(list map[string]interface{}) {
|
|
parent := readline.PcItem("call")
|
|
|
|
for k1, v1 := range list {
|
|
path := readline.PcItem(k1)
|
|
methods, ok := v1.(map[string]interface{})
|
|
if ok {
|
|
for k2, v2 := range methods {
|
|
method := readline.PcItem(k2)
|
|
items, ok := v2.(map[string]interface{})
|
|
if ok {
|
|
for k3 := range items {
|
|
method.Children = append(method.Children,
|
|
callCompleterItem(k3))
|
|
}
|
|
}
|
|
path.Children = append(path.Children, method)
|
|
}
|
|
}
|
|
parent.Children = append(parent.Children, path)
|
|
}
|
|
|
|
// remove previous "call" completer to avoid duplicates
|
|
for i, child := range s.Completer.Children {
|
|
if string(child.GetName())[:4] == "call" {
|
|
s.Completer.Children = append(s.Completer.Children[:i],
|
|
s.Completer.Children[i+1:]...)
|
|
}
|
|
}
|
|
|
|
// add new and improved completer
|
|
s.Completer.Children = append(s.Completer.Children, parent)
|
|
}
|
|
|
|
// Init values for Vars
|
|
func genVars() *ShellVars {
|
|
var vars ShellVars
|
|
vars.Opts = make(map[string]*Opt)
|
|
vars.Opts["host"] = &Opt{
|
|
Description: "Host to connect to by default",
|
|
Val: "192.168.1.1",
|
|
}
|
|
vars.Opts["user"] = &Opt{
|
|
Description: "User to authenticate as by default",
|
|
Val: "user",
|
|
}
|
|
vars.Opts["pass"] = &Opt{
|
|
Description: "Password to authenticate with by default",
|
|
Val: "user",
|
|
}
|
|
vars.Opts["verbose"] = &Opt{
|
|
Description: "Print verbose messages",
|
|
Val: textmutate.Verbose,
|
|
}
|
|
vars.Opts["script_delay"] = &Opt{
|
|
Description: "Number of seconds to wait between each command when running a script",
|
|
Val: float64(0),
|
|
}
|
|
return &vars
|
|
}
|
|
|
|
// Vars is an instance of ShellVars
|
|
var Vars = *genVars()
|