2 /* $OpenBSD: imsg.c,v 1.3 2010/05/26 13:56:07 nicm Exp $ */
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/param.h>
21 #include <sys/socket.h>
32 int imsg_get_fd(struct imsgbuf
*);
35 imsg_init(struct imsgbuf
*ibuf
, int fd
)
37 msgbuf_init(&ibuf
->w
);
38 bzero(&ibuf
->r
, sizeof(ibuf
->r
));
42 TAILQ_INIT(&ibuf
->fds
);
46 imsg_read(struct imsgbuf
*ibuf
)
52 char buf
[CMSG_SPACE(sizeof(int) * 16)];
59 bzero(&msg
, sizeof(msg
));
61 iov
.iov_base
= ibuf
->r
.buf
+ ibuf
->r
.wpos
;
62 iov
.iov_len
= sizeof(ibuf
->r
.buf
) - ibuf
->r
.wpos
;
65 msg
.msg_control
= &cmsgbuf
.buf
;
66 msg
.msg_controllen
= CMSG_SPACE(sizeof(int) * 16);
68 if ((n
= recvmsg(ibuf
->fd
, &msg
, 0)) == -1) {
69 if (errno
!= EINTR
&& errno
!= EAGAIN
) {
77 for (cmsg
= CMSG_FIRSTHDR(&msg
); cmsg
!= NULL
;
78 cmsg
= CMSG_NXTHDR(&msg
, cmsg
)) {
79 if (cmsg
->cmsg_level
== SOL_SOCKET
&&
80 cmsg
->cmsg_type
== SCM_RIGHTS
) {
81 fd
= (*(int *)CMSG_DATA(cmsg
));
82 if ((ifd
= calloc(1, sizeof(struct imsg_fd
))) == NULL
) {
87 TAILQ_INSERT_TAIL(&ibuf
->fds
, ifd
, entry
);
89 /* we do not handle other ctl data level */
96 imsg_get(struct imsgbuf
*ibuf
, struct imsg
*imsg
)
98 size_t av
, left
, datalen
;
102 if (IMSG_HEADER_SIZE
> av
)
105 memcpy(&imsg
->hdr
, ibuf
->r
.buf
, sizeof(imsg
->hdr
));
106 if (imsg
->hdr
.len
< IMSG_HEADER_SIZE
||
107 imsg
->hdr
.len
> MAX_IMSGSIZE
) {
111 if (imsg
->hdr
.len
> av
)
113 datalen
= imsg
->hdr
.len
- IMSG_HEADER_SIZE
;
114 ibuf
->r
.rptr
= ibuf
->r
.buf
+ IMSG_HEADER_SIZE
;
115 if ((imsg
->data
= malloc(datalen
)) == NULL
&& datalen
!= 0)
118 if (imsg
->hdr
.flags
& IMSGF_HASFD
)
119 imsg
->fd
= imsg_get_fd(ibuf
);
123 memcpy(imsg
->data
, ibuf
->r
.rptr
, datalen
);
125 if (imsg
->hdr
.len
< av
) {
126 left
= av
- imsg
->hdr
.len
;
127 memmove(&ibuf
->r
.buf
, ibuf
->r
.buf
+ imsg
->hdr
.len
, left
);
132 return (datalen
+ IMSG_HEADER_SIZE
);
136 imsg_compose(struct imsgbuf
*ibuf
, u_int32_t type
, u_int32_t peerid
,
137 pid_t pid
, int fd
, void *data
, u_int16_t datalen
)
141 if ((wbuf
= imsg_create(ibuf
, type
, peerid
, pid
, datalen
)) == NULL
)
144 if (imsg_add(wbuf
, data
, datalen
) == -1)
149 imsg_close(ibuf
, wbuf
);
155 imsg_composev(struct imsgbuf
*ibuf
, u_int32_t type
, u_int32_t peerid
,
156 pid_t pid
, int fd
, const struct iovec
*iov
, int iovcnt
)
161 for (i
= 0; i
< iovcnt
; i
++)
162 datalen
+= iov
[i
].iov_len
;
164 if ((wbuf
= imsg_create(ibuf
, type
, peerid
, pid
, datalen
)) == NULL
)
167 for (i
= 0; i
< iovcnt
; i
++)
168 if (imsg_add(wbuf
, iov
[i
].iov_base
, iov
[i
].iov_len
) == -1)
173 imsg_close(ibuf
, wbuf
);
180 imsg_create(struct imsgbuf
*ibuf
, u_int32_t type
, u_int32_t peerid
,
181 pid_t pid
, u_int16_t datalen
)
186 datalen
+= IMSG_HEADER_SIZE
;
187 if (datalen
> MAX_IMSGSIZE
) {
195 if ((hdr
.pid
= pid
) == 0)
197 if ((wbuf
= ibuf_dynamic(datalen
, MAX_IMSGSIZE
)) == NULL
) {
200 if (imsg_add(wbuf
, &hdr
, sizeof(hdr
)) == -1)
207 imsg_add(struct ibuf
*msg
, void *data
, u_int16_t datalen
)
210 if (ibuf_add(msg
, data
, datalen
) == -1) {
218 imsg_close(struct imsgbuf
*ibuf
, struct ibuf
*msg
)
220 struct imsg_hdr
*hdr
;
222 hdr
= (struct imsg_hdr
*)msg
->buf
;
224 hdr
->flags
&= ~IMSGF_HASFD
;
226 hdr
->flags
|= IMSGF_HASFD
;
228 hdr
->len
= (u_int16_t
)msg
->wpos
;
230 ibuf_close(&ibuf
->w
, msg
);
234 imsg_free(struct imsg
*imsg
)
240 imsg_get_fd(struct imsgbuf
*ibuf
)
245 if ((ifd
= TAILQ_FIRST(&ibuf
->fds
)) == NULL
)
249 TAILQ_REMOVE(&ibuf
->fds
, ifd
, entry
);
256 imsg_flush(struct imsgbuf
*ibuf
)
258 while (ibuf
->w
.queued
)
259 if (msgbuf_write(&ibuf
->w
) < 0)
265 imsg_clear(struct imsgbuf
*ibuf
)
269 msgbuf_clear(&ibuf
->w
);
270 while ((fd
= imsg_get_fd(ibuf
)) != -1)