3Syntax10.Scn.Fnt fInfoElemsAllocTSyntax10.Scn.Fnt hStampElemsAlloc5 Nov 48F"Title": TCP Connections for Oberon for Linux "Author": Robert Lichtenberger, tanis@sport2.uibk.ac.at "Abstract": This module provides access to the TCProtocol. It is derived from the Windows version "Keywords": TCP network "Version": 0.80 "From": 1 Oct 96 "Until":  "Changes": "Hints": The hardest part were the Available function and the HostByName function. They included Linux system programming and I am not good at that. Be careful when using TCP because I suppose there are still a lot of bugs in it. If you discover one please report them to tanis@sport2.uibk.ac.at. Syntax10i.Scn.Fnt:0WStampElemsAlloc5 Nov 43Syntax10b.Scn.Fnt  " J eG" [8FoldElemsNewR8 MarkElemsAlloc OF8Syntax10.Scn.FntSyntax10i.Scn.Fnt@SSyntax10b.Scn.Fnt`< (* returns i: 0 <= i < ConnTabSize with ConnTab[i] = 0, or -1 *) VAR i: INTEGER; BEGIN i := 0; WHILE i < ConnTabSize DO IF ConnTab[i] = 0 THEN RETURN i END ; INC(i) END ; Kernel.GC; i := 0; WHILE i < ConnTabSize DO IF ConnTab[i] = 0 THEN RETURN i END ; INC(i) END ; RETURN - 1 END FreeConnTabEntry; 8  O!8QSyntax10.Scn.FntSyntax10b.Scn.Fnt  VAR i: INTEGER; C: Connection; BEGIN WHILE i < ConnTabSize DO IF ConnTab[i] # 0 THEN C := SYSTEM.VAL(Connection, ConnTab[i]); IF C.id = id THEN RETURN i END END ; INC(i) END ; RETURN - 1 END ThisConn; 8  O8#Syntax10.Scn.FntYY VAR x: LONGINT; BEGIN x := closesocket(L.socket); L.socket := InvalidSocket END Close; 8  O#[8#Syntax10.Scn.Fnt VAR x: LONGINT; BEGIN WITH L: Listener DO x := closesocket(L.socket); L.socket := InvalidSocket ELSE END END ListenerFinalizer; 8 OS8"aT8 O 8QSyntax10.Scn.FntSyntax10b.Scn.Fnt  TYPE SocketSet = ARRAY 8 OF LONGINT ; Timeout = RECORD sec, usec: LONGINT END ; VAR set: SocketSet; timeout: Timeout; x: LONGINT; idx: INTEGER; BEGIN timeout.sec := 0; timeout.usec := 0; FOR idx := 0 TO 7 DO set[idx] := 0 END; idx := SHORT(L.socket DIV 32); ASSERT(idx < 8); set[idx] := pw2[L.socket MOD 32]; x := select(MAX(LONGINT), SYSTEM.ADR(set), 0, 0, SYSTEM.ADR(timeout)); IF x = SocketError THEN HALT(66) ELSE RETURN x > 0 END END Requested; 8 O 88#Syntax10.Scn.Fnt VAR x: LONGINT; i: INTEGER; BEGIN x := closesocket(C.socket); C.socket := InvalidSocket; i := ThisConn(C.id); IF i >= 0 THEN ConnTab[i] := 0 END END Disconnect; 8 O% 8#Syntax10.Scn.Fnt VAR x: LONGINT; i: INTEGER; BEGIN WITH C: Connection DO x := closesocket(C.socket); C.socket := InvalidSocket; i := ThisConn(C.id); IF i >= 0 THEN ConnTab[i] := 0 END ELSE END END ConnectionFinalizer; 8 O1V8#Syntax10.Scn.Fnt VAR x: LONGINT; i: INTEGER; BEGIN C.socket := accept(L.socket, 0, 0); IF C.socket = SocketError THEN res := NotDone ELSE i := FreeConnTabEntry(); IF i < 0 THEN x := closesocket(C.socket); C.socket := InvalidSocket; res := NotDone ELSE C.id := Input.Time(); ConnTab[i] := SYSTEM.VAL(LONGINT, C); Kernel.RegisterObject(C, ConnectionFinalizer); res := Done END END END Accept; 8 Od8"BZ{8 O >8&Courier10.Scn.FntKdL8 O <j8#Syntax10.Scn.Fnttt BEGIN adr := inetaddr(SYSTEM.ADR(number)); IF adr # 0 THEN res := Done ELSE res := NotDone END END HostByNumber; 8 O +N8CSyntax10.Scn.FntSyntax10i.Scn.Fnt"Lp (** Returns the local hostname *) BEGIN res := SHORT(gethostname(SYSTEM.ADR(s[0]), LEN(s))) END GetHostName; 8 O%p8#Syntax10.Scn.Fntnn VAR name: ARRAY 128 OF CHAR; BEGIN GetHostName(name, res); HostByName(name, adr, res) END GetHostAddress; 8 O08CSyntax10.Scn.Fnt;Syntax10b.Scn.FntR VAR i: INTEGER; BEGIN i := ThisConn(id); IF i >= 0 THEN RETURN SYSTEM.VAL(Connection, ConnTab[i]) ELSE RETURN NIL END END ThisConnection; 8 O M8CSyntax10.Scn.FntSyntax10i.Scn.Fnt88q (* number of bytes that can be read without blocking *) CONST MsgPeek = 2; ONONBLOCK = 2048; FSETFL = 4; VAR x, y: LONGINT; BEGIN x := Unix.Fcntl(C.socket, FSETFL, ONONBLOCK); ASSERT(x # - 1); x := recv(C.socket, SYSTEM.ADR(buffer), BufSize, MsgPeek); y := Unix.Fcntl(C.socket, FSETFL, 0); ASSERT(y # - 1); IF x = -1 THEN x := 0 END; RETURN x; END Available; 8 O 8#Syntax10.Scn.Fnt,, BEGIN RETURN MAX(LONGINT) END AvailToSend; 8 O 88#Syntax10.Scn.FntCC BEGIN RETURN (vec[fd DIV 32] * {(fd MOD 32)} # {}); END fdISSet; 8588.8#Syntax10.Scn.FntAA BEGIN vec[fd DIV 32]:=vec[fd DIV 32]+{(fd MOD 32)}; END fdSet; 88;] O&^8#Syntax10.Scn.Fnt VAR n: LONGINT; BEGIN n := recv(C.socket, SYSTEM.ADR(x), 1, 0); IF n > 0 THEN res := Done ELSE res := NotDone END END Read; 8 O B;8CSyntax10.Scn.FntSyntax10i.Scn.Fnt\% (** receive bytes x[beg] .. x[beg+len]; Precodition: (beg >= 0) AND (beg+len <= LEN(x)) **) VAR n, adr, total: LONGINT; BEGIN ASSERT((beg >= 0) & (LEN(x) >= beg + len)); adr := SYSTEM.ADR(x) + beg; total := 0; WHILE total < len DO n := recv(C.socket, adr, len - total, 0); INC(total, n); INC(adr, n) END ; IF n < len THEN res := NotDone ELSE res := Done END END ReadBytes; 8 O"<8#Syntax10.Scn.Fnt VAR n: LONGINT; nx: INTEGER; BEGIN n := recv(C.socket, SYSTEM.ADR(nx), 2, 0); IF n = 2 THEN res := Done; x := ntohs(nx) ELSE res := NotDone END END ReadInt; 8 O "E8#Syntax10.Scn.Fnt VAR nx, n: LONGINT; BEGIN n := recv(C.socket, SYSTEM.ADR(nx), 4, 0); IF n = 4 THEN res := Done; x := ntohl(nx) ELSE res := NotDone END END ReadLInt; 8  O Z8#Syntax10.Scn.Fnt VAR n: LONGINT; BEGIN n := recv(C.socket, SYSTEM.ADR(r), 4, 0); IF n = 4 THEN res := Done ELSE res := NotDone END END ReadReal; 8 !O #Y8#Syntax10.Scn.Fnt VAR n: LONGINT; BEGIN n := recv(C.socket, SYSTEM.ADR(r), 8, 0); IF n = 8 THEN res := Done ELSE res := NotDone END END ReadLReal; 8 "O[8#Syntax10.Scn.Fnt VAR n: LONGINT; BEGIN n := recv(C.socket, SYSTEM.ADR(s), 4, 0); IF n = 4 THEN res := Done ELSE res := NotDone END END ReadSet; 8 #O (8#Syntax10.Scn.Fnt VAR n: LONGINT; i: INTEGER; ch: CHAR; BEGIN i := 0; res := Done; REPEAT n := recv(C.socket, SYSTEM.ADR(ch), 1, 0); IF n # 1 THEN res := NotDone END ; s[i] := ch; INC(i) UNTIL (ch = 0X) OR (res = NotDone) END ReadString; 8 $O "Z8#Syntax10.Scn.Fnt VAR n: LONGINT; BEGIN n := recv(C.socket, SYSTEM.ADR(b), 1, 0); IF n = 1 THEN res := Done ELSE res := NotDone END END ReadBool; 8<D %O"]8#Syntax10.Scn.Fnt VAR n: LONGINT; BEGIN n := send(C.socket, SYSTEM.ADR(x), 1, 0); IF n = 1 THEN res := Done ELSE res := NotDone END END Write; 8 &O B8CSyntax10.Scn.FntSyntax10i.Scn.FntY (** send bytes x[beg] .. x[beg+len]; Precodition: (beg >= 0) AND (beg+len <= LEN(x)) **) VAR n: LONGINT; BEGIN ASSERT((beg >= 0) & (LEN(x) >= beg + len)); n := send(C.socket, SYSTEM.ADR(x) + beg, len, 0); IF n = len THEN res := Done ELSE res := NotDone END END WriteBytes; 8 'O "W8#Syntax10.Scn.Fnt VAR n: LONGINT; BEGIN n := send(C.socket, SYSTEM.ADR(x), 1, 1); IF n = 1 THEN res := Done ELSE res := NotDone END END WriteUrgent; 8 (OB8CSyntax10.Scn.FntSyntax10i.Scn.FntY (** send bytes x[beg] .. x[beg+len]; Precodition: (beg >= 0) AND (beg+len <= LEN(x)) **) VAR n: LONGINT; BEGIN ASSERT((beg >= 0) & (LEN(x) >= beg + len)); n := send(C.socket, SYSTEM.ADR(x) + beg, len, 1); IF n = len THEN res := Done ELSE res := NotDone END END WriteBytesUrgent; 8 )O ;8#Syntax10.Scn.Fnt VAR nx: INTEGER; n: LONGINT; BEGIN nx := htons(x); n := send(C.socket, SYSTEM.ADR(nx), 2, 0); IF n = 2 THEN res := Done ELSE res := NotDone END END WriteInt; 8 *O C8#Syntax10.Scn.Fnt VAR nx, n: LONGINT; BEGIN nx := htonl(x); n := send(C.socket, SYSTEM.ADR(nx), 4, 0); IF n = 4 THEN res := Done ELSE res := NotDone END END WriteLInt; 8 +O Y8#Syntax10.Scn.Fnt VAR n: LONGINT; BEGIN n := send(C.socket, SYSTEM.ADR(r), 4, 0); IF n = 4 THEN res := Done ELSE res := NotDone END END WriteReal; 8 ,O X8#Syntax10.Scn.Fnt VAR n: LONGINT; BEGIN n := send(C.socket, SYSTEM.ADR(r), 8, 0); IF n = 8 THEN res := Done ELSE res := NotDone END END WriteLReal; 8 -O Z8#Syntax10.Scn.Fnt VAR n: LONGINT; BEGIN n := send(C.socket, SYSTEM.ADR(s), 4, 0); IF n = 4 THEN res := Done ELSE res := NotDone END END WriteSet; 8 .O $8#Syntax10.Scn.Fnt VAR n, len: LONGINT; BEGIN len := 0; WHILE s[len] # 0X DO INC(len) END ; n := send(C.socket, SYSTEM.ADR(s), len + 1, 0); IF n = len + 1 THEN res := Done ELSE res := NotDone END END WriteString; 8 /O Y8#Syntax10.Scn.Fnt VAR n: LONGINT; BEGIN n := send(C.socket, SYSTEM.ADR(b), 1, 0); IF n = 1 THEN res := Done ELSE res := NotDone END END WriteBool; 8 1O8.8#Syntax10.Scn.FntBBpw2[0] := 1; pw2[1] := 2; pw2[2] := 4; pw2[3] := 8; pw2[4] := 16; pw2[5] := 32; pw2[6] := 64; pw2[7] := 128; pw2[8] := 256; pw2[9] := 512; pw2[10] := 1024; pw2[11] := 2048; pw2[12] := 4096; pw2[13] := 8192; pw2[14] := 16384; pw2[15] := 32768; pw2[16] := 65536; pw2[17] := 131072; pw2[18] := 262144; pw2[19] := 524288; pw2[20] := 1048576; pw2[21] := 2097152; pw2[22] := 4194304; pw2[23] := 8388608; pw2[24] := 16777216; pw2[25] := 33554432; pw2[26] := 67108864; pw2[27] := 134217728; pw2[28] := 268435456; pw2[29] := 536870912; pw2[30] := 1073741824; pw2[31] := 0FFFFFFFFH; 888#Syntax10.Scn.Fnt Init8 l%MODULE TCP;  (* TCP Connections for Oberon for Linux -- RLI 1 Oct 96 -  *) IMPORT SYSTEM, Kernel, Input, Unix, Out; CONST Done* = 0; NotDone* = 1; Timeout* = 2; LocalPortInUse* = 3; AnyAdr* = 0; AnyPort* = 0; ConnTabSize = 64; PFInet = 2; SockStream = 1; IPProtoTCP = 6; InvalidSocket = -1; SocketError = -1; BufSize = 64000; TYPE Connection* = POINTER TO ConnectionDesc; ConnectionDesc* = RECORD id-: LONGINT; socket: LONGINT END ; Listener* = POINTER TO ListenerDesc; ListenerDesc = RECORD socket: LONGINT END ; IpAdr* = LONGINT; SockAddr = RECORD (* struct sockaddr_in *) family: INTEGER; socket: INTEGER; internetAddr: LONGINT; zero: ARRAY 8 OF CHAR END ; VAR (* These procedures are bound to their equivalent Linux System calls *) inetaddr: PROCEDURE (str: LONGINT): LONGINT; gethostbyname: PROCEDURE (name: LONGINT): LONGINT; htons: PROCEDURE (x: INTEGER): INTEGER; htonl: PROCEDURE (x: LONGINT): LONGINT; ntohs: PROCEDURE (x: INTEGER): INTEGER; ntohl: PROCEDURE (x: LONGINT): LONGINT; socket: PROCEDURE (af, type, protocol: LONGINT): LONGINT; connect: PROCEDURE (socket, name, namelen: LONGINT): LONGINT; bind: PROCEDURE (socket, name, namelen: LONGINT): LONGINT; closesocket: PROCEDURE (s: LONGINT): LONGINT; gethostname: PROCEDURE (name: LONGINT; namelen: LONGINT): LONGINT; ioctlsocket: PROCEDURE (socket, cmd, argptr: LONGINT): LONGINT; recv: PROCEDURE (socket, bufaddr, buflen, flags: LONGINT): LONGINT; send: PROCEDURE (socket, bufaddr, buflen, flags: LONGINT): LONGINT; listen: PROCEDURE (socket, backlog: LONGINT): LONGINT; accept: PROCEDURE (socket, addr, addrlen: LONGINT): LONGINT; select: PROCEDURE (dummy, read, write, except, timeout: LONGINT): LONGINT; ConnTab: ARRAY ConnTabSize OF LONGINT; (* weak pointers to connections *) pw2: ARRAY 32 OF LONGINT; (* contains 2^0 .. 2^31 *) res-: INTEGER; herrp: LONGINT; buffer: ARRAY BufSize OF CHAR; PROCEDURE HErrno (): LONGINT;  VAR herrno: LONGINT; BEGIN SYSTEM.GET(herrp, herrno); RETURN herrno END HErrno;  PROCEDURE FreeConnTabEntry (): INTEGER;  PROCEDURE ThisConn (id: LONGINT): INTEGER;  PROCEDURE Close* (L: Listener);  PROCEDURE ListenerFinalizer (L: SYSTEM.PTR);  PROCEDURE Listen* (L: Listener; lsocket: INTEGER; radr: IpAdr; rsocket: INTEGER; VAR res: INTEGER);  VAR x: LONGINT; sadr: SockAddr; BEGIN L.socket := socket(PFInet, SockStream, IPProtoTCP); IF L.socket = InvalidSocket THEN res := NotDone ELSE ASSERT(lsocket # AnyPort); (* assign a local socket number *) sadr.family := PFInet; sadr.socket := htons(lsocket); sadr.internetAddr := AnyAdr; x := bind(L.socket, SYSTEM.ADR(sadr), SIZE(SockAddr)); IF x # 0 THEN IF HErrno() = Unix.EADDRINUSE THEN res := LocalPortInUse ELSE res := NotDone END ; x := closesocket(L.socket); RETURN END ; x := listen(L.socket, 5); IF x # 0 THEN x := closesocket(L.socket); res := NotDone; RETURN END END ; Kernel.RegisterObject(L, ListenerFinalizer); res := Done END Listen;  PROCEDURE Requested* (L: Listener): BOOLEAN;  PROCEDURE Disconnect* (C: Connection);  PROCEDURE ConnectionFinalizer (C: SYSTEM.PTR);  PROCEDURE Accept* (L: Listener; C: Connection; VAR res: INTEGER);  PROCEDURE Connect* (C: Connection; lport: INTEGER; Adr: IpAdr; rsocket: INTEGER; timeout: LONGINT; VAR res: INTEGER);  VAR sadr: SockAddr; x, e: LONGINT; i: INTEGER; BEGIN res := Done; C.socket := socket(PFInet, SockStream, 0); IF C.socket = InvalidSocket THEN res := NotDone; ELSE IF lport # AnyPort THEN (* assign a local socket number *) sadr.family := PFInet; sadr.socket := htons(lport); sadr.internetAddr := AnyAdr; x := bind(C.socket, SYSTEM.ADR(sadr), SIZE(SockAddr)); IF x # 0 THEN x := HErrno(); IF x = Unix.EADDRINUSE THEN res := LocalPortInUse ELSE res := NotDone END ; x := closesocket(C.socket); C.socket := InvalidSocket; RETURN END END ; sadr.family := PFInet; sadr.socket := htons(rsocket); sadr.internetAddr := Adr; x := connect(C.socket, SYSTEM.ADR(sadr), SIZE(SockAddr)); IF x # 0 THEN e := HErrno(); IF (e = Unix.ETIMEDOUT) OR (e = Unix.EINTR) THEN res := Timeout ELSE res := NotDone END ; x := closesocket(C.socket); C.socket := InvalidSocket; RETURN END ; i := FreeConnTabEntry(); IF i < 0 THEN x := closesocket(C.socket); C.socket := InvalidSocket; res := NotDone; RETURN ELSE C.id := Input.Time(); ConnTab[i] := SYSTEM.VAL(LONGINT, C) END ; Kernel.RegisterObject(C, ConnectionFinalizer) END END Connect;  PROCEDURE HostByName* (hostname: ARRAY OF CHAR; VAR adr: IpAdr; VAR res: INTEGER);  TYPE hostent = POINTER TO RECORD (* struct hostent*) name, aliases: LONGINT; addrtype, length: INTEGER; adr: LONGINT; (* Dummy, I don't understand why we need adr2 here, but it's C, so I guess it's better no to try *) adr2: LONGINT (* to understand -- ;-) *) END ; VAR host: hostent; err: LONGINT; BEGIN host := SYSTEM.VAL(hostent, gethostbyname(SYSTEM.ADR(hostname))); IF host # NIL THEN SYSTEM.GET(host.adr2, adr); SYSTEM.GET(adr, adr); res := Done ELSE err := HErrno(); IF (err = Unix.ETIMEDOUT) THEN res := Timeout ELSE res := NotDone END ; adr := 0 END END HostByName;  PROCEDURE HostByNumber* (number: ARRAY OF CHAR; VAR adr: IpAdr; VAR res: INTEGER);  PROCEDURE GetHostName* (VAR s: ARRAY OF CHAR; VAR res: INTEGER);  PROCEDURE GetHostAddress* (VAR adr: IpAdr; VAR res: INTEGER);  PROCEDURE ThisConnection* (id: LONGINT): Connection;  PROCEDURE Available* (C: Connection): LONGINT;  PROCEDURE AvailToSend* (C: Connection): LONGINT;  PROCEDURE Connected* (C: Connection): BOOLEAN;  (* can write to C *) CONST MsgPeek = 2; TYPE FDSet = ARRAY 8 OF SET; Timeout = RECORD sec, usec: LONGINT END ; VAR rVec, wVec: FDSet; timeout: Timeout; x: LONGINT; idx: INTEGER; ch: CHAR; PROCEDURE fdISSet(fd: LONGINT; VAR vec: FDSet): BOOLEAN;  PROCEDURE fdZero(numBits: LONGINT; VAR vec: FDSet);  VAR i: INTEGER; lastIndex: LONGINT; BEGIN lastIndex:=numBits DIV 32; i:=0; LOOP vec[i]:={}; IF i=lastIndex THEN EXIT; ELSE i:=i+1; END; END; END fdZero;  PROCEDURE fdSet(fd: LONGINT; VAR vec: FDSet); BEGIN IF C.socket = InvalidSocket THEN RETURN FALSE END; timeout.sec := 0; timeout.usec := 0; fdZero(C.socket,rVec); fdZero(C.socket,wVec); fdSet(C.socket,rVec); fdSet(C.socket,wVec); x := select(C.socket +1, SYSTEM.ADR(rVec), 0, 0, SYSTEM.ADR(timeout)); IF x = SocketError THEN HALT(66) ELSE IF x = 1 THEN RETURN recv(C.socket, SYSTEM.ADR(ch), 1, MsgPeek) = 1; ELSE RETURN TRUE; END; END; END Connected;  (* --------------------- read procedures --------------- *) (* all Read* procedures are blocking, res = Done if connection is alive, NotDone otherwise *) PROCEDURE Read* (C: Connection; VAR x: SYSTEM.BYTE);  PROCEDURE ReadBytes* (C: Connection; VAR x: ARRAY OF SYSTEM.BYTE; beg, len: LONGINT);  PROCEDURE ReadInt* (C: Connection; VAR x: INTEGER);  PROCEDURE ReadLInt* (C: Connection; VAR x: LONGINT);  PROCEDURE ReadReal* (C: Connection; VAR r: REAL);  PROCEDURE ReadLReal* (C: Connection; VAR r: LONGREAL);  PROCEDURE ReadSet* (C: Connection; VAR s: SET);  PROCEDURE ReadString* (C: Connection; VAR s: ARRAY OF CHAR);  PROCEDURE ReadBool* (C: Connection; VAR b: BOOLEAN);  (* --------------------- write procedures --------------- *) (* Blocking, res = Done if connection is alive, NotDone otherwise *) PROCEDURE Write* (C: Connection; x: SYSTEM.BYTE);  PROCEDURE WriteBytes* (C: Connection; VAR x: ARRAY OF SYSTEM.BYTE; beg, len: LONGINT);  PROCEDURE WriteUrgent* (C: Connection; x: SYSTEM.BYTE);  PROCEDURE WriteBytesUrgent* (C: Connection; VAR x: ARRAY OF SYSTEM.BYTE; beg, len: LONGINT);  PROCEDURE WriteInt* (C: Connection; x: INTEGER);  PROCEDURE WriteLInt* (C: Connection; x: LONGINT);  PROCEDURE WriteReal* (C: Connection; r: REAL);  PROCEDURE WriteLReal* (C: Connection; r: LONGREAL);  PROCEDURE WriteSet* (C: Connection; s: SET);  PROCEDURE WriteString* (C: Connection; s: ARRAY OF CHAR);  PROCEDURE WriteBool* (C: Connection; b: BOOLEAN);  PROCEDURE Init;  VAR mod, res: LONGINT; err: ARRAY 32 OF CHAR; i: INTEGER; BEGIN Kernel.dlsym(Kernel.libc, "inet_addr", SYSTEM.VAL(LONGINT, inetaddr)); Kernel.dlsym(Kernel.libc, "gethostbyname", SYSTEM.VAL(LONGINT, gethostbyname)); Kernel.dlsym(Kernel.libc, "errno", herrp); Kernel.dlsym(Kernel.libc, "htons", SYSTEM.VAL(LONGINT, htons)); Kernel.dlsym(Kernel.libc, "htonl", SYSTEM.VAL(LONGINT, htonl)); Kernel.dlsym(Kernel.libc, "ntohs", SYSTEM.VAL(LONGINT, ntohs)); Kernel.dlsym(Kernel.libc, "ntohl", SYSTEM.VAL(LONGINT, ntohl)); Kernel.dlsym(Kernel.libc, "socket", SYSTEM.VAL(LONGINT, socket)); Kernel.dlsym(Kernel.libc, "connect", SYSTEM.VAL(LONGINT, connect)); Kernel.dlsym(Kernel.libc, "bind", SYSTEM.VAL(LONGINT, bind)); Kernel.dlsym(Kernel.libc, "close", SYSTEM.VAL(LONGINT, closesocket)); Kernel.dlsym(Kernel.libc, "gethostname", SYSTEM.VAL(LONGINT, gethostname)); Kernel.dlsym(Kernel.libc, "ioctl", SYSTEM.VAL(LONGINT, ioctlsocket)); Kernel.dlsym(Kernel.libc, "recv", SYSTEM.VAL(LONGINT, recv)); Kernel.dlsym(Kernel.libc, "send", SYSTEM.VAL(LONGINT, send)); Kernel.dlsym(Kernel.libc, "listen", SYSTEM.VAL(LONGINT, listen)); Kernel.dlsym(Kernel.libc, "accept", SYSTEM.VAL(LONGINT, accept)); Kernel.dlsym(Kernel.libc, "select", SYSTEM.VAL(LONGINT, select)); FOR i := 0 TO ConnTabSize - 1 DO ConnTab[i] := 0 END; Init pw2-table res := Done END Init;  BEGIN END TCP.