iscsic_parse.c revision 1.2 1 /* $NetBSD: iscsic_parse.c,v 1.2 2011/10/30 18:40:06 christos 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 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
282 int
283 cl_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
340 int
341 cl_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
420 int
421 cl_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
500 int
501 cl_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
573 int
574 cl_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
623 int
624 cl_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
674 int
675 cl_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
717 int
718 cl_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
750 char
751 cl_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
798 int
799 cl_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
846 int
847 cl_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
894 uint64_t
895 cl_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