s/qmail 4.3.20
Next generation secure email transport
Loading...
Searching...
No Matches
newinclude.c
Go to the documentation of this file.
1#include <sys/stat.h>
2#include <unistd.h>
3#include <stdio.h> // rename
4#include "buffer.h"
5#include "logmsg.h"
6#include "genalloc.h"
7#include "stralloc.h"
8#include "getln.h"
9#include "open.h"
10#include "token822.h"
11#include "control.h"
12#include "auto_qmail.h"
13#include "byte.h"
14#include "env.h"
15#include "qmail.h"
16
17#define WHO "newinclude"
18
19// int rename(const char *,const char *); // stdio.h
20
21static void nomem()
22{
23 logmsg(WHO,111,FATAL,"out of memory");
24}
25static void usage()
26{
27 logmsg(WHO,100,USAGE,"newinclude list");
28}
29
30char *fnlist;
32buffer bi;
33
34stralloc bin = {0};
35#define fnbin bin.s
36stralloc tmp = {0};
37#define fntmp tmp.s
39buffer bt;
40
41
42static void readerr()
43{
44 logmsg(WHO,111,FATAL,B("unable to read: ",fnlist));
45}
47{
48 logmsg(WHO,111,FATAL,B("unable to write to ",fntmp));
49}
50
51static void out(char *s,int len)
52{
53 if (buffer_put(&bt,s,len) == -1) writeerr();
54}
55
56static void doincl(char *buf,int len)
57{
58 if (!len)
59 logmsg(WHO,111,FATAL,"empty :include: filenames not permitted");
60 if (byte_chr(buf,len,'\n') != len)
61 logmsg(WHO,111,FATAL,"newlines not permitted in :include: filenames");
62 if (byte_chr(buf,len,'\0') != len)
63 logmsg(WHO,111,FATAL,"NUL not permitted in :include: filenames");
64 if ((buf[0] != '.') && (buf[0] != '/'))
65 out("./",2);
66 out(buf,len);
67 out("",1);
68}
69
70static void dorecip(char *buf,int len)
71{
72 if (!len)
73 logmsg(WHO,111,FATAL,"empty recipient addresses not permitted");
74 if (byte_chr(buf,len,'\n') != len)
75 logmsg(WHO,111,FATAL,"newlines not permitted in recipient addresses");
76 if (byte_chr(buf,len,'\0') != len)
77 logmsg(WHO,111,FATAL,"NUL not permitted in recipient addresses");
78 if (len > 800)
79 logmsg(WHO,111,FATAL,"addresses must be under 800 bytes");
80 if ((buf[len - 1] == ' ') || (buf[len - 1] == '\t'))
81 logmsg(WHO,111,FATAL,"spaces and tabs not permitted at ends of addresses");
82 out("&",1);
83 out(buf,len);
84 out("",1);
85}
86
87
88static void die_control()
89{
90 logmsg(WHO,111,FATAL,"unable to read controls");
91}
92
93stralloc me = {0};
94stralloc defaulthost = {0};
95stralloc defaultdomain = {0};
96stralloc plusdomain = {0};
97
99{
100 int r;
101 int fddir;
102 char *x;
103
104 fddir = open_read(".");
105 if (fddir == -1)
106 logmsg(WHO,111,FATAL,"unable to open current directory");
107
108 if (chdir(auto_qmail) == -1)
109 logmsg(WHO,111,FATAL,B("unable to chdir to: ",auto_qmail));
110
111 r = control_readline(&me,"control/me");
112 if (r == -1) die_control();
113 if (!r) if (!stralloc_copys(&me,"me")) nomem();
114
115 r = control_readline(&defaultdomain,"control/defaultdomain");
116 if (r == -1) die_control();
117 if (!r) if (!stralloc_copy(&defaultdomain,&me)) nomem();
118 x = env_get("QMAILDEFAULTDOMAIN");
119 if (x) if (!stralloc_copys(&defaultdomain,x)) nomem();
120
121 r = control_readline(&defaulthost,"control/defaulthost");
122 if (r == -1) die_control();
123 if (!r) if (!stralloc_copy(&defaulthost,&me)) nomem();
124 x = env_get("QMAILDEFAULTHOST");
125 if (x) if (!stralloc_copys(&defaulthost,x)) nomem();
126
127 r = control_readline(&plusdomain,"control/plusdomain");
128 if (r == -1) die_control();
129 if (!r) if (!stralloc_copy(&plusdomain,&me)) nomem();
130 x = env_get("QMAILPLUSDOMAIN");
131 if (x) if (!stralloc_copys(&plusdomain,x)) nomem();
132
133 if (fchdir(fddir) == -1)
134 logmsg(WHO,111,FATAL,"unable to set current directory");
135}
136
137stralloc cbuf = {0};
138token822_alloc toks = {0};
139token822_alloc tokaddr = {0};
140stralloc address = {0};
141
142static void gotincl()
143{
145 if (token822_unquote(&address,&tokaddr) != 1) nomem();
146 tokaddr.len = 0;
147 doincl(address.s,address.len);
148}
149
150static void gotaddr()
151{
152 int i;
153 int j;
154 int flaghasat;
155
157 if (token822_unquote(&address,&tokaddr) != 1) nomem();
158
159 flaghasat = 0;
160 for (i = 0;i < tokaddr.len;++i)
161 if (tokaddr.t[i].type == TOKEN822_AT)
162 flaghasat = 1;
163
164 tokaddr.len = 0;
165
166 if (!address.len) return;
167
168 if (!flaghasat)
169 if (address.s[0] == '/') {
170 if (!stralloc_0(&address)) nomem();
171 logmsg(WHO,111,FATAL,B("file delivery for ",address.s," not supported"));
172 }
173 if (!flaghasat)
174 if (address.s[0] == '|') {
175 if (!stralloc_0(&address)) nomem();
176 logmsg(WHO,111,FATAL,B("program delivery for ",address.s," not supported"));
177 }
178
179 if (!flaghasat) {
180 if (!stralloc_cats(&address,"@")) nomem();
181 if (!stralloc_cat(&address,&defaulthost)) nomem();
182 }
183 if (address.s[address.len - 1] == '+') {
184 address.s[address.len - 1] = '.';
185 if (!stralloc_cat(&address,&plusdomain)) nomem();
186 }
187 j = 0;
188 for (i = 0;i < address.len;++i) if (address.s[i] == '@') j = i;
189 for (i = j;i < address.len;++i) if (address.s[i] == '.') break;
190 if (i == address.len) {
191 if (!stralloc_cats(&address,".")) nomem();
192 if (!stralloc_cat(&address,&defaultdomain)) nomem();
193 }
194
195 dorecip(address.s,address.len);
196}
197
198
199stralloc line = {0};
201
202static void parseerr()
203{
204 if (!stralloc_0(&line)) nomem();
205 logmsg(WHO,111,FATAL,B("unable to parse this line: ",line.s));
206}
207
208static void parseline()
209{
210 int wordok;
211 struct token822 *t;
212 struct token822 *beginning;
213
214 switch (token822_parse(&toks,&line,&cbuf)) {
215 case -1: nomem();
216 case 0: parseerr();
217 }
218
219 beginning = toks.t;
220 t = toks.t + toks.len;
221 wordok = 1;
222
223 if (!token822_readyplus(&tokaddr,1)) nomem();
224 tokaddr.len = 0;
225
226 while (t > beginning)
227 switch ((--t)->type) {
228 case TOKEN822_SEMI:
229 break; /*XXX*/
230 case TOKEN822_COLON:
231 if (t >= beginning + 2)
232 if (t[-2].type == TOKEN822_COLON)
233 if (t[-1].type == TOKEN822_ATOM)
234 if (t[-1].slen == 7)
235 if (!byte_diff(t[-1].s,7,"include")) {
236 gotincl();
237 t -= 2;
238 }
239 break; /*XXX*/
240 case TOKEN822_RIGHT:
241 if (tokaddr.len) gotaddr();
242 while ((t > beginning) && (t[-1].type != TOKEN822_LEFT))
243 if (!token822_append(&tokaddr,--t)) nomem();
244 gotaddr();
245 if (t <= beginning) parseerr();
246 --t;
247 while ((t > beginning) && ((t[-1].type == TOKEN822_COMMENT) || (t[-1].type == TOKEN822_ATOM) || (t[-1].type == TOKEN822_QUOTE) || (t[-1].type == TOKEN822_AT) || (t[-1].type == TOKEN822_DOT)))
248 --t;
249 wordok = 0;
250 continue;
252 if (!wordok) if (tokaddr.len) gotaddr();
253 wordok = 0;
254 if (!token822_append(&tokaddr,t)) nomem();
255 continue;
256 case TOKEN822_COMMENT:
257 /* comment is lexically a space; shouldn't affect wordok */
258 break;
259 case TOKEN822_COMMA:
260 if (tokaddr.len) gotaddr();
261 wordok = 1;
262 break;
263 default:
264 wordok = 1;
265 if (!token822_append(&tokaddr,t)) nomem();
266 continue;
267 }
268 if (tokaddr.len) gotaddr();
269}
270
271
272int main(int argc,char * const *argv)
273{
274 int fd;
275
276 umask(033);
277 readcontrols();
278
279 fnlist = argv[1]; if (!fnlist) usage();
280
281 if (!stralloc_copys(&bin,fnlist)) nomem();
282 if (!stralloc_cats(&bin,".bin")) nomem();
283 if (!stralloc_0(&bin)) nomem();
284
285 if (!stralloc_copys(&tmp,fnlist)) nomem();
286 if (!stralloc_cats(&tmp,".tmp")) nomem();
287 if (!stralloc_0(&tmp)) nomem();
288
289 fd = open_read(fnlist);
290 if (fd == -1) readerr();
291 buffer_init(&bi,read,fd,listbuf,sizeof(listbuf));
292
293 fd = open_trunc(fntmp);
294 if (fd == -1) writeerr();
295 buffer_init(&bt,write,fd,tmpbuf,sizeof(tmpbuf));
296
297 for (;;) {
298 if (getln(&bi,&line,&match,'\n') == -1) readerr();
299 if (!line.len) break;
300 if (line.s[0] != '#') parseline();
301 if (!match) break;
302 }
303
304 if (buffer_flush(&bt) == -1) writeerr();
305 if (fsync(fd) == -1) writeerr();
306 if (close(fd) == -1) writeerr(); /* NFS stupidity */
307
308 if (rename(fntmp,fnbin) == -1)
309 logmsg(WHO,111,FATAL,B("unable to move ",fntmp," to: ",fnbin));
310
311 _exit(0);
312}
char auto_qmail[]
int main()
Definition: chkshsgr.c:6
void nomem()
Definition: columnt.c:15
int control_readline(stralloc *sa, char *fn)
Definition: control.c:53
int stralloc_copys(stralloc *, char const *)
stralloc out
Definition: dnscname.c:12
void _exit(int)
int rename(const char *, const char *)
char buf[100+FMT_ULONG]
Definition: hier.c:11
stralloc me
Definition: newinclude.c:93
stralloc defaulthost
Definition: newinclude.c:94
stralloc cbuf
Definition: newinclude.c:137
char tmpbuf[BUFSIZE_LINE]
Definition: newinclude.c:38
#define fnbin
Definition: newinclude.c:35
token822_alloc toks
Definition: newinclude.c:138
stralloc address
Definition: newinclude.c:140
void readcontrols()
Definition: newinclude.c:98
#define fntmp
Definition: newinclude.c:37
char * fnlist
Definition: newinclude.c:30
stralloc tmp
Definition: newinclude.c:36
stralloc line
Definition: newinclude.c:199
buffer bi
Definition: newinclude.c:32
token822_alloc tokaddr
Definition: newinclude.c:139
stralloc plusdomain
Definition: newinclude.c:96
char listbuf[BUFSIZE_LINE]
Definition: newinclude.c:31
void writeerr()
Definition: newinclude.c:46
int match
Definition: newinclude.c:200
stralloc defaultdomain
Definition: newinclude.c:95
#define WHO
Definition: newinclude.c:17
stralloc bin
Definition: newinclude.c:34
buffer bt
Definition: newinclude.c:39
int fd
int j
Definition: qmail-send.c:926
#define BUFSIZE_LINE
Definition: qmail.h:8
void die_control(void)
Definition: qmail-qmqpc.c:31
int slen
Definition: token822.h:9
char * s
Definition: token822.h:8
int type
Definition: token822.h:7
int token822_parse(token822_alloc *ta, stralloc *sa, stralloc *buf)
Definition: token822.c:220
#define TOKEN822_ATOM
Definition: token822.h:29
#define TOKEN822_COMMENT
Definition: token822.h:32
int token822_append(token822_alloc *, struct token822 *)
#define TOKEN822_RIGHT
Definition: token822.h:34
#define TOKEN822_LEFT
Definition: token822.h:33
#define TOKEN822_COMMA
Definition: token822.h:36
int token822_unquote(stralloc *, token822_alloc *)
Definition: token822.c:168
#define TOKEN822_AT
Definition: token822.h:35
#define TOKEN822_SEMI
Definition: token822.h:37
void token822_reverse(token822_alloc *)
Definition: token822.c:9
#define TOKEN822_DOT
Definition: token822.h:39
#define TOKEN822_COLON
Definition: token822.h:38
#define TOKEN822_LITERAL
Definition: token822.h:31
#define TOKEN822_QUOTE
Definition: token822.h:30
int token822_readyplus(token822_alloc *, unsigned int)
void write()