summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mailbox/nntp/Makefile.am17
-rw-r--r--mailbox/nntp/nntp_article.c67
-rw-r--r--mailbox/nntp/nntp_body.c37
-rw-r--r--mailbox/nntp/nntp_connect.c6
-rw-r--r--mailbox/nntp/nntp_date.c99
-rw-r--r--mailbox/nntp/nntp_group.c108
-rw-r--r--mailbox/nntp/nntp_head.c29
-rw-r--r--mailbox/nntp/nntp_last.c72
-rw-r--r--mailbox/nntp/nntp_list_extensions.c110
-rw-r--r--mailbox/nntp/nntp_mode_reader.c66
-rw-r--r--mailbox/nntp/nntp_next.c72
-rw-r--r--mailbox/nntp/nntp_quit.c61
-rw-r--r--mailbox/nntp/nntp_response.c14
-rw-r--r--mailbox/nntp/nntp_stat.c99
14 files changed, 773 insertions, 84 deletions
diff --git a/mailbox/nntp/Makefile.am b/mailbox/nntp/Makefile.am
index 3b3bc77fa..58f43f4c2 100644
--- a/mailbox/nntp/Makefile.am
+++ b/mailbox/nntp/Makefile.am
@@ -24,18 +24,25 @@ INCLUDES = -I${top_srcdir}/include -I${top_srcdir}/mailbox \
lib_LTLIBRARIES = libmu_nntp.la
libmu_nntp_la_SOURCES = \
+ nntp_article.c \
+ nntp_body.c \
nntp_carrier.c \
nntp_connect.c \
nntp_create.c \
+ nntp_date.c \
nntp_debug.c \
nntp_destroy.c \
nntp_disconnect.c \
+ nntp_group.c \
+ nntp_head.c \
+ nntp_last.c \
+ nntp_list_extensions.c \
+ nntp_mode_reader.c \
+ nntp_next.c \
+ nntp_quit.c \
nntp_readline.c \
nntp_response.c \
nntp_sendline.c \
+ nntp_stat.c \
nntp_stream.c \
- nntp_timeout.c \
- nntp_article.c \
- nntp_head.c \
- nntp_body.c
-
+ nntp_timeout.c
diff --git a/mailbox/nntp/nntp_article.c b/mailbox/nntp/nntp_article.c
index c59108d6a..d80cfca4f 100644
--- a/mailbox/nntp/nntp_article.c
+++ b/mailbox/nntp/nntp_article.c
@@ -30,12 +30,12 @@ mu_nntp_article (mu_nntp_t nntp, unsigned long number, unsigned long *pnum, char
char *message_id = NULL;
if (number != 0)
{
- message_id = malloc(128);
+ message_id = malloc (128);
if (message_id == NULL)
{
return ENOMEM;
}
- snprintf(message_id, 127, "%d", number);
+ snprintf (message_id, 127, "%d", number);
}
status = mu_nntp_article_id (nntp, message_id, pnum, mid, pstream);
if (message_id)
@@ -69,7 +69,7 @@ mu_nntp_article_id (mu_nntp_t nntp, const char *message_id, unsigned long *pnum,
status = mu_nntp_writeline (nntp, "ARTICLE %s\r\n", message_id);
}
MU_NNTP_CHECK_ERROR (nntp, status);
- mu_NNTP_debug_cmd (nntp);
+ mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_ARTICLE;
case MU_NNTP_ARTICLE:
@@ -82,31 +82,12 @@ mu_nntp_article_id (mu_nntp_t nntp, const char *message_id, unsigned long *pnum,
status = mu_nntp_response (nntp, NULL, 0, NULL);
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
- MU_NNTP_CHECK_OK (nntp);
+ MU_NNTP_CHECK_CODE(nntp, MU_NNTP_RESP_CODE_ARTICLE_FOLLOW);
nntp->state = MU_NNTP_ARTICLE_RX;
+
/* parse the answer now. */
- if (pnum == NULL)
- {
- pnum = &dummy;
- }
- buf = calloc(sizeof(*buf), 128);
- if (buf == NULL)
- {
- return ENOMEM;
- }
- sscanf (nntp->ack.buf, "220 %d %127s", pnum, buf);
- if (*buf == '\0')
- {
- strcpy (buf, "<0>");
- }
- if (mid)
- {
- *mid = buf;
- }
- else
- {
- free (buf);
- }
+ status = mu_nntp_parse_article(nntp, MU_NNTP_RESP_CODE_ARTICLE_FOLLOW, pnum, mid);
+ MU_NNTP_CHECK_ERROR (nntp, status);
case MU_NNTP_ARTICLE_RX:
status = mu_nntp_stream_create (nntp, pstream);
@@ -124,3 +105,37 @@ mu_nntp_article_id (mu_nntp_t nntp, const char *message_id, unsigned long *pnum,
return status;
}
+
+int
+mu_nntp_parse_article(mu_nntp_t nntp, int code, unsigned long *pnum, char **mid)
+{
+ unsigned long dummy = 0;
+ char *buf;
+ char format[24];
+
+ if (pnum == NULL)
+ pnum = &dummy;
+
+ /* Message ID should not be longer then 250 and smaller then 3. */
+ buf = calloc(1, 256);
+ if (buf == NULL)
+ {
+ return ENOMEM;
+ }
+
+ sprintf (format, "%d %%ld %%%ds", code, 250);
+ sscanf (nntp->ack.buf, format, pnum, buf);
+ if (*buf == '\0')
+ {
+ strcpy (buf, "<0>"); /* RFC 977 */
+ }
+ if (mid)
+ {
+ *mid = buf;
+ }
+ else
+ {
+ free (buf);
+ }
+ return 0;
+}
diff --git a/mailbox/nntp/nntp_body.c b/mailbox/nntp/nntp_body.c
index 1d3e6d8d8..b13b6528d 100644
--- a/mailbox/nntp/nntp_body.c
+++ b/mailbox/nntp/nntp_body.c
@@ -30,7 +30,7 @@ mu_nntp_body (mu_nntp_t nntp, unsigned long number, unsigned long *pnum, char **
char *message_id = NULL;
if (number != 0)
{
- message_id = malloc(128);
+ message_id = malloc (128);
if (message_id == NULL)
{
return ENOMEM;
@@ -49,8 +49,6 @@ int
mu_nntp_body_id (mu_nntp_t nntp, const char *message_id, unsigned long *pnum, char **mid, stream_t *pstream)
{
int status;
- unsigned long dummy = 0;
- char *buf;
if (nntp == NULL)
return EINVAL;
@@ -69,7 +67,7 @@ mu_nntp_body_id (mu_nntp_t nntp, const char *message_id, unsigned long *pnum, ch
status = mu_nntp_writeline (nntp, "BODY %s\r\n", message_id);
}
MU_NNTP_CHECK_ERROR (nntp, status);
- mu_NNTP_debug_cmd (nntp);
+ mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_BODY;
case MU_NNTP_BODY:
@@ -81,32 +79,15 @@ mu_nntp_body_id (mu_nntp_t nntp, const char *message_id, unsigned long *pnum, ch
case MU_NNTP_BODY_ACK:
status = mu_nntp_response (nntp, NULL, 0, NULL);
MU_NNTP_CHECK_EAGAIN (nntp, status);
+
mu_nntp_debug_ack (nntp);
- MU_NNTP_CHECK_OK (nntp);
- nntp->state = MU_NNTP_BODY_RX;
+ MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_BODY_FOLLOW);
+
/* parse the answer now. */
- if (pnum == NULL)
- {
- pnum = &dummy;
- }
- buf = calloc(1, 128);
- if (buf == NULL)
- {
- return ENOMEM;
- }
- sscanf (nntp->ack.buf, "222 %d %127s", pnum, buf);
- if (*buf == '\0')
- {
- strcpy (buf, "<0>");
- }
- if (mid)
- {
- *mid = buf;
- }
- else
- {
- free (buf);
- }
+ status = mu_nntp_parse_article (nntp, MU_NNTP_RESP_CODE_BODY_FOLLOW, pnum, mid);
+ MU_NNTP_CHECK_ERROR (nntp, status);
+
+ nntp->state = MU_NNTP_BODY_RX;
case MU_NNTP_BODY_RX:
status = mu_nntp_stream_create (nntp, pstream);
diff --git a/mailbox/nntp/nntp_connect.c b/mailbox/nntp/nntp_connect.c
index 3e17fe095..5a56225e4 100644
--- a/mailbox/nntp/nntp_connect.c
+++ b/mailbox/nntp/nntp_connect.c
@@ -63,11 +63,15 @@ mu_nntp_connect (mu_nntp_t nntp)
/* Get the greetings. */
{
size_t len = 0;
+ int code;
char *right, *left;
status = mu_nntp_response (nntp, NULL, 0, &len);
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
- if (nntp->ack.buf[0] == '2')
+ /* 200 Service available, posting allowed */
+ /* 2001 Servie available, posting prohibited */
+ code = mu_nntp_response_code(nntp);
+ if (code == MU_NNTP_RESP_CODE_POSTING_ALLOWED || code == MU_NNTP_RESP_CODE_POSTING_PROHIBITED)
{
stream_close (nntp->carrier);
nntp->state = MU_NNTP_NO_STATE;
diff --git a/mailbox/nntp/nntp_date.c b/mailbox/nntp/nntp_date.c
new file mode 100644
index 000000000..1d22b7e63
--- /dev/null
+++ b/mailbox/nntp/nntp_date.c
@@ -0,0 +1,99 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <errno.h>
+#include <mailutils/sys/nntp.h>
+
+int
+mu_nntp_date (mu_nntp_t nntp, unsigned int *year, unsigned int *month, unsigned int *day,
+ unsigned int *hour, unsigned int *min, unsigned int *sec)
+{
+ int status;
+ unsigned long dummy = 0;
+ char *buf;
+
+ if (nntp == NULL)
+ return EINVAL;
+
+ switch (nntp->state)
+ {
+ case MU_NNTP_NO_STATE:
+ status = mu_nntp_writeline (nntp, "DATE\r\n");
+ MU_NNTP_CHECK_ERROR (nntp, status);
+ mu_nntp_debug_cmd (nntp);
+ nntp->state = MU_NNTP_DATE;
+
+ case MU_NNTP_DATE:
+ status = mu_nntp_send (nntp);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+ nntp->acknowledge = 0;
+ nntp->state = MU_NNTP_DATE_ACK;
+
+ case MU_NNTP_DATE_ACK:
+ status = mu_nntp_response (nntp, NULL, 0, NULL);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+ mu_nntp_debug_ack (nntp);
+ MU_NNTP_CHECK_CODE(nntp, MU_NNTP_RESP_CODE_SERVER_DATE);
+ nntp->state = MU_NNTP_NO_STATE;
+
+ /* parse the answer now. */
+ status = mu_parse_date(nntp, MU_NNTP_RESP_CODE_SERVER_DATE, year, month, day, hour, min, sec);
+ MU_NNTP_CHECK_ERROR (nntp, status);
+ break;
+
+ /* They must deal with the error first by reopening. */
+ case MU_NNTP_ERROR:
+ status = ECANCELED;
+ break;
+
+ default:
+ status = EINPROGRESS;
+ }
+
+ return status;
+}
+
+static int
+mu_nntp_parse_date (mu_nntp_t nntp, int code, unsigned int *year, unsigned int *month, unsigned int *day,
+ unsigned int *hour, unsigned int *min, unsigned int *sec)
+{
+ unsigned int dummy = 0;
+ char *buf;
+ char format[32];
+
+ if (year == NULL)
+ year = &dummy;
+ if (month == NULL)
+ month = &dummy;
+ if (day == NULL)
+ day = &dummy;
+ if (hour == NULL)
+ hour = &dummy;
+ if (min == NULL)
+ min = &dummy;
+ if (sec == NULL)
+ sec = &dummy;
+
+ sprintf (format, "%d %%4d%%2d%%2d%%2d%%2d%%2d", code);
+ sscanf (nntp->ack.buf, format, year, month, day, hour, min, sec);
+ return 0;
+}
diff --git a/mailbox/nntp/nntp_group.c b/mailbox/nntp/nntp_group.c
new file mode 100644
index 000000000..534f6396b
--- /dev/null
+++ b/mailbox/nntp/nntp_group.c
@@ -0,0 +1,108 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <mailutils/sys/nntp.h>
+
+int
+mu_nntp_group (mu_nntp_t nntp, const char *group, unsigned long *total, unsigned long *low, unsigned long *high, char **name)
+{
+ int status;
+
+ if (nntp == NULL)
+ return EINVAL;
+ if (group == NULL || *group == '\0')
+ return MU_ERR_OUT_PTR_NULL;
+
+ switch (nntp->state)
+ {
+ case MU_NNTP_NO_STATE:
+ status = mu_nntp_writeline (nntp, "GROUP %s\r\n", group);
+ MU_NNTP_CHECK_ERROR (nntp, status);
+ mu_nntp_debug_cmd (nntp);
+ nntp->state = MU_NNTP_GROUP;
+
+ case MU_NNTP_GROUP:
+ status = mu_nntp_send (nntp);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+ nntp->acknowledge = 0;
+ nntp->state = MU_NNTP_GROUP_ACK;
+
+ case MU_NNTP_GROUP_ACK:
+ status = mu_nntp_response (nntp, NULL, 0, NULL);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+ mu_nntp_debug_ack (nntp);
+ MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_GROUP_SELECTED);
+ nntp->state = MU_NNTP_NO_STATE;
+
+ /* parse group. */
+ status = mu_nntp_parse_group (nntp, MU_NNTP_RESP_CODE_GROUP_SELECTED, total, low, high, name);
+ MU_NNTP_CHECK_ERROR (nntp, status);
+ break;
+
+ /* They must deal with the error first by reopening. */
+ case MU_NNTP_ERROR:
+ status = ECANCELED;
+ break;
+
+ default:
+ status = EINPROGRESS;
+ }
+
+ return status;
+}
+
+
+int
+mu_nntp_parse_group(mu_nntp_t nntp, int code, unsigned long *ptotal, unsigned long *plow, unsigned long *phigh, char **name)
+{
+ unsigned long dummy = 0;
+ char *buf;
+ char format[24];
+
+ if (ptotal == NULL)
+ ptotal = &dummy;
+ if (plow == NULL)
+ plow = &dummy;
+ if (phigh == NULL)
+ phigh = &dummy;
+
+ /* An nntp response is not longer then 512. */
+ buf = calloc(1, 512);
+ if (buf == NULL)
+ {
+ return ENOMEM;
+ }
+
+ sprintf (format, "%d %%d %%d %%d %%%ds", code, 511);
+ sscanf (nntp->ack.buf, format, ptotal, plow, phigh, buf);
+ if (name)
+ {
+ *name = buf;
+ }
+ else
+ {
+ free (buf);
+ }
+ return 0;
+}
diff --git a/mailbox/nntp/nntp_head.c b/mailbox/nntp/nntp_head.c
index 5a1f6ee28..4504af264 100644
--- a/mailbox/nntp/nntp_head.c
+++ b/mailbox/nntp/nntp_head.c
@@ -69,7 +69,7 @@ mu_nntp_head_id (mu_nntp_t nntp, const char *message_id, unsigned long *pnum, ch
status = mu_nntp_writeline (nntp, "HEAD %s\r\n", message_id);
}
MU_NNTP_CHECK_ERROR (nntp, status);
- mu_NNTP_debug_cmd (nntp);
+ mu_nntp_debug_cmd (nntp);
nntp->state = MU_NNTP_HEAD;
case MU_NNTP_HEAD:
@@ -82,31 +82,12 @@ mu_nntp_head_id (mu_nntp_t nntp, const char *message_id, unsigned long *pnum, ch
status = mu_nntp_response (nntp, NULL, 0, NULL);
MU_NNTP_CHECK_EAGAIN (nntp, status);
mu_nntp_debug_ack (nntp);
- MU_NNTP_CHECK_OK (nntp);
+ MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_HEAD_FOLLOW);
nntp->state = MU_NNTP_HEAD_RX;
+
/* parse the answer now. */
- if (pnum == NULL)
- {
- pnum = &dummy;
- }
- buf = calloc(sizeof(*buf), 128);
- if (buf == NULL)
- {
- return ENOMEM;
- }
- sscanf (nntp->ack.buf, "221 %d %127s", pnum, buf);
- if (*buf == '\0')
- {
- strcpy(buf, "<0>");
- }
- if (mid)
- {
- *mid = buf;
- }
- else
- {
- free (buf);
- }
+ status = mu_nntp_parse_article (nntp, MU_NNTP_RESP_CODE_HEAD_FOLLOW, pnum, mid);
+ MU_NNTP_CHECK_ERROR (nntp, status);
case MU_NNTP_HEAD_RX:
status = mu_nntp_stream_create (nntp, pstream);
diff --git a/mailbox/nntp/nntp_last.c b/mailbox/nntp/nntp_last.c
new file mode 100644
index 000000000..326113451
--- /dev/null
+++ b/mailbox/nntp/nntp_last.c
@@ -0,0 +1,72 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <mailutils/sys/nntp.h>
+
+int
+mu_nntp_last (mu_nntp_t nntp, unsigned long *number, char **mid)
+{
+ int status;
+
+ if (nntp == NULL)
+ return EINVAL;
+
+ switch (nntp->state)
+ {
+ case MU_NNTP_NO_STATE:
+ status = mu_nntp_writeline (nntp, "LAST\r\n");
+ MU_NNTP_CHECK_ERROR (nntp, status);
+ mu_nntp_debug_cmd (nntp);
+ nntp->state = MU_NNTP_LAST;
+
+ case MU_NNTP_LAST:
+ status = mu_nntp_send (nntp);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+ nntp->acknowledge = 0;
+ nntp->state = MU_NNTP_LAST_ACK;
+
+ case MU_NNTP_LAST_ACK:
+ status = mu_nntp_response (nntp, NULL, 0, NULL);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+ mu_nntp_debug_ack (nntp);
+ MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_ARTICLE_FOUND);
+ nntp->state = MU_NNTP_NO_STATE;
+
+ status = mu_nntp_parse_article (nntp, MU_NNTP_RESP_CODE_ARTICLE_FOUND, number, mid);
+ MU_NNTP_CHECK_ERROR (nntp, status);
+
+ break;
+
+ /* They must deal with the error first by reopening. */
+ case MU_NNTP_ERROR:
+ status = ECANCELED;
+ break;
+
+ default:
+ status = EINPROGRESS;
+ }
+
+ return status;
+}
+
diff --git a/mailbox/nntp/nntp_list_extensions.c b/mailbox/nntp/nntp_list_extensions.c
new file mode 100644
index 000000000..10154bf81
--- /dev/null
+++ b/mailbox/nntp/nntp_list_extensions.c
@@ -0,0 +1,110 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <mailutils/error.h>
+#include <mailutils/sys/nntp.h>
+
+/*
+ LIST EXTENSIONS command, return a list that contains the result.
+ It is the responsability of the caller to destroy the list(list_destroy).
+ */
+int
+mu_nntp_list_extensions (mu_nntp_t nntp, list_t *plist)
+{
+ int status;
+
+ if (nntp == NULL)
+ return EINVAL;
+ if (plist == NULL)
+ return MU_ERR_OUT_PTR_NULL;
+
+ switch (nntp->state)
+ {
+ case MU_NNTP_NO_STATE:
+ status = mu_nntp_writeline (nntp, "LIST EXTENSIONS\r\n");
+ MU_NNTP_CHECK_ERROR (nntp, status);
+ mu_nntp_debug_cmd (nntp);
+ nntp->state = MU_NNTP_LIST_EXTENSIONS;
+
+ case MU_NNTP_LIST_EXTENSIONS:
+ status = mu_nntp_send (nntp);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+ nntp->acknowledge = 0;
+ nntp->state = MU_NNTP_LIST_EXTENSIONS_ACK;
+
+ case MU_NNTP_LIST_EXTENSIONS_ACK:
+ status = mu_nntp_response (nntp, NULL, 0, NULL);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+ mu_nntp_debug_ack (nntp);
+ MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_LIST_FOLLOW);
+ status = list_create (plist);
+ MU_NNTP_CHECK_ERROR(nntp, status);
+ list_set_destroy_item(*plist, free);
+ nntp->state = MU_NNTP_LIST_EXTENSIONS_RX;
+
+ case MU_NNTP_LIST_EXTENSIONS_RX:
+ {
+ /* CAPA line are 512 octets maximum according to RFC 2449.
+ But do not use the stack and malloc. */
+ char *capability;
+ size_t n = 0;
+
+ capability = malloc (512);
+ if (capability == NULL)
+ {
+ /* MU_NNTP_CHECK_ERROR(nntp, ENOMEM);
+ We need to destroy the list if error. */
+ nntp->io.ptr = nntp->io.buf;
+ nntp->state = MU_NNTP_ERROR;
+ list_destroy (*plist);
+ return ENOMEM;
+ }
+ while ((status = mu_nntp_readline (nntp, capability, 512, &n)) == 0 && n > 0)
+ {
+ /* Nuke the trailing newline */
+ if (capability[n - 1] == '\n')
+ capability[n - 1] = '\0';
+ /* add to the list. */
+ list_append (*plist, strdup (capability));
+ n = 0;
+ }
+ free (capability);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+ nntp->state = MU_NNTP_NO_STATE;
+ break;
+ }
+
+ /* They must deal with the error first by reopening. */
+ case MU_NNTP_ERROR:
+ status = ECANCELED;
+ break;
+
+ default:
+ status = EINPROGRESS;
+ }
+
+ return status;
+}
diff --git a/mailbox/nntp/nntp_mode_reader.c b/mailbox/nntp/nntp_mode_reader.c
new file mode 100644
index 000000000..c5c4e90da
--- /dev/null
+++ b/mailbox/nntp/nntp_mode_reader.c
@@ -0,0 +1,66 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <errno.h>
+#include <mailutils/sys/nntp.h>
+
+int
+mu_nntp_mode_reader (mu_nntp_t nntp)
+{
+ int status;
+
+ if (nntp == NULL)
+ return EINVAL;
+
+ switch (nntp->state)
+ {
+ case MU_NNTP_NO_STATE:
+ status = mu_nntp_writeline (nntp, "MODE READER\r\n");
+ MU_NNTP_CHECK_ERROR (nntp, status);
+ mu_nntp_debug_cmd (nntp);
+ nntp->state = MU_NNTP_MODE_READER;
+
+ case MU_NNTP_MODE_READER:
+ status = mu_nntp_send (nntp);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+ nntp->acknowledge = 0;
+ nntp->state = MU_NNTP_MODE_READER_ACK;
+
+ case MU_NNTP_MODE_READER_ACK:
+ status = mu_nntp_response (nntp, NULL, 0, NULL);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+ mu_nntp_debug_ack (nntp);
+ MU_NNTP_CHECK_CODE2(nntp, MU_NNTP_RESP_CODE_POSTING_ALLOWED, MU_NNTP_RESP_CODE_POSTING_PROHIBITED);
+ nntp->state = MU_NNTP_NO_STATE;
+ break;
+
+ /* They must deal with the error first by reopening. */
+ case MU_NNTP_ERROR:
+ status = ECANCELED;
+ break;
+
+ default:
+ status = EINPROGRESS;
+ }
+
+ return status;
+}
diff --git a/mailbox/nntp/nntp_next.c b/mailbox/nntp/nntp_next.c
new file mode 100644
index 000000000..3e827d312
--- /dev/null
+++ b/mailbox/nntp/nntp_next.c
@@ -0,0 +1,72 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <mailutils/sys/nntp.h>
+
+int
+mu_nntp_next (mu_nntp_t nntp, unsigned long *number, char **mid)
+{
+ int status;
+
+ if (nntp == NULL)
+ return EINVAL;
+
+ switch (nntp->state)
+ {
+ case MU_NNTP_NO_STATE:
+ status = mu_nntp_writeline (nntp, "NEXT\r\n");
+ MU_NNTP_CHECK_ERROR (nntp, status);
+ mu_nntp_debug_cmd (nntp);
+ nntp->state = MU_NNTP_NEXT;
+
+ case MU_NNTP_NEXT:
+ status = mu_nntp_send (nntp);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+ nntp->acknowledge = 0;
+ nntp->state = MU_NNTP_NEXT_ACK;
+
+ case MU_NNTP_NEXT_ACK:
+ status = mu_nntp_response (nntp, NULL, 0, NULL);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+ mu_nntp_debug_ack (nntp);
+ MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_ARTICLE_FOUND);
+ nntp->state = MU_NNTP_NO_STATE;
+
+ status = mu_nntp_parse_article (nntp, MU_NNTP_RESP_CODE_ARTICLE_FOUND, number, mid);
+ MU_NNTP_CHECK_ERROR (nntp, status);
+
+ break;
+
+ /* They must deal with the error first by reopening. */
+ case MU_NNTP_ERROR:
+ status = ECANCELED;
+ break;
+
+ default:
+ status = EINPROGRESS;
+ }
+
+ return status;
+}
+
diff --git a/mailbox/nntp/nntp_quit.c b/mailbox/nntp/nntp_quit.c
new file mode 100644
index 000000000..b1f00a344
--- /dev/null
+++ b/mailbox/nntp/nntp_quit.c
@@ -0,0 +1,61 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <errno.h>
+#include <mailutils/sys/nntp.h>
+
+int
+mu_nntp_quit (mu_nntp_t nntp)
+{
+ int status;
+
+ if (nntp == NULL)
+ return EINVAL;
+
+ switch (nntp->state)
+ {
+ case MU_NNTP_NO_STATE:
+ status = mu_nntp_writeline (nntp, "QUIT\r\n");
+ MU_NNTP_CHECK_ERROR (nntp, status);
+ mu_nntp_debug_cmd (nntp);
+ nntp->state = MU_NNTP_QUIT;
+
+ case MU_NNTP_QUIT:
+ status = mu_nntp_send (nntp);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+ nntp->acknowledge = 0;
+ nntp->state = MU_NNTP_QUIT_ACK;
+
+ case MU_NNTP_QUIT_ACK:
+ status = mu_nntp_response (nntp, NULL, 0, NULL);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+ mu_nntp_debug_ack (nntp);
+ MU_NNTP_CHECK_CODE (nntp, MU_NNTP_RESP_CODE_CLOSING);
+ nntp->state = MU_NNTP_NO_STATE;
+ break;
+
+ default:
+ status = EINPROGRESS;
+ }
+
+ return status;
+}
diff --git a/mailbox/nntp/nntp_response.c b/mailbox/nntp/nntp_response.c
index a943a8743..86ecc7d7d 100644
--- a/mailbox/nntp/nntp_response.c
+++ b/mailbox/nntp/nntp_response.c
@@ -20,6 +20,7 @@
#endif
#include <string.h>
+#include <stdlib.h>
#include <errno.h>
#include <mailutils/sys/nntp.h>
@@ -70,3 +71,16 @@ mu_nntp_response (mu_nntp_t nntp, char *buffer, size_t buflen, size_t *pnread)
*pnread = n;
return status;
}
+
+int
+mu_nntp_response_code(mu_nntp_t nntp)
+{
+ char buffer[4];
+ int code;
+
+ memset (buffer, '\0', 4);
+ mu_nntp_response(nntp, buffer, 4, NULL);
+ /* translate the number, basically strtol() without the overhead. */
+ code = (buffer[0] - '0')*100 + (buffer[1] - '0')*10 + (buffer[2] - '0');
+ return code;
+}
diff --git a/mailbox/nntp/nntp_stat.c b/mailbox/nntp/nntp_stat.c
new file mode 100644
index 000000000..0df9d3514
--- /dev/null
+++ b/mailbox/nntp/nntp_stat.c
@@ -0,0 +1,99 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <errno.h>
+#include <mailutils/sys/nntp.h>
+
+int
+mu_nntp_stat (mu_nntp_t nntp, unsigned long number, unsigned long *pnumber, char **mid)
+{
+ int status;
+ char *message_id = NULL;
+ if (number != 0)
+ {
+ message_id = malloc (128);
+ if (message_id == NULL)
+ {
+ return ENOMEM;
+ }
+ snprintf (message_id, 127, "%ld", number);
+ }
+ status = mu_nntp_stat_id (nntp, message_id, pnumber, mid);
+ if (message_id)
+ {
+ free (message_id);
+ }
+ return status;
+}
+
+int
+mu_nntp_stat_id (mu_nntp_t nntp, const char *message_id, unsigned long *number, char **mid)
+{
+ int status;
+
+ if (nntp == NULL)
+ return EINVAL;
+
+ switch (nntp->state)
+ {
+ case MU_NNTP_NO_STATE:
+ if (message_id == NULL || *message_id == '\0')
+ {
+ status = mu_nntp_writeline (nntp, "STAT\r\n");
+ }
+ else
+ {
+ status = mu_nntp_writeline (nntp, "STAT %s\r\n", message_id);
+ }
+ MU_NNTP_CHECK_ERROR (nntp, status);
+ mu_nntp_debug_cmd (nntp);
+ nntp->state = MU_NNTP_STAT;
+
+ case MU_NNTP_STAT:
+ status = mu_nntp_send (nntp);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+