From 2c8a0f776d5112b0f9ba699cad48d85a4905d87e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Mon, 6 Jan 2025 19:12:49 +0100 Subject: [PATCH] clients/upsclient.c: upscli_splitname(): handle "upsname:port" shortcut attempts Signed-off-by: Jim Klimov --- NEWS.adoc | 2 ++ clients/upsclient.c | 28 ++++++++++++++++++---------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index aed8e8a6a2..ee9fba80b6 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -414,6 +414,8 @@ logic that was previously the content of `upsdrv_shutdown()` methods was often relocated into new `shutdown.default` INSTCMD definitions. [#2670] - common code: + * `upscli_splitname()` should now recognize `upsname:port` typos (missing + the `@hostname` part) and error out gracefully. * introduced a `NUT_DEBUG_SYSLOG` environment variable to tweak activation of syslog message emission (and related detachment of `stderr` when backgrounding), primarily useful for NIT and perhaps systemd. Most diff --git a/clients/upsclient.c b/clients/upsclient.c index d6a3d6ff59..31b6de7f98 100644 --- a/clients/upsclient.c +++ b/clients/upsclient.c @@ -3,7 +3,7 @@ Copyright (C) 2002 Russell Kroll 2008 Arjen de Korte - 2020 - 2024 Jim Klimov + 2020 - 2025 Jim Klimov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1622,7 +1622,7 @@ ssize_t upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen) /* split upsname[@hostname[:port]] into separate components */ int upscli_splitname(const char *buf, char **upsname, char **hostname, uint16_t *port) { - char *s, tmp[SMALLBUF], *last = NULL; + char *sat, *ssc, tmp[SMALLBUF], *last = NULL; /* paranoia */ if ((!buf) || (!upsname) || (!hostname) || (!port)) { @@ -1634,10 +1634,11 @@ int upscli_splitname(const char *buf, char **upsname, char **hostname, uint16_t return -1; } - s = strchr(tmp, '@'); + sat = strchr(tmp, '@'); + ssc = strchr(tmp, ':'); /* someone passed a "@hostname" string? */ - if (s == tmp) { + if (sat == tmp) { fprintf(stderr, "upscli_splitname: got empty upsname string\n"); return -1; } @@ -1653,13 +1654,20 @@ int upscli_splitname(const char *buf, char **upsname, char **hostname, uint16_t return -1; } - /* +/* fprintf(stderr, "upscli_splitname3: got buf='%s', tmp='%s', upsname='%s', possible hostname:port='%s'\n", - NUT_STRARG(buf), NUT_STRARG(tmp), NUT_STRARG(*upsname), NUT_STRARG((s ? s+1 : s))); - */ + NUT_STRARG(buf), NUT_STRARG(tmp), NUT_STRARG(*upsname), NUT_STRARG((sat ? sat+1 : sat))); + */ /* only a upsname is specified, fill in defaults */ - if (s == NULL) { + if (sat == NULL) { + if (ssc) { + /* TOTHINK: Consult isdigit(ssc+1) to shortcut + * `upsname:port` into `upsname@localhost:port`? */ + fprintf(stderr, "upscli_splitname: port specified, but not a hostname\n"); + return -1; + } + if ((*hostname = xstrdup("localhost")) == NULL) { fprintf(stderr, "upscli_splitname: xstrdup failed\n"); return -1; @@ -1670,12 +1678,12 @@ int upscli_splitname(const char *buf, char **upsname, char **hostname, uint16_t } /* someone passed a "upsname@" string? */ - if (!(*(s+1))) { + if (!(*(sat+1))) { fprintf(stderr, "upscli_splitname: got the @ separator and then an empty hostname[:port] string\n"); return -1; } - return upscli_splitaddr(s+1, hostname, port); + return upscli_splitaddr(sat+1, hostname, port); } /* split hostname[:port] into separate components */