Commit acae1d25 acae1d257c398950d72b5ad692f489538f1c7fea by Jeff Bailey

Initial revision

0 parents
1 Jakob Kaivo <jkaivo@ndn.net>
1 1999-09-11 Jeff Bailey <jbailey@cr499794-a.crdva1.bc.wave.home.com>
2
3 * libmailbox/unixmbox.h: Do not prefix config.h defines with _
4
5 1999-09-10 Jeff Bailey <jbailey@cr499794-a.crdva1.bc.wave.home.com>
6
7 * */*: Accomidate directory rearrange
8
1 AUTOMAKE_OPTIONS = gnu 1.4
2
3 SUBDIRS = libmailbox mail
File mode changed
File mode changed
1 dnl Process this file with autoconf to procude a configure script. -*-m4-*-
2 AC_INIT(libmailbox/mailbox.c)
3 AM_INIT_AUTOMAKE(libmailbox, 0.0.19990909)
4 AM_CONFIG_HEADER(config.h)
5 AM_MAINTAINER_MODE
6
7 AC_PROG_CC
8 AC_PROG_INSTALL
9 AC_PROG_LN_S
10 AC_PROG_LIBTOOL
11
12 AC_ARG_ENABLE(-mailbox-install,
13 [ --enable-mailbox-install install libmailbox])
14
15 AM_CONDITIONAL(INSTALL_MAILBOX, test x"${enable_mailbox_install-no}" != xno)
16
17 AC_HEADER_STDC
18 AC_CHECK_HEADERS(malloc.h stdlib.h stdio.h errno.h unistd.h)
19 AC_CHECK_HEADERS(string.h strings.h, break)
20
21 AC_OUTPUT(Makefile libmailbox/Makefile mail/Makefile)
1 # Use automake to process this file -*-Makefile-*-
2
3 if INSTALL_MAILBOX
4 include_HEADERS = mailbox.h
5 lib_LTLIBRARIES = libmailbox.la
6 else
7 noinst_HEADERS = mailbox.h
8 noinst_LTLIBRARIES = libmailbox.la
9 endif
10
11 libmailbox_la_SOURCES = mailbox.c unixmbox.c unixmbox.h
12 libmailbox_la_LDFLAGS = -version-info 0:0:0
13
1 /* copyright and license info go here */
2
3 #include "mailbox.h"
4 #include "unixmbox.h"
5
6 #ifdef _HAVE_ERRNO_H
7 #include <errno.h>
8 #endif
9
10 int _mbox_dummy1 (mailbox * mbox);
11 int _mbox_dummy2 (mailbox * mbox, int num);
12 int _mbox_dummy3 (mailbox * mbox, char *c);
13 char *_mbox_dummy4 (mailbox * mbox, int num);
14
15 mailbox *
16 mbox_open (char *name)
17 {
18 mailbox *mbox = malloc (sizeof (mailbox));
19 if (mbox == NULL)
20 {
21 errno = ENOMEM;
22 return NULL;
23 }
24
25 /* Set up with default data and dummy functions */
26 mbox->name = strdup (name);
27 if (mbox->name == NULL)
28 {
29 errno = ENOMEM;
30 free (mbox);
31 return NULL;
32 }
33 mbox->messages = 0;
34 mbox->num_deleted = 0;
35 mbox->sizes = NULL;
36 mbox->_data = NULL;
37 mbox->_close = _mbox_dummy1;
38 mbox->_delete = _mbox_dummy2;
39 mbox->_undelete = _mbox_dummy2;
40 mbox->_expunge = _mbox_dummy1;
41 mbox->_add_message = _mbox_dummy3;
42 mbox->_is_deleted = _mbox_dummy2;
43 mbox->_get_body = _mbox_dummy4;
44 mbox->_get_header = _mbox_dummy4;
45
46 if (unixmbox_open (mbox) == 0)
47 return mbox;
48 else
49 {
50 /*
51 * Check errno to find out why it failed, if it's simply not a
52 * unix mbox format message, then try other mailbox types,
53 * otherwise, leave errno set and return NULL
54 */
55 }
56
57 /* for example...
58 if (maildir_open (mbox, name) == 1)
59 return mbox;
60 else if (errno != 0)
61 return NULL;
62 else
63 errno = 0;
64 */
65
66 errno = ENOSYS;
67 return NULL;
68 }
69
70 /*
71 * Bogus functions for unimplemented functions that return int
72 */
73 int
74 _mbox_dummy1 (mailbox * mbox)
75 {
76 errno = ENOSYS;
77 return -1;
78 }
79
80 int
81 _mbox_dummy2 (mailbox * mbox, int num)
82 {
83 return _mbox_dummy1 (mbox);
84 }
85 int
86 _mbox_dummy3 (mailbox * mbox, char *c)
87 {
88 return _mbox_dummy1 (mbox);
89 }
90
91 /*
92 * Bogus function for unimplemented functions that return char *
93 */
94 char *
95 _mbox_dummy4 (mailbox * mbox, int num)
96 {
97 errno = ENOSYS;
98 return NULL;
99 }
1 /* copyright and license info go here */
2
3 #ifndef _MAILBOX_H
4 #define _MAILBOX_H 1
5
6 #ifndef __P
7 #if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)
8 #define __P(args) args
9 #else
10 #define __P(args) ()
11 #endif
12 #endif /*!__P */
13
14 /* These need to be documented */
15 #define mbox_close(m) m->_close(m)
16 #define mbox_delete(m,n) m->_delete(m,n)
17 #define mbox_undelete(m,n) m->_undelete(m,n)
18 #define mbox_expunge(m) m->_expunge(m)
19 #define mbox_is_deleted(m,n) m->_is_deleted(m,n)
20 #define mbox_add_message(m,s) m->_add_message(m,s)
21 #define mbox_get_body(m,n) m->_get_body(m,n)
22 #define mbox_get_header(m,n) m->_get_header(m,n)
23
24 typedef struct _mailbox
25 {
26 /* Data */
27 char *name;
28 int messages;
29 int num_deleted;
30 int *sizes;
31 void *_data;
32
33 /* Functions */
34 int (*_close) __P ((struct _mailbox *));
35 int (*_delete) __P ((struct _mailbox *, int));
36 int (*_undelete) __P ((struct _mailbox *, int));
37 int (*_expunge) __P ((struct _mailbox *));
38 int (*_add_message) __P ((struct _mailbox *, char *));
39 int (*_is_deleted) __P ((struct _mailbox *, int));
40 char *(*_get_body) __P ((struct _mailbox *, int));
41 char *(*_get_header) __P ((struct _mailbox *, int));
42 }
43 mailbox;
44
45 mailbox *mbox_open __P ((char *name));
46
47 #endif
1 /* copyright and license info go here */
2
3 #include "unixmbox.h"
4
5 /*
6 * Opens and locks a mailbox
7 */
8 int
9 unixmbox_open (mailbox * mbox)
10 {
11 char buf[80];
12 unsigned int max_count = 10;
13 int mess = 0;
14 unixmbox_data *data = malloc (sizeof (unixmbox_data));
15
16 if (data == NULL)
17 {
18 errno = ENOMEM;
19 free (data);
20 return -1;
21 }
22
23 mbox->_data = data;
24 data->file = fopen (mbox->name, "r+");
25 /* FIXME: do a good, NFS safe, file lock here, with error handling */
26 if (data->file == NULL)
27 {
28 /* errno is set by fopen() */
29 free (data);
30 return -1;
31 }
32
33 data->messages = malloc (sizeof (unixmbox_message) * max_count);
34 mbox->sizes = malloc (sizeof (int) * max_count);
35 if (data->messages == NULL || mbox->sizes == NULL)
36 {
37 unixmbox_close (mbox);
38 errno = ENOMEM;
39 return -1;
40 }
41
42 while (fgets (buf, 80, data->file))
43 {
44 if (!strncmp (buf, "From ", 5))
45 {
46 /* Beginning of a header */
47 while (strchr (buf, '\n') == NULL)
48 fgets (buf, 80, data->file);
49
50 mbox->messages++;
51
52 if (mbox->messages > max_count)
53 {
54 max_count = mbox->messages * 2;
55 data->messages = realloc (data->messages,
56 max_count * sizeof (unixmbox_message));
57 mbox->sizes = realloc (mbox->sizes, max_count * sizeof (int));
58 if (data->messages == NULL || mbox->sizes == NULL)
59 {
60 unixmbox_close (mbox);
61 errno = ENOMEM;
62 return -1;
63 }
64 }
65
66 fgetpos (data->file, &(data->messages[mbox->messages - 1].header));
67 mbox->sizes[mbox->messages - 1] = 0;
68 data->messages[mbox->messages - 1].deleted = 0;
69 mess = 0;
70 }
71 else if (((!strncmp (buf, "\r\n", 2) || strlen (buf) <= 1)) && mess == 0)
72 {
73 /* Beginning of a body */
74 fgetpos (data->file, &(data->messages[mbox->messages - 1].body));
75 mbox->sizes[mbox->messages - 1] += strlen (buf) + 1;
76 mess = 1;
77 }
78 else
79 {
80 mbox->sizes[mbox->messages - 1] += strlen (buf) + 1;
81 fgetpos (data->file, &(data->messages[mbox->messages - 1].end));
82 }
83 }
84
85 mbox->_close = unixmbox_close;
86 mbox->_delete = unixmbox_delete;
87 mbox->_undelete = unixmbox_undelete;
88 mbox->_expunge = unixmbox_expunge;
89 mbox->_add_message = unixmbox_add_message;
90 mbox->_is_deleted = unixmbox_is_deleted;
91 mbox->_get_body = unixmbox_get_body;
92 mbox->_get_header = unixmbox_get_header;
93
94 return 0;
95 }
96
97 /*
98 * Closes and unlocks a mailbox, does not expunge
99 */
100 int
101 unixmbox_close (mailbox * mbox)
102 {
103 unixmbox_data *data = mbox->_data;
104 /* FIXME: good file unlocking, to go along with the locking above */
105 fclose (data->file);
106 free (data->messages);
107 free (mbox->sizes);
108 free (data);
109 free (mbox);
110 return 0;
111 }
112
113 /*
114 * Marks a message for deletion
115 */
116 int
117 unixmbox_delete (mailbox * mbox, int num)
118 {
119 unixmbox_data *data = mbox->_data;
120 if (num > mbox->messages || mbox_is_deleted (mbox, num))
121 {
122 errno = ERANGE;
123 return -1;
124 }
125 else
126 {
127 data->messages[num].deleted = 1;
128 mbox->num_deleted++;
129 }
130 return 0;
131 }
132
133 /*
134 * Unmark a message for deletion
135 */
136 int
137 unixmbox_undelete (mailbox * mbox, int num)
138 {
139 unixmbox_data *data = mbox->_data;
140 if (num > mbox->messages || !mbox_is_deleted (mbox, num))
141 {
142 errno = ERANGE;
143 return -1;
144 }
145 else
146 {
147 data->messages[num].deleted = 0;
148 mbox->num_deleted--;
149 }
150 return 0;
151 }
152
153 /*
154 * Updates a mailbox to remove message marked for deletion
155 * FIXME: BROKEN! DOES NOT WORK! BLOWS UP REAL GOOD!
156 */
157 int
158 unixmbox_expunge (mailbox * mbox)
159 {
160 unixmbox_data *data = mbox->_data;
161 int i = 0, size = 0;
162 char *buf;
163 fpos_t lastpos;
164
165 data->file = freopen (mbox->name, "r+", data->file);
166 if (data->file == NULL)
167 {
168 /* error handling */
169 }
170 fgetpos (data->file, &lastpos);
171
172 for (i = 0; i < mbox->messages; i++)
173 {
174 if (data->messages[i].deleted == 0)
175 {
176 fgetpos (data->file, &lastpos);
177 fsetpos (data->file, &(data->messages[i].header));
178 read (fileno (data->file), buf,
179 data->messages[i + 1].header - data->messages[i].header);
180 fprintf (data->file, "%s", buf);
181 size += strlen (buf);
182 free (buf);
183 }
184 }
185 ftruncate (fileno (data->file), size);
186 return 0;
187 }
188
189 /*
190 * Determines whether or a not a message is marked for deletion
191 */
192 int
193 unixmbox_is_deleted (mailbox * mbox, int num)
194 {
195 unixmbox_data *data = mbox->_data;
196 return (data->messages[num].deleted == 1);
197 }
198
199 /*
200 * Adds a message to the mailbox
201 */
202 int
203 unixmbox_add_message (mailbox * mbox, char *message)
204 {
205 /*
206 * FIXME: please write me
207 * move to end of file and write text, don't forget to update
208 * mbox->messages and mbox->_data->messages
209 */
210 errno = ENOSYS;
211 return -1;
212 }
213
214 /*
215 * Returns a message body
216 */
217 char *
218 unixmbox_get_body (mailbox * mbox, int num)
219 {
220 unixmbox_data *data = mbox->_data;
221 int size = data->messages[num].end - data->messages[num].body;
222 char *buf = malloc ((1 + size) * sizeof (char));
223 if (buf == NULL)
224 {
225 errno = ENOMEM;
226 free (buf);
227 return NULL;
228 }
229 else if (num > mbox->messages || num < 0)
230 {
231 errno = ERANGE;
232 free (buf);
233 return NULL;
234 }
235
236 memset (buf, 0, size + 1);
237 fsetpos (data->file, &(data->messages[num].body));
238 fread (buf, size, sizeof (char), data->file);
239 return buf;
240 }
241
242 /*
243 * Returns just the header of a message
244 */
245 char *
246 unixmbox_get_header (mailbox * mbox, int num)
247 {
248 unixmbox_data *data = mbox->_data;
249 int size = (data->messages[num].body - 1) - data->messages[num].header ;
250 char *buf = malloc ((1 + size) * sizeof (char));
251 if (buf == NULL)
252 {
253 errno = ENOMEM;
254 free (buf);
255 return NULL;
256 }
257 else if (num > mbox->messages || num < 0)
258 {
259 errno = ERANGE;
260 free (buf);
261 return NULL;
262 }
263
264 memset (buf, 0, size + 1);
265 fsetpos (data->file, &(data->messages[num].header));
266 fread (buf, size, sizeof (char), data->file);
267 return buf;
268 }
1 /* copyright and license info go here */
2
3 #ifndef _UNIXMBOX_H
4 #define _UNIXMBOX_H 1
5 #include <mailbox.h>
6 #include "config.h"
7
8 #ifdef HAVE_STDIO_H
9 #include <stdio.h>
10 #endif
11
12 #ifdef HAVE_STDLIB_H
13 #include <stdlib.h>
14 #endif
15
16 #ifdef HAVE_UNISTD_H
17 #include <unistd.h>
18 #endif
19
20 #ifdef HAVE_ERRNO_H
21 #include <errno.h>
22 #endif
23
24 #ifdef HAVE_STRING_H
25 #include <string.h>
26 #elif HAVE_STRINGS_H
27 #include <strings.h>
28 #endif
29
30 typedef struct _unixmbox_message
31 {
32 off_t header;
33 off_t body;
34 off_t end;
35 short deleted;
36 }
37 unixmbox_message;
38
39 typedef struct _unixmbox_data
40 {
41 unixmbox_message *messages;
42 FILE *file;
43 }
44 unixmbox_data;
45
46 int unixmbox_open (mailbox *mbox);
47 int unixmbox_close (mailbox *mbox);
48 int unixmbox_delete (mailbox *mbox, int num);
49 int unixmbox_undelete (mailbox *mbox, int num);
50 int unixmbox_expunge (mailbox *mbox);
51 int unixmbox_is_deleted (mailbox *mbox, int num);
52 int unixmbox_add_message (mailbox *mbox, char *message);
53 char *unixmbox_get_body (mailbox *mbox, int num);
54 char *unixmbox_get_header (mailbox *mbox, int num);
55
56 #endif
1 CPPFLAGS = -I$(top_srcdir)/libmailbox
2
3 bin_PROGRAMS = mail
4
5 mail_LDADD = ../libmailbox/libmailbox.la
1 /* copyright and license info go here */
2
3 #include <mailbox.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6
7 #ifdef HAVE_PATHS_H
8 #include <paths.h>
9 #endif
10
11 #ifndef _PATH_MAILDIR
12 #define _PATH_MAILDIR "/var/spool/mail"
13 #endif
14
15 int
16 main (int argc, char **argv)
17 {
18 char *foo, bar[80];
19 int i = 0;
20 char c = 0;
21 char *mboxname;
22 mailbox *mbox;
23
24 if (argc != 1)
25 {
26 fprintf (stderr, "Usage: %s\n", argv[0]);
27 return 1;
28 }
29
30 mboxname = getenv ("MAIL");
31 if (mboxname == NULL)
32 {
33 foo = getenv ("LOGNAME");
34 mboxname = malloc ((strlen(foo) + strlen(_PATH_MAILDIR) + 2) * sizeof(char));
35 strcpy (mboxname, _PATH_MAILDIR "/");
36 strcat (mboxname, foo);
37 free (foo);
38 }
39
40 mbox = mbox_open (mboxname);
41 printf ("Number of messages: %d\n", mbox->messages);
42 while (1)
43 {
44 printf ("& ");
45 fflush (stdout);
46 fgets (bar, 80, stdin);
47 c = bar[0];
48 if (c == 'd' || c == 'D' || c == 'b' || c == 'B' || c == 'h' ||
49 c == 'H' || c == 'r' || c == 'R')
50 {
51 printf ("# ");
52 fgets (bar, 80, stdin);
53 }
54 switch (c)
55 {
56 case 'q':
57 case 'Q':
58 mbox_close (mbox);
59 return 0;
60 break;
61 case 'r':
62 case 'R':
63 foo = mbox_get_header (mbox, atoi (bar) - 1);
64 printf ("%s\n", foo);
65 free (foo);
66 foo = mbox_get_body (mbox, atoi (bar) - 1);
67 printf ("%s", foo);
68 free (foo);
69 break;
70 case 'h':
71 case 'H':
72 foo = mbox_get_header (mbox, atoi (bar) - 1);
73 printf ("%s", foo);
74 free (foo);
75 break;
76 case 'b':
77 case 'B':
78 foo = mbox_get_body (mbox, atoi (bar) - 1);
79 printf ("%s", foo);
80 free (foo);
81 break;
82 case 'd':
83 case 'D':
84 mbox_delete (mbox, atoi (bar) - 1);
85 break;
86 case 'x':
87 case 'X':
88 mbox_expunge (mbox);
89 break;
90 default:
91 break;
92 }
93 }
94 }