|
@@ -25,10 +25,357 @@
|
|
#include "shellmatta_opt.h"
|
|
#include "shellmatta_opt.h"
|
|
#include "shellmatta_transport.h"
|
|
#include "shellmatta_transport.h"
|
|
#include <stddef.h>
|
|
#include <stddef.h>
|
|
|
|
+#include <stdint.h>
|
|
#include <string.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * @brief processes the passed amount of data - called from the transport layer
|
|
|
|
+ * @param[in] handle shellmatta instance handle
|
|
|
|
+ * @param[in] data pointer to input data to process
|
|
|
|
+ * @param[in] size length of input data to process
|
|
|
|
+ * @return errorcode #SHELLMATTA_OK
|
|
|
|
+ * #SHELLMATTA_USE_FAULT
|
|
|
|
+ */
|
|
|
|
+static shellmatta_retCode_t shellmatta_processDataInt(shellmatta_handle_t handle,
|
|
|
|
+ char *data,
|
|
|
|
+ uint32_t size)
|
|
|
|
+{
|
|
|
|
+ shellmatta_cmd_t *cmd;
|
|
|
|
+ uint8_t cmdExecuted = 0u;
|
|
|
|
+ uint32_t cmdLen;
|
|
|
|
+ char *tempString;
|
|
|
|
+
|
|
|
|
+ shellmatta_retCode_t ret = SHELLMATTA_OK;
|
|
|
|
+ shellmatta_retCode_t cmdRet;
|
|
|
|
+ shellmatta_instance_t *inst = (shellmatta_instance_t*)handle;
|
|
|
|
+
|
|
|
|
+ /** -# in busy mode - keep calling this command */
|
|
|
|
+ if(NULL != inst->busyCmd)
|
|
|
|
+ {
|
|
|
|
+ /** -# just call the function until it is not busy anymore */
|
|
|
|
+ (void)shellmatta_opt_reInit(inst);
|
|
|
|
+ ret = inst->busyCmd->cmdFct(handle, inst->buffer, inst->inputCount);
|
|
|
|
+
|
|
|
|
+ if(SHELLMATTA_BUSY == ret)
|
|
|
|
+ {
|
|
|
|
+ /** -# do nothing - still busy */
|
|
|
|
+ }
|
|
|
|
+ else if(SHELLMATTA_CONTINUE == ret)
|
|
|
|
+ {
|
|
|
|
+ inst->continuousCmd = inst->busyCmd;
|
|
|
|
+ inst->busyCmd = NULL;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ utils_terminateInput(inst);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /** -# call continuous function even if there is no data */
|
|
|
|
+ else if((0u == size) && (NULL != inst->continuousCmd))
|
|
|
|
+ {
|
|
|
|
+ /** -# just call the function without any new data */
|
|
|
|
+ inst->stdinLength = 0u;
|
|
|
|
+ inst->buffer[inst->stdinIdx] = '\0';
|
|
|
|
+ (void)shellmatta_opt_reInit(inst);
|
|
|
|
+ ret = inst->continuousCmd->cmdFct(handle, inst->buffer, inst->inputCount);
|
|
|
|
+
|
|
|
|
+ if(SHELLMATTA_CONTINUE == ret)
|
|
|
|
+ {
|
|
|
|
+ /** -# do nothing just continue */
|
|
|
|
+ }
|
|
|
|
+ else if(SHELLMATTA_BUSY == ret)
|
|
|
|
+ {
|
|
|
|
+ inst->busyCmd = inst->continuousCmd;
|
|
|
|
+ inst->continuousCmd = NULL;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ utils_terminateInput(inst);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ /* nothing to do here - continue parsing the command */
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /** -# process byte wise */
|
|
|
|
+ for (; (inst->byteCounter < size) && (NULL == inst->busyCmd); inst->byteCounter++)
|
|
|
|
+ {
|
|
|
|
+ /** -# in continuous mode - pass data directly to the command */
|
|
|
|
+ if(NULL != inst->continuousCmd)
|
|
|
|
+ {
|
|
|
|
+ /** -# copy data and call command function */
|
|
|
|
+ inst->buffer[inst->stdinIdx] = data[inst->byteCounter];
|
|
|
|
+ inst->buffer[inst->stdinIdx + 1u] = '\0';
|
|
|
|
+ inst->stdinLength = 1u;
|
|
|
|
+ (void)shellmatta_opt_reInit(inst);
|
|
|
|
+ ret = inst->continuousCmd->cmdFct(handle, inst->buffer, inst->inputCount);
|
|
|
|
+
|
|
|
|
+ /** -# check if continuous mode is canceled or interrupted by busy mode */
|
|
|
|
+ if(SHELLMATTA_BUSY == ret)
|
|
|
|
+ {
|
|
|
|
+ inst->busyCmd = inst->continuousCmd;
|
|
|
|
+ inst->continuousCmd = NULL;
|
|
|
|
+ }
|
|
|
|
+ else if(('\x03' == data[inst->byteCounter]))
|
|
|
|
+ {
|
|
|
|
+ /** -# cancel continue session */
|
|
|
|
+ utils_terminateInput(inst);
|
|
|
|
+ ret = SHELLMATTA_OK;
|
|
|
|
+ }
|
|
|
|
+ else if(SHELLMATTA_CONTINUE == ret)
|
|
|
|
+ {
|
|
|
|
+ /** -# do nothing - continue */
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ utils_terminateInput(inst);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /** -# handle escape sequences */
|
|
|
|
+ else if(inst->escapeCounter != 0u)
|
|
|
|
+ {
|
|
|
|
+ escape_handleSequence(inst, data[inst->byteCounter]);
|
|
|
|
+ }
|
|
|
|
+ /** -# handle delimiter as start of processing the command */
|
|
|
|
+ else if (inst->delimiter == data[inst->byteCounter])
|
|
|
|
+ {
|
|
|
|
+ if(0u == inst->hereLength)
|
|
|
|
+ {
|
|
|
|
+ /**
|
|
|
|
+ * @dot
|
|
|
|
+ * digraph heredocParser {
|
|
|
|
+ * start -> wait [ label="<< in first line - store delimiter" ];
|
|
|
|
+ * wait -> wait [ label="delimiter not detected" ];
|
|
|
|
+ * wait -> end [ label="delimiter found - remove all heredoc stuff and send the input to the command" ];
|
|
|
|
+ * }
|
|
|
|
+ * @enddot */
|
|
|
|
+
|
|
|
|
+ /** -# check for heredoc - add string delimiter to stop strstr from searching too far */
|
|
|
|
+ inst->buffer[inst->inputCount] = '\0';
|
|
|
|
+ tempString = strstr(inst->buffer, "<<");
|
|
|
|
+ if(NULL != tempString)
|
|
|
|
+ {
|
|
|
|
+ /*' -# check if length of heredoc delimiter is valid */
|
|
|
|
+ if(inst->inputCount > ((uint32_t)(tempString - inst->buffer) + 2u))
|
|
|
|
+ {
|
|
|
|
+ inst->hereStartIdx = (uint32_t)(tempString - inst->buffer);
|
|
|
|
+ inst->hereDelimiterIdx = inst->hereStartIdx + 2u;
|
|
|
|
+ while((inst->hereDelimiterIdx < inst->inputCount)
|
|
|
|
+ && ( ('\0' == inst->buffer[inst->hereDelimiterIdx])
|
|
|
|
+ || (' ' == inst->buffer[inst->hereDelimiterIdx])))
|
|
|
|
+ {
|
|
|
|
+ inst->hereDelimiterIdx ++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ inst->hereLength = inst->inputCount - inst->hereDelimiterIdx;
|
|
|
|
+
|
|
|
|
+ inst->dirty = true;
|
|
|
|
+ utils_insertChars(inst, &data[inst->byteCounter], 1u);
|
|
|
|
+ inst->lastNewlineIdx = inst->inputCount;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ inst->hereLength = 0u;
|
|
|
|
+
|
|
|
|
+ /** -# store the current command and reset the history buffer */
|
|
|
|
+ inst->dirty = true;
|
|
|
|
+ history_storeCmd(inst);
|
|
|
|
+ history_reset(inst);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ /** -# store the current command and reset the history buffer */
|
|
|
|
+ inst->dirty = true;
|
|
|
|
+ history_storeCmd(inst);
|
|
|
|
+ history_reset(inst);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ tempString = &inst->buffer[inst->lastNewlineIdx];
|
|
|
|
+ cmdLen = inst->inputCount - inst->lastNewlineIdx;
|
|
|
|
+
|
|
|
|
+ /** -# skip newline characters before comparison */
|
|
|
|
+ while(('\n' == *tempString) || ('\r' == *tempString))
|
|
|
|
+ {
|
|
|
|
+ tempString ++;
|
|
|
|
+ cmdLen --;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if( (inst->hereLength == cmdLen)
|
|
|
|
+ && (0 == strncmp( &inst->buffer[inst->hereDelimiterIdx],
|
|
|
|
+ tempString,
|
|
|
|
+ inst->hereLength)))
|
|
|
|
+ {
|
|
|
|
+ /** -# store the current command and reset the history buffer */
|
|
|
|
+ inst->dirty = true;
|
|
|
|
+ history_storeCmd(inst);
|
|
|
|
+ history_reset(inst);
|
|
|
|
+
|
|
|
|
+ /** -# process heredoc as stdin like input */
|
|
|
|
+ /** -# find start of heredoc data */
|
|
|
|
+ inst->stdinIdx = inst->hereDelimiterIdx + inst->hereLength;
|
|
|
|
+ while( ('\n' == inst->buffer[inst->stdinIdx])
|
|
|
|
+ || ('\r' == inst->buffer[inst->stdinIdx]))
|
|
|
|
+ {
|
|
|
|
+ inst->stdinIdx ++;
|
|
|
|
+ }
|
|
|
|
+ /** -# calculate length and terminate stdin string */
|
|
|
|
+ if(inst->stdinIdx < inst->lastNewlineIdx)
|
|
|
|
+ {
|
|
|
|
+ inst->stdinLength = inst->lastNewlineIdx - inst->stdinIdx;
|
|
|
|
+ inst->buffer[inst->lastNewlineIdx] = '\0';
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ inst->stdinLength = 0u;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /** -# calculate length and terminate argument string */
|
|
|
|
+ inst->inputCount = inst->hereStartIdx;
|
|
|
|
+ inst->buffer[inst->hereStartIdx] = '\0';
|
|
|
|
+
|
|
|
|
+ /** -# terminate heredoc session */
|
|
|
|
+ inst->hereLength = 0u;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ /** -# the party goes on - just print the delimiter and store the position */
|
|
|
|
+ inst->lastNewlineIdx = inst->inputCount;
|
|
|
|
+ utils_insertChars(inst, &data[inst->byteCounter], 1u);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(0u == inst->hereLength)
|
|
|
|
+ {
|
|
|
|
+ cmd = inst->cmdList;
|
|
|
|
+
|
|
|
|
+ /** -# determine the cmd len (chars until first space or \0 is found */
|
|
|
|
+ cmdLen = 0u;
|
|
|
|
+ while( (cmdLen < inst->inputCount)
|
|
|
|
+ && (' ' != inst->buffer[cmdLen])
|
|
|
|
+ && ('\r' != inst->buffer[cmdLen])
|
|
|
|
+ && ('\n' != inst->buffer[cmdLen])
|
|
|
|
+ && ('\0' != inst->buffer[cmdLen]))
|
|
|
|
+ {
|
|
|
|
+ cmdLen ++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /** -# search for a matching command */
|
|
|
|
+ while (NULL != cmd)
|
|
|
|
+ {
|
|
|
|
+ /** -# compare command and alias string and length */
|
|
|
|
+ if ( ((cmdLen == strlen(cmd->cmd))
|
|
|
|
+ && (0 == strncmp(inst->buffer, cmd->cmd, cmdLen)))
|
|
|
|
+ || ((NULL != cmd->cmdAlias)
|
|
|
|
+ && (cmdLen == strlen(cmd->cmdAlias))
|
|
|
|
+ && (0 == strncmp(inst->buffer, cmd->cmdAlias, cmdLen))))
|
|
|
|
+ {
|
|
|
|
+ utils_writeEcho(inst, "\r\n", 2u);
|
|
|
|
+ shellmatta_opt_init(inst, cmdLen + 1u);
|
|
|
|
+ cmdExecuted = 1u;
|
|
|
|
+ cmdRet = cmd->cmdFct(handle, inst->buffer, inst->inputCount);
|
|
|
|
+
|
|
|
|
+ switch(cmdRet)
|
|
|
|
+ {
|
|
|
|
+ case SHELLMATTA_CONTINUE:
|
|
|
|
+ /** -# initialize stdin buffer and continuous cmd */
|
|
|
|
+ inst->stdinIdx = inst->inputCount + 1u;
|
|
|
|
+ inst->stdinLength = 0u;
|
|
|
|
+ inst->continuousCmd = cmd;
|
|
|
|
+ ret = cmdRet;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case SHELLMATTA_BUSY:
|
|
|
|
+ inst->busyCmd = cmd;
|
|
|
|
+ ret = cmdRet;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ /* nothing to do - everything ok */
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ cmd = NULL;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ cmd = cmd->next;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ((0u == cmdExecuted) && (inst->inputCount > 0))
|
|
|
|
+ {
|
|
|
|
+ SHELLMATTA_WRITE("\r\nCommand: ", 11u);
|
|
|
|
+ SHELLMATTA_WRITE(inst->buffer, inst->inputCount);
|
|
|
|
+ SHELLMATTA_WRITE(" not found", 10u);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /** -# terminate this session if no continuous mode is requested */
|
|
|
|
+ if( (NULL == inst->continuousCmd)
|
|
|
|
+ && (NULL == inst->busyCmd))
|
|
|
|
+ {
|
|
|
|
+ utils_terminateInput(inst);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ /** -# ignore newline as first character (to be compatible to
|
|
|
|
+ * terminals sending newline after return) */
|
|
|
|
+ else if((0u == inst->inputCount) && ('\n' == data[inst->byteCounter]))
|
|
|
|
+ {
|
|
|
|
+ /* do nothing */
|
|
|
|
+ }
|
|
|
|
+ /** -# check for tabulator key - auto complete */
|
|
|
|
+ else if('\t' == data[inst->byteCounter])
|
|
|
|
+ {
|
|
|
|
+ inst->dirty = true;
|
|
|
|
+ autocomplete_run(inst);
|
|
|
|
+ }
|
|
|
|
+ /** -# check for cancel -
|
|
|
|
+ * terminate current input and print prompt again */
|
|
|
|
+ else if('\x03' == data[inst->byteCounter])
|
|
|
|
+ {
|
|
|
|
+ inst->dirty = false;
|
|
|
|
+ history_reset(inst);
|
|
|
|
+ utils_terminateInput(inst);
|
|
|
|
+ }
|
|
|
|
+ /** -# check for backspace */
|
|
|
|
+ else if( ('\b' == data[inst->byteCounter])
|
|
|
|
+ || ('\x7f' == data[inst->byteCounter]))
|
|
|
|
+ {
|
|
|
|
+ inst->dirty = true;
|
|
|
|
+ utils_removeChars(inst, 1u, true);
|
|
|
|
+ }
|
|
|
|
+ /** -# check for start of escape sequence */
|
|
|
|
+ else if('\x1b' == data[inst->byteCounter])
|
|
|
|
+ {
|
|
|
|
+ inst->escapeCounter = 1u;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ inst->dirty = true;
|
|
|
|
+ utils_insertChars(inst, &data[inst->byteCounter], 1u);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /** -# reset tab counter on not a tab */
|
|
|
|
+ if ('\t' != data[inst->byteCounter])
|
|
|
|
+ {
|
|
|
|
+ inst->tabCounter = 0u;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /** -# initialize the byte buffer if processing of the input is finished */
|
|
|
|
+ if(ret != SHELLMATTA_BUSY)
|
|
|
|
+ {
|
|
|
|
+ inst->byteCounter = 0u;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* @}
|
|
* @}
|
|
* @addtogroup shellmatta_api
|
|
* @addtogroup shellmatta_api
|
|
@@ -117,6 +464,7 @@ shellmatta_retCode_t shellmatta_doInit(
|
|
*handle = (shellmatta_handle_t)inst;
|
|
*handle = (shellmatta_handle_t)inst;
|
|
|
|
|
|
/* init transport layer */
|
|
/* init transport layer */
|
|
|
|
+ inst->transportBusyMark = 0u;
|
|
shellmatta_transport_init(&inst->transportLayer, inst->write);
|
|
shellmatta_transport_init(&inst->transportLayer, inst->write);
|
|
|
|
|
|
/** -# print the first prompt */
|
|
/** -# print the first prompt */
|
|
@@ -373,435 +721,50 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
|
|
char *data,
|
|
char *data,
|
|
uint32_t size)
|
|
uint32_t size)
|
|
{
|
|
{
|
|
- shellmatta_cmd_t *cmd;
|
|
|
|
- uint8_t cmdExecuted = 0u;
|
|
|
|
- uint32_t cmdLen;
|
|
|
|
- char *tempString;
|
|
|
|
-
|
|
|
|
- shellmatta_retCode_t ret = SHELLMATTA_OK;
|
|
|
|
- shellmatta_retCode_t cmdRet;
|
|
|
|
|
|
+ shellmatta_retCode_t ret = SHELLMATTA_OK;
|
|
shellmatta_instance_t *inst = (shellmatta_instance_t*)handle;
|
|
shellmatta_instance_t *inst = (shellmatta_instance_t*)handle;
|
|
|
|
+ char *tmpData;
|
|
|
|
+ uint32_t tmpSize = 0;
|
|
|
|
+ uint32_t i;
|
|
|
|
+ bool processingDone = false;
|
|
|
|
|
|
/** -# check parameters for plausibility */
|
|
/** -# check parameters for plausibility */
|
|
if( (NULL != inst)
|
|
if( (NULL != inst)
|
|
&& (SHELLMATTA_MAGIC == inst->magic))
|
|
&& (SHELLMATTA_MAGIC == inst->magic))
|
|
{
|
|
{
|
|
- if ( (inst->transportLayer.state != STATE_PROCESS_PAYLOAD)
|
|
|
|
- && (inst->transportLayer.state != STATE_MANUAL_INPUT))
|
|
|
|
- {
|
|
|
|
- // TODO: Move this into shellmatta_transport.c
|
|
|
|
- /* use headerCounter to watch how many header fields have been worked on */
|
|
|
|
- uint8_t headerCounter = 0u;
|
|
|
|
- while ( (size > headerCounter)
|
|
|
|
- || ( (true == inst->transportLayer.mandatory)
|
|
|
|
- && (size > headerCounter))
|
|
|
|
- || (true == inst->transportLayer.continueStep))
|
|
|
|
- {
|
|
|
|
- switch (inst->transportLayer.state)
|
|
|
|
- {
|
|
|
|
- case STATE_GET_SOH:
|
|
|
|
- /* wait for SOH or go to payload */
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case STATE_GET_PROTOCOL_VERSION:
|
|
|
|
- inst->transportLayer.protocolVersion = data[headerCounter];
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case STATE_GET_PACKET_TYPE:
|
|
|
|
- inst->transportLayer.packetType = (shellmatta_transport_packet_t)data[headerCounter];
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case STATE_GET_PAYLOAD_LENGTH:
|
|
|
|
- inst->transportLayer.payloadLength = (uint8_t)data[headerCounter];
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case STATE_GET_SOURCE:
|
|
|
|
- inst->transportLayer.source = data[headerCounter];
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case STATE_GET_DESTINATION:
|
|
|
|
- inst->transportLayer.destination = data[headerCounter];
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case STATE_GET_H2S_SEQUENCE_CNT:
|
|
|
|
- inst->transportLayer.packetSequenceCounter_h2s = data[headerCounter];
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case STATE_GET_S2H_SEQUENCE_CNT:
|
|
|
|
- inst->transportLayer.packetSequenceCounter_s2h = data[headerCounter];
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case STATE_GET_PAYLOAD:
|
|
|
|
- if (0u == inst->transportLayer.payloadLength)
|
|
|
|
- {
|
|
|
|
- inst->transportLayer.continueStep = true;
|
|
|
|
- }
|
|
|
|
- inst->transportLayer.payloadBuffer[inst->transportLayer.payloadCounter++] = data[headerCounter];
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case STATE_GET_CRC:
|
|
|
|
- inst->transportLayer.continueStep = false;
|
|
|
|
- inst->transportLayer.crc32 |= (uint8_t)data[headerCounter] << (SHELLMATTA_LENGTH_CRC - 1u - inst->transportLayer.crcCounter++) * 8u;
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- default:
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- /* handling of transport layer fsm */
|
|
|
|
- ret = shellmatta_transport_process(&inst->transportLayer, data, 0);
|
|
|
|
-
|
|
|
|
- /* crc error handling */
|
|
|
|
- if (SHELLMATTA_ERROR == ret)
|
|
|
|
- {
|
|
|
|
- shellmatta_transport_reset(&inst->transportLayer);
|
|
|
|
- utils_writeEcho(inst, "crc error\r\n", 11);
|
|
|
|
- utils_terminateInput(inst);
|
|
|
|
- return SHELLMATTA_OK;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- headerCounter++;
|
|
|
|
-
|
|
|
|
- /* processes payload by forwarding it recursively without transport layer to processData() */
|
|
|
|
- if (inst->transportLayer.state == STATE_PROCESS_PAYLOAD)
|
|
|
|
- {
|
|
|
|
- /* recursive call with complete payload */
|
|
|
|
- shellmatta_processData(handle,
|
|
|
|
- inst->transportLayer.payloadBuffer,
|
|
|
|
- inst->transportLayer.payloadLength);
|
|
|
|
-
|
|
|
|
- shellmatta_transport_process(&inst->transportLayer, data, 0);
|
|
|
|
- return SHELLMATTA_OK;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if ( (inst->transportLayer.active)
|
|
|
|
- && (inst->transportLayer.state != STATE_PROCESS_PAYLOAD)
|
|
|
|
- && (inst->transportLayer.state != STATE_MANUAL_INPUT))
|
|
|
|
- {
|
|
|
|
- return SHELLMATTA_OK;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /** -# in busy mode - keep calling this command */
|
|
|
|
- if(NULL != inst->busyCmd)
|
|
|
|
|
|
+ for (i = inst->transportBusyMark; i < size; i ++)
|
|
{
|
|
{
|
|
- /** -# just call the function until it is not busy anymore */
|
|
|
|
- (void)shellmatta_opt_reInit(inst);
|
|
|
|
- ret = inst->busyCmd->cmdFct(handle, inst->buffer, inst->inputCount);
|
|
|
|
-
|
|
|
|
- if(SHELLMATTA_BUSY == ret)
|
|
|
|
|
|
+ ret = shellmatta_transport_process(&inst->transportLayer, data[i], &tmpData, &tmpSize);
|
|
|
|
+ if (SHELLMATTA_OK == ret)
|
|
{
|
|
{
|
|
- /** -# do nothing - still busy */
|
|
|
|
- }
|
|
|
|
- else if(SHELLMATTA_CONTINUE == ret)
|
|
|
|
- {
|
|
|
|
- inst->continuousCmd = inst->busyCmd;
|
|
|
|
- inst->busyCmd = NULL;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- utils_terminateInput(inst);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- /** -# call continuous function even if there is no data */
|
|
|
|
- else if((0u == size) && (NULL != inst->continuousCmd))
|
|
|
|
- {
|
|
|
|
- /** -# just call the function without any new data */
|
|
|
|
- inst->stdinLength = 0u;
|
|
|
|
- inst->buffer[inst->stdinIdx] = '\0';
|
|
|
|
- (void)shellmatta_opt_reInit(inst);
|
|
|
|
- ret = inst->continuousCmd->cmdFct(handle, inst->buffer, inst->inputCount);
|
|
|
|
|
|
+ ret = shellmatta_processDataInt(handle, tmpData, tmpSize);
|
|
|
|
+ processingDone = true;
|
|
|
|
|
|
- if(SHELLMATTA_CONTINUE == ret)
|
|
|
|
- {
|
|
|
|
- /** -# do nothing just continue */
|
|
|
|
- }
|
|
|
|
- else if(SHELLMATTA_BUSY == ret)
|
|
|
|
- {
|
|
|
|
- inst->busyCmd = inst->continuousCmd;
|
|
|
|
- inst->continuousCmd = NULL;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- utils_terminateInput(inst);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- /* nothing to do here - continue parsing the command */
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /** -# process byte wise */
|
|
|
|
- for (; (inst->byteCounter < size) && (NULL == inst->busyCmd); inst->byteCounter++)
|
|
|
|
- {
|
|
|
|
- /** -# in continuous mode - pass data directly to the command */
|
|
|
|
- if(NULL != inst->continuousCmd)
|
|
|
|
- {
|
|
|
|
- /** -# copy data and call command function */
|
|
|
|
- inst->buffer[inst->stdinIdx] = data[inst->byteCounter];
|
|
|
|
- inst->buffer[inst->stdinIdx + 1u] = '\0';
|
|
|
|
- inst->stdinLength = 1u;
|
|
|
|
- (void)shellmatta_opt_reInit(inst);
|
|
|
|
- ret = inst->continuousCmd->cmdFct(handle, inst->buffer, inst->inputCount);
|
|
|
|
-
|
|
|
|
- /** -# check if continuous mode is canceled or interrupted by busy mode */
|
|
|
|
- if(SHELLMATTA_BUSY == ret)
|
|
|
|
- {
|
|
|
|
- inst->busyCmd = inst->continuousCmd;
|
|
|
|
- inst->continuousCmd = NULL;
|
|
|
|
- }
|
|
|
|
- else if(('\x03' == data[inst->byteCounter]))
|
|
|
|
- {
|
|
|
|
- /** -# cancel continue session */
|
|
|
|
- utils_terminateInput(inst);
|
|
|
|
- ret = SHELLMATTA_OK;
|
|
|
|
- }
|
|
|
|
- else if(SHELLMATTA_CONTINUE == ret)
|
|
|
|
|
|
+ if (SHELLMATTA_BUSY == ret)
|
|
{
|
|
{
|
|
- /** -# do nothing - continue */
|
|
|
|
|
|
+ inst->transportBusyMark = i;
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
- utils_terminateInput(inst);
|
|
|
|
|
|
+ inst->transportBusyMark = 0u;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- /** -# handle escape sequences */
|
|
|
|
- else if(inst->escapeCounter != 0u)
|
|
|
|
- {
|
|
|
|
- escape_handleSequence(inst, data[inst->byteCounter]);
|
|
|
|
- }
|
|
|
|
- /** -# handle delimiter as start of processing the command */
|
|
|
|
- else if (inst->delimiter == data[inst->byteCounter])
|
|
|
|
|
|
+ else if (SHELLMATTA_ERROR == ret)
|
|
{
|
|
{
|
|
- if(0u == inst->hereLength)
|
|
|
|
- {
|
|
|
|
- /**
|
|
|
|
- * @dot
|
|
|
|
- * digraph heredocParser {
|
|
|
|
- * start -> wait [ label="<< in first line - store delimiter" ];
|
|
|
|
- * wait -> wait [ label="delimiter not detected" ];
|
|
|
|
- * wait -> end [ label="delimiter found - remove all heredoc stuff and send the input to the command" ];
|
|
|
|
- * }
|
|
|
|
- * @enddot */
|
|
|
|
-
|
|
|
|
- /** -# check for heredoc - add string delimiter to stop strstr from searching too far */
|
|
|
|
- inst->buffer[inst->inputCount] = '\0';
|
|
|
|
- tempString = strstr(inst->buffer, "<<");
|
|
|
|
- if(NULL != tempString)
|
|
|
|
- {
|
|
|
|
- /*' -# check if length of heredoc delimiter is valid */
|
|
|
|
- if(inst->inputCount > ((uint32_t)(tempString - inst->buffer) + 2u))
|
|
|
|
- {
|
|
|
|
- inst->hereStartIdx = (uint32_t)(tempString - inst->buffer);
|
|
|
|
- inst->hereDelimiterIdx = inst->hereStartIdx + 2u;
|
|
|
|
- while((inst->hereDelimiterIdx < inst->inputCount)
|
|
|
|
- && ( ('\0' == inst->buffer[inst->hereDelimiterIdx])
|
|
|
|
- || (' ' == inst->buffer[inst->hereDelimiterIdx])))
|
|
|
|
- {
|
|
|
|
- inst->hereDelimiterIdx ++;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- inst->hereLength = inst->inputCount - inst->hereDelimiterIdx;
|
|
|
|
-
|
|
|
|
- inst->dirty = true;
|
|
|
|
- utils_insertChars(inst, &data[inst->byteCounter], 1u);
|
|
|
|
- inst->lastNewlineIdx = inst->inputCount;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- inst->hereLength = 0u;
|
|
|
|
-
|
|
|
|
- /** -# store the current command and reset the history buffer */
|
|
|
|
- inst->dirty = true;
|
|
|
|
- history_storeCmd(inst);
|
|
|
|
- history_reset(inst);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- /** -# store the current command and reset the history buffer */
|
|
|
|
- inst->dirty = true;
|
|
|
|
- history_storeCmd(inst);
|
|
|
|
- history_reset(inst);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- tempString = &inst->buffer[inst->lastNewlineIdx];
|
|
|
|
- cmdLen = inst->inputCount - inst->lastNewlineIdx;
|
|
|
|
-
|
|
|
|
- /** -# skip newline characters before comparison */
|
|
|
|
- while(('\n' == *tempString) || ('\r' == *tempString))
|
|
|
|
- {
|
|
|
|
- tempString ++;
|
|
|
|
- cmdLen --;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if( (inst->hereLength == cmdLen)
|
|
|
|
- && (0 == strncmp( &inst->buffer[inst->hereDelimiterIdx],
|
|
|
|
- tempString,
|
|
|
|
- inst->hereLength)))
|
|
|
|
- {
|
|
|
|
- /** -# store the current command and reset the history buffer */
|
|
|
|
- inst->dirty = true;
|
|
|
|
- history_storeCmd(inst);
|
|
|
|
- history_reset(inst);
|
|
|
|
-
|
|
|
|
- /** -# process heredoc as stdin like input */
|
|
|
|
- /** -# find start of heredoc data */
|
|
|
|
- inst->stdinIdx = inst->hereDelimiterIdx + inst->hereLength;
|
|
|
|
- while( ('\n' == inst->buffer[inst->stdinIdx])
|
|
|
|
- || ('\r' == inst->buffer[inst->stdinIdx]))
|
|
|
|
- {
|
|
|
|
- inst->stdinIdx ++;
|
|
|
|
- }
|
|
|
|
- /** -# calculate length and terminate stdin string */
|
|
|
|
- if(inst->stdinIdx < inst->lastNewlineIdx)
|
|
|
|
- {
|
|
|
|
- inst->stdinLength = inst->lastNewlineIdx - inst->stdinIdx;
|
|
|
|
- inst->buffer[inst->lastNewlineIdx] = '\0';
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- inst->stdinLength = 0u;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /** -# calculate length and terminate argument string */
|
|
|
|
- inst->inputCount = inst->hereStartIdx;
|
|
|
|
- inst->buffer[inst->hereStartIdx] = '\0';
|
|
|
|
-
|
|
|
|
- /** -# terminate heredoc session */
|
|
|
|
- inst->hereLength = 0u;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- /** -# the party goes on - just print the delimiter and store the position */
|
|
|
|
- inst->lastNewlineIdx = inst->inputCount;
|
|
|
|
- utils_insertChars(inst, &data[inst->byteCounter], 1u);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if(0u == inst->hereLength)
|
|
|
|
- {
|
|
|
|
- cmd = inst->cmdList;
|
|
|
|
-
|
|
|
|
- /** -# determine the cmd len (chars until first space or \0 is found */
|
|
|
|
- cmdLen = 0u;
|
|
|
|
- while( (cmdLen < inst->inputCount)
|
|
|
|
- && (' ' != inst->buffer[cmdLen])
|
|
|
|
- && ('\r' != inst->buffer[cmdLen])
|
|
|
|
- && ('\n' != inst->buffer[cmdLen])
|
|
|
|
- && ('\0' != inst->buffer[cmdLen]))
|
|
|
|
- {
|
|
|
|
- cmdLen ++;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /** -# search for a matching command */
|
|
|
|
- while (NULL != cmd)
|
|
|
|
- {
|
|
|
|
- /** -# compare command and alias string and length */
|
|
|
|
- if ( ((cmdLen == strlen(cmd->cmd))
|
|
|
|
- && (0 == strncmp(inst->buffer, cmd->cmd, cmdLen)))
|
|
|
|
- || ((NULL != cmd->cmdAlias)
|
|
|
|
- && (cmdLen == strlen(cmd->cmdAlias))
|
|
|
|
- && (0 == strncmp(inst->buffer, cmd->cmdAlias, cmdLen))))
|
|
|
|
- {
|
|
|
|
- utils_writeEcho(inst, "\r\n", 2u);
|
|
|
|
- shellmatta_opt_init(inst, cmdLen + 1u);
|
|
|
|
- cmdExecuted = 1u;
|
|
|
|
- cmdRet = cmd->cmdFct(handle, inst->buffer, inst->inputCount);
|
|
|
|
-
|
|
|
|
- switch(cmdRet)
|
|
|
|
- {
|
|
|
|
- case SHELLMATTA_CONTINUE:
|
|
|
|
- /** -# initialize stdin buffer and continuous cmd */
|
|
|
|
- inst->stdinIdx = inst->inputCount + 1u;
|
|
|
|
- inst->stdinLength = 0u;
|
|
|
|
- inst->continuousCmd = cmd;
|
|
|
|
- ret = cmdRet;
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case SHELLMATTA_BUSY:
|
|
|
|
- inst->busyCmd = cmd;
|
|
|
|
- ret = cmdRet;
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- default:
|
|
|
|
- /* nothing to do - everything ok */
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- cmd = NULL;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- cmd = cmd->next;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if ((0u == cmdExecuted) && (inst->inputCount > 0))
|
|
|
|
- {
|
|
|
|
- SHELLMATTA_WRITE("\r\nCommand: ", 11u);
|
|
|
|
- SHELLMATTA_WRITE(inst->buffer, inst->inputCount);
|
|
|
|
- SHELLMATTA_WRITE(" not found", 10u);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /** -# terminate this session if no continuous mode is requested */
|
|
|
|
- if( (NULL == inst->continuousCmd)
|
|
|
|
- && (NULL == inst->busyCmd))
|
|
|
|
- {
|
|
|
|
- utils_terminateInput(inst);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- /** -# ignore newline as first character (to be compatible to
|
|
|
|
- * terminals sending newline after return) */
|
|
|
|
- else if((0u == inst->inputCount) && ('\n' == data[inst->byteCounter]))
|
|
|
|
- {
|
|
|
|
- /* do nothing */
|
|
|
|
- }
|
|
|
|
- /** -# check for tabulator key - auto complete */
|
|
|
|
- else if('\t' == data[inst->byteCounter])
|
|
|
|
- {
|
|
|
|
- inst->dirty = true;
|
|
|
|
- autocomplete_run(inst);
|
|
|
|
- }
|
|
|
|
- /** -# check for cancel -
|
|
|
|
- * terminate current input and print prompt again */
|
|
|
|
- else if('\x03' == data[inst->byteCounter])
|
|
|
|
- {
|
|
|
|
- inst->dirty = false;
|
|
|
|
- history_reset(inst);
|
|
|
|
|
|
+ utils_writeEcho(inst, "crc error\r\n", 11);
|
|
utils_terminateInput(inst);
|
|
utils_terminateInput(inst);
|
|
}
|
|
}
|
|
- /** -# check for backspace */
|
|
|
|
- else if( ('\b' == data[inst->byteCounter])
|
|
|
|
- || ('\x7f' == data[inst->byteCounter]))
|
|
|
|
- {
|
|
|
|
- inst->dirty = true;
|
|
|
|
- utils_removeChars(inst, 1u, true);
|
|
|
|
- }
|
|
|
|
- /** -# check for start of escape sequence */
|
|
|
|
- else if('\x1b' == data[inst->byteCounter])
|
|
|
|
- {
|
|
|
|
- inst->escapeCounter = 1u;
|
|
|
|
- }
|
|
|
|
else
|
|
else
|
|
{
|
|
{
|
|
- inst->dirty = true;
|
|
|
|
- utils_insertChars(inst, &data[inst->byteCounter], 1u);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /** -# reset tab counter on not a tab */
|
|
|
|
- if ('\t' != data[inst->byteCounter])
|
|
|
|
- {
|
|
|
|
- inst->tabCounter = 0u;
|
|
|
|
|
|
+ /* nothing to do - transport layer busy */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- /** -# initialize the byte buffer if processing of the input is finished */
|
|
|
|
- if(ret != SHELLMATTA_BUSY)
|
|
|
|
|
|
+ /*! -# call the internal processing at least once - for continued and busy commands */
|
|
|
|
+ if (true != processingDone)
|
|
{
|
|
{
|
|
- inst->byteCounter = 0u;
|
|
|
|
|
|
+ ret = shellmatta_processDataInt(handle, tmpData, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
else
|
|
@@ -809,12 +772,6 @@ shellmatta_retCode_t shellmatta_processData(shellmatta_handle_t handle,
|
|
ret = SHELLMATTA_USE_FAULT;
|
|
ret = SHELLMATTA_USE_FAULT;
|
|
}
|
|
}
|
|
|
|
|
|
- /* if manual input happened, reset transport layer fsm back to initial state */
|
|
|
|
- if (inst->transportLayer.state == STATE_MANUAL_INPUT)
|
|
|
|
- {
|
|
|
|
- inst->transportLayer.state = STATE_GET_SOH;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|