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