14 #define INCSIZE (1 << 21)
16 static void set_atime(char *filename
)
21 times
.actime
= time(NULL
);
22 times
.modtime
= st
.st_mtime
;
23 utime(filename
, ×
);
26 static char *mail_start(char *r
)
30 if (!strncmp("From ", s
, 5) && (s
== r
|| *(s
- 1) == '\n'))
32 s
= strchr(s
+ 1, 'F');
37 static char *mail_hdrs(struct mail
*mail
, char *s
)
39 static char stat
[] = "Status:";
40 while (s
&& *s
&& *s
!= '\r' && *s
!= '\n') {
41 if (isalpha(*s
) && mail
->nhdrs
< MAXHDRS
)
42 mail
->hdrs
[mail
->nhdrs
++] = s
;
43 if (!strncasecmp(stat
, s
, sizeof(stat
) - 1))
45 s
= strchr(s
+ 1, '\n');
48 mail
->hdrs
[mail
->nhdrs
] = s
;
52 char *mail_hdr(struct mail
*mail
, char *hdr
)
55 int len
= strlen(hdr
);
56 for (i
= 1; i
< mail
->nhdrs
; i
++)
57 if (!strncasecmp(mail
->hdrs
[i
], hdr
, len
))
62 int hdr_len(char *hdr
)
66 char *r
= strchr(s
, '\n');
68 return strchr(s
, '\0') - hdr
;
70 if (!isspace(*(s
+ 1)))
77 static void mail_stat(struct mail
*mail
)
80 char *s
= mail
->stat_hdr
+ strlen("Status:");
81 while (*s
&& *s
!= '\r' && *s
!= '\n') {
84 mail
->stat
|= STAT_OLD
;
87 mail
->stat
|= STAT_NEW
;
90 mail
->stat
|= STAT_READ
;
94 mail
->orig_stat
= mail
->stat
;
96 mail
->stat
= STAT_NEW
;
100 static char *mail_read(struct mail
*mail
, char *s
)
105 mail
->body
= mail_hdrs(mail
, s
);
106 if (!(end
= mail_start(mail
->body
))) {
108 end
= strchr(mail
->body
, '\0');
110 mail
->len
= end
- mail
->head
;
111 mail
->body_len
= end
- mail
->body
;
113 return last
? NULL
: end
;
116 static void read_mails(struct mbox
*mbox
, char *s
)
119 s
= mail_read(&mbox
->mails
[mbox
->n
++], s
);
122 int mbox_inc(struct mbox
*mbox
)
124 int fd
= open(mbox
->path
, O_RDONLY
| O_LARGEFILE
);
126 int old_len
= mbox
->len
;
127 int len
= file_size(fd
);
131 mbox
->size
= len
+ INCSIZE
+ 1;
132 mbox
->mbox
= malloc(mbox
->size
);
134 if (len
> mbox
->size
- 1)
137 lseek(fd
, mbox
->len
, SEEK_SET
);
138 mbox
->len
+= xread(fd
, mbox
->mbox
+ mbox
->len
, len
);
139 mbox
->mbox
[mbox
->len
] = '\0';
141 set_atime(mbox
->path
);
142 if (old_len
< mbox
->len
)
143 read_mails(mbox
, mbox
->mbox
+ old_len
);
144 return mbox
->n
- old_n
;
147 struct mbox
*mbox_alloc(char *filename
)
150 mbox
= malloc(sizeof(*mbox
));
151 memset(mbox
, 0, sizeof(*mbox
));
152 strcpy(mbox
->path
, filename
);
157 void mbox_free(struct mbox
*mbox
)
163 int mail_head(struct mail
*mail
, char *buf
, int buf_len
,
168 char *dead
= s
+ buf_len
;
169 for (i
= 0; i
< n
; i
++) {
171 int pat_len
= strlen(hdrs
[i
]);
172 for (j
= 0; j
< mail
->nhdrs
; j
++) {
173 char *hdr
= mail
->hdrs
[j
];
174 if (!strncasecmp(hdr
, pat
, pat_len
)) {
175 int hdr_len
= mail
->hdrs
[j
+ 1] - hdr
;
176 if (s
+ hdr_len
> dead
)
178 memcpy(s
, hdr
, hdr_len
);
188 static int mail_changed(struct mail
*mail
)
190 return mail
->orig_stat
!= mail
->stat
;
193 void mail_write(struct mail
*mail
, int fd
)
195 char stat
[32] = "Status: ";
196 char *s
= strchr(stat
, '\0');
197 if (mail
->stat
& STAT_READ
)
201 if (!mail
->stat_hdr
) {
202 xwrite(fd
, mail
->head
, mail
->body
- mail
->head
);
203 xwrite(fd
, stat
, s
- stat
);
204 xwrite(fd
, mail
->body
, mail
->body_len
);
207 if (!mail_changed(mail
)) {
208 xwrite(fd
, mail
->head
, mail
->len
);
210 char *hdr_end
= strchr(mail
->stat_hdr
, '\n');
211 xwrite(fd
, mail
->head
, mail
->stat_hdr
- mail
->head
);
212 xwrite(fd
, stat
, s
- stat
);
214 xwrite(fd
, hdr_end
+ 1,
215 mail
->head
+ mail
->len
- hdr_end
- 1);
219 static int mbox_changed(struct mbox
*mbox
)
222 for (i
= 0; i
< mbox
->n
; i
++)
223 if (mail_changed(&mbox
->mails
[i
]))
228 int mbox_write(struct mbox
*mbox
)
232 if (mbox_inc(mbox
) == -1)
234 if (!mbox_changed(mbox
))
236 fd
= open(mbox
->path
, O_WRONLY
| O_CREAT
, S_IRUSR
| S_IWUSR
);
237 while (i
< mbox
->n
) {
238 char *beg
= mbox
->mails
[i
].head
;
239 char *end
= mbox
->mbox
+ mbox
->len
;
240 while (i
< mbox
->n
&& !mail_changed(&mbox
->mails
[i
]))
243 end
= mbox
->mails
[i
].head
;
244 xwrite(fd
, beg
, end
- beg
);
246 mail_write(&mbox
->mails
[i
++], fd
);