1/*++ 2/* NAME 3/* vstring_vstream 3 4/* SUMMARY 5/* auto-resizing string library, standard I/O interface 6/* SYNOPSIS 7/* #include <vstring_vstream.h> 8/* 9/* int vstring_get(vp, fp) 10/* VSTRING *vp; 11/* VSTREAM *fp; 12/* 13/* int vstring_get_nonl(vp, fp) 14/* VSTRING *vp; 15/* VSTREAM *fp; 16/* 17/* int vstring_get_null(vp, fp) 18/* VSTRING *vp; 19/* VSTREAM *fp; 20/* 21/* int vstring_get_bound(vp, fp, bound) 22/* VSTRING *vp; 23/* VSTREAM *fp; 24/* ssize_t bound; 25/* 26/* int vstring_get_nonl_bound(vp, fp, bound) 27/* VSTRING *vp; 28/* VSTREAM *fp; 29/* ssize_t bound; 30/* 31/* int vstring_get_null_bound(vp, fp, bound) 32/* VSTRING *vp; 33/* VSTREAM *fp; 34/* ssize_t bound; 35/* DESCRIPTION 36/* The routines in this module each read one newline or null-terminated 37/* string from an input stream. In all cases the result is either the 38/* last character read, typically the record terminator, or VSTREAM_EOF. 39/* 40/* vstring_get() reads one line from the named stream, including the 41/* terminating newline character if present. 42/* 43/* vstring_get_nonl() reads a line from the named stream and strips 44/* the trailing newline character. 45/* 46/* vstring_get_null() reads a null-terminated string from the named 47/* stream. 48/* 49/* the vstring_get<whatever>_bound() routines read no more 50/* than \fIbound\fR characters. Otherwise they behave like the 51/* unbounded versions documented above. 52/* DIAGNOSTICS 53/* Fatal errors: memory allocation failure. 54/* Panic: improper string bound. 55/* LICENSE 56/* .ad 57/* .fi 58/* The Secure Mailer license must be distributed with this software. 59/* AUTHOR(S) 60/* Wietse Venema 61/* IBM T.J. Watson Research 62/* P.O. Box 704 63/* Yorktown Heights, NY 10598, USA 64/*--*/ 65 66/* System library. */ 67 68#include "sys_defs.h" 69#include <stdio.h> 70#include <string.h> 71 72/* Application-specific. */ 73 74#include "msg.h" 75#include "vstring.h" 76#include "vstream.h" 77#include "vstring_vstream.h" 78 79 /* 80 * Macro to return the last character added to a VSTRING, for consistency. 81 */ 82#define VSTRING_GET_RESULT(vp) \ 83 (VSTRING_LEN(vp) > 0 ? vstring_end(vp)[-1] : VSTREAM_EOF) 84 85/* vstring_get - read line from file, keep newline */ 86 87int vstring_get(VSTRING *vp, VSTREAM *fp) 88{ 89 int c; 90 91 VSTRING_RESET(vp); 92 while ((c = VSTREAM_GETC(fp)) != VSTREAM_EOF) { 93 VSTRING_ADDCH(vp, c); 94 if (c == '\n') 95 break; 96 } 97 VSTRING_TERMINATE(vp); 98 return (VSTRING_GET_RESULT(vp)); 99} 100 101/* vstring_get_nonl - read line from file, strip newline */ 102 103int vstring_get_nonl(VSTRING *vp, VSTREAM *fp) 104{ 105 int c; 106 107 VSTRING_RESET(vp); 108 while ((c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != '\n') 109 VSTRING_ADDCH(vp, c); 110 VSTRING_TERMINATE(vp); 111 return (c == '\n' ? c : VSTRING_GET_RESULT(vp)); 112} 113 114/* vstring_get_null - read null-terminated string from file */ 115 116int vstring_get_null(VSTRING *vp, VSTREAM *fp) 117{ 118 int c; 119 120 VSTRING_RESET(vp); 121 while ((c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != 0) 122 VSTRING_ADDCH(vp, c); 123 VSTRING_TERMINATE(vp); 124 return (c == 0 ? c : VSTRING_GET_RESULT(vp)); 125} 126 127/* vstring_get_bound - read line from file, keep newline, up to bound */ 128 129int vstring_get_bound(VSTRING *vp, VSTREAM *fp, ssize_t bound) 130{ 131 int c; 132 133 if (bound <= 0) 134 msg_panic("vstring_get_bound: invalid bound %ld", (long) bound); 135 136 VSTRING_RESET(vp); 137 while (bound-- > 0 && (c = VSTREAM_GETC(fp)) != VSTREAM_EOF) { 138 VSTRING_ADDCH(vp, c); 139 if (c == '\n') 140 break; 141 } 142 VSTRING_TERMINATE(vp); 143 return (VSTRING_GET_RESULT(vp)); 144} 145 146/* vstring_get_nonl_bound - read line from file, strip newline, up to bound */ 147 148int vstring_get_nonl_bound(VSTRING *vp, VSTREAM *fp, ssize_t bound) 149{ 150 int c; 151 152 if (bound <= 0) 153 msg_panic("vstring_get_nonl_bound: invalid bound %ld", (long) bound); 154 155 VSTRING_RESET(vp); 156 while (bound-- > 0 && (c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != '\n') 157 VSTRING_ADDCH(vp, c); 158 VSTRING_TERMINATE(vp); 159 return (c == '\n' ? c : VSTRING_GET_RESULT(vp)); 160} 161 162/* vstring_get_null_bound - read null-terminated string from file */ 163 164int vstring_get_null_bound(VSTRING *vp, VSTREAM *fp, ssize_t bound) 165{ 166 int c; 167 168 if (bound <= 0) 169 msg_panic("vstring_get_null_bound: invalid bound %ld", (long) bound); 170 171 VSTRING_RESET(vp); 172 while (bound-- > 0 && (c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != 0) 173 VSTRING_ADDCH(vp, c); 174 VSTRING_TERMINATE(vp); 175 return (c == 0 ? c : VSTRING_GET_RESULT(vp)); 176} 177 178#ifdef TEST 179 180 /* 181 * Proof-of-concept test program: copy the source to this module to stdout. 182 */ 183#include <fcntl.h> 184 185#define TEXT_VSTREAM "vstring_vstream.c" 186 187int main(void) 188{ 189 VSTRING *vp = vstring_alloc(1); 190 VSTREAM *fp; 191 192 if ((fp = vstream_fopen(TEXT_VSTREAM, O_RDONLY, 0)) == 0) 193 msg_fatal("open %s: %m", TEXT_VSTREAM); 194 while (vstring_fgets(vp, fp)) 195 vstream_fprintf(VSTREAM_OUT, "%s", vstring_str(vp)); 196 vstream_fclose(fp); 197 vstream_fflush(VSTREAM_OUT); 198 vstring_free(vp); 199 return (0); 200} 201 202#endif 203