summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlain Magloire <alainm@gnu.org>2004-06-13 02:52:13 +0000
committerAlain Magloire <alainm@gnu.org>2004-06-13 02:52:13 +0000
commitf50de094ab26e6e81438d056e31236e776e4dc65 (patch)
tree887ac1f9f92ce476449c77fe974f3c16aae648b8
parentfcba09634592afea9d4f8e0f05d6baabbd8acd23 (diff)
downloadmailutils-f50de094ab26e6e81438d056e31236e776e4dc65.tar.gz
mailutils-f50de094ab26e6e81438d056e31236e776e4dc65.tar.bz2
nntp_carrier.c nntp_connect.c nntp_create.c nntp_debug.c
nntp_destroy.c nntp_disconnect.c nntp_readline.c nntp_response.c nntp_sendline.c nntp_stream.c nntp_timeout.c framework for NNTP support
-rw-r--r--mailbox/nntp/nntp_carrier.c55
-rw-r--r--mailbox/nntp/nntp_connect.c81
-rw-r--r--mailbox/nntp/nntp_create.c72
-rw-r--r--mailbox/nntp/nntp_debug.c53
-rw-r--r--mailbox/nntp/nntp_destroy.c49
-rw-r--r--mailbox/nntp/nntp_disconnect.c47
-rw-r--r--mailbox/nntp/nntp_readline.c191
-rw-r--r--mailbox/nntp/nntp_response.c72
-rw-r--r--mailbox/nntp/nntp_sendline.c120
-rw-r--r--mailbox/nntp/nntp_stream.c145
-rw-r--r--mailbox/nntp/nntp_timeout.c48
11 files changed, 933 insertions, 0 deletions
diff --git a/mailbox/nntp/nntp_carrier.c b/mailbox/nntp/nntp_carrier.c
new file mode 100644
index 000000000..42ba82a1f
--- /dev/null
+++ b/mailbox/nntp/nntp_carrier.c
@@ -0,0 +1,55 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <mailutils/sys/nntp.h>
+
+int
+mu_nntp_set_carrier (mu_nntp_t nntp, stream_t carrier)
+{
+ /* Sanity checks. */
+ if (nntp == NULL)
+ return EINVAL;
+
+ if (nntp->carrier)
+ {
+ /* Close any old carrier. */
+ mu_nntp_disconnect (nntp);
+ stream_destroy (&nntp->carrier, nntp);
+ }
+ nntp->carrier = carrier;
+ return 0;
+}
+
+int
+mu_nntp_get_carrier (mu_nntp_t nntp, stream_t *pcarrier)
+{
+ /* Sanity checks. */
+ if (nntp == NULL)
+ return EINVAL;
+ if (pcarrier == NULL)
+ return MU_ERR_OUT_PTR_NULL;
+
+ *pcarrier = nntp->carrier;
+ return 0;
+}
diff --git a/mailbox/nntp/nntp_connect.c b/mailbox/nntp/nntp_connect.c
new file mode 100644
index 000000000..3e17fe095
--- /dev/null
+++ b/mailbox/nntp/nntp_connect.c
@@ -0,0 +1,81 @@
+/* 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 <sys/time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <mailutils/sys/nntp.h>
+
+/* Open the connection to the server. */
+int
+mu_nntp_connect (mu_nntp_t nntp)
+{
+ int status;
+
+ /* Sanity checks. */
+ if (nntp == NULL)
+ return EINVAL;
+
+ /* A networking stack. */
+ if (nntp->carrier == NULL)
+ return EINVAL;
+
+ /* Enter the pop state machine, and boogy: AUTHORISATION State. */
+ switch (nntp->state)
+ {
+ default:
+ /* FALLTHROUGH */
+ /* If nntp was in an error state going through here should clear it. */
+
+ case MU_NNTP_NO_STATE:
+ status = mu_nntp_disconnect (nntp);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+ nntp->state = MU_NNTP_CONNECT;
+
+ case MU_NNTP_CONNECT:
+ /* Establish the connection. */
+ status = stream_open (nntp->carrier);
+ MU_NNTP_CHECK_EAGAIN (nntp, status);
+ nntp->acknowledge = 0;
+ nntp->state = MU_NNTP_GREETINGS;
+
+ case MU_NNTP_GREETINGS:
+ /* Get the greetings. */
+ {
+ size_t len = 0;
+ 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')
+ {
+ stream_close (nntp->carrier);
+ nntp->state = MU_NNTP_NO_STATE;
+ return EACCES;
+ }
+ nntp->state = MU_NNTP_NO_STATE;
+ }
+ } /* End AUTHORISATION state. */
+
+ return status;
+}
diff --git a/mailbox/nntp/nntp_create.c b/mailbox/nntp/nntp_create.c
new file mode 100644
index 000000000..5e2d85850
--- /dev/null
+++ b/mailbox/nntp/nntp_create.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 <stdlib.h>
+#include <errno.h>
+#include <mailutils/errno.h>
+#include <mailutils/sys/nntp.h>
+
+/* Initialise a mu_nntp_t handle. */
+
+int
+mu_nntp_create (mu_nntp_t *pnntp)
+{
+ mu_nntp_t nntp;
+
+ /* Sanity check. */
+ if (pnntp == NULL)
+ return EINVAL;
+
+ nntp = calloc (1, sizeof *nntp);
+ if (nntp == NULL)
+ return ENOMEM;
+
+ /* Reserve space for the ack(nowledgement) response.
+ According to RFC 977: The maximum length of the first line of a
+ command response (including the initial greeting) is unchanged at
+ 512 octets (including the terminating CRLF). */
+ nntp->ack.len = 512;
+ nntp->ack.buf = calloc (nntp->ack.len, 1);
+ if (nntp->ack.buf == NULL)
+ {
+ mu_nntp_destroy (&nntp);
+ return ENOMEM;
+ }
+ nntp->ack.ptr = nntp->ack.buf;
+
+ /* Reserve space for the data response/content.
+ RFC 977 recommands 255, but we grow it as needed. */
+ nntp->io.len = 255;
+ nntp->io.buf = calloc (nntp->io.len, 1);
+ if (nntp->io.buf == NULL)
+ {
+ mu_nntp_destroy (&nntp);
+ return ENOMEM;
+ }
+ nntp->io.ptr = nntp->io.buf;
+
+ nntp->state = MU_NNTP_NO_STATE; /* Init with no state. */
+ nntp->timeout = (10 * 60) * 100; /* The default Timeout is 10 minutes. */
+ nntp->acknowledge = 0; /* No Ack received. */
+
+ *pnntp = nntp;
+ return 0; /* Okdoke. */
+}
diff --git a/mailbox/nntp/nntp_debug.c b/mailbox/nntp/nntp_debug.c
new file mode 100644
index 000000000..e18664fb1
--- /dev/null
+++ b/mailbox/nntp/nntp_debug.c
@@ -0,0 +1,53 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <mailutils/sys/nntp.h>
+
+int
+mu_nntp_set_debug (mu_nntp_t nntp, mu_debug_t debug)
+{
+ if (nntp == NULL)
+ return EINVAL;
+ if (nntp->debug)
+ mu_debug_destroy (&nntp->debug, NULL);
+ nntp->debug = debug;
+ return 0;
+}
+
+int
+mu_nntp_debug_cmd (mu_nntp_t nntp)
+{
+ if (nntp->debug)
+ mu_debug_print(nntp->debug, MU_DEBUG_PROT, "%s", nntp->io.buf);
+ return 0;
+}
+
+int
+mu_nntp_debug_ack (mu_nntp_t nntp)
+{
+ if (nntp->debug)
+ {
+ mu_debug_print (nntp->debug, MU_DEBUG_PROT, "%s\n", nntp->ack.buf);
+ }
+ return 0;
+}
diff --git a/mailbox/nntp/nntp_destroy.c b/mailbox/nntp/nntp_destroy.c
new file mode 100644
index 000000000..a70df8168
--- /dev/null
+++ b/mailbox/nntp/nntp_destroy.c
@@ -0,0 +1,49 @@
+/* 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 <stdlib.h>
+#include <mailutils/errno.h>
+#include <mailutils/sys/nntp.h>
+
+void
+mu_nntp_destroy (mu_nntp_t *pnntp)
+{
+ if (pnntp && *pnntp)
+ {
+ mu_nntp_t nntp = *pnntp;
+
+ /* Free the response buffer. */
+ if (nntp->ack.buf)
+ free (nntp->ack.buf);
+
+ /* Free the io buffer. */
+ if (nntp->io.buf)
+ free (nntp->io.buf);
+
+ /* Release the carrier. */
+ if (nntp->carrier)
+ stream_destroy (&nntp->carrier, nntp);
+
+ free (nntp);
+
+ *pnntp = NULL;
+ }
+}
diff --git a/mailbox/nntp/nntp_disconnect.c b/mailbox/nntp/nntp_disconnect.c
new file mode 100644
index 000000000..00b0ff7a1
--- /dev/null
+++ b/mailbox/nntp/nntp_disconnect.c
@@ -0,0 +1,47 @@
+/* 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 <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <mailutils/sys/nntp.h>
+
+int
+mu_nntp_disconnect (mu_nntp_t nntp)
+{
+ /* Sanity checks. */
+ if (nntp == NULL)
+ return EINVAL;
+
+ /* We can keep some of the fields, if they decide to nntp_connect() again but
+ clear the states. */
+ nntp->state = MU_NNTP_NO_STATE;
+ nntp->acknowledge = 0;
+
+ /* Clear the buffers. */
+ memset (nntp->io.buf, '\0', nntp->io.len);
+ nntp->io.ptr = nntp->io.buf;
+ memset (nntp->ack.buf, '\0', nntp->ack.len);
+ nntp->ack.ptr = nntp->ack.buf;
+
+ /* Close the stream. */
+ return stream_close (nntp->carrier);
+}
diff --git a/mailbox/nntp/nntp_readline.c b/mailbox/nntp/nntp_readline.c
new file mode 100644
index 000000000..ba2125ef5
--- /dev/null
+++ b/mailbox/nntp/nntp_readline.c
@@ -0,0 +1,191 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <errno.h>
+#include <mailutils/sys/nntp.h>
+#include <mailutils/error.h>
+
+int
+mu_nntp_carrier_is_ready (stream_t carrier, int flag, int timeout)
+{
+ struct timeval tv, *tvp = NULL;
+ int wflags = flag;
+ int status;
+
+ if (timeout >= 0)
+ {
+ tv.tv_sec = timeout / 100;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ tvp = &tv;
+ }
+ status = stream_wait (carrier, &wflags, tvp);
+ if (status)
+ return 0; /* FIXME: provide a way to return error code! */
+ return wflags & flag;
+}
+
+/* Read a complete line from the nntp server. Transform CRLF to LF, remove
+ the stuff byte termination octet ".", put a null in the buffer
+ when done. And Do a select() (stream_is_readready()) for the timeout. */
+static int
+mu_nntp_getline (mu_nntp_t nntp)
+{
+ size_t n = 0;
+ size_t total = nntp->io.ptr - nntp->io.buf;
+ int status = 0;
+
+ /* Must get a full line before bailing out. */
+ do
+ {
+ /* Timeout with select(), note that we have to reset select()
+ since on linux tv is modified when error. */
+ if (nntp->timeout)
+ {
+ int ready = mu_nntp_carrier_is_ready (nntp->carrier,
+ MU_STREAM_READY_RD,
+ nntp->timeout);
+ if (ready == 0)
+ return ETIMEDOUT;
+ }
+
+ status = stream_sequential_readline (nntp->carrier, nntp->io.buf + total, nntp->io.len - total, &n);
+ if (status != 0)
+ return status;
+
+ /* The server went away: It maybe a timeout and some nntp server
+ does not send the -ERR. Consider this like an error. */
+ if (n == 0)
+ return EIO;
+
+ total += n;
+ nntp->io.nl = memchr (nntp->io.buf, '\n', total);
+ if (nntp->io.nl == NULL) /* Do we have a full line. */
+ {
+ /* Allocate a bigger buffer ? */
+ if (total >= nntp->io.len - 1)
+ {
+ nntp->io.len *= 2;
+ nntp->io.buf = realloc (nntp->io.buf, nntp->io.len + 1);
+ if (nntp->io.buf == NULL)
+ return ENOMEM;
+ }
+ }
+ nntp->io.ptr = nntp->io.buf + total;
+ }
+ while (nntp->io.nl == NULL); /* Bail only if we have a complete line. */
+
+ /* When examining a multi-line response, the client checks to see if the
+ line begins with the termination octet "."(DOT). If yes and if octets
+ other than CRLF follow, the first octet of the line (the termination
+ octet) is stripped away. */
+ if (total >= 3 && nntp->io.buf[0] == '.')
+ {
+ if (nntp->io.buf[1] != '\r' && nntp->io.buf[2] != '\n')
+ {
+ memmove (nntp->io.buf, nntp->io.buf + 1, total - 1);
+ nntp->io.ptr--;
+ nntp->io.nl--;
+ }
+ /* And if CRLF immediately follows the termination character, then
+ the response from the NNTP server is ended and the line containing
+ ".CRLF" is not considered part of the multi-line response. */
+ else if (nntp->io.buf[1] == '\r' && nntp->io.buf[2] == '\n')
+ {
+ nntp->io.buf[0] = '\0';
+ nntp->io.ptr = nntp->io.buf;
+ nntp->io.nl = NULL;
+ }
+ }
+ /* \r\n --> \n\0, conversion. */
+ if (nntp->io.nl > nntp->io.buf)
+ {
+ *(nntp->io.nl - 1) = '\n';
+ *(nntp->io.nl) = '\0';
+ nntp->io.ptr = nntp->io.nl;
+ }
+ return status;
+}
+
+/* Call nntp_getline() for the dirty work, and consume i.e. put
+ in the user buffer only buflen. If buflen == 0 or buffer == NULL
+ nothing is consume, the data is save for another call to nntp_readline()
+ with a buffer != NULL.
+ */
+int
+mu_nntp_readline (mu_nntp_t nntp, char *buffer, size_t buflen, size_t *pnread)
+{
+ size_t nread = 0;
+ size_t n = 0;
+ int status = 0;
+
+ /* Do we need to fill up? Yes if no NL or the buffer is empty. */
+ if (nntp->carrier && (nntp->io.nl == NULL || nntp->io.ptr == nntp->io.buf))
+ {
+ status = mu_nntp_getline (nntp);
+ if (status != 0)
+ return status;
+ }
+
+ /* How much we can copy ? */
+ n = nntp->io.ptr - nntp->io.buf;
+
+ /* Consume the line? */
+ if (buffer && buflen)
+ {
+ buflen--; /* For the null. */
+ if (buflen)
+ {
+ int nleft = buflen - n;
+ /* We got more then requested. */
+ if (nleft < 0)
+ {
+ size_t sentinel;
+ nread = buflen;
+ sentinel = nntp->io.ptr - (nntp->io.buf + nread);
+ memcpy (buffer, nntp->io.buf, nread);
+ memmove (nntp->io.buf, nntp->io.buf + nread, sentinel);
+ nntp->io.ptr = nntp->io.buf + sentinel;
+ }
+ else
+ {
+ /* Drain our buffer. */;
+ nread = n;
+ memcpy (buffer, nntp->io.buf, nread);
+ nntp->io.ptr = nntp->io.buf;
+ /* Clear of all residue. */
+ memset (nntp->io.buf, '\0', nntp->io.len);
+ }
+ }
+ buffer[nread] = '\0';
+ }
+ else
+ nread = n;
+
+ if (pnread)
+ *pnread = nread;
+ return status;
+}
diff --git a/mailbox/nntp/nntp_response.c b/mailbox/nntp/nntp_response.c
new file mode 100644
index 000000000..a943a8743
--- /dev/null
+++ b/mailbox/nntp/nntp_response.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 <mailutils/sys/nntp.h>
+
+/* If we did not grap the ack already, call nntp_readline() but handle
+ Nonblocking also. */
+int
+mu_nntp_response (mu_nntp_t nntp, char *buffer, size_t buflen, size_t *pnread)
+{
+ size_t n = 0;
+ int status = 0;
+
+ if (nntp == NULL)
+ return EINVAL;
+
+ if (!nntp->acknowledge)
+ {
+ size_t len = nntp->ack.len - (nntp->ack.ptr - nntp->ack.buf);
+ status = mu_nntp_readline (nntp, nntp->ack.ptr, len, &n);
+ nntp->ack.ptr += n;
+ if (status == 0)
+ {
+ len = nntp->ack.ptr - nntp->ack.buf;
+ if (len && nntp->ack.buf[len - 1] == '\n')
+ nntp->ack.buf[len - 1] = '\0';
+ nntp->acknowledge = 1; /* Flag that we have the ack. */
+ nntp->ack.ptr = nntp->ack.buf;
+ }
+ else
+ {
+ /* Provide them with an error. */
+ const char *econ = "500 NNTP IO ERROR";
+ n = strlen (econ);
+ strcpy (nntp->ack.buf, econ);
+ }
+ }
+ else
+ n = strlen (nntp->ack.buf);
+
+ if (buffer)
+ {
+ buflen--; /* Leave space for the NULL. */
+ n = (buflen < n) ? buflen : n;
+ memcpy (buffer, nntp->ack.buf, n);
+ buffer[n] = '\0';
+ }
+
+ if (pnread)
+ *pnread = n;
+ return status;
+}
diff --git a/mailbox/nntp/nntp_sendline.c b/mailbox/nntp/nntp_sendline.c
new file mode 100644
index 000000000..e2a3cb09a
--- /dev/null
+++ b/mailbox/nntp/nntp_sendline.c
@@ -0,0 +1,120 @@
+/* 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
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <errno.h>
+#include <mailutils/sys/nntp.h>
+
+/* A socket may write less then expected but stream.c:stream_write() will
+ always try to send the entire buffer unless an error is reported. We have
+ to cope with nonblocking, it is done by keeping track with the nntp->ptr
+ pointer if the write failed we keep track and restart where we left. */
+int
+mu_nntp_send (mu_nntp_t nntp)
+{
+ int status = 0;
+ if (nntp->carrier && (nntp->io.ptr > nntp->io.buf))
+ {
+ size_t n = 0;
+ size_t len = nntp->io.ptr - nntp->io.buf;
+
+ /* Timeout with select(), note that we have to reset select()
+ since on linux tv is modified when error. */
+ if (nntp->timeout)
+ {
+ int ready = mu_nntp_carrier_is_ready (nntp->carrier,
+ MU_STREAM_READY_WR,
+ nntp->timeout);
+ if (ready == 0)
+ return ETIMEDOUT;
+ }
+
+ status = stream_write (nntp->carrier, nntp->io.buf, len, 0, &n);
+ if (n)
+ {
+ /* Consume what we sent. */
+ memmove (nntp->io.buf, nntp->io.buf + n, len - n);
+ nntp->io.ptr -= n;
+ }
+ }
+ else
+ nntp->io.ptr = nntp->io.buf;
+ return status;
+}
+
+/* According to RFC 2449: The maximum length of a command is increased from
+ 47 characters (4 character command, single space, 40 character argument,
+ CRLF) to 255 octets, including the terminating CRLF. But we are flexible
+ on this and realloc() as needed. NOTE: The terminated CRLF is not
+ included. */
+int
+mu_nntp_writeline (mu_nntp_t nntp, const char *format, ...)
+{
+ int len;
+ va_list ap;
+ int done = 1;
+
+ va_start(ap, format);
+ /* C99 says that a conforming implementation of snprintf () should
+ return the number of char that would have been call but many old
+ GNU/Linux && BSD implementations return -1 on error. Worse,
+ QnX/Neutrino actually does not put the terminal null char. So
+ let's try to cope. */
+ do
+ {
+ len = vsnprintf (nntp->io.buf, nntp->io.len - 1, format, ap);
+ if (len < 0 || len >= (int)nntp->io.len
+ || !memchr (nntp->io.buf, '\0', len + 1))
+ {
+ nntp->io.len *= 2;
+ nntp->io.buf = realloc (nntp->io.buf, nntp->io.len);
+ if (nntp->io.buf == NULL)
+ return ENOMEM;
+ done = 0;
+ }
+ else
+ done = 1;
+ }
+ while (!done);
+ va_end(ap);
+ nntp->io.ptr = nntp->io.buf + len;
+ return 0;
+}
+
+int
+mu_nntp_sendline (mu_nntp_t nntp, const char *line)
+{
+ if (line)
+ {
+ int status = mu_nntp_writeline (nntp, line);
+ if (status)
+ return status;
+ }
+ return mu_nntp_send (nntp);
+}
diff --git a/mailbox/nntp/nntp_stream.c b/mailbox/nntp/nntp_stream.c
new file mode 100644
index 000000000..a76f91743
--- /dev/null
+++ b/mailbox/nntp/nntp_stream.c
@@ -0,0 +1,145 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2003, 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>
+
+/* Implementation of the stream for TOP and RETR. */
+struct mu_nntp_stream
+{
+ mu_nntp_t nntp;
+ int done;
+};
+
+static void
+mu_nntp_stream_destroy (stream_t stream)
+{
+ struct mu_nntp_stream *nntp_stream = stream_get_owner (stream);
+ if (nntp_stream)
+ {
+ free (nntp_stream);
+ }
+}
+
+static int
+mu_nntp_stream_read (stream_t stream, char *buf, size_t buflen, off_t offset, size_t *pn)
+{
+ struct mu_nntp_stream *nntp_stream = stream_get_owner (stream);
+ size_t n = 0;
+ int status = 0;
+ char *p = buf;
+
+ (void)offset;
+ if (nntp_stream)
+ {
+ if (!nntp_stream->done)
+ {
+ do
+ {
+ size_t nread = 0;
+
+ /* The nntp_readline () function will always read one less to
+ be able to null terminate the buffer, this will cause
+ serious grief for stream_read() where it is legitimate to
+ have a buffer of 1 char. So we must catch it here. */
+ if (buflen == 1)
+ {
+ char buffer[2];
+ *buffer = '\0';
+ status = mu_nntp_readline (nntp_stream->nntp, buffer, 2, &nread);
+ *p = *buffer;
+ }
+ else
+ status = mu_nntp_readline (nntp_stream->nntp, p, buflen, &nread);
+
+ if (status != 0)
+ break;
+ if (nread == 0)
+ {
+ nntp_stream->nntp->state = MU_NNTP_NO_STATE;
+ nntp_stream->done = 1;
+ break;
+ }
+ n += nread;
+ buflen -= nread;
+ p += nread;
+ }
+ while (buflen > 0);
+ }
+ }
+ if (pn)
+ *pn = n;
+ return status;
+}
+
+static int
+mu_nntp_stream_readline (stream_t stream, char *buf, size_t buflen, off_t offset, size_t *pn)
+{
+ struct mu_nntp_stream *nntp_stream = stream_get_owner (stream);
+ size_t n = 0;
+ int status = 0;
+
+ (void)offset;
+ if (nntp_stream)
+ {
+ if (!nntp_stream->done)
+ {
+ status = mu_nntp_readline (nntp_stream->nntp, buf, buflen, &n);
+ if (n == 0)
+ {
+ nntp_stream->nntp->state = MU_NNTP_NO_STATE;
+ nntp_stream->done = 1;
+ }
+ }
+ }
+ if (pn)
+ *pn = n;
+ return status;
+}
+
+int
+mu_nntp_stream_create (mu_nntp_t nntp, stream_t *pstream)
+{
+ struct mu_nntp_stream *nntp_stream;
+ int status;
+
+ nntp_stream = malloc (sizeof *nntp_stream);
+ if (nntp_stream == NULL)
+ return ENOMEM;
+
+ nntp_stream->nntp = nntp;
+ nntp_stream->done = 0;
+
+ status = stream_create (pstream, MU_STREAM_READ | MU_STREAM_NO_CLOSE | MU_STREAM_NO_CHECK, nntp_stream);
+ if (status != 0)
+ {
+ free (nntp_stream);
+ return status;
+ }
+
+ stream_set_read (*pstream, mu_nntp_stream_read, nntp_stream);
+ stream_set_readline (*pstream, mu_nntp_stream_readline, nntp_stream);
+ stream_set_destroy (*pstream, mu_nntp_stream_destroy, nntp_stream);
+
+ return 0;
+}
diff --git a/mailbox/nntp/nntp_timeout.c b/mailbox/nntp/nntp_timeout.c
new file mode 100644
index 000000000..1e6ea5b34
--- /dev/null
+++ b/mailbox/nntp/nntp_timeout.c
@@ -0,0 +1,48 @@
+/* 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 <stdlib.h>
+#include <errno.h>
+#include <mailutils/sys/nntp.h>
+
+int
+mu_nntp_set_timeout (mu_nntp_t nntp, int timeout)
+{
+ /* Sanity checks. */
+ if (nntp == NULL)
+ return EINVAL;
+
+ nntp->timeout = timeout;
+ return 0;
+}
+
+int
+mu_nntp_get_timeout (mu_nntp_t nntp, int *ptimeout)
+{
+ /* Sanity checks. */
+ if (nntp == NULL)
+ return EINVAL;
+ if (ptimeout == NULL)
+ return MU_ERR_OUT_PTR_NULL;
+
+ *ptimeout = nntp->timeout;
+ return 0;
+}

Return to:

Send suggestions and report system problems to the System administrator.