From nobody Tue Aug 30 20:15:28 2022 X-Original-To: dev-commits-ports-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4MHJTJ6phMz4bFLT; Tue, 30 Aug 2022 20:15:32 +0000 (UTC) (envelope-from cy.schubert@cschubert.com) Received: from omta002.cacentral1.a.cloudfilter.net (omta002.cacentral1.a.cloudfilter.net [3.97.99.33]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "Client", Issuer "CA" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4MHJTH63LFz3WDS; Tue, 30 Aug 2022 20:15:31 +0000 (UTC) (envelope-from cy.schubert@cschubert.com) Received: from shw-obgw-4001a.ext.cloudfilter.net ([10.228.9.142]) by cmsmtp with ESMTP id T0OWouUsqSp39T7dyoYzoX; Tue, 30 Aug 2022 20:15:30 +0000 Received: from spqr.komquats.com ([70.66.148.124]) by cmsmtp with ESMTPA id T7dxo48H3uJwwT7dyoYpE1; Tue, 30 Aug 2022 20:15:30 +0000 X-Authority-Analysis: v=2.4 cv=F+BEy4tN c=1 sm=1 tr=0 ts=630e6fe2 a=Cwc3rblV8FOMdVN/wOAqyQ==:117 a=Cwc3rblV8FOMdVN/wOAqyQ==:17 a=kj9zAlcOel0A:10 a=biHskzXt2R4A:10 a=6I5d2MoRAAAA:8 a=vak6BqsbAAAA:8 a=_tdH1PNtAAAA:8 a=YxBL1-UpAAAA:8 a=EkcXrb_YAAAA:8 a=jQ633TsDu_bFP7LjNvAA:9 a=f6mnnDHi6AdCEp_6:21 a=CjuIK1q_8ugA:10 a=IjZwj45LgO3ly-622nXo:22 a=TeHgf6T8b0GtcBjs-19Q:22 a=bCEIlWor7hXDcxD8j6YS:22 a=Ia-lj3WSrqcvXOmTRaiG:22 a=LK5xJRSDVpKd5WXXoEvA:22 Received: from slippy.cwsent.com (slippy [10.1.1.91]) by spqr.komquats.com (Postfix) with ESMTP id 0837F8FE; Tue, 30 Aug 2022 13:15:28 -0700 (PDT) Received: by slippy.cwsent.com (Postfix, from userid 1000) id CB318293; Tue, 30 Aug 2022 13:15:28 -0700 (PDT) X-Mailer: exmh version 2.9.0 11/07/2018 with nmh-1.7+dev Reply-to: Cy Schubert From: Cy Schubert X-os: FreeBSD X-Sender: cy@cwsent.com X-URL: http://www.cschubert.com/ To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org Subject: Re: git: 9c4a120c36bf - main - sysutils/nut*: Add upslog support for multiple UPSs In-reply-to: <202208301811.27UIBus9084236@gitrepo.freebsd.org> References: <202208301811.27UIBus9084236@gitrepo.freebsd.org> Comments: In-reply-to Cy Schubert message dated "Tue, 30 Aug 2022 18:11:56 +0000." List-Id: Commit messages for all branches of the ports repository List-Archive: https://lists.freebsd.org/archives/dev-commits-ports-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-ports-all@freebsd.org X-BeenThere: dev-commits-ports-all@freebsd.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Date: Tue, 30 Aug 2022 13:15:28 -0700 Message-Id: <20220830201528.CB318293@slippy.cwsent.com> X-CMAE-Envelope: MS4xfHYymeGgTlt6yJ5Z9aRObSAKon0K7lGOiAq98pnz5rvnPcRSI9inmHm0inl9gNq2mf8RZEvtqnj5YJnuPmehdRp9iRtfMwpJIzlFHB/gxhvrRD8Wiee6 2FbS/qhrV5LEoSJIn9nwUtlY+TpHvfb5lMOjEIf3OBRQGKWlYSWTpKSAQrEjozvaXHZStL8mntiiC3ApmoGC5ge7eZMjd2cubJdDOXG2IIWp6fnNk0bq4E/3 yT0LTSEztN+C8k5zxiuuM3Wyx6x9vPHo49bqa7WF+i1xtB5cs3YHkTgbr5ZAiicjZZkhSQA9fUS6zXRtdlSJEg== X-Rspamd-Queue-Id: 4MHJTH63LFz3WDS X-Spamd-Bar: - Authentication-Results: mx1.freebsd.org; dkim=none; dmarc=none; spf=none (mx1.freebsd.org: domain of cy.schubert@cschubert.com has no SPF policy when checking 3.97.99.33) smtp.mailfrom=cy.schubert@cschubert.com X-Spamd-Result: default: False [-1.80 / 15.00]; AUTH_NA(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; NEURAL_HAM_MEDIUM(-1.00)[-1.000]; NEURAL_HAM_SHORT(-1.00)[-0.999]; MV_CASE(0.50)[]; RCVD_IN_DNSWL_MED(-0.20)[3.97.99.33:from]; MIME_GOOD(-0.10)[text/plain]; MIME_TRACE(0.00)[0:+]; R_SPF_NA(0.00)[no SPF record]; MLMMJ_DEST(0.00)[dev-commits-ports-main@freebsd.org,dev-commits-ports-all@freebsd.org]; FROM_EQ_ENVFROM(0.00)[]; R_DKIM_NA(0.00)[]; DMARC_NA(0.00)[cschubert.com: no valid DMARC record]; HAS_REPLYTO(0.00)[Cy.Schubert@cschubert.com]; ARC_NA(0.00)[]; REPLYTO_EQ_FROM(0.00)[]; RCVD_COUNT_FIVE(0.00)[5]; RCVD_VIA_SMTP_AUTH(0.00)[]; ASN(0.00)[asn:16509, ipnet:3.96.0.0/15, country:US]; FROM_HAS_DN(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; RCPT_COUNT_THREE(0.00)[3]; TO_DN_NONE(0.00)[]; RCVD_TLS_LAST(0.00)[] X-ThisMailContainsUnwantedMimeParts: N In message <202208301811.27UIBus9084236@gitrepo.freebsd.org>, Cy Schubert write s: > The branch main has been updated by cy: > > URL: https://cgit.FreeBSD.org/ports/commit/?id=9c4a120c36bfb61a307d04c843eeda > 4f3c43cf4c > > commit 9c4a120c36bfb61a307d04c843eeda4f3c43cf4c > Author: Cy Schubert > AuthorDate: 2022-08-30 05:27:41 +0000 > Commit: Cy Schubert > CommitDate: 2022-08-30 18:04:26 +0000 > > sysutils/nut*: Add upslog support for multiple UPSs > > upslog is a utility that logs UPS status at regular intervals, specified > by the -i option. Unfortunately upslog supports only on UPS. For sites > that need to monitor multiple UPSs the options are to cobble an rc script > for each or doctor up the nut_upslog.in script to support cloning of the > script. Unfortunately an rc script capable of being cloned would become > the source of more PRs and would require significanly more tehcnical > documentation that by itself might become confusing for the average > system administrator. > > Therefore a new -m option is added to support multiple UPSs using the > same invocation of upslog. The patch parses a new -m option and using a > single connection to upsd, queries it for stats about multiple UPSs. > > An rc.conf exemple of how to use this new feature: > nut_upslog_flags="-p /var/db/nut/upslog.pid -m ups1@localhost,/var/log/nu > t\ > /ups1.log -m ups2@localhost,/var/log/nut/ups2.log" > > PR: 265963 > Reported by: vvd@unislabs.com > --- > sysutils/nut-devel/Makefile | 2 +- > sysutils/nut-devel/files/patch-clients_upslog.c | 291 +++++++++++++++++++ > ++ > sysutils/nut-devel/files/patch-docs_man_upslog.txt | 14 + > sysutils/nut/Makefile | 2 +- > sysutils/nut/files/patch-clients_upslog.c | 291 +++++++++++++++++++ > ++ > sysutils/nut/files/patch-docs_man_upslog.8 | 16 ++ > sysutils/nut/files/patch-docs_man_upslog.txt | 14 + > 7 files changed, 628 insertions(+), 2 deletions(-) > > diff --git a/sysutils/nut-devel/Makefile b/sysutils/nut-devel/Makefile > index b3d796bfec97..39a576b32ea6 100644 > --- a/sysutils/nut-devel/Makefile > +++ b/sysutils/nut-devel/Makefile > @@ -1,6 +1,6 @@ > PORTNAME= nut > PORTVERSION= ${NUT_COMMIT_DATE} > -PORTREVISION= 2 > +PORTREVISION= 3 > CATEGORIES= sysutils > PKGNAMESUFFIX= -devel > # MASTER_SITES= http://www.networkupstools.org/source/${PORTVERSION:R}/ > diff --git a/sysutils/nut-devel/files/patch-clients_upslog.c b/sysutils/nut-d > evel/files/patch-clients_upslog.c > new file mode 100644 > index 000000000000..c06eaf45e992 > --- /dev/null > +++ b/sysutils/nut-devel/files/patch-clients_upslog.c > @@ -0,0 +1,291 @@ > +--- clients/upslog.c.orig 2022-08-29 22:20:20.954722000 -0700 > ++++ clients/upslog.c 2022-08-29 22:21:18.844395000 -0700 > +@@ -32,6 +32,10 @@ > + */ > + > + #include "common.h" > ++#include > ++#include > ++#include > ++#include > + #include "nut_platform.h" > + #include "upsclient.h" > + > +@@ -41,32 +45,49 @@ > + #include "upslog.h" > + > + static int reopen_flag = 0, exit_flag = 0; > +- static uint16_t port; > +- static char *upsname, *hostname; > +- static UPSCONN_t ups; > ++ static char *upsname; > ++ static UPSCONN_t *ups; > + > +- static FILE *logfile; > +- static const char *logfn, *monhost; > ++ static char *logfn, *monhost; > + static sigset_t nut_upslog_sigmask; > + static char logbuffer[LARGEBUF], *logformat; > + > + static flist_t *fhead = NULL; > ++ struct monhost_ups { > ++ char *monhost; > ++ char *logfn; > ++ char *upsname; > ++ char *hostname; > ++ uint16_t port; > ++ UPSCONN_t *ups; > ++ FILE *logfile; > ++ struct monhost_ups *next; > ++ }; > ++ static struct monhost_ups *monhost_ups_anchor = NULL; > ++ static struct monhost_ups *monhost_ups_current = NULL; > ++ static struct monhost_ups *monhost_ups_prev = NULL; > + > ++ > + #define DEFAULT_LOGFORMAT "%TIME @Y@m@d @H@M@S% %VAR battery.charge% " \ > + "%VAR input.voltage% %VAR ups.load% [%VAR ups.status%] " \ > + "%VAR ups.temperature% %VAR input.frequency%" > + > + static void reopen_log(void) > + { > +- if (logfile == stdout) { > +- upslogx(LOG_INFO, "logging to stdout"); > +- return; > +- } > ++ for (monhost_ups_current = monhost_ups_anchor; > ++ monhost_ups_current != NULL; > ++ monhost_ups_current = monhost_ups_current->next) { > ++ if (monhost_ups_current->logfile == stdout) { > ++ upslogx(LOG_INFO, "logging to stdout"); > ++ return; > ++ } > + > +- fclose(logfile); > +- logfile = fopen(logfn, "a"); > +- if (logfile == NULL) > +- fatal_with_errno(EXIT_FAILURE, "could not reopen logfile %s", l > ogfn); > ++ if ((monhost_ups_current->logfile = freopen( > ++ monhost_ups_current->logfn, "a", > ++ monhost_ups_current->logfile)) == NULL) > ++ fatal_with_errno(EXIT_FAILURE, > ++ "could not reopen logfile %s", logfn); > ++ } > + } > + > + static void set_reopen_flag(int sig) > +@@ -131,6 +152,8 @@ > + printf(" -p - Base name for PID file (defaults to \"%s\")\n > ", prog); > + printf(" -s - Monitor UPS - @[:] > \n"); > + printf(" - Example: -s myups@server\n"); > ++ printf(" -m - Monitor UPS \n"); > ++ printf(" - Example: -m myups@server,/var/log/myups.log\n > "); > + printf(" -u - Switch to if started as root\n"); > + > + printf("\n"); > +@@ -215,7 +238,7 @@ > + query[2] = var; > + numq = 3; > + > +- ret = upscli_get(&ups, numq, query, &numa, &answer); > ++ ret = upscli_get(ups, numq, query, &numa, &answer); > + > + if ((ret < 0) || (numa < numq)) { > + snprintfcat(logbuffer, sizeof(logbuffer), "NA"); > +@@ -368,7 +391,7 @@ > + } > + > + /* go through the list of functions and call them in order */ > +-static void run_flist(void) > ++static void run_flist(struct monhost_ups *monhost_ups_print) > + { > + flist_t *tmp; > + > +@@ -382,8 +405,8 @@ > + tmp = tmp->next; > + } > + > +- fprintf(logfile, "%s\n", logbuffer); > +- fflush(logfile); > ++ fprintf(monhost_ups_print->logfile, "%s\n", logbuffer); > ++ fflush(monhost_ups_print->logfile); > + } > + > + /* -s > +@@ -396,6 +419,7 @@ > + int main(int argc, char **argv) > + { > + int interval = 30, i, foreground = -1; > ++ size_t monhost_len = 0; > + const char *prog = xbasename(argv[0]); > + time_t now, nextpoll = 0; > + const char *user = NULL; > +@@ -407,7 +431,7 @@ > + > + printf("Network UPS Tools %s %s\n", prog, UPS_VERSION); > + > +- while ((i = getopt(argc, argv, "+hs:l:i:f:u:Vp:FB")) != -1) { > ++ while ((i = getopt(argc, argv, "+hs:l:i:f:u:Vp:FBm:")) != -1) { > + switch(i) { > + case 'h': > + help(prog); > +@@ -415,6 +439,33 @@ > + break; > + #endif > + > ++ case 'm': { /* var scope */ > ++ char *m_arg, *s; > ++ > ++ monhost_ups_prev = monhost_ups_current; > ++ monhost_ups_current = xmalloc(sizeof(st > ruct monhost_ups)); > ++ if (monhost_ups_anchor == NULL) > ++ monhost_ups_anchor = monhost_up > s_current; > ++ else > ++ monhost_ups_prev->next = monhos > t_ups_current; > ++ monhost_ups_current->next = NULL; > ++ monhost_len++; > ++ > ++ /* Be sure to not mangle original optar > g, nor rely on its longevity */ > ++ s = xstrdup(optarg); > ++ m_arg = s; > ++ monhost_ups_current->monhost = xstrdup( > strsep(&m_arg, ",")); > ++ if (!m_arg) > ++ fatalx(EXIT_FAILURE, "Argument > '-m upsspec,logfile' requires exactly 2 components in the tuple"); > ++ monhost_ups_current->logfn = xstrdup(st > rsep(&m_arg, ",")); > ++ if (m_arg) /* Had a third comma - also > unexpected! */ > ++ fatalx(EXIT_FAILURE, "Argument > '-m upsspec,logfile' requires exactly 2 components in the tuple"); > ++ if (upscli_splitname(monhost_ups_curren > t->monhost, &(monhost_ups_current->upsname), &(monhost_ups_current->hostname) > , &(monhost_ups_current->port)) != 0) { > ++ fatalx(EXIT_FAILURE, "Error: in > valid UPS definition. Required format: upsname[@hostname[:port]]\n"); > ++ } > ++ free(s); > ++ } /* var scope */ > ++ break; > + case 's': > + monhost = optarg; > + break; > +@@ -479,42 +530,59 @@ > + snprintfcat(logformat, LARGEBUF, "%s ", argv[i]); > + } > + > +- if (!monhost) > +- fatalx(EXIT_FAILURE, "No UPS defined for monitoring - use -s ystem>"); > ++ if (monhost_ups_anchor == NULL) { > ++ if (monhost) { > ++ monhost_ups_current = xmalloc(sizeof(struct monhost_ups > )); > ++ monhost_ups_anchor = monhost_ups_current; > ++ monhost_ups_current->next = NULL; > ++ monhost_ups_current->monhost = monhost; > ++ monhost_len=1; > ++ } else { > ++ fatalx(EXIT_FAILURE, "No UPS defined for monitoring - u > se -s "); > ++ } > + > +- if (!logfn) > +- fatalx(EXIT_FAILURE, "No filename defined for logging - use -l > "); > ++ if (logfn) > ++ monhost_ups_current->logfn = logfn; > ++ else > ++ fatalx(EXIT_FAILURE, "No filename defined for logging - > use -l "); > ++ } > + > + /* shouldn't happen */ > + if (!logformat) > + fatalx(EXIT_FAILURE, "No format defined - but this should be im > possible"); > + > +- printf("logging status of %s to %s (%is intervals)\n", > +- monhost, logfn, interval); > ++ for (monhost_ups_current = monhost_ups_anchor; > ++ monhost_ups_current != NULL; > ++ monhost_ups_current = monhost_ups_current->next) { > ++ printf("logging status of %s to %s (%is intervals)\n", > ++ monhost_ups_current->monhost, monhost_ups_current->logf > n, interval); > ++ if (upscli_splitname(monhost_ups_current->monhost, &(monhost_up > s_current->upsname), &(monhost_ups_current->hostname), &(monhost_ups_current- > >port)) != 0) { > ++ fatalx(EXIT_FAILURE, "Error: invalid UPS definition. R > equired format: upsname[@hostname[:port]]\n"); > ++ } > + > +- if (upscli_splitname(monhost, &upsname, &hostname, &port) != 0) { > +- fatalx(EXIT_FAILURE, "Error: invalid UPS definition. Required > format: upsname[@hostname[:port]]\n"); > +- } > ++ monhost_ups_current->ups = xmalloc(sizeof(UPSCONN_t)); > ++ if (upscli_connect(monhost_ups_current->ups, monhost_ups_curren > t->hostname, monhost_ups_current->port, UPSCLI_CONN_TRYSSL) < 0) > ++ fprintf(stderr, "Warning: initial connect failed: %s\n" > , > ++ upscli_strerror(monhost_ups_current->ups)); > + > +- if (upscli_connect(&ups, hostname, port, UPSCLI_CONN_TRYSSL) < 0) > +- fprintf(stderr, "Warning: initial connect failed: %s\n", > +- upscli_strerror(&ups)); > ++ if (strcmp(monhost_ups_current->logfn, "-") == 0) > ++ monhost_ups_current->logfile = stdout; > ++ else > ++ monhost_ups_current->logfile = fopen(monhost_ups_curren > t->logfn, "a"); > + > +- if (strcmp(logfn, "-") == 0) > +- logfile = stdout; > +- else > +- logfile = fopen(logfn, "a"); > ++ if (monhost_ups_current->logfile == NULL) > ++ fatal_with_errno(EXIT_FAILURE, "could not open logfile > %s", logfn); > + > +- if (logfile == NULL) > +- fatal_with_errno(EXIT_FAILURE, "could not open logfile %s", log > fn); > ++ } > + > ++ > + /* now drop root if we have it */ > + new_uid = get_user_pwent(user); > + > + open_syslog(prog); > + > + if (foreground < 0) { > +- if (logfile == stdout) { > ++ if (monhost_ups_anchor->logfile == stdout) { > + foreground = 1; > + } else { > + foreground = 0; > +@@ -552,25 +620,35 @@ > + reopen_flag = 0; > + } > + > +- /* reconnect if necessary */ > +- if (upscli_fd(&ups) < 0) { > +- upscli_connect(&ups, hostname, port, 0); > +- } > ++ for (monhost_ups_current = monhost_ups_anchor; > ++ monhost_ups_current != NULL; > ++ monhost_ups_current = monhost_ups_current->next) { > ++ ups = monhost_ups_current->ups; /* XXX Not ideal */ > ++ upsname = monhost_ups_current->upsname; /* XXX Not idea > l */ > ++ /* reconnect if necessary */ > ++ if (upscli_fd(ups) < 0) { > ++ upscli_connect(ups, monhost_ups_current->hostna > me, monhost_ups_current->port, 0); > ++ } > + > +- run_flist(); > ++ run_flist(monhost_ups_current); > + > +- /* don't keep connection open if we don't intend to use it shor > tly */ > +- if (interval > 30) { > +- upscli_disconnect(&ups); > ++ /* don't keep connection open if we don't intend to use > it shortly */ > ++ if (interval > 30) { > ++ upscli_disconnect(ups); > ++ } > + } > + } > + > + upslogx(LOG_INFO, "Signal %d: exiting", exit_flag); > ++ for (monhost_ups_current = monhost_ups_anchor; > ++ monhost_ups_current != NULL; > ++ monhost_ups_current = monhost_ups_current->next) { > + > +- if (logfile != stdout) > +- fclose(logfile); > ++ if (monhost_ups_current->logfile != stdout) > ++ fclose(monhost_ups_current->logfile); > + > +- upscli_disconnect(&ups); > ++ upscli_disconnect(monhost_ups_current->ups); > ++ } > + > + exit(EXIT_SUCCESS); > + } > diff --git a/sysutils/nut-devel/files/patch-docs_man_upslog.txt b/sysutils/nu > t-devel/files/patch-docs_man_upslog.txt > new file mode 100644 > index 000000000000..9e139ccb6105 > --- /dev/null > +++ b/sysutils/nut-devel/files/patch-docs_man_upslog.txt > @@ -0,0 +1,14 @@ > +--- docs/man/upslog.txt.orig 2022-08-30 05:56:15.850373000 -0700 > ++++ docs/man/upslog.txt 2022-08-30 06:01:45.955996000 -0700 > +@@ -78,6 +78,11 @@ > + Monitor this UPS. The format for this option is > + +upsname[@hostname[:port]]+. The default hostname is "localhost". > + > ++*-m* 'tuple':: > ++Monitor multiple UPSs. The format for this option is a tuple of > ++ups and logfile separated by commas. An example would be: > ++`upsname@hostname:9999,/var/log/nut/cps.log` > ++ > + *-u* 'username':: > + > + If started as root, upslog will *setuid*(2) to the user id > diff --git a/sysutils/nut/Makefile b/sysutils/nut/Makefile > index 1bad77416107..30eb3474f0c3 100644 > --- a/sysutils/nut/Makefile > +++ b/sysutils/nut/Makefile > @@ -1,6 +1,6 @@ > PORTNAME= nut > PORTVERSION= 2.8.0 > -PORTREVISION= 10 > +PORTREVISION= 11 > CATEGORIES= sysutils > MASTER_SITES= http://www.networkupstools.org/source/${PORTVERSION:R}/ > > diff --git a/sysutils/nut/files/patch-clients_upslog.c b/sysutils/nut/files/p > atch-clients_upslog.c > new file mode 100644 > index 000000000000..bcebe5bba28c > --- /dev/null > +++ b/sysutils/nut/files/patch-clients_upslog.c > @@ -0,0 +1,291 @@ > +--- clients/upslog.c.orig 2022-08-29 22:20:14.342137000 -0700 > ++++ clients/upslog.c 2022-08-29 22:21:10.934419000 -0700 > +@@ -32,6 +32,10 @@ > + */ > + > + #include "common.h" > ++#include > ++#include > ++#include > ++#include > + #include "nut_platform.h" > + #include "upsclient.h" > + > +@@ -41,32 +45,49 @@ > + #include "upslog.h" > + > + static int reopen_flag = 0, exit_flag = 0; > +- static uint16_t port; > +- static char *upsname, *hostname; > +- static UPSCONN_t ups; > ++ static char *upsname; > ++ static UPSCONN_t *ups; > + > +- static FILE *logfile; > +- static const char *logfn, *monhost; > ++ static char *logfn, *monhost; > + static sigset_t nut_upslog_sigmask; > + static char logbuffer[LARGEBUF], *logformat; > + > + static flist_t *fhead = NULL; > ++ struct monhost_ups { > ++ char *monhost; > ++ char *logfn; > ++ char *upsname; > ++ char *hostname; > ++ uint16_t port; > ++ UPSCONN_t *ups; > ++ FILE *logfile; > ++ struct monhost_ups *next; > ++ }; > ++ static struct monhost_ups *monhost_ups_anchor = NULL; > ++ static struct monhost_ups *monhost_ups_current = NULL; > ++ static struct monhost_ups *monhost_ups_prev = NULL; > + > ++ > + #define DEFAULT_LOGFORMAT "%TIME @Y@m@d @H@M@S% %VAR battery.charge% " \ > + "%VAR input.voltage% %VAR ups.load% [%VAR ups.status%] " \ > + "%VAR ups.temperature% %VAR input.frequency%" > + > + static void reopen_log(void) > + { > +- if (logfile == stdout) { > +- upslogx(LOG_INFO, "logging to stdout"); > +- return; > +- } > ++ for (monhost_ups_current = monhost_ups_anchor; > ++ monhost_ups_current != NULL; > ++ monhost_ups_current = monhost_ups_current->next) { > ++ if (monhost_ups_current->logfile == stdout) { > ++ upslogx(LOG_INFO, "logging to stdout"); > ++ return; > ++ } > + > +- fclose(logfile); > +- logfile = fopen(logfn, "a"); > +- if (logfile == NULL) > +- fatal_with_errno(EXIT_FAILURE, "could not reopen logfile %s", l > ogfn); > ++ if ((monhost_ups_current->logfile = freopen( > ++ monhost_ups_current->logfn, "a", > ++ monhost_ups_current->logfile)) == NULL) > ++ fatal_with_errno(EXIT_FAILURE, > ++ "could not reopen logfile %s", logfn); > ++ } > + } > + > + static void set_reopen_flag(int sig) > +@@ -131,6 +152,8 @@ > + printf(" -p - Base name for PID file (defaults to \"%s\")\n > ", prog); > + printf(" -s - Monitor UPS - @[:] > \n"); > + printf(" - Example: -s myups@server\n"); > ++ printf(" -m - Monitor UPS \n"); > ++ printf(" - Example: -m myups@server,/var/log/myups.log\n > "); > + printf(" -u - Switch to if started as root\n"); > + > + printf("\n"); > +@@ -215,7 +238,7 @@ > + query[2] = var; > + numq = 3; > + > +- ret = upscli_get(&ups, numq, query, &numa, &answer); > ++ ret = upscli_get(ups, numq, query, &numa, &answer); > + > + if ((ret < 0) || (numa < numq)) { > + snprintfcat(logbuffer, sizeof(logbuffer), "NA"); > +@@ -368,7 +391,7 @@ > + } > + > + /* go through the list of functions and call them in order */ > +-static void run_flist(void) > ++static void run_flist(struct monhost_ups *monhost_ups_print) > + { > + flist_t *tmp; > + > +@@ -382,8 +405,8 @@ > + tmp = tmp->next; > + } > + > +- fprintf(logfile, "%s\n", logbuffer); > +- fflush(logfile); > ++ fprintf(monhost_ups_print->logfile, "%s\n", logbuffer); > ++ fflush(monhost_ups_print->logfile); > + } > + > + /* -s > +@@ -396,6 +419,7 @@ > + int main(int argc, char **argv) > + { > + int interval = 30, i, foreground = -1; > ++ size_t monhost_len = 0; > + const char *prog = xbasename(argv[0]); > + time_t now, nextpoll = 0; > + const char *user = NULL; > +@@ -407,7 +431,7 @@ > + > + printf("Network UPS Tools %s %s\n", prog, UPS_VERSION); > + > +- while ((i = getopt(argc, argv, "+hs:l:i:f:u:Vp:FB")) != -1) { > ++ while ((i = getopt(argc, argv, "+hs:l:i:f:u:Vp:FBm:")) != -1) { > + switch(i) { > + case 'h': > + help(prog); > +@@ -415,6 +439,33 @@ > + break; > + #endif > + > ++ case 'm': { /* var scope */ > ++ char *m_arg, *s; > ++ > ++ monhost_ups_prev = monhost_ups_current; > ++ monhost_ups_current = xmalloc(sizeof(st > ruct monhost_ups)); > ++ if (monhost_ups_anchor == NULL) > ++ monhost_ups_anchor = monhost_up > s_current; > ++ else > ++ monhost_ups_prev->next = monhos > t_ups_current; > ++ monhost_ups_current->next = NULL; > ++ monhost_len++; > ++ > ++ /* Be sure to not mangle original optar > g, nor rely on its longevity */ > ++ s = xstrdup(optarg); > ++ m_arg = s; > ++ monhost_ups_current->monhost = xstrdup( > strsep(&m_arg, ",")); > ++ if (!m_arg) > ++ fatalx(EXIT_FAILURE, "Argument > '-m upsspec,logfile' requires exactly 2 components in the tuple"); > ++ monhost_ups_current->logfn = xstrdup(st > rsep(&m_arg, ",")); > ++ if (m_arg) /* Had a third comma - also > unexpected! */ > ++ fatalx(EXIT_FAILURE, "Argument > '-m upsspec,logfile' requires exactly 2 components in the tuple"); > ++ if (upscli_splitname(monhost_ups_curren > t->monhost, &(monhost_ups_current->upsname), &(monhost_ups_current->hostname) > , &(monhost_ups_current->port)) != 0) { > ++ fatalx(EXIT_FAILURE, "Error: in > valid UPS definition. Required format: upsname[@hostname[:port]]\n"); > ++ } > ++ free(s); > ++ } /* var scope */ > ++ break; > + case 's': > + monhost = optarg; > + break; > +@@ -479,42 +530,59 @@ > + snprintfcat(logformat, LARGEBUF, "%s ", argv[i]); > + } > + > +- if (!monhost) > +- fatalx(EXIT_FAILURE, "No UPS defined for monitoring - use -s ystem>"); > ++ if (monhost_ups_anchor == NULL) { > ++ if (monhost) { > ++ monhost_ups_current = xmalloc(sizeof(struct monhost_ups > )); > ++ monhost_ups_anchor = monhost_ups_current; > ++ monhost_ups_current->next = NULL; > ++ monhost_ups_current->monhost = monhost; > ++ monhost_len=1; > ++ } else { > ++ fatalx(EXIT_FAILURE, "No UPS defined for monitoring - u > se -s "); > ++ } > + > +- if (!logfn) > +- fatalx(EXIT_FAILURE, "No filename defined for logging - use -l > "); > ++ if (logfn) > ++ monhost_ups_current->logfn = logfn; > ++ else > ++ fatalx(EXIT_FAILURE, "No filename defined for logging - > use -l "); > ++ } > + > + /* shouldn't happen */ > + if (!logformat) > + fatalx(EXIT_FAILURE, "No format defined - but this should be im > possible"); > + > +- printf("logging status of %s to %s (%is intervals)\n", > +- monhost, logfn, interval); > ++ for (monhost_ups_current = monhost_ups_anchor; > ++ monhost_ups_current != NULL; > ++ monhost_ups_current = monhost_ups_current->next) { > ++ printf("logging status of %s to %s (%is intervals)\n", > ++ monhost_ups_current->monhost, monhost_ups_current->logf > n, interval); > ++ if (upscli_splitname(monhost_ups_current->monhost, &(monhost_up > s_current->upsname), &(monhost_ups_current->hostname), &(monhost_ups_current- > >port)) != 0) { > ++ fatalx(EXIT_FAILURE, "Error: invalid UPS definition. R > equired format: upsname[@hostname[:port]]\n"); > ++ } > + > +- if (upscli_splitname(monhost, &upsname, &hostname, &port) != 0) { > +- fatalx(EXIT_FAILURE, "Error: invalid UPS definition. Required > format: upsname[@hostname[:port]]\n"); > +- } > ++ monhost_ups_current->ups = xmalloc(sizeof(UPSCONN_t)); > ++ if (upscli_connect(monhost_ups_current->ups, monhost_ups_curren > t->hostname, monhost_ups_current->port, UPSCLI_CONN_TRYSSL) < 0) > ++ fprintf(stderr, "Warning: initial connect failed: %s\n" > , > ++ upscli_strerror(monhost_ups_current->ups)); > + > +- if (upscli_connect(&ups, hostname, port, UPSCLI_CONN_TRYSSL) < 0) > +- fprintf(stderr, "Warning: initial connect failed: %s\n", > +- upscli_strerror(&ups)); > ++ if (strcmp(monhost_ups_current->logfn, "-") == 0) > ++ monhost_ups_current->logfile = stdout; > ++ else > ++ monhost_ups_current->logfile = fopen(monhost_ups_curren > t->logfn, "a"); > + > +- if (strcmp(logfn, "-") == 0) > +- logfile = stdout; > +- else > +- logfile = fopen(logfn, "a"); > ++ if (monhost_ups_current->logfile == NULL) > ++ fatal_with_errno(EXIT_FAILURE, "could not open logfile > %s", logfn); > + > +- if (logfile == NULL) > +- fatal_with_errno(EXIT_FAILURE, "could not open logfile %s", log > fn); > ++ } > + > ++ > + /* now drop root if we have it */ > + new_uid = get_user_pwent(user); > + > + open_syslog(prog); > + > + if (foreground < 0) { > +- if (logfile == stdout) { > ++ if (monhost_ups_anchor->logfile == stdout) { > + foreground = 1; > + } else { > + foreground = 0; > +@@ -552,25 +620,35 @@ > + reopen_flag = 0; > + } > + > +- /* reconnect if necessary */ > +- if (upscli_fd(&ups) < 0) { > +- upscli_connect(&ups, hostname, port, 0); > +- } > ++ for (monhost_ups_current = monhost_ups_anchor; > ++ monhost_ups_current != NULL; > ++ monhost_ups_current = monhost_ups_current->next) { > ++ ups = monhost_ups_current->ups; /* XXX Not ideal */ > ++ upsname = monhost_ups_current->upsname; /* XXX Not idea > l */ > ++ /* reconnect if necessary */ > ++ if (upscli_fd(ups) < 0) { > ++ upscli_connect(ups, monhost_ups_current->hostna > me, monhost_ups_current->port, 0); > ++ } > + > +- run_flist(); > ++ run_flist(monhost_ups_current); > + > +- /* don't keep connection open if we don't intend to use it shor > tly */ > +- if (interval > 30) { > +- upscli_disconnect(&ups); > ++ /* don't keep connection open if we don't intend to use > it shortly */ > ++ if (interval > 30) { > ++ upscli_disconnect(ups); > ++ } > + } > + } > + > + upslogx(LOG_INFO, "Signal %d: exiting", exit_flag); > ++ for (monhost_ups_current = monhost_ups_anchor; > ++ monhost_ups_current != NULL; > ++ monhost_ups_current = monhost_ups_current->next) { > + > +- if (logfile != stdout) > +- fclose(logfile); > ++ if (monhost_ups_current->logfile != stdout) > ++ fclose(monhost_ups_current->logfile); > + > +- upscli_disconnect(&ups); > ++ upscli_disconnect(monhost_ups_current->ups); > ++ } > + > + exit(EXIT_SUCCESS); > + } > diff --git a/sysutils/nut/files/patch-docs_man_upslog.8 b/sysutils/nut/files/ > patch-docs_man_upslog.8 > new file mode 100644 > index 000000000000..37b1379ca6bf > --- /dev/null > +++ b/sysutils/nut/files/patch-docs_man_upslog.8 > @@ -0,0 +1,16 @@ > +--- docs/man/upslog.8.orig 2022-08-30 05:56:02.734873000 -0700 > ++++ docs/man/upslog.8 2022-08-30 06:09:47.928348000 -0700 > +@@ -134,6 +134,13 @@ > + upsname[@hostname[:port]]\&. The default hostname is "localhost"\&. > + .RE > + .PP > ++\fB\-m\fR \fItuple\fR > ++.RS 4 > ++Monitor multiple UPSs\&. The format for this option is a tuple of > ++ups and logfile separated by commas\&. An example would be: > ++upsname@hostname:9999,/var/log/nut/cps.log > ++.RE > ++.PP > + \fB\-u\fR \fIusername\fR > + .RS 4 > + If started as root, upslog will > diff --git a/sysutils/nut/files/patch-docs_man_upslog.txt b/sysutils/nut/file > s/patch-docs_man_upslog.txt > new file mode 100644 > index 000000000000..e26d91e2d5f2 > --- /dev/null > +++ b/sysutils/nut/files/patch-docs_man_upslog.txt > @@ -0,0 +1,14 @@ > +--- docs/man/upslog.txt.orig 2022-08-30 05:56:02.761764000 -0700 > ++++ docs/man/upslog.txt 2022-08-30 06:04:33.428455000 -0700 > +@@ -78,6 +78,11 @@ > + Monitor this UPS. The format for this option is > + +upsname[@hostname[:port]]+. The default hostname is "localhost". > + > ++*-m* 'tuple':: > ++Monitor multiple UPSs. The format for this option is a tuple of > ++ups and logfile separated by commas. An example would be: > ++`upsname@hostname:9999,/var/log/nut/cps.log` > ++ > + *-u* 'username':: > + > + If started as root, upslog will *setuid*(2) to the user id A pull request implementing this has been sent to our upstream. -- Cheers, Cy Schubert FreeBSD UNIX: Web: http://www.FreeBSD.org NTP: Web: https://nwtime.org e^(i*pi)+1=0