Previous chapter To contents Next chapter

Chapter 9, File I/O

Programming without reading and writing data from files, sockets, keyboard etc. would be quite pointless. Luckily enough, Pike provides you with an object oriented interface to files, pipes and TCP sockets. All I/O functions and classes are collected in the module Stdio.

9.1 File management - Stdio.File

CLASS
Stdio.File This is the basic I/O object, it provides socket communication as well as file access. It does not buffer reads and writes or provide line-by-line reading, that is done in the FILE object. Stdio.File is completely written in C. What follows is a description of all the functions in Stdio.File.

METHOD
Stdio.File.create - init file struct

SYNTAX
object(Stdio.File) Stdio.File();
object(Stdio.File) Stdio.File(string filename);
object(Stdio.File) Stdio.File(string filename, string mode);
object(Stdio.File) Stdio.File(string filename, string mode, int mask);
object(Stdio.File) Stdio.File(string fd);
object(Stdio.File) Stdio.File(int fd);
object(Stdio.File) Stdio.File(int fd, string mode);

DESCRIPTION
There are four different ways to clone a File. The first is to clone it without any arguments, in which case the you have to call open(), connect() or some other method which connects the File object with a stream.

However, instead of cloning and then calling open(), you can clone the File with a filename and open mode. This is the same thing as cloning and then calling open, except shorter and faster. Default open mode is "r" and default mask is 0666.

Alternatively, you can clone a File with "stdin", "stdout" or "stderr" as argument. This will open the specified standard stream.

For the advanced users, you can use the file descriptors of the systems (note: emulated by pike on some systems - like NT). This is only useful for streaming purposes on unix systems. This is not recommended at all if you don't know what you're into. Default mode for this is "rw".

NOTE
Open mode will be filtered through the system UMASK. You might need to use chmod later.

SEE ALSO
clone and Stdio.File->open

METHOD
Stdio.File.open - open a file

SYNTAX
int open(string filename, string how);
int open(string filename, string how, int mode);

DESCRIPTION
Open a file for read, write or append. The variable how should contain one or more of the following letters:

'r' open file for reading
'w' open file for writing
'a' open file for append (use with 'w')
't' truncate file at open (use with 'w')
'c' create file if it doesn't exist (use with 'w')
'x' fail if file already exist (use with 'c')

How should _always_ contain at least one of 'r' or 'w'.

The third argument is protection bits if the file is created. Default is 0666 (all read+write, in octal notation).

RETURNS
1 on success, 0 otherwise

SEE ALSO
Stdio.File->close

METHOD
Stdio.File.close - close a file

SYNTAX
int close(string how);
int close();

DESCRIPTION
Close the file. Optionally, specify "r", "w" or "rw" to close just the read, just the write or both read and write part of the file respectively. Note that this function will not call the close_callback.

SEE ALSO
Stdio.File->open

METHOD
Stdio.File.read - read data from a file or stream

SYNTAX
string read(int nbytes);
string read(int nbytes, int notall);
string read();

DESCRIPTION
Read tries to read nbytes bytes from the file, and return it as a string. If something goes wrong, zero is returned.

If a one is given as second argument to read(), read will not try its best to read as many bytes as you asked it to read, it will merely try to read as many bytes as the system read function will return. This mainly useful with stream devices which can return exactly one row or packet at a time.

If no arguments are given, read will read to the end of the file/stream.

SEE ALSO
Stdio.File->read_oob and Stdio.File->write

METHOD
Stdio.File.read_oob - read out-of-band data from a stream

SYNTAX
string read_oob(int nbytes);
string read_oob(int nbytes, int notall);
string read_oob();

DESCRIPTION
Tries to read nbytes bytes of out-of-band data from the stream, and returns it as a string. If something goes wrong, zero is returned.

If a one is given as a second argument to read_oob(), only as many bytes of out-of-band data as are currently available will be returned.

If no arguments are given, read_oob will read to the end of the stream.

NOTE
This function is only available if the option '--with-oob' was specified when Pike was compiled.

It is not guaranteed that all out-of-band data sent from the other end will be received. Most streams only allow for a single byte of out-of-band data at a time.

SEE ALSO
Stdio.File->read and Stdio.File->write_oob

METHOD
Stdio.File.write - write data to a file or stream

SYNTAX
int write(string data);

DESCRIPTION
Write data to file or stream and return how many bytes that were actually written. 0 is returned in nonblocking mode if it was not possible to write anything without blocking. -1 is returned if something went wrong and no bytes were written.

SEE ALSO
Stdio.File->read and Stdio.File->write_oob

METHOD
Stdio.File.write_oob - write out-of-band data to a stream

SYNTAX
int write_oob(string data);

DESCRIPTION
Writes out-of-band data to a stream and returns how many bytes that were actually written. -1 is returned if something went wrong and no bytes were written.

NOTE
This function is only available if the option '--with-oob' was specified when Pike was compiled.

It is not guaranteed that all out-of-band data will be received at the other end. Most streams only allow for a single byte of out-of-band data at a time. Some streams will send the rest of the data as ordinary data.

SEE ALSO
Stdio.File->read_oob and Stdio.File->write

METHOD
Stdio.File.seek - seek to a position in a file

SYNTAX
int seek(int pos);

DESCRIPTION
Seek to a position in a file, if pos is less than zero, seek to position pos relative end of file. Returns -1 for failure, or the new position in the file when successful.

SEE ALSO
Stdio.File->tell

METHOD
Stdio.File.tell - tell where we are in a file

SYNTAX
int tell();

DESCRIPTION
Returns the current position in the file.

SEE ALSO
Stdio.File->seek

METHOD
Stdio.File.truncate - truncate a file

SYNTAX
int truncate(int length);

DESCRIPTION
Truncates a file to that length. Returns 1 if ok, 0 if failed.

SEE ALSO
Stdio.File->open

METHOD
Stdio.File.stat - do file_stat on an open file

SYNTAX
array(int) stat();

DESCRIPTION
This function returns the same information as the function file_stat, but for the file it is called in. If file is not an open file, zero will be returned. Zero is also returned if file is a pipe or socket.

SEE ALSO
file_stat

METHOD
Stdio.File.errno - what was last error?

SYNTAX
int errno();

DESCRIPTION
Returns the error code for the last command on this file. Error code is normally cleared when a command is successful.

METHOD
Stdio.File.set_buffer - set internal socket buffer

SYNTAX
void set_buffer(int bufsize, string mode);
void set_buffer(int bufsize);

DESCRIPTION
This function sets the internal buffer size of a socket or stream. The second argument allows you to set the read or write buffer by specifying "r" or "w". It is not guaranteed that this function actually does anything, but it certainly helps to increase data transfer speed when it does.

SEE ALSO
Stdio.File->open_socket and Stdio.Port->accept

METHOD
Stdio.File.set_nonblocking - make stream nonblocking

SYNTAX
void set_nonblocking(function(mixed, string:void) read_callback,
function(mixed:void) write_callback,
function(mixed:void) close_callback);
or
void set_nonblocking(function(mixed, string:void) read_callback,
function(mixed:void) write_callback,
function(mixed:void) close_callback,
function(mixed, string:void) read_oob_callback,
function(mixed:void) write_oob_callback);
or
void set_nonblocking();

DESCRIPTION
This function sets a stream to nonblocking mode. When data arrives on the stream, read_callback will be called with some or all of this data. When the stream has buffer space over for writing, write_callback is called so you can write more data to it. If the stream is closed at the other end, close_callback is called.

When out-of-band data arrives on the stream, read_oob_callback will be called with some or all of this data. When the stream allows out-of-band data to be sent, write_oob_callback is called so that you can write out-of-band data to it.

All callbacks will have the id of file as first argument when called.

If no arguments are given, the callbacks are not changed. The stream is just set to nonblocking mode.

NOTE
Out-of-band data is only supported if Pike was compiled with the option '--with-oob'.

SEE ALSO
Stdio.File->set_blocking and Stdio.File->set_id

METHOD
Stdio.File.set_read_callback - set the read callback

SYNTAX
void set_read_callback(function read_callback)

DESCRIPTION
This function sets the read callback for the file. The read callback is called whenever there is data to read from the file. Note that this function does not set the file nonblocking.

SEE ALSO
Stdio.File->set_nonblocking

METHOD
Stdio.File.set_write_callback - set the write callback

SYNTAX
void set_write_callback(function write_callback)

DESCRIPTION
This function sets the write callback for the file. The write callback is called whenever there is buffer space available to write to for the file. Note that this function does not set the file nonblocking.

SEE ALSO
Stdio.File->set_nonblocking

METHOD
Stdio.File.set_close_callback - set the close callback

SYNTAX
void set_close_callback(function close_callback)

DESCRIPTION
This function sets the close callback for the file. The close callback is called when the remote end of a socket or pipe is closed. Note that this function does not set the file nonblocking.

SEE ALSO
Stdio.File->set_nonblocking

METHOD
Stdio.File.set_blocking - make stream blocking

SYNTAX
void set_blocking();

DESCRIPTION
This function sets a stream to blocking mode. i.e. all reads and writes will wait until data has been written before returning.

SEE ALSO
Stdio.File->set_nonblocking

METHOD
Stdio.File.set_id - set id of this file

SYNTAX
void set_id(mixed id);

DESCRIPTION
This function sets the id of this file. The id is mainly used as an identifier that is sent as the first arguments to all callbacks. The default id is 0. Another possible use of the id is to hold all data related to this file in a mapping or array.

SEE ALSO
Stdio.File->query_id

METHOD
Stdio.File.query_id - get id of this file

SYNTAX
mixed query_id();

DESCRIPTION
This function returns the id of this file.

SEE ALSO
Stdio.File->set_id

METHOD
Stdio.File.query_read_callback - return the read callback function

SYNTAX
function query_read_callback();

DESCRIPTION
This function returns the read_callback, which is set with set_nonblocking or set_read_callback.

SEE ALSO
Stdio.File->set_nonblocking and Stdio.File->set_read_callback

METHOD
Stdio.File.query_write_callback - return the write callback function

SYNTAX
function query_write_callback();

DESCRIPTION
This function returns the write_callback, which is set with set_nonblocking or set_write_callback.

SEE ALSO
Stdio.File->set_nonblocking and Stdio.File->set_write_callback

METHOD
Stdio.File.query_close_callback - return the close callback function

SYNTAX
function query_close_callback();

DESCRIPTION
This function returns the close_callback, which is set with set_nonblocking or set_close_callback.

SEE ALSO
Stdio.File->set_nonblocking and Stdio.File->set_close_callback

METHOD
Stdio.File.dup - duplicate a file

SYNTAX
object(Stdio.File) dup();

DESCRIPTION
This function returns a clone of Stdio.File with all variables copied from this file. Note that all variables, even id, is copied.

SEE ALSO
Stdio.File->assign

METHOD
Stdio.File.dup2 - duplicate a file over another

SYNTAX
int dup2(object(Stdio.File) to);

DESCRIPTION
This function works similarly to Stdio.File->assign, but instead of making the argument a reference to the same file, it creates a new file with the same properties and places it in the argument.

EXAMPLE
/* Redirect stdin to come from the file 'foo' */
object o=Stdio.File();
o->open("foo","r");
o->dup2(Stdio.File("stdin"));

SEE ALSO
Stdio.File->assign and Stdio.File->dup

METHOD
Stdio.File.assign - assign a file

SYNTAX
void assign(object f);

DESCRIPTION
This function takes a clone of Stdio.File and assigns all variables of this file from it. It can be used together with file->dup to move files around.

SEE ALSO
Stdio.File->dup

METHOD
Stdio.File.open_socket - open a socket

SYNTAX
int open_socket(int|void port, string|void address);

DESCRIPTION
This makes this file into a socket ready for connection. The reason for this function is so that you can set the socket to nonblocking or blocking (default is blocking) before you call Stdio.File->connect() This function returns 1 for success, 0 otherwise.

If you give a port number to this function, the socket will be bound to this port locally before connecting anywhere. This is only useful for some silly protocols like FTP. You may also specify an address to bind to if your machine has many IP numbers.

SEE ALSO
Stdio.File->connect and Stdio.File->set_nonblocking

METHOD
Stdio.File.connect - connect a socket to something

SYNTAX
int connect(string IP,int port);

DESCRIPTION
This function connects a socket previously created with Stdio.File->open_socket to a remote socket. The argument is the IP name or number for he remote machine.

This function returns 1 for success, 0 otherwise. Note that if the socket is in nonblocking mode, you have to wait for a write or close callback before you know if the connection failed or not.

SEE ALSO
Stdio.File->query_address

METHOD
Stdio.File.query_address - get addresses

SYNTAX
string query_address();
string query_address(1);

DESCRIPTION
This function returns the remote or local address of a socket on the form "x.x.x.x port". Without argument, the remote address is returned, with argument the local address is returned. If this file is not a socket, not connected or some other error occurs, zero is returned.

SEE ALSO
Stdio.File->connect

METHOD
Stdio.File.pipe - create a two-way pipe

SYNTAX
object pipe();

DESCRIPTION
This function creates a pipe between the object it was called in and an object that is returned. The two ends of the pipe are indistinguishable. If the File object this function is called in was open to begin with, it is closed before the pipe is created.

SEE ALSO
fork

METHOD
Stdio.File.set_close_on_exec - set / clear the close on exec flag

SYNTAX
void set_close_on_exec(int onoff);

DESCRIPTION
This function determines whether this file will be closed when calling exece. Default is that the file WILL be closed on exec except for stdin, stdout and stderr.

SEE ALSO
exece

Here is an example of how to use the TCP functions in Stdio.File in blocking mode. This short program takes a URL as first argument, connects to the WWW server, sends a HEAD request and writes the reply to stdout. For clarity, all calls to Stdio.File use File:: even if that is not strictly necessary.

import Stdio;
inherit File;

int main(int argc, array(string) argv)
{
    string host;
    string path="";
    int port=80;
    sscanf(argv[1],"http://%s",argv[1]);
    sscanf(argv[1],"%s/%s",host,path);
    sscanf(host,"%s:%d",host,port);

    if(!File::open_socket())
    {
        perror("Open socket failed");
        exit(1);
    }

    if(!File::connect(host,port))
    {
        perror("Failed to connect to remote host");
        exit(1);
    }

    File::write(sprintf("HEAD /%s HTTP/1.0\n",path));
    stdout::write(File::read());
}

9.2 Buffered file management - Stdio.FILE

CLASS
Stdio.FILE Stdio.FILE is a buffered version of Stdio.File, it inherits Stdio.File and has most of the functionality of Stdio.File. However, it has an input buffer that allows line-by-line input. Note that the output part of Stdio.FILE is not buffered at this moment. The added functionality of Stdio.FILE is described here:

METHOD
Stdio.FILE.gets - get one line

SYNTAX
string gets();

DESCRIPTION
This function returns one line from the FILE, it returns zero if no more lines are available.

METHOD
Stdio.FILE.printf - formatted print

SYNTAX
string printf(string format, mixed ... data);

DESCRIPTION
This function does approximately the same as: write(sprintf(format,@data))

SEE ALSO
sprintf

METHOD
Stdio.FILE.ungets - put a string back in the buffer

SYNTAX
string ungets(string s);

DESCRIPTION
This function puts a string back in the input buffer. The string can then be read with read, gets or getchar.

METHOD
Stdio.FILE.getchar - get one character from the input stream

SYNTAX
int getchar();

DESCRIPTION
This function returns one character from the input stream. Note that the return value is the ascii value of the character, not a string containing one character.

9.3 Standard streams - Stdio.stdin, stdout and stderr

Any UNIX program has three files open from the beginning. These are called standard input, standard output and standard error stream. These streams are available from Pike as well. They are called Stdio.stdin, Stdio.stdout and Stdio.stderr respectively. Standard input is a clone of Stdio.FILE, which means you can use the line oriented functions. Stdio.stdout and Stdio.stderr are simply clones of Stdio.File.

Example:

int main()
{
    int line;
    while(string s=Stdio.stdin.gets())
        write(sprintf("%5d: %s\n",line++,s));
}
This example will read lines from standard input for as long as there are more lines to read. Each line will then be written to stdout together with the line number. We could use Stdio.stdout.write instead of just write because they are the same function.

9.4 Listening to sockets - Stdio.Port

CLASS
Stdio.Port Stdio.File can handle connections to any TCP socket, but it can not listen to a local TCP port. For this purpose there is a special class called Stdio.Port. Stdio.Port cannot read or write any data, but it can accept connections which will be returned as clones of Stdio.File. These are the methods available in Stdio.Port:

METHOD
Stdio.Port.bind - open socket and bind it to a port

SYNTAX
int bind(int port);
int bind(int port,function accept_callback);
int bind(int port,function accept_callback, string IP);

DESCRIPTION
Bind opens a sockets and binds it to port number on the local machine. If the second argument is present, the socket is set to nonblocking and the callback function is called whenever something connects to the socket. The callback will receive the id for this port as argument. Bind returns 1 on success, and zero on failure.

If the optional argument IP is given, bind will try to bind to this IP name (or number).

SEE ALSO
Stdio.Port->accept

METHOD
Stdio.Port.listen_fd - listen to an already open port

SYNTAX
int listen_fd(int fd);
int listen_fd(int fd,function accept_callback);

DESCRIPTION
This function does the same as Stdio.Port->bind, except that instead of creating a new socket and bind it to a port, it expects that the file descriptor fd is an already open port.

NOTE
This function is only for the advanced user, and is generally used when sockets are passed to Pike at exec time.

SEE ALSO
Stdio.Port->bind and Stdio.Port->accept

METHOD
Stdio.Port.create - create and/or setup a port

SYNTAX
object(Stdio.Port) Stdio.Port("stdin")
object(Stdio.Port) Stdio.Port("stdin",function accept_callback)
object(Stdio.Port) Stdio.Port("stdin",function accept_callback)
object(Stdio.Port) Stdio.Port(int port)
object(Stdio.Port) Stdio.Port(int port,function accept_callback)
object(Stdio.Port) Stdio.Port(int port,function accept_callback, string ip)

DESCRIPTION
When create is called with "stdin" as argument, a socket is created out of the file descriptor 0. This is only useful if that actually is a socket to begin with. When create is called with an int as first argument, it does the same as bind() would do with the same arguments. The second and third argument has the same function as in the bind() call.

SEE ALSO
clone and Stdio.Port->bind

METHOD
Stdio.Port.set_id - set the id of a port

SYNTAX
void set_id(mixed id);

DESCRIPTION
This function sets the id used for accept_callback by this port. The default id is this_object().

SEE ALSO
Stdio.Port->query_id

METHOD
Stdio.Port.query_id - Return the id for this port.

SYNTAX
mixed query_id();

DESCRIPTION
This function returns the id for this port. The id is normally the first argument to accept_callback.

SEE ALSO
Stdio.Port->set_id

METHOD
Stdio.Port.errno - return the last error

SYNTAX
int errno();

DESCRIPTION
If the last call done on this port failed, errno will return an integer describing what went wrong. Refer to your Unix manual for further information.

SEE ALSO
Stdio.Port->errno

METHOD
Stdio.Port.accept - accept a connection

SYNTAX
object accept();

DESCRIPTION
This function completes a connection made from a remote machine to this port. It returns a two-way stream in the form of a copy of Stdio.File. The new file is by default set to blocking.

SEE ALSO
Stdio.File

9.5 UDP socket and message management - Stdio.UDP

CLASS
Stdio.UDP

SYNTAX
Stdio.UDP();

DESCRIPTION
Stdio.UDP is the way of transceiving UDP from Pike.

SEE ALSO
Stdio.File

METHOD
Stdio.UDP.bind

SYNTAX
bind(int port); bind(int port,string address);

DESCRIPTION
binds a port for recieving or transmitting UDP

RETURNS
the called object

METHOD
Stdio.UDP.enable_broadcast

SYNTAX
enable_broadcast()

DESCRIPTION
enable transmission of broadcasts. This is normally only avalable to root users.

RETURNS
1 upon success, 0 otherwise

METHOD
Stdio.UDP.read

SYNTAX
read()
read(int flags)

DESCRIPTION
read from the UDP socket. Flags is a bitfield, 1 for out of band data and 2 for peek.

RETURNS
mapping(string:int|string) in the form
([
   "data" : string recieved data
   "ip" : string   recieved from this ip
   "port" : int    ...and this port
])

SEE ALSO
Stdio.UDP.set_nonblocking and Stdio.UDP.set_read_callback

METHOD
Stdio.UDP.send

SYNTAX
send(string to_addr,int to_port,string data)
send(string to_addr,int to_port,string data,int flags)

DESCRIPTION

RETURNS
number of bytes sent

METHOD
Stdio.UDP.set_nonblocking

SYNTAX
set_nonblocking();
set_blocking();
set_nonblocking(function, mixed ...);

DESCRIPTION
sets this object to be nonblocking or blocking. If set_nonblocking is given with argument, these are passed to set_read_callback().

RETURNS
the called object

METHOD
Stdio.UDP.set_read_callback

SYNTAX
set_read_callback(function(mapping(string:int|string), mixed...), mixed ... extra);

DESCRIPTION
The called function is recieving mapping similar to the return value of read:
([
   "data" : string recieved data
   "ip" : string   recieved from this ip
   "port" : int    ...and this port
])

RETURNS
the called object

METHOD
Stdio.UDP.query_address

SYNTAX
query_address()

DESCRIPTION

RETURNS
the current address in format "<ip> <port>".

SEE ALSO
Stdio.File.query_address

9.6 Terminal management - Stdio.Terminfo

FUNCTION
Stdio.Terminfo.getFallbackTerm - get fallback terminal

SYNTAX
object(Stdio.Terminfo.Terminfo)|object(Stdio.Terminfo.Termcap) getFallbackTerm(string term);

DESCRIPTION
Returns an object describing the fallback terminal for the terminal term. This is usually equvivalent to Stdio.Terminfo.getTerm("dumb").

SEE ALSO
Stdio.Terminfo.getTerm

FUNCTION
Stdio.Terminfo.getTerm - get terminal description

SYNTAX
object(Stdio.Terminfo.Terminfo)|object(Stdio.Terminfo.Termcap) getTerm();
or
object(Stdio.Terminfo.Terminfo)|object(Stdio.Terminfo.Termcap) getTerm(string term);

DESCRIPTION
Returns an object describing the terminal term. If term is not specified, it will default to getenv("TERM") or if that fails to "dumb".

Lookup of terminal information will first be done in the systems terminfo database, and if that fails in the termcap database. If neither database exists, a hardcoded entry for "dumb" will be used.

SEE ALSO
Stdio.Terminfo.getTerminfo, Stdio.Terminfo.getTermcap and Stdio.getFallbackTerm

FUNCTION
Stdio.Terminfo.getTermcap - get termcap description

SYNTAX
object(Stdio.Terminfo.Termcap) getTermcap(string term);

DESCRIPTION
Return the terminal description of term from the systems termcap database. Returns 0 if not found.

SEE ALSO
Stdio.Terminfo.getTerm and Stdio.Terminfo.getTerminfo

FUNCTION
Stdio.Terminfo.getTerminfo - get terminfo description

SYNTAX
object(Stdio.Terminfo.Terminfo) getTerminfo(string term);

DESCRIPTION
Return the terminal description of term from the systems terminfo database. Returns 0 if not found.

SEE ALSO
Stdio.Terminfo.getTerm and Stdio.Terminfo.getTermcap

9.6.1 Stdio.Terminfo.Termcap

CLASS
Stdio.Terminfo.Termcap Termcap terminal decription object.

METHOD
Stdio.Terminfo.Termcap.create - initialize termcap object

SYNTAX
object(Stdio.Terminfo.Termcap) Termcap(string cap);
or
object(Stdio.Terminfo.Termcap) Termcap(string cap, object tcdb);
or
object(Stdio.Terminfo.Termcap) Termcap(string cap, object tcdb, int maxrecurse);

METHOD
Stdio.Terminfo.Termcap.tputs - put termcap string

9.6.2 Stdio.Terminfo.Terminfo

CLASS
Stdio.Terminfo.Terminfo Terminfo terminal description object.

9.7 Simple input-by-prompt - Stdio.Readline

CLASS
Stdio.Readline

METHOD
Stdio.Readline.create - init readline

SYNTAX
object(Stdio.Readline) Stdio.Readline();
or
object(Stdio.Readline) Stdio.Readline(object infd);
or
object(Stdio.Readline) Stdio.Readline(object infd,
object|string interm);

or
object(Stdio.Readline) Stdio.Readline(object infd,
object|string interm,
object outfd);

or
object(Stdio.Readline) Stdio.Readline(object infd,
object|string interm,
object outfd,
object|string outterm);

DESCRIPTION
Creates a Readline object, that takes input from infd, and has output on outfd.

infd defaults to Stdio.stdout.

interm defaults to Stdio.Terminfo.getTerm().

outfd defaults to infd, unless infd is 0, in which case outfd defaults to Stdio.stdout.

outterm defaults to interm.

9.8 Other Stdio functions

The Stdio module also contains a collection of high level IO functions to make it easy to write short and readable Pike programs. Most of these functions are implemented using Stdio.File and Stdio.FILE.

FUNCTION
Stdio.append_path - append paths in a secure way

SYNTAX
string append_path(string absolute, string ... relative);

DESCRIPTION
Append relative paths to an absolute path and remove any "//", "../" or "/." to produce a straightforward absolute path as a result. "../" is ignorded in the relative paths if it makes the created path begin with something else than the absolute path (or so far created path).

EXAMPLE
> Stdio.append_path("/foo/bar/","..");
Result: /foo/bar/
> Stdio.append_path("/foo/bar/","../apa.c");
Result: /foo/bar/apa.c
> Stdio.append_path("/foo/bar","./sune.c");
Result: /foo/bar/sune.c
> Stdio.append_path("/foo/bar","bertil/../../sune.c");
Result: /foo/bar/sune.c
> Stdio.append_path("/foo/bar","klas","bertil/../../sune.c");
Result: /foo/bar/klas/sune.c

SEE ALSO
combine_path

FUNCTION
Stdio.file_size - return the size of a file in bytes

SYNTAX
int file_size(string file);

DESCRIPTION
Give the size of a file. Size -1 indicates that the file either does not exist, or that it is not readable by you. Size -2 indicates that it is a directory.

SEE ALSO
Stdio.write_file and Stdio.read_bytes

FUNCTION
Stdio.exist - check if a path exists

SYNTAX
int exist(string path);

DESCRIPTION
Returns true if the given path exists (is a directory or file), otherwise false.

SEE ALSO
Stdio.is_dir, Stdio.is_file and Stdio.is_link

FUNCTION
Stdio.is_dir - check if a path is a directory

SYNTAX
int is_dir(string path);

DESCRIPTION
Returns true if the given path is a directory, otherwise false.

SEE ALSO
Stdio.exist, Stdio.is_file and Stdio.is_link

FUNCTION
Stdio.is_file - check if a path is a file

SYNTAX
int is_file(string path);

DESCRIPTION
Returns true if the given path is a file, otherwise false.

SEE ALSO
Stdio.exist, Stdio.is_dir and Stdio.is_link

FUNCTION
Stdio.is_link - check if a path is a symbolic link

SYNTAX
int is_link(string path);

DESCRIPTION
Returns true if the given path is a symbolic link, otherwise false.

SEE ALSO
Stdio.exist, Stdio.is_dir and Stdio.is_file

FUNCTION
Stdio.mkdirhier - make a directory hierarchy

SYNTAX
int mkdirhier(string pathname, void|int mode);

DESCRIPTION
Creates zero or more directories to ensure that the given pathname is a directory. Returns zero if it fails and nonzero if it is successful. If a mode is given, it's used for the new directories after being &'ed with the current umask (on OS'es that supports this).

SEE ALSO
mkdir

FUNCTION
Stdio.perror - print error

SYNTAX
void perror(string s);

DESCRIPTION
This function prints a message to stderr along with a description of what went wrong if available. It uses the system errno to find out what went wrong, so it is only applicable to IO errors.

SEE ALSO
Stdio.werror

FUNCTION
Stdio.read_bytes - read a number of bytes into a string from a file

SYNTAX
string read_bytes(string file,int start,int len);
string read_bytes(string file,int start);
string read_bytes(string file);

DESCRIPTION
Read len number of bytes from file file staring at byte start and return it as a string. If len is omitted, the rest of the file will be returned. If start is also omitted, the entire file will be returned.

SEE ALSO
Stdio.write_file

FUNCTION
Stdio.read_file - read a number of lines into a string from file

SYNTAX
string read_file(string file, int start, int len);
string read_file(string file);

DESCRIPTION
Read len lines from the file file after skipping start lines and return those lines as a string. If start and len are omitted the whole file is read.

SEE ALSO
Stdio.read_bytes and Stdio.write_file

FUNCTION
Stdio.readline - read a line from stdin

SYNTAX
string readline(string prompt);

DESCRIPTION
This function is gone. Use Stdio.Readline()->read instead.

SEE ALSO
Stdio.File

FUNCTION
Stdio.recursive_rm - remove a file or a directory tree recursively

SYNTAX
int recursive_rm(string path);

DESCRIPTION
Remove a file or directory a directory tree, return 0 if it fails. Nonzero otherwise.

SEE ALSO
rm

FUNCTION
Stdio.sendfile - send contents from one file to another

SYNTAX
object sendfile(array(string) headers,
object from, int offset, int len,
array(string) trailers,
object to);

or
object sendfile(array(string) headers,
object from, int offset, int len,
array(string) trailers,
object to,
function(int, mixed ...:void) callback,
mixed ... args);

DESCRIPTION
Sends headers followed by len bytes starting at offset from the file from followed by trailers to the file to. When completed callback is called with the total number of bytes sent as the first argument, followed by args.

Any of headers, from and trailers may be left out by setting them to 0.

Setting offset to -1 means send from the current position in from.

Setting len to -1 means send until from's end of file is reached.

NOTE
The sending is performed asynchronously, and may complete before the function returns.

For callback to be called, the backend must be active (ie main() must have returned -1).

In some cases, the backend must also be active for any sending to be performed at all.

SEE ALSO
Stdio.File->set_nonblocking

FUNCTION
Stdio.werror - write to stderr

SYNTAX
void werror(string s);

DESCRIPTION
Writes a message to stderr. Stderr is normally the console, even if the process output has been redirected to a file or pipe.

FUNCTION
Stdio.write_file - append a string to a file

SYNTAX
int write_file(string file, string str)

DESCRIPTION
Append the string str onto the file file. Returns number of bytes written.

SEE ALSO
Stdio.read_bytes

9.9 A simple example

Here is a simple example of how to use the Stdio-functions.

string grep(string indata, string needle)
{
    object out=Stdio.File(),in=Stdio.File();
    object process=
     Process.create_process(({"/bin/grep",needle}),
        (["stdin":out->pipe(),
        "stdout":in->pipe()]) );
    out->write(indata);
    out->close();
    process->wait();
    return in->read();
}
This function filters the indata through the UNIX-command /bin/grep and return the result.

9.10 A more complex example - a simple WWW server

As most of you know, WWW WWW (World Wide Web), works by using a client program which will fetch files from remote servers when asked. Usually by clicking a picture or text. This example is a program for the server which will send files to any computer that requests them. The protocol used to send the file is called HTTP. (Hyper-Text Transfer Protocol)

Usually WWW involves HTML. HTML (Hyper-Text Markup Language) is a way to write documents with embedded pictures and links to other pages. These links are normally displayed underlined and if you click them your WWW- browser will load whatever document that link leads to.

#!/usr/local/bin/pike
                
/* A very small httpd capable of fetching files only. * Written by Fredrik Hübinette as a demonstration of Pike. */
                
inherit Stdio.Port;
We inherit Stdio.Port into this program so we can bind a TCP socket to accept incoming connection. A socket is simply a number to separate communications to and from different programs on the same computer.

Next are some constants that will affect how uHTTPD will operate. This uses the preprocessor directive #define. The preprocessor is the first stage in the compiling process and can make textual processing of the code before it is compiled. As an example, after the first define below, all occurrences of 'BLOCK' will be replaced with 16060.

/* Amount of data moved in one operation */
#define BLOCK 16060
                
/* Where do we have the html files ? */
#define BASE "/usr/local/html/"
                
/* File to return when we can't find the file requested */
#define NOFILE "/user/local/html/nofile.html"
                
/* Port to open */
#define PORT 1905
A port is a destination for a TCP connection. It is simply a number on the local computer. 1905 is not the standard port for HTTP connections though, which means that if you want to access this WWW server from a browser you need to specify the port like this: http://my.host.my.domain:1905/

Next we declare a class called output_class. Later we will clone one instance of this class for each incoming HTTP connection.

class output_class
{
    inherit Stdio.File : socket;
    inherit Stdio.File : file;
Our new class inherits Stdio.File twice. To be able to separate them they are then named 'socket' and 'file'.

    int offset=0;
Then there is a global variable called offset which is initialized to zero. (Each instance of this class will have its own instance of this variable, so it is not truly global, but...) Note that the initialization is done when the class is cloned (or instantiated if you prefer C++ terminology).

Next we define the function write_callback(). Later the program will go into a 'waiting' state, until something is received to process, or until there is buffer space available to write output to. When that happens a callback will be called to do this. The write_callback() is called when there is buffer space available. In the following lines 'void' means that it does not return a value. Write callback will be used further down as a callback and will be called whenever there is room in the socket output buffer.

    void write_callback()
    {
        int written;
        string data;
The following line means: call seek in the inherited program 'file'.
        file::seek(offset);
Move the file pointer to the where we want to the position we want to read from. The file pointer is simply a location in the file, usually it is where the last read() ended and the next will begin. seek() can move this pointer to where we want it though.

        data=file::read(BLOCK);
Read BLOCK (16060) bytes from the file. If there are less that that left to read only that many bytes will be returned.

        if(strlen(data))
        {
If we managed to read something...

            written=socket::write(data);
... we try to write it to the socket.

            if(written >= 0)
            {
                offset+=written;
                return;
            }
Update offset if we managed to write to the socket without errors.

            werror("Error: "+socket::errno()+".\n");
        }
If something went wrong during writing, or there was nothing left to read we destruct this instance of this class.

        destruct(this_object());
    }
That was the end of write_callback()

Next we need a variable to buffer the input received in. We initialize it to an empty string.

    string input="";
And then we define the function that will be called when there is something in the socket input buffer. The first argument 'id' is declared as mixed, which means that it can contain any type of value. The second argument is the contents of the input buffer.

    void read_callback(mixed id,string data)
    {
        string cmd;
                
        input+=data;
Append data to the string input. Then we check if we have received a a complete line yet. If so we parse this and start outputting the file.

        if(sscanf(input,"%s %s%*[\012\015 \t]",cmd,input)>2)
        {
This sscanf is pretty complicated, but in essence it means: put the first word in 'input' in 'cmd' and the second in 'input' and return 2 if successful, 0 otherwise.

            if(cmd!="GET")
            {
                werror("Only method GET is supported.\n");
                destruct(this_object());
                return;
            }
If the first word isn't GET print an error message and terminate this instance of the program. (and thus the connection)
            sscanf(input,"%*[/]%s",input);
Remove the leading slash.

            input=BASE+combine_path("/",input);
Combine the requested file with the base of the HTML tree, this gives us a full filename beginning with a slash. The HTML tree is the directory on the server in which the HTML files are located. Normally all files in this directory can be accessed by anybody by using a WWW browser. So if a user requests 'index.html' then that file name is first added to BASE (/home/hubbe/www/html/ in this case) and if that file exists it will be returned to the browser.
            if(!file::open(input,"r"))
            {
Try opening the file in read-only mode. If this fails, try opening NOFILE instead. Opening the file will enable us to read it later.

if(!file::open(NOFILE,"r"))
{
If this fails too. Write an error message and destruct this object.

    werror("Couldn't find default file.\n");
    destruct(this_object());
    return;
}
            }
Ok, now we set up the socket so we can write the data back.
            socket::set_buffer(65536,"w");
Set the buffer size to 64 kilobytes.

            socket::set_nonblocking(0,write_callback,0);
Make it so that write_callback is called when it is time to write more data to the socket.

            write_callback();
Jump-start the writing.
        }
    }
That was the end of read_callback().

This function is called if the connection is closed while we are reading from the socket.

    void selfdestruct() { destruct(this_object()); }

This function is called when the program is instantiated. It is used to set up data the way we want it. Extra arguments to clone() will be sent to this function. In this case it is the object representing the new connection.

    void create(object f)
    {
        socket::assign(f);
We insert the data from the file f into 'socket'.

        socket::set_nonblocking(read_callback,0,selfdestruct);
Then we set up the callback functions and sets the file nonblocking. Nonblocking mode means that read() and write() will rather return that wait for I/O to finish. Then we sit back and wait for read_callback to be called.

    }
End of create()

};
End of the new class.

Next we define the function called when someone connects.

void accept_callback()
{
    object tmp_output;
This creates a local variable of type 'object'. An object variable can contain a clone of any program. Pike does not consider clones of different programs different types. This also means that function calls to objects have to be resolved at run time.

    tmp_output=accept();
The function accept clones a Stdio.File and makes this equal to the newly connected socket.

    if(!tmp_output) return;
If it failed we just return.

    output_class(tmp_output);
Otherwise we clone an instance of 'output_class' and let it take care of the connection. Each clone of output_class will have its own set of global variables, which will enable many connections to be active at the same time without data being mixed up. Note that the programs will not actually run simultaneously though.

    destruct(tmp_output);
Destruct the object returned by accept(), output_class has already copied the contents of this object.

}

Then there is main, the function that gets it all started.
int main(int argc, array(string) argv)
{
    werror("Starting minimal httpd\n");
Write an encouraging message to stderr.
    if(!bind(PORT, accept_callback))
    {
        werror("Failed to open socket (already bound?)\n");
        return 17;
    }

Bind PORT and set it up to call accept_callback as soon as someone connects to it. If the bind() fails we write an error message and return the 17 to indicate failure.
    return - 17; /* Keep going */
If everything went ok, we return -17, any negative value returned by main() means that the program WON'T exit, it will hang around waiting for events instead. (like someone connecting)
}
That's it, this simple program can be used as the basis for a simple WWW-server. Note that today most WWW servers are very complicated programs, and the above program can never replace a modern WWW server. However, it is very fast if you only want a couple of web pages and have a slow machine available for the server.


Previous chapter To contents Next chapter