1a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
2a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  Copyright (C) 2011-2012 Christian Beier <dontmind@freeshell.org>
3a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
4a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
5a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  This is free software; you can redistribute it and/or modify
6a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  it under the terms of the GNU General Public License as published by
7a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  the Free Software Foundation; either version 2 of the License, or
8a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  (at your option) any later version.
9a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
10a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  This software is distributed in the hope that it will be useful,
11a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  GNU General Public License for more details.
14a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *
15a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  You should have received a copy of the GNU General Public License
16a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  along with this software; if not, write to the Free Software
17a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
18a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat *  USA.
19a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
20a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
21a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
22a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * listen.c - listen for incoming connections
23a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
24a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
25a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef __STRICT_ANSI__
26a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define _BSD_SOURCE
27a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
28a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <unistd.h>
29a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <sys/types.h>
30a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef __MINGW32__
31a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#define close closesocket
32a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <winsock2.h>
33a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#undef max
34a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
35a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <sys/wait.h>
36a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <sys/utsname.h>
37a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
38a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <sys/time.h>
39a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#include <rfb/rfbclient.h>
40a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
41a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
42a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * listenForIncomingConnections() - listen for incoming connections from
43a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * servers, and fork a new process to deal with each connection.
44a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
45a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
46a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatvoid
47a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatlistenForIncomingConnections(rfbClient* client)
48a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
49a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef __MINGW32__
50a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  /* FIXME */
51a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbClientErr("listenForIncomingConnections on MinGW32 NOT IMPLEMENTED\n");
52a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  return;
53a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#else
54a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int listenSocket, listen6Socket = -1;
55a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  fd_set fds;
56a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
57a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  client->listenSpecified = TRUE;
58a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
59a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  listenSocket = ListenAtTcpPortAndAddress(client->listenPort, client->listenAddress);
60a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
61a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if ((listenSocket < 0))
62a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    return;
63a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
64a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbClientLog("%s -listen: Listening on port %d\n",
65a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  client->programName,client->listenPort);
66a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  rfbClientLog("%s -listen: Command line errors are not reported until "
67a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	  "a connection comes in.\n", client->programName);
68a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
69a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_IPv6 /* only try that if we're IPv6-capable, otherwise we may try to bind to the same port which would make all that listening fail */
70a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  /* only do IPv6 listen of listen6Port is set */
71a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if (client->listen6Port > 0)
72a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    {
73a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      listen6Socket = ListenAtTcpPortAndAddress(client->listen6Port, client->listen6Address);
74a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
75a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if (listen6Socket < 0)
76a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return;
77a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
78a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbClientLog("%s -listen: Listening on IPV6 port %d\n",
79a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		   client->programName,client->listenPort);
80a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbClientLog("%s -listen: Command line errors are not reported until "
81a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		   "a connection comes in.\n", client->programName);
82a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
83a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
84a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
85a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  while (TRUE) {
86a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int r;
87a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* reap any zombies */
88a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    int status, pid;
89a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    while ((pid= wait3(&status, WNOHANG, (struct rusage *)0))>0);
90a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
91a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    /* TODO: callback for discard any events (like X11 events) */
92a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
93a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    FD_ZERO(&fds);
94a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
95a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(listenSocket >= 0)
96a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      FD_SET(listenSocket, &fds);
97a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if(listen6Socket >= 0)
98a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      FD_SET(listen6Socket, &fds);
99a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
100a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    r = select(max(listenSocket, listen6Socket)+1, &fds, NULL, NULL, NULL);
101a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
102a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    if (r > 0) {
103a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if (FD_ISSET(listenSocket, &fds))
104a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	client->sock = AcceptTcpConnection(client->listenSock);
105a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      else if (FD_ISSET(listen6Socket, &fds))
106a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	client->sock = AcceptTcpConnection(client->listen6Sock);
107a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
108a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if (client->sock < 0)
109a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return;
110a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if (!SetNonBlocking(client->sock))
111a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return;
112a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
113a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      /* Now fork off a new process to deal with it... */
114a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
115a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      switch (fork()) {
116a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
117a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      case -1:
118a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	rfbClientErr("fork\n");
119a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return;
120a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
121a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      case 0:
122a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	/* child - return to caller */
123a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	close(listenSocket);
124a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	close(listen6Socket);
125a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return;
126a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
127a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      default:
128a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	/* parent - go round and listen again */
129a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	close(client->sock);
130a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	break;
131a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
132a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
133a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  }
134a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
135a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
136a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
137a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
138a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
139a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat/*
140a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * listenForIncomingConnectionsNoFork() - listen for incoming connections
141a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * from servers, but DON'T fork, instead just wait timeout microseconds.
142a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * If timeout is negative, block indefinitly.
143a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * Returns 1 on success (there was an incoming connection on the listen socket
144a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat * and we accepted it successfully), -1 on error, 0 on timeout.
145a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat */
146a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
147a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehatint
148a430b2b5ca4f0967836f5820e8f03adc17fc0a24San MehatlistenForIncomingConnectionsNoFork(rfbClient* client, int timeout)
149a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat{
150a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  fd_set fds;
151a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  struct timeval to;
152a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  int r;
153a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
154a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  to.tv_sec= timeout / 1000000;
155a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  to.tv_usec= timeout % 1000000;
156a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
157a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  client->listenSpecified = TRUE;
158a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
159a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if (client->listenSock < 0)
160a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    {
161a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      client->listenSock = ListenAtTcpPortAndAddress(client->listenPort, client->listenAddress);
162a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
163a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if (client->listenSock < 0)
164a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return -1;
165a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
166a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbClientLog("%s -listennofork: Listening on port %d\n",
167a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		   client->programName,client->listenPort);
168a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbClientLog("%s -listennofork: Command line errors are not reported until "
169a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		   "a connection comes in.\n", client->programName);
170a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
171a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
172a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#ifdef LIBVNCSERVER_IPv6 /* only try that if we're IPv6-capable, otherwise we may try to bind to the same port which would make all that listening fail */
173a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  /* only do IPv6 listen of listen6Port is set */
174a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if (client->listen6Port > 0 && client->listen6Sock < 0)
175a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    {
176a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      client->listen6Sock = ListenAtTcpPortAndAddress(client->listen6Port, client->listen6Address);
177a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
178a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if (client->listen6Sock < 0)
179a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return -1;
180a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
181a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbClientLog("%s -listennofork: Listening on IPV6 port %d\n",
182a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		   client->programName,client->listenPort);
183a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      rfbClientLog("%s -listennofork: Command line errors are not reported until "
184a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat		   "a connection comes in.\n", client->programName);
185a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
186a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat#endif
187a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
188a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  FD_ZERO(&fds);
189a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
190a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if(client->listenSock >= 0)
191a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    FD_SET(client->listenSock, &fds);
192a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if(client->listen6Sock >= 0)
193a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    FD_SET(client->listen6Sock, &fds);
194a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
195a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if (timeout < 0)
196a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    r = select(max(client->listenSock, client->listen6Sock) +1, &fds, NULL, NULL, NULL);
197a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  else
198a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    r = select(max(client->listenSock, client->listen6Sock) +1, &fds, NULL, NULL, &to);
199a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
200a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  if (r > 0)
201a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    {
202a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if (FD_ISSET(client->listenSock, &fds))
203a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	client->sock = AcceptTcpConnection(client->listenSock);
204a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      else if (FD_ISSET(client->listen6Sock, &fds))
205a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	client->sock = AcceptTcpConnection(client->listen6Sock);
206a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
207a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if (client->sock < 0)
208a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return -1;
209a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if (!SetNonBlocking(client->sock))
210a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	return -1;
211a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
212a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(client->listenSock >= 0) {
213a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	close(client->listenSock);
214a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	client->listenSock = -1;
215a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
216a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      if(client->listen6Sock >= 0) {
217a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	close(client->listen6Sock);
218a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat	client->listen6Sock = -1;
219a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      }
220a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat      return r;
221a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat    }
222a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
223a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  /* r is now either 0 (timeout) or -1 (error) */
224a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat  return r;
225a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat}
226a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
227a430b2b5ca4f0967836f5820e8f03adc17fc0a24San Mehat
228