OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [ada/] [socket.c] - Blame information for rev 292

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 281 jeremybenn
/****************************************************************************
2
 *                                                                          *
3
 *                         GNAT COMPILER COMPONENTS                         *
4
 *                                                                          *
5
 *                               S O C K E T                                *
6
 *                                                                          *
7
 *                          C Implementation File                           *
8
 *                                                                          *
9
 *          Copyright (C) 2003-2009, Free Software Foundation, Inc.         *
10
 *                                                                          *
11
 * GNAT is free software;  you can  redistribute it  and/or modify it under *
12
 * terms of the  GNU General Public License as published  by the Free Soft- *
13
 * ware  Foundation;  either version 3,  or (at your option) any later ver- *
14
 * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
15
 * OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY *
16
 * or FITNESS FOR A PARTICULAR PURPOSE.                                     *
17
 *                                                                          *
18
 * As a special exception under Section 7 of GPL version 3, you are granted *
19
 * additional permissions described in the GCC Runtime Library Exception,   *
20
 * version 3.1, as published by the Free Software Foundation.               *
21
 *                                                                          *
22
 * You should have received a copy of the GNU General Public License and    *
23
 * a copy of the GCC Runtime Library Exception along with this program;     *
24
 * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    *
25
 * <http://www.gnu.org/licenses/>.                                          *
26
 *                                                                          *
27
 * GNAT was originally developed  by the GNAT team at  New York University. *
28
 * Extensive contributions were provided by Ada Core Technologies Inc.      *
29
 *                                                                          *
30
 ****************************************************************************/
31
 
32
/*  This file provides a portable binding to the sockets API                */
33
 
34
#include "gsocket.h"
35
#ifdef VMS
36
/*
37
 * For VMS, gsocket.h can't include sockets-related DEC C header files
38
 * when building the runtime (because these files are in a DEC C text library
39
 * (DECC$RTLDEF.TLB) not accessable to GCC). So, we generate a separate header
40
 * file along with s-oscons.ads and include it here.
41
 */
42
# include "s-oscons.h"
43
 
44
/*
45
 * We also need the declaration of struct servent, which s-oscons can't
46
 * provide, so we copy it manually here. This needs to be kept in synch
47
 * with the definition of that structure in the DEC C headers, which
48
 * hopefully won't change frequently.
49
 */
50
struct servent {
51
  char *s_name;     /* official service name */
52
  char **s_aliases; /* alias list */
53
  int  s_port;      /* port # */
54
  char *s_proto;    /* protocol to use */
55
};
56
#endif
57
 
58
#if defined(HAVE_SOCKETS)
59
 
60
/* Include all the necessary system-specific headers and define the
61
 * necessary macros (shared with gen-oscons).
62
 */
63
 
64
#if !defined(SO_NOSIGPIPE) && !defined (MSG_NOSIGNAL)
65
#include <signal.h>
66
#endif
67
/* Required if we will be calling signal() in __gnat_disable_all_sigpipes() */
68
 
69
#include "raise.h"
70
/* Required for __gnat_malloc() */
71
 
72
#include <string.h>
73
/* Required for memcpy() */
74
 
75
extern void __gnat_disable_sigpipe (int fd);
76
extern void __gnat_disable_all_sigpipes (void);
77
extern int  __gnat_create_signalling_fds (int *fds);
78
extern int  __gnat_read_signalling_fd (int rsig);
79
extern int  __gnat_write_signalling_fd (int wsig);
80
extern void  __gnat_close_signalling_fd (int sig);
81
extern void __gnat_last_socket_in_set (fd_set *, int *);
82
extern void __gnat_get_socket_from_set (fd_set *, int *, int *);
83
extern void __gnat_insert_socket_in_set (fd_set *, int);
84
extern int __gnat_is_socket_in_set (fd_set *, int);
85
extern fd_set *__gnat_new_socket_set (fd_set *);
86
extern void __gnat_remove_socket_from_set (fd_set *, int);
87
extern void __gnat_reset_socket_set (fd_set *);
88
extern int  __gnat_get_h_errno (void);
89
extern int  __gnat_socket_ioctl (int, int, int *);
90
extern char * __gnat_servent_s_name (struct servent *);
91
extern char ** __gnat_servent_s_aliases (struct servent *);
92
extern int __gnat_servent_s_port (struct servent *);
93
extern char * __gnat_servent_s_proto (struct servent *);
94
extern void __gnat_servent_set_s_name (struct servent *, char *);
95
extern void __gnat_servent_set_s_aliases (struct servent *, char **);
96
extern void __gnat_servent_set_s_port (struct servent *, int);
97
extern void __gnat_servent_set_s_proto (struct servent *, char *);
98
#if defined (__vxworks) || defined (_WIN32)
99
extern int  __gnat_inet_pton (int, const char *, void *);
100
#endif
101
 
102
/* Disable the sending of SIGPIPE for writes on a broken stream */
103
 
104
void
105
__gnat_disable_sigpipe (int fd)
106
{
107
#ifdef SO_NOSIGPIPE
108
  int val = 1;
109
  (void) setsockopt (fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof val);
110
#endif
111
}
112
 
113
void
114
__gnat_disable_all_sigpipes (void)
115
{
116
#if !defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL) && defined(SIGPIPE)
117
  (void) signal (SIGPIPE, SIG_IGN);
118
#endif
119
}
120
 
121
#if defined (_WIN32) || defined (__vxworks) || defined (VMS)
122
/*
123
 * Signalling FDs operations are implemented in Ada for these platforms
124
 * (see subunit GNAT.Sockets.Thin.Signalling_Fds).
125
 */
126
#else
127
/*
128
 * Create a pair of connected file descriptors fds[0] and fds[1] used for
129
 * signalling by a Selector object. fds[0] is the read end, and fds[1] the
130
 * write end.
131
 */
132
int
133
__gnat_create_signalling_fds (int *fds) {
134
  return pipe (fds);
135
}
136
 
137
/*
138
 * Read one byte of data from rsig, the read end of a pair of signalling fds
139
 * created by __gnat_create_signalling_fds.
140
 */
141
int
142
__gnat_read_signalling_fd (int rsig) {
143
  char c;
144
  return read (rsig, &c, 1);
145
}
146
 
147
/*
148
 * Write one byte of data to wsig, the write end of a pair of signalling fds
149
 * created by __gnat_create_signalling_fds.
150
 */
151
int
152
__gnat_write_signalling_fd (int wsig) {
153
  char c = 0;
154
  return write (wsig, &c, 1);
155
}
156
 
157
/*
158
 * Close one end of a pair of signalling fds
159
 */
160
void
161
__gnat_close_signalling_fd (int sig) {
162
  (void) close (sig);
163
}
164
#endif
165
 
166
/*
167
 * GetXXXbyYYY wrappers
168
 * These functions are used by the default implementation of g-socthi,
169
 * and also by the Windows version.
170
 *
171
 * They can be used for any platform that either provides an intrinsically
172
 * task safe implementation of getXXXbyYYY, or a reentrant variant
173
 * getXXXbyYYY_r. Otherwise, a task safe wrapper, including proper mutual
174
 * exclusion if appropriate, must be implemented in the target specific
175
 * version of g-socthi.
176
 */
177
 
178
#ifdef HAVE_THREAD_SAFE_GETxxxBYyyy
179
int
180
__gnat_safe_gethostbyname (const char *name,
181
  struct hostent *ret, char *buf, size_t buflen,
182
  int *h_errnop)
183
{
184
  struct hostent *rh;
185
  rh = gethostbyname (name);
186
  if (rh == NULL) {
187
    *h_errnop = h_errno;
188
    return -1;
189
  }
190
  *ret = *rh;
191
  *h_errnop = 0;
192
  return 0;
193
}
194
 
195
int
196
__gnat_safe_gethostbyaddr (const char *addr, int len, int type,
197
  struct hostent *ret, char *buf, size_t buflen,
198
  int *h_errnop)
199
{
200
  struct hostent *rh;
201
  rh = gethostbyaddr (addr, len, type);
202
  if (rh == NULL) {
203
    *h_errnop = h_errno;
204
    return -1;
205
  }
206
  *ret = *rh;
207
  *h_errnop = 0;
208
  return 0;
209
}
210
 
211
int
212
__gnat_safe_getservbyname (const char *name, const char *proto,
213
  struct servent *ret, char *buf, size_t buflen)
214
{
215
  struct servent *rh;
216
  rh = getservbyname (name, proto);
217
  if (rh == NULL)
218
    return -1;
219
  *ret = *rh;
220
  return 0;
221
}
222
 
223
int
224
__gnat_safe_getservbyport (int port, const char *proto,
225
  struct servent *ret, char *buf, size_t buflen)
226
{
227
  struct servent *rh;
228
  rh = getservbyport (port, proto);
229
  if (rh == NULL)
230
    return -1;
231
  *ret = *rh;
232
  return 0;
233
}
234
#elif HAVE_GETxxxBYyyy_R
235
int
236
__gnat_safe_gethostbyname (const char *name,
237
  struct hostent *ret, char *buf, size_t buflen,
238
  int *h_errnop)
239
{
240
  struct hostent *rh;
241
  int ri;
242
 
243
#if defined(__linux__) || defined(__GLIBC__)
244
  (void) gethostbyname_r (name, ret, buf, buflen, &rh, h_errnop);
245
#else
246
  rh = gethostbyname_r (name, ret, buf, buflen, h_errnop);
247
#endif
248
  ri = (rh == NULL) ? -1 : 0;
249
  return ri;
250
}
251
 
252
int
253
__gnat_safe_gethostbyaddr (const char *addr, int len, int type,
254
  struct hostent *ret, char *buf, size_t buflen,
255
  int *h_errnop)
256
{
257
  struct hostent *rh;
258
  int ri;
259
 
260
#if defined(__linux__) || defined(__GLIBC__)
261
  (void) gethostbyaddr_r (addr, len, type, ret, buf, buflen, &rh, h_errnop);
262
#else
263
  rh = gethostbyaddr_r (addr, len, type, ret, buf, buflen, h_errnop);
264
#endif
265
  ri = (rh == NULL) ? -1 : 0;
266
  return ri;
267
}
268
 
269
int
270
__gnat_safe_getservbyname (const char *name, const char *proto,
271
  struct servent *ret, char *buf, size_t buflen)
272
{
273
  struct servent *rh;
274
  int ri;
275
 
276
#if defined(__linux__) || defined(__GLIBC__) || defined(__rtems__)
277
  (void) getservbyname_r (name, proto, ret, buf, buflen, &rh);
278
#else
279
  rh = getservbyname_r (name, proto, ret, buf, buflen);
280
#endif
281
  ri = (rh == NULL) ? -1 : 0;
282
  return ri;
283
}
284
 
285
int
286
__gnat_safe_getservbyport (int port, const char *proto,
287
  struct servent *ret, char *buf, size_t buflen)
288
{
289
  struct servent *rh;
290
  int ri;
291
 
292
#if defined(__linux__) || defined(__GLIBC__) || defined(__rtems__)
293
  (void) getservbyport_r (port, proto, ret, buf, buflen, &rh);
294
#else
295
  rh = getservbyport_r (port, proto, ret, buf, buflen);
296
#endif
297
  ri = (rh == NULL) ? -1 : 0;
298
  return ri;
299
}
300
#endif
301
 
302
/* Find the largest socket in the socket set SET. This is needed for
303
   `select'.  LAST is the maximum value for the largest socket. This hint is
304
   used to avoid scanning very large socket sets.  On return, LAST is the
305
   actual largest socket in the socket set. */
306
 
307
void
308
__gnat_last_socket_in_set (fd_set *set, int *last)
309
{
310
  int s;
311
  int l;
312
  l = -1;
313
 
314
#ifdef _WIN32
315
  /* More efficient method for NT. */
316
  for (s = 0; s < set->fd_count; s++)
317
    if ((int) set->fd_array[s] > l)
318
      l = set->fd_array[s];
319
 
320
#else
321
 
322
  for (s = *last; s != -1; s--)
323
    if (FD_ISSET (s, set))
324
      {
325
        l = s;
326
        break;
327
      }
328
#endif
329
 
330
  *last = l;
331
}
332
 
333
/* Get last socket and remove it from the socket set SET.  LAST is the
334
   maximum value of the largest socket.  This hint is used to avoid scanning
335
   very large socket sets.  On return, LAST is set to the actual largest
336
   socket in the socket set. */
337
 
338
void
339
__gnat_get_socket_from_set (fd_set *set, int *last, int *socket)
340
{
341
  *socket = *last;
342
  FD_CLR (*socket, set);
343
  __gnat_last_socket_in_set (set, last);
344
}
345
 
346
/* Insert SOCKET in the socket set SET. */
347
 
348
void
349
__gnat_insert_socket_in_set (fd_set *set, int socket)
350
{
351
  FD_SET (socket, set);
352
}
353
 
354
/* Check whether a given SOCKET is in the socket set SET. */
355
 
356
int
357
__gnat_is_socket_in_set (fd_set *set, int socket)
358
{
359
  return FD_ISSET (socket, set);
360
}
361
 
362
/* Remove SOCKET from the socket set SET. */
363
 
364
void
365
__gnat_remove_socket_from_set (fd_set *set, int socket)
366
{
367
  FD_CLR (socket, set);
368
}
369
 
370
/* Reset SET */
371
void
372
__gnat_reset_socket_set (fd_set *set)
373
{
374
  FD_ZERO (set);
375
}
376
 
377
/* Get the value of the last host error */
378
 
379
int
380
__gnat_get_h_errno (void) {
381
#ifdef __vxworks
382
  int vxw_errno = errno;
383
 
384
  switch (vxw_errno) {
385
    case 0:
386
      return 0;
387
 
388
#ifdef S_hostLib_HOST_NOT_FOUND
389
    case S_hostLib_HOST_NOT_FOUND:
390
#endif
391
    case S_hostLib_UNKNOWN_HOST:
392
      return HOST_NOT_FOUND;
393
 
394
#ifdef S_hostLib_TRY_AGAIN
395
    case S_hostLib_TRY_AGAIN:
396
      return TRY_AGAIN;
397
#endif
398
 
399
#ifdef S_hostLib_NO_RECOVERY
400
    case S_hostLib_NO_RECOVERY:
401
#endif
402
#ifdef S_hostLib_NETDB_INTERNAL
403
    case S_hostLib_NETDB_INTERNAL:
404
#endif
405
    case S_hostLib_INVALID_PARAMETER:
406
      return NO_RECOVERY;
407
 
408
    default:
409
      return -1;
410
  }
411
 
412
#elif defined (VMS)
413
  /* h_errno is defined as follows in OpenVMS' version of <netdb.h>.
414
   * However this header file is not available when building the GNAT
415
   * runtime library using GCC, so we are hardcoding the definition
416
   * directly. Note that the returned address is thread-specific.
417
   */
418
  extern int *decc$h_errno_get_addr ();
419
  return *decc$h_errno_get_addr ();
420
 
421
#elif defined (__rtems__)
422
  /* At this stage in the tool build, no networking .h files are available.
423
   * Newlib does not provide networking .h files and RTEMS is not built yet.
424
   * So we need to explicitly extern h_errno to access it.
425
   */
426
  extern int h_errno;
427
  return h_errno;
428
 
429
#else
430
  return h_errno;
431
#endif
432
}
433
 
434
/* Wrapper for ioctl(2), which is a variadic function */
435
 
436
int
437
__gnat_socket_ioctl (int fd, int req, int *arg) {
438
#if defined (_WIN32)
439
  return ioctlsocket (fd, req, arg);
440
#else
441
  return ioctl (fd, req, arg);
442
#endif
443
}
444
 
445
#ifndef HAVE_INET_PTON
446
 
447
#ifdef VMS
448
# define in_addr_t int
449
# define inet_addr decc$inet_addr
450
#endif
451
 
452
int
453
__gnat_inet_pton (int af, const char *src, void *dst) {
454
  switch (af) {
455
#if defined (_WIN32) && defined (AF_INET6)
456
    case AF_INET6:
457
#endif
458
    case AF_INET:
459
      break;
460
    default:
461
      errno = EAFNOSUPPORT;
462
      return -1;
463
  }
464
 
465
#if defined (__vxworks)
466
  return (inet_aton (src, dst) == OK);
467
 
468
#elif defined (_WIN32)
469
  struct sockaddr_storage ss;
470
  int sslen = sizeof ss;
471
  int rc;
472
 
473
  ss.ss_family = af;
474
  rc = WSAStringToAddressA (src, af, NULL, (struct sockaddr *)&ss, &sslen);
475
  if (rc == 0) {
476
    switch (af) {
477
      case AF_INET:
478
        *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
479
        break;
480
#ifdef AF_INET6
481
      case AF_INET6:
482
        *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
483
        break;
484
#endif
485
    }
486
  }
487
  return (rc == 0);
488
 
489
#elif defined (__hpux__) || defined (VMS)
490
  in_addr_t addr;
491
  int rc = -1;
492
 
493
  if (src == NULL || dst == NULL) {
494
    errno = EINVAL;
495
 
496
  } else if (!strcmp (src, "255.255.255.255")) {
497
    addr = 0xffffffff;
498
    rc = 1;
499
 
500
  } else {
501
    addr = inet_addr (src);
502
    rc = (addr != 0xffffffff);
503
  }
504
  if (rc == 1) {
505
    *(in_addr_t *)dst = addr;
506
  }
507
  return rc;
508
#endif
509
}
510
#endif
511
 
512
/*
513
 * Accessor functions for struct servent.
514
 *
515
 * These are needed because servent has different representations on different
516
 * platforms, and we don't want to deal with that on the Ada side. For example,
517
 * on Linux, we have (see /usr/include netdb.h):
518
 *
519
 *   struct servent
520
 *   {
521
 *     char *s_name;
522
 *     char **s_aliases;
523
 *     int s_port;
524
 *     char *s_proto;
525
 *   };
526
 *
527
 * and on Windows (see mingw's socket.h):
528
 *
529
 *   struct servent {
530
 *     char *s_name;
531
 *     char **s_aliases;
532
 *   #ifdef _WIN64
533
 *     char *s_proto;
534
 *     short s_port;
535
 *   #else
536
 *     short s_port;
537
 *     char *s_proto;
538
 *   #endif
539
 *   };
540
 */
541
 
542
/* Getters */
543
 
544
char *
545
__gnat_servent_s_name (struct servent * s)
546
{
547
  return s->s_name;
548
}
549
 
550
char **
551
__gnat_servent_s_aliases (struct servent * s)
552
{
553
  return s->s_aliases;
554
}
555
 
556
int
557
__gnat_servent_s_port (struct servent * s)
558
{
559
  return s->s_port;
560
}
561
 
562
char *
563
__gnat_servent_s_proto (struct servent * s)
564
{
565
  return s->s_proto;
566
}
567
 
568
/* Setters */
569
 
570
void
571
__gnat_servent_set_s_name (struct servent * s, char * s_name)
572
{
573
  s->s_name = s_name;
574
}
575
 
576
void
577
__gnat_servent_set_s_aliases (struct servent * s, char ** s_aliases)
578
{
579
  s->s_aliases = s_aliases;
580
}
581
 
582
void
583
__gnat_servent_set_s_port (struct servent * s, int s_port)
584
{
585
  s->s_port = s_port;
586
}
587
 
588
void
589
__gnat_servent_set_s_proto (struct servent * s, char * s_proto)
590
{
591
  s->s_proto = s_proto;
592
}
593
 
594
#else
595
# warning Sockets are not supported on this platform
596
#endif /* defined(HAVE_SOCKETS) */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.