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

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: 
1.1.1.2 ! misho      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.
1.1       misho      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: 
1.1.1.2 ! misho      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
1.1       misho      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>