Commit efe54c6d efe54c6d45fc25459febc395e57588eb46580bee by Alain Magloire

Finally took time to put the code in from Jakob first draft, in

an email excerpt:
states is the valid states for a command (eg. LOGIN is only valid in
non-authenticated state, SELECT is valid in authenticated or
selected). success is the state to enter when the command completes
successfully (STATE_NONE means no change) and failure is the state to
enter when the command fails.

The fetch code is getting close to completion! ye!
1 parent a912fe08
1 2001-04-18 Alain Magloire
2
3 Finally took time to put the code in from Jakob first draft, in
4 an email excerpt:
5 states is the valid states for a command (eg. LOGIN is only valid in
6 non-authenticated state, SELECT is valid in authenticated or
7 selected). success is the state to enter when the command completes
8 successfully (STATE_NONE means no change) and failure is the state to
9 enter when the command fails.
10
11 * imap4d/*.c: All the commands check there state.
12 * imap4d/fetch.c: Cleanup the fetch code, and broke
13 the fetch_operation() routine in multiple routines.
14 (fetch_message): New function.
15 (fetch_header): Likewised
16 (fetch_content): Likewised
17 (fetch_io): Likewised
18 (fetch_header_fields): Likewised
19 (fetch_header_fields_not): Likewised
20 (fetch_send_address): Likewised
21
22 * mailbox/header.c: Some functions were usefull while
23 programming the imap server, put them here.
24 (header_aget_value): New function.
25 (header_aget_field_name): New function.
26 (header_aget_field_value): New function.
27
28 * mailbox/memory_stream.c: New file, implemented a
29 malloc() buffer that you can access via the stream interface.
30 * mailbox/file_stream.c: Remove spurious checks.
31 * mailbox/mapfile_stream.c: Remove spurious checks.
32 (_mapfile_read): check if there is no newline left.
33
1 2001-04-16 Alain Magloire 34 2001-04-16 Alain Magloire
2 35
3 To get things to compile on Solaris, change configure to check 36 To get things to compile on Solaris, change configure to check
......
...@@ -72,16 +72,20 @@ MIME-Version ...@@ -72,16 +72,20 @@ MIME-Version
72 72
73 @end deftypefun 73 @end deftypefun
74 74
75 @deftypefun int header_get_value (header_t @var{hdr}, const char *fn, char *fv, size_t len, size_t *n) 75 @deftypefun int header_get_value (header_t @var{hdr}, const char *@var{fn}, char *@var{fv}, size_t @var{len}, size_t *@var{n})
76 Value of field-name @var{fn} is returned in buffer @var{fv} of size @var{len}. 76 Value of field-name @var{fn} is returned in buffer @var{fv} of size @var{len}.
77 The number of bytes written is put in @var{n}. 77 The number of bytes written is put in @var{n}.
78 @end deftypefun 78 @end deftypefun
79 79
80 @deftypefun int header_aget_value (header_t @var{hdr}, const char *@var{fn}, char **@var{fv})
81 The value is allocated.
82 @end deftypefun
83
80 @deftypefun int header_get_stream (header_t @var{hdr}, stream_t *@var{pstream}) 84 @deftypefun int header_get_stream (header_t @var{hdr}, stream_t *@var{pstream})
81 @end deftypefun 85 @end deftypefun
82 86
83 @deftypefun int header_size (header_t @var{hdr}, size_t *@var{size}) 87 @deftypefun int header_set_size (header_t @var{hdr}, size_t *@var{size})
84 @end deftypefun 88 @end deftypefun
85 89
86 @deftypefun int header_lines (header_t @var{hdr}, size_t *@var{lpines}) 90 @deftypefun int header_set_lines (header_t @var{hdr}, size_t *@var{lpines})
87 @end deftypefun 91 @end deftypefun
......
...@@ -24,5 +24,7 @@ ...@@ -24,5 +24,7 @@
24 int 24 int
25 imap4d_append (struct imap4d_command *command, char *arg) 25 imap4d_append (struct imap4d_command *command, char *arg)
26 { 26 {
27 if (! (command->states & state))
28 return util_finish (command, RESP_BAD, "Wrong state");
27 return util_finish (command, RESP_NO, "Not implemented"); 29 return util_finish (command, RESP_NO, "Not implemented");
28 } 30 }
......
...@@ -24,5 +24,7 @@ ...@@ -24,5 +24,7 @@
24 int 24 int
25 imap4d_authenticate (struct imap4d_command *command, char *arg) 25 imap4d_authenticate (struct imap4d_command *command, char *arg)
26 { 26 {
27 if (! (command->states & state))
28 return util_finish (command, RESP_BAD, "Wrong state");
27 return util_finish (command, RESP_NO, "Command not supported"); 29 return util_finish (command, RESP_NO, "Command not supported");
28 } 30 }
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
20 int 20 int
21 imap4d_capability (struct imap4d_command *command, char *arg) 21 imap4d_capability (struct imap4d_command *command, char *arg)
22 { 22 {
23 if (! (command->states & state))
24 return util_finish (command, RESP_BAD, "Wrong state");
23 util_out (RESP_NONE, "CAPABILITY IMAP4rev1"); 25 util_out (RESP_NONE, "CAPABILITY IMAP4rev1");
24 return util_finish (command, RESP_OK, "Completed"); 26 return util_finish (command, RESP_OK, "Completed");
25 } 27 }
......
...@@ -26,5 +26,7 @@ ...@@ -26,5 +26,7 @@
26 int 26 int
27 imap4d_check (struct imap4d_command *command, char *arg) 27 imap4d_check (struct imap4d_command *command, char *arg)
28 { 28 {
29 if (! (command->states & state))
30 return util_finish (command, RESP_BAD, "Wrong state");
29 return util_finish (command, RESP_OK, "Completed"); 31 return util_finish (command, RESP_OK, "Completed");
30 } 32 }
......
...@@ -25,14 +25,11 @@ imap4d_close (struct imap4d_command *command, char *arg) ...@@ -25,14 +25,11 @@ imap4d_close (struct imap4d_command *command, char *arg)
25 { 25 {
26 /* FIXME: Check args. */ 26 /* FIXME: Check args. */
27 /* FIXME: Check state and if they selected. */ 27 /* FIXME: Check state and if they selected. */
28 /* FIXME: state = AUTHENTICATE. */ 28 if (! (command->states & state))
29 29 return util_finish (command, RESP_BAD, "Wrong state");
30 /* FIXME: Check and report errors. */ 30 /* FIXME: Check and report errors. */
31 mailbox_expunge (mbox); 31 mailbox_expunge (mbox);
32 mailbox_close (mbox); 32 mailbox_close (mbox);
33 mailbox_destroy (&mbox); 33 mailbox_destroy (&mbox);
34
35 /* FIXME: state = Not selected. */
36
37 return util_finish (command, RESP_OK, "Completed"); 34 return util_finish (command, RESP_OK, "Completed");
38 } 35 }
......
...@@ -19,29 +19,29 @@ ...@@ -19,29 +19,29 @@
19 19
20 struct imap4d_command imap4d_command_table [] = 20 struct imap4d_command imap4d_command_table [] =
21 { 21 {
22 { "CAPABILITY", imap4d_capability, STATE_ALL, STATE_NONE, STATE_NONE }, 22 { "CAPABILITY", imap4d_capability, STATE_ALL, STATE_NONE, STATE_NONE, NULL },
23 { "NOOP", imap4d_noop, STATE_ALL, STATE_NONE, STATE_NONE }, 23 { "NOOP", imap4d_noop, STATE_ALL, STATE_NONE, STATE_NONE, NULL },
24 { "LOGOUT", imap4d_logout, STATE_ALL, STATE_LOGOUT, STATE_NONE }, 24 { "LOGOUT", imap4d_logout, STATE_ALL, STATE_LOGOUT, STATE_NONE, NULL },
25 { "AUTHENTICATE", imap4d_authenticate, STATE_NONAUTH, STATE_NONE, STATE_AUTH }, 25 { "AUTHENTICATE", imap4d_authenticate, STATE_NONAUTH, STATE_NONE, STATE_AUTH, NULL },
26 { "LOGIN", imap4d_login, STATE_NONAUTH, STATE_NONE, STATE_AUTH }, 26 { "LOGIN", imap4d_login, STATE_NONAUTH, STATE_NONE, STATE_AUTH, NULL },
27 { "SELECT", imap4d_select, STATE_AUTH | STATE_SEL, STATE_AUTH, STATE_SEL }, 27 { "SELECT", imap4d_select, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_SEL, NULL },
28 { "EXAMINE", imap4d_examine, STATE_AUTH | STATE_SEL, STATE_AUTH, STATE_SEL }, 28 { "EXAMINE", imap4d_examine, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_SEL, NULL },
29 { "CREATE", imap4d_create, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, 29 { "CREATE", imap4d_create, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL },
30 { "DELETE", imap4d_delete, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, 30 { "DELETE", imap4d_delete, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL },
31 { "RENAME", imap4d_rename, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, 31 { "RENAME", imap4d_rename, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL },
32 { "SUBSCRIBE", imap4d_subscribe, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, 32 { "SUBSCRIBE", imap4d_subscribe, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL },
33 { "UNSUBSCRIBE", imap4d_unsubscribe, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, 33 { "UNSUBSCRIBE", imap4d_unsubscribe, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL },
34 { "LIST", imap4d_list, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, 34 { "LIST", imap4d_list, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL },
35 { "LSUB", imap4d_lsub, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, 35 { "LSUB", imap4d_lsub, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL },
36 { "STATUS", imap4d_status, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, 36 { "STATUS", imap4d_status, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL },
37 { "APPEND", imap4d_append, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE }, 37 { "APPEND", imap4d_append, STATE_AUTH | STATE_SEL, STATE_NONE, STATE_NONE, NULL },
38 { "CHECK", imap4d_check, STATE_SEL, STATE_NONE, STATE_NONE }, 38 { "CHECK", imap4d_check, STATE_SEL, STATE_NONE, STATE_NONE, NULL },
39 { "CLOSE", imap4d_close, STATE_SEL, STATE_AUTH, STATE_AUTH }, 39 { "CLOSE", imap4d_close, STATE_SEL, STATE_AUTH, STATE_AUTH, NULL },
40 { "EXPUNGE", imap4d_expunge, STATE_SEL, STATE_NONE, STATE_NONE }, 40 { "EXPUNGE", imap4d_expunge, STATE_SEL, STATE_NONE, STATE_NONE, NULL },
41 { "SEARCH", imap4d_search, STATE_SEL, STATE_NONE, STATE_NONE }, 41 { "SEARCH", imap4d_search, STATE_SEL, STATE_NONE, STATE_NONE, NULL },
42 { "FETCH", imap4d_fetch, STATE_SEL, STATE_NONE, STATE_NONE }, 42 { "FETCH", imap4d_fetch, STATE_SEL, STATE_NONE, STATE_NONE, NULL },
43 { "STORE", imap4d_store, STATE_SEL, STATE_NONE, STATE_NONE }, 43 { "STORE", imap4d_store, STATE_SEL, STATE_NONE, STATE_NONE, NULL },
44 { "COPY", imap4d_copy, STATE_SEL, STATE_NONE, STATE_NONE }, 44 { "COPY", imap4d_copy, STATE_SEL, STATE_NONE, STATE_NONE, NULL },
45 { "UID", imap4d_uid, STATE_SEL, STATE_NONE, STATE_NONE }, 45 { "UID", imap4d_uid, STATE_SEL, STATE_NONE, STATE_NONE, NULL },
46 { 0, 0, 0} 46 { NULL, 0, 0, 0, 0, NULL }
47 }; 47 };
......
...@@ -24,5 +24,7 @@ ...@@ -24,5 +24,7 @@
24 int 24 int
25 imap4d_copy (struct imap4d_command *command, char *arg) 25 imap4d_copy (struct imap4d_command *command, char *arg)
26 { 26 {
27 if (! (command->states & state))
28 return util_finish (command, RESP_BAD, "Wrong state");
27 return util_finish (command, RESP_NO, "Command not supported"); 29 return util_finish (command, RESP_NO, "Command not supported");
28 } 30 }
......
...@@ -24,5 +24,7 @@ ...@@ -24,5 +24,7 @@
24 int 24 int
25 imap4d_create (struct imap4d_command *command, char *arg) 25 imap4d_create (struct imap4d_command *command, char *arg)
26 { 26 {
27 if (! (command->states & state))
28 return util_finish (command, RESP_BAD, "Wrong state");
27 return util_finish (command, RESP_NO, "Command not supported"); 29 return util_finish (command, RESP_NO, "Command not supported");
28 } 30 }
......
...@@ -24,5 +24,7 @@ ...@@ -24,5 +24,7 @@
24 int 24 int
25 imap4d_delete (struct imap4d_command *command, char *arg) 25 imap4d_delete (struct imap4d_command *command, char *arg)
26 { 26 {
27 if (! (command->states & state))
28 return util_finish (command, RESP_BAD, "Wrong state");
27 return util_finish (command, RESP_NO, "Command not supported");; 29 return util_finish (command, RESP_NO, "Command not supported");;
28 } 30 }
......
...@@ -24,5 +24,7 @@ ...@@ -24,5 +24,7 @@
24 int 24 int
25 imap4d_examine (struct imap4d_command *command, char *arg) 25 imap4d_examine (struct imap4d_command *command, char *arg)
26 { 26 {
27 if (! (command->states & state))
28 return util_finish (command, RESP_BAD, "Wrong state");
27 return imap4d_select0 (command, arg, MU_STREAM_READ); 29 return imap4d_select0 (command, arg, MU_STREAM_READ);
28 } 30 }
......
...@@ -25,11 +25,12 @@ int ...@@ -25,11 +25,12 @@ int
25 imap4d_expunge (struct imap4d_command *command, char *arg) 25 imap4d_expunge (struct imap4d_command *command, char *arg)
26 { 26 {
27 char *sp = NULL; 27 char *sp = NULL;
28 28 if (! (command->states & state))
29 return util_finish (command, RESP_BAD, "Wrong state");
29 if (util_getword (arg, &sp)) 30 if (util_getword (arg, &sp))
30 return util_finish (command, RESP_NO, "Too many args"); 31 return util_finish (command, RESP_NO, "Too many args");
31 32
32 /* FIXME: Check state, check for errors. */ 33 /* FIXME: check for errors. */
33 mailbox_expunge (mbox); 34 mailbox_expunge (mbox);
34 return util_finish (command, RESP_OK, "Completed"); 35 return util_finish (command, RESP_OK, "Completed");
35 } 36 }
......
...@@ -21,6 +21,7 @@ int *ifile; ...@@ -21,6 +21,7 @@ int *ifile;
21 FILE *ofile; 21 FILE *ofile;
22 unsigned int timeout = 1800; /* RFC2060: 30 minutes, if enable. */ 22 unsigned int timeout = 1800; /* RFC2060: 30 minutes, if enable. */
23 mailbox_t mbox; 23 mailbox_t mbox;
24 int state = STATE_NONAUTH;
24 25
25 static int imap4_mainloop __P ((int, int)); 26 static int imap4_mainloop __P ((int, int));
26 27
......
...@@ -62,6 +62,8 @@ ...@@ -62,6 +62,8 @@
62 #include <mailutils/body.h> 62 #include <mailutils/body.h>
63 #include <mailutils/address.h> 63 #include <mailutils/address.h>
64 #include <mailutils/registrar.h> 64 #include <mailutils/registrar.h>
65 #include <mailutils/filter.h>
66 #include <mailutils/stream.h>
65 67
66 #ifdef __cplusplus 68 #ifdef __cplusplus
67 extern "C" { 69 extern "C" {
...@@ -80,17 +82,17 @@ struct imap4d_command ...@@ -80,17 +82,17 @@ struct imap4d_command
80 const char *name; 82 const char *name;
81 int (*func) __P ((struct imap4d_command *, char *)); 83 int (*func) __P ((struct imap4d_command *, char *));
82 int states; 84 int states;
83 int success;
84 int failure; 85 int failure;
86 int success;
85 char *tag; 87 char *tag;
86 }; 88 };
87 89
88 /* Global variables and constants*/ 90 /* Global variables and constants*/
89 #define STATE_NONE (1 << 0) 91 #define STATE_NONE (0)
90 #define STATE_NONAUTH (1 << 1) 92 #define STATE_NONAUTH (1 << 0)
91 #define STATE_AUTH (1 << 2) 93 #define STATE_AUTH (1 << 1)
92 #define STATE_SEL (1 << 3) 94 #define STATE_SEL (1 << 2)
93 #define STATE_LOGOUT (1 << 4) 95 #define STATE_LOGOUT (1 << 3)
94 96
95 #define STATE_ALL (STATE_NONE | STATE_NONAUTH | STATE_AUTH | STATE_SEL \ 97 #define STATE_ALL (STATE_NONE | STATE_NONAUTH | STATE_AUTH | STATE_SEL \
96 | STATE_LOGOUT) 98 | STATE_LOGOUT)
...@@ -105,7 +107,7 @@ extern struct imap4d_command imap4d_command_table[]; ...@@ -105,7 +107,7 @@ extern struct imap4d_command imap4d_command_table[];
105 extern FILE *ofile; 107 extern FILE *ofile;
106 extern unsigned int timeout; 108 extern unsigned int timeout;
107 extern mailbox_t mbox; 109 extern mailbox_t mbox;
108 extern unsigned int state; 110 extern int state;
109 111
110 /* Imap4 commands */ 112 /* Imap4 commands */
111 int imap4d_capability __P ((struct imap4d_command *, char *)); 113 int imap4d_capability __P ((struct imap4d_command *, char *));
......
...@@ -24,5 +24,7 @@ ...@@ -24,5 +24,7 @@
24 int 24 int
25 imap4d_list (struct imap4d_command *command, char *arg) 25 imap4d_list (struct imap4d_command *command, char *arg)
26 { 26 {
27 if (! (command->states & state))
28 return util_finish (command, RESP_BAD, "Wrong state");
27 return util_finish (command, RESP_NO, "Not supported"); 29 return util_finish (command, RESP_NO, "Not supported");
28 } 30 }
......
...@@ -86,6 +86,8 @@ imap4d_login (struct imap4d_command *command, char *arg) ...@@ -86,6 +86,8 @@ imap4d_login (struct imap4d_command *command, char *arg)
86 int pamerror; 86 int pamerror;
87 #endif /* !USE_LIBPAM */ 87 #endif /* !USE_LIBPAM */
88 88
89 if (! (command->states & state))
90 return util_finish (command, RESP_BAD, "Wrong state");
89 username = util_getword (arg, &sp); 91 username = util_getword (arg, &sp);
90 pass = util_getword (NULL, &sp); 92 pass = util_getword (NULL, &sp);
91 93
......
...@@ -25,6 +25,8 @@ int ...@@ -25,6 +25,8 @@ int
25 imap4d_logout (struct imap4d_command *command, char *arg) 25 imap4d_logout (struct imap4d_command *command, char *arg)
26 { 26 {
27 char *sp = NULL; 27 char *sp = NULL;
28 if (! (command->states & state))
29 return util_finish (command, RESP_BAD, "Wrong state");
28 if (util_getword (arg, &sp)) 30 if (util_getword (arg, &sp))
29 return util_finish (command, RESP_BAD, "Too many args"); 31 return util_finish (command, RESP_BAD, "Too many args");
30 util_out (RESP_BYE, "Logging out"); 32 util_out (RESP_BYE, "Logging out");
......
...@@ -24,5 +24,7 @@ ...@@ -24,5 +24,7 @@
24 int 24 int
25 imap4d_lsub (struct imap4d_command *command, char *arg) 25 imap4d_lsub (struct imap4d_command *command, char *arg)
26 { 26 {
27 if (! (command->states & state))
28 return util_finish (command, RESP_BAD, "Wrong state");
27 return util_finish (command, RESP_NO, "Not supported"); 29 return util_finish (command, RESP_NO, "Not supported");
28 } 30 }
......
...@@ -22,6 +22,8 @@ int ...@@ -22,6 +22,8 @@ int
22 imap4d_noop (struct imap4d_command *command, char *arg) 22 imap4d_noop (struct imap4d_command *command, char *arg)
23 { 23 {
24 char *sp = NULL; 24 char *sp = NULL;
25 if (! (command->states & state))
26 return util_finish (command, RESP_BAD, "Wrong state");
25 if (util_getword (arg, &sp)) 27 if (util_getword (arg, &sp))
26 return util_finish (command, RESP_BAD, "Too many args"); 28 return util_finish (command, RESP_BAD, "Too many args");
27 return util_finish (command, RESP_OK, "Completed"); 29 return util_finish (command, RESP_OK, "Completed");
......
...@@ -24,5 +24,7 @@ ...@@ -24,5 +24,7 @@
24 int 24 int
25 imap4d_rename (struct imap4d_command *command, char *arg) 25 imap4d_rename (struct imap4d_command *command, char *arg)
26 { 26 {
27 if (! (command->states & state))
28 return util_finish (command, RESP_BAD, "Wrong state");
27 return util_finish (command, RESP_NO, "Not Supported"); 29 return util_finish (command, RESP_NO, "Not Supported");
28 } 30 }
......
...@@ -26,5 +26,7 @@ ...@@ -26,5 +26,7 @@
26 int 26 int
27 imap4d_search (struct imap4d_command *command, char *arg) 27 imap4d_search (struct imap4d_command *command, char *arg)
28 { 28 {
29 if (! (command->states & state))
30 return util_finish (command, RESP_BAD, "Wrong state");
29 return util_finish (command, RESP_NO, "Not supported"); 31 return util_finish (command, RESP_NO, "Not supported");
30 } 32 }
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
22 int 22 int
23 imap4d_select (struct imap4d_command *command, char *arg) 23 imap4d_select (struct imap4d_command *command, char *arg)
24 { 24 {
25 if (! (command->states & state))
26 return util_finish (command, RESP_BAD, "Wrong state");
25 return imap4d_select0 (command, arg, MU_STREAM_RDWR); 27 return imap4d_select0 (command, arg, MU_STREAM_RDWR);
26 } 28 }
27 29
...@@ -61,6 +63,7 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags) ...@@ -61,6 +63,7 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags)
61 unsigned long uidvalidity = 0; 63 unsigned long uidvalidity = 0;
62 size_t count = 0, recent = 0, unseen = 0, uidnext = 0; 64 size_t count = 0, recent = 0, unseen = 0, uidnext = 0;
63 65
66 state = STATE_SEL;
64 mailbox_uidvalidity (mbox, &uidvalidity); 67 mailbox_uidvalidity (mbox, &uidvalidity);
65 mailbox_uidnext (mbox, &uidnext); 68 mailbox_uidnext (mbox, &uidnext);
66 mailbox_messages_count (mbox, &count); 69 mailbox_messages_count (mbox, &count);
......
...@@ -27,6 +27,8 @@ imap4d_status (struct imap4d_command *command, char *arg) ...@@ -27,6 +27,8 @@ imap4d_status (struct imap4d_command *command, char *arg)
27 char *sp = NULL; 27 char *sp = NULL;
28 char *mailbox_name; 28 char *mailbox_name;
29 char *data; 29 char *data;
30 if (! (command->states & state))
31 return util_finish (command, RESP_BAD, "Wrong state");
30 mailbox_name = util_getword (arg, &sp); 32 mailbox_name = util_getword (arg, &sp);
31 data = util_getword (NULL, &sp); 33 data = util_getword (NULL, &sp);
32 if (!mailbox_name || !data) 34 if (!mailbox_name || !data)
......
...@@ -24,5 +24,7 @@ ...@@ -24,5 +24,7 @@
24 int 24 int
25 imap4d_store (struct imap4d_command *command, char *arg) 25 imap4d_store (struct imap4d_command *command, char *arg)
26 { 26 {
27 if (! (command->states & state))
28 return util_finish (command, RESP_BAD, "Wrong state");
27 return util_finish (command, RESP_NO, "Not supported"); 29 return util_finish (command, RESP_NO, "Not supported");
28 } 30 }
......
...@@ -24,5 +24,7 @@ ...@@ -24,5 +24,7 @@
24 int 24 int
25 imap4d_subscribe (struct imap4d_command *command, char *arg) 25 imap4d_subscribe (struct imap4d_command *command, char *arg)
26 { 26 {
27 if (! (command->states & state))
28 return util_finish (command, RESP_BAD, "Wrong state");
27 return util_finish (command, RESP_NO, "Not supported"); 29 return util_finish (command, RESP_NO, "Not supported");
28 } 30 }
......
...@@ -25,5 +25,7 @@ ...@@ -25,5 +25,7 @@
25 int 25 int
26 imap4d_uid (struct imap4d_command *command, char *arg) 26 imap4d_uid (struct imap4d_command *command, char *arg)
27 { 27 {
28 if (! (command->states & state))
29 return util_finish (command, RESP_BAD, "Wrong state");
28 return util_finish (command, RESP_NO, "Not supported"); 30 return util_finish (command, RESP_NO, "Not supported");
29 } 31 }
......
...@@ -24,5 +24,7 @@ ...@@ -24,5 +24,7 @@
24 int 24 int
25 imap4d_unsubscribe (struct imap4d_command *command, char *arg) 25 imap4d_unsubscribe (struct imap4d_command *command, char *arg)
26 { 26 {
27 if (! (command->states & state))
28 return util_finish (command, RESP_BAD, "Wrong state");
27 return util_finish (command, RESP_NO, "Not supported"); 29 return util_finish (command, RESP_NO, "Not supported");
28 } 30 }
......
...@@ -207,6 +207,7 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...) ...@@ -207,6 +207,7 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...)
207 { 207 {
208 char *buf = NULL; 208 char *buf = NULL;
209 const char *resp; 209 const char *resp;
210 int new_state;
210 va_list ap; 211 va_list ap;
211 212
212 va_start (ap, format); 213 va_start (ap, format);
...@@ -216,6 +217,9 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...) ...@@ -216,6 +217,9 @@ util_finish (struct imap4d_command *command, int rc, const char *format, ...)
216 resp = sc2string (rc); 217 resp = sc2string (rc);
217 fprintf (ofile, "%s %s%s %s\r\n", command->tag, resp, command->name, buf); 218 fprintf (ofile, "%s %s%s %s\r\n", command->tag, resp, command->name, buf);
218 free (buf); 219 free (buf);
220 new_state = (rc == RESP_OK) ? command->success : command->failure;
221 if (new_state != STATE_NONE)
222 state = new_state;
219 return 0; 223 return 0;
220 } 224 }
221 225
......
...@@ -74,56 +74,70 @@ extern "C" { ...@@ -74,56 +74,70 @@ extern "C" {
74 struct _header; 74 struct _header;
75 typedef struct _header * header_t; 75 typedef struct _header * header_t;
76 76
77 extern int header_create __P ((header_t *, const char *, 77 extern int header_create __P ((header_t *, const char *,
78 size_t, void *)); 78 size_t, void *));
79 extern void header_destroy __P ((header_t *, void *)); 79 extern void header_destroy __P ((header_t *, void *));
80 extern void *header_get_owner __P ((header_t)); 80 extern void *header_get_owner __P ((header_t));
81 81
82 extern int header_is_modified __P ((header_t)); 82 extern int header_is_modified __P ((header_t));
83 extern int header_clear_modified __P ((header_t)); 83 extern int header_clear_modified __P ((header_t));
84 84
85 extern int header_get_property __P ((header_t, property_t *)); 85 extern int header_get_property __P ((header_t, property_t *));
86 extern int header_set_property __P ((header_t, property_t, void *)); 86 extern int header_set_property __P ((header_t, property_t, void *));
87 87
88 extern int header_set_value __P ((header_t, const char *, 88 extern int header_set_value __P ((header_t, const char *,
89 const char *, int)); 89 const char *, int));
90 extern int header_set_set_value __P ((header_t, int (*_set_value) 90 extern int header_set_set_value __P ((header_t,
91 __P ((header_t, const char *, 91 int (*_set_value) __P ((header_t,
92 const char *, int)), void *)); 92 const char *,
93 93 const char *,
94 extern int header_get_value __P ((header_t, const char *, char *, 94 int)),
95 size_t, size_t *)); 95 void *));
96 extern int header_set_get_value __P ((header_t, int (*_get_value) 96
97 __P ((header_t, const char *, char *, 97 extern int header_get_value __P ((header_t, const char *, char *,
98 size_t, size_t *)), void *)); 98 size_t, size_t *));
99 extern int header_set_get_fvalue __P ((header_t, int (*_get_value) 99 extern int header_aget_value __P ((header_t, const char *, char **));
100 __P ((header_t, const char *, char *, 100 extern int header_set_get_value __P ((header_t,
101 size_t, size_t *)), void *)); 101 int (*_get_value) __P ((header_t,
102 102 const char *,
103 extern int header_get_field_count __P ((header_t, size_t *)); 103 char *,
104 extern int header_get_field_value __P ((header_t, size_t, char *, 104 size_t,
105 size_t, size_t *)); 105 size_t *)),
106 extern int header_get_field_name __P ((header_t, size_t, char *, 106 void *));
107 size_t, size_t *)); 107 extern int header_set_get_fvalue __P ((header_t,
108 108 int (*_get_value) __P ((header_t,
109 extern int header_get_stream __P ((header_t, stream_t *)); 109 const char *,
110 extern int header_set_stream __P ((header_t, stream_t, void *)); 110 char *,
111 111 size_t,
112 extern int header_size __P ((header_t, size_t *)); 112 size_t *)),
113 extern int header_set_size __P ((header_t, int (*_size) 113 void *));
114 __P ((header_t, size_t *)), void *)); 114
115 115 extern int header_get_field_count __P ((header_t, size_t *));
116 extern int header_lines __P ((header_t, size_t *)); 116 extern int header_get_field_value __P ((header_t, size_t, char *,
117 extern int header_set_lines __P ((header_t, 117 size_t, size_t *));
118 int (*_lines) __P ((header_t, 118 extern int header_aget_field_value __P ((header_t, size_t, char **));
119 size_t *)), 119 extern int header_get_field_name __P ((header_t, size_t, char *,
120 void *)); 120 size_t, size_t *));
121 121 extern int header_aget_field_name __P ((header_t, size_t, char **));
122 extern int header_set_fill __P ((header_t, 122
123 int (*_fill) __P ((header_t, char *, 123 extern int header_get_stream __P ((header_t, stream_t *));
124 size_t, off_t, 124 extern int header_set_stream __P ((header_t, stream_t, void *));
125
126 extern int header_size __P ((header_t, size_t *));
127 extern int header_set_size __P ((header_t, int (*_size)
128 __P ((header_t, size_t *)), void *));
129
130 extern int header_lines __P ((header_t, size_t *));
131 extern int header_set_lines __P ((header_t,
132 int (*_lines) __P ((header_t,
133 size_t *)),
134 void *));
135
136 extern int header_set_fill __P ((header_t,
137 int (*_fill) __P ((header_t, char *,
138 size_t, off_t,
125 size_t *)), 139 size_t *)),
126 void *owner)); 140 void *owner));
127 #ifdef __cplusplus 141 #ifdef __cplusplus
128 } 142 }
129 #endif 143 #endif
......
...@@ -119,11 +119,12 @@ extern int stream_get_state __P ((stream_t, int *pstate)); ...@@ -119,11 +119,12 @@ extern int stream_get_state __P ((stream_t, int *pstate));
119 /* Misc. */ 119 /* Misc. */
120 extern int file_stream_create __P ((stream_t *stream)); 120 extern int file_stream_create __P ((stream_t *stream));
121 extern int mapfile_stream_create __P ((stream_t *stream)); 121 extern int mapfile_stream_create __P ((stream_t *stream));
122 extern int memory_stream_create __P ((stream_t *stream));
123 extern int tcp_stream_create __P ((stream_t *stream));
122 extern int encoder_stream_create __P ((stream_t *stream, stream_t iostream, 124 extern int encoder_stream_create __P ((stream_t *stream, stream_t iostream,
123 const char *encoding)); 125 const char *encoding));
124 extern int decoder_stream_create __P ((stream_t *stream, stream_t iostream, 126 extern int decoder_stream_create __P ((stream_t *stream, stream_t iostream,
125 const char *encoding)); 127 const char *encoding));
126 extern int tcp_stream_create __P ((stream_t *stream));
127 128
128 #ifdef __cplusplus 129 #ifdef __cplusplus
129 } 130 }
......
...@@ -41,6 +41,7 @@ mbx_imap.c \ ...@@ -41,6 +41,7 @@ mbx_imap.c \
41 mbx_mbox.c \ 41 mbx_mbox.c \
42 mbx_pop.c \ 42 mbx_pop.c \
43 message.c \ 43 message.c \
44 memory_stream.c \
44 mime.c \ 45 mime.c \
45 misc.c \ 46 misc.c \
46 monitor.c \ 47 monitor.c \
......
...@@ -41,8 +41,7 @@ static void ...@@ -41,8 +41,7 @@ static void
41 _file_destroy (stream_t stream) 41 _file_destroy (stream_t stream)
42 { 42 {
43 struct _file_stream *fs = stream_get_owner (stream); 43 struct _file_stream *fs = stream_get_owner (stream);
44 44 if (fs->file)
45 if (fs && fs->file)
46 fclose (fs->file); 45 fclose (fs->file);
47 free (fs); 46 free (fs);
48 } 47 }
...@@ -55,9 +54,6 @@ _file_read (stream_t stream, char *optr, size_t osize, ...@@ -55,9 +54,6 @@ _file_read (stream_t stream, char *optr, size_t osize,
55 size_t n; 54 size_t n;
56 int err = 0; 55 int err = 0;
57 56
58 if (fs == NULL)
59 return EINVAL;
60
61 if (fs->offset != offset) 57 if (fs->offset != offset)
62 { 58 {
63 if (fseek (fs->file, offset, SEEK_SET) != 0) 59 if (fseek (fs->file, offset, SEEK_SET) != 0)
...@@ -87,9 +83,6 @@ _file_readline (stream_t stream, char *optr, size_t osize, ...@@ -87,9 +83,6 @@ _file_readline (stream_t stream, char *optr, size_t osize,
87 size_t n = 0; 83 size_t n = 0;
88 int err = 0; 84 int err = 0;
89 85
90 if (fs == NULL)
91 return EINVAL;
92
93 if (fs->offset != offset) 86 if (fs->offset != offset)
94 { 87 {
95 if (fseek (fs->file, offset, SEEK_SET) != 0) 88 if (fseek (fs->file, offset, SEEK_SET) != 0)
...@@ -123,9 +116,6 @@ _file_write (stream_t stream, const char *iptr, size_t isize, ...@@ -123,9 +116,6 @@ _file_write (stream_t stream, const char *iptr, size_t isize,
123 size_t n; 116 size_t n;
124 int err = 0; 117 int err = 0;
125 118
126 if (fs == NULL)
127 return EINVAL;
128
129 if (fs->offset != offset) 119 if (fs->offset != offset)
130 { 120 {
131 if (fseek (fs->file, offset, SEEK_SET) != 0) 121 if (fseek (fs->file, offset, SEEK_SET) != 0)
...@@ -153,9 +143,6 @@ static int ...@@ -153,9 +143,6 @@ static int
153 _file_truncate (stream_t stream, off_t len) 143 _file_truncate (stream_t stream, off_t len)
154 { 144 {
155 struct _file_stream *fs = stream_get_owner (stream); 145 struct _file_stream *fs = stream_get_owner (stream);
156
157 if (fs == NULL)
158 return EINVAL;
159 if (ftruncate (fileno(fs->file), len) != 0) 146 if (ftruncate (fileno(fs->file), len) != 0)
160 return errno; 147 return errno;
161 return 0; 148 return 0;
...@@ -166,9 +153,6 @@ _file_size (stream_t stream, off_t *psize) ...@@ -166,9 +153,6 @@ _file_size (stream_t stream, off_t *psize)
166 { 153 {
167 struct _file_stream *fs = stream_get_owner (stream); 154 struct _file_stream *fs = stream_get_owner (stream);
168 struct stat stbuf; 155 struct stat stbuf;
169
170 if (fs == NULL)
171 return EINVAL;
172 fflush (fs->file); 156 fflush (fs->file);
173 if (fstat(fileno(fs->file), &stbuf) == -1) 157 if (fstat(fileno(fs->file), &stbuf) == -1)
174 return errno; 158 return errno;
...@@ -181,9 +165,6 @@ static int ...@@ -181,9 +165,6 @@ static int
181 _file_flush (stream_t stream) 165 _file_flush (stream_t stream)
182 { 166 {
183 struct _file_stream *fs = stream_get_owner (stream); 167 struct _file_stream *fs = stream_get_owner (stream);
184
185 if (fs == NULL)
186 return EINVAL;
187 return fflush (fs->file); 168 return fflush (fs->file);
188 } 169 }
189 170
...@@ -191,9 +172,6 @@ static int ...@@ -191,9 +172,6 @@ static int
191 _file_get_fd (stream_t stream, int *pfd) 172 _file_get_fd (stream_t stream, int *pfd)
192 { 173 {
193 struct _file_stream *fs = stream_get_owner (stream); 174 struct _file_stream *fs = stream_get_owner (stream);
194
195 if (fs == NULL)
196 return EINVAL;
197 if (pfd) 175 if (pfd)
198 *pfd = fileno (fs->file); 176 *pfd = fileno (fs->file);
199 return 0; 177 return 0;
...@@ -204,9 +182,6 @@ _file_close (stream_t stream) ...@@ -204,9 +182,6 @@ _file_close (stream_t stream)
204 { 182 {
205 struct _file_stream *fs = stream_get_owner (stream); 183 struct _file_stream *fs = stream_get_owner (stream);
206 int err = 0; 184 int err = 0;
207
208 if (fs == NULL)
209 return EINVAL;
210 if (fs->file) 185 if (fs->file)
211 { 186 {
212 if (fclose (fs->file) != 0) 187 if (fclose (fs->file) != 0)
...@@ -226,9 +201,6 @@ _file_open (stream_t stream, const char *filename, int port, int flags) ...@@ -226,9 +201,6 @@ _file_open (stream_t stream, const char *filename, int port, int flags)
226 201
227 (void)port; /* Ignored. */ 202 (void)port; /* Ignored. */
228 203
229 if (fs == NULL)
230 return EINVAL;
231
232 if (fs->file) 204 if (fs->file)
233 { 205 {
234 fclose (fs->file); 206 fclose (fs->file);
......
...@@ -189,7 +189,7 @@ rfc822_read0 (filter_t filter, char *buffer, size_t buflen, ...@@ -189,7 +189,7 @@ rfc822_read0 (filter_t filter, char *buffer, size_t buflen,
189 rfc822->residue = 0; 189 rfc822->residue = 0;
190 } 190 }
191 buffer += nread; 191 buffer += nread;
192 } while (buflen > 0 || !isreadline); 192 } while (buflen > 0 && !isreadline);
193 193
194 if (isreadline) 194 if (isreadline)
195 *buffer = '\0'; 195 *buffer = '\0';
......
...@@ -495,6 +495,25 @@ header_get_value (header_t header, const char *name, char *buffer, ...@@ -495,6 +495,25 @@ header_get_value (header_t header, const char *name, char *buffer,
495 } 495 }
496 496
497 int 497 int
498 header_aget_value (header_t header, const char *name, char **pvalue)
499 {
500 char *value;
501 size_t n = 0;
502 int status = header_get_value (header, name, NULL, 0, &n);
503 if (status == 0)
504 {
505 value = calloc (n + 1, 1);
506 if (value == NULL)
507 return ENOMEM;
508 header_get_value (header, name, value, n + 1, NULL);
509 *pvalue = value;
510 }
511 else
512 *pvalue = strdup ("");
513 return 0;
514 }
515
516 int
498 header_get_field_count (header_t header, size_t *pcount) 517 header_get_field_count (header_t header, size_t *pcount)
499 { 518 {
500 if (header == NULL) 519 if (header == NULL)
...@@ -553,6 +572,25 @@ header_get_field_name (header_t header, size_t num, char *buf, ...@@ -553,6 +572,25 @@ header_get_field_name (header_t header, size_t num, char *buf,
553 } 572 }
554 573
555 int 574 int
575 header_aget_field_name (header_t header, size_t num, char **pvalue)
576 {
577 char *value;
578 size_t n = 0;
579 int status = header_get_field_name (header, num, NULL, 0, &n);
580 if (status == 0)
581 {
582 value = calloc (n + 1, 1);
583 if (value == NULL)
584 return ENOMEM;
585 header_get_field_name (header, num, value, n + 1, NULL);
586 *pvalue = value;
587 }
588 else
589 *pvalue = strdup ("");
590 return 0;
591 }
592
593 int
556 header_get_field_value (header_t header, size_t num, char *buf, 594 header_get_field_value (header_t header, size_t num, char *buf,
557 size_t buflen, size_t *nwritten) 595 size_t buflen, size_t *nwritten)
558 { 596 {
...@@ -588,6 +626,25 @@ header_get_field_value (header_t header, size_t num, char *buf, ...@@ -588,6 +626,25 @@ header_get_field_value (header_t header, size_t num, char *buf,
588 } 626 }
589 627
590 int 628 int
629 header_aget_field_value (header_t header, size_t num, char **pvalue)
630 {
631 char *value;
632 size_t n = 0;
633 int status = header_get_field_value (header, num, NULL, 0, &n);
634 if (status == 0)
635 {
636 value = calloc (n + 1, 1);
637 if (value == NULL)
638 return ENOMEM;
639 header_get_field_value (header, num, value, n + 1, NULL);
640 *pvalue = value;
641 }
642 else
643 *pvalue = strdup ("");
644 return status;
645 }
646
647 int
591 header_set_lines (header_t header, int (*_lines) 648 header_set_lines (header_t header, int (*_lines)
592 (header_t, size_t *), void *owner) 649 (header_t, size_t *), void *owner)
593 { 650 {
......
...@@ -48,7 +48,7 @@ _mapfile_destroy (stream_t stream) ...@@ -48,7 +48,7 @@ _mapfile_destroy (stream_t stream)
48 { 48 {
49 struct _mapfile_stream *mfs = stream_get_owner (stream); 49 struct _mapfile_stream *mfs = stream_get_owner (stream);
50 50
51 if (mfs && mfs->ptr != MAP_FAILED) 51 if (mfs->ptr != MAP_FAILED)
52 { 52 {
53 munmap (mfs->ptr, mfs->size); 53 munmap (mfs->ptr, mfs->size);
54 close (mfs->fd); 54 close (mfs->fd);
...@@ -61,21 +61,17 @@ _mapfile_read (stream_t stream, char *optr, size_t osize, ...@@ -61,21 +61,17 @@ _mapfile_read (stream_t stream, char *optr, size_t osize,
61 off_t offset, size_t *nbytes) 61 off_t offset, size_t *nbytes)
62 { 62 {
63 struct _mapfile_stream *mfs = stream_get_owner (stream); 63 struct _mapfile_stream *mfs = stream_get_owner (stream);
64 size_t n; 64 size_t n = 0;
65 65
66 if (mfs == NULL || mfs->ptr == MAP_FAILED) 66 if (mfs->ptr == MAP_FAILED)
67 return EINVAL; 67 return EINVAL;
68 68
69 if (offset >= (off_t)mfs->size) 69 if (offset < (off_t)mfs->size)
70 { 70 {
71 if (nbytes) 71 n = ((offset + osize) > mfs->size) ? mfs->size - offset : osize;
72 *nbytes = 0; 72 memcpy (optr, mfs->ptr + offset, n);
73 return 0;
74 } 73 }
75 74
76 n = ((offset + osize) > mfs->size) ? mfs->size - offset : osize;
77 memcpy (optr, mfs->ptr + offset, n);
78
79 if (nbytes) 75 if (nbytes)
80 *nbytes = n; 76 *nbytes = n;
81 return 0; 77 return 0;
...@@ -89,24 +85,21 @@ _mapfile_readline (stream_t stream, char *optr, size_t osize, ...@@ -89,24 +85,21 @@ _mapfile_readline (stream_t stream, char *optr, size_t osize,
89 char *nl; 85 char *nl;
90 size_t n = 0; 86 size_t n = 0;
91 87
92 if (mfs == NULL || mfs->ptr == MAP_FAILED) 88 if (mfs->ptr == MAP_FAILED)
93 return EINVAL; 89 return EINVAL;
94 /* Save space for the null byte. */ 90
95 osize--; 91 if (offset < (off_t)mfs->size)
96 if (offset >= (off_t)mfs->size)
97 { 92 {
98 if (nbytes) 93 /* Save space for the null byte. */
99 *nbytes = 0; 94 osize--;
100 return 0; 95 nl = memchr (mfs->ptr + offset, '\n', mfs->size - offset);
96 n = (nl) ? nl - (mfs->ptr + offset) + 1 : mfs->size - offset;
97 n = (n > osize) ? osize : n;
98 memcpy (optr, mfs->ptr + offset, n);
99 optr[n] = '\0';
101 } 100 }
102
103 nl = memchr (mfs->ptr + offset, '\n', mfs->size - offset);
104 n = nl - (mfs->ptr + offset) + 1;
105 n = (n > osize) ? osize : n;
106 memcpy (optr, mfs->ptr + offset, n);
107 if (nbytes) 101 if (nbytes)
108 *nbytes = n; 102 *nbytes = n;
109 optr[n] = '\0';
110 return 0; 103 return 0;
111 } 104 }
112 105
...@@ -116,7 +109,7 @@ _mapfile_write (stream_t stream, const char *iptr, size_t isize, ...@@ -116,7 +109,7 @@ _mapfile_write (stream_t stream, const char *iptr, size_t isize,
116 { 109 {
117 struct _mapfile_stream *mfs = stream_get_owner (stream); 110 struct _mapfile_stream *mfs = stream_get_owner (stream);
118 111
119 if (mfs == NULL || mfs->ptr == MAP_FAILED) 112 if (mfs->ptr == MAP_FAILED)
120 return EINVAL; 113 return EINVAL;
121 114
122 if (! (mfs->flags & PROT_WRITE)) 115 if (! (mfs->flags & PROT_WRITE))
...@@ -155,7 +148,7 @@ static int ...@@ -155,7 +148,7 @@ static int
155 _mapfile_truncate (stream_t stream, off_t len) 148 _mapfile_truncate (stream_t stream, off_t len)
156 { 149 {
157 struct _mapfile_stream *mfs = stream_get_owner (stream); 150 struct _mapfile_stream *mfs = stream_get_owner (stream);
158 if (mfs == NULL || mfs->ptr == MAP_FAILED) 151 if (mfs->ptr == MAP_FAILED)
159 return EINVAL; 152 return EINVAL;
160 /* Remap. */ 153 /* Remap. */
161 if (munmap (mfs->ptr, mfs->size) != 0) 154 if (munmap (mfs->ptr, mfs->size) != 0)
...@@ -185,7 +178,7 @@ _mapfile_size (stream_t stream, off_t *psize) ...@@ -185,7 +178,7 @@ _mapfile_size (stream_t stream, off_t *psize)
185 struct stat stbuf; 178 struct stat stbuf;
186 int err = 0; 179 int err = 0;
187 180
188 if (mfs == NULL || mfs->ptr == MAP_FAILED) 181 if (mfs->ptr == MAP_FAILED)
189 return EINVAL; 182 return EINVAL;
190 msync (mfs->ptr, mfs->size, MS_SYNC); 183 msync (mfs->ptr, mfs->size, MS_SYNC);
191 if (fstat(mfs->fd, &stbuf) != 0) 184 if (fstat(mfs->fd, &stbuf) != 0)
...@@ -220,8 +213,6 @@ static int ...@@ -220,8 +213,6 @@ static int
220 _mapfile_flush (stream_t stream) 213 _mapfile_flush (stream_t stream)
221 { 214 {
222 struct _mapfile_stream *mfs = stream_get_owner (stream); 215 struct _mapfile_stream *mfs = stream_get_owner (stream);
223 if (mfs == NULL)
224 return EINVAL;
225 return msync (mfs->ptr, mfs->size, MS_SYNC); 216 return msync (mfs->ptr, mfs->size, MS_SYNC);
226 } 217 }
227 218
...@@ -229,8 +220,6 @@ static int ...@@ -229,8 +220,6 @@ static int
229 _mapfile_get_fd (stream_t stream, int *pfd) 220 _mapfile_get_fd (stream_t stream, int *pfd)
230 { 221 {
231 struct _mapfile_stream *mfs = stream_get_owner (stream); 222 struct _mapfile_stream *mfs = stream_get_owner (stream);
232 if (mfs == NULL)
233 return EINVAL;
234 if (pfd) 223 if (pfd)
235 *pfd = mfs->fd; 224 *pfd = mfs->fd;
236 return 0; 225 return 0;
...@@ -241,7 +230,7 @@ _mapfile_close (stream_t stream) ...@@ -241,7 +230,7 @@ _mapfile_close (stream_t stream)
241 { 230 {
242 struct _mapfile_stream *mfs = stream_get_owner (stream); 231 struct _mapfile_stream *mfs = stream_get_owner (stream);
243 int err = 0; 232 int err = 0;
244 if (mfs && mfs->ptr != MAP_FAILED) 233 if (mfs->ptr != MAP_FAILED)
245 { 234 {
246 if (munmap (mfs->ptr, mfs->size) != 0) 235 if (munmap (mfs->ptr, mfs->size) != 0)
247 err = errno; 236 err = errno;
...@@ -262,9 +251,6 @@ _mapfile_open (stream_t stream, const char *filename, int port, int flags) ...@@ -262,9 +251,6 @@ _mapfile_open (stream_t stream, const char *filename, int port, int flags)
262 251
263 (void)port; /* Ignored. */ 252 (void)port; /* Ignored. */
264 253
265 if (mfs == NULL)
266 return EINVAL;
267
268 /* Close any previous file. */ 254 /* Close any previous file. */
269 if (mfs->ptr != MAP_FAILED) 255 if (mfs->ptr != MAP_FAILED)
270 { 256 {
......
1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001 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 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <sys/types.h>
27
28 #include <mailutils/stream.h>
29
30 struct _memory_stream
31 {
32 char *ptr;
33 size_t size;
34 };
35
36 static void
37 _memory_destroy (stream_t stream)
38 {
39 struct _memory_stream *mfs = stream_get_owner (stream);
40 if (mfs && mfs->ptr != NULL)
41 free (mfs->ptr);
42 free (mfs);
43 }
44
45 static int
46 _memory_read (stream_t stream, char *optr, size_t osize,
47 off_t offset, size_t *nbytes)
48 {
49 struct _memory_stream *mfs = stream_get_owner (stream);
50 size_t n = 0;
51 if (mfs->ptr != NULL && (offset <= (off_t)mfs->size))
52 {
53 n = ((offset + osize) > mfs->size) ? mfs->size - offset : osize;
54 memcpy (optr, mfs->ptr + offset, n);
55 }
56 if (nbytes)
57 *nbytes = n;
58 return 0;
59 }
60
61 static int
62 _memory_readline (stream_t stream, char *optr, size_t osize,
63 off_t offset, size_t *nbytes)
64 {
65 struct _memory_stream *mfs = stream_get_owner (stream);
66 char *nl;
67 size_t n = 0;
68 if (mfs->ptr && (offset < (off_t)mfs->size))
69 {
70 /* Save space for the null byte. */
71 osize--;
72 nl = memchr (mfs->ptr + offset, '\n', mfs->size - offset);
73 n = (nl) ? nl - (mfs->ptr + offset) + 1 : mfs->size - offset;
74 n = (n > osize) ? osize : n;
75 memcpy (optr, mfs->ptr + offset, n);
76 optr[n] = '\0';
77 }
78 if (nbytes)
79 *nbytes = n;
80 return 0;
81 }
82
83 static int
84 _memory_write (stream_t stream, const char *iptr, size_t isize,
85 off_t offset, size_t *nbytes)
86 {
87 struct _memory_stream *mfs = stream_get_owner (stream);
88
89 /* Bigger we have to realloc. */
90 if (mfs->size < (offset + isize))
91 {
92 char *tmp = realloc (mfs->ptr, offset + isize);
93 if (tmp == NULL)
94 return ENOMEM;
95 mfs->ptr = tmp;
96 mfs->size = offset + isize;
97 }
98
99 memcpy (mfs->ptr + offset, iptr, isize);
100 if (nbytes)
101 *nbytes = isize;
102 return 0;
103 }
104
105 static int
106 _memory_truncate (stream_t stream, off_t len)
107 {
108 struct _memory_stream *mfs = stream_get_owner (stream);
109
110 if (len == 0)
111 {
112 free (mfs->ptr);
113 mfs->ptr = NULL;
114 }
115 else
116 {
117 char *tmp = realloc (mfs, len);
118 if (tmp == NULL)
119 return ENOMEM;
120 mfs->ptr = tmp;
121 }
122 mfs->size = len;
123 return 0;
124 }
125
126 static int
127 _memory_size (stream_t stream, off_t *psize)
128 {
129 struct _memory_stream *mfs = stream_get_owner (stream);
130 if (psize)
131 *psize = mfs->size;
132 return 0;
133 }
134
135 static int
136 _memory_close (stream_t stream)
137 {
138 struct _memory_stream *mfs = stream_get_owner (stream);
139 if (mfs->ptr)
140 {
141 free (mfs->ptr);
142 mfs->ptr = NULL;
143 mfs->size = 0;
144 }
145 return 0;
146 }
147
148 static int
149 _memory_open (stream_t stream, const char *filename, int port, int flags)
150 {
151 struct _memory_stream *mfs = stream_get_owner (stream);
152
153 (void)port; /* Ignored. */
154 (void)filename; /* Ignored. */
155 (void)flags; /* Ignored. */
156
157 /* Close any previous file. */
158 if (mfs->ptr)
159 {
160 free (mfs->ptr);
161 mfs->ptr = NULL;
162 mfs->size = 0;
163 }
164 stream_set_flags (stream, flags |MU_STREAM_NO_CHECK);
165 return 0;
166 }
167
168 int
169 memory_stream_create (stream_t *stream)
170 {
171 struct _memory_stream *mfs;
172 int ret;
173
174 if (stream == NULL)
175 return EINVAL;
176
177 mfs = calloc (1, sizeof (*mfs));
178 if (mfs == NULL)
179 return ENOMEM;
180
181 mfs->ptr = NULL;
182 mfs->size = 0;
183
184 ret = stream_create (stream, MU_STREAM_NO_CHECK, mfs);
185 if (ret != 0)
186 {
187 free (mfs);
188 return ret;
189 }
190
191 stream_set_open (*stream, _memory_open, mfs);
192 stream_set_close (*stream, _memory_close, mfs);
193 stream_set_read (*stream, _memory_read, mfs);
194 stream_set_readline (*stream, _memory_readline, mfs);
195 stream_set_write (*stream, _memory_write, mfs);
196 stream_set_truncate (*stream, _memory_truncate, mfs);
197 stream_set_size (*stream, _memory_size, mfs);
198 stream_set_destroy (*stream, _memory_destroy, mfs);
199 return 0;
200 }