<!--
  - 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: 2001-05-03 19:14:49 +0200 (Thu, 03 May 2001) $ by $Author: popow $
  -   $Revision: 13785 $
  -
  - 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.os">
    <Title/Operating System Support: <<OS>>/
<p>
This chapter describes the procedures contained in the module <<OS>>

<section>
<title/Conventions/
<p>
Most procedures can be seen as straightforward lifting of POSIX
compatible operating system functions to Oz.  Hence, our description
consists mainly of a reference to the relevant Unix manual page. If
you are running on a Windows based platform you should consult a POSIX
documentation (&eg; <Ptr to="Lewine.91">).
<p>
A major convention is that most <code proglang=C/int/ arguments in C are integers
in Oz. Moreover <code proglang=c/char*/ arguments are virtual strings, if they are
used as input in C. If they are used as output in C they are
strings. An <math.choice><math latex/n/<math html/n/</math.choice>-ary C-function returning a value is implemented as a
<math.choice><math latex/n+1/<math html/n+1/</math.choice>-ary Oz procedure where the last argument serves as output
position.
<p>
Whenever one needs predefined POSIX constants, they can be used as Oz
atoms. Wherever bitwise disjunction of predefined constants is used in
C, a list of atoms (the constant names) is allowed, which is
interpreted as bitwise disjunction of their respective values.
<p>
The functionality of the module <<OS>> can be classified as procedures
which are useful in applications, or procedures needed for building
high level functionality. The latter are only interesting for
programmers who want to build abstractions similar to those provided
by the <<Open>> module.
</section>

<section>
<title/Exceptions/
<p>
If the operating system returns an error, an Oz Exception is
raised which looks as follows:
<<<system(os(?_{A} ?_{S1} ?_{I} ?_{S2}) debug:?_{X})>>>
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 string ?_{S1} describes the operating system routine that raised the exception.
<item> The integer ?_{I} gives an operating system dependent error
number.
<item> The string ?_{S2} describes the exception by some text.
<item> The value ?_{X} might contain some additional debug information.
</list>
</section>

<section>
<title/Random Integers/
<p>
<List>
<Entry> <<rand>> 
<Index class=module/OS<and>rand/
<Synopsis>
<<{OS.rand ??{I}}>>
<Item>
Returns a randomly generated integer.
<p>
See <file /rand(3)/.


<Entry> <<srand>> 
<Index class=module/OS<and>srand/

<Synopsis>
<<{OS.srand ?+{I}}>>
<Item>
Sets the seed for the random number generator used by <<OS.rand>>. If
?_{I} is <<0>>, the seed will be generated from the current time.
<p>
See <file /srand(3)/.


<Entry> <<randLimits>> <Synopsis>
<<{OS.randLimits ??{MinI} ??{MaxI}}>>
<item>
<Index class=module/OS<and>randLimits/
Binds ?_{MinI} and ?_{MaxI} to the smallest and greatest possible
random number obtainable by <<OS.rand>>.
<p>
See <file /rand(3)/.
</list>
</section>

<section>
<title/Files/
<p>
<list>
<Entry> <<tmpnam>> <Synopsis>
<<{OS.tmpnam ??{FileNameS}}>>
<item>
<Index class=module/OS<and>tmpnam/
Returns a freshly created full pathname.
<p>
See <file /tmpnam(2)/.


<Entry> <<unlink>> <Synopsis>
<<{OS.unlink ?+{PathV}}>>
<Index class=module/OS<and>unlink/
<item>
Removes the file with name ?_{PathV}.
<p>
See <file /link(2)/.
</list>
</section>


<section>
<title/Directories/
<p>
<list>

<Entry> <<getDir>> <Synopsis>
<<{OS.getDir ?+{PathV} ??{FileNameSs}}>>
<Index class=module/OS<and>getDir/
<item>
Returns a list of strings giving the files in
the directory ?_{PathV}.
<p>
See <file /opendir(3)/ and <file /readdir(3)/.

<Entry> <<getCWD>> <Synopsis>
<<{OS.getCWD ??{FileNameS}}>>
<Index class=module/OS<and>getCWD/
<item>
Returns in ?_{FileNameS} the path of the current working directory.
<p>
See <file /getcwd(3)/.

<Entry> <<stat>> <Synopsis>
<<{OS.stat ?+{PathV} ??{StatR}}>>
<Index class=module/OS<and>stat/
<item>
Returns a record describing the status of the file ?_{PathV}.
<p>
?_{StatR} has features <<size>>, <<type>>, and <<mtime>>. The
subtree at the feature <<size>> is an integer that gives the size of
the file ?_{PathV}. The subtree at the feature <<type>> is one of the
following atoms: <<reg>> (regular file), <<dir>> (directory), <<chr>>
(character special file), <<blk>> (block special file), <<fifo>> (pipe
or FIFO special file), <<unknown>> (something else).  <<mtime>> is the
time of last modification measured in seconds since the dawn of the
world, which, as we all know, was January 1, 1970.
<p>
See <file /stat(2)/.

<Entry> <<chDir>> <Synopsis>
<<{OS.chDir ?+{PathV}}>>
<Index class=module/OS<and>chDir/
<item>
Changes the current working directory to ?_{PathV}.
<p>
See <file /chdir(2)/.

<Entry> <<mkDir>> <Synopsis>
<<{OS.mkDir ?+{PathV} ?+{ModeAs}}>>
<Index class=module/OS<and>mkDir/
<item>
Creates a directory ?_{PathV}. Access modes are specified by
?_{ModeAs}, similar to <<OS.open>>.
<p>
See <file /mkdir(2)/.

</list>
</section>

<section id="sec-opprog-os-file">
<title/Sockets/
<p>
<list>
<Entry> <<getServByName>> <Synopsis>
<<{OS.getServByName ?+{NameV} ?+{ProtoV} ??{PortIB}}>>
<Index class=module/OS<and>getServByName/
<item>
Returns the port number ?_{PortI} of a service ?_{NameV} reachable in
the Internet domain with the specified protocol ?_{ProtoV}. 
<p>
If the service is unknown, <<false>> is returned.
<p>
As an example, the application
<<<
{OS.getServByName "finger" "tcp" Port}
>>>
binds <<Port>> to the number, where you can connect to your
local finger server.
<p>
See <file /getservbyname(3)/.


<Entry> <<getHostByName>> <Synopsis>
<<{OS.getHostByName ?+{NameV} ??{HostentR}}>>
<Index class=module/OS<and>getHostByName/
<item>
Returns name information for the host ?_{NameV}.
<p>
The record ?{HostentR} has the following features: 
<table class=dyptic>
<tr/<td/
<<name>>     /<td/ official host-name /<td/ string// <tr/ <td/
<<aliases>>  /<td/ alternative host-names /<td/ list of strings // <tr/ <td/
<<addrList>> /<td/ Internet addresses     /<td/ list of strings //
</table>
<p>
See <file /gethostbyname(3)/.
</list>
</section>


<section>
<title/Time/
<p>
<list>
<Entry> <<time>> <Synopsis>
<<{OS.time ??{TimeI}}>>
<Index class=module/OS<and>time/
<item>
Returns the time since 00:00:00 GMT,  Jan.  1,  1970 in seconds.
<p>
See <file /time(2)/.


<Entry> <<gmTime>> <Synopsis>
<<{OS.gmTime ??{GmTimeR}}>>
<Entry> <<localTime>> <Synopsis>
<<{OS.localTime ??{LocalTimeR}}>>
<Index class=module/OS<and>gmTime/

<Index class=module/OS<and>localTime/
<item>
Returns a description of the Coordinated Universal
Time (UTC), respectively a description of the local
time.
<p>
The records ?_{GmTimeR} and ?_{LocalTimeR} have the following
features, where the fields are all integers:
<table class=dyptic>
<tr/<td/
<<sec>>   /<td/ seconds           /<td/ 0&emdash; 61  //<tr/ <td/
<<min>>   /<td/ minutes           /<td/ 0&emdash; 59  //<tr/ <td/
<<hour>>  /<td/ hours             /<td/ 0&emdash; 23  //<tr/ <td/
<<mDay>>  /<td/ day of month      /<td/ 1&emdash; 31  //<tr/ <td/
<<mon>>   /<td/ month of year     /<td/ 0&emdash; 11  //<tr/ <td/
<<year>>  /<td/ years since 1900  /<td/<p.silent>//<tr/ <td/
<<wDay>>  /<td/ days since Sunday /<td/ 0&emdash; 6   //<tr/ <td/
<<yDay>>  /<td/ day of year       /<td/ 0&emdash; 365 //<tr/ <td/
<<isDst>> /<td/ 1 if daylight savings time in effect (DST) /<td/<p.silent>//
</table>
<p>
See <file /gmtime(3)/, <file /localtime(3)/, and <file /time(2)/.
</list>
</section>


<section>
<title/Environment Variables/
<p>
<list>
<Entry> <<getEnv>> <Synopsis>
<<{OS.getEnv ?+{NameV} ??{ValueSB}}>>
<Index class=module/OS<and>getEnv/
<item>
Returns the value of the environment variable
?_{NameV}.
<p>
If a variable with the given name does not exist, the
procedure returns <<false>>.
<p>
As an example, consider:
<<<
{OS.getEnv 'OZHOME'}
>>>
returns where the Oz system has been installed. This
information is also available via <<{System.get home}>>
<Index /System <and> get/ <!--** See <Ptr to="oz.doc.system">). -->
<p>
See <file /getenv(3)/. 



<Entry> <<putEnv>> <Synopsis>
<<{OS.putEnv ?+{NameV} ?+{ValueV}}>>
<Index class=module/OS<and>putEnv/
<item>
Sets the value of the environment variable ?_{NameV} to ?_{ValueV}.
<p>
See <file /putenv(3)/. 
</list>
</section>

<section id="OS-use-misc">
<title/Miscellaneous/
<p>
<list>
<Entry> <<uName>> <Synopsis>
<<{OS.uName ??{UtsnameR}}>>
<Index class=module/OS<and>uName/
<item>
Returns system information.
<p>
The record ?_{UtsnameR} has at least the following features, where all
fields are strings:
<table class=dyptic>
<tr/<td/
<<sysname>>    /<td/ operating system name //<tr/ <td/
<<nodename>>   /<td/ computer name//<tr/ <td/
<<release>>    /<td/ operating system release//<tr/ <td/
<<version>>    /<td/ operating system version//<tr/ <td/
<<machine>>    /<td/ machine architecture //
</table>
<p>
See <file /uname(2)/.

<Entry> <<system>> <Synopsis>
<<{OS.system ?+{CmdV} ??{StatusI}}>>
<Index class=module/OS<and>system/
<item>
Starts a new operating system shell in which the OS command ?_{CmdV}
is executed. The status of the command is reported by ?_{StatusI}.
<p>
See <file /system(3)/.
</list>
</section>


<section>
<title/Low Level Procedures/
<p>
<subsection>
<title/Basic Input and Output/
<p>
<list>
<Entry> <<open>> <Synopsis>
<<{OS.open ?+{FileNameV} ?+{FlagsAs} ?+{ModeAs} ??{DescI}}>>
<Index class=module/OS<and>open/
<item>
Opens a file for reading and/or writing. 
<p>
?_{FlagsAs} must be a list with some of the following atoms as
elements:
<table class=dyptic> <tr/<td/
<<'O_RDONLY'>> /<td/ <<'O_WRONLY'>> /<td/ <<'O_RDWR'>>      //<tr/ <td/ 
<<'O_APPEND'>> /<td/ <<'O_CREAT'>>  /<td/ <<'O_EXCL'>>      //<tr/ <td/
<<'O_TRUNC'>>  /<td/ <<'O_NOCCTY'>> /<td/  <<'O_NONBLOCK'>> //<tr/ <td/
<<'O_SYNC'>> /<td/<p.silent>/<td/<p.silent>//
</table>
Their meanings coincide with their usual POSIX meanings.
<p>
In the same manner ?_{ModeAs} must be a list with elements drawn from:
<table class=dyptic> <tr/<td/
<<'S_IRUSR'>> /<td/ <<'S_IWUSR'>> /<td/ <<'S_IXUSR'>> //<tr/ <td/
<<'S_IRGRP'>> /<td/ <<'S_IWGRP'>> /<td/ <<'S_IXGRP'>> //<tr/ <td/
<<'S_IROTH'>> /<td/ <<'S_IWOTH'>> /<td/ <<'S_IXOTH'>> //
</table>
<p>
See <file /open(2)/ and <file /chmod(2)/.

<Entry> <<fileDesc>> <Synopsis>
<<{OS.fileDesc ?+{FileDescA} ??{FileDescIB}}>>
<Index class=module/OS<and>fileDesc/
<item>
Maps the atoms 
<table class=dyptic> <tr/<td/
<<'STDIN_FILENO'>> //<tr/<td/ 
<<'STDOUT_FILENO'>>//<tr/ <td/
<<'STDERR_FILENO'>> //
</table>
to integers, giving their respective file
descriptor. Note that these descriptors will be duplicated.
<p>
See <file /open(2)/ and <file /dup(2)/.

<Entry> <<read>> <Synopsis>
<<{OS.read ?+{DescI} ?+{MaxI} ??{ListS} ?_{TailX} ??{ReadI}}>>
<Index class=module/OS<and>read/
<item>
Reads data from a file or socket.  Yields a list of characters in
?_{ListS}, where the tail of the list is constrained to
?_{TailX}.
<p>

Implements the <file /read(2)/ system call.


<Entry> <<write>> <Synopsis>
<<{OS.write ?+{DescI} ?+{V} ??{StatusTI}}>>
<Index class=module/OS<and>write/
<item>
Writes the virtual string ?_{V} to a file or a socket by using the
function <file /write(2)/.
<p>
Illegal parts of the virtual string ?_{V} are simply ignored,
and the legal parts are written. 
<p>
If ?_{V} contains
an undetermined variable, ?_{StatusTI} is bound to a ternary
tuple with label <<suspend>>. The first argument is an
integer describing the portion already written, the second the
undetermined variable, and the last to the not yet written part of ?_{V}.
<p>
Otherwise ?_{StatusTI} is bound to the number of characters written.

<Entry> <<lSeek>> <Synopsis>
<<{OS.lSeek ?+{DescI} ?+{WhenceA} ?+{OffsetI} ??{WhereI}}>>
<Index class=module/OS<and>lSeek/
<item>
Positions the seek pointer of a file. 
This procedure is implemented by
the <file /lseek(2)/ function. ?_{WhenceA} must be one of the atoms
<<'SEEK_SET'>>, <<'SEEK_CUR'>>, and <<'SEEK_END'>>.

<Entry> <<close>> <Synopsis>
<<{OS.close ?+{DescI}}>>
<Index class=module/OS<and>close/
<item>
Closes a file or socket by using the <file /close(2)/ function.
</list>
</subsection>

<subsection id="sec-opprog-select">
<title/From Blocking to Suspension/
<p>
<P class=danger>
If reading from a file or a socket via an operating system function,
it is possible that no information is available for
reading. Furthermore, an attempt to write something to a file or to a
socket might not be possible at a certain point in time. In this case
the OS function blocks, &ie; the whole Oz Emulator process will stop
doing any work.
<p>
To overcome this problem, we provide three procedures.
These procedures will suspend rather than block.
<p>
<list>
<Entry> <<acceptSelect>> <Synopsis> <<{OS.acceptSelect ?+{DescI}}>>
<Entry> <<readSelect>> <synopsis><<{OS.readSelect ?+{DescI}}>>
<Entry> <<writeSelect>><synopsis><<{OS.writeSelect ?+{DescI}}>>
<Index class=module/OS<and>readSelect/
<Index class=module/OS<and>acceptSelect/
<Index class=module/OS<and>writeSelect/
<item>
Blocks until a socket connection can be accepted (data is present to
be read, and writing of data is possible, respectively) at the file or
socket with descriptor ?_{DescI}
<p>
For example the following case statement (we assume that
<<Desc>> is bound to a descriptor of a socket):
<<<
{OS.readSelect Desc}
case {OS.read Desc 1024 ?S nil}
of &ellipsis; then
&ellipsis;
end
>>>  
blocks the current thread until data for reading is available. 
<p>
This functionality is implemented by the <file /select(2)/ system
call.
<p>
Before actually closing a file descriptor, the following procedure
needs to be called.

<Entry> <<deSelect>> <Synopsis>
<<{OS.deSelect ?+{DescI}}>>
<Index class=module/OS<and>deSelect/
<item>
Discards all threads depending on the file descriptor ?_{DescI}.
</list>
</subsection>

<subsection>
<title/Sockets/
<p>
<list>
<Entry> <<socket>> 
<Synopsis>
<<{OS.socket ?+{DomainA} ?+{TypeA} ?+{ProtoV} ??{DescI}}>>
<Index class=module/OS<and>socket/
<Item>
Creates a socket. Is implemented by the function
<file /socket(2)/. 
<p>
?_{DomainA} must be either the atom <<'PF_INET'>> or <<'PF_UNIX'>>, whereas
?_{TypeA} must be either <<'SOCK_STREAM'>>, or <<'SOCK_DGRAM'>>. 
<p>
?_{ProtoV} must be a virtual string. If it denotes the empty string, an
appropriate protocol is chosen automatically, otherwise it must denote
a valid protocol name like <<"tcp">> or <<"udp">>.

<Entry> <<bind>> <Synopsis>
<<{OS.bind ?+{SockI} ?+{PortI}}>>
<Index class=module/OS<and>bind/
<item>
Binds a socket to its global name.
<p>
See <file /bind(2)/.

<Entry> <<listen>> <Synopsis>
<<{OS.listen ?+{SockI} ?+{BackLogI}}>>
<Index class=module/OS<and>listen/
<item>
Indicates that a socket is willing to receive connections. 
<p>
See <file /listen(2)/.

<Entry> <<accept>> <Synopsis>
<<{OS.accept ?+{SockI} ??{HostS} ??{PortI} ??{DescI}}>>
<Index class=module/OS<and>accept/
<item>
Accepts a connect request on a socket.
<p>
?_{HostS} is bound to a string describing the host name. 
<index class=module/OS<and>acceptSelect/
It is possible to use <<OS.acceptSelect>> to block a
thread until a connect attempt on this socket is made. 
<p>
See <file /accept(2)/ and <file /gethostbyaddr(3)/. 

<Entry> <<connect>> <Synopsis>
<<{OS.connect ?+{SockI} ?+{HostV} ?+{PortI}}>>
<Index class=module/OS<and>connect/
<item>
Connects to a socket.
<p>
See <file /connect(2)/ and <file /gethostbyaddr(3)/.

<Entry> <<shutDown>> <Synopsis>
<<{OS.shutDown ?+{SockI} ?+{HowI}}>>
<Index class=module/OS<and>shutDown/
<item>
Signals that a socket is not longer interested in sending or receiving
data. 
<p>
See <file /shutdown(2)/.

<Entry> <<getSockName>> <Synopsis>
<<{OS.getSockName ?+{SockI} ??{PortI}}>>
<Index class=module/OS<and>getSockName/
<item>
Gets the name of a socket.
<p>
See <file /getsockname(3)/.

<Entry> <<send>> <Synopsis> <<{OS.send ?+{SockI} ?+{MsgV} ?+{FlagsAs} ??{LenI}}>>
<Entry> <<sendTo>> <Synopsis> <<{OS.sendTo ?+{SockI} ?+{MsgV} ?+{FlagsAs} ?+{HostV} ?+{PortI}} ??{LenI}}>>
<Index class=module/OS<and>send/
<Index class=module/OS<and>sendTo/
<item>
Sends data from a socket.
<p>
?_{FlagsAs} must be a list of atoms; its elements must be either
<<'MSG_OOB'>> or <<'MSG_DONTROUTE'>>.
<p>
See <file /send(2)/ and <file /gethostbyname(3)/.

<Entry> <<receiveFrom>> <Synopsis>
<<<
{OS.receiveFrom ?+{SockI} ?+{MaxI} ?+{FlagsAs} ??{MsgS}
                ?+{TailX} ??{HostS} ??{PortI} ??{LenI}}
>>>
<Index class=module/OS<and>receiveFrom/
<item>
Receives data at a socket.
<p>
?_{FlagsAs} must be a list of atoms; its elements must be either
<<'MSG_OOB'>> or <<'MSG_PEEK'>>.
<p>
See <file /recvfrom(2)/ and <file /gethostbyaddr(3)/.
</list>
</subsection>

<subsection>
<title/Process Control/
<p>
<list>
<Entry> <<kill>> <Synopsis>
<<{OS.kill ?+{PidI} ?+{SigA} ??{StatusI}}>>
<Index class=module/OS<and>kill/
<item>
Implements the <file /kill(2)/ function. ?_{PidI} is the process
identifier, ?_{SigA} is an atom describing the signal to be sent:
depending on the platform different signals are supported; at least
the following signals are supported on all platforms: <<'SIGTERM'>>,
<<'SIGINT'>>.

<Entry> <<pipe>> <Synopsis>
<<{OS.pipe ?+{CmdV} ?+{ArgsVs} ??{PidI} ??{StatusT}}>>
<Index class=module/OS<and>pipe/
<item>
Forks a OS process which executes the command ?_{CmdV} with arguments
?_{ArgsVs}. 
<p>
?_{PidI} is bound to the process identifier. 
?_{StatusT} is bound to a pair of socket or file descriptors where the
standard input, the standard output and the standard error is
redirected to. The first field of the pair is the descriptor for
reading whereas the second field is the descriptor for writing.
<p>
See <file /socketpair(2)/, <file /fork(2)/, <file /execvp(2)/, and
<file /execve(2)/.


<Entry> <<wait>> <Synopsis>
<<{OS.wait ??{PidI} ??{StatI}}>>
<Index class=module/OS<and>wait/
<item>
Implements the <file /wait(2)/ function.

<Entry> <<getPID>> <Synopsis>
<<{OS.getPID ??{PidI}}>>
<Index class=module/OS<and>getPID/
<item>
Returns the current process identifier as integer. See <file/getpid(2)/.

</list>
</section>





