Sergey Poznyakoff pointed out that errno change depending
if _REENTRANT is set or not. So for enable thread we take the approach of always defining _REENTRANT. He also noted that when in standalone the child was not exiting.
Showing
22 changed files
with
368 additions
and
47 deletions
1 | 2001-04-23 Alain Magloire | ||
2 | |||
3 | Sergey Poznyakoff pointed out that errno change depending | ||
4 | if _REENTRANT is set or not. So for enable thread we take | ||
5 | the approach of always defining _REENTRANT. | ||
6 | He also noted that when in standalone the child was not exiting. | ||
7 | |||
8 | * acconfig.h: Define _REENTRANT. | ||
9 | * configure.in: Check for sigaction(). | ||
10 | * configuire.in: AC_DEFINE(_REENTRANT). | ||
11 | |||
12 | * doc/Makefile.am: add rfc2060-errata. | ||
13 | * doc/rfc2060-errata: New File. | ||
14 | |||
15 | * imap4d/copy.c: First Implementation. | ||
16 | * imap4d/status.c: First implementation. | ||
17 | |||
18 | * mailbox/file_stream.c (_file_open): For CREAT, close | ||
19 | the fd if we failed. | ||
20 | * mailbox/folder_imap.c: Remove the _REENTRANT. | ||
21 | * mailbox/mbx_mbox.c: Remove the _REENTRANT. | ||
22 | * mailbox/monitor.c: Remove the _REENTRANT. | ||
23 | |||
24 | * pop3d/pop3d.c (main): maxchildren boosted to 20. | ||
25 | (pop3_daemon_init): Use sigaction() for SIGCHLD, | ||
26 | the sematics of signal() is unreliable on some platforms. | ||
27 | * pop3d/signal.c: Save errno. | ||
28 | |||
1 | 2001-04-22 Alain Magloire | 29 | 2001-04-22 Alain Magloire |
2 | 30 | ||
3 | * imap4d/create.c: First implementation. | 31 | * imap4d/create.c: First implementation. | ... | ... |
... | @@ -71,7 +71,7 @@ if test "$ac_cv_func_fnmatch_works" = "no"; then | ... | @@ -71,7 +71,7 @@ if test "$ac_cv_func_fnmatch_works" = "no"; then |
71 | : LIBOBJS="$LIBOBJS fnmatch.o" | 71 | : LIBOBJS="$LIBOBJS fnmatch.o" |
72 | fi | 72 | fi |
73 | AC_REPLACE_FUNCS(setenv snprintf strtok_r strncasecmp strcasecmp vasprintf) | 73 | AC_REPLACE_FUNCS(setenv snprintf strtok_r strncasecmp strcasecmp vasprintf) |
74 | AC_CHECK_FUNCS(mkstemp) | 74 | AC_CHECK_FUNCS(mkstemp sigaction) |
75 | 75 | ||
76 | dnl Check for libraries | 76 | dnl Check for libraries |
77 | AC_CHECK_FUNCS(argp_parse) | 77 | AC_CHECK_FUNCS(argp_parse) |
... | @@ -104,15 +104,19 @@ if test x"$ac_cv_have_libpam" != x"yes"; then | ... | @@ -104,15 +104,19 @@ if test x"$ac_cv_have_libpam" != x"yes"; then |
104 | fi | 104 | fi |
105 | AC_SUBST(AUTHLIBS) | 105 | AC_SUBST(AUTHLIBS) |
106 | 106 | ||
107 | #When using thread support some platforms need -D_REENTRANT to get the | ||
108 | #right prototypes including errno. | ||
107 | dnl Check threading support | 109 | dnl Check threading support |
108 | if test x"$usepthread" = x"yes"; then | 110 | if test x"$usepthread" = x"yes"; then |
109 | AC_CHECK_LIB(pthread, pthread_cancel, [AC_CHECK_HEADERS(pthread.h, | 111 | AC_CHECK_LIB(pthread, pthread_cancel, [AC_CHECK_HEADERS(pthread.h, |
110 | AC_DEFINE(WITH_PTHREAD)) | 112 | AC_DEFINE(WITH_PTHREAD)) |
111 | LIBS="$LIBS -lpthread" | 113 | LIBS="$LIBS -lpthread" |
114 | AC_DEFINE(_REENTRANT) | ||
112 | AC_CHECK_FUNCS(pthread_rwlock_init)], | 115 | AC_CHECK_FUNCS(pthread_rwlock_init)], |
113 | AC_SEARCH_LIBS(pthread_cancel, pthread, | 116 | AC_SEARCH_LIBS(pthread_cancel, pthread, |
114 | [AC_CHECK_FUNCS(pthread_rwlock_init) | 117 | [AC_CHECK_FUNCS(pthread_rwlock_init) |
115 | AC_CHECK_HEADERS(pthread.h, AC_DEFINE(WITH_PTHREAD))])) | 118 | AC_CHECK_HEADERS(pthread.h, AC_DEFINE(WITH_PTHREAD)) |
119 | ACDEFINE(_REENTRANT)])) | ||
116 | fi | 120 | fi |
117 | 121 | ||
118 | dnl Do we need extra libs for networking? | 122 | dnl Do we need extra libs for networking? | ... | ... |
doc/rfc2060-errata
0 → 100644
1 | Known errors in RFC 2060 as of 13 September 1998: | ||
2 | |||
3 | 1) The SELECT and EXAMINE response list does not mention UIDVALIDITY. | ||
4 | |||
5 | 2) In the definition of store_att_flags, #flag should be 1#flag; in other | ||
6 | words, at least one flag must be given. To do an empty list of flags, | ||
7 | you must use the parenthesized form: "()". | ||
8 | |||
9 | 3) The example in 6.4.6 is missing parenthesis around the FETCH attributes. | ||
10 | It should read: | ||
11 | |||
12 | Example: C: A003 STORE 2:4 +FLAGS (\Deleted) | ||
13 | S: * 2 FETCH (FLAGS (\Deleted \Seen)) | ||
14 | S: * 3 FETCH (FLAGS (\Deleted)) | ||
15 | S: * 4 FETCH (FLAGS (\Deleted \Flagged \Seen)) | ||
16 | S: A003 OK STORE completed | ||
17 | |||
18 | 4) Section 7.4.2 has an example of "a two part message consisting of a | ||
19 | text and a BASE645-encoded text attachment". "BASE645" should be | ||
20 | BASE64. | ||
21 | |||
22 | 5) In the example in 7.4.2 discussed above, there is a spurious close | ||
23 | parenthesis at the end of the example. | ||
24 | |||
25 | 6) Spurious obsolete response "MAILBOX" is listed in mailbox_data and | ||
26 | should be removed. | ||
27 | |||
28 | 7) There is a spurious "<" in the mailbox_data rule that should be removed. | ||
29 | |||
30 | 8) CRLF is missing from the continue_req rule. | ||
31 | |||
32 | 9) The atom in resp_text_code should specifically exclude "]". | ||
33 | |||
34 | 10) The example in 6.3.11 does not show the command continuation request. | ||
35 | |||
36 | 11) NEWNAME is missing from resp_text_code. | ||
37 | |||
38 | 12) There is a missing open parenthesis in the media_basic grammar rule. | ||
39 | |||
40 | 13) Status attributes are incorrectly defined in mailbox_data rule. | ||
41 | |||
42 | 14) The UID FETCH example is missing an "OK" in the response. | ||
43 | |||
44 | 15) Multipart extension data incorrectly specifies that language must be | ||
45 | given along with disposition. |
... | @@ -26,6 +26,7 @@ | ... | @@ -26,6 +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 | (void)arg; | ||
29 | if (! (command->states & state)) | 30 | if (! (command->states & state)) |
30 | return util_finish (command, RESP_BAD, "Wrong state"); | 31 | return util_finish (command, RESP_BAD, "Wrong state"); |
31 | return util_finish (command, RESP_OK, "Completed"); | 32 | return util_finish (command, RESP_OK, "Completed"); | ... | ... |
... | @@ -23,12 +23,16 @@ | ... | @@ -23,12 +23,16 @@ |
23 | int | 23 | int |
24 | imap4d_close (struct imap4d_command *command, char *arg) | 24 | imap4d_close (struct imap4d_command *command, char *arg) |
25 | { | 25 | { |
26 | /* FIXME: Check args. */ | 26 | (void)arg; |
27 | /* FIXME: Check state and if they selected. */ | ||
28 | if (! (command->states & state)) | 27 | if (! (command->states & state)) |
29 | return util_finish (command, RESP_BAD, "Wrong state"); | 28 | return util_finish (command, RESP_BAD, "Wrong state"); |
30 | /* FIXME: Check and report errors. */ | 29 | /* FIXME: Check and report errors. */ |
30 | /* The CLOSE command permanently removes form the currentyl selected | ||
31 | mailbox all messages that have the \\Deleted falg set, and returns | ||
32 | to authenticated state from selected state. */ | ||
31 | mailbox_expunge (mbox); | 33 | mailbox_expunge (mbox); |
34 | /* No messages are removed, and no error is give, if the mailbox is | ||
35 | selected by an EXAMINE command or is otherwise selected read-only. */ | ||
32 | mailbox_close (mbox); | 36 | mailbox_close (mbox); |
33 | mailbox_destroy (&mbox); | 37 | mailbox_destroy (&mbox); |
34 | return util_finish (command, RESP_OK, "Completed"); | 38 | return util_finish (command, RESP_OK, "Completed"); | ... | ... |
... | @@ -21,10 +21,77 @@ | ... | @@ -21,10 +21,77 @@ |
21 | * copy messages in argv[2] to mailbox in argv[3] | 21 | * copy messages in argv[2] to mailbox in argv[3] |
22 | */ | 22 | */ |
23 | 23 | ||
24 | /* FIXME if the mailbox is the one selecte we should send notif. */ | ||
24 | int | 25 | int |
25 | imap4d_copy (struct imap4d_command *command, char *arg) | 26 | imap4d_copy (struct imap4d_command *command, char *arg) |
26 | { | 27 | { |
28 | int status; | ||
29 | char *msgset; | ||
30 | char *name; | ||
31 | char *mailbox_name; | ||
32 | const char *delim = "/"; | ||
33 | char *sp = NULL; | ||
34 | int *set = NULL; | ||
35 | size_t n = 0; | ||
36 | mailbox_t cmbox = NULL; | ||
37 | |||
27 | if (! (command->states & state)) | 38 | if (! (command->states & state)) |
28 | return util_finish (command, RESP_BAD, "Wrong state"); | 39 | return util_finish (command, RESP_BAD, "Wrong state"); |
29 | return util_finish (command, RESP_NO, "Command not supported"); | 40 | |
41 | msgset = util_getword (arg, &sp); | ||
42 | name = util_getword (NULL, &sp); | ||
43 | |||
44 | util_unquote (&name); | ||
45 | if (!msgset || !name || *name == '\0') | ||
46 | return util_finish (command, RESP_BAD, "Too few args"); | ||
47 | |||
48 | /* Get the message numbers in set[]. */ | ||
49 | status = util_msgset (msgset, &set, &n, 0); | ||
50 | if (status != 0) | ||
51 | return util_finish (command, RESP_BAD, "Bogus number set"); | ||
52 | |||
53 | if (strcasecmp (name, "INBOX") == 0) | ||
54 | { | ||
55 | struct passwd *pw = getpwuid (getuid()); | ||
56 | mailbox_name = strdup ((pw) ? pw->pw_name : ""); | ||
57 | } | ||
58 | else | ||
59 | mailbox_name = util_getfullpath (name, delim); | ||
60 | |||
61 | /* If the destination mailbox does not exist, a server should return | ||
62 | an error. */ | ||
63 | status = mailbox_create_default (&cmbox, mailbox_name); | ||
64 | if (status == 0) | ||
65 | { | ||
66 | /* It SHOULD NOT automatifcllly create the mailbox. */ | ||
67 | status = mailbox_open (cmbox, MU_STREAM_RDWR); | ||
68 | if (status == 0) | ||
69 | { | ||
70 | size_t i; | ||
71 | for (i = 0; i < n; i++) | ||
72 | { | ||
73 | message_t msg = NULL; | ||
74 | mailbox_get_message (mbox, set[i], &msg); | ||
75 | mailbox_append_message (cmbox, msg); | ||
76 | } | ||
77 | mailbox_close (cmbox); | ||
78 | } | ||
79 | mailbox_destroy (&cmbox); | ||
80 | } | ||
81 | free (set); | ||
82 | free (mailbox_name); | ||
83 | |||
84 | if (status == 0) | ||
85 | return util_finish (command, RESP_OK, "Completed"); | ||
86 | |||
87 | /* Since we do not call util_finish, reset the state ourself. */ | ||
88 | if (command->failure != STATE_NONE) | ||
89 | state = command->failure; | ||
90 | |||
91 | /* Unless it is certain that the destination mailbix can not be created, | ||
92 | the server MUST send the response code "[TRYCREATE]" as the prefix | ||
93 | of the text of the tagged NO response. This gives a hint to the | ||
94 | client that it can attempt a CREATE command and retry the copy if | ||
95 | the CREATE is successful. */ | ||
96 | return util_send ("%s NO [TRYCREATE] failed\r\n", command->tag); | ||
30 | } | 97 | } | ... | ... |
... | @@ -19,9 +19,13 @@ | ... | @@ -19,9 +19,13 @@ |
19 | #include <unistd.h> | 19 | #include <unistd.h> |
20 | 20 | ||
21 | /* | 21 | /* |
22 | * must create a new mailbox | 22 | * Must create a new mailbox |
23 | */ | 23 | */ |
24 | 24 | ||
25 | /* FIXME: How do we do this ??????: | ||
26 | IF a new mailbox is created with the same name as a mailbox which was | ||
27 | deleted, its unique identifiers MUST be greater than any unique identifiers | ||
28 | used in the previous incarnation of the mailbox. */ | ||
25 | int | 29 | int |
26 | imap4d_create (struct imap4d_command *command, char *arg) | 30 | imap4d_create (struct imap4d_command *command, char *arg) |
27 | { | 31 | { |
... | @@ -50,11 +54,15 @@ imap4d_create (struct imap4d_command *command, char *arg) | ... | @@ -50,11 +54,15 @@ imap4d_create (struct imap4d_command *command, char *arg) |
50 | /* Allocates memory. */ | 54 | /* Allocates memory. */ |
51 | name = util_getfullpath (name, delim); | 55 | name = util_getfullpath (name, delim); |
52 | 56 | ||
53 | /* It will fail if the mailbx already exists. */ | 57 | /* It will fail if the mailbox already exists. */ |
54 | if (access (name, F_OK) != 0) | 58 | if (access (name, F_OK) != 0) |
55 | { | 59 | { |
56 | char *dir; | 60 | char *dir; |
57 | char *d = name + strlen (delim); /* Pass the root delimeter. */ | 61 | char *d = name + strlen (delim); /* Pass the root delimeter. */ |
62 | |||
63 | /*If the server's hierarchy separtor character appears elsewhere in | ||
64 | name, the server SHOULD create any superior hierarchcal names | ||
65 | that are needed for the CREATE command to complete successfully. */ | ||
58 | if (chdir (delim) == 0) /* start on the root. */ | 66 | if (chdir (delim) == 0) /* start on the root. */ |
59 | for (; (dir = strchr (d, delim[0])); d = dir) | 67 | for (; (dir = strchr (d, delim[0])); d = dir) |
60 | { | 68 | { |
... | @@ -76,7 +84,11 @@ imap4d_create (struct imap4d_command *command, char *arg) | ... | @@ -76,7 +84,11 @@ imap4d_create (struct imap4d_command *command, char *arg) |
76 | } | 84 | } |
77 | } | 85 | } |
78 | } | 86 | } |
79 | /* If it ended with the delim they wanted to create a new folder. */ | 87 | /* If the mailbox name is suffixed with the server's hierarchy |
88 | separator character, this is a declaration that the client intends | ||
89 | to create mailbox names under this name in the hierarchy. | ||
90 | |||
91 | In other words is d == '\0' it is not an error. */ | ||
80 | if (rc == RESP_OK && d && *d != '\0') | 92 | if (rc == RESP_OK && d && *d != '\0') |
81 | { | 93 | { |
82 | int fd = creat (d, 0600); | 94 | int fd = creat (d, 0600); | ... | ... |
... | @@ -34,17 +34,14 @@ imap4d_delete (struct imap4d_command *command, char *arg) | ... | @@ -34,17 +34,14 @@ imap4d_delete (struct imap4d_command *command, char *arg) |
34 | return util_finish (command, RESP_BAD, "Wrong state"); | 34 | return util_finish (command, RESP_BAD, "Wrong state"); |
35 | 35 | ||
36 | name = util_getword (arg, &sp); | 36 | name = util_getword (arg, &sp); |
37 | if (!name) | ||
38 | return util_finish (command, RESP_BAD, "Too few arguments"); | ||
39 | |||
40 | util_unquote (&name); | 37 | util_unquote (&name); |
41 | 38 | if (!name || *name == '\0') | |
42 | if (*name == '\0') | ||
43 | return util_finish (command, RESP_BAD, "Too few arguments"); | 39 | return util_finish (command, RESP_BAD, "Too few arguments"); |
44 | 40 | ||
45 | /* Deleting, "Inbox" should always fail. */ | 41 | /* It is an error to attempt to delele "INBOX or a mailbox |
42 | name that dos not exists. */ | ||
46 | if (strcasecmp (name, "INBOX") == 0) | 43 | if (strcasecmp (name, "INBOX") == 0) |
47 | return util_finish (command, RESP_BAD, "Already exist"); | 44 | return util_finish (command, RESP_NO, "Already exist"); |
48 | 45 | ||
49 | /* Allocates memory. */ | 46 | /* Allocates memory. */ |
50 | name = util_getfullpath (name, delim); | 47 | name = util_getfullpath (name, delim); | ... | ... |
... | @@ -110,10 +110,7 @@ imap4d_fetch (struct imap4d_command *command, char *arg) | ... | @@ -110,10 +110,7 @@ imap4d_fetch (struct imap4d_command *command, char *arg) |
110 | return util_finish (command, RESP_BAD, "Wrong state"); | 110 | return util_finish (command, RESP_BAD, "Wrong state"); |
111 | 111 | ||
112 | msgset = util_getword (arg, &sp); | 112 | msgset = util_getword (arg, &sp); |
113 | if (!msgset) | 113 | if (!msgset || !sp || *sp == '\0') |
114 | return util_finish (command, RESP_BAD, "Too few args"); | ||
115 | |||
116 | if (sp == NULL || *sp == '\0') | ||
117 | return util_finish (command, RESP_BAD, "Too few args"); | 114 | return util_finish (command, RESP_BAD, "Too few args"); |
118 | 115 | ||
119 | /* Get the message numbers in set[]. */ | 116 | /* Get the message numbers in set[]. */ | ... | ... |
... | @@ -31,8 +31,15 @@ imap4d_logout (struct imap4d_command *command, char *arg) | ... | @@ -31,8 +31,15 @@ imap4d_logout (struct imap4d_command *command, char *arg) |
31 | return util_finish (command, RESP_BAD, "Too many args"); | 31 | return util_finish (command, RESP_BAD, "Too many args"); |
32 | util_out (RESP_BYE, "Logging out"); | 32 | util_out (RESP_BYE, "Logging out"); |
33 | util_finish (command, RESP_OK, "Completed"); | 33 | util_finish (command, RESP_OK, "Completed"); |
34 | /* Even if a mailbox is slected, a SLECT EXAMINE or LOGOUT | ||
35 | command MAY be issued without previously issuing a CLOSE command. | ||
36 | The SELECT, EXAMINE, and LOGUT commands implictly close the | ||
37 | currently selected mailbox withut doing an expunge. */ | ||
38 | if (mbox) | ||
39 | { | ||
34 | mailbox_close (mbox); | 40 | mailbox_close (mbox); |
35 | mailbox_destroy (&mbox); | 41 | mailbox_destroy (&mbox); |
42 | } | ||
36 | util_quit (0); | 43 | util_quit (0); |
37 | return 0; | 44 | return 0; |
38 | } | 45 | } | ... | ... |
... | @@ -42,6 +42,10 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags) | ... | @@ -42,6 +42,10 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags) |
42 | if (util_getword (NULL, &sp)) | 42 | if (util_getword (NULL, &sp)) |
43 | return util_finish (command, RESP_BAD, "Too many arguments"); | 43 | return util_finish (command, RESP_BAD, "Too many arguments"); |
44 | 44 | ||
45 | /* Even if a mailbox is slected, a SLECT EXAMINE or LOGOUT | ||
46 | command MAY be issued without previously issuing a CLOSE command. | ||
47 | The SELECT, EXAMINE, and LOGUT commands implictly close the | ||
48 | currently selected mailbox withut doing an expunge. */ | ||
45 | if (mbox) | 49 | if (mbox) |
46 | { | 50 | { |
47 | mailbox_close (mbox); | 51 | mailbox_close (mbox); | ... | ... |
... | @@ -21,17 +21,137 @@ | ... | @@ -21,17 +21,137 @@ |
21 | * | 21 | * |
22 | */ | 22 | */ |
23 | 23 | ||
24 | static int status_messages __P ((mailbox_t)); | ||
25 | static int status_recent __P ((mailbox_t)); | ||
26 | static int status_uidnext __P ((mailbox_t)); | ||
27 | static int status_uidvalidity __P ((mailbox_t)); | ||
28 | static int status_unseen __P ((mailbox_t)); | ||
29 | |||
24 | int | 30 | int |
25 | imap4d_status (struct imap4d_command *command, char *arg) | 31 | imap4d_status (struct imap4d_command *command, char *arg) |
26 | { | 32 | { |
27 | char *sp = NULL; | 33 | char *sp = NULL; |
34 | char *name; | ||
28 | char *mailbox_name; | 35 | char *mailbox_name; |
29 | char *data; | 36 | const char *delim = "/"; |
37 | mailbox_t smbox = NULL; | ||
38 | int status; | ||
39 | |||
30 | if (! (command->states & state)) | 40 | if (! (command->states & state)) |
31 | return util_finish (command, RESP_BAD, "Wrong state"); | 41 | return util_finish (command, RESP_BAD, "Wrong state"); |
32 | mailbox_name = util_getword (arg, &sp); | 42 | |
33 | data = util_getword (NULL, &sp); | 43 | name = util_getword (arg, &sp); |
34 | if (!mailbox_name || !data) | 44 | if (!name || !sp) |
35 | return util_finish (command, RESP_BAD, "Too few args"); | 45 | return util_finish (command, RESP_BAD, "Too few args"); |
36 | return util_finish (command, RESP_BAD, "Not supported"); | 46 | |
47 | util_unquote (&name); | ||
48 | |||
49 | if (*name == '\0' || *sp == '\0') | ||
50 | return util_finish (command, RESP_BAD, "Too few args"); | ||
51 | |||
52 | if (strcasecmp (name, "INBOX") == 0) | ||
53 | { | ||
54 | struct passwd *pw = getpwuid (getuid()); | ||
55 | mailbox_name = strdup ((pw) ? pw->pw_name : ""); | ||
56 | } | ||
57 | else | ||
58 | mailbox_name = util_getfullpath (name, delim); | ||
59 | |||
60 | status = mailbox_create_default (&smbox, mailbox_name); | ||
61 | if (status == 0) | ||
62 | { | ||
63 | status = mailbox_open (smbox, MU_STREAM_READ); | ||
64 | if (status == 0) | ||
65 | { | ||
66 | char item[32]; | ||
67 | util_send ("* STATUS %s (", name); | ||
68 | item[0] = '\0'; | ||
69 | /* Get the status item names. */ | ||
70 | while (*sp && *sp != ')') | ||
71 | { | ||
72 | int err = 1; | ||
73 | util_token (item, sizeof (item), &sp); | ||
74 | if (strcasecmp (item, "MESSAGES") == 0) | ||
75 | err = status_messages (smbox); | ||
76 | else if (strcasecmp (item, "RECENT") == 0) | ||
77 | err = status_recent (smbox); | ||
78 | else if (strcasecmp (item, "UIDNEXT") == 0) | ||
79 | err = status_uidnext (smbox); | ||
80 | else if (strcasecmp (item, "UIDVALIDITY") == 0) | ||
81 | err = status_uidvalidity (smbox); | ||
82 | else if (strcasecmp (item, "UNSEEN") == 0) | ||
83 | err = status_unseen (smbox); | ||
84 | if (!err) | ||
85 | util_send (" "); | ||
86 | } | ||
87 | util_send (")\r\n"); | ||
88 | mailbox_close (smbox); | ||
89 | } | ||
90 | mailbox_destroy (&smbox); | ||
91 | } | ||
92 | free (mailbox_name); | ||
93 | |||
94 | if (status == 0) | ||
95 | return util_finish (command, RESP_OK, "Completed"); | ||
96 | return util_finish (command, RESP_NO, "Error opening mailbox"); | ||
97 | } | ||
98 | |||
99 | static int | ||
100 | status_messages (mailbox_t smbox) | ||
101 | { | ||
102 | size_t total = 0; | ||
103 | mailbox_messages_count (smbox, &total); | ||
104 | util_send ("MESSAGES %u", total); | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int | ||
109 | status_recent (mailbox_t smbox) | ||
110 | { | ||
111 | size_t recent = 0; | ||
112 | mailbox_messages_recent (smbox, &recent); | ||
113 | util_send ("RECENT %u", recent); | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static int | ||
118 | status_uidnext (mailbox_t smbox) | ||
119 | { | ||
120 | size_t uidnext = 1; | ||
121 | mailbox_uidnext (smbox, &uidnext); | ||
122 | util_send ("UIDNEXT %u", uidnext); | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static int | ||
127 | status_uidvalidity (mailbox_t smbox) | ||
128 | { | ||
129 | unsigned long uidvalidity = 0; | ||
130 | mailbox_uidvalidity (smbox, &uidvalidity); | ||
131 | util_send ("UIDVALIDITY %u", uidvalidity); | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | /* Note that unlike the unseen response code, which indicates the message | ||
136 | number of the first unseen message, the unseeen item in the response the | ||
137 | status command indicates the quantity of unseen messages. */ | ||
138 | static int | ||
139 | status_unseen (mailbox_t smbox) | ||
140 | { | ||
141 | size_t total = 0; | ||
142 | size_t unseen = 0; | ||
143 | size_t i; | ||
144 | mailbox_messages_count (smbox, &total); | ||
145 | for (i = 1; i <= total; i++) | ||
146 | { | ||
147 | message_t msg = NULL; | ||
148 | attribute_t attr = NULL; | ||
149 | mailbox_get_message (smbox, i, &msg); | ||
150 | message_get_attribute (msg, &attr); | ||
151 | if (!attribute_is_seen (attr)) | ||
152 | unseen++; | ||
153 | } | ||
154 | util_send ("UNSEEN %d", unseen); | ||
155 | return 0; | ||
156 | |||
37 | } | 157 | } | ... | ... |
... | @@ -87,7 +87,7 @@ void | ... | @@ -87,7 +87,7 @@ void |
87 | util_unquote (char **ptr) | 87 | util_unquote (char **ptr) |
88 | { | 88 | { |
89 | char *s = *ptr; | 89 | char *s = *ptr; |
90 | if (*s == '"') | 90 | if (s && *s == '"') |
91 | { | 91 | { |
92 | char *p = ++s; | 92 | char *p = ++s; |
93 | while (*p && *p != '"') | 93 | while (*p && *p != '"') |
... | @@ -426,6 +426,8 @@ util_start (char *tag) | ... | @@ -426,6 +426,8 @@ util_start (char *tag) |
426 | void | 426 | void |
427 | util_quit (int err) | 427 | util_quit (int err) |
428 | { | 428 | { |
429 | if (err) | ||
430 | util_out (RESP_BYE, "Server terminating"); | ||
429 | exit (err); | 431 | exit (err); |
430 | } | 432 | } |
431 | 433 | ... | ... |
... | @@ -260,12 +260,14 @@ _file_open (stream_t stream, const char *filename, int port, int flags) | ... | @@ -260,12 +260,14 @@ _file_open (stream_t stream, const char *filename, int port, int flags) |
260 | 260 | ||
261 | /* Now check that: file and fd reference the same file, | 261 | /* Now check that: file and fd reference the same file, |
262 | file only has one link, file is plain file. */ | 262 | file only has one link, file is plain file. */ |
263 | if (fdbuf.st_dev != filebuf.st_dev || | 263 | if (fdbuf.st_dev != filebuf.st_dev |
264 | fdbuf.st_ino != filebuf.st_ino || | 264 | || fdbuf.st_ino != filebuf.st_ino |
265 | fdbuf.st_nlink != 1 || | 265 | || fdbuf.st_nlink != 1 |
266 | filebuf.st_nlink != 1 || | 266 | || filebuf.st_nlink != 1 |
267 | (fdbuf.st_mode & S_IFMT) != S_IFREG) { | 267 | || (fdbuf.st_mode & S_IFMT) != S_IFREG) |
268 | { | ||
268 | fprintf(stderr,"%s must be a plain file with one link\n", filename); | 269 | fprintf(stderr,"%s must be a plain file with one link\n", filename); |
270 | close (fd); | ||
269 | return EINVAL; | 271 | return EINVAL; |
270 | } | 272 | } |
271 | } | 273 | } | ... | ... |
... | @@ -19,10 +19,6 @@ | ... | @@ -19,10 +19,6 @@ |
19 | # include <config.h> | 19 | # include <config.h> |
20 | #endif | 20 | #endif |
21 | 21 | ||
22 | #ifdef WITH_PTHREAD | ||
23 | # define _REENTRANT | ||
24 | #endif | ||
25 | |||
26 | #include <stdlib.h> | 22 | #include <stdlib.h> |
27 | #include <ctype.h> | 23 | #include <ctype.h> |
28 | #include <stdarg.h> | 24 | #include <stdarg.h> | ... | ... |
... | @@ -22,7 +22,6 @@ | ... | @@ -22,7 +22,6 @@ |
22 | #endif | 22 | #endif |
23 | 23 | ||
24 | #ifdef WITH_PTHREAD | 24 | #ifdef WITH_PTHREAD |
25 | # define _REENTRANT | ||
26 | # ifdef HAVE_PTHREAD_H | 25 | # ifdef HAVE_PTHREAD_H |
27 | # define _XOPEN_SOURCE 500 | 26 | # define _XOPEN_SOURCE 500 |
28 | # include <pthread.h> | 27 | # include <pthread.h> | ... | ... |
... | @@ -31,7 +31,7 @@ int ifile; | ... | @@ -31,7 +31,7 @@ int ifile; |
31 | FILE *ofile; | 31 | FILE *ofile; |
32 | time_t curr_time; | 32 | time_t curr_time; |
33 | char *md5shared; | 33 | char *md5shared; |
34 | unsigned int children; | 34 | volatile unsigned int children; |
35 | 35 | ||
36 | /* Number of child processes. */ | 36 | /* Number of child processes. */ |
37 | unsigned int children = 0; | 37 | unsigned int children = 0; |
... | @@ -54,8 +54,9 @@ main (int argc, char **argv) | ... | @@ -54,8 +54,9 @@ main (int argc, char **argv) |
54 | { | 54 | { |
55 | struct group *gr; | 55 | struct group *gr; |
56 | static int mode = INTERACTIVE; | 56 | static int mode = INTERACTIVE; |
57 | size_t maxchildren = 10; | 57 | size_t maxchildren = 20; |
58 | int c = 0; | 58 | int c = 0; |
59 | int status = OK; | ||
59 | 60 | ||
60 | port = 110; /* Default POP3 port. */ | 61 | port = 110; /* Default POP3 port. */ |
61 | timeout = 0; /* Default timeout of 0. */ | 62 | timeout = 0; /* Default timeout of 0. */ |
... | @@ -151,11 +152,11 @@ main (int argc, char **argv) | ... | @@ -151,11 +152,11 @@ main (int argc, char **argv) |
151 | pop3_daemon (maxchildren); | 152 | pop3_daemon (maxchildren); |
152 | /* exit() -- no way out of daemon except a signal. */ | 153 | /* exit() -- no way out of daemon except a signal. */ |
153 | else | 154 | else |
154 | pop3_mainloop (fileno (stdin), fileno (stdout)); | 155 | status = pop3_mainloop (fileno (stdin), fileno (stdout)); |
155 | 156 | ||
156 | /* Close the syslog connection and exit. */ | 157 | /* Close the syslog connection and exit. */ |
157 | closelog (); | 158 | closelog (); |
158 | return OK; | 159 | return (OK != status); |
159 | } | 160 | } |
160 | 161 | ||
161 | /* Sets things up for daemon mode. */ | 162 | /* Sets things up for daemon mode. */ |
... | @@ -183,7 +184,7 @@ pop3_daemon_init (void) | ... | @@ -183,7 +184,7 @@ pop3_daemon_init (void) |
183 | if (pid == -1) | 184 | if (pid == -1) |
184 | { | 185 | { |
185 | perror("fork failed:"); | 186 | perror("fork failed:"); |
186 | exit (-1); | 187 | exit (1); |
187 | } | 188 | } |
188 | else if (pid > 0) | 189 | else if (pid > 0) |
189 | exit (0); /* Parent exits. */ | 190 | exit (0); /* Parent exits. */ |
... | @@ -192,7 +193,17 @@ pop3_daemon_init (void) | ... | @@ -192,7 +193,17 @@ pop3_daemon_init (void) |
192 | for (i = 0; i < MAXFD; ++i) | 193 | for (i = 0; i < MAXFD; ++i) |
193 | close(i); | 194 | close(i); |
194 | 195 | ||
196 | #ifdef HAVE_SIGACTION | ||
197 | { | ||
198 | struct sigaction act; | ||
199 | act.sa_handler = pop3_sigchld; | ||
200 | sigemptyset (&act.sa_mask); | ||
201 | act.sa_flags = 0; | ||
202 | sigaction (SIGCHLD, &act, NULL); | ||
203 | } | ||
204 | #else | ||
195 | signal (SIGCHLD, pop3_sigchld); | 205 | signal (SIGCHLD, pop3_sigchld); |
206 | #endif | ||
196 | } | 207 | } |
197 | 208 | ||
198 | /* The main part of the daemon. This function reads input from the client and | 209 | /* The main part of the daemon. This function reads input from the client and |
... | @@ -237,7 +248,6 @@ pop3_mainloop (int infile, int outfile) | ... | @@ -237,7 +248,6 @@ pop3_mainloop (int infile, int outfile) |
237 | (int)time (NULL), local_hostname); | 248 | (int)time (NULL), local_hostname); |
238 | free (local_hostname); | 249 | free (local_hostname); |
239 | 250 | ||
240 | fflush (ofile); | ||
241 | fprintf (ofile, "+OK POP3 " WELCOME " %s\r\n", md5shared); | 251 | fprintf (ofile, "+OK POP3 " WELCOME " %s\r\n", md5shared); |
242 | 252 | ||
243 | while (state != UPDATE) | 253 | while (state != UPDATE) |
... | @@ -312,7 +322,7 @@ pop3_mainloop (int infile, int outfile) | ... | @@ -312,7 +322,7 @@ pop3_mainloop (int infile, int outfile) |
312 | } | 322 | } |
313 | 323 | ||
314 | fflush (ofile); | 324 | fflush (ofile); |
315 | return OK; | 325 | return (status != OK); |
316 | } | 326 | } |
317 | 327 | ||
318 | /* Runs GNU POP3 in standalone daemon mode. This opens and binds to a port | 328 | /* Runs GNU POP3 in standalone daemon mode. This opens and binds to a port |
... | @@ -372,12 +382,15 @@ pop3_daemon (unsigned int maxchildren) | ... | @@ -372,12 +382,15 @@ pop3_daemon (unsigned int maxchildren) |
372 | 382 | ||
373 | pid = fork (); | 383 | pid = fork (); |
374 | if (pid == -1) | 384 | if (pid == -1) |
375 | syslog(LOG_ERR, "fork: %s", strerror(errno)); | 385 | syslog(LOG_ERR, "fork: %s", strerror (errno)); |
376 | else if (pid == 0) /* Child. */ | 386 | else if (pid == 0) /* Child. */ |
377 | { | 387 | { |
388 | int status; | ||
378 | close (listenfd); | 389 | close (listenfd); |
379 | /* syslog(); FIXME log the info on the connectiing client. */ | 390 | /* syslog(); FIXME log the info on the connecting client. */ |
380 | pop3_mainloop (connfd, connfd); | 391 | status = pop3_mainloop (connfd, connfd); |
392 | closelog (); | ||
393 | exit (status); | ||
381 | } | 394 | } |
382 | else | 395 | else |
383 | { | 396 | { | ... | ... |
1 | /* GNU copyright notice */ | 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 Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
2 | 18 | ||
3 | #include "pop3d.h" | 19 | #include "pop3d.h" |
4 | 20 | ||
... | @@ -7,8 +23,11 @@ pop3_sigchld (int signo) | ... | @@ -7,8 +23,11 @@ pop3_sigchld (int signo) |
7 | { | 23 | { |
8 | pid_t pid; | 24 | pid_t pid; |
9 | int status; | 25 | int status; |
26 | int old_errno = errno ; | ||
10 | 27 | ||
11 | (void)signo; | 28 | (void)signo; |
29 | errno = 0; | ||
12 | while ( (pid = waitpid(-1, &status, WNOHANG)) > 0) | 30 | while ( (pid = waitpid(-1, &status, WNOHANG)) > 0) |
13 | --children; | 31 | --children; |
32 | errno = old_errno; | ||
14 | } | 33 | } | ... | ... |
-
Please register or sign in to post a comment