libassuan: fix for commit 386e7ee when using a local pinentry.
[libpwmd.git] / assuan / assuan-io.c
blob2d7b8825fbbfb9aa041ddb4c9950de81275e5154
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 && !ctx->no_io_hooks) {
113 if (_assuan_io_hooks.read_hook (ctx, ctx->inbound.fd,
114 buffer, size, &retval) == 1)
115 return retval;
117 return -1;
120 return do_io_read (ctx->inbound.fd, buffer, size);
125 static ssize_t
126 do_io_write (assuan_fd_t fd, const void *buffer, size_t size)
128 #ifdef HAVE_W32_SYSTEM
129 /* Due to the peculiarities of the W32 API we can't use write for a
130 network socket and thus we try to use send first and fallback to
131 write if send detects that it is not a network socket. */
132 int n;
134 n = send (HANDLE2SOCKET(fd), buffer, size, 0);
135 if (n == -1 && WSAGetLastError () == WSAENOTSOCK)
137 DWORD nwrite;
139 n = WriteFile (fd, buffer, size, &nwrite, NULL);
140 if (!n)
142 switch (GetLastError ())
144 case ERROR_BROKEN_PIPE:
145 case ERROR_NO_DATA: errno = EPIPE; break;
146 default: errno = EIO; break;
148 n = -1;
150 else
151 n = (int)nwrite;
153 return n;
154 #else /*!HAVE_W32_SYSTEM*/
155 return write (fd, buffer, size);
156 #endif /*!HAVE_W32_SYSTEM*/
159 ssize_t
160 _assuan_io_write (assuan_fd_t fd, const void *buffer, size_t size)
162 ssize_t retval;
164 if (_assuan_io_hooks.write_hook
165 && _assuan_io_hooks.write_hook (NULL, fd, buffer, size, &retval) == 1)
166 return retval;
167 return do_io_write (fd, buffer, size);
170 ssize_t
171 _assuan_simple_write (assuan_context_t ctx, const void *buffer, size_t size)
173 ssize_t retval;
175 if (_assuan_io_hooks.write_hook && !ctx->no_io_hooks) {
176 if (_assuan_io_hooks.write_hook (ctx, ctx->outbound.fd,
177 buffer, size, &retval) == 1)
178 return retval;
180 return -1;
183 return do_io_write (ctx->outbound.fd, buffer, size);
187 #ifdef HAVE_W32_SYSTEM
189 _assuan_simple_sendmsg (assuan_context_t ctx, void *msg)
190 #else
191 ssize_t
192 _assuan_simple_sendmsg (assuan_context_t ctx, struct msghdr *msg)
193 #endif
195 #ifdef HAVE_W32_SYSTEM
196 return _assuan_error (ASSUAN_Not_Implemented);
197 #else
198 int ret;
199 while ( (ret = sendmsg (ctx->outbound.fd, msg, 0)) == -1 && errno == EINTR)
201 return ret;
202 #endif
206 #ifdef HAVE_W32_SYSTEM
208 _assuan_simple_recvmsg (assuan_context_t ctx, void *msg)
209 #else
210 ssize_t
211 _assuan_simple_recvmsg (assuan_context_t ctx, struct msghdr *msg)
212 #endif
214 #ifdef HAVE_W32_SYSTEM
215 return _assuan_error (ASSUAN_Not_Implemented);
216 #else
217 int ret;
218 while ( (ret = recvmsg (ctx->inbound.fd, msg, 0)) == -1 && errno == EINTR)
220 return ret;
221 #endif
225 void
226 _assuan_usleep (unsigned int usec)
228 if (usec)
230 #ifdef HAVE_NANOSLEEP
231 struct timespec req;
232 struct timespec rem;
234 req.tv_sec = 0;
235 req.tv_nsec = usec * 1000;
237 while (nanosleep (&req, &rem) < 0 && errno == EINTR)
238 req = rem;
240 #elif defined(HAVE_W32_SYSTEM)
241 Sleep (usec / 1000);
242 #else
243 struct timeval tv;
245 tv.tv_sec = usec / 1000000;
246 tv.tv_usec = usec % 1000000;
247 select (0, NULL, NULL, NULL, &tv);
248 #endif