Home | History | Annotate | Line # | Download | only in util
      1 /*	$NetBSD: vstream.h,v 1.5 2026/05/09 18:49:23 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_OWN_VSTRING	VSTREAM_CTL_OWN_VSTRING
    185 #define CA_VSTREAM_CTL_MIN_DATA_RATE(v)	VSTREAM_CTL_MIN_DATA_RATE, CHECK_VAL(VSTREAM_CTL, int, (v))
    186 
    187 CHECK_VAL_HELPER_DCL(VSTREAM_CTL, ssize_t);
    188 CHECK_VAL_HELPER_DCL(VSTREAM_CTL, int);
    189 CHECK_VAL_HELPER_DCL(VSTREAM_CTL, VSTREAM_WAITPID_FN);
    190 CHECK_VAL_HELPER_DCL(VSTREAM_CTL, VSTREAM_RW_FN);
    191 CHECK_PTR_HELPER_DCL(VSTREAM_CTL, void);
    192 CHECK_PTR_HELPER_DCL(VSTREAM_CTL, VSTREAM);
    193 CHECK_CPTR_HELPER_DCL(VSTREAM_CTL, char);
    194 
    195 extern VSTREAM *PRINTFLIKE(1, 2) vstream_printf(const char *,...);
    196 extern VSTREAM *PRINTFLIKE(2, 3) vstream_fprintf(VSTREAM *, const char *,...);
    197 
    198 extern VSTREAM *vstream_popen(int,...);
    199 extern int vstream_pclose(VSTREAM *);
    200 
    201 #define vstream_ispipe(vp)	((vp)->pid != 0)
    202 
    203 /* Legacy API: type-unchecked arguments, internal use. */
    204 #define VSTREAM_POPEN_END	0	/* terminator */
    205 #define VSTREAM_POPEN_COMMAND	1	/* command is string */
    206 #define VSTREAM_POPEN_ARGV	2	/* command is array */
    207 #define VSTREAM_POPEN_UID	3	/* privileges */
    208 #define VSTREAM_POPEN_GID	4	/* privileges */
    209 #define VSTREAM_POPEN_ENV	5	/* extra environment */
    210 #define VSTREAM_POPEN_SHELL	6	/* alternative shell */
    211 #define VSTREAM_POPEN_WAITPID_FN 7	/* child catcher, waitpid() compat. */
    212 #define VSTREAM_POPEN_EXPORT	8	/* exportable environment */
    213 
    214 /* Safer API: type-checked arguments, external use. */
    215 #define CA_VSTREAM_POPEN_END		VSTREAM_POPEN_END
    216 #define CA_VSTREAM_POPEN_COMMAND(v)	VSTREAM_POPEN_COMMAND, CHECK_CPTR(VSTREAM_PPN, char, (v))
    217 #define CA_VSTREAM_POPEN_ARGV(v)	VSTREAM_POPEN_ARGV, CHECK_PPTR(VSTREAM_PPN, char, (v))
    218 #define CA_VSTREAM_POPEN_UID(v)		VSTREAM_POPEN_UID, CHECK_VAL(VSTREAM_PPN, uid_t, (v))
    219 #define CA_VSTREAM_POPEN_GID(v)		VSTREAM_POPEN_GID, CHECK_VAL(VSTREAM_PPN, gid_t, (v))
    220 #define CA_VSTREAM_POPEN_ENV(v)		VSTREAM_POPEN_ENV, CHECK_PPTR(VSTREAM_PPN, char, (v))
    221 #define CA_VSTREAM_POPEN_SHELL(v)	VSTREAM_POPEN_SHELL, CHECK_CPTR(VSTREAM_PPN, char, (v))
    222 #define CA_VSTREAM_POPEN_WAITPID_FN(v)	VSTREAM_POPEN_WAITPID_FN, CHECK_VAL(VSTREAM_PPN, VSTREAM_WAITPID_FN, (v))
    223 #define CA_VSTREAM_POPEN_EXPORT(v)	VSTREAM_POPEN_EXPORT, CHECK_PPTR(VSTREAM_PPN, char, (v))
    224 
    225 CHECK_VAL_HELPER_DCL(VSTREAM_PPN, uid_t);
    226 CHECK_VAL_HELPER_DCL(VSTREAM_PPN, gid_t);
    227 CHECK_VAL_HELPER_DCL(VSTREAM_PPN, VSTREAM_WAITPID_FN);
    228 CHECK_PPTR_HELPER_DCL(VSTREAM_PPN, char);
    229 CHECK_CPTR_HELPER_DCL(VSTREAM_PPN, char);
    230 
    231 extern VSTREAM *vstream_vprintf(const char *, va_list);
    232 extern VSTREAM *vstream_vfprintf(VSTREAM *, const char *, va_list);
    233 
    234 extern ssize_t vstream_peek(VSTREAM *);
    235 extern ssize_t vstream_bufstat(VSTREAM *, int);
    236 
    237 #define VSTREAM_BST_FLAG_IN		(1<<0)
    238 #define VSTREAM_BST_FLAG_OUT		(1<<1)
    239 #define VSTREAM_BST_FLAG_PEND		(1<<2)
    240 
    241 #define VSTREAM_BST_MASK_DIR	(VSTREAM_BST_FLAG_IN | VSTREAM_BST_FLAG_OUT)
    242 #define VSTREAM_BST_IN_PEND	(VSTREAM_BST_FLAG_IN | VSTREAM_BST_FLAG_PEND)
    243 #define VSTREAM_BST_OUT_PEND	(VSTREAM_BST_FLAG_OUT | VSTREAM_BST_FLAG_PEND)
    244 
    245 #define vstream_peek(vp) vstream_bufstat((vp), VSTREAM_BST_IN_PEND)
    246 
    247 extern const char *vstream_peek_data(VSTREAM *);
    248 
    249  /*
    250   * Exception handling. We use pointer to jmp_buf to avoid a lot of unused
    251   * baggage for streams that don't need this functionality.
    252   *
    253   * XXX sigsetjmp()/siglongjmp() save and restore the signal mask which can
    254   * avoid surprises in code that manipulates signals, but unfortunately some
    255   * systems have bugs in their implementation.
    256   */
    257 #ifdef NO_SIGSETJMP
    258 #define vstream_setjmp(stream)		setjmp((stream)->jbuf[0])
    259 #define vstream_longjmp(stream, val)	longjmp((stream)->jbuf[0], (val))
    260 #else
    261 #define vstream_setjmp(stream)		sigsetjmp((stream)->jbuf[0], 1)
    262 #define vstream_longjmp(stream, val)	siglongjmp((stream)->jbuf[0], (val))
    263 #endif
    264 
    265  /*
    266   * Tweaks and workarounds.
    267   */
    268 extern int vstream_tweak_sock(VSTREAM *);
    269 extern int vstream_tweak_tcp(VSTREAM *);
    270 
    271 #define vstream_flags(stream) ((const int) (stream)->buf.flags)
    272 
    273  /*
    274   * Read/write VSTRING memory.
    275   */
    276 #define vstream_memopen(string, flags) \
    277 	vstream_memreopen((VSTREAM *) 0, (string), (flags))
    278 VSTREAM *vstream_memreopen(VSTREAM *, struct VSTRING *, int);
    279 
    280  /*
    281   * Debug logging lockout.
    282   */
    283 extern void vstream_no_debug(VSTREAM *);
    284 
    285 /* LICENSE
    286 /* .ad
    287 /* .fi
    288 /*	The Secure Mailer license must be distributed with this software.
    289 /* AUTHOR(S)
    290 /*	Wietse Venema
    291 /*	IBM T.J. Watson Research
    292 /*	P.O. Box 704
    293 /*	Yorktown Heights, NY 10598, USA
    294 /*
    295 /*	Wietse Venema
    296 /*	Google, Inc.
    297 /*	111 8th Avenue
    298 /*	New York, NY 10011, USA
    299 /*--*/
    300 
    301 #endif
    302