diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG
index c8914c375c8b865cbff4278f83592a11f17a2374..c2eb63424704119336dc87dee242c2df5319341e 100644
--- a/sm5/CHANGELOG
+++ b/sm5/CHANGELOG
@@ -1,6 +1,6 @@
 CHANGELOG for smartmontools
 
-$Id: CHANGELOG,v 1.258 2003/11/16 22:49:14 pjwilliams Exp $
+$Id: CHANGELOG,v 1.259 2003/11/17 03:10:40 ballen4705 Exp $
 
 Maintainers / Developers Key:
 [BA] Bruce Allen
@@ -23,6 +23,10 @@ CURRENT DEVELOPMENT VERSION (see VERSION file in this directory):
 
   <ADDITIONS TO THE CHANGE LOG SHOULD BE ADDED HERE, PLEASE>
 
+  [BA] smartd: deviceclose()->CloseDevice(). Got rid of SCSIDEVELOPMENT
+       macro-enabled code.  Added -W to list of gcc specific options to
+       always enable. Made code clean for -W warnings.
+
   [PW] Added Maxtor DiamondMax VL 30 family to knowndrives table.
 
   [DG] scsi: add warning (when '-l error' active) if Control mode page
@@ -94,10 +98,12 @@ CURRENT DEVELOPMENT VERSION (see VERSION file in this directory):
        devicescan code to also use glob(3). Also verified clean 
        compile on a 4.7 FreeBSD system.
 
-  [BA] smartd: Modified device scan code to use glob(3). Previously it
-       appeared to have trouble when
-       scanning devices on an XFS file system, and used non-public
-       interface to directory entries.
+  [BA] smartd: Modified device scan code to use glob(3). Previously
+       it appeared to have trouble when scanning devices on an XFS
+       file system, and used non-public interface to directory
+       entries. Problems were also reported when /dev/ was on an
+       ext2/3 file system, but there was a JFS partition on the same
+       disk.
 
   [BA] Clearer error messages when device scanning finds no suitable
        devices.
diff --git a/sm5/configure.in b/sm5/configure.in
index 69c682e1f4c1ffb06793470f5ceb813c35e8d9b7..a73b27e6cb7a42716f8a04385812e29f09c687da 100644
--- a/sm5/configure.in
+++ b/sm5/configure.in
@@ -1,5 +1,5 @@
 #
-# $Id: configure.in,v 1.33 2003/11/02 18:15:53 ballen4705 Exp $
+# $Id: configure.in,v 1.34 2003/11/17 03:10:40 ballen4705 Exp $
 #
 dnl Process this file with autoconf to produce a configure script.
 AC_PREREQ(2.50)
@@ -7,7 +7,7 @@ AC_INIT(smartmontools, 5.24, smartmontools-support@lists.sourceforge.net)
 AC_CONFIG_SRCDIR(smartctl.c)
 
 smartmontools_configure_date=`date -u +"%Y/%m/%d %T %Z"`
-smartmontools_cvs_tag=`echo '$Id: configure.in,v 1.33 2003/11/02 18:15:53 ballen4705 Exp $'`
+smartmontools_cvs_tag=`echo '$Id: configure.in,v 1.34 2003/11/17 03:10:40 ballen4705 Exp $'`
 
 AC_DEFINE_UNQUOTED(SMARTMONTOOLS_CONFIGURE_ARGS, "$ac_configure_args",            [smartmontools Configure Arguments])
 AC_DEFINE_UNQUOTED(SMARTMONTOOLS_CONFIGURE_DATE, "$smartmontools_configure_date", [smartmontools Configure Date])
@@ -84,11 +84,15 @@ case "${host}" in
 		AC_SUBST([os_libs], ['']) ;;
 esac
 
-# Add -Wall if using gcc and its not already there specified.
+dnl Add -Wall and -W if using gcc and its not already specified.
 if test "x$GCC" = "xyes"; then
   if test -z "`echo "$CFLAGS" | grep "\-Wall" 2> /dev/null`" ; then
       CFLAGS="$CFLAGS -Wall"
   fi
+# In the next line, do NOT delete the 2 spaces inside double quotes.
+  if test -z "`echo "$CFLAGS " | grep "\-W " 2> /dev/null`" ; then
+      CFLAGS="$CFLAGS -W"
+  fi
 else
  dnl We are NOT using gcc, so enable host-specific compiler flags
  case "${host}" in
diff --git a/sm5/extern.h b/sm5/extern.h
index 4ec14a7c735be240dc4cee29645f1d18cd8fc913..b13f335b702c11fca12b8c8e6e2da9868d9535fe 100644
--- a/sm5/extern.h
+++ b/sm5/extern.h
@@ -25,7 +25,7 @@
 #ifndef EXTERN_H_
 #define EXTERN_H_
 
-#define EXTERN_H_CVSID "$Id: extern.h,v 1.30 2003/10/12 09:10:03 ballen4705 Exp $\n"
+#define EXTERN_H_CVSID "$Id: extern.h,v 1.31 2003/11/17 03:10:40 ballen4705 Exp $\n"
 
 // For development and testing of Selective self-test code
 #define DEVELOP_SELECTIVE_SELF_TEST 0
@@ -43,14 +43,17 @@ typedef struct smartmonctrl_s {
   unsigned char checksmart;
   unsigned char smartvendorattrib;
   unsigned char generalsmartvalues;
+
   unsigned char smartlogdirectory;
   unsigned char smartselftestlog;
   unsigned char smarterrorlog;
   unsigned char smartdisable;
+
   unsigned char smartenable; 
   unsigned char smartstatus;
   unsigned char smartexeoffimmediate;
   unsigned char smartshortselftest;
+
   unsigned char smartextendselftest;
   unsigned char smartconveyanceselftest;
 #if DEVELOP_SELECTIVE_SELF_TEST
@@ -58,6 +61,7 @@ typedef struct smartmonctrl_s {
 #endif
   unsigned char smartshortcapselftest;
   unsigned char smartextendcapselftest;
+
   unsigned char smartconveyancecapselftest;
 #if DEVELOP_SELECTIVE_SELF_TEST
   unsigned char smartselectivecapselftest;
@@ -65,25 +69,30 @@ typedef struct smartmonctrl_s {
   unsigned char smartselftestabort;
   unsigned char smartautoofflineenable;
   unsigned char smartautoofflinedisable;
+
   unsigned char smartautosaveenable;
   unsigned char smartautosavedisable;
 #if DEVELOP_SELECTIVE_SELF_TEST
   unsigned long long smartselectivespan[5][2];
   int smartselectivenumspans;
 #endif
-  int           testcase;
   unsigned char quietmode;
   unsigned char veryquietmode;
+
+  int           testcase;
+
   unsigned char permissive;
   unsigned char conservative;
   unsigned char checksumfail;
   unsigned char checksumignore;
+
   unsigned char reportataioctl;
   unsigned char reportscsiioctl;
   unsigned char fixfirmwarebug;
   // If nonzero, escalade is 1 plus the disk number behind an escalade
   // controller
   unsigned char escalade;
+
   unsigned char ignorepresets;
   unsigned char showpresets;
   // The i'th entry in this array will modify the printed meaning of
@@ -92,6 +101,10 @@ typedef struct smartmonctrl_s {
   // attributedefs[i] is nonzero, it means that the i'th attribute has
   // a non-default meaning.  See the ataPrintSmartAttribName and
   // and parse_attribute_def functions.
+
+  char notused1;    // make structure pack cleanly without holes
+  char notused2;
+
   unsigned char attributedefs[256];
 } smartmonctrl;
 
diff --git a/sm5/os_linux.c b/sm5/os_linux.c
index 29b566541b48cd6b1f98670edddd472b2e5f9375..4352aef32dfe05a7c33dc533abe6ca429eb0e2da 100644
--- a/sm5/os_linux.c
+++ b/sm5/os_linux.c
@@ -60,7 +60,7 @@
 #include "smartd.h"
 #include "utility.h"
 
-const char *os_XXXX_c_cvsid="$Id: os_linux.c,v 1.27 2003/11/16 12:20:14 dpgilbert Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_linux.c,v 1.28 2003/11/17 03:10:40 ballen4705 Exp $" \
 ATACMDS_H_CVSID CONFIG_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID SMARTD_H_CVSID UTILITY_H_CVSID;
 
 // to hold onto exit code for atexit routine
@@ -96,8 +96,10 @@ int deviceclose(int fd){
 int get_dev_names(char*** names, const char* pattern, const char* name, int max) {
   int n = 0, retglob, i, lim;
   char** mp;
-  glob_t globbuf={0};
+  glob_t globbuf;
   
+  memset(&globbuf, 0, sizeof(globbuf));
+
   // in case of non-clean exit
   *names=NULL;
   
diff --git a/sm5/os_linux.cpp b/sm5/os_linux.cpp
index 7e5b207b28fcdeb99361224b1c34294c28a2a43f..61377e49155f655291fc08c9e915d6f8503e1d23 100644
--- a/sm5/os_linux.cpp
+++ b/sm5/os_linux.cpp
@@ -60,7 +60,7 @@
 #include "smartd.h"
 #include "utility.h"
 
-const char *os_XXXX_c_cvsid="$Id: os_linux.cpp,v 1.27 2003/11/16 12:20:14 dpgilbert Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_linux.cpp,v 1.28 2003/11/17 03:10:40 ballen4705 Exp $" \
 ATACMDS_H_CVSID CONFIG_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID SMARTD_H_CVSID UTILITY_H_CVSID;
 
 // to hold onto exit code for atexit routine
@@ -96,8 +96,10 @@ int deviceclose(int fd){
 int get_dev_names(char*** names, const char* pattern, const char* name, int max) {
   int n = 0, retglob, i, lim;
   char** mp;
-  glob_t globbuf={0};
+  glob_t globbuf;
   
+  memset(&globbuf, 0, sizeof(globbuf));
+
   // in case of non-clean exit
   *names=NULL;
   
diff --git a/sm5/scsiprint.c b/sm5/scsiprint.c
index bfe5e1bab2b8958eada7340011341b4393b1beed..84abb83454f04fa355cd3a559e2292be38bb645f 100644
--- a/sm5/scsiprint.c
+++ b/sm5/scsiprint.c
@@ -40,7 +40,7 @@
 
 #define GBUF_SIZE 65535
 
-const char* scsiprint_c_cvsid="$Id: scsiprint.c,v 1.60 2003/11/16 16:59:23 ballen4705 Exp $"
+const char* scsiprint_c_cvsid="$Id: scsiprint.c,v 1.61 2003/11/17 03:10:40 ballen4705 Exp $"
 EXTERN_H_CVSID SCSICMDS_H_CVSID SCSIPRINT_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID;
 
 // control block which points to external global control variables
@@ -608,6 +608,22 @@ static int scsiGetDriveInfo(int device, UINT8 * peripheral_type, int all)
         memset(revision, 0, sizeof(revision));
         strncpy(revision, (char *)&gBuf[32], 4);
         pout("Device: %s %s Version: %s\n", manufacturer, product, revision);
+
+	/* 
+	   Doug: for a bad USB device, the code hangs in the following
+	   line within scsiInquiryVpd():
+
+	   status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
+	   
+	   and within do_scsi_cmnd_io() it hangs in the line:
+
+	   status = ioctl(dev_fd, SCSI_IOCTL_SEND_COMMAND , &wrk);
+
+	   which never returns.  Would it be possible to put in a
+	   sanity check to detect such devices and exit with an error
+	   message, before calling scsiInquiryVpd()?
+
+	*/
         if (0 == (err = scsiInquiryVpd(device, 0x80, gBuf, 64))) {
             /* should use VPD page 0x83 and fall back to this page (0x80)
              * if 0x83 not supported. NAA requires a lot of decoding code */
diff --git a/sm5/scsiprint.cpp b/sm5/scsiprint.cpp
index 483cc90c493013b1bf42132d7ccf5b3c751ff22e..236d3efbc580d4a9498721de718f83dfe4f9853e 100644
--- a/sm5/scsiprint.cpp
+++ b/sm5/scsiprint.cpp
@@ -40,7 +40,7 @@
 
 #define GBUF_SIZE 65535
 
-const char* scsiprint_c_cvsid="$Id: scsiprint.cpp,v 1.60 2003/11/16 16:59:23 ballen4705 Exp $"
+const char* scsiprint_c_cvsid="$Id: scsiprint.cpp,v 1.61 2003/11/17 03:10:40 ballen4705 Exp $"
 EXTERN_H_CVSID SCSICMDS_H_CVSID SCSIPRINT_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID;
 
 // control block which points to external global control variables
@@ -608,6 +608,22 @@ static int scsiGetDriveInfo(int device, UINT8 * peripheral_type, int all)
         memset(revision, 0, sizeof(revision));
         strncpy(revision, (char *)&gBuf[32], 4);
         pout("Device: %s %s Version: %s\n", manufacturer, product, revision);
+
+	/* 
+	   Doug: for a bad USB device, the code hangs in the following
+	   line within scsiInquiryVpd():
+
+	   status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl);
+	   
+	   and within do_scsi_cmnd_io() it hangs in the line:
+
+	   status = ioctl(dev_fd, SCSI_IOCTL_SEND_COMMAND , &wrk);
+
+	   which never returns.  Would it be possible to put in a
+	   sanity check to detect such devices and exit with an error
+	   message, before calling scsiInquiryVpd()?
+
+	*/
         if (0 == (err = scsiInquiryVpd(device, 0x80, gBuf, 64))) {
             /* should use VPD page 0x83 and fall back to this page (0x80)
              * if 0x83 not supported. NAA requires a lot of decoding code */
diff --git a/sm5/smartd.c b/sm5/smartd.c
index 29639b5e65877e276e4bfad77d2a0a30dc487bfe..04b8dcfa3b7fad56c4de106dec25a83c1f76cf70 100644
--- a/sm5/smartd.c
+++ b/sm5/smartd.c
@@ -65,7 +65,7 @@
 extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *escalade_c_cvsid, 
                   *knowndrives_c_cvsid, *os_XXXX_c_cvsid, *scsicmds_c_cvsid, *utility_c_cvsid;
 
-const char *smartd_c_cvsid="$Id: smartd.c,v 1.239 2003/11/16 16:53:02 ballen4705 Exp $" 
+const char *smartd_c_cvsid="$Id: smartd.c,v 1.240 2003/11/17 03:10:40 ballen4705 Exp $" 
                             ATACMDS_H_CVSID ATAPRINT_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID
                             SCSICMDS_H_CVSID SMARTD_H_CVSID UTILITY_H_CVSID; 
 
@@ -771,7 +771,7 @@ int ATADeviceScan(cfgfile *cfg){
     else
       PrintOut(LOG_INFO,"Device: %s, packet devices [this device %s] not SMART capable\n",
 	       name, packetdevicetype(retid-1));
-    deviceclose(fd);
+    CloseDevice(fd, name);
     return 2; 
   }
 
@@ -817,7 +817,7 @@ int ATADeviceScan(cfgfile *cfg){
     }
     else {
       PrintOut(LOG_INFO,"Device: %s, to proceed anyway, use '-T permissive' Directive.\n",name);
-      deviceclose(fd);
+      CloseDevice(fd, name);
       return 2;
     }
   }
@@ -825,7 +825,7 @@ int ATADeviceScan(cfgfile *cfg){
   if (ataEnableSmart(fd)){
     // Enable SMART command has failed
     PrintOut(LOG_INFO,"Device: %s, could not enable SMART capability\n",name);
-    deviceclose(fd);
+    CloseDevice(fd, name);
     return 2; 
   }
   
@@ -958,7 +958,7 @@ int ATADeviceScan(cfgfile *cfg){
   // If no tests available or selected, return
   if (!(cfg->errorlog || cfg->selftest || cfg->smartcheck || 
         cfg->usagefailed || cfg->prefail || cfg->usage)) {
-    deviceclose(fd);
+    CloseDevice(fd, name);
     return 3;
   }
   
@@ -983,144 +983,131 @@ int ATADeviceScan(cfgfile *cfg){
 
 // on success, return 0. On failure, return >0.  Never return <0,
 // please.
-static int SCSIDeviceScan(cfgfile *cfg)
-{
-    int k, fd, err; 
-    char *device = cfg->name;
-    struct scsi_iec_mode_page iec;
-    UINT8  tBuf[64];
-
-    // should we try to register this as a SCSI device?
-    if (! cfg->tryscsi)
-        return 1;
-    // open the device
-    if ((fd = OpenDevice(device, "SCSI")) < 0) {
-#ifdef SCSIDEVELOPMENT
-        PrintOut(LOG_WARNING, "Device: %s, skip\n", device);
-        return 0;
-#else
-        return 1;
-#endif
-    }
-    PrintOut(LOG_INFO,"Device: %s, opened\n", device);
-  
-    // check that it's ready for commands. IE stores its stuff on the media.
-    if ((err = scsiTestUnitReady(fd))) {
-      if (1 == err)
-	PrintOut(LOG_WARNING, "Device: %s, NOT READY (media absent, spun "
-		 "down); skip\n", device);
-      else
-	PrintOut(LOG_ERR, "Device: %s, failed Test Unit Ready [err=%d]\n", 
-		 device, err);
-      deviceclose(fd);
-#ifdef SCSIDEVELOPMENT
-      return 0;
-#else
-      return 2; 
-#endif
-    }
+static int SCSIDeviceScan(cfgfile *cfg) {
+  int k, fd, err; 
+  char *device = cfg->name;
+  struct scsi_iec_mode_page iec;
+  UINT8  tBuf[64];
+  
+  // should we try to register this as a SCSI device?
+  if (!cfg->tryscsi)
+    return 1;
   
-    if ((err = scsiFetchIECmpage(fd, &iec, cfg->modese_len))) {
-      PrintOut(LOG_WARNING, "Device: %s, Fetch of IEC (SMART) mode page "
-	       "failed, err=%d, skip device\n", device, err);
-      deviceclose(fd);
-#ifdef SCSIDEVELOPMENT
-      return 0;
-#else
-      return 3;
-#endif
-    }
+  // open the device
+  if ((fd = OpenDevice(device, "SCSI")) < 0)
+    return 1;
+  PrintOut(LOG_INFO,"Device: %s, opened\n", device);
+    
+  // check that device is ready for commands. IE stores its stuff on
+  // the media.
+  if ((err = scsiTestUnitReady(fd))) {
+    if (1 == err)
+      PrintOut(LOG_INFO, "Device: %s, NOT READY (media absent, spun down); skip device\n", device);
     else
-        cfg->modese_len = iec.modese_len;
-
-    if (! scsi_IsExceptionControlEnabled(&iec)) {
-      PrintOut(LOG_WARNING, "Device: %s, IE (SMART) not enabled, "
-	       "skip device\n", device);
-      deviceclose(fd);
-#ifdef SCSIDEVELOPMENT
-      return 0;
-#else
-      return 3;
-#endif
-    }
+      PrintOut(LOG_CRIT, "Device: %s, failed Test Unit Ready [err=%d]\n", device, err);
+    CloseDevice(fd, device);
+    return 2; 
+  }
+  
+  // Badly-confirming USB storage devices should fail this check.
+  // Doug, is it possible that a device will have functionality that
+  // we might want to monitor with smartd (such as the Temperature
+  // page or Self-test log) but DOESN'T support the IE mode page?  If
+  // so, we might want to make the 'skip device' contingent on a
+  // problem like the wrong length, rather than simply on
+  // non-existence of the page.
+  if ((err = scsiFetchIECmpage(fd, &iec, cfg->modese_len))) {
+    PrintOut(LOG_INFO, 
+	     "Device: %s, Fetch of IEC (SMART) mode page failed, err=%d, skip device\n", device, err);
+    CloseDevice(fd, device);
+    return 3;
+  }
+  else
+    cfg->modese_len = iec.modese_len;
     
-    // Device exists, and does SMART.  Add to list
-    if (numdevscsi >= MAXSCSIDEVICES) {
-      PrintOut(LOG_ERR, "smartd has found more than MAXSCSIDEVICES=%d "
-	       "SCSI devices.\n" "Recompile code from " PROJECTHOME 
-	       " with larger MAXSCSIDEVICES\n", (int)numdevscsi);
-#ifdef SCSIDEVELOPMENT
-      deviceclose(fd);
-      return 0;
-#else
-      EXIT(EXIT_CCONST);
-#endif
-    }
+  // Doug should we try to enable IE if it's not already enabled?
+  // This is what the ATA code does: enables SMART on devices.
+  if (!scsi_IsExceptionControlEnabled(&iec)) {
+    PrintOut(LOG_INFO, "Device: %s, IE (SMART) not enabled, skip device\n", device);
+    CloseDevice(fd, device);
+    return 3;
+  }
+  
+  // Device exists, and does SMART.  Add to list
+  if (numdevscsi >= MAXSCSIDEVICES) {
+    PrintOut(LOG_CRIT, 
+	     "smartd has found more than MAXSCSIDEVICES=%d SCSI devices.\n" 
+	     "Recompile code from " PROJECTHOME " with larger MAXSCSIDEVICES\n", 
+	     (int)numdevscsi);
+    EXIT(EXIT_CCONST);
+  }
+  
+  // Flag that certain log pages are supported (information may be
+  // available from other sources).
+  if (0 == scsiLogSense(fd, SUPPORTED_LPAGES, tBuf, sizeof(tBuf), 0)) {
+    for (k = 4; k < tBuf[3] + LOGPAGEHDRSIZE; ++k) {
+      switch (tBuf[k]) { 
+      case TEMPERATURE_LPAGE:
+	cfg->TempPageSupported = 1;
+	break;
+      case IE_LPAGE:
+	cfg->SmartPageSupported = 1;
+	break;
+      default:
+	break;
+      }
+    }   
+  }
+  
+  // record type of device
+  cfg->tryata = 0;
+  cfg->tryscsi = 1;
+  
+  // get rid of allocated memory only needed for ATA devices.  These
+  // might have been allocated if the user specified Ignore options or
+  // other ATA-only Attribute-specific options on the DEVICESCAN line.
+  cfg->monitorattflags = FreeNonZero(cfg->monitorattflags, NMONITOR*32,__LINE__,__FILE__);
+  cfg->attributedefs   = FreeNonZero(cfg->attributedefs,   MAX_ATTRIBUTE_NUM,__LINE__,__FILE__);
+  cfg->smartval        = FreeNonZero(cfg->smartval,        sizeof(struct ata_smart_values),__LINE__,__FILE__);
+  cfg->smartthres      = FreeNonZero(cfg->smartthres,      sizeof(struct ata_smart_thresholds),__LINE__,__FILE__);
+  
+  // Check if scsiCheckIE() is going to work
+  {
+    UINT8 asc = 0;
+    UINT8 ascq = 0;
+    UINT8 currenttemp = 0;
+    UINT8 triptemp = 0;
     
-    // now we can proceed to register the device
-    PrintOut(LOG_INFO, "Device: %s, is SMART capable. Adding "
-             "to \"monitor\" list.\n",device);
- 
-    // Flag that certain log pages are supported (information may be
-    // available from other sources).
-    if (0 == scsiLogSense(fd, SUPPORTED_LPAGES, tBuf, sizeof(tBuf), 0)) {
-        for (k = 4; k < tBuf[3] + LOGPAGEHDRSIZE; ++k) {
-            switch (tBuf[k]) { 
-                case TEMPERATURE_LPAGE:
-                    cfg->TempPageSupported = 1;
-                    break;
-                case IE_LPAGE:
-                    cfg->SmartPageSupported = 1;
-                    break;
-                default:
-                    break;
-            }
-        }   
+    if (scsiCheckIE(fd, cfg->SmartPageSupported, cfg->TempPageSupported,
+		    &asc, &ascq, &currenttemp, &triptemp)) {
+      PrintOut(LOG_INFO, "Device: %s, unexpectedly failed to read SMART values\n", device);
+      cfg->SuppressReport = 1;
     }
-
-    // record number of device, type of device, increment device count
-    cfg->tryata = 0;
-    cfg->tryscsi = 1;
-
-    // get rid of allocated memory only needed for ATA devices
-    cfg->monitorattflags = FreeNonZero(cfg->monitorattflags, NMONITOR*32,__LINE__,__FILE__);
-    cfg->attributedefs   = FreeNonZero(cfg->attributedefs,   MAX_ATTRIBUTE_NUM,__LINE__,__FILE__);
-    cfg->smartval        = FreeNonZero(cfg->smartval,        sizeof(struct ata_smart_values),__LINE__,__FILE__);
-    cfg->smartthres      = FreeNonZero(cfg->smartthres,      sizeof(struct ata_smart_thresholds),__LINE__,__FILE__);
-
-    // Check if scsiCheckIE() is going to work
-    {
-        UINT8 asc = 0;
-        UINT8 ascq = 0;
-        UINT8 currenttemp = 0;
-        UINT8 triptemp = 0;
-
-        if (scsiCheckIE(fd, cfg->SmartPageSupported, cfg->TempPageSupported,
-                        &asc, &ascq, &currenttemp, &triptemp)) {
-            PrintOut(LOG_INFO, "Device: %s, unexpectedly failed to read SMART"
-                     " values\n", device);
-            cfg->SuppressReport = 1;
-        }
+  }
+  
+  // capability check: self-test-log
+  if (cfg->selftest){
+    int retval=scsiCountFailedSelfTests(fd, 0);
+    if (retval<0) {
+      // no self-test log, turn off monitoring
+      PrintOut(LOG_INFO, "Device: %s, does not support SMART Self-test Log.\n", device);
+      cfg->selftest=0;
+      cfg->selflogcount=0;
+      cfg->selfloghour=0;
     }
-
-    // capability check: self-test-log
-    if (cfg->selftest){
-      int retval=scsiCountFailedSelfTests(fd, 0);
-      if (retval<0) {
-	PrintOut(LOG_INFO, "Device: %s, does not support SMART Self-test Log.\n", device);
-	cfg->selftest=0;
-	cfg->selflogcount=0;
-	cfg->selfloghour=0;
-      }
-      else {
-	cfg->selflogcount=SELFTEST_ERRORCOUNT(retval);
-	cfg->selfloghour =SELFTEST_ERRORHOURS(retval);
-      }
+    else {
+      // register starting values to watch for changes
+      cfg->selflogcount=SELFTEST_ERRORCOUNT(retval);
+      cfg->selfloghour =SELFTEST_ERRORHOURS(retval);
     }
-
-    // close file descriptor
-    CloseDevice(fd, device);
-    return 0;
+  }
+  
+  // tell user we are registering device
+  PrintOut(LOG_INFO, "Device: %s, is SMART capable. Adding to \"monitor\" list.\n", device);
+  
+  // close file descriptor
+  CloseDevice(fd, device);
+  return 0;
 }
 
 // We compare old and new values of the n'th attribute.  Note that n
diff --git a/sm5/smartd.cpp b/sm5/smartd.cpp
index fa0bd593f0914b624b171aa094ec6d4a486b3310..de5ff7ac70e74cdd2327defd3a2b739686f9a78c 100644
--- a/sm5/smartd.cpp
+++ b/sm5/smartd.cpp
@@ -65,7 +65,7 @@
 extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *escalade_c_cvsid, 
                   *knowndrives_c_cvsid, *os_XXXX_c_cvsid, *scsicmds_c_cvsid, *utility_c_cvsid;
 
-const char *smartd_c_cvsid="$Id: smartd.cpp,v 1.239 2003/11/16 16:53:02 ballen4705 Exp $" 
+const char *smartd_c_cvsid="$Id: smartd.cpp,v 1.240 2003/11/17 03:10:40 ballen4705 Exp $" 
                             ATACMDS_H_CVSID ATAPRINT_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID
                             SCSICMDS_H_CVSID SMARTD_H_CVSID UTILITY_H_CVSID; 
 
@@ -771,7 +771,7 @@ int ATADeviceScan(cfgfile *cfg){
     else
       PrintOut(LOG_INFO,"Device: %s, packet devices [this device %s] not SMART capable\n",
 	       name, packetdevicetype(retid-1));
-    deviceclose(fd);
+    CloseDevice(fd, name);
     return 2; 
   }
 
@@ -817,7 +817,7 @@ int ATADeviceScan(cfgfile *cfg){
     }
     else {
       PrintOut(LOG_INFO,"Device: %s, to proceed anyway, use '-T permissive' Directive.\n",name);
-      deviceclose(fd);
+      CloseDevice(fd, name);
       return 2;
     }
   }
@@ -825,7 +825,7 @@ int ATADeviceScan(cfgfile *cfg){
   if (ataEnableSmart(fd)){
     // Enable SMART command has failed
     PrintOut(LOG_INFO,"Device: %s, could not enable SMART capability\n",name);
-    deviceclose(fd);
+    CloseDevice(fd, name);
     return 2; 
   }
   
@@ -958,7 +958,7 @@ int ATADeviceScan(cfgfile *cfg){
   // If no tests available or selected, return
   if (!(cfg->errorlog || cfg->selftest || cfg->smartcheck || 
         cfg->usagefailed || cfg->prefail || cfg->usage)) {
-    deviceclose(fd);
+    CloseDevice(fd, name);
     return 3;
   }
   
@@ -983,144 +983,131 @@ int ATADeviceScan(cfgfile *cfg){
 
 // on success, return 0. On failure, return >0.  Never return <0,
 // please.
-static int SCSIDeviceScan(cfgfile *cfg)
-{
-    int k, fd, err; 
-    char *device = cfg->name;
-    struct scsi_iec_mode_page iec;
-    UINT8  tBuf[64];
-
-    // should we try to register this as a SCSI device?
-    if (! cfg->tryscsi)
-        return 1;
-    // open the device
-    if ((fd = OpenDevice(device, "SCSI")) < 0) {
-#ifdef SCSIDEVELOPMENT
-        PrintOut(LOG_WARNING, "Device: %s, skip\n", device);
-        return 0;
-#else
-        return 1;
-#endif
-    }
-    PrintOut(LOG_INFO,"Device: %s, opened\n", device);
-  
-    // check that it's ready for commands. IE stores its stuff on the media.
-    if ((err = scsiTestUnitReady(fd))) {
-      if (1 == err)
-	PrintOut(LOG_WARNING, "Device: %s, NOT READY (media absent, spun "
-		 "down); skip\n", device);
-      else
-	PrintOut(LOG_ERR, "Device: %s, failed Test Unit Ready [err=%d]\n", 
-		 device, err);
-      deviceclose(fd);
-#ifdef SCSIDEVELOPMENT
-      return 0;
-#else
-      return 2; 
-#endif
-    }
+static int SCSIDeviceScan(cfgfile *cfg) {
+  int k, fd, err; 
+  char *device = cfg->name;
+  struct scsi_iec_mode_page iec;
+  UINT8  tBuf[64];
+  
+  // should we try to register this as a SCSI device?
+  if (!cfg->tryscsi)
+    return 1;
   
-    if ((err = scsiFetchIECmpage(fd, &iec, cfg->modese_len))) {
-      PrintOut(LOG_WARNING, "Device: %s, Fetch of IEC (SMART) mode page "
-	       "failed, err=%d, skip device\n", device, err);
-      deviceclose(fd);
-#ifdef SCSIDEVELOPMENT
-      return 0;
-#else
-      return 3;
-#endif
-    }
+  // open the device
+  if ((fd = OpenDevice(device, "SCSI")) < 0)
+    return 1;
+  PrintOut(LOG_INFO,"Device: %s, opened\n", device);
+    
+  // check that device is ready for commands. IE stores its stuff on
+  // the media.
+  if ((err = scsiTestUnitReady(fd))) {
+    if (1 == err)
+      PrintOut(LOG_INFO, "Device: %s, NOT READY (media absent, spun down); skip device\n", device);
     else
-        cfg->modese_len = iec.modese_len;
-
-    if (! scsi_IsExceptionControlEnabled(&iec)) {
-      PrintOut(LOG_WARNING, "Device: %s, IE (SMART) not enabled, "
-	       "skip device\n", device);
-      deviceclose(fd);
-#ifdef SCSIDEVELOPMENT
-      return 0;
-#else
-      return 3;
-#endif
-    }
+      PrintOut(LOG_CRIT, "Device: %s, failed Test Unit Ready [err=%d]\n", device, err);
+    CloseDevice(fd, device);
+    return 2; 
+  }
+  
+  // Badly-confirming USB storage devices should fail this check.
+  // Doug, is it possible that a device will have functionality that
+  // we might want to monitor with smartd (such as the Temperature
+  // page or Self-test log) but DOESN'T support the IE mode page?  If
+  // so, we might want to make the 'skip device' contingent on a
+  // problem like the wrong length, rather than simply on
+  // non-existence of the page.
+  if ((err = scsiFetchIECmpage(fd, &iec, cfg->modese_len))) {
+    PrintOut(LOG_INFO, 
+	     "Device: %s, Fetch of IEC (SMART) mode page failed, err=%d, skip device\n", device, err);
+    CloseDevice(fd, device);
+    return 3;
+  }
+  else
+    cfg->modese_len = iec.modese_len;
     
-    // Device exists, and does SMART.  Add to list
-    if (numdevscsi >= MAXSCSIDEVICES) {
-      PrintOut(LOG_ERR, "smartd has found more than MAXSCSIDEVICES=%d "
-	       "SCSI devices.\n" "Recompile code from " PROJECTHOME 
-	       " with larger MAXSCSIDEVICES\n", (int)numdevscsi);
-#ifdef SCSIDEVELOPMENT
-      deviceclose(fd);
-      return 0;
-#else
-      EXIT(EXIT_CCONST);
-#endif
-    }
+  // Doug should we try to enable IE if it's not already enabled?
+  // This is what the ATA code does: enables SMART on devices.
+  if (!scsi_IsExceptionControlEnabled(&iec)) {
+    PrintOut(LOG_INFO, "Device: %s, IE (SMART) not enabled, skip device\n", device);
+    CloseDevice(fd, device);
+    return 3;
+  }
+  
+  // Device exists, and does SMART.  Add to list
+  if (numdevscsi >= MAXSCSIDEVICES) {
+    PrintOut(LOG_CRIT, 
+	     "smartd has found more than MAXSCSIDEVICES=%d SCSI devices.\n" 
+	     "Recompile code from " PROJECTHOME " with larger MAXSCSIDEVICES\n", 
+	     (int)numdevscsi);
+    EXIT(EXIT_CCONST);
+  }
+  
+  // Flag that certain log pages are supported (information may be
+  // available from other sources).
+  if (0 == scsiLogSense(fd, SUPPORTED_LPAGES, tBuf, sizeof(tBuf), 0)) {
+    for (k = 4; k < tBuf[3] + LOGPAGEHDRSIZE; ++k) {
+      switch (tBuf[k]) { 
+      case TEMPERATURE_LPAGE:
+	cfg->TempPageSupported = 1;
+	break;
+      case IE_LPAGE:
+	cfg->SmartPageSupported = 1;
+	break;
+      default:
+	break;
+      }
+    }   
+  }
+  
+  // record type of device
+  cfg->tryata = 0;
+  cfg->tryscsi = 1;
+  
+  // get rid of allocated memory only needed for ATA devices.  These
+  // might have been allocated if the user specified Ignore options or
+  // other ATA-only Attribute-specific options on the DEVICESCAN line.
+  cfg->monitorattflags = FreeNonZero(cfg->monitorattflags, NMONITOR*32,__LINE__,__FILE__);
+  cfg->attributedefs   = FreeNonZero(cfg->attributedefs,   MAX_ATTRIBUTE_NUM,__LINE__,__FILE__);
+  cfg->smartval        = FreeNonZero(cfg->smartval,        sizeof(struct ata_smart_values),__LINE__,__FILE__);
+  cfg->smartthres      = FreeNonZero(cfg->smartthres,      sizeof(struct ata_smart_thresholds),__LINE__,__FILE__);
+  
+  // Check if scsiCheckIE() is going to work
+  {
+    UINT8 asc = 0;
+    UINT8 ascq = 0;
+    UINT8 currenttemp = 0;
+    UINT8 triptemp = 0;
     
-    // now we can proceed to register the device
-    PrintOut(LOG_INFO, "Device: %s, is SMART capable. Adding "
-             "to \"monitor\" list.\n",device);
- 
-    // Flag that certain log pages are supported (information may be
-    // available from other sources).
-    if (0 == scsiLogSense(fd, SUPPORTED_LPAGES, tBuf, sizeof(tBuf), 0)) {
-        for (k = 4; k < tBuf[3] + LOGPAGEHDRSIZE; ++k) {
-            switch (tBuf[k]) { 
-                case TEMPERATURE_LPAGE:
-                    cfg->TempPageSupported = 1;
-                    break;
-                case IE_LPAGE:
-                    cfg->SmartPageSupported = 1;
-                    break;
-                default:
-                    break;
-            }
-        }   
+    if (scsiCheckIE(fd, cfg->SmartPageSupported, cfg->TempPageSupported,
+		    &asc, &ascq, &currenttemp, &triptemp)) {
+      PrintOut(LOG_INFO, "Device: %s, unexpectedly failed to read SMART values\n", device);
+      cfg->SuppressReport = 1;
     }
-
-    // record number of device, type of device, increment device count
-    cfg->tryata = 0;
-    cfg->tryscsi = 1;
-
-    // get rid of allocated memory only needed for ATA devices
-    cfg->monitorattflags = FreeNonZero(cfg->monitorattflags, NMONITOR*32,__LINE__,__FILE__);
-    cfg->attributedefs   = FreeNonZero(cfg->attributedefs,   MAX_ATTRIBUTE_NUM,__LINE__,__FILE__);
-    cfg->smartval        = FreeNonZero(cfg->smartval,        sizeof(struct ata_smart_values),__LINE__,__FILE__);
-    cfg->smartthres      = FreeNonZero(cfg->smartthres,      sizeof(struct ata_smart_thresholds),__LINE__,__FILE__);
-
-    // Check if scsiCheckIE() is going to work
-    {
-        UINT8 asc = 0;
-        UINT8 ascq = 0;
-        UINT8 currenttemp = 0;
-        UINT8 triptemp = 0;
-
-        if (scsiCheckIE(fd, cfg->SmartPageSupported, cfg->TempPageSupported,
-                        &asc, &ascq, &currenttemp, &triptemp)) {
-            PrintOut(LOG_INFO, "Device: %s, unexpectedly failed to read SMART"
-                     " values\n", device);
-            cfg->SuppressReport = 1;
-        }
+  }
+  
+  // capability check: self-test-log
+  if (cfg->selftest){
+    int retval=scsiCountFailedSelfTests(fd, 0);
+    if (retval<0) {
+      // no self-test log, turn off monitoring
+      PrintOut(LOG_INFO, "Device: %s, does not support SMART Self-test Log.\n", device);
+      cfg->selftest=0;
+      cfg->selflogcount=0;
+      cfg->selfloghour=0;
     }
-
-    // capability check: self-test-log
-    if (cfg->selftest){
-      int retval=scsiCountFailedSelfTests(fd, 0);
-      if (retval<0) {
-	PrintOut(LOG_INFO, "Device: %s, does not support SMART Self-test Log.\n", device);
-	cfg->selftest=0;
-	cfg->selflogcount=0;
-	cfg->selfloghour=0;
-      }
-      else {
-	cfg->selflogcount=SELFTEST_ERRORCOUNT(retval);
-	cfg->selfloghour =SELFTEST_ERRORHOURS(retval);
-      }
+    else {
+      // register starting values to watch for changes
+      cfg->selflogcount=SELFTEST_ERRORCOUNT(retval);
+      cfg->selfloghour =SELFTEST_ERRORHOURS(retval);
     }
-
-    // close file descriptor
-    CloseDevice(fd, device);
-    return 0;
+  }
+  
+  // tell user we are registering device
+  PrintOut(LOG_INFO, "Device: %s, is SMART capable. Adding to \"monitor\" list.\n", device);
+  
+  // close file descriptor
+  CloseDevice(fd, device);
+  return 0;
 }
 
 // We compare old and new values of the n'th attribute.  Note that n
diff --git a/sm5/smartd.h b/sm5/smartd.h
index aa0f70ac45e31217c23d8a7c6b021e00e2bce509..e90e7a3e6091b8f98fca0b3695af9872c9de31d5 100644
--- a/sm5/smartd.h
+++ b/sm5/smartd.h
@@ -27,7 +27,7 @@
 
 
 #ifndef SMARTD_H_CVSID
-#define SMARTD_H_CVSID "$Id: smartd.h,v 1.57 2003/11/14 11:52:33 dpgilbert Exp $\n"
+#define SMARTD_H_CVSID "$Id: smartd.h,v 1.58 2003/11/17 03:10:41 ballen4705 Exp $\n"
 #endif
 
 // Configuration file
@@ -166,10 +166,13 @@ typedef struct configfile_s {
   char ignorepresets;                     // Ignore database of -v options
   char showpresets;                       // Show database entry for this device
   char removable;                         // Device may disappear (not be present)
-  char *emailcmdline;                     // Program for sending mail (or NULL)
-  char *address;                          // Email addresses (or NULL)
   unsigned char selflogcount;             // total number of self-test errors
+  unsigned char notused1;                 // for packing alignment
+  unsigned char notused2;
+  unsigned char notused3;
   unsigned short selfloghour;             // lifetime hours of last self-test error
+  char *emailcmdline;                     // Program for sending mail (or NULL)
+  char *address;                          // Email addresses (or NULL)
 
   // THE NEXT SET OF ENTRIES TRACK DEVICE STATE AND ARE DYNAMIC
   mailinfo maildata[10];                  // Tracks type/date of email messages sent
@@ -181,7 +184,10 @@ typedef struct configfile_s {
   unsigned char SuppressReport;           // minimize nuisance reports
   unsigned char modese_len;               // mode sense/select cmd len: 0 (don't
                                           // know yet) 6 or 10
-  
+  unsigned char notused4;                 // for packing alignment
+  unsigned char notused5;
+  unsigned char notused6;
+
   // ATA ONLY FROM HERE ON TO THE END
   int ataerrorcount;                      // Total number of ATA errors