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 int mbox_get(struct mbox
*mbox
, int i
, char **msg
, long *msglen
)
58 if (i
< 0 || i
>= mbox
->n
)
62 *msglen
= mbox
->modlen
[i
];
65 *msglen
= mbox
->msglen
[i
];
70 int mbox_set(struct mbox
*mbox
, int i
, char *msg
, long msz
)
72 if (i
< 0 || i
>= mbox
->n
)
75 mbox
->mod
[i
] = malloc(msz
+ 1);
77 mbox
->modlen
[i
] = msz
;
78 memcpy(mbox
->mod
[i
], msg
, msz
);
79 mbox
->mod
[i
][msz
] = '\0';
84 int mbox_len(struct mbox
*mbox
)
89 static int mbox_mails(struct mbox
*mbox
, char *s
, char *e
)
93 for (i
= 0; s
&& s
< e
; i
++) {
96 s
= mbox_from_(s
+ 6, e
);
97 mbox
->msglen
[i
] = s
? s
- r
: mbox
->buf
+ mbox
->len
- r
;
103 static int filesize(int fd
)
110 static int mbox_read(struct mbox
*mbox
)
112 int fd
= open(mbox
->path
, O_RDONLY
);
115 mbox
->len
= filesize(fd
);
116 mbox
->buf
= malloc(mbox
->len
+ 1);
119 xread(fd
, mbox
->buf
, mbox
->len
);
120 mbox
->buf
[mbox
->len
] = '\0';
122 set_atime(mbox
->path
); /* update mbox access time */
123 mbox
->n
= mbox_count(mbox
->buf
, mbox
->buf
+ mbox
->len
);
124 mbox
->msg
= malloc(mbox
->n
* sizeof(mbox
->msg
[0]));
125 mbox
->msglen
= malloc(mbox
->n
* sizeof(mbox
->msglen
[0]));
126 mbox
->mod
= malloc(mbox
->n
* sizeof(mbox
->mod
[0]));
127 mbox
->modlen
= malloc(mbox
->n
* sizeof(mbox
->modlen
[0]));
128 memset(mbox
->mod
, 0, mbox
->n
* sizeof(mbox
->mod
[0]));
129 if (!mbox
->msg
|| !mbox
->msglen
|| !mbox
->mod
|| !mbox
->modlen
)
131 if (mbox_mails(mbox
, mbox
->buf
, mbox
->buf
+ mbox
->len
))
136 static char *sdup(char *s
)
138 int n
= strlen(s
) + 1;
145 struct mbox
*mbox_open(char *path
)
148 mbox
= malloc(sizeof(*mbox
));
151 memset(mbox
, 0, sizeof(*mbox
));
152 mbox
->path
= sdup(path
);
153 if (!mbox
->path
|| mbox_read(mbox
)) {
160 void mbox_free(struct mbox
*mbox
)
163 for (i
= 0; i
< mbox
->n
; i
++)
174 static int mbox_modified(struct mbox
*mbox
)
177 for (i
= 0; i
< mbox
->n
; i
++)
183 int mbox_copy(struct mbox
*mbox
, char *path
)
187 fd
= open(path
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
190 for (i
= 0; i
< mbox
->n
; i
++) {
191 char *msg
= mbox
->mod
[i
] ? mbox
->mod
[i
] : mbox
->msg
[i
];
192 long len
= mbox
->mod
[i
] ? mbox
->modlen
[i
] : mbox
->msglen
[i
];
193 xwrite(fd
, msg
, len
);
199 int mbox_save(struct mbox
*mbox
)
206 if (!mbox_modified(mbox
))
208 fd
= open(mbox
->path
, O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
);
209 newlen
= filesize(fd
) - mbox
->len
;
211 newbuf
= malloc(newlen
);
212 lseek(fd
, mbox
->len
, 0);
213 xread(fd
, newbuf
, newlen
);
215 while (i
< mbox
->n
&& !mbox
->mod
[i
])
216 off
+= mbox
->msglen
[i
++];
218 for (; i
< mbox
->n
; i
++) {
219 char *msg
= mbox
->mod
[i
] ? mbox
->mod
[i
] : mbox
->msg
[i
];
220 long len
= mbox
->mod
[i
] ? mbox
->modlen
[i
] : mbox
->msglen
[i
];
221 xwrite(fd
, msg
, len
);
223 ftruncate(fd
, lseek(fd
, 0, 1));
228 int mbox_ith(char *path
, int n
, char **msg
, long *msz
)
230 int fd
= open(path
, O_RDONLY
);
238 buf
= malloc(len
+ 1);
245 s
= mbox_from_(buf
, e
);
246 for (i
= 0; s
&& i
< n
; i
++)
247 s
= mbox_from_(s
+ 1, e
);
250 r
= mbox_from_(s
+ 1, e
);
253 *msg
= malloc(r
- s
+ 1);
257 memcpy(*msg
, s
, *msz
);