Merge pull request #2680 from masterwishx/work2471-eco_addon
[networkupstools.git] / server / netlist.c
blobd480eb1fa3b9189c4969a0d6f140febabab1d3a6
1 /* netlist.c - LIST handlers for upsd
3 Copyright (C)
4 2003 Russell Kroll <rkroll@exploits.org>
5 2012 Arnaud Quette <arnaud.quette@free.fr>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "common.h"
24 #include "upsd.h"
25 #include "sstate.h"
26 #include "state.h"
27 #include "neterr.h"
29 #include "netlist.h"
31 extern upstype_t *firstups; /* for list_ups */
32 extern nut_ctype_t *firstclient; /* for list_clients */
34 static int tree_dump(st_tree_t *node, nut_ctype_t *client, const char *ups,
35 int rw, int fsd)
37 int ret;
39 if (!node)
40 return 1; /* not an error */
42 if (node->left) {
43 ret = tree_dump(node->left, client, ups, rw, fsd);
45 if (!ret)
46 return 0; /* write failed in child */
49 if (rw) {
51 /* only send this back if it's been flagged RW */
52 if (node->flags & ST_FLAG_RW) {
53 ret = sendback(client, "RW %s %s \"%s\"\n",
54 ups, node->var, node->val);
56 } else {
57 ret = 1; /* dummy */
60 } else {
62 /* normal variable list only */
64 /* status is always a special case */
65 if ((fsd == 1) && (!strcasecmp(node->var, "ups.status"))) {
66 ret = sendback(client, "VAR %s %s \"FSD %s\"\n",
67 ups, node->var, node->val);
69 } else {
70 ret = sendback(client, "VAR %s %s \"%s\"\n",
71 ups, node->var, node->val);
75 if (ret != 1)
76 return 0;
78 if (node->right)
79 return tree_dump(node->right, client, ups, rw, fsd);
81 return 1;
84 static void list_rw(nut_ctype_t *client, const char *upsname)
86 const upstype_t *ups;
88 ups = get_ups_ptr(upsname);
90 if (!ups) {
91 send_err(client, NUT_ERR_UNKNOWN_UPS);
92 return;
95 if (!ups_available(ups, client))
96 return;
98 if (!sendback(client, "BEGIN LIST RW %s\n", upsname))
99 return;
101 if (!tree_dump(ups->inforoot, client, upsname, 1, ups->fsd))
102 return;
104 sendback(client, "END LIST RW %s\n", upsname);
107 static void list_var(nut_ctype_t *client, const char *upsname)
109 const upstype_t *ups;
111 ups = get_ups_ptr(upsname);
113 if (!ups) {
114 send_err(client, NUT_ERR_UNKNOWN_UPS);
115 return;
118 if (!ups_available(ups, client))
119 return;
121 if (!sendback(client, "BEGIN LIST VAR %s\n", upsname))
122 return;
124 if (!tree_dump(ups->inforoot, client, upsname, 0, ups->fsd))
125 return;
127 sendback(client, "END LIST VAR %s\n", upsname);
130 static void list_cmd(nut_ctype_t *client, const char *upsname)
132 const upstype_t *ups;
133 cmdlist_t *ctmp;
135 ups = get_ups_ptr(upsname);
137 if (!ups) {
138 send_err(client, NUT_ERR_UNKNOWN_UPS);
139 return;
142 if (!ups_available(ups, client))
143 return;
145 if (!sendback(client, "BEGIN LIST CMD %s\n", upsname))
146 return;
148 for (ctmp = ups->cmdlist; ctmp != NULL; ctmp = ctmp->next) {
149 if (!sendback(client, "CMD %s %s\n", upsname, ctmp->name))
150 return;
153 sendback(client, "END LIST CMD %s\n", upsname);
156 static void list_enum(nut_ctype_t *client, const char *upsname, const char *var)
158 const upstype_t *ups;
159 const st_tree_t *node;
160 const enum_t *etmp;
162 ups = get_ups_ptr(upsname);
164 if (!ups) {
165 send_err(client, NUT_ERR_UNKNOWN_UPS);
166 return;
169 if (!ups_available(ups, client))
170 return;
172 node = sstate_getnode(ups, var);
174 if (!node) {
175 send_err(client, NUT_ERR_VAR_NOT_SUPPORTED);
176 return;
179 if (!sendback(client, "BEGIN LIST ENUM %s %s\n", upsname, var))
180 return;
182 for (etmp = node->enum_list; etmp != NULL; etmp = etmp->next) {
183 if (!sendback(client, "ENUM %s %s \"%s\"\n",
184 upsname, var, etmp->val))
185 return;
188 sendback(client, "END LIST ENUM %s %s\n", upsname, var);
191 static void list_range(nut_ctype_t *client, const char *upsname, const char *var)
193 const upstype_t *ups;
194 const st_tree_t *node;
195 const range_t *rtmp;
197 ups = get_ups_ptr(upsname);
199 if (!ups) {
200 send_err(client, NUT_ERR_UNKNOWN_UPS);
201 return;
204 if (!ups_available(ups, client))
205 return;
207 node = sstate_getnode(ups, var);
209 if (!node) {
210 send_err(client, NUT_ERR_VAR_NOT_SUPPORTED);
211 return;
214 if (!sendback(client, "BEGIN LIST RANGE %s %s\n", upsname, var))
215 return;
217 for (rtmp = node->range_list; rtmp != NULL; rtmp = rtmp->next) {
218 if (!sendback(client, "RANGE %s %s \"%i\" \"%i\"\n",
219 upsname, var, rtmp->min, rtmp->max))
220 return;
223 sendback(client, "END LIST RANGE %s %s\n", upsname, var);
226 static void list_ups(nut_ctype_t *client)
228 upstype_t *utmp;
229 char esc[SMALLBUF];
231 if (!sendback(client, "BEGIN LIST UPS\n"))
232 return;
234 utmp = firstups;
236 while (utmp) {
237 int ret;
239 if (utmp->desc) {
240 pconf_encode(utmp->desc, esc, sizeof(esc));
241 ret = sendback(client, "UPS %s \"%s\"\n",
242 utmp->name, esc);
244 } else {
245 ret = sendback(client, "UPS %s \"Description unavailable\"\n",
246 utmp->name);
249 if (!ret)
250 return;
252 utmp = utmp->next;
255 sendback(client, "END LIST UPS\n");
258 static void list_clients(nut_ctype_t *client, const char *upsname)
260 const upstype_t *ups;
261 nut_ctype_t *c, *cnext;
263 ups = get_ups_ptr(upsname);
265 if (!ups) {
266 send_err(client, NUT_ERR_UNKNOWN_UPS);
267 return;
270 if (!sendback(client, "BEGIN LIST CLIENT %s\n", upsname))
271 return;
273 if (firstclient) {
274 int ret;
275 /* show connected clients */
276 for (c = firstclient; c; c = cnext) {
277 if (c->loginups && (!ups || !strcasecmp(c->loginups, ups->name))) {
278 ret = sendback(client, "CLIENT %s %s\n", c->loginups, c->addr);
279 if (!ret)
280 return;
282 cnext = c->next;
285 sendback(client, "END LIST CLIENT %s\n", upsname);
288 void net_list(nut_ctype_t *client, size_t numarg, const char **arg)
290 if (numarg < 1) {
291 send_err(client, NUT_ERR_INVALID_ARGUMENT);
292 return;
295 /* LIST UPS */
296 if (!strcasecmp(arg[0], "UPS")) {
297 list_ups(client);
298 return;
301 if (numarg < 2) {
302 send_err(client, NUT_ERR_INVALID_ARGUMENT);
303 return;
306 /* LIST VAR UPS */
307 if (!strcasecmp(arg[0], "VAR")) {
308 list_var(client, arg[1]);
309 return;
312 /* LIST RW UPS */
313 if (!strcasecmp(arg[0], "RW")) {
314 list_rw(client, arg[1]);
315 return;
318 /* LIST CMD UPS */
319 if (!strcasecmp(arg[0], "CMD")) {
320 list_cmd(client, arg[1]);
321 return;
324 /* LIST CLIENT UPS */
325 if (!strcasecmp(arg[0], "CLIENT")) {
326 list_clients(client, arg[1]);
327 return;
330 if (numarg < 3) {
331 send_err(client, NUT_ERR_INVALID_ARGUMENT);
332 return;
335 /* LIST ENUM UPS VARNAME */
336 if (!strcasecmp(arg[0], "ENUM")) {
337 list_enum(client, arg[1], arg[2]);
338 return;
341 /* LIST RANGE UPS VARNAME */
342 if (!strcasecmp(arg[0], "RANGE")) {
343 list_range(client, arg[1], arg[2]);
344 return;
347 send_err(client, NUT_ERR_INVALID_ARGUMENT);