Annotation of uae/src/bsdsocket-posix-new.c, revision 1.1.1.1

1.1       root        1: /*
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   *
                      4:   * bsdsocket.library emulation - Unix
                      5:   *
                      6:   * Copyright 2000-2001 Carl Drougge <[email protected]> <[email protected]>
                      7:   * Copyright 2003-2005 Richard Drummond
                      8:   * Copyright 2004      Jeff Shepherd
                      9:   *
                     10:   * This program is free software; you can redistribute it and/or modify
                     11:   * it under the terms of the GNU General Public License as published by
                     12:   * the Free Software Foundation; either version 2 of the License, or
                     13:   * (at your option) any later version.
                     14:   *
                     15:   * This program is distributed in the hope that it will be useful,
                     16:   * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17:   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18:   * GNU General Public License for more details.
                     19:   *
                     20:   * You should have received a copy of the GNU General Public License
                     21:   * along with this program; if not, write to the Free Software
                     22:   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23:   *
                     24:   */
                     25: 
                     26: #include "sysconfig.h"
                     27: #include "sysdeps.h"
                     28: 
                     29: #include "options.h"
                     30: #include "memory.h"
                     31: #include "custom.h"
                     32: #include "newcpu.h"
                     33: #include "autoconf.h"
                     34: #include "traps.h"
                     35: #include "threaddep/thread.h"
                     36: #include "native2amiga.h"
                     37: #include "bsdsocket.h"
                     38: 
                     39: #ifdef BSDSOCKET
                     40: #include <sys/types.h>
                     41: #include <sys/socket.h>
                     42: #include <sys/select.h>
                     43: #include <sys/ioctl.h>
                     44: #ifdef HAVE_SYS_FILIO_H
                     45: # include <sys/filio.h>
                     46: #endif
                     47: #include <netinet/in.h>
                     48: #include <netinet/tcp.h>
                     49: #include <stddef.h>
                     50: #include <netdb.h>
                     51: 
                     52: #include <signal.h>
                     53: #include <arpa/inet.h>
                     54: 
                     55: //#define DEBUG_BSDSOCKET
                     56: #ifdef DEBUG_BSDSOCKET
                     57: #define DEBUG_LOG write_log
                     58: #else
                     59: #define DEBUG_LOG(...) do ; while(0)
                     60: #endif
                     61: 
                     62: #define WAITSIGNAL     waitsig (context, sb)
                     63: 
                     64: /* Sigqueue is unsafe on SMP machines.
                     65:  * Temporary work-around.
                     66:  */
                     67: //#define SETSIGNAL    addtosigqueue (sb, 0)
                     68: #define SETSIGNAL \
                     69:     do { \
                     70:        uae_Signal (sb->ownertask, sb->sigstosend | ((uae_u32) 1) << sb->signal); \
                     71:        sb->dosignal = 1; \
                     72:     } while (0)
                     73: 
                     74: 
                     75: #define SETERRNO       bsdsocklib_seterrno (sb,mapErrno (errno))
                     76: #define SETHERRNO      bsdsocklib_setherrno (sb, h_errno)
                     77: 
                     78: 
                     79: /* BSD-systems don't seem to have MSG_NOSIGNAL..
                     80:    @@@ We need to catch SIGPIPE on those systems! (?) */
                     81: #ifndef MSG_NOSIGNAL
                     82: #define MSG_NOSIGNAL 0
                     83: #endif
                     84: 
                     85: #define S_GL_result(res) sb->resultval = (res)
                     86: 
                     87: uae_u32 bsdthr_Accept_2 (SB);
                     88: uae_u32 bsdthr_Recv_2 (SB);
                     89: uae_u32 bsdthr_blockingstuff (uae_u32 (*tryfunc)(SB), SB);
                     90: uae_u32 bsdthr_SendRecvAcceptConnect (uae_u32 (*tryfunc)(SB), SB);
                     91: uae_u32 bsdthr_Send_2 (SB);
                     92: uae_u32 bsdthr_Connect_2 (SB);
                     93: uae_u32 bsdthr_WaitSelect (SB);
                     94: uae_u32 bsdthr_Wait (SB);
                     95: void clearsockabort (SB);
                     96: 
                     97: static uae_sem_t sem_queue;
                     98: 
                     99: /**
                    100:  ** Helper functions
                    101:  **/
                    102: 
                    103: /*
                    104:  * Map host errno to amiga errno
                    105:  */
                    106: static int mapErrno (int e)
                    107: {
                    108:     switch (e) {
                    109:        case EINTR:             e = 4;  break;
                    110:        case EDEADLK:           e = 11; break;
                    111:        case EAGAIN:            e = 35; break;
                    112:        case EINPROGRESS:       e = 36; break;
                    113:        case EALREADY:          e = 37; break;
                    114:        case ENOTSOCK:          e = 38; break;
                    115:        case EDESTADDRREQ:      e = 39; break;
                    116:        case EMSGSIZE:          e = 40; break;
                    117:        case EPROTOTYPE:        e = 41; break;
                    118:        case ENOPROTOOPT:       e = 42; break;
                    119:        case EPROTONOSUPPORT:   e = 43; break;
                    120:        case ESOCKTNOSUPPORT:   e = 44; break;
                    121:        case EOPNOTSUPP:        e = 45; break;
                    122:        case EPFNOSUPPORT:      e = 46; break;
                    123:        case EAFNOSUPPORT:      e = 47; break;
                    124:        case EADDRINUSE:        e = 48; break;
                    125:        case EADDRNOTAVAIL:     e = 49; break;
                    126:        case ENETDOWN:          e = 50; break;
                    127:        case ENETUNREACH:       e = 51; break;
                    128:        case ENETRESET:         e = 52; break;
                    129:        case ECONNABORTED:      e = 53; break;
                    130:        case ECONNRESET:        e = 54; break;
                    131:        case ENOBUFS:           e = 55; break;
                    132:        case EISCONN:           e = 56; break;
                    133:        case ENOTCONN:          e = 57; break;
                    134:        case ESHUTDOWN:         e = 58; break;
                    135:        case ETOOMANYREFS:      e = 59; break;
                    136:        case ETIMEDOUT:         e = 60; break;
                    137:        case ECONNREFUSED:      e = 61; break;
                    138:        case ELOOP:             e = 62; break;
                    139:        case ENAMETOOLONG:      e = 63; break;
                    140:        default: break;
                    141:     }
                    142:     return e;
                    143: }
                    144: 
                    145: /*
                    146:  * Map amiga (s|g)etsockopt level into native one
                    147:  */
                    148: static int mapsockoptlevel (int level)
                    149: {
                    150:     switch (level) {
                    151:        case 0xffff:
                    152:            return SOL_SOCKET;
                    153:        case 0:
                    154:            return IPPROTO_IP;
                    155:        case 1:
                    156:            return IPPROTO_ICMP;
                    157:        case 2:
                    158:            return IPPROTO_IGMP;
                    159: #ifdef IPPROTO_IPIP
                    160:        case 4:
                    161:            return IPPROTO_IPIP;
                    162: #endif
                    163:        case 6:
                    164:            return IPPROTO_TCP;
                    165:        case 8:
                    166:            return IPPROTO_EGP;
                    167:        case 12:
                    168:            return IPPROTO_PUP;
                    169:        case 17:
                    170:            return IPPROTO_UDP;
                    171:        case 22:
                    172:            return IPPROTO_IDP;
                    173: #ifdef IPPROTO_TP
                    174:        case 29:
                    175:            return IPPROTO_TP;
                    176: #endif
                    177:        case 98:
                    178:            return IPPROTO_ENCAP;
                    179:        default:
                    180:            DEBUG_LOG ("Unknown sockopt level %d\n", level);
                    181:            return level;
                    182:     }
                    183: }
                    184: 
                    185: /*
                    186:  * Map amiga (s|g)etsockopt optname into native one
                    187:  */
                    188: static int mapsockoptname (int level, int optname)
                    189: {
                    190:     switch (level) {
                    191: 
                    192:        case SOL_SOCKET:
                    193:            switch (optname) {
                    194:                case 0x0001:
                    195:                    return SO_DEBUG;
                    196:                case 0x0002:
                    197:                    return SO_ACCEPTCONN;
                    198:                case 0x0004:
                    199:                    return SO_REUSEADDR;
                    200:                case 0x0008:
                    201:                    return SO_KEEPALIVE;
                    202:                case 0x0010:
                    203:                    return SO_DONTROUTE;
                    204:                case 0x0020:
                    205:                    return SO_BROADCAST;
                    206: #ifdef SO_USELOOPBACK
                    207:                case 0x0040:
                    208:                    return SO_USELOOPBACK;
                    209: #endif
                    210:                case 0x0080:
                    211:                    return SO_LINGER;
                    212:                case  0x0100:
                    213:                    return SO_OOBINLINE;
                    214: #ifdef SO_REUSEPORT
                    215:                case 0x0200:
                    216:                    return SO_REUSEPORT;
                    217: #endif
                    218:                case 0x1001:
                    219:                    return SO_SNDBUF;
                    220:                case 0x1002:
                    221:                    return SO_RCVBUF;
                    222:                case 0x1003:
                    223:                    return SO_SNDLOWAT;
                    224:                case 0x1004:
                    225:                    return SO_RCVLOWAT;
                    226:                case 0x1005:
                    227:                    return SO_SNDTIMEO;
                    228:                case 0x1006:
                    229:                    return SO_RCVTIMEO;
                    230:                case 0x1007:
                    231:                    return SO_ERROR;
                    232:                case 0x1008:
                    233:                    return SO_TYPE;
                    234: 
                    235:                default:
                    236:                    DEBUG_LOG ("Invalid setsockopt option %x for level %d\n",
                    237:                               optname, level);
                    238:                    return -1;
                    239:            }
                    240:            break;
                    241: 
                    242:        case IPPROTO_IP:
                    243:            switch (optname) {
                    244:                case 1:
                    245:                    return IP_OPTIONS;
                    246:                case 2:
                    247:                    return IP_HDRINCL;
                    248:                case 3:
                    249:                    return IP_TOS;
                    250:                case 4:
                    251:                    return IP_TTL;
                    252:                case 5:
                    253:                    return IP_RECVOPTS;
                    254:                case 6:
                    255:                    return IP_RECVRETOPTS;
                    256:                case 8:
                    257:                    return IP_RETOPTS;
                    258:                case 9:
                    259:                    return IP_MULTICAST_IF;
                    260:                case 10:
                    261:                    return IP_MULTICAST_TTL;
                    262:                case 11:
                    263:                    return IP_MULTICAST_LOOP;
                    264:                case 12:
                    265:                    return IP_ADD_MEMBERSHIP;
                    266: 
                    267:                default:
                    268:                    DEBUG_LOG ("Invalid setsockopt option %x for level %d\n",
                    269:                               optname, level);
                    270:                    return -1;
                    271:            }
                    272:            break;
                    273: 
                    274:        case IPPROTO_TCP:
                    275:            switch (optname) {
                    276:                case 1:
                    277:                    return TCP_NODELAY;
                    278:                case 2:
                    279:                    return TCP_MAXSEG;
                    280: 
                    281:                default:
                    282:                    DEBUG_LOG ("Invalid setsockopt option %x for level %d\n",
                    283:                               optname, level);
                    284:                    return -1;
                    285:            }
                    286:            break;
                    287: 
                    288:        default:
                    289:            DEBUG_LOG ("Unknown level %d\n", level);
                    290:            return -1;
                    291:     }
                    292: }
                    293: 
                    294: 
                    295: /*
                    296:  * Map amiga (s|g)etsockopt return value into the correct form
                    297:  */
                    298: static void mapsockoptreturn(int level, int optname, uae_u32 optval, void *buf)
                    299: {
                    300:     switch (level) {
                    301: 
                    302:        case SOL_SOCKET:
                    303:            switch (optname) {
                    304:                case SO_DEBUG:
                    305:                case SO_ACCEPTCONN:
                    306:                case SO_REUSEADDR:
                    307:                case SO_KEEPALIVE:
                    308:                case SO_DONTROUTE:
                    309:                case SO_BROADCAST:
                    310: #ifdef SO_USELOOPBACK
                    311:                case SO_USELOOPBACK:
                    312: #endif
                    313:                case SO_LINGER:
                    314:                case SO_OOBINLINE:
                    315: #ifdef SO_REUSEPORT
                    316:                case SO_REUSEPORT:
                    317: #endif
                    318:                case SO_SNDBUF:
                    319:                case SO_RCVBUF:
                    320:                case SO_SNDLOWAT:
                    321:                case SO_RCVLOWAT:
                    322:                case SO_SNDTIMEO:
                    323:                case SO_RCVTIMEO:
                    324:                case SO_TYPE:
                    325:                    put_long (optval, *(int *)buf);
                    326:                    break;
                    327: 
                    328:                case SO_ERROR:
                    329:                    DEBUG_LOG("New errno is %d\n", mapErrno(*(int *)buf));
                    330:                    put_long (optval, mapErrno(*(int *)buf));
                    331:                    break;
                    332:                default:
                    333:                    break;
                    334:            }
                    335:            break;
                    336: 
                    337:        case IPPROTO_IP:
                    338:            switch (optname) {
                    339:                case IP_OPTIONS:
                    340:                case IP_HDRINCL:
                    341:                case IP_TOS:
                    342:                case IP_TTL:
                    343:                case IP_RECVOPTS:
                    344:                //case IP_RECVRETOPTS:
                    345:                //case IP_RETOPTS:
                    346:                case IP_MULTICAST_IF:
                    347:                case IP_MULTICAST_TTL:
                    348:                case IP_MULTICAST_LOOP:
                    349:                case IP_ADD_MEMBERSHIP:
                    350:                    put_long (optval, *(int *)buf);
                    351:                    break;
                    352: 
                    353:                default:
                    354:                    break;
                    355:            }
                    356:            break;
                    357: 
                    358:        case IPPROTO_TCP:
                    359:            switch (optname) {
                    360:                case TCP_NODELAY:
                    361:                case TCP_MAXSEG:
                    362:                    put_long (optval,*(int *)buf);
                    363:                    break;
                    364: 
                    365:                default:
                    366:                    break;
                    367:            }
                    368:            break;
                    369: 
                    370:        default:
                    371:            break;
                    372:     }
                    373: }
                    374: 
                    375: /*
                    376:  * Map amiga (s|g)etsockopt value from amiga to the appropriate value
                    377:  */
                    378: static void mapsockoptvalue(int level, int optname, uae_u32 optval, void *buf)
                    379: {
                    380:     switch (level) {
                    381: 
                    382:        case SOL_SOCKET:
                    383:            switch (optname) {
                    384:                case SO_DEBUG:
                    385:                case SO_ACCEPTCONN:
                    386:                case SO_REUSEADDR:
                    387:                case SO_KEEPALIVE:
                    388:                case SO_DONTROUTE:
                    389:                case SO_BROADCAST:
                    390: #ifdef SO_USELOOPBACK
                    391:                case SO_USELOOPBACK:
                    392: #endif
                    393:                case SO_LINGER:
                    394:                case SO_OOBINLINE:
                    395: #ifdef SO_REUSEPORT
                    396:                case SO_REUSEPORT:
                    397: #endif
                    398:                case SO_SNDBUF:
                    399:                case SO_RCVBUF:
                    400:                case SO_SNDLOWAT:
                    401:                case SO_RCVLOWAT:
                    402:                case SO_SNDTIMEO:
                    403:                case SO_RCVTIMEO:
                    404:                case SO_TYPE:
                    405:                case SO_ERROR:
                    406:                    *((int *)buf) = get_long (optval);
                    407:                    break;
                    408:                default:
                    409:                    break;
                    410:            }
                    411:            break;
                    412: 
                    413:        case IPPROTO_IP:
                    414:            switch (optname) {
                    415:                case IP_OPTIONS:
                    416:                case IP_HDRINCL:
                    417:                case IP_TOS:
                    418:                case IP_TTL:
                    419:                case IP_RECVOPTS:
                    420:                //case IP_RECVRETOPTS:
                    421:                //case IP_RETOPTS:
                    422:                case IP_MULTICAST_IF:
                    423:                case IP_MULTICAST_TTL:
                    424:                case IP_MULTICAST_LOOP:
                    425:                case IP_ADD_MEMBERSHIP:
                    426:                    *((int *)buf) = get_long (optval);
                    427:                    break;
                    428: 
                    429:                default:
                    430:                    break;
                    431:            }
                    432:            break;
                    433: 
                    434:        case IPPROTO_TCP:
                    435:            switch (optname) {
                    436:                case TCP_NODELAY:
                    437:                case TCP_MAXSEG:
                    438:                    *((int *)buf) = get_long (optval);
                    439:                    break;
                    440: 
                    441:                default:
                    442:                    break;
                    443:            }
                    444:            break;
                    445: 
                    446:        default:
                    447:            break;
                    448:     }
                    449: }
                    450: 
                    451: 
                    452: STATIC_INLINE void fd_zero (uae_u32 fdset, uae_u32 nfds)
                    453: {
                    454:     unsigned int i;
                    455: 
                    456:     for (i = 0; i < nfds; i += 32, fdset += 4)
                    457:        put_long (fdset, 0);
                    458: }
                    459: 
                    460: STATIC_INLINE int bsd_amigaside_FD_ISSET (int n, uae_u32 set)
                    461: {
                    462:     uae_u32 foo = get_long (set + (n / 32));
                    463:     if (foo & (1 << (n % 32)))
                    464:        return 1;
                    465:     return 0;
                    466: }
                    467: 
                    468: STATIC_INLINE void bsd_amigaside_FD_ZERO (uae_u32 set)
                    469: {
                    470:     put_long (set, 0);
                    471:     put_long (set + 4, 0);
                    472: }
                    473: 
                    474: STATIC_INLINE void bsd_amigaside_FD_SET (int n, uae_u32 set)
                    475: {
                    476:     set = set + (n / 32);
                    477:     put_long (set, get_long (set) | (1 << (n % 32)));
                    478: }
                    479: 
                    480: #ifdef DEBUG_BSDSOCKET
                    481: static void printSockAddr (struct sockaddr_in *in)
                    482: {
                    483:     DEBUG_LOG ("Family %d, ", in->sin_family);
                    484:     DEBUG_LOG ("Port %d,",    ntohs (in->sin_port));
                    485:     DEBUG_LOG ("Address %s,", inet_ntoa (in->sin_addr));
                    486: }
                    487: #else
                    488: #define printSockAddr(sockAddr)
                    489: #endif
                    490: 
                    491: /*
                    492:  * Copy a sockaddr object from amiga space to native space
                    493:  */
                    494: static int copysockaddr_a2n (struct sockaddr_in *addr, uae_u32 a_addr, unsigned int len)
                    495: {
                    496:     if ((len > sizeof (struct sockaddr_in)) || (len < 8))
                    497:        return 1;
                    498: 
                    499:     if (a_addr == 0)
                    500:        return 0;
                    501: 
                    502:     addr->sin_family      = get_byte (a_addr + 1);
                    503:     addr->sin_port        = htons (get_word (a_addr + 2));
                    504:     addr->sin_addr.s_addr = htonl (get_long (a_addr + 4));
                    505: 
                    506:     if (len > 8)
                    507:        memcpy (&addr->sin_zero, get_real_address (a_addr + 8), len - 8);   /* Pointless? */
                    508: 
                    509:     return 0;
                    510: }
                    511: 
                    512: /*
                    513:  * Copy a sockaddr object from native space to amiga space
                    514:  */
                    515: static int copysockaddr_n2a (uae_u32 a_addr, const struct sockaddr_in *addr, unsigned int len)
                    516: {
                    517:     if (len < 8)
                    518:        return 1;
                    519: 
                    520:     if (a_addr == 0)
                    521:        return 0;
                    522: 
                    523:     put_byte (a_addr, 0);                       /* Anyone use this field? */
                    524:     put_byte (a_addr + 1, addr->sin_family);
                    525:     put_word (a_addr + 2, ntohs (addr->sin_port));
                    526:     put_long (a_addr + 4, ntohl (addr->sin_addr.s_addr));
                    527: 
                    528:     if (len > 8)
                    529:        memset (get_real_address (a_addr + 8), 0, len - 8);
                    530: 
                    531:     return 0;
                    532: }
                    533: 
                    534: /*
                    535:  * Copy a hostent object from native space to amiga space
                    536:  */
                    537: static void copyHostent (const struct hostent *hostent, SB)
                    538: {
                    539:     int size = 28;
                    540:     int i;
                    541:     int numaddr = 0;
                    542:     int numaliases = 0;
                    543:     uae_u32 aptr;
                    544: 
                    545:     if (hostent->h_name != NULL)
                    546:        size += strlen(hostent->h_name)+1;
                    547: 
                    548:     if (hostent->h_aliases != NULL)
                    549:        while (hostent->h_aliases[numaliases])
                    550:            size += strlen(hostent->h_aliases[numaliases++]) + 5;
                    551: 
                    552:     if (hostent->h_addr_list != NULL) {
                    553:        while (hostent->h_addr_list[numaddr])
                    554:            numaddr++;
                    555:        size += numaddr*(hostent->h_length+4);
                    556:     }
                    557: 
                    558:     aptr = sb->hostent + 28 + numaliases * 4 + numaddr * 4;
                    559: 
                    560:     // transfer hostent to Amiga memory
                    561:     put_long (sb->hostent + 4, sb->hostent + 20);
                    562:     put_long (sb->hostent + 8, hostent->h_addrtype);
                    563:     put_long (sb->hostent + 12, hostent->h_length);
                    564:     put_long (sb->hostent + 16, sb->hostent + 24 + numaliases*4);
                    565: 
                    566:     for (i = 0; i < numaliases; i++)
                    567:        put_long (sb->hostent + 20 + i * 4, addstr (&aptr, hostent->h_aliases[i]));
                    568:     put_long (sb->hostent + 20 + numaliases * 4, 0);
                    569: 
                    570:     for (i = 0; i < numaddr; i++) {
                    571:        put_long (sb->hostent + 24 + (numaliases + i) * 4,
                    572:            addmem (&aptr, hostent->h_addr_list[i], hostent->h_length));
                    573:     }
                    574:     put_long (sb->hostent + 24 + numaliases * 4 + numaddr * 4, 0);
                    575:     put_long (sb->hostent, aptr);
                    576:     addstr (&aptr, hostent->h_name);
                    577: 
                    578:     TRACE (("OK (%s)\n",hostent->h_name));
                    579:     bsdsocklib_seterrno (sb,0);
                    580: }
                    581: 
                    582: /*
                    583:  * Copy a protoent object from native space to Amiga space
                    584:  */
                    585: static void copyProtoent (TrapContext *context, SB, const struct protoent *p)
                    586: {
                    587:     size_t size = 16;
                    588:     int numaliases = 0;
                    589:     int i;
                    590:     uae_u32 aptr;
                    591: 
                    592:     // compute total size of protoent
                    593:     if (p->p_name != NULL)
                    594:        size += strlen (p->p_name) + 1;
                    595: 
                    596:     if (p->p_aliases != NULL)
                    597:        while (p->p_aliases[numaliases])
                    598:            size += strlen (p->p_aliases[numaliases++]) + 5;
                    599: 
                    600:     if (sb->protoent) {
                    601:        uae_FreeMem (context, sb->protoent, sb->protoentsize);
                    602:     }
                    603: 
                    604:     sb->protoent = uae_AllocMem (context, size, 0);
                    605: 
                    606:     if (!sb->protoent) {
                    607:        write_log ("BSDSOCK: WARNING - copyProtoent() ran out of Amiga memory (couldn't allocate %d bytes)\n", size);
                    608:        bsdsocklib_seterrno (sb, 12); // ENOMEM
                    609:        return;
                    610:     }
                    611: 
                    612:     sb->protoentsize = size;
                    613: 
                    614:     aptr = sb->protoent + 16 + numaliases * 4;
                    615: 
                    616:     // transfer protoent to Amiga memory
                    617:     put_long (sb->protoent + 4, sb->protoent + 12);
                    618:     put_long (sb->protoent + 8, p->p_proto);
                    619: 
                    620:     for (i = 0; i < numaliases; i++)
                    621:        put_long (sb->protoent + 12 + i * 4, addstr (&aptr, p->p_aliases[i]));
                    622:     put_long (sb->protoent + 12 + numaliases * 4, 0);
                    623:     put_long (sb->protoent, aptr);
                    624:     addstr (&aptr, p->p_name);
                    625:     bsdsocklib_seterrno(sb, 0);
                    626: }
                    627: 
                    628: 
                    629: 
                    630: uae_u32 bsdthr_WaitSelect (SB)
                    631: {
                    632:     fd_set sets [3];
                    633:     int i, s, set, a_s, max;
                    634:     uae_u32 a_set;
                    635:     struct timeval tv;
                    636:     int r;
                    637: 
                    638:     DEBUG_LOG ("WaitSelect: %d 0x%x 0x%x 0x%x 0x%x 0x%x\n",
                    639:               sb->nfds, sb->sets [0], sb->sets [1], sb->sets [2], sb->timeout, sb->sigmp);
                    640: 
                    641:     if (sb->timeout)
                    642:        DEBUG_LOG ("WaitSelect: timeout %d %d\n", get_long (sb->timeout),
                    643:                   get_long (sb->timeout + 4));
                    644: 
                    645:     FD_ZERO (&sets [0]);
                    646:     FD_ZERO (&sets [1]);
                    647:     FD_ZERO (&sets [2]);
                    648: 
                    649:     /* Set up the abort socket */
                    650:     FD_SET (sb->sockabort[0], &sets[0]);
                    651:     FD_SET (sb->sockabort[0], &sets[2]);
                    652:     max = sb->sockabort[0];
                    653: 
                    654:     for (set = 0; set < 3; set++) {
                    655:        if (sb->sets [set] != 0) {
                    656:            a_set = sb->sets [set];
                    657:            for (i = 0; i < sb->nfds; i++) {
                    658:                if (bsd_amigaside_FD_ISSET (i, a_set)) {
                    659:                    s = getsock (sb, i + 1);
                    660:                    DEBUG_LOG ("WaitSelect: AmigaSide %d set. NativeSide %d.\n", i, s);
                    661:                    if (s == -1) {
                    662:                        write_log ("BSDSOCK: WaitSelect() called with invalid descriptor %d in set %d.\n", i, set);
                    663:                    } else {
                    664:                        FD_SET (s, &sets [set]);
                    665:                        if (max < s) max = s;
                    666:                    }
                    667:                }
                    668:            }
                    669:        }
                    670:     }
                    671: 
                    672:     max++;
                    673: 
                    674:     if (sb->timeout) {
                    675:        tv.tv_sec  = get_long (sb->timeout);
                    676:        tv.tv_usec = get_long (sb->timeout + 4);
                    677:     }
                    678: 
                    679:     DEBUG_LOG("Select going to select\n");
                    680:     r = select (max, &sets [0], &sets [1], &sets [2], (sb->timeout == 0) ? NULL : &tv);
                    681:     DEBUG_LOG("Select returns %d, errno is %d\n", r, errno);
                    682:     if( r > 0 ) {
                    683:        /* Socket told us to abort */
                    684:        if (FD_ISSET (sb->sockabort[0], &sets[0])) {
                    685:            /* read from the pipe to reset it */
                    686:            DEBUG_LOG ("WaitSelect aborted from signal\n");
                    687:            r = 0;
                    688:            for (set = 0; set < 3; set++)
                    689:            if (sb->sets [set] != 0)
                    690:                bsd_amigaside_FD_ZERO (sb->sets [set]);
                    691:            clearsockabort (sb);
                    692:        }
                    693:        else
                    694:        /* This is perhaps slightly inefficient, but I don't care.. */
                    695:        for (set = 0; set < 3; set++) {
                    696:            a_set = sb->sets [set];
                    697:            if (a_set != 0) {
                    698:                bsd_amigaside_FD_ZERO (a_set);
                    699:                for (i = 0; i < sb->nfds; i++) {
                    700:                    a_s = getsock (sb, i + 1);
                    701:                    if (a_s != -1) {
                    702:                        if (FD_ISSET (a_s, &sets [set])) {
                    703:                            DEBUG_LOG ("WaitSelect: NativeSide %d set. AmigaSide %d.\n", a_s, i);
                    704: 
                    705:                            bsd_amigaside_FD_SET (i, a_set);
                    706:                    }
                    707:                }
                    708:            }
                    709:        }
                    710:        }
                    711:     } else if (r == 0) {         /* Timeout. I think we're supposed to clear the sets.. */
                    712:        for (set = 0; set < 3; set++)
                    713:            if (sb->sets [set] != 0)
                    714:                bsd_amigaside_FD_ZERO (sb->sets [set]);
                    715:     }
                    716:     DEBUG_LOG ("WaitSelect: %d(%d)\n", r, errno);
                    717:     return r;
                    718: }
                    719: 
                    720: uae_u32 bsdthr_Accept_2 (SB)
                    721: {
                    722:     int foo, s, s2;
                    723:     long flags;
                    724:     struct sockaddr_in addr;
                    725:     socklen_t hlen = sizeof (struct sockaddr_in);
                    726: 
                    727:     if ((s = accept (sb->s, (struct sockaddr *)&addr, &hlen)) >= 0) {
                    728:        if ((flags = fcntl (s, F_GETFL)) == -1)
                    729:            flags = 0;
                    730:        fcntl (s, F_SETFL, flags & ~O_NONBLOCK); /* @@@ Don't do this if it's supposed to stay nonblocking... */
                    731:        s2 = getsd (sb, s);
                    732:        sb->ftable[s2-1] = sb->ftable[sb->len]; /* new socket inherits the old socket's properties */
                    733:        DEBUG_LOG ("Accept: AmigaSide %d, NativeSide %d, len %d(%d)",
                    734:                   sb->resultval, s, &hlen, get_long (sb->a_addrlen));
                    735:        printSockAddr (&addr);
                    736:        foo = get_long (sb->a_addrlen);
                    737:        if (foo > 16)
                    738:            put_long (sb->a_addrlen, 16);
                    739:        copysockaddr_n2a (sb->a_addr, &addr, foo);
                    740:        return s2 - 1;
                    741:     } else {
                    742:        return -1;
                    743:     }
                    744: }
                    745: 
                    746: uae_u32 bsdthr_Recv_2 (SB)
                    747: {
                    748:     int foo;
                    749:     int l, i;
                    750:     if (sb->from == 0) {
                    751:        foo = recv (sb->s, sb->buf, sb->len, sb->flags /*| MSG_NOSIGNAL*/);
                    752:        DEBUG_LOG ("recv2, recv returns %d, errno is %d\n", foo, errno);
                    753:     } else {
                    754:        struct sockaddr_in addr;
                    755:        socklen_t l = sizeof (struct sockaddr_in);
                    756:        i = get_long (sb->fromlen);
                    757:        copysockaddr_a2n (&addr, sb->from, i);
                    758:        foo = recvfrom (sb->s, sb->buf, sb->len, sb->flags | MSG_NOSIGNAL, (struct sockaddr *)&addr, &l);
                    759:        DEBUG_LOG ("recv2, recvfrom returns %d, errno is %d\n", foo, errno);
                    760:        if (foo >= 0) {
                    761:            copysockaddr_n2a (sb->from, &addr, l);
                    762:            put_long (sb->fromlen, l);
                    763:        }
                    764:     }
                    765:     return foo;
                    766: }
                    767: 
                    768: uae_u32 bsdthr_Send_2 (SB)
                    769: {
                    770:     if (sb->to == 0) {
                    771:        return send (sb->s, sb->buf, sb->len, sb->flags | MSG_NOSIGNAL);
                    772:     } else {
                    773:        struct sockaddr_in addr;
                    774:        int l = sizeof (struct sockaddr_in);
                    775:        copysockaddr_a2n (&addr, sb->to, sb->tolen);
                    776:        return sendto (sb->s, sb->buf, sb->len, sb->flags | MSG_NOSIGNAL,
                    777:                       (struct sockaddr *)&addr, l);
                    778:     }
                    779: }
                    780: 
                    781: uae_u32 bsdthr_Connect_2 (SB)
                    782: {
                    783:     if (sb->action == 1) {
                    784:        struct sockaddr_in addr;
                    785:        int len = sizeof (struct sockaddr_in);
                    786:        int retval;
                    787:        copysockaddr_a2n (&addr, sb->a_addr, sb->a_addrlen);
                    788:        retval = connect (sb->s, (struct sockaddr *)&addr, len);
                    789:        DEBUG_LOG ("Connect returns %d, errno is %d\n", retval, errno);
                    790:        /* Hack: I need to set the action to something other than
                    791:         * 1 but I know action == 2 does the correct thing
                    792:         */
                    793:        sb->action = 2;
                    794:        if (retval == 0) {
                    795:             errno = 0;
                    796:        }
                    797:        return retval;
                    798:     } else {
                    799:        int foo;
                    800:        socklen_t bar;
                    801:        bar = sizeof (foo);
                    802:        if (getsockopt (sb->s, SOL_SOCKET, SO_ERROR, &foo, &bar) == 0) {
                    803:            errno = foo;
                    804:            DEBUG_LOG("Connect status is %d\n", foo);
                    805:            return (foo == 0) ? 0 : -1;
                    806:        }
                    807:        return -1;
                    808:     }
                    809: }
                    810: 
                    811: uae_u32 bsdthr_SendRecvAcceptConnect (uae_u32 (*tryfunc)(SB), SB)
                    812: {
                    813:     return bsdthr_blockingstuff (tryfunc, sb);
                    814: }
                    815: 
                    816: uae_u32 bsdthr_blockingstuff (uae_u32 (*tryfunc)(SB), SB)
                    817: {
                    818:     int done = 0, foo;
                    819:     long flags;
                    820:     int nonblock;
                    821:     if ((flags = fcntl (sb->s, F_GETFL)) == -1)
                    822:        flags = 0;
                    823:     nonblock = (flags & O_NONBLOCK);
                    824:     fcntl (sb->s, F_SETFL, flags | O_NONBLOCK);
                    825:     while (!done) {
                    826:        done = 1;
                    827:        foo = tryfunc (sb);
                    828:        if (foo < 0 && !nonblock) {
                    829:            if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS)) {
                    830:                fd_set readset, writeset, exceptset;
                    831:                int maxfd = (sb->s > sb->sockabort[0]) ? sb->s : sb->sockabort[0];
                    832:                int num;
                    833: 
                    834:                FD_ZERO (&readset);
                    835:                FD_ZERO (&writeset);
                    836:                FD_ZERO (&exceptset);
                    837: 
                    838:                if (sb->action == 3 || sb->action == 6)
                    839:                    FD_SET (sb->s, &readset);
                    840:                if (sb->action == 2 || sb->action == 1 || sb->action == 4)
                    841:                    FD_SET (sb->s, &writeset);
                    842:                FD_SET (sb->sockabort[0], &readset);
                    843: 
                    844:                num = select (maxfd + 1, &readset, &writeset, &exceptset, NULL);
                    845:                if (num == -1) {
                    846:                    DEBUG_LOG ("Blocking select(%d) returns -1,errno is %d\n", sb->sockabort[0],errno);
                    847:                    fcntl (sb->s, F_SETFL, flags);
                    848:                   return -1;
                    849:                }
                    850: 
                    851:                if (FD_ISSET (sb->sockabort[0], &readset) || FD_ISSET (sb->sockabort[0], &writeset)) {
                    852:                    /* reset sock abort pipe */
                    853:                    /* read from the pipe to reset it */
                    854:                    DEBUG_LOG ("select aborted from signal\n");
                    855: 
                    856:                    clearsockabort (sb);
                    857:                    DEBUG_LOG ("Done read\n");
                    858:                    errno = EINTR;
                    859:                    done = 1;
                    860:                } else {
                    861:                    done = 0;
                    862:                }
                    863:            } else if (errno == EINTR)
                    864:                done = 1;
                    865:        }
                    866:     }
                    867:     fcntl (sb->s, F_SETFL, flags);
                    868:     return foo;
                    869: }
                    870: 
                    871: 
                    872: static void *bsdlib_threadfunc (void *arg)
                    873: {
                    874:     struct socketbase *sb = (struct socketbase *) arg;
                    875: 
                    876:     DEBUG_LOG ("THREAD_START\n");
                    877: 
                    878:     while (1) {
                    879:        uae_sem_wait (&sb->sem);
                    880: 
                    881:        DEBUG_LOG ("Socket thread got action %d\n", sb->action);
                    882: 
                    883:        switch (sb->action) {
                    884:            case 0:       /* kill thread (CloseLibrary) */
                    885: 
                    886:                DEBUG_LOG ("THREAD_END\n");
                    887: 
                    888:                uae_sem_destroy (&sb->sem);
                    889:                return NULL;
                    890: 
                    891:            case 1:       /* Connect */
                    892:                sb->resultval = bsdthr_SendRecvAcceptConnect (bsdthr_Connect_2, sb);
                    893:                break;
                    894: 
                    895:            /* @@@ Should check (from|to)len so it's 16.. */
                    896:            case 2:       /* Send[to] */
                    897:                sb->resultval = bsdthr_SendRecvAcceptConnect (bsdthr_Send_2, sb);
                    898:                break;
                    899: 
                    900:            case 3:       /* Recv[from] */
                    901:                sb->resultval = bsdthr_SendRecvAcceptConnect (bsdthr_Recv_2, sb);
                    902:                break;
                    903: 
                    904:            case 4: {     /* Gethostbyname */
                    905:                struct hostent *tmphostent = gethostbyname ((char *)get_real_address (sb->name));
                    906: 
                    907:                if (tmphostent) {
                    908:                    copyHostent (tmphostent, sb);
                    909:                    bsdsocklib_setherrno (sb, 0);
                    910:                } else
                    911:                    SETHERRNO;
                    912: 
                    913:                break;
                    914:            }
                    915: 
                    916:            case 5:       /* WaitSelect */
                    917:                sb->resultval = bsdthr_WaitSelect (sb);
                    918:                break;
                    919: 
                    920:            case 6:       /* Accept */
                    921:                sb->resultval = bsdthr_SendRecvAcceptConnect (bsdthr_Accept_2, sb);
                    922:                break;
                    923: 
                    924:            case 7: {
                    925:                struct hostent *tmphostent = gethostbyaddr (get_real_address (sb->name), sb->a_addrlen, sb->flags);
                    926: 
                    927:                if (tmphostent) {
                    928:                    copyHostent (tmphostent, sb);
                    929:                    bsdsocklib_setherrno (sb, 0);
                    930:                } else
                    931:                    SETHERRNO;
                    932: 
                    933:                break;
                    934:            }
                    935:        }
                    936:        SETERRNO;
                    937:        SETSIGNAL;
                    938:     }
                    939:     return NULL;        /* Just to keep GCC happy.. */
                    940: }
                    941: 
                    942: 
                    943: 
                    944: 
                    945: void host_connect (TrapContext *context, SB, uae_u32 sd, uae_u32 name, uae_u32 namelen)
                    946: {
                    947:     sb->s = getsock (sb, sd + 1);
                    948:     if (sb->s == -1) {
                    949:        sb->resultval = -1;
                    950:        bsdsocklib_seterrno (sb, 9); /* EBADF */
                    951:        return;
                    952:     }
                    953:     sb->a_addr    = name;
                    954:     sb->a_addrlen = namelen;
                    955:     sb->action    = 1;
                    956: 
                    957:     uae_sem_post (&sb->sem);
                    958: 
                    959:     WAITSIGNAL;
                    960: }
                    961: 
                    962: void host_sendto (TrapContext *context, SB, uae_u32 sd, uae_u32 msg, uae_u32 len, uae_u32 flags, uae_u32 to, uae_u32 tolen)
                    963: {
                    964:     sb->s = getsock (sb, sd + 1);
                    965:     if (sb->s == -1) {
                    966:        sb->resultval = -1;
                    967:        bsdsocklib_seterrno (sb, 9); /* EBADF */
                    968:        return;
                    969:     }
                    970:     sb->buf    = get_real_address (msg);
                    971:     sb->len    = len;
                    972:     sb->flags  = flags;
                    973:     sb->to     = to;
                    974:     sb->tolen  = tolen;
                    975:     sb->action = 2;
                    976: 
                    977:     uae_sem_post (&sb->sem);
                    978: 
                    979:     WAITSIGNAL;
                    980: }
                    981: 
                    982: void host_recvfrom (TrapContext *context, SB, uae_u32 sd, uae_u32 msg, uae_u32 len, uae_u32 flags, uae_u32 addr, uae_u32 addrlen)
                    983: {
                    984:     int s = getsock (sb, sd + 1);
                    985: 
                    986:     DEBUG_LOG ("Recv[from](%lx, %d, %lx, %ld, %lx, %lx, %d)\n",
                    987:               sb, sd, msg, len, flags, addr, addrlen);
                    988: 
                    989:     if (s == -1) {
                    990:        sb->resultval = -1;
                    991:        bsdsocklib_seterrno (sb, 9); /* EBADF */;
                    992:        return;
                    993:     }
                    994: 
                    995:     sb->s      = s;
                    996:     sb->buf    = get_real_address (msg);
                    997:     sb->len    = len;
                    998:     sb->flags  = flags;
                    999:     sb->from   = addr;
                   1000:     sb->fromlen= addrlen;
                   1001:     sb->action = 3;
                   1002: 
                   1003:     uae_sem_post (&sb->sem);
                   1004: 
                   1005:     WAITSIGNAL;
                   1006: }
                   1007: 
                   1008: void host_setsockopt (SB, uae_u32 sd, uae_u32 level, uae_u32 optname, uae_u32 optval, uae_u32 optlen)
                   1009: {
                   1010:     int s = getsock (sb, sd + 1);
                   1011:     int nativelevel = mapsockoptlevel (level);
                   1012:     int nativeoptname = mapsockoptname(nativelevel, optname);
                   1013:     void *buf;
                   1014:     if (s == -1) {
                   1015:        sb->resultval = -1;
                   1016:        bsdsocklib_seterrno (sb, 9); /* EBADF */;
                   1017:        return;
                   1018:     }
                   1019: 
                   1020:     if (optval) {
                   1021:        buf = malloc(optlen);
                   1022:        mapsockoptvalue(nativelevel, nativeoptname, optval, buf);
                   1023:     } else {
                   1024:        buf = NULL;
                   1025:     }
                   1026:     sb->resultval  = setsockopt (s, nativelevel, nativeoptname, buf, optlen);
                   1027:     if (buf)
                   1028:            free(buf);
                   1029:     SETERRNO;
                   1030: 
                   1031:     DEBUG_LOG ("setsockopt: sock %d, level %d, 'name' %d(%d), len %d -> %d, %d\n",
                   1032:               s, level, optname, nativeoptname, optlen,
                   1033:               sb->resultval, errno);
                   1034: }
                   1035: 
                   1036: uae_u32 host_getsockname (SB, uae_u32 sd, uae_u32 name, uae_u32 namelen)
                   1037: {
                   1038:     int s;
                   1039:     socklen_t len = sizeof (struct sockaddr_in);
                   1040:     struct sockaddr_in addr;
                   1041: 
                   1042:     DEBUG_LOG ("getsockname(%d,0x%lx,%d) -> ", sd, name, len);
                   1043: 
                   1044:     s = getsock (sb, sd + 1);
                   1045: 
                   1046:     if (s != -1) {
                   1047:        if (getsockname (s, (struct sockaddr *)&addr, &len)) {
                   1048:                SETERRNO;
                   1049:                DEBUG_LOG ("failed (%d)\n", sb->sb_errno);
                   1050:            } else {
                   1051:                int a_nl;
                   1052:                DEBUG_LOG ("okay\n");
                   1053:                a_nl = get_long (namelen);
                   1054:                copysockaddr_n2a (name, &addr, a_nl);
                   1055:                if (a_nl > 16)
                   1056:                    put_long (namelen, 16);
                   1057:                return 0;
                   1058:            }
                   1059:        }
                   1060: 
                   1061:        return -1;
                   1062: }
                   1063: 
                   1064: uae_u32 host_getpeername (SB, uae_u32 sd, uae_u32 name, uae_u32 namelen)
                   1065: {
                   1066:     int s;
                   1067:     socklen_t len = sizeof (struct sockaddr_in);
                   1068:     struct sockaddr_in addr;
                   1069: 
                   1070:     DEBUG_LOG ("getpeername(%d,0x%lx,%d) -> ", sd, name, len);
                   1071: 
                   1072:     s = getsock (sb, sd + 1);
                   1073: 
                   1074:     if (s != -1) {
                   1075:        if (getpeername (s, (struct sockaddr *)&addr, &len)) {
                   1076:                SETERRNO;
                   1077:                DEBUG_LOG ("failed (%d)\n", sb->sb_errno);
                   1078:        } else {
                   1079:            int a_nl;
                   1080:            DEBUG_LOG ("okay\n");
                   1081:            a_nl = get_long (namelen);
                   1082:            copysockaddr_n2a (name, &addr, a_nl);
                   1083:            if (a_nl > 16)
                   1084:                put_long (namelen, 16);
                   1085:            return 0;
                   1086:        }
                   1087:     }
                   1088: 
                   1089:     return -1;
                   1090: }
                   1091: 
                   1092: void host_gethostbynameaddr (TrapContext *context, SB, uae_u32 name, uae_u32 namelen, long addrtype)
                   1093: {
                   1094:     sb->name      = name;
                   1095:     sb->a_addrlen = namelen;
                   1096:     sb->flags     = addrtype;
                   1097:     if (addrtype == -1)
                   1098:        sb->action  = 4;
                   1099:     else
                   1100:        sb->action = 7;
                   1101: 
                   1102:     uae_sem_post (&sb->sem);
                   1103: 
                   1104:     WAITSIGNAL;
                   1105: }
                   1106: 
                   1107: void host_WaitSelect (TrapContext *context, SB, uae_u32 nfds, uae_u32 readfds, uae_u32 writefds, uae_u32 exceptfds,
                   1108:                      uae_u32 timeout, uae_u32 sigmp)
                   1109: {
                   1110:     uae_u32 wssigs = (sigmp) ? get_long (sigmp) : 0;
                   1111:     uae_u32 sigs;
                   1112: 
                   1113:     if (wssigs) {
                   1114:        m68k_dreg (regs, 0) = 0;
                   1115:        m68k_dreg (regs, 1) = wssigs;
                   1116:        sigs = CallLib (context, get_long (4), -0x132) & wssigs;        // SetSignal()
                   1117:        if (sigs) {
                   1118:            DEBUG_LOG ("WaitSelect preempted by signals 0x%08x\n", sigs & wssigs);
                   1119:            put_long (sigmp, sigs);
                   1120:            // Check for zero address -> otherwise WinUAE crashes
                   1121:            if (readfds)   fd_zero (readfds, nfds);
                   1122:            if (writefds)  fd_zero (writefds, nfds);
                   1123:            if (exceptfds) fd_zero (exceptfds, nfds);
                   1124:            sb->resultval = 0;
                   1125:            bsdsocklib_seterrno (sb, 0);
                   1126:            return;
                   1127:        }
                   1128:     }
                   1129: 
                   1130:     if (nfds == 0) {
                   1131:        /* No sockets - Just wait on signals */
                   1132:        m68k_dreg (regs, 0) = wssigs;
                   1133:        sigs = CallLib (context, get_long (4), -0x13e); // Wait()
                   1134: 
                   1135:        if (sigmp)
                   1136:        put_long (sigmp, sigs & wssigs);
                   1137: 
                   1138:        if (readfds)   fd_zero (readfds, nfds);
                   1139:        if (writefds)  fd_zero (writefds, nfds);
                   1140:        if (exceptfds) fd_zero (exceptfds, nfds);
                   1141:        sb->resultval = 0;
                   1142:        return;
                   1143:     }
                   1144: 
                   1145:     sb->nfds = nfds;
                   1146:     sb->sets [0] = readfds;
                   1147:     sb->sets [1] = writefds;
                   1148:     sb->sets [2] = exceptfds;
                   1149:     sb->timeout  = timeout;
                   1150:     sb->sigmp    = wssigs;
                   1151:     sb->action   = 5;
                   1152: 
                   1153:     uae_sem_post (&sb->sem);
                   1154: 
                   1155:     m68k_dreg (regs, 0) = (((uae_u32)1) << sb->signal) | sb->eintrsigs | wssigs;
                   1156:     sigs = CallLib (context, get_long (4), -0x13e); // Wait()
                   1157: 
                   1158:     if (sigmp)
                   1159:        put_long (sigmp, sigs & (sb->eintrsigs | wssigs));
                   1160: 
                   1161:     if (sigs & wssigs) {
                   1162:        /* Received the signals we were waiting on */
                   1163:        DEBUG_LOG ("WaitSelect: got signal(s) %lx\n", sigs);
                   1164: 
                   1165:        if (!(sigs & (((uae_u32)1) << sb->signal))) {
                   1166:            sockabort (sb);
                   1167:            WAITSIGNAL;
                   1168:        }
                   1169: 
                   1170:        sb->resultval = 0;
                   1171:        if (readfds)   fd_zero (readfds, nfds);
                   1172:        if (writefds)  fd_zero (writefds, nfds);
                   1173:        if (exceptfds) fd_zero (exceptfds, nfds);
                   1174: 
                   1175:        bsdsocklib_seterrno (sb, 0);
                   1176:     } else if (sigs & sb->eintrsigs) {
                   1177:        /* Wait select was interrupted */
                   1178:        DEBUG_LOG ("WaitSelect: interrupted\n");
                   1179: 
                   1180:        if (!(sigs & (((uae_u32)1) << sb->signal))) {
                   1181:            sockabort (sb);
                   1182:            WAITSIGNAL;
                   1183:        }
                   1184: 
                   1185:        sb->resultval = -1;
                   1186:        bsdsocklib_seterrno (sb, mapErrno (EINTR));
                   1187:     }
                   1188:     clearsockabort(sb);
                   1189: }
                   1190: 
                   1191: 
                   1192: 
                   1193: void host_accept (TrapContext *context, SB, uae_u32 sd, uae_u32 name, uae_u32 namelen)
                   1194: {
                   1195:     sb->s = getsock (sb, sd + 1);
                   1196:     if (sb->s == -1) {
                   1197:        sb->resultval = -1;
                   1198:        bsdsocklib_seterrno (sb, 9); /* EBADF */
                   1199:        return;
                   1200:     }
                   1201: 
                   1202:     DEBUG_LOG ("accept(%d, %lx, %lx)\n", sb->s, name, namelen);
                   1203:     sb->a_addr    = name;
                   1204:     sb->a_addrlen = namelen;
                   1205:     sb->action    = 6;
                   1206:     sb->len       = sd;
                   1207: 
                   1208:     uae_sem_post (&sb->sem);
                   1209: 
                   1210:     WAITSIGNAL;
                   1211:     DEBUG_LOG ("Accept returns %d\n", sb->resultval);
                   1212: }
                   1213: 
                   1214: int host_socket (SB, int af, int type, int protocol)
                   1215: {
                   1216:     int sd;
                   1217:     int s;
                   1218: 
                   1219:     DEBUG_LOG ("socket(%s,%s,%d) -> ",af == AF_INET ? "AF_INET" : "AF_other",
                   1220:               type == SOCK_STREAM ? "SOCK_STREAM" : type == SOCK_DGRAM ?
                   1221:               "SOCK_DGRAM " : "SOCK_RAW", protocol);
                   1222: 
                   1223:     if ((s = socket (af, type, protocol)) == -1)  {
                   1224:        SETERRNO;
                   1225:        DEBUG_LOG ("failed (%d)\n", sb->sb_errno);
                   1226:        return -1;
                   1227:     } else {
                   1228:        int arg = 1;
                   1229:        sd = getsd (sb, s);
                   1230:        setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg));
                   1231:     }
                   1232: 
                   1233:     sb->ftable[sd-1] = SF_BLOCKING;
                   1234:     DEBUG_LOG ("socket returns Amiga %d, NativeSide %d\n", sd - 1, s);
                   1235:     return sd - 1;
                   1236: }
                   1237: 
                   1238: uae_u32 host_bind (SB, uae_u32 sd, uae_u32 name, uae_u32 namelen)
                   1239: {
                   1240:     uae_u32 success = 0;
                   1241:     struct sockaddr_in addr;
                   1242:     int len = sizeof (struct sockaddr_in);
                   1243:     int s;
                   1244: 
                   1245:     s = getsock (sb, sd + 1);
                   1246:     if (s == -1) {
                   1247:        sb->resultval = -1;
                   1248:        bsdsocklib_seterrno (sb, 9); /* EBADF */
                   1249:        return -1;
                   1250:     }
                   1251: 
                   1252:     DEBUG_LOG ("bind(%d[%d],0x%lx,%d) -> ", sd, s, name, namelen);
                   1253:     copysockaddr_a2n (&addr, name, namelen);
                   1254:     printSockAddr (&addr);
                   1255:     if ((success = bind (s, (struct sockaddr *)&addr, len)) != 0) {
                   1256:        SETERRNO;
                   1257:        DEBUG_LOG ("failed (%d)\n",sb->sb_errno);
                   1258:     } else {
                   1259:        DEBUG_LOG ("OK\n");
                   1260:     }
                   1261:     return success;
                   1262: }
                   1263: 
                   1264: uae_u32 host_listen (SB, uae_u32 sd, uae_u32 backlog)
                   1265: {
                   1266:     int s;
                   1267:     uae_u32 success = -1;
                   1268: 
                   1269:     DEBUG_LOG ("listen(%d,%d) -> ", sd, backlog);
                   1270:     s = getsock (sb, sd + 1);
                   1271: 
                   1272:     if (s == -1) {
                   1273:        bsdsocklib_seterrno (sb, 9);
                   1274:        return -1;
                   1275:     }
                   1276: 
                   1277:     if ((success = listen (s, backlog)) != 0) {
                   1278:        SETERRNO;
                   1279:        DEBUG_LOG ("failed (%d)\n", sb->sb_errno);
                   1280:     } else {
                   1281:        DEBUG_LOG ("OK\n");
                   1282:     }
                   1283:     return success;
                   1284: }
                   1285: 
                   1286: void host_getprotobyname (TrapContext *context, SB, uae_u32 name)
                   1287: {
                   1288:     struct protoent *p = getprotobyname ((char *)get_real_address (name));
                   1289: 
                   1290:     DEBUG_LOG ("Getprotobyname(%s)=%lx\n", get_real_address (name), p);
                   1291: 
                   1292:     if (p == NULL) {
                   1293:        SETERRNO;
                   1294:        return;
                   1295:     }
                   1296: 
                   1297:     copyProtoent (context, sb, p);
                   1298:     TRACE (("OK (%s, %d)\n", p->p_name, p->p_proto));
                   1299: }
                   1300: 
                   1301: void host_getprotobynumber (TrapContext *context, SB, uae_u32 number)
                   1302: {
                   1303:     struct protoent *p = getprotobynumber(number);
                   1304:     DEBUG_LOG("getprotobynumber(%d)=%lx\n", number, p);
                   1305: 
                   1306:     if (p == NULL) {
                   1307:        SETERRNO;
                   1308:        return;
                   1309:     }
                   1310: 
                   1311:     copyProtoent (context, sb, p);
                   1312:     TRACE (("OK (%s, %d)\n", p->p_name, p->p_proto));
                   1313: }
                   1314: 
                   1315: void host_getservbynameport (TrapContext *context, SB, uae_u32 name, uae_u32 proto, uae_u32 type)
                   1316: {
                   1317:     struct servent *s = (type) ?
                   1318:        getservbyport (name, (char *)get_real_address (proto)) :
                   1319:        getservbyname ((char *)get_real_address (name), (char *)get_real_address (proto));
                   1320:     size_t size = 20;
                   1321:     int numaliases = 0;
                   1322:     uae_u32 aptr;
                   1323:     int i;
                   1324: 
                   1325:     if (type) {
                   1326:        DEBUG_LOG("Getservbyport(%d, %s) = %lx\n", name, get_real_address (proto), s);
                   1327:     } else {
                   1328:        DEBUG_LOG("Getservbyname(%s, %s) = %lx\n", get_real_address (name), get_real_address (proto), s);
                   1329:     }
                   1330: 
                   1331:     if (s == NULL) {
                   1332:        SETERRNO;
                   1333:        return;
                   1334:     }
                   1335: 
                   1336:     // compute total size of servent
                   1337:     if (s->s_name != NULL)
                   1338:        size += strlen (s->s_name) + 1;
                   1339: 
                   1340:     if (s->s_proto != NULL)
                   1341:        size += strlen (s->s_proto) + 1;
                   1342: 
                   1343:     if (s->s_aliases != NULL)
                   1344:        while (s->s_aliases[numaliases])
                   1345:            size += strlen (s->s_aliases[numaliases++]) + 5;
                   1346: 
                   1347:     if (sb->servent) {
                   1348:        uae_FreeMem (context, sb->servent, sb->serventsize);
                   1349:     }
                   1350: 
                   1351:     sb->servent = uae_AllocMem (context, size, 0);
                   1352: 
                   1353:     if (!sb->servent) {
                   1354:        write_log ("BSDSOCK: WARNING - getservby%s() ran out of Amiga memory (couldn't allocate %d bytes)\n",type ? "port" : "name", size);
                   1355:        bsdsocklib_seterrno (sb, 12); // ENOMEM
                   1356:        return;
                   1357:     }
                   1358: 
                   1359:     sb->serventsize = size;
                   1360: 
                   1361:     aptr = sb->servent + 20 + numaliases * 4;
                   1362: 
                   1363:     // transfer servent to Amiga memory
                   1364:     put_long (sb->servent + 4, sb->servent + 16);
                   1365:     put_long (sb->servent + 8, (unsigned short)htons (s->s_port));
                   1366: 
                   1367:     for (i = 0; i < numaliases; i++)
                   1368:        put_long (sb->servent + 16 + i * 4, addstr (&aptr, s->s_aliases[i]));
                   1369:     put_long (sb->servent + 16 + numaliases * 4, 0);
                   1370:     put_long (sb->servent, aptr);
                   1371:     addstr (&aptr, s->s_name);
                   1372:     put_long (sb->servent + 12, aptr);
                   1373:     addstr (&aptr, s->s_proto);
                   1374: 
                   1375:     TRACE (("OK (%s, %d)\n", s->s_name, (unsigned short)htons (s->s_port)));
                   1376:     bsdsocklib_seterrno (sb,0);
                   1377: }
                   1378: 
                   1379: int host_sbinit (TrapContext *context, SB)
                   1380: {
                   1381:     if (pipe (sb->sockabort) < 0) {
                   1382:        return 0;
                   1383:     }
                   1384: 
                   1385:     if (fcntl (sb->sockabort[0], F_SETFL, O_NONBLOCK) < 0) {
                   1386:            write_log ("Set nonblock failed %d\n", errno);
                   1387:     }
                   1388: 
                   1389:     uae_sem_init (&sb->sem, 0, 0);
                   1390:     if (0) {
                   1391:        write_log ("BSDSOCK: Failed to create semaphore.\n");
                   1392:        close (sb->sockabort[0]);
                   1393:        close (sb->sockabort[1]);
                   1394:        return 0;
                   1395:     }
                   1396: 
                   1397:     /* Alloc hostent buffer */
                   1398:     sb->hostent = uae_AllocMem (context, 1024, 0);
                   1399:     sb->hostentsize = 1024;
                   1400: 
                   1401:     /* @@@ The thread should be PTHREAD_CREATE_DETACHED */
                   1402:     if (uae_start_thread (bsdlib_threadfunc, (void *)sb, &sb->thread)) {
                   1403:        write_log ("BSDSOCK: Failed to create thread.\n");
                   1404:        uae_sem_destroy (&sb->sem);
                   1405:        close (sb->sockabort[0]);
                   1406:        close (sb->sockabort[1]);
                   1407: 
                   1408:        return 0;
                   1409:     }
                   1410:     return 1;
                   1411: }
                   1412: 
                   1413: void host_sbcleanup (SB)
                   1414: {
                   1415:     int i;
                   1416: 
                   1417:     uae_thread_id thread = sb->thread;
                   1418:     close (sb->sockabort[0]);
                   1419:     close (sb->sockabort[1]);
                   1420:     for (i = 0; i < sb->dtablesize; i++) {
                   1421:        if (sb->dtable[i] != -1) {
                   1422:            close(sb->dtable[i]);
                   1423:        }
                   1424:     }
                   1425:     sb->action = 0;
                   1426: 
                   1427:     uae_sem_post (&sb->sem); /* destroy happens on socket thread */
                   1428: 
                   1429:     /* We need to join with the socket thread to allow the thread to die
                   1430:      * and clean up resources when the underlying thread layer is pthreads.
                   1431:      * Ideally, this shouldn't be necessary, but, for example, when SDL uses
                   1432:      * pthreads, it always creates joinable threads - and we can't do anything
                   1433:      * about that. */
                   1434:     uae_wait_thread (thread);
                   1435: }
                   1436: 
                   1437: void host_sbreset (void)
                   1438: {
                   1439:     /* TODO */
                   1440: }
                   1441: 
                   1442: uae_u32 host_Inet_NtoA (TrapContext *context, SB, uae_u32 in)
                   1443: {
                   1444:     char *addr;
                   1445:     struct in_addr ina;
                   1446:     uae_u32 buf;
                   1447: 
                   1448:     *(uae_u32 *)&ina = htonl (in);
                   1449: 
                   1450:     TRACE (("Inet_NtoA(%lx) -> ", in));
                   1451: 
                   1452:     if ((addr = inet_ntoa(ina)) != NULL) {
                   1453:        buf = m68k_areg (regs, 6) + offsetof (struct UAEBSDBase, scratchbuf);
                   1454:        strncpyha_safe (buf, addr, SCRATCHBUFSIZE);
                   1455:        TRACE (("%s\n", addr));
                   1456:        return buf;
                   1457:     } else
                   1458:        SETERRNO;
                   1459: 
                   1460:     TRACE (("failed (%d)\n", sb->sb_errno));
                   1461: 
                   1462:     return 0;
                   1463: }
                   1464: 
                   1465: uae_u32 host_inet_addr (uae_u32 cp)
                   1466: {
                   1467:     uae_u32 addr;
                   1468:     char *cp_rp;
                   1469: 
                   1470:     cp_rp = (char *)get_real_address (cp);
                   1471: 
                   1472:     addr = htonl (inet_addr (cp_rp));
                   1473: 
                   1474:     TRACE (("inet_addr(%s) -> 0x%08lx\n", cp_rp, addr));
                   1475: 
                   1476:     return addr;
                   1477: }
                   1478: 
                   1479: uae_u32 host_shutdown (SB, uae_u32 sd, uae_u32 how)
                   1480: {
                   1481:     SOCKET s;
                   1482: 
                   1483:     TRACE (("shutdown(%d,%d) -> ", sd, how));
                   1484:     s = getsock (sb, sd + 1);
                   1485: 
                   1486:     if (s != -1) {
                   1487:        if (shutdown (s, how)) {
                   1488:            SETERRNO;
                   1489:            TRACE (("failed (%d)\n", sb->sb_errno));
                   1490:        } else {
                   1491:            TRACE (("OK\n"));
                   1492:            return 0;
                   1493:        }
                   1494:     }
                   1495: 
                   1496:     return -1;
                   1497: }
                   1498: 
                   1499: int host_dup2socket (SB, int fd1, int fd2) {
                   1500:     int s1, s2;
                   1501: 
                   1502:     TRACE (("dup2socket(%d,%d) -> ", fd1, fd2));
                   1503:     fd1++;
                   1504: 
                   1505:     s1 = getsock (sb, fd1);
                   1506:     if (s1 != -1) {
                   1507:        if (fd2 != -1) {
                   1508:            if ((unsigned int) (fd2) >= (unsigned int) sb->dtablesize) {
                   1509:                TRACE (("Bad file descriptor (%d)\n", fd2));
                   1510:                bsdsocklib_seterrno (sb, 9); /* EBADF */
                   1511:            }
                   1512:            fd2++;
                   1513:            s2 = getsock (sb, fd2);
                   1514:            if (s2 != -1) {
                   1515:                close (s2);
                   1516:            }
                   1517:            setsd (sb, fd2, dup (s1));
                   1518:            TRACE (("0(%d)\n", getsock (sb, fd2)));
                   1519:            return 0;
                   1520:        } else {
                   1521:            fd2 = getsd (sb, 1);
                   1522:                if (fd2 != -1) {
                   1523:            setsd (sb, fd2, dup (s1));
                   1524:                        TRACE (("%d(%d)\n", fd2, getsock (sb, fd2)));
                   1525:            return (fd2 - 1);
                   1526:                } else {
                   1527:                        TRACE(("-1\n"));
                   1528:                        return -1;
                   1529:                }
                   1530:        }
                   1531:     }
                   1532:     TRACE (("-1\n"));
                   1533:     return -1;
                   1534: }
                   1535: 
                   1536: uae_u32 host_getsockopt (SB, uae_u32 sd, uae_u32 level, uae_u32 optname,
                   1537:                         uae_u32 optval, uae_u32 optlen)
                   1538: {
                   1539:     socklen_t len = 0;
                   1540:     int r;
                   1541:     int s;
                   1542:     int nativelevel = mapsockoptlevel(level);
                   1543:     int nativeoptname = mapsockoptname(nativelevel, optname);
                   1544:     void *buf = NULL;
                   1545:     s = getsock (sb, sd + 1);
                   1546: 
                   1547:     if (s == -1) {
                   1548:        bsdsocklib_seterrno(sb, 9); /* EBADF */
                   1549:        return -1;
                   1550:     }
                   1551: 
                   1552:     if (optlen) {
                   1553:        len = get_long (optlen);
                   1554:        buf = malloc(len);
                   1555:        if (buf == NULL) {
                   1556:           return -1;
                   1557:        }
                   1558:     }
                   1559: 
                   1560:     r = getsockopt (s, nativelevel, nativeoptname,
                   1561:        optval ? buf : NULL, optlen ? &len : NULL);
                   1562: 
                   1563:     if (optlen)
                   1564:        put_long (optlen, len);
                   1565: 
                   1566:     SETERRNO;
                   1567:     DEBUG_LOG ("getsockopt: sock AmigaSide %d NativeSide %d, level %d, 'name' %x(%d), len %d -> %d, %d\n",
                   1568:        sd, s, level, optname, nativeoptname, len, r, errno);
                   1569: 
                   1570:     if (optval) {
                   1571:        if (r == 0) {
                   1572:            mapsockoptreturn(nativelevel, nativeoptname, optval, buf);
                   1573:        }
                   1574:     }
                   1575: 
                   1576:     if (buf != NULL)
                   1577:        free(buf);
                   1578:     return r;
                   1579: }
                   1580: 
                   1581: uae_u32 host_IoctlSocket (SB, uae_u32 sd, uae_u32 request, uae_u32 arg)
                   1582: {
                   1583:     int sock = getsock (sb, sd + 1);
                   1584:     int r, argval = get_long (arg);
                   1585:     long flags;
                   1586: 
                   1587:     if (sock == -1) {
                   1588:        sb->resultval = -1;
                   1589:        bsdsocklib_seterrno (sb, 9); /* EBADF */
                   1590:        return -1;
                   1591:     }
                   1592: 
                   1593:     if ((flags = fcntl (sock, F_GETFL)) == -1) {
                   1594:        SETERRNO;
                   1595:        return -1;
                   1596:     }
                   1597: 
                   1598:     DEBUG_LOG ("Ioctl code is %lx, flags are %d\n", request, flags);
                   1599: 
                   1600:     switch (request) {
                   1601:        case 0x8004667B: /* FIOGETOWN */
                   1602:            sb->ownertask = get_long (arg);
                   1603:            return 0;
                   1604: 
                   1605:        case 0x8004667C: /* FIOSETOWN */
                   1606:            put_long (arg,sb->ownertask);
                   1607:            return 0;
                   1608:        case 0x8004667D: /* FIOASYNC */
                   1609: #      ifdef O_ASYNC
                   1610:            r = fcntl (sock, F_SETFL, argval ? flags | O_ASYNC : flags & ~O_ASYNC);
                   1611:            return r;
                   1612: #      else
                   1613:            /* O_ASYNC is only available on Linux and BSD systems */
                   1614:            return fcntl (sock, F_GETFL);
                   1615: #      endif
                   1616: 
                   1617:        case 0x8004667E: /* FIONBIO */
                   1618:            r = fcntl (sock, F_SETFL, argval ?
                   1619:                       flags | O_NONBLOCK : flags & ~O_NONBLOCK);
                   1620:            if (argval) {
                   1621:                DEBUG_LOG ("nonblocking\n");
                   1622:                sb->ftable[sd-1] &= ~SF_BLOCKING;
                   1623:            } else {
                   1624:                DEBUG_LOG ("blocking\n");
                   1625:                sb->ftable[sd-1] |= SF_BLOCKING;
                   1626:            }
                   1627:            return r;
                   1628: 
                   1629:        case 0x4004667F: /* FIONREAD */
                   1630:            r = ioctl (sock, FIONREAD, &flags);
                   1631:            if (r >= 0) {
                   1632:                put_long (arg, flags);
                   1633:            }
                   1634:            return r;
                   1635: 
                   1636:     } /* end switch */
                   1637: 
                   1638:     bsdsocklib_seterrno (sb, EINVAL);
                   1639:     return -1;
                   1640: }
                   1641: 
                   1642: int host_CloseSocket (SB, int sd)
                   1643: {
                   1644:     int s = getsock (sb, sd + 1);
                   1645:     int retval;
                   1646: 
                   1647:     if (s == -1) {
                   1648:        bsdsocklib_seterrno (sb, 9); /* EBADF */
                   1649:        return -1;
                   1650:     }
                   1651: 
                   1652:     /*
                   1653:     if (checksd (sb, sd + 1) == 1) {
                   1654:        return 0;
                   1655:     }
                   1656:     */
                   1657:     DEBUG_LOG ("CloseSocket Amiga: %d, NativeSide %d\n", sd, s);
                   1658:     retval = close (s);
                   1659:     SETERRNO;
                   1660:     releasesock (sb, sd + 1);
                   1661:     return retval;
                   1662: }
                   1663: 
                   1664: void host_closesocketquick (int s)
                   1665: {
                   1666:     struct linger l;
                   1667:     l.l_onoff = 0;
                   1668:     l.l_linger = 0;
                   1669:     if (s != -1) {
                   1670:        setsockopt (s, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
                   1671:        close (s);
                   1672:     }
                   1673: }
                   1674: 
                   1675: uae_u32 host_gethostname (uae_u32 name, uae_u32 namelen)
                   1676: {
                   1677:     return gethostname ((char *)get_real_address (name), namelen);
                   1678: }
                   1679: 
                   1680: int init_socket_layer(void)
                   1681: {
                   1682:     uae_sem_init(&sem_queue, 0, 1);
                   1683:     if (0 /* @@@ */) {
                   1684:        DEBUG_LOG("Can't create sem %d\n", errno);
                   1685:        return 0;
                   1686:     }
                   1687: 
                   1688:     return 1;
                   1689: }
                   1690: 
                   1691: void clearsockabort (SB)
                   1692: {
                   1693:     int chr;
                   1694:     int num;
                   1695: 
                   1696:     while ((num = read (sb->sockabort[0], &chr, sizeof(chr))) >= 0) {
                   1697:        DEBUG_LOG ("Sockabort got %d bytes\n", num);
                   1698:        ;
                   1699:     }
                   1700: }
                   1701: 
                   1702: void sockabort (SB)
                   1703: {
                   1704:     int chr = 1;
                   1705:     DEBUG_LOG ("Sock abort!!\n");
                   1706:     write (sb->sockabort[1], &chr, sizeof (chr));
                   1707: }
                   1708: 
                   1709: void locksigqueue (void)
                   1710: {
                   1711:     uae_sem_wait(&sem_queue);
                   1712: }
                   1713: 
                   1714: void unlocksigqueue (void)
                   1715: {
                   1716:     uae_sem_post(&sem_queue);
                   1717: }
                   1718: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.