1*f844e94eSwiz /* $OpenBSD: imsg.c,v 1.23 2023/12/12 15:47:41 claudio Exp $ */
2698d5317Sjmmv
3698d5317Sjmmv /*
4*f844e94eSwiz * Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org>
5698d5317Sjmmv * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
6698d5317Sjmmv *
7698d5317Sjmmv * Permission to use, copy, modify, and distribute this software for any
8698d5317Sjmmv * purpose with or without fee is hereby granted, provided that the above
9698d5317Sjmmv * copyright notice and this permission notice appear in all copies.
10698d5317Sjmmv *
11698d5317Sjmmv * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12698d5317Sjmmv * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13698d5317Sjmmv * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14698d5317Sjmmv * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15698d5317Sjmmv * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16698d5317Sjmmv * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17698d5317Sjmmv * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18698d5317Sjmmv */
19698d5317Sjmmv
2099e242abSchristos #include <sys/types.h>
21698d5317Sjmmv #include <sys/socket.h>
22698d5317Sjmmv #include <sys/uio.h>
23698d5317Sjmmv
24698d5317Sjmmv #include <errno.h>
25698d5317Sjmmv #include <stdlib.h>
26698d5317Sjmmv #include <string.h>
27698d5317Sjmmv #include <unistd.h>
28698d5317Sjmmv
29e9a2d6faSchristos #include "compat.h"
3099e242abSchristos #include "imsg.h"
3199e242abSchristos
32*f844e94eSwiz struct imsg_fd {
33*f844e94eSwiz TAILQ_ENTRY(imsg_fd) entry;
34*f844e94eSwiz int fd;
35*f844e94eSwiz };
36*f844e94eSwiz
3799e242abSchristos int imsg_fd_overhead = 0;
38698d5317Sjmmv
39*f844e94eSwiz static int imsg_dequeue_fd(struct imsgbuf *);
40698d5317Sjmmv
41698d5317Sjmmv void
imsg_init(struct imsgbuf * imsgbuf,int fd)42*f844e94eSwiz imsg_init(struct imsgbuf *imsgbuf, int fd)
43698d5317Sjmmv {
44*f844e94eSwiz msgbuf_init(&imsgbuf->w);
45*f844e94eSwiz memset(&imsgbuf->r, 0, sizeof(imsgbuf->r));
46*f844e94eSwiz imsgbuf->fd = fd;
47*f844e94eSwiz imsgbuf->w.fd = fd;
48*f844e94eSwiz imsgbuf->pid = getpid();
49*f844e94eSwiz TAILQ_INIT(&imsgbuf->fds);
50698d5317Sjmmv }
51698d5317Sjmmv
52698d5317Sjmmv ssize_t
imsg_read(struct imsgbuf * imsgbuf)53*f844e94eSwiz imsg_read(struct imsgbuf *imsgbuf)
54698d5317Sjmmv {
55698d5317Sjmmv struct msghdr msg;
56698d5317Sjmmv struct cmsghdr *cmsg;
57698d5317Sjmmv union {
58698d5317Sjmmv struct cmsghdr hdr;
5999e242abSchristos char buf[CMSG_SPACE(sizeof(int) * 1)];
60698d5317Sjmmv } cmsgbuf;
61698d5317Sjmmv struct iovec iov;
6299e242abSchristos ssize_t n = -1;
63698d5317Sjmmv int fd;
64698d5317Sjmmv struct imsg_fd *ifd;
65698d5317Sjmmv
6699e242abSchristos memset(&msg, 0, sizeof(msg));
6799e242abSchristos memset(&cmsgbuf, 0, sizeof(cmsgbuf));
68698d5317Sjmmv
69*f844e94eSwiz iov.iov_base = imsgbuf->r.buf + imsgbuf->r.wpos;
70*f844e94eSwiz iov.iov_len = sizeof(imsgbuf->r.buf) - imsgbuf->r.wpos;
71698d5317Sjmmv msg.msg_iov = &iov;
72698d5317Sjmmv msg.msg_iovlen = 1;
73698d5317Sjmmv msg.msg_control = &cmsgbuf.buf;
749692a535Sjoerg msg.msg_controllen = CMSG_SPACE(sizeof(int) * 16);
75698d5317Sjmmv
7699e242abSchristos if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL)
7799e242abSchristos return (-1);
7899e242abSchristos
7999e242abSchristos again:
80e9a2d6faSchristos if (getdtablecount() + imsg_fd_overhead +
81e9a2d6faSchristos (int)((CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))
82e9a2d6faSchristos >= getdtablesize()) {
8399e242abSchristos errno = EAGAIN;
8499e242abSchristos free(ifd);
85698d5317Sjmmv return (-1);
86698d5317Sjmmv }
8799e242abSchristos
88*f844e94eSwiz if ((n = recvmsg(imsgbuf->fd, &msg, 0)) == -1) {
89e9a2d6faSchristos if (errno == EINTR)
9099e242abSchristos goto again;
91e9a2d6faSchristos goto fail;
92698d5317Sjmmv }
93698d5317Sjmmv
94*f844e94eSwiz imsgbuf->r.wpos += n;
95698d5317Sjmmv
96698d5317Sjmmv for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
97698d5317Sjmmv cmsg = CMSG_NXTHDR(&msg, cmsg)) {
98698d5317Sjmmv if (cmsg->cmsg_level == SOL_SOCKET &&
99698d5317Sjmmv cmsg->cmsg_type == SCM_RIGHTS) {
10099e242abSchristos int i;
10199e242abSchristos int j;
10299e242abSchristos
10399e242abSchristos /*
10499e242abSchristos * We only accept one file descriptor. Due to C
10599e242abSchristos * padding rules, our control buffer might contain
10699e242abSchristos * more than one fd, and we must close them.
10799e242abSchristos */
10899e242abSchristos j = ((char *)cmsg + cmsg->cmsg_len -
10999e242abSchristos (char *)CMSG_DATA(cmsg)) / sizeof(int);
11099e242abSchristos for (i = 0; i < j; i++) {
11199e242abSchristos fd = ((int *)CMSG_DATA(cmsg))[i];
11299e242abSchristos if (ifd != NULL) {
113698d5317Sjmmv ifd->fd = fd;
114*f844e94eSwiz TAILQ_INSERT_TAIL(&imsgbuf->fds, ifd,
11599e242abSchristos entry);
11699e242abSchristos ifd = NULL;
11799e242abSchristos } else
11899e242abSchristos close(fd);
11999e242abSchristos }
120698d5317Sjmmv }
121698d5317Sjmmv /* we do not handle other ctl data level */
122698d5317Sjmmv }
123698d5317Sjmmv
12499e242abSchristos fail:
12599e242abSchristos free(ifd);
126698d5317Sjmmv return (n);
127698d5317Sjmmv }
128698d5317Sjmmv
129698d5317Sjmmv ssize_t
imsg_get(struct imsgbuf * imsgbuf,struct imsg * imsg)130*f844e94eSwiz imsg_get(struct imsgbuf *imsgbuf, struct imsg *imsg)
131698d5317Sjmmv {
132*f844e94eSwiz struct imsg m;
133698d5317Sjmmv size_t av, left, datalen;
134698d5317Sjmmv
135*f844e94eSwiz av = imsgbuf->r.wpos;
136698d5317Sjmmv
137698d5317Sjmmv if (IMSG_HEADER_SIZE > av)
138698d5317Sjmmv return (0);
139698d5317Sjmmv
140*f844e94eSwiz memcpy(&m.hdr, imsgbuf->r.buf, sizeof(m.hdr));
141*f844e94eSwiz if (m.hdr.len < IMSG_HEADER_SIZE ||
142*f844e94eSwiz m.hdr.len > MAX_IMSGSIZE) {
143698d5317Sjmmv errno = ERANGE;
144698d5317Sjmmv return (-1);
145698d5317Sjmmv }
146*f844e94eSwiz if (m.hdr.len > av)
147698d5317Sjmmv return (0);
148*f844e94eSwiz
149*f844e94eSwiz m.fd = -1;
150*f844e94eSwiz m.buf = NULL;
151*f844e94eSwiz m.data = NULL;
152*f844e94eSwiz
153*f844e94eSwiz datalen = m.hdr.len - IMSG_HEADER_SIZE;
154*f844e94eSwiz imsgbuf->r.rptr = imsgbuf->r.buf + IMSG_HEADER_SIZE;
155*f844e94eSwiz if (datalen != 0) {
156*f844e94eSwiz if ((m.buf = ibuf_open(datalen)) == NULL)
157698d5317Sjmmv return (-1);
158*f844e94eSwiz if (ibuf_add(m.buf, imsgbuf->r.rptr, datalen) == -1) {
159*f844e94eSwiz /* this should never fail */
160*f844e94eSwiz ibuf_free(m.buf);
161*f844e94eSwiz return (-1);
162*f844e94eSwiz }
163*f844e94eSwiz m.data = ibuf_data(m.buf);
164*f844e94eSwiz }
165698d5317Sjmmv
166*f844e94eSwiz if (m.hdr.flags & IMSGF_HASFD)
167*f844e94eSwiz m.fd = imsg_dequeue_fd(imsgbuf);
168698d5317Sjmmv
169*f844e94eSwiz if (m.hdr.len < av) {
170*f844e94eSwiz left = av - m.hdr.len;
171*f844e94eSwiz memmove(&imsgbuf->r.buf, imsgbuf->r.buf + m.hdr.len, left);
172*f844e94eSwiz imsgbuf->r.wpos = left;
173698d5317Sjmmv } else
174*f844e94eSwiz imsgbuf->r.wpos = 0;
175698d5317Sjmmv
176*f844e94eSwiz *imsg = m;
177698d5317Sjmmv return (datalen + IMSG_HEADER_SIZE);
178698d5317Sjmmv }
179698d5317Sjmmv
180698d5317Sjmmv int
imsg_get_ibuf(struct imsg * imsg,struct ibuf * ibuf)181*f844e94eSwiz imsg_get_ibuf(struct imsg *imsg, struct ibuf *ibuf)
182*f844e94eSwiz {
183*f844e94eSwiz if (imsg->buf == NULL) {
184*f844e94eSwiz errno = EBADMSG;
185*f844e94eSwiz return (-1);
186*f844e94eSwiz }
187*f844e94eSwiz return ibuf_get_ibuf(imsg->buf, ibuf_size(imsg->buf), ibuf);
188*f844e94eSwiz }
189*f844e94eSwiz
190*f844e94eSwiz int
imsg_get_data(struct imsg * imsg,void * data,size_t len)191*f844e94eSwiz imsg_get_data(struct imsg *imsg, void *data, size_t len)
192*f844e94eSwiz {
193*f844e94eSwiz if (len == 0) {
194*f844e94eSwiz errno = EINVAL;
195*f844e94eSwiz return (-1);
196*f844e94eSwiz }
197*f844e94eSwiz if (imsg->buf == NULL || ibuf_size(imsg->buf) != len) {
198*f844e94eSwiz errno = EBADMSG;
199*f844e94eSwiz return (-1);
200*f844e94eSwiz }
201*f844e94eSwiz return ibuf_get(imsg->buf, data, len);
202*f844e94eSwiz }
203*f844e94eSwiz
204*f844e94eSwiz int
imsg_get_fd(struct imsg * imsg)205*f844e94eSwiz imsg_get_fd(struct imsg *imsg)
206*f844e94eSwiz {
207*f844e94eSwiz int fd = imsg->fd;
208*f844e94eSwiz
209*f844e94eSwiz imsg->fd = -1;
210*f844e94eSwiz return fd;
211*f844e94eSwiz }
212*f844e94eSwiz
213*f844e94eSwiz uint32_t
imsg_get_id(struct imsg * imsg)214*f844e94eSwiz imsg_get_id(struct imsg *imsg)
215*f844e94eSwiz {
216*f844e94eSwiz return (imsg->hdr.peerid);
217*f844e94eSwiz }
218*f844e94eSwiz
219*f844e94eSwiz size_t
imsg_get_len(struct imsg * imsg)220*f844e94eSwiz imsg_get_len(struct imsg *imsg)
221*f844e94eSwiz {
222*f844e94eSwiz if (imsg->buf == NULL)
223*f844e94eSwiz return 0;
224*f844e94eSwiz return ibuf_size(imsg->buf);
225*f844e94eSwiz }
226*f844e94eSwiz
227*f844e94eSwiz pid_t
imsg_get_pid(struct imsg * imsg)228*f844e94eSwiz imsg_get_pid(struct imsg *imsg)
229*f844e94eSwiz {
230*f844e94eSwiz return (imsg->hdr.pid);
231*f844e94eSwiz }
232*f844e94eSwiz
233*f844e94eSwiz uint32_t
imsg_get_type(struct imsg * imsg)234*f844e94eSwiz imsg_get_type(struct imsg *imsg)
235*f844e94eSwiz {
236*f844e94eSwiz return (imsg->hdr.type);
237*f844e94eSwiz }
238*f844e94eSwiz
239*f844e94eSwiz int
imsg_compose(struct imsgbuf * imsgbuf,uint32_t type,uint32_t id,pid_t pid,int fd,const void * data,size_t datalen)240*f844e94eSwiz imsg_compose(struct imsgbuf *imsgbuf, uint32_t type, uint32_t id, pid_t pid,
241*f844e94eSwiz int fd, const void *data, size_t datalen)
242698d5317Sjmmv {
243698d5317Sjmmv struct ibuf *wbuf;
244698d5317Sjmmv
245*f844e94eSwiz if ((wbuf = imsg_create(imsgbuf, type, id, pid, datalen)) == NULL)
246698d5317Sjmmv return (-1);
247698d5317Sjmmv
248698d5317Sjmmv if (imsg_add(wbuf, data, datalen) == -1)
249698d5317Sjmmv return (-1);
250698d5317Sjmmv
251*f844e94eSwiz ibuf_fd_set(wbuf, fd);
252*f844e94eSwiz imsg_close(imsgbuf, wbuf);
253698d5317Sjmmv
254698d5317Sjmmv return (1);
255698d5317Sjmmv }
256698d5317Sjmmv
257698d5317Sjmmv int
imsg_composev(struct imsgbuf * imsgbuf,uint32_t type,uint32_t id,pid_t pid,int fd,const struct iovec * iov,int iovcnt)258*f844e94eSwiz imsg_composev(struct imsgbuf *imsgbuf, uint32_t type, uint32_t id, pid_t pid,
259e9a2d6faSchristos int fd, const struct iovec *iov, int iovcnt)
260698d5317Sjmmv {
261698d5317Sjmmv struct ibuf *wbuf;
262*f844e94eSwiz int i;
263*f844e94eSwiz size_t datalen = 0;
264698d5317Sjmmv
265698d5317Sjmmv for (i = 0; i < iovcnt; i++)
266698d5317Sjmmv datalen += iov[i].iov_len;
267698d5317Sjmmv
268*f844e94eSwiz if ((wbuf = imsg_create(imsgbuf, type, id, pid, datalen)) == NULL)
269698d5317Sjmmv return (-1);
270698d5317Sjmmv
271698d5317Sjmmv for (i = 0; i < iovcnt; i++)
272698d5317Sjmmv if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1)
273698d5317Sjmmv return (-1);
274698d5317Sjmmv
275*f844e94eSwiz ibuf_fd_set(wbuf, fd);
276*f844e94eSwiz imsg_close(imsgbuf, wbuf);
277698d5317Sjmmv
278698d5317Sjmmv return (1);
279698d5317Sjmmv }
280698d5317Sjmmv
281*f844e94eSwiz /*
282*f844e94eSwiz * Enqueue imsg with payload from ibuf buf. fd passing is not possible
283*f844e94eSwiz * with this function.
284*f844e94eSwiz */
285*f844e94eSwiz int
imsg_compose_ibuf(struct imsgbuf * imsgbuf,uint32_t type,uint32_t id,pid_t pid,struct ibuf * buf)286*f844e94eSwiz imsg_compose_ibuf(struct imsgbuf *imsgbuf, uint32_t type, uint32_t id,
287*f844e94eSwiz pid_t pid, struct ibuf *buf)
288*f844e94eSwiz {
289*f844e94eSwiz struct ibuf *hdrbuf = NULL;
290*f844e94eSwiz struct imsg_hdr hdr;
291*f844e94eSwiz int save_errno;
292*f844e94eSwiz
293*f844e94eSwiz if (ibuf_size(buf) + IMSG_HEADER_SIZE > MAX_IMSGSIZE) {
294*f844e94eSwiz errno = ERANGE;
295*f844e94eSwiz goto fail;
296*f844e94eSwiz }
297*f844e94eSwiz
298*f844e94eSwiz hdr.type = type;
299*f844e94eSwiz hdr.len = ibuf_size(buf) + IMSG_HEADER_SIZE;
300*f844e94eSwiz hdr.flags = 0;
301*f844e94eSwiz hdr.peerid = id;
302*f844e94eSwiz if ((hdr.pid = pid) == 0)
303*f844e94eSwiz hdr.pid = imsgbuf->pid;
304*f844e94eSwiz
305*f844e94eSwiz if ((hdrbuf = ibuf_open(IMSG_HEADER_SIZE)) == NULL)
306*f844e94eSwiz goto fail;
307*f844e94eSwiz if (imsg_add(hdrbuf, &hdr, sizeof(hdr)) == -1)
308*f844e94eSwiz goto fail;
309*f844e94eSwiz
310*f844e94eSwiz ibuf_close(&imsgbuf->w, hdrbuf);
311*f844e94eSwiz ibuf_close(&imsgbuf->w, buf);
312*f844e94eSwiz return (1);
313*f844e94eSwiz
314*f844e94eSwiz fail:
315*f844e94eSwiz save_errno = errno;
316*f844e94eSwiz ibuf_free(buf);
317*f844e94eSwiz ibuf_free(hdrbuf);
318*f844e94eSwiz errno = save_errno;
319*f844e94eSwiz return (-1);
320*f844e94eSwiz }
321*f844e94eSwiz
322*f844e94eSwiz /*
323*f844e94eSwiz * Forward imsg to another channel. Any attached fd is closed.
324*f844e94eSwiz */
325*f844e94eSwiz int
imsg_forward(struct imsgbuf * imsgbuf,struct imsg * msg)326*f844e94eSwiz imsg_forward(struct imsgbuf *imsgbuf, struct imsg *msg)
327*f844e94eSwiz {
328*f844e94eSwiz struct ibuf *wbuf;
329*f844e94eSwiz size_t len = 0;
330*f844e94eSwiz
331*f844e94eSwiz if (msg->fd != -1) {
332*f844e94eSwiz close(msg->fd);
333*f844e94eSwiz msg->fd = -1;
334*f844e94eSwiz }
335*f844e94eSwiz
336*f844e94eSwiz if (msg->buf != NULL) {
337*f844e94eSwiz ibuf_rewind(msg->buf);
338*f844e94eSwiz len = ibuf_size(msg->buf);
339*f844e94eSwiz }
340*f844e94eSwiz
341*f844e94eSwiz if ((wbuf = imsg_create(imsgbuf, msg->hdr.type, msg->hdr.peerid,
342*f844e94eSwiz msg->hdr.pid, len)) == NULL)
343*f844e94eSwiz return (-1);
344*f844e94eSwiz
345*f844e94eSwiz if (msg->buf != NULL) {
346*f844e94eSwiz if (ibuf_add_buf(wbuf, msg->buf) == -1) {
347*f844e94eSwiz ibuf_free(wbuf);
348*f844e94eSwiz return (-1);
349*f844e94eSwiz }
350*f844e94eSwiz }
351*f844e94eSwiz
352*f844e94eSwiz imsg_close(imsgbuf, wbuf);
353*f844e94eSwiz return (1);
354*f844e94eSwiz }
355*f844e94eSwiz
356698d5317Sjmmv struct ibuf *
imsg_create(struct imsgbuf * imsgbuf,uint32_t type,uint32_t id,pid_t pid,size_t datalen)357*f844e94eSwiz imsg_create(struct imsgbuf *imsgbuf, uint32_t type, uint32_t id, pid_t pid,
358*f844e94eSwiz size_t datalen)
359698d5317Sjmmv {
360698d5317Sjmmv struct ibuf *wbuf;
361698d5317Sjmmv struct imsg_hdr hdr;
362698d5317Sjmmv
363698d5317Sjmmv datalen += IMSG_HEADER_SIZE;
364698d5317Sjmmv if (datalen > MAX_IMSGSIZE) {
365698d5317Sjmmv errno = ERANGE;
366698d5317Sjmmv return (NULL);
367698d5317Sjmmv }
368698d5317Sjmmv
369698d5317Sjmmv hdr.type = type;
370698d5317Sjmmv hdr.flags = 0;
371*f844e94eSwiz hdr.peerid = id;
372698d5317Sjmmv if ((hdr.pid = pid) == 0)
373*f844e94eSwiz hdr.pid = imsgbuf->pid;
374698d5317Sjmmv if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
375698d5317Sjmmv return (NULL);
376698d5317Sjmmv }
377698d5317Sjmmv if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
378698d5317Sjmmv return (NULL);
379698d5317Sjmmv
380698d5317Sjmmv return (wbuf);
381698d5317Sjmmv }
382698d5317Sjmmv
383698d5317Sjmmv int
imsg_add(struct ibuf * msg,const void * data,size_t datalen)384*f844e94eSwiz imsg_add(struct ibuf *msg, const void *data, size_t datalen)
385698d5317Sjmmv {
386698d5317Sjmmv if (datalen)
387698d5317Sjmmv if (ibuf_add(msg, data, datalen) == -1) {
388698d5317Sjmmv ibuf_free(msg);
389698d5317Sjmmv return (-1);
390698d5317Sjmmv }
391698d5317Sjmmv return (datalen);
392698d5317Sjmmv }
393698d5317Sjmmv
394698d5317Sjmmv void
imsg_close(struct imsgbuf * imsgbuf,struct ibuf * msg)395*f844e94eSwiz imsg_close(struct imsgbuf *imsgbuf, struct ibuf *msg)
396698d5317Sjmmv {
397698d5317Sjmmv struct imsg_hdr *hdr;
398698d5317Sjmmv
399698d5317Sjmmv hdr = (struct imsg_hdr *)msg->buf;
400698d5317Sjmmv
401698d5317Sjmmv hdr->flags &= ~IMSGF_HASFD;
402*f844e94eSwiz if (ibuf_fd_avail(msg))
403698d5317Sjmmv hdr->flags |= IMSGF_HASFD;
404*f844e94eSwiz hdr->len = ibuf_size(msg);
405698d5317Sjmmv
406*f844e94eSwiz ibuf_close(&imsgbuf->w, msg);
407698d5317Sjmmv }
408698d5317Sjmmv
409698d5317Sjmmv void
imsg_free(struct imsg * imsg)410698d5317Sjmmv imsg_free(struct imsg *imsg)
411698d5317Sjmmv {
412*f844e94eSwiz ibuf_free(imsg->buf);
413698d5317Sjmmv }
414698d5317Sjmmv
415c7e17de0Schristos static int
imsg_dequeue_fd(struct imsgbuf * imsgbuf)416*f844e94eSwiz imsg_dequeue_fd(struct imsgbuf *imsgbuf)
417698d5317Sjmmv {
418698d5317Sjmmv int fd;
419698d5317Sjmmv struct imsg_fd *ifd;
420698d5317Sjmmv
421*f844e94eSwiz if ((ifd = TAILQ_FIRST(&imsgbuf->fds)) == NULL)
422698d5317Sjmmv return (-1);
423698d5317Sjmmv
424698d5317Sjmmv fd = ifd->fd;
425*f844e94eSwiz TAILQ_REMOVE(&imsgbuf->fds, ifd, entry);
426698d5317Sjmmv free(ifd);
427698d5317Sjmmv
428698d5317Sjmmv return (fd);
429698d5317Sjmmv }
430698d5317Sjmmv
431698d5317Sjmmv int
imsg_flush(struct imsgbuf * imsgbuf)432*f844e94eSwiz imsg_flush(struct imsgbuf *imsgbuf)
433698d5317Sjmmv {
434*f844e94eSwiz while (imsgbuf->w.queued)
435*f844e94eSwiz if (msgbuf_write(&imsgbuf->w) <= 0)
436698d5317Sjmmv return (-1);
437698d5317Sjmmv return (0);
438698d5317Sjmmv }
439698d5317Sjmmv
440698d5317Sjmmv void
imsg_clear(struct imsgbuf * imsgbuf)441*f844e94eSwiz imsg_clear(struct imsgbuf *imsgbuf)
442698d5317Sjmmv {
443698d5317Sjmmv int fd;
444698d5317Sjmmv
445*f844e94eSwiz msgbuf_clear(&imsgbuf->w);
446*f844e94eSwiz while ((fd = imsg_dequeue_fd(imsgbuf)) != -1)
447698d5317Sjmmv close(fd);
448698d5317Sjmmv }
449