File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mtr / packet / cmdparse.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:07:30 2021 UTC (3 years, 3 months ago) by misho
Branches: mtr, MAIN
CVS tags: v0_95, v0_94, HEAD
mtr 0.94

    1: /*
    2:     mtr  --  a network diagnostic tool
    3:     Copyright (C) 2016  Matt Kimball
    4: 
    5:     This program is free software; you can redistribute it and/or modify
    6:     it under the terms of the GNU General Public License version 2 as
    7:     published by the Free Software Foundation.
    8: 
    9:     This program is distributed in the hope that it will be useful,
   10:     but WITHOUT ANY WARRANTY; without even the implied warranty of
   11:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12:     GNU General Public License for more details.
   13: 
   14:     You should have received a copy of the GNU General Public License along
   15:     with this program; if not, write to the Free Software Foundation, Inc.,
   16:     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   17: */
   18: 
   19: #include "cmdparse.h"
   20: 
   21: #include <ctype.h>
   22: #include <errno.h>
   23: #include <stdlib.h>
   24: #include <string.h>
   25: 
   26: /*
   27:     NUL terminate the whitespace separated tokens in the command string.
   28:     This modifies command_string in-place with NUL characters.
   29:     Fill the tokens array with pointers to the tokens, and return the
   30:     number of tokens found.
   31: */
   32: static
   33: int tokenize_command(
   34:     char **tokens,
   35:     int max_tokens,
   36:     char *command_string)
   37: {
   38:     int token_count = 0;
   39:     int on_space = 1;
   40:     int i;
   41: 
   42:     for (i = 0; command_string[i]; i++) {
   43:         if (on_space) {
   44:             if (!isspace((unsigned char) command_string[i])) {
   45:                 /*  Take care not to exceed the token array length  */
   46:                 if (token_count >= max_tokens) {
   47:                     return -1;
   48:                 }
   49: 
   50:                 tokens[token_count++] = &command_string[i];
   51:                 on_space = 0;
   52:             }
   53:         } else {
   54:             if (isspace((unsigned char) command_string[i])) {
   55:                 command_string[i] = 0;
   56:                 on_space = 1;
   57:             }
   58:         }
   59:     }
   60: 
   61:     return token_count;
   62: }
   63: 
   64: /*
   65:     Parse a command string (or command reply string) into a command_t
   66:     structure for later semantic interpretation.  Returns EINVAL if the
   67:     command string is unparseable or zero for success.
   68: 
   69:     command_string will be modified in-place with NUL characters terminating
   70:     tokens, and the command_t will use pointers to the contents of
   71:     command_string without copying, so any interpretation of the
   72:     command_t structure requires that the command_string memory has not yet
   73:     been freed or otherwise reused.
   74: */
   75: int parse_command(
   76:     struct command_t *command,
   77:     char *command_string)
   78: {
   79:     char *tokens[MAX_COMMAND_TOKENS];
   80:     int token_count;
   81:     int i;
   82: 
   83:     memset(command, 0, sizeof(struct command_t));
   84: 
   85:     /*  Tokenize the string using whitespace  */
   86:     token_count =
   87:         tokenize_command(tokens, MAX_COMMAND_TOKENS, command_string);
   88:     if (token_count < 2) {
   89:         errno = EINVAL;
   90:         return -1;
   91:     }
   92: 
   93:     /*  Expect the command token to be a numerical value  */
   94:     errno = 0;
   95:     command->token = strtol(tokens[0], NULL, 10);
   96:     if (errno) {
   97:         errno = EINVAL;
   98:         return -1;
   99:     }
  100:     command->command_name = tokens[1];
  101: 
  102:     /*
  103:        The tokens beyond the command name are expected to be in
  104:        name, value pairs.
  105:      */
  106:     i = 2;
  107:     command->argument_count = 0;
  108:     while (i < token_count) {
  109:         /*  It's an error if we get a name without a key  */
  110:         if (i + 1 >= token_count) {
  111:             errno = EINVAL;
  112:             return -1;
  113:         }
  114: 
  115:         /*  It's an error if we get more arguments than we have space for  */
  116:         if (command->argument_count >= MAX_COMMAND_ARGUMENTS) {
  117:             errno = EINVAL;
  118:             return -1;
  119:         }
  120: 
  121:         command->argument_name[command->argument_count] = tokens[i];
  122:         command->argument_value[command->argument_count] = tokens[i + 1];
  123:         command->argument_count++;
  124: 
  125:         i += 2;
  126:     }
  127: 
  128:     return 0;
  129: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>