To avoid confusion, pruned libmailbox directory
Showing
9 changed files
with
0 additions
and
1888 deletions
libmailbox/Makefile.am
deleted
100644 → 0
1 | # Use automake to process this file -*-Makefile-*- | ||
2 | |||
3 | AUTOMAKE_OPTIONS = ../lib/ansi2knr | ||
4 | |||
5 | CFLAGS = -Wall -pedantic -g -DTESTING | ||
6 | |||
7 | include_HEADERS = mailbox.h | ||
8 | lib_LTLIBRARIES = libmailbox.la | ||
9 | |||
10 | libmailbox_la_SOURCES = mailbox.c unixmbox.c unixmbox.h | ||
11 | libmailbox_la_LDFLAGS = -version-info 0:0:0 | ||
12 |
libmailbox/mailbox.c
deleted
100644 → 0
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 "mailbox.h" | ||
23 | #include "unixmbox.h" | ||
24 | |||
25 | #ifdef _HAVE_ERRNO_H | ||
26 | #include <errno.h> | ||
27 | #endif | ||
28 | |||
29 | #include <ctype.h> | ||
30 | #include <sys/stat.h> | ||
31 | #include <unistd.h> | ||
32 | |||
33 | int _mbox_dummy1 (mailbox * mbox); | ||
34 | int _mbox_dummy2 (mailbox * mbox, unsigned int num); | ||
35 | int _mbox_dummy3 (mailbox * mbox, char *c); | ||
36 | char *_mbox_dummy4 (mailbox * mbox, unsigned int num); | ||
37 | |||
38 | mailbox * | ||
39 | mbox_open (const char *name) | ||
40 | { | ||
41 | mailbox *mbox; | ||
42 | struct stat st; | ||
43 | |||
44 | if ( name == NULL ) | ||
45 | { | ||
46 | errno = EINVAL; | ||
47 | return NULL; | ||
48 | } | ||
49 | |||
50 | mbox = malloc (sizeof (mailbox)); | ||
51 | if (mbox == NULL) | ||
52 | { | ||
53 | errno = ENOMEM; | ||
54 | return NULL; | ||
55 | } | ||
56 | |||
57 | /* Set up with default data and dummy functions */ | ||
58 | mbox->name = strdup (name); | ||
59 | if (mbox->name == NULL) | ||
60 | { | ||
61 | errno = ENOMEM; | ||
62 | free (mbox); | ||
63 | return NULL; | ||
64 | } | ||
65 | /* check if we can look at file, prep for checks later in function */ | ||
66 | if (stat (mbox->name, &st) == -1) | ||
67 | { | ||
68 | free (mbox->name); | ||
69 | free (mbox); | ||
70 | return NULL; /* errno set by stat() */ | ||
71 | } | ||
72 | |||
73 | mbox->messages = 0; | ||
74 | mbox->num_deleted = 0; | ||
75 | mbox->sizes = NULL; | ||
76 | mbox->_data = NULL; | ||
77 | mbox->_close = _mbox_dummy1; | ||
78 | mbox->_delete = _mbox_dummy2; | ||
79 | mbox->_undelete = _mbox_dummy2; | ||
80 | mbox->_expunge = _mbox_dummy1; | ||
81 | mbox->_scan = _mbox_dummy1; | ||
82 | mbox->_add_message = _mbox_dummy3; | ||
83 | mbox->_is_deleted = _mbox_dummy2; | ||
84 | mbox->_is_updated = _mbox_dummy1; | ||
85 | mbox->_lock = _mbox_dummy2; | ||
86 | mbox->_get_body = _mbox_dummy4; | ||
87 | mbox->_get_header = _mbox_dummy4; | ||
88 | #ifdef TESTING | ||
89 | mbox->_tester = _mbox_dummy2; | ||
90 | #endif | ||
91 | |||
92 | if (S_ISREG (st.st_mode)) | ||
93 | { | ||
94 | if (unixmbox_open (mbox) == 0) | ||
95 | return mbox; | ||
96 | else | ||
97 | { | ||
98 | /* | ||
99 | * Check errno to find out why it failed, if it's simply not a | ||
100 | * unix mbox format message, then try other mailbox types, | ||
101 | * otherwise, leave errno set and return NULL | ||
102 | */ | ||
103 | if (errno == EBADMSG) | ||
104 | errno = ENOSYS; /* no other mailboxes supported right now */ | ||
105 | } | ||
106 | } | ||
107 | else if (S_ISDIR (st.st_mode)) | ||
108 | { | ||
109 | /* for example... | ||
110 | if (maildir_open (mbox, name) == 1) | ||
111 | return mbox; | ||
112 | */ | ||
113 | errno = ENOSYS; | ||
114 | } | ||
115 | else | ||
116 | errno = EINVAL; /* neither directory nor file, so bomb */ | ||
117 | |||
118 | free (mbox->name); | ||
119 | free (mbox); | ||
120 | return NULL; | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * Gets the contents of a header field | ||
125 | */ | ||
126 | char * | ||
127 | mbox_header_line (mailbox *mbox, unsigned int num, const char *header) | ||
128 | { | ||
129 | char *full, *tmp, *line; | ||
130 | int try = 1; | ||
131 | size_t i = 0, j = 0; | ||
132 | size_t len, lh; | ||
133 | |||
134 | if ( mbox == NULL || header == NULL ) | ||
135 | { | ||
136 | errno = EINVAL; | ||
137 | return NULL; | ||
138 | } | ||
139 | |||
140 | full = mbox_get_header (mbox, num); | ||
141 | if (full == NULL) | ||
142 | return NULL; | ||
143 | |||
144 | lh = strlen (header); | ||
145 | len = strlen (full); | ||
146 | tmp = NULL; | ||
147 | |||
148 | /* First get the appropriate line at the beginning */ | ||
149 | for (i=0; i < len-(lh+2); i++) | ||
150 | { | ||
151 | if (try == 1) | ||
152 | { | ||
153 | if (!strncasecmp(&full[i], header, lh) && full[i+lh] == ':') | ||
154 | { | ||
155 | tmp = strdup (&full[i+lh+2]); | ||
156 | if (tmp == NULL) | ||
157 | { | ||
158 | free(full); | ||
159 | return NULL; | ||
160 | } | ||
161 | break; | ||
162 | } | ||
163 | else | ||
164 | try = 0; | ||
165 | } | ||
166 | else if (full[i] == '\n') | ||
167 | try = 1; | ||
168 | else | ||
169 | try = 0; | ||
170 | } | ||
171 | |||
172 | /* FIXME: hmm, no valid header found, what should errno be? */ | ||
173 | if (tmp == NULL) | ||
174 | { | ||
175 | free(full); | ||
176 | return NULL; | ||
177 | } | ||
178 | /* Now trim the fat */ | ||
179 | len = strlen (tmp); | ||
180 | for (i = 0; i < len; i++) | ||
181 | { | ||
182 | if (tmp[i] == '\n' && i < (len - 1) && isspace (tmp[i+1])) | ||
183 | { | ||
184 | if (tmp[i+1] == '\t') | ||
185 | tmp[i + 1] = ' '; | ||
186 | for (j = i; j < len; j++) | ||
187 | tmp[j] = tmp[j+1]; | ||
188 | } | ||
189 | else if (tmp[i] == '\n') | ||
190 | { | ||
191 | tmp[i] = '\0'; | ||
192 | break; | ||
193 | } | ||
194 | } | ||
195 | line = strdup (tmp); | ||
196 | free (tmp); | ||
197 | free (full); | ||
198 | return line; | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * Gets first LINES lines from message body | ||
203 | */ | ||
204 | char * | ||
205 | mbox_body_lines (mailbox *mbox, unsigned int num, unsigned int lines) | ||
206 | { | ||
207 | char *full, *buf = NULL; | ||
208 | int i=0, line = 0, len; | ||
209 | if (mbox == NULL) | ||
210 | { | ||
211 | errno = EINVAL; | ||
212 | return NULL; | ||
213 | } | ||
214 | if (lines == 0) | ||
215 | return strdup (""); | ||
216 | full = mbox_get_body (mbox, num); | ||
217 | if (full == NULL) | ||
218 | return NULL; | ||
219 | len = strlen (full); | ||
220 | for (i=0; i < len && line < lines; i++) | ||
221 | { | ||
222 | if (full[i] == '\n') | ||
223 | { | ||
224 | line++; | ||
225 | if (line >= lines) | ||
226 | { | ||
227 | full[i+1] = '\0'; | ||
228 | buf = strdup (full); | ||
229 | break; | ||
230 | } | ||
231 | } | ||
232 | } | ||
233 | if (buf == NULL) | ||
234 | buf = strdup (full); | ||
235 | free (full); | ||
236 | return buf; | ||
237 | } | ||
238 | |||
239 | /* | ||
240 | * Bogus functions for unimplemented functions that return int | ||
241 | */ | ||
242 | int | ||
243 | _mbox_dummy1 (mailbox * mbox) | ||
244 | { | ||
245 | errno = ENOSYS; | ||
246 | return -1; | ||
247 | } | ||
248 | |||
249 | int | ||
250 | _mbox_dummy2 (mailbox * mbox, unsigned int num) | ||
251 | { | ||
252 | return _mbox_dummy1 (mbox); | ||
253 | } | ||
254 | int | ||
255 | _mbox_dummy3 (mailbox * mbox, char *c) | ||
256 | { | ||
257 | return _mbox_dummy1 (mbox); | ||
258 | } | ||
259 | |||
260 | /* | ||
261 | * Bogus function for unimplemented functions that return char * | ||
262 | */ | ||
263 | char * | ||
264 | _mbox_dummy4 (mailbox * mbox, unsigned int num) | ||
265 | { | ||
266 | errno = ENOSYS; | ||
267 | return NULL; | ||
268 | } | ||
269 |
libmailbox/mailbox.h
deleted
100644 → 0
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 _MAILBOX_H | ||
19 | #define _MAILBOX_H 1 | ||
20 | |||
21 | #ifndef __P | ||
22 | #if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus) | ||
23 | #define __P(args) args | ||
24 | #else | ||
25 | #define __P(args) () | ||
26 | #endif | ||
27 | #endif /*!__P */ | ||
28 | |||
29 | /* These need to be documented */ | ||
30 | #define mbox_close(m) m->_close(m) | ||
31 | #define mbox_delete(m,n) m->_delete(m,n) | ||
32 | #define mbox_undelete(m,n) m->_undelete(m,n) | ||
33 | #define mbox_expunge(m) m->_expunge(m) | ||
34 | #define mbox_scan(m) m->_scan(m) | ||
35 | #define mbox_is_deleted(m,n) m->_is_deleted(m,n) | ||
36 | #define mbox_is_updated(m) m->_is_updated(m) | ||
37 | #define mbox_add_message(m,s) m->_add_message(m,s) | ||
38 | #define mbox_get_body(m,n) m->_get_body(m,n) | ||
39 | #define mbox_get_header(m,n) m->_get_header(m,n) | ||
40 | #define mbox_lock(m,n) m->_lock(m,n) | ||
41 | #ifdef TESTING | ||
42 | #define mbox_tester(m,n) m->_tester(m,n) | ||
43 | #endif | ||
44 | |||
45 | #include <stdlib.h> | ||
46 | |||
47 | /* Lock settings */ | ||
48 | /* define this way so that it is opaque and can later become a struct w/o | ||
49 | * people noticing (-: | ||
50 | */ | ||
51 | enum _mailbox_lock_t {MO_ULOCK, MO_RLOCK, MO_WLOCK}; /* new type */ | ||
52 | typedef enum _mailbox_lock_t mailbox_lock_t; | ||
53 | |||
54 | typedef struct _mailbox | ||
55 | { | ||
56 | /* Data */ | ||
57 | char *name; | ||
58 | unsigned int messages; | ||
59 | unsigned int num_deleted; | ||
60 | size_t *sizes; | ||
61 | void *_data; | ||
62 | |||
63 | /* Functions */ | ||
64 | int (*_close) __P ((struct _mailbox *)); | ||
65 | int (*_delete) __P ((struct _mailbox *, unsigned int)); | ||
66 | int (*_undelete) __P ((struct _mailbox *, unsigned int)); | ||
67 | int (*_expunge) __P ((struct _mailbox *)); | ||
68 | int (*_add_message) __P ((struct _mailbox *, char *)); | ||
69 | int (*_scan) __P ((struct _mailbox *)); | ||
70 | int (*_is_deleted) __P ((struct _mailbox *, unsigned int)); | ||
71 | int (*_is_updated) __P ((struct _mailbox *)); | ||
72 | int (*_lock) __P((struct _mailbox *, mailbox_lock_t)); | ||
73 | char *(*_get_body) __P ((struct _mailbox *, unsigned int)); | ||
74 | char *(*_get_header) __P ((struct _mailbox *, unsigned int)); | ||
75 | #ifdef TESTING | ||
76 | void (*_tester) __P ((struct _mailbox *, unsigned int)); | ||
77 | #endif | ||
78 | } | ||
79 | mailbox; | ||
80 | |||
81 | mailbox *mbox_open __P ((const char *name)); | ||
82 | |||
83 | char *mbox_header_line __P ((mailbox *mbox, unsigned int num, const char *header)); | ||
84 | char *mbox_body_lines __P ((mailbox *mbox, unsigned int num, unsigned int lines)); | ||
85 | |||
86 | #endif |
libmailbox/maildir.c
deleted
100644 → 0
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)) | ||
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)) | ||
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
deleted
100644 → 0
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 |
libmailbox/mh.c
deleted
100644 → 0
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 "mh.h" | ||
23 | |||
24 | /* | ||
25 | * Opens a mailbox | ||
26 | */ | ||
27 | int | ||
28 | mh_open (mailbox * mbox) | ||
29 | { | ||
30 | unsigned long seq_num = 0; | ||
31 | struct dirent *entry; | ||
32 | mh_data *data; | ||
33 | |||
34 | if(mbox == NULL) | ||
35 | return EINVAL; | ||
36 | |||
37 | data = malloc (sizeof (mh_data)); | ||
38 | data->dir = opendir (mbox->name); | ||
39 | if(data->dir == NULL) | ||
40 | return errno; /* set by opendir() */ | ||
41 | |||
42 | /* process directory */ | ||
43 | while ((entry = readdir (data->dir))) | ||
44 | { | ||
45 | char *foo = NULL; | ||
46 | char fname[PATH_MAX]; | ||
47 | char line[80]; | ||
48 | FILE *fp; | ||
49 | mh_message message; | ||
50 | |||
51 | if (entry->d_name[0] == '.') | ||
52 | { | ||
53 | if (strcmp(entry->d_name, ".mh_sequences") == 0) | ||
54 | /* TODO: deal with mh sequence files */; | ||
55 | continue; | ||
56 | } | ||
57 | |||
58 | if (entry->d_name[0] == ',') | ||
59 | { | ||
60 | message.deleted = 1; | ||
61 | seq_num = strtoul ((entry->d_name) + 1, &foo, 10); | ||
62 | } | ||
63 | else | ||
64 | { | ||
65 | /* TODO: handle ERANGE */ | ||
66 | seq_num = strtoul (entry->d_name, &foo, 10); | ||
67 | } | ||
68 | if (*foo != '\0') /* invalid sequence number */ | ||
69 | { | ||
70 | printf("skipping invalid message: %s\n", entry->d_name); | ||
71 | continue; /* TODO: handle this better? */ | ||
72 | } | ||
73 | |||
74 | sprintf(fname, "%s/%ld", mbox->name, seq_num); | ||
75 | if ((fp = fopen(fname, "r")) == NULL) | ||
76 | continue; /* TODO: handle the error */ | ||
77 | /* TODO: handle corrupt files */ | ||
78 | while (fgets (line, 80, fp)) | ||
79 | { | ||
80 | if ((line[0] == '\r' && line[1] == '\n') || line[0] == '\n') | ||
81 | { | ||
82 | fgetpos(fp, &message.body); | ||
83 | break; | ||
84 | } | ||
85 | } | ||
86 | fclose (fp); | ||
87 | mbox->messages++; | ||
88 | } | ||
89 | |||
90 | /* store next sequence number to use */ | ||
91 | data->sequence = seq_num + 1; | ||
92 | |||
93 | mbox->_data = data; | ||
94 | #if 0 | ||
95 | mbox->_close = mh_close; | ||
96 | mbox->_delete = mh_delete; | ||
97 | mbox->_undelete = mh_undelete; | ||
98 | mbox->_expunge = mh_expunge; | ||
99 | mbox->_add_message = mh_add_message; | ||
100 | mbox->_is_deleted = mh_is_deleted; | ||
101 | mbox->_lock = mh_lock; | ||
102 | mbox->_get_body = mh_get_body; | ||
103 | mbox->_get_header = mh_get_header; | ||
104 | #endif | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | #if 0 | ||
110 | /* | ||
111 | * Closes and unlocks a mailbox, does not expunge | ||
112 | */ | ||
113 | int | ||
114 | mh_close (mailbox * mbox) | ||
115 | { | ||
116 | /* FIXME: hack from unixmbox */ | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | /* | ||
121 | * Marks a message for deletion | ||
122 | */ | ||
123 | int | ||
124 | mh_delete (mailbox * mbox, unsigned int num) | ||
125 | { | ||
126 | mh_data *data; | ||
127 | |||
128 | if (mbox == NULL) | ||
129 | { | ||
130 | errno = EINVAL; | ||
131 | return -1; | ||
132 | } | ||
133 | |||
134 | if (num > mbox->messages || mbox_is_deleted (mbox, num)) | ||
135 | { | ||
136 | errno = ERANGE; | ||
137 | return -1; | ||
138 | } | ||
139 | |||
140 | data = mbox->_data; | ||
141 | data->messages[num].deleted = 1; | ||
142 | mbox->num_deleted++; | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | /* | ||
148 | * Unmark a message for deletion | ||
149 | */ | ||
150 | int | ||
151 | mh_undelete (mailbox * mbox, unsigned int num) | ||
152 | { | ||
153 | mh_data *data; | ||
154 | |||
155 | if (mbox == NULL) | ||
156 | { | ||
157 | errno = EINVAL; | ||
158 | return -1; | ||
159 | } | ||
160 | |||
161 | if (num > mbox->messages || !mbox_is_deleted (mbox, num)) | ||
162 | { | ||
163 | errno = ERANGE; | ||
164 | return -1; | ||
165 | } | ||
166 | |||
167 | data = mbox->_data; | ||
168 | data->messages[num].deleted = 0; | ||
169 | mbox->num_deleted--; | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | /* | ||
175 | * Updates a mailbox to remove message marked for deletion | ||
176 | */ | ||
177 | int | ||
178 | mh_expunge (mailbox * mbox) | ||
179 | { | ||
180 | mh_data *data; | ||
181 | int i = 0; | ||
182 | char old_dir[PATH_MAX]; | ||
183 | |||
184 | if (mbox == NULL) | ||
185 | { | ||
186 | errno = EINVAL; | ||
187 | return -1; | ||
188 | } | ||
189 | |||
190 | getcwd (old_dir, PATH_MAX); | ||
191 | chdir (mbox->name); | ||
192 | |||
193 | if (mbox->num_deleted) | ||
194 | { | ||
195 | data = mbox->_data; | ||
196 | |||
197 | for (i = 0; i < mbox->messages; i++) | ||
198 | { | ||
199 | if (data->messages[i].deleted == 0) | ||
200 | { | ||
201 | unlink (data->messages[i].file); | ||
202 | mbox->num_deleted--; | ||
203 | } | ||
204 | } | ||
205 | } | ||
206 | /* reorder messages? */ | ||
207 | |||
208 | chdir (old_dir); | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | /* | ||
213 | * Determines whether or a not a message is marked for deletion | ||
214 | */ | ||
215 | int | ||
216 | mh_is_deleted (mailbox * mbox, unsigned int num) | ||
217 | { | ||
218 | mh_data *data; | ||
219 | |||
220 | if (mbox == NULL) | ||
221 | { | ||
222 | errno = EINVAL; | ||
223 | return -1; | ||
224 | } | ||
225 | if (mbox->num_deleted == 0) | ||
226 | return 0; | ||
227 | data = mbox->_data; | ||
228 | return (data->messages[num].deleted == 1); | ||
229 | } | ||
230 | |||
231 | int | ||
232 | mh_is_updated (mailbox *mbox) | ||
233 | { | ||
234 | struct stat st; | ||
235 | mh_data *data; | ||
236 | |||
237 | if (mbox == NULL) | ||
238 | { | ||
239 | errno = EINVAL; | ||
240 | return -1; | ||
241 | } | ||
242 | if (stat (mbox->name, &st) == -1) | ||
243 | return -1; | ||
244 | data = mbox->_data; | ||
245 | return (st.st_mtime > data->last_mod_time); | ||
246 | } | ||
247 | |||
248 | /* | ||
249 | * Adds a message to the mailbox | ||
250 | */ | ||
251 | int | ||
252 | mh_add_message (mailbox * mbox, char *message) | ||
253 | { | ||
254 | /* | ||
255 | * FIXME: please write me | ||
256 | * http://www.qmail.org/man/man5/mh.html | ||
257 | */ | ||
258 | errno = ENOSYS; | ||
259 | return -1; | ||
260 | } | ||
261 | |||
262 | /* | ||
263 | * Returns a message body | ||
264 | */ | ||
265 | char * | ||
266 | mh_get_body (mailbox * mbox, unsigned int num) | ||
267 | { | ||
268 | mh_data *data; | ||
269 | char *buf; | ||
270 | char old_dir[PATH_MAX]; | ||
271 | FILE *f; | ||
272 | struct stat st; | ||
273 | size_t size; | ||
274 | |||
275 | if (mbox == NULL) | ||
276 | { | ||
277 | errno = EINVAL; | ||
278 | return NULL; | ||
279 | } | ||
280 | if (num > mbox->messages || num < 0) | ||
281 | { | ||
282 | errno = ERANGE; | ||
283 | return NULL; | ||
284 | } | ||
285 | |||
286 | data = mbox->_data; | ||
287 | getcwd (old_dir, PATH_MAX); | ||
288 | chdir (mbox->name); | ||
289 | |||
290 | if (data->messages[num].location == cur) | ||
291 | chdir ("cur"); | ||
292 | else if (data->messages[num].location == tmp) | ||
293 | chdir ("tmp"); | ||
294 | else if (data->messages[num].location == new) | ||
295 | chdir ("new"); | ||
296 | |||
297 | f = fopen (data->messages[num].file, "r"); | ||
298 | if (f == NULL) | ||
299 | { | ||
300 | chdir (old_dir); | ||
301 | perror (NULL); | ||
302 | return NULL; | ||
303 | } | ||
304 | |||
305 | stat (data->messages[num].file, &st); | ||
306 | size = st.st_size - data->messages[num].body + 1; | ||
307 | |||
308 | buf = malloc (sizeof (char) * size); | ||
309 | if (buf == NULL) | ||
310 | { | ||
311 | fclose (f); | ||
312 | chdir (old_dir); | ||
313 | errno = ENOMEM; | ||
314 | return NULL; | ||
315 | } | ||
316 | |||
317 | memset (buf, 0, size); | ||
318 | if (fsetpos (f, &(data->messages[num].body)) == -1) | ||
319 | { | ||
320 | fclose (f); | ||
321 | chdir (old_dir); | ||
322 | free (buf); | ||
323 | return NULL; | ||
324 | } | ||
325 | |||
326 | if (fread (buf, sizeof (char), size-1, f) < size) | ||
327 | { | ||
328 | fclose (f); | ||
329 | chdir (old_dir); | ||
330 | free (buf); | ||
331 | return NULL; | ||
332 | } | ||
333 | |||
334 | fclose (f); | ||
335 | chdir (old_dir); | ||
336 | return buf; | ||
337 | } | ||
338 | |||
339 | /* | ||
340 | * Returns just the header of a message | ||
341 | */ | ||
342 | char * | ||
343 | mh_get_header (mailbox * mbox, unsigned int num) | ||
344 | { | ||
345 | mh_data *data; | ||
346 | char *buf; | ||
347 | |||
348 | if ( mbox == NULL ) | ||
349 | { | ||
350 | errno = EINVAL; | ||
351 | return NULL; | ||
352 | } | ||
353 | |||
354 | if (num > mbox->messages) | ||
355 | { | ||
356 | errno = ERANGE; | ||
357 | return NULL; | ||
358 | } | ||
359 | |||
360 | data = mbox->_data; | ||
361 | buf = NULL; /* FIXME: read the file until data->message[num].body */ | ||
362 | return buf; | ||
363 | } | ||
364 | |||
365 | /* | ||
366 | * Sets lock mode for a mailbox | ||
367 | * FIXME: What to do for Mh? no locking? | ||
368 | */ | ||
369 | int | ||
370 | mh_lock (mailbox *mbox, mailbox_lock_t mode) | ||
371 | { | ||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | /* FIXME: not implemented */ | ||
376 | int | ||
377 | mh_scan (mailbox *mbox) | ||
378 | { | ||
379 | errno = ENOSYS; | ||
380 | return -1; | ||
381 | } | ||
382 | #endif |
libmailbox/mh.h
deleted
100644 → 0
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 _MH_H | ||
19 | #define _MH_H 1 | ||
20 | |||
21 | #ifdef HAVE_CONFIG_H | ||
22 | #include "config.h" | ||
23 | #endif | ||
24 | |||
25 | #include <mailbox.h> | ||
26 | |||
27 | #ifdef HAVE_STDIO_H | ||
28 | #include <stdio.h> | ||
29 | #endif | ||
30 | |||
31 | #ifdef HAVE_STDLIB_H | ||
32 | #include <stdlib.h> | ||
33 | #endif | ||
34 | |||
35 | /* FIXME need auto* wrapper */ | ||
36 | #include <sys/types.h> | ||
37 | #include <sys/stat.h> | ||
38 | #include <dirent.h> | ||
39 | #include <sys/utsname.h> | ||
40 | #include <time.h> | ||
41 | |||
42 | #include <fcntl.h> | ||
43 | |||
44 | #ifdef HAVE_UNISTD_H | ||
45 | #include <unistd.h> | ||
46 | #endif | ||
47 | |||
48 | #ifdef HAVE_ERRNO_H | ||
49 | #include <errno.h> | ||
50 | #endif | ||
51 | |||
52 | #ifdef HAVE_STRING_H | ||
53 | #include <string.h> | ||
54 | #elif HAVE_STRINGS_H | ||
55 | #include <strings.h> | ||
56 | #endif | ||
57 | |||
58 | typedef struct _mh_message | ||
59 | { | ||
60 | off_t body; | ||
61 | char deleted; | ||
62 | } | ||
63 | mh_message; | ||
64 | |||
65 | typedef struct _mh_data | ||
66 | { | ||
67 | mh_message *messages; | ||
68 | DIR *dir; | ||
69 | unsigned int sequence; | ||
70 | } | ||
71 | mh_data; | ||
72 | |||
73 | int mh_open (mailbox *mbox); | ||
74 | int mh_close (mailbox *mbox); | ||
75 | int mh_delete (mailbox *mbox, unsigned int num); | ||
76 | int mh_undelete (mailbox *mbox, unsigned int num); | ||
77 | int mh_expunge (mailbox *mbox); | ||
78 | int mh_scan (mailbox *mbox); | ||
79 | int mh_is_deleted (mailbox *mbox, unsigned int num); | ||
80 | int mh_is_updated (mailbox *mbox); | ||
81 | int mh_lock (mailbox *mbox, mailbox_lock_t mode); | ||
82 | int mh_add_message (mailbox *mbox, char *message); | ||
83 | char *mh_get_body (mailbox *mbox, unsigned int num); | ||
84 | char *mh_get_header (mailbox *mbox, unsigned int num); | ||
85 | |||
86 | #endif |
libmailbox/unixmbox.c
deleted
100644 → 0
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 "unixmbox.h" | ||
23 | |||
24 | /* | ||
25 | * Opens a mailbox | ||
26 | */ | ||
27 | int | ||
28 | unixmbox_open (mailbox * mbox) | ||
29 | { | ||
30 | char buf[80]; | ||
31 | unsigned int max_count = 10; | ||
32 | int mess = 0; | ||
33 | unixmbox_data *data; | ||
34 | struct stat st; | ||
35 | |||
36 | if (mbox == NULL) | ||
37 | { | ||
38 | errno = EINVAL; | ||
39 | return -1; | ||
40 | } | ||
41 | |||
42 | data = malloc (sizeof (unixmbox_data)); | ||
43 | if (data == NULL) | ||
44 | { | ||
45 | errno = ENOMEM; | ||
46 | free (data); | ||
47 | return -1; | ||
48 | } | ||
49 | |||
50 | mbox->_data = data; | ||
51 | data->file = fopen (mbox->name, "r+"); | ||
52 | if (data->file == NULL) | ||
53 | { | ||
54 | /* errno is set by fopen() */ | ||
55 | free (data); | ||
56 | return -1; | ||
57 | } | ||
58 | |||
59 | data->messages = malloc (sizeof (unixmbox_message) * max_count); | ||
60 | mbox->sizes = malloc (sizeof (int) * max_count); | ||
61 | if (data->messages == NULL || mbox->sizes == NULL) | ||
62 | { | ||
63 | unixmbox_close (mbox); | ||
64 | errno = ENOMEM; | ||
65 | return -1; | ||
66 | } | ||
67 | if (stat (mbox->name, &st) == -1) | ||
68 | { | ||
69 | unixmbox_close (mbox); | ||
70 | return -1; | ||
71 | } | ||
72 | data->last_mod_time = st.st_mtime; | ||
73 | |||
74 | if (fgets (buf, 80, data->file) == NULL) | ||
75 | { | ||
76 | if (feof(data->file)) | ||
77 | goto END; /* empty file, no messages */ | ||
78 | unixmbox_close (mbox); | ||
79 | return -1; | ||
80 | } | ||
81 | if (strncmp (buf, "From ", 5)) | ||
82 | { | ||
83 | /* This is NOT an mbox file */ | ||
84 | unixmbox_close (mbox); | ||
85 | errno = EBADMSG; /* use this to signify wrong mbox type */ | ||
86 | return -1; | ||
87 | } | ||
88 | |||
89 | do | ||
90 | { | ||
91 | if (!strncmp (buf, "From ", 5)) | ||
92 | { | ||
93 | /* Beginning of a header */ | ||
94 | while (strchr (buf, '\n') == NULL) | ||
95 | if (fgets (buf, 80, data->file) == NULL) /* eat the From line */ | ||
96 | { | ||
97 | if (feof (data->file)) | ||
98 | errno = EIO; /* corrupted mailbox? */ | ||
99 | unixmbox_close (mbox); | ||
100 | return -1; | ||
101 | } | ||
102 | |||
103 | mbox->messages++; | ||
104 | |||
105 | if (mbox->messages > max_count) | ||
106 | { | ||
107 | max_count = mbox->messages * 2; | ||
108 | data->messages = realloc (data->messages, | ||
109 | max_count * sizeof (unixmbox_message)); | ||
110 | mbox->sizes = realloc (mbox->sizes, max_count * sizeof (int)); | ||
111 | if (data->messages == NULL || mbox->sizes == NULL) | ||
112 | { | ||
113 | unixmbox_close (mbox); | ||
114 | errno = ENOMEM; | ||
115 | return -1; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | fgetpos (data->file, &(data->messages[mbox->messages - 1].header)); | ||
120 | mbox->sizes[mbox->messages - 1] = 0; | ||
121 | data->messages[mbox->messages - 1].deleted = 0; | ||
122 | mess = 0; | ||
123 | } | ||
124 | else if (((!strncmp (buf, "\r\n", 2) || strlen (buf) <= 1)) && mess == 0) | ||
125 | { | ||
126 | /* Beginning of a body */ | ||
127 | fgetpos (data->file, &(data->messages[mbox->messages - 1].body)); | ||
128 | mbox->sizes[mbox->messages - 1] += strlen (buf) + 1; | ||
129 | mess = 1; | ||
130 | } | ||
131 | else | ||
132 | { | ||
133 | mbox->sizes[mbox->messages - 1] += strlen (buf) + 1; | ||
134 | fgetpos (data->file, &(data->messages[mbox->messages - 1].end)); | ||
135 | } | ||
136 | } | ||
137 | while (fgets (buf, 80, data->file)); | ||
138 | |||
139 | if (!feof (data->file)) /* stopped due to error, not EOF */ | ||
140 | { | ||
141 | unixmbox_close (mbox); | ||
142 | return -1; /* errno is set */ | ||
143 | } | ||
144 | |||
145 | END: | ||
146 | mbox->_close = unixmbox_close; | ||
147 | mbox->_delete = unixmbox_delete; | ||
148 | mbox->_undelete = unixmbox_undelete; | ||
149 | mbox->_expunge = unixmbox_expunge; | ||
150 | mbox->_add_message = unixmbox_add_message; | ||
151 | mbox->_is_deleted = unixmbox_is_deleted; | ||
152 | mbox->_lock = unixmbox_lock; | ||
153 | mbox->_get_body = unixmbox_get_body; | ||
154 | mbox->_get_header = unixmbox_get_header; | ||
155 | #ifdef TESTING | ||
156 | mbox->_tester = unixmbox_tester; | ||
157 | #endif | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * Closes and unlocks a mailbox, does not expunge | ||
164 | */ | ||
165 | int | ||
166 | unixmbox_close (mailbox * mbox) | ||
167 | { | ||
168 | unixmbox_data *data; | ||
169 | |||
170 | if (mbox == NULL) | ||
171 | { | ||
172 | errno = EINVAL; | ||
173 | return -1; | ||
174 | } | ||
175 | data = mbox->_data; | ||
176 | unixmbox_lock (mbox, MO_ULOCK); | ||
177 | if (data->file) | ||
178 | fclose (data->file); | ||
179 | free (data->messages); | ||
180 | free (mbox->sizes); | ||
181 | free (data); | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * Marks a message for deletion | ||
187 | */ | ||
188 | int | ||
189 | unixmbox_delete (mailbox * mbox, unsigned int num) | ||
190 | { | ||
191 | unixmbox_data *data; | ||
192 | |||
193 | if (mbox == NULL) | ||
194 | { | ||
195 | errno = EINVAL; | ||
196 | return -1; | ||
197 | } | ||
198 | |||
199 | if (num > mbox->messages || mbox_is_deleted (mbox, num)) | ||
200 | { | ||
201 | errno = ERANGE; | ||
202 | return -1; | ||
203 | } | ||
204 | |||
205 | data = mbox->_data; | ||
206 | data->messages[num].deleted = 1; | ||
207 | mbox->num_deleted++; | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | /* | ||
213 | * Unmark a message for deletion | ||
214 | */ | ||
215 | int | ||
216 | unixmbox_undelete (mailbox * mbox, unsigned int num) | ||
217 | { | ||
218 | unixmbox_data *data; | ||
219 | |||
220 | if (mbox == NULL) | ||
221 | { | ||
222 | errno = EINVAL; | ||
223 | return -1; | ||
224 | } | ||
225 | |||
226 | if (num > mbox->messages || !mbox_is_deleted (mbox, num)) | ||
227 | { | ||
228 | errno = ERANGE; | ||
229 | return -1; | ||
230 | } | ||
231 | |||
232 | data = mbox->_data; | ||
233 | data->messages[num].deleted = 0; | ||
234 | mbox->num_deleted--; | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | /* | ||
240 | * Updates a mailbox to remove message marked for deletion | ||
241 | * FIXME: BROKEN! DOES NOT WORK! BLOWS UP REAL GOOD! | ||
242 | */ | ||
243 | int | ||
244 | unixmbox_expunge (mailbox * mbox) | ||
245 | { | ||
246 | unixmbox_data *data; | ||
247 | int i = 0; | ||
248 | size_t size = 0, size_read = 0; | ||
249 | char *buf = NULL; | ||
250 | int file; | ||
251 | int deletion_needed = 0; /* true when a deleted message has been found */ | ||
252 | size_t buff_size = 0; | ||
253 | size_t tmp = 0; | ||
254 | |||
255 | if (mbox == NULL) | ||
256 | { | ||
257 | errno = EINVAL; | ||
258 | return -1; | ||
259 | } | ||
260 | if (mbox->num_deleted) | ||
261 | { | ||
262 | data = mbox->_data; | ||
263 | fclose(data->file); | ||
264 | /* error handling */ | ||
265 | data->file = NULL; | ||
266 | file = open(mbox->name, O_RDWR); | ||
267 | /* error handling */ | ||
268 | |||
269 | for (i = 0; i < mbox->messages; i++) | ||
270 | { | ||
271 | if (data->messages[i].deleted == 0) | ||
272 | { | ||
273 | if (deletion_needed) | ||
274 | { | ||
275 | tmp = mbox->sizes[i]; | ||
276 | if (tmp > buff_size) | ||
277 | { | ||
278 | buff_size = tmp; | ||
279 | buf = realloc (buf, tmp); | ||
280 | /* error checking */ | ||
281 | } | ||
282 | lseek (file, data->messages[i].header, SEEK_SET); | ||
283 | size_read = read (file, buf, tmp); | ||
284 | /* error checking */ | ||
285 | lseek (file, size, SEEK_SET); | ||
286 | write (file, buf, size_read); | ||
287 | /* error checking */ | ||
288 | size += size_read; | ||
289 | } | ||
290 | else | ||
291 | { | ||
292 | size += mbox->sizes[i]; | ||
293 | } | ||
294 | } | ||
295 | else | ||
296 | { | ||
297 | deletion_needed = 1; | ||
298 | } | ||
299 | } | ||
300 | close (file); | ||
301 | truncate (mbox->name, size); | ||
302 | free (buf); | ||
303 | } | ||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | * Determines whether or a not a message is marked for deletion | ||
309 | */ | ||
310 | int | ||
311 | unixmbox_is_deleted (mailbox * mbox, unsigned int num) | ||
312 | { | ||
313 | unixmbox_data *data; | ||
314 | |||
315 | if (mbox == NULL) | ||
316 | { | ||
317 | errno = EINVAL; | ||
318 | return -1; | ||
319 | } | ||
320 | if (mbox->num_deleted == 0) | ||
321 | return 0; | ||
322 | data = mbox->_data; | ||
323 | return (data->messages[num].deleted == 1); | ||
324 | } | ||
325 | |||
326 | int | ||
327 | unixmbox_is_updated (mailbox *mbox) | ||
328 | { | ||
329 | struct stat st; | ||
330 | unixmbox_data *data; | ||
331 | |||
332 | if (mbox == NULL) | ||
333 | { | ||
334 | errno = EINVAL; | ||
335 | return -1; | ||
336 | } | ||
337 | if (stat (mbox->name, &st) == -1) | ||
338 | return -1; | ||
339 | data = mbox->_data; | ||
340 | return (st.st_mtime > data->last_mod_time); | ||
341 | } | ||
342 | |||
343 | /* | ||
344 | * Adds a message to the mailbox | ||
345 | */ | ||
346 | int | ||
347 | unixmbox_add_message (mailbox * mbox, char *message) | ||
348 | { | ||
349 | /* | ||
350 | * FIXME: please write me | ||
351 | * move to end of file and write text, don't forget to update | ||
352 | * mbox->messages and mbox->_data->messages | ||
353 | */ | ||
354 | errno = ENOSYS; | ||
355 | return -1; | ||
356 | } | ||
357 | |||
358 | /* | ||
359 | * Returns a message body | ||
360 | */ | ||
361 | char * | ||
362 | unixmbox_get_body (mailbox * mbox, unsigned int num) | ||
363 | { | ||
364 | unixmbox_data *data; | ||
365 | size_t size; | ||
366 | char *buf; | ||
367 | |||
368 | if (mbox == NULL) | ||
369 | { | ||
370 | errno = EINVAL; | ||
371 | return NULL; | ||
372 | } | ||
373 | if (num > mbox->messages || num < 0) | ||
374 | { | ||
375 | errno = ERANGE; | ||
376 | return NULL; | ||
377 | } | ||
378 | |||
379 | data = mbox->_data; | ||
380 | size = data->messages[num].end - data->messages[num].body; | ||
381 | buf = malloc ((1 + size) * sizeof (char)); | ||
382 | if (buf == NULL) | ||
383 | { | ||
384 | errno = ENOMEM; | ||
385 | return NULL; | ||
386 | } | ||
387 | |||
388 | memset (buf, 0, size + 1); | ||
389 | if (fsetpos (data->file, &(data->messages[num].body)) == -1) | ||
390 | { | ||
391 | free (buf); | ||
392 | return NULL; | ||
393 | } | ||
394 | if (fread (buf, sizeof (char), size, data->file) < size) | ||
395 | { | ||
396 | free (buf); | ||
397 | return NULL; | ||
398 | } | ||
399 | return buf; | ||
400 | } | ||
401 | |||
402 | /* | ||
403 | * Returns just the header of a message | ||
404 | */ | ||
405 | char * | ||
406 | unixmbox_get_header (mailbox * mbox, unsigned int num) | ||
407 | { | ||
408 | unixmbox_data *data; | ||
409 | size_t size; | ||
410 | char *buf; | ||
411 | |||
412 | if ( mbox == NULL ) | ||
413 | { | ||
414 | errno = EINVAL; | ||
415 | return NULL; | ||
416 | } | ||
417 | |||
418 | if (num > mbox->messages) | ||
419 | { | ||
420 | errno = ERANGE; | ||
421 | return NULL; | ||
422 | } | ||
423 | |||
424 | data = mbox->_data; | ||
425 | size = (data->messages[num].body - 1) - data->messages[num].header; | ||
426 | buf = malloc ((1 + size) * sizeof (char)); | ||
427 | if (buf == NULL) | ||
428 | { | ||
429 | errno = ENOMEM; | ||
430 | return NULL; | ||
431 | } | ||
432 | |||
433 | memset (buf, 0, size + 1); | ||
434 | |||
435 | if (fsetpos (data->file, &(data->messages[num].header)) == -1) | ||
436 | { | ||
437 | free (buf); | ||
438 | return NULL; | ||
439 | } | ||
440 | if (fread (buf, sizeof (char), size, data->file) < size) | ||
441 | { | ||
442 | free (buf); | ||
443 | return NULL; | ||
444 | } | ||
445 | return buf; | ||
446 | } | ||
447 | |||
448 | /* | ||
449 | * Sets lock mode for a mailbox | ||
450 | * FIXME: this doesn't do anything, really | ||
451 | * Get locking code from Procmail and/or Exim | ||
452 | */ | ||
453 | int | ||
454 | unixmbox_lock (mailbox *mbox, mailbox_lock_t mode) | ||
455 | { | ||
456 | unixmbox_data *data = mbox->_data; | ||
457 | data->lockmode = mode; | ||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | /* FIXME: not implemented */ | ||
462 | int | ||
463 | unixmbox_scan (mailbox *mbox) | ||
464 | { | ||
465 | errno = ENOSYS; | ||
466 | return -1; | ||
467 | } | ||
468 | |||
469 | #ifdef TESTING | ||
470 | void unixmbox_tester (mailbox *mbox, unsigned int num) | ||
471 | { | ||
472 | unixmbox_data *data = mbox->_data; | ||
473 | if (!data || num > mbox->messages || num < 0) | ||
474 | return; | ||
475 | printf ("Message size: %u\n", mbox->sizes[num]); | ||
476 | printf ("Message length: %lu\n", | ||
477 | data->messages[num].end - data->messages[num].header); | ||
478 | } | ||
479 | #endif |
libmailbox/unixmbox.h
deleted
100644 → 0
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 _UNIXMBOX_H | ||
19 | #define _UNIXMBOX_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 | |||
35 | #include <fcntl.h> | ||
36 | |||
37 | #ifdef HAVE_UNISTD_H | ||
38 | #include <unistd.h> | ||
39 | #endif | ||
40 | |||
41 | #ifdef HAVE_ERRNO_H | ||
42 | #include <errno.h> | ||
43 | #endif | ||
44 | |||
45 | #ifdef HAVE_STRING_H | ||
46 | #include <string.h> | ||
47 | #elif HAVE_STRINGS_H | ||
48 | #include <strings.h> | ||
49 | #endif | ||
50 | |||
51 | typedef struct _unixmbox_message | ||
52 | { | ||
53 | off_t header; | ||
54 | off_t body; | ||
55 | off_t end; | ||
56 | char deleted; | ||
57 | } | ||
58 | unixmbox_message; | ||
59 | |||
60 | typedef struct _unixmbox_data | ||
61 | { | ||
62 | unixmbox_message *messages; | ||
63 | FILE *file; | ||
64 | mailbox_lock_t lockmode; | ||
65 | time_t last_mod_time; | ||
66 | } | ||
67 | unixmbox_data; | ||
68 | |||
69 | int unixmbox_open (mailbox *mbox); | ||
70 | int unixmbox_close (mailbox *mbox); | ||
71 | int unixmbox_delete (mailbox *mbox, unsigned int num); | ||
72 | int unixmbox_undelete (mailbox *mbox, unsigned int num); | ||
73 | int unixmbox_expunge (mailbox *mbox); | ||
74 | int unixmbox_scan (mailbox *mbox); | ||
75 | int unixmbox_is_deleted (mailbox *mbox, unsigned int num); | ||
76 | int unixmbox_is_updated (mailbox *mbox); | ||
77 | int unixmbox_lock (mailbox *mbox, mailbox_lock_t mode); | ||
78 | int unixmbox_add_message (mailbox *mbox, char *message); | ||
79 | char *unixmbox_get_body (mailbox *mbox, unsigned int num); | ||
80 | char *unixmbox_get_header (mailbox *mbox, unsigned int num); | ||
81 | |||
82 | #ifdef TESTING | ||
83 | void unixmbox_tester (mailbox *mbox, unsigned int num); | ||
84 | #endif | ||
85 | |||
86 | #endif |
-
Please register or sign in to post a comment