<!--
  - Authors:
  -   Christian Schulte <schulte@ps.uni-sb.de>
  -
  - Contributors (sgml translation):
  -   Daniel Simon <dansim@ps.uni-sb.de>
  -   Andy Walter <anwalt@ps.uni-sb.de>
  -
  - Copyright:
  -   Christian Schulte, 1998
  -
  - Last change:
  -   $Date: 2002/01/10 16:23:02 $ by $Author: duchier $
  -   $Revision: 1.14.2.4 $
  -
  - This file is part of Mozart, an implementation
  - of Oz 3
  -    http://www.mozart-oz.org
  -
  - See the file "LICENSE" or
  -    http://www.mozart-oz.org/LICENSE.html
  - for information on usage and redistribution
  - of this file, and for a DISCLAIMER OF ALL
  - WARRANTIES.
  -
  -->

<chapter id="chapter.open">
    <Title/Files, Sockets, and Pipes: <<Open>>/

<p>
This chapter gives reference documentation for the <<Open>> module. The
module contains the following classes:
<list enum>
<item> <<Open.file>> for reading and writing files.
<item> <<Open.socket>> for Internet socket connections.
<item> <<Open.pipe>> for creation of operating system processes.
<item> <<Open.text>> for reading and writing text line by line and
character by character. It is a mixin class that can be combined with
any of the classes of the <<Open>> module.
</list>

<p>
A tutorial account on open programming can be found in <Ptr.extern
to="ozdoc:op">.

<section><title/Exceptions/
<p>
The methods of any of the <<Open>> module classes can raise three different
exceptions.
<p>
<para><title/operating system/When an operating system exception
occurs the Oz exception
<<<
system(os(?_{A} ?_{I} ?_{S}) debug:?_{X})
>>>
is raised, where:
<list enum>
<item> The atom ?_{A} gives the category of the error (&eg; <<os>> for
operating system or <<net>> for network layer).
<item> The integer ?_{I} gives an operating system dependent error
number.
<item> The string ?_{S} describes the exception by some text.
<item> The value ?_{X} might contain some additional debug information.
</list>

<para><title/already initialized/An exception of the format
<<<
system(open(alreadyInitialized ?_{O} ?_{M}) debug:?_{X})
>>>
is raised if an already initialized object ?_{O} is initialized again by
applying it to the message ?_{M}.

<para><title/already closed/An exception of the format
<<<
system(open(alreadyClosed ?_{O} ?_{M}) debug:?_{X})
>>>
is raised if a method other than <<close>> of an already closed object
?_{O} is applied. ?_{M} is as above the message the object has been
applied to.
</section>

<section id=section.file.obj><title/The Class <<Open.file>>/
<p>
<index class=module scope=section.file.obj/Open<AND>file/
The class <<Open.file>> has the following public methods.

<list>
<entry> <<init>> <synopsis>
<code display>
init(name: ?+{NameV}
     flags:?+{FlagsAs} &lt;= [read]
     mode: ?+{ModeR}   &lt;= mode(owner:[write] all:[read]))
init(url:  ?+{UrlV}
     flags:?+{FlagsAs} &lt;= [read]
     mode: ?+{ModeR}   &lt;= mode(owner:[write] all:[read]))
</code><item>
<index class=module/Open<AND>file<AND>init/
Initializes the file object and associates it with a Unix file.
<p><index/<code/stdin//<index/<code/stdout//<index/<code/stderr//
?_{NameV} is either a valid filename or one of the atoms <<stdin>>,
<<stdout>>, and <<stderr>>. In this case, the standard input, standard
output, or standard error stream is opened, respectively.  
<p>
In addition to using a filename to open a file also a url ?_{UrlV} can be
used. Only one of the features <<name>> or <<url>> is allowed.
<p>
The value of ?_{FlagsAs} must be a list, with its elements chosen from
the following atoms:
<p>
<<read>>,
<<write>>,
<<append>>,
<<create>>,
<<truncate>>,
<<exclude>>,
<<text>>,
<<binary>>
<p>
For reading a file, the atom <<read>> must be
included in ?_{FlagsAs}. Similarly, the atom <<write>> must be
included for writing. It is possible to include both atoms, giving both
read and write access to the file. For files attached to an url, only
reading access is possible.
<p>Atom <<text>> opens a file in text mode.  This is important on
platforms (&eg; Windows) where the line ends are represented on disk
by <samp/CRLF/ rather than just <samp/LF/.  On such platforms, when a
file is opened in text mode, the conversion from <samp/CRLF/ to
<samp/LF/ on reading (and in the reverse direction on writing) happens
automatically.  Atom <<binary>> opens a file in binary mode, where no
such translation happens.  On other platforms (&eg; Linux), these
flags have no effect.
<p>
When a file object is opened, the <def/seek pointer/<index/seek pointer/, 
pointing to the current position in the file, is initialized
to point to the start of the file. Any subsequent read or write takes
place at the position given by this pointer.
<p>
The remaining atoms make sense only if the file is opened for writing.
If the atom <<append>> is included, the seek pointer is moved to the end
of the file prior to each attempt to write to the file.
<p>
If the file to be opened already exists, the presence of the atom
<<create>> has no effect. Otherwise, the file is created.
Including <<truncate>> resets the length of an existing file
to zero and discards its previous content. 
<p>
An attempt to open an existing file fails, if <<exclude>> is
contained. Thus, this flag grants exclusive access of the file object
to the operating system file.  
<p>
If the file is opened for writing and the atom <<create>> is
included, the access rights are set as specified by ?_{ModeR}.
This must be a record with fields drawn from <<all>>,
<<owner>>, <<group>> and <<others>>. Its subterms must be lists of the
atoms <<read>>, <<write>> and <<execute>>. 
<p>
More detailed information can be found in <file/open(2)/,
<file/chmod(2)/, and <file/umask(2)/.

<entry> <<read>> <synopsis>
<code display>
read(list: ??{ListS}  
     tail: ?_{TailX}   &lt;= nil  
     size: ?+{SizeAI} &lt;= 1024  
     len:  ??{LenI}   &lt;= _) 
</code><item>
<index class=module/Open<AND>file<AND>read/
Reads data from a file.

?_{SizeAI} specifies how much data should be read from the file.  If
the field <<len>> is present, ?_{LenI} is bound to the number of bytes
actually read. ?_{LenI} may be less than ?_{SizeAI}. The atom <<all>>
is also a legal value for ?_{SizeAI}. In this case the entire file is
read.
<p>
The data read binds ?_{ListS} to a list of characters. The
tail of the list can be given by ?_{TailX}. The value for ?_{TailX}
defaults to <<nil>>, which means that in this case the list ?_{ListS} is
a string.
<p>
See also <file/read(2)/.

<entry> <<write>> <synopsis>
<code display>
write(vs:  ?+{V} 
      len: ??{I} &lt;= _)
</code><item>
<index class=module/Open<AND>file<AND>write/
Writes the virtual string ?_{V} to a file. 
<p>
See <file/write(2)/.

<entry> <<seek>> <synopsis>
<code display>
seek(whence: ?+{WhenceA} &lt;= set  
     offset: ?+{OffsetI} &lt;= 0)
</code><item>
<index class=module/Open<AND>file<AND>seek/
Sets the file object's seek pointer
<p>
Allowed values for ?_{WhenceA} are the atoms <<set>>, <<current>>, or
<<'end'>>.
<p>
In case of <<set>> the position of the seek pointer is moved
to the absolute position from the beginning of the file given by the
value of ?_{OffsetI}. 
<p>
In case of <<current>> the pointer is moved ahead by ?_{OffsetI}.
Notice, that the pointer can be moved backward by a negative
?_{OffsetI}, and forward by a positive ?_{OffsetI}.
<p>
If <<'end'>> is given, the pointer is moved by ?_{OffsetI} with
respect to the current end of the file. 
<p>
In particular,  invoking <<seek>> with the default parameters moves
the pointer to the beginning of the file.
<p>
See <file/lseek(2)/.

<entry> <<tell>> <synopsis>
<code display>
tell(offset: ??{OffsetI})
</code><item>
<index class=module/Open<AND>file<AND>tell/ 
Returns the current position of the seek pointer
counting from the beginning of the file.
<p>
See <file/lseek(2)/.

<entry> <<close>> <synopsis>
<code display>
close
</code><item>
<index class=module/Open<AND>file<AND>close/
Closes the file object as well as the file.
<p>
See <file/close(2)/.

<entry> <<dOpen>> <synopsis>
<code display>
dOpen(?+{ReadFileDescI} ?+{WriteFileDescI})
</code><item>
<index class=module/Open<AND>file<AND>dOpen /
<p class=danger>
Initializes the object. ?_{ReadFileDescI} and ?_{WriteFileDescI} must
be integers of already open file descriptors (in the usual operating
system sense).
Note that this method should only be used for advanced purposes.

<entry> <<getDesc>> <synopsis>
<code display>
getDesc(??{ReadFileDescIB} ??{WriteFileDescIB})
</code><item>
<index class=module/Open<AND>file<AND>getDesc /
<p class=danger>
Returns the internally used file descriptors.
<p>
If the object is not yet initialized, ?_{ReadFileDescIB} and
?_{WriteFileDescIB} are bound to <<false>>, otherwise to the respective
integers.
Note, that this method is only for advanced purposes.
</list>
</section>

<section id=sec-socket-obj><title/The Class <<Open.socket>>/
<p>
The class <<Open.socket>> has the following public methods.
<index class=module scope=sec-socket-obj/Open<AND>socket/

<list>
<entry> <<init>> <synopsis>
<code display>
init(type:     ?+{TypeA}  &lt;= stream
     protocol: ?+{ProtoV} &lt;= ""
     time:     ?+{TimeI}  &lt;= ~1)                
</code><item>
<index class=module/Open<AND>socket<AND>init/

Initializes a socket object.
<p>
The type of the socket ?_{TypeA} determines the type of the socket,
which can be either <<stream>> or <<datagram>>.
<p>
The protocol is described by ?_{ProtoV} where the empty string <<"">>
means to choose an appropriate protocol automatically. Other possible
values are the TCP protocol <index/protocol<AND>TCP/ (you have to give
<<"tcp">>) for stream sockets, and UDP <index/protocol<AND>UDP/ (you have to
give <<"udp">>) for datagram sockets.
<p>
The integer ?_{TimeI} specifys for how long a time (in milliseconds)
the socket attempts to accept a connection.  The value <<~1>> means
infinite time. See the following description of the <<accept>> method for
more details.
<p>
See also <file/socket(2)/.

<entry> <<bind>> <synopsis>
<code display>
bind(takePort: ?+{TakePortI} &lt;= _  
     port:     ??{PortI}     &lt;= _)
</code><item>
<index class=module/Open<AND>socket<AND>bind /
Names a socket globally.
<p>
If the field <<takePort>> is present, its value is chosen for
binding. Otherwise, a fresh port number value is generated by the
object. This port number is accessible at the field <<port>>.
<p>
See also <file/bind(2)/.

<entry> <<listen>> <synopsis>
<code display>
listen(backLog: ?+{LogI} &lt;= 5)
</code><item>
<index class=module/Open<AND>socket<AND>listen /
Signals that a socket is willing to accept connections.
<p>
?_{LogI} describes the maximum number of pending connections to be
buffered by the system.
<p>
See also <file/listen(2)/.

<entry> <<accept>> <synopsis>
<code display>
accept(accepted:    ??{Object}  &lt;= _
       acceptClass: ?+{Class}    &lt;= _  
       host:        ??{HostSB}   &lt;= _  
       port:        ??{PortIB}   &lt;= _)  
</code><item>
<index class=module/Open<AND>socket<AND>accept /
Accepts a connection from another socket.
<p>
The method suspends until a connection has been accepted or the number
of milliseconds as specified by the time value in the <<init>> method has
elapsed. After this period, no connection will be accepted, and both
?_{PortIB} and ?_{HostSB} are bound to <<false>>.
<p>
If a connection is accepted within the given time, the following
happens: ?_{HostSB} and ?_{PortIB} are bound accordingly if their
fields are present.
<p>
If the fields <<accepted>> and <<acceptClass>> are present, ?_{Object}
is bound to an object created from the class ?_{Class}. ?_{Class} must
be a sub class of <<Open.socket>>. Then the accepted connection is
available with ?_{Object}.
<p>
Otherwise, the access to the socket at which the connection was
accepted, because any subsequent message will refer to the accepted
socket connection.
<p>
See also <file/accept(2)/.

<entry> <<connect>> <synopsis>
<code display>
connect(host: ?+{HostV} &lt;= localhost
        port: ?+{PortI})
</code><item>
<index class=module/Open<AND>socket<AND>connect /
Connects to another socket.
<p>
The address of the socket to connect to is given by ?_{HostV} and
?_{PortI}.
<p>
<p class=danger>
Be very careful in using this method: it blocks the
entire Oz system until it succeeds.
<p>
See <file/connect(2)/.

<entry> <<server>> <synopsis>
<code display>
server(port: ??{PortI}  
       host: ??{HostV} &lt;= localhost)
</code><item>
<index class=module/Open<AND>socket<AND>server /
Initializes a stream socket as a server.

<entry> <<client>> <synopsis>
<code display>
client(port: ?+{PortI}  
       host: ?+{HostV} &lt;= localhost)
</code><item>
<index class=module/Open<AND>socket<AND>client/
Initializes a stream socket as a client.

<entry> <<read>> <synopsis>
<code display>
read(list: ??{ListS}  
     tail: ?_{TailX}  &lt;= nil  
     size: ?+{SizeAI} &lt;= 1024  
     len:  ??{LenI}  &lt;= _)
</code><item>
<index class=module/ Open<AND>socket<AND>read /
Receives data from a stream-connected socket or
from a datagram socket with peer specified.
<p>
An attempt is made to read ?_{SizeAI} bytes from the socket.
?_{ListS} is constrained to the data while the tail of ?_{ListS}
is constrained to ?_{TailX}.
The atom <<all>>
is also a legal value for ?_{SizeAI}. In this case the entire input is
read.
<p>
?_{LenI} is bound to the number of bytes actually read. If the
socket is of type stream and the other end of the connection has been
closed ?_{LenI} is bound to <<0>>.
<p>
See also <file/read(2)/.

<entry> <<receive>> <synopsis>
<code display>
receive(list: ??{ListS}  
        tail: ?_{TailX}  &lt;= nil  
        len:  ??{LenI}  &lt;= _ 
        size: ?+{SizeI} &lt;= 1024 
        host: ??{HostS} &lt;= _  
        port: ??{PortI} &lt;= _)
</code><item>
<index class=module/Open<AND>socket<AND>receive /
Receives data from a socket.
<p>
An attempt is made to read ?_{SizeI} bytes from the socket. 
?_{ListS} is bound to the data while the tail of the list is
bound to ?_{TailX}.
<p>
?_{LenI} is bound to the number of bytes actually read. If the
socket is of type stream and the other end of the connection has been
closed ?_{LenI} is bound to <<0>>.
<p>
The source of the data is signaled by binding ?_{HostS} and
?_{PortI}.
<p>
See also <file/recvfrom(2)/.

<entry> <<write>> <synopsis>
<code display>
write(vs:  ?+{V}
      len: ??{I} &lt;= _)
</code><item>
<index class=module/Open<AND>socket<AND>write/
Writes the virtual string ?_{V} to a stream-connected
socket or to a datagram socket with peer specified.
<p>
?_{I} is bound to the number of characters written.
<p>
See also <file/write(2)/.

<entry> <<send>> <synopsis>
<code display>
send(vs:  ?+{V}
     len: ??{I} &lt;= _)
send(vs:   ?+{V}
     len:  ??{I}     &lt;= _
     port: ?+{PortI}  
     host: ?+{HostV} &lt;= localhost)
</code><item>
<index class=module/Open<AND>socket<AND>send/
Sends data as specified by ?_{V} to a socket.
<p>
The destination of the data may be given by ?_{HostV} and
?_{PortI}. If they are omitted, the data is sent to the peer of a
datagram socket or to the other end of a connection in case of a stream
socket. ?_{I} is bound to the number of characters written.
<p>
See also <file/send(2)/.

<entry> <<shutDown>> <synopsis>
<code display>
shutDown(how: ?+{HowAs} &lt;= [receive send])
</code><item>
<index class=module/Open<AND>socket<AND>shutDown /
Disallows further actions on the socket.
<p>
?_{HowAs} has to be a non-empty list which must contain only the atoms
<<receive>> and <<send>>. The atom <<send>> signals that no
further data transmission is allowed, while <<receive>> signals
that no further data reception is allowed.
<p>
See also <file/shutdown(2)/. 

<entry> <<close>> <synopsis>
<code display>
close
</code><item>
<index class=module/Open<AND>socket<AND>close /
Closes the socket.
<p>
See also <file/close(2)/

<entry> <<flush>> <synopsis>
<code display>
flush(how: ?+{HowAs} &lt;= [receive send])
</code><item>
<index class=module/Open<AND>socket<AND>flush/
Blocks until all requests for reading, receiving,
writing, and sending have been fulfilled.
<p>
?_{HowAs} must be a non-empty list which may include the atoms
<<receive>> and <<send>>. The atom <<send>> signals that the method should
block until all send (or write) requests are fulfilled,
while <<receive>> signals the same for receive (or read).

<entry> <<dOpen>> <synopsis>
<code display>
dOpen(?+{ReadFileDescI} ?+{WriteFileDescI})
</code><item>
<index class=module/Open<AND>socket<AND>dOpen /
<p class=danger>
Initializes the object. ?_{ReadFileDescI} and ?_{WriteFileDescI} must
be integers of already open file descriptors (in the usual operating
system sense).
<p>
Note that this method should only be used for advanced purposes.

<entry> <<getDesc>> <synopsis>
<code display>
getDesc(??{ReadFileDescIB} ??{WriteFileDescIB})
</code><item>
<index class=module/Open<AND>socket<AND>getDesc /
<p class=danger>
Returns the internally used file descriptors.
<p>
If the object is not yet initialized, ?_{ReadFileDescIB} and
?_{WriteFileDescIB} are bound to <<false>>, otherwise to the respective
integers.
<p>
Note, that this method is only for advanced purposes.
</list>
</section>

<Section id=open.pipe><title/The Class <<Open.pipe>>/
<p>
<index scope=open.pipe/Open<and>pipe/
The class <<Open.pipe>> has the following public methods.

<list>
<entry> <<init>> <synopsis>
<code display>
init(cmd:  ?+{CmdV}  
     args: ?+{ArgsVs} &lt;= nil  
     pid:  ??{PidI}   &lt;= _)
</code><item>
<index class=module/Open<AND>pipe<AND>init /
Initilizes the object and forks a process with process identification
?_{PidI} executing the command ?_{CmdV} with arguments ?_{ArgsVs}. 
<p>
The environment of the forked process is inherited from the process
which runs the Oz Emulator. The standard input of
the forked process is connected to sending and writing data, the
standard output and standard error to reading and receiving data. 
<p>
See also <file/execv(3)/, <file/fork(2)/.

<entry> <<read>> <synopsis>
<code display>
read(list: ??{ListS}  
     tail: ?_{TailX}  &lt;= nil  
     size: ?+{SizeAI} &lt;= 1024  
     len:  ??{LenI}  &lt;= _)
</code><item>
<index class=module/Open<AND>pipe<AND>read /
Reads data ?{ListS} from the standard output or standard error of
the forked process.
<p>
An attempt is made to read ?_{SizeI} bytes. ?_{ListS} is bound to
the data read while the tail of ?_{ListS} is bound to ?_{TailX}.
The atom <<all>>
is also a legal value for ?_{SizeAI}. In this case the entire input is
read.
<p>
?_{LenI} is bound to the number of bytes actually read. If the
socket is of type stream and the other end of the connection has been
closed ?_{LenI} is bound to <<0>>.
<p>
See also <file/read(2)/.

<entry> <<write>> <synopsis>
<code display>
write(vs:  ?+{V}
      len: ??{I} &lt;= _)
</code><item>
<index class=module/Open<AND>pipe<AND>write /
Writes the virtual string ?_{V} to the standard input of the forked
process.
<p>
?_{I} is bound to the number of characters written.
<p>
See also <file/write(2)/.

<entry> <<flush>> <synopsis>
<code display>
flush(how: ?+{HowAs} &lt;= [receive send])
</code><item>
<index class=module/Open<AND>pipe<AND>flush /
Blocks until all requests for reading and writing have been performed.
<p>
?_{HowAs} must be a non-empty list which may include the atoms
<<receive>> and <<send>>. The atom <<send>> signals that the method should
block until all write requests are fulfilled,
while <<receive>> signals the same for read.

<entry> <<close>> <synopsis>
<code display>
close(?+{KillB}<=false)
</code><item>
<index class=module/Open<AND>pipe<AND>close /

Closes the object. 

<p>
If ?_{KillB} is <<false>> (the default) the method blocks until all 
pending read and 
write requests have been executed. If the started process is still
running, it is killed by sending the
<file/SIGTERM/<index/<file/SIGTERM// signal. However, note that the
inverse direction is not supported, which means the object is not
automatically closed if the process terminates.

<p> If ?_{KillB} is <<true>> the possibly running process is
immediately terminated by sending the
<file/SIGKILL/<index/<file/SIGKILL// signal.

<p>
See also <file/wait(2)/ and <file/kill(1)/.

<entry> <<dOpen>> <synopsis>
<code display>
dOpen(?+{ReadFileDescI} ?+{WriteFileDescI})
</code><item>
<index class=module/Open<AND>pipe<AND>dOpen /
<p class=danger>
Initializes the object. ?_{ReadFileDescI} and ?_{WriteFileDescI} must
be integers of already open file descriptors (in the usual operating
system sense).
<p>
Note that this method should only be used for advanced purposes.

<entry> <<getDesc>> <synopsis>
<code display>
getDesc(??{ReadFileDescIB} ??{WriteFileDescIB})
</code><item>
<index class=module/Open<AND>pipe<AND>getDesc /
<p class=danger>
Returns the internally used file descriptors.
<p>
If the object is not yet initialized, ?_{ReadFileDescIB} and
?_{WriteFileDescIB} are bound to <<false>>, otherwise to the respective
integers.
<p>
Note that this method is only for advanced purposes.
</list>
</section>

<section id=sec-text-obj><title/The Class <<Open.text>>/
<p>
The mixin class <<Open.text>> has the methods listed below.  Note,
however, that it does not automatically cause a file to be opened in
<code/text/ mode; that must be done explicitly in the <code/init/
method by supplying <code/text/ as one of the flags.
<index scope=sec-text-obj/Open<AND>text/

<list>
<entry> <<getC>> <synopsis>
<code display>
getC(??{I})
</code><item>
<index class=module/Open<AND>text<AND>getC /

Returns the next character, or <<false>> if the input is
at the end.
<p>
Note that if an object is created that inherits from both
<<Open.text>> and <<Open.file>>, the methods <<read>> and <<seek>> from the
classes <<Open.file>>, <<Open.socket>>, and
<<Open.pipe>> and do not work together with this method.

<entry> <<putC>> <synopsis>
<code display>
putC(?+{I})
</code><item>
<index class=module/Open<AND>text<AND>putC /

Writes the character ?_{I}.

<entry> <<unGetC>> <synopsis>
<code display>
unGetC
</code><item>
<index class=module/Open<AND>text<AND>unGetC /

The last character read is written back to the input buffer and may be
used again by <<getC>>. It is allowed only to unget one character.

<entry> <<getS>> <synopsis>
<code display>
getS(??{SB})
</code><item>
<index class=module/Open<AND>text<AND>getS /

Returns the next line of the input as string, or
<<false>> if the input is at the end. ?_{SB} does not contain the newline character. 
<p>
Note that if an object is created that inherits from both
<<Open.text>> and <<Open.file>>, the methods <<read>> and <<seek>> from the
class <<Open.file>>, <<Open.socket>>, and
<<Open.pipe>>  do not work together with this method.

<entry> <<putS>> <synopsis>
<code display>
putS(?+{V})
</code><item>
<index class=module/Open<AND>text<AND>putS /

Writes the virtual string ?_{V}. Note that a newline character is
appended.

<entry> <<atEnd>> <synopsis>
<code display>
atEnd(??{B})
</code><item>
<index class=module/Open<AND>text<AND>atEnd /

Tests whether the end of input is reached.

<entry> <<dOpen>> <synopsis>
<code display>
dOpen(?+{ReadFileDescI} ?+{WriteFileDescI})
</code><item>
<index class=module/Open<AND>text<AND>dOpen /

<p class=danger>
Initializes the object. ?_{ReadFileDescI} and ?_{WriteFileDescI} must
be integers of already open file descriptors (in the usual operating
system sense).
<p>
Note that this method should only be used for advanced purposes.

<entry> <<getDesc>> <synopsis>
<code display>
getDesc(??{ReadFileDescIB} ??{WriteFileDescIB})
</code><item>
<index class=module/Open<AND>text<AND>getDesc /

<p class=danger>
Returns the internally used file descriptors.
<p>
If the object is not yet initialized, ?_{ReadFileDescIB} and
?_{WriteFileDescIB} are bound to <<false>>, otherwise to the respective
integers.
<p>
Note that this method is only for advanced purposes.
</list>
</section>
</chapter>





