flose files & free memory when not needed
[debian/dhcpd-pools.git] / src / output.c
1 /* http://dhcpd-pools.sourceforge.net/
2 ** Copyright 2006- Sami Kerola <kerolasa@iki.fi>
3 **
4 ** This program is free software: you can redistribute it and/or modify
5 ** it under the terms of the GNU General Public License as published by
6 ** the Free Software Foundation, either version 3 of the License, or
7 ** (at your option) any later version.
8 **
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 ** GNU General Public License for more details.
13 **
14 ** You should have received a copy of the GNU General Public License
15 ** along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21
22 #include <stdio.h>
23 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
26 #include <err.h>
27
28 #include "dhcpd-pools.h"
29
30 int output_txt(void)
31 {
32         unsigned int i;
33         struct in_addr first, last;
34         struct range_t *range_p;
35         struct shared_network_t *shared_p;
36         int ret;
37         FILE *outfile;
38
39         if (config.output_file[0]) {
40                 outfile = fopen(config.output_file, "w+");
41                 if (outfile == NULL) {
42                         err(EXIT_FAILURE, "output_txt: %s",
43                             config.output_file);
44                 }
45         } else {
46                 outfile = stdout;
47         }
48
49         range_p = ranges;
50         shared_p = shared_networks;
51
52         if (config.output_limit[0] & output_limit_bit_1) {
53                 fprintf(outfile, "Ranges:\n");
54                 fprintf
55                     (outfile,
56                      "shared net name     first ip           last ip            max   cur    percent  touch   t+c  t+c perc");
57                 if (0 < num_backups) {
58                         fprintf(outfile, "     bu  bu perc");
59                 }
60                 fprintf(outfile, "\n");
61         }
62         if (config.output_limit[1] & output_limit_bit_1) {
63                 for (i = 0; i < num_ranges; i++) {
64                         first.s_addr = ntohl(range_p->first_ip + 1);
65                         last.s_addr = ntohl(range_p->last_ip - 1);
66
67                         if (range_p->shared_net) {
68                                 fprintf(outfile, "%-20s",
69                                         range_p->shared_net->name);
70                         } else {
71                                 fprintf(outfile, "not_defined         ");
72                         }
73                         fprintf(outfile, "%-16s", inet_ntoa(first));
74                         fprintf(outfile,
75                                 " - %-16s %5lu %5lu %10.3f  %5lu %5lu %9.3f",
76                                 inet_ntoa(last),
77                                 range_p->last_ip - range_p->first_ip - 1,
78                                 range_p->count,
79                                 (float) (100 * range_p->count) /
80                                 (range_p->last_ip - range_p->first_ip - 1),
81                                 range_p->touched,
82                                 range_p->touched + range_p->count,
83                                 (float) (100 *
84                                          (range_p->touched +
85                                           range_p->count)) /
86                                 (range_p->last_ip - range_p->first_ip -
87                                  1));
88                         if (0 < num_backups) {
89                                 fprintf(outfile, "%7lu %8.3f",
90                                         range_p->backups,
91                                         (float) (100 * range_p->backups) /
92                                         (range_p->last_ip -
93                                          range_p->first_ip - 1));
94                         }
95                         fprintf(outfile, "\n");
96                         range_p++;
97                 }
98         }
99         if (config.output_limit[1] & output_limit_bit_1
100             && config.output_limit[0] & output_limit_bit_2) {
101                 fprintf(outfile, "\n");
102         }
103         if (config.output_limit[0] & output_limit_bit_2) {
104                 fprintf(outfile, "Shared networks:\n");
105                 fprintf(outfile,
106                         "name                   max   cur     percent  touch    t+c  t+c perc");
107                 if (0 < num_backups) {
108                         fprintf(outfile, "     bu  bu perc");
109                 }
110                 fprintf(outfile, "\n");
111         }
112         if (config.output_limit[1] & output_limit_bit_2) {
113                 for (i = 0; i < num_shared_networks; i++) {
114                         shared_p++;
115                         fprintf(outfile,
116                                 "%-20s %5lu %5lu %10.3f %7lu %6lu %9.3f",
117                                 shared_p->name, shared_p->available,
118                                 shared_p->used,
119                                 (float) (100 * shared_p->used) /
120                                 shared_p->available, shared_p->touched,
121                                 shared_p->touched + shared_p->used,
122                                 (float) (100 *
123                                          (shared_p->touched +
124                                           shared_p->used)) /
125                                 shared_p->available);
126                         if (0 < num_backups) {
127                                 fprintf(outfile, "%7lu %8.3f",
128                                         shared_p->backups,
129                                         (float) (100 * shared_p->backups) /
130                                         shared_p->available);
131                         }
132
133                         fprintf(outfile, "\n");
134                 }
135         }
136         if (config.output_limit[1] & output_limit_bit_2
137             && config.output_limit[0] & output_limit_bit_3) {
138                 fprintf(outfile, "\n");
139         }
140         if (config.output_limit[0] & output_limit_bit_3) {
141                 fprintf(outfile, "Sum of all ranges:\n");
142                 fprintf(outfile,
143                         "name                   max   cur     percent  touch    t+c  t+c perc");
144
145                 if (0 < num_backups) {
146                         fprintf(outfile, "     bu  bu perc");
147                 }
148                 fprintf(outfile, "\n");
149         }
150         if (config.output_limit[1] & output_limit_bit_3) {
151                 fprintf(outfile, "%-20s %5lu %5lu %10.3f %7lu %6lu %9.3f",
152                         shared_networks->name,
153                         shared_networks->available,
154                         shared_networks->used,
155                         (float) (100 * shared_networks->used) /
156                         shared_networks->available,
157                         shared_networks->touched,
158                         shared_networks->touched + shared_networks->used,
159                         (float) (100 *
160                                  (shared_networks->touched +
161                                   shared_networks->used)) /
162                         shared_networks->available);
163
164                 if (0 < num_backups) {
165                         fprintf(outfile, "%7lu %8.3f",
166                                 shared_networks->backups,
167                                 (float) (100 * shared_networks->backups) /
168                                 shared_networks->available);
169                 }
170                 fprintf(outfile, "\n");
171         }
172         if (outfile == stdout) {
173                 ret = fflush(stdout);
174                 if (ret) {
175                         warn("output_txt: fflush");
176                 }
177         } else {
178                 ret = fclose(outfile);
179                 if (ret) {
180                         warn("output_txt: fclose");
181                 }
182         }
183
184         return 0;
185 }
186
187 int output_xml(void)
188 {
189         unsigned int i;
190         struct in_addr first, last;
191         struct range_t *range_p;
192         struct shared_network_t *shared_p;
193         struct macaddr_t *macaddr_p;
194         int ret;
195         FILE *outfile;
196
197         if (config.output_file[0]) {
198                 outfile = fopen(config.output_file, "w+");
199                 if (outfile == NULL) {
200                         err(EXIT_FAILURE, "output_xml: %s",
201                             config.output_file);
202                 }
203         } else {
204                 outfile = stdout;
205         }
206
207         range_p = ranges;
208         shared_p = shared_networks;
209
210         fprintf(outfile, "<dhcpstatus>\n");
211
212         if (macaddr != NULL) {
213                 for (macaddr_p = macaddr; macaddr_p->next != NULL;
214                      macaddr_p = macaddr_p->next) {
215                         fprintf(outfile,
216                                 "<active_lease>\n\t<ip>%s</ip>\n\t<macaddress>%s</macaddress>\n</active_lease>\n",
217                                 macaddr_p->ip, macaddr_p->ethernet);
218                 }
219         }
220
221         if (config.output_limit[1] & output_limit_bit_1) {
222                 for (i = 0; i < num_ranges; i++) {
223                         first.s_addr = ntohl(range_p->first_ip + 1);
224                         last.s_addr = ntohl(range_p->last_ip - 1);
225                         fprintf(outfile, "<subnet>\n");
226                         if (range_p->shared_net) {
227                                 fprintf(outfile,
228                                         "\t<location>%s</location>\n",
229                                         range_p->shared_net->name);
230                         } else {
231                                 fprintf(outfile,
232                                         "\t<location></location>\n");
233                         }
234
235                         fprintf(outfile, "\t<network></network>\n");
236                         fprintf(outfile, "\t<netmask></netmask>\n");
237                         fprintf(outfile, "\t<range>%s ", inet_ntoa(first));
238                         fprintf(outfile, "- %s</range>\n",
239                                 inet_ntoa(last));
240                         fprintf(outfile, "\t<gateway></gateway>\n");
241                         fprintf(outfile, "\t<defined>%lu</defined>\n",
242                                 range_p->last_ip - range_p->first_ip - 1);
243                         fprintf(outfile, "\t<used>%lu</used>\n",
244                                 range_p->count);
245                         fprintf(outfile, "\t<free>%lu</free>\n",
246                                 range_p->last_ip - range_p->first_ip - 1 -
247                                 range_p->count);
248                         range_p++;
249                         fprintf(outfile, "</subnet>\n");
250                 }
251         }
252
253         if (config.output_limit[1] & output_limit_bit_2) {
254                 for (i = 0; i < num_shared_networks; i++) {
255                         shared_p++;
256                         fprintf(outfile, "<shared-network>\n");
257                         fprintf(outfile, "\t<location>%s</location>\n",
258                                 shared_p->name);
259                         fprintf(outfile, "\t<defined>%lu</defined>\n",
260                                 shared_p->available);
261                         fprintf(outfile, "\t<used>%lu</used>\n",
262                                 shared_p->used);
263                         fprintf(outfile, "\t<free>%lu</free>\n",
264                                 shared_p->available - shared_p->used);
265                         fprintf(outfile, "</shared-network>\n");
266                 }
267         }
268
269         if (config.output_limit[0] & output_limit_bit_3) {
270                 fprintf(outfile, "<summary>\n");
271                 fprintf(outfile, "\t<location>%s</location>\n",
272                         shared_networks->name);
273                 fprintf(outfile, "\t<defined>%lu</defined>\n",
274                         shared_networks->available);
275                 fprintf(outfile, "\t<used>%lu</used>\n",
276                         shared_networks->used);
277                 fprintf(outfile, "\t<free>%lu</free>\n",
278                         shared_networks->available -
279                         shared_networks->used);
280                 fprintf(outfile, "</summary>\n");
281         }
282
283         fprintf(outfile, "</dhcpstatus>\n");
284         if (outfile == stdout) {
285                 ret = fflush(stdout);
286                 if (ret) {
287                         warn("output_xml: fflush");
288                 }
289         } else {
290                 ret = fclose(outfile);
291                 if (ret) {
292                         warn("output_xml: fclose");
293                 }
294         }
295
296         return 0;
297 }
298
299 void html_header(FILE * f)
300 {
301         fprintf(f,
302                 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \n");
303         fprintf(f, "  \"http://www.w3.org/TR/html4/strict.dtd\">\n");
304         fprintf(f, "<html>\n");
305         fprintf(f, "<head>\n");
306         fprintf(f, "<meta http-equiv=\"Content-Type\" ");
307         fprintf(f, "content=\"text/html; charset=iso-8859-1\">\n");
308         fprintf(f, "  <title>ISC dhcpd stats</title>\n");
309         fprintf(f, "  <style  TYPE=\"text/css\">\n");
310         fprintf(f, "  <!--\n");
311         fprintf(f, "    table.dhcpd-pools {\n");
312         fprintf(f, "      color: black;\n");
313         fprintf(f, "      vertical-align: middle;\n");
314         fprintf(f, "      text-align: center;\n");
315         fprintf(f, "    }\n");
316         fprintf(f, "    table.dhcpd-pools th.section {\n");
317         fprintf(f, "      color: black;\n");
318         fprintf(f, "      font-size: large;\n");
319         fprintf(f, "      vertical-align: middle;\n");
320         fprintf(f, "      text-align: left;\n");
321         fprintf(f, "    }\n");
322         fprintf(f, "    table.dhcpd-pools th.calign {\n");
323         fprintf(f, "      color: black;\n");
324         fprintf(f, "      vertical-align: middle;\n");
325         fprintf(f, "      text-align: center;\n");
326         fprintf(f, "      text-decoration: underline;\n");
327         fprintf(f, "    }\n");
328         fprintf(f, "    table.dhcpd-pools th.ralign {\n");
329         fprintf(f, "      color: black;\n");
330         fprintf(f, "      vertical-align: middle;\n");
331         fprintf(f, "      text-align: right;\n");
332         fprintf(f, "      text-decoration: underline;\n");
333         fprintf(f, "    }\n");
334         fprintf(f, "    table.dhcpd-pools td.calign {\n");
335         fprintf(f, "      color: black;\n");
336         fprintf(f, "      vertical-align: middle;\n");
337         fprintf(f, "      text-align: center;\n");
338         fprintf(f, "    }\n");
339         fprintf(f, "    table.dhcpd-pools td.ralign {\n");
340         fprintf(f, "      color: black;\n");
341         fprintf(f, "      vertical-align: middle;\n");
342         fprintf(f, "      text-align: right;\n");
343         fprintf(f, "    }\n");
344         fprintf(f, "    p.created {\n");
345         fprintf(f, "      font-size: small;\n");
346         fprintf(f, "      color: grey;\n");
347         fprintf(f, "    }\n");
348         fprintf(f, "    p.updated {\n");
349         fprintf(f, "      font-size: small;\n");
350         fprintf(f, "      color: grey;\n");
351         fprintf(f, "      font-style: italic;\n");
352         fprintf(f, "    }\n");
353         fprintf(f, "  -->\n");
354         fprintf(f, "  </style>\n");
355         fprintf(f, "</head>\n");
356         fprintf(f, "<body>\n");
357 }
358
359 void html_footer(FILE * f)
360 {
361         fprintf(f, "<p><br></p>\n");
362         fprintf(f, "<hr>\n");
363         fprintf(f, "<p class=created>\nData generated by ");
364         fprintf(f, "<a href=\"%s\">", PACKAGE_URL);
365         fprintf(f, "dhcpd-pools</a>.\n</p>\n");
366         fprintf(f, "<p class=updated>\n");
367         fprintf(f, "<script type=\"text/javascript\">\n");
368         fprintf(f, "  document.write(\"Last Updated On \" + ");
369         fprintf(f, "document.lastModified + \".\")\n");
370         fprintf(f, "</script>\n<br>\n</p>\n");
371         fprintf(f, "</body>\n");
372         fprintf(f, "</html>\n");
373 }
374
375 void newrow(FILE * f)
376 {
377         fprintf(f, "<tr>\n");
378 }
379
380 void endrow(FILE * f)
381 {
382         fprintf(f, "</tr>\n\n");
383 }
384
385 void output_line(FILE * f, char *type, char *class, char *text)
386 {
387         fprintf(f, "  <%s class=%s>%s</%s>\n", type, class, text, type);
388 }
389
390 void output_long(FILE * f, char *type, unsigned long unlong)
391 {
392         fprintf(f, "  <%s class=ralign>%lu</%s>\n", type, unlong, type);
393 }
394
395 void output_float(FILE * f, char *type, float fl)
396 {
397         fprintf(f, "  <%s class=ralign>%.3f</%s>\n", type, fl, type);
398 }
399
400 void table_start(FILE * f)
401 {
402         fprintf(f, "<table width=\"75%%\" ");
403         fprintf(f, "class=\"dhcpd-pools\" ");
404         fprintf(f, "summary=\"ISC dhcpd pool usage report\">\n");
405 }
406
407 void table_end(FILE * f)
408 {
409         fprintf(f, "</table>\n");
410 }
411
412 void newsection(FILE * f, char *title)
413 {
414         newrow(f);
415         output_line(f, "td", "calign", "&nbsp;");
416         endrow(f);
417         newrow(f);
418         output_line(f, "th", "section", title);
419         endrow(f);
420 }
421
422 int output_html(void)
423 {
424         unsigned int i;
425         struct in_addr first, last;
426         struct range_t *range_p;
427         struct shared_network_t *shared_p;
428         int ret;
429         FILE *outfile;
430         if (config.output_file[0]) {
431                 outfile = fopen(config.output_file, "w+");
432                 if (outfile == NULL) {
433                         err(EXIT_FAILURE, "output_html: %s",
434                             config.output_file);
435                 }
436         } else {
437                 outfile = stdout;
438         }
439
440         range_p = ranges;
441         shared_p = shared_networks;
442         if (fullhtml) {
443                 html_header(outfile);
444         }
445         table_start(outfile);
446         if (config.output_limit[0] & output_limit_bit_1) {
447                 newsection(outfile, "Ranges:");
448                 newrow(outfile);
449                 output_line(outfile, "th", "calign", "shared net name");
450                 output_line(outfile, "th", "calign", "first ip");
451                 output_line(outfile, "th", "calign", "last ip");
452                 output_line(outfile, "th", "ralign", "max");
453                 output_line(outfile, "th", "ralign", "cur");
454                 output_line(outfile, "th", "ralign", "percent");
455                 output_line(outfile, "th", "ralign", "touch");
456                 output_line(outfile, "th", "ralign", "t+c");
457                 output_line(outfile, "th", "ralign", "t+c perc");
458                 if (0 < num_backups) {
459                         output_line(outfile, "th", "ralign", "bu");
460                         output_line(outfile, "th", "ralign", "bu perc");
461                 }
462                 endrow(outfile);
463         }
464         if (config.output_limit[1] & output_limit_bit_1) {
465                 for (i = 0; i < num_ranges; i++) {
466                         first.s_addr = ntohl(range_p->first_ip + 1);
467                         last.s_addr = ntohl(range_p->last_ip - 1);
468                         newrow(outfile);
469                         if (range_p->shared_net) {
470                                 output_line(outfile, "td", "calign",
471                                             range_p->shared_net->name);
472                         } else {
473                                 output_line(outfile, "td", "calign",
474                                             "not_defined");
475                         }
476                         output_line(outfile, "td", "calign",
477                                     inet_ntoa(first));
478                         output_line(outfile, "td", "calign",
479                                     inet_ntoa(last));
480                         output_long(outfile, "td",
481                                     range_p->last_ip - range_p->first_ip -
482                                     1);
483                         output_long(outfile, "td", range_p->count);
484                         output_float(outfile, "td",
485                                      (float) (100 * range_p->count) /
486                                      (range_p->last_ip -
487                                       range_p->first_ip - 1));
488                         output_long(outfile, "td", range_p->touched);
489                         output_long(outfile, "td",
490                                     range_p->touched + range_p->count);
491                         output_float(outfile, "td",
492                                      (float) (100 *
493                                               (range_p->touched +
494                                                range_p->count)) /
495                                      (range_p->last_ip -
496                                       range_p->first_ip - 1));
497                         if (0 < num_backups) {
498                                 output_long(outfile, "td",
499                                             range_p->backups);
500                                 output_float(outfile, "td",
501                                              (float) (100 *
502                                                       range_p->backups) /
503                                              (range_p->last_ip -
504                                               range_p->first_ip - 1));
505                         }
506                         endrow(outfile);
507                         range_p++;
508                 }
509         }
510         table_end(outfile);
511         table_start(outfile);
512         if (config.output_limit[0] & output_limit_bit_2) {
513                 newsection(outfile, "Shared networks:");
514                 newrow(outfile);
515                 output_line(outfile, "th", "calign", "name");
516                 output_line(outfile, "th", "ralign", "max");
517                 output_line(outfile, "th", "ralign", "cur");
518                 output_line(outfile, "th", "ralign", "percent");
519                 output_line(outfile, "th", "ralign", "touch");
520                 output_line(outfile, "th", "ralign", "t+c");
521                 output_line(outfile, "th", "ralign", "t+c perc");
522                 if (0 < num_backups) {
523                         output_line(outfile, "th", "ralign", "bu");
524                         output_line(outfile, "th", "ralign", "bu perc");
525                 }
526                 endrow(outfile);
527         }
528         if (config.output_limit[1] & output_limit_bit_2) {
529                 for (i = 0; i < num_shared_networks; i++) {
530                         shared_p++;
531                         newrow(outfile);
532                         output_line(outfile, "td", "calign",
533                                     shared_p->name);
534                         output_long(outfile, "td", shared_p->available);
535                         output_long(outfile, "td", shared_p->used);
536                         output_float(outfile, "td",
537                                      (float) (100 * shared_p->used) /
538                                      shared_p->available);
539                         output_long(outfile, "td", shared_p->touched);
540                         output_long(outfile, "td",
541                                     shared_p->touched + shared_p->used);
542                         output_float(outfile, "td",
543                                      (float) (100 *
544                                               (shared_p->touched +
545                                                shared_p->used)) /
546                                      shared_p->available);
547                         if (0 < num_backups) {
548                                 output_long(outfile, "td",
549                                             shared_p->backups);
550                                 output_float(outfile, "td",
551                                              (float) (100 *
552                                                       shared_p->backups) /
553                                              shared_p->available);
554                         }
555
556                         endrow(outfile);
557                 }
558         }
559         if (config.output_limit[0] & output_limit_bit_3) {
560                 newsection(outfile, "Sum of all ranges:");
561                 newrow(outfile);
562                 output_line(outfile, "th", "calign", "name");
563                 output_line(outfile, "th", "ralign", "max");
564                 output_line(outfile, "th", "ralign", "cur");
565                 output_line(outfile, "th", "ralign", "percent");
566                 output_line(outfile, "th", "ralign", "touch");
567                 output_line(outfile, "th", "ralign", "t+c");
568                 output_line(outfile, "th", "ralign", "t+c perc");
569                 if (0 < num_backups) {
570                         output_line(outfile, "th", "ralign", "bu");
571                         output_line(outfile, "th", "ralign", "bu perc");
572                 }
573
574                 endrow(outfile);
575         }
576         if (config.output_limit[1] & output_limit_bit_3) {
577                 newrow(outfile);
578                 output_line(outfile, "td", "calign",
579                             shared_networks->name);
580                 output_long(outfile, "td", shared_networks->available);
581                 output_long(outfile, "td", shared_networks->used);
582                 output_float(outfile, "td",
583                              (float) (100 * shared_networks->used) /
584                              shared_networks->available);
585                 output_long(outfile, "td", shared_networks->touched);
586                 output_long(outfile, "td",
587                             shared_networks->touched +
588                             shared_networks->used);
589                 output_float(outfile, "td",
590                              (float) (100 *
591                                       (shared_networks->touched +
592                                        shared_networks->used)) /
593                              shared_networks->available);
594                 if (0 < num_backups) {
595                         output_long(outfile, "td",
596                                     shared_networks->backups);
597                         output_float(outfile, "td",
598                                      (float) (100 *
599                                               shared_networks->backups) /
600                                      shared_networks->available);
601                 }
602                 endrow(outfile);
603         }
604         table_end(outfile);
605         if (fullhtml) {
606                 html_footer(outfile);
607         }
608         if (outfile == stdout) {
609                 ret = fflush(stdout);
610                 if (ret) {
611                         warn("output_html: fflush");
612                 }
613         } else {
614                 ret = fclose(outfile);
615                 if (ret) {
616                         warn("output_html: fclose");
617                 }
618         }
619         return 0;
620 }
621
622 int output_csv(void)
623 {
624         unsigned int i;
625         struct in_addr first, last;
626         struct range_t *range_p;
627         struct shared_network_t *shared_p;
628         FILE *outfile;
629         int ret;
630         if (config.output_file[0]) {
631                 outfile = fopen(config.output_file, "w+");
632                 if (outfile == NULL) {
633                         err(EXIT_FAILURE, "output_csv: %s",
634                             config.output_file);
635                 }
636         } else {
637                 outfile = stdout;
638         }
639
640         range_p = ranges;
641         shared_p = shared_networks;
642         if (config.output_limit[0] & output_limit_bit_1) {
643                 fprintf(outfile, "\"Ranges:\"\n");
644                 fprintf
645                     (outfile,
646                      "\"shared net name\",\"first ip\",\"last ip\",\"max\",\"cur\",\"percent\",\"touch\",\"t+c\",\"t+c perc\"");
647                 if (0 < num_backups) {
648                         fprintf(outfile, ",\"bu\",\"bu perc\"");
649                 }
650                 fprintf(outfile, "\n");
651         }
652         if (config.output_limit[1] & output_limit_bit_1) {
653                 for (i = 0; i < num_ranges; i++) {
654                         first.s_addr = ntohl(range_p->first_ip + 1);
655                         last.s_addr = ntohl(range_p->last_ip - 1);
656                         if (range_p->shared_net) {
657                                 fprintf(outfile, "\"%s\",",
658                                         range_p->shared_net->name);
659                         } else {
660                                 fprintf(outfile, "\"not_defined\",");
661                         }
662                         fprintf(outfile, "\"%s\",", inet_ntoa(first));
663                         fprintf(outfile,
664                                 "\"%s\",\"%lu\",\"%lu\",\"%.3f\",\"%lu\",\"%lu\",\"%.3f\"",
665                                 inet_ntoa(last),
666                                 range_p->last_ip - range_p->first_ip - 1,
667                                 range_p->count,
668                                 (float) (100 * range_p->count) /
669                                 (range_p->last_ip - range_p->first_ip - 1),
670                                 range_p->touched,
671                                 range_p->touched + range_p->count,
672                                 (float) (100 *
673                                          (range_p->touched +
674                                           range_p->count)) /
675                                 (range_p->last_ip - range_p->first_ip -
676                                  1));
677                         if (0 < num_backups) {
678                                 fprintf(outfile, ",\"%lu\",\"%.3f\"",
679                                         range_p->backups,
680                                         (float) (100 * range_p->backups) /
681                                         (range_p->last_ip -
682                                          range_p->first_ip - 1));
683                         }
684
685                         fprintf(outfile, "\n");
686                         range_p++;
687                 }
688                 fprintf(outfile, "\n");
689         }
690         if (config.output_limit[0] & output_limit_bit_2) {
691                 fprintf(outfile, "\"Shared networks:\"\n");
692                 fprintf(outfile,
693                         "\"name\",\"max\",\"cur\",\"percent\",\"touch\",\"t+c\",\"t+c perc\"");
694                 if (0 < num_backups) {
695                         fprintf(outfile, ",\"bu\",\"bu perc\"");
696                 }
697                 fprintf(outfile, "\n");
698         }
699         if (config.output_limit[1] & output_limit_bit_2) {
700
701                 for (i = 0; i < num_shared_networks; i++) {
702                         shared_p++;
703                         fprintf(outfile,
704                                 "\"%s\",\"%lu\",\"%lu\",\"%.3f\",\"%lu\",\"%lu\",\"%.3f\"",
705                                 shared_p->name, shared_p->available,
706                                 shared_p->used,
707                                 (float) (100 * shared_p->used) /
708                                 shared_p->available, shared_p->touched,
709                                 shared_p->touched + shared_p->used,
710                                 (float) (100 *
711                                          (shared_p->touched +
712                                           shared_p->used)) /
713                                 shared_p->available);
714                         if (0 < num_backups) {
715                                 fprintf(outfile, ",\"%lu\",\"%.3f\"",
716                                         shared_p->backups,
717                                         (float) (100 * shared_p->backups) /
718                                         shared_p->available);
719                         }
720
721                         fprintf(outfile, "\n");
722                 }
723                 fprintf(outfile, "\n");
724         }
725         if (config.output_limit[0] & output_limit_bit_3) {
726                 fprintf(outfile, "\"Sum of all ranges:\"\n");
727                 fprintf(outfile,
728                         "\"name\",\"max\",\"cur\",\"percent\",\"touch\",\"t+c\",\"t+c perc\"");
729                 if (0 < num_backups) {
730                         fprintf(outfile, ",\"bu\",\"bu perc\"");
731                 }
732                 fprintf(outfile, "\n");
733         }
734         if (config.output_limit[1] & output_limit_bit_3) {
735
736                 fprintf(outfile,
737                         "\"%s\",\"%lu\",\"%lu\",\"%.3f\",\"%lu\",\"%lu\",\"%.3f\"",
738                         shared_networks->name, shared_networks->available,
739                         shared_networks->used,
740                         (float) (100 * shared_networks->used) /
741                         shared_networks->available,
742                         shared_networks->touched,
743                         shared_networks->touched + shared_networks->used,
744                         (float) (100 *
745                                  (shared_networks->touched +
746                                   shared_networks->used)) /
747                         shared_networks->available);
748                 if (0 < num_backups) {
749                         fprintf(outfile, "%7lu %8.3f",
750                                 shared_networks->backups,
751                                 (float) (100 * shared_networks->backups) /
752                                 shared_networks->available);
753                 }
754                 fprintf(outfile, "\n");
755         }
756         if (outfile == stdout) {
757                 ret = fflush(stdout);
758                 if (ret) {
759                         warn("output_cvs: fflush");
760                 }
761
762         } else {
763                 ret = fclose(outfile);
764                 if (ret) {
765                         warn("output_cvs: fclose");
766                 }
767
768         }
769         return 0;
770 }