Commit f50de094 f50de094ab26e6e81438d056e31236e776e4dc65 by Alain Magloire

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
1 parent fcba0963
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library 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 GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <string.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <mailutils/sys/nntp.h>
26
27 int
28 mu_nntp_set_carrier (mu_nntp_t nntp, stream_t carrier)
29 {
30 /* Sanity checks. */
31 if (nntp == NULL)
32 return EINVAL;
33
34 if (nntp->carrier)
35 {
36 /* Close any old carrier. */
37 mu_nntp_disconnect (nntp);
38 stream_destroy (&nntp->carrier, nntp);
39 }
40 nntp->carrier = carrier;
41 return 0;
42 }
43
44 int
45 mu_nntp_get_carrier (mu_nntp_t nntp, stream_t *pcarrier)
46 {
47 /* Sanity checks. */
48 if (nntp == NULL)
49 return EINVAL;
50 if (pcarrier == NULL)
51 return MU_ERR_OUT_PTR_NULL;
52
53 *pcarrier = nntp->carrier;
54 return 0;
55 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library 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 GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <sys/time.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <mailutils/sys/nntp.h>
28
29 /* Open the connection to the server. */
30 int
31 mu_nntp_connect (mu_nntp_t nntp)
32 {
33 int status;
34
35 /* Sanity checks. */
36 if (nntp == NULL)
37 return EINVAL;
38
39 /* A networking stack. */
40 if (nntp->carrier == NULL)
41 return EINVAL;
42
43 /* Enter the pop state machine, and boogy: AUTHORISATION State. */
44 switch (nntp->state)
45 {
46 default:
47 /* FALLTHROUGH */
48 /* If nntp was in an error state going through here should clear it. */
49
50 case MU_NNTP_NO_STATE:
51 status = mu_nntp_disconnect (nntp);
52 MU_NNTP_CHECK_EAGAIN (nntp, status);
53 nntp->state = MU_NNTP_CONNECT;
54
55 case MU_NNTP_CONNECT:
56 /* Establish the connection. */
57 status = stream_open (nntp->carrier);
58 MU_NNTP_CHECK_EAGAIN (nntp, status);
59 nntp->acknowledge = 0;
60 nntp->state = MU_NNTP_GREETINGS;
61
62 case MU_NNTP_GREETINGS:
63 /* Get the greetings. */
64 {
65 size_t len = 0;
66 char *right, *left;
67 status = mu_nntp_response (nntp, NULL, 0, &len);
68 MU_NNTP_CHECK_EAGAIN (nntp, status);
69 mu_nntp_debug_ack (nntp);
70 if (nntp->ack.buf[0] == '2')
71 {
72 stream_close (nntp->carrier);
73 nntp->state = MU_NNTP_NO_STATE;
74 return EACCES;
75 }
76 nntp->state = MU_NNTP_NO_STATE;
77 }
78 } /* End AUTHORISATION state. */
79
80 return status;
81 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library 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 GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <mailutils/errno.h>
25 #include <mailutils/sys/nntp.h>
26
27 /* Initialise a mu_nntp_t handle. */
28
29 int
30 mu_nntp_create (mu_nntp_t *pnntp)
31 {
32 mu_nntp_t nntp;
33
34 /* Sanity check. */
35 if (pnntp == NULL)
36 return EINVAL;
37
38 nntp = calloc (1, sizeof *nntp);
39 if (nntp == NULL)
40 return ENOMEM;
41
42 /* Reserve space for the ack(nowledgement) response.
43 According to RFC 977: The maximum length of the first line of a
44 command response (including the initial greeting) is unchanged at
45 512 octets (including the terminating CRLF). */
46 nntp->ack.len = 512;
47 nntp->ack.buf = calloc (nntp->ack.len, 1);
48 if (nntp->ack.buf == NULL)
49 {
50 mu_nntp_destroy (&nntp);
51 return ENOMEM;
52 }
53 nntp->ack.ptr = nntp->ack.buf;
54
55 /* Reserve space for the data response/content.
56 RFC 977 recommands 255, but we grow it as needed. */
57 nntp->io.len = 255;
58 nntp->io.buf = calloc (nntp->io.len, 1);
59 if (nntp->io.buf == NULL)
60 {
61 mu_nntp_destroy (&nntp);
62 return ENOMEM;
63 }
64 nntp->io.ptr = nntp->io.buf;
65
66 nntp->state = MU_NNTP_NO_STATE; /* Init with no state. */
67 nntp->timeout = (10 * 60) * 100; /* The default Timeout is 10 minutes. */
68 nntp->acknowledge = 0; /* No Ack received. */
69
70 *pnntp = nntp;
71 return 0; /* Okdoke. */
72 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library 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 GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <mailutils/sys/nntp.h>
25
26 int
27 mu_nntp_set_debug (mu_nntp_t nntp, mu_debug_t debug)
28 {
29 if (nntp == NULL)
30 return EINVAL;
31 if (nntp->debug)
32 mu_debug_destroy (&nntp->debug, NULL);
33 nntp->debug = debug;
34 return 0;
35 }
36
37 int
38 mu_nntp_debug_cmd (mu_nntp_t nntp)
39 {
40 if (nntp->debug)
41 mu_debug_print(nntp->debug, MU_DEBUG_PROT, "%s", nntp->io.buf);
42 return 0;
43 }
44
45 int
46 mu_nntp_debug_ack (mu_nntp_t nntp)
47 {
48 if (nntp->debug)
49 {
50 mu_debug_print (nntp->debug, MU_DEBUG_PROT, "%s\n", nntp->ack.buf);
51 }
52 return 0;
53 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library 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 GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <stdlib.h>
23 #include <mailutils/errno.h>
24 #include <mailutils/sys/nntp.h>
25
26 void
27 mu_nntp_destroy (mu_nntp_t *pnntp)
28 {
29 if (pnntp && *pnntp)
30 {
31 mu_nntp_t nntp = *pnntp;
32
33 /* Free the response buffer. */
34 if (nntp->ack.buf)
35 free (nntp->ack.buf);
36
37 /* Free the io buffer. */
38 if (nntp->io.buf)
39 free (nntp->io.buf);
40
41 /* Release the carrier. */
42 if (nntp->carrier)
43 stream_destroy (&nntp->carrier, nntp);
44
45 free (nntp);
46
47 *pnntp = NULL;
48 }
49 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library 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 GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <mailutils/sys/nntp.h>
26
27 int
28 mu_nntp_disconnect (mu_nntp_t nntp)
29 {
30 /* Sanity checks. */
31 if (nntp == NULL)
32 return EINVAL;
33
34 /* We can keep some of the fields, if they decide to nntp_connect() again but
35 clear the states. */
36 nntp->state = MU_NNTP_NO_STATE;
37 nntp->acknowledge = 0;
38
39 /* Clear the buffers. */
40 memset (nntp->io.buf, '\0', nntp->io.len);
41 nntp->io.ptr = nntp->io.buf;
42 memset (nntp->ack.buf, '\0', nntp->ack.len);
43 nntp->ack.ptr = nntp->ack.buf;
44
45 /* Close the stream. */
46 return stream_close (nntp->carrier);
47 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library 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 GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <sys/time.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <mailutils/sys/nntp.h>
30 #include <mailutils/error.h>
31
32 int
33 mu_nntp_carrier_is_ready (stream_t carrier, int flag, int timeout)
34 {
35 struct timeval tv, *tvp = NULL;
36 int wflags = flag;
37 int status;
38
39 if (timeout >= 0)
40 {
41 tv.tv_sec = timeout / 100;
42 tv.tv_usec = (timeout % 1000) * 1000;
43 tvp = &tv;
44 }
45 status = stream_wait (carrier, &wflags, tvp);
46 if (status)
47 return 0; /* FIXME: provide a way to return error code! */
48 return wflags & flag;
49 }
50
51 /* Read a complete line from the nntp server. Transform CRLF to LF, remove
52 the stuff byte termination octet ".", put a null in the buffer
53 when done. And Do a select() (stream_is_readready()) for the timeout. */
54 static int
55 mu_nntp_getline (mu_nntp_t nntp)
56 {
57 size_t n = 0;
58 size_t total = nntp->io.ptr - nntp->io.buf;
59 int status = 0;
60
61 /* Must get a full line before bailing out. */
62 do
63 {
64 /* Timeout with select(), note that we have to reset select()
65 since on linux tv is modified when error. */
66 if (nntp->timeout)
67 {
68 int ready = mu_nntp_carrier_is_ready (nntp->carrier,
69 MU_STREAM_READY_RD,
70 nntp->timeout);
71 if (ready == 0)
72 return ETIMEDOUT;
73 }
74
75 status = stream_sequential_readline (nntp->carrier, nntp->io.buf + total, nntp->io.len - total, &n);
76 if (status != 0)
77 return status;
78
79 /* The server went away: It maybe a timeout and some nntp server
80 does not send the -ERR. Consider this like an error. */
81 if (n == 0)
82 return EIO;
83
84 total += n;
85 nntp->io.nl = memchr (nntp->io.buf, '\n', total);
86 if (nntp->io.nl == NULL) /* Do we have a full line. */
87 {
88 /* Allocate a bigger buffer ? */
89 if (total >= nntp->io.len - 1)
90 {
91 nntp->io.len *= 2;
92 nntp->io.buf = realloc (nntp->io.buf, nntp->io.len + 1);
93 if (nntp->io.buf == NULL)
94 return ENOMEM;
95 }
96 }
97 nntp->io.ptr = nntp->io.buf + total;
98 }
99 while (nntp->io.nl == NULL); /* Bail only if we have a complete line. */
100
101 /* When examining a multi-line response, the client checks to see if the
102 line begins with the termination octet "."(DOT). If yes and if octets
103 other than CRLF follow, the first octet of the line (the termination
104 octet) is stripped away. */
105 if (total >= 3 && nntp->io.buf[0] == '.')
106 {
107 if (nntp->io.buf[1] != '\r' && nntp->io.buf[2] != '\n')
108 {
109 memmove (nntp->io.buf, nntp->io.buf + 1, total - 1);
110 nntp->io.ptr--;
111 nntp->io.nl--;
112 }
113 /* And if CRLF immediately follows the termination character, then
114 the response from the NNTP server is ended and the line containing
115 ".CRLF" is not considered part of the multi-line response. */
116 else if (nntp->io.buf[1] == '\r' && nntp->io.buf[2] == '\n')
117 {
118 nntp->io.buf[0] = '\0';
119 nntp->io.ptr = nntp->io.buf;
120 nntp->io.nl = NULL;
121 }
122 }
123 /* \r\n --> \n\0, conversion. */
124 if (nntp->io.nl > nntp->io.buf)
125 {
126 *(nntp->io.nl - 1) = '\n';
127 *(nntp->io.nl) = '\0';
128 nntp->io.ptr = nntp->io.nl;
129 }
130 return status;
131 }
132
133 /* Call nntp_getline() for the dirty work, and consume i.e. put
134 in the user buffer only buflen. If buflen == 0 or buffer == NULL
135 nothing is consume, the data is save for another call to nntp_readline()
136 with a buffer != NULL.
137 */
138 int
139 mu_nntp_readline (mu_nntp_t nntp, char *buffer, size_t buflen, size_t *pnread)
140 {
141 size_t nread = 0;
142 size_t n = 0;
143 int status = 0;
144
145 /* Do we need to fill up? Yes if no NL or the buffer is empty. */
146 if (nntp->carrier && (nntp->io.nl == NULL || nntp->io.ptr == nntp->io.buf))
147 {
148 status = mu_nntp_getline (nntp);
149 if (status != 0)
150 return status;
151 }
152
153 /* How much we can copy ? */
154 n = nntp->io.ptr - nntp->io.buf;
155
156 /* Consume the line? */
157 if (buffer && buflen)
158 {
159 buflen--; /* For the null. */
160 if (buflen)
161 {
162 int nleft = buflen - n;
163 /* We got more then requested. */
164 if (nleft < 0)
165 {
166 size_t sentinel;
167 nread = buflen;
168 sentinel = nntp->io.ptr - (nntp->io.buf + nread);
169 memcpy (buffer, nntp->io.buf, nread);
170 memmove (nntp->io.buf, nntp->io.buf + nread, sentinel);
171 nntp->io.ptr = nntp->io.buf + sentinel;
172 }
173 else
174 {
175 /* Drain our buffer. */;
176 nread = n;
177 memcpy (buffer, nntp->io.buf, nread);
178 nntp->io.ptr = nntp->io.buf;
179 /* Clear of all residue. */
180 memset (nntp->io.buf, '\0', nntp->io.len);
181 }
182 }
183 buffer[nread] = '\0';
184 }
185 else
186 nread = n;
187
188 if (pnread)
189 *pnread = nread;
190 return status;
191 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library 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 GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <string.h>
23 #include <errno.h>
24 #include <mailutils/sys/nntp.h>
25
26 /* If we did not grap the ack already, call nntp_readline() but handle
27 Nonblocking also. */
28 int
29 mu_nntp_response (mu_nntp_t nntp, char *buffer, size_t buflen, size_t *pnread)
30 {
31 size_t n = 0;
32 int status = 0;
33
34 if (nntp == NULL)
35 return EINVAL;
36
37 if (!nntp->acknowledge)
38 {
39 size_t len = nntp->ack.len - (nntp->ack.ptr - nntp->ack.buf);
40 status = mu_nntp_readline (nntp, nntp->ack.ptr, len, &n);
41 nntp->ack.ptr += n;
42 if (status == 0)
43 {
44 len = nntp->ack.ptr - nntp->ack.buf;
45 if (len && nntp->ack.buf[len - 1] == '\n')
46 nntp->ack.buf[len - 1] = '\0';
47 nntp->acknowledge = 1; /* Flag that we have the ack. */
48 nntp->ack.ptr = nntp->ack.buf;
49 }
50 else
51 {
52 /* Provide them with an error. */
53 const char *econ = "500 NNTP IO ERROR";
54 n = strlen (econ);
55 strcpy (nntp->ack.buf, econ);
56 }
57 }
58 else
59 n = strlen (nntp->ack.buf);
60
61 if (buffer)
62 {
63 buflen--; /* Leave space for the NULL. */
64 n = (buflen < n) ? buflen : n;
65 memcpy (buffer, nntp->ack.buf, n);
66 buffer[n] = '\0';
67 }
68
69 if (pnread)
70 *pnread = n;
71 return status;
72 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library 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 GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #define _GNU_SOURCE
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <stdarg.h>
26 #include <sys/time.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 #include <string.h>
30
31 #include <errno.h>
32 #include <mailutils/sys/nntp.h>
33
34 /* A socket may write less then expected but stream.c:stream_write() will
35 always try to send the entire buffer unless an error is reported. We have
36 to cope with nonblocking, it is done by keeping track with the nntp->ptr
37 pointer if the write failed we keep track and restart where we left. */
38 int
39 mu_nntp_send (mu_nntp_t nntp)
40 {
41 int status = 0;
42 if (nntp->carrier && (nntp->io.ptr > nntp->io.buf))
43 {
44 size_t n = 0;
45 size_t len = nntp->io.ptr - nntp->io.buf;
46
47 /* Timeout with select(), note that we have to reset select()
48 since on linux tv is modified when error. */
49 if (nntp->timeout)
50 {
51 int ready = mu_nntp_carrier_is_ready (nntp->carrier,
52 MU_STREAM_READY_WR,
53 nntp->timeout);
54 if (ready == 0)
55 return ETIMEDOUT;
56 }
57
58 status = stream_write (nntp->carrier, nntp->io.buf, len, 0, &n);
59 if (n)
60 {
61 /* Consume what we sent. */
62 memmove (nntp->io.buf, nntp->io.buf + n, len - n);
63 nntp->io.ptr -= n;
64 }
65 }
66 else
67 nntp->io.ptr = nntp->io.buf;
68 return status;
69 }
70
71 /* According to RFC 2449: The maximum length of a command is increased from
72 47 characters (4 character command, single space, 40 character argument,
73 CRLF) to 255 octets, including the terminating CRLF. But we are flexible
74 on this and realloc() as needed. NOTE: The terminated CRLF is not
75 included. */
76 int
77 mu_nntp_writeline (mu_nntp_t nntp, const char *format, ...)
78 {
79 int len;
80 va_list ap;
81 int done = 1;
82
83 va_start(ap, format);
84 /* C99 says that a conforming implementation of snprintf () should
85 return the number of char that would have been call but many old
86 GNU/Linux && BSD implementations return -1 on error. Worse,
87 QnX/Neutrino actually does not put the terminal null char. So
88 let's try to cope. */
89 do
90 {
91 len = vsnprintf (nntp->io.buf, nntp->io.len - 1, format, ap);
92 if (len < 0 || len >= (int)nntp->io.len
93 || !memchr (nntp->io.buf, '\0', len + 1))
94 {
95 nntp->io.len *= 2;
96 nntp->io.buf = realloc (nntp->io.buf, nntp->io.len);
97 if (nntp->io.buf == NULL)
98 return ENOMEM;
99 done = 0;
100 }
101 else
102 done = 1;
103 }
104 while (!done);
105 va_end(ap);
106 nntp->io.ptr = nntp->io.buf + len;
107 return 0;
108 }
109
110 int
111 mu_nntp_sendline (mu_nntp_t nntp, const char *line)
112 {
113 if (line)
114 {
115 int status = mu_nntp_writeline (nntp, line);
116 if (status)
117 return status;
118 }
119 return mu_nntp_send (nntp);
120 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2003, 2004 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library 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 GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <string.h>
23 #include <errno.h>
24 #include <stdlib.h>
25 #include <mailutils/sys/nntp.h>
26
27 /* Implementation of the stream for TOP and RETR. */
28 struct mu_nntp_stream
29 {
30 mu_nntp_t nntp;
31 int done;
32 };
33
34 static void
35 mu_nntp_stream_destroy (stream_t stream)
36 {
37 struct mu_nntp_stream *nntp_stream = stream_get_owner (stream);
38 if (nntp_stream)
39 {
40 free (nntp_stream);
41 }
42 }
43
44 static int
45 mu_nntp_stream_read (stream_t stream, char *buf, size_t buflen, off_t offset, size_t *pn)
46 {
47 struct mu_nntp_stream *nntp_stream = stream_get_owner (stream);
48 size_t n = 0;
49 int status = 0;
50 char *p = buf;
51
52 (void)offset;
53 if (nntp_stream)
54 {
55 if (!nntp_stream->done)
56 {
57 do
58 {
59 size_t nread = 0;
60
61 /* The nntp_readline () function will always read one less to
62 be able to null terminate the buffer, this will cause
63 serious grief for stream_read() where it is legitimate to
64 have a buffer of 1 char. So we must catch it here. */
65 if (buflen == 1)
66 {
67 char buffer[2];
68 *buffer = '\0';
69 status = mu_nntp_readline (nntp_stream->nntp, buffer, 2, &nread);
70 *p = *buffer;
71 }
72 else
73 status = mu_nntp_readline (nntp_stream->nntp, p, buflen, &nread);
74
75 if (status != 0)
76 break;
77 if (nread == 0)
78 {
79 nntp_stream->nntp->state = MU_NNTP_NO_STATE;
80 nntp_stream->done = 1;
81 break;
82 }
83 n += nread;
84 buflen -= nread;
85 p += nread;
86 }
87 while (buflen > 0);
88 }
89 }
90 if (pn)
91 *pn = n;
92 return status;
93 }
94
95 static int
96 mu_nntp_stream_readline (stream_t stream, char *buf, size_t buflen, off_t offset, size_t *pn)
97 {
98 struct mu_nntp_stream *nntp_stream = stream_get_owner (stream);
99 size_t n = 0;
100 int status = 0;
101
102 (void)offset;
103 if (nntp_stream)
104 {
105 if (!nntp_stream->done)
106 {
107 status = mu_nntp_readline (nntp_stream->nntp, buf, buflen, &n);
108 if (n == 0)
109 {
110 nntp_stream->nntp->state = MU_NNTP_NO_STATE;
111 nntp_stream->done = 1;
112 }
113 }
114 }
115 if (pn)
116 *pn = n;
117 return status;
118 }
119
120 int
121 mu_nntp_stream_create (mu_nntp_t nntp, stream_t *pstream)
122 {
123 struct mu_nntp_stream *nntp_stream;
124 int status;
125
126 nntp_stream = malloc (sizeof *nntp_stream);
127 if (nntp_stream == NULL)
128 return ENOMEM;
129
130 nntp_stream->nntp = nntp;
131 nntp_stream->done = 0;
132
133 status = stream_create (pstream, MU_STREAM_READ | MU_STREAM_NO_CLOSE | MU_STREAM_NO_CHECK, nntp_stream);
134 if (status != 0)
135 {
136 free (nntp_stream);
137 return status;
138 }
139
140 stream_set_read (*pstream, mu_nntp_stream_read, nntp_stream);
141 stream_set_readline (*pstream, mu_nntp_stream_readline, nntp_stream);
142 stream_set_destroy (*pstream, mu_nntp_stream_destroy, nntp_stream);
143
144 return 0;
145 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library 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 GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <mailutils/sys/nntp.h>
25
26 int
27 mu_nntp_set_timeout (mu_nntp_t nntp, int timeout)
28 {
29 /* Sanity checks. */
30 if (nntp == NULL)
31 return EINVAL;
32
33 nntp->timeout = timeout;
34 return 0;
35 }
36
37 int
38 mu_nntp_get_timeout (mu_nntp_t nntp, int *ptimeout)
39 {
40 /* Sanity checks. */
41 if (nntp == NULL)
42 return EINVAL;
43 if (ptimeout == NULL)
44 return MU_ERR_OUT_PTR_NULL;
45
46 *ptimeout = nntp->timeout;
47 return 0;
48 }