Home | History | Annotate | Download | only in sm
      1 /*
      2  * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers.
      3  *      All rights reserved.
      4  * Copyright (c) 1990
      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  *	$Id: io.h,v 1.24 2004/03/03 19:14:49 ca Exp $
     15  */
     16 
     17 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     18 
     19 /*-
     20  *	@(#)stdio.h	5.17 (Berkeley) 6/3/91
     21  */
     22 
     23 #ifndef	SM_IO_H
     24 #define SM_IO_H
     25 
     26 #include <stdio.h>
     27 #include <sm/gen.h>
     28 #include <sm/varargs.h>
     29 
     30 /* mode for sm io (exposed) */
     31 #define SM_IO_RDWR	1	/* read-write */
     32 #define SM_IO_RDONLY	2	/* read-only */
     33 #define SM_IO_WRONLY	3	/* write-only */
     34 #define SM_IO_APPEND	4	/* write-only from eof */
     35 #define SM_IO_APPENDRW	5	/* read-write from eof */
     36 #define SM_IO_RDWRTR	6	/* read-write with truncation indicated */
     37 
     38 # define SM_IO_BINARY	0x0	/* binary mode: not used in Unix */
     39 #define SM_IS_BINARY(mode)	(((mode) & SM_IO_BINARY) != 0)
     40 #define SM_IO_MODE(mode)	((mode) & 0x0f)
     41 
     42 #define SM_IO_RDWR_B	(SM_IO_RDWR|SM_IO_BINARY)
     43 #define SM_IO_RDONLY_B	(SM_IO_RDONLY|SM_IO_BINARY)
     44 #define SM_IO_WRONLY_B	(SM_IO_WRONLY|SM_IO_BINARY)
     45 #define SM_IO_APPEND_B	(SM_IO_APPEND|SM_IO_BINARY)
     46 #define SM_IO_APPENDRW_B	(SM_IO_APPENDRW|SM_IO_BINARY)
     47 #define SM_IO_RDWRTR_B	(SM_IO_RDWRTR|SM_IO_BINARY)
     48 
     49 /* for sm_io_fseek, et al api's (exposed) */
     50 #define SM_IO_SEEK_SET	0
     51 #define SM_IO_SEEK_CUR	1
     52 #define SM_IO_SEEK_END	2
     53 
     54 /* flags for info what's with different types (exposed) */
     55 #define SM_IO_WHAT_MODE		1
     56 #define SM_IO_WHAT_VECTORS	2
     57 #define SM_IO_WHAT_FD		3
     58 #define SM_IO_WHAT_TYPE		4
     59 #define SM_IO_WHAT_ISTYPE	5
     60 #define SM_IO_IS_READABLE	6
     61 #define SM_IO_WHAT_TIMEOUT	7
     62 #define SM_IO_WHAT_SIZE		8
     63 
     64 /* info flags (exposed) */
     65 #define SM_IO_FTYPE_CREATE	1
     66 #define SM_IO_FTYPE_MODIFY	2
     67 #define SM_IO_FTYPE_DELETE	3
     68 
     69 #define SM_IO_SL_PRIO		1
     70 
     71 #define SM_IO_OPEN_MAX		20
     72 
     73 /* for internal buffers */
     74 struct smbuf
     75 {
     76 	unsigned char	*smb_base;
     77 	int		smb_size;
     78 };
     79 
     80 /*
     81 **  sm I/O state variables (internal only).
     82 **
     83 **	The following always hold:
     84 **
     85 **		if (flags&(SMLBF|SMWR)) == (SMLBF|SMWR),
     86 **			lbfsize is -bf.size, else lbfsize is 0
     87 **		if flags&SMRD, w is 0
     88 **		if flags&SMWR, r is 0
     89 **
     90 **	This ensures that the getc and putc macros (or inline functions) never
     91 **	try to write or read from a file that is in `read' or `write' mode.
     92 **	(Moreover, they can, and do, automatically switch from read mode to
     93 **	write mode, and back, on "r+" and "w+" files.)
     94 **
     95 **	lbfsize is used only to make the inline line-buffered output stream
     96 **	code as compact as possible.
     97 **
     98 **	ub, up, and ur are used when ungetc() pushes back more characters
     99 **	than fit in the current bf, or when ungetc() pushes back a character
    100 **	that does not match the previous one in bf.  When this happens,
    101 **	ub.base becomes non-nil (i.e., a stream has ungetc() data iff
    102 **	ub.base!=NULL) and up and ur save the current values of p and r.
    103 */
    104 
    105 typedef struct sm_file SM_FILE_T;
    106 
    107 struct sm_file
    108 {
    109 	const char	*sm_magic;	/* This SM_FILE_T is free when NULL */
    110 	unsigned char	*f_p;		/* current position in (some) buffer */
    111 	int		f_r;		/* read space left for getc() */
    112 	int		f_w;		/* write space left for putc() */
    113 	long		f_flags;	/* flags, below */
    114 	short		f_file;		/* fileno, if Unix fd, else -1 */
    115 	struct smbuf	f_bf;		/* the buffer (>= 1 byte, if !NULL) */
    116 	int		f_lbfsize;	/* 0 or -bf.size, for inline putc */
    117 
    118 	/* These can be used for any purpose by a file type implementation: */
    119 	void		*f_cookie;
    120 	int		f_ival;
    121 
    122 	/* operations */
    123 	int		(*f_close) __P((SM_FILE_T *));
    124 	ssize_t		(*f_read)  __P((SM_FILE_T *, char *, size_t));
    125 	off_t		(*f_seek)  __P((SM_FILE_T *, off_t, int));
    126 	ssize_t		(*f_write) __P((SM_FILE_T *, const char *, size_t));
    127 	int		(*f_open) __P((SM_FILE_T *, const void *, int,
    128 					const void *));
    129 	int		(*f_setinfo) __P((SM_FILE_T *, int , void *));
    130 	int		(*f_getinfo) __P((SM_FILE_T *, int , void *));
    131 	int		f_timeout;
    132 	int		f_timeoutstate;   /* either blocking or non-blocking */
    133 	char		*f_type;	/* for by-type lookups */
    134 	struct sm_file	*f_flushfp;	/* flush this before reading parent */
    135 	struct sm_file	*f_modefp;	/* sync mode with this fp */
    136 
    137 	/* separate buffer for long sequences of ungetc() */
    138 	struct smbuf	f_ub;	/* ungetc buffer */
    139 	unsigned char	*f_up;	/* saved f_p when f_p is doing ungetc */
    140 	int		f_ur;	/* saved f_r when f_r is counting ungetc */
    141 
    142 	/* tricks to meet minimum requirements even when malloc() fails */
    143 	unsigned char	f_ubuf[3];	/* guarantee an ungetc() buffer */
    144 	unsigned char	f_nbuf[1];	/* guarantee a getc() buffer */
    145 
    146 	/* Unix stdio files get aligned to block boundaries on fseek() */
    147 	int		f_blksize;	/* stat.st_blksize (may be != bf.size) */
    148 	off_t		f_lseekoff;	/* current lseek offset */
    149 	int		f_dup_cnt;	/* count file dup'd */
    150 };
    151 
    152 __BEGIN_DECLS
    153 extern SM_FILE_T	SmIoF[];
    154 extern const char	SmFileMagic[];
    155 extern SM_FILE_T	SmFtStdio_def;
    156 extern SM_FILE_T	SmFtStdiofd_def;
    157 extern SM_FILE_T	SmFtString_def;
    158 extern SM_FILE_T	SmFtSyslog_def;
    159 extern SM_FILE_T	SmFtRealStdio_def;
    160 
    161 #define SMIOIN_FILENO		0
    162 #define SMIOOUT_FILENO		1
    163 #define SMIOERR_FILENO		2
    164 #define SMIOSTDIN_FILENO	3
    165 #define SMIOSTDOUT_FILENO	4
    166 #define SMIOSTDERR_FILENO	5
    167 
    168 /* Common predefined and already (usually) open files (exposed) */
    169 #define smioin		(&SmIoF[SMIOIN_FILENO])
    170 #define smioout		(&SmIoF[SMIOOUT_FILENO])
    171 #define smioerr		(&SmIoF[SMIOERR_FILENO])
    172 #define smiostdin	(&SmIoF[SMIOSTDIN_FILENO])
    173 #define smiostdout	(&SmIoF[SMIOSTDOUT_FILENO])
    174 #define smiostderr	(&SmIoF[SMIOSTDERR_FILENO])
    175 
    176 #define SmFtStdio	(&SmFtStdio_def)
    177 #define SmFtStdiofd	(&SmFtStdiofd_def)
    178 #define SmFtString	(&SmFtString_def)
    179 #define SmFtSyslog	(&SmFtSyslog_def)
    180 #define SmFtRealStdio	(&SmFtRealStdio_def)
    181 
    182 #ifdef __STDC__
    183 # define SM_IO_SET_TYPE(f, name, open, close, read, write, seek, get, set, timeout) \
    184     (f) = {SmFileMagic, (unsigned char *) 0, 0, 0, 0L, -1, {0}, 0, (void *) 0,\
    185 	0, (close), (read), (seek), (write), (open), (set), (get), (timeout),\
    186 	0, (name)}
    187 # define SM_IO_INIT_TYPE(f, name, open, close, read, write, seek, get, set, timeout)
    188 
    189 #else /* __STDC__ */
    190 # define SM_IO_SET_TYPE(f, name, open, close, read, write, seek, get, set, timeout) (f)
    191 # define SM_IO_INIT_TYPE(f, name, open, close, read, write, seek, get, set, timeout) \
    192 	(f).sm_magic = SmFileMagic;	\
    193 	(f).f_p = (unsigned char *) 0;	\
    194 	(f).f_r = 0;	\
    195 	(f).f_w = 0;	\
    196 	(f).f_flags = 0L;	\
    197 	(f).f_file = 0;	\
    198 	(f).f_bf.smb_base = (unsigned char *) 0;	\
    199 	(f).f_bf.smb_size = 0;	\
    200 	(f).f_lbfsize = 0;	\
    201 	(f).f_cookie = (void *) 0;	\
    202 	(f).f_ival = 0;	\
    203 	(f).f_close = (close);	\
    204 	(f).f_read = (read);	\
    205 	(f).f_seek = (seek);	\
    206 	(f).f_write = (write);	\
    207 	(f).f_open = (open);	\
    208 	(f).f_setinfo = (set);	\
    209 	(f).f_getinfo = (get);	\
    210 	(f).f_timeout = (timeout);	\
    211 	(f).f_timeoutstate = 0;	\
    212 	(f).f_type = (name);
    213 
    214 #endif /* __STDC__ */
    215 
    216 __END_DECLS
    217 
    218 /* Internal flags */
    219 #define SMFBF		0x000001	/* XXXX fully buffered */
    220 #define SMLBF		0x000002	/* line buffered */
    221 #define SMNBF		0x000004	/* unbuffered */
    222 #define SMNOW		0x000008	/* Flush each write; take read now */
    223 #define SMRD		0x000010	/* OK to read */
    224 #define SMWR		0x000020	/* OK to write */
    225 	/* RD and WR are never simultaneously asserted */
    226 #define SMRW		0x000040	/* open for reading & writing */
    227 #define SMFEOF		0x000080	/* found EOF */
    228 #define SMERR		0x000100	/* found error */
    229 #define SMMBF		0x000200	/* buf is from malloc */
    230 #define SMAPP		0x000400	/* fdopen()ed in append mode */
    231 #define SMSTR		0x000800	/* this is an snprintf string */
    232 #define SMOPT		0x001000	/* do fseek() optimisation */
    233 #define SMNPT		0x002000	/* do not do fseek() optimisation */
    234 #define SMOFF		0x004000	/* set iff offset is in fact correct */
    235 #define SMALC		0x010000	/* allocate string space dynamically */
    236 
    237 #define SMMODEMASK	0x0070	/* read/write mode */
    238 
    239 /* defines for timeout constants */
    240 #define SM_TIME_IMMEDIATE	(0)
    241 #define SM_TIME_FOREVER		(-1)
    242 #define SM_TIME_DEFAULT		(-2)
    243 
    244 /* timeout state for blocking */
    245 #define SM_TIME_BLOCK		(0)	/* XXX just bool? */
    246 #define SM_TIME_NONBLOCK	(1)
    247 
    248 /* Exposed buffering type flags */
    249 #define SM_IO_FBF	0	/* setvbuf should set fully buffered */
    250 #define SM_IO_LBF	1	/* setvbuf should set line buffered */
    251 #define SM_IO_NBF	2	/* setvbuf should set unbuffered */
    252 
    253 /* setvbuf buffered, but through at lower file type layers */
    254 #define SM_IO_NOW	3
    255 
    256 /*
    257 **  size of buffer used by setbuf.
    258 **  If underlying filesystem blocksize is discoverable that is used instead
    259 */
    260 
    261 #define SM_IO_BUFSIZ	4096
    262 
    263 #define SM_IO_EOF	(-1)
    264 
    265 /* Functions defined in ANSI C standard.  */
    266 __BEGIN_DECLS
    267 SM_FILE_T *sm_io_autoflush __P((SM_FILE_T *, SM_FILE_T *));
    268 void	 sm_io_automode __P((SM_FILE_T *, SM_FILE_T *));
    269 void	 sm_io_clearerr __P((SM_FILE_T *));
    270 int	 sm_io_close __P((SM_FILE_T *, int SM_NONVOLATILE));
    271 SM_FILE_T *sm_io_dup __P((SM_FILE_T *));
    272 int	 sm_io_eof __P((SM_FILE_T *));
    273 int	 sm_io_error __P((SM_FILE_T *));
    274 char	*sm_io_fgets __P((SM_FILE_T *, int, char *, int));
    275 int	 sm_io_flush __P((SM_FILE_T *, int SM_NONVOLATILE));
    276 
    277 int PRINTFLIKE(3, 4)
    278 sm_io_fprintf __P((SM_FILE_T *, int, const char *, ...));
    279 
    280 int	 sm_io_fputs __P((SM_FILE_T *, int, const char *));
    281 
    282 int SCANFLIKE(3, 4)
    283 sm_io_fscanf __P((SM_FILE_T *, int, const char *, ...));
    284 
    285 int	 sm_io_getc __P((SM_FILE_T *, int));
    286 int	 sm_io_getinfo __P((SM_FILE_T *, int, void *));
    287 SM_FILE_T *sm_io_open __P((const SM_FILE_T *, int SM_NONVOLATILE, const void *,
    288 			   int, const void *));
    289 int	 sm_io_purge __P((SM_FILE_T *));
    290 int	 sm_io_putc __P((SM_FILE_T *, int, int));
    291 size_t	 sm_io_read __P((SM_FILE_T *, int, void *, size_t));
    292 SM_FILE_T *sm_io_reopen __P((const SM_FILE_T *, int SM_NONVOLATILE,
    293 			     const void *, int, const void *, SM_FILE_T *));
    294 void	 sm_io_rewind __P((SM_FILE_T *, int));
    295 int	 sm_io_seek __P((SM_FILE_T *, int SM_NONVOLATILE, long SM_NONVOLATILE,
    296 			 int SM_NONVOLATILE));
    297 int	 sm_io_setinfo __P((SM_FILE_T *, int, void *));
    298 int	 sm_io_setvbuf __P((SM_FILE_T *, int, char *, int, size_t));
    299 
    300 int SCANFLIKE(2, 3)
    301 sm_io_sscanf __P((const char *, char const *, ...));
    302 
    303 long	 sm_io_tell __P((SM_FILE_T *, int SM_NONVOLATILE));
    304 int	 sm_io_ungetc __P((SM_FILE_T *, int, int));
    305 int	 sm_io_vfprintf __P((SM_FILE_T *, int, const char *, va_list));
    306 size_t	 sm_io_write __P((SM_FILE_T *, int, const void *, size_t));
    307 
    308 void	 sm_strio_init __P((SM_FILE_T *, char *, size_t));
    309 
    310 extern SM_FILE_T *
    311 sm_io_fopen __P((
    312 	char *_pathname,
    313 	int _flags,
    314 	...));
    315 
    316 extern SM_FILE_T *
    317 sm_io_stdioopen __P((
    318 	FILE *_stream,
    319 	char *_mode));
    320 
    321 extern int
    322 sm_vasprintf __P((
    323 	char **_str,
    324 	const char *_fmt,
    325 	va_list _ap));
    326 
    327 extern int
    328 sm_vsnprintf __P((
    329 	char *,
    330 	size_t,
    331 	const char *,
    332 	va_list));
    333 
    334 extern void
    335 sm_perror __P((
    336 	const char *));
    337 
    338 __END_DECLS
    339 
    340 /*
    341 ** Functions internal to the implementation.
    342 */
    343 
    344 __BEGIN_DECLS
    345 int	sm_rget __P((SM_FILE_T *, int));
    346 int	sm_vfscanf __P((SM_FILE_T *, int SM_NONVOLATILE, const char *,
    347 			va_list SM_NONVOLATILE));
    348 int	sm_wbuf __P((SM_FILE_T *, int, int));
    349 __END_DECLS
    350 
    351 /*
    352 **  The macros are here so that we can
    353 **  define function versions in the library.
    354 */
    355 
    356 #define sm_getc(f, t) \
    357 	(--(f)->f_r < 0 ? \
    358 		sm_rget(f, t) : \
    359 		(int)(*(f)->f_p++))
    360 
    361 /*
    362 **  This has been tuned to generate reasonable code on the vax using pcc.
    363 **  (It also generates reasonable x86 code using gcc.)
    364 */
    365 
    366 #define sm_putc(f, t, c) \
    367 	(--(f)->f_w < 0 ? \
    368 		(f)->f_w >= (f)->f_lbfsize ? \
    369 			(*(f)->f_p = (c)), *(f)->f_p != '\n' ? \
    370 				(int)*(f)->f_p++ : \
    371 				sm_wbuf(f, t, '\n') : \
    372 			sm_wbuf(f, t, (int)(c)) : \
    373 		(*(f)->f_p = (c), (int)*(f)->f_p++))
    374 
    375 #define sm_eof(p)	(((p)->f_flags & SMFEOF) != 0)
    376 #define sm_error(p)	(((p)->f_flags & SMERR) != 0)
    377 #define sm_clearerr(p)	((void)((p)->f_flags &= ~(SMERR|SMFEOF)))
    378 
    379 #define sm_io_eof(p)	sm_eof(p)
    380 #define sm_io_error(p)	sm_error(p)
    381 
    382 #define sm_io_clearerr(p)	sm_clearerr(p)
    383 
    384 #ifndef lint
    385 # ifndef _POSIX_SOURCE
    386 #  define sm_io_getc(fp, t)	sm_getc(fp, t)
    387 #  define sm_io_putc(fp, t, x)	sm_putc(fp, t, x)
    388 # endif /* _POSIX_SOURCE */
    389 #endif /* lint */
    390 
    391 #endif /* SM_IO_H */
    392