Deleted Added
full compact
findfp.c (90792) findfp.c (94334)
1/*
2 * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Chris Torek.
9 *
10 * By using this file, you agree to the terms and conditions set
11 * forth in the LICENSE file which can be found at the top level of
12 * the sendmail distribution.
13 */
14
15#include <sm/gen.h>
1/*
2 * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Chris Torek.
9 *
10 * By using this file, you agree to the terms and conditions set
11 * forth in the LICENSE file which can be found at the top level of
12 * the sendmail distribution.
13 */
14
15#include <sm/gen.h>
16SM_RCSID("@(#)$Id: findfp.c,v 1.62 2002/01/11 16:33:03 ca Exp $")
16SM_RCSID("@(#)$Id: findfp.c,v 1.66 2002/02/20 02:40:24 ca Exp $")
17#include <stdlib.h>
18#include <unistd.h>
19#include <sys/param.h>
20#include <errno.h>
21#include <string.h>
22#include <syslog.h>
23#include <sm/io.h>
24#include <sm/assert.h>
25#include <sm/heap.h>
26#include <sm/string.h>
27#include <sm/conf.h>
28#include "local.h"
29#include "glue.h"
30
31bool Sm_IO_DidInit; /* IO system has been initialized? */
32
33const char SmFileMagic[] = "sm_file";
34
35/* An open type to map to fopen()-like behavior */
36SM_FILE_T SmFtStdio_def =
37 {SmFileMagic, 0, 0, 0, (SMRW|SMFBF), -1, {0, 0}, 0, 0, 0,
38 sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite,
39 sm_stdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER,
40 SM_TIME_BLOCK, "stdio" };
41
42/* An open type to map to fdopen()-like behavior */
43SM_FILE_T SmFtStdiofd_def =
44 {SmFileMagic, 0, 0, 0, (SMRW|SMFBF), -1, {0, 0}, 0, 0, 0,
45 sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite,
46 sm_stdfdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER,
47 SM_TIME_BLOCK, "stdiofd" };
48
49/* A string file type */
17#include <stdlib.h>
18#include <unistd.h>
19#include <sys/param.h>
20#include <errno.h>
21#include <string.h>
22#include <syslog.h>
23#include <sm/io.h>
24#include <sm/assert.h>
25#include <sm/heap.h>
26#include <sm/string.h>
27#include <sm/conf.h>
28#include "local.h"
29#include "glue.h"
30
31bool Sm_IO_DidInit; /* IO system has been initialized? */
32
33const char SmFileMagic[] = "sm_file";
34
35/* An open type to map to fopen()-like behavior */
36SM_FILE_T SmFtStdio_def =
37 {SmFileMagic, 0, 0, 0, (SMRW|SMFBF), -1, {0, 0}, 0, 0, 0,
38 sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite,
39 sm_stdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER,
40 SM_TIME_BLOCK, "stdio" };
41
42/* An open type to map to fdopen()-like behavior */
43SM_FILE_T SmFtStdiofd_def =
44 {SmFileMagic, 0, 0, 0, (SMRW|SMFBF), -1, {0, 0}, 0, 0, 0,
45 sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite,
46 sm_stdfdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER,
47 SM_TIME_BLOCK, "stdiofd" };
48
49/* A string file type */
50SM_FILE_T _SmFtString_def =
50SM_FILE_T SmFtString_def =
51 {SmFileMagic, 0, 0, 0, (SMRW|SMNBF), -1, {0, 0}, 0, 0, 0,
52 sm_strclose, sm_strread, sm_strseek, sm_strwrite,
53 sm_stropen, sm_strsetinfo, sm_strgetinfo, SM_TIME_FOREVER,
54 SM_TIME_BLOCK, "string" };
55
56#if 0
57/* A file type for syslog communications */
58SM_FILE_T SmFtSyslog_def =
59 {SmFileMagic, 0, 0, 0, (SMRW|SMNBF), -1, {0, 0}, 0, 0, 0,
60 sm_syslogclose, sm_syslogread, sm_syslogseek, sm_syslogwrite,
61 sm_syslogopen, sm_syslogsetinfo, sm_sysloggetinfo, SM_TIME_FOREVER,
62 SM_TIME_BLOCK, "syslog" };
63#endif /* 0 */
64
65#define NDYNAMIC 10 /* add ten more whenever necessary */
66
67#define smio(flags, file, name) \
68 {SmFileMagic, 0, 0, 0, flags, file, {0}, 0, SmIoF+file, 0, \
69 sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite, \
70 sm_stdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER, \
71 SM_TIME_BLOCK, name}
72
73/* sm_magic p r w flags file bf lbfsize cookie ival */
74#define smstd(flags, file, name) \
75 {SmFileMagic, 0, 0, 0, flags, -1, {0}, 0, 0, file, \
76 sm_stdioclose, sm_stdioread, sm_stdioseek, sm_stdiowrite, \
77 sm_stdioopen, sm_stdiosetinfo, sm_stdiogetinfo, SM_TIME_FOREVER,\
78 SM_TIME_BLOCK, name}
79
80/* A file type for interfacing to stdio FILE* streams. */
81SM_FILE_T SmFtRealStdio_def = smstd(SMRW|SMNBF, -1, "realstdio");
82
83 /* the usual - (stdin + stdout + stderr) */
84static SM_FILE_T usual[SM_IO_OPEN_MAX - 3];
85static struct sm_glue smuglue = { 0, SM_IO_OPEN_MAX - 3, usual };
86
87/* List of builtin automagically already open file pointers */
88SM_FILE_T SmIoF[6] =
89{
90 smio(SMRD|SMLBF, SMIOIN_FILENO, "smioin"), /* smioin */
91 smio(SMWR|SMLBF, SMIOOUT_FILENO, "smioout"), /* smioout */
92 smio(SMWR|SMNBF, SMIOERR_FILENO, "smioerr"), /* smioerr */
93 smstd(SMRD|SMNBF, SMIOIN_FILENO, "smiostdin"), /* smiostdin */
94 smstd(SMWR|SMNBF, SMIOOUT_FILENO, "smiostdout"),/* smiostdout */
95 smstd(SMWR|SMNBF, SMIOERR_FILENO, "smiostderr") /* smiostderr */
96};
97
98/* Structure containing list of currently open file pointers */
99struct sm_glue smglue = { &smuglue, 3, SmIoF };
100
101/*
102** SM_MOREGLUE -- adds more space for open file pointers
103**
104** Parameters:
105** n -- number of new spaces for file pointers
106**
107** Returns:
108** Raises an exception if no more memory.
109** Otherwise, returns a pointer to new spaces.
110*/
111
112static struct sm_glue *sm_moreglue_x __P((int));
113static SM_FILE_T empty;
114
115static struct sm_glue *
116sm_moreglue_x(n)
117 register int n;
118{
119 register struct sm_glue *g;
120 register SM_FILE_T *p;
121
51 {SmFileMagic, 0, 0, 0, (SMRW|SMNBF), -1, {0, 0}, 0, 0, 0,
52 sm_strclose, sm_strread, sm_strseek, sm_strwrite,
53 sm_stropen, sm_strsetinfo, sm_strgetinfo, SM_TIME_FOREVER,
54 SM_TIME_BLOCK, "string" };
55
56#if 0
57/* A file type for syslog communications */
58SM_FILE_T SmFtSyslog_def =
59 {SmFileMagic, 0, 0, 0, (SMRW|SMNBF), -1, {0, 0}, 0, 0, 0,
60 sm_syslogclose, sm_syslogread, sm_syslogseek, sm_syslogwrite,
61 sm_syslogopen, sm_syslogsetinfo, sm_sysloggetinfo, SM_TIME_FOREVER,
62 SM_TIME_BLOCK, "syslog" };
63#endif /* 0 */
64
65#define NDYNAMIC 10 /* add ten more whenever necessary */
66
67#define smio(flags, file, name) \
68 {SmFileMagic, 0, 0, 0, flags, file, {0}, 0, SmIoF+file, 0, \
69 sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite, \
70 sm_stdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER, \
71 SM_TIME_BLOCK, name}
72
73/* sm_magic p r w flags file bf lbfsize cookie ival */
74#define smstd(flags, file, name) \
75 {SmFileMagic, 0, 0, 0, flags, -1, {0}, 0, 0, file, \
76 sm_stdioclose, sm_stdioread, sm_stdioseek, sm_stdiowrite, \
77 sm_stdioopen, sm_stdiosetinfo, sm_stdiogetinfo, SM_TIME_FOREVER,\
78 SM_TIME_BLOCK, name}
79
80/* A file type for interfacing to stdio FILE* streams. */
81SM_FILE_T SmFtRealStdio_def = smstd(SMRW|SMNBF, -1, "realstdio");
82
83 /* the usual - (stdin + stdout + stderr) */
84static SM_FILE_T usual[SM_IO_OPEN_MAX - 3];
85static struct sm_glue smuglue = { 0, SM_IO_OPEN_MAX - 3, usual };
86
87/* List of builtin automagically already open file pointers */
88SM_FILE_T SmIoF[6] =
89{
90 smio(SMRD|SMLBF, SMIOIN_FILENO, "smioin"), /* smioin */
91 smio(SMWR|SMLBF, SMIOOUT_FILENO, "smioout"), /* smioout */
92 smio(SMWR|SMNBF, SMIOERR_FILENO, "smioerr"), /* smioerr */
93 smstd(SMRD|SMNBF, SMIOIN_FILENO, "smiostdin"), /* smiostdin */
94 smstd(SMWR|SMNBF, SMIOOUT_FILENO, "smiostdout"),/* smiostdout */
95 smstd(SMWR|SMNBF, SMIOERR_FILENO, "smiostderr") /* smiostderr */
96};
97
98/* Structure containing list of currently open file pointers */
99struct sm_glue smglue = { &smuglue, 3, SmIoF };
100
101/*
102** SM_MOREGLUE -- adds more space for open file pointers
103**
104** Parameters:
105** n -- number of new spaces for file pointers
106**
107** Returns:
108** Raises an exception if no more memory.
109** Otherwise, returns a pointer to new spaces.
110*/
111
112static struct sm_glue *sm_moreglue_x __P((int));
113static SM_FILE_T empty;
114
115static struct sm_glue *
116sm_moreglue_x(n)
117 register int n;
118{
119 register struct sm_glue *g;
120 register SM_FILE_T *p;
121
122 g = (struct sm_glue *) sm_pmalloc_x(sizeof(*g) + ALIGNBYTES +
122 g = (struct sm_glue *) sm_pmalloc_x(sizeof(*g) + SM_ALIGN_BITS +
123 n * sizeof(SM_FILE_T));
123 n * sizeof(SM_FILE_T));
124 p = (SM_FILE_T *) ALIGN(g + 1);
124 p = (SM_FILE_T *) SM_ALIGN(g + 1);
125 g->gl_next = NULL;
126 g->gl_niobs = n;
127 g->gl_iobs = p;
128 while (--n >= 0)
129 *p++ = empty;
130 return g;
131}
132
133/*
134** SM_FP -- allocate and initialize an SM_FILE structure
135**
136** Parameters:
137** t -- file type requested to be opened.
138** flags -- control flags for file type behavior
139** oldfp -- file pointer to reuse if available (optional)
140**
141** Returns:
142** Raises exception on memory exhaustion.
143** Aborts if type is invalid.
144** Otherwise, returns file pointer for requested file type.
145*/
146
147SM_FILE_T *
148sm_fp(t, flags, oldfp)
149 const SM_FILE_T *t;
150 const int flags;
151 SM_FILE_T *oldfp;
152{
153 register SM_FILE_T *fp;
154 register int n;
155 register struct sm_glue *g;
156
157 SM_REQUIRE(t->f_open && t->f_close && (t->f_read || t->f_write));
158
159 if (!Sm_IO_DidInit)
160 sm_init();
161
162 if (oldfp != NULL)
163 {
164 fp = oldfp;
165 goto found; /* for opening reusing an 'fp' */
166 }
167
168 for (g = &smglue;; g = g->gl_next)
169 {
170 for (fp = g->gl_iobs, n = g->gl_niobs; --n >= 0; fp++)
171 if (fp->sm_magic == NULL)
172 goto found;
173 if (g->gl_next == NULL)
174 g->gl_next = sm_moreglue_x(NDYNAMIC);
175 }
176found:
177 fp->sm_magic = SmFileMagic; /* 'fp' now valid and in-use */
178 fp->f_p = NULL; /* no current pointer */
179 fp->f_w = 0; /* nothing to write */
180 fp->f_r = 0; /* nothing to read */
181 fp->f_flags = flags;
182 fp->f_file = -1; /* no file */
183 fp->f_bf.smb_base = NULL; /* no buffer */
184 fp->f_bf.smb_size = 0; /* no buffer size with no buffer */
185 fp->f_lbfsize = 0; /* not line buffered */
186 fp->f_flushfp = NULL; /* no associated flush file */
187
188 fp->f_cookie = fp; /* default: *open* overrides cookie setting */
189 fp->f_close = t->f_close; /* assign close function */
190 fp->f_read = t->f_read; /* assign read function */
191 fp->f_seek = t->f_seek; /* assign seek function */
192 fp->f_write = t->f_write; /* assign write function */
193 fp->f_open = t->f_open; /* assign open function */
194 fp->f_setinfo = t->f_setinfo; /* assign setinfo function */
195 fp->f_getinfo = t->f_getinfo; /* assign getinfo function */
196 fp->f_type = t->f_type; /* file type */
125 g->gl_next = NULL;
126 g->gl_niobs = n;
127 g->gl_iobs = p;
128 while (--n >= 0)
129 *p++ = empty;
130 return g;
131}
132
133/*
134** SM_FP -- allocate and initialize an SM_FILE structure
135**
136** Parameters:
137** t -- file type requested to be opened.
138** flags -- control flags for file type behavior
139** oldfp -- file pointer to reuse if available (optional)
140**
141** Returns:
142** Raises exception on memory exhaustion.
143** Aborts if type is invalid.
144** Otherwise, returns file pointer for requested file type.
145*/
146
147SM_FILE_T *
148sm_fp(t, flags, oldfp)
149 const SM_FILE_T *t;
150 const int flags;
151 SM_FILE_T *oldfp;
152{
153 register SM_FILE_T *fp;
154 register int n;
155 register struct sm_glue *g;
156
157 SM_REQUIRE(t->f_open && t->f_close && (t->f_read || t->f_write));
158
159 if (!Sm_IO_DidInit)
160 sm_init();
161
162 if (oldfp != NULL)
163 {
164 fp = oldfp;
165 goto found; /* for opening reusing an 'fp' */
166 }
167
168 for (g = &smglue;; g = g->gl_next)
169 {
170 for (fp = g->gl_iobs, n = g->gl_niobs; --n >= 0; fp++)
171 if (fp->sm_magic == NULL)
172 goto found;
173 if (g->gl_next == NULL)
174 g->gl_next = sm_moreglue_x(NDYNAMIC);
175 }
176found:
177 fp->sm_magic = SmFileMagic; /* 'fp' now valid and in-use */
178 fp->f_p = NULL; /* no current pointer */
179 fp->f_w = 0; /* nothing to write */
180 fp->f_r = 0; /* nothing to read */
181 fp->f_flags = flags;
182 fp->f_file = -1; /* no file */
183 fp->f_bf.smb_base = NULL; /* no buffer */
184 fp->f_bf.smb_size = 0; /* no buffer size with no buffer */
185 fp->f_lbfsize = 0; /* not line buffered */
186 fp->f_flushfp = NULL; /* no associated flush file */
187
188 fp->f_cookie = fp; /* default: *open* overrides cookie setting */
189 fp->f_close = t->f_close; /* assign close function */
190 fp->f_read = t->f_read; /* assign read function */
191 fp->f_seek = t->f_seek; /* assign seek function */
192 fp->f_write = t->f_write; /* assign write function */
193 fp->f_open = t->f_open; /* assign open function */
194 fp->f_setinfo = t->f_setinfo; /* assign setinfo function */
195 fp->f_getinfo = t->f_getinfo; /* assign getinfo function */
196 fp->f_type = t->f_type; /* file type */
197 fp->f_self = fp; /* self reference for future use */
198
199 fp->f_ub.smb_base = NULL; /* no ungetc buffer */
200 fp->f_ub.smb_size = 0; /* no size for no ungetc buffer */
201
197
198 fp->f_ub.smb_base = NULL; /* no ungetc buffer */
199 fp->f_ub.smb_size = 0; /* no size for no ungetc buffer */
200
202 fp->f_lb.smb_base = NULL; /* no line buffer */
203 fp->f_lb.smb_size = 0; /* no size for no line buffer */
204 if (fp->f_timeout == SM_TIME_DEFAULT)
205 fp->f_timeout = SM_TIME_FOREVER;
206 else
207 fp->f_timeout = t->f_timeout; /* traditional behavior */
208 fp->f_timeoutstate = SM_TIME_BLOCK; /* by default */
209
210 return fp;
211}
212
213/*
214** SM_CLEANUP -- cleanup function when exit called.
215**
216** This function is registered via atexit().
217**
218** Parameters:
219** none
220**
221** Returns:
222** nothing.
223**
224** Side Effects:
225** flushes open files before they are forced closed
226*/
227
228void
229sm_cleanup()
230{
231 int timeout = SM_TIME_DEFAULT;
232
233 (void) sm_fwalk(sm_flush, &timeout); /* `cheating' */
234}
235
236/*
237** SM_INIT -- called whenever sm_io's internal variables must be set up.
238**
239** Parameters:
240** none
241**
242** Returns:
243** none
244**
245** Side Effects:
246** Registers sm_cleanup() using atexit().
247*/
248
249void
250sm_init()
251{
252 if (Sm_IO_DidInit) /* paranoia */
253 return;
254
255 /* more paranoia: initialize pointers in a static variable */
256 empty.f_type = NULL;
257 empty.sm_magic = NULL;
258
259 /* make sure we clean up on exit */
260 atexit(sm_cleanup); /* conservative */
261 Sm_IO_DidInit = true;
262}
263
264/*
265** SM_IO_SETINFO -- change info for an open file type (fp)
266**
267** The generic SM_IO_WHAT_VECTORS is auto supplied for all file types.
268** If the request is to set info other than SM_IO_WHAT_VECTORS then
269** the request is passed on to the file type's specific setinfo vector.
270** WARNING: this is working on an active/open file type.
271**
272** Parameters:
273** fp -- file to make the setting on
274** what -- type of information to set
275** valp -- structure to obtain info from
276**
277** Returns:
278** 0 on success
279** -1 on error and sets errno:
280** - when what != SM_IO_WHAT_VECTORS and setinfo vector
281** not set
282** - when vectored setinfo returns -1
283*/
284
285int
286sm_io_setinfo(fp, what, valp)
287 SM_FILE_T *fp;
288 int what;
289 void *valp;
290{
291 SM_FILE_T *v = (SM_FILE_T *) valp;
292
293 SM_REQUIRE_ISA(fp, SmFileMagic);
294 switch (what)
295 {
296 case SM_IO_WHAT_VECTORS:
297
298 /*
299 ** This is the "generic" available for all.
300 ** This allows the function vectors to be replaced
301 ** while the file type is active.
302 */
303
304 fp->f_close = v->f_close;
305 fp->f_read = v->f_read;
306 fp->f_seek = v->f_seek;
307 fp->f_write = v->f_write;
308 fp->f_open = v->f_open;
309 fp->f_setinfo = v->f_setinfo;
310 fp->f_getinfo = v->f_getinfo;
311 sm_free(fp->f_type);
312 fp->f_type = sm_strdup_x(v->f_type);
313 return 0;
314 case SM_IO_WHAT_TIMEOUT:
315 fp->f_timeout = *((int *)valp);
316 return 0;
317 }
318
319 /* Otherwise the vector will check it out */
320 if (fp->f_setinfo == NULL)
321 {
322 errno = EINVAL;
323 return -1;
324 }
325 else
326 return (*fp->f_setinfo)(fp, what, valp);
327}
328
329/*
330** SM_IO_GETINFO -- get information for an active file type (fp)
331**
332** This function supplies for all file types the answers for the
333** three requests SM_IO_WHAT_VECTORS, SM_IO_WHAT_TYPE and
334** SM_IO_WHAT_ISTYPE. Other requests are handled by the getinfo
335** vector if available for the open file type.
336** SM_IO_WHAT_VECTORS returns information for the file pointer vectors.
337** SM_IO_WHAT_TYPE returns the type identifier for the file pointer
338** SM_IO_WHAT_ISTYPE returns >0 if the passed in type matches the
339** file pointer's type.
340** SM_IO_IS_READABLE returns 1 if there is data available for reading,
341** 0 otherwise.
342**
343** Parameters:
344** fp -- file pointer for active file type
345** what -- type of information request
346** valp -- structure to place obtained info into
347**
348** Returns:
349** -1 on error and sets errno:
350** - when valp==NULL and request expects otherwise
351** - when request is not SM_IO_WHAT_VECTORS and not
352** SM_IO_WHAT_TYPE and not SM_IO_WHAT_ISTYPE
353** and getinfo vector is NULL
354** - when getinfo type vector returns -1
355** >=0 on success
356*/
357
358int
359sm_io_getinfo(fp, what, valp)
360 SM_FILE_T *fp;
361 int what;
362 void *valp;
363{
364 SM_FILE_T *v = (SM_FILE_T *) valp;
365
366 SM_REQUIRE_ISA(fp, SmFileMagic);
367
368 switch (what)
369 {
370 case SM_IO_WHAT_VECTORS:
371
372 /* This is the "generic" available for all */
373 v->f_close = fp->f_close;
374 v->f_read = fp->f_read;
375 v->f_seek = fp->f_seek;
376 v->f_write = fp->f_write;
377 v->f_open = fp->f_open;
378 v->f_setinfo = fp->f_setinfo;
379 v->f_getinfo = fp->f_getinfo;
380 v->f_type = fp->f_type;
381 return 0;
382
383 case SM_IO_WHAT_TYPE:
384 if (valp == NULL)
385 {
386 errno = EINVAL;
387 return -1;
388 }
389 valp = sm_strdup_x(fp->f_type);
390 return 0;
391
392 case SM_IO_WHAT_ISTYPE:
393 if (valp == NULL)
394 {
395 errno = EINVAL;
396 return -1;
397 }
398 return strcmp(fp->f_type, valp) == 0;
399
400 case SM_IO_IS_READABLE:
401
402 /* if there is data in the buffer, it must be readable */
403 if (fp->f_r > 0)
404 return 1;
405
406 /* otherwise query the underlying file */
407 break;
408
409 case SM_IO_WHAT_TIMEOUT:
410 *((int *) valp) = fp->f_timeout;
411 return 0;
412
413 case SM_IO_WHAT_FD:
414 if (fp->f_file > -1)
415 return fp->f_file;
416
417 /* try the file type specific getinfo to see if it knows */
418 break;
419 }
420
421 /* Otherwise the vector will check it out */
422 if (fp->f_getinfo == NULL)
423 {
424 errno = EINVAL;
425 return -1;
426 }
427 return (*fp->f_getinfo)(fp, what, valp);
428}
201 if (fp->f_timeout == SM_TIME_DEFAULT)
202 fp->f_timeout = SM_TIME_FOREVER;
203 else
204 fp->f_timeout = t->f_timeout; /* traditional behavior */
205 fp->f_timeoutstate = SM_TIME_BLOCK; /* by default */
206
207 return fp;
208}
209
210/*
211** SM_CLEANUP -- cleanup function when exit called.
212**
213** This function is registered via atexit().
214**
215** Parameters:
216** none
217**
218** Returns:
219** nothing.
220**
221** Side Effects:
222** flushes open files before they are forced closed
223*/
224
225void
226sm_cleanup()
227{
228 int timeout = SM_TIME_DEFAULT;
229
230 (void) sm_fwalk(sm_flush, &timeout); /* `cheating' */
231}
232
233/*
234** SM_INIT -- called whenever sm_io's internal variables must be set up.
235**
236** Parameters:
237** none
238**
239** Returns:
240** none
241**
242** Side Effects:
243** Registers sm_cleanup() using atexit().
244*/
245
246void
247sm_init()
248{
249 if (Sm_IO_DidInit) /* paranoia */
250 return;
251
252 /* more paranoia: initialize pointers in a static variable */
253 empty.f_type = NULL;
254 empty.sm_magic = NULL;
255
256 /* make sure we clean up on exit */
257 atexit(sm_cleanup); /* conservative */
258 Sm_IO_DidInit = true;
259}
260
261/*
262** SM_IO_SETINFO -- change info for an open file type (fp)
263**
264** The generic SM_IO_WHAT_VECTORS is auto supplied for all file types.
265** If the request is to set info other than SM_IO_WHAT_VECTORS then
266** the request is passed on to the file type's specific setinfo vector.
267** WARNING: this is working on an active/open file type.
268**
269** Parameters:
270** fp -- file to make the setting on
271** what -- type of information to set
272** valp -- structure to obtain info from
273**
274** Returns:
275** 0 on success
276** -1 on error and sets errno:
277** - when what != SM_IO_WHAT_VECTORS and setinfo vector
278** not set
279** - when vectored setinfo returns -1
280*/
281
282int
283sm_io_setinfo(fp, what, valp)
284 SM_FILE_T *fp;
285 int what;
286 void *valp;
287{
288 SM_FILE_T *v = (SM_FILE_T *) valp;
289
290 SM_REQUIRE_ISA(fp, SmFileMagic);
291 switch (what)
292 {
293 case SM_IO_WHAT_VECTORS:
294
295 /*
296 ** This is the "generic" available for all.
297 ** This allows the function vectors to be replaced
298 ** while the file type is active.
299 */
300
301 fp->f_close = v->f_close;
302 fp->f_read = v->f_read;
303 fp->f_seek = v->f_seek;
304 fp->f_write = v->f_write;
305 fp->f_open = v->f_open;
306 fp->f_setinfo = v->f_setinfo;
307 fp->f_getinfo = v->f_getinfo;
308 sm_free(fp->f_type);
309 fp->f_type = sm_strdup_x(v->f_type);
310 return 0;
311 case SM_IO_WHAT_TIMEOUT:
312 fp->f_timeout = *((int *)valp);
313 return 0;
314 }
315
316 /* Otherwise the vector will check it out */
317 if (fp->f_setinfo == NULL)
318 {
319 errno = EINVAL;
320 return -1;
321 }
322 else
323 return (*fp->f_setinfo)(fp, what, valp);
324}
325
326/*
327** SM_IO_GETINFO -- get information for an active file type (fp)
328**
329** This function supplies for all file types the answers for the
330** three requests SM_IO_WHAT_VECTORS, SM_IO_WHAT_TYPE and
331** SM_IO_WHAT_ISTYPE. Other requests are handled by the getinfo
332** vector if available for the open file type.
333** SM_IO_WHAT_VECTORS returns information for the file pointer vectors.
334** SM_IO_WHAT_TYPE returns the type identifier for the file pointer
335** SM_IO_WHAT_ISTYPE returns >0 if the passed in type matches the
336** file pointer's type.
337** SM_IO_IS_READABLE returns 1 if there is data available for reading,
338** 0 otherwise.
339**
340** Parameters:
341** fp -- file pointer for active file type
342** what -- type of information request
343** valp -- structure to place obtained info into
344**
345** Returns:
346** -1 on error and sets errno:
347** - when valp==NULL and request expects otherwise
348** - when request is not SM_IO_WHAT_VECTORS and not
349** SM_IO_WHAT_TYPE and not SM_IO_WHAT_ISTYPE
350** and getinfo vector is NULL
351** - when getinfo type vector returns -1
352** >=0 on success
353*/
354
355int
356sm_io_getinfo(fp, what, valp)
357 SM_FILE_T *fp;
358 int what;
359 void *valp;
360{
361 SM_FILE_T *v = (SM_FILE_T *) valp;
362
363 SM_REQUIRE_ISA(fp, SmFileMagic);
364
365 switch (what)
366 {
367 case SM_IO_WHAT_VECTORS:
368
369 /* This is the "generic" available for all */
370 v->f_close = fp->f_close;
371 v->f_read = fp->f_read;
372 v->f_seek = fp->f_seek;
373 v->f_write = fp->f_write;
374 v->f_open = fp->f_open;
375 v->f_setinfo = fp->f_setinfo;
376 v->f_getinfo = fp->f_getinfo;
377 v->f_type = fp->f_type;
378 return 0;
379
380 case SM_IO_WHAT_TYPE:
381 if (valp == NULL)
382 {
383 errno = EINVAL;
384 return -1;
385 }
386 valp = sm_strdup_x(fp->f_type);
387 return 0;
388
389 case SM_IO_WHAT_ISTYPE:
390 if (valp == NULL)
391 {
392 errno = EINVAL;
393 return -1;
394 }
395 return strcmp(fp->f_type, valp) == 0;
396
397 case SM_IO_IS_READABLE:
398
399 /* if there is data in the buffer, it must be readable */
400 if (fp->f_r > 0)
401 return 1;
402
403 /* otherwise query the underlying file */
404 break;
405
406 case SM_IO_WHAT_TIMEOUT:
407 *((int *) valp) = fp->f_timeout;
408 return 0;
409
410 case SM_IO_WHAT_FD:
411 if (fp->f_file > -1)
412 return fp->f_file;
413
414 /* try the file type specific getinfo to see if it knows */
415 break;
416 }
417
418 /* Otherwise the vector will check it out */
419 if (fp->f_getinfo == NULL)
420 {
421 errno = EINVAL;
422 return -1;
423 }
424 return (*fp->f_getinfo)(fp, what, valp);
425}