]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - share/man/man9/nv.9
Merge ^/head r284737 through r285152.
[FreeBSD/FreeBSD.git] / share / man / man9 / nv.9
1 .\"
2 .\" Copyright (c) 2013 The FreeBSD Foundation
3 .\" All rights reserved.
4 .\"
5 .\" This documentation was written by Pawel Jakub Dawidek under sponsorship
6 .\" the FreeBSD Foundation.
7 .\"
8 .\" Redistribution and use in source and binary forms, with or without
9 .\" modification, are permitted provided that the following conditions
10 .\" are met:
11 .\" 1. Redistributions of source code must retain the above copyright
12 .\"    notice, this list of conditions and the following disclaimer.
13 .\" 2. Redistributions in binary form must reproduce the above copyright
14 .\"    notice, this list of conditions and the following disclaimer in the
15 .\"    documentation and/or other materials provided with the distribution.
16 .\"
17 .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 .\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 .\" SUCH DAMAGE.
28 .\"
29 .\" $FreeBSD$
30 .\"
31 .Dd July 4, 2015
32 .Dt NV 9
33 .Os
34 .Sh NAME
35 .Nm nvlist_create ,
36 .Nm nvlist_destroy ,
37 .Nm nvlist_error ,
38 .Nm nvlist_set_error ,
39 .Nm nvlist_empty ,
40 .Nm nvlist_flags ,
41 .Nm nvlist_exists ,
42 .Nm nvlist_free ,
43 .Nm nvlist_clone ,
44 .Nm nvlist_dump ,
45 .Nm nvlist_fdump ,
46 .Nm nvlist_size ,
47 .Nm nvlist_pack ,
48 .Nm nvlist_unpack ,
49 .Nm nvlist_send ,
50 .Nm nvlist_recv ,
51 .Nm nvlist_xfer ,
52 .Nm nvlist_next ,
53 .Nm nvlist_add ,
54 .Nm nvlist_move ,
55 .Nm nvlist_get ,
56 .Nm nvlist_take
57 .Nd "library for name/value pairs"
58 .Sh LIBRARY
59 .Lb libnv
60 .Sh SYNOPSIS
61 .In nv.h
62 .Ft "nvlist_t *"
63 .Fn nvlist_create "int flags"
64 .Ft void
65 .Fn nvlist_destroy "nvlist_t *nvl"
66 .Ft int
67 .Fn nvlist_error "const nvlist_t *nvl"
68 .Ft void
69 .Fn nvlist_set_error "nvlist_t *nvl, int error"
70 .Ft bool
71 .Fn nvlist_empty "const nvlist_t *nvl"
72 .Ft int
73 .Fn nvlist_flags "const nvlist_t *nvl"
74 .\"
75 .Ft "nvlist_t *"
76 .Fn nvlist_clone "const nvlist_t *nvl"
77 .\"
78 .Ft void
79 .Fn nvlist_dump "const nvlist_t *nvl, int fd"
80 .Ft void
81 .Fn nvlist_fdump "const nvlist_t *nvl, FILE *fp"
82 .\"
83 .Ft size_t
84 .Fn nvlist_size "const nvlist_t *nvl"
85 .Ft "void *"
86 .Fn nvlist_pack "const nvlist_t *nvl" "size_t *sizep"
87 .Ft "nvlist_t *"
88 .Fn nvlist_unpack "const void *buf" "size_t size" "int flags"
89 .\"
90 .Ft int
91 .Fn nvlist_send "int sock" "const nvlist_t *nvl"
92 .Ft "nvlist_t *"
93 .Fn nvlist_recv "int sock" "int flags"
94 .Ft "nvlist_t *"
95 .Fn nvlist_xfer "int sock" "nvlist_t *nvl" "int flags"
96 .\"
97 .Ft "const char *"
98 .Fn nvlist_next "const nvlist_t *nvl" "int *typep" "void **cookiep"
99 .\"
100 .Ft bool
101 .Fn nvlist_exists "const nvlist_t *nvl" "const char *name"
102 .Ft bool
103 .Fn nvlist_exists_type "const nvlist_t *nvl" "const char *name" "int type"
104 .Ft bool
105 .Fn nvlist_exists_null "const nvlist_t *nvl" "const char *name"
106 .Ft bool
107 .Fn nvlist_exists_bool "const nvlist_t *nvl" "const char *name"
108 .Ft bool
109 .Fn nvlist_exists_number "const nvlist_t *nvl" "const char *name"
110 .Ft bool
111 .Fn nvlist_exists_string "const nvlist_t *nvl" "const char *name"
112 .Ft bool
113 .Fn nvlist_exists_nvlist "const nvlist_t *nvl" "const char *name"
114 .Ft bool
115 .Fn nvlist_exists_descriptor "const nvlist_t *nvl" "const char *name"
116 .Ft bool
117 .Fn nvlist_exists_binary "const nvlist_t *nvl" "const char *name"
118 .\"
119 .Ft void
120 .Fn nvlist_add_null "nvlist_t *nvl" "const char *name"
121 .Ft void
122 .Fn nvlist_add_bool "nvlist_t *nvl" "const char *name" "bool value"
123 .Ft void
124 .Fn nvlist_add_number "nvlist_t *nvl" "const char *name" "uint64_t value"
125 .Ft void
126 .Fn nvlist_add_string "nvlist_t *nvl" "const char *name" "const char *value"
127 .Ft void
128 .Fn nvlist_add_stringf "nvlist_t *nvl" "const char *name" "const char *valuefmt" "..."
129 .Ft void
130 .Fn nvlist_add_stringv "nvlist_t *nvl" "const char *name" "const char *valuefmt" "va_list valueap"
131 .Ft void
132 .Fn nvlist_add_nvlist "nvlist_t *nvl" "const char *name" "const nvlist_t *value"
133 .Ft void
134 .Fn nvlist_add_descriptor "nvlist_t *nvl" "const char *name" "int value"
135 .Ft void
136 .Fn nvlist_add_binary "nvlist_t *nvl" "const char *name" "const void *value" "size_t size"
137 .\"
138 .Ft void
139 .Fn nvlist_move_string "nvlist_t *nvl" "const char *name" "char *value"
140 .Ft void
141 .Fn nvlist_move_nvlist "nvlist_t *nvl" "const char *name" "nvlist_t *value"
142 .Ft void
143 .Fn nvlist_move_descriptor "nvlist_t *nvl" "const char *name" "int value"
144 .Ft void
145 .Fn nvlist_move_binary "nvlist_t *nvl" "const char *name" "void *value" "size_t size"
146 .\"
147 .Ft bool
148 .Fn nvlist_get_bool "const nvlist_t *nvl" "const char *name"
149 .Ft uint64_t
150 .Fn nvlist_get_number "const nvlist_t *nvl" "const char *name"
151 .Ft "const char *"
152 .Fn nvlist_get_string "const nvlist_t *nvl" "const char *name"
153 .Ft "const nvlist_t *"
154 .Fn nvlist_get_nvlist "const nvlist_t *nvl" "const char *name"
155 .Ft int
156 .Fn nvlist_get_descriptor "const nvlist_t *nvl" "const char *name"
157 .Ft "const void *"
158 .Fn nvlist_get_binary "const nvlist_t *nvl" "const char *name" "size_t *sizep"
159 .Ft "const nvlist_t *"
160 .Fn nvlist_get_parent "const nvlist_t *nvl" "void **cookiep"
161 .\"
162 .Ft bool
163 .Fn nvlist_take_bool "nvlist_t *nvl" "const char *name"
164 .Ft uint64_t
165 .Fn nvlist_take_number "nvlist_t *nvl" "const char *name"
166 .Ft "char *"
167 .Fn nvlist_take_string "nvlist_t *nvl" "const char *name"
168 .Ft "nvlist_t *"
169 .Fn nvlist_take_nvlist "nvlist_t *nvl" "const char *name"
170 .Ft int
171 .Fn nvlist_take_descriptor "nvlist_t *nvl" "const char *name"
172 .Ft "void *"
173 .Fn nvlist_take_binary "nvlist_t *nvl" "const char *name" "size_t *sizep"
174 .\"
175 .Ft void
176 .Fn nvlist_free "nvlist_t *nvl" "const char *name"
177 .Ft void
178 .Fn nvlist_free_type "nvlist_t *nvl" "const char *name" "int type"
179 .\"
180 .Ft void
181 .Fn nvlist_free_null "nvlist_t *nvl" "const char *name"
182 .Ft void
183 .Fn nvlist_free_bool "nvlist_t *nvl" "const char *name"
184 .Ft void
185 .Fn nvlist_free_number "nvlist_t *nvl" "const char *name"
186 .Ft void
187 .Fn nvlist_free_string "nvlist_t *nvl" "const char *name"
188 .Ft void
189 .Fn nvlist_free_nvlist "nvlist_t *nvl" "const char *name"
190 .Ft void
191 .Fn nvlist_free_descriptor "nvlist_t *nvl" "const char *name"
192 .Ft void
193 .Fn nvlist_free_binary "nvlist_t *nvl" "const char *name"
194 .Sh DESCRIPTION
195 The
196 .Nm libnv
197 library allows to easily manage name value pairs as well as send and receive
198 them over sockets.
199 A group (list) of name value pairs is called an
200 .Nm nvlist .
201 The API supports the following data types:
202 .Bl -ohang -offset indent
203 .It Sy null ( NV_TYPE_NULL )
204 There is no data associated with the name.
205 .It Sy bool ( NV_TYPE_BOOL )
206 The value can be either
207 .Dv true
208 or
209 .Dv false .
210 .It Sy number ( NV_TYPE_NUMBER )
211 The value is a number stored as
212 .Vt uint64_t .
213 .It Sy string ( NV_TYPE_STRING )
214 The value is a C string.
215 .It Sy nvlist ( NV_TYPE_NVLIST )
216 The value is a nested nvlist.
217 .It Sy descriptor ( NV_TYPE_DESCRIPTOR )
218 The value is a file descriptor.
219 Note that file descriptors can be sent only over
220 .Xr unix 4
221 domain sockets.
222 .It Sy binary ( NV_TYPE_BINARY )
223 The value is a binary buffer.
224 .El
225 .Pp
226 The
227 .Fn nvlist_create
228 function allocates memory and initializes an nvlist.
229 .Pp
230 The following flag can be provided:
231 .Pp
232 .Bl -tag -width "NV_FLAG_IGNORE_CASE" -compact -offset indent
233 .It Dv NV_FLAG_IGNORE_CASE
234 Perform case-insensitive lookups of provided names.
235 .It Dv NV_FLAG_NO_UNIQUE
236 Names in the nvlist do not have to be unique.
237 .El
238 .Pp
239 The
240 .Fn nvlist_destroy
241 function destroys the given nvlist.
242 Function does nothing if
243 .Dv NULL
244 nvlist is provided.
245 Function never modifies the
246 .Va errno
247 global variable.
248 .Pp
249 The
250 .Fn nvlist_error
251 function returns any error value that the nvlist accumulated.
252 If the given nvlist is
253 .Dv NULL
254 the
255 .Er ENOMEM
256 error will be returned.
257 .Pp
258 The
259 .Fn nvlist_set_error
260 function sets an nvlist to be in the error state.
261 Subsequent calls to
262 .Fn nvlist_error
263 will return the given error value.
264 This function cannot be used to clear the error state from an nvlist.
265 This function does nothing if the nvlist is already in the error state.
266 .Pp
267 The
268 .Fn nvlist_empty
269 function returns
270 .Dv true
271 if the given nvlist is empty and
272 .Dv false
273 otherwise.
274 The nvlist must not be in error state.
275 .Pp
276 The
277 .Fn nvlist_flags
278 function returns flags used to create the nvlist with the
279 .Fn nvlist_create
280 function.
281 .Pp
282 The
283 .Fn nvlist_clone
284 functions clones the given nvlist.
285 The clone shares no resources with its origin.
286 This also means that all file descriptors that are part of the nvlist will be
287 duplicated with the
288 .Xr dup 2
289 system call before placing them in the clone.
290 .Pp
291 The
292 .Fn nvlist_dump
293 dumps nvlist content for debugging purposes to the given file descriptor
294 .Fa fd .
295 .Pp
296 The
297 .Fn nvlist_fdump
298 dumps nvlist content for debugging purposes to the given file stream
299 .Fa fp .
300 .Pp
301 The
302 .Fn nvlist_size
303 function returns the size of the given nvlist after converting it to binary
304 buffer with the
305 .Fn nvlist_pack
306 function.
307 .Pp
308 The
309 .Fn nvlist_pack
310 function converts the given nvlist to a binary buffer.
311 The function allocates memory for the buffer, which should be freed with the
312 .Xr free 3
313 function.
314 If the
315 .Fa sizep
316 argument is not
317 .Dv NULL ,
318 the size of the buffer will be stored there.
319 The function returns
320 .Dv NULL
321 in case of an error (allocation failure).
322 If the nvlist contains any file descriptors
323 .Dv NULL
324 will be returned.
325 The nvlist must not be in error state.
326 .Pp
327 The
328 .Fn nvlist_unpack
329 function converts the given buffer to the nvlist.
330 The
331 .Fa flags
332 argument defines what type of the top level nvlist is expected to be.
333 Flags are set up using the
334 .Fn nvlist_create
335 function.
336 If the nvlist flags do not match the flags passed to
337 .Fn nvlist_unpack ,
338 the nvlist will not be returned.
339 Every nested nvlist list should be checked using
340 .Fn nvlist_flags
341 function.
342 The function returns
343 .Dv NULL
344 in case of an error.
345 .Pp
346 The
347 .Fn nvlist_send
348 function sends the given nvlist over the socket given by the
349 .Fa sock
350 argument.
351 Note that nvlist that contains file descriptors can only be send over
352 .Xr unix 4
353 domain sockets.
354 .Pp
355 The
356 .Fn nvlist_recv
357 function receives nvlist over the socket given by the
358 .Fa sock
359 argument.
360 The
361 .Fa flags
362 argument defines what type of the top level nvlist is expected to be.
363 Flags are set up using the
364 .Fn nvlist_create
365 function.
366 If the nvlist flags do not match the flags passed to
367 .Fn nvlist_recv ,
368 the nvlist will not be returned.
369 Every nested nvlist list should be checked using
370 .Fn nvlist_flags
371 function.
372 .Pp
373 The
374 .Fn nvlist_xfer
375 function sends the given nvlist over the socket given by the
376 .Fa sock
377 argument and receives nvlist over the same socket.
378 The
379 .Fa flags
380 argument defines what type of the top level nvlist is expected to be.
381 Flags are set up using the
382 .Fn nvlist_create
383 function.
384 If the nvlist flags do not match the flags passed to
385 .Fn nvlist_xfer ,
386 the nvlist will not be returned.
387 Every nested nvlist list should be checked using
388 .Fn nvlist_flags
389 function.
390 The given nvlist is always destroyed.
391 .Pp
392 The
393 .Fn nvlist_next
394 function iterates over the given nvlist returning names and types of subsequent
395 elements.
396 The
397 .Fa cookiep
398 argument allows the function to figure out which element should be returned
399 next.
400 The
401 .Va *cookiep
402 should be set to
403 .Dv NULL
404 for the first call and should not be changed later.
405 Returning
406 .Dv NULL
407 means there are no more elements on the nvlist.
408 The
409 .Fa typep
410 argument can be NULL.
411 Elements may not be removed from the nvlist while traversing it.
412 The nvlist must not be in error state.
413 .Pp
414 The
415 .Fn nvlist_exists
416 function returns
417 .Dv true
418 if element of the given name exists (besides of its type) or
419 .Dv false
420 otherwise.
421 The nvlist must not be in error state.
422 .Pp
423 The
424 .Fn nvlist_exists_type
425 function returns
426 .Dv true
427 if element of the given name and the given type exists or
428 .Dv false
429 otherwise.
430 The nvlist must not be in error state.
431 .Pp
432 The
433 .Fn nvlist_exists_null ,
434 .Fn nvlist_exists_bool ,
435 .Fn nvlist_exists_number ,
436 .Fn nvlist_exists_string ,
437 .Fn nvlist_exists_nvlist ,
438 .Fn nvlist_exists_descriptor ,
439 .Fn nvlist_exists_binary
440 functions return
441 .Dv true
442 if element of the given name and the given type determined by the function name
443 exists or
444 .Dv false
445 otherwise.
446 The nvlist must not be in error state.
447 .Pp
448 The
449 .Fn nvlist_add_null ,
450 .Fn nvlist_add_bool ,
451 .Fn nvlist_add_number ,
452 .Fn nvlist_add_string ,
453 .Fn nvlist_add_stringf ,
454 .Fn nvlist_add_stringv ,
455 .Fn nvlist_add_nvlist ,
456 .Fn nvlist_add_descriptor ,
457 .Fn nvlist_add_binary
458 functions add element to the given nvlist.
459 When adding string or binary buffor the functions will allocate memory
460 and copy the data over.
461 When adding nvlist, the nvlist will be cloned and clone will be added.
462 When adding descriptor, the descriptor will be duplicated using the
463 .Xr dup 2
464 system call and the new descriptor will be added.
465 If an error occurs while adding new element, internal error is set which can be
466 examined using the
467 .Fn nvlist_error
468 function.
469 .Pp
470 The
471 .Fn nvlist_move_string ,
472 .Fn nvlist_move_nvlist ,
473 .Fn nvlist_move_descriptor ,
474 .Fn nvlist_move_binary
475 functions add new element to the given nvlist, but unlike
476 .Fn nvlist_add_<type>
477 functions they will consume the given resource.
478 If an error occurs while adding new element, the resource is destroyed and
479 internal error is set which can be examined using the
480 .Fn nvlist_error
481 function.
482 .Pp
483 The
484 .Fn nvlist_get_bool ,
485 .Fn nvlist_get_number ,
486 .Fn nvlist_get_string ,
487 .Fn nvlist_get_nvlist ,
488 .Fn nvlist_get_descriptor ,
489 .Fn nvlist_get_binary
490 functions allow to obtain value of the given name.
491 In case of string, nvlist, descriptor or binary, returned resource should
492 not be modified - it still belongs to the nvlist.
493 If element of the given name does not exist, the program will be aborted.
494 To avoid that the caller should check for existence before trying to obtain
495 the value or use
496 .Xr dnvlist 3
497 extension, which allows to provide default value for a missing element.
498 The nvlist must not be in error state.
499 .Pp
500 The
501 .Fn nvlist_get_parent
502 function allows to obtain the parent nvlist from the nested nvlist.
503 .Pp
504 The
505 .Fn nvlist_take_bool ,
506 .Fn nvlist_take_number ,
507 .Fn nvlist_take_string ,
508 .Fn nvlist_take_nvlist ,
509 .Fn nvlist_take_descriptor ,
510 .Fn nvlist_take_binary
511 functions return value associated with the given name and remove the element
512 from the nvlist.
513 In case of string and binary values, the caller is responsible for free returned
514 memory using the
515 .Xr free 3
516 function.
517 In case of nvlist, the caller is responsible for destroying returned nvlist
518 using the
519 .Fn nvlist_destroy
520 function.
521 In case of descriptor, the caller is responsible for closing returned descriptor
522 using the
523 .Fn close 2
524 system call.
525 If element of the given name does not exist, the program will be aborted.
526 To avoid that the caller should check for existence before trying to obtain
527 the value or use
528 .Xr dnvlist 3
529 extension, which allows to provide default value for a missing element.
530 The nvlist must not be in error state.
531 .Pp
532 The
533 .Fn nvlist_free
534 function removes element of the given name from the nvlist (besides of its type)
535 and frees all resources associated with it.
536 If element of the given name does not exist, the program will be aborted.
537 The nvlist must not be in error state.
538 .Pp
539 The
540 .Fn nvlist_free_type
541 function removes element of the given name and the given type from the nvlist
542 and frees all resources associated with it.
543 If element of the given name and the given type does not exist, the program
544 will be aborted.
545 The nvlist must not be in error state.
546 .Pp
547 The
548 .Fn nvlist_free_null ,
549 .Fn nvlist_free_bool ,
550 .Fn nvlist_free_number ,
551 .Fn nvlist_free_string ,
552 .Fn nvlist_free_nvlist ,
553 .Fn nvlist_free_descriptor ,
554 .Fn nvlist_free_binary
555 functions remove element of the given name and the given type determined by the
556 function name from the nvlist and free all resources associated with it.
557 If element of the given name and the given type does not exist, the program
558 will be aborted.
559 The nvlist must not be in error state.
560 .Sh EXAMPLES
561 The following example demonstrates how to prepare an nvlist and send it over
562 .Xr unix 4
563 domain socket.
564 .Bd -literal
565 nvlist_t *nvl;
566 int fd;
567
568 fd = open("/tmp/foo", O_RDONLY);
569 if (fd < 0)
570         err(1, "open(\\"/tmp/foo\\") failed");
571
572 nvl = nvlist_create(0);
573 /*
574  * There is no need to check if nvlist_create() succeeded,
575  * as the nvlist_add_<type>() functions can cope.
576  * If it failed, nvlist_send() will fail.
577  */
578 nvlist_add_string(nvl, "filename", "/tmp/foo");
579 nvlist_add_number(nvl, "flags", O_RDONLY);
580 /*
581  * We just want to send the descriptor, so we can give it
582  * for the nvlist to consume (that's why we use nvlist_move
583  * not nvlist_add).
584  */
585 nvlist_move_descriptor(nvl, "fd", fd);
586 if (nvlist_send(sock, nvl) < 0) {
587         nvlist_destroy(nvl);
588         err(1, "nvlist_send() failed");
589 }
590 nvlist_destroy(nvl);
591 .Ed
592 .Pp
593 Receiving nvlist and getting data:
594 .Bd -literal
595 nvlist_t *nvl;
596 const char *command;
597 char *filename;
598 int fd;
599
600 nvl = nvlist_recv(sock, 0);
601 if (nvl == NULL)
602         err(1, "nvlist_recv() failed");
603
604 /* For command we take pointer to nvlist's buffer. */
605 command = nvlist_get_string(nvl, "command");
606 /*
607  * For filename we remove it from the nvlist and take
608  * ownership of the buffer.
609  */
610 filename = nvlist_take_string(nvl, "filename");
611 /* The same for the descriptor. */
612 fd = nvlist_take_descriptor(nvl, "fd");
613
614 printf("command=%s filename=%s fd=%d\n", command, filename, fd);
615
616 nvlist_destroy(nvl);
617 free(filename);
618 close(fd);
619 /* command was freed by nvlist_destroy() */
620 .Ed
621 .Pp
622 Iterating over nvlist:
623 .Bd -literal
624 nvlist_t *nvl;
625 const char *name;
626 void *cookie;
627 int type;
628
629 nvl = nvlist_recv(sock, 0);
630 if (nvl == NULL)
631         err(1, "nvlist_recv() failed");
632
633 cookie = NULL;
634 while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
635         printf("%s=", name);
636         switch (type) {
637         case NV_TYPE_NUMBER:
638                 printf("%ju", (uintmax_t)nvlist_get_number(nvl, name));
639                 break;
640         case NV_TYPE_STRING:
641                 printf("%s", nvlist_get_string(nvl, name));
642                 break;
643         default:
644                 printf("N/A");
645                 break;
646         }
647         printf("\\n");
648 }
649 .Ed
650 .Pp
651 Iterating over every nested nvlist:
652 .Bd -literal
653 nvlist_t *nvl;
654 const char *name;
655 void *cookie;
656 int type;
657
658 nvl = nvlist_recv(sock, 0);
659 if (nvl == NULL)
660         err(1, "nvlist_recv() failed");
661
662 cookie = NULL;
663 do {
664         while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
665                 if (type == NV_TYPE_NVLIST) {
666                         nvl = nvlist_get_nvlist(nvl, name);
667                         cookie = NULL;
668                 }
669         }
670 } while ((nvl = nvlist_get_parent(nvl, &cookie)) != NULL);
671 .Ed
672 .Sh SEE ALSO
673 .Xr close 2 ,
674 .Xr dup 2 ,
675 .Xr open 2 ,
676 .Xr err 3 ,
677 .Xr free 3 ,
678 .Xr printf 3 ,
679 .Xr unix 4
680 .Sh HISTORY
681 The
682 .Nm libnv
683 library appeared in
684 .Fx 11.0 .
685 .Sh AUTHORS
686 .An -nosplit
687 The
688 .Nm libnv
689 library was implemented by
690 .An Pawel Jakub Dawidek Aq Mt pawel@dawidek.net
691 under sponsorship from the FreeBSD Foundation.