2 * Copyright (c) 2000-2002, 2006 Sendmail, Inc. and its suppliers.
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
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.
15 #pragma ident "%Z%%M% %I% %E% SMI"
18 SM_RCSID("@(#)$Id: findfp.c,v 1.67 2006/08/28 21:24:46 ca Exp $")
21 #include <sys/param.h>
26 #include <sm/assert.h>
28 #include <sm/string.h>
33 bool Sm_IO_DidInit
; /* IO system has been initialized? */
35 const char SmFileMagic
[] = "sm_file";
37 /* An open type to map to fopen()-like behavior */
38 SM_FILE_T SmFtStdio_def
=
39 {SmFileMagic
, 0, 0, 0, (SMRW
|SMFBF
), -1, {0, 0}, 0, 0, 0,
40 sm_stdclose
, sm_stdread
, sm_stdseek
, sm_stdwrite
,
41 sm_stdopen
, sm_stdsetinfo
, sm_stdgetinfo
, SM_TIME_FOREVER
,
42 SM_TIME_BLOCK
, "stdio" };
44 /* An open type to map to fdopen()-like behavior */
45 SM_FILE_T SmFtStdiofd_def
=
46 {SmFileMagic
, 0, 0, 0, (SMRW
|SMFBF
), -1, {0, 0}, 0, 0, 0,
47 sm_stdclose
, sm_stdread
, sm_stdseek
, sm_stdwrite
,
48 sm_stdfdopen
, sm_stdsetinfo
, sm_stdgetinfo
, SM_TIME_FOREVER
,
49 SM_TIME_BLOCK
, "stdiofd" };
51 /* A string file type */
52 SM_FILE_T SmFtString_def
=
53 {SmFileMagic
, 0, 0, 0, (SMRW
|SMNBF
), -1, {0, 0}, 0, 0, 0,
54 sm_strclose
, sm_strread
, sm_strseek
, sm_strwrite
,
55 sm_stropen
, sm_strsetinfo
, sm_strgetinfo
, SM_TIME_FOREVER
,
56 SM_TIME_BLOCK
, "string" };
59 /* A file type for syslog communications */
60 SM_FILE_T SmFtSyslog_def
=
61 {SmFileMagic
, 0, 0, 0, (SMRW
|SMNBF
), -1, {0, 0}, 0, 0, 0,
62 sm_syslogclose
, sm_syslogread
, sm_syslogseek
, sm_syslogwrite
,
63 sm_syslogopen
, sm_syslogsetinfo
, sm_sysloggetinfo
, SM_TIME_FOREVER
,
64 SM_TIME_BLOCK
, "syslog" };
67 #define NDYNAMIC 10 /* add ten more whenever necessary */
69 #define smio(flags, file, name) \
70 {SmFileMagic, 0, 0, 0, flags, file, {0}, 0, SmIoF+file, 0, \
71 sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite, \
72 sm_stdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER, \
75 /* sm_magic p r w flags file bf lbfsize cookie ival */
76 #define smstd(flags, file, name) \
77 {SmFileMagic, 0, 0, 0, flags, -1, {0}, 0, 0, file, \
78 sm_stdioclose, sm_stdioread, sm_stdioseek, sm_stdiowrite, \
79 sm_stdioopen, sm_stdiosetinfo, sm_stdiogetinfo, SM_TIME_FOREVER,\
82 /* A file type for interfacing to stdio FILE* streams. */
83 SM_FILE_T SmFtRealStdio_def
= smstd(SMRW
|SMNBF
, -1, "realstdio");
85 /* the usual - (stdin + stdout + stderr) */
86 static SM_FILE_T usual
[SM_IO_OPEN_MAX
- 3];
87 static struct sm_glue smuglue
= { 0, SM_IO_OPEN_MAX
- 3, usual
};
89 /* List of builtin automagically already open file pointers */
92 smio(SMRD
|SMLBF
, SMIOIN_FILENO
, "smioin"), /* smioin */
93 smio(SMWR
|SMLBF
, SMIOOUT_FILENO
, "smioout"), /* smioout */
94 smio(SMWR
|SMNBF
, SMIOERR_FILENO
, "smioerr"), /* smioerr */
95 smstd(SMRD
|SMNBF
, SMIOIN_FILENO
, "smiostdin"), /* smiostdin */
96 smstd(SMWR
|SMNBF
, SMIOOUT_FILENO
, "smiostdout"),/* smiostdout */
97 smstd(SMWR
|SMNBF
, SMIOERR_FILENO
, "smiostderr") /* smiostderr */
100 /* Structure containing list of currently open file pointers */
101 struct sm_glue smglue
= { &smuglue
, 3, SmIoF
};
104 ** SM_MOREGLUE -- adds more space for open file pointers
107 ** n -- number of new spaces for file pointers
110 ** Raises an exception if no more memory.
111 ** Otherwise, returns a pointer to new spaces.
114 static struct sm_glue
*sm_moreglue_x
__P((int));
115 static SM_FILE_T empty
;
117 static struct sm_glue
*
121 register struct sm_glue
*g
;
122 register SM_FILE_T
*p
;
124 g
= (struct sm_glue
*) sm_pmalloc_x(sizeof(*g
) + SM_ALIGN_BITS
+
125 n
* sizeof(SM_FILE_T
));
126 p
= (SM_FILE_T
*) SM_ALIGN(g
+ 1);
136 ** SM_FP -- allocate and initialize an SM_FILE structure
139 ** t -- file type requested to be opened.
140 ** flags -- control flags for file type behavior
141 ** oldfp -- file pointer to reuse if available (optional)
144 ** Raises exception on memory exhaustion.
145 ** Aborts if type is invalid.
146 ** Otherwise, returns file pointer for requested file type.
150 sm_fp(t
, flags
, oldfp
)
155 register SM_FILE_T
*fp
;
157 register struct sm_glue
*g
;
159 SM_REQUIRE(t
->f_open
&& t
->f_close
&& (t
->f_read
|| t
->f_write
));
167 goto found
; /* for opening reusing an 'fp' */
170 for (g
= &smglue
;; g
= g
->gl_next
)
172 for (fp
= g
->gl_iobs
, n
= g
->gl_niobs
; --n
>= 0; fp
++)
173 if (fp
->sm_magic
== NULL
)
175 if (g
->gl_next
== NULL
)
176 g
->gl_next
= sm_moreglue_x(NDYNAMIC
);
179 fp
->sm_magic
= SmFileMagic
; /* 'fp' now valid and in-use */
180 fp
->f_p
= NULL
; /* no current pointer */
181 fp
->f_w
= 0; /* nothing to write */
182 fp
->f_r
= 0; /* nothing to read */
184 fp
->f_file
= -1; /* no file */
185 fp
->f_bf
.smb_base
= NULL
; /* no buffer */
186 fp
->f_bf
.smb_size
= 0; /* no buffer size with no buffer */
187 fp
->f_lbfsize
= 0; /* not line buffered */
188 fp
->f_flushfp
= NULL
; /* no associated flush file */
190 fp
->f_cookie
= fp
; /* default: *open* overrides cookie setting */
191 fp
->f_close
= t
->f_close
; /* assign close function */
192 fp
->f_read
= t
->f_read
; /* assign read function */
193 fp
->f_seek
= t
->f_seek
; /* assign seek function */
194 fp
->f_write
= t
->f_write
; /* assign write function */
195 fp
->f_open
= t
->f_open
; /* assign open function */
196 fp
->f_setinfo
= t
->f_setinfo
; /* assign setinfo function */
197 fp
->f_getinfo
= t
->f_getinfo
; /* assign getinfo function */
198 fp
->f_type
= t
->f_type
; /* file type */
200 fp
->f_ub
.smb_base
= NULL
; /* no ungetc buffer */
201 fp
->f_ub
.smb_size
= 0; /* no size for no ungetc buffer */
203 if (fp
->f_timeout
== SM_TIME_DEFAULT
)
204 fp
->f_timeout
= SM_TIME_FOREVER
;
206 fp
->f_timeout
= t
->f_timeout
; /* traditional behavior */
207 fp
->f_timeoutstate
= SM_TIME_BLOCK
; /* by default */
213 ** SM_CLEANUP -- cleanup function when exit called.
215 ** This function is registered via atexit().
224 ** flushes open files before they are forced closed
230 int timeout
= SM_TIME_DEFAULT
;
232 (void) sm_fwalk(sm_flush
, &timeout
); /* `cheating' */
236 ** SM_INIT -- called whenever sm_io's internal variables must be set up.
245 ** Registers sm_cleanup() using atexit().
251 if (Sm_IO_DidInit
) /* paranoia */
254 /* more paranoia: initialize pointers in a static variable */
256 empty
.sm_magic
= NULL
;
258 /* make sure we clean up on exit */
259 atexit(sm_cleanup
); /* conservative */
260 Sm_IO_DidInit
= true;
264 ** SM_IO_SETINFO -- change info for an open file type (fp)
266 ** The generic SM_IO_WHAT_VECTORS is auto supplied for all file types.
267 ** If the request is to set info other than SM_IO_WHAT_VECTORS then
268 ** the request is passed on to the file type's specific setinfo vector.
269 ** WARNING: this is working on an active/open file type.
272 ** fp -- file to make the setting on
273 ** what -- type of information to set
274 ** valp -- structure to obtain info from
278 ** -1 on error and sets errno:
279 ** - when what != SM_IO_WHAT_VECTORS and setinfo vector
281 ** - when vectored setinfo returns -1
285 sm_io_setinfo(fp
, what
, valp
)
290 SM_FILE_T
*v
= (SM_FILE_T
*) valp
;
292 SM_REQUIRE_ISA(fp
, SmFileMagic
);
295 case SM_IO_WHAT_VECTORS
:
298 ** This is the "generic" available for all.
299 ** This allows the function vectors to be replaced
300 ** while the file type is active.
303 fp
->f_close
= v
->f_close
;
304 fp
->f_read
= v
->f_read
;
305 fp
->f_seek
= v
->f_seek
;
306 fp
->f_write
= v
->f_write
;
307 fp
->f_open
= v
->f_open
;
308 fp
->f_setinfo
= v
->f_setinfo
;
309 fp
->f_getinfo
= v
->f_getinfo
;
311 fp
->f_type
= sm_strdup_x(v
->f_type
);
313 case SM_IO_WHAT_TIMEOUT
:
314 fp
->f_timeout
= *((int *)valp
);
318 /* Otherwise the vector will check it out */
319 if (fp
->f_setinfo
== NULL
)
325 return (*fp
->f_setinfo
)(fp
, what
, valp
);
329 ** SM_IO_GETINFO -- get information for an active file type (fp)
331 ** This function supplies for all file types the answers for the
332 ** three requests SM_IO_WHAT_VECTORS, SM_IO_WHAT_TYPE and
333 ** SM_IO_WHAT_ISTYPE. Other requests are handled by the getinfo
334 ** vector if available for the open file type.
335 ** SM_IO_WHAT_VECTORS returns information for the file pointer vectors.
336 ** SM_IO_WHAT_TYPE returns the type identifier for the file pointer
337 ** SM_IO_WHAT_ISTYPE returns >0 if the passed in type matches the
338 ** file pointer's type.
339 ** SM_IO_IS_READABLE returns 1 if there is data available for reading,
343 ** fp -- file pointer for active file type
344 ** what -- type of information request
345 ** valp -- structure to place obtained info into
348 ** -1 on error and sets errno:
349 ** - when valp==NULL and request expects otherwise
350 ** - when request is not SM_IO_WHAT_VECTORS and not
351 ** SM_IO_WHAT_TYPE and not SM_IO_WHAT_ISTYPE
352 ** and getinfo vector is NULL
353 ** - when getinfo type vector returns -1
358 sm_io_getinfo(fp
, what
, valp
)
363 SM_FILE_T
*v
= (SM_FILE_T
*) valp
;
365 SM_REQUIRE_ISA(fp
, SmFileMagic
);
369 case SM_IO_WHAT_VECTORS
:
376 /* This is the "generic" available for all */
377 v
->f_close
= fp
->f_close
;
378 v
->f_read
= fp
->f_read
;
379 v
->f_seek
= fp
->f_seek
;
380 v
->f_write
= fp
->f_write
;
381 v
->f_open
= fp
->f_open
;
382 v
->f_setinfo
= fp
->f_setinfo
;
383 v
->f_getinfo
= fp
->f_getinfo
;
384 v
->f_type
= fp
->f_type
;
387 case SM_IO_WHAT_TYPE
:
393 valp
= sm_strdup_x(fp
->f_type
);
396 case SM_IO_WHAT_ISTYPE
:
402 return strcmp(fp
->f_type
, valp
) == 0;
404 case SM_IO_IS_READABLE
:
406 /* if there is data in the buffer, it must be readable */
410 /* otherwise query the underlying file */
413 case SM_IO_WHAT_TIMEOUT
:
414 *((int *) valp
) = fp
->f_timeout
;
421 /* try the file type specific getinfo to see if it knows */
425 /* Otherwise the vector will check it out */
426 if (fp
->f_getinfo
== NULL
)
431 return (*fp
->f_getinfo
)(fp
, what
, valp
);