source: trunk/third/sendmail/libsm/findfp.c @ 19204

Revision 19204, 10.8 KB checked in by zacheiss, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19203, which included commits to RCS files with non-trunk default branches.
Line 
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.1.1.1 2003-04-08 15:07:02 zacheiss 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 */
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
122        g = (struct sm_glue *) sm_pmalloc_x(sizeof(*g) + SM_ALIGN_BITS +
123                                            n * sizeof(SM_FILE_T));
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 */
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
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}
Note: See TracBrowser for help on using the repository browser.