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
,": ");