comparison lib/sockutils.c @ 950:c7d7a081cd9c

2008-03-04 Brian Masney <masneyb@gftp.org> * lib/gftp.h lib/socket-connect.c lib/sockutils.c lib/protocols.c lib/Makefile.am lib/charset-conv.c lib/parse-dir-listing.c - split protocols.c into smaller files. No changes were made to the moved functions.
author masneyb
date Tue, 04 Mar 2008 12:28:40 +0000
parents
children a490d94a5b8e
comparison
equal deleted inserted replaced
949:9a6571938f89 950:c7d7a081cd9c
1 /*****************************************************************************/
2 /* sockutils.c - various utilities for dealing with sockets */
3 /* Copyright (C) 1998-2008 Brian Masney <masneyb@gftp.org> */
4 /* */
5 /* This program is free software; you can redistribute it and/or modify */
6 /* it under the terms of the GNU General Public License as published by */
7 /* the Free Software Foundation; either version 2 of the License, or */
8 /* (at your option) any later version. */
9 /* */
10 /* This program is distributed in the hope that it will be useful, */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
13 /* GNU General Public License for more details. */
14 /* */
15 /* You should have received a copy of the GNU General Public License */
16 /* along with this program; if not, write to the Free Software */
17 /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA */
18 /*****************************************************************************/
19
20 #include "gftp.h"
21 static const char cvsid[] = "$Id: protocols.c 952 2008-01-24 23:31:26Z masneyb $";
22
23 ssize_t
24 gftp_get_line (gftp_request * request, gftp_getline_buffer ** rbuf,
25 char * str, size_t len, int fd)
26 {
27 ssize_t (*read_function) (gftp_request * request, void *ptr, size_t size,
28 int fd);
29 char *pos, *nextpos;
30 size_t rlen, nslen;
31 int end_of_buffer;
32 ssize_t ret;
33
34 if (request == NULL || request->read_function == NULL)
35 read_function = gftp_fd_read;
36 else
37 read_function = request->read_function;
38
39 if (*rbuf == NULL)
40 {
41 *rbuf = g_malloc0 (sizeof (**rbuf));
42 (*rbuf)->max_bufsize = len;
43 (*rbuf)->buffer = g_malloc0 ((gulong) ((*rbuf)->max_bufsize + 1));
44
45 if ((ret = read_function (request, (*rbuf)->buffer,
46 (*rbuf)->max_bufsize, fd)) <= 0)
47 {
48 gftp_free_getline_buffer (rbuf);
49 return (ret);
50 }
51 (*rbuf)->buffer[ret] = '\0';
52 (*rbuf)->cur_bufsize = ret;
53 (*rbuf)->curpos = (*rbuf)->buffer;
54 }
55
56 ret = 0;
57 while (1)
58 {
59 pos = strchr ((*rbuf)->curpos, '\n');
60 end_of_buffer = (*rbuf)->curpos == (*rbuf)->buffer &&
61 ((*rbuf)->max_bufsize == (*rbuf)->cur_bufsize || (*rbuf)->eof);
62
63 if ((*rbuf)->cur_bufsize > 0 && (pos != NULL || end_of_buffer))
64 {
65 if (pos != NULL)
66 {
67 nslen = pos - (*rbuf)->curpos + 1;
68 nextpos = pos + 1;
69 if (pos > (*rbuf)->curpos && *(pos - 1) == '\r')
70 pos--;
71 *pos = '\0';
72 }
73 else
74 {
75 nslen = (*rbuf)->cur_bufsize;
76 nextpos = NULL;
77
78 /* This is not an overflow since we allocated one extra byte to
79 buffer above */
80 ((*rbuf)->buffer)[nslen] = '\0';
81 }
82
83 strncpy (str, (*rbuf)->curpos, len);
84 str[len - 1] = '\0';
85 (*rbuf)->cur_bufsize -= nslen;
86
87 if (nextpos != NULL)
88 (*rbuf)->curpos = nextpos;
89 else
90 (*rbuf)->cur_bufsize = 0;
91
92 ret = nslen;
93 break;
94 }
95 else
96 {
97 if ((*rbuf)->cur_bufsize == 0 || *(*rbuf)->curpos == '\0')
98 {
99 rlen = (*rbuf)->max_bufsize;
100 pos = (*rbuf)->buffer;
101 }
102 else
103 {
104 memmove ((*rbuf)->buffer, (*rbuf)->curpos, (*rbuf)->cur_bufsize);
105 pos = (*rbuf)->buffer + (*rbuf)->cur_bufsize;
106 rlen = (*rbuf)->max_bufsize - (*rbuf)->cur_bufsize;
107 }
108
109 (*rbuf)->curpos = (*rbuf)->buffer;
110
111 if ((*rbuf)->eof)
112 ret = 0;
113 else
114 {
115 ret = read_function (request, pos, rlen, fd);
116 if (ret < 0)
117 {
118 gftp_free_getline_buffer (rbuf);
119 return (ret);
120 }
121 }
122
123 if (ret == 0)
124 {
125 if ((*rbuf)->cur_bufsize == 0)
126 {
127 gftp_free_getline_buffer (rbuf);
128 return (ret);
129 }
130
131 (*rbuf)->eof = 1;
132 }
133
134 (*rbuf)->cur_bufsize += ret;
135 (*rbuf)->buffer[(*rbuf)->cur_bufsize] = '\0';
136 }
137 }
138
139 return (ret);
140 }
141
142
143 void
144 gftp_free_getline_buffer (gftp_getline_buffer ** rbuf)
145 {
146 g_free ((*rbuf)->buffer);
147 g_free (*rbuf);
148 *rbuf = NULL;
149 }
150
151
152 ssize_t
153 gftp_fd_read (gftp_request * request, void *ptr, size_t size, int fd)
154 {
155 intptr_t network_timeout;
156 struct timeval tv;
157 fd_set fset;
158 ssize_t ret;
159 int s_ret;
160
161 g_return_val_if_fail (fd >= 0, GFTP_EFATAL);
162
163 gftp_lookup_request_option (request, "network_timeout", &network_timeout);
164
165 errno = 0;
166 ret = 0;
167 FD_ZERO (&fset);
168
169 do
170 {
171 FD_SET (fd, &fset);
172 tv.tv_sec = network_timeout;
173 tv.tv_usec = 0;
174 s_ret = select (fd + 1, &fset, NULL, NULL, &tv);
175 if (s_ret == -1 && (errno == EINTR || errno == EAGAIN))
176 {
177 if (request != NULL && request->cancel)
178 {
179 gftp_disconnect (request);
180 return (GFTP_ERETRYABLE);
181 }
182
183 continue;
184 }
185 else if (s_ret <= 0)
186 {
187 if (request != NULL)
188 {
189 request->logging_function (gftp_logging_error, request,
190 _("Connection to %s timed out\n"),
191 request->hostname);
192 gftp_disconnect (request);
193 }
194
195 return (GFTP_ERETRYABLE);
196 }
197
198 if ((ret = read (fd, ptr, size)) < 0)
199 {
200 if (errno == EINTR || errno == EAGAIN)
201 {
202 if (request != NULL && request->cancel)
203 {
204 gftp_disconnect (request);
205 return (GFTP_ERETRYABLE);
206 }
207
208 continue;
209 }
210
211 if (request != NULL)
212 {
213 request->logging_function (gftp_logging_error, request,
214 _("Error: Could not read from socket: %s\n"),
215 g_strerror (errno));
216 gftp_disconnect (request);
217 }
218
219 return (GFTP_ERETRYABLE);
220 }
221
222 break;
223 }
224 while (1);
225
226 return (ret);
227 }
228
229
230 ssize_t
231 gftp_fd_write (gftp_request * request, const char *ptr, size_t size, int fd)
232 {
233 intptr_t network_timeout;
234 struct timeval tv;
235 int ret, s_ret;
236 ssize_t w_ret;
237 fd_set fset;
238
239 g_return_val_if_fail (fd >= 0, GFTP_EFATAL);
240
241 gftp_lookup_request_option (request, "network_timeout", &network_timeout);
242
243 errno = 0;
244 ret = 0;
245 FD_ZERO (&fset);
246
247 do
248 {
249 FD_SET (fd, &fset);
250 tv.tv_sec = network_timeout;
251 tv.tv_usec = 0;
252 s_ret = select (fd + 1, NULL, &fset, NULL, &tv);
253 if (s_ret == -1 && (errno == EINTR || errno == EAGAIN))
254 {
255 if (request != NULL && request->cancel)
256 {
257 gftp_disconnect (request);
258 return (GFTP_ERETRYABLE);
259 }
260
261 continue;
262 }
263 else if (s_ret <= 0)
264 {
265 if (request != NULL)
266 {
267 request->logging_function (gftp_logging_error, request,
268 _("Connection to %s timed out\n"),
269 request->hostname);
270 gftp_disconnect (request);
271 }
272
273 return (GFTP_ERETRYABLE);
274 }
275
276 w_ret = write (fd, ptr, size);
277 if (w_ret < 0)
278 {
279 if (errno == EINTR || errno == EAGAIN)
280 {
281 if (request != NULL && request->cancel)
282 {
283 gftp_disconnect (request);
284 return (GFTP_ERETRYABLE);
285 }
286
287 continue;
288 }
289
290 if (request != NULL)
291 {
292 request->logging_function (gftp_logging_error, request,
293 _("Error: Could not write to socket: %s\n"),
294 g_strerror (errno));
295 gftp_disconnect (request);
296 }
297
298 return (GFTP_ERETRYABLE);
299 }
300
301 ptr += w_ret;
302 size -= w_ret;
303 ret += w_ret;
304 }
305 while (size > 0);
306
307 return (ret);
308 }
309
310
311 ssize_t
312 gftp_writefmt (gftp_request * request, int fd, const char *fmt, ...)
313 {
314 char *tempstr;
315 va_list argp;
316 ssize_t ret;
317
318 va_start (argp, fmt);
319 tempstr = g_strdup_vprintf (fmt, argp);
320 va_end (argp);
321
322 ret = request->write_function (request, tempstr, strlen (tempstr), fd);
323 g_free (tempstr);
324 return (ret);
325 }
326
327
328 int
329 gftp_fd_set_sockblocking (gftp_request * request, int fd, int non_blocking)
330 {
331 int flags;
332
333 g_return_val_if_fail (fd >= 0, GFTP_EFATAL);
334
335 if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
336 {
337 request->logging_function (gftp_logging_error, request,
338 _("Cannot get socket flags: %s\n"),
339 g_strerror (errno));
340 gftp_disconnect (request);
341 return (GFTP_ERETRYABLE);
342 }
343
344 if (non_blocking)
345 flags |= O_NONBLOCK;
346 else
347 flags &= ~O_NONBLOCK;
348
349 if (fcntl (fd, F_SETFL, flags) < 0)
350 {
351 request->logging_function (gftp_logging_error, request,
352 _("Cannot set socket to non-blocking: %s\n"),
353 g_strerror (errno));
354 gftp_disconnect (request);
355 return (GFTP_ERETRYABLE);
356 }
357
358 return (0);
359 }
360