Annotation of uae/src/bsdsocket-posix-new.c, revision 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.