Debianization, and minor fixes.
[fastforward] / setforward.c
CommitLineData
8d5530c4
MW
1#include "substdio.h"
2#include "subfd.h"
3#include "strerr.h"
4#include "stralloc.h"
5#include "open.h"
6#include "case.h"
7#include "readwrite.h"
8#include "cdbmss.h"
9
10#define FATAL "setforward: fatal: "
11
12void usage()
13{
14 strerr_die1x(100,"setforward: usage: setforward data.cdb data.tmp");
15}
16void nomem()
17{
18 strerr_die2x(111,FATAL,"out of memory");
19}
20void missingsemicolon()
21{
22 strerr_die2x(100,FATAL,"final instruction must end with semicolon");
23}
24void extracolon()
25{
26 strerr_die2x(100,FATAL,"double colons are not permitted");
27}
28void extracomma()
29{
30 strerr_die2x(100,FATAL,"commas are not permitted before colons");
31}
32void nulbyte()
33{
34 strerr_die2x(100,FATAL,"NUL bytes are not permitted");
35}
36void longaddress()
37{
38 strerr_die2x(100,FATAL,"addresses over 800 bytes are not permitted");
39}
40
41char *fncdb;
42char *fntmp;
43int fd;
44struct cdbmss cdbmss;
45stralloc key = {0};
46
47stralloc target = {0}; /* always initialized; no NUL */
48stralloc command = {0}; /* always initialized; no NUL */
49stralloc instr = {0}; /* always initialized */
50
51int flagtarget = 0;
52/* 0: reading target; command is empty; instr is empty */
53/* 1: target is complete; instr still has to be written; reading command */
54
55void writeerr()
56{
57 strerr_die4sys(111,FATAL,"unable to write to ",fntmp,": ");
58}
59
60void doit(prepend,data,datalen)
61char *prepend;
62char *data;
63int datalen;
64{
65 if (!stralloc_copys(&key,prepend)) nomem();
66 if (!stralloc_cat(&key,&target)) nomem();
67 case_lowerb(key.s,key.len);
68 if (cdbmss_add(&cdbmss,key.s,key.len,data,datalen) == -1)
69 writeerr();
70}
71
72int getch(ch)
73char *ch;
74{
75 int r;
76
77 r = substdio_get(subfdinsmall,ch,1);
78 if (r == -1)
79 strerr_die2sys(111,FATAL,"unable to read input: ");
80 return r;
81}
82
83void main(argc,argv)
84int argc;
85char **argv;
86{
87 char ch;
88 int r;
89
90 if (!stralloc_copys(&target,"")) nomem();
91 if (!stralloc_copys(&command,"")) nomem();
92 if (!stralloc_copys(&instr,"")) nomem();
93
94 fncdb = argv[1]; if (!fncdb) usage();
95 fntmp = argv[2]; if (!fntmp) usage();
96
97 fd = open_trunc(fntmp);
98 if (fd == -1)
99 strerr_die4sys(111,FATAL,"unable to create ",fntmp,": ");
100
101 if (cdbmss_start(&cdbmss,fd) == -1) writeerr();
102
103 for (;;) {
104 if (!getch(&ch)) goto eof;
105
106 if (ch == '#') {
107 while (ch != '\n') if (!getch(&ch)) goto eof;
108 continue;
109 }
110
111 if (ch == ' ') continue;
112 if (ch == '\n') continue;
113 if (ch == '\t') continue;
114
115 if (ch == ':') {
116 if (flagtarget) extracolon();
117 flagtarget = 1;
118 continue;
119 }
120
121 if ((ch == ',') || (ch == ';')) {
122 if (!flagtarget) extracomma();
123 if (command.len) {
124 if (command.s[0] == '?') {
125 doit("?",command.s + 1,command.len - 1);
126 }
127 else if ((command.s[0] == '|') || (command.s[0] == '!')) {
128 if (!stralloc_cat(&instr,&command)) nomem();
129 if (!stralloc_0(&instr)) nomem();
130 }
131 else if ((command.s[0] == '.') || (command.s[0] == '/')) {
132 if (!stralloc_cat(&instr,&command)) nomem();
133 if (!stralloc_0(&instr)) nomem();
134 }
135 else {
136 if (command.len > 800) longaddress();
137 if (command.s[0] != '&')
138 if (!stralloc_cats(&instr,"&")) nomem();
139 if (!stralloc_cat(&instr,&command)) nomem();
140 if (!stralloc_0(&instr)) nomem();
141 }
142 }
143
144 if (!stralloc_copys(&command,"")) nomem();
145
146 if (ch == ';') {
147 if (instr.len)
148 doit(":",instr.s,instr.len);
149
150 if (!stralloc_copys(&target,"")) nomem();
151 if (!stralloc_copys(&instr,"")) nomem();
152 flagtarget = 0;
153 }
154 continue;
155 }
156
157 if (ch == '\\') if (!getch(&ch)) goto eof;
158 if (ch == 0) nulbyte();
159 if (!stralloc_append(flagtarget ? &command : &target,&ch)) nomem();
160 }
161
162 eof:
163 if (flagtarget || target.len)
164 missingsemicolon();
165
166 if (cdbmss_finish(&cdbmss) == -1) writeerr();
167 if (fsync(fd) == -1) writeerr();
168 if (close(fd) == -1) writeerr(); /* NFS stupidity */
169
170 if (rename(fntmp,fncdb) == -1)
171 strerr_die6sys(111,FATAL,"unable to move ",fntmp," to ",fncdb,": ");
172
173 _exit(0);
174}