Documentation
¶
Overview ¶
Package telsh provides "middleware" (for the telnet package) that can be used to implement a TELNET or TELNETS server that provides a "shell" interface (also known as a "command-line interface" or "CLI").
Shell interfaces you may be familiar with include: "bash", "csh", "sh", "zsk", etc.
TELNET Server ¶
Here is an example usage:
package main import ( "github.com/reiver/go-oi" "github.com/reiver/go-telnet" "github.com/reiver/go-telnet/telsh" "io" ) func main() { telnetHandler := telsh.NewShellHandler() if err := telnetHandler.RegisterElse( telsh.ProducerFunc( func(ctx telnet.Context, name string, args ...string) telsh.Handler { return telsh.PromoteHandlerFunc( func(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error { oi.LongWrite(stdout, []byte{'w','a','t','?', '\r','\n'}) return nil }, ) }, ), ); nil != err { panic(err) } if err := telnetHandler.Register("help", telsh.ProducerFunc( func(ctx telnet.Context, name string, args ...string) telsh.Handler { return telsh.PromoteHandlerFunc( func(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error { oi.LongWrite(stdout, []byte{'r','t','f','m','!', '\r','\n'}) return nil }, ) }, ), ); nil != err { panic(err) } err := telnet.ListenAndServe(":5555", telnetHandler) if nil != err { //@TODO: Handle this error better. panic(err) } }
Here is a more "unpacked" example:
package main import ( "github.com/reiver/go-oi" "github.com/reiver/go-telnet" "github.com/reiver/go-telnet/telsh" "io" "time" ) var ( shellHandler = telsh.NewShellHandler() ) func init() { shellHandler.Register("dance", telsh.ProducerFunc(producer)) shellHandler.WelcomeMessage = ` __ __ ______ _ _____ ____ __ __ ______ \ \ / /| ____|| | / ____| / __ \ | \/ || ____| \ \ /\ / / | |__ | | | | | | | || \ / || |__ \ \/ \/ / | __| | | | | | | | || |\/| || __| \ /\ / | |____ | |____ | |____ | |__| || | | || |____ \/ \/ |______||______| \_____| \____/ |_| |_||______| ` } func producer(ctx telnet.Context, name string, args ...string) telsh.Handler{ return telsh.PromoteHandlerFunc(handler) } func handler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error { for i:=0; i<20; i++ { oi.LongWriteString(stdout, "\r⠋") time.Sleep(50*time.Millisecond) oi.LongWriteString(stdout, "\r⠙") time.Sleep(50*time.Millisecond) oi.LongWriteString(stdout, "\r⠹") time.Sleep(50*time.Millisecond) oi.LongWriteString(stdout, "\r⠸") time.Sleep(50*time.Millisecond) oi.LongWriteString(stdout, "\r⠼") time.Sleep(50*time.Millisecond) oi.LongWriteString(stdout, "\r⠴") time.Sleep(50*time.Millisecond) oi.LongWriteString(stdout, "\r⠦") time.Sleep(50*time.Millisecond) oi.LongWriteString(stdout, "\r⠧") time.Sleep(50*time.Millisecond) oi.LongWriteString(stdout, "\r⠇") time.Sleep(50*time.Millisecond) oi.LongWriteString(stdout, "\r⠏") time.Sleep(50*time.Millisecond) } oi.LongWriteString(stdout, "\r \r\n") return nil } func main() { addr := ":5555" if err := telnet.ListenAndServe(addr, shellHandler); nil != err { panic(err) } }
Index ¶
- type Handler
- type HandlerFunc
- type Producer
- type ProducerFunc
- type ShellHandler
- func (telnetHandler *ShellHandler) MustRegister(name string, producer Producer) *ShellHandler
- func (telnetHandler *ShellHandler) MustRegisterElse(producer Producer) *ShellHandler
- func (telnetHandler *ShellHandler) MustRegisterHandlerFunc(name string, handlerFunc HandlerFunc) *ShellHandler
- func (telnetHandler *ShellHandler) Register(name string, producer Producer) error
- func (telnetHandler *ShellHandler) RegisterElse(producer Producer) error
- func (telnetHandler *ShellHandler) RegisterHandlerFunc(name string, handlerFunc HandlerFunc) error
- func (telnetHandler *ShellHandler) ServeTELNET(ctx telnet.Context, writer telnet.Writer, reader telnet.Reader)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Handler ¶
type Handler interface { Run() error StdinPipe() (io.WriteCloser, error) StdoutPipe() (io.ReadCloser, error) StderrPipe() (io.ReadCloser, error) }
Hander is an abstraction that represents a "running" shell "command".
Contrast this with a Producer, which is is an abstraction that represents a shell "command".
To use a metaphor, the differences between a Producer and a Handler, is like the difference between a program executable and actually running the program executable.
Conceptually, anything that implements the Hander, and then has its Producer registered with ShellHandler.Register() will be available as a command.
Note that Handler was intentionally made to be compatible with "os/exec", which is part of the Go standard library.
func PromoteHandlerFunc ¶
func PromoteHandlerFunc(fn HandlerFunc, args ...string) Handler
PromoteHandlerFunc turns a HandlerFunc into a Handler.
type HandlerFunc ¶
type HandlerFunc func(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error
HandlerFunc is useful to write inline Producers, and provides an alternative to creating something that implements Handler directly.
For example:
shellHandler := telsh.NewShellHandler() shellHandler.Register("five", telsh.ProducerFunc( func(ctx telnet.Context, name string, args ...string) telsh.Handler{ return telsh.PromoteHandlerFunc( func(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error { oi.LongWrite(stdout, []byte{'5', '\r', '\n'}) return nil }, ) }, ))
Note that PromoteHandlerFunc is used to turn a HandlerFunc into a Handler.
type Producer ¶
A Producer provides a Produce method which creates a Handler.
Producer is an abstraction that represents a shell "command".
Contrast this with a Handler, which is is an abstraction that represents a "running" shell "command".
To use a metaphor, the differences between a Producer and a Handler, is like the difference between a program executable and actually running the program executable.
func Help ¶
func Help(shellHandler *ShellHandler) Producer
type ProducerFunc ¶
ProducerFunc is an adaptor, that can be used to turn a func with the signature:
func(telnet.Context, string, ...string) Handler
Into a Producer
type ShellHandler ¶
type ShellHandler struct { ExitCommandName string Prompt string WelcomeMessage string ExitMessage string // contains filtered or unexported fields }
func NewShellHandler ¶
func NewShellHandler() *ShellHandler
func (*ShellHandler) MustRegister ¶
func (telnetHandler *ShellHandler) MustRegister(name string, producer Producer) *ShellHandler
func (*ShellHandler) MustRegisterElse ¶
func (telnetHandler *ShellHandler) MustRegisterElse(producer Producer) *ShellHandler
func (*ShellHandler) MustRegisterHandlerFunc ¶
func (telnetHandler *ShellHandler) MustRegisterHandlerFunc(name string, handlerFunc HandlerFunc) *ShellHandler
func (*ShellHandler) Register ¶
func (telnetHandler *ShellHandler) Register(name string, producer Producer) error
func (*ShellHandler) RegisterElse ¶
func (telnetHandler *ShellHandler) RegisterElse(producer Producer) error
func (*ShellHandler) RegisterHandlerFunc ¶
func (telnetHandler *ShellHandler) RegisterHandlerFunc(name string, handlerFunc HandlerFunc) error
func (*ShellHandler) ServeTELNET ¶
func (telnetHandler *ShellHandler) ServeTELNET(ctx telnet.Context, writer telnet.Writer, reader telnet.Reader)