Print this page
patch tsoome-feedback
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libipp/libipp.c
+++ new/usr/src/lib/libipp/libipp.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 -#pragma ident "%Z%%M% %I% %E% SMI"
28 -
29 27 #include <stdio.h>
30 28 #include <stdlib.h>
31 29 #include <sys/types.h>
32 30 #include <sys/stat.h>
33 31 #include <unistd.h>
34 32 #include <errno.h>
35 33 #include <strings.h>
36 34 #include <string.h>
37 35 #include <fcntl.h>
38 36 #include <assert.h>
39 37 #include <libipp.h>
40 38 #include <libnvpair.h>
41 39 #include <ipp/ippctl.h>
42 40
43 41 /*
44 42 * Debug macros
45 43 */
46 44
47 45 #if defined(DEBUG) && !defined(lint)
48 46 uint32_t ipp_debug_flags =
49 47 /*
50 48 * DBG_IO |
51 49 */
52 50 DBG_ERR |
53 51 0;
54 52
55 53 #define DBG0(flags, fmt) \
56 54 do { \
57 55 if (flags & ipp_debug_flags) \
58 56 fprintf(stderr, "libipp: " __FN__ ": " fmt); \
59 57 } while (0)
60 58
61 59 #define DBG1(flags, fmt, a) \
62 60 do { \
63 61 if (flags & ipp_debug_flags) \
64 62 fprintf(stderr, "libipp: " __FN__ ": " fmt, a); \
65 63 } while (0)
66 64
67 65 #define DBG2(flags, fmt, a, b) \
68 66 do { \
69 67 if (flags & ipp_debug_flags) \
70 68 fprintf(stderr, "libipp: " __FN__ ": " fmt, a, \
71 69 b); \
72 70 } while (0)
73 71
74 72 #define DBG3(flags, fmt, a, b, c) \
75 73 do { \
76 74 if (flags & ipp_debug_flags) \
77 75 fprintf(stderr, "libipp: " __FN__ ": " fmt, a, \
78 76 b, c); \
79 77 } while (0)
80 78
81 79 #else /* defined(DEBUG) && !defined(lint) */
82 80 #define DBG0(flags, fmt)
83 81 #define DBG1(flags, fmt, a)
84 82 #define DBG2(flags, fmt, a, b)
85 83 #define DBG3(flags, fmt, a, b, c)
86 84 #endif /* defined(DEBUG) && !defined(lint) */
87 85
88 86 /*
89 87 * Control device node
90 88 */
91 89
92 90 #define IPPCTL_DEVICE "/devices/pseudo/ippctl@0:ctl"
93 91
94 92 /*
95 93 * Structures.
96 94 */
97 95
98 96 typedef struct array_desc_t {
99 97 char *name;
100 98 char **array;
101 99 int nelt;
102 100 } array_desc_t;
103 101
104 102 /*
105 103 * Prototypes
106 104 */
107 105
108 106 static int nvlist_callback(nvlist_t *, void *);
109 107 static int string_callback(nvlist_t *, void *);
110 108 static int string_array_callback(nvlist_t *, void *);
111 109 static int dispatch(nvlist_t **, int (*)(nvlist_t *, void *), void *);
112 110
113 111 /*
114 112 * API functions
115 113 */
116 114 #define __FN__ "ipp_action_create"
117 115 int
118 116 ipp_action_create(
119 117 const char *modname,
120 118 const char *aname,
121 119 nvlist_t **nvlpp,
122 120 ipp_flags_t flags)
123 121 {
124 122 nvlist_t *nvlp;
125 123 int rc;
126 124
127 125 /*
128 126 * Sanity check the arguments.
129 127 */
130 128
131 129 if (nvlpp == NULL || modname == NULL || aname == NULL) {
132 130 DBG0(DBG_ERR, "bad argument\n");
133 131 errno = EINVAL;
134 132 return (-1);
135 133 }
136 134
137 135 /*
138 136 * Add our data to the nvlist. (This information will be removed for
139 137 * use by ippctl).
140 138 */
141 139
142 140 nvlp = *nvlpp;
143 141 if ((rc = nvlist_add_byte(nvlp, IPPCTL_OP,
144 142 IPPCTL_OP_ACTION_CREATE)) != 0) {
145 143 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_OP);
146 144 goto failed;
147 145 }
148 146
149 147 if ((rc = nvlist_add_string(nvlp, IPPCTL_MODNAME,
150 148 (char *)modname)) != 0) {
151 149 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n",
152 150 IPPCTL_MODNAME);
153 151 goto failed;
154 152 }
155 153
156 154 if ((rc = nvlist_add_string(nvlp, IPPCTL_ANAME, (char *)aname)) != 0) {
157 155 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_ANAME);
158 156 goto failed;
159 157 }
160 158
161 159 if ((rc = nvlist_add_uint32(nvlp, IPPCTL_FLAGS, flags)) != 0) {
162 160 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_FLAGS);
163 161 goto failed;
164 162 }
165 163
166 164 /*
167 165 * Talk to the kernel.
168 166 */
169 167
170 168 return (dispatch(nvlpp, nvlist_callback, (void *)nvlpp));
171 169 failed:
172 170 errno = rc;
173 171 return (-1);
174 172 }
175 173 #undef __FN__
176 174
177 175 #define __FN__ "ipp_action_destroy"
178 176 int
179 177 ipp_action_destroy(
180 178 const char *aname,
181 179 ipp_flags_t flags)
182 180 {
183 181 nvlist_t *nvlp;
184 182 int rc;
185 183
186 184 /*
187 185 * Sanity check the arguments.
188 186 */
189 187
190 188 if (aname == NULL) {
191 189 DBG0(DBG_ERR, "bad argument\n");
192 190 errno = EINVAL;
193 191 return (-1);
194 192 }
195 193
196 194 /*
197 195 * Create an nvlist for our data as none is passed into the function.
198 196 */
199 197
200 198 if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, 0)) != 0) {
201 199 DBG0(DBG_ERR, "failed to allocate nvlist\n");
202 200 nvlp = NULL;
203 201 goto failed;
204 202 }
205 203
206 204 if ((rc = nvlist_add_byte(nvlp, IPPCTL_OP,
207 205 IPPCTL_OP_ACTION_DESTROY)) != 0) {
208 206 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_OP);
209 207 goto failed;
210 208 }
211 209
212 210 if ((rc = nvlist_add_string(nvlp, IPPCTL_ANAME, (char *)aname)) != 0) {
213 211 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_ANAME);
214 212 goto failed;
215 213 }
216 214
217 215 if ((rc = nvlist_add_uint32(nvlp, IPPCTL_FLAGS, flags)) != 0) {
↓ open down ↓ |
179 lines elided |
↑ open up ↑ |
218 216 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_FLAGS);
219 217 goto failed;
220 218 }
221 219
222 220 /*
223 221 * Talk to the kernel.
224 222 */
225 223
226 224 return (dispatch(&nvlp, NULL, NULL));
227 225 failed:
228 - if (nvlp != NULL)
229 - nvlist_free(nvlp);
226 + nvlist_free(nvlp);
230 227 errno = rc;
231 228 return (-1);
232 229 }
233 230 #undef __FN__
234 231
235 232 #define __FN__ "ipp_action_modify"
236 233 int
237 234 ipp_action_modify(
238 235 const char *aname,
239 236 nvlist_t **nvlpp,
240 237 ipp_flags_t flags)
241 238 {
242 239 nvlist_t *nvlp;
243 240 int rc;
244 241
245 242 /*
246 243 * Sanity check the arguments.
247 244 */
248 245
249 246 if (nvlpp == NULL || aname == NULL) {
250 247 DBG0(DBG_ERR, "bad argument\n");
251 248 errno = EINVAL;
252 249 return (-1);
253 250 }
254 251
255 252 /*
256 253 * Add our data to the nvlist.
257 254 */
258 255
259 256 nvlp = *nvlpp;
260 257 if ((rc = nvlist_add_byte(nvlp, IPPCTL_OP,
261 258 IPPCTL_OP_ACTION_MODIFY)) != 0) {
262 259 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_OP);
263 260 goto failed;
264 261 }
265 262
266 263 if ((rc = nvlist_add_string(nvlp, IPPCTL_ANAME, (char *)aname)) != 0) {
267 264 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_ANAME);
268 265 goto failed;
269 266 }
270 267
271 268 if ((rc = nvlist_add_uint32(nvlp, IPPCTL_FLAGS, flags)) != 0) {
272 269 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_FLAGS);
273 270 goto failed;
274 271 }
275 272
276 273 /*
277 274 * Talk to the kernel.
278 275 */
279 276
280 277 return (dispatch(nvlpp, nvlist_callback, (void *)nvlpp));
281 278 failed:
282 279 errno = rc;
283 280 return (-1);
284 281 }
285 282 #undef __FN__
286 283
287 284 #define __FN__ "ipp_action_info"
288 285 int
289 286 ipp_action_info(
290 287 const char *aname,
291 288 int (*fn)(nvlist_t *, void *),
292 289 void *arg,
293 290 ipp_flags_t flags)
294 291 {
295 292 nvlist_t *nvlp;
296 293 int rc;
297 294
298 295 /*
299 296 * Sanity check the arguments.
300 297 */
301 298
302 299 if (aname == NULL || fn == NULL) {
303 300 DBG0(DBG_ERR, "bad argument\n");
304 301 errno = EINVAL;
305 302 return (-1);
306 303 }
307 304
308 305 /*
309 306 * Create an nvlist for our data.
310 307 */
311 308
312 309 if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, 0)) != 0) {
313 310 DBG0(DBG_ERR, "failed to allocate nvlist\n");
314 311 nvlp = NULL;
315 312 }
316 313
317 314 if ((rc = nvlist_add_byte(nvlp, IPPCTL_OP,
318 315 IPPCTL_OP_ACTION_INFO)) != 0) {
319 316 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_OP);
320 317 goto failed;
321 318 }
322 319
323 320 if ((rc = nvlist_add_string(nvlp, IPPCTL_ANAME, (char *)aname)) != 0) {
324 321 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_ANAME);
325 322 goto failed;
326 323 }
327 324
328 325 if ((rc = nvlist_add_uint32(nvlp, IPPCTL_FLAGS, flags)) != 0) {
↓ open down ↓ |
89 lines elided |
↑ open up ↑ |
329 326 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_FLAGS);
330 327 goto failed;
331 328 }
332 329
333 330 /*
334 331 * Talk to the kernel.
335 332 */
336 333
337 334 return (dispatch(&nvlp, fn, arg));
338 335 failed:
339 - if (nvlp != NULL)
340 - nvlist_free(nvlp);
336 + nvlist_free(nvlp);
341 337 errno = rc;
342 338 return (-1);
343 339 }
344 340 #undef __FN__
345 341
346 342 #define __FN__ "ipp_action_mod"
347 343 int
348 344 ipp_action_mod(
349 345 const char *aname,
350 346 char **modnamep)
351 347 {
352 348 nvlist_t *nvlp;
353 349 int rc;
354 350
355 351 /*
356 352 * Sanity check the arguments.
357 353 */
358 354
359 355 if (aname == NULL || modnamep == NULL) {
360 356 DBG0(DBG_ERR, "bad argument\n");
361 357 errno = EINVAL;
362 358 return (-1);
363 359 }
364 360
365 361 /*
366 362 * Create an nvlist for our data.
367 363 */
368 364
369 365 if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, 0)) != 0) {
370 366 DBG0(DBG_ERR, "failed to allocate nvlist\n");
371 367 nvlp = NULL;
372 368 goto failed;
373 369 }
374 370
375 371 if ((rc = nvlist_add_byte(nvlp, IPPCTL_OP,
376 372 IPPCTL_OP_ACTION_MOD)) != 0) {
377 373 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_OP);
378 374 goto failed;
379 375 }
380 376
381 377 if ((rc = nvlist_add_string(nvlp, IPPCTL_ANAME, (char *)aname)) != 0) {
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
382 378 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_ANAME);
383 379 goto failed;
384 380 }
385 381
386 382 /*
387 383 * Talk to the kernel.
388 384 */
389 385
390 386 return (dispatch(&nvlp, string_callback, (void *)modnamep));
391 387 failed:
392 - if (nvlp != NULL)
393 - nvlist_free(nvlp);
388 + nvlist_free(nvlp);
394 389 errno = rc;
395 390 return (-1);
396 391 }
397 392 #undef __FN__
398 393
399 394 #define __FN__ "ipp_list_mods"
400 395 int
401 396 ipp_list_mods(
402 397 char ***modname_arrayp,
403 398 int *neltp)
404 399 {
405 400 nvlist_t *nvlp;
406 401 array_desc_t ad;
407 402 int rc;
408 403
409 404 /*
410 405 * Sanity check the arguments.
411 406 */
412 407
413 408 if (modname_arrayp == NULL || neltp == NULL) {
414 409 DBG0(DBG_ERR, "bad argument");
415 410 errno = EINVAL;
416 411 return (-1);
417 412 }
418 413
419 414 /*
420 415 * Create an nvlist for our data.
421 416 */
422 417
423 418 if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, 0)) != 0) {
424 419 DBG0(DBG_ERR, "failed to allocate nvlist\n");
425 420 nvlp = NULL;
426 421 }
427 422
428 423 if ((rc = nvlist_add_byte(nvlp, IPPCTL_OP,
429 424 IPPCTL_OP_LIST_MODS)) != 0) {
430 425 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_OP);
431 426 goto failed;
432 427 }
433 428
434 429 /*
435 430 * Talk to the kernel.
436 431 */
437 432
438 433 ad.name = IPPCTL_MODNAME_ARRAY;
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
439 434 ad.array = NULL;
440 435 ad.nelt = 0;
441 436
442 437 if ((rc = dispatch(&nvlp, string_array_callback, (void *)&ad)) == 0) {
443 438 *modname_arrayp = ad.array;
444 439 *neltp = ad.nelt;
445 440 }
446 441
447 442 return (rc);
448 443 failed:
449 - if (nvlp != NULL)
450 - nvlist_free(nvlp);
444 + nvlist_free(nvlp);
451 445 errno = rc;
452 446 return (-1);
453 447 }
454 448 #undef __FN__
455 449
456 450 #define __FN__ "ipp_mod_list_actions"
457 451 int
458 452 ipp_mod_list_actions(
459 453 const char *modname,
460 454 char ***aname_arrayp,
461 455 int *neltp)
462 456 {
463 457 nvlist_t *nvlp;
464 458 array_desc_t ad;
465 459 int rc;
466 460
467 461 /*
468 462 * Sanity check the arguments.
469 463 */
470 464
471 465 if (modname == NULL || aname_arrayp == NULL || neltp == NULL) {
472 466 DBG0(DBG_ERR, "bad argument");
473 467 errno = EINVAL;
474 468 return (-1);
475 469 }
476 470
477 471 /*
478 472 * Create an nvlist for our data.
479 473 */
480 474
481 475 if ((rc = nvlist_alloc(&nvlp, NV_UNIQUE_NAME, 0)) != 0) {
482 476 DBG0(DBG_ERR, "failed to allocate nvlist\n");
483 477 nvlp = NULL;
484 478 }
485 479
486 480 if ((rc = nvlist_add_byte(nvlp, IPPCTL_OP,
487 481 IPPCTL_OP_MOD_LIST_ACTIONS)) != 0) {
488 482 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_OP);
489 483 goto failed;
490 484 }
491 485
492 486 if ((rc = nvlist_add_string(nvlp, IPPCTL_MODNAME,
493 487 (char *)modname)) != 0) {
494 488 DBG1(DBG_ERR, "failed to add '%s' to nvlist\n", IPPCTL_MODNAME);
495 489 goto failed;
496 490 }
497 491
498 492 /*
499 493 * Talk to the kernel.
500 494 */
501 495
502 496 ad.name = IPPCTL_ANAME_ARRAY;
↓ open down ↓ |
42 lines elided |
↑ open up ↑ |
503 497 ad.array = NULL;
504 498 ad.nelt = 0;
505 499
506 500 if ((rc = dispatch(&nvlp, string_array_callback, (void *)&ad)) == 0) {
507 501 *aname_arrayp = ad.array;
508 502 *neltp = ad.nelt;
509 503 }
510 504
511 505 return (rc);
512 506 failed:
513 - if (nvlp != NULL)
514 - nvlist_free(nvlp);
507 + nvlist_free(nvlp);
515 508 errno = rc;
516 509 return (-1);
517 510 }
518 511 #undef __FN__
519 512
520 513 #define __FN__ "ipp_free"
521 514 void
522 515 ipp_free(
523 516 char *buf)
524 517 {
525 518 free(buf);
526 519 }
527 520 #undef __FN__
528 521
529 522 #define __FN__ "ipp_free_array"
530 523 void
531 524 ipp_free_array(
532 525 char **array,
533 526 int nelt)
534 527 {
535 528 int i;
536 529
537 530 assert(array[nelt] == NULL);
538 531
539 532 for (i = 0; i < nelt; i++)
540 533 free(array[i]);
541 534
542 535 free(array);
543 536 }
544 537 #undef __FN__
545 538
546 539 #define __FN__ "nvlist_callback"
547 540 static int
548 541 nvlist_callback(
549 542 nvlist_t *nvlp,
550 543 void *arg)
551 544 {
552 545 nvlist_t **nvlpp = (nvlist_t **)arg;
553 546 int rc;
554 547
555 548 /*
556 549 * Callback function used by ipp_action_create() and
557 550 * ipp_action_modify()
558 551 */
559 552
560 553 DBG0(DBG_IO, "called\n");
561 554
562 555 assert(nvlpp != NULL);
563 556 assert(*nvlpp == NULL);
564 557
565 558 /*
566 559 * Duplicate the nvlist and set the given pointer to point at the new
567 560 * copy.
568 561 */
569 562
570 563 if ((rc = nvlist_dup(nvlp, nvlpp, 0)) != 0) {
571 564 DBG0(DBG_ERR, "failed to dup nvlist\n");
572 565 errno = rc;
573 566 return (-1);
574 567 }
575 568
576 569 return (0);
577 570 }
578 571 #undef __FN__
579 572
580 573 #define __FN__ "string_callback"
581 574 static int
582 575 string_callback(
583 576 nvlist_t *nvlp,
584 577 void *arg)
585 578 {
586 579 char **namep = (char **)arg;
587 580 char *name;
588 581 char *ptr;
589 582 int rc;
590 583
591 584 /*
592 585 * Callback function used by ipp_action_mod()
593 586 */
594 587
595 588 DBG0(DBG_IO, "called\n");
596 589
597 590 assert(namep != NULL);
598 591
599 592 /*
600 593 * Look up the module name from the nvlist.
601 594 */
602 595
603 596 if ((rc = nvlist_lookup_string(nvlp, IPPCTL_MODNAME, &ptr)) != 0) {
604 597 DBG0(DBG_ERR, "failed to find string\n");
605 598 errno = rc;
606 599 return (-1);
607 600 }
608 601
609 602 /*
610 603 * Allocate a duplicate string.
611 604 */
612 605
613 606 if ((name = strdup(ptr)) == NULL) {
614 607 DBG0(DBG_ERR, "failed to duplicate string\n");
615 608 return (-1);
616 609 }
617 610
618 611 /*
619 612 * Set the given pointer to point at the string.
620 613 */
621 614
622 615 *namep = name;
623 616 return (0);
624 617 }
625 618 #undef __FN__
626 619
627 620 #define __FN__ "string_array_callback"
628 621 static int
629 622 string_array_callback(
630 623 nvlist_t *nvlp,
631 624 void *arg)
632 625 {
633 626 array_desc_t *adp = (array_desc_t *)arg;
634 627 char **dst;
635 628 char **src;
636 629 uint_t nelt;
637 630 int i;
638 631 int rc;
639 632
640 633 /*
641 634 * Callback function used by ipp_list_mods()
642 635 */
643 636
644 637 DBG0(DBG_IO, "called\n");
645 638
646 639 assert(adp != NULL);
647 640
648 641 /*
649 642 * Look up the module name from the nvlist.
650 643 */
651 644
652 645 if ((rc = nvlist_lookup_string_array(nvlp, adp->name, &src,
653 646 &nelt)) != 0) {
654 647 DBG0(DBG_ERR, "failed to find array\n");
655 648 errno = rc;
656 649 return (-1);
657 650 }
658 651
659 652 /*
660 653 * Allocate an array.
661 654 */
662 655
663 656 if ((dst = malloc((nelt + 1) * sizeof (char *))) == NULL) {
664 657 DBG0(DBG_ERR, "failed to allocate new array\n");
665 658 return (-1);
666 659 }
667 660
668 661 /*
669 662 * For each string in the array, allocate a new buffer and copy
670 663 * the string into it.
671 664 */
672 665
673 666 for (i = 0; i < nelt; i++) {
674 667 if ((dst[i] = strdup(src[i])) == NULL) {
675 668 while (--i >= 0) {
676 669 free(dst[i]);
677 670 }
678 671 free(dst);
679 672 DBG0(DBG_ERR, "failed to duplicate array\n");
680 673 return (-1);
681 674 }
682 675 }
683 676 dst[nelt] = NULL;
684 677
685 678 /*
686 679 * Set the information to be passed back.
687 680 */
688 681
689 682 adp->array = dst;
690 683 adp->nelt = nelt;
691 684
692 685 return (0);
693 686 }
694 687 #undef __FN__
695 688
696 689 #define __FN__ "dispatch"
697 690 static int
698 691 dispatch(
699 692 nvlist_t **nvlpp,
700 693 int (*fn)(nvlist_t *, void *),
701 694 void *arg)
702 695 {
703 696 char *cbuf = NULL;
704 697 char *dbuf = NULL;
705 698 size_t cbuflen = 0;
706 699 size_t dbuflen = 0;
707 700 size_t thisbuflen = 0;
708 701 size_t nextbuflen = 0;
709 702 int rc;
710 703 ippctl_ioctl_t iioc;
711 704 int fd;
712 705 nvlist_t *cnvlp;
713 706 nvlist_t *dnvlp = NULL;
714 707 int count;
715 708 int rval;
716 709
717 710 /*
718 711 * Sanity check the 'command' nvlist.
719 712 */
720 713
721 714 cnvlp = *nvlpp;
722 715 if (cnvlp == NULL) {
723 716 rc = EINVAL;
724 717 return (-1);
725 718 }
726 719
727 720 /*
728 721 * Pack the nvlist and then free the original.
729 722 */
730 723
731 724 if ((rc = nvlist_pack(cnvlp, &cbuf, &cbuflen, NV_ENCODE_NATIVE,
732 725 0)) != 0) {
733 726 DBG0(DBG_ERR, "failed to pack nvlist\n");
734 727 nvlist_free(cnvlp);
735 728 errno = rc;
736 729 return (-1);
737 730 }
738 731 nvlist_free(cnvlp);
739 732 *nvlpp = NULL;
740 733
741 734 /*
742 735 * Open the control device node.
743 736 */
744 737
745 738 DBG1(DBG_IO, "opening %s\n", IPPCTL_DEVICE);
746 739 if ((fd = open(IPPCTL_DEVICE, O_RDWR | O_NOCTTY)) == -1) {
747 740 DBG1(DBG_ERR, "failed to open %s\n", IPPCTL_DEVICE);
748 741 goto command_failed;
749 742 }
750 743
751 744 /*
752 745 * Set up an ioctl structure to point at the packed nvlist.
753 746 */
754 747
755 748 iioc.ii_buf = cbuf;
756 749 iioc.ii_buflen = cbuflen;
757 750
758 751 /*
759 752 * Issue a command ioctl, passing the ioctl structure.
760 753 */
761 754
762 755 DBG0(DBG_IO, "command\n");
763 756 if ((rc = ioctl(fd, IPPCTL_CMD, &iioc)) < 0) {
764 757 DBG0(DBG_ERR, "command ioctl failed\n");
765 758 goto command_failed;
766 759 }
767 760
768 761 /*
769 762 * Get back the length of the first data buffer.
770 763 */
771 764
772 765 if ((nextbuflen = (size_t)rc) == 0) {
773 766 DBG0(DBG_ERR, "no data buffer\n");
774 767 errno = EPROTO;
775 768 goto command_failed;
776 769 }
777 770
778 771 /*
779 772 * Try to re-use the command buffer as the first data buffer.
780 773 */
781 774
782 775 dbuf = cbuf;
783 776 thisbuflen = cbuflen;
784 777
785 778 count = 0;
786 779 while (nextbuflen != 0) {
787 780 dbuflen = nextbuflen;
788 781
789 782 /*
790 783 * Check whether the buffer we have is long enough for the
791 784 * next lot of data. If it isn't, allocate a new one of
792 785 * the appropriate length.
793 786 */
794 787
795 788 if (nextbuflen > thisbuflen) {
796 789 if ((dbuf = realloc(dbuf, nextbuflen)) == NULL) {
797 790 DBG0(DBG_ERR,
798 791 "failed to allocate data buffer\n");
799 792 goto data_failed;
800 793 }
801 794 thisbuflen = nextbuflen;
802 795 }
803 796
804 797 /*
805 798 * Set up an ioctl structure to point at the data buffer.
806 799 */
807 800
808 801 iioc.ii_buf = dbuf;
809 802 iioc.ii_buflen = dbuflen;
810 803
811 804 /*
812 805 * Issue a data ioctl, passing the ioctl structure.
813 806 */
814 807
815 808 DBG2(DBG_IO, "data[%d]: length = %d\n", count, dbuflen);
816 809 if ((rc = ioctl(fd, IPPCTL_DATA, &iioc)) < 0) {
817 810 DBG0(DBG_ERR, "data ioctl failed\n");
818 811 goto data_failed;
819 812 }
820 813
821 814 /*
822 815 * Get the length of the *next* data buffer, if there is
823 816 * one.
824 817 */
825 818
826 819 nextbuflen = (size_t)rc;
827 820 DBG1(DBG_IO, "nextbuflen = %d\n", nextbuflen);
828 821
829 822 /*
830 823 * Unpack the nvlist that the current data buffer should
831 824 * now contain.
832 825 */
833 826
834 827 if ((rc = nvlist_unpack(dbuf, dbuflen, &dnvlp, 0)) != 0) {
835 828 DBG0(DBG_ERR, "failed to unpack nvlist\n");
836 829 errno = rc;
837 830 goto data_failed;
838 831 }
839 832
840 833 /*
841 834 * The first data buffer should contain the kernel function's
842 835 * return code. Subsequent buffers contain nvlists which
843 836 * should be passed to the given callback function.
844 837 */
845 838
846 839 if (count == 0) {
847 840 if ((rc = nvlist_lookup_int32(dnvlp, IPPCTL_RC,
848 841 &rval)) != 0) {
849 842 DBG0(DBG_ERR, "failed to find return code\n");
850 843 nvlist_free(dnvlp);
851 844 errno = rc;
852 845 goto data_failed;
853 846 }
854 847 } else {
855 848 if (fn != NULL)
856 849 if (fn(dnvlp, arg) != 0) {
857 850
858 851 /*
859 852 * The callback function returned
860 853 * a non-zero value. Abort any further
861 854 * data collection.
862 855 */
863 856
864 857 nvlist_free(dnvlp);
865 858 free(dbuf);
866 859 }
867 860 }
868 861
869 862 /*
870 863 * Free the nvlist now that we have extracted the return
871 864 * code or called the callback function.
872 865 */
873 866
874 867 nvlist_free(dnvlp);
875 868 dnvlp = NULL;
876 869
877 870 count++;
878 871 }
879 872
880 873 /*
881 874 * Free the data buffer as data collection is now complete.
882 875 */
883 876
884 877 free(dbuf);
885 878
886 879 /*
887 880 * Close the control device.
888 881 */
889 882
890 883 (void) close(fd);
891 884
892 885 /*
893 886 * If the kernel returned an error, we should return an error.
894 887 * and set errno.
895 888 */
896 889
897 890 if (rval != 0) {
898 891 DBG1(DBG_IO, "kernel return code = %d\n", rval);
899 892 errno = rval;
900 893 return (-1);
901 894 }
902 895
903 896 return (0);
904 897
905 898 command_failed:
906 899 free(cbuf);
907 900 if (fd != -1)
908 901 (void) close(fd);
909 902 return (-1);
910 903
911 904 data_failed:
912 905 if (dbuf != NULL)
913 906 free(dbuf);
914 907 (void) close(fd);
915 908 return (-1);
916 909 }
917 910 #undef __FN__
↓ open down ↓ |
393 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX