1 /* $NetBSD: iscsic_parse.c,v 1.3 2015/05/30 15:57:32 joerg Exp $ */ 2 3 /*- 4 * Copyright (c) 2005,2006,2011 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Wasabi Systems, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "iscsic_globals.h" 33 34 #include <ctype.h> 35 #include <assert.h> 36 37 /* 38 * get_address: 39 * Get an address specification that may include port and group tag. 40 * 41 * Parameter: 42 * portal The portal address 43 * str The parameter string to scan 44 * 45 * Aborts app on error. 46 */ 47 48 STATIC void 49 get_address(iscsi_portal_address_t * portal, char *str, char *arg) 50 { 51 char *sp, *sp2; 52 int val; 53 54 if (!str || !*str) 55 arg_error(arg, "Address is missing"); 56 57 /* is there a port? don't check inside square brackets (IPv6 addr) */ 58 for (sp = str + 1, val = 0; *sp && (*sp != ':' || val); sp++) { 59 if (*sp == '[') 60 val = 1; 61 else if (*sp == ']') 62 val = 0; 63 } 64 65 /* */ 66 if (*sp) { 67 for (sp2 = sp + 1; *sp2 && *sp2 != ':'; sp2++); 68 /* if there's a second colon, assume it's an unbracketed IPv6 address */ 69 if (!*sp2) { 70 /* truncate source, that's the address */ 71 *sp++ = '\0'; 72 if (sscanf(sp, "%d", &val) != 1) 73 arg_error(arg, "Bad address format: Expected port number"); 74 if (val < 0 || val > 0xffff) 75 arg_error(arg, "Bad address format: Port number out of range"); 76 portal->port = (uint16_t) val; 77 } 78 /* is there a group tag? */ 79 for (; isdigit((unsigned char)*sp); sp++); 80 if (*sp && *sp != ',') 81 arg_error(arg, "Bad address format: Extra character(s) '%c'", *sp); 82 } else 83 for (sp = str + 1; *sp && *sp != ','; sp++); 84 85 if (*sp) { 86 if (sscanf(sp + 1, "%d", &val) != 1) 87 arg_error(arg, "Bad address format: Expected group tag"); 88 if (val < 0 || val > 0xffff) 89 arg_error(arg, "Bad address format: Group tag out of range"); 90 portal->group_tag = (uint16_t) val; 91 /* truncate source, that's the address */ 92 *sp = '\0'; 93 } 94 /* only check length, don't verify correct format (too many possibilities) */ 95 if (strlen(str) >= sizeof(portal->address)) 96 arg_error(arg, "Bad address format: Address string too long"); 97 98 strlcpy((char *)portal->address, str, sizeof(portal->address)); 99 } 100 101 102 103 /* 104 * get_short_int: 105 * Get a short integer. 106 * 107 * Parameter: 108 * sp The parameter string to scan 109 * arg The associated option argument (for error message) 110 * name The argument name 111 * 112 * Returns given integer, aborts app on error. 113 */ 114 115 STATIC uint16_t 116 get_short_int(char *sp, char *arg, const char *name) 117 { 118 int val; 119 120 if (!sp || !*sp) 121 arg_error(arg, "%s is missing", name); 122 123 if (!sscanf(sp, "%d", &val)) 124 arg_error(arg, "Expected integer %s", name); 125 if (val < 0 || val > 0xffff) 126 arg_error(arg, "%s out of range", name); 127 128 return (uint16_t) val; 129 } 130 131 132 /* 133 * get_dsl: 134 * Get MaxRecvDataSegmentLength 135 * 136 * Parameter: 137 * sp The parameter string to scan 138 * arg The associated option argument (for error message) 139 * 140 * Returns given integer, aborts app on error. 141 */ 142 143 STATIC uint32_t 144 get_dsl(char *sp, char *arg) 145 { 146 int val; 147 148 if (!sp || !*sp) 149 arg_error(arg, "Missing MaxRecvDataSegmentLength"); 150 if (!sscanf(sp, "%d", &val)) 151 arg_error(arg, "Integer MaxRecvDataSegmentLength expected"); 152 if (val < 512 || val > 0xffffff) 153 arg_error(arg, "MaxRecvDataSegmentLength out of range"); 154 155 return (uint32_t) val; 156 } 157 158 159 /* 160 * get_str: 161 * Get a string. 162 * 163 * Parameter: 164 * dest The destination string 165 * sp The parameter string to scan 166 * arg The associated option argument (for error message) 167 * name The argument name 168 * 169 * Aborts app on error. 170 */ 171 172 STATIC void 173 get_str(char *dest, char *sp, char *arg, const char *name) 174 { 175 176 if (!sp || !*sp) 177 arg_error(arg, "%s is missing", name); 178 if (strlen(sp) >= ISCSI_STRING_LENGTH) 179 arg_error(arg, "%s is too long", name); 180 181 strlcpy(dest, sp, ISCSI_STRING_LENGTH); 182 } 183 184 /* 185 * cl_get_target: 186 * Get a target address specification that may include name, address, port, 187 * and group tag, with address/port/tag possibly repeated. 188 * 189 * Parameter: 190 * ptarg pointer to hold the resulting add target request parameter 191 * argc, argv program parameters (shifted) 192 * nreq target name is required if TRUE 193 * 194 * Returns: 0 if there is no target, else the size of the allocated 195 * request. 196 * Aborts app on bad parameter or mem allocation error. 197 */ 198 199 int 200 cl_get_target(iscsid_add_target_req_t ** ptarg, int argc, char **argv, int nreq) 201 { 202 iscsid_add_target_req_t *targ; 203 char *sp; 204 size_t num, len, name; 205 int i, p; 206 207 /* count number of addreses first, so we know how much memory to allocate */ 208 for (i = (int)(num = name = 0); i < argc; i++) { 209 if (!argv[i] || argv[i][0] != '-') 210 continue; 211 if (argv[i][1] == 'a') 212 num++; 213 if (argv[i][1] == 'n') 214 name++; 215 } 216 217 if (!name && nreq) 218 return 0; 219 220 len = sizeof(iscsid_add_target_req_t) + 221 num * sizeof(iscsi_portal_address_t); 222 223 if (NULL == (targ = calloc(1, len))) 224 gen_error("Can't allocate %zu bytes of memory", len); 225 226 *ptarg = targ; 227 p = -1; 228 229 for (i = 0; i < argc; i++) { 230 if (!argv[i] || argv[i][0] != '-') 231 continue; 232 233 sp = (argv[i][2]) ? &argv[i][2] : ((i + 1 < argc) ? argv[i + 1] : NULL); 234 235 switch (argv[i][1]) { 236 case 'n': /* target name */ 237 get_str((char *)targ->TargetName, sp, argv[i], "Target name"); 238 break; 239 240 case 'a': /* target address */ 241 get_address(&targ->portal[++p], sp, argv[i]); 242 break; 243 244 case 'p': /* port */ 245 assert(p >= 0); 246 targ->portal[p].port = get_short_int(sp, argv[i], "Port"); 247 break; 248 249 case 'g': /* group tag */ 250 assert(p >= 0); 251 targ->portal[p].group_tag = get_short_int(sp, argv[i], 252 "Group tag"); 253 break; 254 255 default: 256 continue; 257 } 258 if (!argv[i][2]) 259 argv[i + 1] = NULL; 260 261 argv[i] = NULL; 262 } 263 targ->num_portals = p + 1; 264 265 return (int)len; 266 } 267 268 269 /* 270 * cl_get_isns: 271 * Get an iSNS server address specification that may include name, address 272 * and port. 273 * 274 * Parameter: 275 * srv add_isns_server request parameter 276 * argc, argv program parameters (shifted) 277 * 278 * Returns: 0 on error, 1 if OK. 279 */ 280 281 int 282 cl_get_isns(iscsid_add_isns_server_req_t * srv, int argc, char **argv) 283 { 284 iscsi_portal_address_t addr; 285 char *sp; 286 int i, found; 287 288 (void) memset(&addr, 0x0, sizeof(addr)); 289 found = FALSE; 290 291 for (i = 0; i < argc; i++) { 292 if (!argv[i] || argv[i][0] != '-') 293 continue; 294 295 sp = (argv[i][2]) ? &argv[i][2] : ((i + 1 < argc) ? argv[i + 1] : NULL); 296 297 switch (argv[i][1]) { 298 case 'N': /* symbolic name */ 299 get_str((char *)srv->name, sp, argv[i], "Server name"); 300 break; 301 302 case 'a': /* target address */ 303 get_address(&addr, sp, argv[i]); 304 found = TRUE; 305 break; 306 307 case 'p': /* port */ 308 addr.port = get_short_int(sp, argv[i], "Port"); 309 break; 310 311 default: 312 continue; 313 } 314 if (!argv[i][2]) { 315 argv[i + 1] = NULL; 316 } 317 argv[i] = NULL; 318 } 319 320 strlcpy((char *)srv->address, (char *)addr.address, sizeof(srv->address)); 321 srv->port = addr.port; 322 323 return found; 324 } 325 326 327 /* 328 * cl_get_auth_opts: 329 * Get authentication options. 330 * 331 * Parameter: 332 * auth authentication parameters 333 * argc, argv program parameters (shifted) 334 * 335 * Returns: 0 if there are no authorization options, 1 otherwise. 336 * Aborts app on bad parameter. 337 */ 338 339 int 340 cl_get_auth_opts(iscsid_set_target_authentication_req_t *auth, 341 int argc, char **argv) 342 { 343 int n, i, found; 344 char *sp; 345 346 found = FALSE; 347 memset(auth, 0, sizeof(*auth)); 348 349 for (i = 0; i < argc; i++) { 350 if (!argv[i] || argv[i][0] != '-') { 351 continue; 352 } 353 sp = (argv[i][2]) ? &argv[i][2] : ((i + 1 < argc) ? argv[i + 1] : NULL); 354 355 switch (argv[i][1]) { 356 case 't': /* authentication type */ 357 if (!sp || !*sp) 358 arg_error(argv[i], "Missing authentication type"); 359 n = 0; 360 while (*sp) { 361 switch (*sp) { 362 case 'n': /* no authentication */ 363 auth->auth_info.auth_type[n] = ISCSI_AUTH_None; 364 break; 365 case 'c': /* CHAP authentication */ 366 auth->auth_info.auth_type[n] = ISCSI_AUTH_CHAP; 367 break; 368 case 'C': /* Mutual CHAP authentication */ 369 auth->auth_info.auth_type[n] = ISCSI_AUTH_CHAP; 370 auth->auth_info.mutual_auth = 1; 371 break; 372 default: 373 arg_error(argv[i], "Bad authentication type '%c'", *sp); 374 } 375 sp++; 376 n++; 377 } 378 auth->auth_info.auth_number = n; 379 break; 380 381 case 'u': /* user name */ 382 get_str((char *)auth->user_name, sp, argv[i], "User name"); 383 break; 384 385 case 's': /* secret */ 386 get_str((char *)auth->password, sp, argv[i], "Secret"); 387 break; 388 389 case 'S': /* target secret */ 390 get_str((char *)auth->target_password, sp, argv[i], "Target secret"); 391 break; 392 393 default: 394 continue; 395 } 396 if (!argv[i][2]) 397 argv[i + 1] = NULL; 398 399 argv[i] = NULL; 400 found = TRUE; 401 } 402 return found; 403 } 404 405 406 /* 407 * cl_get_target_opts: 408 * Get session/connection options. 409 * 410 * Parameter: 411 * opt target options 412 * argc, argv program parameters (shifted) 413 * 414 * Returns: 0 if there are no target options, 1 otherwise. 415 * Aborts app on bad parameter. 416 */ 417 418 int 419 cl_get_target_opts(iscsid_get_set_target_options_t * opt, int argc, char **argv) 420 { 421 int i, found; 422 char *sp; 423 424 found = FALSE; 425 memset(opt, 0, sizeof(*opt)); 426 427 for (i = 0; i < argc; i++) { 428 if (!argv[i] || argv[i][0] != '-') 429 continue; 430 431 sp = (argv[i][2]) ? &argv[i][2] : ((i + 1 < argc) ? argv[i + 1] : NULL); 432 433 switch (argv[i][1]) { 434 case 'h': /* Header Digest */ 435 opt->HeaderDigest = ISCSI_DIGEST_CRC32C; 436 opt->is_present.HeaderDigest = 1; 437 break; 438 439 case 'd': /* Data Digest */ 440 opt->DataDigest = ISCSI_DIGEST_CRC32C; 441 opt->is_present.DataDigest = 1; 442 break; 443 444 case 'w': /* Time 2 Wait */ 445 opt->DefaultTime2Wait = get_short_int(sp, argv[i], "Time to wait"); 446 opt->is_present.DefaultTime2Wait = 1; 447 if (!argv[i][2]) 448 argv[i + 1] = NULL; 449 break; 450 451 case 'r': /* Time 2 Retain */ 452 opt->DefaultTime2Retain = get_short_int(sp, argv[i], 453 "Time to retain"); 454 opt->is_present.DefaultTime2Retain = 1; 455 if (!argv[i][2]) 456 argv[i + 1] = NULL; 457 break; 458 459 case 'e': /* Error Recovery Level */ 460 opt->ErrorRecoveryLevel = get_short_int(sp, argv[i], 461 "ErrorRecoveryLevel"); 462 opt->is_present.ErrorRecoveryLevel = 1; 463 if (!argv[i][2]) 464 argv[i + 1] = NULL; 465 break; 466 467 case 'l': /* Data Segment Length */ 468 opt->MaxRecvDataSegmentLength = get_dsl(sp, argv[i]); 469 opt->is_present.MaxRecvDataSegmentLength = 1; 470 if (!argv[i][2]) 471 argv[i + 1] = NULL; 472 break; 473 474 default: 475 continue; 476 } 477 argv[i] = NULL; 478 found = TRUE; 479 } 480 return found; 481 } 482 483 484 /* 485 * cl_get_portal: 486 * Get a portal address specification that may include address, port, 487 * and group tag, plus portal options. 488 * 489 * Parameter: 490 * port add portal request parameter 491 * argc, argv program parameters (shifted) 492 * 493 * Returns: FALSE if there is no portal, else TRUE. 494 * Aborts app on bad parameter or mem allocation error. 495 */ 496 497 int 498 cl_get_portal(iscsid_add_portal_req_t * port, int argc, char **argv) 499 { 500 char *sp; 501 int i, found; 502 iscsid_portal_options_t *opt = &port->options; 503 504 found = FALSE; 505 memset(port, 0, sizeof(*port)); 506 507 for (i = 0; i < argc; i++) { 508 if (!argv[i] || argv[i][0] != '-') 509 continue; 510 511 sp = (argv[i][2]) ? &argv[i][2] : ((i + 1 < argc) ? argv[i + 1] : NULL); 512 513 switch (argv[i][1]) { 514 case 'a': /* target address */ 515 get_address(&port->portal, sp, argv[i]); 516 found = TRUE; 517 break; 518 519 case 'p': /* port */ 520 port->portal.port = get_short_int(sp, argv[i], "Port"); 521 break; 522 523 case 'g': /* group tag */ 524 port->portal.group_tag = get_short_int(sp, argv[i], "Group tag"); 525 break; 526 527 case 'h': /* Header Digest */ 528 opt->HeaderDigest = ISCSI_DIGEST_CRC32C; 529 opt->is_present.HeaderDigest = 1; 530 break; 531 532 case 'd': /* Data Digest */ 533 opt->DataDigest = ISCSI_DIGEST_CRC32C; 534 opt->is_present.DataDigest = 1; 535 break; 536 537 case 'l': /* Data Segment Length */ 538 opt->MaxRecvDataSegmentLength = get_dsl(sp, argv[i]); 539 opt->is_present.MaxRecvDataSegmentLength = 1; 540 if (!argv[i][2]) 541 argv[i + 1] = NULL; 542 break; 543 544 default: 545 continue; 546 } 547 if (!argv[i][2]) 548 argv[i + 1] = NULL; 549 550 argv[i] = NULL; 551 } 552 return found; 553 } 554 555 556 /* 557 * cl_get_id: 558 * Get an identifier (symbolic or numeric) 559 * 560 * Parameter: 561 * ident the parameter identifier character 562 * sid the ID 563 * argc, argv program parameters (shifted) 564 * 565 * Returns: 0 if there is no ID, 1 otherwise. 566 * Aborts app on bad parameter. 567 */ 568 569 int 570 cl_get_id(char ident, iscsid_sym_id_t * sid, int argc, char **argv) 571 { 572 int i, found; 573 char *sp; 574 575 found = FALSE; 576 memset(sid, 0, sizeof(*sid)); 577 578 for (i = 0; i < argc && !found; i++) { 579 if (!argv[i] || argv[i][0] != '-') 580 continue; 581 582 if (argv[i][1] == ident) { 583 sp = (argv[i][2]) ? &argv[i][2] : 584 ((i + 1 < argc) ? argv[i + 1] : NULL); 585 586 if (!sp || !*sp) 587 arg_error(argv[i], "Missing ID"); 588 if (strlen(sp) >= ISCSI_STRING_LENGTH) 589 arg_error(argv[i], "ID String too long"); 590 if (!sscanf(sp, "%d", &sid->id)) 591 strlcpy((char *)sid->name, sp, sizeof(sid->name)); 592 else if (!sid->id) 593 arg_error(argv[i], "Invalid ID"); 594 595 if (!argv[i][2]) 596 argv[i + 1] = NULL; 597 598 argv[i] = NULL; 599 found = TRUE; 600 } 601 } 602 return found; 603 } 604 605 606 /* 607 * cl_get_symname: 608 * Get a symbolic name 609 * 610 * Parameter: 611 * sn the name 612 * argc, argv program parameters (shifted) 613 * 614 * Returns: 0 if there is no symbolic name, 1 otherwise. 615 * Aborts app on bad parameter. 616 */ 617 618 int 619 cl_get_symname(uint8_t * sn, int argc, char **argv) 620 { 621 int i, found; 622 char *sp; 623 624 found = FALSE; 625 *sn = '\0'; 626 627 for (i = 0; i < argc && !found; i++) { 628 if (!argv[i] || argv[i][0] != '-') 629 continue; 630 631 if (argv[i][1] == 'N') { 632 sp = (argv[i][2]) ? &argv[i][2] 633 : ((i + 1 < argc) ? argv[i + 1] : NULL); 634 635 if (!sp || !*sp) 636 arg_error(argv[i], "Symbolic name missing"); 637 if (isdigit((unsigned char)*sp)) 638 arg_error(argv[i], "Symbolic name must not be numeric"); 639 if (strlen(sp) >= ISCSI_STRING_LENGTH) 640 arg_error(argv[i], "Symbolic name too long"); 641 642 strlcpy((char *)sn, sp, ISCSI_STRING_LENGTH); 643 644 if (!argv[i][2]) 645 argv[i + 1] = NULL; 646 647 argv[i] = NULL; 648 found = TRUE; 649 } 650 } 651 return found; 652 } 653 654 655 /* 656 * cl_get_string: 657 * Get a string value 658 * 659 * Parameter: 660 * ident the parameter identifier character 661 * pstr the result string 662 * argc, argv program parameters (shifted) 663 * 664 * Returns: 0 if there is no string, 1 otherwise. 665 * Aborts app on bad parameter. 666 */ 667 668 int 669 cl_get_string(char ident, char *pstr, int argc, char **argv) 670 { 671 int i, found; 672 char *sp; 673 674 found = FALSE; 675 *pstr = '\0'; 676 677 for (i = 0; i < argc && !found; i++) { 678 if (!argv[i] || argv[i][0] != '-') 679 continue; 680 681 if (argv[i][1] == ident) { 682 sp = (argv[i][2]) ? &argv[i][2] 683 : ((i + 1 < argc) ? argv[i + 1] : NULL); 684 685 get_str(pstr, sp, argv[i], "String"); 686 687 if (!argv[i][2]) 688 argv[i + 1] = NULL; 689 690 argv[i] = NULL; 691 found = TRUE; 692 } 693 } 694 return found; 695 } 696 697 698 /* 699 * cl_get_opt: 700 * Get an option with no value 701 * 702 * Parameter: 703 * ident the parameter identifier character 704 * argc, argv program parameters (shifted) 705 * 706 * Returns: 0 if the option was not found, 1 otherwise. 707 * Aborts app on bad parameter. 708 */ 709 710 int 711 cl_get_opt(char ident, int argc, char **argv) 712 { 713 int i, found; 714 715 found = FALSE; 716 717 for (i = 0; i < argc && !found; i++) { 718 if (!argv[i] || argv[i][0] != '-') 719 continue; 720 721 if (argv[i][1] == ident) { 722 argv[i] = NULL; 723 found = TRUE; 724 } 725 } 726 return found; 727 } 728 729 730 /* 731 * cl_get_char: 732 * Get an option with a character value 733 * 734 * Parameter: 735 * ident the parameter identifier character 736 * argc, argv program parameters (shifted) 737 * 738 * Returns: The option character (0 if not found). 739 * Aborts app on bad parameter. 740 */ 741 742 char 743 cl_get_char(char ident, int argc, char **argv) 744 { 745 int i, found; 746 char *sp; 747 char ch = 0; 748 749 found = FALSE; 750 751 for (i = 0; i < argc && !found; i++) { 752 if (!argv[i] || argv[i][0] != '-') 753 continue; 754 755 if (argv[i][1] == ident) { 756 sp = (argv[i][2]) ? &argv[i][2] 757 : ((i + 1 < argc) ? argv[i + 1] : NULL); 758 759 if (!sp || !*sp) 760 arg_error(argv[i], "Option character missing"); 761 if (strlen(sp) > 1) 762 arg_error(argv[i], "Option invalid"); 763 ch = *sp; 764 765 if (!argv[i][2]) 766 argv[i + 1] = NULL; 767 768 argv[i] = NULL; 769 found = TRUE; 770 } 771 } 772 773 return ch; 774 } 775 776 777 /* 778 * cl_get_int: 779 * Get an option with an integer value 780 * 781 * Parameter: 782 * ident the parameter identifier character 783 * argc, argv program parameters (shifted) 784 * 785 * Returns: The option value (0 if not found). 786 * Aborts app on bad parameter. 787 */ 788 789 int 790 cl_get_int(char ident, int argc, char **argv) 791 { 792 int i, found; 793 char *sp; 794 int val = 0; 795 796 found = FALSE; 797 798 for (i = 0; i < argc && !found; i++) { 799 if (!argv[i] || argv[i][0] != '-') 800 continue; 801 802 if (argv[i][1] == ident) { 803 sp = (argv[i][2]) ? &argv[i][2] 804 : ((i + 1 < argc) ? argv[i + 1] : NULL); 805 806 if (!sp || !*sp) 807 arg_error(argv[i], "Option value missing"); 808 if (!sscanf(sp, "%i", &val)) 809 arg_error(argv[i], "Integer expected"); 810 811 if (!argv[i][2]) 812 argv[i + 1] = NULL; 813 814 argv[i] = NULL; 815 found = TRUE; 816 } 817 } 818 819 return val; 820 } 821 822 823 /* 824 * cl_get_uint: 825 * Get an option with a positive integer value 826 * 827 * Parameter: 828 * ident the parameter identifier character 829 * argc, argv program parameters (shifted) 830 * 831 * Returns: The option value (-1 if not found). 832 * Aborts app on bad parameter. 833 */ 834 835 #if 0 836 int 837 cl_get_uint(char ident, int argc, char **argv) 838 { 839 int i, found; 840 char *sp; 841 int val = -1; 842 843 found = FALSE; 844 845 for (i = 0; i < argc && !found; i++) { 846 if (!argv[i] || argv[i][0] != '-') 847 continue; 848 849 if (argv[i][1] == ident) { 850 sp = (argv[i][2]) ? &argv[i][2] 851 : ((i + 1 < argc) ? argv[i + 1] : NULL); 852 853 if (!sp || !*sp) 854 arg_error(argv[i], "Option value missing"); 855 if (!sscanf(sp, "%i", &val)) 856 arg_error(argv[i], "Positive integer expected"); 857 858 if (!argv[i][2]) 859 argv[i + 1] = NULL; 860 861 argv[i] = NULL; 862 found = TRUE; 863 } 864 } 865 866 return val; 867 } 868 #endif 869 870 871 /* 872 * cl_get_longlong: 873 * Get an option with a 64-bit value 874 * 875 * Parameter: 876 * ident the parameter identifier character 877 * argc, argv program parameters (shifted) 878 * 879 * Returns: The option value (0 if not found). 880 * Aborts app on bad parameter. 881 */ 882 883 uint64_t 884 cl_get_longlong(char ident, int argc, char **argv) 885 { 886 int i, found; 887 char *sp; 888 uint64_t val = 0; 889 890 found = FALSE; 891 892 for (i = 0; i < argc && !found; i++) { 893 if (!argv[i] || argv[i][0] != '-') 894 continue; 895 896 if (argv[i][1] == ident) { 897 sp = (argv[i][2]) ? &argv[i][2] 898 : ((i + 1 < argc) ? argv[i + 1] : NULL); 899 900 if (!sp || !*sp) 901 arg_error(argv[i], "Option value missing"); 902 if (!sscanf(sp, "%qi", (long long *)(void *)&val)) 903 arg_error(argv[i], "Integer expected"); 904 905 if (!argv[i][2]) 906 argv[i + 1] = NULL; 907 908 argv[i] = NULL; 909 found = TRUE; 910 } 911 } 912 913 return val; 914 } 915