Skip to content

Commit 7eafbf5

Browse files
committed
clients/authconf.{c,h}, docs: further refactor with upscli_normalize_auth_section_parts() which we can share and expose [#3329]
Signed-off-by: Jim Klimov <jimklimov+nut@gmail.com>
1 parent b1dc0d2 commit 7eafbf5

4 files changed

Lines changed: 158 additions & 67 deletions

File tree

clients/authconf.c

Lines changed: 116 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,115 @@ static void authconf_err(const char *errmsg)
292292
upslogx(LOG_ERR, "Error in parseconf(authconf): %s", errmsg);
293293
}
294294

295+
int upscli_normalize_auth_section_parts(
296+
char **out_normalized_sect_name,
297+
char **p_sect_user,
298+
int *out_fixed_sect_user,
299+
char **p_sect_host,
300+
char **p_sect_port)
301+
{
302+
char *sect_user = NULL, *sect_host = NULL, *sect_port = NULL;
303+
304+
/* All p_* args must be non-NULL pointers to `char *` string variables
305+
* which may be freed and re-allocated to return normalized values
306+
* (original strings may themselves be NULL).
307+
* The out_* values are optional and may be NULL if you do not want
308+
* those data points returned.
309+
*/
310+
if (!p_sect_user || !p_sect_host || !p_sect_port) {
311+
upslogx(LOG_ERR, "upscli_normalize_auth_section_parts: NULL pointer-to-string argument provided");
312+
return -1;
313+
}
314+
315+
/* No changes imposed here */
316+
sect_user = *p_sect_user;
317+
318+
sect_host = *p_sect_host;
319+
if (!sect_host || !*sect_host) {
320+
sect_host = xstrdup("localhost");
321+
if (!sect_host) goto failed;
322+
}
323+
324+
sect_port = *p_sect_port;
325+
if (sect_port && *sect_port) {
326+
/* As port is a string, resolve it (if not a number,
327+
* try to get one via "services" naming database) */
328+
char *p = sect_port;
329+
int is_numeric = 1;
330+
331+
while (*p) {
332+
if (!isdigit((unsigned char)*p)) {
333+
is_numeric = 0;
334+
break;
335+
}
336+
p++;
337+
}
338+
339+
if (!is_numeric) {
340+
struct servent *se = getservbyname(sect_port, "tcp");
341+
342+
if (se) {
343+
char portbuf[16];
344+
if (snprintf(portbuf, sizeof(portbuf), "%u", ntohs(se->s_port) < 1)) {
345+
upsdebugx(1, "%s: Failed to construct port number from service name", __func__);
346+
goto failed;
347+
}
348+
sect_port = xstrdup(portbuf);
349+
if (!sect_port) goto failed;
350+
} /* else resolution failed, keep original string */
351+
}
352+
} else {
353+
char portbuf[16];
354+
if (snprintf(portbuf, sizeof(portbuf), "%u", NUT_PORT) < 1) {
355+
upsdebugx(1, "%s: Failed to construct default port number", __func__);
356+
goto failed;
357+
}
358+
sect_port = xstrdup(portbuf);
359+
if (!sect_port) goto failed;
360+
}
361+
362+
/* Only now that we (almost) do not expect failures, we can
363+
* consistently populate caller's output variables (if any) */
364+
if (out_normalized_sect_name) {
365+
char normalized_sect_name_buf[LARGEBUF];
366+
367+
if (snprintf(normalized_sect_name_buf, sizeof(normalized_sect_name_buf), "%s@%s:%s",
368+
sect_user ? sect_user : "",
369+
sect_host,
370+
sect_port) > 0
371+
) {
372+
free(*out_normalized_sect_name);
373+
*out_normalized_sect_name = xstrdup(normalized_sect_name_buf);
374+
} else {
375+
upsdebugx(1, "%s: Failed to reconstruct normalized section header", __func__);
376+
goto failed;
377+
}
378+
}
379+
380+
if (out_fixed_sect_user)
381+
*out_fixed_sect_user = (sect_user && *sect_user);
382+
383+
/* Different pointers? */
384+
if (*p_sect_host != sect_host) {
385+
free(*p_sect_host);
386+
*p_sect_host = sect_host;
387+
}
388+
389+
if (*p_sect_port != sect_port) {
390+
free(*p_sect_port);
391+
*p_sect_port = sect_port;
392+
}
393+
394+
return 0;
395+
396+
failed:
397+
free(sect_user);
398+
free(sect_host);
399+
free(sect_port);
400+
401+
return -1;
402+
}
403+
295404
int upscli_split_auth_section(const char *sect_name,
296405
char **normalized_sect_name,
297406
char **normalized_sect_user,
@@ -352,69 +461,16 @@ int upscli_split_auth_section(const char *sect_name,
352461
}
353462

354463
if (colon && colon[1]) {
355-
/* As port is a string, resolve it (if not a number,
356-
* try to get one via "services" naming database) */
357-
const char *p = colon + 1;
358-
int is_numeric = 1;
359-
360-
while (*p) {
361-
if (!isdigit((unsigned char)*p)) {
362-
is_numeric = 0;
363-
break;
364-
}
365-
p++;
366-
}
367-
368-
if (is_numeric) {
369-
sect_port = xstrdup(colon + 1);
370-
} else {
371-
struct servent *se = getservbyname(colon + 1, "tcp");
372-
373-
if (se) {
374-
char portbuf[16];
375-
snprintf(portbuf, sizeof(portbuf), "%u", ntohs(se->s_port));
376-
sect_port = xstrdup(portbuf);
377-
} else {
378-
/* Resolution failed, fall back to original string */
379-
sect_port = xstrdup(colon + 1);
380-
}
381-
}
382-
464+
/* May get re-normalized below */
465+
sect_port = xstrdup(colon + 1);
383466
if (!sect_port) goto failed;
384467
}
385468

386-
if (!sect_host || !*sect_host) {
387-
free(sect_host);
388-
sect_host = xstrdup("localhost");
389-
if (!sect_host) goto failed;
390-
}
391-
392-
if (!sect_port || !*sect_port) {
393-
free(sect_port);
394-
sect_port = xcalloc(6, sizeof(char));
395-
if (!sect_port) goto failed;
396-
if (snprintf(sect_port, 6, "%u", NUT_PORT) < 1) {
397-
upsdebugx(1, "%s: Failed to construct default port number", __func__);
398-
goto failed;
399-
}
400-
}
401-
402-
/* Only now that we (almost) do not expect failures, we can
403-
* consistently populate caller's output variables (if any) */
404-
if (normalized_sect_name) {
405-
char normalized_sect_name_buf[LARGEBUF];
406-
407-
if (snprintf(normalized_sect_name_buf, sizeof(normalized_sect_name_buf), "%s@%s:%s",
408-
sect_user ? sect_user : "",
409-
sect_host,
410-
sect_port) > 0
411-
) {
412-
*normalized_sect_name = xstrdup(normalized_sect_name_buf);
413-
} else {
414-
upsdebugx(1, "%s: Failed to reconstruct normalized section header from '%s'", __func__, sect_name);
415-
goto failed;
416-
}
417-
}
469+
if (upscli_normalize_auth_section_parts(
470+
normalized_sect_name,
471+
&sect_user, &fixed_sect_user,
472+
&sect_host, &sect_port) < 0
473+
) goto failed;
418474

419475
if (out_fixed_sect_user)
420476
*out_fixed_sect_user = fixed_sect_user;

clients/authconf.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,19 @@ void upscli_free_authconf_list(void);
5252
*/
5353
int upscli_read_authconf(const char *filename, int fatal_errors);
5454

55+
/** All p_* args must be non-NULL pointers to `char *` string variables
56+
* which may be freed and re-allocated to return normalized values
57+
* (original strings may themselves be NULL).
58+
* The out_* values are optional and may be NULL if you do not want
59+
* those data points returned.
60+
*/
61+
int upscli_normalize_auth_section_parts(
62+
char **out_normalized_sect_name,
63+
char **p_sect_user,
64+
int *out_fixed_sect_user,
65+
char **p_sect_host,
66+
char **p_sect_port);
67+
5568
/** Take raw sect_name as input (e.g. a user-written string from config files).
5669
* Normalize it by splitting into user, host, and port components (populating absent values).
5770
* Return normalized components and reconstructed section name in output parameters (if not NULL),

docs/man/Makefile.am

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,7 @@ INST_MAN_DEV_API_PAGES = \
757757
upscli_upserror.$(MAN_SECTION_API) \
758758
upscli_upslog_set_debug_level.$(MAN_SECTION_API) \
759759
upscli_get_authconf_list.$(MAN_SECTION_API) \
760+
upscli_normalize_auth_section_parts.$(MAN_SECTION_API) \
760761
upscli_split_auth_section.$(MAN_SECTION_API) \
761762
upscli_free_authconf_list.$(MAN_SECTION_API) \
762763
upscli_read_authconf.$(MAN_SECTION_API) \
@@ -831,6 +832,9 @@ upscli_sendline_timeout_may_disconnect.$(MAN_SECTION_API): upscli_sendline.$(MAN
831832
upscli_tryconnect.$(MAN_SECTION_API): upscli_connect.$(MAN_SECTION_API)
832833
touch $@
833834

835+
upscli_normalize_auth_section_parts.$(MAN_SECTION_API): upscli_get_authconf_list.$(MAN_SECTION_API)
836+
touch $@
837+
834838
upscli_split_auth_section.$(MAN_SECTION_API): upscli_get_authconf_list.$(MAN_SECTION_API)
835839
touch $@
836840

@@ -988,6 +992,9 @@ upscli_sendline_timeout.html upscli_sendline_timeout_may_disconnect.html: upscli
988992
upscli_tryconnect.html: upscli_connect.html
989993
test -n '$?' -a -s '$@' && rm -f $@ && ln -s $? $@
990994

995+
upscli_normalize_auth_section_parts.html: upscli_get_authconf_list.html
996+
test -n '$?' -a -s '$@' && rm -f $@ && ln -s $? $@
997+
991998
upscli_split_auth_section.html: upscli_get_authconf_list.html
992999
test -n '$?' -a -s '$@' && rm -f $@ && ln -s $? $@
9931000

docs/man/upscli_find_authconf.txt

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ UPSCLI_FIND_AUTHCONF(3)
44
NAME
55
----
66

7-
upscli_find_authconf, upscli_split_auth_section, upscli_free_authconf - Find,
7+
upscli_find_authconf, upscli_normalize_auth_section_parts,
8+
upscli_split_auth_section, upscli_free_authconf - Find,
89
parse name, and free authentication configuration items
910

1011
SYNOPSIS
@@ -13,7 +14,17 @@ SYNOPSIS
1314
------
1415
#include <authconf.h>
1516

16-
upscli_authconf_t *upscli_find_authconf(const char *user, const char *host, const char *port);
17+
upscli_authconf_t *upscli_find_authconf(
18+
const char *user,
19+
const char *host,
20+
const char *port);
21+
22+
int upscli_normalize_auth_section_parts(
23+
char **out_normalized_sect_name,
24+
char **p_sect_user,
25+
int *out_fixed_sect_user,
26+
char **p_sect_host,
27+
char **p_sect_port);
1728

1829
int upscli_split_auth_section(const char *sect_name,
1930
char **normalized_sect_name,
@@ -43,11 +54,15 @@ inherited from the global defaults.
4354

4455
The "*upscli_split_auth_section()*" function splits a `sect_name` which may be
4556
from a user-typed configuration file into user, host and port sections, and
46-
normalizes the values (e.g. a `NULL` 'host' becomes `localhost`, a missing
47-
'port' is defaulted to `NUT_PORT` defined at build configuration time, e.g.
48-
'3493' by default, and a non-numeric string 'port' is resolved in the naming
49-
database of the current operating environment). Resulting normalized values
50-
are returned to caller using pointers provided in the arguments (if not `NULL`).
57+
with "*upscli_normalize_auth_section_parts()*" normalizes the values (e.g. a
58+
`NULL` 'host' becomes `localhost`, a missing 'port' is defaulted to `NUT_PORT`
59+
defined at build configuration time, e.g. '3493' by default, and a non-numeric
60+
string 'port' is resolved in the naming database of the current operating
61+
environment). The resulting normalized values are returned to caller using
62+
pointers provided in the arguments (if not `NULL` in case of
63+
"*upscli_split_auth_section()*", must be not `NULL` in case of
64+
"*upscli_normalize_auth_section_parts()*").
65+
5166
A 'normalized_sect_name' can be also constructed and returned, so that varying
5267
but ultimately identical definitions of the section titles (e.g. `[@localhost]`
5368
and `[@localhost:3493]` can be conflated when parsing configuration files or

0 commit comments

Comments
 (0)