9 #include "auto_qmail.h"
12 #define FATAL "newinclude: fatal: "
16 strerr_die2x(111,FATAL,"out of memory");
20 strerr_die1x(100,"newinclude: usage: newinclude list");
37 strerr_die4sys(111,FATAL,"unable to read ",fnlist,": ");
41 strerr_die4sys(111,FATAL,"unable to write to ",fntmp,": ");
48 if (substdio_put(&sstmp,s,len) == -1) writeerr();
56 strerr_die2x(111,FATAL,"empty :include: filenames not permitted");
57 if (byte_chr(buf,len,'\n') != len)
58 strerr_die2x(111,FATAL,"newlines not permitted in :include: filenames");
59 if (byte_chr(buf,len,'\0') != len)
60 strerr_die2x(111,FATAL,"NUL not permitted in :include: filenames");
61 if ((buf[0] != '.') && (buf[0] != '/'))
72 strerr_die2x(111,FATAL,"empty recipient addresses not permitted");
73 if (byte_chr(buf,len,'\n') != len)
74 strerr_die2x(111,FATAL,"newlines not permitted in recipient addresses");
75 if (byte_chr(buf,len,'\0') != len)
76 strerr_die2x(111,FATAL,"NUL not permitted in recipient addresses");
78 strerr_die2x(111,FATAL,"addresses must be under 800 bytes");
79 if ((buf[len - 1] == ' ') || (buf[len - 1] == '\t'))
80 strerr_die2x(111,FATAL,"spaces and tabs not permitted at ends of addresses");
89 strerr_die2sys(111,FATAL,"unable to read controls: ");
93 stralloc defaulthost = {0};
94 stralloc defaultdomain = {0};
95 stralloc plusdomain = {0};
103 fddir = open_read(".");
105 strerr_die2sys(111,FATAL,"unable to open current directory: ");
107 if (chdir(auto_qmail) == -1)
108 strerr_die4sys(111,FATAL,"unable to chdir to ",auto_qmail,": ");
110 r = control_readline(&me,"control/me");
111 if (r == -1) die_control();
112 if (!r) if (!stralloc_copys(&me,"me")) nomem();
114 r = control_readline(&defaultdomain,"control/defaultdomain");
115 if (r == -1) die_control();
116 if (!r) if (!stralloc_copy(&defaultdomain,&me)) nomem();
117 x = env_get("QMAILDEFAULTDOMAIN");
118 if (x) if (!stralloc_copys(&defaultdomain,x)) nomem();
120 r = control_readline(&defaulthost,"control/defaulthost");
121 if (r == -1) die_control();
122 if (!r) if (!stralloc_copy(&defaulthost,&me)) nomem();
123 x = env_get("QMAILDEFAULTHOST");
124 if (x) if (!stralloc_copys(&defaulthost,x)) nomem();
126 r = control_readline(&plusdomain,"control/plusdomain");
127 if (r == -1) die_control();
128 if (!r) if (!stralloc_copy(&plusdomain,&me)) nomem();
129 x = env_get("QMAILPLUSDOMAIN");
130 if (x) if (!stralloc_copys(&plusdomain,x)) nomem();
132 if (fchdir(fddir) == -1)
133 strerr_die2sys(111,FATAL,"unable to set current directory: ");
137 token822_alloc toks = {0};
138 token822_alloc tokaddr = {0};
139 stralloc address = {0};
143 token822_reverse(&tokaddr);
144 if (token822_unquote(&address,&tokaddr) != 1) nomem();
146 doincl(address.s,address.len);
155 token822_reverse(&tokaddr);
156 if (token822_unquote(&address,&tokaddr) != 1) nomem();
159 for (i = 0;i < tokaddr.len;++i)
160 if (tokaddr.t[i].type == TOKEN822_AT)
165 if (!address.len) return;
168 if (address.s[0] == '/') {
169 if (!stralloc_0(&address)) nomem();
170 strerr_die4x(111,FATAL,"file delivery ",address.s," not supported");
173 if (address.s[0] == '|') {
174 if (!stralloc_0(&address)) nomem();
175 strerr_die4x(111,FATAL,"program delivery ",address.s," not supported");
179 if (!stralloc_cats(&address,"@")) nomem();
180 if (!stralloc_cat(&address,&defaulthost)) nomem();
182 if (address.s[address.len - 1] == '+') {
183 address.s[address.len - 1] = '.';
184 if (!stralloc_cat(&address,&plusdomain)) nomem();
187 for (i = 0;i < address.len;++i) if (address.s[i] == '@') j = i;
188 for (i = j;i < address.len;++i) if (address.s[i] == '.') break;
189 if (i == address.len) {
190 if (!stralloc_cats(&address,".")) nomem();
191 if (!stralloc_cat(&address,&defaultdomain)) nomem();
194 dorecip(address.s,address.len);
203 if (!stralloc_0(&line)) nomem();
204 strerr_die3x(111,FATAL,"unable to parse this line: ",line.s);
211 struct token822 *beginning;
213 switch(token822_parse(&toks,&line,&cbuf)) {
219 t = toks.t + toks.len;
222 if (!token822_readyplus(&tokaddr,1)) nomem();
225 while (t > beginning)
226 switch((--t)->type) {
230 if (t >= beginning + 2)
231 if (t[-2].type == TOKEN822_COLON)
232 if (t[-1].type == TOKEN822_ATOM)
234 if (!byte_diff(t[-1].s,7,"include")) {
240 if (tokaddr.len) gotaddr();
241 while ((t > beginning) && (t[-1].type != TOKEN822_LEFT))
242 if (!token822_append(&tokaddr,--t)) nomem();
244 if (t <= beginning) parseerr();
246 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)))
250 case TOKEN822_ATOM: case TOKEN822_QUOTE: case TOKEN822_LITERAL:
251 if (!wordok) if (tokaddr.len) gotaddr();
253 if (!token822_append(&tokaddr,t)) nomem();
255 case TOKEN822_COMMENT:
256 /* comment is lexically a space; shouldn't affect wordok */
259 if (tokaddr.len) gotaddr();
264 if (!token822_append(&tokaddr,t)) nomem();
267 if (tokaddr.len) gotaddr();
280 fnlist = argv[1]; if (!fnlist) usage();
282 if (!stralloc_copys(&bin,fnlist)) nomem();
283 if (!stralloc_cats(&bin,".bin")) nomem();
284 if (!stralloc_0(&bin)) nomem();
286 if (!stralloc_copys(&tmp,fnlist)) nomem();
287 if (!stralloc_cats(&tmp,".tmp")) nomem();
288 if (!stralloc_0(&tmp)) nomem();
290 fd = open_read(fnlist);
291 if (fd == -1) readerr();
292 substdio_fdbuf(&sslist,read,fd,listbuf,sizeof listbuf);
294 fd = open_trunc(fntmp);
295 if (fd == -1) writeerr();
296 substdio_fdbuf(&sstmp,write,fd,tmpbuf,sizeof tmpbuf);
299 if (getln(&sslist,&line,&match,'\n') == -1) readerr();
300 if (!line.len) break;
301 if (line.s[0] != '#') parseline();
305 if (substdio_flush(&sstmp) == -1) writeerr();
306 if (fsync(fd) == -1) writeerr();
307 if (close(fd) == -1) writeerr(); /* NFS stupidity */
309 if (rename(fntmp,fnbin) == -1)
310 strerr_die6sys(111,FATAL,"unable to move ",fntmp," to ",fnbin,": ");