From 1c452dd4f98e0aba44d7b35e89730b20e1505033 Mon Sep 17 00:00:00 2001
From: daniel <daniel@freepascal.org>
Date: Sun, 14 Jan 2007 18:50:19 +0000
Subject: [PATCH]   + Restore and fix text/file socket functionality.

git-svn-id: trunk@5973 -
---
 rtl/inc/sockets.inc      | 200 +++++++++++++++++++++++++++++++++++++++
 rtl/inc/socketsh.inc     |  13 +++
 rtl/inc/sockovl.inc      |  73 ++++++++++++++
 rtl/netware/nwsock.inc   |  73 ++++++++++++++
 rtl/openbsd/unixsock.inc |  72 ++++++++++++++
 rtl/unix/sockets.pp      |   4 +
 6 files changed, 435 insertions(+)

diff --git a/rtl/inc/sockets.inc b/rtl/inc/sockets.inc
index 758a42c574..edb6acf27e 100644
--- a/rtl/inc/sockets.inc
+++ b/rtl/inc/sockets.inc
@@ -11,6 +11,206 @@
 
  **********************************************************************}
 
+{******************************************************************************
+                     Text File Writeln/ReadLn Support
+******************************************************************************}
+
+
+Procedure OpenSock(var F:Text);
+begin
+  if textrec(f).handle=UnusedHandle then
+   textrec(f).mode:=fmclosed
+  else
+   case textrec(f).userdata[1] of
+     S_OUT : textrec(f).mode:=fmoutput;
+     S_IN : textrec(f).mode:=fminput;
+   else
+    textrec(f).mode:=fmclosed;
+   end;
+end;
+
+
+
+procedure iosock(var f:text);
+
+var r:sizeint;
+    def_error:word;
+
+begin
+  with textrec(f) do
+    begin
+      case mode of
+        fmoutput:
+          begin
+            repeat
+{$ifdef use_readwrite}
+              r:=fpwrite(handle,bufptr^,bufpos);
+{$else}
+              r:=send(handle,bufptr^,bufpos,0);
+{$endif}
+            until (r<>-1) or (errno<>EsysEINTR);
+            bufend:=r;
+            def_error:=101; {File write error.}
+          end;
+        fminput:
+          begin
+            repeat
+{$ifdef use_readwrite}
+              r:=fpread(handle,bufptr^,bufsize);
+{$else}
+              r:=recv(handle,bufptr^,bufsize,0);
+{$endif}
+            until (r<>-1) or (errno<>EsysEINTR);
+            bufend:=r;
+            def_error:=100; {File read error.}
+          end;
+      end;
+      if r=-1 then
+        case errno of
+          EsysEBADF:
+{          EsysENOTSOCK:}   {Why is this constant not defined? (DM)}
+            inoutres:=6;    {Invalid file handle.}
+          EsysEFAULT:
+            inoutres:=217;
+          EsysEINVAL:
+            inoutres:=218;
+        else
+          inoutres:=def_error;
+        end;
+      bufpos:=0;
+    end;
+end;
+
+
+
+Procedure FlushSock(var F:Text);
+begin
+  if (textrec(f).mode=fmoutput) and (textrec(f).bufpos<>0) then
+   begin
+     IOSock(f);
+     textrec(f).bufpos:=0;
+   end;
+end;
+
+
+
+Procedure CloseSock(var F:text);
+begin
+  { Nothing special has to be done here }
+end;
+
+
+
+Procedure Sock2Text(Sock:Longint;Var SockIn,SockOut:Text);
+{
+ Set up two Pascal Text file descriptors for reading and writing)
+}
+begin
+{ First the reading part.}
+  Assign(SockIn,'.');
+  Textrec(SockIn).Handle:=Sock;
+  Textrec(Sockin).userdata[1]:=S_IN;
+  TextRec(SockIn).OpenFunc:=@OpenSock;
+  TextRec(SockIn).InOutFunc:=@IOSock;
+  TextRec(SockIn).FlushFunc:=@FlushSock;
+  TextRec(SockIn).CloseFunc:=@CloseSock;
+  TextRec(SockIn).Mode := fmInput;
+{ Now the writing part. }
+  Assign(SockOut,'.');
+  Textrec(SockOut).Handle:=Sock;
+  Textrec(SockOut).userdata[1]:=S_OUT;
+  TextRec(SockOut).OpenFunc:=@OpenSock;
+  TextRec(SockOut).InOutFunc:=@IOSock;
+  TextRec(SockOut).FlushFunc:=@FlushSock;
+  TextRec(SockOut).CloseFunc:=@CloseSock;
+  TextRec(SockOut).Mode := fmOutput;
+end;
+
+
+{******************************************************************************
+                                Untyped File
+******************************************************************************}
+
+Procedure Sock2File(Sock:Longint;Var SockIn,SockOut:File);
+begin
+{Input}
+  Assign(SockIn,'.');
+  FileRec(SockIn).Handle:=Sock;
+  FileRec(SockIn).RecSize:=1;
+  FileRec(Sockin).userdata[1]:=S_IN;
+  FileRec(SockIn).Mode := fmInput;
+
+{Output}
+  Assign(SockOut,'.');
+  FileRec(SockOut).Handle:=Sock;
+  FileRec(SockOut).RecSize:=1;
+  FileRec(SockOut).userdata[1]:=S_OUT;
+  FileRec(SockOut).Mode := fmOutput;
+end;
+
+{******************************************************************************
+                               InetSock
+******************************************************************************}
+
+Function DoAccept(Sock:longint;Var addr:TInetSockAddr):longint;
+
+Var AddrLen : Longint;
+
+begin
+  AddrLEn:=SizeOf(Addr);
+  DoAccept:=Accept(Sock,Addr,AddrLen);
+end;
+
+Function DoConnect(Sock:longint;const addr: TInetSockAddr): Boolean;
+
+begin
+  DoConnect:=Connect(Sock,Addr,SizeOF(TInetSockAddr));
+end;
+
+Function Connect(Sock:longint;const addr: TInetSockAddr;var SockIn,SockOut:text):Boolean;
+
+begin
+  Connect:=DoConnect(Sock,addr);
+  If Connect then
+     Sock2Text(Sock,SockIn,SockOut);
+end;
+
+Function Connect(Sock:longint;const addr:TInetSockAddr;var SockIn,SockOut:file):Boolean;
+
+begin
+  Connect:=DoConnect(Sock,addr);
+  If Connect then
+     Sock2File(Sock,SockIn,SockOut);
+end;
+
+Function Accept(Sock:longint;var addr:TInetSockAddr;var SockIn,SockOut:text):Boolean;
+var
+  s : longint;
+begin
+  S:=DoAccept(Sock,addr);
+  if S>0 then
+   begin
+     Sock2Text(S,SockIn,SockOut);
+     Accept:=true;
+   end
+  else
+   Accept:=false;
+end;
+
+Function Accept(Sock:longint;var addr:TInetSockAddr;var SockIn,SockOut:File):Boolean;
+var
+  s : longint;
+begin
+  S:=DoAccept(Sock,addr);
+  if S>0 then
+   begin
+     Sock2File(S,SockIn,SockOut);
+     Accept:=true;
+   end
+  else
+   Accept:=false;
+end;
+
 type thostaddr= packed array[1..4] of byte;
 
 function htonl( host : longint):longint; inline;
diff --git a/rtl/inc/socketsh.inc b/rtl/inc/socketsh.inc
index 726d23653a..eefadb0378 100644
--- a/rtl/inc/socketsh.inc
+++ b/rtl/inc/socketsh.inc
@@ -191,6 +191,19 @@ Function SetSocketOptions(Sock,Level,OptName:Longint;const OptVal;optlen:longint
 Function GetSocketOptions(Sock,Level,OptName:Longint;Var OptVal;Var optlen:longint):Longint;
 Function SocketPair(Domain,SocketType,Protocol:Longint;var Pair:TSockArray):Longint;
 
+{Text Support}
+Procedure Sock2Text(Sock:Longint;Var SockIn,SockOut:Text);
+
+{Untyped File Support}
+Procedure Sock2File(Sock:Longint;Var SockIn,SockOut:File);
+
+{Better Pascal Calling, Overloaded Functions!}
+Function Accept(Sock:longint;var addr:TInetSockAddr;var SockIn,SockOut:File):Boolean;
+Function Accept(Sock:longint;var addr:TInetSockAddr;var SockIn,SockOut:text):Boolean;
+Function Connect(Sock:longint;const addr:TInetSockAddr;var SockIn,SockOut:text):Boolean;
+Function Connect(Sock:longint;const addr:TInetSockAddr;var SockIn,SockOut:file):Boolean;
+
+
 { Utility routines}
 function htonl( host : longint):longint; inline;
 Function NToHl( Net : Longint) : Longint; inline;
diff --git a/rtl/inc/sockovl.inc b/rtl/inc/sockovl.inc
index 941b6a0051..393b1cdda7 100644
--- a/rtl/inc/sockovl.inc
+++ b/rtl/inc/sockovl.inc
@@ -119,6 +119,79 @@ begin
   Bind:=(SocketError=0);
 end;
 
+
+
+Function DoAccept(Sock:longint;var addr:string):longint;
+var
+  UnixAddr : TUnixSockAddr;
+  AddrLen  : longint;
+begin
+  AddrLen:=length(addr)+3;
+  DoAccept:=Accept(Sock,UnixAddr,AddrLen);
+  Move(UnixAddr.Path,Addr[1],AddrLen);
+  SetLength(Addr,AddrLen);
+end;
+
+
+
+Function DoConnect(Sock:longint;const addr:string):Boolean;
+var
+  UnixAddr : TUnixSockAddr;
+  AddrLen  : longint;
+begin
+  Str2UnixSockAddr(addr,UnixAddr,AddrLen);
+  DoConnect:=Connect(Sock,UnixAddr,AddrLen);
+end;
+
+Function Accept(Sock:longint;var addr:string;var SockIn,SockOut:text):Boolean;
+var
+  s : longint;
+begin
+  S:=DoAccept(Sock,addr);
+  if S>0 then
+   begin
+     Sock2Text(S,SockIn,SockOut);
+     Accept:=true;
+   end
+  else
+   Accept:=false;
+end;
+
+
+
+Function Accept(Sock:longint;var addr:string;var SockIn,SockOut:File):Boolean;
+var
+  s : longint;
+begin
+  S:=DoAccept(Sock,addr);
+  if S>0 then
+   begin
+     Sock2File(S,SockIn,SockOut);
+     Accept:=true;
+   end
+  else
+   Accept:=false;
+end;
+
+
+
+Function Connect(Sock:longint;const addr:string;var SockIn,SockOut:text):Boolean;
+begin
+  Connect:=DoConnect(Sock,addr);
+  If Connect then
+     Sock2Text(Sock,SockIn,SockOut);
+end;
+
+
+
+Function Connect(Sock:longint;const addr:string;var SockIn,SockOut:file):Boolean;
+begin
+  Connect:=DoConnect(Sock,addr);
+  if Connect then
+     Sock2File(Sock,SockIn,SockOut);
+end;
+
+
 Function CloseSocket (Sock:Longint):Longint;
 begin
   if fpclose(Sock)=0 then
diff --git a/rtl/netware/nwsock.inc b/rtl/netware/nwsock.inc
index fe8f3b524e..8e2962af70 100644
--- a/rtl/netware/nwsock.inc
+++ b/rtl/netware/nwsock.inc
@@ -140,6 +140,79 @@ begin
   Bind:=(SocketError=0);
 end;
 
+
+
+Function DoAccept(Sock:longint;var addr:string):longint;
+var
+  UnixAddr : TUnixSockAddr;
+  AddrLen  : longint;
+begin
+  AddrLen:=length(addr)+3;
+  DoAccept:=Accept(Sock,UnixAddr,AddrLen);
+  Move(UnixAddr.Path,Addr[1],AddrLen);
+  SetLength(Addr,AddrLen);
+end;
+
+
+
+Function DoConnect(Sock:longint;const addr:string):Boolean;
+var
+  UnixAddr : TUnixSockAddr;
+  AddrLen  : longint;
+begin
+  Str2UnixSockAddr(addr,UnixAddr,AddrLen);
+  DoConnect:=Connect(Sock,UnixAddr,AddrLen);
+end;
+
+Function Accept(Sock:longint;var addr:string;var SockIn,SockOut:text):Boolean;
+var
+  s : longint;
+begin
+  S:=DoAccept(Sock,addr);
+  if S>0 then
+   begin
+     Sock2Text(S,SockIn,SockOut);
+     Accept:=true;
+   end
+  else
+   Accept:=false;
+end;
+
+
+
+Function Accept(Sock:longint;var addr:string;var SockIn,SockOut:File):Boolean;
+var
+  s : longint;
+begin
+  S:=DoAccept(Sock,addr);
+  if S>0 then
+   begin
+     Sock2File(S,SockIn,SockOut);
+     Accept:=true;
+   end
+  else
+   Accept:=false;
+end;
+
+
+
+Function Connect(Sock:longint;const addr:string;var SockIn,SockOut:text):Boolean;
+begin
+  Connect:=DoConnect(Sock,addr);
+  If Connect then
+     Sock2Text(Sock,SockIn,SockOut);
+end;
+
+
+
+Function Connect(Sock:longint;const addr:string;var SockIn,SockOut:file):Boolean;
+begin
+  Connect:=DoConnect(Sock,addr);
+  if Connect then
+     Sock2File(Sock,SockIn,SockOut);
+end;
+
+
 // fsread and fswrite are used in socket.inc
 procedure fdwrite (Handle:longint; VAR Data; Len : LONGINT);
 begin
diff --git a/rtl/openbsd/unixsock.inc b/rtl/openbsd/unixsock.inc
index ef54bf8e83..aead21ae2b 100644
--- a/rtl/openbsd/unixsock.inc
+++ b/rtl/openbsd/unixsock.inc
@@ -137,3 +137,75 @@ begin
   Bind:=(SocketError=0);
 end;
 
+
+
+Function DoAccept(Sock:longint;var addr:string):longint;
+var
+  UnixAddr : TUnixSockAddr;
+  AddrLen  : longint;
+begin
+  AddrLen:=length(addr)+3;
+  DoAccept:=Accept(Sock,UnixAddr,AddrLen);
+  Move(UnixAddr.Path,Addr[1],AddrLen);
+  SetLength(Addr,AddrLen);
+end;
+
+
+
+Function DoConnect(Sock:longint;const addr:string):Boolean;
+var
+  UnixAddr : TUnixSockAddr;
+  AddrLen  : longint;
+begin
+  Str2UnixSockAddr(addr,UnixAddr,AddrLen);
+  DoConnect:=Connect(Sock,UnixAddr,AddrLen);
+end;
+
+Function Accept(Sock:longint;var addr:string;var SockIn,SockOut:text):Boolean;
+var
+  s : longint;
+begin
+  S:=DoAccept(Sock,addr);
+  if S>0 then
+   begin
+     Sock2Text(S,SockIn,SockOut);
+     Accept:=true;
+   end
+  else
+   Accept:=false;
+end;
+
+
+
+Function Accept(Sock:longint;var addr:string;var SockIn,SockOut:File):Boolean;
+var
+  s : longint;
+begin
+  S:=DoAccept(Sock,addr);
+  if S>0 then
+   begin
+     Sock2File(S,SockIn,SockOut);
+     Accept:=true;
+   end
+  else
+   Accept:=false;
+end;
+
+
+
+Function Connect(Sock:longint;const addr:string;var SockIn,SockOut:text):Boolean;
+begin
+  Connect:=DoConnect(Sock,addr);
+  If Connect then
+     Sock2Text(Sock,SockIn,SockOut);
+end;
+
+
+
+Function Connect(Sock:longint;const addr:string;var SockIn,SockOut:file):Boolean;
+begin
+  Connect:=DoConnect(Sock,addr);
+  if Connect then
+     Sock2File(Sock,SockIn,SockOut);
+end;
+
diff --git a/rtl/unix/sockets.pp b/rtl/unix/sockets.pp
index 9c936e7d97..1a36f2696e 100644
--- a/rtl/unix/sockets.pp
+++ b/rtl/unix/sockets.pp
@@ -41,6 +41,10 @@ type
 { unix socket specific functions }
 Procedure Str2UnixSockAddr(const addr:string;var t:TUnixSockAddr;var len:longint);
 Function Bind(Sock:longint;const addr:string):boolean;
+Function Connect(Sock:longint;const addr:string;var SockIn,SockOut:text):Boolean;
+Function Connect(Sock:longint;const addr:string;var SockIn,SockOut:file):Boolean;
+Function Accept(Sock:longint;var addr:string;var SockIn,SockOut:text):Boolean;
+Function Accept(Sock:longint;var addr:string;var SockIn,SockOut:File):Boolean;
 
 //function  fpaccept      (s:cint; addrx : psockaddr; addrlen : psocklen):cint; maybelibc
 //function  fpbind      (s:cint; addrx : psockaddr; addrlen : tsocklen):cint;  maybelibc