Lines Matching +full:test2 +full:. +full:good
4 * Copyright (c) 2003, 2004 Silicon Graphics International Corp.
5 * Copyright (c) 1997-2007 Kenneth D. Merry
7 * Copyright (c) 2018 Marcelo Araujo <araujo@FreeBSD.org>
8 * All rights reserved.
11 * under sponsorship from the FreeBSD Foundation.
16 * 1. Redistributions of source code must retain the above copyright
18 * without modification.
19 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
23 * binary redistribution.
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * POSSIBILITY OF SUCH DAMAGES.
38 * $Id: //depot/users/kenm/FreeBSD-test2/usr.sbin/ctladm/ctladm.c#4 $
41 * CAM Target Layer exercise program.
43 * Author: Ken Merry <ken@FreeBSD.org>
46 #include <sys/param.h>
47 #include <sys/callout.h>
48 #include <sys/ioctl.h>
49 #include <sys/linker.h>
50 #include <sys/module.h>
51 #include <sys/queue.h>
52 #include <sys/sbuf.h>
53 #include <sys/nv.h>
54 #include <sys/stat.h>
55 #include <bsdxml.h>
56 #include <ctype.h>
57 #include <err.h>
58 #include <errno.h>
59 #include <fcntl.h>
60 #include <getopt.h>
61 #include <stdlib.h>
62 #include <stdint.h>
63 #include <stdio.h>
64 #include <string.h>
65 #include <unistd.h>
66 #include <cam/scsi/scsi_all.h>
67 #include <cam/scsi/scsi_message.h>
68 #include <cam/ctl/ctl.h>
69 #include <cam/ctl/ctl_io.h>
70 #include <cam/ctl/ctl_backend.h>
71 #include <cam/ctl/ctl_ioctl.h>
72 #include <cam/ctl/ctl_util.h>
73 #include <cam/ctl/ctl_scsi_all.h>
74 #include <dev/nvmf/nvmf_proto.h>
75 #include <camlib.h>
76 #include <libutil.h>
77 #include "ctladm.h"
298 ooa.entries = malloc(len); in cctl_dump_ooa()
299 if (ooa.entries == NULL) { in cctl_dump_ooa()
304 ooa.lun_num = lun; in cctl_dump_ooa()
306 ooa.flags |= CTL_OOA_FLAG_ALL_LUNS; in cctl_dump_ooa()
307 ooa.alloc_len = len; in cctl_dump_ooa()
308 ooa.alloc_num = num_entries; in cctl_dump_ooa()
315 if (ooa.status == CTL_OOA_NEED_MORE_SPACE) { in cctl_dump_ooa()
317 free(ooa.entries); in cctl_dump_ooa()
318 ooa.entries = NULL; in cctl_dump_ooa()
322 if (ooa.status != CTL_OOA_OK) { in cctl_dump_ooa()
324 ooa.status); in cctl_dump_ooa()
330 for (i = 0; i < ooa.fill_num; i++) { in cctl_dump_ooa()
336 entry = &ooa.entries[i]; in cctl_dump_ooa()
338 delta_bt = ooa.cur_bt; in cctl_dump_ooa()
341 cmd_latency = ts.tv_sec * 1000; in cctl_dump_ooa()
342 if (ts.tv_nsec > 0) in cctl_dump_ooa()
343 cmd_latency += ts.tv_nsec / 1000000; in cctl_dump_ooa()
345 fprintf(stdout, "LUN %jd tag 0x%jx%s%s%s%s%s%s%s: %s. CDB: %s " in cctl_dump_ooa()
366 free(ooa.entries); in cctl_dump_ooa()
429 warnx("ctladm port -l is deprecated. " in cctl_port()
553 * a specific frontend, but not both. in cctl_port()
556 * all. This is primarily needed for the enable/disable ioctls. in cctl_port()
557 * This will be a no-op for the listing code. For the set ioctl, in cctl_port()
558 * we'll throw an error, since that only works on one port at a time. in cctl_port()
570 * These are needed for all but list/dump mode. in cctl_port()
572 entry.port_type = port_type; in cctl_port()
573 entry.targ_port = targ_port; in cctl_port()
597 strlcpy(req.driver, driver, sizeof(req.driver)); in cctl_port()
598 req.result = result_buf; in cctl_port()
599 req.result_len = sizeof(result_buf); in cctl_port()
602 req.reqtype = CTL_REQ_REMOVE; in cctl_port()
607 req.reqtype = CTL_REQ_CREATE; in cctl_port()
609 req.args = nvlist_pack(option_list, &req.args_len); in cctl_port()
610 if (req.args == NULL) { in cctl_port()
617 free(req.args); in cctl_port()
624 switch (req.status) { in cctl_port()
626 warnx("error: %s", req.error_str); in cctl_port()
630 warnx("warning: %s", req.error_str); in cctl_port()
634 req.result_nvl = nvlist_unpack(result_buf, req.result_len, 0); in cctl_port()
635 if (req.result_nvl == NULL) { in cctl_port()
639 created_port = nvlist_get_number(req.result_nvl, "port_id"); in cctl_port()
644 nvlist_destroy(req.result_nvl); in cctl_port()
649 warnx("unknown status: %d", req.status); in cctl_port()
664 entry.flags |= CTL_PORT_WWNN_VALID; in cctl_port()
665 entry.wwnn = wwnn; in cctl_port()
668 entry.flags |= CTL_PORT_WWPN_VALID; in cctl_port()
669 entry.wwpn = wwpn; in cctl_port()
720 } while (((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS) in cctl_do_io()
762 delay_info.delay_loc = CTL_DELAY_LOC_DATAMOVE; in cctl_delay()
764 delay_info.delay_loc = CTL_DELAY_LOC_DONE; in cctl_delay()
773 delay_info.delay_type = CTL_DELAY_TYPE_ONESHOT; in cctl_delay()
775 delay_info.delay_type = CTL_DELAY_TYPE_CONT; in cctl_delay()
782 delay_info.lun_id = lun; in cctl_delay()
783 delay_info.delay_secs = delaytime; in cctl_delay()
790 switch (delay_info.status) { in cctl_delay()
803 delay_info.delay_type); in cctl_delay()
818 delay_info.status); in cctl_delay()
868 err_desc.lun_id = lun; in cctl_error_inject()
888 if (err_desc.lun_error != CTL_LUN_INJ_NONE) { in cctl_error_inject()
896 err_desc.lun_error = err_type; in cctl_error_inject()
902 err_desc.error_pattern |= pattern; in cctl_error_inject()
964 hook.argc = argc - optind; in cctl_error_inject()
965 hook.argv = argv + optind; in cctl_error_inject()
966 hook.got = 0; in cctl_error_inject()
974 (uint8_t *)&err_desc.custom_sense, in cctl_error_inject()
977 optind += hook.got; in cctl_error_inject()
986 err_desc.serial = delete_id; in cctl_error_inject()
995 if (err_desc.lun_error == CTL_LUN_INJ_NONE) { in cctl_error_inject()
1000 } else if ((err_desc.lun_error == CTL_LUN_INJ_CUSTOM) in cctl_error_inject()
1008 err_desc.lun_error |= CTL_LUN_INJ_CONTINUOUS; in cctl_error_inject()
1012 * wants returned from stdin. in cctl_error_inject()
1017 u_int8_t *buf_ptr = (uint8_t *)&err_desc.custom_sense; in cctl_error_inject()
1031 if (err_desc.error_pattern == CTL_LUN_PAT_NONE) { in cctl_error_inject()
1038 err_desc.error_pattern |= CTL_LUN_PAT_RANGE; in cctl_error_inject()
1042 * custom patterns. At that point, the user could specify in cctl_error_inject()
1044 * to verify whether range checking is possible there. The in cctl_error_inject()
1046 * executed. in cctl_error_inject()
1049 if ((err_desc.pattern & CTL_LUN_PAT_READWRITE) == 0) { in cctl_error_inject()
1056 err_desc.lba_range.lba = lba; in cctl_error_inject()
1057 err_desc.lba_range.len = len; in cctl_error_inject()
1065 (uintmax_t)err_desc.serial); in cctl_error_inject()
1087 * if we ever acquire the ability to have multiple targets. in cctl_lunlist()
1104 switch (lun_data->luns[i].lundata[0] & RPL_LUNDATA_ATYP_MASK) { in cctl_lunlist()
1106 lun_val = lun_data->luns[i].lundata[1]; in cctl_lunlist()
1109 lun_val = (lun_data->luns[i].lundata[0] & in cctl_lunlist()
1111 (lun_data->luns[i].lundata[1] << in cctl_lunlist()
1118 lun_data->luns[i].lundata[0] & in cctl_lunlist()
1212 io->io_hdr.nexus.targ_lun = lun; in cctl_sync_cache()
1213 io->io_hdr.nexus.initid = iid; in cctl_sync_cache()
1220 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) { in cctl_sync_cache()
1258 * pending I/O will finish before the stop command executes. This in cctl_start_stop()
1261 * to any other command except an INQUIRY. (See ctl_ser_table.c.) in cctl_start_stop()
1272 io->io_hdr.nexus.targ_lun = lun; in cctl_start_stop()
1273 io->io_hdr.nexus.initid = iid; in cctl_start_stop()
1281 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) { in cctl_start_stop()
1437 io->io_hdr.nexus.targ_lun = lun; in cctl_mode_sense()
1438 io->io_hdr.nexus.initid = iid; in cctl_mode_sense()
1445 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) { in cctl_mode_sense()
1450 if (io->scsiio.cdb[0] == MODE_SENSE_6) { in cctl_mode_sense()
1587 io->io_hdr.nexus.initid = iid; in cctl_read_capacity()
1588 io->io_hdr.nexus.targ_lun = lun; in cctl_read_capacity()
1595 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) { in cctl_read_capacity()
1661 io->io_hdr.flags |= CTL_FLAG_NO_DATAMOVE; in cctl_read_write()
1776 io->io_hdr.nexus.targ_lun = lun; in cctl_read_write()
1777 io->io_hdr.nexus.initid = iid; in cctl_read_write()
1784 if (((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) in cctl_read_write()
1793 } else if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS) in cctl_read_write()
1829 * lun_data includes space for 1 lun, allocate space for 4 initially. in cctl_get_luns()
1830 * If that isn't enough, we'll allocate more. in cctl_get_luns()
1851 io->io_hdr.nexus.initid = iid; in cctl_get_luns()
1852 io->io_hdr.nexus.targ_lun = lun; in cctl_get_luns()
1859 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) { in cctl_get_luns()
1902 switch (lun_data->luns[i].lundata[0] & RPL_LUNDATA_ATYP_MASK) { in cctl_report_luns()
1904 lun_val = lun_data->luns[i].lundata[1]; in cctl_report_luns()
1907 lun_val = (lun_data->luns[i].lundata[0] & in cctl_report_luns()
1909 (lun_data->luns[i].lundata[1] << in cctl_report_luns()
1916 lun_data->luns[i].lundata[0] & in cctl_report_luns()
1949 io->io_hdr.nexus.targ_lun = lun; in cctl_tur()
1950 io->io_hdr.nexus.initid = iid; in cctl_tur()
1957 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) in cctl_tur()
1989 io->io_hdr.nexus.targ_lun = lun; in cctl_get_inquiry()
1990 io->io_hdr.nexus.initid = iid; in cctl_get_inquiry()
1997 if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS) { in cctl_get_inquiry()
2061 io->io_hdr.nexus.targ_lun = lun; in cctl_req_sense()
2062 io->io_hdr.nexus.initid = iid; in cctl_req_sense()
2069 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) { in cctl_req_sense()
2070 bcopy(sense_data, &io->scsiio.sense_data, sizeof(*sense_data)); in cctl_req_sense()
2071 io->scsiio.sense_len = sizeof(*sense_data); in cctl_req_sense()
2118 io->io_hdr.nexus.targ_lun = lun; in cctl_report_target_port_group()
2119 io->io_hdr.nexus.initid = iid; in cctl_report_target_port_group()
2126 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) { in cctl_report_target_port_group()
2184 io->io_hdr.nexus.targ_lun = lun; in cctl_inquiry_vpd_devid()
2185 io->io_hdr.nexus.initid = iid; in cctl_inquiry_vpd_devid()
2192 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) { in cctl_inquiry_vpd_devid()
2270 io->io_hdr.nexus.targ_lun = lun; in cctl_persistent_reserve_in()
2271 io->io_hdr.nexus.initid = iid; in cctl_persistent_reserve_in()
2278 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) { in cctl_persistent_reserve_in()
2390 io->io_hdr.nexus.targ_lun = lun; in cctl_persistent_reserve_out()
2391 io->io_hdr.nexus.initid = iid; in cctl_persistent_reserve_out()
2397 if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS) { in cctl_persistent_reserve_out()
2502 strlcpy(req.backend, backend_name, sizeof(req.backend)); in cctl_create_lun()
2503 req.reqtype = CTL_LUNREQ_CREATE; in cctl_create_lun()
2506 req.reqdata.create.blocksize_bytes = blocksize; in cctl_create_lun()
2509 req.reqdata.create.lun_size_bytes = lun_size; in cctl_create_lun()
2512 req.reqdata.create.flags |= CTL_LUN_FLAG_ID_REQ; in cctl_create_lun()
2513 req.reqdata.create.req_lun_id = req_lun_id; in cctl_create_lun()
2516 req.reqdata.create.flags |= CTL_LUN_FLAG_DEV_TYPE; in cctl_create_lun()
2519 req.reqdata.create.device_type = device_type; in cctl_create_lun()
2521 req.reqdata.create.device_type = T_DIRECT; in cctl_create_lun()
2524 strlcpy(req.reqdata.create.serial_num, serial_num, in cctl_create_lun()
2525 sizeof(req.reqdata.create.serial_num)); in cctl_create_lun()
2526 req.reqdata.create.flags |= CTL_LUN_FLAG_SERIAL_NUM; in cctl_create_lun()
2530 strlcpy(req.reqdata.create.device_id, device_id, in cctl_create_lun()
2531 sizeof(req.reqdata.create.device_id)); in cctl_create_lun()
2532 req.reqdata.create.flags |= CTL_LUN_FLAG_DEVID; in cctl_create_lun()
2535 req.args = nvlist_pack(option_list, &req.args_len); in cctl_create_lun()
2536 if (req.args == NULL) { in cctl_create_lun()
2543 free(req.args); in cctl_create_lun()
2550 switch (req.status) { in cctl_create_lun()
2552 warnx("LUN creation error: %s", req.error_str); in cctl_create_lun()
2556 warnx("LUN creation warning: %s", req.error_str); in cctl_create_lun()
2561 warnx("unknown LUN creation status: %d", req.status); in cctl_create_lun()
2567 fprintf(stdout, "backend: %s\n", req.backend); in cctl_create_lun()
2568 fprintf(stdout, "device type: %d\n",req.reqdata.create.device_type); in cctl_create_lun()
2570 (uintmax_t)req.reqdata.create.lun_size_bytes); in cctl_create_lun()
2572 req.reqdata.create.blocksize_bytes); in cctl_create_lun()
2573 fprintf(stdout, "LUN ID: %d\n", req.reqdata.create.req_lun_id); in cctl_create_lun()
2574 fprintf(stdout, "Serial Number: %s\n", req.reqdata.create.serial_num); in cctl_create_lun()
2575 fprintf(stdout, "Device ID: %s\n", req.reqdata.create.device_id); in cctl_create_lun()
2641 strlcpy(req.backend, backend_name, sizeof(req.backend)); in cctl_rm_lun()
2642 req.reqtype = CTL_LUNREQ_RM; in cctl_rm_lun()
2644 req.reqdata.rm.lun_id = lun_id; in cctl_rm_lun()
2646 req.args = nvlist_pack(option_list, &req.args_len); in cctl_rm_lun()
2647 if (req.args == NULL) { in cctl_rm_lun()
2654 free(req.args); in cctl_rm_lun()
2661 switch (req.status) { in cctl_rm_lun()
2663 warnx("LUN removal error: %s", req.error_str); in cctl_rm_lun()
2667 warnx("LUN removal warning: %s", req.error_str); in cctl_rm_lun()
2672 warnx("unknown LUN removal status: %d", req.status); in cctl_rm_lun()
2760 strlcpy(req.backend, backend_name, sizeof(req.backend)); in cctl_modify_lun()
2761 req.reqtype = CTL_LUNREQ_MODIFY; in cctl_modify_lun()
2763 req.reqdata.modify.lun_id = lun_id; in cctl_modify_lun()
2764 req.reqdata.modify.lun_size_bytes = lun_size; in cctl_modify_lun()
2766 req.args = nvlist_pack(option_list, &req.args_len); in cctl_modify_lun()
2767 if (req.args == NULL) { in cctl_modify_lun()
2774 free(req.args); in cctl_modify_lun()
2781 switch (req.status) { in cctl_modify_lun()
2783 warnx("LUN modification error: %s", req.error_str); in cctl_modify_lun()
2787 warnx("LUN modification warning: %s", req.error_str); in cctl_modify_lun()
2792 warnx("unknown LUN modification status: %d", req.status); in cctl_modify_lun()
2949 /* Nothing. */ in cctl_islist_end_element()
2952 * Unknown element; ignore it for forward compatibility. in cctl_islist_end_element()
2985 STAILQ_INIT(&islist.conn_list); in cctl_islist()
3004 req.type = CTL_ISCSI_LIST; in cctl_islist()
3005 req.data.list.alloc_len = conn_len; in cctl_islist()
3006 req.data.list.conn_xml = conn_str; in cctl_islist()
3014 if (req.status == CTL_ISCSI_ERROR) { in cctl_islist()
3016 __func__, req.error_str); in cctl_islist()
3017 } else if (req.status == CTL_ISCSI_LIST_NEED_MORE_SPACE) { in cctl_islist()
3051 STAILQ_FOREACH(conn, &islist.conn_list, links) { in cctl_islist()
3072 STAILQ_FOREACH(conn, &islist.conn_list, links) { in cctl_islist()
3127 req.type = CTL_ISCSI_LOGOUT; in cctl_islogout()
3128 req.data.logout.connection_id = connection_id; in cctl_islogout()
3130 strlcpy(req.data.logout.initiator_addr, in cctl_islogout()
3131 initiator_addr, sizeof(req.data.logout.initiator_addr)); in cctl_islogout()
3133 strlcpy(req.data.logout.initiator_name, in cctl_islogout()
3134 initiator_name, sizeof(req.data.logout.initiator_name)); in cctl_islogout()
3136 req.data.logout.all = 1; in cctl_islogout()
3144 if (req.status != CTL_ISCSI_OK) { in cctl_islogout()
3146 __func__, req.error_str); in cctl_islogout()
3200 req.type = CTL_ISCSI_TERMINATE; in cctl_isterminate()
3201 req.data.terminate.connection_id = connection_id; in cctl_isterminate()
3203 strlcpy(req.data.terminate.initiator_addr, in cctl_isterminate()
3204 initiator_addr, sizeof(req.data.terminate.initiator_addr)); in cctl_isterminate()
3206 strlcpy(req.data.terminate.initiator_name, in cctl_isterminate()
3207 initiator_name, sizeof(req.data.terminate.initiator_name)); in cctl_isterminate()
3209 req.data.terminate.all = 1; in cctl_isterminate()
3217 if (req.status != CTL_ISCSI_OK) { in cctl_isterminate()
3219 "termination request:\n%s", __func__, req.error_str); in cctl_isterminate()
3230 /* Helper function to output values from an nvlist of strings. */
3243 * Backend LUN information.
3359 /* Nothing. */ in cctl_end_element()
3400 STAILQ_INIT(&devlist.lun_list); in cctl_devlist()
3422 list.alloc_len = lun_len; in cctl_devlist()
3423 list.status = CTL_LUN_LIST_NONE; in cctl_devlist()
3424 list.lun_xml = lun_str; in cctl_devlist()
3432 if (list.status == CTL_LUN_LIST_ERROR) { in cctl_devlist()
3434 __func__, list.error_str); in cctl_devlist()
3435 } else if (list.status == CTL_LUN_LIST_NEED_MORE_SPACE) { in cctl_devlist()
3469 STAILQ_FOREACH(lun, &devlist.lun_list, links) { in cctl_devlist()
3491 * Port information.
3627 /* Nothing. */ in cctl_end_pelement()
3692 STAILQ_INIT(&portlist.port_list); in cctl_portlist()
3726 list.alloc_len = port_len; in cctl_portlist()
3727 list.status = CTL_LUN_LIST_NONE; in cctl_portlist()
3728 list.lun_xml = port_str; in cctl_portlist()
3736 if (list.status == CTL_LUN_LIST_ERROR) { in cctl_portlist()
3738 __func__, list.error_str); in cctl_portlist()
3739 } else if (list.status == CTL_LUN_LIST_NEED_MORE_SPACE) { in cctl_portlist()
3773 STAILQ_FOREACH(port, &portlist.port_list, links) { in cctl_portlist()
3823 lm.port = UINT32_MAX; in cctl_lunmap()
3824 lm.plun = UINT32_MAX; in cctl_lunmap()
3825 lm.lun = UINT32_MAX; in cctl_lunmap()
3830 lm.port = strtoll(optarg, NULL, 0); in cctl_lunmap()
3833 lm.plun = strtoll(optarg, NULL, 0); in cctl_lunmap()
3836 lm.lun = strtoll(optarg, NULL, 0); in cctl_lunmap()
3951 /* Nothing. */ in cctl_nvlist_end_element()
3954 * Unknown element; ignore it for forward compatibility. in cctl_nvlist_end_element()
4005 STAILQ_INIT(&nvlist.conn_list); in cctl_nvlist()
4024 req.type = CTL_NVMF_LIST; in cctl_nvlist()
4025 req.data.list.alloc_len = conn_len; in cctl_nvlist()
4026 req.data.list.conn_xml = conn_str; in cctl_nvlist()
4034 if (req.status == CTL_NVMF_ERROR) { in cctl_nvlist()
4036 __func__, req.error_str); in cctl_nvlist()
4037 } else if (req.status == CTL_NVMF_LIST_NEED_MORE_SPACE) { in cctl_nvlist()
4071 STAILQ_FOREACH(conn, &nvlist.conn_list, links) { in cctl_nvlist()
4082 STAILQ_FOREACH(conn, &nvlist.conn_list, links) { in cctl_nvlist()
4132 req.type = CTL_NVMF_TERMINATE; in cctl_nvterminate()
4133 req.data.terminate.cntlid = cntlid; in cctl_nvterminate()
4135 strlcpy(req.data.terminate.hostnqn, in cctl_nvterminate()
4136 hostnqn, sizeof(req.data.terminate.hostnqn)); in cctl_nvterminate()
4138 req.data.terminate.all = 1; in cctl_nvterminate()
4146 if (req.status != CTL_NVMF_OK) { in cctl_nvterminate()
4148 "termination request:\n%s", __func__, req.error_str); in cctl_nvterminate()
4252 "-b backend : backend name (\"block\", \"ramdisk\", etc.)\n" in usage()
4261 "-b backend : backend name (\"block\", \"ramdisk\", etc.)\n" in usage()
4339 * Get the base option. in main()
4367 * Ahh, getopt(3) is a pain. in main()
4369 * This is a gross hack. There really aren't many other good in main()
4371 * this. getopt is kinda braindead, so you end up having to run in main()
4373 * the option string for the other invocation. in main()
4375 * You would think that you could just have two groups of options. in main()
4378 * invocation of getopt. It doesn't quite work out that way. When in main()
4380 * to the argument _after_ the first argument in the second group. in main()
4382 * recognize the first argument it gets and then bails out. in main()
4386 * argument", but there isn't one. So there's no real clean way to in main()
4388 * of getopt know about the other. in main()
4392 * (in the subfunction) would fail in one of two ways. In the case in main()
4394 * pointing to the argument after the one it should be pointing at. in main()
4397 * it doesn't understand. in main()
4400 * whether optind had been incremented one option too far. The in main()
4402 * both invocations all of the expect options for either invocation. in main()
4405 * (non-GPL!) command line parsing interface than getopt. I in main()
4407 * work better. Who knows, I may talk myself into doing it someday, in main()
4408 * if the standards weenies let me. As it is, it just leads to in main()
4409 * hackery like this and causes people to avoid it in some cases. in main()
4420 * accepted argv[1..2] as the command name, and as a possible in main()
4421 * device name. in main()
4428 * subfunctions. in main()
4456 * Default to opening the CTL device for now. in main()