summaryrefslogtreecommitdiff
path: root/gnu/usr.sbin/sendmail/include/sm/io.h
blob: db56fba432add09b9894f3a74f5e6a9d8ae31189 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
/*
 * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers.
 *      All rights reserved.
 * Copyright (c) 1990
 * 	 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.
 *
 *	$Sendmail: io.h,v 1.24 2004/03/03 19:14:49 ca Exp $
 */

/*-
 *	@(#)stdio.h	5.17 (Berkeley) 6/3/91
 */

#ifndef	SM_IO_H
#define SM_IO_H

#include <stdio.h>
#include <sm/gen.h>
#include <sm/varargs.h>

/* mode for sm io (exposed) */
#define SM_IO_RDWR	1	/* read-write */
#define SM_IO_RDONLY	2	/* read-only */
#define SM_IO_WRONLY	3	/* write-only */
#define SM_IO_APPEND	4	/* write-only from eof */
#define SM_IO_APPENDRW	5	/* read-write from eof */
#define SM_IO_RDWRTR	6	/* read-write with truncation indicated */

# define SM_IO_BINARY	0x0	/* binary mode: not used in Unix */
#define SM_IS_BINARY(mode)	(((mode) & SM_IO_BINARY) != 0)
#define SM_IO_MODE(mode)	((mode) & 0x0f)

#define SM_IO_RDWR_B	(SM_IO_RDWR|SM_IO_BINARY)
#define SM_IO_RDONLY_B	(SM_IO_RDONLY|SM_IO_BINARY)
#define SM_IO_WRONLY_B	(SM_IO_WRONLY|SM_IO_BINARY)
#define SM_IO_APPEND_B	(SM_IO_APPEND|SM_IO_BINARY)
#define SM_IO_APPENDRW_B	(SM_IO_APPENDRW|SM_IO_BINARY)
#define SM_IO_RDWRTR_B	(SM_IO_RDWRTR|SM_IO_BINARY)

/* for sm_io_fseek, et al api's (exposed) */
#define SM_IO_SEEK_SET	0
#define SM_IO_SEEK_CUR	1
#define SM_IO_SEEK_END	2

/* flags for info what's with different types (exposed) */
#define SM_IO_WHAT_MODE		1
#define SM_IO_WHAT_VECTORS	2
#define SM_IO_WHAT_FD		3
#define SM_IO_WHAT_TYPE		4
#define SM_IO_WHAT_ISTYPE	5
#define SM_IO_IS_READABLE	6
#define SM_IO_WHAT_TIMEOUT	7
#define SM_IO_WHAT_SIZE		8

/* info flags (exposed) */
#define SM_IO_FTYPE_CREATE	1
#define SM_IO_FTYPE_MODIFY	2
#define SM_IO_FTYPE_DELETE	3

#define SM_IO_SL_PRIO		1

#define SM_IO_OPEN_MAX		20

/* for internal buffers */
struct smbuf
{
	unsigned char	*smb_base;
	int		smb_size;
};

/*
**  sm I/O state variables (internal only).
**
**	The following always hold:
**
**		if (flags&(SMLBF|SMWR)) == (SMLBF|SMWR),
**			lbfsize is -bf.size, else lbfsize is 0
**		if flags&SMRD, w is 0
**		if flags&SMWR, r is 0
**
**	This ensures that the getc and putc macros (or inline functions) never
**	try to write or read from a file that is in `read' or `write' mode.
**	(Moreover, they can, and do, automatically switch from read mode to
**	write mode, and back, on "r+" and "w+" files.)
**
**	lbfsize is used only to make the inline line-buffered output stream
**	code as compact as possible.
**
**	ub, up, and ur are used when ungetc() pushes back more characters
**	than fit in the current bf, or when ungetc() pushes back a character
**	that does not match the previous one in bf.  When this happens,
**	ub.base becomes non-nil (i.e., a stream has ungetc() data iff
**	ub.base!=NULL) and up and ur save the current values of p and r.
*/

typedef struct sm_file SM_FILE_T;

struct sm_file
{
	const char	*sm_magic;	/* This SM_FILE_T is free when NULL */
	unsigned char	*f_p;		/* current position in (some) buffer */
	int		f_r;		/* read space left for getc() */
	int		f_w;		/* write space left for putc() */
	long		f_flags;	/* flags, below */
	short		f_file;		/* fileno, if Unix fd, else -1 */
	struct smbuf	f_bf;		/* the buffer (>= 1 byte, if !NULL) */
	int		f_lbfsize;	/* 0 or -bf.size, for inline putc */

	/* These can be used for any purpose by a file type implementation: */
	void		*f_cookie;
	int		f_ival;

	/* operations */
	int		(*f_close) __P((SM_FILE_T *));
	ssize_t		(*f_read)  __P((SM_FILE_T *, char *, size_t));
	off_t		(*f_seek)  __P((SM_FILE_T *, off_t, int));
	ssize_t		(*f_write) __P((SM_FILE_T *, const char *, size_t));
	int		(*f_open) __P((SM_FILE_T *, const void *, int,
					const void *));
	int		(*f_setinfo) __P((SM_FILE_T *, int , void *));
	int		(*f_getinfo) __P((SM_FILE_T *, int , void *));
	int		f_timeout;
	int		f_timeoutstate;   /* either blocking or non-blocking */
	char		*f_type;	/* for by-type lookups */
	struct sm_file	*f_flushfp;	/* flush this before reading parent */
	struct sm_file	*f_modefp;	/* sync mode with this fp */

	/* separate buffer for long sequences of ungetc() */
	struct smbuf	f_ub;	/* ungetc buffer */
	unsigned char	*f_up;	/* saved f_p when f_p is doing ungetc */
	int		f_ur;	/* saved f_r when f_r is counting ungetc */

	/* tricks to meet minimum requirements even when malloc() fails */
	unsigned char	f_ubuf[3];	/* guarantee an ungetc() buffer */
	unsigned char	f_nbuf[1];	/* guarantee a getc() buffer */

	/* Unix stdio files get aligned to block boundaries on fseek() */
	int		f_blksize;	/* stat.st_blksize (may be != bf.size) */
	off_t		f_lseekoff;	/* current lseek offset */
	int		f_dup_cnt;	/* count file dup'd */
};

__BEGIN_DECLS
extern SM_FILE_T	SmIoF[];
extern const char	SmFileMagic[];
extern SM_FILE_T	SmFtStdio_def;
extern SM_FILE_T	SmFtStdiofd_def;
extern SM_FILE_T	SmFtString_def;
extern SM_FILE_T	SmFtSyslog_def;
extern SM_FILE_T	SmFtRealStdio_def;

#define SMIOIN_FILENO		0
#define SMIOOUT_FILENO		1
#define SMIOERR_FILENO		2
#define SMIOSTDIN_FILENO	3
#define SMIOSTDOUT_FILENO	4
#define SMIOSTDERR_FILENO	5

/* Common predefined and already (usually) open files (exposed) */
#define smioin		(&SmIoF[SMIOIN_FILENO])
#define smioout		(&SmIoF[SMIOOUT_FILENO])
#define smioerr		(&SmIoF[SMIOERR_FILENO])
#define smiostdin	(&SmIoF[SMIOSTDIN_FILENO])
#define smiostdout	(&SmIoF[SMIOSTDOUT_FILENO])
#define smiostderr	(&SmIoF[SMIOSTDERR_FILENO])

#define SmFtStdio	(&SmFtStdio_def)
#define SmFtStdiofd	(&SmFtStdiofd_def)
#define SmFtString	(&SmFtString_def)
#define SmFtSyslog	(&SmFtSyslog_def)
#define SmFtRealStdio	(&SmFtRealStdio_def)

#ifdef __STDC__
# define SM_IO_SET_TYPE(f, name, open, close, read, write, seek, get, set, timeout) \
    (f) = {SmFileMagic, (unsigned char *) 0, 0, 0, 0L, -1, {0}, 0, (void *) 0,\
	0, (close), (read), (seek), (write), (open), (set), (get), (timeout),\
	0, (name)}
# define SM_IO_INIT_TYPE(f, name, open, close, read, write, seek, get, set, timeout)

#else /* __STDC__ */
# define SM_IO_SET_TYPE(f, name, open, close, read, write, seek, get, set, timeout) (f)
# define SM_IO_INIT_TYPE(f, name, open, close, read, write, seek, get, set, timeout) \
	(f).sm_magic = SmFileMagic;	\
	(f).f_p = (unsigned char *) 0;	\
	(f).f_r = 0;	\
	(f).f_w = 0;	\
	(f).f_flags = 0L;	\
	(f).f_file = 0;	\
	(f).f_bf.smb_base = (unsigned char *) 0;	\
	(f).f_bf.smb_size = 0;	\
	(f).f_lbfsize = 0;	\
	(f).f_cookie = (void *) 0;	\
	(f).f_ival = 0;	\
	(f).f_close = (close);	\
	(f).f_read = (read);	\
	(f).f_seek = (seek);	\
	(f).f_write = (write);	\
	(f).f_open = (open);	\
	(f).f_setinfo = (set);	\
	(f).f_getinfo = (get);	\
	(f).f_timeout = (timeout);	\
	(f).f_timeoutstate = 0;	\
	(f).f_type = (name);

#endif /* __STDC__ */

__END_DECLS

/* Internal flags */
#define SMFBF		0x000001	/* XXXX fully buffered */
#define SMLBF		0x000002	/* line buffered */
#define SMNBF		0x000004	/* unbuffered */
#define SMNOW		0x000008	/* Flush each write; take read now */
#define SMRD		0x000010	/* OK to read */
#define SMWR		0x000020	/* OK to write */
	/* RD and WR are never simultaneously asserted */
#define SMRW		0x000040	/* open for reading & writing */
#define SMFEOF		0x000080	/* found EOF */
#define SMERR		0x000100	/* found error */
#define SMMBF		0x000200	/* buf is from malloc */
#define SMAPP		0x000400	/* fdopen()ed in append mode */
#define SMSTR		0x000800	/* this is an snprintf string */
#define SMOPT		0x001000	/* do fseek() optimisation */
#define SMNPT		0x002000	/* do not do fseek() optimisation */
#define SMOFF		0x004000	/* set iff offset is in fact correct */
#define SMALC		0x010000	/* allocate string space dynamically */

#define SMMODEMASK	0x0070	/* read/write mode */

/* defines for timeout constants */
#define SM_TIME_IMMEDIATE	(0)
#define SM_TIME_FOREVER		(-1)
#define SM_TIME_DEFAULT		(-2)

/* timeout state for blocking */
#define SM_TIME_BLOCK		(0)	/* XXX just bool? */
#define SM_TIME_NONBLOCK	(1)

/* Exposed buffering type flags */
#define SM_IO_FBF	0	/* setvbuf should set fully buffered */
#define SM_IO_LBF	1	/* setvbuf should set line buffered */
#define SM_IO_NBF	2	/* setvbuf should set unbuffered */

/* setvbuf buffered, but through at lower file type layers */
#define SM_IO_NOW	3

/*
**  size of buffer used by setbuf.
**  If underlying filesystem blocksize is discoverable that is used instead
*/

#define SM_IO_BUFSIZ	4096

#define SM_IO_EOF	(-1)

/* Functions defined in ANSI C standard.  */
__BEGIN_DECLS
SM_FILE_T *sm_io_autoflush __P((SM_FILE_T *, SM_FILE_T *));
void	 sm_io_automode __P((SM_FILE_T *, SM_FILE_T *));
void	 sm_io_clearerr __P((SM_FILE_T *));
int	 sm_io_close __P((SM_FILE_T *, int SM_NONVOLATILE));
SM_FILE_T *sm_io_dup __P((SM_FILE_T *));
int	 sm_io_eof __P((SM_FILE_T *));
int	 sm_io_error __P((SM_FILE_T *));
char	*sm_io_fgets __P((SM_FILE_T *, int, char *, int));
int	 sm_io_flush __P((SM_FILE_T *, int SM_NONVOLATILE));

int PRINTFLIKE(3, 4)
sm_io_fprintf __P((SM_FILE_T *, int, const char *, ...));

int	 sm_io_fputs __P((SM_FILE_T *, int, const char *));

int SCANFLIKE(3, 4)
sm_io_fscanf __P((SM_FILE_T *, int, const char *, ...));

int	 sm_io_getc __P((SM_FILE_T *, int));
int	 sm_io_getinfo __P((SM_FILE_T *, int, void *));
SM_FILE_T *sm_io_open __P((const SM_FILE_T *, int SM_NONVOLATILE, const void *,
			   int, const void *));
int	 sm_io_purge __P((SM_FILE_T *));
int	 sm_io_putc __P((SM_FILE_T *, int, int));
size_t	 sm_io_read __P((SM_FILE_T *, int, void *, size_t));
SM_FILE_T *sm_io_reopen __P((const SM_FILE_T *, int SM_NONVOLATILE,
			     const void *, int, const void *, SM_FILE_T *));
void	 sm_io_rewind __P((SM_FILE_T *, int));
int	 sm_io_seek __P((SM_FILE_T *, int SM_NONVOLATILE, long SM_NONVOLATILE,
			 int SM_NONVOLATILE));
int	 sm_io_setinfo __P((SM_FILE_T *, int, void *));
int	 sm_io_setvbuf __P((SM_FILE_T *, int, char *, int, size_t));

int SCANFLIKE(2, 3)
sm_io_sscanf __P((const char *, char const *, ...));

long	 sm_io_tell __P((SM_FILE_T *, int SM_NONVOLATILE));
int	 sm_io_ungetc __P((SM_FILE_T *, int, int));
int	 sm_io_vfprintf __P((SM_FILE_T *, int, const char *, va_list));
size_t	 sm_io_write __P((SM_FILE_T *, int, const void *, size_t));

void	 sm_strio_init __P((SM_FILE_T *, char *, size_t));

extern SM_FILE_T *
sm_io_fopen __P((
	char *_pathname,
	int _flags,
	...));

extern SM_FILE_T *
sm_io_stdioopen __P((
	FILE *_stream,
	char *_mode));

extern int
sm_vasprintf __P((
	char **_str,
	const char *_fmt,
	va_list _ap));

extern int
sm_vsnprintf __P((
	char *,
	size_t,
	const char *,
	va_list));

extern void
sm_perror __P((
	const char *));

__END_DECLS

/*
** Functions internal to the implementation.
*/

__BEGIN_DECLS
int	sm_rget __P((SM_FILE_T *, int));
int	sm_vfscanf __P((SM_FILE_T *, int SM_NONVOLATILE, const char *,
			va_list SM_NONVOLATILE));
int	sm_wbuf __P((SM_FILE_T *, int, int));
__END_DECLS

/*
**  The macros are here so that we can
**  define function versions in the library.
*/

#define sm_getc(f, t) \
	(--(f)->f_r < 0 ? \
		sm_rget(f, t) : \
		(int)(*(f)->f_p++))

/*
**  This has been tuned to generate reasonable code on the vax using pcc.
**  (It also generates reasonable x86 code using gcc.)
*/

#define sm_putc(f, t, c) \
	(--(f)->f_w < 0 ? \
		(f)->f_w >= (f)->f_lbfsize ? \
			(*(f)->f_p = (c)), *(f)->f_p != '\n' ? \
				(int)*(f)->f_p++ : \
				sm_wbuf(f, t, '\n') : \
			sm_wbuf(f, t, (int)(c)) : \
		(*(f)->f_p = (c), (int)*(f)->f_p++))

#define sm_eof(p)	(((p)->f_flags & SMFEOF) != 0)
#define sm_error(p)	(((p)->f_flags & SMERR) != 0)
#define sm_clearerr(p)	((void)((p)->f_flags &= ~(SMERR|SMFEOF)))

#define sm_io_eof(p)	sm_eof(p)
#define sm_io_error(p)	sm_error(p)

#define sm_io_clearerr(p)	sm_clearerr(p)

#ifndef lint
# ifndef _POSIX_SOURCE
#  define sm_io_getc(fp, t)	sm_getc(fp, t)
#  define sm_io_putc(fp, t, x)	sm_putc(fp, t, x)
# endif /* _POSIX_SOURCE */
#endif /* lint */

#endif /* SM_IO_H */