#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;
const char SmFileMagic[] = "sm_file";
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" };
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" };
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
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
#define NDYNAMIC 10
#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}
#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}
SM_FILE_T SmFtRealStdio_def = smstd(SMRW|SMNBF, -1, "realstdio");
static SM_FILE_T usual[SM_IO_OPEN_MAX - 3];
static struct sm_glue smuglue = { 0, SM_IO_OPEN_MAX - 3, usual };
SM_FILE_T SmIoF[6] =
{
smio(SMRD|SMLBF, SMIOIN_FILENO, "smioin"),
smio(SMWR|SMLBF, SMIOOUT_FILENO, "smioout"),
smio(SMWR|SMNBF, SMIOERR_FILENO, "smioerr"),
smstd(SMRD|SMNBF, SMIOIN_FILENO, "smiostdin"),
smstd(SMWR|SMNBF, SMIOOUT_FILENO, "smiostdout"),
smstd(SMWR|SMNBF, SMIOERR_FILENO, "smiostderr")
};
struct sm_glue smglue = { &smuglue, 3, SmIoF };
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_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 (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->f_p = NULL;
fp->f_w = 0;
fp->f_r = 0;
fp->f_flags = flags;
fp->f_file = -1;
fp->f_bf.smb_base = NULL;
fp->f_bf.smb_size = 0;
fp->f_lbfsize = 0;
fp->f_flushfp = NULL;
fp->f_cookie = fp;
fp->f_close = t->f_close;
fp->f_read = t->f_read;
fp->f_seek = t->f_seek;
fp->f_write = t->f_write;
fp->f_open = t->f_open;
fp->f_setinfo = t->f_setinfo;
fp->f_getinfo = t->f_getinfo;
fp->f_type = t->f_type;
fp->f_ub.smb_base = NULL;
fp->f_ub.smb_size = 0;
if (fp->f_timeout == SM_TIME_DEFAULT)
fp->f_timeout = SM_TIME_FOREVER;
else
fp->f_timeout = t->f_timeout;
fp->f_timeoutstate = SM_TIME_BLOCK;
return fp;
}
void
sm_cleanup()
{
int timeout = SM_TIME_DEFAULT;
(void) sm_fwalk(sm_flush, &timeout);
}
void
sm_init()
{
if (Sm_IO_DidInit)
return;
empty.f_type = NULL;
empty.sm_magic = NULL;
atexit(sm_cleanup);
Sm_IO_DidInit = true;
}
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:
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;
}
if (fp->f_setinfo == NULL)
{
errno = EINVAL;
return -1;
}
else
return (*fp->f_setinfo)(fp, what, valp);
}
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;
}
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 (fp->f_r > 0)
return 1;
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;
break;
}
if (fp->f_getinfo == NULL)
{
errno = EINVAL;
return -1;
}
return (*fp->f_getinfo)(fp, what, valp);
}