1 /* netget.c - GET handlers for upsd
2 
3    Copyright (C) 2003  Russell Kroll <rkroll@exploits.org>
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 
20 #include "common.h"
21 
22 #include "upsd.h"
23 #include "sstate.h"
24 #include "state.h"
25 #include "desc.h"
26 #include "neterr.h"
27 
28 #include "netget.h"
29 
get_numlogins(nut_ctype_t * client,const char * upsname)30 static void get_numlogins(nut_ctype_t *client, const char *upsname)
31 {
32 	const	upstype_t	*ups;
33 
34 	ups = get_ups_ptr(upsname);
35 
36 	if (!ups) {
37 		send_err(client, NUT_ERR_UNKNOWN_UPS);
38 		return;
39 	}
40 
41 	if (!ups_available(ups, client))
42 		return;
43 
44 	sendback(client, "NUMLOGINS %s %d\n", upsname, ups->numlogins);
45 }
46 
get_upsdesc(nut_ctype_t * client,const char * upsname)47 static void get_upsdesc(nut_ctype_t *client, const char *upsname)
48 {
49 	const	upstype_t	*ups;
50 	char	esc[SMALLBUF];
51 
52 	ups = get_ups_ptr(upsname);
53 
54 	if (!ups) {
55 		send_err(client, NUT_ERR_UNKNOWN_UPS);
56 		return;
57 	}
58 
59 	if (ups->desc) {
60 		pconf_encode(ups->desc, esc, sizeof(esc));
61 		sendback(client, "UPSDESC %s \"%s\"\n", upsname, esc);
62 
63 	} else {
64 
65 		sendback(client, "UPSDESC %s \"Unavailable\"\n", upsname);
66 	}
67 }
68 
get_desc(nut_ctype_t * client,const char * upsname,const char * var)69 static void get_desc(nut_ctype_t *client, const char *upsname, const char *var)
70 {
71 	const	upstype_t	*ups;
72 	const	char	*desc;
73 
74 	ups = get_ups_ptr(upsname);
75 
76 	if (!ups) {
77 		send_err(client, NUT_ERR_UNKNOWN_UPS);
78 		return;
79 	}
80 
81 	if (!ups_available(ups, client))
82 		return;
83 
84 	desc = desc_get_var(var);
85 
86 	if (desc)
87 		sendback(client, "DESC %s %s \"%s\"\n", upsname, var, desc);
88 	else
89 		sendback(client, "DESC %s %s \"Description unavailable\"\n", upsname, var);
90 }
91 
get_cmddesc(nut_ctype_t * client,const char * upsname,const char * cmd)92 static void get_cmddesc(nut_ctype_t *client, const char *upsname, const char *cmd)
93 {
94 	const	upstype_t	*ups;
95 	const	char	*desc;
96 
97 	ups = get_ups_ptr(upsname);
98 
99 	if (!ups) {
100 		send_err(client, NUT_ERR_UNKNOWN_UPS);
101 		return;
102 	}
103 
104 	if (!ups_available(ups, client))
105 		return;
106 
107 	desc = desc_get_cmd(cmd);
108 
109 	if (desc)
110 		sendback(client, "CMDDESC %s %s \"%s\"\n", upsname, cmd, desc);
111 	else
112 		sendback(client, "CMDDESC %s %s \"Description unavailable\"\n",
113 			upsname, cmd);
114 }
115 
get_type(nut_ctype_t * client,const char * upsname,const char * var)116 static void get_type(nut_ctype_t *client, const char *upsname, const char *var)
117 {
118 	char	buf[SMALLBUF];
119 	const	upstype_t	*ups;
120 	const	st_tree_t	*node;
121 
122 	ups = get_ups_ptr(upsname);
123 
124 	if (!ups) {
125 		send_err(client, NUT_ERR_UNKNOWN_UPS);
126 		return;
127 	}
128 
129 	if (!ups_available(ups, client))
130 		return;
131 
132 	node = sstate_getnode(ups, var);
133 
134 	if (!node) {
135 		send_err(client, NUT_ERR_VAR_NOT_SUPPORTED);
136 		return;
137 	}
138 
139 	snprintf(buf, sizeof(buf), "TYPE %s %s", upsname, var);
140 
141 	if (node->flags & ST_FLAG_RW)
142 		snprintfcat(buf, sizeof(buf), " RW");
143 
144 	if (node->enum_list) {
145 		snprintfcat(buf, sizeof(buf), " ENUM");
146 	}
147 
148 	if (node->range_list) {
149 		snprintfcat(buf, sizeof(buf), " RANGE");
150 	}
151 
152 	if (node->flags & ST_FLAG_STRING) {
153 		sendback(client, "%s STRING:%ld\n", buf, node->aux);
154 		return;
155 	}
156 
157 	/* Any variable that is not string | range | enum is just a simple
158 	 * numeric value */
159 
160 	sendback(client, "%s NUMBER\n", buf);
161 }
162 
get_var_server(nut_ctype_t * client,const char * upsname,const char * var)163 static void get_var_server(nut_ctype_t *client, const char *upsname, const char *var)
164 {
165 	if (!strcasecmp(var, "server.info")) {
166 		sendback(client, "VAR %s server.info "
167 			"\"Network UPS Tools upsd %s - "
168 			"http://www.networkupstools.org/\"\n",
169 			upsname, UPS_VERSION);
170 		return;
171 	}
172 
173 	if (!strcasecmp(var, "server.version")) {
174 		sendback(client, "VAR %s server.version \"%s\"\n",
175 			upsname, UPS_VERSION);
176 		return;
177 	}
178 
179 	send_err(client, NUT_ERR_VAR_NOT_SUPPORTED);
180 }
181 
get_var(nut_ctype_t * client,const char * upsname,const char * var)182 static void get_var(nut_ctype_t *client, const char *upsname, const char *var)
183 {
184 	const	upstype_t	*ups;
185 	const	char	*val;
186 
187 	/* ignore upsname for server.* variables */
188 	if (!strncasecmp(var, "server.", 7)) {
189 		get_var_server(client, upsname, var);
190 		return;
191 	}
192 
193 	ups = get_ups_ptr(upsname);
194 
195 	if (!ups) {
196 		send_err(client, NUT_ERR_UNKNOWN_UPS);
197 		return;
198 	}
199 
200 	if (!ups_available(ups, client))
201 		return;
202 
203 	val = sstate_getinfo(ups, var);
204 
205 	if (!val) {
206 		send_err(client, NUT_ERR_VAR_NOT_SUPPORTED);
207 		return;
208 	}
209 
210 	/* handle special case for status */
211 	if ((!strcasecmp(var, "ups.status")) && (ups->fsd))
212 		sendback(client, "VAR %s %s \"FSD %s\"\n", upsname, var, val);
213 	else
214 		sendback(client, "VAR %s %s \"%s\"\n", upsname, var, val);
215 }
216 
net_get(nut_ctype_t * client,size_t numarg,const char ** arg)217 void net_get(nut_ctype_t *client, size_t numarg, const char **arg)
218 {
219 	if (numarg < 1) {
220 		send_err(client, NUT_ERR_INVALID_ARGUMENT);
221 		return;
222 	}
223 
224 	/* GET TRACKING [ID] */
225 	if (!strcasecmp(arg[0], "TRACKING")) {
226 		if (numarg < 2) {
227 			sendback(client, "%s\n", (client->tracking) ? "ON" : "OFF");
228 		}
229 		else {
230 			if (client->tracking)
231 				sendback(client, "%s\n", tracking_get(arg[1]));
232 			else
233 				send_err(client, NUT_ERR_FEATURE_NOT_CONFIGURED);
234 		}
235 		return;
236 	}
237 
238 	if (numarg < 2) {
239 		send_err(client, NUT_ERR_INVALID_ARGUMENT);
240 		return;
241 	}
242 
243 	/* GET NUMLOGINS UPS */
244 	if (!strcasecmp(arg[0], "NUMLOGINS")) {
245 		get_numlogins(client, arg[1]);
246 		return;
247 	}
248 
249 	/* GET UPSDESC UPS */
250 	if (!strcasecmp(arg[0], "UPSDESC")) {
251 		get_upsdesc(client, arg[1]);
252 		return;
253 	}
254 
255 	if (numarg < 3) {
256 		send_err(client, NUT_ERR_INVALID_ARGUMENT);
257 		return;
258 	}
259 
260 	/* GET VAR UPS VARNAME */
261 	if (!strncasecmp(arg[0], "VAR", 3)) {
262 		get_var(client, arg[1], arg[2]);
263 		return;
264 	}
265 
266 	/* GET TYPE UPS VARNAME */
267 	if (!strcasecmp(arg[0], "TYPE")) {
268 		get_type(client, arg[1], arg[2]);
269 		return;
270 	}
271 
272 	/* GET DESC UPS VARNAME */
273 	if (!strcasecmp(arg[0], "DESC")) {
274 		get_desc(client, arg[1], arg[2]);
275 		return;
276 	}
277 
278 	/* GET CMDDESC UPS CMDNAME */
279 	if (!strcasecmp(arg[0], "CMDDESC")) {
280 		get_cmddesc(client, arg[1], arg[2]);
281 		return;
282 	}
283 
284 	send_err(client, NUT_ERR_INVALID_ARGUMENT);
285 	return;
286 }
287