Merge pull request #515 from msekletar/icmp-socket-leak
[mtr.git] / packet / cmdparse.c
blob85757b622b98f82a5541d1309545df8f8051d756
1 /*
2 mtr -- a network diagnostic tool
3 Copyright (C) 2016 Matt Kimball
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.
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.
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.
19 #include "cmdparse.h"
21 #include <ctype.h>
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <string.h>
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.
32 static
33 int tokenize_command(
34 char **tokens,
35 int max_tokens,
36 char *command_string)
38 int token_count = 0;
39 int on_space = 1;
40 int i;
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;
50 tokens[token_count++] = &command_string[i];
51 on_space = 0;
53 } else {
54 if (isspace((unsigned char) command_string[i])) {
55 command_string[i] = 0;
56 on_space = 1;
61 return token_count;
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.
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.
75 int parse_command(
76 struct command_t *command,
77 char *command_string)
79 char *tokens[MAX_COMMAND_TOKENS];
80 int token_count;
81 int i;
83 memset(command, 0, sizeof(struct command_t));
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;
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;
100 command->command_name = tokens[1];
103 The tokens beyond the command name are expected to be in
104 name, value pairs.
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;
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;
121 command->argument_name[command->argument_count] = tokens[i];
122 command->argument_value[command->argument_count] = tokens[i + 1];
123 command->argument_count++;
125 i += 2;
128 return 0;