Blame


1 5565365c 2024-03-27 op /*
2 83fccf2d 2024-03-27 op * bufio.c was written by Omar Polo <op@omarpolo.com>
3 83fccf2d 2024-03-27 op *
4 5565365c 2024-03-27 op * This is free and unencumbered software released into the public domain.
5 5565365c 2024-03-27 op *
6 5565365c 2024-03-27 op * Anyone is free to copy, modify, publish, use, compile, sell, or
7 5565365c 2024-03-27 op * distribute this software, either in source code form or as a compiled
8 5565365c 2024-03-27 op * binary, for any purpose, commercial or non-commercial, and by any
9 5565365c 2024-03-27 op * means.
10 5565365c 2024-03-27 op *
11 5565365c 2024-03-27 op * In jurisdictions that recognize copyright laws, the author or authors
12 5565365c 2024-03-27 op * of this software dedicate any and all copyright interest in the
13 5565365c 2024-03-27 op * software to the public domain. We make this dedication for the benefit
14 5565365c 2024-03-27 op * of the public at large and to the detriment of our heirs and
15 5565365c 2024-03-27 op * successors. We intend this dedication to be an overt act of
16 5565365c 2024-03-27 op * relinquishment in perpetuity of all present and future rights to this
17 5565365c 2024-03-27 op * software under copyright law.
18 5565365c 2024-03-27 op *
19 5565365c 2024-03-27 op * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 5565365c 2024-03-27 op * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 5565365c 2024-03-27 op * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 5565365c 2024-03-27 op * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 5565365c 2024-03-27 op * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 5565365c 2024-03-27 op * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 5565365c 2024-03-27 op * OTHER DEALINGS IN THE SOFTWARE.
26 5565365c 2024-03-27 op */
27 5565365c 2024-03-27 op
28 5565365c 2024-03-27 op #include <assert.h>
29 5565365c 2024-03-27 op #include <errno.h>
30 5565365c 2024-03-27 op #include <stdarg.h>
31 5565365c 2024-03-27 op #include <stdint.h>
32 5565365c 2024-03-27 op #include <stdio.h>
33 5565365c 2024-03-27 op #include <stdlib.h>
34 5565365c 2024-03-27 op #include <string.h>
35 5565365c 2024-03-27 op #include <tls.h>
36 5565365c 2024-03-27 op #include <unistd.h>
37 5565365c 2024-03-27 op
38 5565365c 2024-03-27 op #include "bufio.h"
39 5565365c 2024-03-27 op
40 5565365c 2024-03-27 op int
41 5565365c 2024-03-27 op buf_init(struct buf *buf)
42 5565365c 2024-03-27 op {
43 5565365c 2024-03-27 op const size_t cap = BIO_CHUNK;
44 5565365c 2024-03-27 op
45 5565365c 2024-03-27 op memset(buf, 0, sizeof(*buf));
46 5565365c 2024-03-27 op if ((buf->buf = malloc(cap)) == NULL)
47 5565365c 2024-03-27 op return (-1);
48 5565365c 2024-03-27 op buf->cap = cap;
49 5565365c 2024-03-27 op return (0);
50 5565365c 2024-03-27 op }
51 5565365c 2024-03-27 op
52 5565365c 2024-03-27 op static int
53 5565365c 2024-03-27 op buf_grow(struct buf *buf)
54 5565365c 2024-03-27 op {
55 5565365c 2024-03-27 op size_t newcap;
56 5565365c 2024-03-27 op void *t;
57 5565365c 2024-03-27 op
58 5565365c 2024-03-27 op newcap = buf->cap + BIO_CHUNK;
59 5565365c 2024-03-27 op t = realloc(buf->buf, newcap);
60 5565365c 2024-03-27 op if (t == NULL)
61 5565365c 2024-03-27 op return (-1);
62 5565365c 2024-03-27 op buf->buf = t;
63 5565365c 2024-03-27 op buf->cap = newcap;
64 5565365c 2024-03-27 op return (0);
65 5565365c 2024-03-27 op }
66 5565365c 2024-03-27 op
67 5565365c 2024-03-27 op int
68 5565365c 2024-03-27 op buf_has_line(struct buf *buf, const char *nl)
69 5565365c 2024-03-27 op {
70 5565365c 2024-03-27 op return (memmem(buf->buf, buf->len, nl, strlen(nl)) != NULL);
71 5565365c 2024-03-27 op }
72 5565365c 2024-03-27 op
73 5565365c 2024-03-27 op char *
74 5565365c 2024-03-27 op buf_getdelim(struct buf *buf, const char *nl, size_t *len)
75 5565365c 2024-03-27 op {
76 5565365c 2024-03-27 op uint8_t *endl;
77 5565365c 2024-03-27 op size_t nlen;
78 5565365c 2024-03-27 op
79 5565365c 2024-03-27 op *len = 0;
80 5565365c 2024-03-27 op
81 5565365c 2024-03-27 op nlen = strlen(nl);
82 5565365c 2024-03-27 op if ((endl = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
83 5565365c 2024-03-27 op return (NULL);
84 5565365c 2024-03-27 op *len = endl + nlen - buf->buf;
85 5565365c 2024-03-27 op *endl = '\0';
86 5565365c 2024-03-27 op return (buf->buf);
87 5565365c 2024-03-27 op }
88 5565365c 2024-03-27 op
89 5565365c 2024-03-27 op void
90 5565365c 2024-03-27 op buf_drain(struct buf *buf, size_t l)
91 5565365c 2024-03-27 op {
92 5565365c 2024-03-27 op buf->cur = 0;
93 5565365c 2024-03-27 op
94 5565365c 2024-03-27 op if (l >= buf->len) {
95 5565365c 2024-03-27 op buf->len = 0;
96 5565365c 2024-03-27 op return;
97 5565365c 2024-03-27 op }
98 5565365c 2024-03-27 op
99 5565365c 2024-03-27 op memmove(buf->buf, buf->buf + l, buf->len - l);
100 5565365c 2024-03-27 op buf->len -= l;
101 5565365c 2024-03-27 op }
102 5565365c 2024-03-27 op
103 5565365c 2024-03-27 op void
104 5565365c 2024-03-27 op buf_drain_line(struct buf *buf, const char *nl)
105 5565365c 2024-03-27 op {
106 5565365c 2024-03-27 op uint8_t *endln;
107 5565365c 2024-03-27 op size_t nlen;
108 5565365c 2024-03-27 op
109 5565365c 2024-03-27 op nlen = strlen(nl);
110 5565365c 2024-03-27 op if ((endln = memmem(buf->buf, buf->len, nl, nlen)) == NULL)
111 5565365c 2024-03-27 op return;
112 5565365c 2024-03-27 op buf_drain(buf, endln + nlen - buf->buf);
113 5565365c 2024-03-27 op }
114 5565365c 2024-03-27 op
115 5565365c 2024-03-27 op void
116 5565365c 2024-03-27 op buf_free(struct buf *buf)
117 5565365c 2024-03-27 op {
118 5565365c 2024-03-27 op free(buf->buf);
119 5565365c 2024-03-27 op memset(buf, 0, sizeof(*buf));
120 5565365c 2024-03-27 op }
121 5565365c 2024-03-27 op
122 5565365c 2024-03-27 op int
123 5565365c 2024-03-27 op bufio_init(struct bufio *bio)
124 5565365c 2024-03-27 op {
125 5565365c 2024-03-27 op memset(bio, 0, sizeof(*bio));
126 5565365c 2024-03-27 op bio->fd = -1;
127 5565365c 2024-03-27 op
128 5565365c 2024-03-27 op if (buf_init(&bio->wbuf) == -1)
129 5565365c 2024-03-27 op return (-1);
130 5565365c 2024-03-27 op if (buf_init(&bio->rbuf) == -1) {
131 5565365c 2024-03-27 op buf_free(&bio->wbuf);
132 5565365c 2024-03-27 op return (-1);
133 5565365c 2024-03-27 op }
134 5565365c 2024-03-27 op return (0);
135 5565365c 2024-03-27 op }
136 5565365c 2024-03-27 op
137 5565365c 2024-03-27 op void
138 5565365c 2024-03-27 op bufio_free(struct bufio *bio)
139 5565365c 2024-03-27 op {
140 5565365c 2024-03-27 op if (bio->ctx)
141 5565365c 2024-03-27 op tls_free(bio->ctx);
142 5565365c 2024-03-27 op bio->ctx = NULL;
143 5565365c 2024-03-27 op
144 5565365c 2024-03-27 op if (bio->fd != -1)
145 5565365c 2024-03-27 op close(bio->fd);
146 5565365c 2024-03-27 op bio->fd = -1;
147 5565365c 2024-03-27 op
148 5565365c 2024-03-27 op buf_free(&bio->rbuf);
149 5565365c 2024-03-27 op buf_free(&bio->wbuf);
150 5565365c 2024-03-27 op }
151 5565365c 2024-03-27 op
152 5565365c 2024-03-27 op int
153 5565365c 2024-03-27 op bufio_close(struct bufio *bio)
154 5565365c 2024-03-27 op {
155 5565365c 2024-03-27 op if (bio->ctx == NULL)
156 5565365c 2024-03-27 op return (0);
157 5565365c 2024-03-27 op
158 5565365c 2024-03-27 op switch (tls_close(bio->ctx)) {
159 5565365c 2024-03-27 op case 0:
160 5565365c 2024-03-27 op return 0;
161 5565365c 2024-03-27 op case TLS_WANT_POLLIN:
162 5565365c 2024-03-27 op errno = EAGAIN;
163 5565365c 2024-03-27 op bio->wantev = BUFIO_WANT_READ;
164 5565365c 2024-03-27 op return (-1);
165 5565365c 2024-03-27 op case TLS_WANT_POLLOUT:
166 5565365c 2024-03-27 op errno = EAGAIN;
167 5565365c 2024-03-27 op bio->wantev = BUFIO_WANT_WRITE;
168 5565365c 2024-03-27 op return (-1);
169 5565365c 2024-03-27 op default:
170 5565365c 2024-03-27 op return (-1);
171 5565365c 2024-03-27 op }
172 5565365c 2024-03-27 op }
173 5565365c 2024-03-27 op
174 5565365c 2024-03-27 op int
175 5565365c 2024-03-27 op bufio_reset(struct bufio *bio)
176 5565365c 2024-03-27 op {
177 5565365c 2024-03-27 op bufio_free(bio);
178 5565365c 2024-03-27 op return (bufio_init(bio));
179 5565365c 2024-03-27 op }
180 5565365c 2024-03-27 op
181 5565365c 2024-03-27 op void
182 5565365c 2024-03-27 op bufio_set_fd(struct bufio *bio, int fd)
183 5565365c 2024-03-27 op {
184 5565365c 2024-03-27 op bio->fd = fd;
185 5565365c 2024-03-27 op }
186 5565365c 2024-03-27 op
187 5565365c 2024-03-27 op int
188 5565365c 2024-03-27 op bufio_starttls(struct bufio *bio, const char *host, int insecure,
189 5565365c 2024-03-27 op const uint8_t *cert, size_t certlen, const uint8_t *key, size_t keylen)
190 5565365c 2024-03-27 op {
191 5565365c 2024-03-27 op struct tls_config *conf;
192 5565365c 2024-03-27 op
193 5565365c 2024-03-27 op if ((conf = tls_config_new()) == NULL)
194 5565365c 2024-03-27 op return (-1);
195 5565365c 2024-03-27 op
196 5565365c 2024-03-27 op if (insecure) {
197 5565365c 2024-03-27 op tls_config_insecure_noverifycert(conf);
198 5565365c 2024-03-27 op tls_config_insecure_noverifyname(conf);
199 5565365c 2024-03-27 op tls_config_insecure_noverifytime(conf);
200 5565365c 2024-03-27 op }
201 5565365c 2024-03-27 op
202 5565365c 2024-03-27 op if (cert && tls_config_set_keypair_mem(conf, cert, certlen,
203 5565365c 2024-03-27 op key, keylen) == -1) {
204 5565365c 2024-03-27 op tls_config_free(conf);
205 5565365c 2024-03-27 op return (-1);
206 5565365c 2024-03-27 op }
207 5565365c 2024-03-27 op
208 5565365c 2024-03-27 op if ((bio->ctx = tls_client()) == NULL) {
209 5565365c 2024-03-27 op tls_config_free(conf);
210 5565365c 2024-03-27 op return (-1);
211 5565365c 2024-03-27 op }
212 5565365c 2024-03-27 op
213 5565365c 2024-03-27 op if (tls_configure(bio->ctx, conf) == -1) {
214 5565365c 2024-03-27 op tls_config_free(conf);
215 5565365c 2024-03-27 op return (-1);
216 5565365c 2024-03-27 op }
217 5565365c 2024-03-27 op
218 5565365c 2024-03-27 op tls_config_free(conf);
219 5565365c 2024-03-27 op
220 5565365c 2024-03-27 op if (tls_connect_socket(bio->ctx, bio->fd, host) == -1)
221 5565365c 2024-03-27 op return (-1);
222 5565365c 2024-03-27 op
223 5565365c 2024-03-27 op return (0);
224 5565365c 2024-03-27 op }
225 5565365c 2024-03-27 op
226 5565365c 2024-03-27 op int
227 5565365c 2024-03-27 op bufio_ev(struct bufio *bio)
228 5565365c 2024-03-27 op {
229 5565365c 2024-03-27 op short ev;
230 5565365c 2024-03-27 op
231 5565365c 2024-03-27 op if (bio->wantev)
232 5565365c 2024-03-27 op return (bio->wantev);
233 5565365c 2024-03-27 op
234 5565365c 2024-03-27 op ev = BUFIO_WANT_READ;
235 5565365c 2024-03-27 op if (bio->wbuf.len != 0)
236 5565365c 2024-03-27 op ev |= BUFIO_WANT_WRITE;
237 5565365c 2024-03-27 op
238 5565365c 2024-03-27 op return (ev);
239 5565365c 2024-03-27 op }
240 5565365c 2024-03-27 op
241 5565365c 2024-03-27 op int
242 5565365c 2024-03-27 op bufio_handshake(struct bufio *bio)
243 5565365c 2024-03-27 op {
244 5565365c 2024-03-27 op if (bio->ctx == NULL) {
245 5565365c 2024-03-27 op errno = EINVAL;
246 5565365c 2024-03-27 op return (-1);
247 5565365c 2024-03-27 op }
248 5565365c 2024-03-27 op
249 5565365c 2024-03-27 op switch (tls_handshake(bio->ctx)) {
250 5565365c 2024-03-27 op case 0:
251 5565365c 2024-03-27 op return (0);
252 5565365c 2024-03-27 op case TLS_WANT_POLLIN:
253 5565365c 2024-03-27 op errno = EAGAIN;
254 5565365c 2024-03-27 op bio->wantev = BUFIO_WANT_READ;
255 5565365c 2024-03-27 op return (-1);
256 5565365c 2024-03-27 op case TLS_WANT_POLLOUT:
257 5565365c 2024-03-27 op errno = EAGAIN;
258 5565365c 2024-03-27 op bio->wantev = BUFIO_WANT_WRITE;
259 5565365c 2024-03-27 op return (-1);
260 5565365c 2024-03-27 op default:
261 5565365c 2024-03-27 op return (-1);
262 5565365c 2024-03-27 op }
263 5565365c 2024-03-27 op }
264 5565365c 2024-03-27 op
265 5565365c 2024-03-27 op ssize_t
266 5565365c 2024-03-27 op bufio_read(struct bufio *bio)
267 5565365c 2024-03-27 op {
268 5565365c 2024-03-27 op struct buf *rbuf = &bio->rbuf;
269 5565365c 2024-03-27 op ssize_t r;
270 5565365c 2024-03-27 op
271 5565365c 2024-03-27 op assert(rbuf->cap >= rbuf->len);
272 5565365c 2024-03-27 op if (rbuf->cap - rbuf->len < BIO_CHUNK) {
273 5565365c 2024-03-27 op if (buf_grow(rbuf) == -1)
274 5565365c 2024-03-27 op return (-1);
275 5565365c 2024-03-27 op }
276 5565365c 2024-03-27 op
277 5565365c 2024-03-27 op if (bio->ctx) {
278 5565365c 2024-03-27 op r = tls_read(bio->ctx, rbuf->buf + rbuf->len,
279 5565365c 2024-03-27 op rbuf->cap - rbuf->len);
280 5565365c 2024-03-27 op switch (r) {
281 5565365c 2024-03-27 op case TLS_WANT_POLLIN:
282 5565365c 2024-03-27 op errno = EAGAIN;
283 5565365c 2024-03-27 op bio->wantev = BUFIO_WANT_READ;
284 5565365c 2024-03-27 op return (-1);
285 5565365c 2024-03-27 op case TLS_WANT_POLLOUT:
286 5565365c 2024-03-27 op errno = EAGAIN;
287 5565365c 2024-03-27 op bio->wantev = BUFIO_WANT_WRITE;
288 5565365c 2024-03-27 op return (-1);
289 5565365c 2024-03-27 op case -1:
290 5565365c 2024-03-27 op return (-1);
291 5565365c 2024-03-27 op default:
292 5565365c 2024-03-27 op bio->wantev = 0;
293 5565365c 2024-03-27 op rbuf->len += r;
294 5565365c 2024-03-27 op return (r);
295 5565365c 2024-03-27 op }
296 5565365c 2024-03-27 op }
297 5565365c 2024-03-27 op
298 5565365c 2024-03-27 op r = read(bio->fd, rbuf->buf + rbuf->len, rbuf->cap - rbuf->len);
299 5565365c 2024-03-27 op if (r == -1)
300 5565365c 2024-03-27 op return (-1);
301 5565365c 2024-03-27 op rbuf->len += r;
302 5565365c 2024-03-27 op return (r);
303 5565365c 2024-03-27 op }
304 5565365c 2024-03-27 op
305 5565365c 2024-03-27 op size_t
306 5565365c 2024-03-27 op bufio_drain(struct bufio *bio, void *d, size_t len)
307 5565365c 2024-03-27 op {
308 5565365c 2024-03-27 op struct buf *rbuf = &bio->rbuf;
309 5565365c 2024-03-27 op
310 5565365c 2024-03-27 op if (len > rbuf->len)
311 5565365c 2024-03-27 op len = rbuf->len;
312 5565365c 2024-03-27 op memcpy(d, rbuf->buf, len);
313 5565365c 2024-03-27 op buf_drain(rbuf, len);
314 5565365c 2024-03-27 op return (len);
315 5565365c 2024-03-27 op }
316 5565365c 2024-03-27 op
317 5565365c 2024-03-27 op ssize_t
318 5565365c 2024-03-27 op bufio_write(struct bufio *bio)
319 5565365c 2024-03-27 op {
320 5565365c 2024-03-27 op struct buf *wbuf = &bio->wbuf;
321 5565365c 2024-03-27 op ssize_t w;
322 5565365c 2024-03-27 op
323 5565365c 2024-03-27 op if (bio->ctx) {
324 5565365c 2024-03-27 op switch (w = tls_write(bio->ctx, wbuf->buf, wbuf->len)) {
325 5565365c 2024-03-27 op case TLS_WANT_POLLIN:
326 5565365c 2024-03-27 op errno = EAGAIN;
327 5565365c 2024-03-27 op bio->wantev = BUFIO_WANT_READ;
328 5565365c 2024-03-27 op return (-1);
329 5565365c 2024-03-27 op case TLS_WANT_POLLOUT:
330 5565365c 2024-03-27 op errno = EAGAIN;
331 5565365c 2024-03-27 op bio->wantev = BUFIO_WANT_WRITE;
332 5565365c 2024-03-27 op return (-1);
333 5565365c 2024-03-27 op case -1:
334 5565365c 2024-03-27 op return (-1);
335 5565365c 2024-03-27 op default:
336 5565365c 2024-03-27 op bio->wantev = 0;
337 5565365c 2024-03-27 op buf_drain(wbuf, w);
338 5565365c 2024-03-27 op return (w);
339 5565365c 2024-03-27 op }
340 5565365c 2024-03-27 op }
341 5565365c 2024-03-27 op
342 5565365c 2024-03-27 op w = write(bio->fd, wbuf->buf, wbuf->len);
343 5565365c 2024-03-27 op if (w == -1)
344 5565365c 2024-03-27 op return (-1);
345 5565365c 2024-03-27 op buf_drain(wbuf, w);
346 5565365c 2024-03-27 op return (w);
347 5565365c 2024-03-27 op }
348 5565365c 2024-03-27 op
349 5565365c 2024-03-27 op const char *
350 5565365c 2024-03-27 op bufio_io_err(struct bufio *bio)
351 5565365c 2024-03-27 op {
352 5565365c 2024-03-27 op if (bio->ctx)
353 5565365c 2024-03-27 op return tls_error(bio->ctx);
354 5565365c 2024-03-27 op
355 5565365c 2024-03-27 op return strerror(errno);
356 5565365c 2024-03-27 op }
357 5565365c 2024-03-27 op
358 5565365c 2024-03-27 op int
359 5565365c 2024-03-27 op bufio_compose(struct bufio *bio, const void *d, size_t len)
360 5565365c 2024-03-27 op {
361 5565365c 2024-03-27 op struct buf *wbuf = &bio->wbuf;
362 5565365c 2024-03-27 op
363 5565365c 2024-03-27 op while (wbuf->cap - wbuf->len < len) {
364 5565365c 2024-03-27 op if (buf_grow(wbuf) == -1)
365 5565365c 2024-03-27 op return (-1);
366 5565365c 2024-03-27 op }
367 5565365c 2024-03-27 op
368 5565365c 2024-03-27 op memcpy(wbuf->buf + wbuf->len, d, len);
369 5565365c 2024-03-27 op wbuf->len += len;
370 5565365c 2024-03-27 op return (0);
371 5565365c 2024-03-27 op }
372 5565365c 2024-03-27 op
373 5565365c 2024-03-27 op int
374 5565365c 2024-03-27 op bufio_compose_str(struct bufio *bio, const char *str)
375 5565365c 2024-03-27 op {
376 5565365c 2024-03-27 op return (bufio_compose(bio, str, strlen(str)));
377 5565365c 2024-03-27 op }
378 5565365c 2024-03-27 op
379 5565365c 2024-03-27 op int
380 5565365c 2024-03-27 op bufio_compose_fmt(struct bufio *bio, const char *fmt, ...)
381 5565365c 2024-03-27 op {
382 5565365c 2024-03-27 op va_list ap;
383 5565365c 2024-03-27 op char *str;
384 5565365c 2024-03-27 op int r;
385 5565365c 2024-03-27 op
386 5565365c 2024-03-27 op va_start(ap, fmt);
387 5565365c 2024-03-27 op r = vasprintf(&str, fmt, ap);
388 5565365c 2024-03-27 op va_end(ap);
389 5565365c 2024-03-27 op
390 5565365c 2024-03-27 op if (r == -1)
391 5565365c 2024-03-27 op return (-1);
392 5565365c 2024-03-27 op r = bufio_compose(bio, str, r);
393 5565365c 2024-03-27 op free(str);
394 5565365c 2024-03-27 op return (r);
395 5565365c 2024-03-27 op }
396 5565365c 2024-03-27 op
397 5565365c 2024-03-27 op void
398 5565365c 2024-03-27 op bufio_rewind_cursor(struct bufio *bio)
399 5565365c 2024-03-27 op {
400 5565365c 2024-03-27 op bio->rbuf.cur = 0;
401 5565365c 2024-03-27 op }
402 5565365c 2024-03-27 op
403 5565365c 2024-03-27 op int
404 5565365c 2024-03-27 op bufio_get_cb(void *d)
405 5565365c 2024-03-27 op {
406 5565365c 2024-03-27 op struct bufio *bio = d;
407 5565365c 2024-03-27 op struct buf *rbuf = &bio->rbuf;
408 5565365c 2024-03-27 op
409 5565365c 2024-03-27 op if (rbuf->cur >= rbuf->len)
410 5565365c 2024-03-27 op return (EOF);
411 5565365c 2024-03-27 op return (rbuf->buf[rbuf->cur++]);
412 5565365c 2024-03-27 op }
413 5565365c 2024-03-27 op
414 5565365c 2024-03-27 op int
415 5565365c 2024-03-27 op bufio_peek_cb(void *d)
416 5565365c 2024-03-27 op {
417 5565365c 2024-03-27 op struct bufio *bio = d;
418 5565365c 2024-03-27 op struct buf *rbuf = &bio->rbuf;
419 5565365c 2024-03-27 op
420 5565365c 2024-03-27 op if (rbuf->cur >= rbuf->len)
421 5565365c 2024-03-27 op return (EOF);
422 5565365c 2024-03-27 op return (rbuf->buf[rbuf->cur]);
423 5565365c 2024-03-27 op }