Added beginnings of Maildir support.
Showing
4 changed files
with
502 additions
and
0 deletions
1 | 1999-11-23 Jakob 'sparky' Kaivo <jkaivo@elijah.nodomainname.net> | ||
2 | |||
3 | * TODO: Mention Maildir | ||
4 | |||
5 | * libmailbox/mailbox.c (mbox_init): new function | ||
6 | |||
7 | * libmailbox/maildir.h: new file | ||
8 | |||
9 | * libmailbox/maildir.c: new file | ||
10 | |||
11 | * libmailbox/mailbox.c (mbox_open): uncommented maildir_open attempt | ||
12 | |||
1 | 1999-11-15 Jeff Bailey <jbailey@nisa.net> | 13 | 1999-11-15 Jeff Bailey <jbailey@nisa.net> |
2 | 14 | ||
3 | * lib/ansi2knr*: Add | 15 | * lib/ansi2knr*: Add | ... | ... |
... | @@ -20,6 +20,8 @@ | ... | @@ -20,6 +20,8 @@ |
20 | 20 | ||
21 | + libmailbox has a nasty bug -- if the mailbox is empty, the library has no idea | 21 | + libmailbox has a nasty bug -- if the mailbox is empty, the library has no idea |
22 | what to do (Shaleh Oct 07/99) | 22 | what to do (Shaleh Oct 07/99) |
23 | |||
24 | * Maildir is VERY rough | ||
23 | 25 | ||
24 | [mail] | 26 | [mail] |
25 | - clean up 'mail''s compilation, why is there a mail script? | 27 | - clean up 'mail''s compilation, why is there a mail script? | ... | ... |
libmailbox/maildir.c
0 → 100644
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | #include <config.h> | ||
20 | #endif | ||
21 | |||
22 | #include "maildir.h" | ||
23 | |||
24 | /* | ||
25 | * Opens a mailbox | ||
26 | */ | ||
27 | int | ||
28 | maildir_open (mailbox * mbox) | ||
29 | { | ||
30 | int i; | ||
31 | int alloced = 0; | ||
32 | maildir_data *data; | ||
33 | struct dirent *entry; | ||
34 | char old_dir[PATH_MAX]; | ||
35 | struct utsname *utsinfo; | ||
36 | uname (utsinfo); | ||
37 | |||
38 | getcwd (old_dir, PATH_MAX); | ||
39 | chdir (mbox->name); | ||
40 | |||
41 | data->new = opendir ("new"); | ||
42 | data->tmp = opendir ("tmp"); | ||
43 | data->cur = opendir ("cur"); | ||
44 | data->time = time (NULL); | ||
45 | data->pid = getpid (); | ||
46 | data->sequence = 0; | ||
47 | /* data->host = strdup (utsinfo->sysname); */ | ||
48 | data->messages = malloc (10 * sizeof (maildir_message)); | ||
49 | alloced = 10; | ||
50 | |||
51 | /* process the new directory */ | ||
52 | while ((entry = readdir (data->new)) && (entry != NULL)) | ||
53 | { | ||
54 | /* no dot files */ | ||
55 | if (entry->d_name[0] != '.') | ||
56 | { | ||
57 | if (mbox->messages >= alloced) | ||
58 | { | ||
59 | alloced *= 2; | ||
60 | data->messages = realloc (data->messages, | ||
61 | alloced * sizeof (maildir_message)); | ||
62 | /* check */ | ||
63 | } | ||
64 | data->messages[mbox->messages].deleted = 0; | ||
65 | data->messages[mbox->messages].info = NULL; | ||
66 | data->messages[mbox->messages].location = new; | ||
67 | data->messages[mbox->messages].file = strdup (entry->d_name); | ||
68 | /* check */ | ||
69 | mbox->messages++; | ||
70 | } | ||
71 | } | ||
72 | |||
73 | /* then the cur directory */ | ||
74 | while ((entry = readdir (data->cur)) && (entry != NULL)) | ||
75 | { | ||
76 | if (entry->d_name[0] != '.') | ||
77 | { | ||
78 | if (mbox->messages >= alloced) | ||
79 | { | ||
80 | alloced *= 2; | ||
81 | data->messages = realloc (data->messages, | ||
82 | alloced * sizeof (maildir_message)); | ||
83 | /* check */ | ||
84 | } | ||
85 | data->messages[mbox->messages].deleted = 0; | ||
86 | data->messages[mbox->messages].location = cur; | ||
87 | data->messages[mbox->messages].file = strdup (entry->d_name); | ||
88 | /* check */ | ||
89 | /* data->messages[i].info = parse_for_info (entry->d_name); */ | ||
90 | mbox->messages++; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | for (i=0; i < mbox->messages; i++) | ||
95 | { | ||
96 | FILE *f; | ||
97 | char buf[80]; | ||
98 | chdir (mbox->name); | ||
99 | if (data->messages[i].location == new) | ||
100 | chdir ("new"); | ||
101 | else if (data->messages[i].location == cur) | ||
102 | chdir ("cur"); | ||
103 | f = fopen (data->messages[i].file, "r"); | ||
104 | data->messages[i].body = 0; | ||
105 | while (fgets (buf, 80, f)) | ||
106 | if (!strncmp (buf, "\r\n", 2) || strlen (buf) <= 1) | ||
107 | fgetpos (f, &(data->messages[i].body)); | ||
108 | fclose (f); | ||
109 | } | ||
110 | |||
111 | mbox->_data = data; | ||
112 | mbox->_close = maildir_close; | ||
113 | mbox->_delete = maildir_delete; | ||
114 | mbox->_undelete = maildir_undelete; | ||
115 | mbox->_expunge = maildir_expunge; | ||
116 | mbox->_add_message = maildir_add_message; | ||
117 | mbox->_is_deleted = maildir_is_deleted; | ||
118 | mbox->_lock = maildir_lock; | ||
119 | mbox->_get_body = maildir_get_body; | ||
120 | mbox->_get_header = maildir_get_header; | ||
121 | |||
122 | chdir (old_dir); | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * Closes and unlocks a mailbox, does not expunge | ||
128 | */ | ||
129 | int | ||
130 | maildir_close (mailbox * mbox) | ||
131 | { | ||
132 | /* FIXME: hack from unixmbox */ | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * Marks a message for deletion | ||
138 | */ | ||
139 | int | ||
140 | maildir_delete (mailbox * mbox, unsigned int num) | ||
141 | { | ||
142 | maildir_data *data; | ||
143 | |||
144 | if (mbox == NULL) | ||
145 | { | ||
146 | errno = EINVAL; | ||
147 | return -1; | ||
148 | } | ||
149 | |||
150 | if (num > mbox->messages || mbox_is_deleted (mbox, num)) | ||
151 | { | ||
152 | errno = ERANGE; | ||
153 | return -1; | ||
154 | } | ||
155 | |||
156 | data = mbox->_data; | ||
157 | data->messages[num].deleted = 1; | ||
158 | mbox->num_deleted++; | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * Unmark a message for deletion | ||
165 | */ | ||
166 | int | ||
167 | maildir_undelete (mailbox * mbox, unsigned int num) | ||
168 | { | ||
169 | maildir_data *data; | ||
170 | |||
171 | if (mbox == NULL) | ||
172 | { | ||
173 | errno = EINVAL; | ||
174 | return -1; | ||
175 | } | ||
176 | |||
177 | if (num > mbox->messages || !mbox_is_deleted (mbox, num)) | ||
178 | { | ||
179 | errno = ERANGE; | ||
180 | return -1; | ||
181 | } | ||
182 | |||
183 | data = mbox->_data; | ||
184 | data->messages[num].deleted = 0; | ||
185 | mbox->num_deleted--; | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * Updates a mailbox to remove message marked for deletion | ||
192 | */ | ||
193 | int | ||
194 | maildir_expunge (mailbox * mbox) | ||
195 | { | ||
196 | maildir_data *data; | ||
197 | int i = 0; | ||
198 | char old_dir[PATH_MAX]; | ||
199 | |||
200 | if (mbox == NULL) | ||
201 | { | ||
202 | errno = EINVAL; | ||
203 | return -1; | ||
204 | } | ||
205 | |||
206 | getcwd (old_dir, PATH_MAX); | ||
207 | chdir (mbox->name); | ||
208 | |||
209 | if (mbox->num_deleted) | ||
210 | { | ||
211 | data = mbox->_data; | ||
212 | |||
213 | for (i = 0; i < mbox->messages; i++) | ||
214 | { | ||
215 | if (data->messages[i].deleted == 0) | ||
216 | { | ||
217 | unlink (data->messages[i].file); | ||
218 | mbox->num_deleted--; | ||
219 | } | ||
220 | } | ||
221 | } | ||
222 | /* reorder messages? */ | ||
223 | |||
224 | chdir (old_dir); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | /* | ||
229 | * Determines whether or a not a message is marked for deletion | ||
230 | */ | ||
231 | int | ||
232 | maildir_is_deleted (mailbox * mbox, unsigned int num) | ||
233 | { | ||
234 | maildir_data *data; | ||
235 | |||
236 | if (mbox == NULL) | ||
237 | { | ||
238 | errno = EINVAL; | ||
239 | return -1; | ||
240 | } | ||
241 | if (mbox->num_deleted == 0) | ||
242 | return 0; | ||
243 | data = mbox->_data; | ||
244 | return (data->messages[num].deleted == 1); | ||
245 | } | ||
246 | |||
247 | int | ||
248 | maildir_is_updated (mailbox *mbox) | ||
249 | { | ||
250 | struct stat st; | ||
251 | maildir_data *data; | ||
252 | |||
253 | if (mbox == NULL) | ||
254 | { | ||
255 | errno = EINVAL; | ||
256 | return -1; | ||
257 | } | ||
258 | if (stat (mbox->name, &st) == -1) | ||
259 | return -1; | ||
260 | data = mbox->_data; | ||
261 | return (st.st_mtime > data->last_mod_time); | ||
262 | } | ||
263 | |||
264 | /* | ||
265 | * Adds a message to the mailbox | ||
266 | */ | ||
267 | int | ||
268 | maildir_add_message (mailbox * mbox, char *message) | ||
269 | { | ||
270 | /* | ||
271 | * FIXME: please write me | ||
272 | * http://www.qmail.org/man/man5/maildir.html | ||
273 | */ | ||
274 | errno = ENOSYS; | ||
275 | return -1; | ||
276 | } | ||
277 | |||
278 | /* | ||
279 | * Returns a message body | ||
280 | */ | ||
281 | char * | ||
282 | maildir_get_body (mailbox * mbox, unsigned int num) | ||
283 | { | ||
284 | maildir_data *data; | ||
285 | char *buf; | ||
286 | char old_dir[PATH_MAX]; | ||
287 | FILE *f; | ||
288 | struct stat st; | ||
289 | size_t size; | ||
290 | |||
291 | if (mbox == NULL) | ||
292 | { | ||
293 | errno = EINVAL; | ||
294 | return NULL; | ||
295 | } | ||
296 | if (num > mbox->messages || num < 0) | ||
297 | { | ||
298 | errno = ERANGE; | ||
299 | return NULL; | ||
300 | } | ||
301 | |||
302 | data = mbox->_data; | ||
303 | getcwd (old_dir, PATH_MAX); | ||
304 | chdir (mbox->name); | ||
305 | |||
306 | if (data->messages[num].location == cur) | ||
307 | chdir ("cur"); | ||
308 | else if (data->messages[num].location == tmp) | ||
309 | chdir ("tmp"); | ||
310 | else if (data->messages[num].location == new) | ||
311 | chdir ("new"); | ||
312 | |||
313 | f = fopen (data->messages[num].file, "r"); | ||
314 | if (f == NULL) | ||
315 | { | ||
316 | chdir (old_dir); | ||
317 | perror (NULL); | ||
318 | return NULL; | ||
319 | } | ||
320 | |||
321 | stat (data->messages[num].file, &st); | ||
322 | size = st.st_size - data->messages[num].body + 1; | ||
323 | |||
324 | buf = malloc (sizeof (char) * size); | ||
325 | if (buf == NULL) | ||
326 | { | ||
327 | fclose (f); | ||
328 | chdir (old_dir); | ||
329 | errno = ENOMEM; | ||
330 | return NULL; | ||
331 | } | ||
332 | |||
333 | memset (buf, 0, size); | ||
334 | if (fsetpos (f, &(data->messages[num].body)) == -1) | ||
335 | { | ||
336 | fclose (f); | ||
337 | chdir (old_dir); | ||
338 | free (buf); | ||
339 | return NULL; | ||
340 | } | ||
341 | |||
342 | if (fread (buf, sizeof (char), size-1, f) < size) | ||
343 | { | ||
344 | fclose (f); | ||
345 | chdir (old_dir); | ||
346 | free (buf); | ||
347 | return NULL; | ||
348 | } | ||
349 | |||
350 | fclose (f); | ||
351 | chdir (old_dir); | ||
352 | return buf; | ||
353 | } | ||
354 | |||
355 | /* | ||
356 | * Returns just the header of a message | ||
357 | */ | ||
358 | char * | ||
359 | maildir_get_header (mailbox * mbox, unsigned int num) | ||
360 | { | ||
361 | maildir_data *data; | ||
362 | char *buf; | ||
363 | |||
364 | if ( mbox == NULL ) | ||
365 | { | ||
366 | errno = EINVAL; | ||
367 | return NULL; | ||
368 | } | ||
369 | |||
370 | if (num > mbox->messages) | ||
371 | { | ||
372 | errno = ERANGE; | ||
373 | return NULL; | ||
374 | } | ||
375 | |||
376 | data = mbox->_data; | ||
377 | buf = NULL; /* FIXME: read the file until data->message[num].body */ | ||
378 | return buf; | ||
379 | } | ||
380 | |||
381 | /* | ||
382 | * Sets lock mode for a mailbox | ||
383 | * FIXME: What to do for Maildir? no locking? | ||
384 | */ | ||
385 | int | ||
386 | maildir_lock (mailbox *mbox, mailbox_lock_t mode) | ||
387 | { | ||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | /* FIXME: not implemented */ | ||
392 | int | ||
393 | maildir_scan (mailbox *mbox) | ||
394 | { | ||
395 | errno = ENOSYS; | ||
396 | return -1; | ||
397 | } |
libmailbox/maildir.h
0 → 100644
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | #ifndef _MAILDIR_H | ||
19 | #define _MAILDIR_H 1 | ||
20 | #include <mailbox.h> | ||
21 | #include "config.h" | ||
22 | |||
23 | #ifdef HAVE_STDIO_H | ||
24 | #include <stdio.h> | ||
25 | #endif | ||
26 | |||
27 | #ifdef HAVE_STDLIB_H | ||
28 | #include <stdlib.h> | ||
29 | #endif | ||
30 | |||
31 | /* FIXME need auto* wrapper */ | ||
32 | #include <sys/types.h> | ||
33 | #include <sys/stat.h> | ||
34 | #include <dirent.h> | ||
35 | #include <sys/utsname.h> | ||
36 | #include <time.h> | ||
37 | |||
38 | #include <fcntl.h> | ||
39 | |||
40 | #ifdef HAVE_UNISTD_H | ||
41 | #include <unistd.h> | ||
42 | #endif | ||
43 | |||
44 | #ifdef HAVE_ERRNO_H | ||
45 | #include <errno.h> | ||
46 | #endif | ||
47 | |||
48 | #ifdef HAVE_STRING_H | ||
49 | #include <string.h> | ||
50 | #elif HAVE_STRINGS_H | ||
51 | #include <strings.h> | ||
52 | #endif | ||
53 | |||
54 | typedef struct _maildir_message | ||
55 | { | ||
56 | off_t body; | ||
57 | char deleted; | ||
58 | enum { new, tmp, cur } location; | ||
59 | char *file; | ||
60 | char *info; | ||
61 | } | ||
62 | maildir_message; | ||
63 | |||
64 | typedef struct _maildir_data | ||
65 | { | ||
66 | maildir_message *messages; | ||
67 | DIR *new; | ||
68 | DIR *cur; | ||
69 | DIR *tmp; | ||
70 | time_t time; | ||
71 | pid_t pid; | ||
72 | unsigned int sequence; | ||
73 | char *host; | ||
74 | time_t last_mod_time; | ||
75 | } | ||
76 | maildir_data; | ||
77 | |||
78 | int maildir_open (mailbox *mbox); | ||
79 | int maildir_close (mailbox *mbox); | ||
80 | int maildir_delete (mailbox *mbox, unsigned int num); | ||
81 | int maildir_undelete (mailbox *mbox, unsigned int num); | ||
82 | int maildir_expunge (mailbox *mbox); | ||
83 | int maildir_scan (mailbox *mbox); | ||
84 | int maildir_is_deleted (mailbox *mbox, unsigned int num); | ||
85 | int maildir_is_updated (mailbox *mbox); | ||
86 | int maildir_lock (mailbox *mbox, mailbox_lock_t mode); | ||
87 | int maildir_add_message (mailbox *mbox, char *message); | ||
88 | char *maildir_get_body (mailbox *mbox, unsigned int num); | ||
89 | char *maildir_get_header (mailbox *mbox, unsigned int num); | ||
90 | |||
91 | #endif |
-
Please register or sign in to post a comment