16 char **msg
; /* messages */
17 long *msglen
; /* message lengths */
18 char **mod
; /* modified messages */
19 long *modlen
; /* modified message lengths */
20 char *buf
; /* mbox buffer */
21 long len
; /* buf len */
22 int n
; /* number of messages */
25 static void set_atime(char *filename
)
30 times
.actime
= time(NULL
);
31 times
.modtime
= st
.st_mtime
;
32 utime(filename
, ×
);
35 static char *mbox_from_(char *s
, char *e
)
38 while (s
&& s
+ 6 < e
) {
39 if (s
[0] == 'F' && s
[1] == 'r' && s
[2] == 'o' &&
40 s
[3] == 'm' && s
[4] == ' ')
42 r
= memchr(s
, '\n', e
- s
);
43 s
= r
&& r
+ 7 < e
? r
+ 1 : NULL
;
48 static int mbox_count(char *s
, char *e
)
51 while ((s
= mbox_from_(s
, e
)))
56 void mbox_get(struct mbox
*mbox
, int i
, char **msg
, long *msglen
)
60 *msglen
= mbox
->modlen
[i
];
63 *msglen
= mbox
->msglen
[i
];
67 void mbox_set(struct mbox
*mbox
, int i
, char *msg
, long msz
)
70 mbox
->mod
[i
] = malloc(msz
+ 1);
72 mbox
->modlen
[i
] = msz
;
73 memcpy(mbox
->mod
[i
], msg
, msz
);
74 mbox
->mod
[i
][msz
] = '\0';
78 int mbox_len(struct mbox
*mbox
)
83 static int mbox_mails(struct mbox
*mbox
, char *s
, char *e
)
87 for (i
= 0; s
&& s
< e
; i
++) {
90 s
= mbox_from_(s
+ 6, e
);
91 mbox
->msglen
[i
] = s
? s
- r
: mbox
->buf
+ mbox
->len
- r
;
97 static int filesize(int fd
)
104 static int mbox_read(struct mbox
*mbox
)
106 int fd
= open(mbox
->path
, O_RDONLY
);
109 mbox
->len
= filesize(fd
);
110 mbox
->buf
= malloc(mbox
->len
+ 1);
113 xread(fd
, mbox
->buf
, mbox
->len
);
114 mbox
->buf
[mbox
->len
] = '\0';
116 set_atime(mbox
->path
); /* update mbox access time */
117 mbox
->n
= mbox_count(mbox
->buf
, mbox
->buf
+ mbox
->len
);
118 mbox
->msg
= malloc(mbox
->n
* sizeof(mbox
->msg
[0]));
119 mbox
->msglen
= malloc(mbox
->n
* sizeof(mbox
->msglen
[0]));
120 mbox
->mod
= malloc(mbox
->n
* sizeof(mbox
->mod
[0]));
121 mbox
->modlen
= malloc(mbox
->n
* sizeof(mbox
->modlen
[0]));
122 memset(mbox
->mod
, 0, mbox
->n
* sizeof(mbox
->mod
[0]));
123 if (!mbox
->msg
|| !mbox
->msglen
|| !mbox
->mod
|| !mbox
->modlen
)
125 if (mbox_mails(mbox
, mbox
->buf
, mbox
->buf
+ mbox
->len
))
130 static char *sdup(char *s
)
132 int n
= strlen(s
) + 1;
139 struct mbox
*mbox_open(char *path
)
142 mbox
= malloc(sizeof(*mbox
));
145 memset(mbox
, 0, sizeof(*mbox
));
146 mbox
->path
= sdup(path
);
147 if (!mbox
->path
|| mbox_read(mbox
)) {
154 void mbox_free(struct mbox
*mbox
)
157 for (i
= 0; i
< mbox
->n
; i
++)
168 static int mbox_modified(struct mbox
*mbox
)
171 for (i
= 0; i
< mbox
->n
; i
++)
177 int mbox_copy(struct mbox
*mbox
, char *path
)
181 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
184 for (i
= 0; i
< mbox
->n
; i
++) {
185 char *msg
= mbox
->mod
[i
] ? mbox
->mod
[i
] : mbox
->msg
[i
];
186 long len
= mbox
->mod
[i
] ? mbox
->modlen
[i
] : mbox
->msglen
[i
];
187 xwrite(fd
, msg
, len
);
193 int mbox_save(struct mbox
*mbox
)
200 if (!mbox_modified(mbox
))
202 fd
= open(mbox
->path
, O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
);
203 newlen
= filesize(fd
) - mbox
->len
;
205 newbuf
= malloc(newlen
);
206 lseek(fd
, mbox
->len
, 0);
207 xread(fd
, newbuf
, newlen
);
209 while (i
< mbox
->n
&& !mbox
->mod
[i
])
210 off
+= mbox
->msglen
[i
++];
212 for (; i
< mbox
->n
; i
++) {
213 char *msg
= mbox
->mod
[i
] ? mbox
->mod
[i
] : mbox
->msg
[i
];
214 long len
= mbox
->mod
[i
] ? mbox
->modlen
[i
] : mbox
->msglen
[i
];
215 xwrite(fd
, msg
, len
);
217 ftruncate(fd
, lseek(fd
, 0, 1));
222 int mbox_ith(char *path
, int n
, char **msg
, long *msz
)
224 int fd
= open(path
, O_RDONLY
);
232 buf
= malloc(len
+ 1);
239 s
= mbox_from_(buf
, e
);
240 for (i
= 0; s
&& i
< n
; i
++)
241 s
= mbox_from_(s
+ 1, e
);
244 r
= mbox_from_(s
+ 1, e
);
247 *msg
= malloc(r
- s
+ 1);
251 memcpy(*msg
, s
, *msz
);