8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / sendmail / libsm / findfp.c
blobd78b5cb57f33597c5b93ee1ea8e4fdcf908f1263
1 /*
2 * Copyright (c) 2000-2002, 2006 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.
7 * This code is derived from software contributed to Berkeley by
8 * Chris Torek.
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"
17 #include <sm/gen.h>
18 SM_RCSID("@(#)$Id: findfp.c,v 1.67 2006/08/28 21:24:46 ca Exp $")
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <sys/param.h>
22 #include <errno.h>
23 #include <string.h>
24 #include <syslog.h>
25 #include <sm/io.h>
26 #include <sm/assert.h>
27 #include <sm/heap.h>
28 #include <sm/string.h>
29 #include <sm/conf.h>
30 #include "local.h"
31 #include "glue.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" };
58 #if 0
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" };
65 #endif /* 0 */
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, \
73 SM_TIME_BLOCK, name}
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,\
80 SM_TIME_BLOCK, name}
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 */
90 SM_FILE_T SmIoF[6] =
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
106 ** Parameters:
107 ** n -- number of new spaces for file pointers
109 ** Returns:
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 *
118 sm_moreglue_x(n)
119 register int n;
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);
127 g->gl_next = NULL;
128 g->gl_niobs = n;
129 g->gl_iobs = p;
130 while (--n >= 0)
131 *p++ = empty;
132 return g;
136 ** SM_FP -- allocate and initialize an SM_FILE structure
138 ** Parameters:
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)
143 ** Returns:
144 ** Raises exception on memory exhaustion.
145 ** Aborts if type is invalid.
146 ** Otherwise, returns file pointer for requested file type.
149 SM_FILE_T *
150 sm_fp(t, flags, oldfp)
151 const SM_FILE_T *t;
152 const int flags;
153 SM_FILE_T *oldfp;
155 register SM_FILE_T *fp;
156 register int n;
157 register struct sm_glue *g;
159 SM_REQUIRE(t->f_open && t->f_close && (t->f_read || t->f_write));
161 if (!Sm_IO_DidInit)
162 sm_init();
164 if (oldfp != NULL)
166 fp = oldfp;
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)
174 goto found;
175 if (g->gl_next == NULL)
176 g->gl_next = sm_moreglue_x(NDYNAMIC);
178 found:
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 */
183 fp->f_flags = flags;
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;
205 else
206 fp->f_timeout = t->f_timeout; /* traditional behavior */
207 fp->f_timeoutstate = SM_TIME_BLOCK; /* by default */
209 return fp;
213 ** SM_CLEANUP -- cleanup function when exit called.
215 ** This function is registered via atexit().
217 ** Parameters:
218 ** none
220 ** Returns:
221 ** nothing.
223 ** Side Effects:
224 ** flushes open files before they are forced closed
227 void
228 sm_cleanup()
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.
238 ** Parameters:
239 ** none
241 ** Returns:
242 ** none
244 ** Side Effects:
245 ** Registers sm_cleanup() using atexit().
248 void
249 sm_init()
251 if (Sm_IO_DidInit) /* paranoia */
252 return;
254 /* more paranoia: initialize pointers in a static variable */
255 empty.f_type = NULL;
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.
271 ** Parameters:
272 ** fp -- file to make the setting on
273 ** what -- type of information to set
274 ** valp -- structure to obtain info from
276 ** Returns:
277 ** 0 on success
278 ** -1 on error and sets errno:
279 ** - when what != SM_IO_WHAT_VECTORS and setinfo vector
280 ** not set
281 ** - when vectored setinfo returns -1
285 sm_io_setinfo(fp, what, valp)
286 SM_FILE_T *fp;
287 int what;
288 void *valp;
290 SM_FILE_T *v = (SM_FILE_T *) valp;
292 SM_REQUIRE_ISA(fp, SmFileMagic);
293 switch (what)
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;
310 sm_free(fp->f_type);
311 fp->f_type = sm_strdup_x(v->f_type);
312 return 0;
313 case SM_IO_WHAT_TIMEOUT:
314 fp->f_timeout = *((int *)valp);
315 return 0;
318 /* Otherwise the vector will check it out */
319 if (fp->f_setinfo == NULL)
321 errno = EINVAL;
322 return -1;
324 else
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,
340 ** 0 otherwise.
342 ** Parameters:
343 ** fp -- file pointer for active file type
344 ** what -- type of information request
345 ** valp -- structure to place obtained info into
347 ** Returns:
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
354 ** >=0 on success
358 sm_io_getinfo(fp, what, valp)
359 SM_FILE_T *fp;
360 int what;
361 void *valp;
363 SM_FILE_T *v = (SM_FILE_T *) valp;
365 SM_REQUIRE_ISA(fp, SmFileMagic);
367 switch (what)
369 case SM_IO_WHAT_VECTORS:
370 if (valp == NULL)
372 errno = EINVAL;
373 return -1;
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;
385 return 0;
387 case SM_IO_WHAT_TYPE:
388 if (valp == NULL)
390 errno = EINVAL;
391 return -1;
393 valp = sm_strdup_x(fp->f_type);
394 return 0;
396 case SM_IO_WHAT_ISTYPE:
397 if (valp == NULL)
399 errno = EINVAL;
400 return -1;
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 */
407 if (fp->f_r > 0)
408 return 1;
410 /* otherwise query the underlying file */
411 break;
413 case SM_IO_WHAT_TIMEOUT:
414 *((int *) valp) = fp->f_timeout;
415 return 0;
417 case SM_IO_WHAT_FD:
418 if (fp->f_file > -1)
419 return fp->f_file;
421 /* try the file type specific getinfo to see if it knows */
422 break;
425 /* Otherwise the vector will check it out */
426 if (fp->f_getinfo == NULL)
428 errno = EINVAL;
429 return -1;
431 return (*fp->f_getinfo)(fp, what, valp);