9 #include "auto_qmail.h"
13 #define FATAL "newaliases: fatal: "
17 strerr_die2x(111,FATAL
,"out of memory");
21 strerr_die2x(100,FATAL
,"NUL bytes are not permitted");
25 strerr_die2x(100,FATAL
,"addresses over 800 bytes are not permitted");
29 strerr_die2sys(111,FATAL
,"unable to write to /etc/aliases.tmp: ");
33 strerr_die2sys(111,FATAL
,"unable to read /etc/aliases: ");
37 strerr_die2sys(111,FATAL
,"unable to read controls: ");
41 stralloc defaulthost
= {0};
42 stralloc defaultdomain
= {0};
43 stralloc plusdomain
= {0};
50 fddir
= open_read(".");
52 strerr_die2sys(111,FATAL
,"unable to open current directory: ");
54 if (chdir(auto_qmail
) == -1)
55 strerr_die4sys(111,FATAL
,"unable to chdir to ",auto_qmail
,": ");
57 r
= control_readline(&me
,"control/me");
58 if (r
== -1) die_control();
59 if (!r
) if (!stralloc_copys(&me
,"me")) nomem();
61 r
= control_readline(&defaultdomain
,"control/defaultdomain");
62 if (r
== -1) die_control();
63 if (!r
) if (!stralloc_copy(&defaultdomain
,&me
)) nomem();
65 r
= control_readline(&defaulthost
,"control/defaulthost");
66 if (r
== -1) die_control();
67 if (!r
) if (!stralloc_copy(&defaulthost
,&me
)) nomem();
69 r
= control_readline(&plusdomain
,"control/plusdomain");
70 if (r
== -1) die_control();
71 if (!r
) if (!stralloc_copy(&plusdomain
,&me
)) nomem();
73 if (fchdir(fddir
) == -1)
74 strerr_die2sys(111,FATAL
,"unable to set current directory: ");
77 stralloc target
= {0};
78 stralloc fulltarget
= {0};
82 token822_alloc toks
= {0};
83 token822_alloc tokaddr
= {0};
84 stralloc address
= {0};
88 token822_reverse(&tokaddr
);
89 if (token822_unquote(&address
,&tokaddr
) != 1) nomem();
93 strerr_die2x(111,FATAL
,"empty :include: filenames not permitted");
94 if (byte_chr(address
.s
,address
.len
,'\0') < address
.len
)
95 strerr_die2x(111,FATAL
,"NUL not permitted in :include: filenames");
97 if ((address
.s
[0] != '.') && (address
.s
[0] != '/'))
98 if (!stralloc_cats(&instr
,"./")) nomem();
99 if (!stralloc_cat(&instr
,&address
)) nomem();
100 if (!stralloc_cats(&instr
,".bin")) nomem();
101 if (!stralloc_0(&instr
)) nomem();
110 token822_reverse(&tokaddr
);
111 if (token822_unquote(&address
,&tokaddr
) != 1) nomem();
114 strerr_die2x(111,FATAL
,"empty recipient addresses not permitted");
117 for (i
= 0;i
< tokaddr
.len
;++i
)
118 if (tokaddr
.t
[i
].type
== TOKEN822_AT
)
123 if (!address
.len
) return;
126 if (address
.s
[0] == '/') {
127 if (!stralloc_0(&address
)) nomem();
128 strerr_die4x(111,FATAL
,"file delivery ",address
.s
," not supported");
131 if (address
.s
[0] == '|') {
132 if (byte_chr(address
.s
,address
.len
,'\0') < address
.len
)
133 strerr_die2x(111,FATAL
,"NUL not permitted in program names");
134 if (!stralloc_cats(&instr
,"!")) nomem();
135 if (!stralloc_catb(&instr
,address
.s
+ 1,address
.len
- 1)) nomem();
136 if (!stralloc_0(&instr
)) nomem();
142 if (!stralloc_cats(&instr
,"&")) nomem();
143 if (!stralloc_cat(&instr
,&fulltarget
)) nomem();
144 if (!stralloc_0(&instr
)) nomem();
148 if (!stralloc_cats(&address
,"@")) nomem();
150 if (!stralloc_copy(&target
,&address
)) nomem();
151 if (!stralloc_copy(&fulltarget
,&address
)) nomem();
153 if (fulltarget
.s
[fulltarget
.len
- 1] == '@')
154 if (!stralloc_cat(&fulltarget
,&defaulthost
)) nomem();
155 if (fulltarget
.s
[fulltarget
.len
- 1] == '+') {
156 fulltarget
.s
[fulltarget
.len
- 1] = '.';
157 if (!stralloc_cat(&fulltarget
,&plusdomain
)) nomem();
161 for (i
= 0;i
< fulltarget
.len
;++i
) if (fulltarget
.s
[i
] == '@') j
= i
;
162 for (i
= j
;i
< fulltarget
.len
;++i
) if (fulltarget
.s
[i
] == '.') break;
163 if (i
== fulltarget
.len
) {
164 if (!stralloc_cats(&fulltarget
,".")) nomem();
165 if (!stralloc_cat(&fulltarget
,&defaultdomain
)) nomem();
168 if (fulltarget
.len
> 800) longaddress();
169 if (byte_chr(fulltarget
.s
,fulltarget
.len
,'\0') < fulltarget
.len
)
170 strerr_die2x(111,FATAL
,"NUL not permitted in recipient addresses");
174 stralloc newline
= {0};
179 if (!stralloc_0(&line
)) nomem();
180 strerr_die3x(111,FATAL
,"unable to parse this line: ",line
.s
);
187 struct token822
*beginning
;
189 switch(token822_parse(&toks
,&line
,&cbuf
)) {
195 t
= toks
.t
+ toks
.len
;
198 if (!token822_readyplus(&tokaddr
,1)) nomem();
201 while (t
> beginning
)
202 switch((--t
)->type
) {
206 if (t
>= beginning
+ 2)
207 if (t
[-2].type
== TOKEN822_COLON
)
208 if (t
[-1].type
== TOKEN822_ATOM
)
210 if (!byte_diff(t
[-1].s
,7,"include")) {
216 if (tokaddr
.len
) gotaddr();
217 while ((t
> beginning
) && (t
[-1].type
!= TOKEN822_LEFT
))
218 if (!token822_append(&tokaddr
,--t
)) nomem();
220 if (t
<= beginning
) parseerr();
222 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
)))
226 case TOKEN822_ATOM
: case TOKEN822_QUOTE
: case TOKEN822_LITERAL
:
227 if (!wordok
) if (tokaddr
.len
) gotaddr();
229 if (!token822_append(&tokaddr
,t
)) nomem();
231 case TOKEN822_COMMENT
:
232 /* comment is lexically a space; shouldn't affect wordok */
235 if (tokaddr
.len
) gotaddr();
240 if (!token822_append(&tokaddr
,t
)) nomem();
243 if (tokaddr
.len
) gotaddr();
248 struct cdbmss cdbmss
;
254 if (target
.len
) parseerr();
258 if (!target
.len
) parseerr();
260 if (stralloc_starts(&target
,"owner-")) {
261 if (!stralloc_copys(&key
,"?")) nomem();
262 if (!stralloc_catb(&key
,target
.s
+ 6,target
.len
- 6)) nomem();
263 case_lowerb(key
.s
,key
.len
);
264 if (cdbmss_add(&cdbmss
,key
.s
,key
.len
,fulltarget
.s
,fulltarget
.len
) == -1) writeerr();
267 if (!stralloc_copys(&key
,":")) nomem();
268 if (!stralloc_cat(&key
,&target
)) nomem();
269 case_lowerb(key
.s
,key
.len
);
270 if (cdbmss_add(&cdbmss
,key
.s
,key
.len
,instr
.s
,instr
.len
) == -1) writeerr();
280 fd
= open_read("/etc/aliases");
281 if (fd
== -1) readerr();
282 substdio_fdbuf(&ssin
,read
,fd
,inbuf
,sizeof inbuf
);
284 fd
= open_trunc("/etc/aliases.tmp");
285 if (fd
== -1) strerr_die2sys(111,FATAL
,"unable to create /etc/aliases.tmp: ");
286 if (cdbmss_start(&cdbmss
,fd
) == -1) writeerr();
288 if (!stralloc_copys(&line
,"")) nomem();
291 if (getln(&ssin
,&newline
,&match
,'\n') != 0) readerr();
293 if (match
&& (newline
.s
[0] == '\n')) continue;
295 if (match
&& ((newline
.s
[0] == ' ') || (newline
.s
[0] == '\t'))) {
296 if (!stralloc_cat(&line
,&newline
)) nomem();
301 if (line
.s
[0] != '#') {
302 if (!stralloc_copys(&target
,"")) nomem();
303 if (!stralloc_copys(&fulltarget
,"")) nomem();
304 if (!stralloc_copys(&instr
,"")) nomem();
310 if (!stralloc_copy(&line
,&newline
)) nomem();
313 if (cdbmss_finish(&cdbmss
) == -1) writeerr();
314 if (fsync(fd
) == -1) writeerr();
315 if (close(fd
) == -1) writeerr(); /* NFS stupidity */
317 if (rename("/etc/aliases.tmp","/etc/aliases.cdb") == -1)
318 strerr_die2sys(111,FATAL
,"unable to move /etc/aliases.tmp to /etc/aliases.cdb: ");