xref: /freebsd/lib/libopenbsd/imsg_init.3 (revision fa9896e082a1046ff4fbc75fcba4d18d1f2efc19)
170623c80SCraig Rodrigues.\" $OpenBSD: imsg_init.3,v 1.13 2015/07/11 16:23:59 deraadt Exp $
270623c80SCraig Rodrigues.\"
370623c80SCraig Rodrigues.\" Copyright (c) 2010 Nicholas Marriott <nicm@openbsd.org>
470623c80SCraig Rodrigues.\"
570623c80SCraig Rodrigues.\" Permission to use, copy, modify, and distribute this software for any
670623c80SCraig Rodrigues.\" purpose with or without fee is hereby granted, provided that the above
770623c80SCraig Rodrigues.\" copyright notice and this permission notice appear in all copies.
870623c80SCraig Rodrigues.\"
970623c80SCraig Rodrigues.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1070623c80SCraig Rodrigues.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1170623c80SCraig Rodrigues.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1270623c80SCraig Rodrigues.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1370623c80SCraig Rodrigues.\" WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
1470623c80SCraig Rodrigues.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
1570623c80SCraig Rodrigues.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1670623c80SCraig Rodrigues.\"
1770623c80SCraig Rodrigues.Dd $Mdocdate: July 11 2015 $
1870623c80SCraig Rodrigues.Dt IMSG_INIT 3
1970623c80SCraig Rodrigues.Os
2070623c80SCraig Rodrigues.Sh NAME
2170623c80SCraig Rodrigues.Nm imsg_init ,
2270623c80SCraig Rodrigues.Nm imsg_read ,
2370623c80SCraig Rodrigues.Nm imsg_get ,
2470623c80SCraig Rodrigues.Nm imsg_compose ,
2570623c80SCraig Rodrigues.Nm imsg_composev ,
2670623c80SCraig Rodrigues.Nm imsg_create ,
2770623c80SCraig Rodrigues.Nm imsg_add ,
2870623c80SCraig Rodrigues.Nm imsg_close ,
2970623c80SCraig Rodrigues.Nm imsg_free ,
3070623c80SCraig Rodrigues.Nm imsg_flush ,
3170623c80SCraig Rodrigues.Nm imsg_clear ,
3270623c80SCraig Rodrigues.Nm ibuf_open ,
3370623c80SCraig Rodrigues.Nm ibuf_dynamic ,
3470623c80SCraig Rodrigues.Nm ibuf_add ,
3570623c80SCraig Rodrigues.Nm ibuf_reserve ,
3670623c80SCraig Rodrigues.Nm ibuf_seek ,
3770623c80SCraig Rodrigues.Nm ibuf_size ,
3870623c80SCraig Rodrigues.Nm ibuf_left ,
3970623c80SCraig Rodrigues.Nm ibuf_close ,
4070623c80SCraig Rodrigues.Nm ibuf_write ,
4170623c80SCraig Rodrigues.Nm ibuf_free ,
4270623c80SCraig Rodrigues.Nm msgbuf_init ,
4370623c80SCraig Rodrigues.Nm msgbuf_clear ,
4470623c80SCraig Rodrigues.Nm msgbuf_write ,
4570623c80SCraig Rodrigues.Nm msgbuf_drain
4670623c80SCraig Rodrigues.Nd IPC messaging functions
4770623c80SCraig Rodrigues.Sh SYNOPSIS
4870623c80SCraig Rodrigues.In sys/types.h
4970623c80SCraig Rodrigues.In sys/queue.h
5070623c80SCraig Rodrigues.In sys/uio.h
5170623c80SCraig Rodrigues.In imsg.h
5270623c80SCraig Rodrigues.Ft void
5370623c80SCraig Rodrigues.Fn imsg_init "struct imsgbuf *ibuf" "int fd"
5470623c80SCraig Rodrigues.Ft ssize_t
5570623c80SCraig Rodrigues.Fn imsg_read "struct imsgbuf *ibuf"
5670623c80SCraig Rodrigues.Ft ssize_t
5770623c80SCraig Rodrigues.Fn imsg_get "struct imsgbuf *ibuf" "struct imsg *imsg"
5870623c80SCraig Rodrigues.Ft int
5970623c80SCraig Rodrigues.Fn imsg_compose "struct imsgbuf *ibuf" "u_int32_t type" "uint32_t peerid" \
6070623c80SCraig Rodrigues    "pid_t pid" "int fd" "const void *data" "u_int16_t datalen"
6170623c80SCraig Rodrigues.Ft int
6270623c80SCraig Rodrigues.Fn imsg_composev "struct imsgbuf *ibuf" "u_int32_t type" "u_int32_t peerid" \
6370623c80SCraig Rodrigues    "pid_t pid" "int fd" "const struct iovec *iov" "int iovcnt"
6470623c80SCraig Rodrigues.Ft "struct ibuf *"
6570623c80SCraig Rodrigues.Fn imsg_create "struct imsgbuf *ibuf" "u_int32_t type" "u_int32_t peerid" \
6670623c80SCraig Rodrigues    "pid_t pid" "u_int16_t datalen"
6770623c80SCraig Rodrigues.Ft int
6870623c80SCraig Rodrigues.Fn imsg_add "struct ibuf *buf" "const void *data" "u_int16_t datalen"
6970623c80SCraig Rodrigues.Ft void
7070623c80SCraig Rodrigues.Fn imsg_close "struct imsgbuf *ibuf" "struct ibuf *msg"
7170623c80SCraig Rodrigues.Ft void
7270623c80SCraig Rodrigues.Fn imsg_free "struct imsg *imsg"
7370623c80SCraig Rodrigues.Ft int
7470623c80SCraig Rodrigues.Fn imsg_flush "struct imsgbuf *ibuf"
7570623c80SCraig Rodrigues.Ft void
7670623c80SCraig Rodrigues.Fn imsg_clear "struct imsgbuf *ibuf"
7770623c80SCraig Rodrigues.Ft "struct ibuf *"
7870623c80SCraig Rodrigues.Fn ibuf_open "size_t len"
7970623c80SCraig Rodrigues.Ft "struct ibuf *"
8070623c80SCraig Rodrigues.Fn ibuf_dynamic "size_t len" "size_t max"
8170623c80SCraig Rodrigues.Ft int
8270623c80SCraig Rodrigues.Fn ibuf_add "struct ibuf *buf" "const void *data" "size_t len"
8370623c80SCraig Rodrigues.Ft "void *"
8470623c80SCraig Rodrigues.Fn ibuf_reserve "struct ibuf *buf" "size_t len"
8570623c80SCraig Rodrigues.Ft "void *"
8670623c80SCraig Rodrigues.Fn ibuf_seek "struct ibuf *buf" "size_t pos" "size_t len"
8770623c80SCraig Rodrigues.Ft size_t
8870623c80SCraig Rodrigues.Fn ibuf_size "struct ibuf *buf"
8970623c80SCraig Rodrigues.Ft size_t
9070623c80SCraig Rodrigues.Fn ibuf_left "struct ibuf *buf"
9170623c80SCraig Rodrigues.Ft void
9270623c80SCraig Rodrigues.Fn ibuf_close "struct msgbuf *msgbuf" "struct ibuf *buf"
9370623c80SCraig Rodrigues.Ft int
9470623c80SCraig Rodrigues.Fn ibuf_write "struct msgbuf *msgbuf"
9570623c80SCraig Rodrigues.Ft void
9670623c80SCraig Rodrigues.Fn ibuf_free "struct ibuf *buf"
9770623c80SCraig Rodrigues.Ft void
9870623c80SCraig Rodrigues.Fn msgbuf_init "struct msgbuf *msgbuf"
9970623c80SCraig Rodrigues.Ft void
10070623c80SCraig Rodrigues.Fn msgbuf_clear "struct msgbuf *msgbuf"
10170623c80SCraig Rodrigues.Ft int
10270623c80SCraig Rodrigues.Fn msgbuf_write "struct msgbuf *msgbuf"
10370623c80SCraig Rodrigues.Ft void
10470623c80SCraig Rodrigues.Fn msgbuf_drain "struct msgbuf *msgbuf" "size_t n"
10570623c80SCraig Rodrigues.Sh DESCRIPTION
10670623c80SCraig RodriguesThe
10770623c80SCraig Rodrigues.Nm imsg
10870623c80SCraig Rodriguesfunctions provide a simple mechanism for communication between processes
10970623c80SCraig Rodriguesusing sockets.
11070623c80SCraig RodriguesEach transmitted message is guaranteed to be presented to the receiving program
11170623c80SCraig Rodrigueswhole.
11270623c80SCraig RodriguesThey are commonly used in privilege separated processes, where processes with
11370623c80SCraig Rodriguesdifferent rights are required to cooperate.
11470623c80SCraig Rodrigues.Pp
11570623c80SCraig RodriguesA program using these functions should be linked with
11670623c80SCraig Rodrigues.Em -lutil .
11770623c80SCraig Rodrigues.Pp
11870623c80SCraig RodriguesThe basic
11970623c80SCraig Rodrigues.Nm
12070623c80SCraig Rodriguesstructure is the
12170623c80SCraig Rodrigues.Em imsgbuf ,
12270623c80SCraig Rodrigueswhich wraps a file descriptor and represents one side of a channel on which
12370623c80SCraig Rodriguesmessages are sent and received:
12470623c80SCraig Rodrigues.Bd -literal -offset indent
12570623c80SCraig Rodriguesstruct imsgbuf {
12670623c80SCraig Rodrigues	TAILQ_HEAD(, imsg_fd)	fds;
12770623c80SCraig Rodrigues	struct ibuf_read	r;
12870623c80SCraig Rodrigues	struct msgbuf		w;
12970623c80SCraig Rodrigues	int			fd;
13070623c80SCraig Rodrigues	pid_t			pid;
13170623c80SCraig Rodrigues};
13270623c80SCraig Rodrigues.Ed
13370623c80SCraig Rodrigues.Pp
13470623c80SCraig Rodrigues.Fn imsg_init
13570623c80SCraig Rodriguesis a routine which initializes
13670623c80SCraig Rodrigues.Fa ibuf
13770623c80SCraig Rodriguesas one side of a channel associated with
13870623c80SCraig Rodrigues.Fa fd .
13970623c80SCraig RodriguesThe file descriptor is used to send and receive messages,
14070623c80SCraig Rodriguesbut is not closed by any of the imsg functions.
14170623c80SCraig RodriguesAn imsgbuf is initialized with the
14270623c80SCraig Rodrigues.Em w
14370623c80SCraig Rodriguesmember as the output buffer queue,
14470623c80SCraig Rodrigues.Em fd
14570623c80SCraig Rodrigueswith the file descriptor passed to
14670623c80SCraig Rodrigues.Fn imsg_init
14770623c80SCraig Rodriguesand the other members for internal use only.
14870623c80SCraig Rodrigues.Pp
14970623c80SCraig RodriguesThe
15070623c80SCraig Rodrigues.Fn imsg_clear
15170623c80SCraig Rodriguesfunction frees any data allocated as part of an imsgbuf.
15270623c80SCraig Rodrigues.Pp
15370623c80SCraig Rodrigues.Fn imsg_create ,
15470623c80SCraig Rodrigues.Fn imsg_add
15570623c80SCraig Rodriguesand
15670623c80SCraig Rodrigues.Fn imsg_close
15770623c80SCraig Rodriguesare generic construction routines for messages that are to be sent using an
15870623c80SCraig Rodriguesimsgbuf.
15970623c80SCraig Rodrigues.Pp
16070623c80SCraig Rodrigues.Fn imsg_create
16170623c80SCraig Rodriguescreates a new message with header specified by
16270623c80SCraig Rodrigues.Fa type ,
16370623c80SCraig Rodrigues.Fa peerid
16470623c80SCraig Rodriguesand
16570623c80SCraig Rodrigues.Fa pid .
16670623c80SCraig RodriguesA
16770623c80SCraig Rodrigues.Fa pid
16870623c80SCraig Rodriguesof zero uses the process ID returned by
16970623c80SCraig Rodrigues.Xr getpid 2
17070623c80SCraig Rodrigueswhen
17170623c80SCraig Rodrigues.Fa ibuf
17270623c80SCraig Rodrigueswas initialized.
17370623c80SCraig RodriguesIn addition to this common imsg header,
17470623c80SCraig Rodrigues.Fa datalen
17570623c80SCraig Rodriguesbytes of space may be reserved for attaching to this imsg.
17670623c80SCraig RodriguesThis space is populated using
17770623c80SCraig Rodrigues.Fn imsg_add .
17870623c80SCraig RodriguesAdditionally, the file descriptor
17970623c80SCraig Rodrigues.Fa fd
18070623c80SCraig Rodriguesmay be passed over the socket to the other process.
18170623c80SCraig RodriguesIf
18270623c80SCraig Rodrigues.Fa fd
18370623c80SCraig Rodriguesis given, it is closed in the sending program after the message is sent.
18470623c80SCraig RodriguesA value of \-1 indicates no file descriptor should be passed.
18570623c80SCraig Rodrigues.Fn imsg_create
18670623c80SCraig Rodriguesreturns a pointer to a new message if it succeeds, NULL otherwise.
18770623c80SCraig Rodrigues.Pp
18870623c80SCraig Rodrigues.Fn imsg_add
18970623c80SCraig Rodriguesappends to
19070623c80SCraig Rodrigues.Fa imsg
19170623c80SCraig Rodrigues.Fa len
19270623c80SCraig Rodriguesbytes of ancillary data pointed to by
19370623c80SCraig Rodrigues.Fa buf .
19470623c80SCraig RodriguesIt returns
19570623c80SCraig Rodrigues.Fa len
19670623c80SCraig Rodriguesif it succeeds, \-1 otherwise.
19770623c80SCraig Rodrigues.Pp
19870623c80SCraig Rodrigues.Fn imsg_close
19970623c80SCraig Rodriguescompletes creation of
20070623c80SCraig Rodrigues.Fa imsg
20170623c80SCraig Rodriguesby adding it to
20270623c80SCraig Rodrigues.Fa imsgbuf
20370623c80SCraig Rodriguesoutput buffer.
20470623c80SCraig Rodrigues.Pp
20570623c80SCraig Rodrigues.Fn imsg_compose
20670623c80SCraig Rodriguesis a routine which is used to quickly create and queue an imsg.
20770623c80SCraig RodriguesIt takes the same parameters as the
20870623c80SCraig Rodrigues.Fn imsg_create ,
20970623c80SCraig Rodrigues.Fn imsg_add
21070623c80SCraig Rodriguesand
21170623c80SCraig Rodrigues.Fn imsg_close
21270623c80SCraig Rodriguesroutines,
21370623c80SCraig Rodriguesexcept that only one ancillary data buffer can be provided.
21470623c80SCraig RodriguesThis routine returns 1 if it succeeds, \-1 otherwise.
21570623c80SCraig Rodrigues.Pp
21670623c80SCraig Rodrigues.Fn imsg_composev
21770623c80SCraig Rodriguesis similar to
21870623c80SCraig Rodrigues.Fn imsg_compose .
21970623c80SCraig RodriguesIt takes the same parameters, except that the ancillary data buffer is specified
22070623c80SCraig Rodriguesby
22170623c80SCraig Rodrigues.Fa iovec .
22270623c80SCraig Rodrigues.Pp
22370623c80SCraig Rodrigues.Fn imsg_flush
22470623c80SCraig Rodriguesis a function which calls
22570623c80SCraig Rodrigues.Fn msgbuf_write
22670623c80SCraig Rodriguesin a loop until all imsgs in the output buffer are sent.
22770623c80SCraig RodriguesIt returns 0 if it succeeds, \-1 otherwise.
22870623c80SCraig Rodrigues.Pp
22970623c80SCraig RodriguesThe
23070623c80SCraig Rodrigues.Fn imsg_read
23170623c80SCraig Rodriguesroutine reads pending data with
23270623c80SCraig Rodrigues.Xr recvmsg 2
23370623c80SCraig Rodriguesand queues it as individual messages on
23470623c80SCraig Rodrigues.Fa imsgbuf .
23570623c80SCraig RodriguesIt returns the number of bytes read on success, or \-1 on error.
23670623c80SCraig RodriguesA return value of \-1 from
23770623c80SCraig Rodrigues.Fn imsg_read
23870623c80SCraig Rodriguesinvalidates
23970623c80SCraig Rodrigues.Fa imsgbuf ,
24070623c80SCraig Rodriguesand renders it suitable only for passing to
24170623c80SCraig Rodrigues.Fn imsg_clear .
24270623c80SCraig Rodrigues.Pp
24370623c80SCraig Rodrigues.Fn imsg_get
24470623c80SCraig Rodriguesfills in an individual imsg pending on
24570623c80SCraig Rodrigues.Fa imsgbuf
24670623c80SCraig Rodriguesinto the structure pointed to by
24770623c80SCraig Rodrigues.Fa imsg .
24870623c80SCraig RodriguesIt returns the total size of the message, 0 if no messages are ready, or \-1
24970623c80SCraig Rodriguesfor an error.
25070623c80SCraig RodriguesReceived messages are returned as a
25170623c80SCraig Rodrigues.Em struct imsg ,
25270623c80SCraig Rodrigueswhich must be freed by
25370623c80SCraig Rodrigues.Fn imsg_free
25470623c80SCraig Rodrigueswhen no longer required.
25570623c80SCraig Rodrigues.Em struct imsg
25670623c80SCraig Rodrigueshas this form:
25770623c80SCraig Rodrigues.Bd -literal -offset indent
25870623c80SCraig Rodriguesstruct imsg {
25970623c80SCraig Rodrigues	struct imsg_hdr	 hdr;
26070623c80SCraig Rodrigues	int		 fd;
26170623c80SCraig Rodrigues	void		*data;
26270623c80SCraig Rodrigues};
26370623c80SCraig Rodrigues
26470623c80SCraig Rodriguesstruct imsg_hdr {
26570623c80SCraig Rodrigues	u_int32_t	 type;
26670623c80SCraig Rodrigues	u_int16_t	 len;
26770623c80SCraig Rodrigues	u_int16_t	 flags;
26870623c80SCraig Rodrigues	u_int32_t	 peerid;
26970623c80SCraig Rodrigues	u_int32_t	 pid;
27070623c80SCraig Rodrigues};
27170623c80SCraig Rodrigues.Ed
27270623c80SCraig Rodrigues.Pp
27370623c80SCraig RodriguesThe header members are:
27470623c80SCraig Rodrigues.Bl -tag -width Ds -offset indent
27570623c80SCraig Rodrigues.It type
27670623c80SCraig RodriguesA integer identifier, typically used to express the meaning of the message.
27770623c80SCraig Rodrigues.It len
27870623c80SCraig RodriguesThe total length of the imsg, including the header and any ancillary data
27970623c80SCraig Rodriguestransmitted with the message (pointed to by the
28070623c80SCraig Rodrigues.Em data
28170623c80SCraig Rodriguesmember of the message itself).
28270623c80SCraig Rodrigues.It flags
28370623c80SCraig RodriguesFlags used internally by the imsg functions: should not be used by application
28470623c80SCraig Rodriguesprograms.
28570623c80SCraig Rodrigues.It peerid, pid
28670623c80SCraig Rodrigues32-bit values specified on message creation and free for any use by the
28770623c80SCraig Rodriguescaller, normally used to identify the message sender.
28870623c80SCraig Rodrigues.El
28970623c80SCraig Rodrigues.Pp
29070623c80SCraig RodriguesIn addition,
29170623c80SCraig Rodrigues.Em struct imsg
29270623c80SCraig Rodrigueshas the following:
29370623c80SCraig Rodrigues.Bl -tag -width Ds -offset indent
29470623c80SCraig Rodrigues.It fd
29570623c80SCraig RodriguesThe file descriptor specified when the message was created and passed using the
29670623c80SCraig Rodriguessocket control message API, or \-1 if no file descriptor was sent.
29770623c80SCraig Rodrigues.It data
29870623c80SCraig RodriguesA pointer to the ancillary data transmitted with the imsg.
29970623c80SCraig Rodrigues.El
30070623c80SCraig Rodrigues.Pp
30170623c80SCraig RodriguesThe IMSG_HEADER_SIZE define is the size of the imsg message header, which
30270623c80SCraig Rodriguesmay be subtracted from the
30370623c80SCraig Rodrigues.Fa len
30470623c80SCraig Rodriguesmember of
30570623c80SCraig Rodrigues.Em struct imsg_hdr
30670623c80SCraig Rodriguesto obtain the length of any additional data passed with the message.
30770623c80SCraig Rodrigues.Pp
30870623c80SCraig RodriguesMAX_IMSGSIZE is defined as the maximum size of a single imsg, currently
30970623c80SCraig Rodrigues16384 bytes.
31070623c80SCraig Rodrigues.Sh BUFFERS
31170623c80SCraig RodriguesThe imsg API defines functions to manipulate buffers, used internally and during
31270623c80SCraig Rodriguesconstruction of imsgs with
31370623c80SCraig Rodrigues.Fn imsg_create .
31470623c80SCraig RodriguesA
31570623c80SCraig Rodrigues.Em struct ibuf
31670623c80SCraig Rodriguesis a single buffer and a
31770623c80SCraig Rodrigues.Em struct msgbuf
31870623c80SCraig Rodriguesa queue of output buffers for transmission:
31970623c80SCraig Rodrigues.Bd -literal -offset indent
32070623c80SCraig Rodriguesstruct ibuf {
32170623c80SCraig Rodrigues	TAILQ_ENTRY(ibuf)	 entry;
32270623c80SCraig Rodrigues	u_char			*buf;
32370623c80SCraig Rodrigues	size_t			 size;
32470623c80SCraig Rodrigues	size_t			 max;
32570623c80SCraig Rodrigues	size_t			 wpos;
32670623c80SCraig Rodrigues	size_t			 rpos;
32770623c80SCraig Rodrigues	int			 fd;
32870623c80SCraig Rodrigues};
32970623c80SCraig Rodrigues
33070623c80SCraig Rodriguesstruct msgbuf {
33170623c80SCraig Rodrigues	TAILQ_HEAD(, ibuf)	 bufs;
33270623c80SCraig Rodrigues	u_int32_t		 queued;
33370623c80SCraig Rodrigues	int			 fd;
33470623c80SCraig Rodrigues};
33570623c80SCraig Rodrigues.Ed
33670623c80SCraig Rodrigues.Pp
33770623c80SCraig RodriguesThe
33870623c80SCraig Rodrigues.Fn ibuf_open
33970623c80SCraig Rodriguesfunction allocates a fixed-length buffer.
34070623c80SCraig RodriguesThe buffer may not be resized and may contain a maximum of
34170623c80SCraig Rodrigues.Fa len
34270623c80SCraig Rodriguesbytes.
34370623c80SCraig RodriguesOn success
34470623c80SCraig Rodrigues.Fn ibuf_open
34570623c80SCraig Rodriguesreturns a pointer to the buffer; on failure it returns NULL.
34670623c80SCraig Rodrigues.Pp
34770623c80SCraig Rodrigues.Fn ibuf_dynamic
348*837fe325SEitan Adlerallocates a resizable buffer of initial length
34970623c80SCraig Rodrigues.Fa len
35070623c80SCraig Rodriguesand maximum size
35170623c80SCraig Rodrigues.Fa max .
35270623c80SCraig RodriguesBuffers allocated with
35370623c80SCraig Rodrigues.Fn ibuf_dynamic
35470623c80SCraig Rodriguesare automatically grown if necessary when data is added.
35570623c80SCraig Rodrigues.Pp
35670623c80SCraig Rodrigues.Fn ibuf_add
35770623c80SCraig Rodriguesis a routine which appends a block of data to
35870623c80SCraig Rodrigues.Fa buf .
35970623c80SCraig Rodrigues0 is returned on success and \-1 on failure.
36070623c80SCraig Rodrigues.Pp
36170623c80SCraig Rodrigues.Fn ibuf_reserve
36270623c80SCraig Rodriguesis used to reserve
36370623c80SCraig Rodrigues.Fa len
36470623c80SCraig Rodriguesbytes in
36570623c80SCraig Rodrigues.Fa buf .
36670623c80SCraig RodriguesA pointer to the start of the reserved space is returned, or NULL on error.
36770623c80SCraig Rodrigues.Pp
36870623c80SCraig Rodrigues.Fn ibuf_seek
36970623c80SCraig Rodriguesis a function which returns a pointer to the part of the buffer at offset
37070623c80SCraig Rodrigues.Fa pos
37170623c80SCraig Rodriguesand of extent
37270623c80SCraig Rodrigues.Fa len .
37370623c80SCraig RodriguesNULL is returned if the requested range is outside the part of the buffer
37470623c80SCraig Rodriguesin use.
37570623c80SCraig Rodrigues.Pp
37670623c80SCraig Rodrigues.Fn ibuf_size
37770623c80SCraig Rodriguesand
37870623c80SCraig Rodrigues.Fn ibuf_left
37970623c80SCraig Rodriguesare functions which return the total bytes used and available in
38070623c80SCraig Rodrigues.Fa buf
38170623c80SCraig Rodriguesrespectively.
38270623c80SCraig Rodrigues.Pp
38370623c80SCraig Rodrigues.Fn ibuf_close
38470623c80SCraig Rodriguesappends
38570623c80SCraig Rodrigues.Fa buf
38670623c80SCraig Rodriguesto
38770623c80SCraig Rodrigues.Fa msgbuf
38870623c80SCraig Rodriguesready to be sent.
38970623c80SCraig Rodrigues.Pp
39070623c80SCraig RodriguesThe
39170623c80SCraig Rodrigues.Fn ibuf_write
39270623c80SCraig Rodriguesroutine transmits as many pending buffers as possible from
39370623c80SCraig Rodrigues.Fn msgbuf
39470623c80SCraig Rodriguesusing
39570623c80SCraig Rodrigues.Xr writev 2 .
39670623c80SCraig RodriguesIt returns 1 if it succeeds, \-1 on error and 0 when no buffers were
39770623c80SCraig Rodriguespending or an EOF condition on the socket is detected.
39870623c80SCraig RodriguesTemporary resource shortages are returned with errno
39970623c80SCraig Rodrigues.Er EAGAIN
40070623c80SCraig Rodriguesand require the application to retry again in the future.
40170623c80SCraig Rodrigues.Pp
40270623c80SCraig Rodrigues.Fn ibuf_free
40370623c80SCraig Rodriguesfrees
40470623c80SCraig Rodrigues.Fa buf
40570623c80SCraig Rodriguesand any associated storage.
40670623c80SCraig Rodrigues.Pp
40770623c80SCraig RodriguesThe
40870623c80SCraig Rodrigues.Fn msgbuf_init
40970623c80SCraig Rodriguesfunction initializes
41070623c80SCraig Rodrigues.Fa msgbuf
41170623c80SCraig Rodriguesso that buffers may be appended to it.
41270623c80SCraig RodriguesThe
41370623c80SCraig Rodrigues.Em fd
41470623c80SCraig Rodriguesmember should also be set directly before
41570623c80SCraig Rodrigues.Fn msgbuf_write
41670623c80SCraig Rodriguesis used.
41770623c80SCraig Rodrigues.Pp
41870623c80SCraig Rodrigues.Fn msgbuf_clear
41970623c80SCraig Rodriguesempties a msgbuf, removing and discarding any queued buffers.
42070623c80SCraig Rodrigues.Pp
42170623c80SCraig RodriguesThe
42270623c80SCraig Rodrigues.Fn msgbuf_write
42370623c80SCraig Rodriguesroutine calls
42470623c80SCraig Rodrigues.Xr sendmsg 2
42570623c80SCraig Rodriguesto transmit buffers queued in
42670623c80SCraig Rodrigues.Fa msgbuf .
42770623c80SCraig RodriguesIt returns 1 if it succeeds, \-1 on error, and 0 when the queue was empty
42870623c80SCraig Rodriguesor an EOF condition on the socket is detected.
42970623c80SCraig RodriguesTemporary resource shortages are returned with errno
43070623c80SCraig Rodrigues.Er EAGAIN
43170623c80SCraig Rodriguesand require the application to retry again in the future.
43270623c80SCraig Rodrigues.Pp
43370623c80SCraig Rodrigues.Fn msgbuf_drain
43470623c80SCraig Rodriguesdiscards data from buffers queued in
43570623c80SCraig Rodrigues.Fa msgbuf
43670623c80SCraig Rodriguesuntil
43770623c80SCraig Rodrigues.Fa n
43870623c80SCraig Rodriguesbytes have been removed or
43970623c80SCraig Rodrigues.Fa msgbuf
44070623c80SCraig Rodriguesis empty.
44170623c80SCraig Rodrigues.Sh EXAMPLES
44270623c80SCraig RodriguesIn a typical program, a channel between two processes is created with
44370623c80SCraig Rodrigues.Xr socketpair 2 ,
44470623c80SCraig Rodriguesand an
44570623c80SCraig Rodrigues.Em imsgbuf
44670623c80SCraig Rodriguescreated around one file descriptor in each process:
44770623c80SCraig Rodrigues.Bd -literal -offset indent
44870623c80SCraig Rodriguesstruct imsgbuf	parent_ibuf, child_ibuf;
44970623c80SCraig Rodriguesint		imsg_fds[2];
45070623c80SCraig Rodrigues
45170623c80SCraig Rodriguesif (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, imsg_fds) == -1)
45270623c80SCraig Rodrigues	err(1, "socketpair");
45370623c80SCraig Rodrigues
45470623c80SCraig Rodriguesswitch (fork()) {
45570623c80SCraig Rodriguescase -1:
45670623c80SCraig Rodrigues	err(1, "fork");
45770623c80SCraig Rodriguescase 0:
45870623c80SCraig Rodrigues	/* child */
45970623c80SCraig Rodrigues	close(imsg_fds[0]);
46070623c80SCraig Rodrigues	imsg_init(&child_ibuf, imsg_fds[1]);
46170623c80SCraig Rodrigues	exit(child_main(&child_ibuf));
46270623c80SCraig Rodrigues}
46370623c80SCraig Rodrigues
46470623c80SCraig Rodrigues/* parent */
46570623c80SCraig Rodriguesclose(imsg_fds[1]);
46670623c80SCraig Rodriguesimsg_init(&parent_ibuf, imsg_fds[0]);
46770623c80SCraig Rodriguesexit(parent_main(&parent_ibuf));
46870623c80SCraig Rodrigues.Ed
46970623c80SCraig Rodrigues.Pp
47070623c80SCraig RodriguesMessages may then be composed and queued on the
47170623c80SCraig Rodrigues.Em imsgbuf ,
47270623c80SCraig Rodriguesfor example using the
47370623c80SCraig Rodrigues.Fn imsg_compose
47470623c80SCraig Rodriguesfunction:
47570623c80SCraig Rodrigues.Bd -literal -offset indent
47670623c80SCraig Rodriguesenum imsg_type {
47770623c80SCraig Rodrigues	IMSG_A_MESSAGE,
47870623c80SCraig Rodrigues	IMSG_MESSAGE2
47970623c80SCraig Rodrigues};
48070623c80SCraig Rodrigues
48170623c80SCraig Rodriguesint
48270623c80SCraig Rodrigueschild_main(struct imsgbuf *ibuf)
48370623c80SCraig Rodrigues{
48470623c80SCraig Rodrigues	int	idata;
48570623c80SCraig Rodrigues	...
48670623c80SCraig Rodrigues	idata = 42;
48770623c80SCraig Rodrigues	imsg_compose(ibuf, IMSG_A_MESSAGE,
48870623c80SCraig Rodrigues		0, 0, -1, &idata, sizeof idata);
48970623c80SCraig Rodrigues	...
49070623c80SCraig Rodrigues}
49170623c80SCraig Rodrigues.Ed
49270623c80SCraig Rodrigues.Pp
49370623c80SCraig RodriguesA mechanism such as
49470623c80SCraig Rodrigues.Xr poll 2
49570623c80SCraig Rodriguesor the
49670623c80SCraig Rodrigues.Xr event 3
49770623c80SCraig Rodrigueslibrary is used to monitor the socket file descriptor.
49870623c80SCraig RodriguesWhen the socket is ready for writing, queued messages are transmitted with
49970623c80SCraig Rodrigues.Fn msgbuf_write :
50070623c80SCraig Rodrigues.Bd -literal -offset indent
50170623c80SCraig Rodrigues	if (msgbuf_write(&ibuf-\*(Gtw) \*(Lt= 0 && errno != EAGAIN) {
50270623c80SCraig Rodrigues		/* handle write failure */
50370623c80SCraig Rodrigues	}
50470623c80SCraig Rodrigues.Ed
50570623c80SCraig Rodrigues.Pp
50670623c80SCraig RodriguesAnd when ready for reading, messages are first received using
50770623c80SCraig Rodrigues.Fn imsg_read
50870623c80SCraig Rodriguesand then extracted with
50970623c80SCraig Rodrigues.Fn imsg_get :
51070623c80SCraig Rodrigues.Bd -literal -offset indent
51170623c80SCraig Rodriguesvoid
51270623c80SCraig Rodriguesdispatch_imsg(struct imsgbuf *ibuf)
51370623c80SCraig Rodrigues{
51470623c80SCraig Rodrigues	struct imsg	imsg;
51570623c80SCraig Rodrigues	ssize_t         n, datalen;
51670623c80SCraig Rodrigues	int		idata;
51770623c80SCraig Rodrigues
51870623c80SCraig Rodrigues	if ((n = imsg_read(ibuf)) == -1 || n == 0) {
51970623c80SCraig Rodrigues		/* handle socket error */
52070623c80SCraig Rodrigues	}
52170623c80SCraig Rodrigues
52270623c80SCraig Rodrigues	for (;;) {
52370623c80SCraig Rodrigues		if ((n = imsg_get(ibuf, &imsg)) == -1) {
52470623c80SCraig Rodrigues			/* handle read error */
52570623c80SCraig Rodrigues		}
52670623c80SCraig Rodrigues		if (n == 0)	/* no more messages */
52770623c80SCraig Rodrigues			return;
52870623c80SCraig Rodrigues		datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
52970623c80SCraig Rodrigues
53070623c80SCraig Rodrigues		switch (imsg.hdr.type) {
53170623c80SCraig Rodrigues		case IMSG_A_MESSAGE:
53270623c80SCraig Rodrigues			if (datalen \*(Lt sizeof idata) {
53370623c80SCraig Rodrigues				/* handle corrupt message */
53470623c80SCraig Rodrigues			}
53570623c80SCraig Rodrigues			memcpy(&idata, imsg.data, sizeof idata);
53670623c80SCraig Rodrigues			/* handle message received */
53770623c80SCraig Rodrigues			break;
53870623c80SCraig Rodrigues		...
53970623c80SCraig Rodrigues		}
54070623c80SCraig Rodrigues
54170623c80SCraig Rodrigues		imsg_free(&imsg);
54270623c80SCraig Rodrigues	}
54370623c80SCraig Rodrigues}
54470623c80SCraig Rodrigues.Ed
54570623c80SCraig Rodrigues.Sh SEE ALSO
54670623c80SCraig Rodrigues.Xr socketpair 2 ,
54770623c80SCraig Rodrigues.Xr unix 4
548