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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [ada/] [socket.c] - Blame information for rev 711

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

Line No. Rev Author Line
1 706 jeremybenn
/****************************************************************************
2
 *                                                                          *
3
 *                         GNAT COMPILER COMPONENTS                         *
4
 *                                                                          *
5
 *                               S O C K E T                                *
6
 *                                                                          *
7
 *                          C Implementation File                           *
8
 *                                                                          *
9
 *          Copyright (C) 2003-2010, 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
 
36
#ifdef VMS
37
/*
38
 * For VMS, gsocket.h can't include sockets-related DEC C header files
39
 * when building the runtime (because these files are in a DEC C text library
40
 * (DECC$RTLDEF.TLB) not accessible to GCC). So, we generate a separate header
41
 * file along with s-oscons.ads and include it here.
42
 */
43
# include "s-oscons.h"
44
 
45
/*
46
 * We also need the declaration of struct hostent/servent, which s-oscons
47
 * can't provide, so we copy it manually here. This needs to be kept in synch
48
 * with the definition of that structure in the DEC C headers, which
49
 * hopefully won't change frequently.
50
 */
51
typedef char *__netdb_char_ptr __attribute__ (( mode (SI) ));
52
typedef __netdb_char_ptr *__netdb_char_ptr_ptr __attribute__ (( mode (SI) ));
53
 
54
struct hostent {
55
  __netdb_char_ptr     h_name;
56
  __netdb_char_ptr_ptr h_aliases;
57
  int                  h_addrtype;
58
  int                  h_length;
59
  __netdb_char_ptr_ptr h_addr_list;
60
};
61
 
62
struct servent {
63
  __netdb_char_ptr     s_name;
64
  __netdb_char_ptr_ptr s_aliases;
65
  int                  s_port;
66
  __netdb_char_ptr     s_proto;
67
};
68
#endif
69
 
70
#if defined(HAVE_SOCKETS)
71
 
72
/* Include all the necessary system-specific headers and define the
73
 * necessary macros (shared with gen-oscons).
74
 */
75
 
76
#if !defined(SO_NOSIGPIPE) && !defined (MSG_NOSIGNAL)
77
#include <signal.h>
78
#endif
79
/* Required if we will be calling signal() in __gnat_disable_all_sigpipes() */
80
 
81
#include "raise.h"
82
/* Required for __gnat_malloc() */
83
 
84
#include <string.h>
85
/* Required for memcpy() */
86
 
87
extern void __gnat_disable_sigpipe (int fd);
88
extern void __gnat_disable_all_sigpipes (void);
89
extern int  __gnat_create_signalling_fds (int *fds);
90
extern int  __gnat_read_signalling_fd (int rsig);
91
extern int  __gnat_write_signalling_fd (int wsig);
92
extern void  __gnat_close_signalling_fd (int sig);
93
extern void __gnat_last_socket_in_set (fd_set *, int *);
94
extern void __gnat_get_socket_from_set (fd_set *, int *, int *);
95
extern void __gnat_insert_socket_in_set (fd_set *, int);
96
extern int __gnat_is_socket_in_set (fd_set *, int);
97
extern fd_set *__gnat_new_socket_set (fd_set *);
98
extern void __gnat_remove_socket_from_set (fd_set *, int);
99
extern void __gnat_reset_socket_set (fd_set *);
100
extern int  __gnat_get_h_errno (void);
101
extern int  __gnat_socket_ioctl (int, int, int *);
102
 
103
extern char * __gnat_servent_s_name (struct servent *);
104
extern char * __gnat_servent_s_alias (struct servent *, int index);
105
extern unsigned short __gnat_servent_s_port (struct servent *);
106
extern char * __gnat_servent_s_proto (struct servent *);
107
 
108
extern char * __gnat_hostent_h_name (struct hostent *);
109
extern char * __gnat_hostent_h_alias (struct hostent *, int);
110
extern int __gnat_hostent_h_addrtype (struct hostent *);
111
extern int __gnat_hostent_h_length (struct hostent *);
112
extern char * __gnat_hostent_h_addr (struct hostent *, int);
113
 
114
#ifndef HAVE_INET_PTON
115
extern int  __gnat_inet_pton (int, const char *, void *);
116
#endif
117
 
118
/* Disable the sending of SIGPIPE for writes on a broken stream */
119
 
120
void
121
__gnat_disable_sigpipe (int fd)
122
{
123
#ifdef SO_NOSIGPIPE
124
  int val = 1;
125
  (void) setsockopt (fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof val);
126
#endif
127
}
128
 
129
void
130
__gnat_disable_all_sigpipes (void)
131
{
132
#if !defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL) && defined(SIGPIPE)
133
  (void) signal (SIGPIPE, SIG_IGN);
134
#endif
135
}
136
 
137
#if defined (_WIN32) || defined (__vxworks) || defined (VMS)
138
/*
139
 * Signalling FDs operations are implemented in Ada for these platforms
140
 * (see subunit GNAT.Sockets.Thin.Signalling_Fds).
141
 */
142
#else
143
/*
144
 * Create a pair of connected file descriptors fds[0] and fds[1] used for
145
 * signalling by a Selector object. fds[0] is the read end, and fds[1] the
146
 * write end.
147
 */
148
int
149
__gnat_create_signalling_fds (int *fds) {
150
  return pipe (fds);
151
}
152
 
153
/*
154
 * Read one byte of data from rsig, the read end of a pair of signalling fds
155
 * created by __gnat_create_signalling_fds.
156
 */
157
int
158
__gnat_read_signalling_fd (int rsig) {
159
  char c;
160
  return read (rsig, &c, 1);
161
}
162
 
163
/*
164
 * Write one byte of data to wsig, the write end of a pair of signalling fds
165
 * created by __gnat_create_signalling_fds.
166
 */
167
int
168
__gnat_write_signalling_fd (int wsig) {
169
  char c = 0;
170
  return write (wsig, &c, 1);
171
}
172
 
173
/*
174
 * Close one end of a pair of signalling fds
175
 */
176
void
177
__gnat_close_signalling_fd (int sig) {
178
  (void) close (sig);
179
}
180
#endif
181
 
182
/*
183
 * Handling of gethostbyname, gethostbyaddr, getservbyname and getservbyport
184
 * =========================================================================
185
 *
186
 * This module exposes __gnat_getXXXbyYYY operations with the same signature
187
 * as the reentrant variant getXXXbyYYY_r.
188
 *
189
 * On platforms where getXXXbyYYY is intrinsically reentrant, the provided user
190
 * buffer argument is ignored.
191
 *
192
 * When getXXXbyYYY is not reentrant but getXXXbyYYY_r exists, the latter is
193
 * used, and the provided buffer argument must point to a valid, thread-local
194
 * buffer (usually on the caller's stack).
195
 *
196
 * When getXXXbyYYY is not reentrant and no reentrant getXXXbyYYY_r variant
197
 * is available, the non-reentrant getXXXbyYYY is called, the provided user
198
 * buffer is ignored, and the caller is expected to take care of mutual
199
 * exclusion.
200
 */
201
 
202
#ifdef HAVE_GETxxxBYyyy_R
203
int
204
__gnat_gethostbyname (const char *name,
205
  struct hostent *ret, char *buf, size_t buflen,
206
  int *h_errnop)
207
{
208
  struct hostent *rh;
209
  int ri;
210
 
211
#if defined(__linux__) || defined(__GLIBC__)
212
  (void) gethostbyname_r (name, ret, buf, buflen, &rh, h_errnop);
213
#else
214
  rh = gethostbyname_r (name, ret, buf, buflen, h_errnop);
215
#endif
216
  ri = (rh == NULL) ? -1 : 0;
217
  return ri;
218
}
219
 
220
int
221
__gnat_gethostbyaddr (const char *addr, int len, int type,
222
  struct hostent *ret, char *buf, size_t buflen,
223
  int *h_errnop)
224
{
225
  struct hostent *rh;
226
  int ri;
227
 
228
#if defined(__linux__) || defined(__GLIBC__)
229
  (void) gethostbyaddr_r (addr, len, type, ret, buf, buflen, &rh, h_errnop);
230
#else
231
  rh = gethostbyaddr_r (addr, len, type, ret, buf, buflen, h_errnop);
232
#endif
233
  ri = (rh == NULL) ? -1 : 0;
234
  return ri;
235
}
236
 
237
int
238
__gnat_getservbyname (const char *name, const char *proto,
239
  struct servent *ret, char *buf, size_t buflen)
240
{
241
  struct servent *rh;
242
  int ri;
243
 
244
#if defined(__linux__) || defined(__GLIBC__) || defined(__rtems__)
245
  (void) getservbyname_r (name, proto, ret, buf, buflen, &rh);
246
#else
247
  rh = getservbyname_r (name, proto, ret, buf, buflen);
248
#endif
249
  ri = (rh == NULL) ? -1 : 0;
250
  return ri;
251
}
252
 
253
int
254
__gnat_getservbyport (int port, const char *proto,
255
  struct servent *ret, char *buf, size_t buflen)
256
{
257
  struct servent *rh;
258
  int ri;
259
 
260
#if defined(__linux__) || defined(__GLIBC__) || defined(__rtems__)
261
  (void) getservbyport_r (port, proto, ret, buf, buflen, &rh);
262
#else
263
  rh = getservbyport_r (port, proto, ret, buf, buflen);
264
#endif
265
  ri = (rh == NULL) ? -1 : 0;
266
  return ri;
267
}
268
#elif defined (__vxworks)
269
static char vxw_h_name[MAXHOSTNAMELEN + 1];
270
static char *vxw_h_aliases[1] = { NULL };
271
static int vxw_h_addr;
272
static char *vxw_h_addr_list[2] = { (char*) &vxw_h_addr, NULL };
273
 
274
int
275
__gnat_gethostbyname (const char *name,
276
  struct hostent *ret, char *buf, size_t buflen,
277
  int *h_errnop)
278
{
279
  vxw_h_addr = hostGetByName (name);
280
  if (vxw_h_addr == ERROR) {
281
    *h_errnop = __gnat_get_h_errno ();
282
    return -1;
283
  }
284
  ret->h_name      = name;
285
  ret->h_aliases   = &vxw_h_aliases;
286
  ret->h_addrtype  = AF_INET;
287
  ret->h_length    = 4;
288
  ret->h_addr_list = &vxw_h_addr_list;
289
  return 0;
290
}
291
 
292
int
293
__gnat_gethostbyaddr (const char *addr, int len, int type,
294
  struct hostent *ret, char *buf, size_t buflen,
295
  int *h_errnop)
296
{
297
  if (type != AF_INET) {
298
    *h_errnop = EAFNOSUPPORT;
299
    return -1;
300
  }
301
 
302
  if (addr == NULL || len != 4) {
303
    *h_errnop = EINVAL;
304
    return -1;
305
  }
306
 
307
  if (hostGetByAddr (*(int*)addr, &vxw_h_name) != OK) {
308
    *h_errnop = __gnat_get_h_errno ();
309
    return -1;
310
  }
311
 
312
  vxw_h_addr       = addr;
313
 
314
  ret->h_name      = &vxw_h_name;
315
  ret->h_aliases   = &vxw_h_aliases;
316
  ret->h_addrtype  = AF_INET;
317
  ret->h_length    = 4;
318
  ret->h_addr_list = &vxw_h_addr_list;
319
}
320
 
321
int
322
__gnat_getservbyname (const char *name, const char *proto,
323
  struct servent *ret, char *buf, size_t buflen)
324
{
325
  /* Not available under VxWorks */
326
  return -1;
327
}
328
 
329
int
330
__gnat_getservbyport (int port, const char *proto,
331
  struct servent *ret, char *buf, size_t buflen)
332
{
333
  /* Not available under VxWorks */
334
  return -1;
335
}
336
#else
337
int
338
__gnat_gethostbyname (const char *name,
339
  struct hostent *ret, char *buf, size_t buflen,
340
  int *h_errnop)
341
{
342
  struct hostent *rh;
343
  rh = gethostbyname (name);
344
  if (rh == NULL) {
345
    *h_errnop = __gnat_get_h_errno ();
346
    return -1;
347
  }
348
  *ret = *rh;
349
  *h_errnop = 0;
350
  return 0;
351
}
352
 
353
int
354
__gnat_gethostbyaddr (const char *addr, int len, int type,
355
  struct hostent *ret, char *buf, size_t buflen,
356
  int *h_errnop)
357
{
358
  struct hostent *rh;
359
  rh = gethostbyaddr (addr, len, type);
360
  if (rh == NULL) {
361
    *h_errnop = __gnat_get_h_errno ();
362
    return -1;
363
  }
364
  *ret = *rh;
365
  *h_errnop = 0;
366
  return 0;
367
}
368
 
369
int
370
__gnat_getservbyname (const char *name, const char *proto,
371
  struct servent *ret, char *buf, size_t buflen)
372
{
373
  struct servent *rh;
374
  rh = getservbyname (name, proto);
375
  if (rh == NULL)
376
    return -1;
377
  *ret = *rh;
378
  return 0;
379
}
380
 
381
int
382
__gnat_getservbyport (int port, const char *proto,
383
  struct servent *ret, char *buf, size_t buflen)
384
{
385
  struct servent *rh;
386
  rh = getservbyport (port, proto);
387
  if (rh == NULL)
388
    return -1;
389
  *ret = *rh;
390
  return 0;
391
}
392
#endif
393
 
394
/* Find the largest socket in the socket set SET. This is needed for
395
   `select'.  LAST is the maximum value for the largest socket. This hint is
396
   used to avoid scanning very large socket sets.  On return, LAST is the
397
   actual largest socket in the socket set. */
398
 
399
void
400
__gnat_last_socket_in_set (fd_set *set, int *last)
401
{
402
  int s;
403
  int l;
404
  l = -1;
405
 
406
#ifdef _WIN32
407
  /* More efficient method for NT. */
408
  for (s = 0; s < set->fd_count; s++)
409
    if ((int) set->fd_array[s] > l)
410
      l = set->fd_array[s];
411
 
412
#else
413
 
414
  for (s = *last; s != -1; s--)
415
    if (FD_ISSET (s, set))
416
      {
417
        l = s;
418
        break;
419
      }
420
#endif
421
 
422
  *last = l;
423
}
424
 
425
/* Get last socket and remove it from the socket set SET.  LAST is the
426
   maximum value of the largest socket.  This hint is used to avoid scanning
427
   very large socket sets.  On return, LAST is set to the actual largest
428
   socket in the socket set. */
429
 
430
void
431
__gnat_get_socket_from_set (fd_set *set, int *last, int *socket)
432
{
433
  *socket = *last;
434
  FD_CLR (*socket, set);
435
  __gnat_last_socket_in_set (set, last);
436
}
437
 
438
/* Insert SOCKET in the socket set SET. */
439
 
440
void
441
__gnat_insert_socket_in_set (fd_set *set, int socket)
442
{
443
  FD_SET (socket, set);
444
}
445
 
446
/* Check whether a given SOCKET is in the socket set SET. */
447
 
448
int
449
__gnat_is_socket_in_set (fd_set *set, int socket)
450
{
451
  return FD_ISSET (socket, set);
452
}
453
 
454
/* Remove SOCKET from the socket set SET. */
455
 
456
void
457
__gnat_remove_socket_from_set (fd_set *set, int socket)
458
{
459
  FD_CLR (socket, set);
460
}
461
 
462
/* Reset SET */
463
void
464
__gnat_reset_socket_set (fd_set *set)
465
{
466
  FD_ZERO (set);
467
}
468
 
469
/* Get the value of the last host error */
470
 
471
int
472
__gnat_get_h_errno (void) {
473
#ifdef __vxworks
474
  int vxw_errno = errno;
475
 
476
  switch (vxw_errno) {
477
    case 0:
478
      return 0;
479
 
480
#ifdef S_hostLib_HOST_NOT_FOUND
481
    case S_hostLib_HOST_NOT_FOUND:
482
#endif
483
    case S_hostLib_UNKNOWN_HOST:
484
      return HOST_NOT_FOUND;
485
 
486
#ifdef S_hostLib_TRY_AGAIN
487
    case S_hostLib_TRY_AGAIN:
488
      return TRY_AGAIN;
489
#endif
490
 
491
#ifdef S_hostLib_NO_RECOVERY
492
    case S_hostLib_NO_RECOVERY:
493
#endif
494
#ifdef S_hostLib_NETDB_INTERNAL
495
    case S_hostLib_NETDB_INTERNAL:
496
#endif
497
    case S_hostLib_INVALID_PARAMETER:
498
      return NO_RECOVERY;
499
 
500
    default:
501
      return -1;
502
  }
503
 
504
#elif defined (VMS)
505
  /* h_errno is defined as follows in OpenVMS' version of <netdb.h>.
506
   * However this header file is not available when building the GNAT
507
   * runtime library using GCC, so we are hardcoding the definition
508
   * directly. Note that the returned address is thread-specific.
509
   */
510
  extern int *decc$h_errno_get_addr ();
511
  return *decc$h_errno_get_addr ();
512
 
513
#elif defined (__rtems__)
514
  /* At this stage in the tool build, no networking .h files are available.
515
   * Newlib does not provide networking .h files and RTEMS is not built yet.
516
   * So we need to explicitly extern h_errno to access it.
517
   */
518
  extern int h_errno;
519
  return h_errno;
520
 
521
#else
522
  return h_errno;
523
#endif
524
}
525
 
526
/* Wrapper for ioctl(2), which is a variadic function */
527
 
528
int
529
__gnat_socket_ioctl (int fd, int req, int *arg) {
530
#if defined (_WIN32)
531
  return ioctlsocket (fd, req, arg);
532
#elif defined (__APPLE__)
533
  /*
534
   * On Darwin, req is an unsigned long, and we want to convert without sign
535
   * extension to get the proper bit pattern in the case of a 64 bit kernel.
536
   */
537
  return ioctl (fd, (unsigned int) req, arg);
538
#else
539
  return ioctl (fd, req, arg);
540
#endif
541
}
542
 
543
#ifndef HAVE_INET_PTON
544
 
545
#ifdef VMS
546
# define in_addr_t int
547
# define inet_addr decc$inet_addr
548
#endif
549
 
550
int
551
__gnat_inet_pton (int af, const char *src, void *dst) {
552
  switch (af) {
553
#if defined (_WIN32) && defined (AF_INET6)
554
    case AF_INET6:
555
#endif
556
    case AF_INET:
557
      break;
558
    default:
559
      errno = EAFNOSUPPORT;
560
      return -1;
561
  }
562
 
563
#if defined (__vxworks)
564
  return (inet_aton (src, dst) == OK);
565
 
566
#elif defined (_WIN32)
567
  struct sockaddr_storage ss;
568
  int sslen = sizeof ss;
569
  int rc;
570
 
571
  ss.ss_family = af;
572
  rc = WSAStringToAddressA (src, af, NULL, (struct sockaddr *)&ss, &sslen);
573
  if (rc == 0) {
574
    switch (af) {
575
      case AF_INET:
576
        *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
577
        break;
578
#ifdef AF_INET6
579
      case AF_INET6:
580
        *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
581
        break;
582
#endif
583
    }
584
  }
585
  return (rc == 0);
586
 
587
#elif defined (__hpux__) || defined (VMS)
588
  in_addr_t addr;
589
  int rc = -1;
590
 
591
  if (src == NULL || dst == NULL) {
592
    errno = EINVAL;
593
 
594
  } else if (!strcmp (src, "255.255.255.255")) {
595
    addr = 0xffffffff;
596
    rc = 1;
597
 
598
  } else {
599
    addr = inet_addr (src);
600
    rc = (addr != 0xffffffff);
601
  }
602
  if (rc == 1) {
603
    *(in_addr_t *)dst = addr;
604
  }
605
  return rc;
606
#endif
607
}
608
#endif
609
 
610
/*
611
 * Accessor functions for struct hostent.
612
 */
613
 
614
char * __gnat_hostent_h_name (struct hostent * h) {
615
  return h->h_name;
616
}
617
 
618
char * __gnat_hostent_h_alias (struct hostent * h, int index) {
619
  return h->h_aliases[index];
620
}
621
 
622
int __gnat_hostent_h_addrtype (struct hostent * h) {
623
  return h->h_addrtype;
624
}
625
 
626
int __gnat_hostent_h_length (struct hostent * h) {
627
  return h->h_length;
628
}
629
 
630
char * __gnat_hostent_h_addr (struct hostent * h, int index) {
631
  return h->h_addr_list[index];
632
}
633
 
634
/*
635
 * Accessor functions for struct servent.
636
 *
637
 * These are needed because servent has different representations on different
638
 * platforms, and we don't want to deal with that on the Ada side. For example,
639
 * on Linux, we have (see /usr/include netdb.h):
640
 *
641
 *   struct servent
642
 *   {
643
 *     char *s_name;
644
 *     char **s_aliases;
645
 *     int s_port;
646
 *     char *s_proto;
647
 *   };
648
 *
649
 * and on Windows (see mingw's socket.h):
650
 *
651
 *   struct servent {
652
 *     char *s_name;
653
 *     char **s_aliases;
654
 *   #ifdef _WIN64
655
 *     char *s_proto;
656
 *     short s_port;
657
 *   #else
658
 *     short s_port;
659
 *     char *s_proto;
660
 *   #endif
661
 *   };
662
 */
663
 
664
char *
665
__gnat_servent_s_name (struct servent * s)
666
{
667
  return s->s_name;
668
}
669
 
670
char *
671
__gnat_servent_s_alias (struct servent * s, int index)
672
{
673
  return s->s_aliases[index];
674
}
675
 
676
unsigned short
677
__gnat_servent_s_port (struct servent * s)
678
{
679
  return s->s_port;
680
}
681
 
682
char *
683
__gnat_servent_s_proto (struct servent * s)
684
{
685
  return s->s_proto;
686
}
687
 
688
#else
689
# warning Sockets are not supported on this platform
690
#endif /* defined(HAVE_SOCKETS) */

powered by: WebSVN 2.1.0

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