debian/rules: Use `git' potty wrapper.
[qmail] / qmail-qread.c
1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include "stralloc.h"
4 #include "substdio.h"
5 #include "subfd.h"
6 #include "fmt.h"
7 #include "str.h"
8 #include "getln.h"
9 #include "fmtqfn.h"
10 #include "readsubdir.h"
11 #include "auto_qmail.h"
12 #include "open.h"
13 #include "datetime.h"
14 #include "date822fmt.h"
15 #include "readwrite.h"
16 #include "error.h"
17 #include "exit.h"
18
19 readsubdir rs;
20
21 void die(n) int n; { substdio_flush(subfdout); _exit(n); }
22
23 void warn(s1,s2) char *s1; char *s2;
24 {
25 char *x;
26 x = error_str(errno);
27 substdio_puts(subfdout,s1);
28 substdio_puts(subfdout,s2);
29 substdio_puts(subfdout,": ");
30 substdio_puts(subfdout,x);
31 substdio_puts(subfdout,"\n");
32 }
33
34 void die_nomem() { substdio_puts(subfdout,"fatal: out of memory\n"); die(111); }
35 void die_chdir() { warn("fatal: unable to chdir",""); die(111); }
36 void die_opendir(fn) char *fn; { warn("fatal: unable to opendir ",fn); die(111); }
37
38 void err(id) unsigned long id;
39 {
40 char foo[FMT_ULONG];
41 foo[fmt_ulong(foo,id)] = 0;
42 warn("warning: trouble with #",foo);
43 }
44
45 char fnmess[FMTQFN];
46 char fninfo[FMTQFN];
47 char fnlocal[FMTQFN];
48 char fnremote[FMTQFN];
49 char fnbounce[FMTQFN];
50
51 char inbuf[1024];
52 stralloc sender = {0};
53
54 unsigned long id;
55 datetime_sec qtime;
56 int flagbounce;
57 unsigned long size;
58
59 unsigned int fmtstats(s)
60 char *s;
61 {
62 struct datetime dt;
63 unsigned int len;
64 unsigned int i;
65
66 len = 0;
67 datetime_tai(&dt,qtime);
68 i = date822fmt(s,&dt) - 7/*XXX*/; len += i; if (s) s += i;
69 i = fmt_str(s," GMT #"); len += i; if (s) s += i;
70 i = fmt_ulong(s,id); len += i; if (s) s += i;
71 i = fmt_str(s," "); len += i; if (s) s += i;
72 i = fmt_ulong(s,size); len += i; if (s) s += i;
73 i = fmt_str(s," <"); len += i; if (s) s += i;
74 i = fmt_str(s,sender.s + 1); len += i; if (s) s += i;
75 i = fmt_str(s,"> "); len += i; if (s) s += i;
76 if (flagbounce)
77 {
78 i = fmt_str(s," bouncing"); len += i; if (s) s += i;
79 }
80
81 return len;
82 }
83
84 stralloc stats = {0};
85
86 void out(s,n) char *s; unsigned int n;
87 {
88 while (n > 0)
89 {
90 substdio_put(subfdout,((*s >= 32) && (*s <= 126)) ? s : "_",1);
91 --n;
92 ++s;
93 }
94 }
95 void outs(s) char *s; { out(s,str_len(s)); }
96 void outok(s) char *s; { substdio_puts(subfdout,s); }
97
98 void putstats()
99 {
100 if (!stralloc_ready(&stats,fmtstats(FMT_LEN))) die_nomem();
101 stats.len = fmtstats(stats.s);
102 out(stats.s,stats.len);
103 outok("\n");
104 }
105
106 stralloc line = {0};
107
108 void main()
109 {
110 int channel;
111 int match;
112 struct stat st;
113 int fd;
114 substdio ss;
115 int x;
116
117 if (chdir(auto_qmail) == -1) die_chdir();
118 if (chdir("queue") == -1) die_chdir();
119 readsubdir_init(&rs,"info",die_opendir);
120
121 while (x = readsubdir_next(&rs,&id))
122 if (x > 0)
123 {
124 fmtqfn(fnmess,"mess/",id,1);
125 fmtqfn(fninfo,"info/",id,1);
126 fmtqfn(fnlocal,"local/",id,1);
127 fmtqfn(fnremote,"remote/",id,1);
128 fmtqfn(fnbounce,"bounce/",id,0);
129
130 if (stat(fnmess,&st) == -1) { err(id); continue; }
131 size = st.st_size;
132 flagbounce = !stat(fnbounce,&st);
133
134 fd = open_read(fninfo);
135 if (fd == -1) { err(id); continue; }
136 substdio_fdbuf(&ss,read,fd,inbuf,sizeof(inbuf));
137 if (getln(&ss,&sender,&match,0) == -1) die_nomem();
138 if (fstat(fd,&st) == -1) { close(fd); err(id); continue; }
139 close(fd);
140 qtime = st.st_mtime;
141
142 putstats();
143
144 for (channel = 0;channel < 2;++channel)
145 {
146 fd = open_read(channel ? fnremote : fnlocal);
147 if (fd == -1)
148 {
149 if (errno != error_noent)
150 err(id);
151 }
152 else
153 {
154 for (;;)
155 {
156 if (getln(&ss,&line,&match,0) == -1) die_nomem();
157 if (!match) break;
158 switch(line.s[0])
159 {
160 case 'D':
161 outok(" done");
162 case 'T':
163 outok(channel ? "\tremote\t" : "\tlocal\t");
164 outs(line.s + 1);
165 outok("\n");
166 break;
167 }
168 }
169 close(fd);
170 }
171 }
172 }
173
174 die(0);
175 }