Commit 5f3d0446 5f3d0446aa5694c64d925623e2d81d5098ec3341 by Jakob Kaivo

Added beginnings of Maildir support.

1 parent 6c15b6c3
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?
......
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 }
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