xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/vstring_vstream.c (revision 33881f779a77dce6440bdc44610d94de75bebefe)
1 /*	$NetBSD: vstring_vstream.c,v 1.2 2020/03/18 19:05:22 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	vstring_vstream 3
6 /* SUMMARY
7 /*	auto-resizing string library, standard I/O interface
8 /* SYNOPSIS
9 /*	#include <vstring_vstream.h>
10 /*
11 /*	int	vstring_get_flags(vp, fp, flags)
12 /*	VSTRING	*vp;
13 /*	VSTREAM	*fp;
14 /*	int	flags
15 /*
16 /*	int	vstring_get_flags_nonl(vp, fp, flags)
17 /*	VSTRING	*vp;
18 /*	VSTREAM	*fp;
19 /*	int	flags
20 /*
21 /*	int	vstring_get_flags_null(vp, fp, flags)
22 /*	VSTRING	*vp;
23 /*	VSTREAM	*fp;
24 /*	int	flags
25 /*
26 /*	int	vstring_get_flags_bound(vp, fp, flags, bound)
27 /*	VSTRING	*vp;
28 /*	VSTREAM	*fp;
29 /*	ssize_t	bound;
30 /*	int	flags
31 /*
32 /*	int	vstring_get_flags_nonl_bound(vp, fp, flags, bound)
33 /*	VSTRING	*vp;
34 /*	VSTREAM	*fp;
35 /*	ssize_t	bound;
36 /*	int	flags
37 /*
38 /*	int	vstring_get_flags_null_bound(vp, fp, flags, bound)
39 /*	VSTRING	*vp;
40 /*	VSTREAM	*fp;
41 /*	ssize_t	bound;
42 /*	int	flags
43 /* CONVENIENCE API
44 /*	int	vstring_get(vp, fp)
45 /*	VSTRING	*vp;
46 /*	VSTREAM	*fp;
47 /*
48 /*	int	vstring_get_nonl(vp, fp)
49 /*	VSTRING	*vp;
50 /*	VSTREAM	*fp;
51 /*
52 /*	int	vstring_get_null(vp, fp)
53 /*	VSTRING	*vp;
54 /*	VSTREAM	*fp;
55 /*
56 /*	int	vstring_get_bound(vp, fp, bound)
57 /*	VSTRING	*vp;
58 /*	VSTREAM	*fp;
59 /*	ssize_t	bound;
60 /*
61 /*	int	vstring_get_nonl_bound(vp, fp, bound)
62 /*	VSTRING	*vp;
63 /*	VSTREAM	*fp;
64 /*	ssize_t	bound;
65 /*
66 /*	int	vstring_get_null_bound(vp, fp, bound)
67 /*	VSTRING	*vp;
68 /*	VSTREAM	*fp;
69 /*	ssize_t	bound;
70 /* DESCRIPTION
71 /*	The routines in this module each read one newline or null-terminated
72 /*	string from an input stream. In all cases the result is either the
73 /*	last character read, typically the record terminator, or VSTREAM_EOF.
74 /*	The flags argument is VSTRING_GET_FLAG_NONE (default) or
75 /*	VSTRING_GET_FLAG_APPEND (append instead of overwrite).
76 /*
77 /*	vstring_get_flags() reads one line from the named stream, including the
78 /*	terminating newline character if present.
79 /*
80 /*	vstring_get_flags_nonl() reads a line from the named stream and strips
81 /*	the trailing newline character.
82 /*
83 /*	vstring_get_flags_null() reads a null-terminated string from the named
84 /*	stream.
85 /*
86 /*	the vstring_get_flags<whatever>_bound() routines read no more
87 /*	than \fIbound\fR characters.  Otherwise they behave like the
88 /*	unbounded versions documented above.
89 /*
90 /*	The functions without _flags in their name accept the same
91 /*	arguments except flags. These functions use the default
92 /*	flags value.
93 /* DIAGNOSTICS
94 /*	Fatal errors: memory allocation failure.
95 /*	Panic: improper string bound.
96 /* LICENSE
97 /* .ad
98 /* .fi
99 /*	The Secure Mailer license must be distributed with this software.
100 /* AUTHOR(S)
101 /*	Wietse Venema
102 /*	IBM T.J. Watson Research
103 /*	P.O. Box 704
104 /*	Yorktown Heights, NY 10598, USA
105 /*
106 /*	Wietse Venema
107 /*	Google, Inc.
108 /*	111 8th Avenue
109 /*	New York, NY 10011, USA
110 /*--*/
111 
112 /* System library. */
113 
114 #include "sys_defs.h"
115 #include <stdio.h>
116 #include <string.h>
117 
118 /* Application-specific. */
119 
120 #include "msg.h"
121 #include "vstring.h"
122 #include "vstream.h"
123 #include "vstring_vstream.h"
124 
125  /*
126   * Macro to return the last character added to a VSTRING, for consistency.
127   */
128 #define VSTRING_GET_RESULT(vp, baselen) \
129     (VSTRING_LEN(vp) > (base_len) ? vstring_end(vp)[-1] : VSTREAM_EOF)
130 
131 /* vstring_get_flags - read line from file, keep newline */
132 
vstring_get_flags(VSTRING * vp,VSTREAM * fp,int flags)133 int     vstring_get_flags(VSTRING *vp, VSTREAM *fp, int flags)
134 {
135     int     c;
136     ssize_t base_len;
137 
138     if ((flags & VSTRING_GET_FLAG_APPEND) == 0)
139 	VSTRING_RESET(vp);
140     base_len = VSTRING_LEN(vp);
141     while ((c = VSTREAM_GETC(fp)) != VSTREAM_EOF) {
142 	VSTRING_ADDCH(vp, c);
143 	if (c == '\n')
144 	    break;
145     }
146     VSTRING_TERMINATE(vp);
147     return (VSTRING_GET_RESULT(vp, baselen));
148 }
149 
150 /* vstring_get_flags_nonl - read line from file, strip newline */
151 
vstring_get_flags_nonl(VSTRING * vp,VSTREAM * fp,int flags)152 int     vstring_get_flags_nonl(VSTRING *vp, VSTREAM *fp, int flags)
153 {
154     int     c;
155     ssize_t base_len;
156 
157     if ((flags & VSTRING_GET_FLAG_APPEND) == 0)
158 	VSTRING_RESET(vp);
159     base_len = VSTRING_LEN(vp);
160     while ((c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != '\n')
161 	VSTRING_ADDCH(vp, c);
162     VSTRING_TERMINATE(vp);
163     return (c == '\n' ? c : VSTRING_GET_RESULT(vp, baselen));
164 }
165 
166 /* vstring_get_flags_null - read null-terminated string from file */
167 
vstring_get_flags_null(VSTRING * vp,VSTREAM * fp,int flags)168 int     vstring_get_flags_null(VSTRING *vp, VSTREAM *fp, int flags)
169 {
170     int     c;
171     ssize_t base_len;
172 
173     if ((flags & VSTRING_GET_FLAG_APPEND) == 0)
174 	VSTRING_RESET(vp);
175     base_len = VSTRING_LEN(vp);
176     while ((c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != 0)
177 	VSTRING_ADDCH(vp, c);
178     VSTRING_TERMINATE(vp);
179     return (c == 0 ? c : VSTRING_GET_RESULT(vp, baselen));
180 }
181 
182 /* vstring_get_flags_bound - read line from file, keep newline, up to bound */
183 
vstring_get_flags_bound(VSTRING * vp,VSTREAM * fp,int flags,ssize_t bound)184 int     vstring_get_flags_bound(VSTRING *vp, VSTREAM *fp, int flags,
185 				        ssize_t bound)
186 {
187     int     c;
188     ssize_t base_len;
189 
190     if (bound <= 0)
191 	msg_panic("vstring_get_bound: invalid bound %ld", (long) bound);
192 
193     if ((flags & VSTRING_GET_FLAG_APPEND) == 0)
194 	VSTRING_RESET(vp);
195     base_len = VSTRING_LEN(vp);
196     while (bound-- > 0 && (c = VSTREAM_GETC(fp)) != VSTREAM_EOF) {
197 	VSTRING_ADDCH(vp, c);
198 	if (c == '\n')
199 	    break;
200     }
201     VSTRING_TERMINATE(vp);
202     return (VSTRING_GET_RESULT(vp, baselen));
203 }
204 
205 /* vstring_get_flags_nonl_bound - read line from file, strip newline, up to bound */
206 
vstring_get_flags_nonl_bound(VSTRING * vp,VSTREAM * fp,int flags,ssize_t bound)207 int     vstring_get_flags_nonl_bound(VSTRING *vp, VSTREAM *fp, int flags,
208 				             ssize_t bound)
209 {
210     int     c;
211     ssize_t base_len;
212 
213     if (bound <= 0)
214 	msg_panic("vstring_get_nonl_bound: invalid bound %ld", (long) bound);
215 
216     if ((flags & VSTRING_GET_FLAG_APPEND) == 0)
217 	VSTRING_RESET(vp);
218     base_len = VSTRING_LEN(vp);
219     while (bound-- > 0 && (c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != '\n')
220 	VSTRING_ADDCH(vp, c);
221     VSTRING_TERMINATE(vp);
222     return (c == '\n' ? c : VSTRING_GET_RESULT(vp, baselen));
223 }
224 
225 /* vstring_get_flags_null_bound - read null-terminated string from file */
226 
vstring_get_flags_null_bound(VSTRING * vp,VSTREAM * fp,int flags,ssize_t bound)227 int     vstring_get_flags_null_bound(VSTRING *vp, VSTREAM *fp, int flags,
228 				             ssize_t bound)
229 {
230     int     c;
231     ssize_t base_len;
232 
233     if (bound <= 0)
234 	msg_panic("vstring_get_null_bound: invalid bound %ld", (long) bound);
235 
236     if ((flags & VSTRING_GET_FLAG_APPEND) == 0)
237 	VSTRING_RESET(vp);
238     base_len = VSTRING_LEN(vp);
239     while (bound-- > 0 && (c = VSTREAM_GETC(fp)) != VSTREAM_EOF && c != 0)
240 	VSTRING_ADDCH(vp, c);
241     VSTRING_TERMINATE(vp);
242     return (c == 0 ? c : VSTRING_GET_RESULT(vp, baselen));
243 }
244 
245 #ifdef TEST
246 
247  /*
248   * Proof-of-concept test program: copy the source to this module to stdout.
249   */
250 #include <fcntl.h>
251 
252 #define TEXT_VSTREAM    "vstring_vstream.c"
253 
main(void)254 int     main(void)
255 {
256     VSTRING *vp = vstring_alloc(1);
257     VSTREAM *fp;
258 
259     if ((fp = vstream_fopen(TEXT_VSTREAM, O_RDONLY, 0)) == 0)
260 	msg_fatal("open %s: %m", TEXT_VSTREAM);
261     while (vstring_fgets(vp, fp))
262 	vstream_fprintf(VSTREAM_OUT, "%s", vstring_str(vp));
263     vstream_fclose(fp);
264     vstream_fflush(VSTREAM_OUT);
265     vstring_free(vp);
266     return (0);
267 }
268 
269 #endif
270