1 /*        $NetBSD: vstream.h,v 1.4 2022/10/08 16:12:50 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 flush 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 timeout */
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     int     min_data_rate;              /* min data rate for time limit */
65     struct VSTRING *vstring;            /* memory-backed stream */
66 } VSTREAM;
67 
68 extern VSTREAM vstream_fstd[];                    /* pre-defined streams */
69 
70 #define VSTREAM_IN            (&vstream_fstd[0])
71 #define VSTREAM_OUT           (&vstream_fstd[1])
72 #define VSTREAM_ERR           (&vstream_fstd[2])
73 
74 #define VSTREAM_FLAG_RD_ERR   VBUF_FLAG_RD_ERR    /* read error */
75 #define VSTREAM_FLAG_WR_ERR   VBUF_FLAG_WR_ERR    /* write error */
76 #define VSTREAM_FLAG_RD_TIMEOUT         VBUF_FLAG_RD_TIMEOUT          /* read timeout */
77 #define VSTREAM_FLAG_WR_TIMEOUT         VBUF_FLAG_WR_TIMEOUT          /* write timeout */
78 
79 #define   VSTREAM_FLAG_ERR    VBUF_FLAG_ERR       /* some I/O error */
80 #define VSTREAM_FLAG_EOF      VBUF_FLAG_EOF       /* end of file */
81 #define VSTREAM_FLAG_TIMEOUT  VBUF_FLAG_TIMEOUT   /* timeout error */
82 #define VSTREAM_FLAG_FIXED    VBUF_FLAG_FIXED     /* fixed-size buffer */
83 #define VSTREAM_FLAG_BAD      VBUF_FLAG_BAD
84 
85 /* Flags 1<<24 and above are reserved for VSTRING. */
86 #define VSTREAM_FLAG_READ     (1<<8)    /* read buffer */
87 #define VSTREAM_FLAG_WRITE    (1<<9)    /* write buffer */
88 #define VSTREAM_FLAG_SEEK     (1<<10)   /* seek info valid */
89 #define VSTREAM_FLAG_NSEEK    (1<<11)   /* can't seek this file */
90 #define VSTREAM_FLAG_DOUBLE   (1<<12)   /* double buffer */
91 #define VSTREAM_FLAG_DEADLINE (1<<13)   /* deadline active */
92 #define VSTREAM_FLAG_MEMORY   (1<<14)   /* internal stream */
93 #define VSTREAM_FLAG_OWN_VSTRING (1<<15)/* owns VSTRING resource */
94 
95 #define VSTREAM_PURGE_READ    (1<<0)    /* flush unread data */
96 #define VSTREAM_PURGE_WRITE   (1<<1)    /* flush unwritten data */
97 #define VSTREAM_PURGE_BOTH    (VSTREAM_PURGE_READ|VSTREAM_PURGE_WRITE)
98 
99 #define VSTREAM_BUFSIZE                 4096
100 
101 extern VSTREAM *vstream_fopen(const char *, int, mode_t);
102 extern int vstream_fclose(VSTREAM *);
103 extern off_t WARN_UNUSED_RESULT vstream_fseek(VSTREAM *, off_t, int);
104 extern off_t vstream_ftell(VSTREAM *);
105 extern int vstream_fpurge(VSTREAM *, int);
106 extern int vstream_fflush(VSTREAM *);
107 extern int vstream_fputs(const char *, VSTREAM *);
108 extern VSTREAM *vstream_fdopen(int, int);
109 extern int vstream_fdclose(VSTREAM *);
110 
111 #define vstream_fread(v, b, n)          vbuf_read(&(v)->buf, (b), (n))
112 #define vstream_fwrite(v, b, n)         vbuf_write(&(v)->buf, (b), (n))
113 
114 #define VSTREAM_PUTC(ch, vp)  VBUF_PUT(&(vp)->buf, (ch))
115 #define VSTREAM_GETC(vp)      VBUF_GET(&(vp)->buf)
116 #define vstream_ungetc(vp, ch)          vbuf_unget(&(vp)->buf, (ch))
117 #define VSTREAM_EOF           VBUF_EOF
118 
119 #define VSTREAM_PUTCHAR(ch)   VSTREAM_PUTC((ch), VSTREAM_OUT)
120 #define VSTREAM_GETCHAR()     VSTREAM_GETC(VSTREAM_IN)
121 
122 #define vstream_fileno(vp)    ((vp)->fd)
123 #define vstream_req_bufsize(vp)         ((const ssize_t) ((vp)->req_bufsize))
124 #define vstream_context(vp)   ((vp)->context)
125 #define vstream_rd_error(vp)  vbuf_rd_error(&(vp)->buf)
126 #define vstream_wr_error(vp)  vbuf_wr_error(&(vp)->buf)
127 #define vstream_ferror(vp)    vbuf_error(&(vp)->buf)
128 #define vstream_feof(vp)      vbuf_eof(&(vp)->buf)
129 #define vstream_rd_timeout(vp)          vbuf_rd_timeout(&(vp)->buf)
130 #define vstream_wr_timeout(vp)          vbuf_wr_timeout(&(vp)->buf)
131 #define vstream_ftimeout(vp)  vbuf_timeout(&(vp)->buf)
132 #define vstream_clearerr(vp)  vbuf_clearerr(&(vp)->buf)
133 #define VSTREAM_PATH(vp)      ((vp)->path ? (const char *) (vp)->path : "unknown_stream")
134 #define vstream_ftime(vp)     ((time_t) ((vp)->iotime.tv_sec))
135 #define vstream_ftimeval(vp)  ((vp)->iotime)
136 
137 #define vstream_fstat(vp, fl) ((vp)->buf.flags & (fl))
138 
139 extern ssize_t vstream_fread_buf(VSTREAM *, struct VSTRING *, ssize_t);
140 extern ssize_t vstream_fread_app(VSTREAM *, struct VSTRING *, ssize_t);
141 extern void vstream_control(VSTREAM *, int,...);
142 
143 /* Legacy API: type-unchecked arguments, internal use. */
144 #define VSTREAM_CTL_END                 0
145 #define VSTREAM_CTL_READ_FN   1
146 #define VSTREAM_CTL_WRITE_FN  2
147 #define VSTREAM_CTL_PATH      3
148 #define VSTREAM_CTL_DOUBLE    4
149 #define VSTREAM_CTL_READ_FD   5
150 #define VSTREAM_CTL_WRITE_FD  6
151 #define VSTREAM_CTL_WAITPID_FN          7
152 #define VSTREAM_CTL_TIMEOUT   8
153 #define VSTREAM_CTL_EXCEPT    9
154 #define VSTREAM_CTL_CONTEXT   10
155 #ifdef F_DUPFD
156 #define VSTREAM_CTL_DUPFD     11
157 #endif
158 #define VSTREAM_CTL_BUFSIZE   12
159 #define VSTREAM_CTL_SWAP_FD   13
160 #define VSTREAM_CTL_START_DEADLINE 14
161 #define VSTREAM_CTL_STOP_DEADLINE 15
162 #define VSTREAM_CTL_OWN_VSTRING         16
163 #define VSTREAM_CTL_MIN_DATA_RATE 17
164 
165 /* Safer API: type-checked arguments, external use. */
166 #define CA_VSTREAM_CTL_END              VSTREAM_CTL_END
167 #define CA_VSTREAM_CTL_READ_FN(v)       VSTREAM_CTL_READ_FN, CHECK_VAL(VSTREAM_CTL, VSTREAM_RW_FN, (v))
168 #define CA_VSTREAM_CTL_WRITE_FN(v)      VSTREAM_CTL_WRITE_FN, CHECK_VAL(VSTREAM_CTL, VSTREAM_RW_FN, (v))
169 #define CA_VSTREAM_CTL_PATH(v)                    VSTREAM_CTL_PATH, CHECK_CPTR(VSTREAM_CTL, char, (v))
170 #define CA_VSTREAM_CTL_DOUBLE           VSTREAM_CTL_DOUBLE
171 #define CA_VSTREAM_CTL_READ_FD(v)       VSTREAM_CTL_READ_FD, CHECK_VAL(VSTREAM_CTL, int, (v))
172 #define CA_VSTREAM_CTL_WRITE_FD(v)      VSTREAM_CTL_WRITE_FD, CHECK_VAL(VSTREAM_CTL, int, (v))
173 #define CA_VSTREAM_CTL_WAITPID_FN(v)    VSTREAM_CTL_WAITPID_FN, CHECK_VAL(VSTREAM_CTL, VSTREAM_WAITPID_FN, (v))
174 #define CA_VSTREAM_CTL_TIMEOUT(v)       VSTREAM_CTL_TIMEOUT, CHECK_VAL(VSTREAM_CTL, int, (v))
175 #define CA_VSTREAM_CTL_EXCEPT           VSTREAM_CTL_EXCEPT
176 #define CA_VSTREAM_CTL_CONTEXT(v)       VSTREAM_CTL_CONTEXT, CHECK_PTR(VSTREAM_CTL, void, (v))
177 #ifdef F_DUPFD
178 #define CA_VSTREAM_CTL_DUPFD(v)                   VSTREAM_CTL_DUPFD, CHECK_VAL(VSTREAM_CTL, int, (v))
179 #endif
180 #define CA_VSTREAM_CTL_BUFSIZE(v)       VSTREAM_CTL_BUFSIZE, CHECK_VAL(VSTREAM_CTL, ssize_t, (v))
181 #define CA_VSTREAM_CTL_SWAP_FD(v)       VSTREAM_CTL_SWAP_FD, CHECK_PTR(VSTREAM_CTL, VSTREAM, (v))
182 #define CA_VSTREAM_CTL_START_DEADLINE   VSTREAM_CTL_START_DEADLINE
183 #define CA_VSTREAM_CTL_STOP_DEADLINE    VSTREAM_CTL_STOP_DEADLINE
184 #define CA_VSTREAM_CTL_MIN_DATA_RATE(v) VSTREAM_CTL_MIN_DATA_RATE, CHECK_VAL(VSTREAM_CTL, int, (v))
185 
186 CHECK_VAL_HELPER_DCL(VSTREAM_CTL, ssize_t);
187 CHECK_VAL_HELPER_DCL(VSTREAM_CTL, int);
188 CHECK_VAL_HELPER_DCL(VSTREAM_CTL, VSTREAM_WAITPID_FN);
189 CHECK_VAL_HELPER_DCL(VSTREAM_CTL, VSTREAM_RW_FN);
190 CHECK_PTR_HELPER_DCL(VSTREAM_CTL, void);
191 CHECK_PTR_HELPER_DCL(VSTREAM_CTL, VSTREAM);
192 CHECK_CPTR_HELPER_DCL(VSTREAM_CTL, char);
193 
194 extern VSTREAM *PRINTFLIKE(1, 2) vstream_printf(const char *,...);
195 extern VSTREAM *PRINTFLIKE(2, 3) vstream_fprintf(VSTREAM *, const char *,...);
196 
197 extern VSTREAM *vstream_popen(int,...);
198 extern int vstream_pclose(VSTREAM *);
199 
200 #define vstream_ispipe(vp)    ((vp)->pid != 0)
201 
202 /* Legacy API: type-unchecked arguments, internal use. */
203 #define VSTREAM_POPEN_END     0         /* terminator */
204 #define VSTREAM_POPEN_COMMAND 1         /* command is string */
205 #define VSTREAM_POPEN_ARGV    2         /* command is array */
206 #define VSTREAM_POPEN_UID     3         /* privileges */
207 #define VSTREAM_POPEN_GID     4         /* privileges */
208 #define VSTREAM_POPEN_ENV     5         /* extra environment */
209 #define VSTREAM_POPEN_SHELL   6         /* alternative shell */
210 #define VSTREAM_POPEN_WAITPID_FN 7      /* child catcher, waitpid() compat. */
211 #define VSTREAM_POPEN_EXPORT  8         /* exportable environment */
212 
213 /* Safer API: type-checked arguments, external use. */
214 #define CA_VSTREAM_POPEN_END            VSTREAM_POPEN_END
215 #define CA_VSTREAM_POPEN_COMMAND(v)     VSTREAM_POPEN_COMMAND, CHECK_CPTR(VSTREAM_PPN, char, (v))
216 #define CA_VSTREAM_POPEN_ARGV(v)        VSTREAM_POPEN_ARGV, CHECK_PPTR(VSTREAM_PPN, char, (v))
217 #define CA_VSTREAM_POPEN_UID(v)                   VSTREAM_POPEN_UID, CHECK_VAL(VSTREAM_PPN, uid_t, (v))
218 #define CA_VSTREAM_POPEN_GID(v)                   VSTREAM_POPEN_GID, CHECK_VAL(VSTREAM_PPN, gid_t, (v))
219 #define CA_VSTREAM_POPEN_ENV(v)                   VSTREAM_POPEN_ENV, CHECK_PPTR(VSTREAM_PPN, char, (v))
220 #define CA_VSTREAM_POPEN_SHELL(v)       VSTREAM_POPEN_SHELL, CHECK_CPTR(VSTREAM_PPN, char, (v))
221 #define CA_VSTREAM_POPEN_WAITPID_FN(v)  VSTREAM_POPEN_WAITPID_FN, CHECK_VAL(VSTREAM_PPN, VSTREAM_WAITPID_FN, (v))
222 #define CA_VSTREAM_POPEN_EXPORT(v)      VSTREAM_POPEN_EXPORT, CHECK_PPTR(VSTREAM_PPN, char, (v))
223 
224 CHECK_VAL_HELPER_DCL(VSTREAM_PPN, uid_t);
225 CHECK_VAL_HELPER_DCL(VSTREAM_PPN, gid_t);
226 CHECK_VAL_HELPER_DCL(VSTREAM_PPN, VSTREAM_WAITPID_FN);
227 CHECK_PPTR_HELPER_DCL(VSTREAM_PPN, char);
228 CHECK_CPTR_HELPER_DCL(VSTREAM_PPN, char);
229 
230 extern VSTREAM *vstream_vprintf(const char *, va_list);
231 extern VSTREAM *vstream_vfprintf(VSTREAM *, const char *, va_list);
232 
233 extern ssize_t vstream_peek(VSTREAM *);
234 extern ssize_t vstream_bufstat(VSTREAM *, int);
235 
236 #define VSTREAM_BST_FLAG_IN             (1<<0)
237 #define VSTREAM_BST_FLAG_OUT            (1<<1)
238 #define VSTREAM_BST_FLAG_PEND           (1<<2)
239 
240 #define VSTREAM_BST_MASK_DIR  (VSTREAM_BST_FLAG_IN | VSTREAM_BST_FLAG_OUT)
241 #define VSTREAM_BST_IN_PEND   (VSTREAM_BST_FLAG_IN | VSTREAM_BST_FLAG_PEND)
242 #define VSTREAM_BST_OUT_PEND  (VSTREAM_BST_FLAG_OUT | VSTREAM_BST_FLAG_PEND)
243 
244 #define vstream_peek(vp) vstream_bufstat((vp), VSTREAM_BST_IN_PEND)
245 
246 extern const char *vstream_peek_data(VSTREAM *);
247 
248  /*
249   * Exception handling. We use pointer to jmp_buf to avoid a lot of unused
250   * baggage for streams that don't need this functionality.
251   *
252   * XXX sigsetjmp()/siglongjmp() save and restore the signal mask which can
253   * avoid surprises in code that manipulates signals, but unfortunately some
254   * systems have bugs in their implementation.
255   */
256 #ifdef NO_SIGSETJMP
257 #define vstream_setjmp(stream)                    setjmp((stream)->jbuf[0])
258 #define vstream_longjmp(stream, val)    longjmp((stream)->jbuf[0], (val))
259 #else
260 #define vstream_setjmp(stream)                    sigsetjmp((stream)->jbuf[0], 1)
261 #define vstream_longjmp(stream, val)    siglongjmp((stream)->jbuf[0], (val))
262 #endif
263 
264  /*
265   * Tweaks and workarounds.
266   */
267 extern int vstream_tweak_sock(VSTREAM *);
268 extern int vstream_tweak_tcp(VSTREAM *);
269 
270 #define vstream_flags(stream) ((const int) (stream)->buf.flags)
271 
272  /*
273   * Read/write VSTRING memory.
274   */
275 #define vstream_memopen(string, flags) \
276           vstream_memreopen((VSTREAM *) 0, (string), (flags))
277 VSTREAM *vstream_memreopen(VSTREAM *, struct VSTRING *, int);
278 
279 /* LICENSE
280 /* .ad
281 /* .fi
282 /*        The Secure Mailer license must be distributed with this software.
283 /* AUTHOR(S)
284 /*        Wietse Venema
285 /*        IBM T.J. Watson Research
286 /*        P.O. Box 704
287 /*        Yorktown Heights, NY 10598, USA
288 /*
289 /*        Wietse Venema
290 /*        Google, Inc.
291 /*        111 8th Avenue
292 /*        New York, NY 10011, USA
293 /*--*/
294 
295 #endif
296