xref: /openbsd-src/lib/libutil/imsg_init.3 (revision ff59764deb7c720c75d582b75dac4b924ec7c8a6)
1*ff59764dSclaudio.\" $OpenBSD: imsg_init.3,v 1.41 2024/11/26 13:57:31 claudio Exp $
2dfaf6462Snicm.\"
304426297Sclaudio.\" Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org>
4dfaf6462Snicm.\" Copyright (c) 2010 Nicholas Marriott <nicm@openbsd.org>
5dfaf6462Snicm.\"
6dfaf6462Snicm.\" Permission to use, copy, modify, and distribute this software for any
7dfaf6462Snicm.\" purpose with or without fee is hereby granted, provided that the above
8dfaf6462Snicm.\" copyright notice and this permission notice appear in all copies.
9dfaf6462Snicm.\"
10dfaf6462Snicm.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11dfaf6462Snicm.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12dfaf6462Snicm.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13dfaf6462Snicm.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14dfaf6462Snicm.\" WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15dfaf6462Snicm.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16dfaf6462Snicm.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17dfaf6462Snicm.\"
18*ff59764dSclaudio.Dd $Mdocdate: November 26 2024 $
19d5c9e083Sclaudio.Dt IMSG_ADD 3
20dfaf6462Snicm.Os
21dfaf6462Snicm.Sh NAME
22d5c9e083Sclaudio.Nm imsg_add ,
23d5c9e083Sclaudio.Nm imsg_close ,
24d5c9e083Sclaudio.Nm imsg_compose ,
25d5c9e083Sclaudio.Nm imsg_compose_ibuf ,
26d5c9e083Sclaudio.Nm imsg_composev ,
27d5c9e083Sclaudio.Nm imsg_create ,
28d5c9e083Sclaudio.Nm imsg_forward ,
29d5c9e083Sclaudio.Nm imsg_free ,
30dfaf6462Snicm.Nm imsg_get ,
3104426297Sclaudio.Nm imsg_get_data ,
3204426297Sclaudio.Nm imsg_get_fd ,
33d5c9e083Sclaudio.Nm imsg_get_ibuf ,
3404426297Sclaudio.Nm imsg_get_id ,
35d5c9e083Sclaudio.Nm imsg_get_ibuf ,
3604426297Sclaudio.Nm imsg_get_len ,
3704426297Sclaudio.Nm imsg_get_pid ,
3804426297Sclaudio.Nm imsg_get_type ,
392621cab2Sclaudio.Nm imsgbuf_allow_fdpass ,
40d5c9e083Sclaudio.Nm imsgbuf_clear ,
41d5c9e083Sclaudio.Nm imsgbuf_flush ,
42d5c9e083Sclaudio.Nm imsgbuf_init ,
43a17071b2Sclaudio.Nm imsgbuf_queuelen ,
44d5c9e083Sclaudio.Nm imsgbuf_read ,
452621cab2Sclaudio.Nm imsgbuf_set_maxsize ,
46d5c9e083Sclaudio.Nm imsgbuf_write
47dfaf6462Snicm.Nd IPC messaging functions
48dfaf6462Snicm.Sh SYNOPSIS
4986f9d4cdStedu.In sys/queue.h
5086f9d4cdStedu.In imsg.h
512621cab2Sclaudio.Fd #define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
522621cab2Sclaudio.Fd #define MAX_IMSGSIZE 16384
53d5c9e083Sclaudio.Ft int
54d5c9e083Sclaudio.Fn imsg_add "struct ibuf *msg" "const void *data" "size_t datalen"
55dfaf6462Snicm.Ft void
56d5c9e083Sclaudio.Fn imsg_close "struct imsgbuf *imsgbuf" "struct ibuf *msg"
5704426297Sclaudio.Ft int
5804426297Sclaudio.Fn imsg_compose "struct imsgbuf *imsgbuf" "uint32_t type" "uint32_t id" \
5904426297Sclaudio    "pid_t pid" "int fd" "const void *data" "size_t datalen"
6004426297Sclaudio.Ft int
6104426297Sclaudio.Fn imsg_compose_ibuf "struct imsgbuf *imsgbuf" "uint32_t type" \
6204426297Sclaudio    "uint32_t id" "pid_t pid" "struct ibuf *buf"
63dfaf6462Snicm.Ft "struct ibuf *"
6404426297Sclaudio.Fn imsg_create "struct imsgbuf *imsgbuf" "uint32_t type" "uint32_t id" \
6504426297Sclaudio    "pid_t pid" "size_t datalen"
66dfaf6462Snicm.Ft int
67d5c9e083Sclaudio.Fn imsg_forward "struct imsgbuf *imsgbuf" "struct imsg *msg"
68dfaf6462Snicm.Ft void
69dfaf6462Snicm.Fn imsg_free "struct imsg *imsg"
70d5c9e083Sclaudio.Ft ssize_t
71d5c9e083Sclaudio.Fn imsg_get "struct imsgbuf *imsgbuf" "struct imsg *imsg"
72dfaf6462Snicm.Ft int
73d5c9e083Sclaudio.Fn imsg_get_data "struct imsg *imsg" "void *data" "size_t len"
74d5c9e083Sclaudio.Ft int
75d5c9e083Sclaudio.Fn imsg_get_fd "struct imsg *imsg"
76d5c9e083Sclaudio.Ft int
77d5c9e083Sclaudio.Fn imsg_get_ibuf "struct imsg *imsg" "struct ibuf *ibuf"
78d5c9e083Sclaudio.Ft uint32_t
79d5c9e083Sclaudio.Fn imsg_get_id "struct imsg *imsg"
80d5c9e083Sclaudio.Ft size_t
81d5c9e083Sclaudio.Fn imsg_get_len "struct imsg *imsg"
82d5c9e083Sclaudio.Ft pid_t
83d5c9e083Sclaudio.Fn imsg_get_pid "struct imsg *imsg"
84d5c9e083Sclaudio.Ft uint32_t
85d5c9e083Sclaudio.Fn imsg_get_type "struct imsg *imsg"
86d5c9e083Sclaudio.Ft void
872621cab2Sclaudio.Fn imsgbuf_allow_fdpass "struct imsgbuf *imsgbuf"
882621cab2Sclaudio.Ft void
89d5c9e083Sclaudio.Fn imsgbuf_clear "struct imsgbuf *imsgbuf"
90d5c9e083Sclaudio.Ft int
91d5c9e083Sclaudio.Fn imsgbuf_flush "struct imsgbuf *imsgbuf"
922621cab2Sclaudio.Ft int
93d5c9e083Sclaudio.Fn imsgbuf_init "struct imsgbuf *imsgbuf" "int fd"
94a17071b2Sclaudio.Ft uint32_t
95a17071b2Sclaudio.Fn imsgbuf_queuelen "struct imsgbuf *imsgbuf"
96c362c6deSclaudio.Ft int
97d5c9e083Sclaudio.Fn imsgbuf_read "struct imsgbuf *imsgbuf"
98*ff59764dSclaudio.Ft int
992621cab2Sclaudio.Fn imsgbuf_set_maxsize "struct imsgbuf *imsgbuf" "uint32_t maxsize"
100d5c9e083Sclaudio.Ft int
101d5c9e083Sclaudio.Fn imsgbuf_write "struct imsgbuf *imsgbuf"
10247373215Sclaudio.In sys/uio.h
10347373215Sclaudio.Ft int
10447373215Sclaudio.Fn imsg_composev "struct imsgbuf *imsgbuf" "uint32_t type" "uint32_t id" \
10547373215Sclaudio    "pid_t pid" "int fd" "const struct iovec *iov" "int iovcnt"
106dfaf6462Snicm.Sh DESCRIPTION
107dfaf6462SnicmThe
108dfaf6462Snicm.Nm imsg
109a6f4f68aSjmcfunctions provide a simple mechanism for communication between local processes
110dfaf6462Snicmusing sockets.
111dfaf6462SnicmEach transmitted message is guaranteed to be presented to the receiving program
112dfaf6462Snicmwhole.
113dfaf6462SnicmThey are commonly used in privilege separated processes, where processes with
114dfaf6462Snicmdifferent rights are required to cooperate.
115dfaf6462Snicm.Pp
116dfaf6462SnicmA program using these functions should be linked with
117dfaf6462Snicm.Em -lutil .
118dfaf6462Snicm.Pp
119d5c9e083Sclaudio.Fn imsgbuf_init
12019778535Sclaudioinitializes
12104426297Sclaudio.Fa imsgbuf
122dfaf6462Snicmas one side of a channel associated with
123dfaf6462Snicm.Fa fd .
124dfaf6462SnicmThe file descriptor is used to send and receive messages,
125dfaf6462Snicmbut is not closed by any of the imsg functions.
1262621cab2SclaudioIt returns 0 if successful and -1 on failure.
1272621cab2Sclaudio.Pp
1282621cab2Sclaudio.Fn imsgbuf_allow_fdpass
1292621cab2Sclaudioenables file descriptor passing in both directions for this
1302621cab2Sclaudio.Fa imsgbuf .
1312621cab2Sclaudio.Pp
1322621cab2Sclaudio.Fn imsgbuf_set_maxsize
1332621cab2Sclaudiochanges the default maximum imsg size from
1342621cab2Sclaudio.Dv MAX_IMSGSIZE
1352621cab2Sclaudioto
1362621cab2Sclaudio.Fa maxsize .
1372621cab2Sclaudio.Fa maxsize
1382621cab2Sclaudiomust be bigger than
1392621cab2Sclaudio.Dv IMSG_HEADER_SIZE .
140*ff59764dSclaudioIt returns 0 if successful and -1 on failure.
141dfaf6462Snicm.Pp
142dfaf6462SnicmThe
143d5c9e083Sclaudio.Fn imsgbuf_clear
144dfaf6462Snicmfunction frees any data allocated as part of an imsgbuf.
145d5c9e083SclaudioThis function does not close the file descriptor used for communication.
146d5c9e083Sclaudio.Pp
147d5c9e083SclaudioThe
148d5c9e083Sclaudio.Fn imsgbuf_read
149d5c9e083Sclaudioroutine reads pending data with
150d5c9e083Sclaudio.Xr recvmsg 2
151d5c9e083Sclaudioand queues it as individual messages on
152d5c9e083Sclaudio.Fa imsgbuf .
153c362c6deSclaudioIt returns 1 on success, 0 if the connection is closed, or \-1 on error
154c362c6deSclaudioand the global variable
155c362c6deSclaudio.Va errno
156c362c6deSclaudiois set to indicate the error.
157c362c6deSclaudioThe errors
158c362c6deSclaudio.Er EINTR
159c362c6deSclaudioand
160c362c6deSclaudio.Er EAGAIN
161c362c6deSclaudioare treated as follows.
162c362c6deSclaudio.Er EINTR
163c362c6deSclaudiowill automatically retry the read operation while the other errors are
164c362c6deSclaudioignored with a 1 return.
165d5c9e083Sclaudio.Pp
166d5c9e083Sclaudio.Fn imsgbuf_write
167d5c9e083Sclaudiowrites out queued messages.
168d5c9e083SclaudioIt returns 0 if it succeeds, -1 on error and the global variable
169d5c9e083Sclaudio.Va errno
170d5c9e083Sclaudiois set to indicate the error.
171d5c9e083SclaudioThe errors
172d5c9e083Sclaudio.Er EINTR ,
173d5c9e083Sclaudio.Er EAGAIN ,
174d5c9e083Sclaudioand
175d5c9e083Sclaudio.Er ENOBUFS
176d5c9e083Sclaudioare treated as follows.
177d5c9e083Sclaudio.Er EINTR
178d5c9e083Sclaudiowill automatically retry the write operation while the other errors are
179d5c9e083Sclaudioignored with a 0 return.
180d5c9e083Sclaudio.Pp
181d5c9e083Sclaudio.Fn imsgbuf_flush
182d5c9e083Sclaudiocalls
183d5c9e083Sclaudio.Fn imsgbuf_write
184d5c9e083Sclaudioin a loop until all imsgs in the output buffer are sent.
185d5c9e083SclaudioIt returns 0 if it succeeds, \-1 otherwise and the global variable
186d5c9e083Sclaudio.Va errno
187d5c9e083Sclaudiois set to indicate the error.
188d5c9e083Sclaudio.Fn imsgbuf_flush
189d5c9e083Sclaudioshould not be called on non-blocking sockets since it will busy loop if the
190d5c9e083Sclaudiosocket is not available.
191dfaf6462Snicm.Pp
192a17071b2Sclaudio.Fn imsgbuf_queuelen
193a17071b2Sclaudioreturns the number of messages ready to be sent.
194a17071b2SclaudioThis function returns 0 if no messages are pending for transmission.
195a17071b2Sclaudio.Pp
196dfaf6462Snicm.Fn imsg_create ,
197dfaf6462Snicm.Fn imsg_add
198dfaf6462Snicmand
199dfaf6462Snicm.Fn imsg_close
200dfaf6462Snicmare generic construction routines for messages that are to be sent using an
201dfaf6462Snicmimsgbuf.
202dfaf6462Snicm.Pp
203dfaf6462Snicm.Fn imsg_create
204dfaf6462Snicmcreates a new message with header specified by
205dfaf6462Snicm.Fa type ,
20604426297Sclaudio.Fa id
2070802db80Ssthenand
208dfaf6462Snicm.Fa pid .
209dfaf6462SnicmA
210dfaf6462Snicm.Fa pid
211dfaf6462Snicmof zero uses the process ID returned by
212dfaf6462Snicm.Xr getpid 2
213dfaf6462Snicmwhen
21404426297Sclaudio.Fa imsgbuf
215dfaf6462Snicmwas initialized.
216dfaf6462SnicmIn addition to this common imsg header,
217dfaf6462Snicm.Fa datalen
218dfaf6462Snicmbytes of space may be reserved for attaching to this imsg.
219dfaf6462SnicmThis space is populated using
220dfaf6462Snicm.Fn imsg_add .
221dfaf6462Snicm.Fn imsg_create
222dfaf6462Snicmreturns a pointer to a new message if it succeeds, NULL otherwise.
223dfaf6462Snicm.Pp
224dfaf6462Snicm.Fn imsg_add
225dfaf6462Snicmappends to
22608c753b7Snicm.Fa msg
22708c753b7Snicm.Fa datalen
228dfaf6462Snicmbytes of ancillary data pointed to by
22908c753b7Snicm.Fa data .
230dfaf6462SnicmIt returns
2318f6effc9Sjmc.Fa datalen
232f9b15afbSstspif it succeeds, otherwise
233f9b15afbSstsp.Fa msg
234f9b15afbSstspis freed and \-1 is returned.
235dfaf6462Snicm.Pp
236dfaf6462Snicm.Fn imsg_close
237dfaf6462Snicmcompletes creation of
23808c753b7Snicm.Fa msg
239dfaf6462Snicmby adding it to
24004426297Sclaudio.Fa imsgbuf
241dfaf6462Snicmoutput buffer.
242dfaf6462Snicm.Pp
243dfaf6462Snicm.Fn imsg_compose
24419778535Sclaudiois used to quickly create and queue an imsg.
245dfaf6462SnicmIt takes the same parameters as the
246dfaf6462Snicm.Fn imsg_create ,
247dfaf6462Snicm.Fn imsg_add
248dfaf6462Snicmand
249dfaf6462Snicm.Fn imsg_close
250dfaf6462Snicmroutines,
251dfaf6462Snicmexcept that only one ancillary data buffer can be provided.
25269cc8ae2SzhukAdditionally, the file descriptor
25369cc8ae2Szhuk.Fa fd
25469cc8ae2Szhukmay be passed over the socket to the other process.
25569cc8ae2SzhukIf
25669cc8ae2Szhuk.Fa fd
25769cc8ae2Szhukis given, it is closed in the sending program after the message is sent.
25869cc8ae2SzhukA value of \-1 indicates no file descriptor should be passed.
259dfaf6462SnicmThis routine returns 1 if it succeeds, \-1 otherwise.
260dfaf6462Snicm.Pp
261dfaf6462Snicm.Fn imsg_composev
262dfaf6462Snicmis similar to
263dfaf6462Snicm.Fn imsg_compose .
264dfaf6462SnicmIt takes the same parameters, except that the ancillary data buffer is specified
265dfaf6462Snicmby
266dfaf6462Snicm.Fa iovec .
267dfaf6462Snicm.Pp
26819778535Sclaudio.Fn imsg_compose_ibuf
26919778535Sclaudiois similar to
27019778535Sclaudio.Fn imsg_compose .
27119778535SclaudioIt takes the same parameters, except that the ancillary data buffer is specified
27219778535Sclaudioby an ibuf
27319778535Sclaudio.Fa buf .
27419778535SclaudioThis routine returns 1 if it succeeds, \-1 otherwise.
27519778535SclaudioIn either case the buffer
27619778535Sclaudio.Fa buf
27719778535Sclaudiois consumed by the function.
27819778535Sclaudio.Pp
27904426297Sclaudio.Fn imsg_forward
28004426297Sclaudioforwards a just received
28104426297Sclaudio.Fa msg
28204426297Sclaudiounaltered on
28304426297Sclaudio.Fa imsgbuf .
2846d41500aSclaudioFile descriptors are not forwarded by this function.
2856d41500aSclaudioIt is possible to call
2866d41500aSclaudio.Fn imsg_forward
2876d41500aSclaudiomore than once per message.
28804426297Sclaudio.Pp
289dfaf6462Snicm.Fn imsg_get
290dfaf6462Snicmfills in an individual imsg pending on
291dfaf6462Snicm.Fa imsgbuf
292dfaf6462Snicminto the structure pointed to by
293dfaf6462Snicm.Fa imsg .
294dfaf6462SnicmIt returns the total size of the message, 0 if no messages are ready, or \-1
295dfaf6462Snicmfor an error.
296dfaf6462SnicmReceived messages are returned as a
297dfaf6462Snicm.Em struct imsg ,
2987adf0adcSsthenwhich must be freed by
299dfaf6462Snicm.Fn imsg_free
300dfaf6462Snicmwhen no longer required.
301dfaf6462Snicm.Pp
30204426297SclaudioThe accessors
30304426297Sclaudio.Fn imsg_get_type ,
30404426297Sclaudio.Fn imsg_get_pid ,
30504426297Sclaudio.Fn imsg_get_id ,
30604426297Sclaudioand
30704426297Sclaudio.Fn imsg_get_len ,
30804426297Sclaudioreturn the
30904426297Sclaudio.Fa type ,
31004426297Sclaudio.Fa pid ,
31104426297Sclaudio.Fa id ,
31204426297Sclaudioand payload length used in
31304426297Sclaudio.Fn imsg_create
31404426297Sclaudioto build the
31504426297Sclaudio.Fa imsg .
31604426297SclaudioIf there is no payload
31704426297Sclaudio.Fn imsg_get_len
31804426297Sclaudioreturns 0.
319dfaf6462Snicm.Pp
32004426297Sclaudio.Fn imsg_get_fd
32104426297Sclaudioreturns the file descriptor and passes the responsibility to track the
32204426297Sclaudiodescriptor back to the program.
3236d41500aSclaudioUnclaimed file descriptors are closed by
3246d41500aSclaudio.Fn imsg_free .
325dfaf6462Snicm.Pp
32604426297Sclaudio.Fn imsg_get_data
32704426297Sclaudioand
32804426297Sclaudio.Fn imsg_get_ibuf
32904426297Sclaudioare used to extract the payload of an
33004426297Sclaudio.Fa imsg .
33104426297Sclaudio.Fn imsg_get_data
33204426297Sclaudiocan be used if the structure of the payload is known and can be extracted
33304426297Sclaudioin one go.
33404426297Sclaudio0 is returned on success and \-1 on failure.
33504426297Sclaudio.Fn imsg_get_ibuf
33604426297Sclaudioinitializes the passed
33704426297Sclaudio.Fa ibuf
33804426297Sclaudioto hold the payload which can be read using
33904426297Sclaudio.Xr ibuf_get 3 .
34004426297SclaudioThe
34104426297Sclaudio.Fa ibuf
34204426297Sclaudioremains valid until
34304426297Sclaudio.Fn imsg_free
34404426297Sclaudiois called and there is no need to call
34504426297Sclaudio.Fn ibuf_free
34604426297Sclaudioon this stack based buffer.
34704426297SclaudioThe function returns 0 on success, \-1 otherwise.
348dfaf6462Snicm.Pp
349dfaf6462SnicmMAX_IMSGSIZE is defined as the maximum size of a single imsg, currently
350dfaf6462Snicm16384 bytes.
351dfaf6462Snicm.Sh EXAMPLES
352dfaf6462SnicmIn a typical program, a channel between two processes is created with
353dfaf6462Snicm.Xr socketpair 2 ,
354dfaf6462Snicmand an
355dfaf6462Snicm.Em imsgbuf
356dfaf6462Snicmcreated around one file descriptor in each process:
357dfaf6462Snicm.Bd -literal -offset indent
358dfaf6462Snicmstruct imsgbuf	parent_ibuf, child_ibuf;
359dfaf6462Snicmint		imsg_fds[2];
360dfaf6462Snicm
361dfaf6462Snicmif (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, imsg_fds) == -1)
362dfaf6462Snicm	err(1, "socketpair");
363dfaf6462Snicm
364dfaf6462Snicmswitch (fork()) {
365dfaf6462Snicmcase -1:
366dfaf6462Snicm	err(1, "fork");
367dfaf6462Snicmcase 0:
368dfaf6462Snicm	/* child */
369dfaf6462Snicm	close(imsg_fds[0]);
3702621cab2Sclaudio	if (imsgbuf_init(&child_ibuf, imsg_fds[1]) == -1)
3712621cab2Sclaudio		err(1, NULL);
372dfaf6462Snicm	exit(child_main(&child_ibuf));
373dfaf6462Snicm}
374dfaf6462Snicm
375dfaf6462Snicm/* parent */
376dfaf6462Snicmclose(imsg_fds[1]);
3772621cab2Sclaudioif (imsgbuf_init(&parent_ibuf, imsg_fds[0]) == -1)
3782621cab2Sclaudio	err(1, NULL);
379dfaf6462Snicmexit(parent_main(&parent_ibuf));
380dfaf6462Snicm.Ed
381dfaf6462Snicm.Pp
382dfaf6462SnicmMessages may then be composed and queued on the
383dfaf6462Snicm.Em imsgbuf ,
384dfaf6462Snicmfor example using the
385dfaf6462Snicm.Fn imsg_compose
386dfaf6462Snicmfunction:
387dfaf6462Snicm.Bd -literal -offset indent
388dfaf6462Snicmenum imsg_type {
389dfaf6462Snicm	IMSG_A_MESSAGE,
390dfaf6462Snicm	IMSG_MESSAGE2
391657b656bSderaadt};
392dfaf6462Snicm
393dfaf6462Snicmint
39404426297Sclaudiochild_main(struct imsgbuf *imsgbuf)
395dfaf6462Snicm{
396dfaf6462Snicm	int	idata;
397dfaf6462Snicm	...
398dfaf6462Snicm	idata = 42;
39904426297Sclaudio	imsg_compose(imsgbuf, IMSG_A_MESSAGE,
400dfaf6462Snicm	    0, 0, -1, &idata, sizeof idata);
401dfaf6462Snicm	...
402dfaf6462Snicm}
403dfaf6462Snicm.Ed
404dfaf6462Snicm.Pp
405dfaf6462SnicmA mechanism such as
406dfaf6462Snicm.Xr poll 2
407dfaf6462Snicmor the
408dfaf6462Snicm.Xr event 3
409dfaf6462Snicmlibrary is used to monitor the socket file descriptor.
410dfaf6462SnicmWhen the socket is ready for writing, queued messages are transmitted with
411d5c9e083Sclaudio.Fn imsgbuf_write :
412dfaf6462Snicm.Bd -literal -offset indent
413d5c9e083Sclaudio	if (imsgbuf_write(imsgbuf) == -1) {
414317c8015Sclaudio		if (errno == EPIPE)
415a0a7f51dSreyk			/* handle closed connection */
416317c8015Sclaudio		else
417317c8015Sclaudio			/* handle write failure */
418a0a7f51dSreyk	}
419dfaf6462Snicm.Ed
420dfaf6462Snicm.Pp
421dfaf6462SnicmAnd when ready for reading, messages are first received using
422d5c9e083Sclaudio.Fn imsgbuf_read
423dfaf6462Snicmand then extracted with
424dfaf6462Snicm.Fn imsg_get :
425dfaf6462Snicm.Bd -literal -offset indent
426dfaf6462Snicmvoid
42704426297Sclaudiodispatch_imsg(struct imsgbuf *imsgbuf)
428dfaf6462Snicm{
429dfaf6462Snicm	struct imsg	imsg;
43004426297Sclaudio	ssize_t         n;
431dfaf6462Snicm	int		idata;
432dfaf6462Snicm
4332621cab2Sclaudio	switch (imsgbuf_read(imsgbuf)) {
4342621cab2Sclaudio	case -1:
435a0a7f51dSreyk		/* handle read error */
4362621cab2Sclaudio		break;
4372621cab2Sclaudio	case 0:
438a0a7f51dSreyk		/* handle closed connection */
4392621cab2Sclaudio		break;
440dfaf6462Snicm	}
441dfaf6462Snicm
442dfaf6462Snicm	for (;;) {
44304426297Sclaudio		if ((n = imsg_get(imsgbuf, &imsg)) == -1) {
444dfaf6462Snicm			/* handle read error */
445dfaf6462Snicm		}
446dfaf6462Snicm		if (n == 0)	/* no more messages */
447dfaf6462Snicm			return;
448dfaf6462Snicm
44904426297Sclaudio		switch (imsg_get_type(&imsg)) {
450dfaf6462Snicm		case IMSG_A_MESSAGE:
45104426297Sclaudio			if (imsg_get_data(&imsg, &idata,
45204426297Sclaudio			    sizeof(idata)) == -1) {
453dfaf6462Snicm				/* handle corrupt message */
454dfaf6462Snicm			}
455dfaf6462Snicm			/* handle message received */
456dfaf6462Snicm			break;
457dfaf6462Snicm		...
458dfaf6462Snicm		}
459dfaf6462Snicm
460dfaf6462Snicm		imsg_free(&imsg);
461dfaf6462Snicm	}
462dfaf6462Snicm}
463dfaf6462Snicm.Ed
464dfaf6462Snicm.Sh SEE ALSO
465dfaf6462Snicm.Xr socketpair 2 ,
46604426297Sclaudio.Xr ibuf_add 3 ,
467dfaf6462Snicm.Xr unix 4
468