UPS: apcupsd clean sources
[tomato.git] / release / src / router / apcupsd / src / lib / apcevents.c
blob44bbea34e66b7c6380ff31f64a216cd9de109f64
1 /*
2 * apcevents.c
4 * Output EVENTS information.
5 */
7 /*
8 * Copyright (C) 1999-2006 Kern Sibbald
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of version 2 of the GNU General
12 * Public License as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public
20 * License along with this program; if not, write to the Free
21 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22 * MA 02111-1307, USA.
25 #include "apc.h"
27 #define NLE 50 /* number of events to send and keep */
30 * If the ups->eventfile exceeds ups->eventfilemax kilobytes, trim it to
31 * slightly less than that maximum, preserving lines at end of the file.
33 * Returns:
35 * -1 if any error occurred
36 * 0 if file did not need to be trimmed
37 * 1 if file was trimmed
39 int trim_eventfile(UPSINFO *ups)
41 int nbytes, maxb, i, rwerror = 0, status = -1;
42 struct stat statbuf;
43 unsigned char *buf;
45 if (ups->eventfilemax == 0 || ups->event_fd < 0 || ups->eventfile[0] == 0)
46 return 0;
48 maxb = ups->eventfilemax * 1024;
49 if (stat(ups->eventfile, &statbuf) < 0)
50 return -1;
51 if (statbuf.st_size <= maxb)
52 return 0; /* file is not yet too large - nothing to do */
54 maxb = (maxb * 80) / 100; /* file is too large - reduce to 80% of max */
55 buf = (unsigned char *)malloc(maxb);
56 if (!buf)
57 return -1;
59 write_lock(ups);
61 /* Read the desired number of bytes from end of file */
62 if (lseek(ups->event_fd, -maxb, SEEK_END) < 0) {
63 log_event(ups, LOG_CRIT, "lseek failed in trim_eventfile.");
64 goto trim_done;
67 nbytes = 0;
68 while (nbytes < maxb) {
69 int r = read(ups->event_fd, buf + nbytes, maxb - nbytes);
71 if (r < 0)
72 rwerror++;
73 if (r <= 0)
74 break;
75 nbytes += r;
78 /* Skip to the first new line */
79 for (i = 0; i < nbytes; i++) {
80 if (buf[i] == '\n') {
81 i++;
82 break;
85 nbytes -= i;
87 /* Truncate the file and write the buffer */
88 lseek(ups->event_fd, 0, SEEK_SET);
89 ftruncate(ups->event_fd, 0);
90 while (nbytes) {
91 int r = write(ups->event_fd, buf + i, nbytes);
93 if (r <= 0) {
94 rwerror++;
95 break;
97 i += r;
98 nbytes -= r;
100 status = 1;
102 trim_done:
103 write_unlock(ups);
104 free(buf);
106 if (rwerror)
107 log_event(ups, LOG_CRIT, "read/write failed in trim_eventfile.");
109 return status;
112 #ifdef HAVE_NISSERVER
115 * Send the last events.
116 * Returns:
117 * -1 error or EOF
118 * 0 OK
120 int output_events(int sockfd, FILE *events_file)
122 char *le[NLE];
123 int i, j;
124 int nrec = 0;
125 int stat = 0;
127 for (i = 0; i < NLE; i++)
128 le[i] = NULL;
130 for (i = 0; i < NLE; i++)
131 if ((le[i] = (char *)malloc(MAXSTRING)) == NULL)
132 goto bailout;
134 i = 0;
135 while (fgets(le[i], MAXSTRING, events_file) != NULL) {
136 nrec++;
137 i++;
138 if (i >= NLE) /* wrap */
139 i = 0;
142 if (nrec > NLE) {
143 nrec = NLE; /* number of records to output */
144 i -= (i / NLE) * NLE; /* first record to output */
145 } else {
146 i = 0;
149 for (j = 0; j < nrec; j++) {
150 if (net_send(sockfd, le[i], strlen(le[i])) <= 0)
151 goto bailout;
153 if (++i >= NLE)
154 i = 0;
157 goto goodout;
159 bailout:
160 stat = -1;
162 goodout:
163 if (net_send(sockfd, NULL, 0) < 0) /* send eof */
164 stat = -1;
166 for (i = 0; i < NLE; i++)
167 if (le[i] != NULL)
168 free(le[i]);
170 return stat;
173 #endif /* HAVE_NISSERVER */