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