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