]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/sendmail/libsm/io.html
Merge commit '850ef5ae11d69ea3381bd310f564f025fc8caea3'
[FreeBSD/FreeBSD.git] / contrib / sendmail / libsm / io.html
1 <html>
2 <head>
3 <title>libsm sm_io general overview</title>
4 </head>
5 <body>
6 <a href="index.html">Back to libsm overview</a>
7 <center>
8 <h1>libsm sm_io general overview</h1>
9 <br> $Id: io.html,v 1.3 2001-03-17 03:22:50 gshapiro Exp $
10 </center>
11 <h2> Introduction </h2>
12 <p>
13 The <i>sm_io</i> portion of the <i>libsm</i> library is similar to
14 the <i>stdio</i> library. It is derived from the Chris Torek version
15 of the <i>stdio</i> library (BSD). There are some key differences
16 described below between <i>sm_io</i> and <i>stdio</i> but many
17 similarities will be noticed.
18 </p>
19 <p>
20 A key difference between <i>stdio</i> and <i>sm_io</i> is that the
21 functional code that does the open, close, read, write, etc. on a file
22 can be different for different files. For example, with <i>stdio</i>
23 the functional code (read, write) is either the default supplied in the
24 library or a "programmer specified" set of functions set via
25 <i>sm_io_open()</i>. Whichever set of functions are specified <b>all</b>
26 open's, read's, write's, etc use the same set of functions. In contrast, with
27 <i>sm_io</i> a different set of functions can be specified with each
28 active file for read's, write's, etc. These different function sets
29 are identified as <b>file types</b> (see <tt>sm_io_open()</tt>). Each function
30 set can handle the actions directly, pass the action request to
31 another function set or do some work before passing it on to another function
32 set. The setting of a function set for a file type can be done for
33 a file type at any time (even after the type is open).
34 </p>
35 <p>
36 A second difference is the use of <a href="rpool.html"><b>rpools</b></a>.
37 An <b>rpool</b> is specified with the opening of a file
38 (<tt>sm_io_open()</tt>).
39 This allows of a file to be associated with an rpool so that when the
40 rpool is released the open file will be closed; the <tt>sm_io_open()</tt>
41 registers that <tt>sm_io_close()</tt> should be called when the rpool is
42 released.
43 </p>
44 <p>
45 A third difference is that the I/O functions take a <i>timeout</i>
46 argument. This allows the setting of a maximum amount of time allowable
47 for the I/O to be completed. This means the calling program does not need
48 to setup it's own timeout mechanism. NOTE: SIGALRM's should not be
49 active in the calling program when an I/O function with a <i>timeout</i>
50 is used.
51 </p>
52 <p>
53 When converting source code from <i>stdio</i> to <i>sm_io</i> be
54 very careful to NOTE: the arguments to functions have been rationalized.
55 That is, unlike <i>stdio</i>, all <i>sm_io</i> functions that
56 take a file pointer (SM_FILE_T *) argument have the file pointer
57 as the first argument. Also not all functions with <i>stdio</i> have
58 an identical matching <i>sm_io</i> API: the API list has been thinned
59 since a number of <i>stdio</i> API's overlapped in functionality.
60 Remember many functions also have a <i>timeout</i> argument added.
61 </p>
62 <p>
63 When a file is going to be opened, the file type is included with
64 <tt>sm_io_open()</tt>.
65 A file type is either one automatically included with the <i>sm_io</i>
66 library or one created by the program at runtime.
67 File types can be either buffered or unbuffered. When buffered the buffering
68 is either the builtin <i>sm_io</i> buffering or as done by the file type.
69 File types can be disk files, strings, TCP/IP connections or whatever
70 your imagination can come up with that can be read and/or written to.
71 </p>
72 <p>
73 Information about a particular file type or pointer can be obtained or set with
74 the <i>sm_io</i> "info" functions.
75 The <tt>sm_io_setinfo()</tt> and <tt>sm_io_getinfo()</tt> functions work on
76 an active file pointer.
77 </p>
78 <h2>Include files</h2>
79 <p>
80 There is one main include file for use with sm_io: <i>io.h</i>. Since the
81 use of <b>rpools</b> is specified with <tt>sm_io_open()</tt> an
82 <b>rpool</b> may
83 be created and thus <i>rpool.h</i> may need to be included as well
84 (before io.h).
85 </p>
86 <pre>
87 #include &lt;rpool.h&gt;
88 #include &lt;io.h&gt;
89 </pre>
90
91 <h2>Functions/API's</h2>
92 <p>
93 Below is a list of the functions for <i>sm_io</i> listed in
94 alphabetical order. Currently these functions return error codes
95 and set errno when appropriate. These (may?/will?) change to
96 raising exceptions later.
97 </p>
98 <pre>
99 <a href="#sm_io_autoflush">SM_FILE_T *sm_io_autoflush(SM_FILE_T *fp, SM_FILE_T *)</a>
100
101 <a href="#sm_io_automode">void sm_io_automode(SM_FILE_T *fp, SM_FILE_T *)</a>
102
103 <a href="#defaultapi">void sm_io_clearerr(SM_FILE_T *fp)</a>
104
105 <a href="#sm_io_close">int sm_io_close(SM_FILE_T *fp, int timeout)</a>
106
107 <a href="#defaultapi">int sm_io_dup(SM_FILE_T *fp)</a>
108
109 <a href="#defaultapi">int sm_io_eof(SM_FILE_T *fp)</a>
110
111 <a href="#defaultapi">int sm_io_error(SM_FILE_T *fp)</a>
112
113 <a href="#defaultapi">char * sm_io_fgets(SM_FILE_T *fp, int timeout, char *buf, int n)</a>
114
115 <a href="#defaultapi">int sm_io_flush(SM_FILE_T *fp, int timeout)</a>
116
117 <a href="#sm_io_fopen">int sm_io_fopen(char *pathname, int flags [, MODE_T mode])</a>
118
119 <a href="#defaultapi">int sm_io_fprintf(SM_FILE_T *fp, int timeout, const char *fmt, ...)</a>
120
121 <a href="#defaultapi">int sm_io_fputs(s, int, SM_FILE_T *fp)</a>
122
123 <a href="#defaultapi">int sm_io_fscanf(SM_FILE_T *fp, int timeout, char const *fmt, ...) </a>
124
125 <a href="#defaultapi">int sm_io_getc(SM_FILE_T *fp, int timeout)</a>
126
127 <a href="#sm_io_getinfo">void sm_io_getinfo(SM_FILE_T *sfp, int what, void *valp)</a>
128
129 <a href="#sm_io_open">SM_FILE_T * sm_io_open(SM_FILE_T type, int timeout, void *info, int flags, void *rpool)</a>
130
131 <a href="#defaultapi">int sm_io_purge(SM_FILE_T *fp)</a>
132
133 <a href="#defaultapi">int sm_io_putc(SM_FILE_T *fp, int timeout, int c)</a>
134
135 <a href="#defaultapi">size_t sm_io_read(SM_FILE_T *fp, int timeout, char *buf, size_t size)</a>
136
137 <a href="#sm_io_reopen">SM_FILE_T * sm_io_open(SM_FILE_T type, int timeout, void *info, int flags, void *rpool)</a>
138
139 <a href="#defaultapi">void sm_io_rewind(SM_FILE_T *fp, int timeout)</a>
140
141 <a href="#defaultapi">int sm_io_seek(SM_FILE_T *fp, off_t offset, int timeout, int whence)</a>
142
143 <a href="#sm_io_setinfo">void sm_io_setinfo(SM_FILE_T *sfp, int what, void *valp)</a>
144
145 <a href="#defaultapi">int sm_io_setvbuf(SM_FILE_T *fp, int timeout, char *buf, int mode, size_t size)</a>
146
147 <a href="#defaultapi">int sm_io_sscanf(const char *str, char const *fmt, ...)</a>
148
149 <a href="#defaultapi">long sm_io_tell(SM_FILE_T *fp, int timeout)</a>
150
151 <a href="#defaultapi">int sm_io_ungetc(SM_FILE_T *fp, int timeout, int c)</a>
152
153 <a href="#defaultapi">size_t sm_io_write(SM_FILE_T *fp, int timeout, char *buf, size_t size)</a>
154
155 <a href="#defaultapi">int sm_snprintf(char *str, size_t n, char const *fmt, ...)</a>
156
157 </pre>
158 <h2><a name="timeouts">Timeouts</a></h2>
159 <p>
160 For many of the functions a <i>timeout</i> argument is given. This limits
161 the amount of time allowed for the function to complete. There are three
162 pre-defined values:
163 <menu>
164 <li>
165 SM_TIME_DEFAULT - timeout using the default setting for this file type
166 </li>
167 <li>
168 SM_TIME_FOREVER - timeout will take forever; blocks until task completed
169 </li>
170 <li>
171 SM_TIME_IMMEDIATE - timeout (virtually) now
172 </li>
173 </menu>
174 </p>
175 <p>
176 A function caller can also specify a positive integer value in milliseconds.
177 A function will return with <i>errno</i> set to EINVAL if a bad value
178 is given for <i>timeout</i>.
179 When a function times out the function returns in error with <i>errno</i>
180 set to <b>EAGAIN</b>. In the future this may change to an exception being
181 thrown.
182 </p>
183 <h2>Function Descriptions</h2>
184 <dl>
185 <!-- SM_IO_FOPEN -->
186 <p></p>
187 <dt><tt><a name="sm_io_fopen">
188 SM_FILE_T *
189 <br>
190 sm_io_fopen(char *pathname, int flags)
191 <br>
192 SM_FILE_T *
193 <br>
194 sm_io_fopen(char *pathname, int flags, MODE_T mode)
195 </a></tt></dt>
196 <dd>
197 Open the file named by <tt>pathname</tt>, and associate a stream with it.
198 The arguments are the same as for the <tt>open(2)</tt> system call.
199 <br>
200 If memory could not be allocated, an exception is raised.
201 If successful, an <tt>SM_FILE_T</tt> pointer is returned.
202 Otherwise, <tt>NULL</tt> is returned and <tt>errno</tt> is set.
203 <!-- SM_IO_OPEN -->
204 <p></p>
205 <dt><tt><a name="sm_io_open">
206 SM_FILE_T *
207 <br>
208 sm_io_open(const SM_FILE_T *type, int timeout, const void *info, int flags, void *rpool)
209 </a></tt></dt>
210 <dd>
211 Opens a file by <i>type</i> directed by <i>info</i>. <i>Type</i> is a filled-in
212 SM_FILE_T structure from the following builtin list
213 (<a href="#builtins"><b>descriptions below</b></a>)
214 or one specified by the program. 
215 <menu>
216 <li>
217 SmFtString
218 </li>
219 <li>
220 SmFtStdio
221 </li>
222 <li>
223 SmFtStdiofd
224 </li>
225 <li>
226 smioin <b>*</b>
227 </li>
228 <li>
229 smioout <b>*</b>
230 </li>
231 <li>
232 smioerr <b>*</b>
233 </li>
234 <li>
235 smiostdin <b>*</b>
236 </li>
237 <li>
238 smiostdout <b>*</b>
239 </li>
240 <li>
241 smiostderr <b>*</b>
242 </li>
243 <li>
244 SmFtSyslog
245 </li>
246 </menu>
247 <br>
248 The above list of file types are already appropriately filled in. Those marked
249 with a "<b>*</b>" are already open and may be used directly and immediately.
250 For program specified types, to set the <i>type</i> argument easily and with minimal error the macro
251 <b>SM_IO_SET_TYPE</b> should be used. The SM_FILE_T structure is fairly
252 large, but only a small portion of it need to be initialized for a new
253 type.
254 See also <a href="#writefunctions">"Writing Functions for a File Type"</a>.
255 <menu>
256 <pre>
257 SM_IO_SET_TYPE(type, name, open, close, read, write, seek, get, set, timeout)
258 </pre>
259 </menu>
260 <br>
261 <i>Timeout</i> is set as described in the <a href="#timeouts"><b>Timeouts</b></a>
262 section.
263 <br>
264 <i>Info</i> is information that describes for the file type what is
265 to be opened and any associated information.
266 For a disk file this would be a file path; with a TCP
267 connection this could be an a structure containing an IP address and port.
268 <br><i>Flags</i> is a
269 set of sm_io flags that describes how the file is to be interacted with:
270 <menu>
271 <li>
272 SM_IO_RDWR      - read and write
273 </li>
274 <li>
275 SM_IO_RDONLY    - read only
276 </li>
277 <li>
278 SM_IO_WRONLY    - write only
279 </li>
280 <li>
281 SM_IO_APPEND    - allow write to EOF only
282 </li>
283 <li>
284 SM_IO_APPENDRW  - allow read-write from EOF only
285 </li>
286 <li>
287 SM_IO_RDWRTR    - read and write with truncation of file first
288 </li>
289 </menu>
290 <i>Rpool</i> is the address of the rpool that this open is to be associated
291 with. When the rpool is released then the close function for this
292 file type will be automatically called to close the file for cleanup.
293 If NULL is specified for <i>rpool</i> then the close function is not
294 associated (attached) to an rpool.
295 <br>
296 On cannot allocate memory, an exception is raised.
297 If the <i>type</i> is invalid, <tt>sm_io_open</tt> will abort the process.
298 On success an SM_FILE_T * pointer is returned.
299 On failure the NULL pointer is returned and errno is set.
300 </dd>
301 <!-- SM_IO_SETINFO -->
302 <p></p>
303 <dt><tt><a name="sm_io_setinfo">
304 int
305 <br>
306 sm_io_setinfo(SM_FILE_T *sfp, int what, void *valp)
307 </a></tt></dt>
308 <dd>
309 For the open file <i>sfp</i> set the indicated information (<i>what</i>)
310 to the new value <i>(valp</i>).
311 This will make the change for this SM_FILE_T only. The file
312 type that <i>sfp</i> originally belonged to will still be
313 configured the same way (this is to prevent side-effect
314 to other open's of the same file type, particularly with threads).
315 The value of <i>what</i> will be file-type dependent since this function
316 is one of the per file type setable functions.
317 One value for <i>what</i> that is valid for all file types is
318 SM_WHAT_VECTORS. This sets the currently open file with a new function
319 vector set for open, close, etc. The new values are taken from <i>valp</i>
320 a SM_FILE_T filled in by the used via the macro SM_IO_SET_TYPE
321 (see and <a href="#writefunctions">
322 "Writing Functions for a File Type"</a> for more information).
323 <br>
324 On success 0 (zero) is returned. On failure -1 is returned and errno is set.
325 </dd>
326 <!-- SM_IO_GETINFO -->
327 <p></p>
328 <dt><tt><a name="sm_io_getinfo">
329 int
330 <br>
331 sm_io_getinfo(SM_FILE_T *sfp, int what, void *valp)
332 </a></tt></dt>
333 <dd>
334 For the open file <i>sfp</i> get the indicated information (<i>what</i>)
335 and place the result in <i>(valp</i>).
336 This will obtain information for SM_FILE_T only and may be different than
337 the information for the file type it was originally opened as.
338 The value of <i>what</i> will be file type dependent since this function
339 is one of the per file type setable functions.
340 One value for <i>what</i> that is valid for all file types is
341 SM_WHAT_VECTORS. This gets from the currently open file a copy of
342 the function vectors and stores them in <i>valp</i> a SM_FILE_T
343 (see <a href="#writefunctions">
344 "Writing Functions for a File Type"</a> for more information).
345 <br>
346 On success 0 (zero) is returned. On failure -1 is returned and errno is set.
347 </dd>
348 <!-- SM_IO_AUTOFLUSH -->
349 <p></p>
350 <dt><tt><a name="sm_io_autoflush">
351 void
352 <br>
353 sm_io_autoflush(SM_FILE_T *fp1, *SM_FILE_T fp2)
354 </a></tt></dt>
355 <dd>
356 Associate a read of <i>fp1</i> with a data flush for <i>fp2</i>. If a read
357 of <i>fp1</i> discovers that there is no data available to be read, then
358 <i>fp2</i> will have it's data buffer flushed for writable data. It is
359 assumed that <i>fp1</i> is open for reading and <i>fp2</i> is open
360 for writing.
361 <br>
362 On return the old file pointer associated with <i>fp1</i> for flushing
363 is returned. A return of NULL is no an error; this merely indicates no
364 previous association.
365 </dd>
366 <!-- SM_IO_AUTOMODE -->
367 <p></p>
368 <dt><tt><a name="sm_io_automode">
369 void
370 <br>
371 sm_io_automode(SM_FILE_T *fp1, *SM_FILE_T fp2)
372 <dt>
373 </a></tt></dt>
374 <dd>
375 Associate the two file pointers for blocking/non-blocking mode changes.
376 In the handling of timeouts <i>sm_io</i> may need to switch the mode of
377 a file between blocking and non-blocking. If the underlying file descriptor
378 has been duplicated with <tt>dup(2)</tt> and these descriptors are used
379 by <i>sm_io</i> (for example with an SmFtStdiofd file type), then this API
380 should be called to associate them. Otherwise odd behavior (i.e. errors)
381 may result that is not consistently reproducible nor easily identifiable.
382 </dd>
383 <!-- SM_IO_CLOSE -->
384 <p></p>
385 <dt><tt><a name="sm_io_close">
386 int
387 <br>
388 sm_io_close(SM_FILE_T *sfp, int timeout)
389 </a></tt></dt>
390 <dd>
391 Release all resources (file handles, memory, etc.) associated with
392 the open SM_FILE_T <i>sfp</i>. If buffering is active then the
393 buffer is flushed before any resources are released.
394 <i>Timeout</i> is set as described in the <a href="#timeouts"><b>Timeouts</b></a>
395 section.
396 The first resources released after buffer flushing will be the
397 buffer itself. Then the <b>close</b> function specified in the
398 file type at open will be called. It is the responsibility
399 of the <b>close</b> function to release any file type
400 specific resources allocated and to call <tt>sm_io_close()</tt>
401 for the next file type layer(s) that the current file type uses (if any).
402 <br>
403 On success 0 (zero) is returned. On failure SM_IO_EOF is returned and
404 errno is set.
405 </dd>
406 </dl>
407 <h2>
408 <a name="builtins">Description of Builtin File Types</a>
409 </h2>
410 <p>
411 There are several builtin file types as mentioned in <tt>sm_io_open()</tt>.
412 More file types may be added later.
413 </p>
414 <dl>
415 <p></p>
416 <dt><tt>SmFtString</tt></dt>
417 <dd>
418 Operates on a character string. <i>SmFtString</i> is a file type only.
419 The string starts at the location 0 (zero)
420 and ends at the last character. A read will obtain the requested
421 number of characters if available; else as many as possible. A read
422 will not terminate the read characters with a NULL ('\0'). A write
423 will place the number of requested characters at the current location.
424 To append to a string either the pointer must currently be at the end
425 of the string or a seek done to position the pointer. The file type
426 handles the space needed for the string. Thus space needed for the
427 string will be grown automagically without the user worrying about
428 space management.
429 </dd>
430 <dt><tt>SmFtStdio</tt></dt>
431 <dd>
432 A predefined SM_FILE_T structure with function vectors pointing to
433 functions that result in the file-type behaving as the system stdio
434 normally does. The <i>info</i> portion of the <tt>sm_io_open</tt>
435 is the path of the file to be opened. Note that this file type
436 does not interact with the system's stdio. Thus a program mixing system
437 stdio and sm_io stdio (SmFtStdio) will result in uncoordinated input
438 and output.
439 </dd>
440 <dt><tt>SmFtStdiofd</tt></dt>
441 <dd>
442 A predefined SM_FILE_T structure with function vectors pointing to
443 functions that result in the file-type behaving as the system stdio
444 normally does. The <i>info</i> portion of the <tt>sm_io_open</tt>
445 is a file descriptor (the value returned by open(2)).  Note that this file type
446 does not interact with the system's stdio. Thus a program mixing system
447 stdio and sm_io stdio (SmFtStdio) will result in uncoordinated input
448 and output.
449 </dd>
450 <dt><tt>smioin</tt></dt>
451 <dt><tt>smioout</tt></dt>
452 <dt><tt>smioerr</tt></dt>
453 <dd>
454 The three types <i>smioin</i>, <i>smioout</i> and <i>smioerr</i> are grouped
455 together. These three types
456 perform in the same manner as <b>stdio</b>'s <i>stdin</i>, <i>stdout</i>
457 and <i>stderr</i>.  These types are both the names and the file pointers.
458 They are already open when a program starts (unless the parent explicitly
459 closed file descriptors 0, 1 and 2).
460 Thus <tt>sm_io_open()</tt> should never be called for these types:
461 the named file pointers should be used directly.
462 <i>Smioin</i> and <i>smioout</i> are buffered
463 by default. <i>Smioerr</i> is not buffered by default. Calls to <b>stdio</b>
464 are safe to make when using these three<b>sm_io</b> file pointers.
465 There is no interaction between <b>sm_io</b> and <b>stdio</b>. Hence,
466 due to buffering, the sequence of input and output data from both <b>sm_io</b>
467 and <b>stdio</b> at the same time may appear unordered. For
468 coordination between <b>sm_io</b> and <b>stdio</b> use the three
469 file pointers below (<i>smiostdin, smiostdout, smiostderr</i>).
470 </dd>
471 <dt><tt>smiostdin</tt></dt>
472 <dt><tt>smiostdout</tt></dt>
473 <dt><tt>smiostderr</tt></dt>
474 <dd>
475 The three types <i>smiostdin</i>, <i>smioostdut</i> and <i>smiostderr</i>
476 are grouped together. These three types
477 perform in the same manner as <b>stdio</b>'s <i>stdin</i>, <i>stdout</i>
478 and <i>stderr</i>.  These types are both the names and file pointers.
479 They are already open when a program starts (unless the parent explicitly
480 close file descriptors 0, 1 and 2).
481 Thus <tt>sm_io_open()</tt> should
482 never be called: the named file pointers should be used directly.
483 Calls to <b>stdio</b> are safe to make when using these three<b>sm_io</b>
484 file pointers though no code is shared between the two libraries.
485 However, the input and output between <i>sm_io</i> and <i>stdio</i> is
486 coordinated for these three file pointers: <i>smiostdin</i>,
487 <i>smiostdout</i> and <i>smiostderr</i> are layered on-top-of
488 the system's <i>stdio</i>.
489 <i>Smiostdin</i>, <i>smiostdout</i>
490 and <i>Smiostderr</i> are not buffered by default.
491 Hence, due to buffering in <i>stdio</i> only, the sequence of input and
492 output data from both <b>sm_io</b> and <b>stdio</b> at the same time will
493 appear ordered. If <i>sm_io</i> buffering is turned on then the
494 input and output can appear unordered or lost.
495 </dd>
496 <dt><tt>SmFtSyslog</tt></dt>
497 <dd>
498 This opens the channel to the system log. Reads are not allowed. Writes
499 cannot be undone once they have left the <i>sm_io</i> buffer.
500 The man pages for <tt>syslog(3)</tt> should be read for information
501 on syslog.
502 </dd>
503 </dl>
504 <p></p>
505 <hr>
506 <p></p>
507 <h2>
508 <a name="writefunctions">
509 Writing Functions for a File Type
510 </a>
511 </h2>
512 <p>
513 When writing functions to create a file type a function needs to
514 be created for each function vector in the SM_FILE_T structure
515 that will be passed to <tt>sm_io_open()</tt> or <tt>sm_io_setinfo()</tt>.
516 Otherwise the setting will be rejected and <i>errno</i> set to EINVAL.
517 Each function should accept and handle the number and types of arguments as
518 described in the portion of the SM_FILE_T structure shown below:
519 </p>
520 <pre>
521         int      (*open) __P((SM_FILE_T *fp, const void *, int flags,
522                               const void *rpool));
523         int      (*close) __P((SM_FILE_T *fp));
524         int      (*read)  __P((SM_FILE_T *fp, char *buf, size_t size));
525         int      (*write) __P((SM_FILE_T *fp, const char *buf, size_t size));
526         off_t    (*seek)  __P((SM_FILE_T *fp, off_t offset, int whence));
527         int      (*getinfo) __P((SM_FILE_T *fp, int what, void *valp));
528         int      (*setinfo) __P((SM_FILE_T *fp, int what, void *valp));
529 </pre>
530 <p>
531 The macro SM_IO_SET_TYPE should be used to initialized an SM_FILE_T as a file
532 type for an <tt>sm_io_open()</tt>:
533 <menu>
534 <pre>
535 SM_IO_SET_TYPE(type, name, open, close, read, write, seek, get, set, timeout)
536 </pre>
537 <br>
538 where:
539 <menu>
540 <li>
541 type    - is the SM_FILE_T being filled-in
542 </li>
543 <li>
544 name    - a human readable character string for human identification purposes
545 </li>
546 <li>
547 open    - the vector to the open function
548 </li>
549 <li>
550 close   - the vector to the close function
551 </li>
552 <li>
553 read    - the vector to the read function
554 </li>
555 <li>
556 write   - the vector to the write function
557 </li>
558 <li>
559 seek    - the vector to the seek function
560 </li>
561 <li>
562 set     - the vector to the set function
563 </li>
564 <li>
565 get     - the vector to the get function
566 </li>
567 <li>
568 timeout - the default to be used for a timeout when SM_TIME_DEFAULT specified
569 </li>
570 </menu>
571 </menu>
572 You should avoid trying to change or use the other structure members of the
573 SM_FILE_T. The file pointer content (internal structure members) of an active
574 file should only be set and observed with the "info" functions.
575 The two exceptions to the above statement are the structure members
576 <i>cookie</i> and <i>ival</i>. <i>Cookie</i> is of type <tt>void *</tt>
577 while <i>ival</i> is of type <tt>int</tt>.
578 These two structure members exist specifically
579 for your created file type to use.
580 The <i>sm_io</i> functions
581 will not change or set these two structure members;
582 only specific file type will change or set these variables.
583 </p>
584 <p>
585 For maintaining information privately about status for a file type the
586 information should be encapsulated in a <i>cookie</i>. A <i>cookie</i>
587 is an opaque type that contains information that is only known to
588 the file type layer itself. The <i>sm_io</i> package will know
589 nothing about the contents of the <i>cookie</i>; <i>sm_io</i> only
590 maintains the location of the <i>cookie</i> so that it may be passed
591 to the functions of a file type. It is up to the file type to
592 determine what to do with the <i>cookie</i>. It is the responsibility
593 of the file type's open to create the cookie and point the SM_FILE_T's
594 <i>cookie</i> at the address of the cookie.
595 It is the responsibility of close to clean up
596 any resources that the cookie and instance of the file type have used.
597 </p>
598 <p>
599 For the <i>cookie</i> to be passed to all members of a function type
600 cleanly the location of the cookie must assigned during
601 the call to open. The file type functions should not attempt to
602 maintain the <i>cookie</i> internally since the file type may have
603 several instances (file pointers).
604 </p>
605 <p>
606 The SM_FILE_T's member <i>ival</i> may be used in a manner similar to
607 <i>cookie</i>. It is not to be used for maintaining the file's offset
608 or access status (other members do that). It is intended as a "light"
609 reference.
610 </p>
611 <p>
612 The file type vector functions are called by the <tt>sm_io_*()</tt>
613 functions after <i>sm_io</i> processing has occurred. The <i>sm_io</i>
614 processing validates SM_FILE_T's and may then handle the call entirely
615 itself or pass the request to the file type vector functions.
616 </p>
617 <p>
618 All of the "int" functions should return -1 (minus one) on failure
619 and 0 (zero) or greater on success. <i>Errno</i> should be set to
620 provide diagnostic information to the caller if it has not already
621 been set by another function the file type function used.
622 </p>
623 <p>
624 Examples are a wonderful manner of clarifying details. Below is an example
625 of an open function.
626 </p>
627 <p>
628 This shows the setup.
629 <menu>
630 <pre>
631 SM_FILE_T *fp;
632 SM_FILE_T SM_IO_SET_TYPE(vector, "my_type", myopen, myclose, myread, mywrite,
633                                 myseek, myget, myset, SM_TIME_FOREVER);
634
635 fp = sm_io_open(&vector, 1000, "data", SM_IO_RDONLY, NULL);
636
637 if (fp == NULL)
638         return(-1);
639 </pre>
640 The above code open's a file of type "my_type". The <i>info</i> is set
641 to a string "data". "data" may be the name of a file or have some special
642 meaning to the file type. For sake of the example, we will have it be
643 the name of a file in the home directory of the user running the program.
644 Now the only file type function that is dependent on this information
645 will be the open function.
646 <br>
647 We have also specified read-only access (SM_IO_RDONLY) and that no <i>rpool</i>
648 will be used. The <i>timeout</i> has been set to 1000 milliseconds which
649 directs that the file and all associated setup should be done within
650 1000 milliseconds or return that the function erred (with errno==EAGAIN).
651 <pre>
652 int myopen(fp, info, flags, rpools)
653         SM_FILE_T *fp;
654         const void *info; 
655         int flags;
656         void *rpool;
657 {
658         /*
659         **  now we could do the open raw (i.e with read(2)), but we will
660         **  use file layering instead. We will use the <i>stdio</i> file
661         **  type (different than the system's stdio).
662         */
663         struct passwd *pw;
664         char path[PATH_MAX];
665
666         pw = getpwuid(getuid());
667         sm_io_snprintf(path, PATH_MAX, "%s/%s", pw->pw_dir, info);
668
669         /*
670         **  Okay. Now the path pass-in has been prefixed with the
671         **  user's HOME directory. We'll call the regular stdio (SmFtStdio)
672         **  now to handle the rest of the open.
673         */
674         fp->cookie = sm_io_open(SmFtStdio, path, flags, rpools);
675         if (fp->cookie == NULL)
676                 return(-1) /* errno set by sm_io_open call */
677         else
678                 return(0);
679 }
680 </pre>
681 Later on when a write is performed the function <tt>mywrite</tt> will
682 be invoked. To match the above <tt>myopen</tt>, <tt>mywrite</tt> could
683 be written as:
684 <pre>
685 int mywrite(fp, buf, size)
686         SM_FILE_T *fp;
687         char *buf;
688         size_t size;
689 {
690         /*
691         **  As an example, we can change, modify, refuse, filter, etc.
692         **  the content being passed through before we ask the SmFtStdio
693         **  to do the actual write.
694         **  This example is very simple and contrived, but this keeps it
695         **  clear.
696         */
697         if (size == 0)
698                 return(0); /* why waste the cycles? */
699         if (*buf == 'X')
700                 *buf = 'Y';
701
702         /*
703         **  Note that the file pointer passed to the next level is the
704         **  one that was stored in the cookie during the open.
705         */
706         return(sm_io_write(fp->cookie, buf, size));
707 }
708 </pre>
709 As a thought-exercise for the fair reader: how would you modify the
710 above two functions to make a "tee". That is the program will call
711 <tt>sm_io_open</tt> or <tt>sm_io_write</tt> and two or more files will
712 be opened and written to. (Hint: create a cookie to hold two or more
713 file pointers).
714 </menu>
715 </p>
716 <p></p>
717 <hr>
718 <br>
719 <hr>
720 <p></p>
721 <center>
722 <h1>
723 <a name="defaultapi">
724 libsm sm_io default API definition
725 </a>
726 </h1>
727 </center>
728 <h2> Introduction </h2>
729 <p>
730 A number of <i>sm_io</i> API's perform similar to their <i>stdio</i>
731 counterparts (same name as when the "sm_io_" is removed).
732 One difference between <i>sm_io</i> and <i>stdio</i> functions is that
733 if a "file pointer" (FILE/SM_FILE_T)
734 is one of the arguments for the function, then it is now the first
735 argument. <i>Sm_io</i> is standardized so that when a file pointer is
736 one of the arguments to function then it will always be the first
737 argument. Many of the <i>sm_io</i> function take a <i>timeout</i>
738 argument (see <a href="#timeouts"><b>Timeouts</b></a>).
739 </p>
740 <p>
741 The API you have selected is one of these. Please consult the
742 appropriate <i>stdio</i> man page for now.
743 </p>
744
745 </body>
746 </html>