/************************************************************************* * (C) 2010 AITNET ltd - Sofia/Bulgaria - * by Michael Pounov * * $Author: misho $ * $Id: aitcli.h,v 1.3 2011/03/16 17:24:03 misho Exp $ * *************************************************************************/ #ifndef __AITCLI_H #define __AITCLI_H #include #include #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(); /* 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