1 /* $NetBSD: kod_management.c,v 1.1.1.1 2009/12/13 16:57:10 kardel Exp $ */ 2 3 #include <string.h> 4 #include <sys/types.h> 5 #include <sys/stat.h> 6 7 #include "kod_management.h" 8 #include "log.h" 9 #include "sntp-opts.h" 10 #include "ntp_stdlib.h" 11 #define DEBUG 12 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 */ 16 17 18 /* 19 * Search for a KOD entry 20 */ 21 int 22 search_entry ( 23 char *hostname, 24 struct kod_entry **dst 25 ) 26 { 27 register int a, b, resc = 0; 28 29 for (a = 0; a < kod_db_cnt; a++) 30 if (!strcmp(kod_db[a]->hostname, hostname)) 31 resc++; 32 33 if (!resc) { 34 *dst = NULL; 35 return 0; 36 } 37 38 *dst = emalloc(resc * sizeof(**dst)); 39 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++; 45 } 46 47 return resc; 48 } 49 50 51 void 52 add_entry( 53 char *hostname, 54 char *type /* 4 bytes not \0 terminated */ 55 ) 56 { 57 int n; 58 struct kod_entry *pke; 59 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'; 67 68 /* 69 * insert in address ("hostname") order to find duplicates 70 */ 71 for (n = 0; n < kod_db_cnt; n++) 72 if (strcmp(kod_db[n]->hostname, pke->hostname) >= 0) 73 break; 74 75 if (n < kod_db_cnt && 76 0 == strcmp(kod_db[n]->hostname, pke->hostname)) { 77 kod_db[n]->timestamp = pke->timestamp; 78 return; 79 } 80 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; 87 } 88 89 90 void 91 delete_entry( 92 char *hostname, 93 char *type 94 ) 95 { 96 register int a; 97 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; 102 103 if (a == kod_db_cnt) 104 return; 105 106 free(kod_db[a]); 107 kod_db_cnt--; 108 109 if (a < kod_db_cnt) 110 memmove(&kod_db[a], &kod_db[a + 1], 111 (kod_db_cnt - a) * sizeof(kod_db[0])); 112 } 113 114 115 void 116 write_kod_db(void) 117 { 118 FILE *db_s; 119 char *pch; 120 int dirmode; 121 register int a; 122 123 db_s = fopen(kod_db_file, "w"); 124 125 /* 126 * If opening fails, blindly attempt to create each directory 127 * in the path first, then retry the open. 128 */ 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); 139 } 140 db_s = fopen(kod_db_file, "w"); 141 } 142 143 if (NULL == db_s) { 144 char msg[80]; 145 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); 153 154 return; 155 } 156 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); 161 } 162 163 fflush(db_s); 164 fclose(db_s); 165 } 166 167 168 void 169 kod_init_kod_db( 170 const char *db_file 171 ) 172 { 173 /* 174 * Max. of 254 characters for hostname, 10 for timestamp, 4 for 175 * kisscode, 2 for spaces, 1 for \n, and 1 for \0 176 */ 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; 183 184 atexit(write_kod_db); 185 186 #ifdef DEBUG 187 printf("Initializing KOD DB...\n"); 188 #endif 189 190 kod_db_file = estrdup(db_file); 191 192 193 db_s = fopen(db_file, "r"); 194 195 if (NULL == db_s) { 196 char msg[80]; 197 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); 204 205 return; 206 } 207 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 */ 211 212 while (!feof(db_s) && NULL != fgets(fbuf, sizeof(fbuf), db_s)) { 213 214 /* ignore blank lines */ 215 if ('\n' == fbuf[0]) 216 continue; 217 218 sepc = 0; 219 len = strlen(fbuf); 220 for (a = 0; a < len; a++) { 221 if (' ' == fbuf[a]) 222 sepc++; 223 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); 236 } 237 fclose(db_s); 238 return; 239 } 240 sepc = 0; 241 kod_db_cnt++; 242 } 243 } 244 } 245 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; 252 } 253 254 #ifdef DEBUG 255 printf("KoD DB %s contains %d entries, reading...\n", db_file, kod_db_cnt); 256 #endif 257 258 rewind(db_s); 259 260 kod_db = emalloc(sizeof(kod_db[0]) * kod_db_cnt); 261 262 /* Read contents of file */ 263 for (b = 0; 264 !feof(db_s) && !ferror(db_s) && b < kod_db_cnt; 265 b++) { 266 267 str_ptr = fgets(fbuf, sizeof(fbuf), db_s); 268 if (NULL == str_ptr) { 269 error = 1; 270 break; 271 } 272 273 /* ignore blank lines */ 274 if ('\n' == fbuf[0]) { 275 b--; 276 continue; 277 } 278 279 kod_db[b] = emalloc(sizeof(*kod_db[b])); 280 281 if (3 != sscanf(fbuf, "%llx %4s %254s", &ull, 282 kod_db[b]->type, kod_db[b]->hostname)) { 283 284 free(kod_db[b]); 285 kod_db[b] = NULL; 286 error = 1; 287 break; 288 } 289 290 kod_db[b]->timestamp = (time_t)ull; 291 } 292 293 if (ferror(db_s) || error) { 294 char msg[80]; 295 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); 303 304 return; 305 } 306 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 315 } 316