1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <unistd.h>
5 #include "buffer.h"
6 #include "exit.h"
7 #include "cdb_make.h"
8 #include "open.h"
9 #include "stralloc.h"
10 #include "getln.h"
11 #include "strerr.h"
12 #include "byte.h"
13 #include "scan.h"
14 #include "fmt.h"
15 #include "ip4.h"
16 
17 #define FATAL "rbldns-data: fatal: "
18 
nomem(void)19 void nomem(void)
20 {
21   strerr_die2x(111,FATAL,"out of memory");
22 }
23 
24 int fd;
25 buffer b;
26 char bspace[1024];
27 
28 int fdcdb;
29 struct cdb_make cdb;
30 static stralloc tmp;
31 
32 static stralloc line;
33 int match = 1;
34 unsigned long linenum = 0;
35 
36 char strnum[FMT_ULONG];
37 
syntaxerror(const char * why)38 void syntaxerror(const char *why)
39 {
40   strnum[fmt_ulong(strnum,linenum)] = 0;
41   strerr_die4x(111,FATAL,"unable to parse data line ",strnum,why);
42 }
die_datatmp(void)43 void die_datatmp(void)
44 {
45   strerr_die2sys(111,FATAL,"unable to create data.tmp: ");
46 }
47 
main()48 int main()
49 {
50   char ip[4];
51   unsigned long u;
52   unsigned int j;
53   unsigned int k;
54   char ch;
55 
56   umask(022);
57 
58   fd = open_read("data");
59   if (fd == -1) strerr_die2sys(111,FATAL,"unable to open data: ");
60   buffer_init(&b,buffer_unixread,fd,bspace,sizeof bspace);
61 
62   fdcdb = open_trunc("data.tmp");
63   if (fdcdb == -1) die_datatmp();
64   if (cdb_make_start(&cdb,fdcdb) == -1) die_datatmp();
65 
66   while (match) {
67     ++linenum;
68     if (getln(&b,&line,&match,'\n') == -1)
69       strerr_die2sys(111,FATAL,"unable to read line: ");
70 
71     while (line.len) {
72       ch = line.s[line.len - 1];
73       if ((ch != ' ') && (ch != '\t') && (ch != '\n')) break;
74       --line.len;
75     }
76     if (!line.len) continue;
77 
78     switch(line.s[0]) {
79       default:
80 	syntaxerror(": unrecognized leading character");
81       case '#':
82 	break;
83       case ':':
84 	j = byte_chr(line.s + 1,line.len - 1,':');
85 	if (j >= line.len - 1) syntaxerror(": missing colon");
86 	if (ip4_scan(line.s + 1,ip) != j) syntaxerror(": malformed IP address");
87 	if (!stralloc_copyb(&tmp,ip,4)) nomem();
88 	if (!stralloc_catb(&tmp,line.s + j + 2,line.len - j - 2)) nomem();
89         if (cdb_make_add(&cdb,"",0,tmp.s,tmp.len) == -1)
90           die_datatmp();
91         break;
92       case '0': case '1': case '2': case '3': case '4':
93       case '5': case '6': case '7': case '8': case '9':
94 	if (!stralloc_0(&line)) nomem();
95 	j = 0;
96 	if (!stralloc_copys(&tmp,"")) nomem();
97 	for (;;) {
98 	  k = scan_ulong(line.s + j,&u);
99 	  if (!k) break;
100 	  ch = u;
101 	  if (!stralloc_catb(&tmp,&ch,1)) nomem();
102 	  j += k;
103 	  if (line.s[j] != '.') break;
104 	  ++j;
105 	}
106 	if (!stralloc_catb(&tmp,"\0\0\0\0",4)) nomem();
107 	tmp.len = 4;
108 	if (line.s[j] == '/')
109 	  scan_ulong(line.s + j + 1,&u);
110 	else
111 	  u = 32;
112 	if (u > 32) u = 32;
113 	ch = u;
114 	if (!stralloc_catb(&tmp,&ch,1)) nomem();
115         if (cdb_make_add(&cdb,tmp.s,tmp.len,"",0) == -1)
116           die_datatmp();
117 	break;
118     }
119   }
120 
121   if (cdb_make_finish(&cdb) == -1) die_datatmp();
122   if (fsync(fdcdb) == -1) die_datatmp();
123   if (close(fdcdb) == -1) die_datatmp(); /* NFS stupidity */
124   if (rename("data.tmp","data.cdb") == -1)
125     strerr_die2sys(111,FATAL,"unable to move data.tmp to data.cdb: ");
126 
127   _exit(0);
128 }
129