diff options
Diffstat (limited to 'contrib/sendmail/libsm/io.html')
-rw-r--r-- | contrib/sendmail/libsm/io.html | 745 |
1 files changed, 745 insertions, 0 deletions
diff --git a/contrib/sendmail/libsm/io.html b/contrib/sendmail/libsm/io.html new file mode 100644 index 000000000000..5304d26236bd --- /dev/null +++ b/contrib/sendmail/libsm/io.html @@ -0,0 +1,745 @@ +<html> +<head> +<title>libsm sm_io general overview</title> +</head> +<body> +<a href="index.html">Back to libsm overview</a> +<center> +<h1>libsm sm_io general overview</h1> +<br> $Id: io.html,v 1.3 2001-03-17 03:22:50 gshapiro Exp $ +</center> +<h2> Introduction </h2> +<p> +The <i>sm_io</i> portion of the <i>libsm</i> library is similar to +the <i>stdio</i> library. It is derived from the Chris Torek version +of the <i>stdio</i> library (BSD). There are some key differences +described below between <i>sm_io</i> and <i>stdio</i> but many +similarities will be noticed. +</p> +<p> +A key difference between <i>stdio</i> and <i>sm_io</i> is that the +functional code that does the open, close, read, write, etc. on a file +can be different for different files. For example, with <i>stdio</i> +the functional code (read, write) is either the default supplied in the +library or a "programmer specified" set of functions set via +<i>sm_io_open()</i>. Whichever set of functions are specified <b>all</b> +open's, read's, write's, etc use the same set of functions. In contrast, with +<i>sm_io</i> a different set of functions can be specified with each +active file for read's, write's, etc. These different function sets +are identified as <b>file types</b> (see <tt>sm_io_open()</tt>). Each function +set can handle the actions directly, pass the action request to +another function set or do some work before passing it on to another function +set. The setting of a function set for a file type can be done for +a file type at any time (even after the type is open). +</p> +<p> +A second difference is the use of <a href="rpool.html"><b>rpools</b></a>. +An <b>rpool</b> is specified with the opening of a file +(<tt>sm_io_open()</tt>). +This allows of a file to be associated with an rpool so that when the +rpool is released the open file will be closed; the <tt>sm_io_open()</tt> +registers that <tt>sm_io_close()</tt> should be called when the rpool is +released. +</p> +<p> +A third difference is that the I/O functions take a <i>timeout</i> +argument. This allows the setting of a maximum amount of time allowable +for the I/O to be completed. This means the calling program does not need +to setup it's own timeout mechanism. NOTE: SIGALRM's should not be +active in the calling program when an I/O function with a <i>timeout</i> +is used. +</p> +<p> +When converting source code from <i>stdio</i> to <i>sm_io</i> be +very careful to NOTE: the arguments to functions have been rationalized. +That is, unlike <i>stdio</i>, all <i>sm_io</i> functions that +take a file pointer (SM_FILE_T *) argument have the file pointer +as the first argument. Also not all functions with <i>stdio</i> have +an identical matching <i>sm_io</i> API: the API list has been thinned +since a number of <i>stdio</i> API's overlapped in functionality. +Remember many functions also have a <i>timeout</i> argument added. +</p> +<p> +When a file is going to be opened, the file type is included with +<tt>sm_io_open()</tt>. +A file type is either one automatically included with the <i>sm_io</i> +library or one created by the program at runtime. +File types can be either buffered or unbuffered. When buffered the buffering +is either the builtin <i>sm_io</i> buffering or as done by the file type. +File types can be disk files, strings, TCP/IP connections or whatever +your imagination can come up with that can be read and/or written to. +</p> +<p> +Information about a particular file type or pointer can be obtained or set with +the <i>sm_io</i> "info" functions. +The <tt>sm_io_setinfo()</tt> and <tt>sm_io_getinfo()</tt> functions work on +an active file pointer. +</p> +<h2>Include files</h2> +<p> +There is one main include file for use with sm_io: <i>io.h</i>. Since the +use of <b>rpools</b> is specified with <tt>sm_io_open()</tt> an +<b>rpool</b> may +be created and thus <i>rpool.h</i> may need to be included as well +(before io.h). +</p> +<pre> +#include <rpool.h> +#include <io.h> +</pre> + +<h2>Functions/API's</h2> +<p> +Below is a list of the functions for <i>sm_io</i> listed in +alphabetical order. Currently these functions return error codes +and set errno when appropriate. These (may?/will?) change to +raising exceptions later. +</p> +<pre> +<a href="#sm_io_autoflush">SM_FILE_T *sm_io_autoflush(SM_FILE_T *fp, SM_FILE_T *)</a> + +<a href="#sm_io_automode">void sm_io_automode(SM_FILE_T *fp, SM_FILE_T *)</a> + +<a href="#defaultapi">void sm_io_clearerr(SM_FILE_T *fp)</a> + +<a href="#sm_io_close">int sm_io_close(SM_FILE_T *fp, int timeout)</a> + +<a href="#defaultapi">int sm_io_dup(SM_FILE_T *fp)</a> + +<a href="#defaultapi">int sm_io_eof(SM_FILE_T *fp)</a> + +<a href="#defaultapi">int sm_io_error(SM_FILE_T *fp)</a> + +<a href="#defaultapi">char * sm_io_fgets(SM_FILE_T *fp, int timeout, char *buf, int n)</a> + +<a href="#defaultapi">int sm_io_flush(SM_FILE_T *fp, int timeout)</a> + +<a href="#sm_io_fopen">int sm_io_fopen(char *pathname, int flags [, MODE_T mode])</a> + +<a href="#defaultapi">int sm_io_fprintf(SM_FILE_T *fp, int timeout, const char *fmt, ...)</a> + +<a href="#defaultapi">int sm_io_fputs(s, int, SM_FILE_T *fp)</a> + +<a href="#defaultapi">int sm_io_fscanf(SM_FILE_T *fp, int timeout, char const *fmt, ...) </a> + +<a href="#defaultapi">int sm_io_getc(SM_FILE_T *fp, int timeout)</a> + +<a href="#sm_io_getinfo">void sm_io_getinfo(SM_FILE_T *sfp, int what, void *valp)</a> + +<a href="#sm_io_open">SM_FILE_T * sm_io_open(SM_FILE_T type, int timeout, void *info, int flags, void *rpool)</a> + +<a href="#defaultapi">int sm_io_purge(SM_FILE_T *fp)</a> + +<a href="#defaultapi">int sm_io_putc(SM_FILE_T *fp, int timeout, int c)</a> + +<a href="#defaultapi">size_t sm_io_read(SM_FILE_T *fp, int timeout, char *buf, size_t size)</a> + +<a href="#sm_io_reopen">SM_FILE_T * sm_io_open(SM_FILE_T type, int timeout, void *info, int flags, void *rpool)</a> + +<a href="#defaultapi">void sm_io_rewind(SM_FILE_T *fp, int timeout)</a> + +<a href="#defaultapi">int sm_io_seek(SM_FILE_T *fp, off_t offset, int timeout, int whence)</a> + +<a href="#sm_io_setinfo">void sm_io_setinfo(SM_FILE_T *sfp, int what, void *valp)</a> + +<a href="#defaultapi">int sm_io_setvbuf(SM_FILE_T *fp, int timeout, char *buf, int mode, size_t size)</a> + +<a href="#defaultapi">int sm_io_sscanf(const char *str, char const *fmt, ...)</a> + +<a href="#defaultapi">long sm_io_tell(SM_FILE_T *fp, int timeout)</a> + +<a href="#defaultapi">int sm_io_ungetc(SM_FILE_T *fp, int timeout, int c)</a> + +<a href="#defaultapi">size_t sm_io_write(SM_FILE_T *fp, int timeout, char *buf, size_t size)</a> + +<a href="#defaultapi">int sm_snprintf(char *str, size_t n, char const *fmt, ...)</a> + +</pre> +<a name="timeouts"> +<h2>Timeouts</h2> +<p> +For many of the functions a <i>timeout</i> argument is given. This limits +the amount of time allowed for the function to complete. There are three +pre-defined values: +<menu> +<li> +SM_TIME_DEFAULT - timeout using the default setting for this file type +</li> +<li> +SM_TIME_FOREVER - timeout will take forever; blocks until task completed +</li> +<li> +SM_TIME_IMMEDIATE - timeout (virtually) now +</li> +</menu> +</p> +<p> +A function caller can also specify a positive integer value in milliseconds. +A function will return with <i>errno</i> set to EINVAL if a bad value +is given for <i>timeout</i>. +When a function times out the function returns in error with <i>errno</i> +set to <b>EAGAIN</b>. In the future this may change to an exception being +thrown. +</p> +<h2>Function Descriptions</h2> +<dl> +<!-- SM_IO_FOPEN --> +<p></p> +<dt><tt><a name="sm_io_fopen"> +SM_FILE_T * +<br> +sm_io_fopen(char *pathname, int flags) +<br> +SM_FILE_T * +<br> +sm_io_fopen(char *pathname, int flags, MODE_T mode) +</a></tt></dt> +<dd> +Open the file named by <tt>pathname</tt>, and associate a stream with it. +The arguments are the same as for the <tt>open(2)</tt> system call. +<br> +If memory could not be allocated, an exception is raised. +If successful, an <tt>SM_FILE_T</tt> pointer is returned. +Otherwise, <tt>NULL</tt> is returned and <tt>errno</tt> is set. +<!-- SM_IO_OPEN --> +<p></p> +<dt><tt><a name="sm_io_open"> +SM_FILE_T * +<br> +sm_io_open(const SM_FILE_T *type, int timeout, const void *info, int flags, void *rpool) +</a></tt></dt> +<dd> +Opens a file by <i>type</i> directed by <i>info</i>. <i>Type</i> is a filled-in +SM_FILE_T structure from the following builtin list +(<a href="#builtins"><b>descriptions below</b></a>) +or one specified by the program. +<menu> +<li> +SmFtString +</li> +<li> +SmFtStdio +</li> +<li> +SmFtStdiofd +</li> +<li> +smioin <b>*</b> +</li> +<li> +smioout <b>*</b> +</li> +<li> +smioerr <b>*</b> +</li> +<li> +smiostdin <b>*</b> +</li> +<li> +smiostdout <b>*</b> +</li> +<li> +smiostderr <b>*</b> +</li> +<li> +SmFtSyslog +</li> +</menu> +<br> +The above list of file types are already appropriately filled in. Those marked +with a "<b>*</b>" are already open and may be used directly and immediately. +For program specified types, to set the <i>type</i> argument easily and with minimal error the macro +<b>SM_IO_SET_TYPE</b> should be used. The SM_FILE_T structure is fairly +large, but only a small portion of it need to be initialized for a new +type. +See also <a href="#writefunctions">"Writing Functions for a File Type"</a>. +<menu> +<pre> +SM_IO_SET_TYPE(type, name, open, close, read, write, seek, get, set, timeout) +</pre> +</menu> +<br> +<i>Timeout</i> is set as described in the <a href="#timeouts"><b>Timeouts</b></a> +section. +<br> +<i>Info</i> is information that describes for the file type what is +to be opened and any associated information. +For a disk file this would be a file path; with a TCP +connection this could be an a structure containing an IP address and port. +<br><i>Flags</i> is a +set of sm_io flags that describes how the file is to be interacted with: +<menu> +<li> +SM_IO_RDWR - read and write +</li> +<li> +SM_IO_RDONLY - read only +</li> +<li> +SM_IO_WRONLY - write only +</li> +<li> +SM_IO_APPEND - allow write to EOF only +</li> +<li> +SM_IO_APPENDRW - allow read-write from EOF only +</li> +<li> +SM_IO_RDWRTR - read and write with truncation of file first +</li> +</menu> +<i>Rpool</i> is the address of the rpool that this open is to be associated +with. When the rpool is released then the close function for this +file type will be automatically called to close the file for cleanup. +If NULL is specified for <i>rpool</i> then the close function is not +associated (attached) to an rpool. +<br> +On cannot allocate memory, an exception is raised. +If the <i>type</i> is invalid, <tt>sm_io_open</tt> will abort the process. +On success an SM_FILE_T * pointer is returned. +On failure the NULL pointer is returned and errno is set. +</dd> +<!-- SM_IO_SETINFO --> +<p></p> +<dt><tt><a name="sm_io_setinfo"> +int +<br> +sm_io_setinfo(SM_FILE_T *sfp, int what, void *valp) +</a></tt></dt> +<dd> +For the open file <i>sfp</i> set the indicated information (<i>what</i>) +to the new value <i>(valp</i>). +This will make the change for this SM_FILE_T only. The file +type that <i>sfp</i> originally belonged to will still be +configured the same way (this is to prevent side-effect +to other open's of the same file type, particularly with threads). +The value of <i>what</i> will be file-type dependant since this function +is one of the per file type setable functions. +One value for <i>what</i> that is valid for all file types is +SM_WHAT_VECTORS. This sets the currently open file with a new function +vector set for open, close, etc. The new values are taken from <i>valp</i> +a SM_FILE_T filled in by the used via the macro SM_IO_SET_TYPE +(see and <a href="#writefunctions"> +"Writing Functions for a File Type"</a> for more information). +<br> +On success 0 (zero) is returned. On failure -1 is returned and errno is set. +</dd> +<!-- SM_IO_GETINFO --> +<p></p> +<dt><tt><a name="sm_io_getinfo"> +int +<br> +sm_io_getinfo(SM_FILE_T *sfp, int what, void *valp) +</a></tt></dt> +<dd> +For the open file <i>sfp</i> get the indicated information (<i>what</i>) +and place the result in <i>(valp</i>). +This will obtain information for SM_FILE_T only and may be different than +the information for the file type it was originally opened as. +The value of <i>what</i> will be file type dependant since this function +is one of the per file type setable functions. +One value for <i>what</i> that is valid for all file types is +SM_WHAT_VECTORS. This gets from the currently open file a copy of +the function vectors and stores them in <i>valp</i> a SM_FILE_T +(see <a href="#writefunctions"> +"Writing Functions for a File Type"</a> for more information). +<br> +On success 0 (zero) is returned. On failure -1 is returned and errno is set. +</dd> +<!-- SM_IO_AUTOFLUSH --> +<p></p> +<dt><tt><a name="sm_io_autoflush"> +void +<br> +sm_io_autoflush(SM_FILE_T *fp1, *SM_FILE_T fp2) +</a></tt></dt> +<dd> +Associate a read of <i>fp1</i> with a data flush for <i>fp2</i>. If a read +of <i>fp1</i> discovers that there is no data available to be read, then +<i>fp2</i> will have it's data buffer flushed for writable data. It is +assumed that <i>fp1</i> is open for reading and <i>fp2</i> is open +for writing. +<br> +On return the old file pointer associated with <i>fp1</i> for flushing +is returned. A return of NULL is no an error; this merely indicates no +previous association. +</dd> +<!-- SM_IO_AUTOMODE --> +<p></p> +<dt><tt><a name="sm_io_automode"> +void +<br> +sm_io_automode(SM_FILE_T *fp1, *SM_FILE_T fp2) +<dt><tt><a name="sm_io_automode"> +</a></tt></dt> +<dd> +Associate the two file pointers for blocking/non-blocking mode changes. +In the handling of timeouts <i>sm_io</i> may need to switch the mode of +a file between blocking and non-blocking. If the underlying file descriptor +has been duplicated with <tt>dup(2)</tt> and these descriptors are used +by <i>sm_io</i> (for example with an SmFtStdiofd file type), then this API +should be called to associate them. Otherwise odd behavior (i.e. errors) +may result that is not consistently reproducable nor easily identifiable. +</dd> +<!-- SM_IO_CLOSE --> +<p></p> +<dt><tt><a name="sm_io_close"> +int +<br> +sm_io_close(SM_FILE_T *sfp, int timeout) +</a></tt></dt> +<dd> +Release all resources (file handles, memory, etc.) associated with +the open SM_FILE_T <i>sfp</i>. If buffering is active then the +buffer is flushed before any resources are released. +<i>Timeout</i> is set as described in the <a href="#timeouts"><b>Timeouts</b></a> +section. +The first resources released after buffer flushing will be the +buffer itself. Then the <b>close</b> function specified in the +file type at open will be called. It is the responsibility +of the <b>close</b> function to release any file type +specific resources allocated and to call <tt>sm_io_close()</tt> +for the next file type layer(s) that the current file type uses (if any). +<br> +On success 0 (zero) is returned. On failure SM_IO_EOF is returned and +errno is set. +</dd> +</dl> +<h2> +<a name="builtins">Description of Builtin File Types</a> +</h2> +<p> +There are several builtin file types as mentioned in <tt>sm_io_open()</tt>. +More file types may be added later. +</p> +<dl> +<p></p> +<dt><tt>SmFtString</tt></dt> +<dd> +Operates on a character string. <i>SmFtString</i> is a file type only. +The string starts at the location 0 (zero) +and ends at the last character. A read will obtain the requested +number of characters if available; else as many as possible. A read +will not terminate the read characters with a NULL ('\0'). A write +will place the number of requested characters at the current location. +To append to a string either the pointer must currently be at the end +of the string or a seek done to position the pointer. The file type +handles the space needed for the string. Thus space needed for the +string will be grown automagically without the user worrying about +space management. +</dd> +<dt><tt>SmFtStdio</tt></dt> +<dd> +A predefined SM_FILE_T structure with function vectors pointing to +functions that result in the file-type behaving as the system stdio +normally does. The <i>info</i> portion of the <tt>sm_io_open</tt> +is the path of the file to be opened. Note that this file type +does not interact with the system's stdio. Thus a program mixing system +stdio and sm_io stdio (SmFtStdio) will result in uncoordinated input +and output. +</dd> +<dt><tt>SmFtStdiofd</tt></dt> +<dd> +A predefined SM_FILE_T structure with function vectors pointing to +functions that result in the file-type behaving as the system stdio +normally does. The <i>info</i> portion of the <tt>sm_io_open</tt> +is a file descriptor (the value returned by open(2)). Note that this file type +does not interact with the system's stdio. Thus a program mixing system +stdio and sm_io stdio (SmFtStdio) will result in uncoordinated input +and output. +</dd> +<dt><tt>smioin</tt></dt> +<dt><tt>smioout</tt></dt> +<dt><tt>smioerr</tt></dt> +<dd> +The three types <i>smioin</i>, <i>smioout</i> and <i>smioerr</i> are grouped +together. These three types +perform in the same manner as <b>stdio</b>'s <i>stdin</i>, <i>stdout</i> +and <i>stderr</i>. These types are both the names and the file pointers. +They are already open when a program starts (unless the parent explictly +closed file descriptors 0, 1 and 2). +Thus <tt>sm_io_open()</tt> should never be called for these types: +the named file pointers should be used directly. +<i>Smioin</i> and <i>smioout</i> are buffered +by default. <i>Smioerr</i> is not buffered by default. Calls to <b>stdio</b> +are safe to make when using these three<b>sm_io</b> file pointers. +There is no interaction between <b>sm_io</b> and <b>stdio</b>. Hence, +due to buffering, the sequence of input and output data from both <b>sm_io</b> +and <b>stdio</b> at the same time may appear unordered. For +coordination between <b>sm_io</b> and <b>stdio</b> use the three +file pointers below (<i>smiostdin, smiostdout, smiostderr</i>). +</dd> +<dt><tt>smiostdin</tt></dt> +<dt><tt>smiostdout</tt></dt> +<dt><tt>smiostderr</tt></dt> +<dd> +The three types <i>smiostdin</i>, <i>smioostdut</i> and <i>smiostderr</i> +are grouped together. These three types +perform in the same manner as <b>stdio</b>'s <i>stdin</i>, <i>stdout</i> +and <i>stderr</i>. These types are both the names and file pointers. +They are already open when a program starts (unless the parent explictly +close file descriptors 0, 1 and 2). +Thus <tt>sm_io_open()</tt> should +never be called: the named file pointers should be used directly. +Calls to <b>stdio</b> are safe to make when using these three<b>sm_io</b> +file pointers though no code is shared between the two libaries. +However, the input and output between <i>sm_io</i> and <i>stdio</i> is +coordinated for these three file pointers: <i>smiostdin</i>, +<i>smiostdout</i> and <i>smiostderr</i> are layered on-top-of +the system's <i>stdio</i>. +<i>Smiostdin</i>, <i>smiostdout</i> +and <i>Smiostderr</i> are not buffered by default. +Hence, due to buffering in <i>stdio</i> only, the sequence of input and +output data from both <b>sm_io</b> and <b>stdio</b> at the same time will +appear ordered. If <i>sm_io</i> buffering is turned on then the +input and output can appear unordered or lost. +</dd> +<dt><tt>SmFtSyslog</tt></dt> +<dd> +This opens the channel to the system log. Reads are not allowed. Writes +cannot be undone once they have left the <i>sm_io</i> buffer. +The man pages for <tt>syslog(3)</tt> should be read for information +on syslog. +</dd> +</dl> +<p></p> +<hr> +<p></p> +<h2> +<a name="writefunctions"> +Writing Functions for a File Type +</a> +</h2> +<p> +When writing functions to create a file type a function needs to +be created for each function vector in the SM_FILE_T structure +that will be passed to <tt>sm_io_open()</tt> or <tt>sm_io_setinfo()</tt>. +Otherwise the setting will be rejected and <i>errno</i> set to EINVAL. +Each function should accept and handle the number and types of arguments as +described in the portion of the SM_FILE_T structure shown below: +</p> +<pre> + int (*open) __P((SM_FILE_T *fp, const void *, int flags, + const void *rpool)); + int (*close) __P((SM_FILE_T *fp)); + int (*read) __P((SM_FILE_T *fp, char *buf, size_t size)); + int (*write) __P((SM_FILE_T *fp, const char *buf, size_t size)); + off_t (*seek) __P((SM_FILE_T *fp, off_t offset, int whence)); + int (*getinfo) __P((SM_FILE_T *fp, int what, void *valp)); + int (*setinfo) __P((SM_FILE_T *fp, int what, void *valp)); +</pre> +<p> +The macro SM_IO_SET_TYPE should be used to initialized an SM_FILE_T as a file +type for an <tt>sm_io_open()</tt>: +<menu> +<pre> +SM_IO_SET_TYPE(type, name, open, close, read, write, seek, get, set, timeout) +</pre> +<br> +where: +<menu> +<li> +type - is the SM_FILE_T being filled-in +</li> +<li> +name - a human readable character string for human identification purposes +</li> +<li> +open - the vector to the open function +</li> +<li> +close - the vector to the close function +</li> +<li> +read - the vector to the read function +</li> +<li> +write - the vector to the write function +</li> +<li> +seek - the vector to the seek function +</li> +<li> +set - the vector to the set function +</li> +<li> +get - the vector to the get function +</li> +<li> +timeout - the default to be used for a timeout when SM_TIME_DEFAULT specified +</li> +</menu> +</menu> +You should avoid trying to change or use the other structure members of the +SM_FILE_T. The file pointer content (internal structure members) of an active +file should only be set and observed with the "info" functions. +The two exceptions to the above statement are the structure members +<i>cookie</i> and <i>ival</i>. <i>Cookie</i> is of type <tt>void *</tt> +while <i>ival</i> is of type <tt>int</tt>. These two structure members exist +specificly for your created file type to use. The <i>sm_io</i> functions +will not change or set these two structure members; only specific file type +will change or set these variables. +</p> +<p> +For maintaining information privately about status for a file type the +information should be encapsulated in a <i>cookie</i>. A <i>cookie</i> +is an opaque type that contains information that is only known to +the file type layer itself. The <i>sm_io</i> package will know +nothing about the contents of the <i>cookie</i>; <i>sm_io</i> only +maintains the location of the <i>cookie</i> so that it may be passed +to the functions of a file type. It is up to the file type to +determine what to do with the <i>cookie</i>. It is the responsibility +of the file type's open to create the cookie and point the SM_FILE_T's +<i>cookie</i> at the address of the cookie. +It is the responsibility of close to clean up +any resources that the cookie and instance of the file type have used. +</p> +<p> +For the <i>cookie</i> to be passed to all members of a function type +cleanly the location of the cookie must assigned during +the call to open. The file type functions should not attempt to +maintain the <i>cookie</i> internally since the file type may have +serveral instances (file pointers). +</p> +<p> +The SM_FILE_T's member <i>ival</i> may be used in a manner similar to +<i>cookie</i>. It is not to be used for maintaining the file's offset +or access status (other members do that). It is intended as a "light" +reference. +</p> +<p> +The file type vector functions are called by the <tt>sm_io_*()</tt> +functions after <i>sm_io</i> processing has occurred. The <i>sm_io</i> +processing validates SM_FILE_T's and may then handle the call entirely +itself or pass the request to the file type vector functions. +</p> +<p> +All of the "int" functions should return -1 (minus one) on failure +and 0 (zero) or greater on success. <i>Errno</i> should be set to +provide diagnostic information to the caller if it has not already +been set by another function the file type function used. +</p> +<p> +Examples are a wonderful manner of clarifying details. Below is an example +of an open function. +</p> +<p> +This shows the setup. +<menu> +<pre> +SM_FILE_T *fp; +SM_FILE_T SM_IO_SET_TYPE(vector, "my_type", myopen, myclose, myread, mywrite, + myseek, myget, myset, SM_TIME_FOREVER); + +fp = sm_io_open(&vector, 1000, "data", SM_IO_RDONLY, NULL); + +if (fp == NULL) + return(-1); +</pre> +The above code open's a file of type "my_type". The <i>info</i> is set +to a string "data". "data" may be the name of a file or have some special +meaning to the file type. For sake of the example, we will have it be +the name of a file in the home directory of the user running the program. +Now the only file type function that is dependent on this information +will be the open function. +<br> +We have also specified read-only access (SM_IO_RDONLY) and that no <i>rpool</i> +will be used. The <i>timeout</i> has been set to 1000 milliseconds which +directs that the file and all associated setup should be done within +1000 milliseconds or return that the function erred (with errno==EAGAIN). +<pre> +int myopen(fp, info, flags, rpools) + SM_FILE_T *fp; + const void *info; + int flags; + void *rpool; +{ + /* + ** now we could do the open raw (i.e with read(2)), but we will + ** use file layering instead. We will use the <i>stdio</i> file + ** type (different than the system's stdio). + */ + struct passwd *pw; + char path[PATH_MAX]; + + pw = getpwuid(getuid()); + sm_io_snprintf(path, PATH_MAX, "%s/%s", pw->pw_dir, info); + + /* + ** Okay. Now the path pass-in has been prefixed with the + ** user's HOME directory. We'll call the regular stdio (SmFtStdio) + ** now to handle the rest of the open. + */ + fp->cookie = sm_io_open(SmFtStdio, path, flags, rpools); + if (fp->cookie == NULL) + return(-1) /* errno set by sm_io_open call */ + else + return(0); +} +</pre> +Later on when a write is performed the function <tt>mywrite</tt> will +be invoked. To match the above <tt>myopen</tt>, <tt>mywrite</tt> could +be written as: +<pre> +int mywrite(fp, buf, size) + SM_FILE_T *fp; + char *buf; + size_t size; +{ + /* + ** As an example, we can change, modify, refuse, filter, etc. + ** the content being passed through before we ask the SmFtStdio + ** to do the actual write. + ** This example is very simple and contrived, but this keeps it + ** clear. + */ + if (size == 0) + return(0); /* why waste the cycles? */ + if (*buf == 'X') + *buf = 'Y'; + + /* + ** Note that the file pointer passed to the next level is the + ** one that was stored in the cookie during the open. + */ + return(sm_io_write(fp->cookie, buf, size)); +} +</pre> +As a thought-exercise for the fair reader: how would you modify the +above two functions to make a "tee". That is the program will call +<tt>sm_io_open</tt> or <tt>sm_io_write</tt> and two or more files will +be opened and written to. (Hint: create a cookie to hold two or more +file pointers). +</menu> +</p> +<p></p> +<hr> +<br> +<hr> +<p></p> +<center> +<h1> +<a name="defaultapi"> +libsm sm_io default API definition +</a> +</h1> +</center> +<h2> Introduction </h2> +<p> +A number of <i>sm_io</i> API's perform similar to their <i>stdio</i> +counterparts (same name as when the "sm_io_" is removed). +One difference between <i>sm_io</i> and <i>stdio</i> functions is that +if a "file pointer" (FILE/SM_FILE_T) +is one of the arguments for the function, then it is now the first +argument. <i>Sm_io</i> is standardized so that when a file pointer is +one of the arguments to function then it will always be the first +arguement. Many of the <i>sm_io</i> function take a <i>timeout</i> +argument (see <a href="#timeouts"><b>Timeouts</b></a>). +</p> +<p> +The API you have selected is one of these. Please consult the +appropriate <i>stdio</i> man page for now. +</p> + +</body> +</html> |