Logo Search packages:      
Sourcecode: batv-milter version File versions  Download package

findfp.c

/*
 * Copyright (c) 2000-2002, 2006 Sendmail, Inc. and its suppliers.
 *      All rights reserved.
 * Copyright (c) 1990, 1993
 *    The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Chris Torek.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 */

#include <sm/gen.h>
SM_RCSID("@(#)$Id: findfp.c,v 1.67 2006/08/28 21:24:46 ca Exp $")
#include <stdlib.h>
#include <unistd.h>
#include <sys/param.h>
#include <errno.h>
#include <string.h>
#include <syslog.h>
#include <sm/io.h>
#include <sm/assert.h>
#include <sm/heap.h>
#include <sm/string.h>
#include <sm/conf.h>
#include "local.h"
#include "glue.h"

bool  Sm_IO_DidInit;    /* IO system has been initialized? */

const char SmFileMagic[] = "sm_file";

/* An open type to map to fopen()-like behavior */
SM_FILE_T SmFtStdio_def =
    {SmFileMagic, 0, 0, 0, (SMRW|SMFBF), -1, {0, 0}, 0, 0, 0,
      sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite,
      sm_stdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER,
      SM_TIME_BLOCK, "stdio" };

/* An open type to map to fdopen()-like behavior */
SM_FILE_T SmFtStdiofd_def =
    {SmFileMagic, 0, 0, 0, (SMRW|SMFBF), -1, {0, 0}, 0, 0, 0,
      sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite,
      sm_stdfdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER,
      SM_TIME_BLOCK, "stdiofd" };

/* A string file type */
SM_FILE_T SmFtString_def =
    {SmFileMagic, 0, 0, 0, (SMRW|SMNBF), -1, {0, 0}, 0, 0, 0,
      sm_strclose, sm_strread, sm_strseek, sm_strwrite,
      sm_stropen, sm_strsetinfo, sm_strgetinfo, SM_TIME_FOREVER,
      SM_TIME_BLOCK, "string" };

#if 0
/* A file type for syslog communications */
SM_FILE_T SmFtSyslog_def =
    {SmFileMagic, 0, 0, 0, (SMRW|SMNBF), -1, {0, 0}, 0, 0, 0,
      sm_syslogclose, sm_syslogread, sm_syslogseek, sm_syslogwrite,
      sm_syslogopen, sm_syslogsetinfo, sm_sysloggetinfo, SM_TIME_FOREVER,
      SM_TIME_BLOCK, "syslog" };
#endif /* 0 */

#define NDYNAMIC 10           /* add ten more whenever necessary */

#define smio(flags, file, name)                                   \
    {SmFileMagic, 0, 0, 0, flags, file, {0}, 0, SmIoF+file, 0,          \
      sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite,           \
      sm_stdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER,  \
      SM_TIME_BLOCK, name}

/* sm_magic p r w flags file bf lbfsize cookie ival */
#define smstd(flags, file, name)                            \
    {SmFileMagic, 0, 0, 0, flags, -1, {0}, 0, 0, file,                  \
      sm_stdioclose, sm_stdioread, sm_stdioseek, sm_stdiowrite,   \
      sm_stdioopen, sm_stdiosetinfo, sm_stdiogetinfo, SM_TIME_FOREVER,\
      SM_TIME_BLOCK, name}

/* A file type for interfacing to stdio FILE* streams. */
SM_FILE_T SmFtRealStdio_def = smstd(SMRW|SMNBF, -1, "realstdio");

                        /* the usual - (stdin + stdout + stderr) */
static SM_FILE_T usual[SM_IO_OPEN_MAX - 3];
static struct sm_glue smuglue = { 0, SM_IO_OPEN_MAX - 3, usual };

/* List of builtin automagically already open file pointers */
SM_FILE_T SmIoF[6] =
{
      smio(SMRD|SMLBF, SMIOIN_FILENO, "smioin"),      /* smioin */
      smio(SMWR|SMLBF, SMIOOUT_FILENO, "smioout"),    /* smioout */
      smio(SMWR|SMNBF, SMIOERR_FILENO, "smioerr"),    /* smioerr */
      smstd(SMRD|SMNBF, SMIOIN_FILENO, "smiostdin"),  /* smiostdin */
      smstd(SMWR|SMNBF, SMIOOUT_FILENO, "smiostdout"),/* smiostdout */
      smstd(SMWR|SMNBF, SMIOERR_FILENO, "smiostderr") /* smiostderr */
};

/* Structure containing list of currently open file pointers */
struct sm_glue smglue = { &smuglue, 3, SmIoF };

/*
**  SM_MOREGLUE -- adds more space for open file pointers
**
**    Parameters:
**          n -- number of new spaces for file pointers
**
**    Returns:
**          Raises an exception if no more memory.
**          Otherwise, returns a pointer to new spaces.
*/

static struct sm_glue *sm_moreglue_x __P((int));
static SM_FILE_T empty;

static struct sm_glue *
sm_moreglue_x(n)
      register int n;
{
      register struct sm_glue *g;
      register SM_FILE_T *p;

      g = (struct sm_glue *) sm_pmalloc_x(sizeof(*g) + SM_ALIGN_BITS +
                                  n * sizeof(SM_FILE_T));
      p = (SM_FILE_T *) SM_ALIGN(g + 1);
      g->gl_next = NULL;
      g->gl_niobs = n;
      g->gl_iobs = p;
      while (--n >= 0)
            *p++ = empty;
      return g;
}

/*
**  SM_FP -- allocate and initialize an SM_FILE structure
**
**    Parameters:
**          t -- file type requested to be opened.
**          flags -- control flags for file type behavior
**          oldfp -- file pointer to reuse if available (optional)
**
**    Returns:
**          Raises exception on memory exhaustion.
**          Aborts if type is invalid.
**          Otherwise, returns file pointer for requested file type.
*/

SM_FILE_T *
sm_fp(t, flags, oldfp)
      const SM_FILE_T *t;
      const int flags;
      SM_FILE_T *oldfp;
{
      register SM_FILE_T *fp;
      register int n;
      register struct sm_glue *g;

      SM_REQUIRE(t->f_open && t->f_close && (t->f_read || t->f_write));

      if (!Sm_IO_DidInit)
            sm_init();

      if (oldfp != NULL)
      {
            fp = oldfp;
            goto found; /* for opening reusing an 'fp' */
      }

      for (g = &smglue;; g = g->gl_next)
      {
            for (fp = g->gl_iobs, n = g->gl_niobs; --n >= 0; fp++)
                  if (fp->sm_magic == NULL)
                        goto found;
            if (g->gl_next == NULL)
                  g->gl_next = sm_moreglue_x(NDYNAMIC);
      }
found:
      fp->sm_magic = SmFileMagic; /* 'fp' now valid and in-use */
      fp->f_p = NULL;         /* no current pointer */
      fp->f_w = 0;            /* nothing to write */
      fp->f_r = 0;            /* nothing to read */
      fp->f_flags = flags;
      fp->f_file = -1;        /* no file */
      fp->f_bf.smb_base = NULL;     /* no buffer */
      fp->f_bf.smb_size = 0;  /* no buffer size with no buffer */
      fp->f_lbfsize = 0;      /* not line buffered */
      fp->f_flushfp = NULL;   /* no associated flush file */

      fp->f_cookie = fp;      /* default: *open* overrides cookie setting */
      fp->f_close = t->f_close;     /* assign close function */
      fp->f_read = t->f_read;       /* assign read function */
      fp->f_seek = t->f_seek;       /* assign seek function */
      fp->f_write = t->f_write;     /* assign write function */
      fp->f_open = t->f_open;       /* assign open function */
      fp->f_setinfo = t->f_setinfo; /* assign setinfo function */
      fp->f_getinfo = t->f_getinfo; /* assign getinfo function */
      fp->f_type = t->f_type;       /* file type */

      fp->f_ub.smb_base = NULL;     /* no ungetc buffer */
      fp->f_ub.smb_size = 0;        /* no size for no ungetc buffer */

      if (fp->f_timeout == SM_TIME_DEFAULT)
            fp->f_timeout = SM_TIME_FOREVER;
      else
            fp->f_timeout = t->f_timeout; /* traditional behavior */
      fp->f_timeoutstate = SM_TIME_BLOCK; /* by default */

      return fp;
}

/*
**  SM_CLEANUP -- cleanup function when exit called.
**
**    This function is registered via atexit().
**
**    Parameters:
**          none
**
**    Returns:
**          nothing.
**
**    Side Effects:
**          flushes open files before they are forced closed
*/

void
sm_cleanup()
{
      int timeout = SM_TIME_DEFAULT;

      (void) sm_fwalk(sm_flush, &timeout); /* `cheating' */
}

/*
**  SM_INIT -- called whenever sm_io's internal variables must be set up.
**
**    Parameters:
**          none
**
**    Returns:
**          none
**
**    Side Effects:
**          Registers sm_cleanup() using atexit().
*/

void
sm_init()
{
      if (Sm_IO_DidInit)      /* paranoia */
            return;

      /* more paranoia: initialize pointers in a static variable */
      empty.f_type = NULL;
      empty.sm_magic = NULL;

      /* make sure we clean up on exit */
      atexit(sm_cleanup);           /* conservative */
      Sm_IO_DidInit = true;
}

/*
**  SM_IO_SETINFO -- change info for an open file type (fp)
**
**    The generic SM_IO_WHAT_VECTORS is auto supplied for all file types.
**    If the request is to set info other than SM_IO_WHAT_VECTORS then
**    the request is passed on to the file type's specific setinfo vector.
**    WARNING: this is working on an active/open file type.
**
**    Parameters:
**          fp -- file to make the setting on
**          what -- type of information to set
**          valp -- structure to obtain info from
**
**    Returns:
**          0 on success
**          -1 on error and sets errno:
**                - when what != SM_IO_WHAT_VECTORS and setinfo vector
**                      not set
**                - when vectored setinfo returns -1
*/

int
sm_io_setinfo(fp, what, valp)
      SM_FILE_T *fp;
      int what;
      void *valp;
{
      SM_FILE_T *v = (SM_FILE_T *) valp;

      SM_REQUIRE_ISA(fp, SmFileMagic);
      switch (what)
      {
        case SM_IO_WHAT_VECTORS:

            /*
            **  This is the "generic" available for all.
            **  This allows the function vectors to be replaced
            **  while the file type is active.
            */

            fp->f_close = v->f_close;
            fp->f_read = v->f_read;
            fp->f_seek = v->f_seek;
            fp->f_write = v->f_write;
            fp->f_open = v->f_open;
            fp->f_setinfo = v->f_setinfo;
            fp->f_getinfo = v->f_getinfo;
            sm_free(fp->f_type);
            fp->f_type = sm_strdup_x(v->f_type);
            return 0;
        case SM_IO_WHAT_TIMEOUT:
            fp->f_timeout = *((int *)valp);
            return 0;
      }

      /* Otherwise the vector will check it out */
      if (fp->f_setinfo == NULL)
      {
            errno = EINVAL;
            return -1;
      }
      else
            return (*fp->f_setinfo)(fp, what, valp);
}

/*
**  SM_IO_GETINFO -- get information for an active file type (fp)
**
**  This function supplies for all file types the answers for the
**          three requests SM_IO_WHAT_VECTORS, SM_IO_WHAT_TYPE and
**          SM_IO_WHAT_ISTYPE. Other requests are handled by the getinfo
**          vector if available for the open file type.
**    SM_IO_WHAT_VECTORS returns information for the file pointer vectors.
**    SM_IO_WHAT_TYPE returns the type identifier for the file pointer
**    SM_IO_WHAT_ISTYPE returns >0 if the passed in type matches the
**          file pointer's type.
**    SM_IO_IS_READABLE returns 1 if there is data available for reading,
**          0 otherwise.
**
**    Parameters:
**          fp -- file pointer for active file type
**          what -- type of information request
**          valp -- structure to place obtained info into
**
**    Returns:
**          -1 on error and sets errno:
**                - when valp==NULL and request expects otherwise
**                - when request is not SM_IO_WHAT_VECTORS and not
**                      SM_IO_WHAT_TYPE and not SM_IO_WHAT_ISTYPE
**                      and getinfo vector is NULL
**                - when getinfo type vector returns -1
**          >=0 on success
*/

int
sm_io_getinfo(fp, what, valp)
      SM_FILE_T *fp;
      int what;
      void *valp;
{
      SM_FILE_T *v = (SM_FILE_T *) valp;

      SM_REQUIRE_ISA(fp, SmFileMagic);

      switch (what)
      {
        case SM_IO_WHAT_VECTORS:
            if (valp == NULL)
            {
                  errno = EINVAL;
                  return -1;
            }

            /* This is the "generic" available for all */
            v->f_close = fp->f_close;
            v->f_read = fp->f_read;
            v->f_seek = fp->f_seek;
            v->f_write = fp->f_write;
            v->f_open = fp->f_open;
            v->f_setinfo = fp->f_setinfo;
            v->f_getinfo = fp->f_getinfo;
            v->f_type = fp->f_type;
            return 0;

        case SM_IO_WHAT_TYPE:
            if (valp == NULL)
            {
                  errno = EINVAL;
                  return -1;
            }
            valp = sm_strdup_x(fp->f_type);
            return 0;

        case SM_IO_WHAT_ISTYPE:
            if (valp == NULL)
            {
                  errno = EINVAL;
                  return -1;
            }
            return strcmp(fp->f_type, valp) == 0;

        case SM_IO_IS_READABLE:

            /* if there is data in the buffer, it must be readable */
            if (fp->f_r > 0)
                  return 1;

            /* otherwise query the underlying file */
            break;

         case SM_IO_WHAT_TIMEOUT:
            *((int *) valp) = fp->f_timeout;
            return 0;

        case SM_IO_WHAT_FD:
            if (fp->f_file > -1)
                  return fp->f_file;

            /* try the file type specific getinfo to see if it knows */
            break;
      }

      /* Otherwise the vector will check it out */
      if (fp->f_getinfo == NULL)
      {
            errno = EINVAL;
            return -1;
      }
      return (*fp->f_getinfo)(fp, what, valp);
}

Generated by  Doxygen 1.6.0   Back to index