/* * FreeRTOS+CLI V1.0.4 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * 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. * * http://www.FreeRTOS.org * http://aws.amazon.com/freertos * * 1 tab == 4 spaces! */ /* Standard includes. */ #include #include #include #include /* Utils includes. */ #include #include "FreeRTOS_CLI.h" /* * The callback function that is executed when "help" is entered. This is the * only default command that is always present. */ static int prvHelpCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ); /* * Return the number of parameters that follow the command name. */ static int8_t prvGetNumberOfParameters( const char *pcCommandString ); /* The definition of the "help" command. This command is always at the front of the list of registered commands. */ static CLI_Command_Definition_t xHelpCommand = { "help", "\r\nhelp:\r\n Lists all the registered commands\r\n\r\n", prvHelpCommand, NULL, }; /*-----------------------------------------------------------*/ int CLIRegisterCommand( CLI_Command_Definition_t *pxCommandToRegister ) { static CLI_Command_Definition_t *pxLastCommandInList = &xHelpCommand; CLI_Command_Definition_t *pxNewListItem; /* Check the parameter is not NULL. */ ASSERT( pxCommandToRegister ); pxNewListItem = pxCommandToRegister; CLI_ENTER_CRITICAL() { /* The new list item will get added to the end of the list, so pxNext has nowhere to point. */ pxNewListItem->pxNext = NULL; /* Add the newly created list item to the end of the already existing list. */ pxLastCommandInList->pxNext = pxNewListItem; /* Set the end of list marker to the new list item. */ pxLastCommandInList = pxNewListItem; } CLI_EXIT_CRITICAL() return CLI_TRUE; } /*-----------------------------------------------------------*/ int CLIProcessCommand( const char * const pcCommandInput, char * pcWriteBuffer, size_t xWriteBufferLen ) { static const CLI_Command_Definition_t *pxCommand = NULL; int xReturn = CLI_TRUE; const char *pcRegisteredCommandString; size_t xCommandStringLength; /* Note: This function is not re-entrant. It must not be called from more thank one task. */ if( pxCommand == NULL ) { /* Search for the command string in the list of registered commands. */ for( pxCommand = &xHelpCommand; pxCommand != NULL; pxCommand = pxCommand->pxNext ) { pcRegisteredCommandString = pxCommand->pcCommand; xCommandStringLength = strlen( pcRegisteredCommandString ); /* To ensure the string lengths match exactly, so as not to pick up a sub-string of a longer command, check the byte after the expected end of the string is either the end of the string or a space before a parameter. */ if( ( pcCommandInput[ xCommandStringLength ] == ' ' ) || ( pcCommandInput[ xCommandStringLength ] == 0x00 ) ) { if( strncmp( pcCommandInput, pcRegisteredCommandString, xCommandStringLength ) == 0 ) { break; } } } } if( ( pxCommand != NULL ) && ( xReturn == CLI_FALSE ) ) { /* The command was found, but the number of parameters with the command was incorrect. */ strncpy( pcWriteBuffer, "Incorrect command parameter(s). Enter \"help\" to view a list of available commands.\r\n\r\n", xWriteBufferLen ); pxCommand = NULL; } else if( pxCommand != NULL ) { /* Call the callback function that is registered to this command. */ xReturn = pxCommand->pxCommandInterpreter( pcWriteBuffer, xWriteBufferLen, pcCommandInput ); /* If xReturn is CLI_FALSE, then no further strings will be returned after this one, and pxCommand can be reset to NULL ready to search for the next entered command. */ if( xReturn == CLI_FALSE ) { pxCommand = NULL; } } else { /* pxCommand was NULL, the command was not found. */ strncpy( pcWriteBuffer, "Command not recognised. Enter 'help' to view a list of available commands.\r\n\r\n", xWriteBufferLen ); xReturn = CLI_FALSE; } return xReturn; } /*-----------------------------------------------------------*/ const char *CLIGetParameter( const char *pcCommandString, uint32_t uxWantedParameter, int *pxParameterStringLength ) { uint32_t uxParametersFound = 0; const char *pcReturn = NULL; *pxParameterStringLength = 0; while( uxParametersFound < uxWantedParameter ) { /* Find the start of the next string. */ while( ( ( *pcCommandString ) != 0x00 ) && ( ( *pcCommandString ) == ' ' ) ) { pcCommandString++; } /* Was a string found? */ if( *pcCommandString != 0x00 ) { /* Is this the start of the required parameter? */ uxParametersFound++; if( uxParametersFound == uxWantedParameter ) { /* How long is the parameter? */ pcReturn = pcCommandString; while( ( ( *pcCommandString ) != 0x00 ) && ( ( *pcCommandString ) != ' ' ) ) { ( *pxParameterStringLength )++; pcCommandString++; } if( *pxParameterStringLength == 0 ) { pcReturn = NULL; } break; } } else { break; } } return pcReturn; } /*-----------------------------------------------------------*/ static int prvHelpCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) { static const CLI_Command_Definition_t * pxCommand = NULL; int xReturn; ( void ) pcCommandString; if( pxCommand == NULL ) { /* Reset the pxCommand pointer back to the start of the list. */ pxCommand = &xHelpCommand; } /* Return the next command help string, before moving the pointer on to the next command in the list. */ strncpy( pcWriteBuffer, pxCommand->pcHelpString, xWriteBufferLen ); pxCommand = pxCommand->pxNext; if( pxCommand == NULL ) { /* There are no more commands in the list, so there will be no more strings to return after this one and CLI_FALSE should be returned. */ xReturn = CLI_FALSE; } else { xReturn = CLI_TRUE; } return xReturn; } /*-----------------------------------------------------------*/ static int8_t prvGetNumberOfParameters( const char *pcCommandString ) { int8_t cParameters = 0; int xLastCharacterWasSpace = CLI_FALSE; /* Count the number of space delimited words in pcCommandString. */ while( *pcCommandString != 0x00 ) { if( ( *pcCommandString ) == ' ' ) { if( xLastCharacterWasSpace != CLI_TRUE ) { cParameters++; xLastCharacterWasSpace = CLI_TRUE; } } else { xLastCharacterWasSpace = CLI_FALSE; } pcCommandString++; } /* If the command string ended with spaces, then there will have been too many parameters counted. */ if( xLastCharacterWasSpace == CLI_TRUE ) { cParameters--; } /* The value returned is one less than the number of space delimited words, as the first word should be the command itself. */ return cParameters; }