From d79ccc65f7134839a6d00f0eb70f43c2b614e9c8 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Thu, 7 Mar 2019 23:08:40 +0100 Subject: add osmo_str_startswith() Move from a static implementation in tdef_vty.c to utils.c, I also want to use this in osmo-msc. The point is that the telnet VTY allows unambiguous partly matches of keyword args. For example, if I have a command definition of: compare (apples|oranges) then it is perfectly legal as for the vty parser to write only compare app One could expect the VTY to then pass the unambiguous match of "apples" to the parsing function, but that is not the case. Hence a VTY function implementation is faced with parsing a keyword of "app" instead of the expected "apples". This is actually a very widespread bug in our VTY implementations, which assume that exactly one full keyword will always be found. I am now writing new commands in a way that are able to manage only the starts of keywords. Arguably, strstr(a, b) == a does the same thing, but it searches the entire string unnecessarily. Change-Id: Ib2ffb0e9a870dd52e081c7e66d8818057d159513 --- src/utils.c | 14 ++++++++++++++ src/vty/tdef_vty.c | 12 +----------- 2 files changed, 15 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/utils.c b/src/utils.c index b8b4ef56..9ab990ab 100644 --- a/src/utils.c +++ b/src/utils.c @@ -928,4 +928,18 @@ const char osmo_luhn(const char* in, int in_len) return (sum * 9) % 10 + '0'; } +/*! Compare start of a string. + * This is an optimisation of 'strstr(str, startswith_str) == str' because it doesn't search through the entire string. + * \param str (Longer) string to compare. + * \param startswith_str (Shorter) string to compare with the start of str. + * \return true iff the first characters of str fully match startswith_str or startswith_str is empty. */ +bool osmo_str_startswith(const char *str, const char *startswith_str) +{ + if (!startswith_str || !*startswith_str) + return true; + if (!str) + return false; + return strncmp(str, startswith_str, strlen(startswith_str)) == 0; +} + /*! @} */ diff --git a/src/vty/tdef_vty.c b/src/vty/tdef_vty.c index 28de21a7..0dac2bf5 100644 --- a/src/vty/tdef_vty.c +++ b/src/vty/tdef_vty.c @@ -247,16 +247,6 @@ void osmo_tdef_vty_write(struct vty *vty, struct osmo_tdef *tdefs, const char *p /*! Singleton Tnnn groups definition as set by osmo_tdef_vty_groups_init(). */ static struct osmo_tdef_group *global_tdef_groups; -/*! \return true iff the first characters of str fully match startswith_str or both are empty. */ -static bool startswith(const char *str, const char *startswith_str) -{ - if (!startswith_str) - return true; - if (!str) - return false; - return strncmp(str, startswith_str, strlen(startswith_str)) == 0; -} - DEFUN(show_timer, show_timer_cmd, "DYNAMIC", "DYNAMIC") /* show timer [(alpha|beta|gamma)] [TNNNN] */ { @@ -268,7 +258,7 @@ DEFUN(show_timer, show_timer_cmd, "DYNAMIC", "DYNAMIC") * like "softw" or "t" (which can also be ambiguous). */ osmo_tdef_groups_for_each(g, global_tdef_groups) { - if (!group_arg || startswith(g->name, group_arg)) + if (!group_arg || osmo_str_startswith(g->name, group_arg)) osmo_tdef_vty_show_cmd(vty, g->tdefs, T_arg, "%s: ", g->name); } return CMD_SUCCESS; -- cgit v1.2.3