1 /* $Id: status.c 7547 2006-08-26 06:18:14Z eagle $
3 ** Periodic status reporting.
7 #include "portable/socket.h"
9 #include "inn/innconf.h"
13 #define MIN_REFRESH 60 /* 1 min */
15 #if defined(HTML_STATUS)
16 #define STATUS_FILE "inn_status.html" /* will be in pathhttp */
18 #define STATUS_FILE "inn.status" /* will be in pathlog */
21 typedef struct _STATUS {
25 unsigned short activeCxn;
26 unsigned short sleepingCxns;
28 unsigned long accepted;
29 unsigned long refused;
30 unsigned long rejected;
31 unsigned long Duplicate;
32 unsigned long Unwanted_u;
33 unsigned long Unwanted_d;
34 unsigned long Unwanted_g;
35 unsigned long Unwanted_s;
36 unsigned long Unwanted_f;
40 unsigned long Check_send;
41 unsigned long Check_deferred;
42 unsigned long Check_got;
43 unsigned long Check_cybercan;
44 unsigned long Takethis;
45 unsigned long Takethis_Ok;
46 unsigned long Takethis_Err;
48 unsigned long Ihave_Duplicate;
49 unsigned long Ihave_Deferred;
50 unsigned long Ihave_SendIt;
51 unsigned long Ihave_Cybercan;
55 static unsigned STATUSlast_time;
62 static struct timeval start_tv;
66 gettimeofday(&start_tv, NULL);
69 gettimeofday(&tv, NULL);
70 return((tv.tv_sec - start_tv.tv_sec) * 1000 +
71 (tv.tv_usec - start_tv.tv_usec) / 1000);
79 STATUSlast_time = STATUSgettime(); /* First invocation */
81 strlcpy(start_time, ctime(&now), sizeof(start_time));
85 PrettySize(float size, char *str)
87 if (size > 1073741824) /* 1024*1024*1024 */
88 sprintf (str, "%.1fGb", size / 1073741824.);
90 if (size > 1048576) /* 1024*1024 */
91 sprintf (str, "%.1fMb", size / 1048576.);
93 sprintf (str, "%.1fkb", size / 1024.);
104 int sleepingCxns = 0;
106 unsigned long duplicate = 0;
107 unsigned long offered;
108 unsigned long accepted = 0;
109 unsigned long refused = 0;
110 unsigned long rejected = 0;
112 float DuplicateSize = 0;
114 char TempString[SMBUF];
116 STATUS *head, *status, *tmp;
120 #if defined(HTML_STATUS)
121 path = concatpath(innconf->pathhttp, STATUS_FILE);
123 path = concatpath(innconf->pathlog, STATUS_FILE);
125 if ((F = Fopen(path, "w", TEMPORARYOPEN)) == NULL) {
126 syslog(L_ERROR, "%s cannot open %s: %m", LogName, path);
130 #if defined(HTML_STATUS)
133 fprintf (F,"<HTML>\n<HEAD>\n<META HTTP-EQUIV=\"Refresh\" CONTENT=\"%ld;\">\n",
134 innconf->status < MIN_REFRESH ? MIN_REFRESH : innconf->status);
135 fprintf (F, "<TITLE>%s: incoming feeds</TITLE>\n", innconf->pathhost);
136 fprintf (F, "</HEAD>\n<BODY>\n<PRE>\n") ;
137 #endif /* defined(HTML_STATUS) */
139 fprintf (F, "%s\n", inn_version_string);
140 fprintf (F, "pid %d started %s\n", (int) getpid(), start_time);
143 for (i = 0; (cp = CHANiter(&i, CTnntp)) != NULL; ) {
146 cp->Address.ss_family == 0 ? "localhost" : RChostname(cp),
148 for (status = head ; status != NULL ; status = status->next) {
149 if (strcmp(TempString, status->name) == 0)
152 if (status == NULL) {
153 status = xmalloc(sizeof(STATUS));
154 peers++; /* a new peer */
155 strlcpy(status->name, TempString, sizeof(status->name));
156 if (cp->Address.ss_family == 0) {
157 /* Connections from lc.c do not have an IP address. */
158 memset(&status->ip_addr, 0, sizeof(status->ip_addr));
160 strlcpy(status->ip_addr,
161 sprint_sockaddr((struct sockaddr *)&cp->Address),
162 sizeof(status->ip_addr));
164 status->can_stream = cp->Streaming;
165 status->seconds = status->Size = status->DuplicateSize = 0;
166 status->Ihave = status->Ihave_Duplicate =
167 status->Ihave_Deferred = status->Ihave_SendIt =
168 status->Ihave_Cybercan = 0;
169 status->Check = status->Check_send =
170 status->Check_deferred = status->Check_got =
171 status->Check_cybercan = 0;
172 status->Takethis = status->Takethis_Ok = status->Takethis_Err = 0;
173 status->activeCxn = status->sleepingCxns = 0;
174 status->accepted = 0;
175 status->refused = status->rejected = 0;
176 status->Duplicate = status->Unwanted_u = 0;
177 status->Unwanted_d = status->Unwanted_g = 0;
178 status->Unwanted_s = status->Unwanted_f = 0;
186 if (Now.time - cp->Started > status->seconds)
187 status->seconds = Now.time - cp->Started;
188 if (Now.time - cp->Started > seconds)
189 seconds = Now.time - cp->Started;
190 status->accepted += cp->Received;
191 accepted += cp->Received;
192 status->refused += cp->Refused;
193 refused += cp->Refused;
194 status->rejected += cp->Rejected;
195 rejected += cp->Rejected;
196 status->Duplicate += cp->Duplicate;
197 duplicate += cp->Duplicate;
198 status->Unwanted_u += cp->Unwanted_u;
199 status->Unwanted_d += cp->Unwanted_d;
200 status->Unwanted_g += cp->Unwanted_g;
201 status->Unwanted_s += cp->Unwanted_s;
202 status->Unwanted_f += cp->Unwanted_f;
203 status->Ihave += cp->Ihave;
204 status->Ihave_Duplicate += cp->Ihave_Duplicate;
205 status->Ihave_Deferred += cp->Ihave_Deferred;
206 status->Ihave_SendIt += cp->Ihave_SendIt;
207 status->Ihave_Cybercan += cp->Ihave_Cybercan;
208 status->Check += cp->Check;
209 status->Check_send += cp->Check_send;
210 status->Check_deferred += cp->Check_deferred;
211 status->Check_got += cp->Check_got;
212 status->Check_cybercan += cp->Check_cybercan;
213 status->Takethis += cp->Takethis;
214 status->Takethis_Ok += cp->Takethis_Ok;
215 status->Takethis_Err += cp->Takethis_Err;
216 status->Size += cp->Size;
217 status->DuplicateSize += cp->DuplicateSize;
219 DuplicateSize += cp->DuplicateSize;
220 if (CHANsleeping(cp)) {
222 status->sleepingCxns++;
231 strlcpy (TempString, ctime (&now), sizeof(TempString));
232 fprintf (F, "Updated: %s", TempString);
233 fprintf (F, "(peers: %d, active-cxns: %d, sleeping-cxns: %d)\n\n",
234 peers, activeCxn, sleepingCxns);
236 fprintf (F, "Mode: %s", Mode == OMrunning ? "running" :
237 Mode == OMpaused ? "paused" :
238 Mode == OMthrottled ? "throttled" : "Unknown");
239 if ((Mode == OMpaused) || (Mode == OMthrottled))
240 fprintf (F, " (%s)", ModeReason);
242 /* Global configuration */
243 fprintf (F, "\n\nConfiguration file: %s\n\n", _PATH_CONFIG);
245 fprintf (F, "Global configuration parameters:\n");
246 fprintf (F, " Largest Article: %ld bytes\n", innconf->maxartsize);
247 fprintf (F, " Max Incoming connections: ");
248 if (innconf->maxconnections)
249 fprintf (F, "%ld\n", innconf->maxconnections);
251 fprintf (F, "unlimited\n");
252 fprintf (F, " Max Outgoing file feeds: %d\n", MaxOutgoing);
253 fprintf (F, " Cutoff: ");
254 if (innconf->artcutoff)
255 fprintf (F, "%ld days\n", innconf->artcutoff);
257 fprintf (F, "none\n");
258 fprintf (F, " Timeout period: %ld seconds\n",
259 (long)TimeOut.tv_sec);
260 if (innconf->remembertrash) {
261 fprintf (F, " Remember Trash: Yes\n");
263 fprintf (F, " Remember Trash: No\n");
266 fprintf (F, " Tcl filtering: %s\n",
267 TCLFilterActive ? "enabled" : "disabled");
268 #endif /* defined(DO_TCL) */
270 fprintf (F, " Perl filtering: %s\n",
271 PerlFilterActive ? "enabled" : "disabled");
272 #endif /* defined(DO_PERL) */
277 fprintf (F, "global (process)\n");
278 fprintf (F, " seconds: %ld\n", (long) seconds);
279 offered = accepted + refused + rejected;
280 fprintf (F, " offered: %-9ld\n", offered);
281 if (!offered) offered = 1; /* to avoid division by zero */
282 if (!size) size = 1; /* avoid divide by zero here too */
283 fprintf (F, " accepted: %-9ld %%accepted: %.1f%%\n",
284 accepted, (float) accepted / offered * 100);
285 fprintf (F, " refused: %-9ld %%refused: %.1f%%\n",
286 refused, (float) refused / offered * 100);
287 fprintf (F, " rejected: %-9ld %%rejected: %.1f%%\n",
288 rejected, (float) rejected / offered * 100);
289 fprintf (F, " duplicated: %-9ld %%duplicated: %.1f%%\n",
290 duplicate, (float) duplicate / offered * 100);
291 fprintf (F, " bytes: %-7s\n", PrettySize (size + DuplicateSize, str));
292 fprintf (F, " duplicated size: %-7s %%duplicated size: %.1f%%\n",
293 PrettySize(DuplicateSize, str), (float) DuplicateSize / size * 100);
297 for (status = head ; status != NULL ;) {
298 fprintf (F, "%s\n", status->name);
299 fprintf (F, " seconds: %-7ld ", (long) status->seconds);
300 fprintf (F, " duplicates: %-7ld ", status->Duplicate);
301 fprintf (F, " ip address: %s\n", status->ip_addr);
302 fprintf (F, " offered: %-7ld ",
303 status->accepted + status->refused + status->rejected);
304 fprintf (F, " uw newsgroups: %-7ld ", status->Unwanted_g);
305 fprintf (F, " active cxns: %d\n", status->activeCxn);
306 fprintf (F, " accepted: %-7ld ", status->accepted);
307 fprintf (F, "uw distributions: %-7ld ", status->Unwanted_d);
308 fprintf (F, " sleeping cxns: %d\n", status->sleepingCxns);
309 fprintf (F, " refused: %-7ld ", status->refused);
310 fprintf (F, " unapproved: %-7ld ", status->Unwanted_u);
311 fprintf (F, "want streaming: %s\n",
312 status->can_stream ? "Yes" : "No");
313 fprintf (F, " rejected: %-7ld ", status->rejected);
314 fprintf (F, " filtered: %-7ld ", status->Unwanted_f);
315 fprintf (F, " is streaming: %s\n",
316 (status->Check || status->Takethis) ? "Yes" : "No");
317 fprintf (F, " size: %-8s ", PrettySize(status->Size, str));
318 fprintf (F, " bad sites: %-7ld ", status->Unwanted_s);
319 fprintf (F, "duplicate size: %s\n", PrettySize(status->DuplicateSize, str));
320 fprintf (F, " Protocol:\n");
321 fprintf (F, " Ihave: %-6ld SendIt[%d]: %-6ld Got[%d]: %-6ld Deferred[%d]: %ld\n",
322 status->Ihave, NNTP_SENDIT_VAL, status->Ihave_SendIt,
323 NNTP_HAVEIT_VAL, status->Ihave_Duplicate, NNTP_RESENDIT_VAL,
324 status->Ihave_Deferred);
325 fprintf (F, " Check: %-6ld SendIt[%d]: %-6ld Got[%d]: %-6ld Deferred[%d]: %ld\n",
326 status->Check, NNTP_OK_SENDID_VAL, status->Check_send,
327 NNTP_ERR_GOTID_VAL, status->Check_got, NNTP_RESENDID_VAL,
328 status->Check_deferred);
329 fprintf (F, " Takethis: %-6ld Ok[%d]: %-6ld Error[%d]: %-6ld\n",
330 status->Takethis, NNTP_OK_RECID_VAL, status->Takethis_Ok,
331 NNTP_ERR_FAILID_VAL, status->Takethis_Err);
332 if (innconf->refusecybercancels) {
333 fprintf (F, " Cancelrejects: Ihave[%d]: %-6ld Check[%d]: %-6ld\n",
334 NNTP_HAVEIT_VAL, status->Ihave_Cybercan,
335 NNTP_ERR_GOTID_VAL, status->Check_cybercan);
343 #if defined(HTML_STATUS)
345 fprintf (F,"</PRE>\n</BODY>\n</HTML>\n");
346 #endif /* defined(HTML_STATUS) */
352 STATUSmainloophook(void)
356 if (!innconf->status)
358 now = STATUSgettime();
360 if (now - STATUSlast_time > (unsigned)(innconf->status * 1000)) {
362 STATUSlast_time = now;