14 #define INCSIZE (1 << 22)
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
)
31 if (!strncmp("From ", s
, 5) && (s
== r
|| *(s
- 1) == '\n'))
33 t
= strchr(s
+ 1, 'F');
34 s
= t
? t
: strchr(s
, '\0');
39 static char *mail_hdrs(struct mail
*mail
, char *s
)
41 static char stat
[] = "Status:";
43 while (s
&& *s
&& *s
!= '\r' && *s
!= '\n') {
44 if (isalpha(*s
) && mail
->nhdrs
< MAXHDRS
)
45 mail
->hdrs
[mail
->nhdrs
++] = s
;
46 if (!strncmp(stat
, s
, sizeof(stat
) - 1))
48 if ((r
= strchr(s
+ 1, '\n')))
51 s
= strchr(s
+ 1, '\0');
53 mail
->hdrs
[mail
->nhdrs
] = s
;
57 static int startswith(char *s
, char *r
)
62 if (tolower(c1
) != tolower(c2
))
68 char *mail_hdr(struct mail
*mail
, char *hdr
)
71 for (i
= 1; i
< mail
->nhdrs
; i
++)
72 if (startswith(mail
->hdrs
[i
], hdr
))
77 int hdr_len(char *hdr
)
81 char *r
= strchr(s
, '\n');
83 return strchr(s
, '\0') - hdr
;
91 static void mail_stat(struct mail
*mail
)
94 char *s
= mail
->stat_hdr
+ strlen("Status:");
95 while (*s
&& *s
!= '\r' && *s
!= '\n') {
98 mail
->stat
|= STAT_OLD
;
101 mail
->stat
|= STAT_NEW
;
104 mail
->stat
|= STAT_READ
;
108 mail
->orig_stat
= mail
->stat
;
110 mail
->stat
= STAT_NEW
;
114 char *mail_read(struct mail
*mail
, char *s
)
118 mail
->body
= mail_hdrs(mail
, s
);
119 end
= mail_start(mail
->body
);
120 mail
->len
= end
- mail
->head
;
121 mail
->body_len
= end
- mail
->body
;
126 static void read_mails(struct mbox
*mbox
, char *s
)
129 s
= mail_read(&mbox
->mails
[mbox
->n
++], s
);
132 int mbox_inc(struct mbox
*mbox
)
134 int fd
= open(mbox
->path
, O_RDONLY
);
136 int old_len
= mbox
->len
;
137 int len
= file_size(fd
);
141 mbox
->size
= len
+ INCSIZE
+ 1;
142 mbox
->mbox
= malloc(mbox
->size
);
144 if (len
> mbox
->size
- 1)
147 lseek(fd
, mbox
->len
, SEEK_SET
);
148 mbox
->len
+= xread(fd
, mbox
->mbox
+ mbox
->len
, len
);
149 mbox
->mbox
[mbox
->len
] = '\0';
151 set_atime(mbox
->path
);
152 if (old_len
< mbox
->len
)
153 read_mails(mbox
, mbox
->mbox
+ old_len
);
154 return mbox
->n
- old_n
;
157 struct mbox
*mbox_alloc(char *filename
)
160 mbox
= malloc(sizeof(*mbox
));
161 memset(mbox
, 0, sizeof(*mbox
));
162 strcpy(mbox
->path
, filename
);
167 void mbox_free(struct mbox
*mbox
)
173 int mail_head(struct mail
*mail
, char *buf
, int buf_len
,
178 char *dead
= s
+ buf_len
;
179 for (i
= 0; i
< n
; i
++) {
181 for (j
= 0; j
< mail
->nhdrs
; j
++) {
182 char *hdr
= mail
->hdrs
[j
];
183 if (startswith(hdr
, pat
)) {
184 int hdr_len
= mail
->hdrs
[j
+ 1] - hdr
;
185 if (s
+ hdr_len
> dead
)
187 memcpy(s
, hdr
, hdr_len
);
197 static int mail_changed(struct mail
*mail
)
199 return mail
->orig_stat
!= mail
->stat
;
202 void mail_write(struct mail
*mail
, int fd
)
204 char stat
[32] = "Status: ";
205 char *s
= strchr(stat
, '\0');
206 if (mail
->stat
& STAT_READ
)
208 if (mail
->stat
& STAT_OLD
)
210 if (mail
->stat
& STAT_NEW
)
213 if (!mail_changed(mail
)) {
214 xwrite(fd
, mail
->head
, mail
->len
);
216 char *hdr_beg
= mail
->body
;
217 char *hdr_end
= mail
->body
;
218 if (mail
->stat_hdr
) {
219 char *nl
= strchr(mail
->stat_hdr
, '\n');
220 hdr_beg
= mail
->stat_hdr
;
221 hdr_end
= nl
? nl
+ 1 : mail
->body
;
223 xwrite(fd
, mail
->head
, hdr_beg
- mail
->head
);
224 xwrite(fd
, stat
, s
- stat
);
226 xwrite(fd
, hdr_end
, mail
->head
+ mail
->len
- hdr_end
);
230 static int mbox_changed(struct mbox
*mbox
)
233 for (i
= 0; i
< mbox
->n
; i
++)
234 if (mail_changed(&mbox
->mails
[i
]))
239 int mbox_write(struct mbox
*mbox
)
243 if (mbox_inc(mbox
) == -1)
245 if (!mbox_changed(mbox
))
247 fd
= open(mbox
->path
, O_WRONLY
| O_TRUNC
| O_CREAT
, S_IRUSR
| S_IWUSR
);
248 while (i
< mbox
->n
) {
249 char *beg
= mbox
->mails
[i
].head
;
250 char *end
= mbox
->mbox
+ mbox
->len
;
251 while (i
< mbox
->n
&& !mail_changed(&mbox
->mails
[i
]))
254 end
= mbox
->mails
[i
].head
;
255 xwrite(fd
, beg
, end
- beg
);
256 if (i
< mbox
->n
&& !(mbox
->mails
[i
].stat
& STAT_DEL
))
257 mail_write(&mbox
->mails
[i
], fd
);