1 /*
2  * Client test program for apcnisd to be used
3  * as a base for the new master/slave code.
4  *
5  * Build it with: cc newslave.c ../lib/libapc.a -o newclient
6  *
7  * Execute: ./newslave [host[:port]]
8  *
9  * The two commands currently (Apr 2001) accepted by the
10  * server are "status" and "events".
11  *
12  */
13 
14 #include "apc.h"
15 
16 #ifdef HAVE_NISLIB
17 
18 /* Default values, can be changed on command line */
19 #define SERV_TCP_PORT 3551
20 #define SERV_HOST_ADDR "127.0.0.1"
21 
22 #define BIGBUF 4096
23 char statbuf[BIGBUF];
24 int statlen = BIGBUF;
25 
26 /* List of variables that can be read by getupsvar()
27  * First field is that name given to getupsvar(),
28  * Second field is our internal name as produced by the STATUS
29  *   output from apcupsd.
30  * Third field, if 0 returns everything to the end of the
31  *    line, and if 1 returns only to first space (e.g. integers,
32  *    and floating point values.
33  */
34 static struct {
35    const char *request;
36    const char *upskeyword;
37    int nfields;
38 } cmdtrans[] = {
39    {"model",      "MODEL",    0},
40    {"upsmodel",   "UPSMODEL", 0},
41    {"date",       "DATE",     0},
42    {"battcap",    "BCHARGE",  1},
43    {"mbattchg",   "MBATTCHG", 1},
44    {"battvolt",   "BATTV",    1},
45    {"nombattv",   "NOMBATTV", 1},
46    {"utility",    "LINEV",    1},
47    {"upsload",    "LOADPCT",  1},
48    {"loadpct",    "LOADPCT",  1},
49    {"outputv",    "OUTPUTV",  1},
50    {"status",     "STATFLAG", 1},
51    {"linemin",    "MINLINEV", 1},
52    {"linemax",    "MAXLINEV", 1},
53    {"upstemp",    "ITEMP",    1},
54    {"outputfreq", "LINEFREQ", 1},
55    {"translo",    "LOTRANS",  1},
56    {"transhi",    "HITRANS",  1},
57    {"runtime",    "TIMELEFT", 1},
58    {"mintimel",   "MINTIMEL", 1},
59    {"retpct",     "RETPCT",   1},          /* min batt to turn on UPS */
60    {"sense",      "SENSE",    1},
61    {"hostname",   "HOSTNAME", 1},
62    {"battdate",   "BATTDATE", 1},
63    {"serialno",   "SERIALNO", 1},
64    {"lastxfer",   "LASTXFER", 0},          /* reason for last xfer to batteries */
65    {"selftest",   "SELFTEST", 1},          /* results of last self test */
66    {"laststest",  "LASTSTEST", 0},
67    {"version",    "VERSION",  1},
68    {"upsname",    "UPSNAME",  1},
69    {"lowbatt",    "DLOWBATT", 1},          /* low battery power off delay */
70    {"battpct",    "BCHARGE",  1},
71    {"highxfer",   "HITRANS",  1},
72    {"lowxfer",    "LOTRANS",  1},
73    {"cable",      "CABLE",    0},
74    {"firmware",   "FIRMWARE", 0},
75    {NULL, NULL}
76 };
77 
78 int fetch_data(char *host, int port);
79 int getupsvar(char *host, int port, const char *request, char *answer, int anslen);
80 int fill_buffer(int sockfd);
81 
82 extern int net_errno;
83 
error_abort(char * msg)84 void error_abort(char *msg)
85 {
86    fprintf(stderr, msg);
87    exit(1);
88 }
89 
main(int argc,char * argv[])90 int main(int argc, char *argv[])
91 {
92    int port;
93    char host[200];
94    char msg[200], *p;
95    char hostname[100];
96    char release[100];
97    char upsname[100];
98    char status[100];
99 
100    strcpy(host, SERV_HOST_ADDR);
101    port = SERV_TCP_PORT;
102 
103    if (argc > 1) {
104       strcpy(host, argv[1]); /* get host from command line */
105       p = strchr(host, ':');
106       if (p) {
107 	 *p++ = 0;
108 	 port = atoi(p);
109       }
110    }
111 
112    if (getupsvar(host, port, "hostname", msg, sizeof(msg)) <= 0) {
113        printf("Error getting variable\n");
114        exit(1);
115    }
116    strcpy(hostname, msg);
117 
118    if (getupsvar(host, port, "version", msg, sizeof(msg)) <= 0) {
119        printf("Error getting variable\n");
120        exit(1);
121    }
122    strcpy(release, msg);
123 
124    if (getupsvar(host, port, "upsname", msg, sizeof(msg)) <= 0) {
125        printf("Error getting variable\n");
126        exit(1);
127    }
128    strcpy(upsname, msg);
129 
130    if (getupsvar(host, port, "status", msg, sizeof(msg)) <= 0) {
131        printf("Error getting variable\n");
132        exit(1);
133    }
134    strcpy(status, msg);
135 
136    printf("For host=%s ups=%s apcupsd version=%s, the Status=%s\n",
137        hostname, upsname, release, status);
138 
139    exit(0);
140 }
141 
142 
143 /*
144  * Read data into memory buffer to be used by getupsvar()
145  * Returns 0 on error
146  * Returns 1 if data fetched
147  */
fetch_data(char * host,int port)148 int fetch_data(char *host, int port)
149 {
150    int sockfd;
151    int stat;
152 
153    if ((sockfd = net_open(host, NULL, port)) < 0) {
154       printf("fetch_data: tcp_open failed for %s port %d", host, port);
155       return 0;
156    }
157 
158    stat = fill_buffer(sockfd);		     /* fill statbuf */
159    net_close(sockfd);
160    return stat;
161 
162 }
163 
164 /*
165  *
166  * Returns 1 if var found
167  *   answer has var
168  * Returns 0 if variable name not found
169  *   answer has "Not found" is variable name not found
170  *   answer may have "N/A" if the UPS does not support this
171  *	 feature
172  * Returns -1 if network problem
173  *   answer has "N/A" if host is not available or network error
174  */
getupsvar(char * host,int port,const char * request,char * answer,int anslen)175 int getupsvar(char *host, int port, const char *request, char *answer, int anslen)
176 {
177     int i;
178     const char *stat_match = NULL;
179     char *find;
180     int nfields = 0;
181 
182     if (!fetch_data(host, port)) {
183         strcpy(answer, "N/A");
184 	return -1;
185     }
186 
187     for (i=0; cmdtrans[i].request; i++)
188 	if (!(strcmp(cmdtrans[i].request, request))) {
189 	     stat_match = cmdtrans[i].upskeyword;
190 	     nfields = cmdtrans[i].nfields;
191 	}
192 
193     if (stat_match != NULL) {
194 	if ((find=strstr(statbuf, stat_match)) != NULL) {
195 	     if (nfields == 1)	/* get one field */
196                  sscanf (find, "%*s %*s %s", answer);
197 	     else {		/* get everything to eol */
198 		 i = 0;
199 		 find += 11;  /* skip label */
200                  while (*find != '\n')
201 		     answer[i++] = *find++;
202 		 answer[i] = 0;
203 	     }
204              if (strcmp(answer, "N/A") == 0)
205 		 return 0;
206 	     return 1;
207 	}
208     }
209 
210     strcpy(answer, "Not found");
211     return 0;
212 }
213 
214 #define MAXLINE 512
215 
216 /* Fill buffer with data from UPS network daemon
217  * Returns 0 on error
218  * Returns 1 if OK
219  */
fill_buffer(int sockfd)220 int fill_buffer(int sockfd)
221 {
222    int n, stat = 1;
223    char buf[1000];
224 
225    statbuf[0] = 0;
226    statlen = 0;
227    if (net_send(sockfd, "status", 6) != 6) {
228       printf("fill_buffer: write error on socket\n");
229       return 0;
230    }
231 
232    while ((n = net_recv(sockfd, buf, sizeof(buf)-1)) > 0) {
233       buf[n] = 0;
234       strcat(statbuf, buf);
235    }
236    if (n < 0)
237       stat = 0;
238 
239    statlen = strlen(statbuf);
240    return stat;
241 
242 }
243 
244 #else /* HAVE_NISLIB */
245 
main(int argc,char * argv[])246 int main(int argc, char *argv[]) {
247     printf("Sorry, NIS code is not compiled in apcupsd.\n");
248     return 1;
249 }
250 
251 #endif /* HAVE_NISLIB */
252