4.12.1.20 I/O functions

MFL provides a set of functions for writing to disk files, pipes or sockets and reading from them. The idea behind them is the same as in most other programming languages: first you open the resource with a call to open which returns a descriptor i.e. an integer number uniquely identifying the resource. Then you can write or read from it using this descriptor. Finally, when the resource is no longer needed, you can close it with a call to close.

Built-in Function: number open (string name)

The name argument specifies the name of a resource to open and the access rights you need to have on it. The function returns a descriptor of the opened stream, which can subsequently be used as an argument to other I/O operations.

First symbols of name determine the type of the resource to be opened and the access mode:

>

The rest of name is a name of a file. Open the file for read-write access. If the file exists, truncate it to zero length, otherwise create the file.

>>

The rest of name is a name of a file. Open the file for appending (writing at end of file). The file is created if it does not exist.

|

Treat the rest of name as the command name and its arguments. Run this command and open its standard input for writing.

|&

Treat the rest of name as the command name and its arguments. Run this command and set up for two-way communication with it, i.e writes to the descriptor returned by open will send data to the program's standard input, reads from the descriptor will get data from the program's standard output.

@

Treat the rest of name as the URL of a socket to connect to. Valid URL forms are described in milter port specification.

If none of these prefixes is used, name is treated as a name of an existing file and open will attempt to open this file for reading.

The open function will signal exception e_failure if it is unable to open the resource or get the required access to it.

Built-in Function: void close (number rd)

The argument rd is a resource descriptor returned by a previous call to open. The function close closes the resource and deallocates any memory associated with it.

close will signal e_range exception if rd lies outside of allowed range of resource descriptors.

Notice that you are not required to close resources opened by open. Any unclosed resource will be closed automatically upon the termination of the filtering program.

The following functions provide basic read/write capabilities.

Built-in Function: void write (number rd, string str   [, number size])

Writes the string str to the resource descriptor rd. If the size argument is given, writes this number of bytes.

The function will signal e_range exception if rd lies outside of allowed range of resource descriptors, and e_io exception if an I/O error occurs.

Built-in Function: string read (number rd, number n)

Read and return n bytes from the resource descriptor rd.

The function may signal the following exceptions:

e_range

rd lies outside of allowed range of resource descriptors.

e_eof

End of file encountered.

e_io

An I/O error occurred.

Built-in Function: string getdelim (number rd, string delim)

Read and return the next string terminated by delim (which must be a string of length 1) from the resource descriptor rd. The terminating delim character will be removed from the return value.

The function may signal the following exceptions:

e_range

rd lies outside of allowed range of resource descriptors.

e_eof

End of file encountered.

e_io

An I/O error occurred.

Built-in Function: string getline (number rd)

Read and return the next newline-terminated string from the resource descriptor rd. The terminating newline character will be removed from the return value.

This function is equivalent to:

 
  getdelim(rd, "\n")

The function may signal the following exceptions:

e_range

rd lies outside of allowed range of resource descriptors.

e_eof

End of file encountered.

e_io

An I/O error occurred.

The following example shows how mailfromd I/O functions can be used to automatically add IP addresses to an RBL zone:

 
set nsupdate_cmd
  "/usr/bin/nsupdate -k /etc/bind/Kmail.+157+14657.private"
  
func block_address(string addr)
do
  number fd
  string domain

  set fd open "|%nsupdate_cmd"

  set domain revip(%addr) . ".rbl.myzone.come"
  write(%fd, "prereq nxrrset %domain A\n"
             "update add %domain 86400 A %addr\n\n"
done

The function revip is defined in revip.