From 32559e5f5e652c79040764f116fd53179a4093c3 Mon Sep 17 00:00:00 2001
From: ballen4705 <ballen4705@4ea69e1a-61f1-4043-bf83-b5c94c648137>
Date: Wed, 30 Oct 2002 10:18:37 +0000
Subject: [PATCH] release 24

git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@173 4ea69e1a-61f1-4043-bf83-b5c94c648137
---
 sm5/CHANGELOG          |  33 ++++++-
 sm5/TODO               |   5 +-
 sm5/VERSION            |   2 +-
 sm5/atacmds.c          |  72 +++++++-------
 sm5/atacmds.cpp        |  72 +++++++-------
 sm5/atacmds.h          |  30 +++---
 sm5/ataprint.c         | 217 ++++++++++++++++++++---------------------
 sm5/ataprint.cpp       | 217 ++++++++++++++++++++---------------------
 sm5/ataprint.h         |  20 ++--
 sm5/smartd.8           |  29 ++++--
 sm5/smartd.c           |  68 ++++++++-----
 sm5/smartd.cpp         |  68 ++++++++-----
 sm5/smartmontools.spec |  22 ++++-
 13 files changed, 474 insertions(+), 381 deletions(-)

diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG
index 578fdd93c..ae0c680ad 100644
--- a/sm5/CHANGELOG
+++ b/sm5/CHANGELOG
@@ -1,6 +1,6 @@
 CHANGELOG for smartmontools
 
-$Id: CHANGELOG,v 1.31 2002/10/30 06:02:37 ballen4705 Exp $
+$Id: CHANGELOG,v 1.32 2002/10/30 10:18:37 ballen4705 Exp $
 
 Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 
@@ -23,9 +23,40 @@ California, Santa Cruz. http://ssrc.soe.ucsc.edu/
 
 NOTES FOR FUTURE RELEASES: see TODO file.
 
+Added 
+.B \-C <N>
+This sets the time in between disk checks to be 
+.B <N>
+seconds apart.  Note that although you can give this Directive
+multiple times on different lines of the configuration file, only the
+final value that is given has an effect, and applies to all the disks.
+The default value of 
+.B <N> 
+is 1800 sec, and the minimum allowed value is
+ten seconds.
 
 CURRENT RELEASE (see VERSION file in this directory):
 
+smartmontools-5.0.24
+
+  Added new Directive for Configuration file:
+-C <N> This sets the time in between disk checks to be <N>
+      seconds apart.  Note that  although  you  can  give
+      this Directive multiple times on different lines of
+      the configuration file, only the final  value  that
+      is  given  has  an  effect,  and applies to all the
+      disks.  The default value of <N> is 1800  sec,  and
+      the minimum allowed value is ten seconds.
+
+    Problem wasn't the print format. F.L.W. Meunier <0@pervalidus.net>
+    sent me a gcc 3.2 build and I ran it under a debugger.  The
+    problem seems to be with passing the very large (2x512+4) byte
+    data structures as arguments.  I never liked this anyway; it was
+    inherited from smartsuite.  So I've changed all the heavyweight
+    functions (ATA ones, anyone) to just passing pointers, not hideous
+    kB size structures on the stack.  Hopefully this will now build OK
+    under gcc 3.2 with any sensible compilation options.
+
 smartmontools-5.0.23
 
     Because of reported problems with GCC 3.2 compile, I have gone
diff --git a/sm5/TODO b/sm5/TODO
index 162c8ece2..23c17e8ae 100644
--- a/sm5/TODO
+++ b/sm5/TODO
@@ -4,7 +4,7 @@ Home page of code is: http://smartmontools.sourceforge.net
 
 Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 
-$Id: TODO,v 1.18 2002/10/29 14:19:10 ballen4705 Exp $
+$Id: TODO,v 1.19 2002/10/30 10:18:37 ballen4705 Exp $
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the Free
@@ -67,6 +67,3 @@ General Fixes
 -------------
 
 Fix lots of syntax like if (a != 0)
-
-Pass pointer to big structures like "device" and smartval, not the
-whole 2kB of data!  I've started doing this but haven't finished yet.
diff --git a/sm5/VERSION b/sm5/VERSION
index 409940768..a45fd52cc 100644
--- a/sm5/VERSION
+++ b/sm5/VERSION
@@ -1 +1 @@
-23
+24
diff --git a/sm5/atacmds.c b/sm5/atacmds.c
index b78c270cb..f1a3bf671 100644
--- a/sm5/atacmds.c
+++ b/sm5/atacmds.c
@@ -30,7 +30,7 @@
 #include <stdlib.h>
 #include "atacmds.h"
 
-const char *CVSid1="$Id: atacmds.c,v 1.35 2002/10/30 06:02:38 ballen4705 Exp $" CVSID1;
+const char *CVSid1="$Id: atacmds.c,v 1.36 2002/10/30 10:18:37 ballen4705 Exp $" CVSID1;
 
 // These Drive Identity tables are taken from hdparm 5.2, and are also
 // given in the ATA/ATAPI specs for the IDENTIFY DEVICE command.  Note
@@ -199,17 +199,17 @@ int ataReadHDIdentity (int device, struct hd_driveid *buf){
 // describing which revision.  Note that Revision 0 of ATA-3 does NOT
 // support SMART.  For this one case we return -3 rather than +3 as
 // the version number.  See notes above.
-int ataVersionInfo (const char** description, struct hd_driveid drive, unsigned short *minor){
+int ataVersionInfo (const char** description, struct hd_driveid *drive, unsigned short *minor){
   unsigned short major;
   int i;
   
   // get major and minor ATA revision numbers
 #ifdef __NEW_HD_DRIVE_ID
-  major=drive.major_rev_num;
-  *minor=drive.minor_rev_num;
+  major=drive->major_rev_num;
+  *minor=drive->minor_rev_num;
 #else
-  major=drive.word80;
-  *minor=drive.word81;
+  major=drive->word80;
+  *minor=drive->word81;
 #endif
   
   // First check if device has ANY ATA version information in it
@@ -242,16 +242,16 @@ int ataVersionInfo (const char** description, struct hd_driveid drive, unsigned
 }
 
 // returns 1 if SMART supported, 0 if not supported or can't tell
-int ataSmartSupport(struct hd_driveid drive){
+int ataSmartSupport(struct hd_driveid *drive){
   unsigned short word82,word83;
 
   // get correct bits of IDENTIFY DEVICE structure
 #ifdef __NEW_HD_DRIVE_ID
-  word82=drive.command_set_1;
-  word83=drive.command_set_2;
+  word82=drive->command_set_1;
+  word83=drive->command_set_2;
 #else
-  word82=drive.command_sets;
-  word83=drive.word83;
+  word82=drive->command_sets;
+  word83=drive->word83;
 #endif
 
   // Note this does not work for ATA3 < Revision 6, when word82 and word83 were added
@@ -260,16 +260,16 @@ int ataSmartSupport(struct hd_driveid drive){
 }
 
 // returns 1 if SMART enabled, 0 if SMART disabled, -1 if can't tell
-int ataIsSmartEnabled(struct hd_driveid drive){
+int ataIsSmartEnabled(struct hd_driveid *drive){
     unsigned short word85,word87;
 
   // Get correct bits of IDENTIFY DRIVE structure
 #ifdef __NEW_HD_DRIVE_ID
-  word85=drive.cfs_enable_1;
-  word87=drive.csf_default;
+  word85=drive->cfs_enable_1;
+  word87=drive->csf_default;
 #else
-  word85=drive.word85;
-  word87=drive.word87;
+  word85=drive->word85;
+  word87=drive->word87;
 #endif
   
   if ((word87 & 0x0001<<14) && !(word87 & 0x0001<<15))
@@ -583,39 +583,39 @@ int ataSmartTest(int device, int testtype){
 }
 
 /* Test Time Functions */
-int TestTime(struct ata_smart_values data,int testtype){
+int TestTime(struct ata_smart_values *data,int testtype){
   switch (testtype){
   case OFFLINE_FULL_SCAN:
-    return (int) data.total_time_to_complete_off_line;
+    return (int) data->total_time_to_complete_off_line;
   case SHORT_SELF_TEST:
   case SHORT_CAPTIVE_SELF_TEST:
-    return (int) data.short_test_completion_time;
+    return (int) data->short_test_completion_time;
   case EXTEND_SELF_TEST:
   case EXTEND_CAPTIVE_SELF_TEST:
-    return (int) data.extend_test_completion_time;
+    return (int) data->extend_test_completion_time;
   default:
     return 0;
   }
 }
 
 
-int isSmartErrorLogCapable ( struct ata_smart_values data){
-   return data.errorlog_capability & 0x01;
+int isSmartErrorLogCapable ( struct ata_smart_values *data){
+   return data->errorlog_capability & 0x01;
 }
-int isSupportExecuteOfflineImmediate ( struct ata_smart_values data){
-   return data.offline_data_collection_capability & 0x01;
+int isSupportExecuteOfflineImmediate ( struct ata_smart_values *data){
+   return data->offline_data_collection_capability & 0x01;
 }
-int isSupportAutomaticTimer ( struct ata_smart_values data){
-   return data.offline_data_collection_capability & 0x02;
+int isSupportAutomaticTimer ( struct ata_smart_values *data){
+   return data->offline_data_collection_capability & 0x02;
 }
-int isSupportOfflineAbort ( struct ata_smart_values data){
-   return data.offline_data_collection_capability & 0x04;
+int isSupportOfflineAbort ( struct ata_smart_values *data){
+   return data->offline_data_collection_capability & 0x04;
 }
-int isSupportOfflineSurfaceScan ( struct ata_smart_values data){
-   return data.offline_data_collection_capability & 0x08;
+int isSupportOfflineSurfaceScan ( struct ata_smart_values *data){
+   return data->offline_data_collection_capability & 0x08;
 }
-int isSupportSelfTest (struct ata_smart_values data){
-   return data.offline_data_collection_capability & 0x10;
+int isSupportSelfTest (struct ata_smart_values *data){
+   return data->offline_data_collection_capability & 0x10;
 }
 
 
@@ -634,8 +634,8 @@ int isSupportSelfTest (struct ata_smart_values data){
 
 // onlyfailed=0 : are or were any age or prefailure attributes <= threshold
 // onlyfailed=1:  are any prefailure attributes <= threshold now
-int ataCheckSmart(struct ata_smart_values data,
-		  struct ata_smart_thresholds thresholds,
+int ataCheckSmart(struct ata_smart_values *data,
+		  struct ata_smart_thresholds *thresholds,
 		  int onlyfailed){
   int i;
   
@@ -643,8 +643,8 @@ int ataCheckSmart(struct ata_smart_values data,
   for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){
 
     // pointers to disk's values and vendor's thresholds
-    struct ata_smart_attribute *disk=data.vendor_attributes+i;
-    struct ata_smart_threshold_entry *thre=thresholds.thres_entries+i;
+    struct ata_smart_attribute *disk=data->vendor_attributes+i;
+    struct ata_smart_threshold_entry *thre=thresholds->thres_entries+i;
  
     // consider only valid attributes
     if (disk->id && thre->id){
diff --git a/sm5/atacmds.cpp b/sm5/atacmds.cpp
index 21a84b46f..acf7c86e7 100644
--- a/sm5/atacmds.cpp
+++ b/sm5/atacmds.cpp
@@ -30,7 +30,7 @@
 #include <stdlib.h>
 #include "atacmds.h"
 
-const char *CVSid1="$Id: atacmds.cpp,v 1.35 2002/10/30 06:02:38 ballen4705 Exp $" CVSID1;
+const char *CVSid1="$Id: atacmds.cpp,v 1.36 2002/10/30 10:18:37 ballen4705 Exp $" CVSID1;
 
 // These Drive Identity tables are taken from hdparm 5.2, and are also
 // given in the ATA/ATAPI specs for the IDENTIFY DEVICE command.  Note
@@ -199,17 +199,17 @@ int ataReadHDIdentity (int device, struct hd_driveid *buf){
 // describing which revision.  Note that Revision 0 of ATA-3 does NOT
 // support SMART.  For this one case we return -3 rather than +3 as
 // the version number.  See notes above.
-int ataVersionInfo (const char** description, struct hd_driveid drive, unsigned short *minor){
+int ataVersionInfo (const char** description, struct hd_driveid *drive, unsigned short *minor){
   unsigned short major;
   int i;
   
   // get major and minor ATA revision numbers
 #ifdef __NEW_HD_DRIVE_ID
-  major=drive.major_rev_num;
-  *minor=drive.minor_rev_num;
+  major=drive->major_rev_num;
+  *minor=drive->minor_rev_num;
 #else
-  major=drive.word80;
-  *minor=drive.word81;
+  major=drive->word80;
+  *minor=drive->word81;
 #endif
   
   // First check if device has ANY ATA version information in it
@@ -242,16 +242,16 @@ int ataVersionInfo (const char** description, struct hd_driveid drive, unsigned
 }
 
 // returns 1 if SMART supported, 0 if not supported or can't tell
-int ataSmartSupport(struct hd_driveid drive){
+int ataSmartSupport(struct hd_driveid *drive){
   unsigned short word82,word83;
 
   // get correct bits of IDENTIFY DEVICE structure
 #ifdef __NEW_HD_DRIVE_ID
-  word82=drive.command_set_1;
-  word83=drive.command_set_2;
+  word82=drive->command_set_1;
+  word83=drive->command_set_2;
 #else
-  word82=drive.command_sets;
-  word83=drive.word83;
+  word82=drive->command_sets;
+  word83=drive->word83;
 #endif
 
   // Note this does not work for ATA3 < Revision 6, when word82 and word83 were added
@@ -260,16 +260,16 @@ int ataSmartSupport(struct hd_driveid drive){
 }
 
 // returns 1 if SMART enabled, 0 if SMART disabled, -1 if can't tell
-int ataIsSmartEnabled(struct hd_driveid drive){
+int ataIsSmartEnabled(struct hd_driveid *drive){
     unsigned short word85,word87;
 
   // Get correct bits of IDENTIFY DRIVE structure
 #ifdef __NEW_HD_DRIVE_ID
-  word85=drive.cfs_enable_1;
-  word87=drive.csf_default;
+  word85=drive->cfs_enable_1;
+  word87=drive->csf_default;
 #else
-  word85=drive.word85;
-  word87=drive.word87;
+  word85=drive->word85;
+  word87=drive->word87;
 #endif
   
   if ((word87 & 0x0001<<14) && !(word87 & 0x0001<<15))
@@ -583,39 +583,39 @@ int ataSmartTest(int device, int testtype){
 }
 
 /* Test Time Functions */
-int TestTime(struct ata_smart_values data,int testtype){
+int TestTime(struct ata_smart_values *data,int testtype){
   switch (testtype){
   case OFFLINE_FULL_SCAN:
-    return (int) data.total_time_to_complete_off_line;
+    return (int) data->total_time_to_complete_off_line;
   case SHORT_SELF_TEST:
   case SHORT_CAPTIVE_SELF_TEST:
-    return (int) data.short_test_completion_time;
+    return (int) data->short_test_completion_time;
   case EXTEND_SELF_TEST:
   case EXTEND_CAPTIVE_SELF_TEST:
-    return (int) data.extend_test_completion_time;
+    return (int) data->extend_test_completion_time;
   default:
     return 0;
   }
 }
 
 
-int isSmartErrorLogCapable ( struct ata_smart_values data){
-   return data.errorlog_capability & 0x01;
+int isSmartErrorLogCapable ( struct ata_smart_values *data){
+   return data->errorlog_capability & 0x01;
 }
-int isSupportExecuteOfflineImmediate ( struct ata_smart_values data){
-   return data.offline_data_collection_capability & 0x01;
+int isSupportExecuteOfflineImmediate ( struct ata_smart_values *data){
+   return data->offline_data_collection_capability & 0x01;
 }
-int isSupportAutomaticTimer ( struct ata_smart_values data){
-   return data.offline_data_collection_capability & 0x02;
+int isSupportAutomaticTimer ( struct ata_smart_values *data){
+   return data->offline_data_collection_capability & 0x02;
 }
-int isSupportOfflineAbort ( struct ata_smart_values data){
-   return data.offline_data_collection_capability & 0x04;
+int isSupportOfflineAbort ( struct ata_smart_values *data){
+   return data->offline_data_collection_capability & 0x04;
 }
-int isSupportOfflineSurfaceScan ( struct ata_smart_values data){
-   return data.offline_data_collection_capability & 0x08;
+int isSupportOfflineSurfaceScan ( struct ata_smart_values *data){
+   return data->offline_data_collection_capability & 0x08;
 }
-int isSupportSelfTest (struct ata_smart_values data){
-   return data.offline_data_collection_capability & 0x10;
+int isSupportSelfTest (struct ata_smart_values *data){
+   return data->offline_data_collection_capability & 0x10;
 }
 
 
@@ -634,8 +634,8 @@ int isSupportSelfTest (struct ata_smart_values data){
 
 // onlyfailed=0 : are or were any age or prefailure attributes <= threshold
 // onlyfailed=1:  are any prefailure attributes <= threshold now
-int ataCheckSmart(struct ata_smart_values data,
-		  struct ata_smart_thresholds thresholds,
+int ataCheckSmart(struct ata_smart_values *data,
+		  struct ata_smart_thresholds *thresholds,
 		  int onlyfailed){
   int i;
   
@@ -643,8 +643,8 @@ int ataCheckSmart(struct ata_smart_values data,
   for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){
 
     // pointers to disk's values and vendor's thresholds
-    struct ata_smart_attribute *disk=data.vendor_attributes+i;
-    struct ata_smart_threshold_entry *thre=thresholds.thres_entries+i;
+    struct ata_smart_attribute *disk=data->vendor_attributes+i;
+    struct ata_smart_threshold_entry *thre=thresholds->thres_entries+i;
  
     // consider only valid attributes
     if (disk->id && thre->id){
diff --git a/sm5/atacmds.h b/sm5/atacmds.h
index 5140c89ef..cbe706cfc 100644
--- a/sm5/atacmds.h
+++ b/sm5/atacmds.h
@@ -26,7 +26,7 @@
 #define _ATACMDS_H_
 
 #ifndef CVSID1
-#define CVSID1 "$Id: atacmds.h,v 1.23 2002/10/30 06:02:39 ballen4705 Exp $\n"
+#define CVSID1 "$Id: atacmds.h,v 1.24 2002/10/30 10:18:37 ballen4705 Exp $\n"
 #endif
 
 // These are the major and minor versions for smartd and smartctl
@@ -297,50 +297,50 @@ int ataSmartSelfTestAbort (int device);
 
 // Returns the latest compatibility of ATA/ATAPI Version the device
 // supports. Returns -1 if Version command is not supported
-int ataVersionInfo (const char **description, struct hd_driveid drive, unsigned short *minor);
+int ataVersionInfo (const char **description, struct hd_driveid *drive, unsigned short *minor);
 
 // If SMART supported, this is guaranteed to return 1 if SMART is enabled, else 0.
 int ataDoesSmartWork(int device);
 
 // returns 1 if SMART supported, 0 if not supported or can't tell
-int ataSmartSupport ( struct hd_driveid drive);
+int ataSmartSupport ( struct hd_driveid *drive);
 
 // Return values:
 //  1: SMART enabled
 //  0: SMART disabled
 // -1: can't tell if SMART is enabled -- try issuing ataDoesSmartWork command to see
-int ataIsSmartEnabled(struct hd_driveid drive);
+int ataIsSmartEnabled(struct hd_driveid *drive);
 
 /* Check SMART for Threshold failure */
 // onlyfailed=0 : are or were any age or prefailure attributes <= threshold
 // onlyfailed=1:  are any prefailure attributes <= threshold now
-int ataCheckSmart ( struct ata_smart_values data, struct ata_smart_thresholds thresholds, int onlyfailed);
+int ataCheckSmart ( struct ata_smart_values *data, struct ata_smart_thresholds *thresholds, int onlyfailed);
 
 int ataSmartStatus2(int device);
 
 // int isOfflineTestTime ( struct ata_smart_values data)
 //  returns S.M.A.R.T. Offline Test Time in seconds
-int isOfflineTestTime ( struct ata_smart_values data);
+int isOfflineTestTime ( struct ata_smart_values *data);
 
-int isShortSelfTestTime ( struct ata_smart_values data);
+int isShortSelfTestTime ( struct ata_smart_values *data);
 
-int isExtendedSelfTestTime ( struct ata_smart_values data);
+int isExtendedSelfTestTime ( struct ata_smart_values *data);
 
-int isSmartErrorLogCapable ( struct ata_smart_values data);
+int isSmartErrorLogCapable ( struct ata_smart_values *data);
 
-int isSupportExecuteOfflineImmediate ( struct ata_smart_values data);
+int isSupportExecuteOfflineImmediate ( struct ata_smart_values *data);
 
-int isSupportAutomaticTimer ( struct ata_smart_values data);
+int isSupportAutomaticTimer ( struct ata_smart_values *data);
 
-int isSupportOfflineAbort ( struct ata_smart_values data);
+int isSupportOfflineAbort ( struct ata_smart_values *data);
 
-int isSupportOfflineSurfaceScan ( struct ata_smart_values data);
+int isSupportOfflineSurfaceScan ( struct ata_smart_values *data);
 
-int isSupportSelfTest (struct ata_smart_values data);
+int isSupportSelfTest (struct ata_smart_values *data);
 
 int ataSmartTest(int device, int testtype);
 
-int TestTime(struct ata_smart_values data,int testtype);
+int TestTime(struct ata_smart_values *data,int testtype);
 
 // Prints Attribute Name for standard SMART attributes. Writes a
 // 30 byte string with attribute name into output
diff --git a/sm5/ataprint.c b/sm5/ataprint.c
index e4ceb9a10..13e24bf3b 100644
--- a/sm5/ataprint.c
+++ b/sm5/ataprint.c
@@ -29,7 +29,7 @@
 #include "smartctl.h"
 #include "extern.h"
 
-const char *CVSid2="$Id: ataprint.c,v 1.39 2002/10/30 06:02:39 ballen4705 Exp $"
+const char *CVSid2="$Id: ataprint.c,v 1.40 2002/10/30 10:18:37 ballen4705 Exp $"
 CVSID1 CVSID2 CVSID3 CVSID6;
 
 // for passing global control variables
@@ -63,7 +63,7 @@ void printswap(char *in, unsigned int n){
 }
 
 
-void ataPrintDriveInfo (struct hd_driveid drive){
+void ataPrintDriveInfo (struct hd_driveid *drive){
   int version;
   const char *description;
   char unknown[64];
@@ -71,13 +71,13 @@ void ataPrintDriveInfo (struct hd_driveid drive){
 
   // print out model, serial # and firmware versions  (byte-swap ASCI strings)
   pout("Device Model:     ");
-  printswap(drive.model,40);
+  printswap(drive->model,40);
 
   pout("Serial Number:    ");
-  printswap(drive.serial_no,20);
+  printswap(drive->serial_no,20);
 
   pout("Firmware Version: ");
-  printswap(drive.fw_rev,8);
+  printswap(drive->fw_rev,8);
 
   // now get ATA version info
   version=ataVersionInfo(&description,drive, &minorrev);
@@ -107,89 +107,88 @@ void ataPrintDriveInfo (struct hd_driveid drive){
 }
 
 
-/* void PrintSmartOfflineStatus ( struct ata_smart_values data) 
-   prints verbose value Off-line data collection status byte */
-void PrintSmartOfflineStatus(struct ata_smart_values data){
+/*  prints verbose value Off-line data collection status byte */
+void PrintSmartOfflineStatus(struct ata_smart_values *data){
   pout("Off-line data collection status: ");	
   
-  switch(data.offline_data_collection_status){
+  switch(data->offline_data_collection_status){
   case 0x00:
   case 0x80:
     pout("(0x%02x)\tOffline data collection activity was\n\t\t\t\t\t",
-	 (int)data.offline_data_collection_status);
+	 (int)data->offline_data_collection_status);
     pout("never started.\n");
     break;
   case 0x01:
   case 0x81:
     pout("(0x%02x)\tReserved.\n",
-	 (int)data.offline_data_collection_status);
+	 (int)data->offline_data_collection_status);
     break;
   case 0x02:
   case 0x82:
     pout("(0x%02x)\tOffline data collection activity \n\t\t\t\t\t",
-	 (int)data.offline_data_collection_status);
+	 (int)data->offline_data_collection_status);
     pout("completed without error.\n");
     break;
   case 0x03:
   case 0x83:
     pout("(0x%02x)\tReserved.\n",
-	 (int)data.offline_data_collection_status);
+	 (int)data->offline_data_collection_status);
     break;
   case 0x04:
   case 0x84:
     pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
-	 (int)data.offline_data_collection_status);
+	 (int)data->offline_data_collection_status);
     pout("suspended by an interrupting command from host.\n");
     break;
   case 0x05:
   case 0x85:
     pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
-	 (int)data.offline_data_collection_status);
+	 (int)data->offline_data_collection_status);
     pout("aborted by an interrupting command from host.\n");
     break;
   case 0x06:
   case 0x86:
     pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
-	 (int)data.offline_data_collection_status);
+	 (int)data->offline_data_collection_status);
     pout("aborted by the device with a fatal error.\n");
     break;
   default:
-    if ( ((data.offline_data_collection_status >= 0x07) &&
-	  (data.offline_data_collection_status <= 0x3f)) ||
-	 ((data.offline_data_collection_status >= 0xc0) &&
-	  (data.offline_data_collection_status <= 0xff)) )
-      pout("(0x%02x)\tVendor Specific.\n",(int)data.offline_data_collection_status);
+    if ( ((data->offline_data_collection_status >= 0x07) &&
+	  (data->offline_data_collection_status <= 0x3f)) ||
+	 ((data->offline_data_collection_status >= 0xc0) &&
+	  (data->offline_data_collection_status <= 0xff)) )
+      pout("(0x%02x)\tVendor Specific.\n",(int)data->offline_data_collection_status);
     else
-      pout("(0x%02x)\tReserved.\n",(int)data.offline_data_collection_status);
+      pout("(0x%02x)\tReserved.\n",(int)data->offline_data_collection_status);
   }
 }
 
 
 
-void PrintSmartSelfExecStatus ( struct ata_smart_values data)
+void PrintSmartSelfExecStatus(struct ata_smart_values *data)
 {
    pout("Self-test execution status:      ");
    
-   switch (data.self_test_exec_status >> 4)
+   switch (data->self_test_exec_status >> 4)
    {
       case 0:
         pout("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t",
-                (int)data.self_test_exec_status);
+                (int)data->self_test_exec_status);
         pout("without error or no self-test has ever \n\t\t\t\t\tbeen run.\n");
         break;
        case 1:
          pout("(%4d)\tThe self-test routine was aborted by\n\t\t\t\t\t",
-                 (int)data.self_test_exec_status);
+                 (int)data->self_test_exec_status);
          pout("the host.\n");
          break;
        case 2:
          pout("(%4d)\tThe self-test routine was interrupted\n\t\t\t\t\t",
-                 (int)data.self_test_exec_status);
+                 (int)data->self_test_exec_status);
          pout("by the host with a hard or soft reset.\n");
          break;
        case 3:
           pout("(%4d)\tA fatal error or unknown test error\n\t\t\t\t\t",
-                  (int)data.self_test_exec_status);
+                  (int)data->self_test_exec_status);
           pout("occurred while the device was executing\n\t\t\t\t\t");
           pout("its self-test routine and the device \n\t\t\t\t\t");
           pout("was unable to complete the self-test \n\t\t\t\t\t");
@@ -197,36 +196,36 @@ void PrintSmartSelfExecStatus ( struct ata_smart_values data)
           break;
        case 4:
           pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t",
-                  (int)data.self_test_exec_status);
+                  (int)data->self_test_exec_status);
           pout("a test element that failed and the test\n\t\t\t\t\t");
           pout("element that failed is not known.\n");
           break;
        case 5:
           pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t",
-                  (int)data.self_test_exec_status);
+                  (int)data->self_test_exec_status);
           pout("the electrical element of the test\n\t\t\t\t\t");
           pout("failed.\n");
           break;
        case 6:
           pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t",
-                  (int)data.self_test_exec_status);
+                  (int)data->self_test_exec_status);
           pout("the servo (and/or seek) element of the \n\t\t\t\t\t");
           pout("test failed.\n");
           break;
        case 7:
           pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t",
-                  (int)data.self_test_exec_status);
+                  (int)data->self_test_exec_status);
           pout("the read element of the test failed.\n");
           break;
        case 15:
           pout("(%4d)\tSelf-test routine in progress...\n\t\t\t\t\t",
-                  (int)data.self_test_exec_status);
+                  (int)data->self_test_exec_status);
           pout("%1d0%% of test remaining.\n", 
-                  (int)(data.self_test_exec_status & 0x0f));
+                  (int)(data->self_test_exec_status & 0x0f));
           break;
        default:
           pout("(%4d)\tReserved.\n",
-                  (int)data.self_test_exec_status);
+                  (int)data->self_test_exec_status);
           break;
    }
 	
@@ -234,21 +233,21 @@ void PrintSmartSelfExecStatus ( struct ata_smart_values data)
 
 
 
-void PrintSmartTotalTimeCompleteOffline ( struct ata_smart_values data){
+void PrintSmartTotalTimeCompleteOffline ( struct ata_smart_values *data){
   pout("Total time to complete off-line \n");
   pout("data collection: \t\t (%4d) seconds.\n", 
-       (int)data.total_time_to_complete_off_line);
+       (int)data->total_time_to_complete_off_line);
 }
 
 
 
-void PrintSmartOfflineCollectCap ( struct ata_smart_values data)
+void PrintSmartOfflineCollectCap(struct ata_smart_values *data)
 {
    pout("Offline data collection\n");
    pout("capabilities: \t\t\t (0x%02x) ",
-            (int)data.offline_data_collection_capability);
+            (int)data->offline_data_collection_capability);
 
-   if (data.offline_data_collection_capability == 0x00)
+   if (data->offline_data_collection_capability == 0x00)
    {
       pout("\tOff-line data collection not supported.\n");
    } 
@@ -278,23 +277,23 @@ void PrintSmartOfflineCollectCap ( struct ata_smart_values data)
 
 
 
-void PrintSmartCapability ( struct ata_smart_values data)
+void PrintSmartCapability ( struct ata_smart_values *data)
 {
    pout("SMART capabilities:            ");
-   pout("(0x%04x)\t", (int)data.smart_capability);
+   pout("(0x%04x)\t", (int)data->smart_capability);
    
-   if (data.smart_capability == 0x00)
+   if (data->smart_capability == 0x00)
    {
        pout("Automatic saving of SMART data\t\t\t\t\tis not implemented.\n");
    } 
    else 
    {
 	
-      pout( "%s\n", (data.smart_capability & 0x01)? 
+      pout( "%s\n", (data->smart_capability & 0x01)? 
               "Saves SMART data before entering\n\t\t\t\t\tpower-saving mode.":
               "Does not save SMART data before\n\t\t\t\t\tentering power-saving mode.");
 		
-      if ( data.smart_capability & 0x02 )
+      if ( data->smart_capability & 0x02 )
       {
           pout("\t\t\t\t\tSupports SMART auto save timer.\n");
       }
@@ -303,7 +302,7 @@ void PrintSmartCapability ( struct ata_smart_values data)
 
 
 
-void PrintSmartErrorLogCapability ( struct ata_smart_values data)
+void PrintSmartErrorLogCapability ( struct ata_smart_values *data)
 {
 
    pout("Error logging capability:       ");
@@ -311,23 +310,23 @@ void PrintSmartErrorLogCapability ( struct ata_smart_values data)
    if ( isSmartErrorLogCapable(data) )
    {
       pout(" (0x%02x)\tError logging supported.\n",
-               (int)data.errorlog_capability);
+               (int)data->errorlog_capability);
    }
    else {
        pout(" (0x%02x)\tError logging NOT supported.\n",
-                (int)data.errorlog_capability);
+                (int)data->errorlog_capability);
    }
 }
 
 
 
-void PrintSmartShortSelfTestPollingTime ( struct ata_smart_values data)
+void PrintSmartShortSelfTestPollingTime (struct ata_smart_values *data)
 {
    if ( isSupportSelfTest(data) )
    {
       pout("Short self-test routine \n");
       pout("recommended polling time: \t (%4d) minutes.\n", 
-               (int)data.short_test_completion_time);
+               (int)data->short_test_completion_time);
 
    }
    else
@@ -338,13 +337,13 @@ void PrintSmartShortSelfTestPollingTime ( struct ata_smart_values data)
 }
 
 
-void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values data)
+void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values *data)
 {
    if ( isSupportSelfTest(data) )
    {
       pout("Extended self-test routine \n");
       pout("recommended polling time: \t (%4d) minutes.\n", 
-               (int)data.extend_test_completion_time);
+               (int)data->extend_test_completion_time);
    }
    else
    {
@@ -357,8 +356,8 @@ void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values data)
 // onlyfailed=0 : print all attribute values
 // onlyfailed=1:  just ones that are currently failed and have prefailure bit set
 // onlyfailed=2:  ones that are failed, or have failed with or without prefailure bit set
-void PrintSmartAttribWithThres (struct ata_smart_values data, 
-				struct ata_smart_thresholds thresholds,
+void PrintSmartAttribWithThres (struct ata_smart_values *data, 
+				struct ata_smart_thresholds *thresholds,
 				int onlyfailed){
   int i,j;
   long long rawvalue;
@@ -367,8 +366,8 @@ void PrintSmartAttribWithThres (struct ata_smart_values data,
   // step through all vendor attributes
   for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){
     char *status;
-    struct ata_smart_attribute *disk=data.vendor_attributes+i;
-    struct ata_smart_threshold_entry *thre=thresholds.thres_entries+i;
+    struct ata_smart_attribute *disk=data->vendor_attributes+i;
+    struct ata_smart_threshold_entry *thre=thresholds->thres_entries+i;
     
     // consider only valid attributes
     if (disk->id && thre->id){
@@ -389,7 +388,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values data,
       // print header only if needed
       if (needheader){
 	if (!onlyfailed){
-	  pout("SMART Attributes Data Structure revision number: %d\n",(int)data.revnumber);
+	  pout("SMART Attributes Data Structure revision number: %d\n",(int)data->revnumber);
 	  pout("Vendor Specific SMART Attributes with Thresholds:\n");
 	}
 	pout("ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE     WHEN_FAILED RAW_VALUE\n");
@@ -463,7 +462,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values data,
 }
 
 
-void ataPrintGeneralSmartValues(struct ata_smart_values data){
+void ataPrintGeneralSmartValues(struct ata_smart_values *data){
   pout("General SMART Values:\n");
   
   PrintSmartOfflineStatus(data); 
@@ -494,31 +493,31 @@ int nonempty(unsigned char *testarea,int n){
 }
 
 // returns number of errors
-void ataPrintSmartErrorlog (struct ata_smart_errorlog data){
+void ataPrintSmartErrorlog (struct ata_smart_errorlog *data){
   int i,j,k;
   
-  pout("SMART Error Log Version: %d\n", (int)data.revnumber);
+  pout("SMART Error Log Version: %d\n", (int)data->revnumber);
   
   // if no errors logged, return
-  if (!data.error_log_pointer){
+  if (!data->error_log_pointer){
     pout("No Errors Logged\n\n");
     return;
   }
   QUIETON(con);
   // if log pointer out of range, return
-  if ( data.error_log_pointer>5 ){
+  if ( data->error_log_pointer>5 ){
     pout("Invalid Error Log index = %02x (T13/1321D rev 1c"
 	 "Section 8.41.6.8.2.2 gives valid range from 1 to 5)\n\n",
-	 (int)data.error_log_pointer);
+	 (int)data->error_log_pointer);
     return;
   }
   
   // starting printing error log info
-  if (data.ata_error_count<=5)
-    pout( "ATA Error Count: %d\n", (int)data.ata_error_count);
+  if (data->ata_error_count<=5)
+    pout( "ATA Error Count: %d\n", (int)data->ata_error_count);
   else
     pout( "ATA Error Count: %d (device log contains only the most recent five errors)\n",
-	   (int)data.ata_error_count);
+	   (int)data->ata_error_count);
   QUIETOFF(con);
   pout("\tDCR = Device Control Register\n");
   pout("\tFR  = Features Register\n");
@@ -537,12 +536,12 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data){
   for (k = 4; k >= 0; k-- ) {
     
     // The error log data structure entries are a circular buffer
-    i=(data.error_log_pointer+k)%5;
+    i=(data->error_log_pointer+k)%5;
     
     // Spec says: unused error log structures shall be zero filled
-    if (nonempty((unsigned char*)&(data.errorlog_struct[i]),sizeof(data.errorlog_struct[i]))){
+    if (nonempty((unsigned char*)&(data->errorlog_struct[i]),sizeof(data->errorlog_struct[i]))){
       char *msgstate;
-      switch (data.errorlog_struct[i].error_struct.state){
+      switch (data->errorlog_struct[i].error_struct.state){
       case 0x00: msgstate="in an unknown state";break;
       case 0x01: msgstate="sleeping"; break;
       case 0x02: msgstate="in standby mode"; break;
@@ -553,22 +552,22 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data){
       // See table 42 of ATA5 spec
       QUIETON(con);
       pout("Error %d occurred at disk power-on lifetime: %d hours\n",
-	     (int)(5-k), (int)data.errorlog_struct[i].error_struct.timestamp);
+	     (int)(5-k), (int)data->errorlog_struct[i].error_struct.timestamp);
       QUIETOFF(con);
       pout("When the command that caused the error occurred, the device was %s.\n",msgstate);
       pout("After command completion occurred, registers were:\n");
       pout("ER:%02x SC:%02x SN:%02x CL:%02x CH:%02x D/H:%02x ST:%02x\n",
-	   (int)data.errorlog_struct[i].error_struct.error_register,
-	   (int)data.errorlog_struct[i].error_struct.sector_count,
-	   (int)data.errorlog_struct[i].error_struct.sector_number,
-	   (int)data.errorlog_struct[i].error_struct.cylinder_low,
-	   (int)data.errorlog_struct[i].error_struct.cylinder_high,
-	   (int)data.errorlog_struct[i].error_struct.drive_head,
-	   (int)data.errorlog_struct[i].error_struct.status);
+	   (int)data->errorlog_struct[i].error_struct.error_register,
+	   (int)data->errorlog_struct[i].error_struct.sector_count,
+	   (int)data->errorlog_struct[i].error_struct.sector_number,
+	   (int)data->errorlog_struct[i].error_struct.cylinder_low,
+	   (int)data->errorlog_struct[i].error_struct.cylinder_high,
+	   (int)data->errorlog_struct[i].error_struct.drive_head,
+	   (int)data->errorlog_struct[i].error_struct.status);
       pout("Sequence of commands leading to the command that caused the error were:\n");
       pout("DCR   FR   SC   SN   CL   CH   D/H   CR   Timestamp\n");
       for ( j = 4; j >= 0; j--){
-	struct ata_smart_errorlog_command_struct *thiscommand=&(data.errorlog_struct[i].commands[j]);
+	struct ata_smart_errorlog_command_struct *thiscommand=&(data->errorlog_struct[i].commands[j]);
 	
 	// Spec says: unused data command structures shall be zero filled
 	if (nonempty((unsigned char*)thiscommand,sizeof(*thiscommand)))
@@ -595,15 +594,15 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data){
 }
 
 // return value is number of entries found where the self-test showed an error
-int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog data,int allentries){
+int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog *data,int allentries){
   int i,j,noheaderprinted=1;
   int retval=0;
 
   if (allentries)
-    pout("SMART Self-test log, version number %d\n",(int)data.revnumber);
-  if ((data.revnumber!=0x0001) && allentries)
+    pout("SMART Self-test log, version number %d\n",(int)data->revnumber);
+  if ((data->revnumber!=0x0001) && allentries)
     pout("Warning - structure revision number does not match spec!\n");
-  if (data.mostrecenttest==0){
+  if (data->mostrecenttest==0){
     if (allentries)
       pout("No self-tests have been logged\n\n");
     return 0;
@@ -613,8 +612,8 @@ int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog data,int allentries){
   for (i=20;i>=0;i--){    
     struct ata_smart_selftestlog_struct *log;
     // log is a circular buffer
-    j=(i+data.mostrecenttest)%21;
-    log=data.selftest_struct+j;
+    j=(i+data->mostrecenttest)%21;
+    log=data->selftest_struct+j;
 
     if (nonempty((unsigned char*)log,sizeof(*log))){
       char *msgtest,*msgstat,percent[64],firstlba[64];
@@ -680,17 +679,17 @@ int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog data,int allentries){
   return retval;
 }
 
-void ataPseudoCheckSmart ( struct ata_smart_values data, 
-                           struct ata_smart_thresholds thresholds) {
+void ataPseudoCheckSmart ( struct ata_smart_values *data, 
+                           struct ata_smart_thresholds *thresholds) {
   int i;
   int failed = 0;
   for (i = 0 ; i < NUMBER_ATA_SMART_ATTRIBUTES ; i++) {
-    if (data.vendor_attributes[i].id &&   
-	thresholds.thres_entries[i].id &&
-	data.vendor_attributes[i].status.flag.prefailure &&
-	(data.vendor_attributes[i].current <= thresholds.thres_entries[i].threshold) &&
-	(thresholds.thres_entries[i].threshold != 0xFE)){
-      pout("Attribute ID %d Failed\n",(int)data.vendor_attributes[i].id);
+    if (data->vendor_attributes[i].id &&   
+	thresholds->thres_entries[i].id &&
+	data->vendor_attributes[i].status.flag.prefailure &&
+	(data->vendor_attributes[i].current <= thresholds->thres_entries[i].threshold) &&
+	(thresholds->thres_entries[i].threshold != 0xFE)){
+      pout("Attribute ID %d Failed\n",(int)data->vendor_attributes[i].id);
       failed = 1;
     } 
   }   
@@ -722,11 +721,11 @@ int ataPrintMain (int fd){
   // Print most drive identity information if requested
   if (con->driveinfo){
     pout("=== START OF INFORMATION SECTION ===\n");
-    ataPrintDriveInfo(drive);
+    ataPrintDriveInfo(&drive);
   }
   
   // now check if drive supports SMART; otherwise time to exit
-  if (!ataSmartSupport(drive)){
+  if (!ataSmartSupport(&drive)){
     pout("SMART support is: Unavailable - device lacks SMART capability.\n");
     pout("                  Checking to be sure by trying SMART ENABLE command.\n");
     if (ataEnableSmart(fd)){
@@ -816,7 +815,7 @@ int ataPrintMain (int fd){
 
   // Enable/Disable Off-line testing
   if (con->smartautoofflineenable){
-    if (!isSupportAutomaticTimer(smartval)){
+    if (!isSupportAutomaticTimer(&smartval)){
       pout("Warning: device does not support SMART Automatic Timers.\n\n");
     }
     if (ataEnableAutoOffline(fd)){
@@ -827,7 +826,7 @@ int ataPrintMain (int fd){
       pout("SMART Automatic Offline Testing Enabled every four hours.\n");
   }
   if (con->smartautoofflinedisable){
-    if (!isSupportAutomaticTimer(smartval)){
+    if (!isSupportAutomaticTimer(&smartval)){
       pout("Warning: device does not support SMART Automatic Timers.\n\n");
     }
     if (ataDisableAutoOffline(fd)){
@@ -855,14 +854,14 @@ int ataPrintMain (int fd){
       pout("SMART overall-health self-assessment test result: FAILED!\n"
 	     "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n");
       QUIETOFF(con);
-      if (ataCheckSmart(smartval, smartthres,1)){
+      if (ataCheckSmart(&smartval, &smartthres,1)){
 	returnval|=FAILATTR;
 	if (con->smartvendorattrib)
 	  pout("See vendor-specific Attribute list for failed Attributes.\n\n");
 	else {
 	  QUIETON(con);
 	  pout("Failed Attributes:\n");
-	  PrintSmartAttribWithThres(smartval, smartthres,1);
+	  PrintSmartAttribWithThres(&smartval, &smartthres,1);
 	}
       }
       else
@@ -872,13 +871,13 @@ int ataPrintMain (int fd){
     }
     else {
       pout("SMART overall-health self-assessment test result: PASSED\n");
-      if (ataCheckSmart(smartval, smartthres,0)){
+      if (ataCheckSmart(&smartval, &smartthres,0)){
 	if (con->smartvendorattrib)
 	  pout("See vendor-specific Attribute list for marginal Attributes.\n\n");
 	else {
 	  QUIETON(con);
 	  pout("Please note the following marginal attributes:\n");
-	  PrintSmartAttribWithThres(smartval, smartthres,2);
+	  PrintSmartAttribWithThres(&smartval, &smartthres,2);
 	} 
 	returnval|=FAILAGE;
       }
@@ -890,18 +889,18 @@ int ataPrintMain (int fd){
   
   // Print general SMART values
   if (con->generalsmartvalues)
-    ataPrintGeneralSmartValues(smartval); 
+    ataPrintGeneralSmartValues(&smartval); 
   
   // Print vendor-specific attributes
   if (con->smartvendorattrib){
     QUIETON(con);
-    PrintSmartAttribWithThres(smartval, smartthres,con->quietmode?2:0);
+    PrintSmartAttribWithThres(&smartval, &smartthres,con->quietmode?2:0);
     QUIETOFF(con);
   }
   
   // Print SMART error log
   if (con->smarterrorlog){
-    if (!isSmartErrorLogCapable(smartval))
+    if (!isSmartErrorLogCapable(&smartval))
       pout("Warning: device does not support Error Logging\n");
     if (ataReadErrorLog(fd, &smarterror)){
       pout("Smartctl: SMART Errorlog Read Failed\n");
@@ -909,14 +908,14 @@ int ataPrintMain (int fd){
     }
     else {
       // turn on quiet mode inside this
-      ataPrintSmartErrorlog(smarterror);
+      ataPrintSmartErrorlog(&smarterror);
       QUIETOFF(con);
     }
   }
   
   // Print SMART self-test log
   if (con->smartselftestlog){
-    if (!isSmartErrorLogCapable(smartval))
+    if (!isSmartErrorLogCapable(&smartval))
       pout("Warning: device does not support Self Test Logging\n");
     else {
       if(ataReadSelfTestLog(fd, &smartselftest)){
@@ -925,7 +924,7 @@ int ataPrintMain (int fd){
       }
       else {
 	QUIETON(con);
-	if (ataPrintSmartSelfTestlog(smartselftest,!con->quietmode))
+	if (ataPrintSmartSelfTestlog(&smartselftest,!con->quietmode))
 	  returnval|=FAILLOG;
 	QUIETOFF(con);
 	pout("\n");
@@ -939,9 +938,9 @@ int ataPrintMain (int fd){
   
   pout("=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n");
   // if doing a self-test, be sure it's supported by the hardware
-  if (con->testcase==OFFLINE_FULL_SCAN &&  !isSupportExecuteOfflineImmediate(smartval))
+  if (con->testcase==OFFLINE_FULL_SCAN &&  !isSupportExecuteOfflineImmediate(&smartval))
     pout("Warning: device does not support Execute Off-Line Immediate function.\n\n");
-  else if (!isSupportSelfTest(smartval))
+  else if (!isSupportSelfTest(&smartval))
     pout("Warning: device does not support Self-Test functions.\n\n");
   
   // Now do the test
@@ -949,7 +948,7 @@ int ataPrintMain (int fd){
     return returnval|=FAILSMART;
   
   // Tell user how long test will take to complete  
-  if ((timewait=TestTime(smartval,con->testcase))){ 
+  if ((timewait=TestTime(&smartval,con->testcase))){ 
     pout("Please wait %d %s for test to complete.\n",
 	    (int)timewait, con->testcase==OFFLINE_FULL_SCAN?"seconds":"minutes");
     
diff --git a/sm5/ataprint.cpp b/sm5/ataprint.cpp
index 19159a734..20d233d84 100644
--- a/sm5/ataprint.cpp
+++ b/sm5/ataprint.cpp
@@ -29,7 +29,7 @@
 #include "smartctl.h"
 #include "extern.h"
 
-const char *CVSid2="$Id: ataprint.cpp,v 1.39 2002/10/30 06:02:39 ballen4705 Exp $"
+const char *CVSid2="$Id: ataprint.cpp,v 1.40 2002/10/30 10:18:37 ballen4705 Exp $"
 CVSID1 CVSID2 CVSID3 CVSID6;
 
 // for passing global control variables
@@ -63,7 +63,7 @@ void printswap(char *in, unsigned int n){
 }
 
 
-void ataPrintDriveInfo (struct hd_driveid drive){
+void ataPrintDriveInfo (struct hd_driveid *drive){
   int version;
   const char *description;
   char unknown[64];
@@ -71,13 +71,13 @@ void ataPrintDriveInfo (struct hd_driveid drive){
 
   // print out model, serial # and firmware versions  (byte-swap ASCI strings)
   pout("Device Model:     ");
-  printswap(drive.model,40);
+  printswap(drive->model,40);
 
   pout("Serial Number:    ");
-  printswap(drive.serial_no,20);
+  printswap(drive->serial_no,20);
 
   pout("Firmware Version: ");
-  printswap(drive.fw_rev,8);
+  printswap(drive->fw_rev,8);
 
   // now get ATA version info
   version=ataVersionInfo(&description,drive, &minorrev);
@@ -107,89 +107,88 @@ void ataPrintDriveInfo (struct hd_driveid drive){
 }
 
 
-/* void PrintSmartOfflineStatus ( struct ata_smart_values data) 
-   prints verbose value Off-line data collection status byte */
-void PrintSmartOfflineStatus(struct ata_smart_values data){
+/*  prints verbose value Off-line data collection status byte */
+void PrintSmartOfflineStatus(struct ata_smart_values *data){
   pout("Off-line data collection status: ");	
   
-  switch(data.offline_data_collection_status){
+  switch(data->offline_data_collection_status){
   case 0x00:
   case 0x80:
     pout("(0x%02x)\tOffline data collection activity was\n\t\t\t\t\t",
-	 (int)data.offline_data_collection_status);
+	 (int)data->offline_data_collection_status);
     pout("never started.\n");
     break;
   case 0x01:
   case 0x81:
     pout("(0x%02x)\tReserved.\n",
-	 (int)data.offline_data_collection_status);
+	 (int)data->offline_data_collection_status);
     break;
   case 0x02:
   case 0x82:
     pout("(0x%02x)\tOffline data collection activity \n\t\t\t\t\t",
-	 (int)data.offline_data_collection_status);
+	 (int)data->offline_data_collection_status);
     pout("completed without error.\n");
     break;
   case 0x03:
   case 0x83:
     pout("(0x%02x)\tReserved.\n",
-	 (int)data.offline_data_collection_status);
+	 (int)data->offline_data_collection_status);
     break;
   case 0x04:
   case 0x84:
     pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
-	 (int)data.offline_data_collection_status);
+	 (int)data->offline_data_collection_status);
     pout("suspended by an interrupting command from host.\n");
     break;
   case 0x05:
   case 0x85:
     pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
-	 (int)data.offline_data_collection_status);
+	 (int)data->offline_data_collection_status);
     pout("aborted by an interrupting command from host.\n");
     break;
   case 0x06:
   case 0x86:
     pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t",
-	 (int)data.offline_data_collection_status);
+	 (int)data->offline_data_collection_status);
     pout("aborted by the device with a fatal error.\n");
     break;
   default:
-    if ( ((data.offline_data_collection_status >= 0x07) &&
-	  (data.offline_data_collection_status <= 0x3f)) ||
-	 ((data.offline_data_collection_status >= 0xc0) &&
-	  (data.offline_data_collection_status <= 0xff)) )
-      pout("(0x%02x)\tVendor Specific.\n",(int)data.offline_data_collection_status);
+    if ( ((data->offline_data_collection_status >= 0x07) &&
+	  (data->offline_data_collection_status <= 0x3f)) ||
+	 ((data->offline_data_collection_status >= 0xc0) &&
+	  (data->offline_data_collection_status <= 0xff)) )
+      pout("(0x%02x)\tVendor Specific.\n",(int)data->offline_data_collection_status);
     else
-      pout("(0x%02x)\tReserved.\n",(int)data.offline_data_collection_status);
+      pout("(0x%02x)\tReserved.\n",(int)data->offline_data_collection_status);
   }
 }
 
 
 
-void PrintSmartSelfExecStatus ( struct ata_smart_values data)
+void PrintSmartSelfExecStatus(struct ata_smart_values *data)
 {
    pout("Self-test execution status:      ");
    
-   switch (data.self_test_exec_status >> 4)
+   switch (data->self_test_exec_status >> 4)
    {
       case 0:
         pout("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t",
-                (int)data.self_test_exec_status);
+                (int)data->self_test_exec_status);
         pout("without error or no self-test has ever \n\t\t\t\t\tbeen run.\n");
         break;
        case 1:
          pout("(%4d)\tThe self-test routine was aborted by\n\t\t\t\t\t",
-                 (int)data.self_test_exec_status);
+                 (int)data->self_test_exec_status);
          pout("the host.\n");
          break;
        case 2:
          pout("(%4d)\tThe self-test routine was interrupted\n\t\t\t\t\t",
-                 (int)data.self_test_exec_status);
+                 (int)data->self_test_exec_status);
          pout("by the host with a hard or soft reset.\n");
          break;
        case 3:
           pout("(%4d)\tA fatal error or unknown test error\n\t\t\t\t\t",
-                  (int)data.self_test_exec_status);
+                  (int)data->self_test_exec_status);
           pout("occurred while the device was executing\n\t\t\t\t\t");
           pout("its self-test routine and the device \n\t\t\t\t\t");
           pout("was unable to complete the self-test \n\t\t\t\t\t");
@@ -197,36 +196,36 @@ void PrintSmartSelfExecStatus ( struct ata_smart_values data)
           break;
        case 4:
           pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t",
-                  (int)data.self_test_exec_status);
+                  (int)data->self_test_exec_status);
           pout("a test element that failed and the test\n\t\t\t\t\t");
           pout("element that failed is not known.\n");
           break;
        case 5:
           pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t",
-                  (int)data.self_test_exec_status);
+                  (int)data->self_test_exec_status);
           pout("the electrical element of the test\n\t\t\t\t\t");
           pout("failed.\n");
           break;
        case 6:
           pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t",
-                  (int)data.self_test_exec_status);
+                  (int)data->self_test_exec_status);
           pout("the servo (and/or seek) element of the \n\t\t\t\t\t");
           pout("test failed.\n");
           break;
        case 7:
           pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t",
-                  (int)data.self_test_exec_status);
+                  (int)data->self_test_exec_status);
           pout("the read element of the test failed.\n");
           break;
        case 15:
           pout("(%4d)\tSelf-test routine in progress...\n\t\t\t\t\t",
-                  (int)data.self_test_exec_status);
+                  (int)data->self_test_exec_status);
           pout("%1d0%% of test remaining.\n", 
-                  (int)(data.self_test_exec_status & 0x0f));
+                  (int)(data->self_test_exec_status & 0x0f));
           break;
        default:
           pout("(%4d)\tReserved.\n",
-                  (int)data.self_test_exec_status);
+                  (int)data->self_test_exec_status);
           break;
    }
 	
@@ -234,21 +233,21 @@ void PrintSmartSelfExecStatus ( struct ata_smart_values data)
 
 
 
-void PrintSmartTotalTimeCompleteOffline ( struct ata_smart_values data){
+void PrintSmartTotalTimeCompleteOffline ( struct ata_smart_values *data){
   pout("Total time to complete off-line \n");
   pout("data collection: \t\t (%4d) seconds.\n", 
-       (int)data.total_time_to_complete_off_line);
+       (int)data->total_time_to_complete_off_line);
 }
 
 
 
-void PrintSmartOfflineCollectCap ( struct ata_smart_values data)
+void PrintSmartOfflineCollectCap(struct ata_smart_values *data)
 {
    pout("Offline data collection\n");
    pout("capabilities: \t\t\t (0x%02x) ",
-            (int)data.offline_data_collection_capability);
+            (int)data->offline_data_collection_capability);
 
-   if (data.offline_data_collection_capability == 0x00)
+   if (data->offline_data_collection_capability == 0x00)
    {
       pout("\tOff-line data collection not supported.\n");
    } 
@@ -278,23 +277,23 @@ void PrintSmartOfflineCollectCap ( struct ata_smart_values data)
 
 
 
-void PrintSmartCapability ( struct ata_smart_values data)
+void PrintSmartCapability ( struct ata_smart_values *data)
 {
    pout("SMART capabilities:            ");
-   pout("(0x%04x)\t", (int)data.smart_capability);
+   pout("(0x%04x)\t", (int)data->smart_capability);
    
-   if (data.smart_capability == 0x00)
+   if (data->smart_capability == 0x00)
    {
        pout("Automatic saving of SMART data\t\t\t\t\tis not implemented.\n");
    } 
    else 
    {
 	
-      pout( "%s\n", (data.smart_capability & 0x01)? 
+      pout( "%s\n", (data->smart_capability & 0x01)? 
               "Saves SMART data before entering\n\t\t\t\t\tpower-saving mode.":
               "Does not save SMART data before\n\t\t\t\t\tentering power-saving mode.");
 		
-      if ( data.smart_capability & 0x02 )
+      if ( data->smart_capability & 0x02 )
       {
           pout("\t\t\t\t\tSupports SMART auto save timer.\n");
       }
@@ -303,7 +302,7 @@ void PrintSmartCapability ( struct ata_smart_values data)
 
 
 
-void PrintSmartErrorLogCapability ( struct ata_smart_values data)
+void PrintSmartErrorLogCapability ( struct ata_smart_values *data)
 {
 
    pout("Error logging capability:       ");
@@ -311,23 +310,23 @@ void PrintSmartErrorLogCapability ( struct ata_smart_values data)
    if ( isSmartErrorLogCapable(data) )
    {
       pout(" (0x%02x)\tError logging supported.\n",
-               (int)data.errorlog_capability);
+               (int)data->errorlog_capability);
    }
    else {
        pout(" (0x%02x)\tError logging NOT supported.\n",
-                (int)data.errorlog_capability);
+                (int)data->errorlog_capability);
    }
 }
 
 
 
-void PrintSmartShortSelfTestPollingTime ( struct ata_smart_values data)
+void PrintSmartShortSelfTestPollingTime (struct ata_smart_values *data)
 {
    if ( isSupportSelfTest(data) )
    {
       pout("Short self-test routine \n");
       pout("recommended polling time: \t (%4d) minutes.\n", 
-               (int)data.short_test_completion_time);
+               (int)data->short_test_completion_time);
 
    }
    else
@@ -338,13 +337,13 @@ void PrintSmartShortSelfTestPollingTime ( struct ata_smart_values data)
 }
 
 
-void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values data)
+void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values *data)
 {
    if ( isSupportSelfTest(data) )
    {
       pout("Extended self-test routine \n");
       pout("recommended polling time: \t (%4d) minutes.\n", 
-               (int)data.extend_test_completion_time);
+               (int)data->extend_test_completion_time);
    }
    else
    {
@@ -357,8 +356,8 @@ void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values data)
 // onlyfailed=0 : print all attribute values
 // onlyfailed=1:  just ones that are currently failed and have prefailure bit set
 // onlyfailed=2:  ones that are failed, or have failed with or without prefailure bit set
-void PrintSmartAttribWithThres (struct ata_smart_values data, 
-				struct ata_smart_thresholds thresholds,
+void PrintSmartAttribWithThres (struct ata_smart_values *data, 
+				struct ata_smart_thresholds *thresholds,
 				int onlyfailed){
   int i,j;
   long long rawvalue;
@@ -367,8 +366,8 @@ void PrintSmartAttribWithThres (struct ata_smart_values data,
   // step through all vendor attributes
   for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){
     char *status;
-    struct ata_smart_attribute *disk=data.vendor_attributes+i;
-    struct ata_smart_threshold_entry *thre=thresholds.thres_entries+i;
+    struct ata_smart_attribute *disk=data->vendor_attributes+i;
+    struct ata_smart_threshold_entry *thre=thresholds->thres_entries+i;
     
     // consider only valid attributes
     if (disk->id && thre->id){
@@ -389,7 +388,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values data,
       // print header only if needed
       if (needheader){
 	if (!onlyfailed){
-	  pout("SMART Attributes Data Structure revision number: %d\n",(int)data.revnumber);
+	  pout("SMART Attributes Data Structure revision number: %d\n",(int)data->revnumber);
 	  pout("Vendor Specific SMART Attributes with Thresholds:\n");
 	}
 	pout("ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE     WHEN_FAILED RAW_VALUE\n");
@@ -463,7 +462,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values data,
 }
 
 
-void ataPrintGeneralSmartValues(struct ata_smart_values data){
+void ataPrintGeneralSmartValues(struct ata_smart_values *data){
   pout("General SMART Values:\n");
   
   PrintSmartOfflineStatus(data); 
@@ -494,31 +493,31 @@ int nonempty(unsigned char *testarea,int n){
 }
 
 // returns number of errors
-void ataPrintSmartErrorlog (struct ata_smart_errorlog data){
+void ataPrintSmartErrorlog (struct ata_smart_errorlog *data){
   int i,j,k;
   
-  pout("SMART Error Log Version: %d\n", (int)data.revnumber);
+  pout("SMART Error Log Version: %d\n", (int)data->revnumber);
   
   // if no errors logged, return
-  if (!data.error_log_pointer){
+  if (!data->error_log_pointer){
     pout("No Errors Logged\n\n");
     return;
   }
   QUIETON(con);
   // if log pointer out of range, return
-  if ( data.error_log_pointer>5 ){
+  if ( data->error_log_pointer>5 ){
     pout("Invalid Error Log index = %02x (T13/1321D rev 1c"
 	 "Section 8.41.6.8.2.2 gives valid range from 1 to 5)\n\n",
-	 (int)data.error_log_pointer);
+	 (int)data->error_log_pointer);
     return;
   }
   
   // starting printing error log info
-  if (data.ata_error_count<=5)
-    pout( "ATA Error Count: %d\n", (int)data.ata_error_count);
+  if (data->ata_error_count<=5)
+    pout( "ATA Error Count: %d\n", (int)data->ata_error_count);
   else
     pout( "ATA Error Count: %d (device log contains only the most recent five errors)\n",
-	   (int)data.ata_error_count);
+	   (int)data->ata_error_count);
   QUIETOFF(con);
   pout("\tDCR = Device Control Register\n");
   pout("\tFR  = Features Register\n");
@@ -537,12 +536,12 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data){
   for (k = 4; k >= 0; k-- ) {
     
     // The error log data structure entries are a circular buffer
-    i=(data.error_log_pointer+k)%5;
+    i=(data->error_log_pointer+k)%5;
     
     // Spec says: unused error log structures shall be zero filled
-    if (nonempty((unsigned char*)&(data.errorlog_struct[i]),sizeof(data.errorlog_struct[i]))){
+    if (nonempty((unsigned char*)&(data->errorlog_struct[i]),sizeof(data->errorlog_struct[i]))){
       char *msgstate;
-      switch (data.errorlog_struct[i].error_struct.state){
+      switch (data->errorlog_struct[i].error_struct.state){
       case 0x00: msgstate="in an unknown state";break;
       case 0x01: msgstate="sleeping"; break;
       case 0x02: msgstate="in standby mode"; break;
@@ -553,22 +552,22 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data){
       // See table 42 of ATA5 spec
       QUIETON(con);
       pout("Error %d occurred at disk power-on lifetime: %d hours\n",
-	     (int)(5-k), (int)data.errorlog_struct[i].error_struct.timestamp);
+	     (int)(5-k), (int)data->errorlog_struct[i].error_struct.timestamp);
       QUIETOFF(con);
       pout("When the command that caused the error occurred, the device was %s.\n",msgstate);
       pout("After command completion occurred, registers were:\n");
       pout("ER:%02x SC:%02x SN:%02x CL:%02x CH:%02x D/H:%02x ST:%02x\n",
-	   (int)data.errorlog_struct[i].error_struct.error_register,
-	   (int)data.errorlog_struct[i].error_struct.sector_count,
-	   (int)data.errorlog_struct[i].error_struct.sector_number,
-	   (int)data.errorlog_struct[i].error_struct.cylinder_low,
-	   (int)data.errorlog_struct[i].error_struct.cylinder_high,
-	   (int)data.errorlog_struct[i].error_struct.drive_head,
-	   (int)data.errorlog_struct[i].error_struct.status);
+	   (int)data->errorlog_struct[i].error_struct.error_register,
+	   (int)data->errorlog_struct[i].error_struct.sector_count,
+	   (int)data->errorlog_struct[i].error_struct.sector_number,
+	   (int)data->errorlog_struct[i].error_struct.cylinder_low,
+	   (int)data->errorlog_struct[i].error_struct.cylinder_high,
+	   (int)data->errorlog_struct[i].error_struct.drive_head,
+	   (int)data->errorlog_struct[i].error_struct.status);
       pout("Sequence of commands leading to the command that caused the error were:\n");
       pout("DCR   FR   SC   SN   CL   CH   D/H   CR   Timestamp\n");
       for ( j = 4; j >= 0; j--){
-	struct ata_smart_errorlog_command_struct *thiscommand=&(data.errorlog_struct[i].commands[j]);
+	struct ata_smart_errorlog_command_struct *thiscommand=&(data->errorlog_struct[i].commands[j]);
 	
 	// Spec says: unused data command structures shall be zero filled
 	if (nonempty((unsigned char*)thiscommand,sizeof(*thiscommand)))
@@ -595,15 +594,15 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data){
 }
 
 // return value is number of entries found where the self-test showed an error
-int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog data,int allentries){
+int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog *data,int allentries){
   int i,j,noheaderprinted=1;
   int retval=0;
 
   if (allentries)
-    pout("SMART Self-test log, version number %d\n",(int)data.revnumber);
-  if ((data.revnumber!=0x0001) && allentries)
+    pout("SMART Self-test log, version number %d\n",(int)data->revnumber);
+  if ((data->revnumber!=0x0001) && allentries)
     pout("Warning - structure revision number does not match spec!\n");
-  if (data.mostrecenttest==0){
+  if (data->mostrecenttest==0){
     if (allentries)
       pout("No self-tests have been logged\n\n");
     return 0;
@@ -613,8 +612,8 @@ int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog data,int allentries){
   for (i=20;i>=0;i--){    
     struct ata_smart_selftestlog_struct *log;
     // log is a circular buffer
-    j=(i+data.mostrecenttest)%21;
-    log=data.selftest_struct+j;
+    j=(i+data->mostrecenttest)%21;
+    log=data->selftest_struct+j;
 
     if (nonempty((unsigned char*)log,sizeof(*log))){
       char *msgtest,*msgstat,percent[64],firstlba[64];
@@ -680,17 +679,17 @@ int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog data,int allentries){
   return retval;
 }
 
-void ataPseudoCheckSmart ( struct ata_smart_values data, 
-                           struct ata_smart_thresholds thresholds) {
+void ataPseudoCheckSmart ( struct ata_smart_values *data, 
+                           struct ata_smart_thresholds *thresholds) {
   int i;
   int failed = 0;
   for (i = 0 ; i < NUMBER_ATA_SMART_ATTRIBUTES ; i++) {
-    if (data.vendor_attributes[i].id &&   
-	thresholds.thres_entries[i].id &&
-	data.vendor_attributes[i].status.flag.prefailure &&
-	(data.vendor_attributes[i].current <= thresholds.thres_entries[i].threshold) &&
-	(thresholds.thres_entries[i].threshold != 0xFE)){
-      pout("Attribute ID %d Failed\n",(int)data.vendor_attributes[i].id);
+    if (data->vendor_attributes[i].id &&   
+	thresholds->thres_entries[i].id &&
+	data->vendor_attributes[i].status.flag.prefailure &&
+	(data->vendor_attributes[i].current <= thresholds->thres_entries[i].threshold) &&
+	(thresholds->thres_entries[i].threshold != 0xFE)){
+      pout("Attribute ID %d Failed\n",(int)data->vendor_attributes[i].id);
       failed = 1;
     } 
   }   
@@ -722,11 +721,11 @@ int ataPrintMain (int fd){
   // Print most drive identity information if requested
   if (con->driveinfo){
     pout("=== START OF INFORMATION SECTION ===\n");
-    ataPrintDriveInfo(drive);
+    ataPrintDriveInfo(&drive);
   }
   
   // now check if drive supports SMART; otherwise time to exit
-  if (!ataSmartSupport(drive)){
+  if (!ataSmartSupport(&drive)){
     pout("SMART support is: Unavailable - device lacks SMART capability.\n");
     pout("                  Checking to be sure by trying SMART ENABLE command.\n");
     if (ataEnableSmart(fd)){
@@ -816,7 +815,7 @@ int ataPrintMain (int fd){
 
   // Enable/Disable Off-line testing
   if (con->smartautoofflineenable){
-    if (!isSupportAutomaticTimer(smartval)){
+    if (!isSupportAutomaticTimer(&smartval)){
       pout("Warning: device does not support SMART Automatic Timers.\n\n");
     }
     if (ataEnableAutoOffline(fd)){
@@ -827,7 +826,7 @@ int ataPrintMain (int fd){
       pout("SMART Automatic Offline Testing Enabled every four hours.\n");
   }
   if (con->smartautoofflinedisable){
-    if (!isSupportAutomaticTimer(smartval)){
+    if (!isSupportAutomaticTimer(&smartval)){
       pout("Warning: device does not support SMART Automatic Timers.\n\n");
     }
     if (ataDisableAutoOffline(fd)){
@@ -855,14 +854,14 @@ int ataPrintMain (int fd){
       pout("SMART overall-health self-assessment test result: FAILED!\n"
 	     "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n");
       QUIETOFF(con);
-      if (ataCheckSmart(smartval, smartthres,1)){
+      if (ataCheckSmart(&smartval, &smartthres,1)){
 	returnval|=FAILATTR;
 	if (con->smartvendorattrib)
 	  pout("See vendor-specific Attribute list for failed Attributes.\n\n");
 	else {
 	  QUIETON(con);
 	  pout("Failed Attributes:\n");
-	  PrintSmartAttribWithThres(smartval, smartthres,1);
+	  PrintSmartAttribWithThres(&smartval, &smartthres,1);
 	}
       }
       else
@@ -872,13 +871,13 @@ int ataPrintMain (int fd){
     }
     else {
       pout("SMART overall-health self-assessment test result: PASSED\n");
-      if (ataCheckSmart(smartval, smartthres,0)){
+      if (ataCheckSmart(&smartval, &smartthres,0)){
 	if (con->smartvendorattrib)
 	  pout("See vendor-specific Attribute list for marginal Attributes.\n\n");
 	else {
 	  QUIETON(con);
 	  pout("Please note the following marginal attributes:\n");
-	  PrintSmartAttribWithThres(smartval, smartthres,2);
+	  PrintSmartAttribWithThres(&smartval, &smartthres,2);
 	} 
 	returnval|=FAILAGE;
       }
@@ -890,18 +889,18 @@ int ataPrintMain (int fd){
   
   // Print general SMART values
   if (con->generalsmartvalues)
-    ataPrintGeneralSmartValues(smartval); 
+    ataPrintGeneralSmartValues(&smartval); 
   
   // Print vendor-specific attributes
   if (con->smartvendorattrib){
     QUIETON(con);
-    PrintSmartAttribWithThres(smartval, smartthres,con->quietmode?2:0);
+    PrintSmartAttribWithThres(&smartval, &smartthres,con->quietmode?2:0);
     QUIETOFF(con);
   }
   
   // Print SMART error log
   if (con->smarterrorlog){
-    if (!isSmartErrorLogCapable(smartval))
+    if (!isSmartErrorLogCapable(&smartval))
       pout("Warning: device does not support Error Logging\n");
     if (ataReadErrorLog(fd, &smarterror)){
       pout("Smartctl: SMART Errorlog Read Failed\n");
@@ -909,14 +908,14 @@ int ataPrintMain (int fd){
     }
     else {
       // turn on quiet mode inside this
-      ataPrintSmartErrorlog(smarterror);
+      ataPrintSmartErrorlog(&smarterror);
       QUIETOFF(con);
     }
   }
   
   // Print SMART self-test log
   if (con->smartselftestlog){
-    if (!isSmartErrorLogCapable(smartval))
+    if (!isSmartErrorLogCapable(&smartval))
       pout("Warning: device does not support Self Test Logging\n");
     else {
       if(ataReadSelfTestLog(fd, &smartselftest)){
@@ -925,7 +924,7 @@ int ataPrintMain (int fd){
       }
       else {
 	QUIETON(con);
-	if (ataPrintSmartSelfTestlog(smartselftest,!con->quietmode))
+	if (ataPrintSmartSelfTestlog(&smartselftest,!con->quietmode))
 	  returnval|=FAILLOG;
 	QUIETOFF(con);
 	pout("\n");
@@ -939,9 +938,9 @@ int ataPrintMain (int fd){
   
   pout("=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n");
   // if doing a self-test, be sure it's supported by the hardware
-  if (con->testcase==OFFLINE_FULL_SCAN &&  !isSupportExecuteOfflineImmediate(smartval))
+  if (con->testcase==OFFLINE_FULL_SCAN &&  !isSupportExecuteOfflineImmediate(&smartval))
     pout("Warning: device does not support Execute Off-Line Immediate function.\n\n");
-  else if (!isSupportSelfTest(smartval))
+  else if (!isSupportSelfTest(&smartval))
     pout("Warning: device does not support Self-Test functions.\n\n");
   
   // Now do the test
@@ -949,7 +948,7 @@ int ataPrintMain (int fd){
     return returnval|=FAILSMART;
   
   // Tell user how long test will take to complete  
-  if ((timewait=TestTime(smartval,con->testcase))){ 
+  if ((timewait=TestTime(&smartval,con->testcase))){ 
     pout("Please wait %d %s for test to complete.\n",
 	    (int)timewait, con->testcase==OFFLINE_FULL_SCAN?"seconds":"minutes");
     
diff --git a/sm5/ataprint.h b/sm5/ataprint.h
index 8bff3e511..993537101 100644
--- a/sm5/ataprint.h
+++ b/sm5/ataprint.h
@@ -26,7 +26,7 @@
 #define _SMART_PRINT_H_
 
 #ifndef CVSID2
-#define CVSID2 "$Id: ataprint.h,v 1.13 2002/10/28 23:46:59 ballen4705 Exp $\n"
+#define CVSID2 "$Id: ataprint.h,v 1.14 2002/10/30 10:18:37 ballen4705 Exp $\n"
 #endif
 
 #include <stdio.h>
@@ -40,24 +40,24 @@
 
 
 /* Prints ATA Drive Information and S.M.A.R.T. Capability */
-void ataPrintDriveInfo(struct hd_driveid);
+void ataPrintDriveInfo(struct hd_driveid *);
 
-void ataPrintGeneralSmartValues(struct ata_smart_values);
+void ataPrintGeneralSmartValues(struct ata_smart_values *);
 
-void ataPrintSmartThresholds(struct ata_smart_thresholds);
+void ataPrintSmartThresholds(struct ata_smart_thresholds *);
 
-void ataPrintSmartErrorlog(struct ata_smart_errorlog);
+void ataPrintSmartErrorlog(struct ata_smart_errorlog *);
 
-void PrintSmartAttributes(struct ata_smart_values data);
+void PrintSmartAttributes(struct ata_smart_values *data);
 
-void PrintSmartAttribWithThres(struct ata_smart_values data,
-                                struct ata_smart_thresholds thresholds,
+void PrintSmartAttribWithThres(struct ata_smart_values *data,
+                                struct ata_smart_thresholds *thresholds,
 				int onlyfailed);
 
 // returns number of entries that had logged errors
-int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog data, int allentries);
+int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog *data, int allentries);
 
-void ataPseudoCheckSmart(struct ata_smart_values, struct ata_smart_thresholds );
+void ataPseudoCheckSmart(struct ata_smart_values *, struct ata_smart_thresholds *);
 
 
 
diff --git a/sm5/smartd.8 b/sm5/smartd.8
index 2efe77654..9883d13b6 100644
--- a/sm5/smartd.8
+++ b/sm5/smartd.8
@@ -13,7 +13,7 @@
 \# at the Concurrent Systems Laboratory (now part of the Storage Systems
 \# Research Center), Jack Baskin School of Engineering, University of
 \# California, Santa Cruz. http://ssrc.soe.ucsc.edu/
-.TH SMARTD 8  "$Date: 2002/10/29 16:59:02 $" "smartmontools-5.0"
+.TH SMARTD 8  "$Date: 2002/10/30 10:18:37 $" "smartmontools-5.0"
 .SH NAME
 smartd \- S.M.A.R.T. Daemon
 .SH SYNOPSIS
@@ -256,6 +256,17 @@ character in the device name is an 's' or an 'h'.  If it can't guess
 from this fifth character, then it will simply try to access the
 device using first ATA and then SCSI ioctl()s.
 .TP
+.B \-C <N>
+This sets the time in between disk checks to be 
+.B <N>
+seconds apart.  Note that although you can give this Directive
+multiple times on different lines of the configuration file, only the
+final value that is given has an effect, and applies to all the disks.
+The default value of 
+.B <N> 
+is 1800 sec, and the minimum allowed value is
+ten seconds.
+.TP
 .B \-c
 Check: Will check the SMART status of the disk.  If any prefailure
 attributes are less than or equal to their threshold values, then disk
@@ -302,7 +313,7 @@ its value since the last check, 30 min ago.
 .TP
 .B \-u
 Usage: Report anytime that a usage attribute has changed its value
-since the last check, 30 min ago.
+since the last check, N seconds ago.
 .TP
 .B \-t
 Track: Equivalent to turning on the two previous flags '\-t' and '\-u'.
@@ -310,21 +321,21 @@ Tracks changes in
 .I all
 device attributes.
 .TP
-.B \-i INT
+.B \-i <ID>
 Ignore: This Directive modifies the behavior of the '\-f' attribute
 and has no effect without it.  
-.I This Directive takes a decimal integer argument INT in the range from 1 to 255.
-It means to ignore device attribute number INT, when checking for
+.I This Directive takes a decimal integer argument <ID> in the range from 1 to 255.
+It means to ignore device attribute number <ID>, when checking for
 failure of usage attributes.  This is useful, for example, if you have
 a very old disk and don't want to keep getting messages about the
 hours-on-lifetime attribute (usually attribute 9) failing.
 .TP
-.B \-I INT
+.B \-I <ID>
 Ignore: This Directive modifies the
 behavior of the '\-p', '\-u', and '\-t' attributes
 and has no effect without one of them.  
-.I This Directive takes a decimal integer argument INT in the range from 1 to 255.
-It means to ignore device attribute INT, when tracking changes in the
+.I This Directive takes a decimal integer argument <ID> in the range from 1 to 255.
+It means to ignore device attribute <ID>, when tracking changes in the
 attribute values.  This is useful, for example, if one of the device
 attributes is the disk temperature (usually attribute 194 or
 231). It's annoying to get reports each time the temperature changes.
@@ -466,4 +477,4 @@ Please let us know if there is an on\-line source for this document.
 
 .SH
 CVS ID OF THIS PAGE:
-$Id: smartd.8,v 1.16 2002/10/29 16:59:02 ballen4705 Exp $
+$Id: smartd.8,v 1.17 2002/10/30 10:18:37 ballen4705 Exp $
diff --git a/sm5/smartd.c b/sm5/smartd.c
index fcce22da6..fa567bf05 100644
--- a/sm5/smartd.c
+++ b/sm5/smartd.c
@@ -44,7 +44,7 @@
 
 // CVS ID strings
 extern const char *CVSid1, *CVSid2;
-const char *CVSid6="$Id: smartd.c,v 1.46 2002/10/30 06:02:40 ballen4705 Exp $" 
+const char *CVSid6="$Id: smartd.c,v 1.47 2002/10/30 10:18:37 ballen4705 Exp $" 
 CVSID1 CVSID2 CVSID3 CVSID4 CVSID7;
 
 // global variable used for control of printing, passing arguments, etc.
@@ -173,6 +173,7 @@ void Directives() {
   printout(LOG_INFO,"Configuration file Directives (following device name):\n");
   printout(LOG_INFO,"  -A    Device is an ATA device\n");
   printout(LOG_INFO,"  -S    Device is a SCSI device\n");
+  printout(LOG_INFO,"  -C N  Check disks once every N seconds, where N>=10.\n");
   printout(LOG_INFO,"  -c    Monitor SMART Health Status, report if failed\n");
   printout(LOG_INFO,"  -l    Monitor SMART Error Log, report new errors\n");
   printout(LOG_INFO,"  -L    Monitor SMART Self-Test Log, report new errors\n");
@@ -251,7 +252,7 @@ int selftesterrorcount(int fd, char *name){
   }
   
   // return current number of self-test errors
-  return ataPrintSmartSelfTestlog(log,0);
+  return ataPrintSmartSelfTestlog(&log,0);
 }
 
 
@@ -274,7 +275,7 @@ int atadevicescan2(atadevices_t *devices, cfgfile *cfg){
   
   // Get drive identity structure
   // May want to add options to enable autosave, automatic online testing
-  if (ataReadHDIdentity (fd,&drive) || !ataSmartSupport(drive) || ataEnableSmart(fd)){
+  if (ataReadHDIdentity (fd,&drive) || !ataSmartSupport(&drive) || ataEnableSmart(fd)){
     // device exists, but not able to do SMART
     printout(LOG_INFO,"Device: %s, not SMART capable, or couldn't enable SMART\n",device);
     close(fd);
@@ -530,7 +531,7 @@ int ataCheckDevice(atadevices_t *drive){
     struct ata_smart_values     curval;
     struct ata_smart_thresholds *thresh=drive->smartthres;
     
-    // Read current attribute values. *drive contains old values adn thresholds
+    // Read current attribute values. *drive contains old values and thresholds
     if (ataReadSmartValues(fd,&curval))
       printout(LOG_CRIT, "Device: %s, failed to read SMART Attribute Data\n", name);
     else {  
@@ -559,11 +560,16 @@ int ataCheckDevice(atadevices_t *drive){
 	
 	// This block tracks usage or prefailure attributes to see if they are changing
 	if ((cfg->usage || cfg->prefail) && ((att=ataCompareSmartValues2(&curval, drive->smartval, thresh, i, name)))){
+
+	  // I should probably clean this up by defining a union to
+	  // with one int=four unsigned chars to do this.
 	  const int mask=0xff;
-	  int prefail=(att>>24) & mask;
-	  int id     =(att>>16) & mask;
-	  int oldval =(att>>8)  & mask;
 	  int newval =(att>>0)  & mask;
+	  int oldval =(att>>8)  & mask;
+	  int id     =(att>>16) & mask;
+	  int prefail=(att>>24) & mask;
+
+	  // for printing attribute name
 	  char attname[64],*loc=attname;
 	  
 	  // are we tracking this attribute?
@@ -587,7 +593,7 @@ int ataCheckDevice(atadevices_t *drive){
       } // end of loop over attributes
      
       // Save the new values into *drive for the next time around
-      memcpy(drive->smartval,&curval,sizeof(curval));
+      *drive->smartval=curval;
     } 
   }
   
@@ -760,10 +766,11 @@ int parsetoken(char *token,cfgfile *cfg){
     cfg->selftest=1;
     cfg->errorlog=1;
     break;
-  case 'i':
-  case 'I':
+  case 'i': // ignore
+  case 'I': // ignore
+  case 'C': // period (time interval) for checking
     // ignore a particular vendor attribute for tracking (i) or
-    // failure (I)
+    // failure (I).  Or give a check interval for sleeping.
     arg=strtok(NULL,delim);
     // make sure argument is there
     if (!arg) {
@@ -775,21 +782,34 @@ int parsetoken(char *token,cfgfile *cfg){
     // get argument value, check that it's properly-formed, an
     // integer, and in-range
     val=strtol(arg,&endptr,10);
-    if (*endptr!='\0' || val<=0 || val>255)  {
-      printout(LOG_CRIT,"Drive %s Directive: %s at line %d of file %s has argument: %s, needs 0 < n < 256\n",
-	       name,token,lineno,CONFIGFILE,arg);
-      Directives();
-      exit(1);
+    switch (sym) {
+    case 'C':
+      if (*endptr!='\0' || val<10) {
+	printout(LOG_CRIT,"Drive %s Directive: %s, line %d, file %s, has argument: %s, mimimum is ten secoonds\n",
+		 name,token,lineno,CONFIGFILE,arg);
+	Directives();
+	exit(1);
+      }
+      checktime=val;
+      return 1;
+    case 'i':
+    case 'I':
+      if (*endptr!='\0' || val<=0 || val>255 )  {
+	printout(LOG_CRIT,"Drive %s Directive: %s, line %d, file %s, has argument: %s, needs 0 < n < 256\n",
+		 name,token,lineno,CONFIGFILE,arg);
+	Directives();
+	exit(1);
+      }
+      // put into correct list (bitmaps, access only with isattoff()
+      // function. Turns OFF corresponding attribute.
+      if (sym=='I')
+	isattoff(val,cfg->trackatt,1);
+      else
+	isattoff(val,cfg->failatt,1);
+      return 1;
     }
-    // put into correct list (bitmaps, access only with isattoff()
-    // function. Turns OFF corresponding attribute.
-    if (sym=='I')
-      isattoff(val,cfg->trackatt,1);
-    else
-      isattoff(val,cfg->failatt,1);
-    break;
   default:
-    printout(LOG_CRIT,"Drive: %s, unknown option: %s at line %d of file %s\n",
+    printout(LOG_CRIT,"Drive: %s, unknown Directive: %s at line %d of file %s\n",
 	     name,token,lineno,CONFIGFILE);
     Directives();
     exit(1);
diff --git a/sm5/smartd.cpp b/sm5/smartd.cpp
index d86b3440a..899a1a687 100644
--- a/sm5/smartd.cpp
+++ b/sm5/smartd.cpp
@@ -44,7 +44,7 @@
 
 // CVS ID strings
 extern const char *CVSid1, *CVSid2;
-const char *CVSid6="$Id: smartd.cpp,v 1.46 2002/10/30 06:02:40 ballen4705 Exp $" 
+const char *CVSid6="$Id: smartd.cpp,v 1.47 2002/10/30 10:18:37 ballen4705 Exp $" 
 CVSID1 CVSID2 CVSID3 CVSID4 CVSID7;
 
 // global variable used for control of printing, passing arguments, etc.
@@ -173,6 +173,7 @@ void Directives() {
   printout(LOG_INFO,"Configuration file Directives (following device name):\n");
   printout(LOG_INFO,"  -A    Device is an ATA device\n");
   printout(LOG_INFO,"  -S    Device is a SCSI device\n");
+  printout(LOG_INFO,"  -C N  Check disks once every N seconds, where N>=10.\n");
   printout(LOG_INFO,"  -c    Monitor SMART Health Status, report if failed\n");
   printout(LOG_INFO,"  -l    Monitor SMART Error Log, report new errors\n");
   printout(LOG_INFO,"  -L    Monitor SMART Self-Test Log, report new errors\n");
@@ -251,7 +252,7 @@ int selftesterrorcount(int fd, char *name){
   }
   
   // return current number of self-test errors
-  return ataPrintSmartSelfTestlog(log,0);
+  return ataPrintSmartSelfTestlog(&log,0);
 }
 
 
@@ -274,7 +275,7 @@ int atadevicescan2(atadevices_t *devices, cfgfile *cfg){
   
   // Get drive identity structure
   // May want to add options to enable autosave, automatic online testing
-  if (ataReadHDIdentity (fd,&drive) || !ataSmartSupport(drive) || ataEnableSmart(fd)){
+  if (ataReadHDIdentity (fd,&drive) || !ataSmartSupport(&drive) || ataEnableSmart(fd)){
     // device exists, but not able to do SMART
     printout(LOG_INFO,"Device: %s, not SMART capable, or couldn't enable SMART\n",device);
     close(fd);
@@ -530,7 +531,7 @@ int ataCheckDevice(atadevices_t *drive){
     struct ata_smart_values     curval;
     struct ata_smart_thresholds *thresh=drive->smartthres;
     
-    // Read current attribute values. *drive contains old values adn thresholds
+    // Read current attribute values. *drive contains old values and thresholds
     if (ataReadSmartValues(fd,&curval))
       printout(LOG_CRIT, "Device: %s, failed to read SMART Attribute Data\n", name);
     else {  
@@ -559,11 +560,16 @@ int ataCheckDevice(atadevices_t *drive){
 	
 	// This block tracks usage or prefailure attributes to see if they are changing
 	if ((cfg->usage || cfg->prefail) && ((att=ataCompareSmartValues2(&curval, drive->smartval, thresh, i, name)))){
+
+	  // I should probably clean this up by defining a union to
+	  // with one int=four unsigned chars to do this.
 	  const int mask=0xff;
-	  int prefail=(att>>24) & mask;
-	  int id     =(att>>16) & mask;
-	  int oldval =(att>>8)  & mask;
 	  int newval =(att>>0)  & mask;
+	  int oldval =(att>>8)  & mask;
+	  int id     =(att>>16) & mask;
+	  int prefail=(att>>24) & mask;
+
+	  // for printing attribute name
 	  char attname[64],*loc=attname;
 	  
 	  // are we tracking this attribute?
@@ -587,7 +593,7 @@ int ataCheckDevice(atadevices_t *drive){
       } // end of loop over attributes
      
       // Save the new values into *drive for the next time around
-      memcpy(drive->smartval,&curval,sizeof(curval));
+      *drive->smartval=curval;
     } 
   }
   
@@ -760,10 +766,11 @@ int parsetoken(char *token,cfgfile *cfg){
     cfg->selftest=1;
     cfg->errorlog=1;
     break;
-  case 'i':
-  case 'I':
+  case 'i': // ignore
+  case 'I': // ignore
+  case 'C': // period (time interval) for checking
     // ignore a particular vendor attribute for tracking (i) or
-    // failure (I)
+    // failure (I).  Or give a check interval for sleeping.
     arg=strtok(NULL,delim);
     // make sure argument is there
     if (!arg) {
@@ -775,21 +782,34 @@ int parsetoken(char *token,cfgfile *cfg){
     // get argument value, check that it's properly-formed, an
     // integer, and in-range
     val=strtol(arg,&endptr,10);
-    if (*endptr!='\0' || val<=0 || val>255)  {
-      printout(LOG_CRIT,"Drive %s Directive: %s at line %d of file %s has argument: %s, needs 0 < n < 256\n",
-	       name,token,lineno,CONFIGFILE,arg);
-      Directives();
-      exit(1);
+    switch (sym) {
+    case 'C':
+      if (*endptr!='\0' || val<10) {
+	printout(LOG_CRIT,"Drive %s Directive: %s, line %d, file %s, has argument: %s, mimimum is ten secoonds\n",
+		 name,token,lineno,CONFIGFILE,arg);
+	Directives();
+	exit(1);
+      }
+      checktime=val;
+      return 1;
+    case 'i':
+    case 'I':
+      if (*endptr!='\0' || val<=0 || val>255 )  {
+	printout(LOG_CRIT,"Drive %s Directive: %s, line %d, file %s, has argument: %s, needs 0 < n < 256\n",
+		 name,token,lineno,CONFIGFILE,arg);
+	Directives();
+	exit(1);
+      }
+      // put into correct list (bitmaps, access only with isattoff()
+      // function. Turns OFF corresponding attribute.
+      if (sym=='I')
+	isattoff(val,cfg->trackatt,1);
+      else
+	isattoff(val,cfg->failatt,1);
+      return 1;
     }
-    // put into correct list (bitmaps, access only with isattoff()
-    // function. Turns OFF corresponding attribute.
-    if (sym=='I')
-      isattoff(val,cfg->trackatt,1);
-    else
-      isattoff(val,cfg->failatt,1);
-    break;
   default:
-    printout(LOG_CRIT,"Drive: %s, unknown option: %s at line %d of file %s\n",
+    printout(LOG_CRIT,"Drive: %s, unknown Directive: %s at line %d of file %s\n",
 	     name,token,lineno,CONFIGFILE);
     Directives();
     exit(1);
diff --git a/sm5/smartmontools.spec b/sm5/smartmontools.spec
index 7a928dabe..607f19305 100644
--- a/sm5/smartmontools.spec
+++ b/sm5/smartmontools.spec
@@ -1,4 +1,4 @@
-Release:  23
+Release:  24
 Summary:	SMARTmontools - for monitoring S.M.A.R.T. disks and devices
 Name:		smartmontools
 Version:	5.0
@@ -18,7 +18,7 @@ Packager:       Bruce Allen <smartmontools-support@lists.sourceforge.net>
 # http://telia.dl.sourceforge.net/sourceforge/smartmontools/smartmontools-%{version}-%{release}.tar.gz
 
 # CVS ID of this file is:
-# $Id: smartmontools.spec,v 1.34 2002/10/30 06:02:40 ballen4705 Exp $
+# $Id: smartmontools.spec,v 1.35 2002/10/30 10:18:37 ballen4705 Exp $
 
 # Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 # Home page: http://smartmontools.sourceforge.net
@@ -112,7 +112,24 @@ fi
 
 %define date	%(echo `LC_ALL="C" date +"%a %b %d %Y"`)
 %changelog
+
 * Wed Oct 29 2002 Bruce Allen  <smartmontools-support@lists.sourceforge.net>
+ Added new Directive for Configuration file:
+-C <N> This sets the time in between disk checks to be <N>
+  seconds apart.  Note that  although  you  can  give
+  this Directive multiple times on different lines of
+  the configuration file, only the final  value  that
+  is  given  has  an  effect,  and applies to all the
+  disks.  The default value of <N> is 1800  sec,  and
+  the minimum allowed value is ten seconds.
+- Problem wasn't the print format. F.L.W. Meunier <0@pervalidus.net>
+  sent me a gcc 3.2 build and I ran it under a debugger.  The
+  problem seems to be with passing the very large (2x512+4) byte
+  data structures as arguments.  I never liked this anyway; it was
+  inherited from smartsuite.  So I've changed all the heavyweight
+  functions (ATA ones, anyone) to just passing pointers, not hideous
+  kB size structures on the stack.  Hopefully this will now build OK
+  under gcc 3.2 with any sensible compilation options.
 - Because of reported problems with GCC 3.2 compile, I have gone
   thorough the code and explicitly changed all print format
   parameters to correspond EXACTLY to int unless they have to be
@@ -123,7 +140,6 @@ fi
   values. This means the objects of type char or short int (whether
   signed or not) are promoted to either int or unsigned int, as
   required.
-* Wed Oct 29 2002 Bruce Allen  <smartmontools-support@lists.sourceforge.net>
 - smartd, smartctl now warn if they find an attribute whose ID
   number does not match between Data and Threshold structures.
 - Fixed nasty bug which led to wrong number of arguments for a
-- 
GitLab