Implement CLOCK_MONOTONIC using getnanouptime(), which in DragonFly is
[dragonfly.git] / contrib / cvs-1.12.9 / src / socket-client.c
1 /* CVS socket client stuff.
2
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; either version 2, or (at your option)
6    any later version.
7
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.  */
12
13 #include <config.h>
14
15 #include "cvs.h"
16 #include "buffer.h"
17
18 #ifdef CLIENT_SUPPORT
19
20 #include "socket-client.h"
21
22
23 #if defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI)
24
25 struct hostent *
26 init_sockaddr( struct sockaddr_in *name, char *hostname, unsigned int port )
27 {
28     struct hostent *hostinfo;
29     unsigned short shortport = port;
30
31     memset (name, 0, sizeof (*name));
32     name->sin_family = AF_INET;
33     name->sin_port = htons (shortport);
34     hostinfo = gethostbyname (hostname);
35     if (hostinfo == NULL)
36     {
37         fprintf (stderr, "Unknown host %s.\n", hostname);
38         exit (EXIT_FAILURE);
39     }
40     name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
41     return hostinfo;
42 }
43
44 #endif
45
46 #ifdef NO_SOCKET_TO_FD
47
48 /* Under certain circumstances, we must communicate with the server
49    via a socket using send() and recv().  This is because under some
50    operating systems (OS/2 and Windows 95 come to mind), a socket
51    cannot be converted to a file descriptor -- it must be treated as a
52    socket and nothing else.
53    
54    We may also need to deal with socket routine error codes differently
55    in these cases.  This is handled through the SOCK_ERRNO and
56    SOCK_STRERROR macros. */
57
58 /* These routines implement a buffer structure which uses send and
59    recv.  The buffer is always in blocking mode so we don't implement
60    the block routine.  */
61
62 /* Note that it is important that these routines always handle errors
63    internally and never return a positive errno code, since it would in
64    general be impossible for the caller to know in general whether any
65    error code came from a socket routine (to decide whether to use
66    SOCK_STRERROR or simply strerror to print an error message). */
67
68 /* We use an instance of this structure as the closure field.  */
69
70 struct socket_buffer
71 {
72     /* The socket number.  */
73     int socket;
74 };
75
76 static int socket_buffer_input (void *, char *, int, int, int *);
77 static int socket_buffer_output (void *, const char *, int, int *);
78 static int socket_buffer_flush (void *);
79 static int socket_buffer_shutdown (struct buffer *);
80
81
82
83 /* Create a buffer based on a socket.  */
84
85 struct buffer *
86 socket_buffer_initialize( int socket, int input,
87                           void (*memory) ( struct buffer * ) )
88 {
89     struct socket_buffer *sbuf = xmalloc (sizeof *sbuf);
90     sbuf->socket = socket;
91     return buf_initialize (input ? socket_buffer_input : NULL,
92                            input ? NULL : socket_buffer_output,
93                            input ? NULL : socket_buffer_flush,
94                            NULL,
95                            socket_buffer_shutdown,
96                            memory,
97                            sbuf);
98 }
99
100
101
102 /* The buffer input function for a buffer built on a socket.  */
103
104 static int
105 socket_buffer_input( void *closure, char *data, int need, int size, int *got )
106 {
107     struct socket_buffer *sb = (struct socket_buffer *) closure;
108     int nbytes;
109
110     /* I believe that the recv function gives us exactly the semantics
111        we want.  If there is a message, it returns immediately with
112        whatever it could get.  If there is no message, it waits until
113        one comes in.  In other words, it is not like read, which in
114        blocking mode normally waits until all the requested data is
115        available.  */
116
117     *got = 0;
118
119     do
120     {
121
122         /* Note that for certain (broken?) networking stacks, like
123            VMS's UCX (not sure what version, problem reported with
124            recv() in 1997), and (according to windows-NT/config.h)
125            Windows NT 3.51, we must call recv or send with a
126            moderately sized buffer (say, less than 200K or something),
127            or else there may be network errors (somewhat hard to
128            produce, e.g. WAN not LAN or some such).  buf_read_data
129            makes sure that we only recv() BUFFER_DATA_SIZE bytes at
130            a time.  */
131
132         nbytes = recv (sb->socket, data, size, 0);
133         if (nbytes < 0)
134             error (1, 0, "reading from server: %s", SOCK_STRERROR (SOCK_ERRNO));
135         if (nbytes == 0)
136         {
137             /* End of file (for example, the server has closed
138                the connection).  If we've already read something, we
139                just tell the caller about the data, not about the end of
140                file.  If we've read nothing, we return end of file.  */
141             if (*got == 0)
142                 return -1;
143             else
144                 return 0;
145         }
146         need -= nbytes;
147         size -= nbytes;
148         data += nbytes;
149         *got += nbytes;
150     }
151     while (need > 0);
152
153     return 0;
154 }
155
156
157
158 /* The buffer output function for a buffer built on a socket.  */
159
160 static int
161 socket_buffer_output( void *closure, const char *data, int have, int *wrote )
162 {
163     struct socket_buffer *sb = (struct socket_buffer *) closure;
164
165     *wrote = have;
166
167     /* See comment in socket_buffer_input regarding buffer size we pass
168        to send and recv.  */
169
170 #ifdef SEND_NEVER_PARTIAL
171     /* If send() never will produce a partial write, then just do it.  This
172        is needed for systems where its return value is something other than
173        the number of bytes written.  */
174     if (send (sb->socket, data, have, 0) < 0)
175         error (1, 0, "writing to server socket: %s", SOCK_STRERROR (SOCK_ERRNO));
176 #else
177     while (have > 0)
178     {
179         int nbytes;
180
181         nbytes = send (sb->socket, data, have, 0);
182         if (nbytes < 0)
183             error (1, 0, "writing to server socket: %s", SOCK_STRERROR (SOCK_ERRNO));
184
185         have -= nbytes;
186         data += nbytes;
187     }
188 #endif
189
190     return 0;
191 }
192
193
194
195 /* The buffer flush function for a buffer built on a socket.  */
196
197 /*ARGSUSED*/
198 static int
199 socket_buffer_flush( void *closure )
200 {
201     /* Nothing to do.  Sockets are always flushed.  */
202     return 0;
203 }
204
205
206
207 static int
208 socket_buffer_shutdown( struct buffer *buf )
209 {
210     struct socket_buffer *n = (struct socket_buffer *) buf->closure;
211     char tmp;
212
213     /* no need to flush children of an endpoint buffer here */
214
215     if (buf->input)
216     {
217         int err = 0;
218         if (! buf_empty_p (buf)
219             || (err = recv (n->socket, &tmp, 1, 0)) > 0)
220             error (0, 0, "dying gasps from %s unexpected", current_parsed_root->hostname);
221         else if (err == -1)
222             error (0, 0, "reading from %s: %s", current_parsed_root->hostname, SOCK_STRERROR (SOCK_ERRNO));
223
224         /* shutdown() socket */
225 # ifdef SHUTDOWN_SERVER
226         if (current_parsed_root->method != server_method)
227 # endif
228         if (shutdown (n->socket, 0) < 0)
229         {
230             error (1, 0, "shutting down server socket: %s", SOCK_STRERROR (SOCK_ERRNO));
231         }
232
233         buf->input = NULL;
234     }
235     else if (buf->output)
236     {
237         /* shutdown() socket */
238 # ifdef SHUTDOWN_SERVER
239         /* FIXME:  Should have a SHUTDOWN_SERVER_INPUT &
240          * SHUTDOWN_SERVER_OUTPUT
241          */
242         if (current_parsed_root->method == server_method)
243             SHUTDOWN_SERVER (n->socket);
244         else
245 # endif
246         if (shutdown (n->socket, 1) < 0)
247         {
248             error (1, 0, "shutting down server socket: %s", SOCK_STRERROR (SOCK_ERRNO));
249         }
250
251         buf->output = NULL;
252     }
253
254     return 0;
255 }
256
257 #endif /* NO_SOCKET_TO_FD */
258
259 #endif /* CLIENT_SUPPORT */