|
1 #include <sys/types.h> |
|
2 #include <sys/stat.h> |
|
3 #include "substdio.h" |
|
4 #include "readwrite.h" |
|
5 #include "subfd.h" |
|
6 #include "sgetopt.h" |
|
7 #include "control.h" |
|
8 #include "constmap.h" |
|
9 #include "stralloc.h" |
|
10 #include "fmt.h" |
|
11 #include "str.h" |
|
12 #include "scan.h" |
|
13 #include "open.h" |
|
14 #include "error.h" |
|
15 #include "getln.h" |
|
16 #include "auto_break.h" |
|
17 #include "auto_qmail.h" |
|
18 #include "auto_usera.h" |
|
19 |
|
20 void die_chdir() |
|
21 { |
|
22 substdio_putsflush(subfderr,"qmail-pw2u: fatal: unable to chdir\n"); |
|
23 _exit(111); |
|
24 } |
|
25 void die_nomem() |
|
26 { |
|
27 substdio_putsflush(subfderr,"qmail-pw2u: fatal: out of memory\n"); |
|
28 _exit(111); |
|
29 } |
|
30 void die_read() |
|
31 { |
|
32 substdio_putsflush(subfderr,"qmail-pw2u: fatal: unable to read input\n"); |
|
33 _exit(111); |
|
34 } |
|
35 void die_write() |
|
36 { |
|
37 substdio_putsflush(subfderr,"qmail-pw2u: fatal: unable to write output\n"); |
|
38 _exit(111); |
|
39 } |
|
40 void die_control() |
|
41 { |
|
42 substdio_putsflush(subfderr,"qmail-pw2u: fatal: unable to read controls\n"); |
|
43 _exit(111); |
|
44 } |
|
45 void die_alias() |
|
46 { |
|
47 substdio_puts(subfderr,"qmail-pw2u: fatal: unable to find "); |
|
48 substdio_puts(subfderr,auto_usera); |
|
49 substdio_puts(subfderr," user\n"); |
|
50 substdio_flush(subfderr); |
|
51 _exit(111); |
|
52 } |
|
53 void die_home(fn) char *fn; |
|
54 { |
|
55 substdio_puts(subfderr,"qmail-pw2u: fatal: unable to stat "); |
|
56 substdio_puts(subfderr,fn); |
|
57 substdio_puts(subfderr,"\n"); |
|
58 substdio_flush(subfderr); |
|
59 _exit(111); |
|
60 } |
|
61 void die_user(s,len) char *s; unsigned int len; |
|
62 { |
|
63 substdio_puts(subfderr,"qmail-pw2u: fatal: unable to find "); |
|
64 substdio_put(subfderr,s,len); |
|
65 substdio_puts(subfderr," user for subuser\n"); |
|
66 substdio_flush(subfderr); |
|
67 _exit(111); |
|
68 } |
|
69 |
|
70 char *dashcolon = "-:"; |
|
71 int flagalias = 0; |
|
72 int flagnoupper = 1; |
|
73 int homestrategy = 2; |
|
74 /* 2: skip if home does not exist; skip if home is not owned by user */ |
|
75 /* 1: stop if home does not exist; skip if home is not owned by user */ |
|
76 /* 0: don't worry about home */ |
|
77 |
|
78 int okincl; stralloc incl = {0}; struct constmap mapincl; |
|
79 int okexcl; stralloc excl = {0}; struct constmap mapexcl; |
|
80 int okmana; stralloc mana = {0}; struct constmap mapmana; |
|
81 |
|
82 stralloc allusers = {0}; struct constmap mapuser; |
|
83 |
|
84 stralloc uugh = {0}; |
|
85 stralloc user = {0}; |
|
86 stralloc uidstr = {0}; |
|
87 stralloc gidstr = {0}; |
|
88 stralloc home = {0}; |
|
89 unsigned long uid; |
|
90 |
|
91 stralloc line = {0}; |
|
92 |
|
93 void doaccount() |
|
94 { |
|
95 struct stat st; |
|
96 int i; |
|
97 char *mailnames; |
|
98 char *x; |
|
99 unsigned int xlen; |
|
100 |
|
101 if (byte_chr(line.s,line.len,'\0') < line.len) return; |
|
102 |
|
103 x = line.s; xlen = line.len; i = byte_chr(x,xlen,':'); if (i == xlen) return; |
|
104 if (!stralloc_copyb(&user,x,i)) die_nomem(); |
|
105 if (!stralloc_0(&user)) die_nomem(); |
|
106 ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return; |
|
107 ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return; |
|
108 if (!stralloc_copyb(&uidstr,x,i)) die_nomem(); |
|
109 if (!stralloc_0(&uidstr)) die_nomem(); |
|
110 scan_ulong(uidstr.s,&uid); |
|
111 ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return; |
|
112 if (!stralloc_copyb(&gidstr,x,i)) die_nomem(); |
|
113 if (!stralloc_0(&gidstr)) die_nomem(); |
|
114 ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return; |
|
115 ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return; |
|
116 if (!stralloc_copyb(&home,x,i)) die_nomem(); |
|
117 if (!stralloc_0(&home)) die_nomem(); |
|
118 |
|
119 if (!uid) return; |
|
120 if (flagnoupper) |
|
121 for (i = 0;i < user.len;++i) |
|
122 if ((user.s[i] >= 'A') && (user.s[i] <= 'Z')) |
|
123 return; |
|
124 if (okincl) |
|
125 if (!constmap(&mapincl,user.s,user.len - 1)) |
|
126 return; |
|
127 if (okexcl) |
|
128 if (constmap(&mapexcl,user.s,user.len - 1)) |
|
129 return; |
|
130 if (homestrategy) { |
|
131 if (stat(home.s,&st) == -1) { |
|
132 if (errno != error_noent) die_home(home.s); |
|
133 if (homestrategy == 1) die_home(home.s); |
|
134 return; |
|
135 } |
|
136 if (st.st_uid != uid) return; |
|
137 } |
|
138 |
|
139 if (!stralloc_copys(&uugh,":")) die_nomem(); |
|
140 if (!stralloc_cats(&uugh,user.s)) die_nomem(); |
|
141 if (!stralloc_cats(&uugh,":")) die_nomem(); |
|
142 if (!stralloc_cats(&uugh,uidstr.s)) die_nomem(); |
|
143 if (!stralloc_cats(&uugh,":")) die_nomem(); |
|
144 if (!stralloc_cats(&uugh,gidstr.s)) die_nomem(); |
|
145 if (!stralloc_cats(&uugh,":")) die_nomem(); |
|
146 if (!stralloc_cats(&uugh,home.s)) die_nomem(); |
|
147 if (!stralloc_cats(&uugh,":")) die_nomem(); |
|
148 |
|
149 /* XXX: avoid recording in allusers unless sub actually needs it */ |
|
150 if (!stralloc_cats(&allusers,user.s)) die_nomem(); |
|
151 if (!stralloc_cats(&allusers,":")) die_nomem(); |
|
152 if (!stralloc_catb(&allusers,uugh.s,uugh.len)) die_nomem(); |
|
153 if (!stralloc_0(&allusers)) die_nomem(); |
|
154 |
|
155 if (str_equal(user.s,auto_usera)) { |
|
156 if (substdio_puts(subfdout,"+") == -1) die_write(); |
|
157 if (substdio_put(subfdout,uugh.s,uugh.len) == -1) die_write(); |
|
158 if (substdio_puts(subfdout,dashcolon) == -1) die_write(); |
|
159 if (substdio_puts(subfdout,":\n") == -1) die_write(); |
|
160 flagalias = 1; |
|
161 } |
|
162 |
|
163 mailnames = 0; |
|
164 if (okmana) |
|
165 mailnames = constmap(&mapmana,user.s,user.len - 1); |
|
166 if (!mailnames) |
|
167 mailnames = user.s; |
|
168 |
|
169 for (;;) { |
|
170 while (*mailnames == ':') ++mailnames; |
|
171 if (!*mailnames) break; |
|
172 |
|
173 i = str_chr(mailnames,':'); |
|
174 |
|
175 if (substdio_puts(subfdout,"=") == -1) die_write(); |
|
176 if (substdio_put(subfdout,mailnames,i) == -1) die_write(); |
|
177 if (substdio_put(subfdout,uugh.s,uugh.len) == -1) die_write(); |
|
178 if (substdio_puts(subfdout,"::\n") == -1) die_write(); |
|
179 |
|
180 if (*auto_break) { |
|
181 if (substdio_puts(subfdout,"+") == -1) die_write(); |
|
182 if (substdio_put(subfdout,mailnames,i) == -1) die_write(); |
|
183 if (substdio_put(subfdout,auto_break,1) == -1) die_write(); |
|
184 if (substdio_put(subfdout,uugh.s,uugh.len) == -1) die_write(); |
|
185 if (substdio_puts(subfdout,dashcolon) == -1) die_write(); |
|
186 if (substdio_puts(subfdout,":\n") == -1) die_write(); |
|
187 } |
|
188 |
|
189 mailnames += i; |
|
190 } |
|
191 } |
|
192 |
|
193 stralloc sub = {0}; |
|
194 |
|
195 void dosubuser() |
|
196 { |
|
197 int i; |
|
198 char *x; |
|
199 unsigned int xlen; |
|
200 char *uugh; |
|
201 |
|
202 x = line.s; xlen = line.len; i = byte_chr(x,xlen,':'); if (i == xlen) return; |
|
203 if (!stralloc_copyb(&sub,x,i)) die_nomem(); |
|
204 ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return; |
|
205 uugh = constmap(&mapuser,x,i); |
|
206 if (!uugh) die_user(x,i); |
|
207 ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return; |
|
208 |
|
209 if (substdio_puts(subfdout,"=") == -1) die_write(); |
|
210 if (substdio_put(subfdout,sub.s,sub.len) == -1) die_write(); |
|
211 if (substdio_puts(subfdout,uugh) == -1) die_write(); |
|
212 if (substdio_puts(subfdout,dashcolon) == -1) die_write(); |
|
213 if (substdio_put(subfdout,x,i) == -1) die_write(); |
|
214 if (substdio_puts(subfdout,":\n") == -1) die_write(); |
|
215 |
|
216 if (*auto_break) { |
|
217 if (substdio_puts(subfdout,"+") == -1) die_write(); |
|
218 if (substdio_put(subfdout,sub.s,sub.len) == -1) die_write(); |
|
219 if (substdio_put(subfdout,auto_break,1) == -1) die_write(); |
|
220 if (substdio_puts(subfdout,uugh) == -1) die_write(); |
|
221 if (substdio_puts(subfdout,dashcolon) == -1) die_write(); |
|
222 if (substdio_put(subfdout,x,i) == -1) die_write(); |
|
223 if (substdio_puts(subfdout,"-:\n") == -1) die_write(); |
|
224 } |
|
225 } |
|
226 |
|
227 int fd; |
|
228 substdio ss; |
|
229 char ssbuf[SUBSTDIO_INSIZE]; |
|
230 |
|
231 void main(argc,argv) |
|
232 int argc; |
|
233 char **argv; |
|
234 { |
|
235 int opt; |
|
236 int match; |
|
237 |
|
238 while ((opt = getopt(argc,argv,"/ohHuUc:C")) != opteof) |
|
239 switch(opt) { |
|
240 case '/': dashcolon = "-/:"; break; |
|
241 case 'o': homestrategy = 2; break; |
|
242 case 'h': homestrategy = 1; break; |
|
243 case 'H': homestrategy = 0; break; |
|
244 case 'u': flagnoupper = 0; break; |
|
245 case 'U': flagnoupper = 1; break; |
|
246 case 'c': *auto_break = *optarg; break; |
|
247 case 'C': *auto_break = 0; break; |
|
248 case '?': |
|
249 default: |
|
250 _exit(100); |
|
251 } |
|
252 |
|
253 if (chdir(auto_qmail) == -1) die_chdir(); |
|
254 |
|
255 /* no need for control_init() */ |
|
256 |
|
257 okincl = control_readfile(&incl,"users/include",0); |
|
258 if (okincl == -1) die_control(); |
|
259 if (okincl) if (!constmap_init(&mapincl,incl.s,incl.len,0)) die_nomem(); |
|
260 |
|
261 okexcl = control_readfile(&excl,"users/exclude",0); |
|
262 if (okexcl == -1) die_control(); |
|
263 if (okexcl) if (!constmap_init(&mapexcl,excl.s,excl.len,0)) die_nomem(); |
|
264 |
|
265 okmana = control_readfile(&mana,"users/mailnames",0); |
|
266 if (okmana == -1) die_control(); |
|
267 if (okmana) if (!constmap_init(&mapmana,mana.s,mana.len,1)) die_nomem(); |
|
268 |
|
269 if (!stralloc_copys(&allusers,"")) die_nomem(); |
|
270 |
|
271 for (;;) { |
|
272 if (getln(subfdin,&line,&match,'\n') == -1) die_read(); |
|
273 doaccount(); |
|
274 if (!match) break; |
|
275 } |
|
276 if (!flagalias) die_alias(); |
|
277 |
|
278 fd = open_read("users/subusers"); |
|
279 if (fd == -1) { |
|
280 if (errno != error_noent) die_control(); |
|
281 } |
|
282 else { |
|
283 substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf)); |
|
284 |
|
285 if (!constmap_init(&mapuser,allusers.s,allusers.len,1)) die_nomem(); |
|
286 |
|
287 for (;;) { |
|
288 if (getln(&ss,&line,&match,'\n') == -1) die_read(); |
|
289 dosubuser(); |
|
290 if (!match) break; |
|
291 } |
|
292 |
|
293 close(fd); |
|
294 } |
|
295 |
|
296 fd = open_read("users/append"); |
|
297 if (fd == -1) { |
|
298 if (errno != error_noent) die_control(); |
|
299 } |
|
300 else { |
|
301 substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf)); |
|
302 for (;;) { |
|
303 if (getln(&ss,&line,&match,'\n') == -1) die_read(); |
|
304 if (substdio_put(subfdout,line.s,line.len) == -1) die_write(); |
|
305 if (!match) break; |
|
306 } |
|
307 } |
|
308 |
|
309 if (substdio_puts(subfdout,".\n") == -1) die_write(); |
|
310 if (substdio_flush(subfdout) == -1) die_write(); |
|
311 _exit(0); |
|
312 } |