Fixed a segfault during an SSH connection failure.
[libpwmd.git] / assuan / assuan-io.c
blob647237db2d181ad05d24418690fd609a985a753a
1 /* assuan-io.c - Wraps the read and write functions.
2 * Copyright (C) 2002, 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
4 * This file is part of Assuan.
6 * Assuan is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
11 * Assuan is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <time.h>
25 #include <sys/time.h>
26 #include <sys/types.h>
27 #ifdef HAVE_SYS_SOCKET_H
28 # include <sys/socket.h>
29 #endif
30 #include <unistd.h>
31 #include <errno.h>
32 #ifdef HAVE_W32_SYSTEM
33 # include <windows.h>
34 #else
35 # include <sys/wait.h>
36 #endif
38 #include "assuan-defs.h"
41 #ifndef HAVE_W32_SYSTEM
42 pid_t
43 _assuan_waitpid (pid_t pid, int *status, int options)
45 return waitpid (pid, status, options);
47 #endif
50 static ssize_t
51 do_io_read (assuan_fd_t fd, void *buffer, size_t size)
53 #ifdef HAVE_W32_SYSTEM
54 /* Due to the peculiarities of the W32 API we can't use read for a
55 network socket and thus we try to use recv first and fallback to
56 read if recv detects that it is not a network socket. */
57 int n;
59 n = recv (HANDLE2SOCKET(fd), buffer, size, 0);
60 if (n == -1)
62 switch (WSAGetLastError ())
64 case WSAENOTSOCK:
66 DWORD nread = 0;
68 n = ReadFile (fd, buffer, size, &nread, NULL);
69 if (!n)
71 switch (GetLastError())
73 case ERROR_BROKEN_PIPE: errno = EPIPE; break;
74 default: errno = EIO;
76 n = -1;
78 else
79 n = (int)nread;
81 break;
83 case WSAEWOULDBLOCK: errno = EAGAIN; break;
84 case ERROR_BROKEN_PIPE: errno = EPIPE; break;
85 default: errno = EIO; break;
88 return n;
89 #else /*!HAVE_W32_SYSTEM*/
90 return read (fd, buffer, size);
91 #endif /*!HAVE_W32_SYSTEM*/
95 ssize_t
96 _assuan_io_read (assuan_fd_t fd, void *buffer, size_t size)
98 ssize_t retval;
100 if (_assuan_io_hooks.read_hook
101 && _assuan_io_hooks.read_hook (NULL, fd, buffer, size, &retval) == 1)
102 return retval;
104 return do_io_read (fd, buffer, size);
107 ssize_t
108 _assuan_simple_read (assuan_context_t ctx, void *buffer, size_t size)
110 ssize_t retval;
112 if (_assuan_io_hooks.read_hook
113 && _assuan_io_hooks.read_hook (ctx, ctx->inbound.fd,
114 buffer, size, &retval) == 1)
115 return retval;
117 return do_io_read (ctx->inbound.fd, buffer, size);
122 static ssize_t
123 do_io_write (assuan_fd_t fd, const void *buffer, size_t size)
125 #ifdef HAVE_W32_SYSTEM
126 /* Due to the peculiarities of the W32 API we can't use write for a
127 network socket and thus we try to use send first and fallback to
128 write if send detects that it is not a network socket. */
129 int n;
131 n = send (HANDLE2SOCKET(fd), buffer, size, 0);
132 if (n == -1 && WSAGetLastError () == WSAENOTSOCK)
134 DWORD nwrite;
136 n = WriteFile (fd, buffer, size, &nwrite, NULL);
137 if (!n)
139 switch (GetLastError ())
141 case ERROR_BROKEN_PIPE:
142 case ERROR_NO_DATA: errno = EPIPE; break;
143 default: errno = EIO; break;
145 n = -1;
147 else
148 n = (int)nwrite;
150 return n;
151 #else /*!HAVE_W32_SYSTEM*/
152 return write (fd, buffer, size);
153 #endif /*!HAVE_W32_SYSTEM*/
156 ssize_t
157 _assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size)
159 ssize_t retval;
161 if (_assuan_io_hooks.write_hook
162 && _assuan_io_hooks.write_hook (NULL, fd, buffer, size, &retval) == 1)
163 return retval;
164 return do_io_write (fd, buffer, size);
167 ssize_t
168 _assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)
170 ssize_t retval;
172 if (_assuan_io_hooks.write_hook
173 && _assuan_io_hooks.write_hook (ctx, ctx->outbound.fd,
174 buffer, size, &retval) == 1)
175 return retval;
177 return do_io_write (ctx->outbound.fd, buffer, size);
181 #ifdef HAVE_W32_SYSTEM
183 _assuan_simple_sendmsg (assuan_context_t ctx, void *msg)
184 #else
185 ssize_t
186 _assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg)
187 #endif
189 #ifdef HAVE_W32_SYSTEM
190 return _assuan_error (ASSUAN_Not_Implemented);
191 #else
192 int ret;
193 while ( (ret = sendmsg (ctx->outbound.fd, msg, 0)) == -1 && errno == EINTR)
195 return ret;
196 #endif
200 #ifdef HAVE_W32_SYSTEM
202 _assuan_simple_recvmsg (assuan_context_t ctx, void *msg)
203 #else
204 ssize_t
205 _assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg)
206 #endif
208 #ifdef HAVE_W32_SYSTEM
209 return _assuan_error (ASSUAN_Not_Implemented);
210 #else
211 int ret;
212 while ( (ret = recvmsg (ctx->inbound.fd, msg, 0)) == -1 && errno == EINTR)
214 return ret;
215 #endif
219 void
220 _assuan_usleep (unsigned int usec)
222 if (usec)
224 #ifdef HAVE_NANOSLEEP
225 struct timespec req;
226 struct timespec rem;
228 req.tv_sec = 0;
229 req.tv_nsec = usec * 1000;
231 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
232 req = rem;
234 #elif defined(HAVE_W32_SYSTEM)
235 Sleep (usec / 1000);
236 #else
237 struct timeval tv;
239 tv.tv_sec = usec / 1000000;
240 tv.tv_usec = usec % 1000000;
241 select (0, NULL, NULL, NULL, &tv);
242 #endif