Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / bsd / ntp / dist / sntp / kod_management.c
blob87097db7bb17a93b8c32f311f6e250292582e443
1 /* $NetBSD$ */
3 #include <string.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
7 #include "kod_management.h"
8 #include "log.h"
9 #include "sntp-opts.h"
10 #include "ntp_stdlib.h"
11 #define DEBUG
13 int kod_init = 0, kod_db_cnt = 0;
14 const char *kod_db_file;
15 struct kod_entry **kod_db; /* array of pointers to kod_entry */
19 * Search for a KOD entry
21 int
22 search_entry (
23 char *hostname,
24 struct kod_entry **dst
27 register int a, b, resc = 0;
29 for (a = 0; a < kod_db_cnt; a++)
30 if (!strcmp(kod_db[a]->hostname, hostname))
31 resc++;
33 if (!resc) {
34 *dst = NULL;
35 return 0;
38 *dst = emalloc(resc * sizeof(**dst));
40 b = 0;
41 for (a = 0; a < kod_db_cnt; a++)
42 if (!strcmp(kod_db[a]->hostname, hostname)) {
43 (*dst)[b] = *kod_db[a];
44 b++;
47 return resc;
51 void
52 add_entry(
53 char *hostname,
54 char *type /* 4 bytes not \0 terminated */
57 int n;
58 struct kod_entry *pke;
60 pke = emalloc(sizeof(*pke));
61 pke->timestamp = time(NULL);
62 memcpy(pke->type, type, 4);
63 pke->type[sizeof(pke->type) - 1] = '\0';
64 strncpy(pke->hostname, hostname,
65 sizeof(pke->hostname));
66 pke->hostname[sizeof(pke->hostname) - 1] = '\0';
69 * insert in address ("hostname") order to find duplicates
71 for (n = 0; n < kod_db_cnt; n++)
72 if (strcmp(kod_db[n]->hostname, pke->hostname) >= 0)
73 break;
75 if (n < kod_db_cnt &&
76 0 == strcmp(kod_db[n]->hostname, pke->hostname)) {
77 kod_db[n]->timestamp = pke->timestamp;
78 return;
81 kod_db_cnt++;
82 kod_db = erealloc(kod_db, kod_db_cnt * sizeof(kod_db[0]));
83 if (n != kod_db_cnt - 1)
84 memmove(&kod_db[n + 1], &kod_db[n],
85 sizeof(kod_db[0]) * ((kod_db_cnt - 1) - n));
86 kod_db[n] = pke;
90 void
91 delete_entry(
92 char *hostname,
93 char *type
96 register int a;
98 for (a = 0; a < kod_db_cnt; a++)
99 if (!strcmp(kod_db[a]->hostname, hostname)
100 && !strcmp(kod_db[a]->type, type))
101 break;
103 if (a == kod_db_cnt)
104 return;
106 free(kod_db[a]);
107 kod_db_cnt--;
109 if (a < kod_db_cnt)
110 memmove(&kod_db[a], &kod_db[a + 1],
111 (kod_db_cnt - a) * sizeof(kod_db[0]));
115 void
116 write_kod_db(void)
118 FILE *db_s;
119 char *pch;
120 int dirmode;
121 register int a;
123 db_s = fopen(kod_db_file, "w");
126 * If opening fails, blindly attempt to create each directory
127 * in the path first, then retry the open.
129 if (NULL == db_s && strlen(kod_db_file)) {
130 dirmode = S_IRUSR | S_IWUSR | S_IXUSR
131 | S_IRGRP | S_IXGRP
132 | S_IROTH | S_IXOTH;
133 pch = strchr(kod_db_file + 1, DIR_SEP);
134 while (NULL != pch) {
135 *pch = '\0';
136 mkdir(kod_db_file, dirmode);
137 *pch = DIR_SEP;
138 pch = strchr(pch + 1, DIR_SEP);
140 db_s = fopen(kod_db_file, "w");
143 if (NULL == db_s) {
144 char msg[80];
146 snprintf(msg, sizeof(msg),
147 "Can't open KOD db file %s for writing!",
148 kod_db_file);
149 #ifdef DEBUG
150 debug_msg(msg);
151 #endif
152 log_msg(msg, 2);
154 return;
157 for (a = 0; a < kod_db_cnt; a++) {
158 fprintf(db_s, "%16.16llx %s %s\n", (unsigned long long)
159 kod_db[a]->timestamp, kod_db[a]->type,
160 kod_db[a]->hostname);
163 fflush(db_s);
164 fclose(db_s);
168 void
169 kod_init_kod_db(
170 const char *db_file
174 * Max. of 254 characters for hostname, 10 for timestamp, 4 for
175 * kisscode, 2 for spaces, 1 for \n, and 1 for \0
177 char fbuf[254+10+4+2+1+1];
178 FILE *db_s;
179 int a, b, sepc, len;
180 unsigned long long ull;
181 char *str_ptr;
182 char error = 0;
184 atexit(write_kod_db);
186 #ifdef DEBUG
187 printf("Initializing KOD DB...\n");
188 #endif
190 kod_db_file = estrdup(db_file);
193 db_s = fopen(db_file, "r");
195 if (NULL == db_s) {
196 char msg[80];
198 snprintf(msg, sizeof(msg), "kod_init_kod_db(): Cannot open KoD db file %s", db_file);
199 #ifdef DEBUG
200 debug_msg(msg);
201 printf("%s\n", msg);
202 #endif
203 log_msg(msg, 2);
205 return;
208 if (ENABLED_OPT(NORMALVERBOSE))
209 printf("Starting to read KoD file %s...\n", db_file);
210 /* First let's see how many entries there are and check for right syntax */
212 while (!feof(db_s) && NULL != fgets(fbuf, sizeof(fbuf), db_s)) {
214 /* ignore blank lines */
215 if ('\n' == fbuf[0])
216 continue;
218 sepc = 0;
219 len = strlen(fbuf);
220 for (a = 0; a < len; a++) {
221 if (' ' == fbuf[a])
222 sepc++;
224 if ('\n' == fbuf[a]) {
225 if (sepc != 2) {
226 if (strcmp(db_file, "/dev/null")) {
227 char msg[80];
228 snprintf(msg, sizeof(msg),
229 "Syntax error in KoD db file %s in line %i (missing space)",
230 db_file, kod_db_cnt + 1);
231 #ifdef DEBUG
232 debug_msg(msg);
233 printf("%s\n", msg);
234 #endif
235 log_msg(msg, 1);
237 fclose(db_s);
238 return;
240 sepc = 0;
241 kod_db_cnt++;
246 if (0 == kod_db_cnt) {
247 #ifdef DEBUG
248 printf("KoD DB %s empty.\n", db_file);
249 #endif
250 fclose(db_s);
251 return;
254 #ifdef DEBUG
255 printf("KoD DB %s contains %d entries, reading...\n", db_file, kod_db_cnt);
256 #endif
258 rewind(db_s);
260 kod_db = emalloc(sizeof(kod_db[0]) * kod_db_cnt);
262 /* Read contents of file */
263 for (b = 0;
264 !feof(db_s) && !ferror(db_s) && b < kod_db_cnt;
265 b++) {
267 str_ptr = fgets(fbuf, sizeof(fbuf), db_s);
268 if (NULL == str_ptr) {
269 error = 1;
270 break;
273 /* ignore blank lines */
274 if ('\n' == fbuf[0]) {
275 b--;
276 continue;
279 kod_db[b] = emalloc(sizeof(*kod_db[b]));
281 if (3 != sscanf(fbuf, "%llx %4s %254s", &ull,
282 kod_db[b]->type, kod_db[b]->hostname)) {
284 free(kod_db[b]);
285 kod_db[b] = NULL;
286 error = 1;
287 break;
290 kod_db[b]->timestamp = (time_t)ull;
293 if (ferror(db_s) || error) {
294 char msg[80];
296 kod_db_cnt = b;
297 snprintf(msg, sizeof(msg), "An error occured while parsing the KoD db file %s", db_file);
298 #ifdef DEBUG
299 debug_msg(msg);
300 #endif
301 log_msg(msg, 2);
302 fclose(db_s);
304 return;
307 fclose(db_s);
308 #ifdef DEBUG
309 for (a = 0; a < kod_db_cnt; a++)
310 printf("KoD entry %d: %s at %llx type %s\n", a,
311 kod_db[a]->hostname,
312 (unsigned long long)kod_db[a]->timestamp,
313 kod_db[a]->type);
314 #endif