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