Annotation of embedaddon/mtr/packet/cmdparse.c, revision 1.1

1.1     ! misho       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
        !            15:     along with this program; if not, write to the Free Software
        !            16:     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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:     comamnd_string will be modified in-place with NUL characters terminating
        !            70:     tokens, and the command_t will use pointers to the conents 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>