/*************************************************************************
* (C) 2010 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
* by Michael Pounov <misho@openbsd-bg.org>
*
* $Author: misho $
* $Id: aitcli.h,v 1.3.2.1 2011/03/16 17:43:07 misho Exp $
*
*************************************************************************/
#ifndef __AITCLI_H
#define __AITCLI_H
#include <termios.h>
#include <sys/queue.h>
#define STRSIZ 256
/* Key definitions */
#define K_F1 "\x1b\x4f\x50"
#define K_F2 "\x1b\x4f\x51"
#define K_F3 "\x1b\x4f\x52"
#define K_F4 "\x1b\x4f\x53"
#define K_F5 "\x1b\x5b\x31\x35\x7e"
#define K_F6 "\x1b\x5b\x31\x37\x7e"
#define K_F7 "\x1b\x5b\x31\x38\x7e"
#define K_F8 "\x1b\x5b\x31\x39\x7e"
#define K_F9 "\x1b\x5b\x32\x30\x7e"
#define K_F10 "\x1b\x5b\x32\x31\x7e"
#define K_F11 "\x1b\x5b\x32\x33\x7e"
#define K_F12 "\x1b\x5b\x32\x34\x7e"
#define K_CTRL_F1 "\x1b\x5b\x6b"
#define K_CTRL_F2 "\x1b\x5b\x6c"
#define K_CTRL_F3 "\x1b\x5b\x6d"
#define K_CTRL_F4 "\x1b\x5b\x6e"
#define K_CTRL_F5 "\x1b\x5b\x6f"
#define K_CTRL_F6 "\x1b\x5b\x70"
#define K_CTRL_F7 "\x1b\x5b\x71"
#define K_CTRL_F8 "\x1b\x5b\x72"
#define K_CTRL_F9 "\x1b\x5b\x73"
#define K_CTRL_F10 "\x1b\x5b\x74"
#define K_CTRL_F11 "\x1b\x5b\x75"
#define K_CTRL_F12 "\x1b\x5b\x76"
#define K_CTRL_SH_F1 "\x1b\x5b\x77"
#define K_CTRL_SH_F2 "\x1b\x5b\x78"
#define K_CTRL_SH_F3 "\x1b\x5b\x79"
#define K_CTRL_SH_F4 "\x1b\x5b\x7a"
#define K_CTRL_SH_F5 "\x1b\x5b\x40"
#define K_CTRL_SH_F6 "\x1b\x5b\x5b"
#define K_CTRL_SH_F7 "\x1b\x5b\x5c"
#define K_CTRL_SH_F8 "\x1b\x5b\x5d"
#define K_CTRL_SH_F9 "\x1b\x5b\x5e"
#define K_CTRL_SH_F10 "\x1b\x5b\x5f"
#define K_CTRL_SH_F11 "\x1b\x5b\x60"
#define K_CTRL_SH_F12 "\x1b\x5b\x7b"
#define K_INS "\x1b\x5b\x32\x7e"
#define K_DEL "\x1b\x5b\x33\x7e"
#define K_PGUP "\x1b\x5b\x35\x7e"
#define K_PGDN "\x1b\x5b\x36\x7e"
#define K_HOME "\x1b\x5b\x48"
#define K_END "\x1b\x5b\x46"
#define K_UP "\x1b\x5b\x41"
#define K_DOWN "\x1b\x5b\x42"
#define K_RIGHT "\x1b\x5b\x43"
#define K_LEFT "\x1b\x5b\x44"
#define K_NULL "\x0"
#define K_CR "\xd"
#define K_BTAB "\x1b\x5b\x5a"
#define K_TAB "\x9"
#define K_ENTER "\xa"
#define K_ESC "\x1b"
#define K_BACKSPACE "\x7f"
#define K_SPACE "\x20"
#define K_CTRL_SPACE K_NULL
#define K_CTRL_2 K_NULL
#define K_CTRL_A "\x1"
#define K_CTRL_B "\x2"
#define K_CTRL_C "\x3"
#define K_CTRL_D "\x4"
#define K_CTRL_E "\x5"
#define K_CTRL_F "\x6"
#define K_CTRL_G "\x7"
#define K_CTRL_H "\x8"
#define K_CTRL_I K_TAB
#define K_CTRL_J K_ENTER
#define K_CTRL_K "\xb"
#define K_CTRL_L "\xc"
#define K_CTRL_M K_ENTER // K_CR
#define K_CTRL_N "\xe"
#define K_CTRL_O "\xf"
#define K_CTRL_P "\x10"
#define K_CTRL_Q "\x11"
#define K_CTRL_R "\x12"
#define K_CTRL_S "\x13"
#define K_CTRL_T "\x14"
#define K_CTRL_U "\x15"
#define K_CTRL_V "\x16"
#define K_CTRL_W "\x17"
#define K_CTRL_X "\x18"
#define K_CTRL_Y "\x19"
#define K_CTRL_Z "\x1a"
#define K_CTRL_LBRACE "\x1b"
#define K_CTRL_PIPE "\x1c"
#define K_CTRL_RBRACE "\x1d"
#define K_CTRL_6 "\x1e"
#define K_CTRL__ "\x1f"
#define K_X_CTRL_INS "\x1b\x5b\x32\x3b\x35\x7e"
#define K_X_CTRL_DEL "\x1b\x5b\x33\x3b\x35\x7e"
#define K_X_CTRL_PGUP "\x1b\x5b\x35\x3b\x35\x7e"
#define K_X_CTRL_PGDN "\x1b\x5b\x36\x3b\x35\x7e"
#define K_X_CTRL_HOME "\x1b\x5b\x31\x3b\x35\x48"
#define K_X_CTRL_END "\x1b\x5b\x31\x3b\x35\x46"
#define K_X_CTRL_UP "\x1b\x5b\x31\x3b\x35\x41"
#define K_X_CTRL_DOWN "\x1b\x5b\x31\x3b\x35\x42"
#define K_X_CTRL_RIGHT "\x1b\x5b\x31\x3b\x35\x43"
#define K_X_CTRL_LEFT "\x1b\x5b\x31\x3b\x35\x44"
#define K_X_ALT_INS "\x1b\x5b\x32\x3b\x33\x7e"
#define K_X_ALT_DEL "\x1b\x5b\x33\x3b\x33\x7e"
#define K_X_ALT_PGUP "\x1b\x5b\x35\x3b\x33\x7e"
#define K_X_ALT_PGDN "\x1b\x5b\x36\x3b\x33\x7e"
#define K_X_ALT_HOME "\x1b\x5b\x31\x3b\x33\x48"
#define K_X_ALT_END "\x1b\x5b\x31\x3b\x33\x46"
#define K_X_ALT_UP "\x1b\x5b\x31\x3b\x33\x41"
#define K_X_ALT_DOWN "\x1b\x5b\x31\x3b\x33\x42"
#define K_X_ALT_RIGHT "\x1b\x5b\x31\x3b\x33\x43"
#define K_X_ALT_LEFT "\x1b\x5b\x31\x3b\x33\x44"
#define K_X_CTL_A_INS "\x1b\x5b\x32\x3b\x37\x7e"
#define K_X_CTL_A_DEL "\x1b\x5b\x33\x3b\x37\x7e"
#define K_X_CTL_A_PGUP "\x1b\x5b\x35\x3b\x37\x7e"
#define K_X_CTL_A_PGDN "\x1b\x5b\x36\x3b\x37\x7e"
#define K_X_CTL_A_HOME "\x1b\x5b\x31\x3b\x37\x48"
#define K_X_CTL_A_END "\x1b\x5b\x31\x3b\x37\x46"
#define K_X_CTL_A_UP "\x1b\x5b\x31\x3b\x37\x41"
#define K_X_CTL_A_DOWN "\x1b\x5b\x31\x3b\x37\x42"
#define K_X_CTL_A_RIGHT "\x1b\x5b\x31\x3b\x37\x43"
#define K_X_CTL_A_LEFT "\x1b\x5b\x31\x3b\x37\x44"
/* History types */
struct tagHistory {
int hist_len;
char hist_line[BUFSIZ];
TAILQ_ENTRY(tagHistory) hist_next;
};
typedef TAILQ_HEAD(tqHistoryHead, tagHistory) history_t;
/* Bind keys structure types */
typedef int (*bindkey_func_t)(int idx, /*linebuffer_t **/ void * __restrict buffer);
typedef struct {
int key_len;
unsigned char key_ch[8];
bindkey_func_t key_func;
} bindkey_t;
/* Commands structure for CLI */
typedef int (*cmd_func_t)(/*linebuffer_t **/ void * __restrict buffer, int idx, char ** __restrict args);
struct tagCommand {
int cmd_level;
int cmd_len;
char cmd_name[STRSIZ];
char cmd_info[STRSIZ];
char cmd_help[STRSIZ];
cmd_func_t cmd_func;
SLIST_ENTRY(tagCommand) cmd_next;
};
typedef SLIST_HEAD(slCommandHead, tagCommand) commands_t;
/* Main structure, Buffer for CLI work with thread models ;-) special designed by M.Punov */
typedef struct {
char line_mode;
char *line_prompt;
int line_bol;
int line_eol;
int line_len;
char *line_buf;
const struct tagHistory *line_h;
history_t line_history;
bindkey_t *line_keys;
int line_level;
commands_t line_cmds;
int line_in;
int line_out;
} linebuffer_t;
/* Error support functions */
// cli_GetErrno() Get error code of last operation
inline int cli_GetErrno();
// cli_GetError() Get error text of last operation
inline const char *cli_GetError();
/* TELNET support for CLI */
#define MAX_SUB_LEN 255
struct telnetAttrs {
unsigned char ta_cmd;
unsigned char ta_opt;
unsigned char ta_sublen;
unsigned char ta_sub[MAX_SUB_LEN];
};
#ifndef NDEBUG
/*
* cli_telnetDumpAttrs() Telnet debug attributes list, if NDEBUG defined not include
* @attr = attributes list
* @nAttr = attributes list size
* return: none
*/
void cli_telnetDumpAttrs(struct telnetAttrs *attr, int nAttr);
#else
extern void cli_telnetDumpAttrs(struct telnetAttrs *, int);
#endif
/*
* cli_telnetRecv() Telnet receive commands, negotiate with telnet peer
* @sock = socket for communication
* @attr = received attributes list, must be free after use, but if NULL receive in binary mode
* @nAttr = received attributes list size, if is NULL receive in binary mode
* @pdata = received data in supplied buffer
* @datLen = buffer pdata size
* return: 0 not present data; -1 error:: can`t read; -2 timeout; -3 EOF; >0 number of received bytes
*/
int cli_telnetRecv(int sock, struct telnetAttrs **attr, int *nAttr, void *data, int datLen);
/*
* cli_telnetSend() Telnet send commands, negotiate with telnet peer
* @sock = socket for communication
* @attr = send attributes list
* @nAttr = send attributes list size
* @data = data for send
* @datLen = data size
* @Term = Terminate with GA (Go Ahead), 1 send after data GA command
* return: 0 not sended commands; -1 error:: can`t send; >0 number of sended bytes
*/
int cli_telnetSend(int sock, struct telnetAttrs *attr, int nAttr, void *data, int datLen, int Term);
/*
* cli_telnet_Get_SubOpt() Telnet get sub option function
* @attr = input attribute
* @code = sub-option code for opt
* @data = sub-option data
* @datLen = data size set max size in input, output return copy size
* return: -1 can`t get option; !=-1 option code
*/
inline int cli_telnet_Get_SubOpt(struct telnetAttrs *attr, unsigned char *code,
void *data, unsigned char *datLen);
/*
* cli_telnet_Set_SubOpt() Telnet set sub option function
* @attr = output attribute
* @opt = attribute option
* @code = sub-option code for opt, if 0xff not specified
* @data = sub-option data, if NULL not specified
* @datLen = data size, if 0 not specified
* return: -1 can`t set sub-otion; 0 ok
*/
inline int cli_telnet_Set_SubOpt(struct telnetAttrs *attr, unsigned char opt, unsigned char code,
void *data, unsigned char datLen);
/*
* cli_telnet_GetCmd() Telnet get command
* @attr = input attribute
* return: -1 can`t get command; !=-1 command <<24 return sublen, <<8 return option, <<0 command
*/
inline unsigned int cli_telnet_GetCmd(struct telnetAttrs *attr);
/*
* cli_telnet_SetCmd() Telnet set command
* @attr = input attribute
* @cmd = command
* @opt = option, if 0xff not specified
* @arg1 = sub-option code, if 0xff not specified
* @arg2 = sub-option data, if NULL not specified
* @arg3 = sub-option data size, if 0 not specified data
* return: -1 can`t set command; !=-1 ok
*/
inline int cli_telnet_SetCmd(struct telnetAttrs *attr, unsigned char cmd, unsigned char opt, ...);
/*
* cli_telnet_Answer() Automatic generate commands answer to send from telnet
* @caps = Array of capability options
* @nCaps = number of capability options
* @attr = input attribute
* @nAttr = number of input attributes
* @ans = output answered attributes, must be free() after use
* @Ans = number of output answered attributes
* return: -1 can`t answer; !=-1 ok
*/
int cli_telnet_Answer(unsigned char *caps, int nCaps, struct telnetAttrs *attr, int nAttr,
struct telnetAttrs **ans, int *Ans);
// Add capability option, x = 0 false, 1 true
#define ADD_CAPS(opt, x) ((opt) | (x) ? 0x80 : 0)
// Is supported this option ...
#define SUP_CAPS(caps) ((caps) & 0x80)
// get capability option
#define CAP(caps) ((caps) & 0x7f)
/* CLI Helper functions */
/*
* cli_Cmd_Unsupported() Builtin helper function for unsupported commands
* @buffer = CLI buffer
* @idx = Selected command ID
* @args = Parsed arguments array
* return: RETCODE_OK ok
*/
int cli_Cmd_Unsupported(void * __restrict buffer, int idx, char ** __restrict args);
/* CLI Functions */
/*
* cli_BindKey() Bind function to key
* @key = key structure
* @buffer = CLI buffer
* return: RETCODE_ERR error, RETCODE_OK ok, >0 bind at position
*/
int cli_BindKey(bindkey_t * __restrict key, linebuffer_t * __restrict buffer);
/*
* cli_addCommand() Add command to CLI session
* @buffer = CLI buffer
* @csCmd = Command name
* @cliLevel = Level in CLI, -1 unprivi(view from all), 0 main config, 1 sub config ...
* @funcCmd = Callback function when user call command
* @csInfo = Inline information for command
* @csHelp = Help line when call help
* return: RETCODE_ERR error, RETCODE_OK ok
*/
int
cli_addCommand(linebuffer_t * __restrict buffer, const char *csCmd, int cliLevel, cmd_func_t funcCmd,
const char *csInfo, const char *csHelp);
/*
* cli_delCommand() Delete command from CLI session
* @buffer = CLI buffer
* @csCmd = Command name
* @cliLevel = Level in CLI, -1 unprivi(view from all), 0 main config, 1 sub config ...
* return: RETCODE_ERR error, RETCODE_OK ok
*/
int
cli_delCommand(linebuffer_t * __restrict buffer, const char *csCmd, int cliLevel);
/*
* cli_updCommand() Update command in CLI session
* @buffer = CLI buffer
* @csCmd = Command name
* @cliLevel = Level in CLI, -1 unprivi(view from all), 0 main config, 1 sub config ...
* @funcCmd = Callback function when user call command
* @csInfo = Inline information for command
* @csHelp = Help line when call help
* return: RETCODE_ERR error, RETCODE_OK ok
*/
int
cli_updCommand(linebuffer_t * __restrict buffer, const char *csCmd, int cliLevel, cmd_func_t funcCmd,
const char *csInfo, const char *csHelp);
/*
* cli_addHistory() Add line to history
* @buffer = CLI buffer
* @str = Add custom text or if NULL use readed line from CLI buffer
* return: RETCODE_ERR error, RETCODE_OK ok
*/
int cli_addHistory(linebuffer_t * __restrict buffer, const char * __restrict str);
/*
* cli_saveHistory() Save history to file
* @buffer = CLI buffer
* @histfile = History filename, if NULL will be use default name
* @lines = Maximum history lines to save
* return: RETCODE_ERR error, RETCODE_OK ok
*/
int cli_saveHistory(linebuffer_t * __restrict buffer, const char *histfile, int lines);
/*
* cli_loadHistory() Load history from file
* @buffer = CLI buffer
* @histfile = History filename, if NULL will be use default name
* return: RETCODE_ERR error, RETCODE_OK ok
*/
int cli_loadHistory(linebuffer_t * __restrict buffer, const char *histfile);
/*
* cli_resetHistory() Reset history search in CLI session
* @buffer = CLI buffer
* return: none
*/
inline void cli_resetHistory(linebuffer_t * __restrict buffer);
/*
* cli_freeLine() Clear entire line
* @buffer = CLI buffer
* return: RETCODE_ERR error, RETCODE_OK ok
*/
inline int cli_freeLine(linebuffer_t * __restrict buffer);
/*
* cli_setPrompt() Set new prompt for CLI session
* @buffer = CLI buffer
* @prompt = new text for prompt or if NULL disable prompt
* return: none
*/
inline void cli_setPrompt(linebuffer_t * __restrict buffer, const char *prompt);
/*
* cli_Printf() Send message to CLI session
* @buffer = CLI buffer
* @fmt = printf format string
* @... = arguments defined in fmt
* return: none
*/
inline void cli_Printf(linebuffer_t * __restrict buffer, char *fmt, ...);
/*
* cli_PrintHelp() Print help screen
* @buffer = CLI buffer
* return: none
*/
inline void cli_PrintHelp(linebuffer_t * __restrict buffer);
/*
* cliEnd() Clear data, Free resources and close CLI session
* @buffer = CLI buffer
* return: RETCODE_ERR error, RETCODE_OK ok
*/
void cliEnd(linebuffer_t * __restrict buffer);
/*
* cliInit() Start CLI session, allocate memory for resources and bind keys
* @fin = Input device handle
* @fout = Output device handle
* @prompt = text for prompt, if NULL disable prompt
* return: NULL if error or !=NULL CLI buffer
*/
linebuffer_t *cliInit(int fin, int fout, const char *prompt);
/*
* cliInitLine() Init CLI input line terminal
* @buffer = CLI buffer
* return: none
*/
int cliInitLine(linebuffer_t * __restrict buffer);
/*
* cliReadLine() Read line from opened CLI session
* @buffer = CLI buffer
* return: NULL if error or !=NULL readed line, must be free after use!
*/
char *cliReadLine(linebuffer_t * __restrict buffer);
/*
* cliLoop() CLI main loop
* @buffer = CLI buffer
* @csHistFile = History file name
* return: RETCODE_ERR error, RETCODE_OK ok
*/
int cliLoop(linebuffer_t * __restrict buffer, const char *csHistFile);
/*
* cliNetLoop() CLI network main loop binded to socket
* @buffer = CLI buffer
* @csHistFile = History file name
* @sock = client socket
* @term = stdin termios
* @win = window size of tty
* return: RETCODE_ERR error, RETCODE_OK ok
*/
int cliNetLoop(linebuffer_t * __restrict buffer, const char *csHistFile, int sock);
#endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>