prepare_memory bug: initialization missing
[debian/dhcpd-pools.git] / src / dhcpd-pools.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 #ifdef  HAVE_STDLIB_H
24 #include <stdlib.h>
25 #else                           /* Not STDC_HEADERS */
26 extern char *malloc();
27 #endif                          /* STDC_HEADERS */
28 #ifdef  HAVE_STRING_H
29 #include <string.h>
30 #else
31 #include <strings.h>
32 #endif
33 #include <err.h>
34 #include <errno.h>
35 #include <getopt.h>
36
37 #include "defaults.h"
38 #include "dhcpd-pools.h"
39
40 int main(int argc, char **argv)
41 {
42         int i, c, sorts = 0;
43         int option_index = 0;
44         char *tmp;
45         struct range_t *tmp_ranges;
46
47         /* Options for getopt_long */
48         static struct option const long_options[] = {
49                 {"config", required_argument, 0, (int) 'c'},
50                 {"leases", required_argument, 0, (int) 'l'},
51                 {"format", required_argument, 0, (int) 'f'},
52                 {"sort", required_argument, 0, (int) 's'},
53                 {"reverse", no_argument, 0, (int) 'r'},
54                 {"output", required_argument, 0, (int) 'o'},
55                 {"limit", required_argument, 0, (int) 'L'},
56                 {"version", no_argument, 0, (int) 'v'},
57                 {"help", no_argument, 0, (int) 'h'},
58                 {0, 0, 0, 0}
59         };
60
61         /* FIXME: make these allocations dynamic up on need. */
62         config.dhcpdconf_file = safe_malloc(sizeof(char) * MAXLEN);
63         config.dhcpdlease_file = safe_malloc(sizeof(char) * MAXLEN);
64         config.output_file = safe_malloc(sizeof(char) * MAXLEN);
65
66         /* Make sure string has zero lenght if there is no
67          * command line option */
68         config.output_file[0] = '\0';
69
70         /* File location defaults */
71         strncpy(config.dhcpdconf_file, DHCPDCONF_FILE,
72                 (size_t) MAXLEN - 1);
73         strncpy(config.dhcpdlease_file, DHCPDLEASE_FILE,
74                 (size_t) MAXLEN - 1);
75         tmp = OUTPUT_LIMIT;
76         config.output_limit[0] = (int) (*tmp - '0');
77         tmp++;
78         config.output_limit[1] = (int) (*tmp - '0');
79         fullhtml = false;
80
81         /* Make sure some output format is selected by default */
82         strncpy(config.output_format, OUTPUT_FORMAT, (size_t) 1);
83
84         /* Default sort order is by IPs small to big */
85         config.reverse_order = false;
86
87         /* Parse command line options */
88         while (1) {
89                 c = getopt_long(argc, argv, "c:l:f:o:s:rL:vh",
90                                 long_options, &option_index);
91
92                 if (c == EOF)
93                         break;
94
95                 switch (c) {
96                 case 'c':
97                         /* config file */
98                         strncpy(config.dhcpdconf_file, optarg,
99                                 (size_t) MAXLEN - 1);
100                         break;
101                 case 'l':
102                         /* lease file */
103                         strncpy(config.dhcpdlease_file, optarg,
104                                 (size_t) MAXLEN - 1);
105                         break;
106                 case 'f':
107                         /* Output format */
108                         strncpy(config.output_format, optarg, (size_t) 1);
109                         break;
110                 case 's':
111                         /* Output sorting option */
112                         sorts = strlen(optarg);
113                         if (5 < sorts) {
114                                 warnx
115                                     ("main: only first 5 sort orders will be used");
116                                 strncpy(config.sort, optarg, (size_t) 5);
117                                 sorts = 5;
118                         } else {
119                                 strncpy(config.sort, optarg,
120                                         (size_t) sorts);
121                         }
122                         for (i = 0; i < sorts; i++) {
123                                 field_selector(config.sort[i]);
124                         }
125                         break;
126                 case 'r':
127                         /* What ever sort in reverse order */
128                         config.reverse_order = true;
129                         break;
130                 case 'o':
131                         /* Output file */
132                         strncpy(config.output_file, optarg,
133                                 (size_t) MAXLEN - 1);
134                         break;
135                 case 'L':
136                         /* Specification what will be printed */
137                         for (i = 0; i < 2; i++) {
138                                 if (optarg[i] >= '0' && optarg[i] < '8') {
139                                         config.output_limit[i] =
140                                             (int) optarg[i] - '0';
141                                 } else {
142                                         errx(EXIT_FAILURE,
143                                              "main: output mask `%s' is illegal",
144                                              optarg);
145                                 }
146                         }
147                         break;
148                 case 'v':
149                         /* Print version */
150                         print_version();
151                 case 'h':
152                         /* Print help */
153                         usage(EXIT_SUCCESS);
154                 default:
155                         errx(EXIT_FAILURE,
156                              "Try `%s --help' for more information.",
157                              program_invocation_short_name);
158                 }
159         }
160
161         /* Output function selection */
162         switch (config.output_format[0]) {
163         case 't':
164                 output_analysis = output_txt;
165                 break;
166         case 'h':
167                 output_analysis = output_html;
168                 break;
169         case 'H':
170                 output_analysis = output_html;
171                 fullhtml = true;
172                 break;
173         case 'x':
174                 output_analysis = output_xml;
175                 break;
176         case 'X':
177                 output_analysis = output_xml;
178                 break;
179         case 'c':
180                 output_analysis = output_csv;
181                 break;
182         default:
183                 errx(EXIT_FAILURE, "main: unknown output format `%c'",
184                      config.output_format[0]);
185         }
186
187         /* Do the job */
188         prepare_memory();
189         parse_config(true, config.dhcpdconf_file, shared_networks);
190
191         parse_leases();
192         prepare_data();
193         do_counting();
194         tmp_ranges = safe_malloc(sizeof(struct range_t) * num_ranges);
195         if (sorts != 0) {
196                 mergesort_ranges(ranges, num_ranges, tmp_ranges);
197         }
198         if (config.reverse_order == true) {
199                 flip_ranges(ranges, tmp_ranges);
200         }
201         free(tmp_ranges);
202         output_analysis();
203
204         clean_up();
205         return (EXIT_SUCCESS);
206 }
207
208 /* Global allocations, counter resets etc */
209 int prepare_memory()
210 {
211         RANGES = 64;
212         num_ranges = num_shared_networks = 0;
213         shared_networks =
214             safe_malloc(sizeof(struct shared_network_t) * SHARED_NETWORKS);
215
216         ranges = safe_malloc(sizeof(struct range_t) * RANGES);
217         macaddr = NULL;
218
219         /* First shared network entry is all networks */
220         shared_networks->name = safe_strdup("All networks");
221         shared_networks->used = 0;
222         shared_networks->touched = 0;
223         shared_networks->backups = 0;
224
225         return 0;
226 }