From a024a17e877a26effef069aa823c45503bbad888 Mon Sep 17 00:00:00 2001 From: Bram Matthys Date: Fri, 13 Jan 2023 08:55:10 +0100 Subject: [PATCH] Add strtoken_noskip() and use it from the PROTOCTL EAUTH= code so we can deal with empty fields that get sent f.e. by anope, like EAUTH=services.test.net,,,Anope-2.0.11 Apparently this is similar to strsep(), or actually hypothetical strsep_r(), a function which does not seem to exist. --- include/common.h | 1 + src/modules/protoctl.c | 10 ++++----- src/support.c | 48 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/include/common.h b/include/common.h index 8cddcda7c..e595e4b8e 100644 --- a/include/common.h +++ b/include/common.h @@ -96,6 +96,7 @@ extern int myncmp(const char *, const char *, int); #endif extern char *strtoken(char **, char *, char *); +extern char *strtoken_noskip(char **, char *, char *); extern MODVAR int global_count, max_global_count; #ifdef _WIN32 diff --git a/src/modules/protoctl.c b/src/modules/protoctl.c index 21312003e..c45af25e0 100644 --- a/src/modules/protoctl.c +++ b/src/modules/protoctl.c @@ -243,7 +243,7 @@ CMD_FUNC(cmd_protoctl) p = NULL; } - servername = strtoken(&p, buf, ","); + servername = strtoken_noskip(&p, buf, ","); if (!servername || !valid_server_name(servername)) { exit_client(client, NULL, "Bogus server name"); @@ -251,14 +251,12 @@ CMD_FUNC(cmd_protoctl) } - protocol = strtoken(&p, NULL, ","); + protocol = strtoken_noskip(&p, NULL, ","); if (protocol) { - flags = strtoken(&p, NULL, ","); + flags = strtoken_noskip(&p, NULL, ","); if (flags) - { - software = strtoken(&p, NULL, ","); - } + software = strtoken_noskip(&p, NULL, ","); } /* Set client->name but don't add to hash list, this gives better diff --git a/src/support.c b/src/support.c index 8cc602ebd..6b1914a22 100644 --- a/src/support.c +++ b/src/support.c @@ -82,6 +82,54 @@ char *strtoken(char **save, char *str, char *fs) return (tmp); } +/** Walk through a string of tokens, using a set of separators. + * This is the special version that won't skip/merge tokens, + * eg "a,,c" would return "a", then "" (empty), then "c". + * This in contrast to strtoken() which would return "a" and then "c". + * This strtoken_noskip() will also not skip tokens at the + * beginning, eg ",,c" would return "" (empty), "" (empty), "c". + * + * @param save Pointer used for saving between calls + * @param str String to parse (will be altered!) + * @param fs Separator character(s) + * @returns substring (token) + * @note This function works similar to (but not identical?) to strtok_r(). + */ +char *strtoken_noskip(char **save, char *str, char *fs) +{ + char *pos, *tmp; + + if (str) + { + pos = str; /* new string scan */ + } else { + if (*save == NULL) + { + /* We reached the end of the string */ + return NULL; + } + pos = *save; /* keep last position across calls */ + } + + tmp = pos; /* start position, used for returning later */ + + /* Hunt for next separator (fs in pos) */ + while (*pos && !strchr(fs, *pos)) + pos++; + + if (!*pos) + { + /* Next call is end of string */ + *save = NULL; + *pos++ = '\0'; + } else { + *pos++ = '\0'; + *save = pos; + } + + return tmp; +} + /** Convert binary address to an IP string - like inet_ntop but will always return the uncompressed IPv6 form. * @param af Address family (AF_INET, AF_INET6) * @param in Address (binary)