1/* 2 * Copyright (c) 2000-2002, 2004, 2013 Proofpoint, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1990 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Chris Torek. 9 * 10 * By using this file, you agree to the terms and conditions set 11 * forth in the LICENSE file which can be found at the top level of 12 * the sendmail distribution. 13 * 14 * $Id: io.h,v 1.26 2013-11-22 20:51:31 ca Exp $ 15 */ 16 17/*- 18 * @(#)stdio.h 5.17 (Berkeley) 6/3/91 19 */ 20 21#ifndef SM_IO_H 22#define SM_IO_H 23 24#include <stdio.h> 25#include <sm/gen.h> 26#include <sm/varargs.h> 27 28/* mode for sm io (exposed) */ 29#define SM_IO_RDWR 1 /* read-write */ 30#define SM_IO_RDONLY 2 /* read-only */ 31#define SM_IO_WRONLY 3 /* write-only */ 32#define SM_IO_APPEND 4 /* write-only from eof */ 33#define SM_IO_APPENDRW 5 /* read-write from eof */ 34#define SM_IO_RDWRTR 6 /* read-write with truncation indicated */ 35 36# define SM_IO_BINARY 0x0 /* binary mode: not used in Unix */ 37#define SM_IS_BINARY(mode) (((mode) & SM_IO_BINARY) != 0) 38#define SM_IO_MODE(mode) ((mode) & 0x0f) 39 40#define SM_IO_RDWR_B (SM_IO_RDWR|SM_IO_BINARY) 41#define SM_IO_RDONLY_B (SM_IO_RDONLY|SM_IO_BINARY) 42#define SM_IO_WRONLY_B (SM_IO_WRONLY|SM_IO_BINARY) 43#define SM_IO_APPEND_B (SM_IO_APPEND|SM_IO_BINARY) 44#define SM_IO_APPENDRW_B (SM_IO_APPENDRW|SM_IO_BINARY) 45#define SM_IO_RDWRTR_B (SM_IO_RDWRTR|SM_IO_BINARY) 46 47/* for sm_io_fseek, et al api's (exposed) */ 48#define SM_IO_SEEK_SET 0 49#define SM_IO_SEEK_CUR 1 50#define SM_IO_SEEK_END 2 51 52/* flags for info what's with different types (exposed) */ 53#define SM_IO_WHAT_MODE 1 54#define SM_IO_WHAT_VECTORS 2 55#define SM_IO_WHAT_FD 3 56/* was WHAT_TYPE 4 unused */ 57#define SM_IO_WHAT_ISTYPE 5 58#define SM_IO_IS_READABLE 6 59#define SM_IO_WHAT_TIMEOUT 7 60#define SM_IO_WHAT_SIZE 8 61 62/* info flags (exposed) */ 63#define SM_IO_FTYPE_CREATE 1 64#define SM_IO_FTYPE_MODIFY 2 65#define SM_IO_FTYPE_DELETE 3 66 67#define SM_IO_SL_PRIO 1 68 69#define SM_IO_OPEN_MAX 20 70 71/* for internal buffers */ 72struct smbuf 73{ 74 unsigned char *smb_base; 75 int smb_size; 76}; 77 78/* 79** sm I/O state variables (internal only). 80** 81** The following always hold: 82** 83** if (flags&(SMLBF|SMWR)) == (SMLBF|SMWR), 84** lbfsize is -bf.size, else lbfsize is 0 85** if flags&SMRD, w is 0 86** if flags&SMWR, r is 0 87** 88** This ensures that the getc and putc macros (or inline functions) never 89** try to write or read from a file that is in `read' or `write' mode. 90** (Moreover, they can, and do, automatically switch from read mode to 91** write mode, and back, on "r+" and "w+" files.) 92** 93** lbfsize is used only to make the inline line-buffered output stream 94** code as compact as possible. 95** 96** ub, up, and ur are used when ungetc() pushes back more characters 97** than fit in the current bf, or when ungetc() pushes back a character 98** that does not match the previous one in bf. When this happens, 99** ub.base becomes non-nil (i.e., a stream has ungetc() data iff 100** ub.base!=NULL) and up and ur save the current values of p and r. 101*/ 102 103typedef struct sm_file SM_FILE_T; 104 105struct sm_file 106{ 107 const char *sm_magic; /* This SM_FILE_T is free when NULL */ 108 unsigned char *f_p; /* current position in (some) buffer */ 109 int f_r; /* read space left for getc() */ 110 int f_w; /* write space left for putc() */ 111 long f_flags; /* flags, below */ 112 short f_file; /* fileno, if Unix fd, else -1 */ 113 struct smbuf f_bf; /* the buffer (>= 1 byte, if !NULL) */ 114 int f_lbfsize; /* 0 or -bf.size, for inline putc */ 115 116 /* These can be used for any purpose by a file type implementation: */ 117 void *f_cookie; 118 int f_ival; 119 120 /* operations */ 121 int (*f_close) __P((SM_FILE_T *)); 122 ssize_t (*f_read) __P((SM_FILE_T *, char *, size_t)); 123 off_t (*f_seek) __P((SM_FILE_T *, off_t, int)); 124 ssize_t (*f_write) __P((SM_FILE_T *, const char *, size_t)); 125 int (*f_open) __P((SM_FILE_T *, const void *, int, 126 const void *)); 127 int (*f_setinfo) __P((SM_FILE_T *, int , void *)); 128 int (*f_getinfo) __P((SM_FILE_T *, int , void *)); 129 int f_timeout; 130 int f_timeoutstate; /* either blocking or non-blocking */ 131 char *f_type; /* for by-type lookups */ 132 struct sm_file *f_flushfp; /* flush this before reading parent */ 133 struct sm_file *f_modefp; /* sync mode with this fp */ 134 135 /* separate buffer for long sequences of ungetc() */ 136 struct smbuf f_ub; /* ungetc buffer */ 137 unsigned char *f_up; /* saved f_p when f_p is doing ungetc */ 138 int f_ur; /* saved f_r when f_r is counting ungetc */ 139 140 /* tricks to meet minimum requirements even when malloc() fails */ 141 unsigned char f_ubuf[3]; /* guarantee an ungetc() buffer */ 142 unsigned char f_nbuf[1]; /* guarantee a getc() buffer */ 143 144 /* Unix stdio files get aligned to block boundaries on fseek() */ 145 int f_blksize; /* stat.st_blksize (may be != bf.size) */ 146 off_t f_lseekoff; /* current lseek offset */ 147 int f_dup_cnt; /* count file dup'd */ 148}; 149 150__BEGIN_DECLS 151extern SM_FILE_T SmIoF[]; 152extern const char SmFileMagic[]; 153extern SM_FILE_T SmFtStdio_def; 154extern SM_FILE_T SmFtStdiofd_def; 155extern SM_FILE_T SmFtString_def; 156extern SM_FILE_T SmFtSyslog_def; 157extern SM_FILE_T SmFtRealStdio_def; 158 159#define SMIOIN_FILENO 0 160#define SMIOOUT_FILENO 1 161#define SMIOERR_FILENO 2 162#define SMIOSTDIN_FILENO 3 163#define SMIOSTDOUT_FILENO 4 164#define SMIOSTDERR_FILENO 5 165 166/* Common predefined and already (usually) open files (exposed) */ 167#define smioin (&SmIoF[SMIOIN_FILENO]) 168#define smioout (&SmIoF[SMIOOUT_FILENO]) 169#define smioerr (&SmIoF[SMIOERR_FILENO]) 170#define smiostdin (&SmIoF[SMIOSTDIN_FILENO]) 171#define smiostdout (&SmIoF[SMIOSTDOUT_FILENO]) 172#define smiostderr (&SmIoF[SMIOSTDERR_FILENO]) 173 174#define SmFtStdio (&SmFtStdio_def) 175#define SmFtStdiofd (&SmFtStdiofd_def) 176#define SmFtString (&SmFtString_def) 177#define SmFtSyslog (&SmFtSyslog_def) 178#define SmFtRealStdio (&SmFtRealStdio_def) 179 180#ifdef __STDC__ 181# define SM_IO_SET_TYPE(f, name, open, close, read, write, seek, get, set, timeout) \ 182 (f) = {SmFileMagic, (unsigned char *) 0, 0, 0, 0L, -1, {0}, 0, (void *) 0,\ 183 0, (close), (read), (seek), (write), (open), (set), (get), (timeout),\ 184 0, (name)} 185# define SM_IO_INIT_TYPE(f, name, open, close, read, write, seek, get, set, timeout) 186 187#else /* __STDC__ */ 188# define SM_IO_SET_TYPE(f, name, open, close, read, write, seek, get, set, timeout) (f) 189# define SM_IO_INIT_TYPE(f, name, open, close, read, write, seek, get, set, timeout) \ 190 (f).sm_magic = SmFileMagic; \ 191 (f).f_p = (unsigned char *) 0; \ 192 (f).f_r = 0; \ 193 (f).f_w = 0; \ 194 (f).f_flags = 0L; \ 195 (f).f_file = 0; \ 196 (f).f_bf.smb_base = (unsigned char *) 0; \ 197 (f).f_bf.smb_size = 0; \ 198 (f).f_lbfsize = 0; \ 199 (f).f_cookie = (void *) 0; \ 200 (f).f_ival = 0; \ 201 (f).f_close = (close); \ 202 (f).f_read = (read); \ 203 (f).f_seek = (seek); \ 204 (f).f_write = (write); \ 205 (f).f_open = (open); \ 206 (f).f_setinfo = (set); \ 207 (f).f_getinfo = (get); \ 208 (f).f_timeout = (timeout); \ 209 (f).f_timeoutstate = 0; \ 210 (f).f_type = (name); 211 212#endif /* __STDC__ */ 213 214__END_DECLS 215 216/* Internal flags */ 217#define SMFBF 0x000001 /* XXXX fully buffered */ 218#define SMLBF 0x000002 /* line buffered */ 219#define SMNBF 0x000004 /* unbuffered */ 220#define SMNOW 0x000008 /* Flush each write; take read now */ 221#define SMRD 0x000010 /* OK to read */ 222#define SMWR 0x000020 /* OK to write */ 223 /* RD and WR are never simultaneously asserted */ 224#define SMRW 0x000040 /* open for reading & writing */ 225#define SMFEOF 0x000080 /* found EOF */ 226#define SMERR 0x000100 /* found error */ 227#define SMMBF 0x000200 /* buf is from malloc */ 228#define SMAPP 0x000400 /* fdopen()ed in append mode */ 229#define SMSTR 0x000800 /* this is an snprintf string */ 230#define SMOPT 0x001000 /* do fseek() optimisation */ 231#define SMNPT 0x002000 /* do not do fseek() optimisation */ 232#define SMOFF 0x004000 /* set iff offset is in fact correct */ 233#define SMALC 0x010000 /* allocate string space dynamically */ 234 235#define SMMODEMASK 0x0070 /* read/write mode */ 236 237/* defines for timeout constants */ 238#define SM_TIME_IMMEDIATE (0) 239#define SM_TIME_FOREVER (-1) 240#define SM_TIME_DEFAULT (-2) 241 242/* timeout state for blocking */ 243#define SM_TIME_BLOCK (0) /* XXX just bool? */ 244#define SM_TIME_NONBLOCK (1) 245 246/* Exposed buffering type flags */ 247#define SM_IO_FBF 0 /* setvbuf should set fully buffered */ 248#define SM_IO_LBF 1 /* setvbuf should set line buffered */ 249#define SM_IO_NBF 2 /* setvbuf should set unbuffered */ 250 251/* setvbuf buffered, but through at lower file type layers */ 252#define SM_IO_NOW 3 253 254/* 255** size of buffer used by setbuf. 256** If underlying filesystem blocksize is discoverable that is used instead 257*/ 258 259#define SM_IO_BUFSIZ 4096 260 261#define SM_IO_EOF (-1) 262 263/* Functions defined in ANSI C standard. */ 264__BEGIN_DECLS 265SM_FILE_T *sm_io_autoflush __P((SM_FILE_T *, SM_FILE_T *)); 266void sm_io_automode __P((SM_FILE_T *, SM_FILE_T *)); 267void sm_io_clearerr __P((SM_FILE_T *)); 268int sm_io_close __P((SM_FILE_T *, int SM_NONVOLATILE)); 269SM_FILE_T *sm_io_dup __P((SM_FILE_T *)); 270int sm_io_eof __P((SM_FILE_T *)); 271int sm_io_error __P((SM_FILE_T *)); 272int sm_io_fgets __P((SM_FILE_T *, int, char *, int)); 273int sm_io_flush __P((SM_FILE_T *, int SM_NONVOLATILE)); 274 275int PRINTFLIKE(3, 4) 276sm_io_fprintf __P((SM_FILE_T *, int, const char *, ...)); 277 278int sm_io_fputs __P((SM_FILE_T *, int, const char *)); 279 280int SCANFLIKE(3, 4) 281sm_io_fscanf __P((SM_FILE_T *, int, const char *, ...)); 282 283int sm_io_getc __P((SM_FILE_T *, int)); 284int sm_io_getinfo __P((SM_FILE_T *, int, void *)); 285SM_FILE_T *sm_io_open __P((const SM_FILE_T *, int SM_NONVOLATILE, const void *, 286 int, const void *)); 287int sm_io_purge __P((SM_FILE_T *)); 288int sm_io_putc __P((SM_FILE_T *, int, int)); 289size_t sm_io_read __P((SM_FILE_T *, int, void *, size_t)); 290SM_FILE_T *sm_io_reopen __P((const SM_FILE_T *, int SM_NONVOLATILE, 291 const void *, int, const void *, SM_FILE_T *)); 292void sm_io_rewind __P((SM_FILE_T *, int)); 293int sm_io_seek __P((SM_FILE_T *, int SM_NONVOLATILE, long SM_NONVOLATILE, 294 int SM_NONVOLATILE)); 295int sm_io_setinfo __P((SM_FILE_T *, int, void *)); 296int sm_io_setvbuf __P((SM_FILE_T *, int, char *, int, size_t)); 297 298int SCANFLIKE(2, 3) 299sm_io_sscanf __P((const char *, char const *, ...)); 300 301long sm_io_tell __P((SM_FILE_T *, int SM_NONVOLATILE)); 302int sm_io_ungetc __P((SM_FILE_T *, int, int)); 303int sm_io_vfprintf __P((SM_FILE_T *, int, const char *, va_list)); 304size_t sm_io_write __P((SM_FILE_T *, int, const void *, size_t)); 305 306void sm_strio_init __P((SM_FILE_T *, char *, size_t)); 307 308extern SM_FILE_T * 309sm_io_fopen __P(( 310 char *_pathname, 311 int _flags, 312 ...)); 313 314extern SM_FILE_T * 315sm_io_stdioopen __P(( 316 FILE *_stream, 317 char *_mode)); 318 319extern int 320sm_vasprintf __P(( 321 char **_str, 322 const char *_fmt, 323 va_list _ap)); 324 325extern int 326sm_vsnprintf __P(( 327 char *, 328 size_t, 329 const char *, 330 va_list)); 331 332extern void 333sm_perror __P(( 334 const char *)); 335 336__END_DECLS 337 338/* 339** Functions internal to the implementation. 340*/ 341 342__BEGIN_DECLS 343int sm_rget __P((SM_FILE_T *, int)); 344int sm_vfscanf __P((SM_FILE_T *, int SM_NONVOLATILE, const char *, 345 va_list)); 346int sm_wbuf __P((SM_FILE_T *, int, int)); 347__END_DECLS 348 349/* 350** The macros are here so that we can 351** define function versions in the library. 352*/ 353 354#define sm_getc(f, t) \ 355 (--(f)->f_r < 0 ? \ 356 sm_rget(f, t) : \ 357 (int)(*(f)->f_p++)) 358 359/* 360** This has been tuned to generate reasonable code on the vax using pcc. 361** (It also generates reasonable x86 code using gcc.) 362*/ 363 364#define sm_putc(f, t, c) \ 365 (--(f)->f_w < 0 ? \ 366 (f)->f_w >= (f)->f_lbfsize ? \ 367 (*(f)->f_p = (c)), *(f)->f_p != '\n' ? \ 368 (int)*(f)->f_p++ : \ 369 sm_wbuf(f, t, '\n') : \ 370 sm_wbuf(f, t, (int)(c)) : \ 371 (*(f)->f_p = (c), (int)*(f)->f_p++)) 372 373#define sm_eof(p) (((p)->f_flags & SMFEOF) != 0) 374#define sm_error(p) (((p)->f_flags & SMERR) != 0) 375#define sm_clearerr(p) ((void)((p)->f_flags &= ~(SMERR|SMFEOF))) 376 377#define sm_io_eof(p) sm_eof(p) 378#define sm_io_error(p) sm_error(p) 379 380#define sm_io_clearerr(p) sm_clearerr(p) 381 382#ifndef lint 383# ifndef _POSIX_SOURCE 384# define sm_io_getc(fp, t) sm_getc(fp, t) 385# define sm_io_putc(fp, t, x) sm_putc(fp, t, x) 386# endif 387#endif /* lint */ 388 389#endif /* SM_IO_H */ 390