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