Commit 020839e9 020839e928fe761ea76b0b41389e8de50d57a6e2 by Alain Magloire

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.
1 parent 2b99aa95
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.
......
...@@ -8,3 +8,4 @@ of errors. ...@@ -8,3 +8,4 @@ of errors.
8 8
9 Frank Belew <frb@wiw.org> 9 Frank Belew <frb@wiw.org>
10 Vesselin Atanasov <vesselin@bgnet.bg> 10 Vesselin Atanasov <vesselin@bgnet.bg>
11 Sergey Poznyakoff <gray@Mirddin.farlep.net>
......
...@@ -29,3 +29,6 @@ ...@@ -29,3 +29,6 @@
29 29
30 /* Define if using libreadline */ 30 /* Define if using libreadline */
31 #undef WITH_READLINE 31 #undef WITH_READLINE
32
33 /* Define _REENTRANT when using threads. */
34 #undef _REENTRANT
......
...@@ -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?
......
...@@ -6,6 +6,7 @@ EXTRA_DIST = \ ...@@ -6,6 +6,7 @@ EXTRA_DIST = \
6 rfc1939.txt \ 6 rfc1939.txt \
7 rfc1957.txt \ 7 rfc1957.txt \
8 rfc2060.txt \ 8 rfc2060.txt \
9 rfc2060-errata \
9 rfc2449.txt \ 10 rfc2449.txt \
10 address.texi \ 11 address.texi \
11 attribute.texi \ 12 attribute.texi \
......
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>
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
25 #endif 25 #endif
26 26
27 #ifdef WITH_PTHREAD 27 #ifdef WITH_PTHREAD
28 # define _REENTRANT
29 # ifdef HAVE_PTHREAD_H 28 # ifdef HAVE_PTHREAD_H
30 # include <pthread.h> 29 # include <pthread.h>
31 # endif 30 # endif
......
...@@ -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 }
......