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