xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/vstream.h (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: vstream.h,v 1.2 2017/02/14 01:16:49 christos Exp $	*/
2 
3 #ifndef _VSTREAM_H_INCLUDED_
4 #define _VSTREAM_H_INCLUDED_
5 
6 /*++
7 /* NAME
8 /*	vstream 3h
9 /* SUMMARY
10 /*	simple buffered I/O package
11 /* SYNOPSIS
12 /*	#include <vstream.h>
13 /* DESCRIPTION
14 /* .nf
15 
16  /*
17   * System library.
18   */
19 #include <sys/time.h>
20 #include <time.h>
21 #include <fcntl.h>
22 #include <stdarg.h>
23 #include <setjmp.h>
24 #include <unistd.h>
25 
26  /*
27   * Utility library.
28   */
29 #include <vbuf.h>
30 #include <check_arg.h>
31 
32  /*
33   * Simple buffered stream. The members of this structure are not part of the
34   * official interface and can change without prior notice.
35   */
36 typedef ssize_t (*VSTREAM_RW_FN) (int, void *, size_t, int, void *);
37 typedef pid_t(*VSTREAM_WAITPID_FN) (pid_t, WAIT_STATUS_T *, int);
38 
39 #ifdef NO_SIGSETJMP
40 #define VSTREAM_JMP_BUF	jmp_buf
41 #else
42 #define VSTREAM_JMP_BUF	sigjmp_buf
43 #endif
44 
45 typedef struct VSTREAM {
46     VBUF    buf;			/* generic intelligent buffer */
47     int     fd;				/* file handle, no 256 limit */
48     VSTREAM_RW_FN read_fn;		/* buffer fill action */
49     VSTREAM_RW_FN write_fn;		/* buffer fill action */
50     ssize_t req_bufsize;		/* requested read/write buffer size */
51     void   *context;			/* application context */
52     off_t   offset;			/* cached seek info */
53     char   *path;			/* give it at least try */
54     int     read_fd;			/* read channel (double-buffered) */
55     int     write_fd;			/* write channel (double-buffered) */
56     VBUF    read_buf;			/* read buffer (double-buffered) */
57     VBUF    write_buf;			/* write buffer (double-buffered) */
58     pid_t   pid;			/* vstream_popen/close() */
59     VSTREAM_WAITPID_FN waitpid_fn;	/* vstream_popen/close() */
60     int     timeout;			/* read/write timout */
61     VSTREAM_JMP_BUF *jbuf;		/* exception handling */
62     struct timeval iotime;		/* time of last fill/flush */
63     struct timeval time_limit;		/* read/write time limit */
64 } VSTREAM;
65 
66 extern VSTREAM vstream_fstd[];		/* pre-defined streams */
67 
68 #define VSTREAM_IN		(&vstream_fstd[0])
69 #define VSTREAM_OUT		(&vstream_fstd[1])
70 #define VSTREAM_ERR		(&vstream_fstd[2])
71 
72 #define VSTREAM_FLAG_RD_ERR	VBUF_FLAG_RD_ERR	/* read error */
73 #define VSTREAM_FLAG_WR_ERR	VBUF_FLAG_WR_ERR	/* write error */
74 #define VSTREAM_FLAG_RD_TIMEOUT	VBUF_FLAG_RD_TIMEOUT	/* read timeout */
75 #define VSTREAM_FLAG_WR_TIMEOUT	VBUF_FLAG_WR_TIMEOUT	/* write timeout */
76 
77 #define	VSTREAM_FLAG_ERR	VBUF_FLAG_ERR	/* some I/O error */
78 #define VSTREAM_FLAG_EOF	VBUF_FLAG_EOF	/* end of file */
79 #define VSTREAM_FLAG_TIMEOUT	VBUF_FLAG_TIMEOUT	/* timeout error */
80 #define VSTREAM_FLAG_FIXED	VBUF_FLAG_FIXED	/* fixed-size buffer */
81 #define VSTREAM_FLAG_BAD	VBUF_FLAG_BAD
82 
83 #define VSTREAM_FLAG_READ	(1<<8)	/* read buffer */
84 #define VSTREAM_FLAG_WRITE	(1<<9)	/* write buffer */
85 #define VSTREAM_FLAG_SEEK	(1<<10)	/* seek info valid */
86 #define VSTREAM_FLAG_NSEEK	(1<<11)	/* can't seek this file */
87 #define VSTREAM_FLAG_DOUBLE	(1<<12)	/* double buffer */
88 #define VSTREAM_FLAG_DEADLINE	(1<<13)	/* deadline active */
89 
90 #define VSTREAM_PURGE_READ	(1<<0)	/* flush unread data */
91 #define VSTREAM_PURGE_WRITE	(1<<1)	/* flush unwritten data */
92 #define VSTREAM_PURGE_BOTH	(VSTREAM_PURGE_READ|VSTREAM_PURGE_WRITE)
93 
94 #define VSTREAM_BUFSIZE		4096
95 
96 extern VSTREAM *vstream_fopen(const char *, int, mode_t);
97 extern int vstream_fclose(VSTREAM *);
98 extern off_t WARN_UNUSED_RESULT vstream_fseek(VSTREAM *, off_t, int);
99 extern off_t vstream_ftell(VSTREAM *);
100 extern int vstream_fpurge(VSTREAM *, int);
101 extern int vstream_fflush(VSTREAM *);
102 extern int vstream_fputs(const char *, VSTREAM *);
103 extern VSTREAM *vstream_fdopen(int, int);
104 extern int vstream_fdclose(VSTREAM *);
105 
106 #define vstream_fread(v, b, n)	vbuf_read(&(v)->buf, (b), (n))
107 #define vstream_fwrite(v, b, n)	vbuf_write(&(v)->buf, (b), (n))
108 
109 #define VSTREAM_PUTC(ch, vp)	VBUF_PUT(&(vp)->buf, (ch))
110 #define VSTREAM_GETC(vp)	VBUF_GET(&(vp)->buf)
111 #define vstream_ungetc(vp, ch)	vbuf_unget(&(vp)->buf, (ch))
112 #define VSTREAM_EOF		VBUF_EOF
113 
114 #define VSTREAM_PUTCHAR(ch)	VSTREAM_PUTC((ch), VSTREAM_OUT)
115 #define VSTREAM_GETCHAR()	VSTREAM_GETC(VSTREAM_IN)
116 
117 #define vstream_fileno(vp)	((vp)->fd)
118 #define vstream_req_bufsize(vp)	((const ssize_t) ((vp)->req_bufsize))
119 #define vstream_context(vp)	((vp)->context)
120 #define vstream_rd_error(vp)	vbuf_rd_error(&(vp)->buf)
121 #define vstream_wr_error(vp)	vbuf_wr_error(&(vp)->buf)
122 #define vstream_ferror(vp)	vbuf_error(&(vp)->buf)
123 #define vstream_feof(vp)	vbuf_eof(&(vp)->buf)
124 #define vstream_rd_timeout(vp)	vbuf_rd_timeout(&(vp)->buf)
125 #define vstream_wr_timeout(vp)	vbuf_wr_timeout(&(vp)->buf)
126 #define vstream_ftimeout(vp)	vbuf_timeout(&(vp)->buf)
127 #define vstream_clearerr(vp)	vbuf_clearerr(&(vp)->buf)
128 #define VSTREAM_PATH(vp)	((vp)->path ? (const char *) (vp)->path : "unknown_stream")
129 #define vstream_ftime(vp)	((time_t) ((vp)->iotime.tv_sec))
130 #define vstream_ftimeval(vp)	((vp)->iotime)
131 
132 #define vstream_fstat(vp, fl)	((vp)->buf.flags & (fl))
133 
134 extern void vstream_control(VSTREAM *, int,...);
135 
136 /* Legacy API: type-unchecked arguments, internal use. */
137 #define VSTREAM_CTL_END		0
138 #define VSTREAM_CTL_READ_FN	1
139 #define VSTREAM_CTL_WRITE_FN	2
140 #define VSTREAM_CTL_PATH	3
141 #define VSTREAM_CTL_DOUBLE	4
142 #define VSTREAM_CTL_READ_FD	5
143 #define VSTREAM_CTL_WRITE_FD	6
144 #define VSTREAM_CTL_WAITPID_FN	7
145 #define VSTREAM_CTL_TIMEOUT	8
146 #define VSTREAM_CTL_EXCEPT	9
147 #define VSTREAM_CTL_CONTEXT	10
148 #ifdef F_DUPFD
149 #define VSTREAM_CTL_DUPFD	11
150 #endif
151 #define VSTREAM_CTL_BUFSIZE	12
152 #define VSTREAM_CTL_SWAP_FD	13
153 #define VSTREAM_CTL_START_DEADLINE 14
154 #define VSTREAM_CTL_STOP_DEADLINE 15
155 
156 /* Safer API: type-checked arguments, external use. */
157 #define CA_VSTREAM_CTL_END		VSTREAM_CTL_END
158 #define CA_VSTREAM_CTL_READ_FN(v)	VSTREAM_CTL_READ_FN, CHECK_VAL(VSTREAM_CTL, VSTREAM_RW_FN, (v))
159 #define CA_VSTREAM_CTL_WRITE_FN(v)	VSTREAM_CTL_WRITE_FN, CHECK_VAL(VSTREAM_CTL, VSTREAM_RW_FN, (v))
160 #define CA_VSTREAM_CTL_PATH(v)		VSTREAM_CTL_PATH, CHECK_CPTR(VSTREAM_CTL, char, (v))
161 #define CA_VSTREAM_CTL_DOUBLE		VSTREAM_CTL_DOUBLE
162 #define CA_VSTREAM_CTL_READ_FD(v)	VSTREAM_CTL_READ_FD, CHECK_VAL(VSTREAM_CTL, int, (v))
163 #define CA_VSTREAM_CTL_WRITE_FD(v)	VSTREAM_CTL_WRITE_FD, CHECK_VAL(VSTREAM_CTL, int, (v))
164 #define CA_VSTREAM_CTL_WAITPID_FN(v)	VSTREAM_CTL_WAITPID_FN, CHECK_VAL(VSTREAM_CTL, VSTREAM_WAITPID_FN, (v))
165 #define CA_VSTREAM_CTL_TIMEOUT(v)	VSTREAM_CTL_TIMEOUT, CHECK_VAL(VSTREAM_CTL, int, (v))
166 #define CA_VSTREAM_CTL_EXCEPT		VSTREAM_CTL_EXCEPT
167 #define CA_VSTREAM_CTL_CONTEXT(v)	VSTREAM_CTL_CONTEXT, CHECK_PTR(VSTREAM_CTL, void, (v))
168 #ifdef F_DUPFD
169 #define CA_VSTREAM_CTL_DUPFD(v)		VSTREAM_CTL_DUPFD, CHECK_VAL(VSTREAM_CTL, int, (v))
170 #endif
171 #define CA_VSTREAM_CTL_BUFSIZE(v)	VSTREAM_CTL_BUFSIZE, CHECK_VAL(VSTREAM_CTL, ssize_t, (v))
172 #define CA_VSTREAM_CTL_SWAP_FD(v)	VSTREAM_CTL_SWAP_FD, CHECK_PTR(VSTREAM_CTL, VSTREAM, (v))
173 #define CA_VSTREAM_CTL_START_DEADLINE	VSTREAM_CTL_START_DEADLINE
174 #define CA_VSTREAM_CTL_STOP_DEADLINE	VSTREAM_CTL_STOP_DEADLINE
175 
176 CHECK_VAL_HELPER_DCL(VSTREAM_CTL, ssize_t);
177 CHECK_VAL_HELPER_DCL(VSTREAM_CTL, int);
178 CHECK_VAL_HELPER_DCL(VSTREAM_CTL, VSTREAM_WAITPID_FN);
179 CHECK_VAL_HELPER_DCL(VSTREAM_CTL, VSTREAM_RW_FN);
180 CHECK_PTR_HELPER_DCL(VSTREAM_CTL, void);
181 CHECK_PTR_HELPER_DCL(VSTREAM_CTL, VSTREAM);
182 CHECK_CPTR_HELPER_DCL(VSTREAM_CTL, char);
183 
184 extern VSTREAM *PRINTFLIKE(1, 2) vstream_printf(const char *,...);
185 extern VSTREAM *PRINTFLIKE(2, 3) vstream_fprintf(VSTREAM *, const char *,...);
186 
187 extern VSTREAM *vstream_popen(int,...);
188 extern int vstream_pclose(VSTREAM *);
189 
190 #define vstream_ispipe(vp)	((vp)->pid != 0)
191 
192 /* Legacy API: type-unchecked arguments, internal use. */
193 #define VSTREAM_POPEN_END	0	/* terminator */
194 #define VSTREAM_POPEN_COMMAND	1	/* command is string */
195 #define VSTREAM_POPEN_ARGV	2	/* command is array */
196 #define VSTREAM_POPEN_UID	3	/* privileges */
197 #define VSTREAM_POPEN_GID	4	/* privileges */
198 #define VSTREAM_POPEN_ENV	5	/* extra environment */
199 #define VSTREAM_POPEN_SHELL	6	/* alternative shell */
200 #define VSTREAM_POPEN_WAITPID_FN 7	/* child catcher, waitpid() compat. */
201 #define VSTREAM_POPEN_EXPORT	8	/* exportable environment */
202 
203 /* Safer API: type-checked arguments, external use. */
204 #define CA_VSTREAM_POPEN_END		VSTREAM_POPEN_END
205 #define CA_VSTREAM_POPEN_COMMAND(v)	VSTREAM_POPEN_COMMAND, CHECK_CPTR(VSTREAM_PPN, char, (v))
206 #define CA_VSTREAM_POPEN_ARGV(v)	VSTREAM_POPEN_ARGV, CHECK_PPTR(VSTREAM_PPN, char, (v))
207 #define CA_VSTREAM_POPEN_UID(v)		VSTREAM_POPEN_UID, CHECK_VAL(VSTREAM_PPN, uid_t, (v))
208 #define CA_VSTREAM_POPEN_GID(v)		VSTREAM_POPEN_GID, CHECK_VAL(VSTREAM_PPN, gid_t, (v))
209 #define CA_VSTREAM_POPEN_ENV(v)		VSTREAM_POPEN_ENV, CHECK_PPTR(VSTREAM_PPN, char, (v))
210 #define CA_VSTREAM_POPEN_SHELL(v)	VSTREAM_POPEN_SHELL, CHECK_CPTR(VSTREAM_PPN, char, (v))
211 #define CA_VSTREAM_POPEN_WAITPID_FN(v)	VSTREAM_POPEN_WAITPID_FN, CHECK_VAL(VSTREAM_PPN, VSTREAM_WAITPID_FN, (v))
212 #define CA_VSTREAM_POPEN_EXPORT(v)	VSTREAM_POPEN_EXPORT, CHECK_PPTR(VSTREAM_PPN, char, (v))
213 
214 CHECK_VAL_HELPER_DCL(VSTREAM_PPN, uid_t);
215 CHECK_VAL_HELPER_DCL(VSTREAM_PPN, gid_t);
216 CHECK_VAL_HELPER_DCL(VSTREAM_PPN, VSTREAM_WAITPID_FN);
217 CHECK_PPTR_HELPER_DCL(VSTREAM_PPN, char);
218 CHECK_CPTR_HELPER_DCL(VSTREAM_PPN, char);
219 
220 extern VSTREAM *vstream_vprintf(const char *, va_list);
221 extern VSTREAM *vstream_vfprintf(VSTREAM *, const char *, va_list);
222 
223 extern ssize_t vstream_peek(VSTREAM *);
224 extern ssize_t vstream_bufstat(VSTREAM *, int);
225 
226 #define VSTREAM_BST_FLAG_IN		(1<<0)
227 #define VSTREAM_BST_FLAG_OUT		(1<<1)
228 #define VSTREAM_BST_FLAG_PEND		(1<<2)
229 
230 #define VSTREAM_BST_MASK_DIR	(VSTREAM_BST_FLAG_IN | VSTREAM_BST_FLAG_OUT)
231 #define VSTREAM_BST_IN_PEND	(VSTREAM_BST_FLAG_IN | VSTREAM_BST_FLAG_PEND)
232 #define VSTREAM_BST_OUT_PEND	(VSTREAM_BST_FLAG_OUT | VSTREAM_BST_FLAG_PEND)
233 
234 #define vstream_peek(vp) vstream_bufstat((vp), VSTREAM_BST_IN_PEND)
235 
236 extern const char *vstream_peek_data(VSTREAM *);
237 
238  /*
239   * Exception handling. We use pointer to jmp_buf to avoid a lot of unused
240   * baggage for streams that don't need this functionality.
241   *
242   * XXX sigsetjmp()/siglongjmp() save and restore the signal mask which can
243   * avoid surprises in code that manipulates signals, but unfortunately some
244   * systems have bugs in their implementation.
245   */
246 #ifdef NO_SIGSETJMP
247 #define vstream_setjmp(stream)		setjmp((stream)->jbuf[0])
248 #define vstream_longjmp(stream, val)	longjmp((stream)->jbuf[0], (val))
249 #else
250 #define vstream_setjmp(stream)		sigsetjmp((stream)->jbuf[0], 1)
251 #define vstream_longjmp(stream, val)	siglongjmp((stream)->jbuf[0], (val))
252 #endif
253 
254  /*
255   * Tweaks and workarounds.
256   */
257 extern int vstream_tweak_sock(VSTREAM *);
258 extern int vstream_tweak_tcp(VSTREAM *);
259 
260 #define vstream_flags(stream) ((const int) (stream)->buf.flags)
261 
262 /* LICENSE
263 /* .ad
264 /* .fi
265 /*	The Secure Mailer license must be distributed with this software.
266 /* AUTHOR(S)
267 /*	Wietse Venema
268 /*	IBM T.J. Watson Research
269 /*	P.O. Box 704
270 /*	Yorktown Heights, NY 10598, USA
271 /*--*/
272 
273 #endif
274