Next: , Previous: , Up: Library   [Contents][Index]

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

The number of available resource descriptors is limited. The default limit is 1024. You can tailor it to your needs using the max-streams runtime configuration statement. See max-streams, for a detailed description.

By default, all I/O operations are unbuffered. This can be changed by setting the following global variables:

Built-in variable: number io_buffering

Sets the default buffering type. Allowed values are (symbolic names are defined in status.mfl module):

0
BUFFER_NONE

No buffering. This is the default.

1
BUFFER_FULL

Full buffering. Size of the buffer is set by the io_buffer_size global variable (see below).

2
BUFFER_LINE

Line buffering. When reading, it is pretty much the same as BUFFER_FULL. When writing, the data are accumulated in buffer and actually sent to the underlying transport stream when the newline character is seen.

The initial size of the buffer is set by the io_buffer_size variable. It will grow as needed during the I/O.

Built-in variable: number io_buffer_size

Set the buffer size if io_buffering is set to BUFFER_FULL or BUFFER_LINE. By default, this variable is set to the size of the system page.

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.

Buffering mode for the opened stream is defined by the io_buffering and io_buffer_size global variables. It can be changed using the setbuf function (see setbuf).

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. The standard error is closed before launching the program. This can be altered by using the following versions of this construct:

|2>null: command

Standard error is redirected to /dev/null.

|2>file:name command

Execute command with its standard error redirected to the file name. If the file exists, it will be truncated.

|2>>file:name command

Standard error of the command is appended to the file name. If file does not exist, it will be created.

The ‘|2>null:’ construct described above is a shortcut for

|2>>file:/dev/null command
|2>syslog:facility[.priority] command

Standard error is redirected to the given syslog facility and, optionally, priority. If the latter is omitted, ‘LOG_ERR’ is assumed.

Valid values for facility are: ‘user’, ‘daemon’, ‘auth’, ‘authpriv’, ‘mail’, and ‘local0’ through ‘local7’. Valid values for priority are: ‘emerg’, ‘alert’, ‘crit’, ‘err’, ‘warning’, ‘notice’, ‘info’, ‘debug’. Both facility and priority may be given in upper, lower or mixed cases.

Notice, that no whitespace characters are allowed between ‘|’ and ‘2>’.

|<

Treat the rest of name as the command name and its arguments. Run this command with its stdin closed and stdout open for reading.

The standard error is treated as described above (see ‘|’).

|&

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.

The standard error is treated as described above (see ‘|’). For example, the following redirects it to syslog ‘mail.debug’:

|&2>syslog:mail.debug command
@

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: number spawn (string cmd [, number in, number out, number err])

Runs the supplied command cmd. The syntax of the cmd is the same as for the name argument to open (see above), which begins with ‘|’, excepting that the ‘|’ sign is optional. That is:

spawn("/bin/cat")

has exactly the same effect as

open("|/bin/cat")

Optional arguments specify file stream descriptors to be used for the program standard input, output and error streams, correspondingly. If supplied, these should be the values returned by a previous call to open or tempfile. The value ‘-1’ means no redirection.

Buffering mode for the opened stream is defined by the io_buffering and io_buffer_size global variables. It can be changed using the setbuf function (see setbuf).

The example below starts the awk program with a simple expression as its argument and redirects the content of the file /etc/passwd to its standard input. The returned stream descriptor is bound to the command’s standard output (see the description of ‘|<’ prefix above). The standard error is closed:

number fd spawn("<awk -F: '{print $1}'", open("/etc/passwd"))
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. See max-streams.

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.

Built-in Function: void shutdown (number rd, number how)

This function causes all or part of a full-duplex connection to be closed. The rd must be either a socket descriptor (returned by open(@...)) or a two-way pipe socket descriptor (returned by open(|&...)), otherwise the call to shutdown is completely equivalent to close.

The how argument identifies which part of the connection to shut down:

SHUT_RD

Read connection. All further receptions will be disallowed.

SHUT_WR

Write connection. All further transmissions will be disallowed.

SHUT_RDWR

Shut down both read and write parts.

Built-in Function: number tempfile ([string tmpdir])

Creates a nameless temporary file and returns its descriptor. Optional tmpdir supplies the directory where to create the file, instead of the default /tmp.

Built-in Function: void rewind (number rd)

Rewinds the stream identified by rd to its beginning.

Built-in Function: number copy (number dst, number src)

Copies all data from the stream src to dst. Returns number of bytes copied.

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.

This function always attempts to write the requested amount of data. It will signal e_range exception if rd lies outside of allowed range of resource descriptors, e_io exception if an I/O error occurs, and e_eof exception if it wrote 0 bytes (e.g. because the underlying device is full).

Built-in Function: void write_body (number rd, pointer bp , number size)

Write the body segment of length size from pointer bp to the stream rd. This function can be used only in prog body (see body handler). Its second and third arguments correspond exactly to the parameters of the body handler, so the following construct writes the message body to the resource fd, which should have been open prior to invoking the body handler:

prog body
do
  write_body(fd, $1, $2)
done
Built-in Function: string read (number rd, number n)

Read and return at most n bytes from the resource descriptor rd.

If there are less than n bytes in the stream, the remaining bytes will be returned. Use length() to obtain the actual size of the returned data. If there are no bytes left, the e_eof exception will be signalled.

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 from the resource descriptor rd.

The terminating delim string will be removed from the return value.

When using this function, it is highly recommended to enable full buffering for fd, either by setting io_buffering before open (see io_buffering) or by calling setbuf after it (see setbuf). See getline, for an example.

This 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 line from the resource descriptor rd. A line is any sequence of characters terminated with the default line delimiter. The default delimiter is a property of rd, i.e. different descriptors can have different line delimiters. The default value is ‘\n’ (ASCII 10), and can be changed using the fd_set_delimiter function (see below).

When using this function, it is highly recommended to enable full buffering for fd, either by setting io_buffering before open (see io_buffering) or by calling setbuf after it (see setbuf), e.g.:

  set fd open(input)
  setbuf(fd, BUFFER_FULL)
  set line getline(fd)
  ...

This 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: void fd_set_delimiter (number fd, string delim)

Set new line delimiter for the descriptor fd, which must be in opened state.

Default delimiter is a newline character (ASCII 10). The following example shows how to change it to CRLF sequence:

fd_set_delimiter(fd, "\r\n")
Built-in Function: string fd_delimiter (number fd)

Returns the line delimiter string for fd.

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 reverse_ipstr(addr) . ".rbl.myzone.come"
  write(fd, "prereq nxrrset %domain A\n"
             "update add %domain 86400 A %addr\n\n"
done

The function reverse_ipstr is defined in Internet address manipulation functions.

Built-in Function: void setbuf(number fd, [number type, number size])

Changes the buffering mode of fd according to the remaining two arguments. The type specifies buffering type (see io_buffering), and size supplies the buffer size for buffering types BUFFER_FULL and BUFFER_LINE. If size is omitted, it defaults to io_buffer_size (see io_buffer_size). Omitted type defaults to io_buffering (see io_buffering).

Built-in Function: number getbuftype(number fd)

Returns the type of buffering currently in effect for the descriptor fd. See io_buffering, for a list of possible return values.

If this function returns BUFFER_FULL or BUFFER_LINE, you can use getbufsize to get the associated buffer size.

Built-in Function: number getbufsize(number fd)

Returns the buffer size for the descriptor fd.


Next: , Previous: , Up: Library   [Contents][Index]