21 Operating System Support: OS

This chapter describes the procedures contained in the module OS

21.1 Conventions

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 (e. g. [Lew91]).

A major convention is that most int arguments in C are integers in Oz. Moreover 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 n-ary C-function returning a value is implemented as a n+1-ary Oz procedure where the last argument serves as output position.

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.

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.

21.2 Exceptions

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:

  1. The atom A gives the category of the error (e. g. os for operating system or net for network layer).

  2. The string S1 describes the operating system routine that raised the exception.

  3. The integer I gives an operating system dependent error number.

  4. The string S2 describes the exception by some text.

  5. The value X might contain some additional debug information.

21.3 Random Integers

rand

{OS.rand ?I}

Returns a randomly generated integer.

See rand(3).

srand

{OS.srand +I}

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.

See srand(3).

randLimits

{OS.randLimits ?MinI ?MaxI}

Binds MinI and MaxI to the smallest and greatest possible random number obtainable by OS.rand.

See rand(3).

21.4 Files

tmpnam

{OS.tmpnam ?FileNameS}

Returns a freshly created full pathname.

See tmpnam(2).

unlink

{OS.unlink +PathV}

Removes the file with name PathV.

See link(2).

21.5 Directories

getDir

{OS.getDir +PathV ?FileNameSs}

Returns a list of strings giving the files in the directory PathV.

See opendir(3) and readdir(3).

getCWD

{OS.getCWD ?FileNameS}

Returns in FileNameS the path of the current working directory.

See getcwd(3).

stat

{OS.stat +PathV ?StatR}

Returns a record describing the status of the file PathV.

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.

See stat(2).

chDir

{OS.chDir +PathV}

Changes the current working directory to PathV.

See chdir(2).

mkDir

{OS.mkDir +PathV +ModeAs}

Creates a directory PathV. Access modes are specified by ModeAs, similar to OS.open.

See mkdir(2).

21.6 Sockets

getServByName

{OS.getServByName +NameV +ProtoV ?PortIB}

Returns the port number PortI of a service NameV reachable in the Internet domain with the specified protocol ProtoV.

If the service is unknown, false is returned.

As an example, the application

{OS.getServByName "finger" "tcp" Port}

binds Port to the number, where you can connect to your local finger server.

See getservbyname(3).

getHostByName

{OS.getHostByName +NameV ?HostentR}

Returns name information for the host NameV.

The record HostentR has the following features:

name

official host-name

string

aliases

alternative host-names

list of strings

addrList

Internet addresses

list of strings

See gethostbyname(3).

21.7 Time

time

{OS.time ?TimeI}

Returns the time since 00:00:00 GMT, Jan. 1, 1970 in seconds.

See time(2).

gmTime

{OS.gmTime ?GmTimeR}

localTime

{OS.localTime ?LocalTimeR}

Returns a description of the Coordinated Universal Time (UTC), respectively a description of the local time.

The records GmTimeR and LocalTimeR have the following features, where the fields are all integers:

sec

seconds

0 - 61

min

minutes

0 - 59

hour

hours

0 - 23

mDay

day of month

1 - 31

mon

month of year

0 - 11

year

years since 1900

wDay

days since Sunday

0 - 6

yDay

day of year

0 - 365

isDst

1 if daylight savings time in effect (DST)

See gmtime(3), localtime(3), and time(2).

21.8 Environment Variables

getEnv

{OS.getEnv +NameV ?ValueSB}

Returns the value of the environment variable NameV.

If a variable with the given name does not exist, the procedure returns false.

As an example, consider:

{OS.getEnv 'OZHOME'}

returns where the Oz system has been installed. This information is also available via {System.get home}

See getenv(3).

putEnv

{OS.putEnv +NameV +ValueV}

Sets the value of the environment variable NameV to ValueV.

See putenv(3).

21.9 Miscellaneous

uName

{OS.uName ?UtsnameR}

Returns system information.

The record UtsnameR has at least the following features, where all fields are strings:

sysname

operating system name

nodename

computer name

release

operating system release

version

operating system version

machine

machine architecture

See uname(2).

system

{OS.system +CmdV ?StatusI}

Starts a new operating system shell in which the OS command CmdV is executed. The status of the command is reported by StatusI.

See system(3).

21.10 Low Level Procedures

21.10.1 Basic Input and Output

open

{OS.open +FileNameV +FlagsAs +ModeAs ?DescI}

Opens a file for reading and/or writing.

FlagsAs must be a list with some of the following atoms as elements:

'O_RDONLY'

'O_WRONLY'

'O_RDWR'

'O_APPEND'

'O_CREAT'

'O_EXCL'

'O_TRUNC'

'O_NOCCTY'

'O_NONBLOCK'

'O_SYNC'

Their meanings coincide with their usual POSIX meanings.

In the same manner ModeAs must be a list with elements drawn from:

'S_IRUSR'

'S_IWUSR'

'S_IXUSR'

'S_IRGRP'

'S_IWGRP'

'S_IXGRP'

'S_IROTH'

'S_IWOTH'

'S_IXOTH'

See open(2) and chmod(2).

fileDesc

{OS.fileDesc +FileDescA ?FileDescIB}

Maps the atoms

'STDIN_FILENO'

'STDOUT_FILENO'

'STDERR_FILENO'

to integers, giving their respective file descriptor. Note that these descriptors will be duplicated.

See open(2) and dup(2).

read

{OS.read +DescI +MaxI ?ListS TailX ?ReadI}

Reads data from a file or socket. Yields a list of characters in ListS, where the tail of the list is constrained to TailX.

Implements the read(2) system call.

write

{OS.write +DescI +V ?StatusTI}

Writes the virtual string V to a file or a socket by using the function write(2).

Illegal parts of the virtual string V are simply ignored, and the legal parts are written.

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.

Otherwise StatusTI is bound to the number of characters written.

lSeek

{OS.lSeek +DescI +WhenceA +OffsetI ?WhereI}

Positions the seek pointer of a file. This procedure is implemented by the lseek(2) function. WhenceA must be one of the atoms 'SEEK_SET', 'SEEK_CUR', and 'SEEK_END'.

close

{OS.close +DescI}

Closes a file or socket by using the close(2) function.

21.10.2 From Blocking to Suspension

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, i. e. the whole Oz Emulator process will stop doing any work.

To overcome this problem, we provide three procedures. These procedures will suspend rather than block.

acceptSelect

{OS.acceptSelect +DescI}

readSelect

{OS.readSelect +DescI}

writeSelect

{OS.writeSelect +DescI}

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

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 
... then... 
end

blocks the current thread until data for reading is available.

This functionality is implemented by the select(2) system call.

Before actually closing a file descriptor, the following procedure needs to be called.

deSelect

{OS.deSelect +DescI}

Discards all threads depending on the file descriptor DescI.

21.10.3 Sockets

socket

{OS.socket +DomainA +TypeA +ProtoV ?DescI}

Creates a socket. Is implemented by the function socket(2).

DomainA must be either the atom 'PF_INET' or 'PF_UNIX', whereas TypeA must be either 'SOCK_STREAM', or 'SOCK_DGRAM'.

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".

bind

{OS.bind +SockI +PortI}

Binds a socket to its global name.

See bind(2).

listen

{OS.listen +SockI +BackLogI}

Indicates that a socket is willing to receive connections.

See listen(2).

accept

{OS.accept +SockI ?HostS ?PortI ?DescI}

Accepts a connect request on a socket.

HostS is bound to a string describing the host name. It is possible to use OS.acceptSelect to block a thread until a connect attempt on this socket is made.

See accept(2) and gethostbyaddr(3).

connect

{OS.connect +SockI +HostV +PortI}

Connects to a socket.

See connect(2) and gethostbyaddr(3).

shutDown

{OS.shutDown +SockI +HowI}

Signals that a socket is not longer interested in sending or receiving data.

See shutdown(2).

getSockName

{OS.getSockName +SockI ?PortI}

Gets the name of a socket.

See getsockname(3).

send

{OS.send +SockI +MsgV +FlagsAs ?LenI}

sendTo

{OS.sendTo +SockI +MsgV +FlagsAs +HostV +PortI?LenI}

Sends data from a socket.

FlagsAs must be a list of atoms; its elements must be either 'MSG_OOB' or 'MSG_DONTROUTE'.

See send(2) and gethostbyname(3).

receiveFrom

{OS.receiveFrom +SockI +MaxI +FlagsAs ?MsgS 
                
+TailX ?HostS ?PortI ?LenI}

Receives data at a socket.

FlagsAs must be a list of atoms; its elements must be either 'MSG_OOB' or 'MSG_PEEK'.

See recvfrom(2) and gethostbyaddr(3).

21.10.4 Process Control

kill

{OS.kill +PidI +SigA ?StatusI}

Implements the 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'.

pipe

{OS.pipe +CmdV +ArgsVs ?PidI ?StatusT}

Forks a OS process which executes the command CmdV with arguments ArgsVs.

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.

See socketpair(2), fork(2), execvp(2), and execve(2).

wait

{OS.wait ?PidI ?StatI}

Implements the wait(2) function.

getPID

{OS.getPID ?PidI}

Returns the current process identifier as integer. See getpid(2).


Denys Duchier, Leif Kornstaedt, Martin Homik, Tobias Müller, Christian Schulte and Peter Van Roy
Version 1.4.0 (20080702)