s/qmail 4.3.20
Next generation secure email transport
Loading...
Searching...
No Matches
qmail-qmaint.c
Go to the documentation of this file.
1/*
2 Based on an implementation of queue-fix 1.2 by Eric Huss
3*/
4#include <unistd.h>
5#include <sys/stat.h>
6#include <pwd.h>
7#include <grp.h>
8#include <stdio.h> // rename
9#include "stralloc.h"
10#include "direntry.h"
11#include "fmt.h"
12#include "fmtqfn.h"
13#include "error.h"
14#include "buffer.h"
15#include "getln.h"
16#include "str.h"
17#include "open.h"
18#include "fifo.h"
19#include "scan.h"
20#include "readsubdir.h"
21#include "logmsg.h"
22#include "exit.h"
23#include "auto_queue.h"
24#include "auto_split.h"
25#include "auto_uids.h"
26#include "datetime.h"
27#include "date822fmt.h"
28
29#define WHO "qmail-qmaint"
30
31stralloc queue_dir = {0}; /*the root queue dir with trailing slash*/
32stralloc check_dir = {0}; /*the current directory being checked*/
33stralloc temp_dirname = {0}; /*temporary used for checking directories */
34stralloc temp_filename = {0}; /*temporary used for checking individuals*/
35stralloc old_name = {0}; /*used in rename*/
36stralloc new_name = {0}; /*used in rename*/
37stralloc mess_dir = {0}; /*used for renaming in mess dir*/
38stralloc dkim_dir = {0}; /*used for cleaning up dkim dir*/
39stralloc query = {0}; /*used in interactive query function*/
40stralloc birth_date = {0}; /*used to display dkim messages*/
41
42char strnum[FMT_ULONG];
49
55
56static void die_make(char *name)
57{
58 logmsg(WHO,111,ERROR,B("Failed to make: ",name));
59}
60
61static void die_check()
62{
63 logmsg(WHO,111,ERROR,"Failed while checking directory structure. \nEnsure the given queue exists and you have permission to access it.");
64}
65
66static void die_nomem()
67{
68 logmsg(WHO,110,ERROR,"Out of memory.");
69}
70
71static void err_unlink(unsigned long id)
72{
73 char foo[FMT_ULONG];
74 foo[fmt_ulong(foo,id)] = 0;
75 logmsg(WHO,100,ERROR,B("trouble with unlinking #",foo));
76}
77
78static void err_chdir()
79{
80 logmsg(WHO,110,FATAL,"unable to chdir");
81}
82
83/*returns 1==yes, 0==no*/
84
85static int confirm()
86{
87 int match;
88
89 if (getln(buffer_0,&query,&match,'\n')) return 0;
90 if (!match) return 0;
91 if (query.s[0] == 'y' || query.s[0] == 'Y' || query.s[0] == '\n') return 1;
92 return 0;
93}
94
95/*gid may be -1 on files for "unknown*/
96
97#define DIRS logmsg(WHO,0,WARN,"It looks like some directories don't exist, should I create them? (Y/n)")
98#define FILES logmsg(WHO,0,WARN,"It looks like some files don't exist, should I create them? (Y/n)")
99
100#define PERMS logmsg(WHO,0,WARN,B("It looks like permissions are wrong for ",name," should I fix them? (Y/n)"))
101#define CPERMS logmsg(WHO,0,WARN,B("Changing permissions: ",name," => ",pnum))
102
103#define OWNER logmsg(WHO,0,WARN,B("It looks like ownerships are wrong for ",name," should I fix them? (Y/n)"))
104#define COWNER logmsg(WHO,0,WARN,B("Changing ownership: ",name," => ",unum,"/",gnum))
105
106static int check_item(char *name,int uid,int gid,int perm,char type,int size)
107{
108 struct stat st;
109 int fd;
110 char num[12];
111 char unum[12];
112 char gnum[12];
113 char pnum[12];
114
115 /*check for existence and proper credentials*/
116
117 strnum[fmt_uint(unum,uid)] = 0;
118 strnum[fmt_uint(gnum,gid)] = 0;
119 strnum[fmt_uint(pnum,perm)] = 0;
120
121 switch (type) {
122 case 'd': /*directory*/
123 if (stat(name,&st)) {
124 if (errno != ENOENT) return -1;
126 DIRS; if (!confirm()) return -1;
127 flag_dircreate = 1;
128 }
129 /*create it*/
130 logmsg(WHO,0,INFO,B("Creating directory: ",name));
131 if (mkdir(name,perm)) die_make(name);
132 CPERMS; if (chmod(name,perm)) die_make(name);
133 COWNER; if (chown(name,uid,gid)) die_make(name);
134 return 0;
135 }
136 /*check the values*/
137 if (st.st_uid != uid || st.st_gid != gid) {
138 if (!flag_permfix && flag_interactive) { OWNER; if (!confirm()) return -1; flag_permfix = 1; }
139 COWNER; if (chown(name,uid,gid)) die_make(name);
140 }
141 if ((st.st_mode & 07777) != perm) {
142 if (!flag_permfix && flag_interactive) { PERMS; if (!confirm()) return -1; flag_permfix = 1; }
143 CPERMS; if (chmod(name,perm)) die_make(name);
144 }
145 return 0;
146 case 'f': /*regular file*/
147 if (stat(name,&st)) return -1;
148 /*check the values*/
149 if (st.st_uid != uid || (st.st_gid != gid && gid != -1)) {
150 if (!flag_permfix && flag_interactive) { OWNER; if (!confirm()) return -1; flag_permfix = 1; }
151 COWNER; if (chown(name,uid,gid)) die_make(name);
152 }
153 if ((st.st_mode & 07777) != perm) {
154 if (!flag_permfix && flag_interactive) { PERMS; if (!confirm()) return -1; flag_permfix = 1; }
155 CPERMS; if (chmod(name,perm)) die_make(name);
156 }
157 return 0;
158 case 'z': /*regular file with a size*/
159 if (stat(name,&st)) {
160 if (errno != ENOENT) return -1;
162 FILES; if (!confirm()) return -1;
163 flag_filecreate = 1;
164 }
165 /*create it*/
166
167 strnum[fmt_ulong(num,size)] = 0;
168 logmsg(WHO,0,INFO,B("Creating: ",name," with size ",num));
169 fd = open_trunc(name);
170 if (fd == -1) die_make(name);
171 while (size--) { if (write(fd,"",1)!=1) die_make(name); }
172 close(fd);
173 CPERMS; if (chmod(name,perm)) die_make(name);
174 COWNER; if (chown(name,uid,gid)) die_make(name);
175 return 0;
176 }
177 /*check the values*/
178 if (st.st_uid != uid || (st.st_gid != gid && gid != -1)) {
179 if (!flag_permfix && flag_interactive) { OWNER; if (!confirm()) return -1; flag_permfix = 1; }
180 COWNER; if (chown(name,uid,gid)) die_make(name);
181 }
182 if ((st.st_mode & 07777) != perm) {
183 if (!flag_permfix && flag_interactive) { PERMS; if (!confirm()) return -1; flag_permfix = 1; }
184 CPERMS; if (chmod(name,perm)) die_make(name);
185 }
186 if (st.st_size != size) {
187 logmsg(WHO,0,WARN,B("File ",name," has not the right size. I will not fix it, please investigate."));
188 }
189 return 0;
190 case 'p': /*a named pipe*/
191 if (stat(name,&st)) {
192 if (errno != ENOENT) return -1;
194 FILES; if (!confirm()) return -1;
195 flag_filecreate = 1;
196 }
197 /*create it*/
198 logmsg(WHO,INFO,0,B("Creating fifo: ",name));
199 if (fifo_make(name,perm)) die_make(name);
200 CPERMS; if (chmod(name,perm)) die_make(name);
201 COWNER; if (chown(name,uid,gid)) die_make(name);
202 return 0;
203 }
204 /*check the values*/
205 if (st.st_uid != uid || (st.st_gid != gid && gid != -1)) {
206 if (!flag_permfix && flag_interactive) { OWNER; if (!confirm()) return -1; flag_permfix = 1; }
207 COWNER; if (chown(name,uid,gid)) die_make(name);
208 }
209 if ((st.st_mode & 07777) != perm) {
210 if (!flag_permfix && flag_interactive) { PERMS; if (!confirm()) return -1; flag_permfix = 1; }
211 CPERMS; if (chmod(name,perm)) die_make(name);
212 }
213 return 0;
214 }
215
216 return 0;
217}
218
219static int check_files(char * directory,int uid,int gid,int perm)
220{
221 DIR *dir;
222 direntry *d;
223
224 dir = opendir(directory);
225
226 if (!dir) return -1;
227 while ((d = readdir(dir))) {
228 if (d->d_name[0] == '.') continue;
229 if (!stralloc_copys(&temp_filename,directory)) die_nomem();
230 if (!stralloc_append(&temp_filename,"/")) die_nomem();
231 if (!stralloc_cats(&temp_filename,d->d_name)) die_nomem();
232 if (!stralloc_0(&temp_filename)) die_nomem();
233 if (check_item(temp_filename.s,uid,gid,perm,'f',0)) { closedir(dir); return -1; }
234 }
235 closedir(dir);
236 return 0;
237}
238
239static void warn_files(char * directory)
240{
241 DIR *dir;
242 direntry *d;
243 int found = 0;
244
245 dir = opendir(directory);
246 if (!dir) return;
247
248 while ((d = readdir(dir))) {
249 if (d->d_name[0] == '.') continue;
250 found = 1;
251 break;
252 }
253
254 closedir(dir);
255
256 if (found)
257 logmsg(WHO,0,WARN,B("Found files in ",directory," that shouldn't be there. I will not remove them. You should consider checking it out."));
258}
259
260static int check_splits(char * directory,int dir_uid,int dir_gid,int dir_perm,int file_gid,int file_perm)
261{
262 DIR *dir;
263 direntry *d;
264 int i;
265
266 for (i = 0; i < split_num ; i++) {
267 strnum[fmt_ulong(strnum,i)] = 0;
268 if (!stralloc_copys(&temp_dirname,directory)) die_nomem();
269 if (!stralloc_append(&temp_dirname,"/")) die_nomem();
270 if (!stralloc_cats(&temp_dirname,strnum)) die_nomem();
271 if (!stralloc_0(&temp_dirname)) die_nomem();
272
273 /*check the split dir*/
274 if (check_item(temp_dirname.s,dir_uid,dir_gid,dir_perm,'d',0)) return -1;
275
276 /*check its contents*/
277 dir = opendir(temp_dirname.s);
278 if (!dir) return -1;
279 while ((d = readdir(dir))) {
280 if (d->d_name[0] == '.') continue;
282 if (!stralloc_append(&temp_filename,"/")) die_nomem();
283 if (!stralloc_cats(&temp_filename,d->d_name)) die_nomem();
284 if (!stralloc_0(&temp_filename)) die_nomem();
285 if (check_item(temp_filename.s,dir_uid,file_gid,file_perm,'f',0)) { closedir(dir); return -1; }
286 }
287 closedir(dir);
288 }
289
290 return 0;
291}
292
293static int rename_mess(char *dir,char *part,char *new_part,char *old_filename,char *new_filename)
294{
295
297 logmsg(WHO,0,INFO,"It looks like some files need to be renamed, should I rename them? (Y/n)\n");
298 if (!confirm()) return -1;
299 flag_namefix = 1;
300 }
301
302 /*prepare the old filename*/
303 if (!stralloc_copy(&old_name,&queue_dir)) die_nomem();
304 if (!stralloc_cats(&old_name,dir)) die_nomem();
305 if (!stralloc_cats(&old_name,part)) die_nomem();
306 if (!stralloc_append(&old_name,"/")) die_nomem();
307 if (!stralloc_cats(&old_name,old_filename)) die_nomem();
308 if (!stralloc_0(&old_name)) die_nomem();
309
310 /*prepare the new filename*/
311 if (!stralloc_copy(&new_name,&queue_dir)) die_nomem();
312 if (!stralloc_cats(&new_name,dir)) die_nomem();
313 if (!stralloc_cats(&new_name,new_part)) die_nomem();
314 if (!stralloc_append(&new_name,"/")) die_nomem();
315 if (!stralloc_cats(&new_name,new_filename)) die_nomem();
316 if (!stralloc_0(&new_name)) die_nomem();
317
318 logmsg(WHO,0,INFO,B("Renaming ",old_name.s," to ",new_name.s));
319 if (rename(old_name.s,new_name.s)) {
320 if (errno != ENOENT) return -1;
321 }
322
323 return 0;
324}
325
326static unsigned int datefmt(char *s,datetime_sec when)
327{
328 unsigned int i;
329 unsigned int len;
330 struct datetime dt;
331 datetime_tai(&dt,when);
332 len = 0;
333 i = fmt_str(s," Date: "); len += i; if (s) s += i;
334 i = date822fmt(s,&dt); len += i; if (s) s += i;
335 return len;
336}
337
338static int date_make(datetime_sec when)
339{
340 if (!stralloc_ready(&birth_date,datefmt(FMT_LEN,when))) return 0;
341 birth_date.len = datefmt(birth_date.s,when);
342 return 1;
343}
344
345static int cleanup_dkim()
346{
347 DIR *dir;
348 direntry *d;
349 struct stat st;
350 int deleted = 0;
351
352 if (chdir(auto_queue) == -1) err_chdir();
353 if (chdir("queue/dkim") == -1) return 0;
354
355 if (!stralloc_copy(&dkim_dir,&queue_dir)) die_nomem();
356 if (!stralloc_cats(&dkim_dir,"dkim/")) die_nomem();
357
358 for (int i = 0; i < split_num; i++) {
359 strnum[fmt_uint(strnum,i)] = 0;
360 if (!stralloc_copy(&temp_dirname,&dkim_dir)) die_nomem();
361 if (!stralloc_cats(&temp_dirname,strnum)) die_nomem();
362 if (!stralloc_append(&temp_dirname,"/")) die_nomem();
363
364 dir = opendir(temp_dirname.s);
365 if (!dir) continue;
366
367 while ((d = readdir(dir))) {
368 if (d->d_name[0] == '.') continue;
369 /*check for dkim remnant */
370 if (!stralloc_copy(&temp_filename,&temp_dirname)) die_nomem();
371 if (!stralloc_cats(&temp_filename,d->d_name)) die_nomem();
372 if (!stralloc_0(&temp_filename)) die_nomem();
373
374 if (stat(temp_filename.s,&st) == -1) continue;
375 date_make(st.st_mtime);
376 // message
377 logmsg(WHO,0,INFO,B("Deleting DKIM remnant message: ",temp_filename.s,birth_date.s," !"));
378 // delete
379 if (unlink(temp_filename.s) == -1) {
380 logmsg(WHO,111,ERROR,B("Can't remove file: ",temp_filename.s));
381 }
382 // counter
383 ++deleted;
384 }
385 }
386
387 return deleted;
388}
389
390static int fix_part(char *part)
391{
392 DIR *dir;
393 direntry *d;
394 struct stat st;
395 char inode[FMT_ULONG];
396 char new_part[FMT_ULONG];
397 unsigned int old_inode;
398 unsigned int part_num;
399 unsigned int correct_part_num;
400
401 scan_uint(part,&part_num);
402
403 if (!stralloc_copy(&mess_dir,&queue_dir)) die_nomem();
404 if (!stralloc_cats(&mess_dir,"mess/")) die_nomem();
405 if (!stralloc_cats(&mess_dir,part)) die_nomem();
406 if (!stralloc_0(&mess_dir)) die_nomem();
407
408 dir = opendir(mess_dir.s);
409 if (!dir) return -1;
410
411 while ((d = readdir(dir))) {
412 if (d->d_name[0] == '.') continue;
413 /*check from mess*/
415 if (!stralloc_append(&temp_filename,"/")) die_nomem();
416 if (!stralloc_cats(&temp_filename,d->d_name)) die_nomem();
417 if (!stralloc_0(&temp_filename)) die_nomem();
418 if (stat(temp_filename.s,&st)) { closedir(dir); return -1; }
419
420 /*check that filename == inode number*/
421 /*check that inode%auto_split == part_num*/
422 scan_uint(d->d_name,&old_inode);
423 correct_part_num = st.st_ino % split_num;
424 if (st.st_ino != old_inode || part_num != correct_part_num) {
425 /*rename*/
426 inode[fmt_ulong(inode,st.st_ino)] = 0;
427 new_part[fmt_ulong(new_part,correct_part_num)] = 0;
428 if (rename_mess("dkim/",part,new_part,d->d_name,inode)) { closedir(dir); return -1; }
429 if (rename_mess("mess/",part,new_part,d->d_name,inode)) { closedir(dir); return -1; }
430 if (rename_mess("info/",part,new_part,d->d_name,inode)) { closedir(dir); return -1; }
431 if (rename_mess("local/",part,new_part,d->d_name,inode)) { closedir(dir); return -1; }
432 if (rename_mess("remote/",part,new_part,d->d_name,inode)) { closedir(dir); return -1; }
433 if (rename_mess("todo/",part,new_part,d->d_name,inode)) { closedir(dir); return -1; }
434 if (rename_mess("intd/",part,new_part,d->d_name,inode)) { closedir(dir); return -1; }
435
436 if (rename_mess("bounce","","",d->d_name,inode)) { closedir(dir); return -1; }
437 }
438 }
439
440 closedir(dir);
441 return 0;
442}
443
444static int fix_names()
445{
446 int i;
447
448 if (!stralloc_copy(&check_dir,&queue_dir)) die_nomem();
449 if (!stralloc_cats(&check_dir,"mess")) die_nomem();
450 if (!stralloc_0(&check_dir)) die_nomem();
451
452 for (i = 0; i < split_num; i++) {
453 strnum[fmt_ulong(strnum,i)] = 0;
454 if (fix_part(strnum)) return -1;
455 }
456
457 return 0;
458}
459
460static int check_dirs()
461{
462 /*check queue existence*/
463 if (!stralloc_copy(&check_dir,&queue_dir)) die_nomem();
464 if (!stralloc_0(&check_dir)) die_nomem();
465 if (check_item(check_dir.s,qmailq_uid,qmail_gid,0750,'d',0)) return -1;
466
467 if (!stralloc_copy(&check_dir,&queue_dir)) die_nomem();
468 if (!stralloc_cats(&check_dir,"info")) die_nomem();
469 if (!stralloc_0(&check_dir)) die_nomem();
470 if (check_item(check_dir.s,qmails_uid,qmail_gid,0700,'d',0)) return -1;
471 if (check_splits(check_dir.s,qmails_uid,qmail_gid,0700,qmail_gid,0600)) return -1;
472
473 if (!stralloc_copy(&check_dir,&queue_dir)) die_nomem();
474 if (!stralloc_cats(&check_dir,"mess")) die_nomem();
475 if (!stralloc_0(&check_dir)) die_nomem();
476 if (check_item(check_dir.s,qmailq_uid,qmail_gid,0750,'d',0)) return -1;
477 if (check_splits(check_dir.s,qmailq_uid,qmail_gid,0750,-1,0644)) return -1;
478
479 if (!stralloc_copy(&check_dir,&queue_dir)) die_nomem();
480 if (!stralloc_cats(&check_dir,"remote")) die_nomem();
481 if (!stralloc_0(&check_dir)) die_nomem();
482 if (check_item(check_dir.s,qmails_uid,qmail_gid,0700,'d',0)) return -1;
483 if (check_splits(check_dir.s,qmails_uid,qmail_gid,0700,qmail_gid,0600)) return -1;
484
485 if (!stralloc_copy(&check_dir,&queue_dir)) die_nomem();
486 if (!stralloc_cats(&check_dir,"local")) die_nomem();
487 if (!stralloc_0(&check_dir)) die_nomem();
488 if (check_item(check_dir.s,qmails_uid,qmail_gid,0700,'d',0)) return -1;
489 if (check_splits(check_dir.s,qmails_uid,qmail_gid,0700,qmail_gid,0600)) return -1;
490
491 if (!stralloc_copy(&check_dir,&queue_dir)) die_nomem();
492 if (!stralloc_cats(&check_dir,"intd")) die_nomem();
493 if (!stralloc_0(&check_dir)) die_nomem();
494 if (check_item(check_dir.s,qmailq_uid,qmail_gid,0700,'d',0)) return -1;
495 if (check_splits(check_dir.s,qmailq_uid,qmail_gid,0700,qmail_gid,0600)) return -1;
496
497 /*check the bigtodo queue */
498 if (!stralloc_copy(&check_dir,&queue_dir)) die_nomem();
499 if (!stralloc_cats(&check_dir,"todo")) die_nomem();
500 if (!stralloc_0(&check_dir)) die_nomem();
501 if (check_item(check_dir.s,qmailq_uid,qmail_gid,0750,'d',0)) return -1;
502 if (check_splits(check_dir.s,qmailq_uid,qmail_gid,0750,-1,0644)) return -1;
503
504 /*check the dkim staging area */
505 if (!stralloc_copy(&check_dir,&queue_dir)) die_nomem();
506 if (!stralloc_cats(&check_dir,"dkim")) die_nomem();
507 if (!stralloc_0(&check_dir)) die_nomem();
508 if (check_item(check_dir.s,qmailq_uid,qmail_gid,0750,'d',0)) return -1;
509 if (check_splits(check_dir.s,qmailq_uid,qmail_gid,0750,qmail_gid,0644)) return -1;
510
511 /*check the others*/
512 if (!stralloc_copy(&check_dir,&queue_dir)) die_nomem();
513 if (!stralloc_cats(&check_dir,"bounce")) die_nomem();
514 if (!stralloc_0(&check_dir)) die_nomem();
515 if (check_item(check_dir.s,qmails_uid,qmail_gid,0700,'d',0)) return -1;
516 if (check_files(check_dir.s,qmails_uid,qmail_gid,0600)) return -1;
517
518 if (!stralloc_copy(&check_dir,&queue_dir)) die_nomem();
519 if (!stralloc_cats(&check_dir,"pid")) die_nomem();
520 if (!stralloc_0(&check_dir)) die_nomem();
521 if (check_item(check_dir.s,qmailq_uid,qmail_gid,0700,'d',0)) return -1;
522
523 warn_files(check_dir.s);
524
525 /* lock has special files that must exist */
526 if (!stralloc_copy(&check_dir,&queue_dir)) die_nomem();
527 if (!stralloc_cats(&check_dir,"lock")) die_nomem();
528 if (!stralloc_0(&check_dir)) die_nomem();
529 if (check_item(check_dir.s,qmailq_uid,qmail_gid,0750,'d',0)) return -1;
530
531 if (!stralloc_copy(&check_dir,&queue_dir)) die_nomem();
532 if (!stralloc_cats(&check_dir,"lock/sendmutex")) die_nomem();
533 if (!stralloc_0(&check_dir)) die_nomem();
534 if (check_item(check_dir.s,qmails_uid,qmail_gid,0600,'z',0)) return -1;
535
536 if (!stralloc_copy(&check_dir,&queue_dir)) die_nomem();
537 if (!stralloc_cats(&check_dir,"lock/tcpto")) die_nomem();
538 if (!stralloc_0(&check_dir)) die_nomem();
539 if (check_item(check_dir.s,qmailr_uid,qmail_gid,0644,'z',1024)) return -1;
540
541 if (!stralloc_copy(&check_dir,&queue_dir)) die_nomem();
542 if (!stralloc_cats(&check_dir,"lock/trigger")) die_nomem();
543 if (!stralloc_0(&check_dir)) die_nomem();
544 if (check_item(check_dir.s,qmails_uid,qmail_gid,0622,'p',0)) return -1;
545
546 return 0;
547}
548
549/* stolen from qmail-send */
550
551stralloc fn = {0};
552
553static void fnmake_init() { while (!stralloc_ready(&fn,FMTQFN)) die_nomem(); }
554static void fnmake_local(unsigned long id) { fn.len = fmtqfn(fn.s,"local/",id,1); }
555static void fnmake_remote(unsigned long id) { fn.len = fmtqfn(fn.s,"remote/",id,1); }
556static void fnmake_mess(unsigned long id) { fn.len = fmtqfn(fn.s,"mess/",id,1); }
557static void fnmake_dkim(unsigned long id) { fn.len = fmtqfn(fn.s,"dkim/",id,1); }
558static void fnmake_info(unsigned long id) { fn.len = fmtqfn(fn.s,"info/",id,1); }
559static void fnmake_bounce(unsigned long id) { fn.len = fmtqfn(fn.s,"bounce/",id,0); }
560
561static void warn_unlink(unsigned long id)
562{
563 char foo[FMT_ULONG];
564 foo[fmt_ulong(foo,id)] = 0;
565 logmsg(WHO,99,WARN,B("no such file to unlink #",foo));
566}
567
568static int delete_msg(unsigned long id)
569{
570 struct stat st;
571 int bounce = 1;
572
573 if (chdir(auto_queue) == -1) err_chdir();
574 if (chdir("queue") == -1) err_chdir();
575
576 fnmake_init();
577
578 fnmake_mess(id); // regular message pre-processed
579 if (stat(fn.s,&st) == -1) err_unlink(id);
580 else bounce = 0;
581 if (!bounce && unlink(fn.s) == -1)
582 if (errno != ENOENT) err_unlink(id);
583
584 fnmake_info(id); // not delivered yet
585 if (!stat(fn.s,&st))
586 if (unlink(fn.s) == -1)
587 if (errno != ENOENT) err_unlink(id);
588
589 if (bounce) {
590 fnmake_bounce(id);
591 if (!stat(fn.s,&st)) { warn_unlink(id); return 1; }
592 if (unlink(fn.s) == -1)
593 if (errno != ENOENT) err_unlink(id);
594 }
595
596 fnmake_remote(id);
597 if (!stat(fn.s,&st))
598 if (unlink(fn.s) == -1)
599 if (errno != ENOENT) err_unlink(id);
600
601 fnmake_local(id);
602 if (!stat(fn.s,&st))
603 if (unlink(fn.s) == -1)
604 if (errno != ENOENT) err_unlink(id);
605
606 return 0;
607}
608
609int main(int argc, char * const *argv)
610{
611 char *mess = 0;
612 unsigned long id = 0;
613 unsigned int n;
614
615
616 if (argc > 1) {
617 if (!str_diff(argv[1],"-i")) {
619 } else if (!str_diff(argv[1],"-d")) {
620 if (!argv[2]) logmsg(WHO,111,USAGE,"qmail-qmaint [-i] || [-d messid] || [-D]");
621 mess = argv[2];
622 flag_delete = 1;
623 scan_ulong(mess,&id);
624 } else if (!str_diff(argv[1],"-D")) {
625 flag_delete = 2;
626 } else
627 logmsg(WHO,111,USAGE,"qmail-qmaint [-i] || [-d messid] || [-D]");
628 }
629
631 if (!stralloc_cats(&queue_dir,"/queue/")) die_nomem();
632
633 logmsg(WHO,0,INFO,B("Checking s/qmail queue at: ",auto_queue,"/queue/"));
634
635 /* get constants */
636
642
643 /*check that all the proper directories exist with proper credentials*/
644
645 if (check_dirs()) die_check();
646
647 if (flag_delete == 1) {
648 if (!delete_msg(id))
649 logmsg(WHO,0,INFO,B("file ",mess," from queue deleted."));
650 } else if (flag_delete == 2) {
651 n = cleanup_dkim();
652 strnum[fmt_uint(strnum,n)] = 0;
653 logmsg(WHO,0,INFO,B(strnum," DKIM staging files from queue deleted."));
654 } else
655 if (fix_names()) die_check();
656
657 logmsg(WHO,0,INFO,"done.");
658
659 _exit (0);
660}
char auto_queue[]
int auto_split
int auto_gidq
int auto_uidr
int auto_uidq
int auto_uids
int main()
Definition: chkshsgr.c:6
char num[FMT_ULONG]
Definition: chkspawn.c:8
unsigned int date822fmt(char *s, struct datetime *dt)
Definition: date822fmt.c:9
void datetime_tai(struct datetime *dt, datetime_sec t)
Definition: datetime.c:4
long datetime_sec
Definition: datetime.h:15
int stralloc_copys(stralloc *, char const *)
void _exit(int)
int rename(const char *, const char *)
buffer mess
Definition: fastforward.c:65
int fifo_make(char *fn, int mode)
Definition: fifo.c:8
unsigned int fmtqfn(char *s, char *dirslash, unsigned long id, int flagsplit)
Definition: fmtqfn.c:5
#define FMTQFN
Definition: fmtqfn.h:6
void perm(char *prefix1, char *prefix2, char *prefix3, char *file, int type, int uid, int gid, int mode)
Definition: instcheck.c:12
int match
Definition: matchup.c:196
ulongalloc uid
Definition: matchup.c:59
int fd
stralloc foo
Definition: qmail-local.c:74
stralloc check_dir
Definition: qmail-qmaint.c:32
int qmails_uid
Definition: qmail-qmaint.c:51
stralloc dkim_dir
Definition: qmail-qmaint.c:38
int qmail_gid
Definition: qmail-qmaint.c:53
int flag_interactive
Definition: qmail-qmaint.c:43
stralloc queue_dir
Definition: qmail-qmaint.c:31
stralloc fn
Definition: qmail-qmaint.c:551
#define OWNER
Definition: qmail-qmaint.c:103
stralloc temp_dirname
Definition: qmail-qmaint.c:33
int flag_delete
Definition: qmail-qmaint.c:48
stralloc temp_filename
Definition: qmail-qmaint.c:34
char strnum[FMT_ULONG]
Definition: qmail-qmaint.c:42
int flag_permfix
Definition: qmail-qmaint.c:46
stralloc new_name
Definition: qmail-qmaint.c:36
int qmailr_uid
Definition: qmail-qmaint.c:52
stralloc mess_dir
Definition: qmail-qmaint.c:37
#define CPERMS
Definition: qmail-qmaint.c:101
stralloc birth_date
Definition: qmail-qmaint.c:40
stralloc query
Definition: qmail-qmaint.c:39
int qmailq_uid
Definition: qmail-qmaint.c:50
int split_num
Definition: qmail-qmaint.c:54
#define COWNER
Definition: qmail-qmaint.c:104
int flag_dircreate
Definition: qmail-qmaint.c:44
#define DIRS
Definition: qmail-qmaint.c:97
#define WHO
Definition: qmail-qmaint.c:29
int flag_filecreate
Definition: qmail-qmaint.c:45
int flag_namefix
Definition: qmail-qmaint.c:47
stralloc old_name
Definition: qmail-qmaint.c:35
#define FILES
Definition: qmail-qmaint.c:98
#define PERMS
Definition: qmail-qmaint.c:100
unsigned long size
Definition: qmail-qread.c:56
struct datetime dt
Definition: qmail-queue.c:35
struct del * d[CHANNELS]
Definition: qmail-send.c:726
void die_nomem(void)
Definition: qreceipt.c:23
void write()