10 #include <sys/types.h>
15 #define INCSIZE (1 << 22)
17 static void set_atime(char *filename
)
22 times
.actime
= time(NULL
);
23 times
.modtime
= st
.st_mtime
;
24 utime(filename
, ×
);
27 static char *mail_start(char *r
)
32 if (!strncmp("From ", s
, 5) && (s
== r
|| *(s
- 1) == '\n'))
34 if ((t
= strchr(s
+ 1, 'F')))
42 static char *mail_hdrs(struct mail
*mail
, char *s
)
44 static char stat
[] = "Status:";
46 while (s
&& *s
&& *s
!= '\r' && *s
!= '\n') {
47 if (isalpha(*s
) && mail
->nhdrs
< MAXHDRS
)
48 mail
->hdrs
[mail
->nhdrs
++] = s
;
49 if (!strncmp(stat
, s
, sizeof(stat
) - 1))
51 if ((r
= strchr(s
+ 1, '\n')))
54 s
= strchr(s
+ 1, '\0');
56 mail
->hdrs
[mail
->nhdrs
] = s
;
60 char *mail_hdr(struct mail
*mail
, char *hdr
)
63 int len
= strlen(hdr
);
64 for (i
= 1; i
< mail
->nhdrs
; i
++)
65 if (!strncasecmp(mail
->hdrs
[i
], hdr
, len
))
70 int hdr_len(char *hdr
)
74 char *r
= strchr(s
, '\n');
76 return strchr(s
, '\0') - hdr
;
84 static void mail_stat(struct mail
*mail
)
87 char *s
= mail
->stat_hdr
+ strlen("Status:");
88 while (*s
&& *s
!= '\r' && *s
!= '\n') {
91 mail
->stat
|= STAT_OLD
;
94 mail
->stat
|= STAT_NEW
;
97 mail
->stat
|= STAT_READ
;
101 mail
->orig_stat
= mail
->stat
;
103 mail
->stat
= STAT_NEW
;
107 char *mail_read(struct mail
*mail
, char *s
)
111 mail
->body
= mail_hdrs(mail
, s
);
112 end
= mail_start(mail
->body
);
113 mail
->len
= end
- mail
->head
;
114 mail
->body_len
= end
- mail
->body
;
119 static void read_mails(struct mbox
*mbox
, char *s
)
122 s
= mail_read(&mbox
->mails
[mbox
->n
++], s
);
125 int mbox_inc(struct mbox
*mbox
)
127 int fd
= open(mbox
->path
, O_RDONLY
);
129 int old_len
= mbox
->len
;
130 int len
= file_size(fd
);
134 mbox
->size
= len
+ INCSIZE
+ 1;
135 mbox
->mbox
= malloc(mbox
->size
);
137 if (len
> mbox
->size
- 1)
140 lseek(fd
, mbox
->len
, SEEK_SET
);
141 mbox
->len
+= xread(fd
, mbox
->mbox
+ mbox
->len
, len
);
142 mbox
->mbox
[mbox
->len
] = '\0';
144 set_atime(mbox
->path
);
145 if (old_len
< mbox
->len
)
146 read_mails(mbox
, mbox
->mbox
+ old_len
);
147 return mbox
->n
- old_n
;
150 struct mbox
*mbox_alloc(char *filename
)
153 mbox
= malloc(sizeof(*mbox
));
154 memset(mbox
, 0, sizeof(*mbox
));
155 strcpy(mbox
->path
, filename
);
160 void mbox_free(struct mbox
*mbox
)
166 int mail_head(struct mail
*mail
, char *buf
, int buf_len
,
171 char *dead
= s
+ buf_len
;
172 for (i
= 0; i
< n
; i
++) {
174 int pat_len
= strlen(hdrs
[i
]);
175 for (j
= 0; j
< mail
->nhdrs
; j
++) {
176 char *hdr
= mail
->hdrs
[j
];
177 if (!strncasecmp(hdr
, pat
, pat_len
)) {
178 int hdr_len
= mail
->hdrs
[j
+ 1] - hdr
;
179 if (s
+ hdr_len
> dead
)
181 memcpy(s
, hdr
, hdr_len
);
191 static int mail_changed(struct mail
*mail
)
193 return mail
->orig_stat
!= mail
->stat
;
196 void mail_write(struct mail
*mail
, int fd
)
198 char stat
[32] = "Status: ";
199 char *s
= strchr(stat
, '\0');
200 if (mail
->stat
& STAT_READ
)
202 if (mail
->stat
& STAT_OLD
)
204 if (mail
->stat
& STAT_NEW
)
207 if (!mail
->stat_hdr
) {
208 xwrite(fd
, mail
->head
, mail
->body
- mail
->head
);
209 xwrite(fd
, stat
, s
- stat
);
210 xwrite(fd
, mail
->body
, mail
->body_len
);
213 if (!mail_changed(mail
)) {
214 xwrite(fd
, mail
->head
, mail
->len
);
216 char *hdr_end
= strchr(mail
->stat_hdr
, '\n');
217 xwrite(fd
, mail
->head
, mail
->stat_hdr
- mail
->head
);
218 xwrite(fd
, stat
, s
- stat
);
220 xwrite(fd
, hdr_end
+ 1,
221 mail
->head
+ mail
->len
- hdr_end
- 1);
225 static int mbox_changed(struct mbox
*mbox
)
228 for (i
= 0; i
< mbox
->n
; i
++)
229 if (mail_changed(&mbox
->mails
[i
]))
234 int mbox_write(struct mbox
*mbox
)
238 if (mbox_inc(mbox
) == -1)
240 if (!mbox_changed(mbox
))
242 fd
= open(mbox
->path
, O_WRONLY
| O_TRUNC
| O_CREAT
, S_IRUSR
| S_IWUSR
);
243 while (i
< mbox
->n
) {
244 char *beg
= mbox
->mails
[i
].head
;
245 char *end
= mbox
->mbox
+ mbox
->len
;
246 while (i
< mbox
->n
&& !mail_changed(&mbox
->mails
[i
]))
249 end
= mbox
->mails
[i
].head
;
250 xwrite(fd
, beg
, end
- beg
);
251 if (i
< mbox
->n
&& !(mbox
->mails
[i
].stat
& STAT_DEL
))
252 mail_write(&mbox
->mails
[i
], fd
);