ezmlmx 0.68
ezmlmx
Loading...
Searching...
No Matches
ezmlm-idx.c
Go to the documentation of this file.
1#include <sys/types.h>
2#include <sys/stat.h>
3#include <unistd.h>
4#include "stralloc.h"
5#include "error.h"
6#include "lock.h"
7#include "readclose.h"
8#include "open.h"
9#include "getln.h"
10#include "getoptb.h"
11#include "case.h"
12#include "scan.h"
13#include "str.h"
14#include "fmt.h"
15#include "readwrite.h"
16#include "exit.h"
17#include "buffer.h"
18#include "sig.h"
19#include "byte.h"
20#include "idx.h"
21#include "mime.h"
22#include "errtxt.h"
23#include "getconf.h"
24#include "makehash.h"
25#include "auto_version.h"
26#include "logmsg.h"
27#include "lockfile.h"
28
29#define WHO "ezmlm-idx"
30
36
37
38char strnum[FMT_ULONG];
39char hash[HASHLEN];
40
41stralloc fnadir = {0};
42stralloc fnif = {0};
43stralloc fnifn = {0};
44stralloc fnaf = {0};
45
46stralloc line = {0};
47stralloc lines = {0};
48stralloc dummy = {0};
49
52int fd;
53int flagdate = 0; /* use 'Received:' header by default, =1 -> 'Date:' */
54
55/* for reading index and in ezmlm-idx for reading message */
56
57static buffer bi;
58static char inbuf[1024];
59
60buffer bx;
61char indexbuf[1024];
62
63struct stat st;
64
65stralloc subject = {0};
66stralloc author = {0};
67stralloc authmail = {0};
68stralloc received = {0};
69stralloc prefix = {0};
70stralloc charset = {0};
71
72stralloc num = {0};
73
74static void die_usage(void) { logmsg(WHO,100,USAGE,"ezmlm-idx [-dDF] [-f msg] dir"); }
75static void die_nomem(void) { logmsg(WHO,100,FATAL,ERR_NOMEM); }
76
88
90{
91int foundsubject = 0;
92int issubject = 0;
93int isfrom = 0;
94int foundreceived = 0;
95int foundfrom = 0;
96int match;
97int r;
98unsigned int pos,pos1;
99
100 buffer_init(&bi,read,fd,inbuf,sizeof(inbuf));
101 for (;;) {
102 if (getln(&bi,&line,&match,'\n') == -1)
103 logmsg(WHO,111,FATAL,ERR_READ_INPUT);
104 if (match) {
105 if (line.len == 1)
106 break;
107 if (*line.s == ' ' || *line.s == '\t') { /* continuation */
108 if (issubject) {
109 if (!stralloc_cat(&subject,&line)) die_nomem();
110 } else if (isfrom)
111 if (!stralloc_cat(&author,&line)) die_nomem();
112 } else {
113 issubject = 0;
114 isfrom = 0;
115 if (!foundsubject && case_startb(line.s,line.len,"Subject:")) {
116 if (!stralloc_copyb(&subject,line.s+8,line.len-8)) die_nomem();
117 foundsubject = 1;
118 issubject = 1;
119 } else if (!foundfrom && case_startb(line.s,line.len,"From:")) {
120 if (!stralloc_copyb(&author,line.s+5,line.len-5)) die_nomem();
121 foundfrom = 1;
122 isfrom = 1;
123 } else if (!flagdate && !foundreceived &&
124 case_startb(line.s,line.len,"Received:")) {
125 pos = byte_chr(line.s,line.len,';');
126 if (pos != line.len)
127 if (!stralloc_copyb(&received,line.s+pos+2,line.len - pos - 3))
128 die_nomem();
129 foundreceived = 1;
130 } else if (flagdate && !foundreceived &&
131 case_startb(line.s,line.len,"Date:")) {
132 if (line.len < 22) continue; /* illegal */
133 pos = 6 + byte_chr(line.s+6,line.len-6,',');
134 if (pos == line.len)
135 pos = 5;
136 ++pos;
137 while (line.s[pos] == ' ' || line.s[pos] == '\t') ++pos; /* dd */
138 pos1 = pos + 3;
139 while (++pos1 < line.len && line.s[pos1] != ' '); /* mo */
140 ++pos1;
141 if (!stralloc_copyb(&received,line.s+pos,pos1 - pos))
142 die_nomem(); /* '01 Jun ' */
143 if (pos1 + 2 < line.len) {
144 if (line.s[pos1 + 2] == ' ') { /* 2-digit */
145 if (line.s[pos1] >= '7') { /* >= 70 */
146 if (!stralloc_cats(&received,"19")) die_nomem();
147 } else if (!stralloc_cats(&received,"20")) die_nomem();
148 pos = pos1 + 3; /* 2 digit */
149 } else
150 pos = pos1 + 5; /* 4 digit */
151 if (pos < line.len) {
152 pos += byte_chr(line.s+pos,line.len-pos,' '); /* after time */
153 if (pos < line.len) {
154 ++pos; /* zone */
155 while (line.s[pos] != ' ' && line.s[pos] != '\n') ++pos;
156 } else
157 pos = line.len - 1; /* no zone. Illegal; better than 0 */
158 if (!stralloc_catb(&received,line.s+pos1,pos - pos1))
159 die_nomem();
160 foundreceived = 1;
161 continue;
162 }
163 }
164 received.len = 0; /* bad format - scrap */
165 }
166 }
167 } else
168 break;
169 }
170
171 if (foundsubject) {
172 concat_hdr(subject.s,subject.len,&lines); /* make 1 line */
173 decode_hdr(lines.s,lines.len,&line); /* decode mime */
174 r= unfold_hdr(line.s,line.len,&subject,charset.s,&prefix,1); /* trim mime */
175 }
176 else {
177 r = 0;
178 subject.len = 0;
179 }
180 return r;
181}
182
183int main(int argc,char **argv)
184{
185 char *dir, *cp;
186 unsigned long msgnum = 0L;
187 unsigned long msgmax;
188 int opt,r;
189
190 while ((opt = getoptb(argc,argv,"dDf:FvV")) != opteof)
191 switch (opt) {
192 case 'd': flagdate = 1; break;
193 case 'D': flagdate = 0; break;
194 case 'f': if (optarg) scan_ulong(optarg,&msgnum); break;
195 case 'F': msgnum = 0L;
196 case 'v':
197 case 'V': logmsg(WHO,0,VERSION,auto_version);
198 default: die_usage();
199 }
200 dir = argv[optind];
201 if (!dir) die_usage();
202
203 if (chdir(dir) == -1)
204 logmsg(WHO,100,FATAL,B(ERR_SWITCH,dir));
205
206 umask(022);
207 sig_pipeignore(); /* obtain lock to write index files */
208 fdlock = lockfile("lock");
209
210 getconf_line(&charset,"charset",0,dir);
211 if (!stralloc_0(&charset)) die_nomem();
212
213 getconf_line(&prefix,"prefix",0,dir); /* support rfc2047-encoded prefix */
214 decode_hdr(prefix.s,prefix.len,&line);
215 unfold_hdr(line.s,line.len,&prefix,charset.s,&dummy,0); /* need only decoded one */
216
217 switch (openreadclose("num",&num,32)) { /* Get message number */
218 case -1: logmsg(WHO,100,FATAL,B(ERR_READ,"/num: ",dir));
219 case 0: logmsg(WHO,100,FATAL,B(ERR_NOEXIST,"/num :",dir));
220 }
221 if (!stralloc_0(&num)) die_nomem();
222 scan_ulong(num.s,&msgmax);
223 if (msgnum > msgmax) _exit(0);
224 if (msgnum) {
225 msgnum = (msgnum / 100) * 100 - 1;
226 }
227 while (++msgnum <= msgmax) {
228 if (msgnum == 1 || !(msgnum % 100)) {
229 if (!stralloc_copys(&fnadir,"archive/")) die_nomem();
230 if (!stralloc_catb(&fnadir,strnum,fmt_ulong(strnum,msgnum / 100))) die_nomem();
231 if (!stralloc_copy(&fnifn,&fnadir)) die_nomem();
232 if (!stralloc_copy(&fnif,&fnadir)) die_nomem();
233 if (!stralloc_cats(&fnif,"/index")) die_nomem();
234 if (!stralloc_cats(&fnifn,"/indexn")) die_nomem();
235 if (!stralloc_0(&fnadir)) die_nomem();
236 if (!stralloc_0(&fnifn)) die_nomem();
237 if (!stralloc_0(&fnif)) die_nomem();
238
239 if (mkdir(fnadir.s,0755) == -1) /* May not exist, so be nice and make it */
240 if (errno != EEXIST)
241 logmsg(WHO,100,FATAL,B(ERR_CREATE,fnadir.s));
242
243 fdindexn = open_trunc(fnifn.s); /* Open index */
244 if (fdindexn == -1)
245 logmsg(WHO,100,FATAL,B(ERR_WRITE,fnifn.s));
246
247 buffer_init(&bx,buffer_unixwrite,fdindexn,indexbuf,sizeof(indexbuf)); /* set up buffers for index */
248 }
249
250 /* Get subject without the 'Subject: ' make sure there is one */
251
252 if (!stralloc_copys(&fnaf,fnadir.s)) die_nomem();
253 if (!stralloc_cats(&fnaf,"/")) die_nomem();
254 if (!stralloc_catb(&fnaf,strnum,
255 fmt_uint0(strnum,(unsigned int) (msgnum % 100),2))) die_nomem();
256 if (!stralloc_0(&fnaf)) die_nomem();
257 fd = open_read(fnaf.s);
258 if (fd == -1) {
259 if (errno != ENOENT)
260 logmsg(WHO,100,FATAL,B(ERR_READ,fnaf.s));
261 } else if (fstat(fd,&st) == -1 || (!(st.st_mode & 0100)))
262 close(fd);
263 else {
264 int k;
265 subject.len = 0; /* clear in case they're mibig in msg */
266 author.len = 0;
267 received.len = 0;
269 close(fd);
270 if (!stralloc_copyb(&line,strnum,fmt_ulong(strnum,msgnum))) die_nomem();
271 if (!stralloc_cats(&line,": ")) die_nomem();
272 makehash(subject.s,subject.len,hash);
273 if (!stralloc_catb(&line,hash,HASHLEN)) die_nomem();
274 if (!stralloc_cats(&line," ")) die_nomem();
275 if (r & 1) /* reply */
276 if (!stralloc_cats(&line,"Re: ")) die_nomem();
277 if (!stralloc_cat(&line,&subject)) die_nomem();
278 if (!stralloc_cats(&line,"\n\t")) die_nomem();
279 if (!stralloc_cat(&line,&received)) die_nomem();
280 if (!stralloc_cats(&line,";")) die_nomem();
281
283 mkauthhash(lines.s,lines.len,hash);
284 if (!stralloc_catb(&line,hash,HASHLEN)) die_nomem();
285
286 k = author_name(&cp,lines.s,lines.len);
287 decode_hdr(cp,k,&author);
288
290
291 if (!stralloc_cats(&line," ")) die_nomem();
292 if (!stralloc_cat(&line,&lines)) die_nomem();
293 if (!stralloc_cats(&line,"\n")) die_nomem();
294 if (buffer_put(&bx,line.s,line.len) == -1)
295 logmsg(WHO,100,FATAL,B(ERR_WRITE,fnifn.s));
296 }
297
298 if (!((msgnum + 1) % 100) ||
299 (msgnum == msgmax)) { /* last in this set */
300 if (buffer_flush(&bx) == -1)
301 logmsg(WHO,100,FATAL,B(ERR_FLUSH,fnifn.s));
302 if (fsync(fdindexn) == -1)
303 logmsg(WHO,100,FATAL,B(ERR_SYNC,fnifn.s));
304 if (fchmod(fdindexn,MODE_ARCHIVE | 0700) == -1)
305 logmsg(WHO,100,FATAL,B(ERR_WRITE,fnifn.s));
306 if (close(fdindexn) == -1)
307 logmsg(WHO,100,FATAL,B(ERR_CLOSE,fnifn.s));
308 if (rename(fnifn.s,fnif.s) == -1)
309 logmsg(WHO,111,FATAL,B(ERR_MOVE,fnifn.s));
310 }
311 }
312 fd = open_append("indexed");
313 if (fd == -1)
314 logmsg(WHO,100,FATAL,B(ERR_CREATE,"/indexed: ",dir));
315 close(fd);
316 close(fdlock);
317 _exit(0);
318
319 return 0;
320}
#define MODE_ARCHIVE
Definition idx.h:183
void mkauthhash(const char *s, unsigned int len, char *h)
Definition makehash.c:133
void makehash(const char *indata, unsigned int inlen, char *hash)
Definition makehash.c:104
const char auto_version[]
int unfold_hdr(char *, unsigned long, stralloc *, const char *, stralloc *, int)
Definition unfold_hdr.c:160
Error messages. If you translate these, I would urge you to keep the English version as well....
#define ERR_FLUSH
Definition errtxt.h:20
#define ERR_NOMEM
Definition errtxt.h:14
#define ERR_SYNC
Definition errtxt.h:22
#define ERR_MOVE
Definition errtxt.h:29
#define ERR_NOEXIST
Definition errtxt.h:40
#define ERR_READ_INPUT
Definition errtxt.h:26
#define ERR_READ
Definition errtxt.h:18
#define ERR_CREATE
Definition errtxt.h:28
#define ERR_SWITCH
Definition errtxt.h:42
#define ERR_WRITE
Definition errtxt.h:17
#define ERR_CLOSE
Definition errtxt.h:16
int lockfile(const char *)
Definition lockfile.c:15
void die_nomem()
Definition getconf.c:17
int getconf_line(stralloc *sa, const char *fn, int flagrequired, const char *dir)
Definition getconf.c:53
unsigned int author_name(char **sout, char *s, unsigned int l)
Definition author.c:19
#define WHO
Definition author.c:1
char indexbuf[1024]
Definition ezmlm-get.c:163
buffer bx
Definition ezmlm-get.c:162
char inbuf[1024]
stralloc num
char * dir
buffer bi
int main()
Definition ezmlm-weed.c:69
void concat_hdr(char *indata, unsigned int n, stralloc *outdata)
Definition concat_hdr.c:25
int opt
Definition ezmlm-cron.c:53
const char * cp
Definition ezmlm-cron.c:76
int fdlock
Definition ezmlm-cron.c:71
int fd
Definition ezmlm-cgi.c:141
stralloc author
Definition ezmlm-cgi.c:118
const char * charset
Definition ezmlm-cgi.c:110
int match
Definition ezmlm-cgi.c:140
stralloc subject
Definition ezmlm-cgi.c:119
void decode_hdr(const char *indata, unsigned int n, stralloc *outdata)
Definition decode_hdr.c:24
#define HASHLEN
Definition idxthread.c:25
stralloc authmail
Definition ezmlm-idx.c:67
stralloc fnaf
Definition ezmlm-idx.c:44
stralloc prefix
Definition ezmlm-idx.c:69
int fdindexn
Definition ezmlm-idx.c:50
stralloc fnif
Definition ezmlm-idx.c:42
stralloc lines
Definition ezmlm-idx.c:47
int idx_get_trimsubject(void)
reads an open message from 'fd', extracts the subject (if any), and returns the subject in 'sub',...
Definition ezmlm-idx.c:89
stralloc fnadir
Definition ezmlm-idx.c:41
int flagdate
Definition ezmlm-idx.c:53
stralloc dummy
Definition ezmlm-idx.c:48
stralloc fnifn
Definition ezmlm-idx.c:43
stralloc received
Definition ezmlm-idx.c:68
unsigned long msgnum
const char * logmsg(const char *dir, unsigned long num, unsigned long listno, unsigned long subs, int done)
Definition loginfo.c:32