findfp.c revision 90792
190792Sgshapiro/* 290792Sgshapiro * Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers. 390792Sgshapiro * All rights reserved. 490792Sgshapiro * Copyright (c) 1990, 1993 590792Sgshapiro * The Regents of the University of California. All rights reserved. 690792Sgshapiro * 790792Sgshapiro * This code is derived from software contributed to Berkeley by 890792Sgshapiro * Chris Torek. 990792Sgshapiro * 1090792Sgshapiro * By using this file, you agree to the terms and conditions set 1190792Sgshapiro * forth in the LICENSE file which can be found at the top level of 1290792Sgshapiro * the sendmail distribution. 1390792Sgshapiro */ 1490792Sgshapiro 1590792Sgshapiro#include <sm/gen.h> 1690792SgshapiroSM_RCSID("@(#)$Id: findfp.c,v 1.62 2002/01/11 16:33:03 ca Exp $") 1790792Sgshapiro#include <stdlib.h> 1890792Sgshapiro#include <unistd.h> 1990792Sgshapiro#include <sys/param.h> 2090792Sgshapiro#include <errno.h> 2190792Sgshapiro#include <string.h> 2290792Sgshapiro#include <syslog.h> 2390792Sgshapiro#include <sm/io.h> 2490792Sgshapiro#include <sm/assert.h> 2590792Sgshapiro#include <sm/heap.h> 2690792Sgshapiro#include <sm/string.h> 2790792Sgshapiro#include <sm/conf.h> 2890792Sgshapiro#include "local.h" 2990792Sgshapiro#include "glue.h" 3090792Sgshapiro 3190792Sgshapirobool Sm_IO_DidInit; /* IO system has been initialized? */ 3290792Sgshapiro 3390792Sgshapiroconst char SmFileMagic[] = "sm_file"; 3490792Sgshapiro 3590792Sgshapiro/* An open type to map to fopen()-like behavior */ 3690792SgshapiroSM_FILE_T SmFtStdio_def = 3790792Sgshapiro {SmFileMagic, 0, 0, 0, (SMRW|SMFBF), -1, {0, 0}, 0, 0, 0, 3890792Sgshapiro sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite, 3990792Sgshapiro sm_stdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER, 4090792Sgshapiro SM_TIME_BLOCK, "stdio" }; 4190792Sgshapiro 4290792Sgshapiro/* An open type to map to fdopen()-like behavior */ 4390792SgshapiroSM_FILE_T SmFtStdiofd_def = 4490792Sgshapiro {SmFileMagic, 0, 0, 0, (SMRW|SMFBF), -1, {0, 0}, 0, 0, 0, 4590792Sgshapiro sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite, 4690792Sgshapiro sm_stdfdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER, 4790792Sgshapiro SM_TIME_BLOCK, "stdiofd" }; 4890792Sgshapiro 4990792Sgshapiro/* A string file type */ 5090792SgshapiroSM_FILE_T _SmFtString_def = 5190792Sgshapiro {SmFileMagic, 0, 0, 0, (SMRW|SMNBF), -1, {0, 0}, 0, 0, 0, 5290792Sgshapiro sm_strclose, sm_strread, sm_strseek, sm_strwrite, 5390792Sgshapiro sm_stropen, sm_strsetinfo, sm_strgetinfo, SM_TIME_FOREVER, 5490792Sgshapiro SM_TIME_BLOCK, "string" }; 5590792Sgshapiro 5690792Sgshapiro#if 0 5790792Sgshapiro/* A file type for syslog communications */ 5890792SgshapiroSM_FILE_T SmFtSyslog_def = 5990792Sgshapiro {SmFileMagic, 0, 0, 0, (SMRW|SMNBF), -1, {0, 0}, 0, 0, 0, 6090792Sgshapiro sm_syslogclose, sm_syslogread, sm_syslogseek, sm_syslogwrite, 6190792Sgshapiro sm_syslogopen, sm_syslogsetinfo, sm_sysloggetinfo, SM_TIME_FOREVER, 6290792Sgshapiro SM_TIME_BLOCK, "syslog" }; 6390792Sgshapiro#endif /* 0 */ 6490792Sgshapiro 6590792Sgshapiro#define NDYNAMIC 10 /* add ten more whenever necessary */ 6690792Sgshapiro 6790792Sgshapiro#define smio(flags, file, name) \ 6890792Sgshapiro {SmFileMagic, 0, 0, 0, flags, file, {0}, 0, SmIoF+file, 0, \ 6990792Sgshapiro sm_stdclose, sm_stdread, sm_stdseek, sm_stdwrite, \ 7090792Sgshapiro sm_stdopen, sm_stdsetinfo, sm_stdgetinfo, SM_TIME_FOREVER, \ 7190792Sgshapiro SM_TIME_BLOCK, name} 7290792Sgshapiro 7390792Sgshapiro/* sm_magic p r w flags file bf lbfsize cookie ival */ 7490792Sgshapiro#define smstd(flags, file, name) \ 7590792Sgshapiro {SmFileMagic, 0, 0, 0, flags, -1, {0}, 0, 0, file, \ 7690792Sgshapiro sm_stdioclose, sm_stdioread, sm_stdioseek, sm_stdiowrite, \ 7790792Sgshapiro sm_stdioopen, sm_stdiosetinfo, sm_stdiogetinfo, SM_TIME_FOREVER,\ 7890792Sgshapiro SM_TIME_BLOCK, name} 7990792Sgshapiro 8090792Sgshapiro/* A file type for interfacing to stdio FILE* streams. */ 8190792SgshapiroSM_FILE_T SmFtRealStdio_def = smstd(SMRW|SMNBF, -1, "realstdio"); 8290792Sgshapiro 8390792Sgshapiro /* the usual - (stdin + stdout + stderr) */ 8490792Sgshapirostatic SM_FILE_T usual[SM_IO_OPEN_MAX - 3]; 8590792Sgshapirostatic struct sm_glue smuglue = { 0, SM_IO_OPEN_MAX - 3, usual }; 8690792Sgshapiro 8790792Sgshapiro/* List of builtin automagically already open file pointers */ 8890792SgshapiroSM_FILE_T SmIoF[6] = 8990792Sgshapiro{ 9090792Sgshapiro smio(SMRD|SMLBF, SMIOIN_FILENO, "smioin"), /* smioin */ 9190792Sgshapiro smio(SMWR|SMLBF, SMIOOUT_FILENO, "smioout"), /* smioout */ 9290792Sgshapiro smio(SMWR|SMNBF, SMIOERR_FILENO, "smioerr"), /* smioerr */ 9390792Sgshapiro smstd(SMRD|SMNBF, SMIOIN_FILENO, "smiostdin"), /* smiostdin */ 9490792Sgshapiro smstd(SMWR|SMNBF, SMIOOUT_FILENO, "smiostdout"),/* smiostdout */ 9590792Sgshapiro smstd(SMWR|SMNBF, SMIOERR_FILENO, "smiostderr") /* smiostderr */ 9690792Sgshapiro}; 9790792Sgshapiro 9890792Sgshapiro/* Structure containing list of currently open file pointers */ 9990792Sgshapirostruct sm_glue smglue = { &smuglue, 3, SmIoF }; 10090792Sgshapiro 10190792Sgshapiro/* 10290792Sgshapiro** SM_MOREGLUE -- adds more space for open file pointers 10390792Sgshapiro** 10490792Sgshapiro** Parameters: 10590792Sgshapiro** n -- number of new spaces for file pointers 10690792Sgshapiro** 10790792Sgshapiro** Returns: 10890792Sgshapiro** Raises an exception if no more memory. 10990792Sgshapiro** Otherwise, returns a pointer to new spaces. 11090792Sgshapiro*/ 11190792Sgshapiro 11290792Sgshapirostatic struct sm_glue *sm_moreglue_x __P((int)); 11390792Sgshapirostatic SM_FILE_T empty; 11490792Sgshapiro 11590792Sgshapirostatic struct sm_glue * 11690792Sgshapirosm_moreglue_x(n) 11790792Sgshapiro register int n; 11890792Sgshapiro{ 11990792Sgshapiro register struct sm_glue *g; 12090792Sgshapiro register SM_FILE_T *p; 12190792Sgshapiro 12290792Sgshapiro g = (struct sm_glue *) sm_pmalloc_x(sizeof(*g) + ALIGNBYTES + 12390792Sgshapiro n * sizeof(SM_FILE_T)); 12490792Sgshapiro p = (SM_FILE_T *) ALIGN(g + 1); 12590792Sgshapiro g->gl_next = NULL; 12690792Sgshapiro g->gl_niobs = n; 12790792Sgshapiro g->gl_iobs = p; 12890792Sgshapiro while (--n >= 0) 12990792Sgshapiro *p++ = empty; 13090792Sgshapiro return g; 13190792Sgshapiro} 13290792Sgshapiro 13390792Sgshapiro/* 13490792Sgshapiro** SM_FP -- allocate and initialize an SM_FILE structure 13590792Sgshapiro** 13690792Sgshapiro** Parameters: 13790792Sgshapiro** t -- file type requested to be opened. 13890792Sgshapiro** flags -- control flags for file type behavior 13990792Sgshapiro** oldfp -- file pointer to reuse if available (optional) 14090792Sgshapiro** 14190792Sgshapiro** Returns: 14290792Sgshapiro** Raises exception on memory exhaustion. 14390792Sgshapiro** Aborts if type is invalid. 14490792Sgshapiro** Otherwise, returns file pointer for requested file type. 14590792Sgshapiro*/ 14690792Sgshapiro 14790792SgshapiroSM_FILE_T * 14890792Sgshapirosm_fp(t, flags, oldfp) 14990792Sgshapiro const SM_FILE_T *t; 15090792Sgshapiro const int flags; 15190792Sgshapiro SM_FILE_T *oldfp; 15290792Sgshapiro{ 15390792Sgshapiro register SM_FILE_T *fp; 15490792Sgshapiro register int n; 15590792Sgshapiro register struct sm_glue *g; 15690792Sgshapiro 15790792Sgshapiro SM_REQUIRE(t->f_open && t->f_close && (t->f_read || t->f_write)); 15890792Sgshapiro 15990792Sgshapiro if (!Sm_IO_DidInit) 16090792Sgshapiro sm_init(); 16190792Sgshapiro 16290792Sgshapiro if (oldfp != NULL) 16390792Sgshapiro { 16490792Sgshapiro fp = oldfp; 16590792Sgshapiro goto found; /* for opening reusing an 'fp' */ 16690792Sgshapiro } 16790792Sgshapiro 16890792Sgshapiro for (g = &smglue;; g = g->gl_next) 16990792Sgshapiro { 17090792Sgshapiro for (fp = g->gl_iobs, n = g->gl_niobs; --n >= 0; fp++) 17190792Sgshapiro if (fp->sm_magic == NULL) 17290792Sgshapiro goto found; 17390792Sgshapiro if (g->gl_next == NULL) 17490792Sgshapiro g->gl_next = sm_moreglue_x(NDYNAMIC); 17590792Sgshapiro } 17690792Sgshapirofound: 17790792Sgshapiro fp->sm_magic = SmFileMagic; /* 'fp' now valid and in-use */ 17890792Sgshapiro fp->f_p = NULL; /* no current pointer */ 17990792Sgshapiro fp->f_w = 0; /* nothing to write */ 18090792Sgshapiro fp->f_r = 0; /* nothing to read */ 18190792Sgshapiro fp->f_flags = flags; 18290792Sgshapiro fp->f_file = -1; /* no file */ 18390792Sgshapiro fp->f_bf.smb_base = NULL; /* no buffer */ 18490792Sgshapiro fp->f_bf.smb_size = 0; /* no buffer size with no buffer */ 18590792Sgshapiro fp->f_lbfsize = 0; /* not line buffered */ 18690792Sgshapiro fp->f_flushfp = NULL; /* no associated flush file */ 18790792Sgshapiro 18890792Sgshapiro fp->f_cookie = fp; /* default: *open* overrides cookie setting */ 18990792Sgshapiro fp->f_close = t->f_close; /* assign close function */ 19090792Sgshapiro fp->f_read = t->f_read; /* assign read function */ 19190792Sgshapiro fp->f_seek = t->f_seek; /* assign seek function */ 19290792Sgshapiro fp->f_write = t->f_write; /* assign write function */ 19390792Sgshapiro fp->f_open = t->f_open; /* assign open function */ 19490792Sgshapiro fp->f_setinfo = t->f_setinfo; /* assign setinfo function */ 19590792Sgshapiro fp->f_getinfo = t->f_getinfo; /* assign getinfo function */ 19690792Sgshapiro fp->f_type = t->f_type; /* file type */ 19790792Sgshapiro fp->f_self = fp; /* self reference for future use */ 19890792Sgshapiro 19990792Sgshapiro fp->f_ub.smb_base = NULL; /* no ungetc buffer */ 20090792Sgshapiro fp->f_ub.smb_size = 0; /* no size for no ungetc buffer */ 20190792Sgshapiro 20290792Sgshapiro fp->f_lb.smb_base = NULL; /* no line buffer */ 20390792Sgshapiro fp->f_lb.smb_size = 0; /* no size for no line buffer */ 20490792Sgshapiro if (fp->f_timeout == SM_TIME_DEFAULT) 20590792Sgshapiro fp->f_timeout = SM_TIME_FOREVER; 20690792Sgshapiro else 20790792Sgshapiro fp->f_timeout = t->f_timeout; /* traditional behavior */ 20890792Sgshapiro fp->f_timeoutstate = SM_TIME_BLOCK; /* by default */ 20990792Sgshapiro 21090792Sgshapiro return fp; 21190792Sgshapiro} 21290792Sgshapiro 21390792Sgshapiro/* 21490792Sgshapiro** SM_CLEANUP -- cleanup function when exit called. 21590792Sgshapiro** 21690792Sgshapiro** This function is registered via atexit(). 21790792Sgshapiro** 21890792Sgshapiro** Parameters: 21990792Sgshapiro** none 22090792Sgshapiro** 22190792Sgshapiro** Returns: 22290792Sgshapiro** nothing. 22390792Sgshapiro** 22490792Sgshapiro** Side Effects: 22590792Sgshapiro** flushes open files before they are forced closed 22690792Sgshapiro*/ 22790792Sgshapiro 22890792Sgshapirovoid 22990792Sgshapirosm_cleanup() 23090792Sgshapiro{ 23190792Sgshapiro int timeout = SM_TIME_DEFAULT; 23290792Sgshapiro 23390792Sgshapiro (void) sm_fwalk(sm_flush, &timeout); /* `cheating' */ 23490792Sgshapiro} 23590792Sgshapiro 23690792Sgshapiro/* 23790792Sgshapiro** SM_INIT -- called whenever sm_io's internal variables must be set up. 23890792Sgshapiro** 23990792Sgshapiro** Parameters: 24090792Sgshapiro** none 24190792Sgshapiro** 24290792Sgshapiro** Returns: 24390792Sgshapiro** none 24490792Sgshapiro** 24590792Sgshapiro** Side Effects: 24690792Sgshapiro** Registers sm_cleanup() using atexit(). 24790792Sgshapiro*/ 24890792Sgshapiro 24990792Sgshapirovoid 25090792Sgshapirosm_init() 25190792Sgshapiro{ 25290792Sgshapiro if (Sm_IO_DidInit) /* paranoia */ 25390792Sgshapiro return; 25490792Sgshapiro 25590792Sgshapiro /* more paranoia: initialize pointers in a static variable */ 25690792Sgshapiro empty.f_type = NULL; 25790792Sgshapiro empty.sm_magic = NULL; 25890792Sgshapiro 25990792Sgshapiro /* make sure we clean up on exit */ 26090792Sgshapiro atexit(sm_cleanup); /* conservative */ 26190792Sgshapiro Sm_IO_DidInit = true; 26290792Sgshapiro} 26390792Sgshapiro 26490792Sgshapiro/* 26590792Sgshapiro** SM_IO_SETINFO -- change info for an open file type (fp) 26690792Sgshapiro** 26790792Sgshapiro** The generic SM_IO_WHAT_VECTORS is auto supplied for all file types. 26890792Sgshapiro** If the request is to set info other than SM_IO_WHAT_VECTORS then 26990792Sgshapiro** the request is passed on to the file type's specific setinfo vector. 27090792Sgshapiro** WARNING: this is working on an active/open file type. 27190792Sgshapiro** 27290792Sgshapiro** Parameters: 27390792Sgshapiro** fp -- file to make the setting on 27490792Sgshapiro** what -- type of information to set 27590792Sgshapiro** valp -- structure to obtain info from 27690792Sgshapiro** 27790792Sgshapiro** Returns: 27890792Sgshapiro** 0 on success 27990792Sgshapiro** -1 on error and sets errno: 28090792Sgshapiro** - when what != SM_IO_WHAT_VECTORS and setinfo vector 28190792Sgshapiro** not set 28290792Sgshapiro** - when vectored setinfo returns -1 28390792Sgshapiro*/ 28490792Sgshapiro 28590792Sgshapiroint 28690792Sgshapirosm_io_setinfo(fp, what, valp) 28790792Sgshapiro SM_FILE_T *fp; 28890792Sgshapiro int what; 28990792Sgshapiro void *valp; 29090792Sgshapiro{ 29190792Sgshapiro SM_FILE_T *v = (SM_FILE_T *) valp; 29290792Sgshapiro 29390792Sgshapiro SM_REQUIRE_ISA(fp, SmFileMagic); 29490792Sgshapiro switch (what) 29590792Sgshapiro { 29690792Sgshapiro case SM_IO_WHAT_VECTORS: 29790792Sgshapiro 29890792Sgshapiro /* 29990792Sgshapiro ** This is the "generic" available for all. 30090792Sgshapiro ** This allows the function vectors to be replaced 30190792Sgshapiro ** while the file type is active. 30290792Sgshapiro */ 30390792Sgshapiro 30490792Sgshapiro fp->f_close = v->f_close; 30590792Sgshapiro fp->f_read = v->f_read; 30690792Sgshapiro fp->f_seek = v->f_seek; 30790792Sgshapiro fp->f_write = v->f_write; 30890792Sgshapiro fp->f_open = v->f_open; 30990792Sgshapiro fp->f_setinfo = v->f_setinfo; 31090792Sgshapiro fp->f_getinfo = v->f_getinfo; 31190792Sgshapiro sm_free(fp->f_type); 31290792Sgshapiro fp->f_type = sm_strdup_x(v->f_type); 31390792Sgshapiro return 0; 31490792Sgshapiro case SM_IO_WHAT_TIMEOUT: 31590792Sgshapiro fp->f_timeout = *((int *)valp); 31690792Sgshapiro return 0; 31790792Sgshapiro } 31890792Sgshapiro 31990792Sgshapiro /* Otherwise the vector will check it out */ 32090792Sgshapiro if (fp->f_setinfo == NULL) 32190792Sgshapiro { 32290792Sgshapiro errno = EINVAL; 32390792Sgshapiro return -1; 32490792Sgshapiro } 32590792Sgshapiro else 32690792Sgshapiro return (*fp->f_setinfo)(fp, what, valp); 32790792Sgshapiro} 32890792Sgshapiro 32990792Sgshapiro/* 33090792Sgshapiro** SM_IO_GETINFO -- get information for an active file type (fp) 33190792Sgshapiro** 33290792Sgshapiro** This function supplies for all file types the answers for the 33390792Sgshapiro** three requests SM_IO_WHAT_VECTORS, SM_IO_WHAT_TYPE and 33490792Sgshapiro** SM_IO_WHAT_ISTYPE. Other requests are handled by the getinfo 33590792Sgshapiro** vector if available for the open file type. 33690792Sgshapiro** SM_IO_WHAT_VECTORS returns information for the file pointer vectors. 33790792Sgshapiro** SM_IO_WHAT_TYPE returns the type identifier for the file pointer 33890792Sgshapiro** SM_IO_WHAT_ISTYPE returns >0 if the passed in type matches the 33990792Sgshapiro** file pointer's type. 34090792Sgshapiro** SM_IO_IS_READABLE returns 1 if there is data available for reading, 34190792Sgshapiro** 0 otherwise. 34290792Sgshapiro** 34390792Sgshapiro** Parameters: 34490792Sgshapiro** fp -- file pointer for active file type 34590792Sgshapiro** what -- type of information request 34690792Sgshapiro** valp -- structure to place obtained info into 34790792Sgshapiro** 34890792Sgshapiro** Returns: 34990792Sgshapiro** -1 on error and sets errno: 35090792Sgshapiro** - when valp==NULL and request expects otherwise 35190792Sgshapiro** - when request is not SM_IO_WHAT_VECTORS and not 35290792Sgshapiro** SM_IO_WHAT_TYPE and not SM_IO_WHAT_ISTYPE 35390792Sgshapiro** and getinfo vector is NULL 35490792Sgshapiro** - when getinfo type vector returns -1 35590792Sgshapiro** >=0 on success 35690792Sgshapiro*/ 35790792Sgshapiro 35890792Sgshapiroint 35990792Sgshapirosm_io_getinfo(fp, what, valp) 36090792Sgshapiro SM_FILE_T *fp; 36190792Sgshapiro int what; 36290792Sgshapiro void *valp; 36390792Sgshapiro{ 36490792Sgshapiro SM_FILE_T *v = (SM_FILE_T *) valp; 36590792Sgshapiro 36690792Sgshapiro SM_REQUIRE_ISA(fp, SmFileMagic); 36790792Sgshapiro 36890792Sgshapiro switch (what) 36990792Sgshapiro { 37090792Sgshapiro case SM_IO_WHAT_VECTORS: 37190792Sgshapiro 37290792Sgshapiro /* This is the "generic" available for all */ 37390792Sgshapiro v->f_close = fp->f_close; 37490792Sgshapiro v->f_read = fp->f_read; 37590792Sgshapiro v->f_seek = fp->f_seek; 37690792Sgshapiro v->f_write = fp->f_write; 37790792Sgshapiro v->f_open = fp->f_open; 37890792Sgshapiro v->f_setinfo = fp->f_setinfo; 37990792Sgshapiro v->f_getinfo = fp->f_getinfo; 38090792Sgshapiro v->f_type = fp->f_type; 38190792Sgshapiro return 0; 38290792Sgshapiro 38390792Sgshapiro case SM_IO_WHAT_TYPE: 38490792Sgshapiro if (valp == NULL) 38590792Sgshapiro { 38690792Sgshapiro errno = EINVAL; 38790792Sgshapiro return -1; 38890792Sgshapiro } 38990792Sgshapiro valp = sm_strdup_x(fp->f_type); 39090792Sgshapiro return 0; 39190792Sgshapiro 39290792Sgshapiro case SM_IO_WHAT_ISTYPE: 39390792Sgshapiro if (valp == NULL) 39490792Sgshapiro { 39590792Sgshapiro errno = EINVAL; 39690792Sgshapiro return -1; 39790792Sgshapiro } 39890792Sgshapiro return strcmp(fp->f_type, valp) == 0; 39990792Sgshapiro 40090792Sgshapiro case SM_IO_IS_READABLE: 40190792Sgshapiro 40290792Sgshapiro /* if there is data in the buffer, it must be readable */ 40390792Sgshapiro if (fp->f_r > 0) 40490792Sgshapiro return 1; 40590792Sgshapiro 40690792Sgshapiro /* otherwise query the underlying file */ 40790792Sgshapiro break; 40890792Sgshapiro 40990792Sgshapiro case SM_IO_WHAT_TIMEOUT: 41090792Sgshapiro *((int *) valp) = fp->f_timeout; 41190792Sgshapiro return 0; 41290792Sgshapiro 41390792Sgshapiro case SM_IO_WHAT_FD: 41490792Sgshapiro if (fp->f_file > -1) 41590792Sgshapiro return fp->f_file; 41690792Sgshapiro 41790792Sgshapiro /* try the file type specific getinfo to see if it knows */ 41890792Sgshapiro break; 41990792Sgshapiro } 42090792Sgshapiro 42190792Sgshapiro /* Otherwise the vector will check it out */ 42290792Sgshapiro if (fp->f_getinfo == NULL) 42390792Sgshapiro { 42490792Sgshapiro errno = EINVAL; 42590792Sgshapiro return -1; 42690792Sgshapiro } 42790792Sgshapiro return (*fp->f_getinfo)(fp, what, valp); 42890792Sgshapiro} 429