not implemented.
Showing
12 changed files
with
0 additions
and
2600 deletions
mailbox/mbx_imap.c
deleted
100644 → 0
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 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 Library 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 Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library 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 | #include <errno.h> | ||
19 | #include <mailbox0.h> | ||
20 | #include <registrar0.h> | ||
21 | |||
22 | |||
23 | static int mailbox_imap_create (mailbox_t *mbox, const char *name); | ||
24 | static void mailbox_imap_destroy (mailbox_t *mbox); | ||
25 | |||
26 | struct mailbox_registrar _mailbox_imap_registrar = | ||
27 | { | ||
28 | "IMAP4", | ||
29 | mailbox_imap_create, mailbox_imap_destroy | ||
30 | }; | ||
31 | |||
32 | void | ||
33 | mailbox_imap_destroy (mailbox_t *mbox) | ||
34 | { | ||
35 | (void)mbox; | ||
36 | return; | ||
37 | } | ||
38 | |||
39 | int | ||
40 | mailbox_imap_create (mailbox_t *mbox, const char *name) | ||
41 | { | ||
42 | (void)mbox; (void)name; | ||
43 | return ENOSYS; | ||
44 | } |
mailbox/mbx_mdir.c
deleted
100644 → 0
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 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 Library 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 Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library 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 | #include <errno.h> | ||
19 | #include <mailbox0.h> | ||
20 | #include <registrar0.h> | ||
21 | |||
22 | static int mailbox_maildir_create (mailbox_t *mbox, const char *name); | ||
23 | static void mailbox_maildir_destroy (mailbox_t *mbox); | ||
24 | |||
25 | struct mailbox_registrar _mailbox_maildir_registrar = | ||
26 | { | ||
27 | "MAILDIR", | ||
28 | mailbox_maildir_create, mailbox_maildir_destroy | ||
29 | }; | ||
30 | |||
31 | int | ||
32 | mailbox_maildir_create (mailbox_t *mbox, const char *name) | ||
33 | { | ||
34 | (void)mbox; (void)name; | ||
35 | return ENOSYS; | ||
36 | } | ||
37 | |||
38 | void | ||
39 | mailbox_maildir_destroy (mailbox_t *mbox) | ||
40 | { | ||
41 | (void)mbox; | ||
42 | return; | ||
43 | } |
mailbox/mbx_mh.c
deleted
100644 → 0
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | * Copyright (C) 1999, 2000 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 Library 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 Library General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU Library 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 | |||
19 | #include <dirent.h> | ||
20 | #include <errno.h> | ||
21 | #include <string.h> | ||
22 | #include <sys/stat.h> | ||
23 | #include <sys/types.h> | ||
24 | #include <unistd.h> | ||
25 | #include <stdlib.h> | ||
26 | #include <ctype.h> | ||
27 | |||
28 | #include <mailbox0.h> | ||
29 | #include <registrar0.h> | ||
30 | |||
31 | static int mailbox_mh_create (mailbox_t *pmbox, const char *name); | ||
32 | static void mailbox_mh_destroy (mailbox_t *pmbox); | ||
33 | |||
34 | struct mailbox_registrar _mailbox_mh_registrar = | ||
35 | { | ||
36 | "MH", | ||
37 | mailbox_mh_create, mailbox_mh_destroy | ||
38 | }; | ||
39 | |||
40 | typedef struct _mh_data | ||
41 | { | ||
42 | time_t mtime; /* used for checking if mailbox was updated */ | ||
43 | } mh_data; | ||
44 | |||
45 | static int mh_open (mailbox_t mbox, int flags); | ||
46 | static int mh_close (mailbox_t mbox); | ||
47 | static int mh_scan (mailbox_t mbox, size_t msgno, size_t *msgs); | ||
48 | static int mh_sequence(const char *name); | ||
49 | |||
50 | static int | ||
51 | mailbox_mh_create (mailbox_t *pmbox, const char *name) | ||
52 | { | ||
53 | mailbox_t mbox; | ||
54 | mh_data *data; | ||
55 | |||
56 | mbox = malloc(sizeof(*mbox)); | ||
57 | data = malloc(sizeof(mh_data)); | ||
58 | mbox->name = malloc(strlen(name) + 1); | ||
59 | strcpy(mbox->name, name); | ||
60 | mbox->data = data; | ||
61 | mbox->_create = mailbox_mh_create; | ||
62 | mbox->_destroy = mailbox_mh_destroy; | ||
63 | mbox->_open = mh_open; | ||
64 | mbox->_close = mh_close; | ||
65 | mbox->_scan = mh_scan; | ||
66 | *pmbox = mbox; | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static void | ||
72 | mailbox_mh_destroy (mailbox_t *pmbox) | ||
73 | { | ||
74 | free((*pmbox)->data); | ||
75 | free((*pmbox)->name); | ||
76 | free(*pmbox); | ||
77 | pmbox = NULL; | ||
78 | } | ||
79 | |||
80 | /* FIXME: handle create once the design is ready */ | ||
81 | |||
82 | /* mh_scan actually does all the dirty work */ | ||
83 | static int | ||
84 | mh_open (mailbox_t mbox, int flags) | ||
85 | { | ||
86 | struct stat st; | ||
87 | mh_data *data; | ||
88 | |||
89 | (void) flags; | ||
90 | if (stat(mbox->name, &st) == -1) | ||
91 | return errno; | ||
92 | |||
93 | if (! S_ISDIR(st.st_mode)) | ||
94 | return EINVAL; /* mailbox is not a directory, thus it is also not MH */ | ||
95 | |||
96 | data = mbox->data; | ||
97 | /* FIXME: does mtime change when the dir has a new file added? */ | ||
98 | data->mtime = st.st_mtime; | ||
99 | |||
100 | return 0; /* everything is fine */ | ||
101 | } | ||
102 | |||
103 | static int | ||
104 | mh_close (mailbox_t mbox) | ||
105 | { | ||
106 | mh_data *data; | ||
107 | |||
108 | data = mbox->data; | ||
109 | |||
110 | /* FIXME: implementation */ | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static int | ||
115 | mh_scan (mailbox_t mbox, size_t msgno, size_t *msgs) | ||
116 | { | ||
117 | struct stat st; | ||
118 | DIR *maildir; | ||
119 | struct dirent *entry; | ||
120 | mh_data *data; | ||
121 | unsigned int count = 0; | ||
122 | int parse_sequence_file = 0; | ||
123 | |||
124 | (void)msgno; | ||
125 | |||
126 | data = mbox->data; | ||
127 | |||
128 | maildir = opendir(mbox->name); | ||
129 | |||
130 | while((entry = readdir(maildir)) != NULL) { | ||
131 | if(strcmp(".", entry->d_name) == 0 || | ||
132 | strcmp("..", entry->d_name) == 0) | ||
133 | continue; | ||
134 | /* FIXME: handle this MH extension */ | ||
135 | if(entry->d_name[0] == '+') | ||
136 | continue; | ||
137 | /* FIXME: decide what to do with messages marked for removal */ | ||
138 | if(entry->d_name[0] == ',') | ||
139 | continue; | ||
140 | if(entry->d_name[0] == '.') { | ||
141 | if(strcmp(".mh_sequences", entry->d_name)) | ||
142 | continue; /* spurious file beginning w/ '.' */ | ||
143 | else { /* MH info in .mh_sequences */ | ||
144 | /* FIXME: parse this file */ | ||
145 | parse_sequence_file = 1; | ||
146 | } | ||
147 | } | ||
148 | if(mh_sequence(entry->d_name)) { | ||
149 | /* FIXME: parse file */ | ||
150 | count++; | ||
151 | } | ||
152 | } | ||
153 | closedir(maildir); | ||
154 | |||
155 | if(parse_sequence_file && count) { | ||
156 | FILE *fp; | ||
157 | char *path = malloc(strlen(mbox->name) + strlen(".mh_sequences") + 2); | ||
158 | sprintf(path, "%s/.mh_sequences", mbox->name); | ||
159 | fp = fopen(path, "r"); | ||
160 | while(!feof(fp)) { | ||
161 | /* FIXME: parse the contents */ | ||
162 | } | ||
163 | fclose(fp); | ||
164 | free(path); | ||
165 | } | ||
166 | |||
167 | stat(mbox->name, &st); | ||
168 | data->mtime = st.st_mtime; | ||
169 | |||
170 | if(msgs) | ||
171 | *msgs = count; | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * Local atoi() | ||
177 | * created this to guarantee that name is only digits, normal atoi allows | ||
178 | * whitespace | ||
179 | */ | ||
180 | static int | ||
181 | mh_sequence(const char *name) | ||
182 | { | ||
183 | const char *sequence; | ||
184 | int i; | ||
185 | |||
186 | for(i = 0, sequence = name; *sequence; sequence++) { | ||
187 | if(!isdigit(*sequence)) | ||
188 | return 0; | ||
189 | i *= 10; | ||
190 | i += (*sequence - '0'); | ||
191 | } | ||
192 | return i; | ||
193 | } |
mailbox/mbx_mmdf.c
deleted
100644 → 0
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 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 Library 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 Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library 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 | #include <errno.h> | ||
19 | |||
20 | #include <mailbox0.h> | ||
21 | #include <registrar0.h> | ||
22 | |||
23 | static int mailbox_mmdf_create (mailbox_t *mbox, const char *name); | ||
24 | static void mailbox_mmdf_destroy (mailbox_t *mbox); | ||
25 | |||
26 | struct mailbox_registrar _mailbox_mmdf_registrar = | ||
27 | { | ||
28 | "MMDF", | ||
29 | mailbox_mmdf_create, mailbox_mmdf_destroy | ||
30 | }; | ||
31 | |||
32 | static int | ||
33 | mailbox_mmdf_create (mailbox_t *mbox, const char *name) | ||
34 | { | ||
35 | (void)mbox; (void)name; | ||
36 | return ENOSYS; | ||
37 | } | ||
38 | |||
39 | static void | ||
40 | mailbox_mmdf_destroy (mailbox_t *mbox) | ||
41 | { | ||
42 | (void)mbox; | ||
43 | return; | ||
44 | } |
mailbox/mbx_unix.c
deleted
100644 → 0
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 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 Library 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 Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library 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 | /* First draft by Alain Magloire */ | ||
19 | |||
20 | #include <mailbox0.h> | ||
21 | #include <registrar0.h> | ||
22 | #include <message0.h> | ||
23 | #include <url0.h> | ||
24 | #include <stream0.h> | ||
25 | #include <body0.h> | ||
26 | #include <header0.h> | ||
27 | #include <attribute0.h> | ||
28 | #include <mailutils/header.h> | ||
29 | #include <mailutils/auth.h> | ||
30 | #include <mailutils/locker.h> | ||
31 | |||
32 | //#define HAVE_PTHREAD_H | ||
33 | |||
34 | #include <stdlib.h> | ||
35 | #include <stdio.h> | ||
36 | #include <time.h> | ||
37 | #include <sys/stat.h> | ||
38 | #include <fcntl.h> | ||
39 | #include <unistd.h> | ||
40 | #include <signal.h> | ||
41 | #include <time.h> | ||
42 | #ifdef HAVE_PTHREAD_H | ||
43 | # include <pthread.h> | ||
44 | #else | ||
45 | # define flockfile(arg) | ||
46 | # define funlockfile(arg) | ||
47 | #endif | ||
48 | #include <string.h> | ||
49 | #include <ctype.h> | ||
50 | #include <limits.h> | ||
51 | #include <errno.h> | ||
52 | |||
53 | #define ATTRIBUTE_IS_DELETED(flag) (flag & MU_ATTRIBUTE_DELETED) | ||
54 | #define ATTRIBUTE_IS_EQUAL(flag1, flag2) (flag1 == flag2) | ||
55 | |||
56 | struct _unix_message; | ||
57 | struct _unix_data; | ||
58 | |||
59 | typedef struct _unix_data* unix_data_t; | ||
60 | typedef struct _unix_message* unix_message_t; | ||
61 | |||
62 | static int unix_create (mailbox_t *pmbox, const char *name); | ||
63 | static void unix_destroy (mailbox_t *pmbox); | ||
64 | |||
65 | struct mailbox_registrar _mailbox_unix_registrar = | ||
66 | { | ||
67 | "UNIX MBOX", | ||
68 | unix_create, unix_destroy | ||
69 | }; | ||
70 | |||
71 | /* Keep the position of where the header and body starts and ends. | ||
72 | old_flags is the "Status:" message. */ | ||
73 | struct _unix_message | ||
74 | { | ||
75 | /* Offset of the parts of the messages in the mailbox. */ | ||
76 | off_t header_from; | ||
77 | off_t header_from_end; | ||
78 | /* Little hack to make things easier * when updating the attribute. */ | ||
79 | off_t header_status; | ||
80 | off_t header_status_end; | ||
81 | off_t body; | ||
82 | off_t body_end; | ||
83 | |||
84 | /* The old_flags contains the definition of Header. */ | ||
85 | int old_flags; | ||
86 | /* The new_flags holds the attributes changes for the current session. We | ||
87 | use this so when expunging we can tell when an attribute been modified. | ||
88 | This is a big help so we can jump to the first modify email for speed | ||
89 | in expunging (see mark dirty). */ | ||
90 | int new_flags; | ||
91 | |||
92 | size_t header_lines; | ||
93 | size_t body_lines; | ||
94 | stream_t stream; | ||
95 | |||
96 | /* A message attach to it. */ | ||
97 | message_t message; | ||
98 | |||
99 | }; | ||
100 | |||
101 | /* The umessages is an array of pointers that contains umessages_count of | ||
102 | unix_message_t*; umessages[umessages_count]. We do it this because | ||
103 | realloc() can move everything to a new memory region and invalidating all | ||
104 | the pointers someone has on the messages. Thanks to <Dave Inglis> for | ||
105 | pointing this out. The messages_count is the count number of messages | ||
106 | parsed so far. */ | ||
107 | struct _unix_data | ||
108 | { | ||
109 | unix_message_t *umessages; | ||
110 | size_t umessages_count; | ||
111 | size_t messages_count; | ||
112 | stream_t stream; | ||
113 | #ifdef HAVE_PTHREAD_H | ||
114 | pthread_mutex_t mutex; | ||
115 | #endif | ||
116 | off_t size; | ||
117 | |||
118 | /* The variables below are use to hold the state when appending messages. */ | ||
119 | enum unix_state | ||
120 | { | ||
121 | UNIX_NO_STATE=0, UNIX_STATE_FROM, UNIX_STATE_DATE, UNIX_STATE_APPEND | ||
122 | } state ; | ||
123 | char *from; | ||
124 | char *date; | ||
125 | off_t off; | ||
126 | |||
127 | }; | ||
128 | |||
129 | /* Mailbox implementation. */ | ||
130 | static int unix_open (mailbox_t mbox, int flag); | ||
131 | static int unix_close (mailbox_t mbox); | ||
132 | static int unix_get_message (mailbox_t, size_t msgno, message_t *msg); | ||
133 | static int unix_append_message (mailbox_t, message_t msg); | ||
134 | static int unix_messages_count (mailbox_t, size_t *msgno); | ||
135 | static int unix_expunge (mailbox_t); | ||
136 | static int unix_num_deleted (mailbox_t, size_t *); | ||
137 | static int unix_scan (mailbox_t, size_t count, size_t *pcount); | ||
138 | static int unix_is_updated (mailbox_t); | ||
139 | static int unix_size (mailbox_t, off_t *size); | ||
140 | |||
141 | |||
142 | /* private stuff */ | ||
143 | static int unix_scan0 (mailbox_t, size_t count, size_t *pcount, int); | ||
144 | static int unix_get_header_read (stream_t is, char *buffer, size_t len, | ||
145 | off_t off, size_t *pnread); | ||
146 | static int unix_get_fd (stream_t is, int *pfd); | ||
147 | static int unix_get_flags (attribute_t, int *); | ||
148 | static int unix_set_flags (attribute_t, int); | ||
149 | static int unix_unset_flags (attribute_t, int); | ||
150 | static int unix_readstream (stream_t is, char *buffer, size_t buflen, | ||
151 | off_t off, size_t *pnread); | ||
152 | static int unix_header_size (header_t header, size_t *psize); | ||
153 | static int unix_header_lines (header_t header, size_t *plines); | ||
154 | static int unix_body_size (body_t body, size_t *psize); | ||
155 | static int unix_body_lines (body_t body, size_t *plines); | ||
156 | static int unix_msg_from (message_t msg, char *buf, size_t len, | ||
157 | size_t *pnwrite); | ||
158 | static int unix_msg_received (message_t msg, char *buf, size_t len, | ||
159 | size_t *pnwrite); | ||
160 | static int unix_lock (mailbox_t mbox, int flag); | ||
161 | static int unix_touchlock (mailbox_t mbox); | ||
162 | static int unix_unlock (mailbox_t mbox); | ||
163 | static int unix_ilock (mailbox_t mbox, int flag); | ||
164 | static int unix_iunlock (mailbox_t mbox); | ||
165 | |||
166 | /* We allocate the mailbox_t struct, but don't do any parsing on the name or | ||
167 | even test for existence. However we do strip any leading "unix:" part of | ||
168 | the name, this is suppose to be the protocol/scheme name. Hopefully there | ||
169 | will not be a mailbox name "unix:". */ | ||
170 | static int | ||
171 | unix_create (mailbox_t *pmbox, const char *name) | ||
172 | { | ||
173 | mailbox_t mbox; | ||
174 | unix_data_t mud; | ||
175 | size_t name_len; | ||
176 | |||
177 | /* Sanity check. */ | ||
178 | if (name == NULL || *name == '\0') | ||
179 | return EINVAL; | ||
180 | |||
181 | name_len = strlen (name); | ||
182 | |||
183 | #define UNIX_SCHEME "unix:" | ||
184 | #define UNIX_SCHEME_LEN 5 | ||
185 | #define SEPARATOR '/' | ||
186 | |||
187 | /* Skip the url scheme. */ | ||
188 | if (name_len > UNIX_SCHEME_LEN | ||
189 | && (name[0] == 'u' || name[0] == 'U') | ||
190 | && (name[1] == 'n' || name[1] == 'N') | ||
191 | && (name[2] == 'i' || name[2] == 'i') | ||
192 | && (name[3] == 'x' || name[3] == 'x' ) | ||
193 | && name[4] == ':') | ||
194 | { | ||
195 | name += UNIX_SCHEME_LEN; | ||
196 | name_len -= UNIX_SCHEME_LEN; | ||
197 | } | ||
198 | |||
199 | /* Allocate memory for mbox (mailbox_t). */ | ||
200 | mbox = calloc (1, sizeof (*mbox)); | ||
201 | if (mbox == NULL) | ||
202 | return ENOMEM; | ||
203 | |||
204 | /* Allocate specific unix mbox data. */ | ||
205 | mud = mbox->data = calloc (1, sizeof (*mud)); | ||
206 | if (mbox->data == NULL) | ||
207 | { | ||
208 | unix_destroy (&mbox); | ||
209 | return ENOMEM; | ||
210 | } | ||
211 | |||
212 | /* Copy the name. | ||
213 | We do not do any further interpretation after the scheme "unix:" | ||
214 | Because for example on distributed system like QnX4 a file name is | ||
215 | //390/etc/passwd. So the best approach is to let the OS handle it | ||
216 | for example if we receive: "unix:///var/mail/alain" the mailbox name | ||
217 | will be "///var/mail/alain" we let open() do the right thing. | ||
218 | So it will let things like this "unix://390/var/mail/alain" where | ||
219 | "//390/var/mail/alain" _is_ the filename, pass correctely. */ | ||
220 | mbox->name = calloc (name_len + 1, sizeof (char)); | ||
221 | if (mbox->name == NULL) | ||
222 | { | ||
223 | unix_destroy (&mbox); | ||
224 | return ENOMEM; | ||
225 | } | ||
226 | memcpy (mbox->name, name, name_len); | ||
227 | |||
228 | #ifdef HAVE_PHTREAD_H | ||
229 | /* Mutex when accessing the structure fields. */ | ||
230 | /* FIXME: should we use rdwr locks instead ?? */ | ||
231 | pthread_mutex_init (&(mbox->mutex), NULL); | ||
232 | #endif | ||
233 | |||
234 | mbox->_create = unix_create; | ||
235 | mbox->_destroy = unix_destroy; | ||
236 | |||
237 | mbox->_open = unix_open; | ||
238 | mbox->_close = unix_close; | ||
239 | |||
240 | /* Messages. */ | ||
241 | mbox->_get_message = unix_get_message; | ||
242 | mbox->_append_message = unix_append_message; | ||
243 | mbox->_messages_count = unix_messages_count; | ||
244 | mbox->_expunge = unix_expunge; | ||
245 | mbox->_num_deleted = unix_num_deleted; | ||
246 | |||
247 | mbox->_scan = unix_scan; | ||
248 | mbox->_is_updated = unix_is_updated; | ||
249 | |||
250 | mbox->_size = unix_size; | ||
251 | |||
252 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, "unix_create(%s)\n", | ||
253 | mbox->name); | ||
254 | (*pmbox) = mbox; | ||
255 | |||
256 | return 0; /* okdoke */ | ||
257 | } | ||
258 | |||
259 | /* Free all ressources associated with Unix mailbox. */ | ||
260 | static void | ||
261 | unix_destroy (mailbox_t *pmbox) | ||
262 | { | ||
263 | if (pmbox && *pmbox) | ||
264 | { | ||
265 | mailbox_t mbox = *pmbox; | ||
266 | unix_close (mbox); | ||
267 | if (mbox->data) | ||
268 | { | ||
269 | size_t i; | ||
270 | unix_data_t mud = mbox->data; | ||
271 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, | ||
272 | "unix_destroy (%s/%s)\n", mbox->name); | ||
273 | for (i = 0; i < mud->umessages_count; i++) | ||
274 | { | ||
275 | unix_message_t mum = mud->umessages[i]; | ||
276 | if (mum == NULL) | ||
277 | { | ||
278 | message_destroy (&(mum->message), mum); | ||
279 | free (mum); | ||
280 | } | ||
281 | } | ||
282 | free (mud->umessages); | ||
283 | free (mbox->data); | ||
284 | } | ||
285 | free (mbox->name); | ||
286 | /* Free the event array. */ | ||
287 | free (mbox->event); | ||
288 | /* Destroy the url. */ | ||
289 | if (mbox->url) | ||
290 | url_destroy (&(mbox->url)); | ||
291 | if (mbox->locker) | ||
292 | locker_destroy (&(mbox->locker)); | ||
293 | if (mbox->auth) | ||
294 | auth_destroy (&(mbox->auth), mbox); | ||
295 | if(mbox->stream) | ||
296 | stream_destroy (&(mbox->stream), mbox); | ||
297 | unix_iunlock (mbox); | ||
298 | #ifdef HAVE_PTHREAD_H | ||
299 | if (mbox->mutex) | ||
300 | ptread_mutex_destroy (&(mbox->mutex)); | ||
301 | #endif | ||
302 | free (mbox); | ||
303 | *pmbox = NULL; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | /* Open the file. */ | ||
308 | static int | ||
309 | unix_open (mailbox_t mbox, int flags) | ||
310 | { | ||
311 | unix_data_t mud = mbox->data; | ||
312 | int status = 0; | ||
313 | |||
314 | if (mud == NULL) | ||
315 | return EINVAL; | ||
316 | |||
317 | /* Authentication prologues. */ | ||
318 | if (mbox->auth) | ||
319 | auth_prologue (mbox->auth); | ||
320 | |||
321 | /* Get a stream. */ | ||
322 | if (mbox->stream == NULL) | ||
323 | { | ||
324 | /* FIXME: for small mbox we shout try to mmap (). */ | ||
325 | |||
326 | status = (flags & MU_STREAM_CREAT) || (flags & MU_STREAM_APPEND); | ||
327 | if (status == 0) | ||
328 | status = mapfile_stream_create (&(mbox->stream)); | ||
329 | if (status != 0) | ||
330 | { | ||
331 | status = file_stream_create (&(mbox->stream)); | ||
332 | if (status != 0) | ||
333 | return status; | ||
334 | } | ||
335 | status = stream_open (mbox->stream, mbox->name, 0, flags); | ||
336 | if (status != 0) | ||
337 | return status; | ||
338 | } | ||
339 | else | ||
340 | { | ||
341 | status = stream_open (mbox->stream, mbox->name, 0, flags); | ||
342 | if (status != 0) | ||
343 | return status; | ||
344 | } | ||
345 | |||
346 | /* Authentication epilogue. */ | ||
347 | if (mbox->auth) | ||
348 | auth_epilogue (mbox->auth); | ||
349 | |||
350 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, "unix_open(%s, %d)\n", | ||
351 | mbox->name, flags); | ||
352 | |||
353 | /* Give an appopriate way to lock. */ | ||
354 | if (mbox->locker == NULL) | ||
355 | locker_create (&(mbox->locker), mbox->name, strlen (mbox->name), | ||
356 | MU_LOCKER_PID | MU_LOCKER_FCNTL); | ||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | static int | ||
361 | unix_close (mailbox_t mbox) | ||
362 | { | ||
363 | unix_data_t mud = mbox->data; | ||
364 | size_t i; | ||
365 | |||
366 | if (mud == NULL) | ||
367 | return EINVAL; | ||
368 | |||
369 | /* Make sure we do not hold any lock for that file. */ | ||
370 | unix_unlock (mbox); | ||
371 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, "unix_close(%s)\n", | ||
372 | mbox->name); | ||
373 | |||
374 | /* Before closing we need to remove all the messages | ||
375 | - to reclaim the memory | ||
376 | - to prepare for another scan. */ | ||
377 | for (i = 0; i < mud->umessages_count; i++) | ||
378 | { | ||
379 | unix_message_t mum = mud->umessages[i]; | ||
380 | /* Destroy the attach messages. */ | ||
381 | if (mum == NULL) | ||
382 | { | ||
383 | message_destroy (&(mum->message), mum); | ||
384 | free (mum); | ||
385 | } | ||
386 | } | ||
387 | free (mud->umessages); | ||
388 | mud->umessages = NULL; | ||
389 | mud->messages_count = mud->umessages_count = 0; | ||
390 | mud->size = 0; | ||
391 | return stream_close (mbox->stream); | ||
392 | } | ||
393 | |||
394 | /* Mailbox Parsing. */ | ||
395 | #include "mbx_unixscan.c" | ||
396 | |||
397 | static int | ||
398 | unix_scan (mailbox_t mbox, size_t msgno, size_t *pcount) | ||
399 | { | ||
400 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, "unix_scan(%s)\n", mbox->name); | ||
401 | return unix_scan0 (mbox, msgno, pcount, 1); | ||
402 | } | ||
403 | |||
404 | |||
405 | /* FIXME: How to handle a shrink ? meaning, the &^$^@%#@^& user start two | ||
406 | browsers and delete files in one. My views is that we should scream | ||
407 | bloody murder and hunt them with a machette. But for now just play dumb, | ||
408 | but maybe the best approach is to pack our things and leave .i.e exit(). */ | ||
409 | static int | ||
410 | unix_is_updated (mailbox_t mbox) | ||
411 | { | ||
412 | off_t size; | ||
413 | unix_data_t mud = mbox->data; | ||
414 | |||
415 | if (mud == NULL) | ||
416 | return EINVAL; | ||
417 | if (stream_size (mbox->stream, &size) != 0) | ||
418 | return 0; | ||
419 | return (mud->size == size); | ||
420 | } | ||
421 | |||
422 | static int | ||
423 | unix_num_deleted (mailbox_t mbox, size_t *pnum) | ||
424 | { | ||
425 | unix_data_t mud = mbox->data; | ||
426 | unix_message_t mum; | ||
427 | size_t i, total; | ||
428 | if (mud == NULL) | ||
429 | return EINVAL; | ||
430 | for (i = total = 0; i < mud->messages_count; i++) | ||
431 | { | ||
432 | mum = mud->umessages[i]; | ||
433 | if (ATTRIBUTE_IS_DELETED (mum->new_flags)) | ||
434 | total++; | ||
435 | } | ||
436 | |||
437 | if (pnum) | ||
438 | *pnum = total; | ||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | /* FIXME: the use of tmpfile() on some system can lead to race condition, We | ||
443 | should use a safer approach. */ | ||
444 | static FILE * | ||
445 | unix_tmpfile (mailbox_t mbox, char **pbox) | ||
446 | { | ||
447 | const char *tmpdir; | ||
448 | int fd; | ||
449 | FILE *fp; | ||
450 | const char *basename; | ||
451 | |||
452 | /* P_tmpdir should be define in <stdio.h>. */ | ||
453 | #ifndef P_tmpdir | ||
454 | # define P_tmpdir "/tmp" | ||
455 | #endif | ||
456 | |||
457 | tmpdir = getenv ("TEMPDIR") ? getenv ("TEMPDIR") : P_tmpdir; | ||
458 | basename = strrchr (mbox->name, '/'); | ||
459 | if (basename) | ||
460 | basename++; | ||
461 | else | ||
462 | basename = mbox->name; | ||
463 | *pbox = calloc (strlen (tmpdir) + strlen ("MBOX_") + | ||
464 | strlen (basename) + 1, sizeof (char)); | ||
465 | if (*pbox == NULL) | ||
466 | return NULL; | ||
467 | sprintf (*pbox, "%s/%s%s", tmpdir, "MBOX_", basename); | ||
468 | |||
469 | /* FIXME: I don't think this is the righ approach, creating an anonymous | ||
470 | file would be better ? no trace left behind. */ | ||
471 | /* Create the file. It must not exist. If it does exist, fail. */ | ||
472 | fd = open (*pbox, O_RDWR|O_CREAT|O_EXCL, 0600); | ||
473 | if (fd < 0) | ||
474 | { | ||
475 | fprintf (stderr,"Can't create %s\n", *pbox); | ||
476 | fprintf (stderr,"delete file <%s>, Please\n", *pbox); | ||
477 | fprintf (stderr, "It was likely due to an error when expunging\n"); | ||
478 | return NULL; | ||
479 | } | ||
480 | fp = fdopen (fd, "w+"); | ||
481 | if (fp == 0) | ||
482 | { | ||
483 | close(fd); | ||
484 | free (*pbox); | ||
485 | *pbox = NULL; | ||
486 | } | ||
487 | |||
488 | /* Really I should just remove the file here. */ | ||
489 | /* remove(*pbox); */ | ||
490 | return fp; | ||
491 | } | ||
492 | |||
493 | /* For the expunge bits we took a very cautionnary approach, meaning | ||
494 | we create temporary file in the tmpdir copy all the file not mark deleted, | ||
495 | and skip the deleted ones, truncate the real mailbox to the desired size | ||
496 | and overwrite with the tmp mailbox. The approach to do everyting | ||
497 | in core is tempting but require to much memory, it is not rare now | ||
498 | a day to have 30 Megs mailbox, also there is danger for filesystems | ||
499 | with quotas, or some program may not respect the advisory lock and | ||
500 | decide to append a new message while your expunging etc ... | ||
501 | The real downside to the approach we take is that when things go wrong | ||
502 | the temporary file bay be left in /tmp, which is not all that bad | ||
503 | because at least have something to recuparate when failure. */ | ||
504 | static int | ||
505 | unix_expunge (mailbox_t mbox) | ||
506 | { | ||
507 | unix_data_t mud = mbox->data; | ||
508 | unix_message_t mum; | ||
509 | int status = 0; | ||
510 | sigset_t sigset; | ||
511 | FILE *tempfile; | ||
512 | size_t nread; | ||
513 | size_t i, j, dirty, first; | ||
514 | off_t marker = 0; | ||
515 | off_t total = 0; | ||
516 | char buffer [BUFSIZ]; | ||
517 | char *tmpmbox = NULL; | ||
518 | |||
519 | if (mud == NULL) | ||
520 | return EINVAL; | ||
521 | |||
522 | /* Noop. */ | ||
523 | if (mud->messages_count == 0) | ||
524 | return 0; | ||
525 | |||
526 | /* Do we have a consistent view of the mailbox. */ | ||
527 | /* FIXME: this is not enough, we can do better | ||
528 | - by checking the file size and scream bloody murder if it has shrink. | ||
529 | - if its bigger we should be able to handle it before the ftruncate () | ||
530 | by copying back the new messages. */ | ||
531 | if (! unix_is_updated (mbox)) | ||
532 | { | ||
533 | fprintf (stderr, "mailbox is not updated, try again.\n"); | ||
534 | return EAGAIN; | ||
535 | } | ||
536 | |||
537 | /* Mark dirty the first mail with an attribute change. */ | ||
538 | for (dirty = 0; dirty < mud->messages_count; dirty++) | ||
539 | { | ||
540 | mum = mud->umessages[dirty]; | ||
541 | if (mum->new_flags && | ||
542 | ! ATTRIBUTE_IS_EQUAL (mum->old_flags, mum->new_flags)) | ||
543 | break; | ||
544 | } | ||
545 | |||
546 | /* Did something change ? */ | ||
547 | if (dirty == mud->messages_count) | ||
548 | return 0; /* Nothing change, bail out. */ | ||
549 | |||
550 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, "unix_expunge (%s)\n", | ||
551 | mbox->name); | ||
552 | |||
553 | /* This is redundant, we go to the loop again. But it's more secure here | ||
554 | since we don't want to be disturb when expunging. */ | ||
555 | for (j = 0; j < mud->messages_count; j++) | ||
556 | { | ||
557 | mum = mud->umessages[j]; | ||
558 | if (mum && mum->new_flags && ATTRIBUTE_IS_DELETED (mum->new_flags)) | ||
559 | message_destroy (&(mum->message), mum); | ||
560 | } | ||
561 | |||
562 | /* Create a tempory file. */ | ||
563 | tempfile = unix_tmpfile (mbox, &tmpmbox); | ||
564 | if (tempfile == NULL) | ||
565 | { | ||
566 | fprintf (stderr, "Failed to create temporary file when expunging.\n"); | ||
567 | free (tmpmbox); | ||
568 | return errno; | ||
569 | } | ||
570 | |||
571 | /* Get the lock. */ | ||
572 | if (unix_lock (mbox, MU_LOCKER_WRLOCK) < 0) | ||
573 | { | ||
574 | fclose (tempfile); | ||
575 | remove (tmpmbox); | ||
576 | free (tmpmbox); | ||
577 | fprintf (stderr, "Failed to grab the lock\n"); | ||
578 | return ENOLCK; | ||
579 | } | ||
580 | |||
581 | /* Critical section, we can not allowed signal here. */ | ||
582 | sigemptyset (&sigset); | ||
583 | sigaddset (&sigset, SIGTERM); | ||
584 | sigaddset (&sigset, SIGHUP); | ||
585 | sigaddset (&sigset, SIGTSTP); | ||
586 | sigaddset (&sigset, SIGINT); | ||
587 | sigaddset (&sigset, SIGWINCH); | ||
588 | sigprocmask (SIG_BLOCK, &sigset, 0); | ||
589 | |||
590 | unix_ilock (mbox, MU_LOCKER_RDLOCK); | ||
591 | |||
592 | /* Set the marker position. */ | ||
593 | total = marker = mud->umessages[dirty]->header_from; | ||
594 | |||
595 | /* Copy to tempfile emails not mark deleted. */ | ||
596 | for (first = 1, i = dirty; i < mud->messages_count; i++) | ||
597 | { | ||
598 | mum = mud->umessages[i]; | ||
599 | |||
600 | /* Skip it, if mark for deletion. */ | ||
601 | if (ATTRIBUTE_IS_DELETED (mum->new_flags)) | ||
602 | continue; | ||
603 | |||
604 | /* Add a NL separator between messages. */ | ||
605 | if (first) | ||
606 | first = 0; | ||
607 | else | ||
608 | { | ||
609 | fputc ('\n', tempfile); | ||
610 | total++; | ||
611 | } | ||
612 | |||
613 | /* Begining of header copy. */ | ||
614 | { | ||
615 | off_t current; | ||
616 | /* This is done in two parts first we check if the attribute changed, | ||
617 | if yes then we have to update the "Status:" field. Unfortunately | ||
618 | there is no requirement for the "Status:" to be the last field, so | ||
619 | we take the long approach; Copy up to the Status, update the | ||
620 | Status and copy the rest. */ | ||
621 | |||
622 | /* Attribute change ? */ | ||
623 | if (mum->new_flags | ||
624 | &&! ATTRIBUTE_IS_EQUAL (mum->old_flags, mum->new_flags) | ||
625 | && mum->header_status > mum->header_from) | ||
626 | { | ||
627 | size_t n = 0; | ||
628 | off_t offset = mum->header_from; | ||
629 | size_t len = mum->header_status - mum->header_from; | ||
630 | current = mum->header_status_end; | ||
631 | while (len > 0) | ||
632 | { | ||
633 | nread = (len < sizeof (buffer)) ? len : sizeof (buffer); | ||
634 | if ((status = stream_read (mbox->stream, buffer, | ||
635 | nread, offset, &n) != 0) | ||
636 | || fwrite(buffer, sizeof(*buffer), n, tempfile) != n) | ||
637 | { | ||
638 | if (status == 0) | ||
639 | status = errno; | ||
640 | fprintf (stderr, "Error expunge:%d: (%s)\n", __LINE__, | ||
641 | strerror (status)); | ||
642 | goto bailout0; | ||
643 | } | ||
644 | len -= n; | ||
645 | total += n; | ||
646 | offset += n; | ||
647 | } | ||
648 | |||
649 | /* Put the new attributes. */ | ||
650 | { | ||
651 | char abuf[64]; | ||
652 | size_t na = 0; | ||
653 | abuf[0] = '\0'; | ||
654 | flags_to_string (mum->new_flags, abuf, sizeof(abuf), &na); | ||
655 | fputs (abuf, tempfile); | ||
656 | total += na; | ||
657 | } | ||
658 | } | ||
659 | else /* Attribute did not change. */ | ||
660 | current = mum->header_from; | ||
661 | |||
662 | /* Copy the rest of header without changes. */ | ||
663 | { | ||
664 | size_t n = 0; | ||
665 | off_t offset = current; | ||
666 | size_t len = mum->body - current; | ||
667 | while (len > 0) | ||
668 | { | ||
669 | nread = (len < sizeof (buffer)) ? len : sizeof (buffer); | ||
670 | if ((status = stream_read (mbox->stream, buffer, nread, | ||
671 | offset, &n) != 0) | ||
672 | || fwrite(buffer, sizeof(*buffer), n, tempfile) != n) | ||
673 | { | ||
674 | if (status == 0) | ||
675 | status = errno; | ||
676 | fprintf (stderr, "Error expunge:%d: %s", __LINE__, | ||
677 | strerror (status)); | ||
678 | goto bailout0; | ||
679 | } | ||
680 | len -= n; | ||
681 | total += n; | ||
682 | offset += n; | ||
683 | } | ||
684 | } | ||
685 | } /* End of header copy. */ | ||
686 | |||
687 | /* Copy the body. */ | ||
688 | { | ||
689 | size_t n = 0; | ||
690 | off_t offset = mum->body; | ||
691 | size_t len = mum->body_end - mum->body; | ||
692 | while (len > 0) | ||
693 | { | ||
694 | nread = (len < sizeof (buffer)) ? len : sizeof (buffer); | ||
695 | if ((status = stream_read (mbox->stream, buffer, nread, | ||
696 | offset, &n) != 0) | ||
697 | || fwrite(buffer, sizeof(*buffer), n, tempfile) != n) | ||
698 | { | ||
699 | if (status == 0) | ||
700 | status = errno; | ||
701 | fprintf (stderr, "Error expunge:%d: %s", __LINE__, | ||
702 | strerror (status)); | ||
703 | goto bailout0; | ||
704 | } | ||
705 | len -= n; | ||
706 | total += n; | ||
707 | offset += n; | ||
708 | } | ||
709 | } /* End of body copy. */ | ||
710 | } /* for (;;) */ | ||
711 | |||
712 | /* Caution: before ftruncate()ing the file see if we've receiving new mail | ||
713 | Some program may not respect the lock, or the lock was held for too | ||
714 | long. */ | ||
715 | { | ||
716 | off_t size = 0; | ||
717 | if (stream_size (mbox->stream, &size) == 0) | ||
718 | { | ||
719 | size_t n = 0; | ||
720 | off_t offset = size; | ||
721 | size_t len = size - mud->size; | ||
722 | while (len > 0) | ||
723 | { | ||
724 | nread = (len < sizeof (buffer)) ? len : sizeof (buffer); | ||
725 | if ((status = stream_read (mbox->stream, buffer, nread, | ||
726 | offset, &n) != 0) | ||
727 | || fwrite(buffer, sizeof(*buffer), n, tempfile) != n) | ||
728 | { | ||
729 | if (status == 0) | ||
730 | status = errno; | ||
731 | fprintf (stderr, "Error expunge:%d: %s", __LINE__, | ||
732 | strerror (status)); | ||
733 | goto bailout0; | ||
734 | } | ||
735 | len -= n; | ||
736 | total += n; | ||
737 | offset += n; | ||
738 | } | ||
739 | } | ||
740 | } /* End of precaution. */ | ||
741 | |||
742 | /* Seek and rewrite it. */ | ||
743 | rewind (tempfile); | ||
744 | if (total > 0) | ||
745 | { | ||
746 | size_t n = 0; | ||
747 | off_t offset = marker; | ||
748 | while ((nread = fread (buffer, sizeof (*buffer), | ||
749 | sizeof (buffer), tempfile)) != 0) | ||
750 | { | ||
751 | while (nread) | ||
752 | { | ||
753 | status = stream_write (mbox->stream, buffer, nread, offset, &n); | ||
754 | if (status != 0) | ||
755 | { | ||
756 | fprintf (stderr, "Error expunge:%d: %s\n", __LINE__, | ||
757 | strerror (status)); | ||
758 | goto bailout; | ||
759 | } | ||
760 | nread -= n; | ||
761 | offset += n; | ||
762 | } | ||
763 | } | ||
764 | } | ||
765 | |||
766 | /* How can I handle error here ?? */ | ||
767 | clearerr (tempfile); | ||
768 | |||
769 | /* Flush/truncation. */ | ||
770 | stream_flush (mbox->stream); | ||
771 | status = stream_truncate (mbox->stream, total); | ||
772 | if (status != 0) | ||
773 | { | ||
774 | fprintf (stderr, "Error expunging:%d: %s", __LINE__, strerror (status)); | ||
775 | goto bailout; | ||
776 | } | ||
777 | |||
778 | bailout0: | ||
779 | /* Don't remove the tmp mbox in case of errors, when writing back. */ | ||
780 | remove (tmpmbox); | ||
781 | |||
782 | bailout: | ||
783 | |||
784 | free (tmpmbox); | ||
785 | /* Release the locks. */ | ||
786 | unix_unlock (mbox); | ||
787 | unix_iunlock (mbox); | ||
788 | fclose (tempfile); | ||
789 | sigprocmask (SIG_UNBLOCK, &sigset, 0); | ||
790 | |||
791 | /* We need to readjust the pointers. */ | ||
792 | if (status == 0) | ||
793 | { | ||
794 | size_t dlast; | ||
795 | for (j = dirty, dlast = mud->messages_count - 1; | ||
796 | j < mud->messages_count; j++) | ||
797 | { | ||
798 | /* Clear all the references, any attach messages been already | ||
799 | destroy above. */ | ||
800 | mum = mud->umessages[j]; | ||
801 | if (mum->new_flags && ATTRIBUTE_IS_DELETED (mum->new_flags)) | ||
802 | { | ||
803 | memmove (mud->umessages + j, mud->umessages + j + 1, | ||
804 | (dlast - dirty) * sizeof (mum)); | ||
805 | mum->header_from = mum->header_from_end = 0; | ||
806 | mum->header_status = mum->header_status_end = 0; | ||
807 | mum->body = mum->body_end = 0; | ||
808 | mum->header_lines = mum->body_lines = 0; | ||
809 | mud->umessages[dlast] = mum; | ||
810 | dlast--; | ||
811 | mum = mud->umessages[j]; | ||
812 | } | ||
813 | mum->header_from = mum->header_from_end = 0; | ||
814 | mum->header_status = mum->header_status_end = 0; | ||
815 | mum->body = mum->body_end = 0; | ||
816 | mum->header_lines = mum->body_lines = 0; | ||
817 | } | ||
818 | /* This is should reset the messages_count, the last argument 0 means | ||
819 | not to send event notification. */ | ||
820 | unix_scan0 (mbox, dirty, NULL, 0); | ||
821 | } | ||
822 | return status; | ||
823 | } | ||
824 | |||
825 | static int | ||
826 | unix_get_fd (stream_t is, int *pfd) | ||
827 | { | ||
828 | unix_message_t mum = is->owner; | ||
829 | |||
830 | if (mum == NULL) | ||
831 | return EINVAL; | ||
832 | |||
833 | return stream_get_fd (mum->stream, pfd); | ||
834 | } | ||
835 | |||
836 | static int | ||
837 | unix_get_flags (attribute_t attr, int *pflags) | ||
838 | { | ||
839 | unix_message_t mum = attr->owner; | ||
840 | |||
841 | if (mum == NULL) | ||
842 | return EINVAL; | ||
843 | |||
844 | if (pflags) | ||
845 | *pflags = mum->new_flags; | ||
846 | return 0; | ||
847 | } | ||
848 | |||
849 | static int | ||
850 | unix_set_flags (attribute_t attr, int flags) | ||
851 | { | ||
852 | unix_message_t mum = attr->owner; | ||
853 | |||
854 | if (mum == NULL) | ||
855 | return EINVAL; | ||
856 | |||
857 | mum->new_flags |= flags; | ||
858 | return 0; | ||
859 | } | ||
860 | |||
861 | static int | ||
862 | unix_unset_flags (attribute_t attr, int flags) | ||
863 | { | ||
864 | unix_message_t mum = attr->owner; | ||
865 | |||
866 | if (mum == NULL) | ||
867 | return EINVAL; | ||
868 | |||
869 | mum->new_flags &= ~flags; | ||
870 | return 0; | ||
871 | } | ||
872 | |||
873 | static int | ||
874 | unix_readstream (stream_t is, char *buffer, size_t buflen, | ||
875 | off_t off, size_t *pnread) | ||
876 | { | ||
877 | unix_message_t mum = is->owner; | ||
878 | size_t nread = 0; | ||
879 | |||
880 | if (mum == NULL) | ||
881 | return EINVAL; | ||
882 | |||
883 | if (buffer == NULL || buflen == 0) | ||
884 | { | ||
885 | if (pnread) | ||
886 | *pnread = nread; | ||
887 | return 0; | ||
888 | } | ||
889 | |||
890 | { | ||
891 | off_t ln = mum->body_end - (mum->body + off); | ||
892 | size_t n = 0; | ||
893 | int status; | ||
894 | if (ln > 0) | ||
895 | { | ||
896 | nread = ((size_t)ln < buflen) ? ln : buflen; | ||
897 | /* Position the file pointer and the buffer. */ | ||
898 | status = stream_read (mum->stream, buffer, nread, mum->body + off, &n); | ||
899 | if (status != 0) | ||
900 | return status; | ||
901 | } | ||
902 | } | ||
903 | |||
904 | if (pnread) | ||
905 | *pnread = nread; | ||
906 | return 0; | ||
907 | } | ||
908 | |||
909 | static int | ||
910 | unix_get_header_read (stream_t is, char *buffer, size_t len, | ||
911 | off_t off, size_t *pnread) | ||
912 | { | ||
913 | unix_message_t mum = is->owner; | ||
914 | size_t nread = 0; | ||
915 | int status = 0; | ||
916 | off_t ln; | ||
917 | |||
918 | if (mum == NULL) | ||
919 | return EINVAL; | ||
920 | |||
921 | ln = mum->body - (mum->header_from_end + off); | ||
922 | if (ln > 0) | ||
923 | { | ||
924 | nread = ((size_t)ln < len) ? ln : len; | ||
925 | /* Position the file pointer and the buffer. */ | ||
926 | status = stream_read (mum->stream, buffer, nread, | ||
927 | mum->header_from_end + off, &nread); | ||
928 | } | ||
929 | if (pnread) | ||
930 | *pnread = nread; | ||
931 | return status; | ||
932 | } | ||
933 | |||
934 | static int | ||
935 | unix_header_size (header_t header, size_t *psize) | ||
936 | { | ||
937 | unix_message_t mum = header->owner; | ||
938 | if (mum == NULL) | ||
939 | return EINVAL; | ||
940 | if (psize) | ||
941 | *psize = mum->body - mum->header_from_end; | ||
942 | return 0; | ||
943 | } | ||
944 | |||
945 | static int | ||
946 | unix_header_lines (header_t header, size_t *plines) | ||
947 | { | ||
948 | unix_message_t mum = header->owner; | ||
949 | if (mum == NULL) | ||
950 | return EINVAL; | ||
951 | if (plines) | ||
952 | *plines = mum->header_lines; | ||
953 | return 0; | ||
954 | } | ||
955 | |||
956 | static int | ||
957 | unix_body_size (body_t body, size_t *psize) | ||
958 | { | ||
959 | unix_message_t mum = body->owner; | ||
960 | if (mum == NULL) | ||
961 | return EINVAL; | ||
962 | if (psize) | ||
963 | *psize = mum->body_end - mum->body + 1; | ||
964 | return 0; | ||
965 | } | ||
966 | |||
967 | static int | ||
968 | unix_body_lines (body_t body, size_t *plines) | ||
969 | { | ||
970 | unix_message_t mum = body->owner; | ||
971 | if (mum == NULL) | ||
972 | return EINVAL; | ||
973 | if (plines) | ||
974 | *plines = mum->body_lines; | ||
975 | return 0; | ||
976 | } | ||
977 | |||
978 | static int | ||
979 | unix_msg_received (message_t msg, char *buf, size_t len, | ||
980 | size_t *pnwrite) | ||
981 | { | ||
982 | unix_message_t mum = msg->owner; | ||
983 | size_t n = 0; | ||
984 | int status; | ||
985 | char buffer[512]; | ||
986 | |||
987 | if (mum == NULL) | ||
988 | return EINVAL; | ||
989 | |||
990 | status = stream_readline (mum->stream, buffer, sizeof(buffer), | ||
991 | mum->header_from, &n); | ||
992 | if (status != 0) | ||
993 | { | ||
994 | if (pnwrite) | ||
995 | *pnwrite = 0; | ||
996 | if (buf) | ||
997 | *buf = '\0'; | ||
998 | return status; | ||
999 | } | ||
1000 | |||
1001 | if (n > 5) | ||
1002 | { | ||
1003 | char *s = strchr (buffer + 5, ' '); | ||
1004 | if (s) | ||
1005 | { | ||
1006 | if (buf && len > 0) | ||
1007 | { | ||
1008 | strncpy (buf, s + 1, len); | ||
1009 | buffer [len - 1] = '\0'; | ||
1010 | } | ||
1011 | if (pnwrite) | ||
1012 | *pnwrite = strlen (s + 1); | ||
1013 | return 0; | ||
1014 | } | ||
1015 | } | ||
1016 | if (pnwrite) | ||
1017 | *pnwrite = 0; | ||
1018 | if (buf) | ||
1019 | *buf = '\0'; | ||
1020 | return 0; | ||
1021 | } | ||
1022 | |||
1023 | static int | ||
1024 | unix_msg_from (message_t msg, char *buf, size_t len, size_t *pnwrite) | ||
1025 | { | ||
1026 | unix_message_t mum = msg->owner; | ||
1027 | size_t n = 0; | ||
1028 | int status; | ||
1029 | char buffer[512]; | ||
1030 | |||
1031 | if (mum == NULL) | ||
1032 | return EINVAL; | ||
1033 | |||
1034 | status = stream_readline (mum->stream, buffer, sizeof(buffer), | ||
1035 | mum->header_from, &n); | ||
1036 | if (status != 0) | ||
1037 | { | ||
1038 | if (pnwrite) | ||
1039 | *pnwrite = 0; | ||
1040 | if (buf) | ||
1041 | *buf = '\0'; | ||
1042 | return status; | ||
1043 | } | ||
1044 | |||
1045 | if (n > 5) | ||
1046 | { | ||
1047 | char *s = strchr (buffer + 5, ' '); | ||
1048 | if (s) | ||
1049 | { | ||
1050 | *s = '\0'; | ||
1051 | if (buf && len > 0) | ||
1052 | { | ||
1053 | strncpy (buf, buffer + 5, len); | ||
1054 | buffer [len - 1] = '\0'; | ||
1055 | } | ||
1056 | if (pnwrite) | ||
1057 | *pnwrite = strlen (buffer + 5); | ||
1058 | return 0; | ||
1059 | } | ||
1060 | } | ||
1061 | if (pnwrite) | ||
1062 | *pnwrite = 0; | ||
1063 | if (buf) | ||
1064 | *buf = '\0'; | ||
1065 | return 0; | ||
1066 | } | ||
1067 | |||
1068 | static int | ||
1069 | unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ||
1070 | { | ||
1071 | int status; | ||
1072 | unix_data_t mud = mbox->data; | ||
1073 | unix_message_t mum; | ||
1074 | message_t msg = NULL; | ||
1075 | |||
1076 | /* Sanity checks. */ | ||
1077 | if (pmsg == NULL || mud == NULL || (!(mud->messages_count > 0 && msgno > 0 | ||
1078 | && msgno <= mud->messages_count))) | ||
1079 | return EINVAL; | ||
1080 | |||
1081 | mum = mud->umessages[msgno - 1]; | ||
1082 | |||
1083 | /* Check if we already have it. */ | ||
1084 | if (mum->message) | ||
1085 | { | ||
1086 | if (pmsg) | ||
1087 | *pmsg = mum->message; | ||
1088 | return 0; | ||
1089 | } | ||
1090 | |||
1091 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, | ||
1092 | "unix_get_message(%s, %d)\n", mbox->name, msgno); | ||
1093 | |||
1094 | /* Get an empty message struct. */ | ||
1095 | status = message_create (&msg, mum); | ||
1096 | if (status != 0) | ||
1097 | return status; | ||
1098 | |||
1099 | /* Set the header. */ | ||
1100 | { | ||
1101 | header_t header = NULL; | ||
1102 | stream_t stream = NULL; | ||
1103 | if ((status = header_create (&header, NULL, 0, mum)) != 0 | ||
1104 | || (status = stream_create (&stream, MU_STREAM_READ, mum)) != 0) | ||
1105 | { | ||
1106 | stream_destroy (&stream, mum); | ||
1107 | header_destroy (&header, mum); | ||
1108 | message_destroy (&msg, mum); | ||
1109 | return status; | ||
1110 | } | ||
1111 | stream_set_read (stream, unix_get_header_read, mum); | ||
1112 | stream_set_fd (stream, unix_get_fd, mum); | ||
1113 | stream_set_flags (stream, MU_STREAM_READ, mum); | ||
1114 | header_set_stream (header, stream, mum); | ||
1115 | header_set_size (header, unix_header_size, mum); | ||
1116 | header_set_lines (header, unix_header_lines, mum); | ||
1117 | message_set_header (msg, header, mum); | ||
1118 | } | ||
1119 | |||
1120 | /* Set the attribute. */ | ||
1121 | { | ||
1122 | attribute_t attribute; | ||
1123 | status = attribute_create (&attribute, mum); | ||
1124 | if (status != 0) | ||
1125 | { | ||
1126 | message_destroy (&msg, mum); | ||
1127 | return status; | ||
1128 | } | ||
1129 | mum->new_flags = mum->old_flags; | ||
1130 | attribute_set_get_flags (attribute, unix_get_flags, mum); | ||
1131 | attribute_set_set_flags (attribute, unix_set_flags, mum); | ||
1132 | attribute_set_unset_flags (attribute, unix_unset_flags, mum); | ||
1133 | message_set_attribute (msg, attribute, mum); | ||
1134 | } | ||
1135 | |||
1136 | /* Prepare the body. */ | ||
1137 | { | ||
1138 | body_t body = NULL; | ||
1139 | stream_t stream = NULL; | ||
1140 | int flags = MU_STREAM_READ; | ||
1141 | if ((status = body_create (&body, mum)) != 0 | ||
1142 | || (status = stream_create (&stream, flags, mum)) != 0) | ||
1143 | { | ||
1144 | body_destroy (&body, mum); | ||
1145 | stream_destroy (&stream, mum); | ||
1146 | message_destroy (&msg, mum); | ||
1147 | return status; | ||
1148 | } | ||
1149 | stream_set_read (stream, unix_readstream, mum); | ||
1150 | stream_set_fd (stream, unix_get_fd, mum); | ||
1151 | stream_get_flags (mbox->stream, &flags); | ||
1152 | stream_set_flags (stream, flags, mum); | ||
1153 | body_set_stream (body, stream, mum); | ||
1154 | body_set_size (body, unix_body_size, mum); | ||
1155 | body_set_lines (body, unix_body_lines, mum); | ||
1156 | message_set_body (msg, body, mum); | ||
1157 | } | ||
1158 | |||
1159 | /* Set the envelope. */ | ||
1160 | message_set_from (msg, unix_msg_from, mum); | ||
1161 | message_set_received (msg, unix_msg_received, mum); | ||
1162 | |||
1163 | /* Attach the message to the mailbox unix data. */ | ||
1164 | mum->message = msg; | ||
1165 | |||
1166 | if (pmsg) | ||
1167 | *pmsg = msg; | ||
1168 | return 0; | ||
1169 | } | ||
1170 | |||
1171 | static int | ||
1172 | unix_append_message (mailbox_t mbox, message_t msg) | ||
1173 | { | ||
1174 | unix_data_t mud = mbox->data; | ||
1175 | if (msg == NULL || mud == NULL) | ||
1176 | return EINVAL; | ||
1177 | |||
1178 | mailbox_debug (mbox, MU_MAILBOX_DEBUG_TRACE, | ||
1179 | "unix_append_message (%s)\n", mbox->name); | ||
1180 | |||
1181 | unix_lock (mbox, MU_LOCKER_WRLOCK); | ||
1182 | { | ||
1183 | off_t size; | ||
1184 | int status; | ||
1185 | size_t n = 0; | ||
1186 | char nl = '\n'; | ||
1187 | |||
1188 | /* Move to the end of the file, not necesary if _APPEND mode. */ | ||
1189 | status = stream_size (mbox->stream, &size); | ||
1190 | if (status != 0) | ||
1191 | { | ||
1192 | unix_unlock (mbox); | ||
1193 | return status; | ||
1194 | } | ||
1195 | |||
1196 | switch (mud->state) | ||
1197 | { | ||
1198 | case UNIX_NO_STATE: | ||
1199 | mud->from = calloc (128, sizeof (char)); | ||
1200 | if (mud->from == NULL) | ||
1201 | { | ||
1202 | unix_unlock (mbox); | ||
1203 | return ENOMEM; | ||
1204 | } | ||
1205 | mud->date = calloc (128, sizeof (char)); | ||
1206 | if (mud->date == NULL) | ||
1207 | { | ||
1208 | free (mud->from); | ||
1209 | mud->from = NULL; | ||
1210 | mud->state = UNIX_NO_STATE; | ||
1211 | unix_unlock (mbox); | ||
1212 | return ENOMEM; | ||
1213 | } | ||
1214 | mud->off = 0; | ||
1215 | mud->state = UNIX_STATE_FROM; | ||
1216 | |||
1217 | case UNIX_STATE_FROM: | ||
1218 | /* Generate a "From " separator. */ | ||
1219 | { | ||
1220 | char *s; | ||
1221 | size_t len = 0; | ||
1222 | status = message_from (msg, mud->from, 127, &len); | ||
1223 | if (status != 0) | ||
1224 | { | ||
1225 | if (status != EAGAIN) | ||
1226 | { | ||
1227 | free (mud->from); | ||
1228 | free (mud->date); | ||
1229 | mud->date = mud->from = NULL; | ||
1230 | mud->state = UNIX_NO_STATE; | ||
1231 | unix_unlock (mbox); | ||
1232 | } | ||
1233 | return status; | ||
1234 | } | ||
1235 | /* Nuke trailing newline. */ | ||
1236 | s = memchr (mud->from, nl, len); | ||
1237 | if (s) | ||
1238 | *s = '\0'; | ||
1239 | mud->state = UNIX_STATE_DATE; | ||
1240 | } | ||
1241 | |||
1242 | case UNIX_STATE_DATE: | ||
1243 | /* Generate a date for the "From " separator. */ | ||
1244 | { | ||
1245 | char *s; | ||
1246 | size_t len = 0; | ||
1247 | status = message_received (msg, mud->date, 127, &len); | ||
1248 | if (status != 0) | ||
1249 | { | ||
1250 | if (status != EAGAIN) | ||
1251 | { | ||
1252 | free (mud->from); | ||
1253 | free (mud->date); | ||
1254 | mud->date = mud->from = NULL; | ||
1255 | mud->state = UNIX_NO_STATE; | ||
1256 | unix_unlock (mbox); | ||
1257 | } | ||
1258 | return status; | ||
1259 | } | ||
1260 | /* Nuke trailing newline. */ | ||
1261 | s = memchr (mud->date, nl, len); | ||
1262 | if (s) | ||
1263 | *s = '\0'; | ||
1264 | /* Write the separator to the mailbox. */ | ||
1265 | stream_write (mbox->stream, "From ", 5, size, &n); | ||
1266 | size += n; | ||
1267 | stream_write (mbox->stream, mud->from, strlen (mud->from), size, &n); | ||
1268 | size += n; | ||
1269 | stream_write (mbox->stream, " ", 1, size, &n); | ||
1270 | size += n; | ||
1271 | stream_write (mbox->stream, mud->date, strlen (mud->date), size, &n); | ||
1272 | size += n; | ||
1273 | stream_write (mbox->stream, &nl , 1, size, &n); | ||
1274 | size += n; | ||
1275 | free (mud->from); | ||
1276 | free (mud->date); | ||
1277 | mud->from = mud->date = NULL; | ||
1278 | mud->state = UNIX_STATE_APPEND; | ||
1279 | } | ||
1280 | |||
1281 | case UNIX_STATE_APPEND: | ||
1282 | /* Append the Message. */ | ||
1283 | { | ||
1284 | char buffer[BUFSIZ]; | ||
1285 | size_t nread = 0; | ||
1286 | stream_t is; | ||
1287 | message_get_stream (msg, &is); | ||
1288 | do | ||
1289 | { | ||
1290 | status = stream_read (is, buffer, sizeof (buffer), mud->off, | ||
1291 | &nread); | ||
1292 | if (status != 0) | ||
1293 | { | ||
1294 | if (status != EAGAIN) | ||
1295 | { | ||
1296 | free (mud->from); | ||
1297 | free (mud->date); | ||
1298 | mud->date = mud->from = NULL; | ||
1299 | mud->state = UNIX_NO_STATE; | ||
1300 | unix_unlock (mbox); | ||
1301 | } | ||
1302 | stream_flush (mbox->stream); | ||
1303 | return status; | ||
1304 | } | ||
1305 | stream_write (mbox->stream, buffer, nread, size, &n); | ||
1306 | mud->off += nread; | ||
1307 | size += n; | ||
1308 | } | ||
1309 | while (nread > 0); | ||
1310 | stream_write (mbox->stream, &nl, 1, size, &n); | ||
1311 | } | ||
1312 | |||
1313 | default: | ||
1314 | break; | ||
1315 | } | ||
1316 | } | ||
1317 | stream_flush (mbox->stream); | ||
1318 | mud->state = UNIX_NO_STATE; | ||
1319 | unix_unlock (mbox); | ||
1320 | return 0; | ||
1321 | } | ||
1322 | |||
1323 | static int | ||
1324 | unix_size (mailbox_t mbox, off_t *psize) | ||
1325 | { | ||
1326 | off_t size; | ||
1327 | int status; | ||
1328 | |||
1329 | if (mbox == NULL) | ||
1330 | return EINVAL; | ||
1331 | |||
1332 | /* Maybe was not open yet ?? */ | ||
1333 | status = stream_size (mbox->stream, &size); | ||
1334 | if (status != 0) | ||
1335 | return status; | ||
1336 | if (psize) | ||
1337 | *psize = size; | ||
1338 | return 0; | ||
1339 | } | ||
1340 | |||
1341 | static int | ||
1342 | unix_messages_count (mailbox_t mbox, size_t *pcount) | ||
1343 | { | ||
1344 | unix_data_t mud = mbox->data; | ||
1345 | if (mud == NULL) | ||
1346 | return EINVAL; | ||
1347 | |||
1348 | if (! unix_is_updated (mbox)) | ||
1349 | return unix_scan0 (mbox, 1, pcount, 1); | ||
1350 | |||
1351 | if (pcount) | ||
1352 | *pcount = mud->messages_count; | ||
1353 | |||
1354 | return 0; | ||
1355 | } | ||
1356 | |||
1357 | /* Locking. */ | ||
1358 | static int | ||
1359 | unix_lock (mailbox_t mbox, int flag) | ||
1360 | { | ||
1361 | if (mbox && mbox->locker != NULL) | ||
1362 | { | ||
1363 | locker_t locker = mbox->locker; | ||
1364 | locker_lock (locker, flag); | ||
1365 | } | ||
1366 | return 0; | ||
1367 | } | ||
1368 | |||
1369 | static int | ||
1370 | unix_touchlock (mailbox_t mbox) | ||
1371 | { | ||
1372 | if (mbox && mbox->locker != NULL) | ||
1373 | { | ||
1374 | locker_t locker = mbox->locker; | ||
1375 | locker_touchlock (locker); | ||
1376 | } | ||
1377 | return 0; | ||
1378 | } | ||
1379 | |||
1380 | static int | ||
1381 | unix_unlock (mailbox_t mbox) | ||
1382 | { | ||
1383 | if (mbox && mbox->locker != NULL) | ||
1384 | { | ||
1385 | locker_t locker = mbox->locker; | ||
1386 | locker_unlock (locker); | ||
1387 | } | ||
1388 | return 0; | ||
1389 | } | ||
1390 | |||
1391 | static int | ||
1392 | unix_ilock (mailbox_t mbox, int flag) | ||
1393 | { | ||
1394 | #ifdef HAVE_PTHREAD_H | ||
1395 | (void)flag; /* We should use rwlocks for more concurency. */ | ||
1396 | if (mbox == NULL) | ||
1397 | return EINVAL; | ||
1398 | return pthread_mutex_lock (&(mbox->mutex)); | ||
1399 | #else | ||
1400 | (void)mbox; (void)flag; | ||
1401 | return 0; | ||
1402 | #endif | ||
1403 | } | ||
1404 | |||
1405 | static int | ||
1406 | unix_iunlock (mailbox_t mbox) | ||
1407 | { | ||
1408 | #ifdef HAVE_PTHREAD_H | ||
1409 | if (mbox == NULL) | ||
1410 | return EINVAL; | ||
1411 | return pthread_mutex_unlock (&(mbox->mutex)); | ||
1412 | #else | ||
1413 | (void)mbox; | ||
1414 | return 0; | ||
1415 | #endif | ||
1416 | } |
mailbox/mbx_unixscan.c
deleted
100644 → 0
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 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 Library 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 Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library 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 | /* Credits to the c-client and its Authors | ||
19 | * The notorius c-client VALID() macro, was written by Mark Crispin. | ||
20 | */ | ||
21 | |||
22 | /* Parsing. | ||
23 | * The approach is to detect the "From " as start of a | ||
24 | * new message, give the position of the header and scan | ||
25 | * until "\n" then set header_end, set body position, | ||
26 | * scan until we it another "From " and set body_end. | ||
27 | * | ||
28 | ************************************ | ||
29 | * This is a classic case of premature optimisation | ||
30 | * being the root of all Evil(Donald E. Knuth). | ||
31 | * But I'm under "pressure" ;-) to come with | ||
32 | * something "faster". I think it's wastefull | ||
33 | * to spend time to gain a few seconds on 30Megs mailboxes | ||
34 | * ... but then again ... in computer time, 60 seconds, is eternity. | ||
35 | * | ||
36 | * If they use the event notification stuff | ||
37 | * to get some headers/messages early ... it's like pissing | ||
38 | * in the wind(sorry don't have the english equivalent). | ||
39 | * The worst is progress_bar it should be ... &*($^ nuke. | ||
40 | * For the events, we have to remove the *.LCK file, | ||
41 | * release the locks, flush the stream save the pointers | ||
42 | * etc ... hurry and wait... | ||
43 | * I this point I'm pretty much ranting. | ||
44 | * | ||
45 | */ | ||
46 | |||
47 | /* From the C-Client, part of pine */ | ||
48 | /* You are not expected to understand this macro, but read the next page if | ||
49 | * you are not faint of heart. | ||
50 | * | ||
51 | * Known formats to the VALID macro are: | ||
52 | * From user Wed Dec 2 05:53 1992 | ||
53 | * BSD From user Wed Dec 2 05:53:22 1992 | ||
54 | * SysV From user Wed Dec 2 05:53 PST 1992 | ||
55 | * rn From user Wed Dec 2 05:53:22 PST 1992 | ||
56 | * From user Wed Dec 2 05:53 -0700 1992 | ||
57 | * From user Wed Dec 2 05:53:22 -0700 1992 | ||
58 | * From user Wed Dec 2 05:53 1992 PST | ||
59 | * From user Wed Dec 2 05:53:22 1992 PST | ||
60 | * From user Wed Dec 2 05:53 1992 -0700 | ||
61 | * Solaris From user Wed Dec 2 05:53:22 1992 -0700 | ||
62 | * | ||
63 | * Plus all of the above with `` remote from xxx'' after it. Thank you very | ||
64 | * much, smail and Solaris, for making my life considerably more complicated. | ||
65 | */ | ||
66 | /* | ||
67 | * What? You want to understand the VALID macro anyway? Alright, since you | ||
68 | * insist. Actually, it isn't really all that difficult, provided that you | ||
69 | * take it step by step. | ||
70 | * | ||
71 | * Line 1 Initializes the return ti value to failure (0); | ||
72 | * Lines 2-3 Validates that the 1st-5th characters are ``From ''. | ||
73 | * Lines 4-6 Validates that there is an end of line and points x at it. | ||
74 | * Lines 7-14 First checks to see if the line is at least 41 characters long | ||
75 | . | ||
76 | * If so, it scans backwards to find the rightmost space. From | ||
77 | * that point, it scans backwards to see if the string matches | ||
78 | * `` remote from''. If so, it sets x to point to the space at | ||
79 | * the start of the string. | ||
80 | * Line 15 Makes sure that there are at least 27 characters in the line. | ||
81 | * Lines 16-21 Checks if the date/time ends with the year (there is a space | ||
82 | * five characters back). If there is a colon three characters | ||
83 | * further back, there is no timezone field, so zn is set to 0 | ||
84 | * and ti is set in front of the year. Otherwise, there must | ||
85 | * either to be a space four characters back for a three-letter | ||
86 | * timezone, or a space six characters back followed by a + or - | ||
87 | * for a numeric timezone; in either case, zn and ti become the | ||
88 | * offset of the space immediately before it. | ||
89 | * Lines 22-24 Are the failure case for line 14. If there is a space four | ||
90 | * characters back, it is a three-letter timezone; there must be | ||
91 | a | ||
92 | * space for the year nine characters back. zn is the zone | ||
93 | * offset; ti is the offset of the space. | ||
94 | * Lines 25-28 Are the failure case for line 20. If there is a space six | ||
95 | * characters back, it is a numeric timezone; there must be a | ||
96 | * space eleven characters back and a + or - five characters back | ||
97 | . | ||
98 | * zn is the zone offset; ti is the offset of the space. | ||
99 | * Line 29-32 If ti is valid, make sure that the string before ti is of the | ||
100 | * form www mmm dd hh:mm or www mmm dd hh:mm:ss, otherwise | ||
101 | * invalidate ti. There must be a colon three characters back | ||
102 | * and a space six or nine characters back (depending upon | ||
103 | * whether or not the character six characters back is a colon). | ||
104 | * There must be a space three characters further back (in front | ||
105 | * of the day), one seven characters back (in front of the month) | ||
106 | , | ||
107 | * and one eleven characters back (in front of the day of week). | ||
108 | * ti is set to be the offset of the space before the time. | ||
109 | * | ||
110 | * Why a macro? It gets invoked a *lot* in a tight loop. On some of the | ||
111 | * newer pipelined machines it is faster being open-coded than it would be if | ||
112 | * subroutines are called. | ||
113 | * | ||
114 | * Why does it scan backwards from the end of the line, instead of doing the | ||
115 | * much easier forward scan? There is no deterministic way to parse the | ||
116 | * ``user'' field, because it may contain unquoted spaces! Yes, I tested it t | ||
117 | o | ||
118 | * see if unquoted spaces were possible. They are, and I've encountered enoug | ||
119 | h | ||
120 | * evil mail to be totally unwilling to trust that ``it will never happen''. | ||
121 | */ | ||
122 | #define VALID(s,x,ti,zn) { \ | ||
123 | ti = 0; \ | ||
124 | if ((*s == 'F') && (s[1] == 'r') && (s[2] == 'o') && (s[3] == 'm') && \ | ||
125 | (s[4] == ' ')) { \ | ||
126 | for (x = s + 5; *x && *x != '\n'; x++); \ | ||
127 | if (x) { \ | ||
128 | if (x - s >= 41) { \ | ||
129 | for (zn = -1; x[zn] != ' '; zn--); \ | ||
130 | if ((x[zn-1] == 'm') && (x[zn-2] == 'o') && (x[zn-3] == 'r') && \ | ||
131 | (x[zn-4] == 'f') && (x[zn-5] == ' ') && (x[zn-6] == 'e') && \ | ||
132 | (x[zn-7] == 't') && (x[zn-8] == 'o') && (x[zn-9] == 'm') && \ | ||
133 | (x[zn-10] == 'e') && (x[zn-11] == 'r') && (x[zn-12] == ' '))\ | ||
134 | x += zn - 12; \ | ||
135 | } \ | ||
136 | if (x - s >= 27) { \ | ||
137 | if (x[-5] == ' ') { \ | ||
138 | if (x[-8] == ':') zn = 0,ti = -5; \ | ||
139 | else if (x[-9] == ' ') ti = zn = -9; \ | ||
140 | else if ((x[-11] == ' ') && ((x[-10]=='+') || (x[-10]=='-'))) \ | ||
141 | ti = zn = -11; \ | ||
142 | } \ | ||
143 | else if (x[-4] == ' ') { \ | ||
144 | if (x[-9] == ' ') zn = -4,ti = -9; \ | ||
145 | } \ | ||
146 | else if (x[-6] == ' ') { \ | ||
147 | if ((x[-11] == ' ') && ((x[-5] == '+') || (x[-5] == '-'))) \ | ||
148 | zn = -6,ti = -11; \ | ||
149 | } \ | ||
150 | if (ti && !((x[ti - 3] == ':') && \ | ||
151 | (x[ti -= ((x[ti - 6] == ':') ? 9 : 6)] == ' ') && \ | ||
152 | (x[ti - 3] == ' ') && (x[ti - 7] == ' ') && \ | ||
153 | (x[ti - 11] == ' '))) ti = 0; \ | ||
154 | } \ | ||
155 | } \ | ||
156 | } \ | ||
157 | } | ||
158 | |||
159 | #define STRLEN(s, i) \ | ||
160 | do \ | ||
161 | { \ | ||
162 | char *tmp = (s);\ | ||
163 | while (*tmp) tmp++; \ | ||
164 | i = tmp - s; \ | ||
165 | } while (0) | ||
166 | |||
167 | #define ATTRIBUTE_SET(buf,mum,c0,c1,type) \ | ||
168 | do \ | ||
169 | { \ | ||
170 | char *s; \ | ||
171 | for (s = (buf) + 7; *s; s++) \ | ||
172 | { \ | ||
173 | if (*s == c0 || *s == c1) \ | ||
174 | { \ | ||
175 | (mum)->old_flags |= (type); \ | ||
176 | break; \ | ||
177 | } \ | ||
178 | } \ | ||
179 | } while (0) | ||
180 | |||
181 | #define ISSTATUS(buf) (\ | ||
182 | (buf[0] == 'S' || buf[0] == 's') && \ | ||
183 | (buf[1] == 'T' || buf[1] == 't') && \ | ||
184 | (buf[2] == 'A' || buf[2] == 'a') && \ | ||
185 | (buf[3] == 'T' || buf[3] == 't') && \ | ||
186 | (buf[4] == 'U' || buf[4] == 'u') && \ | ||
187 | (buf[5] == 'S' || buf[5] == 's') && (buf[6] == ':')) | ||
188 | |||
189 | /* Notification. */ | ||
190 | #define MAILBOX_NOTIFICATION(mbox,which,bailing) \ | ||
191 | do \ | ||
192 | { \ | ||
193 | size_t i; \ | ||
194 | event_t event; \ | ||
195 | for (i = 0; i < (mbox)->event_num; i++) \ | ||
196 | { \ | ||
197 | event = &((mbox)->event[i]); \ | ||
198 | if ((event->_action) && (event->type & (which))) \ | ||
199 | bailing |= event->_action (which, event->arg); \ | ||
200 | } \ | ||
201 | } while (0) | ||
202 | |||
203 | /* Notifications ADD_MESG. */ | ||
204 | #define DISPATCH_ADD_MSG(mbox,mud) \ | ||
205 | do \ | ||
206 | { \ | ||
207 | int bailing = 0; \ | ||
208 | unix_iunlock (mbox); \ | ||
209 | MAILBOX_NOTIFICATION (mbox, MU_EVT_MBX_MSG_ADD, bailing); \ | ||
210 | if (bailing != 0) \ | ||
211 | { \ | ||
212 | if (pcount) \ | ||
213 | *pcount = (mud)->messages_count; \ | ||
214 | unix_unlock (mbox); \ | ||
215 | return EINTR; \ | ||
216 | } \ | ||
217 | unix_ilock (mbox, MU_LOCKER_WRLOCK); \ | ||
218 | } while (0); | ||
219 | |||
220 | /* Notification MBX_PROGRESS | ||
221 | We do not want to fire up the progress notification every line, it will be | ||
222 | too expensive, so we do it arbitrarely every 10 000 Lines. | ||
223 | FIXME: maybe this should be configurable. */ | ||
224 | /* This is more tricky we can not leave the mum struct incomplete. So we | ||
225 | only tell them about the complete messages. */ | ||
226 | #define DISPATCH_PROGRESS(mbox,mud) \ | ||
227 | do \ | ||
228 | { \ | ||
229 | { \ | ||
230 | int bailing = 0; \ | ||
231 | unix_iunlock (mbox); \ | ||
232 | mud->messages_count--; \ | ||
233 | MAILBOX_NOTIFICATION (mbox, MU_EVT_MBX_PROGRESS,bailing); \ | ||
234 | if (bailing != 0) \ | ||
235 | { \ | ||
236 | if (pcount) \ | ||
237 | *pcount = (mud)->messages_count; \ | ||
238 | unix_unlock (mbox); \ | ||
239 | return EINTR; \ | ||
240 | } \ | ||
241 | mud->messages_count++; \ | ||
242 | unix_ilock (mbox, MU_LOCKER_WRLOCK); \ | ||
243 | } \ | ||
244 | } while (0) | ||
245 | |||
246 | /* Allocate slots for the new messages. */ | ||
247 | /* size_t num = 2 * ((mud)->messages_count) + 10; */ | ||
248 | #define ALLOCATE_MSGS(mbox,mud) \ | ||
249 | do \ | ||
250 | { \ | ||
251 | if ((mud)->messages_count >= (mud)->umessages_count) \ | ||
252 | { \ | ||
253 | unix_message_t *m; \ | ||
254 | size_t num = ((mud)->umessages_count) + 1; \ | ||
255 | m = realloc ((mud)->umessages, num * sizeof (*m)); \ | ||
256 | if (m == NULL) \ | ||
257 | { \ | ||
258 | unix_iunlock (mbox); \ | ||
259 | unix_unlock (mbox); \ | ||
260 | return ENOMEM; \ | ||
261 | } \ | ||
262 | (mud)->umessages = m; \ | ||
263 | (mud)->umessages[num - 1] = calloc (1, sizeof (*(mum))); \ | ||
264 | if ((mud)->umessages[num - 1] == NULL) \ | ||
265 | { \ | ||
266 | unix_iunlock (mbox); \ | ||
267 | unix_unlock (mbox); \ | ||
268 | return ENOMEM; \ | ||
269 | } \ | ||
270 | (mud)->umessages_count = num; \ | ||
271 | } \ | ||
272 | } while (0) | ||
273 | |||
274 | static int | ||
275 | unix_scan0 (mailbox_t mbox, size_t msgno, size_t *pcount, int do_notif) | ||
276 | { | ||
277 | #define MSGLINELEN 1024 | ||
278 | char buf[MSGLINELEN]; | ||
279 | int inheader; | ||
280 | int inbody; | ||
281 | off_t total = 0; | ||
282 | unix_data_t mud = mbox->data; | ||
283 | unix_message_t mum = NULL; | ||
284 | int status = 0; | ||
285 | size_t lines; | ||
286 | int newline; | ||
287 | size_t n = 0; | ||
288 | |||
289 | int zn, isfrom = 0; | ||
290 | char *temp; | ||
291 | |||
292 | /* Sanity. */ | ||
293 | if (mud == NULL) | ||
294 | return EINVAL; | ||
295 | |||
296 | /* Save the timestamp and size. */ | ||
297 | status = stream_size (mbox->stream, &(mud->size)); | ||
298 | if (status != 0) | ||
299 | return status; | ||
300 | |||
301 | /* Grab the locks. */ | ||
302 | unix_ilock (mbox, MU_LOCKER_WRLOCK); | ||
303 | unix_lock (mbox, MU_LOCKER_RDLOCK); | ||
304 | |||
305 | /* Seek to the starting point. */ | ||
306 | if (mud->umessages && msgno > 0 && mud->messages_count > 0 | ||
307 | && msgno <= mud->messages_count) | ||
308 | { | ||
309 | mum = mud->umessages[msgno - 1]; | ||
310 | if (mum) | ||
311 | total = mum->header_from; | ||
312 | mud->messages_count = msgno - 1; | ||
313 | } | ||
314 | else | ||
315 | mud->messages_count = 0; | ||
316 | |||
317 | newline = 1; | ||
318 | errno = lines = inheader = inbody = 0; | ||
319 | |||
320 | while ((status = stream_readline (mbox->stream, buf, sizeof (buf), | ||
321 | total, &n)) == 0 && n != 0) | ||
322 | { | ||
323 | int nl; | ||
324 | total += n; | ||
325 | |||
326 | nl = (*buf == '\n') ? 1 : 0; | ||
327 | VALID(buf, temp, isfrom, zn); | ||
328 | isfrom = (isfrom) ? 1 : 0; | ||
329 | |||
330 | /* Which part of the message are we in ? */ | ||
331 | inheader = isfrom | ((!nl) & inheader); | ||
332 | inbody = (!isfrom) & (!inheader); | ||
333 | |||
334 | lines++; | ||
335 | |||
336 | if (inheader) | ||
337 | { | ||
338 | /* New message. */ | ||
339 | if (isfrom) | ||
340 | { | ||
341 | /* Signal the end of the body. */ | ||
342 | if (mum && !mum->body_end) | ||
343 | { | ||
344 | mum->body_end = total - n - newline; | ||
345 | mum->body_lines = --lines - newline; | ||
346 | if (do_notif) | ||
347 | DISPATCH_ADD_MSG(mbox, mud); | ||
348 | } | ||
349 | /* Allocate_msgs will initialize mum. */ | ||
350 | ALLOCATE_MSGS(mbox, mud); | ||
351 | mud->messages_count++; | ||
352 | mum = mud->umessages[mud->messages_count - 1]; | ||
353 | mum->stream = mbox->stream; | ||
354 | mum->header_from = total - n; | ||
355 | mum->header_from_end = total; | ||
356 | lines = 0; | ||
357 | } | ||
358 | else if ((n > 7) && ISSTATUS(buf)) | ||
359 | { | ||
360 | mum->header_status = total - n; | ||
361 | mum->header_status_end = total; | ||
362 | ATTRIBUTE_SET(buf, mum, 'r', 'R', MU_ATTRIBUTE_READ); | ||
363 | ATTRIBUTE_SET(buf, mum, 'o', 'O', MU_ATTRIBUTE_SEEN); | ||
364 | ATTRIBUTE_SET(buf, mum, 'a', 'A', MU_ATTRIBUTE_ANSWERED); | ||
365 | ATTRIBUTE_SET(buf, mum, 'd', 'D', MU_ATTRIBUTE_DELETED); | ||
366 | } | ||
367 | } | ||
368 | |||
369 | /* Body. */ | ||
370 | if (inbody) | ||
371 | { | ||
372 | /* Set the body position. */ | ||
373 | if (mum && !mum->body) | ||
374 | { | ||
375 | mum->body = total - n + nl; | ||
376 | mum->header_lines = lines; | ||
377 | lines = 0; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | newline = nl; | ||
382 | |||
383 | /* Every 50 mesgs update the lock, it should be every minute. */ | ||
384 | if ((mud->messages_count % 50) == 0) | ||
385 | unix_touchlock (mbox); | ||
386 | |||
387 | /* Ping them every 1000 lines. */ | ||
388 | if (do_notif) | ||
389 | if (((lines +1) % 1000) == 0) | ||
390 | DISPATCH_PROGRESS(mbox, mud); | ||
391 | |||
392 | } /* while */ | ||
393 | |||
394 | if (mum) | ||
395 | { | ||
396 | mum->body_end = total - newline; | ||
397 | mum->body_lines = lines - newline; | ||
398 | if (do_notif) | ||
399 | DISPATCH_ADD_MSG(mbox, mud); | ||
400 | } | ||
401 | unix_iunlock (mbox); | ||
402 | unix_unlock (mbox); | ||
403 | if (pcount) | ||
404 | *pcount = mud->messages_count; | ||
405 | return status; | ||
406 | } |
mailbox/url_imap.c
deleted
100644 → 0
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 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 Library 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 Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library 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 | #include <url0.h> | ||
19 | #include <mailutils/registrar.h> | ||
20 | #include <errno.h> | ||
21 | |||
22 | static int url_imap_create (url_t *purl, const char *name); | ||
23 | static void url_imap_destroy (url_t *purl); | ||
24 | |||
25 | struct url_registrar _url_imap_registrar = | ||
26 | { | ||
27 | "imap://", | ||
28 | url_imap_create, url_imap_destroy | ||
29 | }; | ||
30 | |||
31 | static void | ||
32 | url_imap_destroy (url_t *purl) | ||
33 | { | ||
34 | (void)purl; | ||
35 | return; | ||
36 | } | ||
37 | |||
38 | static int | ||
39 | url_imap_create (url_t *purl, const char *name) | ||
40 | { | ||
41 | (void)purl; (void)name; | ||
42 | return ENOSYS; | ||
43 | } |
mailbox/url_mail.c
deleted
100644 → 0
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 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 Library 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 Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library 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 | #include <url0.h> | ||
19 | #include <mailutils/registrar.h> | ||
20 | #include <errno.h> | ||
21 | |||
22 | static int url_mailto_create (url_t *purl, const char *name); | ||
23 | static void url_mailto_destroy (url_t *purl); | ||
24 | |||
25 | struct url_registrar _url_mailto_registrar = | ||
26 | { | ||
27 | "mailto:", | ||
28 | url_mailto_create, url_mailto_destroy | ||
29 | }; | ||
30 | |||
31 | static void | ||
32 | url_mailto_destroy (url_t *purl) | ||
33 | { | ||
34 | (void)purl; | ||
35 | return; | ||
36 | } | ||
37 | |||
38 | static int | ||
39 | url_mailto_create (url_t *purl, const char *name) | ||
40 | { | ||
41 | (void)purl; (void)name; | ||
42 | return ENOSYS; | ||
43 | } |
mailbox/url_mdir.c
deleted
100644 → 0
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 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 Library 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 Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library 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 | #include <url0.h> | ||
19 | #include <mailutils/registrar.h> | ||
20 | |||
21 | #include <errno.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <string.h> | ||
24 | |||
25 | static void url_maildir_destroy (url_t *purl); | ||
26 | static int url_maildir_create (url_t *purl, const char *name); | ||
27 | |||
28 | struct url_registrar _url_maildir_registrar = | ||
29 | { | ||
30 | "maildir:", | ||
31 | url_maildir_create, url_maildir_destroy | ||
32 | }; | ||
33 | |||
34 | static void | ||
35 | url_maildir_destroy (url_t *purl) | ||
36 | { | ||
37 | if (purl && *purl) | ||
38 | { | ||
39 | url_t url = *purl; | ||
40 | free (url->scheme); | ||
41 | free (url->path); | ||
42 | free (url); | ||
43 | *purl = NULL; | ||
44 | } | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | MAILDIR URL | ||
49 | maildir: | ||
50 | */ | ||
51 | static int | ||
52 | url_maildir_create (url_t *purl, const char *name) | ||
53 | { | ||
54 | url_t url; | ||
55 | struct url_registrar *ureg = &_url_maildir_registrar; | ||
56 | size_t len, scheme_len = strlen (ureg->scheme); | ||
57 | |||
58 | /* reject the obvious */ | ||
59 | if (name == NULL || strncmp (ureg->scheme, name, scheme_len) != 0 | ||
60 | || (len = strlen (name)) < (scheme_len + 1) /* (scheme)+1(path)*/) | ||
61 | return EINVAL; | ||
62 | |||
63 | /* do I need to decode url encoding '% hex hex' ? */ | ||
64 | |||
65 | url = calloc(1, sizeof (*url)); | ||
66 | if (url == NULL) | ||
67 | return EINVAL; | ||
68 | |||
69 | /* TYPE */ | ||
70 | url->_create = ureg->_create; | ||
71 | url->_destroy = ureg->_destroy; | ||
72 | |||
73 | /* SCHEME */ | ||
74 | url->scheme = strdup (ureg->scheme); | ||
75 | if (url->scheme == NULL) | ||
76 | { | ||
77 | ureg->_destroy (&url); | ||
78 | return ENOMEM; | ||
79 | } | ||
80 | |||
81 | /* PATH */ | ||
82 | name += scheme_len; /* pass the scheme */ | ||
83 | url->path = strdup (name); | ||
84 | if (url->path == NULL) | ||
85 | { | ||
86 | ureg->_destroy (&url); | ||
87 | return ENOMEM; | ||
88 | } | ||
89 | |||
90 | *purl = url; | ||
91 | return 0; | ||
92 | } |
mailbox/url_mh.c
deleted
100644 → 0
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 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 Library 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 Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library 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 | #include <url0.h> | ||
19 | #include <mailutils/registrar.h> | ||
20 | |||
21 | #include <errno.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <string.h> | ||
24 | |||
25 | static void url_mh_destroy (url_t *purl); | ||
26 | static int url_mh_create (url_t *purl, const char *name); | ||
27 | |||
28 | struct url_registrar _url_mh_registrar = | ||
29 | { | ||
30 | "mh:", | ||
31 | url_mh_create, url_mh_destroy | ||
32 | }; | ||
33 | |||
34 | static void | ||
35 | url_mh_destroy (url_t *purl) | ||
36 | { | ||
37 | if (purl && *purl) | ||
38 | { | ||
39 | url_t url = *purl; | ||
40 | free (url->scheme); | ||
41 | free (url->path); | ||
42 | free (url); | ||
43 | *purl = NULL; | ||
44 | } | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | MH URL | ||
49 | mh: | ||
50 | */ | ||
51 | static int | ||
52 | url_mh_create (url_t *purl, const char *name) | ||
53 | { | ||
54 | url_t url; | ||
55 | struct url_registrar *ureg = &_url_mh_registrar; | ||
56 | size_t len, scheme_len = strlen (ureg->scheme); | ||
57 | |||
58 | /* reject the obvious */ | ||
59 | if (name == NULL || strncmp (ureg->scheme, name, scheme_len) != 0 | ||
60 | || (len = strlen (name)) < (scheme_len + 1) /* (scheme)+1(path)*/) | ||
61 | return EINVAL; | ||
62 | |||
63 | /* do I need to decode url encoding '% hex hex' ? */ | ||
64 | |||
65 | url = calloc(1, sizeof (*url)); | ||
66 | if (url == NULL) | ||
67 | return ENOMEM; | ||
68 | |||
69 | /* TYPE */ | ||
70 | url->_create = ureg->_create; | ||
71 | url->_destroy = ureg->_destroy; | ||
72 | |||
73 | /* SCHEME */ | ||
74 | url->scheme = strdup (ureg->scheme); | ||
75 | if (url->scheme == NULL) | ||
76 | { | ||
77 | ureg->_destroy (&url); | ||
78 | return ENOMEM; | ||
79 | } | ||
80 | |||
81 | /* PATH */ | ||
82 | name += scheme_len; /* pass the scheme */ | ||
83 | url->path = strdup (name); | ||
84 | if (url->path == NULL) | ||
85 | { | ||
86 | ureg->_destroy (&url); | ||
87 | return ENOMEM; | ||
88 | } | ||
89 | |||
90 | *purl = url; | ||
91 | return 0; | ||
92 | } |
mailbox/url_mmdf.c
deleted
100644 → 0
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 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 Library 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 Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library 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 | #include <url0.h> | ||
19 | #include <mailutils/registrar.h> | ||
20 | |||
21 | #include <errno.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <string.h> | ||
24 | |||
25 | static void url_mmdf_destroy (url_t *purl); | ||
26 | static int url_mmdf_create (url_t *purl, const char *name); | ||
27 | |||
28 | struct url_registrar _url_mmdf_registrar = | ||
29 | { | ||
30 | "mmdf:", | ||
31 | url_mmdf_create, url_mmdf_destroy | ||
32 | }; | ||
33 | |||
34 | static void | ||
35 | url_mmdf_destroy (url_t *purl) | ||
36 | { | ||
37 | if (purl && *purl) | ||
38 | { | ||
39 | url_t url = *purl; | ||
40 | free (url->scheme); | ||
41 | free (url->path); | ||
42 | free (url); | ||
43 | *purl = NULL; | ||
44 | } | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | MMDF URL | ||
49 | mmdf: | ||
50 | */ | ||
51 | static int | ||
52 | url_mmdf_create (url_t *purl, const char *name) | ||
53 | { | ||
54 | url_t url; | ||
55 | struct url_registrar *ureg = &_url_mmdf_registrar; | ||
56 | size_t len, scheme_len = strlen (ureg->scheme); | ||
57 | |||
58 | /* reject the obvious */ | ||
59 | if (name == NULL || strncmp (ureg->scheme, name, scheme_len) != 0 | ||
60 | || (len = strlen (name)) < 8 /* 7(scheme)+1(path)*/) | ||
61 | return EINVAL; | ||
62 | |||
63 | /* do I need to decode url encoding '% hex hex' ? */ | ||
64 | |||
65 | url = calloc(1, sizeof (*url)); | ||
66 | if (url == NULL) | ||
67 | return ENOMEM; | ||
68 | |||
69 | /* TYPE */ | ||
70 | url->_create = ureg->_create; | ||
71 | url->_destroy = ureg->_destroy; | ||
72 | |||
73 | /* SCHEME */ | ||
74 | url->scheme = strdup (ureg->scheme); | ||
75 | if (url->scheme == NULL) | ||
76 | { | ||
77 | ureg->_destroy (&url); | ||
78 | return ENOMEM; | ||
79 | } | ||
80 | |||
81 | /* PATH */ | ||
82 | name += scheme_len; /* pass the scheme */ | ||
83 | url->path = strdup (name); | ||
84 | if (url->path == NULL) | ||
85 | { | ||
86 | ureg->_destroy (&url); | ||
87 | return ENOMEM; | ||
88 | } | ||
89 | |||
90 | *purl = url; | ||
91 | return 0; | ||
92 | } |
mailbox/url_unix.c
deleted
100644 → 0
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 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 Library 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 Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library 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 | #include <url0.h> | ||
19 | #include <mailutils/registrar.h> | ||
20 | |||
21 | #include <errno.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <string.h> | ||
24 | |||
25 | static void url_unix_destroy (url_t *purl); | ||
26 | static int url_unix_create (url_t *purl, const char *name); | ||
27 | |||
28 | struct url_registrar _url_unix_registrar = | ||
29 | { | ||
30 | "unix:", | ||
31 | url_unix_create, url_unix_destroy | ||
32 | }; | ||
33 | |||
34 | static void | ||
35 | url_unix_destroy (url_t *purl) | ||
36 | { | ||
37 | if (purl && *purl) | ||
38 | { | ||
39 | url_t url = *purl; | ||
40 | free (url->scheme); | ||
41 | free (url->path); | ||
42 | free (url); | ||
43 | *purl = NULL; | ||
44 | } | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | UNIX Mbox | ||
49 | unix:/path | ||
50 | */ | ||
51 | static int | ||
52 | url_unix_create (url_t *purl, const char *name) | ||
53 | { | ||
54 | url_t url; | ||
55 | struct url_registrar *ureg = &_url_unix_registrar; | ||
56 | size_t len, scheme_len = strlen (ureg->scheme); | ||
57 | |||
58 | /* reject the obvious */ | ||
59 | if (name == NULL || strncmp (ureg->scheme, name, scheme_len) != 0 | ||
60 | || (len = strlen (name)) < scheme_len + 1 /* 7(scheme)+1(path)*/) | ||
61 | return EINVAL; | ||
62 | |||
63 | /* do I need to decode url encoding '% hex hex' ? */ | ||
64 | |||
65 | url = calloc(1, sizeof (*url)); | ||
66 | if (url == NULL) | ||
67 | return ENOMEM; | ||
68 | |||
69 | /* TYPE */ | ||
70 | url->_create = ureg->_create; | ||
71 | url->_destroy = ureg->_destroy; | ||
72 | |||
73 | /* SCHEME */ | ||
74 | url->scheme = strdup (ureg->scheme); | ||
75 | if (url->scheme == NULL) | ||
76 | { | ||
77 | ureg->_destroy (&url); | ||
78 | return ENOMEM; | ||
79 | } | ||
80 | |||
81 | /* PATH */ | ||
82 | name += scheme_len; /* pass the scheme */ | ||
83 | url->path = strdup (name); | ||
84 | if (url->path == NULL) | ||
85 | { | ||
86 | ureg->_destroy (&url); | ||
87 | return ENOMEM; | ||
88 | } | ||
89 | |||
90 | *purl = url; | ||
91 | return 0; | ||
92 | } |
-
Please register or sign in to post a comment