1
0
mirror of https://github.com/taigrr/arduinolibs synced 2025-01-18 04:33:12 -08:00

Rename Terminal library to Shell library

This commit is contained in:
Rhys Weatherley
2016-03-13 07:24:22 +10:00
parent 4c51be9ae8
commit f5dc64aa7c
16 changed files with 8 additions and 8 deletions

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2016 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "LoginShell.h"
/**
* \class LoginShell LoginShell.h <LoginShell.h>
* \brief Command-line shell access via a login shell.
*
* This class provides a command-line shell with login support.
* The user is prompted for username and password when they connect
* and other commands will not be available until the correct credentials
* have been supplied.
*
* \sa Shell
*/
/**
* \typedef ShellPasswordCheckFunc
* \brief Password checking function for login shells.
*
* \param username Points to the user name that was supplied at login.
* \param password Points to the password that was supplied at login.
*
* \return Returns zero or greater if the username and password combination
* is correct, negative if incorrect.
*
* The return value is reported to the application as Shell::userid(),
* which can be used by the application to restrict the set of commands
* that are available to the user, or to restrict the behaviour of
* those commands when acting on critical resources.
*
* Timing can be very important: the check should take the same amount of
* time for valid and invalid user identifiers or passwords so that an
* attacker cannot gain knowledge about the valid users on the system
* based on failed login attempts.
*
* \relates LoginShell
* \sa Shell::userid()
*/
/**
* \brief Constructs a new login shell.
*
* This constructor must be followed by a call to begin() to specify
* the underlying I/O stream.
*/
LoginShell::LoginShell()
: machName(0)
, checkFunc(0)
{
}
/**
* \brief Destroys this login shell.
*/
LoginShell::~LoginShell()
{
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2016 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef LOGIN_SHELL_h
#define LOGIN_SHELL_h
#include "Shell.h"
typedef int (*ShellPasswordCheckFunc)(const char *username, const char *password);
class LoginShell : public Shell
{
public:
LoginShell();
virtual ~LoginShell();
const char *machineName() const { return machName; }
void setMachineName(const char *machineName) { machName = machineName; }
ShellPasswordCheckFunc passwordCheckFunction() const { return checkFunc; }
void setPasswordCheckFunction(ShellPasswordCheckFunc function) { checkFunc = function; }
protected:
virtual void beginSession();
virtual void printPrompt();
virtual void execute();
private:
const char *machName;
ShellPasswordCheckFunc checkFunc;
};
#endif

1092
libraries/Shell/Shell.cpp Normal file

File diff suppressed because it is too large Load Diff

163
libraries/Shell/Shell.h Normal file
View File

@@ -0,0 +1,163 @@
/*
* Copyright (C) 2016 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef SHELL_h
#define SHELL_h
#include "Terminal.h"
#include <Client.h>
class Shell;
class ShellArguments;
class LoginShell;
#if defined(__arm__)
#define SHELL_MAX_CMD_LEN 256
#else
#define SHELL_MAX_CMD_LEN 64
#endif
typedef void (*ShellCommandFunc)(Shell &shell, int argc, const ShellArguments &argv);
/** @cond */
typedef struct
{
const char *name;
const char *help;
ShellCommandFunc func;
} ShellCommandInfo;
class ShellCommandRegister
{
public:
inline ShellCommandRegister(const ShellCommandInfo *_info);
const ShellCommandInfo *info;
ShellCommandRegister *next;
};
/** @endcond */
class Shell : public Terminal
{
public:
Shell();
virtual ~Shell();
bool begin(Stream &stream, size_t maxHistory = 0, Terminal::Mode mode = Serial);
bool begin(Client &client, size_t maxHistory = 0, Terminal::Mode mode = Telnet);
void end();
void loop();
static void registerCommand(ShellCommandRegister *cmd);
const char *prompt() const { return prom; }
void setPrompt(const char *prompt) { prom = prompt; }
int userid() const { return uid; }
void setUserid(int userid) { uid = userid; }
void help();
void exit();
protected:
virtual void beginSession();
virtual void printPrompt();
virtual void execute();
private:
char buffer[SHELL_MAX_CMD_LEN];
size_t curStart;
size_t curLen;
size_t curMax;
char *history;
size_t historyWrite;
size_t historyRead;
size_t historySize;
const char *prom;
bool isClient;
uint8_t lineMode;
int uid;
unsigned long timer;
// Disable copy constructor and operator=().
Shell(const Shell &other) {}
Shell &operator=(const Shell &) { return *this; }
bool beginShell(Stream &stream, size_t maxHistory, Terminal::Mode mode);
bool execute(const ShellArguments &argv);
void executeBuiltin(const char *cmd);
void clearCharacters(size_t len);
void changeHistory(bool up);
void clearHistory();
friend class LoginShell;
};
class ShellArguments
{
friend class Shell;
private:
ShellArguments(char *buffer, size_t len);
~ShellArguments() {}
public:
int count() const { return argc; }
const char *operator[](int index) const;
private:
const char *line;
size_t size;
int argc;
mutable int currentIndex;
mutable size_t currentPosn;
// Disable copy constructor and operator=().
ShellArguments(const ShellArguments &other) {}
ShellArguments &operator=(const ShellArguments &) { return *this; }
};
/** @cond */
inline ShellCommandRegister::ShellCommandRegister(const ShellCommandInfo *_info)
: info(_info)
, next(0)
{
Shell::registerCommand(this);
}
/** @endcond */
#define ShellCommand(name,help,function) \
static char const shell_id_##name[] PROGMEM = #name; \
static char const shell_help_##name[] PROGMEM = help; \
static ShellCommandInfo const shell_info_##name PROGMEM = { \
shell_id_##name, \
shell_help_##name, \
(function) \
}; \
static ShellCommandRegister shell_cmd_##name(&shell_info_##name)
#endif

View File

@@ -0,0 +1,116 @@
/*
* Copyright (C) 2016 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef TELNET_DEFS_h
#define TELNET_DEFS_h
// References:
// https://tools.ietf.org/html/rfc854
// http://www.iana.org/assignments/telnet-options/telnet-options.xhtml
namespace TelnetDefs
{
/** Telnet commands */
enum Command
{
EndOfFile = 236, /**< EOF */
Suspend = 237, /**< Suspend process */
Abort = 238, /**< Abort process */
EndOfRecord = 239, /**< End of record command */
SubEnd = 240, /**< End option sub-negotiation */
NOP = 241, /**< No operation */
DataMark = 242, /**< Data mark */
Break = 243, /**< Break */
Interrupt = 244, /**< Interrupt process */
AbortOutput = 245, /**< Abort output */
AreYouThere = 246, /**< Are you there? */
EraseChar = 247, /**< Erase character */
EraseLine = 248, /**< Erase line */
GoAhead = 249, /**< Go ahead in half-duplex mode */
SubStart = 250, /**< Option sub-negotiation */
WILL = 251, /**< Will use option */
WONT = 252, /**< Won't use option */
DO = 253, /**< Do use option */
DONT = 254, /**< Don't use option */
IAC = 255 /**< Interpret As Command */
};
/** Telnet options used in sub-negotiations */
enum Option
{
Binary = 0, /**< Binary transmission */
Echo = 1, /**< Echo */
Reconnection = 2, /**< Reconnection */
SuppressGoAhead = 3, /**< Suppress half-duplex go ahead signals */
ApproxMsgSize = 4, /**< Approx message size negotiation */
Status = 5, /**< Give status on prevailing options */
TimingMark = 6, /**< Timing mark */
RemoteTransmitEcho = 7, /**< Remote controlled transmit and echo */
LineWidth = 8, /**< Line width */
PageSize = 9, /**< Page size */
CarriageReturn = 10, /**< Carriage return disposition */
HorzTabStops = 11, /**< Horizontal tab stops */
HorzTabStopDisp = 12, /**< Horizontal tab stop disposition */
FormFeed = 13, /**< Form feed disposition */
VertTabStops = 14, /**< Vertical tab stops */
VertTabStopDisp = 15, /**< Vertical tab stop disposition */
LineFeed = 16, /**< Line feed disposition */
ExtendedASCII = 17, /**< Extended ASCII */
Logout = 18, /**< Force logout */
ByteMacro = 19, /**< Byte macro */
DataEntryTerminal = 20, /**< Data entry terminal */
SUPDUP = 21, /**< SUPDUP protocol */
SUPDUPOutput = 22, /**< SUPDUP output */
SendLocation = 23, /**< Send the user's location */
TerminalType = 24, /**< Terminal type */
EndOfRecordOption = 25, /**< End of record option */
TACACSUserId = 26, /**< TACACS user identification */
OutputMarking = 27, /**< Output marking */
TerminalLocation = 28, /**< Terminal location number */
Telnet3270Regime = 29, /**< Telnet 3270 regime */
X3Pad = 30, /**< X.3 PAD */
WindowSize = 31, /**< Window size */
Speed = 32, /**< Terminal speed */
RemoteFlowControl = 33, /**< Remote flow control */
Linemode = 34, /**< Linemode option */
XDisplay = 35, /**< X display location */
EnvironmentOld = 36, /**< Environment variables (old version) */
Authentication = 37, /**< Authentication */
Encryption = 38, /**< Encryption */
Environment = 39, /**< Environment variables (new version) */
TN3270E = 40, /**< TN3270E */
XAUTH = 41, /**< XAUTH */
Charset = 42, /**< Character set */
RemoteSerialPort = 43, /**< Remote serial port */
ComPortControl = 44, /**< COM port control */
SuppressLocalEcho = 45, /**< Suppress local echo */
StartTLS = 46, /**< Start TLS session */
Kermit = 47, /**< KERMIT protocol */
SendURL = 48, /**< Send URL */
ForwardX = 49, /**< Forward X protocol */
Extended = 255 /**< Extended options list */
};
};
#endif

1464
libraries/Shell/Terminal.cpp Normal file

File diff suppressed because it is too large Load Diff

146
libraries/Shell/Terminal.h Normal file
View File

@@ -0,0 +1,146 @@
/*
* Copyright (C) 2016 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef TERMINAL_h
#define TERMINAL_h
#include <Arduino.h>
#include <USBAPI.h>
#include "USBKeysExtra.h"
// Special key code that indicates that unicodeKey() contains the actual code.
#define KEY_UNICODE 0x1000
// Special key code that indicates that the window size has changed.
#define KEY_WINSIZE 0x1001
class Terminal : public Stream
{
public:
Terminal();
virtual ~Terminal();
enum Mode
{
Serial,
Telnet
};
void begin(Stream &stream, Mode mode = Serial);
void end();
Stream *stream() const { return _stream; }
Terminal::Mode mode() const { return (Terminal::Mode)mod; }
virtual int available();
virtual int peek();
virtual int read();
virtual void flush();
virtual size_t write(uint8_t c);
virtual size_t write(const uint8_t *buffer, size_t size);
using Stream::write;
void writeProgMem(const char *str);
int readKey();
long unicodeKey() const { return ucode; }
size_t writeUnicode(long code);
int columns() const { return ncols; }
int rows() const { return nrows; }
bool setWindowSize(int columns, int rows);
void clear();
void clearToEOL();
void cursorMove(int x, int y);
void cursorLeft();
void cursorRight();
void cursorUp();
void cursorDown();
void backspace();
void insertLine();
void insertChar();
void deleteLine();
void deleteChar();
void scrollUp();
void scrollDown();
void normal();
void bold();
void underline();
void blink();
void reverse();
enum Color
{
Black = 0x00,
DarkRed = 0x01,
DarkGreen = 0x02,
DarkYellow = 0x03,
DarkBlue = 0x04,
DarkMagenta = 0x05,
DarkCyan = 0x06,
LightGray = 0x07,
DarkGray = 0x08,
Red = 0x09,
Green = 0x0A,
Yellow = 0x0B,
Blue = 0x0C,
Magenta = 0x0D,
Cyan = 0x0E,
White = 0x0F
};
void color(Color fg);
void color(Color fg, Color bg);
static bool isWideCharacter(long code);
static size_t utf8Length(long code);
static size_t utf8Format(uint8_t *buffer, long code);
private:
Stream *_stream;
long ucode;
int ncols, nrows;
unsigned long timer;
uint16_t offset;
uint8_t state;
uint8_t utf8len;
uint8_t mod;
uint8_t sb[8];
uint8_t flags;
int matchEscape(int ch);
void telnetCommand(uint8_t type, uint8_t option);
};
#endif

View File

@@ -0,0 +1,124 @@
/*
* Copyright (C) 2016 Southern Storm Software, Pty Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef USBKEYSEXTRA_h
#define USBKEYSEXTRA_h
// Extra key codes that are not included in the standard USBAPI.h header.
// Reference: http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
// Note: USBAPI.h shifts the Hut codes by adding 136 (0x88) so that
// they don't intersect with ASCII. We do that here as well so
// that these codes can be used with Keyboard.press(). We use #ifndef
// here in case the core Arduino libraries add these in the future.
#ifndef KEY_PRINT_SCREEN
#define KEY_PRINT_SCREEN (0x46 + 0x88)
#endif
#ifndef KEY_SCROLL_LOCK
#define KEY_SCROLL_LOCK (0x47 + 0x88)
#endif
#ifndef KEY_PAUSE
#define KEY_PAUSE (0x48 + 0x88)
#endif
#ifndef KEY_NUM_LOCK
#define KEY_NUM_LOCK (0x53 + 0x88)
#endif
#ifndef KEY_NUMPAD_5
#define KEY_NUMPAD_5 (0x5D + 0x88)
#endif
#ifndef KEY_F13
#define KEY_F13 (0x68 + 0x88)
#endif
#ifndef KEY_F14
#define KEY_F14 (0x69 + 0x88)
#endif
#ifndef KEY_F15
#define KEY_F15 (0x6A + 0x88)
#endif
#ifndef KEY_F16
#define KEY_F16 (0x6B + 0x88)
#endif
#ifndef KEY_F17
#define KEY_F17 (0x6C + 0x88)
#endif
#ifndef KEY_F18
#define KEY_F18 (0x6D + 0x88)
#endif
#ifndef KEY_F19
#define KEY_F19 (0x6E + 0x88)
#endif
#ifndef KEY_F20
#define KEY_F20 (0x6F + 0x88)
#endif
#ifndef KEY_F21
#define KEY_F21 (0x70 + 0x88)
#endif
#ifndef KEY_F22
#define KEY_F22 (0x71 + 0x88)
#endif
#ifndef KEY_F23
#define KEY_F23 (0x72 + 0x88)
#endif
#ifndef KEY_F24
#define KEY_F24 (0x73 + 0x88)
#endif
// USB does not have a code for "Back Tab" as it is usually Shift-TAB.
// For convenience, we map it to the ASCII vertical tab character (0x0B).
#define KEY_BACK_TAB 0x0B
#ifndef KEY_RETURN
// If the Arduino variant does not support USB, then USBAPI.h will not
// define the key codes that we need. So we define them here instead.
#define KEY_RETURN (0x28 + 0x88)
#define KEY_ESC (0x29 + 0x88)
#define KEY_BACKSPACE (0x2A + 0x88)
#define KEY_TAB (0x2B + 0x88)
#define KEY_CAPS_LOCK (0x39 + 0x88)
#define KEY_F1 (0x3A + 0x88)
#define KEY_F2 (0x3B + 0x88)
#define KEY_F3 (0x3C + 0x88)
#define KEY_F4 (0x3D + 0x88)
#define KEY_F5 (0x3E + 0x88)
#define KEY_F6 (0x3F + 0x88)
#define KEY_F7 (0x40 + 0x88)
#define KEY_F8 (0x41 + 0x88)
#define KEY_F9 (0x42 + 0x88)
#define KEY_F10 (0x43 + 0x88)
#define KEY_F11 (0x44 + 0x88)
#define KEY_F12 (0x45 + 0x88)
#define KEY_INSERT (0x49 + 0x88)
#define KEY_HOME (0x4A + 0x88)
#define KEY_PAGE_UP (0x4B + 0x88)
#define KEY_DELETE (0x4C + 0x88)
#define KEY_END (0x4D + 0x88)
#define KEY_PAGE_DOWN (0x4E + 0x88)
#define KEY_RIGHT_ARROW (0x4F + 0x88)
#define KEY_LEFT_ARROW (0x50 + 0x88)
#define KEY_DOWN_ARROW (0x51 + 0x88)
#define KEY_UP_ARROW (0x52 + 0x88)
#endif
#endif

View File

@@ -0,0 +1,127 @@
/*
This example tests the Terminal class by displaying the VT100 keys that
are pressed. A real terminal program like PuTTY will be needed.
This example is placed into the public domain.
*/
#include <Terminal.h>
#include <avr/pgmspace.h>
Terminal term;
#define K(name) {name, #name}
struct KeyInfo
{
uint8_t code;
char name[19];
};
struct KeyInfo const keys[] PROGMEM = {
K(KEY_RETURN),
K(KEY_ESC),
K(KEY_BACKSPACE),
K(KEY_TAB),
K(KEY_BACK_TAB),
K(KEY_CAPS_LOCK),
K(KEY_F1),
K(KEY_F2),
K(KEY_F3),
K(KEY_F4),
K(KEY_F5),
K(KEY_F6),
K(KEY_F7),
K(KEY_F8),
K(KEY_F9),
K(KEY_F10),
K(KEY_F11),
K(KEY_F12),
K(KEY_F13),
K(KEY_F14),
K(KEY_F15),
K(KEY_F16),
K(KEY_F17),
K(KEY_F18),
K(KEY_F19),
K(KEY_F20),
K(KEY_F21),
K(KEY_F22),
K(KEY_F23),
K(KEY_F24),
K(KEY_INSERT),
K(KEY_HOME),
K(KEY_PAGE_UP),
K(KEY_DELETE),
K(KEY_END),
K(KEY_PAGE_DOWN),
K(KEY_RIGHT_ARROW),
K(KEY_LEFT_ARROW),
K(KEY_DOWN_ARROW),
K(KEY_UP_ARROW),
K(KEY_PRINT_SCREEN),
K(KEY_SCROLL_LOCK),
K(KEY_PAUSE),
K(KEY_NUM_LOCK),
K(KEY_NUMPAD_5),
{0, ""}
};
void setup()
{
Serial.begin(9600);
term.begin(Serial);
term.println("Press keys to see their codes ...");
term.println();
}
void loop()
{
int key = term.readKey();
if (key >= 0x21 && key <= 0x7E) {
// Printable ASCII character.
term.print("ASCII: ");
term.write((uint8_t)key);
term.println();
} else if (key == 0x20) {
// Space.
term.println("ASCII: SPACE");
} else if (key == KEY_UNICODE) {
// Extended Unicode character.
term.print("Unicode: U+");
term.print(term.unicodeKey(), 16);
term.println();
} else if (key == KEY_WINSIZE) {
// Change in window size.
term.print("New window size: ");
term.print(term.columns());
term.print("x");
term.println(term.rows());
} else if (key >= 0 && key <= 0xFF) {
// Special arrow or function key.
const uint8_t *table = (const uint8_t *)keys;
int code;
while ((code = pgm_read_byte(table)) != 0) {
if (code == key) {
term.print("Special: ");
term.writeProgMem((const char *)(table + 1));
term.println();
break;
}
table += sizeof(struct KeyInfo);
}
if (!code) {
// Non-printable ASCII or unknown key.
if (key < 0x20)
term.print("ASCII: 0x");
else
term.print("Unknown: 0x");
term.print(key, 16);
term.println();
}
} else if (key >= 0) {
// Unknown keycode. Print in hex.
term.print("Unknown: 0x");
term.print(key, 16);
term.println();
}
}

View File

@@ -0,0 +1,35 @@
/*
This example demonstrates how to create a simple shell on the serial port.
This example is placed into the public domain.
*/
#include <Shell.h>
Shell shell;
int ledPin = 13;
void cmdLed(Shell &shell, int argc, const ShellArguments &argv)
{
if (argc > 1 && !strcmp(argv[1], "on"))
digitalWrite(ledPin, HIGH);
else
digitalWrite(ledPin, LOW);
}
ShellCommand(led, "Turns the status LED on or off", cmdLed);
void setup()
{
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
shell.setPrompt("Command: ");
shell.begin(Serial, 5);
}
void loop()
{
shell.loop();
}

View File

@@ -0,0 +1,80 @@
/*
This example demonstrates how to create a simple telnet server.
This example is placed into the public domain.
*/
#include <SPI.h>
#include <Ethernet.h>
#include <Shell.h>
#include <LoginShell.h>
byte macAddress[6] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
int ledPin = 13;
EthernetServer server(23);
EthernetClient client;
bool haveClient = false;
LoginShell shell;
void cmdLed(Shell &shell, int argc, const ShellArguments &argv)
{
if (argc > 1 && !strcmp(argv[1], "on"))
digitalWrite(ledPin, HIGH);
else
digitalWrite(ledPin, LOW);
}
ShellCommand(led, "Turns the status LED on or off", cmdLed);
void setup()
{
// Configure I/O.
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
// Start the serial port for status messages.
Serial.begin(9600);
Serial.println();
Serial.print("Acquiring IP address ... ");
// Start Ethernet running and get an IP address via DHCP.
if (Ethernet.begin(macAddress))
Serial.println(Ethernet.localIP());
else
Serial.println("failed");
// Listen on port 23 for incoming telnet connections.
server.begin();
shell.setMachineName("Arduino");
}
void loop()
{
// Maintain the DHCP lease over time.
Ethernet.maintain();
// Handle new/disconnecting clients.
if (!haveClient) {
// Check for new client connections.
client = server.available();
if (client) {
haveClient = true;
shell.begin(client, 5);
}
} else if (!client.connected()) {
// The current client has been disconnected. Shut down the shell.
shell.end();
client.stop();
client = EthernetClient();
haveClient = false;
}
// Perform periodic shell processing on the active client.
shell.loop();
}

View File

@@ -0,0 +1,4 @@
Shell KEYWORD1
LoginShell KEYWORD1
Terminal KEYWORD1
loop KEYWORD2