--- embedaddon/smartmontools/smartctl.cpp 2012/02/21 16:32:16 1.1 +++ embedaddon/smartmontools/smartctl.cpp 2013/07/22 01:17:36 1.1.1.3 @@ -4,7 +4,7 @@ * Home page of code is: http://smartmontools.sourceforge.net * * Copyright (C) 2002-11 Bruce Allen - * Copyright (C) 2008-11 Christian Franke + * Copyright (C) 2008-12 Christian Franke * Copyright (C) 2000 Michael Cornwell * * This program is free software; you can redistribute it and/or modify @@ -13,8 +13,7 @@ * any later version. * * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * (for example COPYING); If not, see . * * This code was originally developed as a Senior Thesis by Michael Cornwell * at the Concurrent Systems Laboratory (now part of the Storage Systems @@ -41,10 +40,6 @@ #include #endif -#if defined(__QNXNTO__) -#include // TODO: Why is this include necessary on QNX ? -#endif - #include "int64.h" #include "atacmds.h" #include "dev_interface.h" @@ -55,7 +50,7 @@ #include "smartctl.h" #include "utility.h" -const char * smartctl_cpp_cvsid = "$Id: smartctl.cpp,v 1.1 2012/02/21 16:32:16 misho Exp $" +const char * smartctl_cpp_cvsid = "$Id: smartctl.cpp,v 1.1.1.3 2013/07/22 01:17:36 misho Exp $" CONFIG_H_CVSID SMARTCTL_H_CVSID; // Globals to control printing @@ -73,7 +68,7 @@ static void UsageSummary() return; } -static std::string getvalidarglist(char opt); +static std::string getvalidarglist(int opt); /* void prints help information for command syntax */ static void Usage() @@ -85,9 +80,13 @@ static void Usage() " Display this help and exit\n\n" " -V, --version, --copyright, --license\n" " Print license, copyright, and version information and exit\n\n" -" -i, --info \n" +" -i, --info\n" " Show identity information for device\n\n" -" -a, --all \n" +" --identify[=[w][nvb]]\n" +" Show words and bits from IDENTIFY DEVICE data (ATA)\n\n" +" -g NAME, --get=NAME\n" +" Get device setting: all, aam, apm, lookahead, security, wcache, rcache\n\n" +" -a, --all\n" " Show all SMART information for device\n\n" " -x, --xall\n" " Show all information for device\n\n" @@ -119,6 +118,10 @@ static void Usage() " Enable/disable automatic offline testing on device (on/off)\n\n" " -S VALUE, --saveauto=VALUE (ATA)\n" " Enable/disable Attribute autosave on device (on/off)\n\n" +" -s NAME[,VALUE], --set=NAME[,VALUE]\n" +" Enable/disable/change device setting: aam,[N|off], apm,[N|off],\n" +" lookahead,[on|off], security-freeze, standby,[N|off|now],\n" +" wcache,[on|off], rcache,[on|off]\n\n" ); printf( "======================================= READ AND DISPLAY DATA OPTIONS =====\n\n" @@ -129,7 +132,7 @@ static void Usage() " -A, --attributes\n" " Show device SMART vendor-specific Attributes and values\n\n" " -f FORMAT, --format=FORMAT (ATA)\n" -" Set output format for attributes to one of: old, brief\n\n" +" Set output format for attributes: old, brief, hex[,id|val]\n\n" " -l TYPE, --log=TYPE\n" " Show device log. TYPE: error, selftest, selective, directory[,g|s],\n" " xerror[,N][,error], xselftest[,N][,selftest],\n" @@ -140,13 +143,14 @@ static void Usage() " -v N,OPTION , --vendorattribute=N,OPTION (ATA)\n" " Set display OPTION for vendor Attribute N (see man page)\n\n" " -F TYPE, --firmwarebug=TYPE (ATA)\n" -" Use firmware bug workaround: none, samsung, samsung2,\n" -" samsung3, swapid\n\n" +" Use firmware bug workaround:\n" +" %s, swapid\n\n" " -P TYPE, --presets=TYPE (ATA)\n" " Drive-specific presets: use, ignore, show, showall\n\n" " -B [+]FILE, --drivedb=[+]FILE (ATA)\n" " Read and replace [add] drive database from FILE\n" " [default is +%s", + get_valid_firmwarebug_args(), get_drivedb_path_add() ); #ifdef SMARTMONTOOLS_DRIVEDBDIR @@ -160,7 +164,7 @@ static void Usage() "]\n\n" "============================================ DEVICE SELF-TEST OPTIONS =====\n\n" " -t TEST, --test=TEST\n" -" Run test. TEST: offline, short, long, conveyance, vendor,N,\n" +" Run test. TEST: offline, short, long, conveyance, force, vendor,N,\n" " select,M-N, pending,N, afterselect,[on|off]\n\n" " -C, --captive\n" " Do test in captive mode (along with -t)\n\n" @@ -172,9 +176,12 @@ static void Usage() printf("%s\n", examples.c_str()); } +// Values for --long only options, see parse_options() +enum { opt_identify = 1000, opt_scan, opt_scan_open, opt_set, opt_smart }; + /* Returns a string containing a formatted list of the valid arguments to the option opt or empty on failure. Note 'v' case different */ -static std::string getvalidarglist(char opt) +static std::string getvalidarglist(int opt) { switch (opt) { case 'q': @@ -187,7 +194,7 @@ static std::string getvalidarglist(char opt) return "warn, exit, ignore"; case 'r': return "ioctl[,N], ataioctl[,N], scsiioctl[,N]"; - case 's': + case opt_smart: case 'o': case 'S': return "on, off"; @@ -202,14 +209,23 @@ static std::string getvalidarglist(char opt) case 'P': return "use, ignore, show, showall"; case 't': - return "offline, short, long, conveyance, vendor,N, select,M-N, " + return "offline, short, long, conveyance, force, vendor,N, select,M-N, " "pending,N, afterselect,[on|off]"; case 'F': - return "none, samsung, samsung2, samsung3, swapid"; + return std::string(get_valid_firmwarebug_args()) + ", swapid"; case 'n': return "never, sleep, standby, idle"; case 'f': - return "old, brief"; + return "old, brief, hex[,id|val]"; + case 'g': + return "aam, apm, lookahead, security, wcache, rcache"; + case opt_set: + return "aam,[N|off], apm,[N|off], lookahead,[on|off], security-freeze, " + "standby,[N|off|now], wcache,[on|off], rcache,[on|off]"; + case 's': + return getvalidarglist(opt_smart)+", "+getvalidarglist(opt_set); + case opt_identify: + return "n, wn, w, v, wv, wb"; case 'v': default: return ""; @@ -218,7 +234,7 @@ static std::string getvalidarglist(char opt) /* Prints the message "=======> VALID ARGUMENTS ARE: \n", where is the list of valid arguments for option opt. */ -static void printvalidarglistmessage(char opt) +static void printvalidarglistmessage(int opt) { if (opt=='v'){ pout("=======> VALID ARGUMENTS ARE:\n\thelp\n%s\n<=======\n", @@ -244,15 +260,15 @@ static checksum_err_mode_t checksum_err_mode = CHECKSU static void scan_devices(const char * type, bool with_open, char ** argv); + /* Takes command options and sets features to be run */ static const char * parse_options(int argc, char** argv, - ata_print_options & ataopts, - scsi_print_options & scsiopts) + ata_print_options & ataopts, scsi_print_options & scsiopts, + bool & print_type_only) { // Please update getvalidarglist() if you edit shortopts - const char *shortopts = "h?Vq:d:T:b:r:s:o:S:HcAl:iaxv:P:t:CXF:n:B:f:"; + const char *shortopts = "h?Vq:d:T:b:r:s:o:S:HcAl:iaxv:P:t:CXF:n:B:f:g:"; // Please update getvalidarglist() if you edit longopts - enum { opt_scan = 1000, opt_scan_open = 1001 }; struct option longopts[] = { { "help", no_argument, 0, 'h' }, { "usage", no_argument, 0, 'h' }, @@ -264,7 +280,7 @@ static const char * parse_options(int argc, char** arg { "tolerance", required_argument, 0, 'T' }, { "badsum", required_argument, 0, 'b' }, { "report", required_argument, 0, 'r' }, - { "smart", required_argument, 0, 's' }, + { "smart", required_argument, 0, opt_smart }, { "offlineauto", required_argument, 0, 'o' }, { "saveauto", required_argument, 0, 'S' }, { "health", no_argument, 0, 'H' }, @@ -283,6 +299,9 @@ static const char * parse_options(int argc, char** arg { "nocheck", required_argument, 0, 'n' }, { "drivedb", required_argument, 0, 'B' }, { "format", required_argument, 0, 'f' }, + { "get", required_argument, 0, 'g' }, + { "identify", optional_argument, 0, opt_identify }, + { "set", required_argument, 0, opt_set }, { "scan", no_argument, 0, opt_scan }, { "scan-open", no_argument, 0, opt_scan_open }, { 0, 0, 0, 0 } @@ -323,7 +342,10 @@ static const char * parse_options(int argc, char** arg } break; case 'd': - type = (strcmp(optarg, "auto") ? optarg : (char *)0); + if (!strcmp(optarg, "test")) + print_type_only = true; + else + type = (strcmp(optarg, "auto") ? optarg : (char *)0); break; case 'T': if (!strcmp(optarg,"normal")) { @@ -375,17 +397,22 @@ static const char * parse_options(int argc, char** arg free(s); } break; + case 's': + case opt_smart: // --smart if (!strcmp(optarg,"on")) { ataopts.smart_enable = scsiopts.smart_enable = true; ataopts.smart_disable = scsiopts.smart_disable = false; } else if (!strcmp(optarg,"off")) { ataopts.smart_disable = scsiopts.smart_disable = true; ataopts.smart_enable = scsiopts.smart_enable = false; + } else if (optchar == 's') { + goto case_s_continued; // --set, see below } else { badarg = true; } break; + case 'o': if (!strcmp(optarg,"on")) { ataopts.smart_auto_offl_enable = true; @@ -413,19 +440,10 @@ static const char * parse_options(int argc, char** arg scsiopts.smart_ss_media_log = true; break; case 'F': - if (!strcmp(optarg,"none")) { - ataopts.fix_firmwarebug = FIX_NONE; - } else if (!strcmp(optarg,"samsung")) { - ataopts.fix_firmwarebug = FIX_SAMSUNG; - } else if (!strcmp(optarg,"samsung2")) { - ataopts.fix_firmwarebug = FIX_SAMSUNG2; - } else if (!strcmp(optarg,"samsung3")) { - ataopts.fix_firmwarebug = FIX_SAMSUNG3; - } else if (!strcmp(optarg,"swapid")) { + if (!strcmp(optarg, "swapid")) ataopts.fix_swapped_id = true; - } else { + else if (!parse_firmwarebug_def(optarg, ataopts.firmwarebugs)) badarg = true; - } break; case 'c': ataopts.smart_general_values = true; @@ -472,7 +490,7 @@ static const char * parse_options(int argc, char** arg unsigned interval = 0; int n1 = -1, n2 = -1, len = strlen(optarg); if (!( sscanf(optarg,"scttempint,%u%n,p%n", &interval, &n1, &n2) == 1 && 0 < interval && interval <= 0xffff && (n1 == len || n2 == len))) { - strcpy(extraerror, "Option -l scttempint,N[,p] must have positive integer N\n"); + snprintf(extraerror, sizeof(extraerror), "Option -l scttempint,N[,p] must have positive integer N\n"); badarg = true; } ataopts.sct_temp_int = interval; @@ -528,7 +546,7 @@ static const char * parse_options(int argc, char** arg ataopts.sct_erc_writetime = wt; } else { - sprintf(extraerror, "Option -l scterc,[READTIME,WRITETIME] syntax error\n"); + snprintf(extraerror, sizeof(extraerror), "Option -l scterc,[READTIME,WRITETIME] syntax error\n"); badarg = true; } } else if ( !strncmp(optarg, "gplog," , sizeof("gplog," )-1) @@ -544,14 +562,14 @@ static const char * parse_options(int argc, char** arg const char * erropt = (gpl ? "gplog" : "smartlog"); if (!( n1 == len || n2 == len || (n3 == len && (sign == '+' || sign == '-')))) { - sprintf(extraerror, "Option -l %s,ADDR[,FIRST[-LAST|+SIZE]] syntax error\n", erropt); + snprintf(extraerror, sizeof(extraerror), "Option -l %s,ADDR[,FIRST[-LAST|+SIZE]] syntax error\n", erropt); badarg = true; } else if (!( logaddr <= 0xff && page <= (gpl ? 0xffffU : 0x00ffU) && 0 < nsectors && (nsectors <= (gpl ? 0xffffU : 0xffU) || nsectors == ~0U) && (sign != '-' || page <= nsectors) )) { - sprintf(extraerror, "Option -l %s,ADDR[,FIRST[-LAST|+SIZE]] parameter out of range\n", erropt); + snprintf(extraerror, sizeof(extraerror), "Option -l %s,ADDR[,FIRST[-LAST|+SIZE]] parameter out of range\n", erropt); badarg = true; } else { @@ -567,6 +585,22 @@ static const char * parse_options(int argc, char** arg case 'i': ataopts.drive_info = scsiopts.drive_info = true; break; + + case opt_identify: + ataopts.identify_word_level = ataopts.identify_bit_level = 0; + if (optarg) { + for (int i = 0; optarg[i]; i++) { + switch (optarg[i]) { + case 'w': ataopts.identify_word_level = 1; break; + case 'n': ataopts.identify_bit_level = -1; break; + case 'v': ataopts.identify_bit_level = 1; break; + case 'b': ataopts.identify_bit_level = 2; break; + default: badarg = true; + } + } + } + break; + case 'a': ataopts.drive_info = scsiopts.drive_info = true; ataopts.smart_check_status = scsiopts.smart_check_status = true; @@ -592,12 +626,18 @@ static const char * parse_options(int argc, char** arg ataopts.smart_logdir = ataopts.gp_logdir = true; ataopts.sct_temp_sts = ataopts.sct_temp_hist = true; ataopts.sct_erc_get = true; + ataopts.devstat_all_pages = true; ataopts.sataphy = true; + ataopts.get_set_used = true; + ataopts.get_aam = ataopts.get_apm = true; + ataopts.get_security = true; + ataopts.get_lookahead = ataopts.get_wcache = true; + scsiopts.get_rcd = scsiopts.get_wce = true; scsiopts.smart_background_log = true; scsiopts.smart_ss_media_log = true; scsiopts.sasphy = true; if (!output_format_set) - ataopts.output_format = 1; // '-f brief' + ataopts.output_format |= ata_print_options::FMT_BRIEF; break; case 'v': // parse vendor-specific definitions of attributes @@ -648,6 +688,9 @@ static const char * parse_options(int argc, char** arg } else if (!strcmp(optarg,"conveyance")) { testcnt++; ataopts.smart_selftest_type = CONVEYANCE_SELF_TEST; + } else if (!strcmp(optarg,"force")) { + ataopts.smart_selftest_force = true; + scsiopts.smart_selftest_force = true; } else if (!strcmp(optarg,"afterselect,on")) { // scan remainder of disk after doing selected segment ataopts.smart_selective_args.scan_after_select = 2; @@ -661,10 +704,10 @@ static const char * parse_options(int argc, char** arg errno=0; i=(int)strtol(optarg+strlen("pending,"), &tailptr, 10); if (errno || *tailptr != '\0') { - sprintf(extraerror, "Option -t pending,N requires N to be a non-negative integer\n"); + snprintf(extraerror, sizeof(extraerror), "Option -t pending,N requires N to be a non-negative integer\n"); badarg = true; } else if (i<0 || i>65535) { - sprintf(extraerror, "Option -t pending,N (N=%d) must have 0 <= N <= 65535\n", i); + snprintf(extraerror, sizeof(extraerror), "Option -t pending,N (N=%d) must have 0 <= N <= 65535\n", i); badarg = true; } else { ataopts.smart_selective_args.pending_time = i+1; @@ -675,15 +718,15 @@ static const char * parse_options(int argc, char** arg // parse range of LBAs to test uint64_t start, stop; int mode; if (split_selective_arg(optarg, &start, &stop, &mode)) { - sprintf(extraerror, "Option -t select,M-N must have non-negative integer M and N\n"); + snprintf(extraerror, sizeof(extraerror), "Option -t select,M-N must have non-negative integer M and N\n"); badarg = true; } else { if (ataopts.smart_selective_args.num_spans >= 5 || start > stop) { if (start > stop) { - sprintf(extraerror, "ERROR: Start LBA (%"PRIu64") > ending LBA (%"PRId64") in argument \"%s\"\n", + snprintf(extraerror, sizeof(extraerror), "ERROR: Start LBA (%"PRIu64") > ending LBA (%"PRId64") in argument \"%s\"\n", start, stop, optarg); } else { - sprintf(extraerror,"ERROR: No more than five selective self-test spans may be" + snprintf(extraerror, sizeof(extraerror),"ERROR: No more than five selective self-test spans may be" " defined\n"); } badarg = true; @@ -695,13 +738,13 @@ static const char * parse_options(int argc, char** arg ataopts.smart_selftest_type = SELECTIVE_SELF_TEST; } } else if (!strncmp(optarg, "scttempint", sizeof("scstempint")-1)) { - strcpy(extraerror, "-t scttempint is no longer supported, use -l scttempint instead\n"); + snprintf(extraerror, sizeof(extraerror), "-t scttempint is no longer supported, use -l scttempint instead\n"); badarg = true; } else if (!strncmp(optarg, "vendor,", sizeof("vendor,")-1)) { unsigned subcmd = ~0U; int n = -1; if (!( sscanf(optarg, "%*[a-z],0x%x%n", &subcmd, &n) == 1 && subcmd <= 0xff && n == (int)strlen(optarg))) { - strcpy(extraerror, "Option -t vendor,0xNN syntax error\n"); + snprintf(extraerror, sizeof(extraerror), "Option -t vendor,0xNN syntax error\n"); badarg = true; } else @@ -732,14 +775,23 @@ static const char * parse_options(int argc, char** arg badarg = true; break; case 'f': - output_format_set = true; - if (!strcmp(optarg,"old")) { - ataopts.output_format = 0; - } else if (!strcmp(optarg,"brief")) { - ataopts.output_format = 1; - } else { - badarg = true; + if (!strcmp(optarg, "old")) { + ataopts.output_format &= ~ata_print_options::FMT_BRIEF; + output_format_set = true; } + else if (!strcmp(optarg, "brief")) { + ataopts.output_format |= ata_print_options::FMT_BRIEF; + output_format_set = true; + } + else if (!strcmp(optarg, "hex")) + ataopts.output_format |= ata_print_options::FMT_HEX_ID + | ata_print_options::FMT_HEX_VAL; + else if (!strcmp(optarg, "hex,id")) + ataopts.output_format |= ata_print_options::FMT_HEX_ID; + else if (!strcmp(optarg, "hex,val")) + ataopts.output_format |= ata_print_options::FMT_HEX_VAL; + else + badarg = true; break; case 'B': { @@ -759,6 +811,115 @@ static const char * parse_options(int argc, char** arg EXIT(0); break; + case 'g': + case_s_continued: // -s, see above + case opt_set: // --set + { + ataopts.get_set_used = true; + bool get = (optchar == 'g'); + char name[16+1]; unsigned val; + int n1 = -1, n2 = -1, n3 = -1, len = strlen(optarg); + if (sscanf(optarg, "%16[^,=]%n%*[,=]%n%u%n", name, &n1, &n2, &val, &n3) >= 1 + && (n1 == len || (!get && n2 > 0))) { + bool on = (n2 > 0 && !strcmp(optarg+n2, "on")); + bool off = (n2 > 0 && !strcmp(optarg+n2, "off")); + if (n3 != len) + val = ~0U; + + if (get && !strcmp(name, "all")) { + ataopts.get_aam = ataopts.get_apm = true; + ataopts.get_security = true; + ataopts.get_lookahead = ataopts.get_wcache = true; + scsiopts.get_rcd = scsiopts.get_wce = true; + } + else if (!strcmp(name, "aam")) { + if (get) + ataopts.get_aam = true; + else if (off) + ataopts.set_aam = -1; + else if (val <= 254) + ataopts.set_aam = val + 1; + else { + snprintf(extraerror, sizeof(extraerror), "Option -s aam,N must have 0 <= N <= 254\n"); + badarg = true; + } + } + else if (!strcmp(name, "apm")) { + if (get) + ataopts.get_apm = true; + else if (off) + ataopts.set_apm = -1; + else if (1 <= val && val <= 254) + ataopts.set_apm = val + 1; + else { + snprintf(extraerror, sizeof(extraerror), "Option -s apm,N must have 1 <= N <= 254\n"); + badarg = true; + } + } + else if (!strcmp(name, "lookahead")) { + if (get) { + ataopts.get_lookahead = true; + } + else if (off) + ataopts.set_lookahead = -1; + else if (on) + ataopts.set_lookahead = 1; + else + badarg = true; + } + else if (!strcmp(name, "rcache")) { + if (get) + scsiopts.get_rcd = true; + else if (off) + scsiopts.set_rcd = -1; + else if (on) + scsiopts.set_rcd = 1; + else + badarg = true; + } + else if (get && !strcmp(name, "security")) { + ataopts.get_security = true; + } + else if (!get && !strcmp(optarg, "security-freeze")) { + ataopts.set_security_freeze = true; + } + else if (!get && !strcmp(optarg, "standby,now")) { + ataopts.set_standby_now = true; + } + else if (!get && !strcmp(name, "standby")) { + if (off) + ataopts.set_standby = 0 + 1; + else if (val <= 255) + ataopts.set_standby = val + 1; + else { + snprintf(extraerror, sizeof(extraerror), "Option -s standby,N must have 0 <= N <= 255\n"); + badarg = true; + } + } + else if (!strcmp(name, "wcache")) { + if (get) { + ataopts.get_wcache = true; + scsiopts.get_wce = true; + } + else if (off) { + ataopts.set_wcache = -1; + scsiopts.set_wce = -1; + } + else if (on) { + ataopts.set_wcache = 1; + scsiopts.set_wce = 1; + } + else + badarg = true; + } + else + badarg = true; + } + else + badarg = true; + } + break; + case opt_scan: case opt_scan_open: scan = optchar; @@ -773,7 +934,7 @@ static const char * parse_options(int argc, char** arg // Check whether the option is a long option that doesn't map to -h. if (arg[1] == '-' && optchar != 'h') { // Iff optopt holds a valid option then argument must be missing. - if (optopt && (strchr(shortopts, optopt) != NULL)) { + if (optopt && (optopt >= opt_scan || strchr(shortopts, optopt))) { pout("=======> ARGUMENT REQUIRED FOR OPTION: %s\n", arg+2); printvalidarglistmessage(optopt); } else @@ -783,7 +944,7 @@ static const char * parse_options(int argc, char** arg UsageSummary(); EXIT(FAILCMD); } - if (optopt) { + if (0 < optopt && optopt < '~') { // Iff optopt holds a valid option then argument must be // missing. Note (BA) this logic seems to fail using Solaris // getopt! @@ -807,7 +968,11 @@ static const char * parse_options(int argc, char** arg // It would be nice to print the actual option name given by the user // here, but we just print the short form. Please fix this if you know // a clean way to do it. - pout("=======> INVALID ARGUMENT TO -%c: %s\n", optchar, optarg); + char optstr[] = { (char)optchar, 0 }; + pout("=======> INVALID ARGUMENT TO -%s: %s\n", + (optchar == opt_identify ? "-identify" : + optchar == opt_set ? "-set" : + optchar == opt_smart ? "-smart" : optstr), optarg); printvalidarglistmessage(optchar); if (extraerror[0]) pout("=======> %s", extraerror); @@ -1046,20 +1211,16 @@ static int main_worker(int argc, char **argv) // Parse input arguments ata_print_options ataopts; scsi_print_options scsiopts; - const char * type = parse_options(argc, argv, ataopts, scsiopts); + bool print_type_only = false; + const char * type = parse_options(argc, argv, ataopts, scsiopts, print_type_only); - // '-d test' -> Report result of autodetection - bool print_type_only = (type && !strcmp(type, "test")); - if (print_type_only) - type = 0; - const char * name = argv[argc-1]; smart_device_auto_ptr dev; if (!strcmp(name,"-")) { // Parse "smartctl -r ataioctl,2 ..." output from stdin if (type || print_type_only) { - pout("Smartctl: -d option is not allowed in conjunction with device name \"-\".\n"); + pout("-d option is not allowed in conjunction with device name \"-\".\n"); UsageSummary(); return FAILCMD; } @@ -1074,7 +1235,7 @@ static int main_worker(int argc, char **argv) if (type) printvalidarglistmessage('d'); else - pout("Smartctl: please specify device type with the -d option.\n"); + pout("Please specify device type with the -d option.\n"); UsageSummary(); return FAILCMD; }