Added
Link Here
|
1 |
--- clients/upslog.c.orig 2022-08-26 07:34:30.078268000 -0700 |
2 |
+++ clients/upslog.c 2022-08-26 07:35:31.267936000 -0700 |
3 |
@@ -32,6 +32,10 @@ |
4 |
*/ |
5 |
|
6 |
#include "common.h" |
7 |
+#include <signal.h> |
8 |
+#include <unistd.h> |
9 |
+#include <sys/types.h> |
10 |
+#include <sys/wait.h> |
11 |
#include "nut_platform.h" |
12 |
#include "upsclient.h" |
13 |
|
14 |
@@ -41,17 +45,32 @@ |
15 |
#include "upslog.h" |
16 |
|
17 |
static int reopen_flag = 0, exit_flag = 0; |
18 |
+ static int wait_status; |
19 |
static uint16_t port; |
20 |
static char *upsname, *hostname; |
21 |
static UPSCONN_t ups; |
22 |
|
23 |
static FILE *logfile; |
24 |
- static const char *logfn, *monhost; |
25 |
+ static char *logfn, *monhost; |
26 |
static sigset_t nut_upslog_sigmask; |
27 |
static char logbuffer[LARGEBUF], *logformat; |
28 |
|
29 |
static flist_t *fhead = NULL; |
30 |
+ struct monhost_child { |
31 |
+ char *monhost; |
32 |
+ char *logfn; |
33 |
+ char *pidfilebase; |
34 |
+ pid_t pid; |
35 |
+ struct monhost_child *next; |
36 |
+ }; |
37 |
+ static struct monhost_child *monhost_child_anchor = NULL; |
38 |
+ static struct monhost_child *monhost_child_current = NULL; |
39 |
+ static struct monhost_child *monhost_child_prev = NULL; |
40 |
+ static struct sigaction upslog_sigaction; |
41 |
+ static int trapped_signals[] = { SIGINT, SIGTERM, SIGCHLD }; |
42 |
+ static pid_t daemon_pid; |
43 |
|
44 |
+ |
45 |
#define DEFAULT_LOGFORMAT "%TIME @Y@m@d @H@M@S% %VAR battery.charge% " \ |
46 |
"%VAR input.voltage% %VAR ups.load% [%VAR ups.status%] " \ |
47 |
"%VAR ups.temperature% %VAR input.frequency%" |
48 |
@@ -131,6 +150,8 @@ |
49 |
printf(" -p <pidbase> - Base name for PID file (defaults to \"%s\")\n", prog); |
50 |
printf(" -s <ups> - Monitor UPS <ups> - <upsname>@<host>[:<port>]\n"); |
51 |
printf(" - Example: -s myups@server\n"); |
52 |
+ printf(" -m <tuple> - Monitor UPS <ups,logfile,pidfile>,\n"); |
53 |
+ printf(" - Example: -m myups@server,/var/log/myups.log,/var/run/myups.pid\n"); |
54 |
printf(" -u <user> - Switch to <user> if started as root\n"); |
55 |
|
56 |
printf("\n"); |
57 |
@@ -393,9 +414,24 @@ |
58 |
* -u <username> |
59 |
*/ |
60 |
|
61 |
+static void term_handler(int signo) |
62 |
+{ |
63 |
+ if (signo != SIGCHLD && monhost_child_anchor != NULL) { |
64 |
+ for (monhost_child_current = monhost_child_anchor; |
65 |
+ monhost_child_current != NULL; |
66 |
+ monhost_child_current = monhost_child_current->next |
67 |
+ ) { |
68 |
+ kill(monhost_child_current->pid, signo); |
69 |
+ } |
70 |
+ |
71 |
+ fatalx(EXIT_FAILURE, "Killed by user"); |
72 |
+ } |
73 |
+} |
74 |
+ |
75 |
int main(int argc, char **argv) |
76 |
{ |
77 |
int interval = 30, i, foreground = -1; |
78 |
+ size_t monhost_len = 0, mh; |
79 |
const char *prog = xbasename(argv[0]); |
80 |
time_t now, nextpoll = 0; |
81 |
const char *user = NULL; |
82 |
@@ -407,7 +443,7 @@ |
83 |
|
84 |
printf("Network UPS Tools %s %s\n", prog, UPS_VERSION); |
85 |
|
86 |
- while ((i = getopt(argc, argv, "+hs:l:i:f:u:Vp:FB")) != -1) { |
87 |
+ while ((i = getopt(argc, argv, "+hs:l:i:f:u:Vp:FBm:")) != -1) { |
88 |
switch(i) { |
89 |
case 'h': |
90 |
help(prog); |
91 |
@@ -415,6 +451,33 @@ |
92 |
break; |
93 |
#endif |
94 |
|
95 |
+ case 'm': { /* var scope */ |
96 |
+ char *m_arg, *s; |
97 |
+ |
98 |
+ monhost_child_prev = monhost_child_current; |
99 |
+ monhost_child_current = xmalloc(sizeof(struct monhost_child)); |
100 |
+ if (monhost_child_anchor == NULL) |
101 |
+ monhost_child_anchor = monhost_child_current; |
102 |
+ else |
103 |
+ monhost_child_prev->next = monhost_child_current; |
104 |
+ monhost_child_current->next = NULL; |
105 |
+ monhost_len++; |
106 |
+ |
107 |
+ /* Be sure to not mangle original optarg, nor rely on its longevity */ |
108 |
+ s = xstrdup(optarg); |
109 |
+ m_arg = s; |
110 |
+ monhost_child_current->monhost = xstrdup(strsep(&m_arg, ",")); |
111 |
+ if (!m_arg) |
112 |
+ fatalx(EXIT_FAILURE, "Argument '-m upsspec,logfile,pidfile' requires exactly 3 components in the tuple"); |
113 |
+ monhost_child_current->logfn = xstrdup(strsep(&m_arg, ",")); |
114 |
+ if (!m_arg) |
115 |
+ fatalx(EXIT_FAILURE, "Argument '-m upsspec,logfile,pidfile' requires exactly 3 components in the tuple"); |
116 |
+ monhost_child_current->pidfilebase = xstrdup(strsep(&m_arg, ",")); |
117 |
+ if (m_arg) /* Had a third comma - also unexpected! */ |
118 |
+ fatalx(EXIT_FAILURE, "Argument '-m upsspec,logfile,pidfile' requires exactly 3 components in the tuple"); |
119 |
+ free(s); |
120 |
+ } /* var scope */ |
121 |
+ break; |
122 |
case 's': |
123 |
monhost = optarg; |
124 |
break; |
125 |
@@ -477,6 +540,39 @@ |
126 |
|
127 |
for (i = 3; i < argc; i++) |
128 |
snprintfcat(logformat, LARGEBUF, "%s ", argv[i]); |
129 |
+ } |
130 |
+ |
131 |
+ if (monhost_child_anchor != NULL) { |
132 |
+ if (foreground > 0) |
133 |
+ daemon_pid = 0; |
134 |
+ else |
135 |
+ daemon_pid = fork(); |
136 |
+ if (!daemon_pid) { |
137 |
+ upsdebugx(1,"Forking to log %" PRIuSIZE " devices", monhost_len); |
138 |
+ for (monhost_child_current = monhost_child_anchor; |
139 |
+ monhost_child_current != NULL; |
140 |
+ monhost_child_current = monhost_child_current->next) { |
141 |
+ if ((monhost_child_current->pid = fork()) == 0) { |
142 |
+ monhost = monhost_child_current->monhost; |
143 |
+ logfn = monhost_child_current->logfn; |
144 |
+ pidfilebase = monhost_child_current->pidfilebase; |
145 |
+ foreground = 1; |
146 |
+ break; |
147 |
+ } |
148 |
+ } |
149 |
+ for (mh = 0; mh < sizeof(trapped_signals)/sizeof(trapped_signals[0]); mh++) { |
150 |
+ upslog_sigaction.sa_handler = &term_handler; |
151 |
+ sigfillset(&upslog_sigaction.sa_mask); |
152 |
+ upslog_sigaction.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT; |
153 |
+ sigaction(trapped_signals[mh], &upslog_sigaction, NULL); |
154 |
+ } |
155 |
+ become_user(get_user_pwent(user)); |
156 |
+ writepid(pidfilebase); |
157 |
+ while(wait(&wait_status) > 0); |
158 |
+ exit(EXIT_SUCCESS); |
159 |
+ } else { |
160 |
+ exit(EXIT_SUCCESS); |
161 |
+ } |
162 |
} |
163 |
|
164 |
if (!monhost) |