Merge branch 'obsd-master'
[tmux.git] / compat / imsg-buffer.c
blob265e8cc642bcdd1122f227e0bc5d1cd7c8a8323b
1 /* $OpenBSD: imsg-buffer.c,v 1.31 2024/11/26 13:57:31 claudio Exp $ */
3 /*
4 * Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org>
5 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <sys/uio.h>
23 #include <arpa/inet.h>
25 #include <limits.h>
26 #include <errno.h>
27 #include <stdint.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
32 #include "compat.h"
33 #include "imsg.h"
35 #undef htobe16
36 #define htobe16 htons
37 #undef htobe32
38 #define htobe32 htonl
39 #undef htobe64
40 #define htobe64 htonll
41 #undef be16toh
42 #define be16toh ntohs
43 #undef be32toh
44 #define be32toh ntohl
45 #undef be64toh
46 #define be64toh ntohll
48 struct msgbuf {
49 TAILQ_HEAD(, ibuf) bufs;
50 TAILQ_HEAD(, ibuf) rbufs;
51 uint32_t queued;
52 char *rbuf;
53 struct ibuf *rpmsg;
54 struct ibuf *(*readhdr)(struct ibuf *, void *, int *);
55 void *rarg;
56 size_t roff;
57 size_t hdrsize;
60 static void msgbuf_read_enqueue(struct msgbuf *, struct ibuf *);
61 static void msgbuf_enqueue(struct msgbuf *, struct ibuf *);
62 static void msgbuf_dequeue(struct msgbuf *, struct ibuf *);
63 static void msgbuf_drain(struct msgbuf *, size_t);
65 #define IBUF_FD_MARK_ON_STACK -2
67 struct ibuf *
68 ibuf_open(size_t len)
70 struct ibuf *buf;
72 if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
73 return (NULL);
74 if (len > 0) {
75 if ((buf->buf = calloc(len, 1)) == NULL) {
76 free(buf);
77 return (NULL);
80 buf->size = buf->max = len;
81 buf->fd = -1;
83 return (buf);
86 struct ibuf *
87 ibuf_dynamic(size_t len, size_t max)
89 struct ibuf *buf;
91 if (max == 0 || max < len) {
92 errno = EINVAL;
93 return (NULL);
96 if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
97 return (NULL);
98 if (len > 0) {
99 if ((buf->buf = calloc(len, 1)) == NULL) {
100 free(buf);
101 return (NULL);
104 buf->size = len;
105 buf->max = max;
106 buf->fd = -1;
108 return (buf);
111 void *
112 ibuf_reserve(struct ibuf *buf, size_t len)
114 void *b;
116 if (len > SIZE_MAX - buf->wpos) {
117 errno = ERANGE;
118 return (NULL);
120 if (buf->fd == IBUF_FD_MARK_ON_STACK) {
121 /* can not grow stack buffers */
122 errno = EINVAL;
123 return (NULL);
126 if (buf->wpos + len > buf->size) {
127 unsigned char *nb;
129 /* check if buffer is allowed to grow */
130 if (buf->wpos + len > buf->max) {
131 errno = ERANGE;
132 return (NULL);
134 nb = realloc(buf->buf, buf->wpos + len);
135 if (nb == NULL)
136 return (NULL);
137 memset(nb + buf->size, 0, buf->wpos + len - buf->size);
138 buf->buf = nb;
139 buf->size = buf->wpos + len;
142 b = buf->buf + buf->wpos;
143 buf->wpos += len;
144 return (b);
148 ibuf_add(struct ibuf *buf, const void *data, size_t len)
150 void *b;
152 if ((b = ibuf_reserve(buf, len)) == NULL)
153 return (-1);
155 memcpy(b, data, len);
156 return (0);
160 ibuf_add_ibuf(struct ibuf *buf, const struct ibuf *from)
162 return ibuf_add(buf, ibuf_data(from), ibuf_size(from));
166 ibuf_add_n8(struct ibuf *buf, uint64_t value)
168 uint8_t v;
170 if (value > UINT8_MAX) {
171 errno = EINVAL;
172 return (-1);
174 v = value;
175 return ibuf_add(buf, &v, sizeof(v));
179 ibuf_add_n16(struct ibuf *buf, uint64_t value)
181 uint16_t v;
183 if (value > UINT16_MAX) {
184 errno = EINVAL;
185 return (-1);
187 v = htobe16(value);
188 return ibuf_add(buf, &v, sizeof(v));
192 ibuf_add_n32(struct ibuf *buf, uint64_t value)
194 uint32_t v;
196 if (value > UINT32_MAX) {
197 errno = EINVAL;
198 return (-1);
200 v = htobe32(value);
201 return ibuf_add(buf, &v, sizeof(v));
205 ibuf_add_n64(struct ibuf *buf, uint64_t value)
207 value = htobe64(value);
208 return ibuf_add(buf, &value, sizeof(value));
212 ibuf_add_h16(struct ibuf *buf, uint64_t value)
214 uint16_t v;
216 if (value > UINT16_MAX) {
217 errno = EINVAL;
218 return (-1);
220 v = value;
221 return ibuf_add(buf, &v, sizeof(v));
225 ibuf_add_h32(struct ibuf *buf, uint64_t value)
227 uint32_t v;
229 if (value > UINT32_MAX) {
230 errno = EINVAL;
231 return (-1);
233 v = value;
234 return ibuf_add(buf, &v, sizeof(v));
238 ibuf_add_h64(struct ibuf *buf, uint64_t value)
240 return ibuf_add(buf, &value, sizeof(value));
244 ibuf_add_zero(struct ibuf *buf, size_t len)
246 void *b;
248 if ((b = ibuf_reserve(buf, len)) == NULL)
249 return (-1);
250 memset(b, 0, len);
251 return (0);
254 void *
255 ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
257 /* only allow seeking between rpos and wpos */
258 if (ibuf_size(buf) < pos || SIZE_MAX - pos < len ||
259 ibuf_size(buf) < pos + len) {
260 errno = ERANGE;
261 return (NULL);
264 return (buf->buf + buf->rpos + pos);
268 ibuf_set(struct ibuf *buf, size_t pos, const void *data, size_t len)
270 void *b;
272 if ((b = ibuf_seek(buf, pos, len)) == NULL)
273 return (-1);
275 memcpy(b, data, len);
276 return (0);
280 ibuf_set_n8(struct ibuf *buf, size_t pos, uint64_t value)
282 uint8_t v;
284 if (value > UINT8_MAX) {
285 errno = EINVAL;
286 return (-1);
288 v = value;
289 return (ibuf_set(buf, pos, &v, sizeof(v)));
293 ibuf_set_n16(struct ibuf *buf, size_t pos, uint64_t value)
295 uint16_t v;
297 if (value > UINT16_MAX) {
298 errno = EINVAL;
299 return (-1);
301 v = htobe16(value);
302 return (ibuf_set(buf, pos, &v, sizeof(v)));
306 ibuf_set_n32(struct ibuf *buf, size_t pos, uint64_t value)
308 uint32_t v;
310 if (value > UINT32_MAX) {
311 errno = EINVAL;
312 return (-1);
314 v = htobe32(value);
315 return (ibuf_set(buf, pos, &v, sizeof(v)));
319 ibuf_set_n64(struct ibuf *buf, size_t pos, uint64_t value)
321 value = htobe64(value);
322 return (ibuf_set(buf, pos, &value, sizeof(value)));
326 ibuf_set_h16(struct ibuf *buf, size_t pos, uint64_t value)
328 uint16_t v;
330 if (value > UINT16_MAX) {
331 errno = EINVAL;
332 return (-1);
334 v = value;
335 return (ibuf_set(buf, pos, &v, sizeof(v)));
339 ibuf_set_h32(struct ibuf *buf, size_t pos, uint64_t value)
341 uint32_t v;
343 if (value > UINT32_MAX) {
344 errno = EINVAL;
345 return (-1);
347 v = value;
348 return (ibuf_set(buf, pos, &v, sizeof(v)));
352 ibuf_set_h64(struct ibuf *buf, size_t pos, uint64_t value)
354 return (ibuf_set(buf, pos, &value, sizeof(value)));
357 void *
358 ibuf_data(const struct ibuf *buf)
360 return (buf->buf + buf->rpos);
363 size_t
364 ibuf_size(const struct ibuf *buf)
366 return (buf->wpos - buf->rpos);
369 size_t
370 ibuf_left(const struct ibuf *buf)
372 /* on stack buffers have no space left */
373 if (buf->fd == IBUF_FD_MARK_ON_STACK)
374 return (0);
375 return (buf->max - buf->wpos);
379 ibuf_truncate(struct ibuf *buf, size_t len)
381 if (ibuf_size(buf) >= len) {
382 buf->wpos = buf->rpos + len;
383 return (0);
385 if (buf->fd == IBUF_FD_MARK_ON_STACK) {
386 /* only allow to truncate down for stack buffers */
387 errno = ERANGE;
388 return (-1);
390 return ibuf_add_zero(buf, len - ibuf_size(buf));
393 void
394 ibuf_rewind(struct ibuf *buf)
396 buf->rpos = 0;
399 void
400 ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
402 msgbuf_enqueue(msgbuf, buf);
405 void
406 ibuf_from_buffer(struct ibuf *buf, void *data, size_t len)
408 memset(buf, 0, sizeof(*buf));
409 buf->buf = data;
410 buf->size = buf->wpos = len;
411 buf->fd = IBUF_FD_MARK_ON_STACK;
414 void
415 ibuf_from_ibuf(struct ibuf *buf, const struct ibuf *from)
417 ibuf_from_buffer(buf, ibuf_data(from), ibuf_size(from));
421 ibuf_get(struct ibuf *buf, void *data, size_t len)
423 if (ibuf_size(buf) < len) {
424 errno = EBADMSG;
425 return (-1);
428 memcpy(data, ibuf_data(buf), len);
429 buf->rpos += len;
430 return (0);
434 ibuf_get_ibuf(struct ibuf *buf, size_t len, struct ibuf *new)
436 if (ibuf_size(buf) < len) {
437 errno = EBADMSG;
438 return (-1);
441 ibuf_from_buffer(new, ibuf_data(buf), len);
442 buf->rpos += len;
443 return (0);
447 ibuf_get_h16(struct ibuf *buf, uint16_t *value)
449 return ibuf_get(buf, value, sizeof(*value));
453 ibuf_get_h32(struct ibuf *buf, uint32_t *value)
455 return ibuf_get(buf, value, sizeof(*value));
459 ibuf_get_h64(struct ibuf *buf, uint64_t *value)
461 return ibuf_get(buf, value, sizeof(*value));
465 ibuf_get_n8(struct ibuf *buf, uint8_t *value)
467 return ibuf_get(buf, value, sizeof(*value));
471 ibuf_get_n16(struct ibuf *buf, uint16_t *value)
473 int rv;
475 rv = ibuf_get(buf, value, sizeof(*value));
476 *value = be16toh(*value);
477 return (rv);
481 ibuf_get_n32(struct ibuf *buf, uint32_t *value)
483 int rv;
485 rv = ibuf_get(buf, value, sizeof(*value));
486 *value = be32toh(*value);
487 return (rv);
491 ibuf_get_n64(struct ibuf *buf, uint64_t *value)
493 int rv;
495 rv = ibuf_get(buf, value, sizeof(*value));
496 *value = be64toh(*value);
497 return (rv);
500 char *
501 ibuf_get_string(struct ibuf *buf, size_t len)
503 char *str;
505 if (ibuf_size(buf) < len) {
506 errno = EBADMSG;
507 return (NULL);
510 str = strndup(ibuf_data(buf), len);
511 if (str == NULL)
512 return (NULL);
513 buf->rpos += len;
514 return (str);
518 ibuf_skip(struct ibuf *buf, size_t len)
520 if (ibuf_size(buf) < len) {
521 errno = EBADMSG;
522 return (-1);
525 buf->rpos += len;
526 return (0);
529 void
530 ibuf_free(struct ibuf *buf)
532 if (buf == NULL)
533 return;
534 /* if buf lives on the stack abort before causing more harm */
535 if (buf->fd == IBUF_FD_MARK_ON_STACK)
536 abort();
537 if (buf->fd >= 0)
538 close(buf->fd);
539 freezero(buf->buf, buf->size);
540 free(buf);
544 ibuf_fd_avail(struct ibuf *buf)
546 return (buf->fd >= 0);
550 ibuf_fd_get(struct ibuf *buf)
552 int fd;
554 /* negative fds are internal use and equivalent to -1 */
555 if (buf->fd < 0)
556 return (-1);
557 fd = buf->fd;
558 buf->fd = -1;
559 return (fd);
562 void
563 ibuf_fd_set(struct ibuf *buf, int fd)
565 /* if buf lives on the stack abort before causing more harm */
566 if (buf->fd == IBUF_FD_MARK_ON_STACK)
567 abort();
568 if (buf->fd >= 0)
569 close(buf->fd);
570 buf->fd = -1;
571 if (fd >= 0)
572 buf->fd = fd;
575 struct msgbuf *
576 msgbuf_new(void)
578 struct msgbuf *msgbuf;
580 if ((msgbuf = calloc(1, sizeof(*msgbuf))) == NULL)
581 return (NULL);
582 msgbuf->queued = 0;
583 TAILQ_INIT(&msgbuf->bufs);
584 TAILQ_INIT(&msgbuf->rbufs);
586 return msgbuf;
589 struct msgbuf *
590 msgbuf_new_reader(size_t hdrsz,
591 struct ibuf *(*readhdr)(struct ibuf *, void *, int *), void *arg)
593 struct msgbuf *msgbuf;
594 char *buf;
596 if (hdrsz == 0 || hdrsz > IBUF_READ_SIZE / 2) {
597 errno = EINVAL;
598 return (NULL);
601 if ((buf = malloc(IBUF_READ_SIZE)) == NULL)
602 return (NULL);
604 msgbuf = msgbuf_new();
605 if (msgbuf == NULL) {
606 free(buf);
607 return (NULL);
610 msgbuf->rbuf = buf;
611 msgbuf->hdrsize = hdrsz;
612 msgbuf->readhdr = readhdr;
613 msgbuf->rarg = arg;
615 return (msgbuf);
618 void
619 msgbuf_free(struct msgbuf *msgbuf)
621 if (msgbuf == NULL)
622 return;
623 msgbuf_clear(msgbuf);
624 free(msgbuf->rbuf);
625 free(msgbuf);
628 uint32_t
629 msgbuf_queuelen(struct msgbuf *msgbuf)
631 return (msgbuf->queued);
634 void
635 msgbuf_clear(struct msgbuf *msgbuf)
637 struct ibuf *buf;
639 /* write side */
640 while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
641 msgbuf_dequeue(msgbuf, buf);
642 msgbuf->queued = 0;
644 /* read side */
645 while ((buf = TAILQ_FIRST(&msgbuf->rbufs)) != NULL) {
646 TAILQ_REMOVE(&msgbuf->rbufs, buf, entry);
647 ibuf_free(buf);
649 msgbuf->roff = 0;
650 ibuf_free(msgbuf->rpmsg);
651 msgbuf->rpmsg = NULL;
654 struct ibuf *
655 msgbuf_get(struct msgbuf *msgbuf)
657 struct ibuf *buf;
659 if ((buf = TAILQ_FIRST(&msgbuf->rbufs)) != NULL)
660 TAILQ_REMOVE(&msgbuf->rbufs, buf, entry);
661 return buf;
665 ibuf_write(int fd, struct msgbuf *msgbuf)
667 struct iovec iov[IOV_MAX];
668 struct ibuf *buf;
669 unsigned int i = 0;
670 ssize_t n;
672 memset(&iov, 0, sizeof(iov));
673 TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
674 if (i >= IOV_MAX)
675 break;
676 iov[i].iov_base = ibuf_data(buf);
677 iov[i].iov_len = ibuf_size(buf);
678 i++;
680 if (i == 0)
681 return (0); /* nothing queued */
683 again:
684 if ((n = writev(fd, iov, i)) == -1) {
685 if (errno == EINTR)
686 goto again;
687 if (errno == EAGAIN || errno == ENOBUFS)
688 /* lets retry later again */
689 return (0);
690 return (-1);
693 msgbuf_drain(msgbuf, n);
694 return (0);
698 msgbuf_write(int fd, struct msgbuf *msgbuf)
700 struct iovec iov[IOV_MAX];
701 struct ibuf *buf, *buf0 = NULL;
702 unsigned int i = 0;
703 ssize_t n;
704 struct msghdr msg;
705 struct cmsghdr *cmsg;
706 union {
707 struct cmsghdr hdr;
708 char buf[CMSG_SPACE(sizeof(int))];
709 } cmsgbuf;
711 memset(&iov, 0, sizeof(iov));
712 memset(&msg, 0, sizeof(msg));
713 memset(&cmsgbuf, 0, sizeof(cmsgbuf));
714 TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
715 if (i >= IOV_MAX)
716 break;
717 if (i > 0 && buf->fd != -1)
718 break;
719 iov[i].iov_base = ibuf_data(buf);
720 iov[i].iov_len = ibuf_size(buf);
721 i++;
722 if (buf->fd != -1)
723 buf0 = buf;
726 if (i == 0)
727 return (0); /* nothing queued */
729 msg.msg_iov = iov;
730 msg.msg_iovlen = i;
732 if (buf0 != NULL) {
733 msg.msg_control = (caddr_t)&cmsgbuf.buf;
734 msg.msg_controllen = sizeof(cmsgbuf.buf);
735 cmsg = CMSG_FIRSTHDR(&msg);
736 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
737 cmsg->cmsg_level = SOL_SOCKET;
738 cmsg->cmsg_type = SCM_RIGHTS;
739 *(int *)CMSG_DATA(cmsg) = buf0->fd;
742 again:
743 if ((n = sendmsg(fd, &msg, 0)) == -1) {
744 if (errno == EINTR)
745 goto again;
746 if (errno == EAGAIN || errno == ENOBUFS)
747 /* lets retry later again */
748 return (0);
749 return (-1);
753 * assumption: fd got sent if sendmsg sent anything
754 * this works because fds are passed one at a time
756 if (buf0 != NULL) {
757 close(buf0->fd);
758 buf0->fd = -1;
761 msgbuf_drain(msgbuf, n);
763 return (0);
766 static int
767 ibuf_read_process(struct msgbuf *msgbuf, int fd)
769 struct ibuf rbuf, msg;
770 ssize_t sz;
772 ibuf_from_buffer(&rbuf, msgbuf->rbuf, msgbuf->roff);
774 do {
775 if (msgbuf->rpmsg == NULL) {
776 if (ibuf_size(&rbuf) < msgbuf->hdrsize)
777 break;
778 /* get size from header */
779 ibuf_from_buffer(&msg, ibuf_data(&rbuf),
780 msgbuf->hdrsize);
781 if ((msgbuf->rpmsg = msgbuf->readhdr(&msg,
782 msgbuf->rarg, &fd)) == NULL)
783 goto fail;
786 if (ibuf_left(msgbuf->rpmsg) <= ibuf_size(&rbuf))
787 sz = ibuf_left(msgbuf->rpmsg);
788 else
789 sz = ibuf_size(&rbuf);
791 /* neither call below can fail */
792 if (ibuf_get_ibuf(&rbuf, sz, &msg) == -1 ||
793 ibuf_add_ibuf(msgbuf->rpmsg, &msg) == -1)
794 goto fail;
796 if (ibuf_left(msgbuf->rpmsg) == 0) {
797 msgbuf_read_enqueue(msgbuf, msgbuf->rpmsg);
798 msgbuf->rpmsg = NULL;
800 } while (ibuf_size(&rbuf) > 0);
802 if (ibuf_size(&rbuf) > 0)
803 memmove(msgbuf->rbuf, ibuf_data(&rbuf), ibuf_size(&rbuf));
804 msgbuf->roff = ibuf_size(&rbuf);
806 if (fd != -1)
807 close(fd);
808 return (1);
810 fail:
811 /* XXX how to properly clean up is unclear */
812 if (fd != -1)
813 close(fd);
814 return (-1);
818 ibuf_read(int fd, struct msgbuf *msgbuf)
820 struct iovec iov;
821 ssize_t n;
823 if (msgbuf->rbuf == NULL) {
824 errno = EINVAL;
825 return (-1);
828 iov.iov_base = msgbuf->rbuf + msgbuf->roff;
829 iov.iov_len = IBUF_READ_SIZE - msgbuf->roff;
831 again:
832 if ((n = readv(fd, &iov, 1)) == -1) {
833 if (errno == EINTR)
834 goto again;
835 if (errno == EAGAIN)
836 /* lets retry later again */
837 return (1);
838 return (-1);
840 if (n == 0) /* connection closed */
841 return (0);
843 msgbuf->roff += n;
844 /* new data arrived, try to process it */
845 return (ibuf_read_process(msgbuf, -1));
849 msgbuf_read(int fd, struct msgbuf *msgbuf)
851 struct msghdr msg;
852 struct cmsghdr *cmsg;
853 union {
854 struct cmsghdr hdr;
855 char buf[CMSG_SPACE(sizeof(int) * 1)];
856 } cmsgbuf;
857 struct iovec iov;
858 ssize_t n;
859 int fdpass = -1;
861 if (msgbuf->rbuf == NULL) {
862 errno = EINVAL;
863 return (-1);
866 memset(&msg, 0, sizeof(msg));
867 memset(&cmsgbuf, 0, sizeof(cmsgbuf));
869 iov.iov_base = msgbuf->rbuf + msgbuf->roff;
870 iov.iov_len = IBUF_READ_SIZE - msgbuf->roff;
871 msg.msg_iov = &iov;
872 msg.msg_iovlen = 1;
873 msg.msg_control = &cmsgbuf.buf;
874 msg.msg_controllen = sizeof(cmsgbuf.buf);
876 again:
877 if ((n = recvmsg(fd, &msg, 0)) == -1) {
878 if (errno == EINTR)
879 goto again;
880 if (errno == EMSGSIZE)
882 * Not enough fd slots: fd passing failed, retry
883 * to receive the message without fd.
884 * imsg_get_fd() will return -1 in that case.
886 goto again;
887 if (errno == EAGAIN)
888 /* lets retry later again */
889 return (1);
890 return (-1);
892 if (n == 0) /* connection closed */
893 return (0);
895 msgbuf->roff += n;
897 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
898 cmsg = CMSG_NXTHDR(&msg, cmsg)) {
899 if (cmsg->cmsg_level == SOL_SOCKET &&
900 cmsg->cmsg_type == SCM_RIGHTS) {
901 int i, j, f;
904 * We only accept one file descriptor. Due to C
905 * padding rules, our control buffer might contain
906 * more than one fd, and we must close them.
908 j = ((char *)cmsg + cmsg->cmsg_len -
909 (char *)CMSG_DATA(cmsg)) / sizeof(int);
910 for (i = 0; i < j; i++) {
911 f = ((int *)CMSG_DATA(cmsg))[i];
912 if (i == 0)
913 fdpass = f;
914 else
915 close(f);
918 /* we do not handle other ctl data level */
921 /* new data arrived, try to process it */
922 return (ibuf_read_process(msgbuf, fdpass));
925 static void
926 msgbuf_read_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
928 /* if buf lives on the stack abort before causing more harm */
929 if (buf->fd == IBUF_FD_MARK_ON_STACK)
930 abort();
931 TAILQ_INSERT_TAIL(&msgbuf->rbufs, buf, entry);
934 static void
935 msgbuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
937 /* if buf lives on the stack abort before causing more harm */
938 if (buf->fd == IBUF_FD_MARK_ON_STACK)
939 abort();
940 TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
941 msgbuf->queued++;
944 static void
945 msgbuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
947 TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
948 msgbuf->queued--;
949 ibuf_free(buf);
952 static void
953 msgbuf_drain(struct msgbuf *msgbuf, size_t n)
955 struct ibuf *buf, *next;
957 for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
958 buf = next) {
959 next = TAILQ_NEXT(buf, entry);
960 if (n >= ibuf_size(buf)) {
961 n -= ibuf_size(buf);
962 msgbuf_dequeue(msgbuf, buf);
963 } else {
964 buf->rpos += n;
965 n = 0;