From 582da09fd55fdf839a432c89c8917258a5b16f03 Mon Sep 17 00:00:00 2001 From: pjwilliams <pjwilliams@4ea69e1a-61f1-4043-bf83-b5c94c648137> Date: Wed, 11 Dec 2002 00:11:31 +0000 Subject: [PATCH] smartctl now supports new options -- see README git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@369 4ea69e1a-61f1-4043-bf83-b5c94c648137 --- sm5/extern.h | 3 +- sm5/smartctl.c | 336 ++++++++++++++++++++++++++++++++++------------- sm5/smartctl.cpp | 336 ++++++++++++++++++++++++++++++++++------------- sm5/smartctl.h | 47 ++++++- 4 files changed, 536 insertions(+), 186 deletions(-) diff --git a/sm5/extern.h b/sm5/extern.h index 11ea651ef..90b1d6f66 100644 --- a/sm5/extern.h +++ b/sm5/extern.h @@ -27,7 +27,7 @@ #ifndef CVSID3 -#define CVSID3 "$Id: extern.h,v 1.10 2002/11/07 11:00:56 ballen4705 Exp $\n" +#define CVSID3 "$Id: extern.h,v 1.11 2002/12/11 00:11:30 pjwilliams Exp $\n" #endif // Block used for global control/communications. If you need more @@ -60,6 +60,7 @@ typedef struct ataprintmain_s { unsigned char permissive; unsigned char conservative; unsigned char checksumfail; + unsigned char checksumignore; } atamainctrl; #endif diff --git a/sm5/smartctl.c b/sm5/smartctl.c index 464bb8f28..77442a8cc 100644 --- a/sm5/smartctl.c +++ b/sm5/smartctl.c @@ -31,6 +31,9 @@ #include <sys/types.h> #include <string.h> #include <stdarg.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#endif #include "smartctl.h" #include "atacmds.h" #include "ataprint.h" @@ -39,7 +42,7 @@ #include "extern.h" extern const char *CVSid1, *CVSid2, *CVSid3, *CVSid4; -const char* CVSid5="$Id: smartctl.c,v 1.29 2002/11/25 08:40:48 ballen4705 Exp $" +const char* CVSid5="$Id: smartctl.c,v 1.30 2002/12/11 00:11:31 pjwilliams Exp $" CVSID1 CVSID2 CVSID3 CVSID4 CVSID5 CVSID6; // This is a block containing all the "control variables". We declare @@ -118,16 +121,38 @@ void Usage ( void){ printf(" smartctl -qvL /dev/hda (Prints Self-Test & Attribute errors.)\n"); } -const char opts[] = { - DRIVEINFO, CHECKSMART, SMARTVERBOSEALL, SMARTVENDORATTRIB, - GENERALSMARTVALUES, SMARTERRORLOG, SMARTSELFTESTLOG, SMARTDISABLE, - SMARTENABLE, SMARTAUTOOFFLINEENABLE, SMARTAUTOOFFLINEDISABLE, - SMARTEXEOFFIMMEDIATE, SMARTSHORTSELFTEST, SMARTEXTENDSELFTEST, - SMARTSHORTCAPSELFTEST, SMARTEXTENDCAPSELFTEST, SMARTSELFTESTABORT, - SMARTAUTOSAVEENABLE,SMARTAUTOSAVEDISABLE,PRINTCOPYLEFT,SMART009MINUTES, - QUIETMODE,VERYQUIETMODE,NOTSCSIDEVICE,NOTATADEVICE, - EXITCHECKSUMERROR,ULTRACONSERVATIVE,PERMISSIVE, - 'h','?','\0' +const char shortopts[] = { + S_OPT_HELP, + S_OPT_ALT_HELP, + S_OPT_VERSION, + S_OPT_QUIETMODE, + ':', + S_OPT_DEVICE, + ':', + S_OPT_TOLERANCE, + ':', + S_OPT_BADSUM, + ':', + S_OPT_SMART, + ':', + S_OPT_OFFLINEAUTO, + ':', + S_OPT_SAVEAUTO, + ':', + S_OPT_HEALTH, + S_OPT_CAPABILITIES, + S_OPT_ATTRIBUTES, + S_OPT_LOG, + ':', + S_OPT_INFO, + S_OPT_ALL, + S_OPT_VENDORATTRIBUTE, + ':', + S_OPT_TEST, + ':', + S_OPT_CAPTIVE, + S_OPT_ABORT, + '\0' }; unsigned char printcopyleft=0,tryata=0,tryscsi=0; @@ -135,124 +160,240 @@ unsigned char printcopyleft=0,tryata=0,tryscsi=0; /* Takes command options and sets features to be run */ void ParseOpts (int argc, char** argv){ int optchar; + int badarg; + int captive; + struct { + int n; + char *option; + } vendorattribute; extern char *optarg; extern int optopt, optind, opterr; +#ifdef HAVE_GETOPT_LONG + char *arg; + struct option longopts[] = { + { L_OPT_HELP, no_argument, 0, S_OPT_HELP }, + { L_OPT_USAGE, no_argument, 0, S_OPT_HELP }, + { L_OPT_VERSION, no_argument, 0, S_OPT_VERSION }, + { L_OPT_COPYRIGHT, no_argument, 0, S_OPT_VERSION }, + { L_OPT_LICENSE, no_argument, 0, S_OPT_VERSION }, + { L_OPT_QUIETMODE, required_argument, 0, S_OPT_QUIETMODE }, + { L_OPT_DEVICE, required_argument, 0, S_OPT_DEVICE }, + { L_OPT_TOLERANCE, required_argument, 0, S_OPT_TOLERANCE }, + { L_OPT_BADSUM, required_argument, 0, S_OPT_BADSUM }, + { L_OPT_SMART, required_argument, 0, S_OPT_SMART }, + { L_OPT_OFFLINEAUTO, required_argument, 0, S_OPT_OFFLINEAUTO }, + { L_OPT_SAVEAUTO, required_argument, 0, S_OPT_SAVEAUTO }, + { L_OPT_HEALTH, no_argument, 0, S_OPT_HEALTH }, + { L_OPT_CAPABILITIES, no_argument, 0, S_OPT_CAPABILITIES }, + { L_OPT_ATTRIBUTES, no_argument, 0, S_OPT_ATTRIBUTES }, + { L_OPT_LOG, required_argument, 0, S_OPT_LOG }, + { L_OPT_INFO, no_argument, 0, S_OPT_INFO }, + { L_OPT_ALL, no_argument, 0, S_OPT_ALL }, + { L_OPT_VENDORATTRIBUTE, required_argument, 0, S_OPT_VENDORATTRIBUTE }, + { L_OPT_TEST, required_argument, 0, S_OPT_TEST }, + { L_OPT_CAPTIVE, no_argument, 0, S_OPT_CAPTIVE }, + { L_OPT_ABORT, no_argument, 0, S_OPT_ABORT }, + { 0, 0, 0, 0 } + }; +#endif memset(con,0,sizeof(*con)); con->testcase=-1; opterr=optopt=0; - while (-1 != (optchar = getopt(argc, argv, opts))) { + badarg = captive = FALSE; +#ifdef HAVE_GETOPT_LONG + while (-1 != (optchar = getopt_long(argc, argv, shortopts, longopts, NULL))) { +#else + while (-1 != (optchar = getopt(argc, argv, shortopts))) { +#endif switch (optchar){ - case EXITCHECKSUMERROR: - con->checksumfail=1; - break; - case PERMISSIVE: - con->permissive=1; + case S_OPT_VERSION: + printcopyleft=TRUE; break; - case ULTRACONSERVATIVE: - con->conservative=1; + case S_OPT_QUIETMODE: + if (!strcmp(optarg,"errorsonly")) { + con->quietmode = TRUE; + con->veryquietmode = FALSE; + } else if (!strcmp(optarg,"silent")) { + con->veryquietmode = TRUE; + con->quietmode = TRUE; + } else { + badarg = TRUE; + } break; - case NOTATADEVICE: - tryata=0; - tryscsi=1; + case S_OPT_DEVICE: + if (!strcmp(optarg,"ata")) { + tryata = TRUE; + tryscsi = FALSE; + } else if (!strcmp(optarg,"scsi")) { + tryata = TRUE; + tryscsi = FALSE; + } else { + badarg = TRUE; + } break; - case NOTSCSIDEVICE: - tryata=1; - tryscsi=0; + case S_OPT_TOLERANCE: + if (!strcmp(optarg,"normal")) { + con->conservative = FALSE; + con->permissive = FALSE; + } else if (!strcmp(optarg,"conservative")) { + con->conservative = TRUE; + con->permissive = FALSE; + } else if (!strcmp(optarg,"permissive")) { + con->permissive = TRUE; + con->conservative = FALSE; + } else { + badarg = TRUE; + } break; - case QUIETMODE: - con->quietmode=TRUE; + case S_OPT_BADSUM: + if (!strcmp(optarg,"warn")) { + con->checksumfail = FALSE; + con->checksumignore = FALSE; + } else if (!strcmp(optarg,"exit")) { + con->checksumfail = TRUE; + con->checksumignore = FALSE; + } else if (!strcmp(optarg,"ignore")) { + con->checksumignore = TRUE; + con->checksumfail = FALSE; + } else { + badarg = TRUE; + } break; - case VERYQUIETMODE: - con->veryquietmode=TRUE; + case S_OPT_SMART: + if (!strcmp(optarg,"on")) { + con->smartenable = TRUE; + con->smartdisable = FALSE; + } else if (!strcmp(optarg,"off")) { + con->smartdisable = TRUE; + con->smartenable = FALSE; + } else { + badarg = TRUE; + } break; - case SMART009MINUTES: - con->smart009minutes=TRUE; + case S_OPT_OFFLINEAUTO: + if (!strcmp(optarg,"on")) { + con->smartautoofflineenable = TRUE; + con->smartautoofflinedisable = FALSE; + } else if (!strcmp(optarg,"off")) { + con->smartautoofflinedisable = TRUE; + con->smartautoofflineenable = FALSE; + } else { + badarg = TRUE; + } break; - case PRINTCOPYLEFT : - printcopyleft=TRUE; + case S_OPT_SAVEAUTO: + if (!strcmp(optarg,"on")) { + con->smartautosaveenable = TRUE; + con->smartautosavedisable = FALSE; + } else if (!strcmp(optarg,"off")) { + con->smartautosavedisable = TRUE; + con->smartautosaveenable = FALSE; + } else { + badarg = TRUE; + } break; - case DRIVEINFO : - con->driveinfo = TRUE; - break; - case CHECKSMART : + case S_OPT_HEALTH: con->checksmart = TRUE; break; - case SMARTVERBOSEALL : - con->driveinfo = TRUE; - con->checksmart = TRUE; + case S_OPT_CAPABILITIES: con->generalsmartvalues = TRUE; - con->smartvendorattrib = TRUE; - con->smarterrorlog = TRUE; - con->smartselftestlog = TRUE; break; - case SMARTVENDORATTRIB : + case S_OPT_ATTRIBUTES: con->smartvendorattrib = TRUE; break; - case GENERALSMARTVALUES : - con->generalsmartvalues = TRUE; - break; - case SMARTERRORLOG : - con->smarterrorlog = TRUE; - break; - case SMARTSELFTESTLOG : - con->smartselftestlog = TRUE; - break; - case SMARTDISABLE : - con->smartdisable = TRUE; - break; - case SMARTENABLE : - con->smartenable = TRUE; - break; - case SMARTAUTOSAVEENABLE: - con->smartautosaveenable = TRUE; - break; - case SMARTAUTOSAVEDISABLE: - con->smartautosavedisable = TRUE; - break; - case SMARTAUTOOFFLINEENABLE: - con->smartautoofflineenable = TRUE; - break; - case SMARTAUTOOFFLINEDISABLE: - con->smartautoofflinedisable = TRUE; - break; - case SMARTEXEOFFIMMEDIATE: - con->smartexeoffimmediate = TRUE; - con->testcase=OFFLINE_FULL_SCAN; + case S_OPT_LOG: + if (!strcmp(optarg,"error")) { + con->smarterrorlog = TRUE; + } else if (!strcmp(optarg,"selftest")) { + con->smartselftestlog = TRUE; + } else { + badarg = TRUE; + } break; - case SMARTSHORTSELFTEST : - con->smartshortselftest = TRUE; - con->testcase=SHORT_SELF_TEST; + case S_OPT_INFO: + con->driveinfo = TRUE; + break; + case S_OPT_ALL: + con->driveinfo = TRUE; + con->checksmart = TRUE; + con->generalsmartvalues = TRUE; + con->smartvendorattrib = TRUE; + con->smarterrorlog = TRUE; + con->smartselftestlog = TRUE; break; - case SMARTEXTENDSELFTEST : - con->smartextendselftest = TRUE; - con->testcase=EXTEND_SELF_TEST; + case S_OPT_VENDORATTRIBUTE: + vendorattribute.option = (char *)malloc(strlen(optarg)+1); + if (sscanf(optarg,"%u,%s",&(vendorattribute.n),vendorattribute.option) != 2) { + badarg = TRUE; + } + if (vendorattribute.n == 9 && !strcmp(vendorattribute.option,"minutes")) { + con->smart009minutes=TRUE; + } else { + // Should handle this better + badarg = TRUE; + } + free(vendorattribute.option); break; - case SMARTSHORTCAPSELFTEST: - con->smartshortcapselftest = TRUE; - con->testcase=SHORT_CAPTIVE_SELF_TEST; + case S_OPT_TEST: + if (!strcmp(optarg,"offline")) { + con->smartexeoffimmediate = TRUE; + con->testcase = OFFLINE_FULL_SCAN; + } else if (!strcmp(optarg,"short")) { + con->smartshortselftest = TRUE; + con->testcase = SHORT_SELF_TEST; + } else if (!strcmp(optarg,"long")) { + con->smartextendselftest = TRUE; + con->testcase = EXTEND_SELF_TEST; + } else { + badarg = TRUE; + } break; - case SMARTEXTENDCAPSELFTEST: - con->smartextendcapselftest = TRUE; - con->testcase=EXTEND_CAPTIVE_SELF_TEST; + case S_OPT_CAPTIVE: + captive = TRUE; break; - case SMARTSELFTESTABORT: + case S_OPT_ABORT: con->smartselftestabort = TRUE; - con->testcase=ABORT_SELF_TEST; + con->testcase = ABORT_SELF_TEST; break; - case 'h': - case '?': + case S_OPT_HELP: + case S_OPT_ALT_HELP: default: con->veryquietmode=FALSE; printslogan(); - if (optopt){ - pout("=======> UNRECOGNIZED OPTION: %c <=======\n\n",(int)optopt); +#ifdef HAVE_GETOPT_LONG + // Point arg to the argument in which this option was found. + arg = argv[optind-1]; + // Check whether the option is a long option and options that map to -h. + if (arg[1] == '-' && optchar != S_OPT_HELP) { + // Iff optopt holds a valid option then argument must be missing. + if (optopt && (strchr(shortopts, optopt) != NULL)) { + pout("=======> ARGUMENT REQUIRED FOR OPTION: %s <=======\n\n",arg+2); + } else { + pout("=======> UNRECOGNIZED OPTION: %s <=======\n\n",arg+2); + } + Usage(); + exit(FAILCMD); + } +#endif + if (optopt) { + // Iff optopt holds a valid option then argument must be missing. + if (strchr(shortopts, optopt) != NULL){ + pout("=======> ARGUMENT REQUIRED FOR OPTION: %c <=======\n\n",optopt); + } else { + pout("=======> UNRECOGNIZED OPTION: %c <=======\n\n",optopt); + } Usage(); exit(FAILCMD); } Usage(); exit(0); } + if (badarg) { + pout("=======> INVALID ARGUMENT: %s <======= \n\n",optarg); + Usage(); + exit(FAILCMD); + } } // Do this here, so results are independent of argument order if (con->quietmode) @@ -268,6 +409,17 @@ void ParseOpts (int argc, char** argv){ exit(FAILCMD); } + // If captive option was used, change test type if appropriate. + if (captive && con->smartshortselftest) { + con->smartshortselftest = FALSE; + con->smartshortcapselftest = TRUE; + con->testcase = SHORT_CAPTIVE_SELF_TEST; + } else if (captive && con->smartextendselftest) { + con->smartextendselftest = FALSE; + con->smartextendcapselftest = TRUE; + con->testcase = EXTEND_CAPTIVE_SELF_TEST; + } + // From here on, normal operations... printslogan(); diff --git a/sm5/smartctl.cpp b/sm5/smartctl.cpp index 34b528ec9..c214dc0a1 100644 --- a/sm5/smartctl.cpp +++ b/sm5/smartctl.cpp @@ -31,6 +31,9 @@ #include <sys/types.h> #include <string.h> #include <stdarg.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#endif #include "smartctl.h" #include "atacmds.h" #include "ataprint.h" @@ -39,7 +42,7 @@ #include "extern.h" extern const char *CVSid1, *CVSid2, *CVSid3, *CVSid4; -const char* CVSid5="$Id: smartctl.cpp,v 1.29 2002/11/25 08:40:48 ballen4705 Exp $" +const char* CVSid5="$Id: smartctl.cpp,v 1.30 2002/12/11 00:11:31 pjwilliams Exp $" CVSID1 CVSID2 CVSID3 CVSID4 CVSID5 CVSID6; // This is a block containing all the "control variables". We declare @@ -118,16 +121,38 @@ void Usage ( void){ printf(" smartctl -qvL /dev/hda (Prints Self-Test & Attribute errors.)\n"); } -const char opts[] = { - DRIVEINFO, CHECKSMART, SMARTVERBOSEALL, SMARTVENDORATTRIB, - GENERALSMARTVALUES, SMARTERRORLOG, SMARTSELFTESTLOG, SMARTDISABLE, - SMARTENABLE, SMARTAUTOOFFLINEENABLE, SMARTAUTOOFFLINEDISABLE, - SMARTEXEOFFIMMEDIATE, SMARTSHORTSELFTEST, SMARTEXTENDSELFTEST, - SMARTSHORTCAPSELFTEST, SMARTEXTENDCAPSELFTEST, SMARTSELFTESTABORT, - SMARTAUTOSAVEENABLE,SMARTAUTOSAVEDISABLE,PRINTCOPYLEFT,SMART009MINUTES, - QUIETMODE,VERYQUIETMODE,NOTSCSIDEVICE,NOTATADEVICE, - EXITCHECKSUMERROR,ULTRACONSERVATIVE,PERMISSIVE, - 'h','?','\0' +const char shortopts[] = { + S_OPT_HELP, + S_OPT_ALT_HELP, + S_OPT_VERSION, + S_OPT_QUIETMODE, + ':', + S_OPT_DEVICE, + ':', + S_OPT_TOLERANCE, + ':', + S_OPT_BADSUM, + ':', + S_OPT_SMART, + ':', + S_OPT_OFFLINEAUTO, + ':', + S_OPT_SAVEAUTO, + ':', + S_OPT_HEALTH, + S_OPT_CAPABILITIES, + S_OPT_ATTRIBUTES, + S_OPT_LOG, + ':', + S_OPT_INFO, + S_OPT_ALL, + S_OPT_VENDORATTRIBUTE, + ':', + S_OPT_TEST, + ':', + S_OPT_CAPTIVE, + S_OPT_ABORT, + '\0' }; unsigned char printcopyleft=0,tryata=0,tryscsi=0; @@ -135,124 +160,240 @@ unsigned char printcopyleft=0,tryata=0,tryscsi=0; /* Takes command options and sets features to be run */ void ParseOpts (int argc, char** argv){ int optchar; + int badarg; + int captive; + struct { + int n; + char *option; + } vendorattribute; extern char *optarg; extern int optopt, optind, opterr; +#ifdef HAVE_GETOPT_LONG + char *arg; + struct option longopts[] = { + { L_OPT_HELP, no_argument, 0, S_OPT_HELP }, + { L_OPT_USAGE, no_argument, 0, S_OPT_HELP }, + { L_OPT_VERSION, no_argument, 0, S_OPT_VERSION }, + { L_OPT_COPYRIGHT, no_argument, 0, S_OPT_VERSION }, + { L_OPT_LICENSE, no_argument, 0, S_OPT_VERSION }, + { L_OPT_QUIETMODE, required_argument, 0, S_OPT_QUIETMODE }, + { L_OPT_DEVICE, required_argument, 0, S_OPT_DEVICE }, + { L_OPT_TOLERANCE, required_argument, 0, S_OPT_TOLERANCE }, + { L_OPT_BADSUM, required_argument, 0, S_OPT_BADSUM }, + { L_OPT_SMART, required_argument, 0, S_OPT_SMART }, + { L_OPT_OFFLINEAUTO, required_argument, 0, S_OPT_OFFLINEAUTO }, + { L_OPT_SAVEAUTO, required_argument, 0, S_OPT_SAVEAUTO }, + { L_OPT_HEALTH, no_argument, 0, S_OPT_HEALTH }, + { L_OPT_CAPABILITIES, no_argument, 0, S_OPT_CAPABILITIES }, + { L_OPT_ATTRIBUTES, no_argument, 0, S_OPT_ATTRIBUTES }, + { L_OPT_LOG, required_argument, 0, S_OPT_LOG }, + { L_OPT_INFO, no_argument, 0, S_OPT_INFO }, + { L_OPT_ALL, no_argument, 0, S_OPT_ALL }, + { L_OPT_VENDORATTRIBUTE, required_argument, 0, S_OPT_VENDORATTRIBUTE }, + { L_OPT_TEST, required_argument, 0, S_OPT_TEST }, + { L_OPT_CAPTIVE, no_argument, 0, S_OPT_CAPTIVE }, + { L_OPT_ABORT, no_argument, 0, S_OPT_ABORT }, + { 0, 0, 0, 0 } + }; +#endif memset(con,0,sizeof(*con)); con->testcase=-1; opterr=optopt=0; - while (-1 != (optchar = getopt(argc, argv, opts))) { + badarg = captive = FALSE; +#ifdef HAVE_GETOPT_LONG + while (-1 != (optchar = getopt_long(argc, argv, shortopts, longopts, NULL))) { +#else + while (-1 != (optchar = getopt(argc, argv, shortopts))) { +#endif switch (optchar){ - case EXITCHECKSUMERROR: - con->checksumfail=1; - break; - case PERMISSIVE: - con->permissive=1; + case S_OPT_VERSION: + printcopyleft=TRUE; break; - case ULTRACONSERVATIVE: - con->conservative=1; + case S_OPT_QUIETMODE: + if (!strcmp(optarg,"errorsonly")) { + con->quietmode = TRUE; + con->veryquietmode = FALSE; + } else if (!strcmp(optarg,"silent")) { + con->veryquietmode = TRUE; + con->quietmode = TRUE; + } else { + badarg = TRUE; + } break; - case NOTATADEVICE: - tryata=0; - tryscsi=1; + case S_OPT_DEVICE: + if (!strcmp(optarg,"ata")) { + tryata = TRUE; + tryscsi = FALSE; + } else if (!strcmp(optarg,"scsi")) { + tryata = TRUE; + tryscsi = FALSE; + } else { + badarg = TRUE; + } break; - case NOTSCSIDEVICE: - tryata=1; - tryscsi=0; + case S_OPT_TOLERANCE: + if (!strcmp(optarg,"normal")) { + con->conservative = FALSE; + con->permissive = FALSE; + } else if (!strcmp(optarg,"conservative")) { + con->conservative = TRUE; + con->permissive = FALSE; + } else if (!strcmp(optarg,"permissive")) { + con->permissive = TRUE; + con->conservative = FALSE; + } else { + badarg = TRUE; + } break; - case QUIETMODE: - con->quietmode=TRUE; + case S_OPT_BADSUM: + if (!strcmp(optarg,"warn")) { + con->checksumfail = FALSE; + con->checksumignore = FALSE; + } else if (!strcmp(optarg,"exit")) { + con->checksumfail = TRUE; + con->checksumignore = FALSE; + } else if (!strcmp(optarg,"ignore")) { + con->checksumignore = TRUE; + con->checksumfail = FALSE; + } else { + badarg = TRUE; + } break; - case VERYQUIETMODE: - con->veryquietmode=TRUE; + case S_OPT_SMART: + if (!strcmp(optarg,"on")) { + con->smartenable = TRUE; + con->smartdisable = FALSE; + } else if (!strcmp(optarg,"off")) { + con->smartdisable = TRUE; + con->smartenable = FALSE; + } else { + badarg = TRUE; + } break; - case SMART009MINUTES: - con->smart009minutes=TRUE; + case S_OPT_OFFLINEAUTO: + if (!strcmp(optarg,"on")) { + con->smartautoofflineenable = TRUE; + con->smartautoofflinedisable = FALSE; + } else if (!strcmp(optarg,"off")) { + con->smartautoofflinedisable = TRUE; + con->smartautoofflineenable = FALSE; + } else { + badarg = TRUE; + } break; - case PRINTCOPYLEFT : - printcopyleft=TRUE; + case S_OPT_SAVEAUTO: + if (!strcmp(optarg,"on")) { + con->smartautosaveenable = TRUE; + con->smartautosavedisable = FALSE; + } else if (!strcmp(optarg,"off")) { + con->smartautosavedisable = TRUE; + con->smartautosaveenable = FALSE; + } else { + badarg = TRUE; + } break; - case DRIVEINFO : - con->driveinfo = TRUE; - break; - case CHECKSMART : + case S_OPT_HEALTH: con->checksmart = TRUE; break; - case SMARTVERBOSEALL : - con->driveinfo = TRUE; - con->checksmart = TRUE; + case S_OPT_CAPABILITIES: con->generalsmartvalues = TRUE; - con->smartvendorattrib = TRUE; - con->smarterrorlog = TRUE; - con->smartselftestlog = TRUE; break; - case SMARTVENDORATTRIB : + case S_OPT_ATTRIBUTES: con->smartvendorattrib = TRUE; break; - case GENERALSMARTVALUES : - con->generalsmartvalues = TRUE; - break; - case SMARTERRORLOG : - con->smarterrorlog = TRUE; - break; - case SMARTSELFTESTLOG : - con->smartselftestlog = TRUE; - break; - case SMARTDISABLE : - con->smartdisable = TRUE; - break; - case SMARTENABLE : - con->smartenable = TRUE; - break; - case SMARTAUTOSAVEENABLE: - con->smartautosaveenable = TRUE; - break; - case SMARTAUTOSAVEDISABLE: - con->smartautosavedisable = TRUE; - break; - case SMARTAUTOOFFLINEENABLE: - con->smartautoofflineenable = TRUE; - break; - case SMARTAUTOOFFLINEDISABLE: - con->smartautoofflinedisable = TRUE; - break; - case SMARTEXEOFFIMMEDIATE: - con->smartexeoffimmediate = TRUE; - con->testcase=OFFLINE_FULL_SCAN; + case S_OPT_LOG: + if (!strcmp(optarg,"error")) { + con->smarterrorlog = TRUE; + } else if (!strcmp(optarg,"selftest")) { + con->smartselftestlog = TRUE; + } else { + badarg = TRUE; + } break; - case SMARTSHORTSELFTEST : - con->smartshortselftest = TRUE; - con->testcase=SHORT_SELF_TEST; + case S_OPT_INFO: + con->driveinfo = TRUE; + break; + case S_OPT_ALL: + con->driveinfo = TRUE; + con->checksmart = TRUE; + con->generalsmartvalues = TRUE; + con->smartvendorattrib = TRUE; + con->smarterrorlog = TRUE; + con->smartselftestlog = TRUE; break; - case SMARTEXTENDSELFTEST : - con->smartextendselftest = TRUE; - con->testcase=EXTEND_SELF_TEST; + case S_OPT_VENDORATTRIBUTE: + vendorattribute.option = (char *)malloc(strlen(optarg)+1); + if (sscanf(optarg,"%u,%s",&(vendorattribute.n),vendorattribute.option) != 2) { + badarg = TRUE; + } + if (vendorattribute.n == 9 && !strcmp(vendorattribute.option,"minutes")) { + con->smart009minutes=TRUE; + } else { + // Should handle this better + badarg = TRUE; + } + free(vendorattribute.option); break; - case SMARTSHORTCAPSELFTEST: - con->smartshortcapselftest = TRUE; - con->testcase=SHORT_CAPTIVE_SELF_TEST; + case S_OPT_TEST: + if (!strcmp(optarg,"offline")) { + con->smartexeoffimmediate = TRUE; + con->testcase = OFFLINE_FULL_SCAN; + } else if (!strcmp(optarg,"short")) { + con->smartshortselftest = TRUE; + con->testcase = SHORT_SELF_TEST; + } else if (!strcmp(optarg,"long")) { + con->smartextendselftest = TRUE; + con->testcase = EXTEND_SELF_TEST; + } else { + badarg = TRUE; + } break; - case SMARTEXTENDCAPSELFTEST: - con->smartextendcapselftest = TRUE; - con->testcase=EXTEND_CAPTIVE_SELF_TEST; + case S_OPT_CAPTIVE: + captive = TRUE; break; - case SMARTSELFTESTABORT: + case S_OPT_ABORT: con->smartselftestabort = TRUE; - con->testcase=ABORT_SELF_TEST; + con->testcase = ABORT_SELF_TEST; break; - case 'h': - case '?': + case S_OPT_HELP: + case S_OPT_ALT_HELP: default: con->veryquietmode=FALSE; printslogan(); - if (optopt){ - pout("=======> UNRECOGNIZED OPTION: %c <=======\n\n",(int)optopt); +#ifdef HAVE_GETOPT_LONG + // Point arg to the argument in which this option was found. + arg = argv[optind-1]; + // Check whether the option is a long option and options that map to -h. + if (arg[1] == '-' && optchar != S_OPT_HELP) { + // Iff optopt holds a valid option then argument must be missing. + if (optopt && (strchr(shortopts, optopt) != NULL)) { + pout("=======> ARGUMENT REQUIRED FOR OPTION: %s <=======\n\n",arg+2); + } else { + pout("=======> UNRECOGNIZED OPTION: %s <=======\n\n",arg+2); + } + Usage(); + exit(FAILCMD); + } +#endif + if (optopt) { + // Iff optopt holds a valid option then argument must be missing. + if (strchr(shortopts, optopt) != NULL){ + pout("=======> ARGUMENT REQUIRED FOR OPTION: %c <=======\n\n",optopt); + } else { + pout("=======> UNRECOGNIZED OPTION: %c <=======\n\n",optopt); + } Usage(); exit(FAILCMD); } Usage(); exit(0); } + if (badarg) { + pout("=======> INVALID ARGUMENT: %s <======= \n\n",optarg); + Usage(); + exit(FAILCMD); + } } // Do this here, so results are independent of argument order if (con->quietmode) @@ -268,6 +409,17 @@ void ParseOpts (int argc, char** argv){ exit(FAILCMD); } + // If captive option was used, change test type if appropriate. + if (captive && con->smartshortselftest) { + con->smartshortselftest = FALSE; + con->smartshortcapselftest = TRUE; + con->testcase = SHORT_CAPTIVE_SELF_TEST; + } else if (captive && con->smartextendselftest) { + con->smartextendselftest = FALSE; + con->smartextendcapselftest = TRUE; + con->testcase = EXTEND_CAPTIVE_SELF_TEST; + } + // From here on, normal operations... printslogan(); diff --git a/sm5/smartctl.h b/sm5/smartctl.h index 5a59a2ef7..79e3eec7d 100644 --- a/sm5/smartctl.h +++ b/sm5/smartctl.h @@ -26,7 +26,7 @@ #define __SMARTCTL_H_ #ifndef CVSID6 -#define CVSID6 "$Id: smartctl.h,v 1.13 2002/11/07 19:07:20 ballen4705 Exp $\n" +#define CVSID6 "$Id: smartctl.h,v 1.14 2002/12/11 00:11:31 pjwilliams Exp $\n" #endif /* Defines for command line options */ @@ -59,6 +59,51 @@ #define ULTRACONSERVATIVE 'U' #define PERMISSIVE 'P' +#define S_OPT_HELP 'h' +#define S_OPT_ALT_HELP '?' +#define S_OPT_VERSION 'V' +#define S_OPT_QUIETMODE 'q' +#define S_OPT_DEVICE 'd' +#define S_OPT_TOLERANCE 'T' +#define S_OPT_BADSUM 'b' +#define S_OPT_SMART 's' +#define S_OPT_OFFLINEAUTO 'o' +#define S_OPT_SAVEAUTO 'S' +#define S_OPT_HEALTH 'H' +#define S_OPT_CAPABILITIES 'c' +#define S_OPT_ATTRIBUTES 'A' +#define S_OPT_LOG 'l' +#define S_OPT_INFO 'i' +#define S_OPT_ALL 'a' +#define S_OPT_VENDORATTRIBUTE 'v' +#define S_OPT_TEST 't' +#define S_OPT_CAPTIVE 'C' +#define S_OPT_ABORT 'X' +#ifdef HAVE_GETOPT_LONG +#define L_OPT_HELP "help" +#define L_OPT_USAGE "usage" +#define L_OPT_VERSION "version" +#define L_OPT_COPYRIGHT "copyright" +#define L_OPT_LICENSE "license" +#define L_OPT_QUIETMODE "quietmode" +#define L_OPT_DEVICE "device" +#define L_OPT_TOLERANCE "tolerance" +#define L_OPT_BADSUM "badsum" +#define L_OPT_SMART "smart" +#define L_OPT_OFFLINEAUTO "offlineauto" +#define L_OPT_SAVEAUTO "saveauto" +#define L_OPT_HEALTH "health" +#define L_OPT_CAPABILITIES "capabilities" +#define L_OPT_ATTRIBUTES "attributes" +#define L_OPT_LOG "log" +#define L_OPT_INFO "info" +#define L_OPT_ALL "all" +#define L_OPT_VENDORATTRIBUTE "vendorattribute" +#define L_OPT_TEST "test" +#define L_OPT_CAPTIVE "captive" +#define L_OPT_ABORT "abort" +#endif + /* Boolean Values */ #define TRUE 0x01 -- GitLab