telsh

package
v0.0.0-...-9ff0b2a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 21, 2018 License: MIT Imports: 7 Imported by: 5

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

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

type Producer interface {
	Produce(telnet.Context, string, ...string) Handler
}

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

type ProducerFunc func(telnet.Context, string, ...string) Handler

ProducerFunc is an adaptor, that can be used to turn a func with the signature:

func(telnet.Context, string, ...string) Handler

Into a Producer

func (ProducerFunc) Produce

func (fn ProducerFunc) Produce(ctx telnet.Context, name string, args ...string) Handler

Produce makes ProducerFunc fit the Producer interface.

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)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL