|
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 } |