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