1/* $NetBSD: iscsic_parse.c,v 1.1 2011/10/23 21:11:23 agc 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 48STATIC void 49get_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 115STATIC uint16_t 116get_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 143STATIC uint32_t 144get_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 172STATIC void 173get_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 199int 200cl_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 DEB(9, ("cl_get_target returns %zu\n", len)); 266 return (int)len; 267} 268 269 270/* 271 * cl_get_isns: 272 * Get an iSNS server address specification that may include name, address 273 * and port. 274 * 275 * Parameter: 276 * srv add_isns_server request parameter 277 * argc, argv program parameters (shifted) 278 * 279 * Returns: 0 on error, 1 if OK. 280 */ 281 282int 283cl_get_isns(iscsid_add_isns_server_req_t * srv, int argc, char **argv) 284{ 285 iscsi_portal_address_t addr; 286 char *sp; 287 int i, found; 288 289 (void) memset(&addr, 0x0, sizeof(addr)); 290 found = FALSE; 291 292 for (i = 0; i < argc; i++) { 293 if (!argv[i] || argv[i][0] != '-') 294 continue; 295 296 sp = (argv[i][2]) ? &argv[i][2] : ((i + 1 < argc) ? argv[i + 1] : NULL); 297 298 switch (argv[i][1]) { 299 case 'N': /* symbolic name */ 300 get_str((char *)srv->name, sp, argv[i], "Server name"); 301 break; 302 303 case 'a': /* target address */ 304 get_address(&addr, sp, argv[i]); 305 found = TRUE; 306 break; 307 308 case 'p': /* port */ 309 addr.port = get_short_int(sp, argv[i], "Port"); 310 break; 311 312 default: 313 continue; 314 } 315 if (!argv[i][2]) { 316 argv[i + 1] = NULL; 317 } 318 argv[i] = NULL; 319 } 320 321 strlcpy((char *)srv->address, (char *)addr.address, sizeof(srv->address)); 322 srv->port = addr.port; 323 324 return found; 325} 326 327 328/* 329 * cl_get_auth_opts: 330 * Get authentication options. 331 * 332 * Parameter: 333 * auth authentication parameters 334 * argc, argv program parameters (shifted) 335 * 336 * Returns: 0 if there are no authorization options, 1 otherwise. 337 * Aborts app on bad parameter. 338 */ 339 340int 341cl_get_auth_opts(iscsid_set_target_authentication_req_t *auth, 342 int argc, char **argv) 343{ 344 int n, i, found; 345 char *sp; 346 347 found = FALSE; 348 memset(auth, 0, sizeof(*auth)); 349 350 for (i = 0; i < argc; i++) { 351 if (!argv[i] || argv[i][0] != '-') { 352 continue; 353 } 354 sp = (argv[i][2]) ? &argv[i][2] : ((i + 1 < argc) ? argv[i + 1] : NULL); 355 356 switch (argv[i][1]) { 357 case 't': /* authentication type */ 358 if (!sp || !*sp) 359 arg_error(argv[i], "Missing authentication type"); 360 n = 0; 361 while (*sp) { 362 switch (*sp) { 363 case 'n': /* no authentication */ 364 auth->auth_info.auth_type[n] = ISCSI_AUTH_None; 365 break; 366 case 'c': /* CHAP authentication */ 367 auth->auth_info.auth_type[n] = ISCSI_AUTH_CHAP; 368 break; 369 case 'C': /* Mutual CHAP authentication */ 370 auth->auth_info.auth_type[n] = ISCSI_AUTH_CHAP; 371 auth->auth_info.mutual_auth = 1; 372 break; 373 default: 374 arg_error(argv[i], "Bad authentication type '%c'", *sp); 375 } 376 sp++; 377 n++; 378 } 379 auth->auth_info.auth_number = n; 380 break; 381 382 case 'u': /* user name */ 383 get_str((char *)auth->user_name, sp, argv[i], "User name"); 384 break; 385 386 case 's': /* secret */ 387 get_str((char *)auth->password, sp, argv[i], "Secret"); 388 break; 389 390 case 'S': /* target secret */ 391 get_str((char *)auth->target_password, sp, argv[i], "Target secret"); 392 break; 393 394 default: 395 continue; 396 } 397 if (!argv[i][2]) 398 argv[i + 1] = NULL; 399 400 argv[i] = NULL; 401 found = TRUE; 402 } 403 DEB(9, ("cl_get_auth_opts returns %d\n", found)); 404 return found; 405} 406 407 408/* 409 * cl_get_target_opts: 410 * Get session/connection options. 411 * 412 * Parameter: 413 * opt target options 414 * argc, argv program parameters (shifted) 415 * 416 * Returns: 0 if there are no target options, 1 otherwise. 417 * Aborts app on bad parameter. 418 */ 419 420int 421cl_get_target_opts(iscsid_get_set_target_options_t * opt, int argc, char **argv) 422{ 423 int i, found; 424 char *sp; 425 426 found = FALSE; 427 memset(opt, 0, sizeof(*opt)); 428 429 for (i = 0; i < argc; i++) { 430 if (!argv[i] || argv[i][0] != '-') 431 continue; 432 433 sp = (argv[i][2]) ? &argv[i][2] : ((i + 1 < argc) ? argv[i + 1] : NULL); 434 435 switch (argv[i][1]) { 436 case 'h': /* Header Digest */ 437 opt->HeaderDigest = ISCSI_DIGEST_CRC32C; 438 opt->is_present.HeaderDigest = 1; 439 break; 440 441 case 'd': /* Data Digest */ 442 opt->DataDigest = ISCSI_DIGEST_CRC32C; 443 opt->is_present.DataDigest = 1; 444 break; 445 446 case 'w': /* Time 2 Wait */ 447 opt->DefaultTime2Wait = get_short_int(sp, argv[i], "Time to wait"); 448 opt->is_present.DefaultTime2Wait = 1; 449 if (!argv[i][2]) 450 argv[i + 1] = NULL; 451 break; 452 453 case 'r': /* Time 2 Retain */ 454 opt->DefaultTime2Retain = get_short_int(sp, argv[i], 455 "Time to retain"); 456 opt->is_present.DefaultTime2Retain = 1; 457 if (!argv[i][2]) 458 argv[i + 1] = NULL; 459 break; 460 461 case 'e': /* Error Recovery Level */ 462 opt->ErrorRecoveryLevel = get_short_int(sp, argv[i], 463 "ErrorRecoveryLevel"); 464 opt->is_present.ErrorRecoveryLevel = 1; 465 if (!argv[i][2]) 466 argv[i + 1] = NULL; 467 break; 468 469 case 'l': /* Data Segment Length */ 470 opt->MaxRecvDataSegmentLength = get_dsl(sp, argv[i]); 471 opt->is_present.MaxRecvDataSegmentLength = 1; 472 if (!argv[i][2]) 473 argv[i + 1] = NULL; 474 break; 475 476 default: 477 continue; 478 } 479 argv[i] = NULL; 480 found = TRUE; 481 } 482 DEB(9, ("cl_get_target_opts returns %d\n", found)); 483 return found; 484} 485 486 487/* 488 * cl_get_portal: 489 * Get a portal address specification that may include address, port, 490 * and group tag, plus portal options. 491 * 492 * Parameter: 493 * port add portal request parameter 494 * argc, argv program parameters (shifted) 495 * 496 * Returns: FALSE if there is no portal, else TRUE. 497 * Aborts app on bad parameter or mem allocation error. 498 */ 499 500int 501cl_get_portal(iscsid_add_portal_req_t * port, int argc, char **argv) 502{ 503 char *sp; 504 int i, found; 505 iscsid_portal_options_t *opt = &port->options; 506 507 found = FALSE; 508 memset(port, 0, sizeof(*port)); 509 510 for (i = 0; i < argc; i++) { 511 if (!argv[i] || argv[i][0] != '-') 512 continue; 513 514 sp = (argv[i][2]) ? &argv[i][2] : ((i + 1 < argc) ? argv[i + 1] : NULL); 515 516 switch (argv[i][1]) { 517 case 'a': /* target address */ 518 get_address(&port->portal, sp, argv[i]); 519 found = TRUE; 520 break; 521 522 case 'p': /* port */ 523 port->portal.port = get_short_int(sp, argv[i], "Port"); 524 break; 525 526 case 'g': /* group tag */ 527 port->portal.group_tag = get_short_int(sp, argv[i], "Group tag"); 528 break; 529 530 case 'h': /* Header Digest */ 531 opt->HeaderDigest = ISCSI_DIGEST_CRC32C; 532 opt->is_present.HeaderDigest = 1; 533 break; 534 535 case 'd': /* Data Digest */ 536 opt->DataDigest = ISCSI_DIGEST_CRC32C; 537 opt->is_present.DataDigest = 1; 538 break; 539 540 case 'l': /* Data Segment Length */ 541 opt->MaxRecvDataSegmentLength = get_dsl(sp, argv[i]); 542 opt->is_present.MaxRecvDataSegmentLength = 1; 543 if (!argv[i][2]) 544 argv[i + 1] = NULL; 545 break; 546 547 default: 548 continue; 549 } 550 if (!argv[i][2]) 551 argv[i + 1] = NULL; 552 553 argv[i] = NULL; 554 } 555 DEB(9, ("cl_get_portal returns %d\n", found)); 556 return found; 557} 558 559 560/* 561 * cl_get_id: 562 * Get an identifier (symbolic or numeric) 563 * 564 * Parameter: 565 * ident the parameter identifier character 566 * sid the ID 567 * argc, argv program parameters (shifted) 568 * 569 * Returns: 0 if there is no ID, 1 otherwise. 570 * Aborts app on bad parameter. 571 */ 572 573int 574cl_get_id(char ident, iscsid_sym_id_t * sid, int argc, char **argv) 575{ 576 int i, found; 577 char *sp; 578 579 found = FALSE; 580 memset(sid, 0, sizeof(*sid)); 581 582 for (i = 0; i < argc && !found; i++) { 583 if (!argv[i] || argv[i][0] != '-') 584 continue; 585 586 if (argv[i][1] == ident) { 587 sp = (argv[i][2]) ? &argv[i][2] : 588 ((i + 1 < argc) ? argv[i + 1] : NULL); 589 590 if (!sp || !*sp) 591 arg_error(argv[i], "Missing ID"); 592 if (strlen(sp) >= ISCSI_STRING_LENGTH) 593 arg_error(argv[i], "ID String too long"); 594 if (!sscanf(sp, "%d", &sid->id)) 595 strlcpy((char *)sid->name, sp, sizeof(sid->name)); 596 else if (!sid->id) 597 arg_error(argv[i], "Invalid ID"); 598 599 if (!argv[i][2]) 600 argv[i + 1] = NULL; 601 602 argv[i] = NULL; 603 found = TRUE; 604 } 605 } 606 DEB(9, ("cl_get_id returns %d\n", found)); 607 return found; 608} 609 610 611/* 612 * cl_get_symname: 613 * Get a symbolic name 614 * 615 * Parameter: 616 * sn the name 617 * argc, argv program parameters (shifted) 618 * 619 * Returns: 0 if there is no symbolic name, 1 otherwise. 620 * Aborts app on bad parameter. 621 */ 622 623int 624cl_get_symname(uint8_t * sn, int argc, char **argv) 625{ 626 int i, found; 627 char *sp; 628 629 found = FALSE; 630 *sn = '\0'; 631 632 for (i = 0; i < argc && !found; i++) { 633 if (!argv[i] || argv[i][0] != '-') 634 continue; 635 636 if (argv[i][1] == 'N') { 637 sp = (argv[i][2]) ? &argv[i][2] 638 : ((i + 1 < argc) ? argv[i + 1] : NULL); 639 640 if (!sp || !*sp) 641 arg_error(argv[i], "Symbolic name missing"); 642 if (isdigit((unsigned char)*sp)) 643 arg_error(argv[i], "Symbolic name must not be numeric"); 644 if (strlen(sp) >= ISCSI_STRING_LENGTH) 645 arg_error(argv[i], "Symbolic name too long"); 646 647 strlcpy((char *)sn, sp, ISCSI_STRING_LENGTH); 648 649 if (!argv[i][2]) 650 argv[i + 1] = NULL; 651 652 argv[i] = NULL; 653 found = TRUE; 654 } 655 } 656 DEB(9, ("cl_get_symname returns %d\n", found)); 657 return found; 658} 659 660 661/* 662 * cl_get_string: 663 * Get a string value 664 * 665 * Parameter: 666 * ident the parameter identifier character 667 * pstr the result string 668 * argc, argv program parameters (shifted) 669 * 670 * Returns: 0 if there is no string, 1 otherwise. 671 * Aborts app on bad parameter. 672 */ 673 674int 675cl_get_string(char ident, char *pstr, int argc, char **argv) 676{ 677 int i, found; 678 char *sp; 679 680 found = FALSE; 681 *pstr = '\0'; 682 683 for (i = 0; i < argc && !found; i++) { 684 if (!argv[i] || argv[i][0] != '-') 685 continue; 686 687 if (argv[i][1] == ident) { 688 sp = (argv[i][2]) ? &argv[i][2] 689 : ((i + 1 < argc) ? argv[i + 1] : NULL); 690 691 get_str(pstr, sp, argv[i], "String"); 692 693 if (!argv[i][2]) 694 argv[i + 1] = NULL; 695 696 argv[i] = NULL; 697 found = TRUE; 698 } 699 } 700 DEB(9, ("cl_get_string returns %d\n", found)); 701 return found; 702} 703 704 705/* 706 * cl_get_opt: 707 * Get an option with no value 708 * 709 * Parameter: 710 * ident the parameter identifier character 711 * argc, argv program parameters (shifted) 712 * 713 * Returns: 0 if the option was not found, 1 otherwise. 714 * Aborts app on bad parameter. 715 */ 716 717int 718cl_get_opt(char ident, int argc, char **argv) 719{ 720 int i, found; 721 722 found = FALSE; 723 724 for (i = 0; i < argc && !found; i++) { 725 if (!argv[i] || argv[i][0] != '-') 726 continue; 727 728 if (argv[i][1] == ident) { 729 argv[i] = NULL; 730 found = TRUE; 731 } 732 } 733 DEB(9, ("cl_get_opt returns %d\n", found)); 734 return found; 735} 736 737 738/* 739 * cl_get_char: 740 * Get an option with a character value 741 * 742 * Parameter: 743 * ident the parameter identifier character 744 * argc, argv program parameters (shifted) 745 * 746 * Returns: The option character (0 if not found). 747 * Aborts app on bad parameter. 748 */ 749 750char 751cl_get_char(char ident, int argc, char **argv) 752{ 753 int i, found; 754 char *sp; 755 char ch = 0; 756 757 found = FALSE; 758 759 for (i = 0; i < argc && !found; i++) { 760 if (!argv[i] || argv[i][0] != '-') 761 continue; 762 763 if (argv[i][1] == ident) { 764 sp = (argv[i][2]) ? &argv[i][2] 765 : ((i + 1 < argc) ? argv[i + 1] : NULL); 766 767 if (!sp || !*sp) 768 arg_error(argv[i], "Option character missing"); 769 if (strlen(sp) > 1) 770 arg_error(argv[i], "Option invalid"); 771 ch = *sp; 772 773 if (!argv[i][2]) 774 argv[i + 1] = NULL; 775 776 argv[i] = NULL; 777 found = TRUE; 778 } 779 } 780 DEB(9, ("cl_get_charopt returns %c\n", ch)); 781 782 return ch; 783} 784 785 786/* 787 * cl_get_int: 788 * Get an option with an integer value 789 * 790 * Parameter: 791 * ident the parameter identifier character 792 * argc, argv program parameters (shifted) 793 * 794 * Returns: The option value (0 if not found). 795 * Aborts app on bad parameter. 796 */ 797 798int 799cl_get_int(char ident, int argc, char **argv) 800{ 801 int i, found; 802 char *sp; 803 int val = 0; 804 805 found = FALSE; 806 807 for (i = 0; i < argc && !found; i++) { 808 if (!argv[i] || argv[i][0] != '-') 809 continue; 810 811 if (argv[i][1] == ident) { 812 sp = (argv[i][2]) ? &argv[i][2] 813 : ((i + 1 < argc) ? argv[i + 1] : NULL); 814 815 if (!sp || !*sp) 816 arg_error(argv[i], "Option value missing"); 817 if (!sscanf(sp, "%i", &val)) 818 arg_error(argv[i], "Integer expected"); 819 820 if (!argv[i][2]) 821 argv[i + 1] = NULL; 822 823 argv[i] = NULL; 824 found = TRUE; 825 } 826 } 827 DEB(9, ("cl_get_int returns %d\n", val)); 828 829 return val; 830} 831 832 833/* 834 * cl_get_uint: 835 * Get an option with a positive integer value 836 * 837 * Parameter: 838 * ident the parameter identifier character 839 * argc, argv program parameters (shifted) 840 * 841 * Returns: The option value (-1 if not found). 842 * Aborts app on bad parameter. 843 */ 844 845#if 0 846int 847cl_get_uint(char ident, int argc, char **argv) 848{ 849 int i, found; 850 char *sp; 851 int val = -1; 852 853 found = FALSE; 854 855 for (i = 0; i < argc && !found; i++) { 856 if (!argv[i] || argv[i][0] != '-') 857 continue; 858 859 if (argv[i][1] == ident) { 860 sp = (argv[i][2]) ? &argv[i][2] 861 : ((i + 1 < argc) ? argv[i + 1] : NULL); 862 863 if (!sp || !*sp) 864 arg_error(argv[i], "Option value missing"); 865 if (!sscanf(sp, "%i", &val)) 866 arg_error(argv[i], "Positive integer expected"); 867 868 if (!argv[i][2]) 869 argv[i + 1] = NULL; 870 871 argv[i] = NULL; 872 found = TRUE; 873 } 874 } 875 DEB(9, ("cl_get_uint returns %d\n", val)); 876 877 return val; 878} 879#endif 880 881 882/* 883 * cl_get_longlong: 884 * Get an option with a 64-bit value 885 * 886 * Parameter: 887 * ident the parameter identifier character 888 * argc, argv program parameters (shifted) 889 * 890 * Returns: The option value (0 if not found). 891 * Aborts app on bad parameter. 892 */ 893 894uint64_t 895cl_get_longlong(char ident, int argc, char **argv) 896{ 897 int i, found; 898 char *sp; 899 uint64_t val = 0; 900 901 found = FALSE; 902 903 for (i = 0; i < argc && !found; i++) { 904 if (!argv[i] || argv[i][0] != '-') 905 continue; 906 907 if (argv[i][1] == ident) { 908 sp = (argv[i][2]) ? &argv[i][2] 909 : ((i + 1 < argc) ? argv[i + 1] : NULL); 910 911 if (!sp || !*sp) 912 arg_error(argv[i], "Option value missing"); 913 if (!sscanf(sp, "%qi", (long long *)(void *)&val)) 914 arg_error(argv[i], "Integer expected"); 915 916 if (!argv[i][2]) 917 argv[i + 1] = NULL; 918 919 argv[i] = NULL; 920 found = TRUE; 921 } 922 } 923 DEB(9, ("cl_get_longlong returns %qd\n", val)); 924 925 return val; 926} 927