ip protocol usage statistics and more
[svn/Prometheus-QoS/.git] / htmlandlogs.c
CommitLineData
9a56ab25 1#include "cll1-0.6.2.h"\r
2#include "ipstruct.h"\r
3#define STRLEN 512\r
4\r
5extern int row_odd_even;\r
6extern int use_jquery_popups;\r
7extern struct IP *ips, *ip, *sharedip;\r
8extern struct Group *groups, *group;\r
9extern struct Keyword *keyword, *defaultkeyword, *keywords;\r
10extern const int highest_priority;\r
11extern const char *version;\r
12extern const char *stats_html_signature;\r
13extern char *jquery_url;\r
14extern int keywordcount;\r
15extern long long int line;\r
16extern int dry_run;\r
17extern int qos_proxy;\r
18extern char *title;\r
19extern char *log_url;\r
20extern int found_lmsid;\r
21extern char *lms_url;\r
22extern char *log_dir;\r
ca6f7e80 23extern char *ip6prefix;\r
9a56ab25 24\r
25const char *tr_odd_even(void);\r
26/* implemented in prometheus.c, shared with parselogs.c */\r
27\r
28void append_log(struct IP *self) /*using global variables*/\r
29{\r
30 char *d, *str;\r
31 FILE *f; \r
32\r
33 date(d); /* this is typical cll1.h macro - prints current date */ \r
0995c4ad 34 string(str, STRLEN); \r
35 sprintf(str, "%s/%s.log", log_dir, self->name);\r
36\r
37 /*-----------------------------------------------------------------*/\r
38 printf("Writing traffic log %s ...\n", str);\r
39 /*-----------------------------------------------------------------*/\r
40 f = fopen(str, "a");\r
9a56ab25 41 if(f > 0)\r
42 {\r
0995c4ad 43 fprintf(f, "%ld\t%s\t%Lu\t%Lu\t%Lu\t%Lu\t%d\t%d\t%d\t%d\t%s",\r
44 time(NULL), self->name, self->traffic, self->direct, self->proxy,\r
45 self->upload, self->min, self->max, self->desired, self->lmsid, d); /* d = date*/\r
9a56ab25 46 fclose(f);\r
47 }\r
48 else\r
49 {\r
50 perror(str);\r
51 }\r
52}\r
53\r
54void write_htmlandlogs(char *html, char *d, int total, int just_preview)\r
55{\r
56 int i;\r
57 char *str;\r
0db8e993 58 FILE *f=fopen(html, "w");\r
9a56ab25 59\r
60 string(str,STRLEN); \r
61 if(f > 0)\r
62 {\r
63 int count=1;\r
64 i=0;\r
65\r
9a56ab25 66 if(use_jquery_popups)\r
67 {\r
68 fprintf(f,"<script type=\"text/javascript\" src=\"%s\"></script>\n", jquery_url);\r
69 }\r
70 fputs("<table class=\"decorated last\">\n\\r
71<caption>Bandwidth classes</caption>\n\\r
72<thead><tr>\n\\r
73<th style=\"text-align: right\">#</th>\n\\r
74<th style=\"text-align: right\">group</th>\n\\r
75<th style=\"text-align: right\">IPs</th>\n\\r
76<th style=\"text-align: right\">requested</th>\n",f);\r
77 fprintf(f,"<th colspan=\"%d\">data limits</th>\n", keywordcount);\r
78 fputs("</tr></thead><tbody>\n",f);\r
79\r
80 row_odd_even = 0;\r
81 for_each(group, groups) \r
82 { \r
83#ifdef DEBUG\r
84 printf("%d kb/s group: %d bandwidth requested: %d kb/s\n",group->min,group->count,group->desired);\r
85#endif\r
86 fprintf(f, "%s<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d&nbsp;kb/s</td>",\r
87 tr_odd_even(), count, group->min);\r
88 fprintf(f, "<td style=\"text-align: right\">%d</td><td style=\"text-align: right\">%d&nbsp;kb/s</td>",\r
89 group->count, group->desired);\r
90\r
91 for_each(keyword, keywords) if(keyword->ip_count)\r
92 {\r
ca6f7e80 93 fprintf(f, "<td style=\"text-align: right\"><span style=\"color:#%s\">%d&nbsp;MB</span></td>",\r
94 keyword->html_color, group->min*keyword->data_limit);\r
9a56ab25 95 } \r
96 i += group->desired; \r
97 total += group->count;\r
98 count++; \r
99 }\r
100#ifdef DEBUG\r
101 printf("Total groups: %d Total bandwidth requested: %d kb/s\nAGGREGATION: 1/%d\n",\r
102 count, i, i/line);\r
103#endif\r
104 fprintf(f,"</tr></tbody>\n\\r
105<thead><tr>\n\\r
106<th colspan=\"2\" style=\"text-align: left\">Line %Ld kb/s</td>",line);\r
107 fprintf(f,"<th style=\"text-align: right\">%d</td><th style=\"text-align: right\">%d kb/s</td>",total,i);\r
108\r
109 for_each(keyword, keywords) if(keyword->ip_count)\r
110 {\r
111 fprintf(f,"<th style=\"text-align: right\">%d IPs</th>",keyword->ip_count);\r
112 }\r
113 fprintf(f,"</tr><tr><th colspan=\"4\">Aggregation 1/%d</th>\n", (int)(0.5+i/line));\r
114 fprintf(f,"<th colspan=\"%d\">%d traffic classes</th></tr>\n", keywordcount, total);\r
115\r
116 fputs("</thead></table>\n",f);\r
117 }\r
118 else\r
119 {\r
120 perror(html);\r
121 }\r
122\r
123 i=0;\r
124 if(f > 0)\r
125 {\r
126 unsigned long long total_traffic=0, total_direct=0, total_proxy=0, total_upload=0, tmp_sum=0;\r
127 int active_classes=0;\r
128 int colspan=12;\r
129 struct Sum {unsigned long long l; int i; list(Sum);} *sum,*sums=NULL;\r
130 int limit_count=0, prio_count=0;\r
131 int popup_button=0;\r
132\r
133 if(qos_proxy)\r
134 {\r
135 colspan++;\r
136 }\r
137 \r
138 fprintf(f,"<p><table class=\"decorated last\">\n<caption>%s",title);\r
139 fprintf(f," (%s)</caption>\n", d);\r
140 fputs("<thead><tr>\n<th colspan=\"3\">&nbsp;</th>\n",f);\r
141 fputs("<th style=\"text-align: right\">credit</th>\n\\r
142<th style=\"text-align: right\">FUP</th>\n\\r
143<th style=\"text-align: right\">total</th>\n\\r
144<th style=\"text-align: right\">down</th>\n",f);\r
145 if(qos_proxy)\r
146 {\r
147 fputs("<th style=\"text-align: right\">proxy</th>\n",f);\r
148 }\r
149 fputs("<th style=\"text-align: right\">up</th>\n\\r
150<th style=\"text-align: right\">min</th>\n\\r
151<th style=\"text-align: right\">max</th>\n\\r
152<th style=\"text-align: right\">limit</th>\n\\r
153<th>&nbsp;</th>\n\\r
154</tr><tr>\n\\r
155<th style=\"text-align: right\">#</th>\n\\r
156<th>hostname [+sharing]</th>\n\\r
157<th style=\"text-align: right\">LMS</th>\n\\r
158<th style=\"text-align: right\">MB</th>\n\\r
159<th style=\"text-align: right\">MB</th>\n\\r
160<th style=\"text-align: right\">MB</th>\n\\r
161<th style=\"text-align: right\">MB</th>\n\\r
162<th style=\"text-align: right\">MB</th>\n\\r
163<th style=\"text-align: right\">kb/s</th>\n\\r
164<th style=\"text-align: right\">kb/s</th>\n\\r
165<th style=\"text-align: right\">kb/s</th>\n\\r
166<th>prio</th>\n\\r
167</tr></thead><tbody>\n",f); \r
168\r
169 row_odd_even = 0;\r
170 for_each(ip,ips) if(!use_jquery_popups || !ip->sharing)\r
171 {\r
172 char *f1="", *f2="";\r
173 i++;\r
174\r
175 if(ip->max < ip->desired) \r
ca6f7e80 176 {\r
177 f1 = "<span style=\"color:red\">";\r
9a56ab25 178 f2 = "</span>"; \r
179 limit_count++; \r
ca6f7e80 180 }\r
181 else if(ip->prio > highest_priority+1)\r
182 {\r
183 f1 = "<span style=\"color:brown\">";\r
184 f2 = "</span>";\r
9a56ab25 185 prio_count++; \r
186 } \r
187\r
188#ifdef DEBUG\r
189 printf("%03d. %-22s %10Lu (%d/%d)\n",i ,ip->name, ip->traffic, ip->min, ip->max); \r
190#endif\r
191 /* hostnames -------------------------------------- */\r
192 fprintf(f,"%s<td style=\"text-align: right\"><a name=\"%s\"></a>%d</td><td><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s</a>\n", \r
193 tr_odd_even(), ip->name, i, log_url, ip->name, ip->name);\r
194\r
195 if(use_jquery_popups)\r
196 {\r
ca6f7e80 197 fprintf(f, "<span id=\"sharing_%d\" style=\"display:none\">",i);\r
9a56ab25 198 popup_button=0;\r
ca6f7e80 199\r
0b9c3c19 200 for_each(sharedip, ips) if(eq(ip->name, sharedip->sharing) && !sharedip->v6) /* IPv4 only */\r
9a56ab25 201 {\r
ca6f7e80 202 fprintf(f, "<br /><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s</a>\n", \r
203 log_url, sharedip->name, sharedip->name);\r
9a56ab25 204 popup_button++;\r
205 }\r
ca6f7e80 206\r
0b9c3c19 207 for_each(sharedip, ips) if(eq(ip->name, sharedip->sharing) && sharedip->v6) /* IPv6 only */\r
f64d5431 208 {\r
ca6f7e80 209 fprintf(f, "<br /><a class=\"blue\" target=\"_blank\" href=\"%s%s.log\">%s/64</a>\n", \r
210 log_url, sharedip->addr, sharedip->addr);\r
f64d5431 211 popup_button++;\r
212 }\r
ca6f7e80 213\r
9a56ab25 214 fputs("</span>\n",f);\r
215 if(popup_button)\r
216 {\r
ca6f7e80 217 fprintf(f, "<span>[<a class=\"blue\" href=\"#\" onClick=\"$(this).parent().hide();$(\'#sharing_%d\').show();$(\'#download_%d\').show();$(\'#upload_%d\').show();return(false);\" style=\"cursor: pointer;\">+%d</a>]</span>",\r
218 i, i, i, popup_button);\r
9a56ab25 219 }\r
220 }\r
221 fputs("</td>\n",f);\r
222 /* ----------------------------------------------- */\r
223\r
224 if(found_lmsid)\r
225 {\r
226 fputs("<td style=\"text-align: right\">",f);\r
227 if(ip->lmsid > 0)\r
228 {\r
229 fprintf(f,"<a class=\"blue\" target=\"_blank\" href=\"%s%d\">%04d</a>\n", lms_url, ip->lmsid, ip->lmsid);\r
230 }\r
231 else if(ip->lmsid == 0)\r
232 {\r
233 fputs("-------",f);\r
234 }\r
235 fputs("</td>\n",f);\r
236 }\r
237 fprintf(f,"<td style=\"text-align: right\">%Lu</td>\n", ip->credit);\r
238 fprintf(f,"<td style=\"text-align: right\"><span style=\"color:#%s\">%Lu</span></td>",\r
e48d46c9 239 ip->keyword->html_color, ip->realquota);\r
9a56ab25 240 fprintf(f,"<td style=\"text-align: right\">%s%Lu%s", f1, ip->traffic, f2);\r
241\r
242 /* download --------------------------------------- */\r
243 fprintf(f,"</td><td style=\"text-align: right\">%Lu", ip->direct);\r
244 if(use_jquery_popups)\r
245 {\r
ca6f7e80 246 fprintf(f,"<span id=\"download_%d\" style=\"display:none\">", i);\r
0b9c3c19 247 for_each(sharedip, ips) if(eq(ip->name, sharedip->sharing) && !sharedip->v6) /* IPv4 only */\r
f64d5431 248 {\r
249 fprintf(f,"<br />%Lu", sharedip->direct);\r
250 }\r
0b9c3c19 251 for_each(sharedip, ips) if(eq(ip->name, sharedip->sharing) && sharedip->v6) /* IPv6 only */\r
9a56ab25 252 {\r
253 fprintf(f,"<br />%Lu", sharedip->direct);\r
254 }\r
255 fputs("</span>\n",f);\r
256 }\r
257 fputs("</td>\n",f);\r
258 /* ----------------------------------------------- */\r
259\r
260 if(qos_proxy)\r
261 {\r
262 fprintf(f,"<td style=\"text-align: right\">%Lu</td>\n", ip->proxy);\r
263 }\r
264 /* upload ---------------------------------------- */\r
265 fprintf(f,"<td style=\"text-align: right\">%Lu", ip->upload);\r
266 if(use_jquery_popups)\r
267 {\r
ca6f7e80 268 fprintf(f,"<span id=\"upload_%d\" style=\"display:none\">", i);\r
0b9c3c19 269 for_each(sharedip,ips) if(eq(ip->name, sharedip->sharing) && !sharedip->v6) /* IPv4 only */\r
f64d5431 270 {\r
271 fprintf(f,"<br />%Lu", sharedip->upload);\r
272 }\r
0b9c3c19 273 for_each(sharedip,ips) if(eq(ip->name, sharedip->sharing) && sharedip->v6) /* IPv6 only */\r
9a56ab25 274 {\r
275 fprintf(f,"<br />%Lu", sharedip->upload);\r
276 }\r
277 fputs("</span>\n",f);\r
278 }\r
279 fputs("</td>\n",f);\r
280 /* ----------------------------------------------- */\r
281\r
282 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
283<td style=\"text-align: right\">%d</td>\n\\r
284<td style=\"text-align: right\">%s%d%s</td>\n\\r
285<td>%s%d%s</td></tr>\n",\r
286 ip->min, ip->desired, \r
287 f1, ip->max, f2, \r
288 f1, ip->prio, f2);\r
289\r
290 total_traffic+=ip->traffic;\r
291 total_direct+=ip->direct;\r
292 total_proxy+=ip->proxy;\r
293 total_upload+=ip->upload;\r
294 if(ip->traffic>0)\r
295 {\r
296 active_classes++;\r
297 tmp_sum+=ip->traffic;\r
298 create(sum,Sum);\r
299 sum->l=tmp_sum;\r
300 sum->i=active_classes;\r
301 insert(sum,sums,order_by,i);\r
302 }\r
303\r
304 if(!just_preview)\r
305 {\r
306 append_log(ip);\r
307 for_each(sharedip,ips) if(eq(ip->name, sharedip->sharing))\r
308 {\r
309 append_log(sharedip);\r
310 }\r
311 }\r
312 }\r
313 fprintf(f,"</tbody><thead><tr>\n\\r
314<th colspan=\"%d\" style=\"text-align: left\">%d CLASSES</th>", colspan-7, i);\r
315 fprintf(f,"<th style=\"text-align: right\">%Lu</th><th style=\"text-align: right\">%Lu</th>\n", total_traffic, total_direct);\r
316 if(qos_proxy)\r
317 {\r
318 fprintf(f,"<th style=\"text-align: right\">%Lu</th>\n", total_proxy);\r
319 }\r
320 fprintf(f,"<th style=\"text-align: right\">%Lu</th>", total_upload);\r
321 fprintf(f,"<th colspan=\"4\"><span style=\"color:red\">LIMIT %dx</span> <span style=\"color:brown\">LOW-PRIO %dx</span></th></tr>\n</thead></table>\n",limit_count,prio_count);\r
322\r
ca6f7e80 323 if(ip6prefix)\r
324 {\r
325 unsigned long long pkts4 =0, pkts6 = 0, bytes4 = 0, bytes6 = 0;\r
326 for_each(ip, ips)\r
327 { \r
328 if(ip->v6)\r
329 {\r
330 bytes6 += ip->traffic;\r
331 pkts6 += ip->pktsdown+ip->pktsup;\r
332 }\r
333 else\r
334 {\r
335 bytes4 += ip->traffic;\r
336 pkts4 += ip->pktsdown+ip->pktsup;\r
337 }\r
338 }\r
339\r
340 fputs("<p><table class=\"decorated last\"><caption>IP protocols usage</caption>\n",f);\r
341 fprintf(f, "%s<td>Total IPv4</td><td style=\"text-align: right\">%Lu MB (%.2f %%)</td><td style=\"text-align: right\">%Lu packets (%d %%)</td></tr>\n",\r
342 tr_odd_even(), bytes4, (float)(100*bytes4)/(bytes4+bytes6), pkts4, (float)(100*pkts4)/(pkts4+pkts6));\r
343 fprintf(f, "%s<td>Total IPv6</td><td style=\"text-align: right\">%Lu MB (%.2f %%)</td><td style=\"text-align: right\">%Lu packets (%d %%)</td></tr>\n",\r
344 tr_odd_even(), bytes6, (float)(100*bytes6)/(bytes4+bytes6), pkts6, (float)(100*pkts6)/(pkts4+pkts6));\r
345 fputs("</table>\n", f);\r
346 }\r
347\r
9a56ab25 348 row_odd_even = 0;\r
349 if(active_classes>10)\r
350 {\r
351 int top20_count=0,top20_perc1=0;\r
352 long long top20_perc2=0;\r
353 unsigned long long top20_sum=0l;\r
354 \r
355 fputs("<a name=\"erp\"></a><p><table class=\"decorated last\"><caption>Enterprise Resource Planning (ERP)</caption>\n",f);\r
356 fputs("<thead><tr>\n\\r
357<th>Analytic category</th>\n\\r
358<th colspan=\"2\" style=\"text-align: center\">Active Classes</th>\n\\r
359<th colspan=\"2\" style=\"text-align: center\">Data transfers</th>\n\\r
360</tr></thead><tbody>\n",f);\r
361\r
362 if_exists(sum,sums,sum->l>=total_traffic/4)\r
363 {\r
364 fprintf(f,"%s<td>Top 25%% of traffic</td>\n", tr_odd_even());\r
365 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
366<td style=\"text-align: right\">%d %%</td>\n\\r
367<td style=\"text-align: right\">%Lu MB</td>\n\\r
368<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
369 sum->i, (100*sum->i+50)/active_classes, sum->l, (100*sum->l+50)/total_traffic);\r
370 }\r
371 \r
372 if_exists(sum,sums,sum->i==10)\r
373 {\r
374 fprintf(f,"%s<td>Top 10 downloaders</td>\n", tr_odd_even());\r
375 fprintf(f,"<td style=\"text-align: right\"><strong>10</strong></td>\n\\r
376<td style=\"text-align: right\">%d %%</td>\n\\r
377<td style=\"text-align: right\">%Lu MB</td>\n\\r
378<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
379 (100*sum->i+50)/active_classes, sum->l, (100*sum->l+50)/total_traffic);\r
380 }\r
381\r
382 if_exists(sum,sums,sum->l>=total_traffic/2)\r
383 {\r
384 fprintf(f,"%s<td>Top 50%% of traffic</td>\n", tr_odd_even());\r
385 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
386<td style=\"text-align: right\">%d %%</td>\n\\r
387<td style=\"text-align: right\">%Lu MB</td>\n\\r
388<td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",\r
389 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
390 }\r
391\r
392 if_exists(sum,sums,sum->l>=4*total_traffic/5)\r
393 {\r
394 fprintf(f,"%s<td>Top 80%% of traffic</td>\n", tr_odd_even());\r
395 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
396<td style=\"text-align: right\">%d %%</td>\n\\r
397<td style=\"text-align: right\">%Lu MB</td>\n\\r
398<td style=\"text-align: right\"><strong>%Ld %%</strong></td></tr>\n",\r
399 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
400 }\r
401\r
402 if_exists(sum,sums,sum->i>=(active_classes+1)/5)\r
403 {\r
404 fprintf(f,"%s<td>Top 20%% downloaders</td>\n", tr_odd_even());\r
405 top20_count=sum->i;\r
406 top20_perc1=(100*sum->i+50)/active_classes;\r
407 top20_sum=sum->l;\r
408 top20_perc2=(100*sum->l+50)/total_traffic;\r
409 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
410<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
411<td style=\"text-align: right\">%Lu MB</td>\n\\r
412<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
413 top20_count,top20_perc1,top20_sum,top20_perc2);\r
414 }\r
415\r
416 if_exists(sum,sums,sum->i>=(active_classes+1)/4)\r
417 {\r
418 fprintf(f,"%s<td>Top 25%% downloaders</td>\n", tr_odd_even());\r
419 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
420<td style=\"text-align: right\">%d %%</td>\n\\r
421<td style=\"text-align: right\">%Lu MB</td>\n\\r
422<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
423 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
424 }\r
425\r
426 if_exists(sum,sums,sum->i>=(active_classes+1)/2)\r
427 {\r
428 fprintf(f,"%s<td>Top 50%% downloaders</td>\n", tr_odd_even());\r
429 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
430<td style=\"text-align: right\"><strong>%d %%</strong></td>\n\\r
431<td style=\"text-align: right\">%Lu MB</td>\n\\r
432<td style=\"text-align: right\">%Ld %%</td></tr>\n",\r
433 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
434 }\r
435\r
436 if_exists(sum,sums,sum->i>=4*(active_classes+1)/5)\r
437 {\r
438 fprintf(f,"%s<td>Top 80%% downloaders</td>\n", tr_odd_even());\r
439 fprintf(f,"<td style=\"text-align: right\">%d</td>\n\\r
440<td style=\"text-align: right\">%d %%</td>\n\\r
441<td style=\"text-align: right\">%Lu MB</td>\n\\r
442<td style=\"text-align: right\">%Ld %%</td></tr></tbody>\n",\r
443 sum->i,(100*sum->i+50)/active_classes,sum->l,(100*sum->l+50)/total_traffic);\r
444 }\r
445\r
446 fprintf(f,"<thead><tr><th><a class=\"blue\" target=\"_blank\" href=\"%sERP.log\">All users, all traffic</a></th>\n", log_url);\r
447 fprintf(f,"<th style=\"text-align: right\">%d</th>\n\\r
448<th style=\"text-align: right\">100 %%</th>\n\\r
449<th style=\"text-align: right\">%Lu MB</th>\n\\r
450<th style=\"text-align: right\">100 %%</th></tr>\n",active_classes,total_traffic);\r
451 fputs("</thead></table>\n", f);\r
452\r
453 /* write basic ERP data to log directory */\r
454 if(!just_preview)\r
455 {\r
456 FILE *iplog;\r
457 sprintf(str,"%s/ERP.log",log_dir);\r
458 iplog=fopen(str,"a");\r
459 if(iplog)\r
460 {\r
461 fprintf(iplog,"%ld\t%d\t%d %%\t%Lu M\t%Ld %%\tACTIVE %d\tTRAFFIC %Lu M\tCLASSES %d\tFUP-LIMIT %d\tLOW-PRIO %d\t%s",\r
462 time(NULL), top20_count, top20_perc1, top20_sum, top20_perc2, \r
463 active_classes, total_traffic, i, limit_count, prio_count, d); /* d = date*/\r
464 fclose(iplog);\r
465 }\r
466 else\r
467 {\r
468 perror(str);\r
469 }\r
470 }\r
471 }\r
472\r
473 fprintf(f, stats_html_signature, version);\r
474 fclose(f);\r
475 }\r
476}
This page took 0.565647 seconds and 4 git commands to generate.