/* ***************************************************************************** * cmd_engine.c * * \brief Command Engine - Command processing * * * \author Terry, AB5K * \author Stephen Hicks, N5AC * \date 23-AUG-2011 * * Instructions for adding a new command: * 1. Add a reference in the "command_defs commands[]" array below * 2. If help is needed, add a reference to lpszCommandDescriptionBasic[] in the cmd_basics.c file. * ******************************************************************************* * * Copyright (C) 2014 FlexRadio Systems. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Contact Information: * email: gplflexradiosystems.com * Mail: FlexRadio Systems, Suite 1-150, 4616 W. Howard LN, Austin, TX 78728 * * ************************************************************************** */ #include #include #include #include #include #include #include "../common.h" #include "datatypes.h" #include "cmd.h" #include "main.h" static struct termios old, new; // For Terminal IO //#include "drv_bq32000.h" //#include "messages.h" //#include "client_manager.h" //#include "radio.h" char *CMD_UNRECOGNIZED = "Unrecognized command \"%s\".\r\n"; // Command Function Pointer called by the interpreter. typedef uint32 handler(int, int, char**); static char PrevLine[80]; typedef struct _command_def { const char* commandName; handler *pFunction; } command_def; static command_def commands[] = { { 0, cmd_undefined }, // Space Holder { "b", cmd_banner }, // Display Banner { "banner", cmd_banner }, // Display Banner { "cls", cmd_cls }, // Clear Screen { "date", cmd_date }, // Print the date/time { "exit", cmd_exit }, // Exit the program { "help", cmd_help }, // Help Menu { "quit", cmd_exit }, // Exit the program { "slice", cmd_slice }, // Handle slice changes { "time", cmd_time }, // Print the time { "?", cmd_help }, // Display Help { 0, cmd_undefined }, // Undefined - must be last in the list }; //long execute_command(int requester_fd, int cmd_num, int argc, char *argv); // ################################################################# // ## // ## Command Interpreter // ## // ################################################################# unsigned int command(void) { char line[512]; char *pLine = line; get_line(pLine, 512 * sizeof(char)); process_command(line); return (1); } uint32 process_command(char* command_txt) { uint32 cmd_ret = SUCCESS; int cmd_num; int argc; char *argv[MAX_ARGC + 1]; //Add one extra so we can null terminate the array output("CMD Received = '%s'\n", command_txt); tokenize(command_txt, &argc, argv, MAX_ARGC); if (argc > 0) { cmd_num = 1; while (cmd_num > 0) { if ((commands[cmd_num].commandName == 0) || (strcmp(argv[0], commands[cmd_num].commandName) == 0)) { //Execute the requested command cmd_ret = commands[cmd_num].pFunction(1, argc, argv); cmd_num = 0; } else { cmd_num++; } } } return cmd_ret; } // ################################################################# // ## // ## void tokenize(char*, int*, char**, max_arguments); // ## // ## Breaks a single character string into an array of tokens. // ################################################################# void tokenize( char* line, // Input String int* pargc, // Number of arguments char** argv, // Array of strings holding tokens int max_arguments // Maximum Tokens allowed ) { BOOL inside_string = FALSE; BOOL inside_token = FALSE; char* readp; *pargc = 0; // Read through the entire string searching for tokens for (readp = line; *readp; readp++) { // Search for start of token if (!inside_token) { // Ignore white spaces if ((*readp == ' ') || (*readp == '\t')) { ; } // Start of a new token else { if (*readp == '\"') { inside_string = TRUE; } else { inside_token = TRUE; argv[*pargc] = readp; (*pargc)++; if(*pargc > max_arguments) break; } } } // We are inside the token else { // inside token // Found the end of the token if ( (!inside_string && ((*readp == ' ') || (*readp == '\t'))) | (inside_string && (*readp == '\"')) ) { inside_string = FALSE; inside_token = FALSE; *readp = 0; } } } // End of input line terminates a token if (inside_token) { *readp = 0; readp++; } argv[*pargc] = 0; // Null-terminate just to be nice } // ################################################################# // ## // ## void command_get_line(char *, int) // ## // ################################################################# void get_line(char * line, int maxlen) { char *pLine = line; char *pPrevLine = PrevLine; char c = 0; *pLine = 0; for (;;) { c = getch(); // Escape Sequences if (c == '\033') { while (pLine > line) { printf("\b \b"); pLine--; *pLine = 0; } c = getch(); if (c == '[') { c = getch(); if (c == 'A') { // Restore previous command pLine = line; pPrevLine = PrevLine; while(*pPrevLine) { *pLine = *pPrevLine; pLine++; pPrevLine++; } *pLine = 0; printf("%s",line); } } } else if ((c == '\n') || (c == '\r')) { printf("\r\n"); break; } // Check for backspace or delete key. else if ((c == '\b') || (c == 0x7F)) { if (pLine > line) { printf("\b \b"); pLine--; *pLine = 0; } } // Check for escape key or control-U. else if (c == 0x15) { while (pLine > line) { printf("\b \b"); pLine--; *pLine = 0; } } else if (c > 0) { printf("%c",c); *pLine = c; pLine++; *pLine = 0; } } *pLine = 0; pLine = line; pPrevLine = PrevLine; while(*pLine) { *pPrevLine = *pLine; pLine++; pPrevLine++; } *pPrevLine = 0; } /* ***************************************************************************** * getch() and getche() functionality for UNIX, * based on termios (terminal handling functions) * * This code snippet was written by Wesley Stessens (wesley@ubuntu.com) * It is released in the Public Domain. */ /* Initialize new terminal i/o settings */ void initTermios(int echo) { int n = tcgetattr(0, &old); /* grab old terminal i/o settings */ if (n == -1) return; new = old; /* make new settings same as old settings */ new.c_lflag &= ~ICANON; /* disable buffered i/o */ new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */ tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */ } /* Restore old terminal i/o settings */ void resetTermios(void) { tcsetattr(0, TCSANOW, &old); } /* Read 1 character - echo defines echo mode */ char getch_(int echo) { char ch; initTermios(echo); ch = (char)getchar(); resetTermios(); return ch; } /* Read 1 character without echo */ char getch(void) { return getch_(0); } /* Read 1 character with echo */ char getche(void) { return getch_(1); }