diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG
index 103a98292fb91e2a5d8488fe6ae439c4e806806a..c3fcca188c6bfc22cb4f66d8d08ed6ef19bc3cf8 100644
--- a/sm5/CHANGELOG
+++ b/sm5/CHANGELOG
@@ -1,6 +1,6 @@
 CHANGELOG for smartmontools
 
-$Id: CHANGELOG,v 1.174 2003/08/11 14:21:51 ballen4705 Exp $
+$Id: CHANGELOG,v 1.175 2003/08/13 12:33:22 ballen4705 Exp $
 
 Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 
@@ -38,6 +38,15 @@ CURRENT DEVELOPMENT VERSION (see VERSION file in this directory):
  
   <ADDITIONS TO THE CHANGE LOG SHOULD BE ADDED HERE, PLEASE>
 
+  [BA] Additional work on dynamic memory allocation/deallocation.
+       This should have no effect on smartctl, but clears that way
+       for smartd to dynamically add and remove entries.  It should
+       also now be easier to modify smartd to re-read its config
+       file on HUP (which is easy) without leaking memory (which is
+       harder). The philosophy is that memory for data structures in
+       smartd is now allocated only on demand, the first time it
+       is needed.
+
   [BA] smartd: finished cleanup.  Now use create/rm functions for
        cfgentries and dynamic memory allocation almost everywhere.
        Philosophy: aggresively try and provoke SEGV to help find
diff --git a/sm5/atacmdnames.c b/sm5/atacmdnames.c
index e4b9a1a80116537cec94e7e85876ec7d1f6928bf..5242c0229d22cd5b2265147b9059c5b841aa4ded 100644
--- a/sm5/atacmdnames.c
+++ b/sm5/atacmdnames.c
@@ -24,7 +24,9 @@
 #include <stdlib.h>
 #include <stdio.h>
 
-const char *atacmdnames_c_cvsid="$Id: atacmdnames.c,v 1.8 2003/07/23 21:35:12 pjwilliams Exp $" ATACMDNAMES_H_CVSID;
+#define COMMAND_TABLE_SIZE 256
+
+const char *atacmdnames_c_cvsid="$Id: atacmdnames.c,v 1.9 2003/08/13 12:33:22 ballen4705 Exp $" ATACMDNAMES_H_CVSID;
 
 const char cmd_reserved[]        = "[RESERVED]";
 const char cmd_vendor_specific[] = "[VENDOR SPECIFIC]";
@@ -34,7 +36,7 @@ const char cmd_reserved_mcpt[]   = "[RESERVED FOR MEDIA CARD PASS THROUGH]";
 const char cmd_recalibrate_ret4[]= "RECALIBRATE [RET-4]";
 const char cmd_seek_ret4[]       = "SEEK [RET-4]";
 
-const char *command_table[256] = {
+const char *command_table[COMMAND_TABLE_SIZE] = {
 /*-------------------------------------------------- 00h-0Fh -----*/
   "NOP",
   cmd_reserved,
@@ -322,11 +324,11 @@ const char *look_up_ata_command(unsigned char c_code, unsigned char f_reg) {
   // check that command table not messed up.  The compiler will issue
   // warnings if there are too many array elements, but won't issue
   // warnings if there are not enough of them.
-  if (sizeof(command_table) != sizeof(char *)*256){
+  if (sizeof(command_table) != sizeof(char *)*COMMAND_TABLE_SIZE){
     fprintf(stderr, 
 	    "Problem in atacmdnames.c.  Command Table command_table[] does\n"
-	    "not have 256 entries!  It has %d entries. Please fix it.\n",
-	    (int)(sizeof(command_table)/sizeof(char *)));
+	    "not have %d entries!  It has %d entries. Please fix it.\n",
+	    COMMAND_TABLE_SIZE, (int)(sizeof(command_table)/sizeof(char *)));
     abort();
   }
 
diff --git a/sm5/atacmdnames.cpp b/sm5/atacmdnames.cpp
index 594f924e0a16999d8f9fb2c3f4f199289620dcbe..8291fc3dc487cf12b6448a09afcfeef705e82d64 100644
--- a/sm5/atacmdnames.cpp
+++ b/sm5/atacmdnames.cpp
@@ -24,7 +24,9 @@
 #include <stdlib.h>
 #include <stdio.h>
 
-const char *atacmdnames_c_cvsid="$Id: atacmdnames.cpp,v 1.8 2003/07/23 21:35:12 pjwilliams Exp $" ATACMDNAMES_H_CVSID;
+#define COMMAND_TABLE_SIZE 256
+
+const char *atacmdnames_c_cvsid="$Id: atacmdnames.cpp,v 1.9 2003/08/13 12:33:22 ballen4705 Exp $" ATACMDNAMES_H_CVSID;
 
 const char cmd_reserved[]        = "[RESERVED]";
 const char cmd_vendor_specific[] = "[VENDOR SPECIFIC]";
@@ -34,7 +36,7 @@ const char cmd_reserved_mcpt[]   = "[RESERVED FOR MEDIA CARD PASS THROUGH]";
 const char cmd_recalibrate_ret4[]= "RECALIBRATE [RET-4]";
 const char cmd_seek_ret4[]       = "SEEK [RET-4]";
 
-const char *command_table[256] = {
+const char *command_table[COMMAND_TABLE_SIZE] = {
 /*-------------------------------------------------- 00h-0Fh -----*/
   "NOP",
   cmd_reserved,
@@ -322,11 +324,11 @@ const char *look_up_ata_command(unsigned char c_code, unsigned char f_reg) {
   // check that command table not messed up.  The compiler will issue
   // warnings if there are too many array elements, but won't issue
   // warnings if there are not enough of them.
-  if (sizeof(command_table) != sizeof(char *)*256){
+  if (sizeof(command_table) != sizeof(char *)*COMMAND_TABLE_SIZE){
     fprintf(stderr, 
 	    "Problem in atacmdnames.c.  Command Table command_table[] does\n"
-	    "not have 256 entries!  It has %d entries. Please fix it.\n",
-	    (int)(sizeof(command_table)/sizeof(char *)));
+	    "not have %d entries!  It has %d entries. Please fix it.\n",
+	    COMMAND_TABLE_SIZE, (int)(sizeof(command_table)/sizeof(char *)));
     abort();
   }
 
diff --git a/sm5/atacmds.c b/sm5/atacmds.c
index 9649e55694dfd8e025b2db10bf8a558d92da882e..2630215ea7bdc87120e268876f30a5266fa5caea 100644
--- a/sm5/atacmds.c
+++ b/sm5/atacmds.c
@@ -33,7 +33,7 @@
 #include "extern.h"
 #include "utility.h"
 
-const char *atacmds_c_cvsid="$Id: atacmds.c,v 1.114 2003/08/05 16:27:43 ballen4705 Exp $" ATACMDS_H_CVSID ESCALADE_H_CVSID EXTERN_H_CVSID UTILITY_H_CVSID;
+const char *atacmds_c_cvsid="$Id: atacmds.c,v 1.115 2003/08/13 12:33:22 ballen4705 Exp $" ATACMDS_H_CVSID ESCALADE_H_CVSID EXTERN_H_CVSID UTILITY_H_CVSID;
 
 // for passing global control variables
 extern smartmonctrl *con;
@@ -172,9 +172,18 @@ const char *vendorattributeargs[] = {
 // This is a utility function for parsing pairs like "9,minutes" or
 // "220,temp", and putting the correct flag into the attributedefs
 // array.  Returns 1 if problem, 0 if pair has been recongized.
-int parse_attribute_def(char *pair, unsigned char *defs){
+int parse_attribute_def(char *pair, unsigned char **defsptr){
   int i,j;
   char temp[32];
+  unsigned char *defs;
+
+  // If array does not exist, allocate it
+  if (!*defsptr && !(*defsptr=(unsigned char *)calloc(MAX_ATTRIBUTE_NUM, 1))){
+    pout("Out of memory in parse_attribute_def\n");
+    exit(1);
+  }
+
+  defs=*defsptr;
 
   // look along list and see if we find the pair
   for (i=0; vendorattributeargs[i] && strcmp(pair, vendorattributeargs[i]); i++);
@@ -198,17 +207,17 @@ int parse_attribute_def(char *pair, unsigned char *defs){
     return 0;
   case 4:
     // print all attributes in raw 8-bit form
-    for (j=0; j<256; j++)
+    for (j=0; j<MAX_ATTRIBUTE_NUM; j++)
       defs[j]=253;
     return 0;
   case 5:
     // print all attributes in raw 16-bit form
-    for (j=0; j<256; j++)
+    for (j=0; j<MAX_ATTRIBUTE_NUM; j++)
       defs[j]=254;
     return 0;
   case 6:
     // print all attributes in raw 48-bit form
-    for (j=0; j<256; j++)
+    for (j=0; j<MAX_ATTRIBUTE_NUM; j++)
       defs[j]=255;
     return 0;
   case 7:
@@ -663,7 +672,7 @@ int smartcommandhandler(int device, smart_command_set command, int select, char
       pout("\n");
   }
   
-  if (getsdata && data==NULL){
+  if (getsdata && !data){
     pout("REPORT-IOCTL: Unable to execute command %s : data destination address is NULL\n", commandstrings[command]);
     return -1;
   }
@@ -1378,6 +1387,7 @@ long long ataPrintSmartAttribRawValue(char *out,
   long long rawvalue;
   unsigned word[3];
   int j;
+  unsigned char select;
   
   // convert the six individual bytes to a long long (8 byte) integer.
   // This is the value that we'll eventually return.
@@ -1400,8 +1410,14 @@ long long ataPrintSmartAttribRawValue(char *out,
     word[j] |= attribute->raw[2*j];
   }
   
+  // if no data array, Attributes have default interpretations
+  if (defs)
+    select=defs[attribute->id];
+  else
+    select=0;
+
   // Print six one-byte quantities.
-  if (defs[attribute->id]==253){
+  if (select==253){
     for (j=0; j<5; j++)
       out+=sprintf(out, "%d ", attribute->raw[5-j]);
     out+=sprintf(out, "%d ", attribute->raw[0]);
@@ -1409,13 +1425,13 @@ long long ataPrintSmartAttribRawValue(char *out,
   } 
   
   // Print three two-byte quantities
-  if (defs[attribute->id]==254){
+  if (select==254){
     out+=sprintf(out, "%d %d %d", word[2], word[1], word[0]); 
     return rawvalue;
   } 
   
   // Print one six-byte quantity
-  if (defs[attribute->id]==255){
+  if (select==255){
     out+=sprintf(out, "%llu", rawvalue);
     return rawvalue;
   }
@@ -1432,20 +1448,20 @@ long long ataPrintSmartAttribRawValue(char *out,
     break;
     // Power on time
   case 9:
-    if (defs[9]==1){
+    if (select==1){
       // minutes
       long long tmp1=rawvalue/60;
       long long tmp2=rawvalue%60;
       out+=sprintf(out, "%lluh+%02llum", tmp1, tmp2);
     }
-    else if (defs[9]==3){
+    else if (select==3){
       // seconds
       long long hours=rawvalue/3600;
       long long minutes=(rawvalue-3600*hours)/60;
       long long seconds=rawvalue%60;
       out+=sprintf(out, "%lluh+%02llum+%02llus", hours, minutes, seconds);
     }
-    else if (defs[9]==4){
+    else if (select==4){
       // 30-second counter
       long long tmp1=rawvalue/120;
       long long tmp2=(rawvalue-120*tmp1)/2;
@@ -1457,7 +1473,7 @@ long long ataPrintSmartAttribRawValue(char *out,
     break;
    // Load unload cycles
   case 193:
-    if (defs[193]==1){
+    if (select==1){
       // loadunload
       long load  =attribute->raw[0] + (attribute->raw[1]<<8) + (attribute->raw[2]<<16);
       long unload=attribute->raw[3] + (attribute->raw[4]<<8) + (attribute->raw[5]<<16);
@@ -1469,13 +1485,13 @@ long long ataPrintSmartAttribRawValue(char *out,
     break;
     // Temperature
   case 194:
-    if (defs[194]==1){
+    if (select==1){
       // ten times temperature in Celsius
       int deg=word[0]/10;
       int tenths=word[0]%10;
       out+=sprintf(out, "%d.%d", deg, tenths);
     }
-    else if (defs[194]==2)
+    else if (select==2)
       // unknown attribute
       out+=sprintf(out, "%llu", rawvalue);
     else {
@@ -1498,8 +1514,16 @@ long long ataPrintSmartAttribRawValue(char *out,
 // manufacturers use different attribute IDs for an attribute with the
 // same name.  The variable val should contain a non-zero value if a particular
 // attributes has a non-default interpretation.
-void ataPrintSmartAttribName(char *out, unsigned char id, unsigned char val){
+void ataPrintSmartAttribName(char *out, unsigned char id, unsigned char *definitions){
   char *name;
+  unsigned char val;
+
+  // If no data array, use default interpretations
+  if (definitions)
+    val=definitions[id];
+  else
+    val=0;
+
   switch (id){
     
   case 1:
diff --git a/sm5/atacmds.cpp b/sm5/atacmds.cpp
index d70e2aa130f63237c932648ab24bd2b926c84b27..31554963121fa2f0972d856a4c57a638ea8ddf7e 100644
--- a/sm5/atacmds.cpp
+++ b/sm5/atacmds.cpp
@@ -33,7 +33,7 @@
 #include "extern.h"
 #include "utility.h"
 
-const char *atacmds_c_cvsid="$Id: atacmds.cpp,v 1.114 2003/08/05 16:27:43 ballen4705 Exp $" ATACMDS_H_CVSID ESCALADE_H_CVSID EXTERN_H_CVSID UTILITY_H_CVSID;
+const char *atacmds_c_cvsid="$Id: atacmds.cpp,v 1.115 2003/08/13 12:33:22 ballen4705 Exp $" ATACMDS_H_CVSID ESCALADE_H_CVSID EXTERN_H_CVSID UTILITY_H_CVSID;
 
 // for passing global control variables
 extern smartmonctrl *con;
@@ -172,9 +172,18 @@ const char *vendorattributeargs[] = {
 // This is a utility function for parsing pairs like "9,minutes" or
 // "220,temp", and putting the correct flag into the attributedefs
 // array.  Returns 1 if problem, 0 if pair has been recongized.
-int parse_attribute_def(char *pair, unsigned char *defs){
+int parse_attribute_def(char *pair, unsigned char **defsptr){
   int i,j;
   char temp[32];
+  unsigned char *defs;
+
+  // If array does not exist, allocate it
+  if (!*defsptr && !(*defsptr=(unsigned char *)calloc(MAX_ATTRIBUTE_NUM, 1))){
+    pout("Out of memory in parse_attribute_def\n");
+    exit(1);
+  }
+
+  defs=*defsptr;
 
   // look along list and see if we find the pair
   for (i=0; vendorattributeargs[i] && strcmp(pair, vendorattributeargs[i]); i++);
@@ -198,17 +207,17 @@ int parse_attribute_def(char *pair, unsigned char *defs){
     return 0;
   case 4:
     // print all attributes in raw 8-bit form
-    for (j=0; j<256; j++)
+    for (j=0; j<MAX_ATTRIBUTE_NUM; j++)
       defs[j]=253;
     return 0;
   case 5:
     // print all attributes in raw 16-bit form
-    for (j=0; j<256; j++)
+    for (j=0; j<MAX_ATTRIBUTE_NUM; j++)
       defs[j]=254;
     return 0;
   case 6:
     // print all attributes in raw 48-bit form
-    for (j=0; j<256; j++)
+    for (j=0; j<MAX_ATTRIBUTE_NUM; j++)
       defs[j]=255;
     return 0;
   case 7:
@@ -663,7 +672,7 @@ int smartcommandhandler(int device, smart_command_set command, int select, char
       pout("\n");
   }
   
-  if (getsdata && data==NULL){
+  if (getsdata && !data){
     pout("REPORT-IOCTL: Unable to execute command %s : data destination address is NULL\n", commandstrings[command]);
     return -1;
   }
@@ -1378,6 +1387,7 @@ long long ataPrintSmartAttribRawValue(char *out,
   long long rawvalue;
   unsigned word[3];
   int j;
+  unsigned char select;
   
   // convert the six individual bytes to a long long (8 byte) integer.
   // This is the value that we'll eventually return.
@@ -1400,8 +1410,14 @@ long long ataPrintSmartAttribRawValue(char *out,
     word[j] |= attribute->raw[2*j];
   }
   
+  // if no data array, Attributes have default interpretations
+  if (defs)
+    select=defs[attribute->id];
+  else
+    select=0;
+
   // Print six one-byte quantities.
-  if (defs[attribute->id]==253){
+  if (select==253){
     for (j=0; j<5; j++)
       out+=sprintf(out, "%d ", attribute->raw[5-j]);
     out+=sprintf(out, "%d ", attribute->raw[0]);
@@ -1409,13 +1425,13 @@ long long ataPrintSmartAttribRawValue(char *out,
   } 
   
   // Print three two-byte quantities
-  if (defs[attribute->id]==254){
+  if (select==254){
     out+=sprintf(out, "%d %d %d", word[2], word[1], word[0]); 
     return rawvalue;
   } 
   
   // Print one six-byte quantity
-  if (defs[attribute->id]==255){
+  if (select==255){
     out+=sprintf(out, "%llu", rawvalue);
     return rawvalue;
   }
@@ -1432,20 +1448,20 @@ long long ataPrintSmartAttribRawValue(char *out,
     break;
     // Power on time
   case 9:
-    if (defs[9]==1){
+    if (select==1){
       // minutes
       long long tmp1=rawvalue/60;
       long long tmp2=rawvalue%60;
       out+=sprintf(out, "%lluh+%02llum", tmp1, tmp2);
     }
-    else if (defs[9]==3){
+    else if (select==3){
       // seconds
       long long hours=rawvalue/3600;
       long long minutes=(rawvalue-3600*hours)/60;
       long long seconds=rawvalue%60;
       out+=sprintf(out, "%lluh+%02llum+%02llus", hours, minutes, seconds);
     }
-    else if (defs[9]==4){
+    else if (select==4){
       // 30-second counter
       long long tmp1=rawvalue/120;
       long long tmp2=(rawvalue-120*tmp1)/2;
@@ -1457,7 +1473,7 @@ long long ataPrintSmartAttribRawValue(char *out,
     break;
    // Load unload cycles
   case 193:
-    if (defs[193]==1){
+    if (select==1){
       // loadunload
       long load  =attribute->raw[0] + (attribute->raw[1]<<8) + (attribute->raw[2]<<16);
       long unload=attribute->raw[3] + (attribute->raw[4]<<8) + (attribute->raw[5]<<16);
@@ -1469,13 +1485,13 @@ long long ataPrintSmartAttribRawValue(char *out,
     break;
     // Temperature
   case 194:
-    if (defs[194]==1){
+    if (select==1){
       // ten times temperature in Celsius
       int deg=word[0]/10;
       int tenths=word[0]%10;
       out+=sprintf(out, "%d.%d", deg, tenths);
     }
-    else if (defs[194]==2)
+    else if (select==2)
       // unknown attribute
       out+=sprintf(out, "%llu", rawvalue);
     else {
@@ -1498,8 +1514,16 @@ long long ataPrintSmartAttribRawValue(char *out,
 // manufacturers use different attribute IDs for an attribute with the
 // same name.  The variable val should contain a non-zero value if a particular
 // attributes has a non-default interpretation.
-void ataPrintSmartAttribName(char *out, unsigned char id, unsigned char val){
+void ataPrintSmartAttribName(char *out, unsigned char id, unsigned char *definitions){
   char *name;
+  unsigned char val;
+
+  // If no data array, use default interpretations
+  if (definitions)
+    val=definitions[id];
+  else
+    val=0;
+
   switch (id){
     
   case 1:
diff --git a/sm5/atacmds.h b/sm5/atacmds.h
index ec0ba2f4b2dd06d59f466e1cec051af30c318ab4..2c742c319f4c7c5df0b627d7a3bff2701555dcc6 100644
--- a/sm5/atacmds.h
+++ b/sm5/atacmds.h
@@ -26,7 +26,7 @@
 #define _ATACMDS_H_
 
 #ifndef ATACMDS_H_CVSID
-#define ATACMDS_H_CVSID "$Id: atacmds.h,v 1.48 2003/08/05 16:27:43 ballen4705 Exp $\n"
+#define ATACMDS_H_CVSID "$Id: atacmds.h,v 1.49 2003/08/13 12:33:23 ballen4705 Exp $\n"
 #endif
 
 #include <sys/ioctl.h>
@@ -437,7 +437,7 @@ long long ataPrintSmartAttribRawValue(char *out,
 
 // Prints Attribute Name for standard SMART attributes. Writes a
 // 30 byte string with attribute name into output
-void ataPrintSmartAttribName(char *output, unsigned char id, unsigned char val);
+void ataPrintSmartAttribName(char *output, unsigned char id, unsigned char *definitions);
 
 // This checks the n'th attribute in the attribute list, NOT the
 // attribute with id==n.  If the attribute does not exist, or the
@@ -455,16 +455,21 @@ int ataCheckAttribute(struct ata_smart_values *data,
 // Structure with the incorrect checksum.
 void checksumwarning(const char *string);
 
+#define MAX_ATTRIBUTE_NUM 256
+
 extern const char *vendorattributeargs[];
 
 // function to parse pairs like "9,minutes" or "220,temp".  See end of
 // extern.h for definition of defs[].  Returns 0 if pair recognized,
-// else 1 if there is a problem.
-int parse_attribute_def(char *pair, unsigned char *defs);
+// else 1 if there is a problem.  Allocates memory for array if the
+// array address is *defs==NULL.
+int parse_attribute_def(char *pair, unsigned char **defs);
 
 // Function to return a string containing a list of the arguments in
 // vendorattributeargs[].  Returns NULL if the required memory can't
 // be allocated.
 char *create_vendor_attribute_arg_list(void);
 
+
+
 #endif /* _ATACMDS_H_ */
diff --git a/sm5/ataprint.c b/sm5/ataprint.c
index 355f7ead76a18e0945b35022ed36809f3df8bae9..70f4bdf609c00af2faf24df928abec7c5f2ca504 100644
--- a/sm5/ataprint.c
+++ b/sm5/ataprint.c
@@ -34,7 +34,7 @@
 #include "utility.h"
 #include "knowndrives.h"
 
-const char *ataprint_c_cvsid="$Id: ataprint.c,v 1.96 2003/07/22 14:08:58 ballen4705 Exp $"
+const char *ataprint_c_cvsid="$Id: ataprint.c,v 1.97 2003/08/13 12:33:23 ballen4705 Exp $"
 ATACMDNAMES_H_CVSID ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID;
 
 // for passing global control variables
@@ -452,7 +452,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values *data,
 	status="    -";
 
       // Print name of attribute
-      ataPrintSmartAttribName(attributename,disk->id, con->attributedefs[disk->id]);
+      ataPrintSmartAttribName(attributename,disk->id, con->attributedefs);
       pout("%-28s",attributename);
 
       // printing line for each valid attribute
@@ -470,8 +470,8 @@ void PrintSmartAttribWithThres (struct ata_smart_values *data,
       // print a warning if there is inconsistency here!
       if (disk->id != thre->id){
 	char atdat[64],atthr[64];
-	ataPrintSmartAttribName(atdat, disk->id, con->attributedefs[disk->id]);
-	ataPrintSmartAttribName(atthr, thre->id, con->attributedefs[thre->id]);
+	ataPrintSmartAttribName(atdat, disk->id, con->attributedefs);
+	ataPrintSmartAttribName(atthr, thre->id, con->attributedefs);
 	pout("%-28s<== Data Page      |  WARNING: PREVIOUS ATTRIBUTE HAS TWO\n",atdat);
 	pout("%-28s<== Threshold Page |  INCONSISTENT IDENTITIES IN THE DATA\n",atthr);
       }
@@ -873,8 +873,15 @@ int ataPrintMain (int fd){
   }
 
   // Use preset vendor attribute options unless user has requested otherwise.
-  if (!con->ignorepresets)
-    applypresets(&drive, con->attributedefs, con);
+  if (!con->ignorepresets){
+    unsigned char *charptr;
+    if ((charptr=con->attributedefs))
+      applypresets(&drive, &charptr, con);
+    else {
+      pout("Fatal internal error in ataPrintMain()\n");
+      exit(1);
+    }
+  }
 
   // Print most drive identity information if requested
   if (con->driveinfo){
diff --git a/sm5/ataprint.cpp b/sm5/ataprint.cpp
index c1b78852352aeab9a385aa4ca3de188ca22562b0..0e1b222c0faed71701a8611a47a01fc3a900be7b 100644
--- a/sm5/ataprint.cpp
+++ b/sm5/ataprint.cpp
@@ -34,7 +34,7 @@
 #include "utility.h"
 #include "knowndrives.h"
 
-const char *ataprint_c_cvsid="$Id: ataprint.cpp,v 1.96 2003/07/22 14:08:58 ballen4705 Exp $"
+const char *ataprint_c_cvsid="$Id: ataprint.cpp,v 1.97 2003/08/13 12:33:23 ballen4705 Exp $"
 ATACMDNAMES_H_CVSID ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID;
 
 // for passing global control variables
@@ -452,7 +452,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values *data,
 	status="    -";
 
       // Print name of attribute
-      ataPrintSmartAttribName(attributename,disk->id, con->attributedefs[disk->id]);
+      ataPrintSmartAttribName(attributename,disk->id, con->attributedefs);
       pout("%-28s",attributename);
 
       // printing line for each valid attribute
@@ -470,8 +470,8 @@ void PrintSmartAttribWithThres (struct ata_smart_values *data,
       // print a warning if there is inconsistency here!
       if (disk->id != thre->id){
 	char atdat[64],atthr[64];
-	ataPrintSmartAttribName(atdat, disk->id, con->attributedefs[disk->id]);
-	ataPrintSmartAttribName(atthr, thre->id, con->attributedefs[thre->id]);
+	ataPrintSmartAttribName(atdat, disk->id, con->attributedefs);
+	ataPrintSmartAttribName(atthr, thre->id, con->attributedefs);
 	pout("%-28s<== Data Page      |  WARNING: PREVIOUS ATTRIBUTE HAS TWO\n",atdat);
 	pout("%-28s<== Threshold Page |  INCONSISTENT IDENTITIES IN THE DATA\n",atthr);
       }
@@ -873,8 +873,15 @@ int ataPrintMain (int fd){
   }
 
   // Use preset vendor attribute options unless user has requested otherwise.
-  if (!con->ignorepresets)
-    applypresets(&drive, con->attributedefs, con);
+  if (!con->ignorepresets){
+    unsigned char *charptr;
+    if ((charptr=con->attributedefs))
+      applypresets(&drive, &charptr, con);
+    else {
+      pout("Fatal internal error in ataPrintMain()\n");
+      exit(1);
+    }
+  }
 
   // Print most drive identity information if requested
   if (con->driveinfo){
diff --git a/sm5/knowndrives.c b/sm5/knowndrives.c
index 84fdb7d6d07dd5988aee7dc882c270fc14e38d03..63693d9758fedbe3af16b8b973ac8b2d6120be30 100644
--- a/sm5/knowndrives.c
+++ b/sm5/knowndrives.c
@@ -24,7 +24,7 @@
 #include "knowndrives.h"
 #include "utility.h"
 
-const char *knowndrives_c_cvsid="$Id: knowndrives.c,v 1.35 2003/08/11 13:25:20 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID KNOWNDRIVES_H_CVSID UTILITY_H_CVSID;
+const char *knowndrives_c_cvsid="$Id: knowndrives.c,v 1.36 2003/08/13 12:33:23 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID KNOWNDRIVES_H_CVSID UTILITY_H_CVSID;
 
 #define MODEL_STRING_LENGTH                         40
 #define FIRMWARE_STRING_LENGTH                       8
@@ -89,6 +89,8 @@ const unsigned char vendoropts_Hitachi_DK23EA[][2] = {
   {0,0}
 };
 
+const char same_as_minus_F[]="Fixes byte order in some SMART data (same as -F samsung)";
+const char may_need_minus_F_disabled[]="Contact developers; may need -F samsung disabled";
 
 /* Special-purpose functions for use in knowndrives[]. */
 void specialpurpose_reverse_samsung(smartmonctrl *con)
@@ -148,15 +150,15 @@ const drivesettings knowndrives[] = {
     NULL,
     vendoropts_Samsung_SV4012H,
     specialpurpose_reverse_samsung,
-    "Fixes byte order in some SMART data (same as -F)"
+    same_as_minus_F
   },
   { // Samsung SV4012H (all other firmware)
     "^SAMSUNG SV4012H$",
     ".*",
-    "Contact developers; may need -F disabled",
+    may_need_minus_F_disabled,
     vendoropts_Samsung_SV4012H,
     specialpurpose_reverse_samsung,
-    "Fixes byte order in some SMART data (same as -F)"
+    same_as_minus_F
   },
   { // Samsung SV1204H (known firmware)
     "^SAMSUNG SV1204H$",
@@ -164,15 +166,15 @@ const drivesettings knowndrives[] = {
     NULL,
     vendoropts_Samsung_SV1204H,
     specialpurpose_reverse_samsung,
-    "Fixes byte order in some SMART data (same as -F)"
+    same_as_minus_F
   },
   { //Samsung SV1204H (all other firmware)
     "^SAMSUNG SV1204H$",
     ".*",
-    "Contact developers; may need -F disabled",
+    may_need_minus_F_disabled,
     vendoropts_Samsung_SV1204H,
     specialpurpose_reverse_samsung,
-    "Fixes byte order in some SMART data (same as -F)"
+    same_as_minus_F
   },
   { // Samsung SV0412H (known firmware)
     "^SAMSUNG SV0412H$",
@@ -180,15 +182,15 @@ const drivesettings knowndrives[] = {
     NULL,
     vendoropts_Samsung_SV1204H,
     specialpurpose_reverse_samsung,
-    "Fixes byte order in some SMART data (same as -F)"
+    same_as_minus_F
   },
   { // Samsung SV0412H (all other firmware)
     "^SAMSUNG SV0412H$",
     ".*",
-    "Contact developers; may need -F disabled",
+    may_need_minus_F_disabled,
     vendoropts_Samsung_SV1204H,
     specialpurpose_reverse_samsung,
-    "Fixes byte order in some SMART data (same as -F)"
+    same_as_minus_F
   },
   { //Samsung SP1604N, tested with FW TM100-23
     "^SAMSUNG SP1604N$",
@@ -205,20 +207,10 @@ const drivesettings knowndrives[] = {
     NULL,
     NULL
   },
-
-
-
-
-
-
-
-
-
-
   { // Samsung ALL OTHER DRIVES
     "^SAMSUNG.*",
     ".*",
-    "Contact developers; may need -F enabled.\n",
+    "Contact developers; may need -F samsung enabled.\n",
     NULL, NULL, NULL
   },
   { // Maxtor 6L080J4 and 4K080H4
@@ -361,12 +353,17 @@ void showonepreset(const drivesettings *drivetable){
   if (presets && (*presets)[0]) while (1) {
     char out[64];
     const int attr = (*presets)[0], val  = (*presets)[1];
-    
+    unsigned char fakearray[MAX_ATTRIBUTE_NUM];
+
     // if we are at the end of the attribute list, break out
     if (!attr)  
       break;
     
-    ataPrintSmartAttribName(out, attr, val);
+    // This is a hack. ataPrintSmartAttribName() needs a pointer to an
+    // "array" to dereference, so we provide such a pointer.
+    fakearray[attr]=val;
+    ataPrintSmartAttribName(out, attr, fakearray);
+
     // Use leading zeros instead of spaces so that everything lines up.
     out[0] = (out[0] == ' ') ? '0' : out[0];
     out[1] = (out[1] == ' ') ? '0' : out[1];
@@ -442,11 +439,19 @@ void showpresets(const struct hd_driveid *drive){
 // (if any) for the given drive in knowndrives[].  Values that have
 // already been set in opts will not be changed.  Returns <0 if drive
 // not recognized else index >=0 into drive database.
-int applypresets(const struct hd_driveid *drive, unsigned char opts[256],
+int applypresets(const struct hd_driveid *drive, unsigned char **optsptr,
                   smartmonctrl *con) {
   int i;
+  unsigned char *opts;
   char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1];
   
+  if (*optsptr==NULL && !(*optsptr=(unsigned char *)calloc(MAX_ATTRIBUTE_NUM,1))){
+    pout("Unable to allocate memory in applypresets()");
+    exit(1);
+  }
+
+  opts=*optsptr;
+
   // get the drive's model/firmware strings
   formatdriveidstring(model, drive->model, MODEL_STRING_LENGTH);
   formatdriveidstring(firmware, drive->fw_rev, FIRMWARE_STRING_LENGTH);
diff --git a/sm5/knowndrives.cpp b/sm5/knowndrives.cpp
index baf6ee05fffdab2c34a3f82427dc4ce30f01d82b..84016614e2a83c9da0480caf0c44b896dcce50c2 100644
--- a/sm5/knowndrives.cpp
+++ b/sm5/knowndrives.cpp
@@ -24,7 +24,7 @@
 #include "knowndrives.h"
 #include "utility.h"
 
-const char *knowndrives_c_cvsid="$Id: knowndrives.cpp,v 1.35 2003/08/11 13:25:20 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID KNOWNDRIVES_H_CVSID UTILITY_H_CVSID;
+const char *knowndrives_c_cvsid="$Id: knowndrives.cpp,v 1.36 2003/08/13 12:33:23 ballen4705 Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID KNOWNDRIVES_H_CVSID UTILITY_H_CVSID;
 
 #define MODEL_STRING_LENGTH                         40
 #define FIRMWARE_STRING_LENGTH                       8
@@ -89,6 +89,8 @@ const unsigned char vendoropts_Hitachi_DK23EA[][2] = {
   {0,0}
 };
 
+const char same_as_minus_F[]="Fixes byte order in some SMART data (same as -F samsung)";
+const char may_need_minus_F_disabled[]="Contact developers; may need -F samsung disabled";
 
 /* Special-purpose functions for use in knowndrives[]. */
 void specialpurpose_reverse_samsung(smartmonctrl *con)
@@ -148,15 +150,15 @@ const drivesettings knowndrives[] = {
     NULL,
     vendoropts_Samsung_SV4012H,
     specialpurpose_reverse_samsung,
-    "Fixes byte order in some SMART data (same as -F)"
+    same_as_minus_F
   },
   { // Samsung SV4012H (all other firmware)
     "^SAMSUNG SV4012H$",
     ".*",
-    "Contact developers; may need -F disabled",
+    may_need_minus_F_disabled,
     vendoropts_Samsung_SV4012H,
     specialpurpose_reverse_samsung,
-    "Fixes byte order in some SMART data (same as -F)"
+    same_as_minus_F
   },
   { // Samsung SV1204H (known firmware)
     "^SAMSUNG SV1204H$",
@@ -164,15 +166,15 @@ const drivesettings knowndrives[] = {
     NULL,
     vendoropts_Samsung_SV1204H,
     specialpurpose_reverse_samsung,
-    "Fixes byte order in some SMART data (same as -F)"
+    same_as_minus_F
   },
   { //Samsung SV1204H (all other firmware)
     "^SAMSUNG SV1204H$",
     ".*",
-    "Contact developers; may need -F disabled",
+    may_need_minus_F_disabled,
     vendoropts_Samsung_SV1204H,
     specialpurpose_reverse_samsung,
-    "Fixes byte order in some SMART data (same as -F)"
+    same_as_minus_F
   },
   { // Samsung SV0412H (known firmware)
     "^SAMSUNG SV0412H$",
@@ -180,15 +182,15 @@ const drivesettings knowndrives[] = {
     NULL,
     vendoropts_Samsung_SV1204H,
     specialpurpose_reverse_samsung,
-    "Fixes byte order in some SMART data (same as -F)"
+    same_as_minus_F
   },
   { // Samsung SV0412H (all other firmware)
     "^SAMSUNG SV0412H$",
     ".*",
-    "Contact developers; may need -F disabled",
+    may_need_minus_F_disabled,
     vendoropts_Samsung_SV1204H,
     specialpurpose_reverse_samsung,
-    "Fixes byte order in some SMART data (same as -F)"
+    same_as_minus_F
   },
   { //Samsung SP1604N, tested with FW TM100-23
     "^SAMSUNG SP1604N$",
@@ -205,20 +207,10 @@ const drivesettings knowndrives[] = {
     NULL,
     NULL
   },
-
-
-
-
-
-
-
-
-
-
   { // Samsung ALL OTHER DRIVES
     "^SAMSUNG.*",
     ".*",
-    "Contact developers; may need -F enabled.\n",
+    "Contact developers; may need -F samsung enabled.\n",
     NULL, NULL, NULL
   },
   { // Maxtor 6L080J4 and 4K080H4
@@ -361,12 +353,17 @@ void showonepreset(const drivesettings *drivetable){
   if (presets && (*presets)[0]) while (1) {
     char out[64];
     const int attr = (*presets)[0], val  = (*presets)[1];
-    
+    unsigned char fakearray[MAX_ATTRIBUTE_NUM];
+
     // if we are at the end of the attribute list, break out
     if (!attr)  
       break;
     
-    ataPrintSmartAttribName(out, attr, val);
+    // This is a hack. ataPrintSmartAttribName() needs a pointer to an
+    // "array" to dereference, so we provide such a pointer.
+    fakearray[attr]=val;
+    ataPrintSmartAttribName(out, attr, fakearray);
+
     // Use leading zeros instead of spaces so that everything lines up.
     out[0] = (out[0] == ' ') ? '0' : out[0];
     out[1] = (out[1] == ' ') ? '0' : out[1];
@@ -442,11 +439,19 @@ void showpresets(const struct hd_driveid *drive){
 // (if any) for the given drive in knowndrives[].  Values that have
 // already been set in opts will not be changed.  Returns <0 if drive
 // not recognized else index >=0 into drive database.
-int applypresets(const struct hd_driveid *drive, unsigned char opts[256],
+int applypresets(const struct hd_driveid *drive, unsigned char **optsptr,
                   smartmonctrl *con) {
   int i;
+  unsigned char *opts;
   char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1];
   
+  if (*optsptr==NULL && !(*optsptr=(unsigned char *)calloc(MAX_ATTRIBUTE_NUM,1))){
+    pout("Unable to allocate memory in applypresets()");
+    exit(1);
+  }
+
+  opts=*optsptr;
+
   // get the drive's model/firmware strings
   formatdriveidstring(model, drive->model, MODEL_STRING_LENGTH);
   formatdriveidstring(firmware, drive->fw_rev, FIRMWARE_STRING_LENGTH);
diff --git a/sm5/knowndrives.h b/sm5/knowndrives.h
index afeeb2565f57b820c4cac1fc5c1768bad30b47b8..01e18c9248cbed012d1b6d43189fa6b750c46331 100644
--- a/sm5/knowndrives.h
+++ b/sm5/knowndrives.h
@@ -20,7 +20,7 @@
 #ifndef __KNOWNDRIVES_H_
 #define __KNOWNDRIVES_H_
 
-#define KNOWNDRIVES_H_CVSID "$Id: knowndrives.h,v 1.6 2003/04/20 15:38:38 ballen4705 Exp $\n"
+#define KNOWNDRIVES_H_CVSID "$Id: knowndrives.h,v 1.7 2003/08/13 12:33:23 ballen4705 Exp $\n"
 
 #include <linux/hdreg.h>
 #include "extern.h"
@@ -76,7 +76,7 @@ void showallpresets(void);
 // already been set in opts will not be changed.  Also sets options in
 // con.  Returns <0 if drive not recognized else index of drive in
 // database.
-int applypresets(const struct hd_driveid *drive, unsigned char opts[256],
+int applypresets(const struct hd_driveid *drive, unsigned char **opts,
                   smartmonctrl *con);
 
 #endif
diff --git a/sm5/smartctl.c b/sm5/smartctl.c
index 3eca064e3a2c31391424af184357c501ba7933a3..a0ccde35f84e33075d4c136d75cb815a5e72bc0d 100644
--- a/sm5/smartctl.c
+++ b/sm5/smartctl.c
@@ -43,7 +43,7 @@
 #include "utility.h"
 
 extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *escalade_c_cvsid, *knowndrives_c_cvsid, *scsicmds_c_cvsid, *scsiprint_c_cvsid, *utility_c_cvsid; 
-const char* smartctl_c_cvsid="$Id: smartctl.c,v 1.84 2003/08/12 03:50:06 ballen4705 Exp $"
+const char* smartctl_c_cvsid="$Id: smartctl.c,v 1.85 2003/08/13 12:33:23 ballen4705 Exp $"
 ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SCSIPRINT_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID;
 
 // This is a block containing all the "control variables".  We declare
@@ -237,11 +237,8 @@ void Usage (void){
 }
 
 /* Returns a pointer to a static string containing a formatted list of the valid
-   arguments to the option opt or NULL on failure. */
+   arguments to the option opt or NULL on failure. Note 'v' case different */
 const char *getvalidarglist(char opt) {
-  static char *v_list = NULL;
-  char *s;
-
   switch (opt) {
   case 'q':
     return "errorsonly, silent";
@@ -259,16 +256,6 @@ const char *getvalidarglist(char opt) {
     return "on, off";
   case 'l':
     return "error, selftest, directory";
-  case 'v':
-    if (v_list) 
-      return v_list;
-    if (!(s = create_vendor_attribute_arg_list()))
-      return NULL;
-    // Allocate space for tab + "help" + newline + s + terminating 0
-    v_list = (char *)malloc(7+strlen(s));
-    sprintf(v_list, "\thelp\n%s", s);
-    free(s);
-    return v_list;
   case 'P':
     return "use, ignore, show, showall";
   case 't':
@@ -279,6 +266,7 @@ const char *getvalidarglist(char opt) {
 #endif
   case 'F':
     return "none, samsung";
+  case 'v':
   default:
     return NULL;
   }
@@ -287,22 +275,33 @@ const char *getvalidarglist(char opt) {
 /* Prints the message "=======> VALID ARGUMENTS ARE: <LIST>  <=======\n", where
    <LIST> is the list of valid arguments for option opt. */
 void printvalidarglistmessage(char opt) {
-  const char *s;
-  char separator;
-
-  if (!(s = getvalidarglist(opt))) {
+  char *s;
+  
+  if (opt=='v')
+    s=create_vendor_attribute_arg_list();
+  else
+    s=(char *)getvalidarglist(opt);
+  
+  if (!s) {
     pout("Error whilst constructing argument list for option %c", opt);
     return;
   }
-
+ 
+  if (opt=='v'){
+    pout("=======> VALID ARGUMENTS ARE:\n\thelp\n%s\n<=======\n", s);
+    free(s);
+  }
+  else {
   // getvalidarglist() might produce a multiline or single line string.  We
   // need to figure out which to get the formatting right.
-  separator = strchr(s, '\n') ? '\n' : ' ';
+    char separator = strchr(s, '\n') ? '\n' : ' ';
+    pout("=======> VALID ARGUMENTS ARE:%c%s%c<=======\n", separator, (char *)s, separator);
+  }
 
-  pout("=======> VALID ARGUMENTS ARE:%c%s%c<=======\n", separator, (char *)s,
-    separator);
+  return;
 }
 
+
 unsigned char tryata=0,tryscsi=0;
 
 /*      Takes command options and sets features to be run */	
@@ -310,6 +309,7 @@ void ParseOpts (int argc, char** argv){
   int optchar;
   int badarg;
   int captive;
+  unsigned char *charp;
   extern char *optarg;
   extern int optopt, optind, opterr;
   // Please update getvalidarglist() if you edit shortopts
@@ -556,7 +556,12 @@ void ParseOpts (int argc, char** argv){
         free(s);
         exit(0);
       }
-      if (parse_attribute_def(optarg, con->attributedefs))
+      charp=con->attributedefs;
+      if (!charp){
+	pout("Fatal internal error in ParseOpts()\n");
+	exit(FAILCMD);
+      }
+      if (parse_attribute_def(optarg, &charp))
 	badarg = TRUE;
       break;    
     case 'P':
diff --git a/sm5/smartctl.cpp b/sm5/smartctl.cpp
index bc42dec6af8cdbd23e17a6088cc92c162ef83f71..6089fd7286105873433bdafcbce5dbe8957e7a42 100644
--- a/sm5/smartctl.cpp
+++ b/sm5/smartctl.cpp
@@ -43,7 +43,7 @@
 #include "utility.h"
 
 extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *escalade_c_cvsid, *knowndrives_c_cvsid, *scsicmds_c_cvsid, *scsiprint_c_cvsid, *utility_c_cvsid; 
-const char* smartctl_c_cvsid="$Id: smartctl.cpp,v 1.84 2003/08/12 03:50:06 ballen4705 Exp $"
+const char* smartctl_c_cvsid="$Id: smartctl.cpp,v 1.85 2003/08/13 12:33:23 ballen4705 Exp $"
 ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SCSIPRINT_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID;
 
 // This is a block containing all the "control variables".  We declare
@@ -237,11 +237,8 @@ void Usage (void){
 }
 
 /* Returns a pointer to a static string containing a formatted list of the valid
-   arguments to the option opt or NULL on failure. */
+   arguments to the option opt or NULL on failure. Note 'v' case different */
 const char *getvalidarglist(char opt) {
-  static char *v_list = NULL;
-  char *s;
-
   switch (opt) {
   case 'q':
     return "errorsonly, silent";
@@ -259,16 +256,6 @@ const char *getvalidarglist(char opt) {
     return "on, off";
   case 'l':
     return "error, selftest, directory";
-  case 'v':
-    if (v_list) 
-      return v_list;
-    if (!(s = create_vendor_attribute_arg_list()))
-      return NULL;
-    // Allocate space for tab + "help" + newline + s + terminating 0
-    v_list = (char *)malloc(7+strlen(s));
-    sprintf(v_list, "\thelp\n%s", s);
-    free(s);
-    return v_list;
   case 'P':
     return "use, ignore, show, showall";
   case 't':
@@ -279,6 +266,7 @@ const char *getvalidarglist(char opt) {
 #endif
   case 'F':
     return "none, samsung";
+  case 'v':
   default:
     return NULL;
   }
@@ -287,22 +275,33 @@ const char *getvalidarglist(char opt) {
 /* Prints the message "=======> VALID ARGUMENTS ARE: <LIST>  <=======\n", where
    <LIST> is the list of valid arguments for option opt. */
 void printvalidarglistmessage(char opt) {
-  const char *s;
-  char separator;
-
-  if (!(s = getvalidarglist(opt))) {
+  char *s;
+  
+  if (opt=='v')
+    s=create_vendor_attribute_arg_list();
+  else
+    s=(char *)getvalidarglist(opt);
+  
+  if (!s) {
     pout("Error whilst constructing argument list for option %c", opt);
     return;
   }
-
+ 
+  if (opt=='v'){
+    pout("=======> VALID ARGUMENTS ARE:\n\thelp\n%s\n<=======\n", s);
+    free(s);
+  }
+  else {
   // getvalidarglist() might produce a multiline or single line string.  We
   // need to figure out which to get the formatting right.
-  separator = strchr(s, '\n') ? '\n' : ' ';
+    char separator = strchr(s, '\n') ? '\n' : ' ';
+    pout("=======> VALID ARGUMENTS ARE:%c%s%c<=======\n", separator, (char *)s, separator);
+  }
 
-  pout("=======> VALID ARGUMENTS ARE:%c%s%c<=======\n", separator, (char *)s,
-    separator);
+  return;
 }
 
+
 unsigned char tryata=0,tryscsi=0;
 
 /*      Takes command options and sets features to be run */	
@@ -310,6 +309,7 @@ void ParseOpts (int argc, char** argv){
   int optchar;
   int badarg;
   int captive;
+  unsigned char *charp;
   extern char *optarg;
   extern int optopt, optind, opterr;
   // Please update getvalidarglist() if you edit shortopts
@@ -556,7 +556,12 @@ void ParseOpts (int argc, char** argv){
         free(s);
         exit(0);
       }
-      if (parse_attribute_def(optarg, con->attributedefs))
+      charp=con->attributedefs;
+      if (!charp){
+	pout("Fatal internal error in ParseOpts()\n");
+	exit(FAILCMD);
+      }
+      if (parse_attribute_def(optarg, &charp))
 	badarg = TRUE;
       break;    
     case 'P':
diff --git a/sm5/smartd.8 b/sm5/smartd.8
index 28e16963385420dc420bd5f983637b54069d2a86..fe3c1e507d9cec6949216719285f691f08696958 100644
--- a/sm5/smartd.8
+++ b/sm5/smartd.8
@@ -1,6 +1,6 @@
 \# Copyright (C) 2002-3 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 \# 
-\# $Id: smartd.8,v 1.104 2003/08/07 09:58:02 ballen4705 Exp $
+\# $Id: smartd.8,v 1.105 2003/08/13 12:33:23 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
@@ -16,7 +16,7 @@
 \# Research Center), Jack Baskin School of Engineering, University of
 \# California, Santa Cruz. http://ssrc.soe.ucsc.edu/
 \#
-.TH SMARTD 8  "$Date: 2003/08/07 09:58:02 $" "smartmontools-5.1"
+.TH SMARTD 8  "$Date: 2003/08/13 12:33:23 $" "smartmontools-5.1"
 .SH NAME
 smartd \- SMART Disk Monitoring Daemon
 .SH SYNOPSIS
@@ -105,10 +105,10 @@ to see the available options.
 .B \-d, \-\-debug
 Runs 
 .B smartd 
-in ""debug"" mode. In this mode, it does not 
-.B fork
-(2) and displays status information to STDOUT.  It also prints more
-verbose information about what it is doing.
+in \(dqdebug\(dq mode. In this mode, it displays status information to
+STDOUT rather than logging it in SYSLOG and does not \fBfork(2)\fP.
+It also prints more verbose information about what it is doing than
+when operating in \(dqdaemon\(dq mode.
 .TP
 .B \-D, \-\-showdirectives
 Prints a list (to STDOUT) of all the possible Directives which may
@@ -152,7 +152,7 @@ containing the
 Process ID number (PID).
 To avoid symlink attacks make sure the directory to which
 pidfile is written is only writeable for root.  Without this option,
-or if the --debug option is given, no PID file is written on startup.
+or if the \-\-debug option is given, no PID file is written on startup.
 If
 .B smartd
 is killed with a maskable signal then the pidfile is removed.
@@ -576,9 +576,9 @@ command-line option.]
 .B \-f
 Check for 'failure' of any Usage Attributes.  If these
 Attributes are less than or equal to the threshold, it does NOT
-indicate imminent disk failure.  It ""indicates an advisory condition
+indicate imminent disk failure.  It \(dqindicates an advisory condition
 where the usage or age of the device has exceeded its intended design
-life period."" [Please see the
+life period.\(dq [Please see the
 .B smartctl \-A
 command-line option.]
 
@@ -1322,4 +1322,4 @@ smartmontools home page at \fBhttp://smartmontools.sourceforge.net/\fP .
 
 .SH
 CVS ID OF THIS PAGE:
-$Id: smartd.8,v 1.104 2003/08/07 09:58:02 ballen4705 Exp $
+$Id: smartd.8,v 1.105 2003/08/13 12:33:23 ballen4705 Exp $
diff --git a/sm5/smartd.c b/sm5/smartd.c
index 3bca96ba9800ed8ed3d85e8dc22362621a95b1fc..1cc878c1e63ad7c82f1c95d25e26133daf5c4e0d 100644
--- a/sm5/smartd.c
+++ b/sm5/smartd.c
@@ -50,7 +50,7 @@
 #include "utility.h"
 
 extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *escalade_c_cvsid, *knowndrives_c_cvsid, *scsicmds_c_cvsid, *utility_c_cvsid;
-const char *smartd_c_cvsid="$Id: smartd.c,v 1.188 2003/08/11 20:43:05 ballen4705 Exp $" 
+const char *smartd_c_cvsid="$Id: smartd.c,v 1.189 2003/08/13 12:33:23 ballen4705 Exp $" 
 ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SMARTD_H_CVSID UTILITY_H_CVSID; 
 
 // Forward declarations
@@ -339,7 +339,7 @@ void pout(char *fmt, ...){
 
 // tell user that we ignore HUP signals
 void huphandler(int sig){
-  printout(LOG_CRIT,"HUP ignored: smartd does NOT re-read /etc/smartd.conf.\n");
+  printout(LOG_INFO,"HUP ignored: smartd does NOT re-read /etc/smartd.conf.\n");
   return;
 }
 
@@ -619,8 +619,9 @@ int atadevicescan(cfgfile *cfg){
   // options unless user has requested otherwise.
   if (!cfg->ignorepresets){
 
-    // do whatever applypresets decides to do
-    if (applypresets(&drive, cfg->attributedefs, con)<0)
+    // do whatever applypresets decides to do. Will allocate memory if
+    // cfg->attributedefs if needed.
+    if (applypresets(&drive, &cfg->attributedefs, con)<0)
       printout(LOG_INFO, "Device: %s, not found in smartd database.\n", name);
     else
       printout(LOG_INFO, "Device: %s, found in smartd database.\n", name);
@@ -886,8 +887,8 @@ static int scsidevicescan(cfgfile *cfg)
     cfg->tryscsi = 1;
 
     // get rid of allocated memory only needed for ATA devices
-    cfg->monitorattflags = checkfree(cfg->monitorattflags);
-    cfg->attributedefs   = checkfree(cfg->attributedefs);
+    cfg->monitorattflags = freenonzero(cfg->monitorattflags);
+    cfg->attributedefs   = freenonzero(cfg->attributedefs);
     cfg->smartval        = freenonzero(cfg->smartval);
     cfg->smartthres      = freenonzero(cfg->smartthres);
 
@@ -960,12 +961,31 @@ int  ataCompareSmartValues(changedattribute_t *delta,
 // sorting functions! Entry is ZERO <==> the attribute ON. Calling
 // with set=0 tells you if the attribute is being tracked or not.
 // Calling with set=1 turns the attribute OFF.
-int isattoff(unsigned char attr,unsigned char *data, int set){
-  // locate correct attribute
+int isattoff(unsigned char attr, unsigned char **datap, int set, int which){
+  unsigned char *data;
   int loc=attr>>3;
   int bit=attr & 0x07;
   unsigned char mask=0x01<<bit;
 
+  if (which>=NMONITOR){
+    printout(LOG_CRIT, "Internal error in isattoff().  which == %d\n", which);
+    exit(EXIT_NOMEM);
+  }
+
+  if (*datap == NULL){
+    // null data implies Attributes are off...
+    if (!set)
+      return 1;
+    
+    // we are writing
+    if (!(*datap=calloc(NMONITOR*32, 1))){
+      printout(LOG_CRIT,"No memory to create monattflags\n");
+      exit(EXIT_NOMEM);
+    }
+  }
+  
+  data=*datap+which*32;
+
   // attribute zero is always OFF
   if (!attr)
     return 1;
@@ -1037,11 +1057,11 @@ int ataCheckDevice(cfgfile *cfg){
           
           // are we ignoring failures of this attribute?
           att *= -1;
-          if (!isattoff(att, cfg->monitorattflags, 0)){
+          if (!isattoff(att, &cfg->monitorattflags, 0, MONITOR_FAILUSE)){
             char attname[64], *loc=attname;
             
             // get attribute name & skip white space
-            ataPrintSmartAttribName(loc, att, cfg->attributedefs[att]);
+            ataPrintSmartAttribName(loc, att, cfg->attributedefs);
             while (*loc && *loc==' ') loc++;
             
             // warning message
@@ -1058,19 +1078,19 @@ int ataCheckDevice(cfgfile *cfg){
 
           // if the only change is the raw value, and we're not
           // tracking raw value, then continue loop over attributes
-          if (!delta.sameraw && delta.newval==delta.oldval && !isattoff(id, cfg->monitorattflags+96, 0))
+          if (!delta.sameraw && delta.newval==delta.oldval && !isattoff(id, &cfg->monitorattflags, 0, MONITOR_RAW))
             continue;
 
           // are we tracking this attribute?
-          if (!isattoff(id, cfg->monitorattflags+32, 0)){
+          if (!isattoff(id, &cfg->monitorattflags, 0, MONITOR_IGNORE)){
             char newrawstring[64], oldrawstring[64], attname[64], *loc=attname;
 
             // get attribute name, skip spaces
-            ataPrintSmartAttribName(loc, id, cfg->attributedefs[id]);
+            ataPrintSmartAttribName(loc, id, cfg->attributedefs);
             while (*loc && *loc==' ') loc++;
             
             // has the user asked for us to print raw values?
-            if (isattoff(id, cfg->monitorattflags+64, 0)) {
+            if (isattoff(id, &cfg->monitorattflags, 0, MONITOR_RAWPRINT)) {
               // get raw values (as a string) and add to printout
               char rawstring[64];
               ataPrintSmartAttribRawValue(rawstring, curval.vendor_attributes+i, cfg->attributedefs);
@@ -1587,23 +1607,23 @@ int parsetoken(char *token,cfgfile *cfg){
   case 'i':
     // ignore failure of usage attribute
     val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255);
-    isattoff(val,cfg->monitorattflags,1);
+    isattoff(val, &cfg->monitorattflags, 1, MONITOR_FAILUSE);
     break;
   case 'I':
     // ignore attribute for tracking purposes
     val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255);
-    isattoff(val,cfg->monitorattflags+32,1);
+    isattoff(val, &cfg->monitorattflags, 1, MONITOR_IGNORE);
     break;
   case 'r':
     // print raw value when tracking
     val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255);
-    isattoff(val,cfg->monitorattflags+64,1);
+    isattoff(val, &cfg->monitorattflags, 1, MONITOR_RAWPRINT);
     break;
   case 'R':
     // track changes in raw value (forces printing of raw value)
     val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255);
-    isattoff(val,cfg->monitorattflags+64,1);
-    isattoff(val,cfg->monitorattflags+96,1);
+    isattoff(val, &cfg->monitorattflags, 1, MONITOR_RAWPRINT);
+    isattoff(val, &cfg->monitorattflags, 1, MONITOR_RAW);
     break;
   case 'm':
     // send email to address that follows
@@ -1624,7 +1644,7 @@ int parsetoken(char *token,cfgfile *cfg){
     // non-default vendor-specific attribute meaning
     if ((arg=strtok(NULL,delim)) == NULL) {
       missingarg = 1;
-    } else if (parse_attribute_def(arg, cfg->attributedefs)){   
+    } else if (parse_attribute_def(arg, &cfg->attributedefs)){   
       badarg = 1;
     }
     break;
@@ -1685,19 +1705,20 @@ cfgfile *createcfgentry(cfgfile *original){
   // if structure had data, copy it
   if (original)
     memcpy(add, original, sizeof(cfgfile));
-
-  // Always make this storage
-  if (
-      !(add->monitorattflags=(unsigned char *)calloc(NMONITOR*32,1)) ||
-      !(add->attributedefs=(unsigned char *)calloc(256,1))
-      ) goto badexit;
-
-  if (original){
-      memcpy(add->attributedefs,   original->attributedefs,   256);
-      memcpy(add->monitorattflags, original->monitorattflags, NMONITOR*32);
+  
+  // make private copies of these ONLY if they are in use
+  if (add->attributedefs) {
+    if (!(add->attributedefs=(unsigned char *)calloc(MAX_ATTRIBUTE_NUM,1)))
+      goto badexit;
+    memcpy(add->attributedefs, original->attributedefs, MAX_ATTRIBUTE_NUM);
+  }
+  
+  if (add->monitorattflags) {
+    if (!(add->monitorattflags=(unsigned char *)calloc(NMONITOR*32, 1)))
+      goto badexit;
+    memcpy(add->monitorattflags, original->monitorattflags, NMONITOR*32);
   }
   
-  // make private copies of these ONLY if they are used
   if (add->name &&
       !(add->name=strdup(add->name))
       ) goto badexit;
@@ -1727,19 +1748,19 @@ cfgfile *createcfgentry(cfgfile *original){
 
 // Removes config file entry, freeing all memory
 cfgfile *rmconfigentry(cfgfile *original){
-
+  
   if (!original){
     printout(LOG_CRIT,"Error - rmconfigentry() called with NULL pointer argument\n");
     exit(EXIT_NOMEM);
   }
-
-  freenonzero(original->smartthres);
-  freenonzero(original->smartval);
-  freenonzero(original->address);
-  freenonzero(original->emailcmdline);
-  freenonzero(original->name);
-  freenonzero(original->monitorattflags);
-  freenonzero(original->attributedefs);
+  
+  original->smartthres      = freenonzero(original->smartthres);
+  original->smartval        = freenonzero(original->smartval);
+  original->address         = freenonzero(original->address);
+  original->emailcmdline    = freenonzero(original->emailcmdline);
+  original->name            = freenonzero(original->name);
+  original->monitorattflags = freenonzero(original->monitorattflags);
+  original->attributedefs   = freenonzero(original->attributedefs);
   freenonzero(original);
   
   return NULL;
@@ -2280,10 +2301,8 @@ int makeconfigentries(int num, char *name, int start){
     cfg->tryscsi= (name[5]=='s');
     
     // Remove device name, if it's there, and put in correct one
-    if (cfg->name)
-      cfg->name=checkfree(cfg->name);
-    cfg->name=strdup(name);
-    if (!cfg->name) {
+    cfg->name=freenonzero(cfg->name);
+    if (!(cfg->name=strdup(name))){
       printout(LOG_CRIT,"Out of memory making device scan list, %s\n", strerror(errno));
       exit(EXIT_NOMEM);
     }
diff --git a/sm5/smartd.cpp b/sm5/smartd.cpp
index 29e7f8cb1e655453bbf793df71eb336627a90981..12945928900478eefd54ef7dba987b86578bc722 100644
--- a/sm5/smartd.cpp
+++ b/sm5/smartd.cpp
@@ -50,7 +50,7 @@
 #include "utility.h"
 
 extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *escalade_c_cvsid, *knowndrives_c_cvsid, *scsicmds_c_cvsid, *utility_c_cvsid;
-const char *smartd_c_cvsid="$Id: smartd.cpp,v 1.188 2003/08/11 20:43:05 ballen4705 Exp $" 
+const char *smartd_c_cvsid="$Id: smartd.cpp,v 1.189 2003/08/13 12:33:23 ballen4705 Exp $" 
 ATACMDS_H_CVSID ATAPRINT_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SMARTD_H_CVSID UTILITY_H_CVSID; 
 
 // Forward declarations
@@ -339,7 +339,7 @@ void pout(char *fmt, ...){
 
 // tell user that we ignore HUP signals
 void huphandler(int sig){
-  printout(LOG_CRIT,"HUP ignored: smartd does NOT re-read /etc/smartd.conf.\n");
+  printout(LOG_INFO,"HUP ignored: smartd does NOT re-read /etc/smartd.conf.\n");
   return;
 }
 
@@ -619,8 +619,9 @@ int atadevicescan(cfgfile *cfg){
   // options unless user has requested otherwise.
   if (!cfg->ignorepresets){
 
-    // do whatever applypresets decides to do
-    if (applypresets(&drive, cfg->attributedefs, con)<0)
+    // do whatever applypresets decides to do. Will allocate memory if
+    // cfg->attributedefs if needed.
+    if (applypresets(&drive, &cfg->attributedefs, con)<0)
       printout(LOG_INFO, "Device: %s, not found in smartd database.\n", name);
     else
       printout(LOG_INFO, "Device: %s, found in smartd database.\n", name);
@@ -886,8 +887,8 @@ static int scsidevicescan(cfgfile *cfg)
     cfg->tryscsi = 1;
 
     // get rid of allocated memory only needed for ATA devices
-    cfg->monitorattflags = checkfree(cfg->monitorattflags);
-    cfg->attributedefs   = checkfree(cfg->attributedefs);
+    cfg->monitorattflags = freenonzero(cfg->monitorattflags);
+    cfg->attributedefs   = freenonzero(cfg->attributedefs);
     cfg->smartval        = freenonzero(cfg->smartval);
     cfg->smartthres      = freenonzero(cfg->smartthres);
 
@@ -960,12 +961,31 @@ int  ataCompareSmartValues(changedattribute_t *delta,
 // sorting functions! Entry is ZERO <==> the attribute ON. Calling
 // with set=0 tells you if the attribute is being tracked or not.
 // Calling with set=1 turns the attribute OFF.
-int isattoff(unsigned char attr,unsigned char *data, int set){
-  // locate correct attribute
+int isattoff(unsigned char attr, unsigned char **datap, int set, int which){
+  unsigned char *data;
   int loc=attr>>3;
   int bit=attr & 0x07;
   unsigned char mask=0x01<<bit;
 
+  if (which>=NMONITOR){
+    printout(LOG_CRIT, "Internal error in isattoff().  which == %d\n", which);
+    exit(EXIT_NOMEM);
+  }
+
+  if (*datap == NULL){
+    // null data implies Attributes are off...
+    if (!set)
+      return 1;
+    
+    // we are writing
+    if (!(*datap=calloc(NMONITOR*32, 1))){
+      printout(LOG_CRIT,"No memory to create monattflags\n");
+      exit(EXIT_NOMEM);
+    }
+  }
+  
+  data=*datap+which*32;
+
   // attribute zero is always OFF
   if (!attr)
     return 1;
@@ -1037,11 +1057,11 @@ int ataCheckDevice(cfgfile *cfg){
           
           // are we ignoring failures of this attribute?
           att *= -1;
-          if (!isattoff(att, cfg->monitorattflags, 0)){
+          if (!isattoff(att, &cfg->monitorattflags, 0, MONITOR_FAILUSE)){
             char attname[64], *loc=attname;
             
             // get attribute name & skip white space
-            ataPrintSmartAttribName(loc, att, cfg->attributedefs[att]);
+            ataPrintSmartAttribName(loc, att, cfg->attributedefs);
             while (*loc && *loc==' ') loc++;
             
             // warning message
@@ -1058,19 +1078,19 @@ int ataCheckDevice(cfgfile *cfg){
 
           // if the only change is the raw value, and we're not
           // tracking raw value, then continue loop over attributes
-          if (!delta.sameraw && delta.newval==delta.oldval && !isattoff(id, cfg->monitorattflags+96, 0))
+          if (!delta.sameraw && delta.newval==delta.oldval && !isattoff(id, &cfg->monitorattflags, 0, MONITOR_RAW))
             continue;
 
           // are we tracking this attribute?
-          if (!isattoff(id, cfg->monitorattflags+32, 0)){
+          if (!isattoff(id, &cfg->monitorattflags, 0, MONITOR_IGNORE)){
             char newrawstring[64], oldrawstring[64], attname[64], *loc=attname;
 
             // get attribute name, skip spaces
-            ataPrintSmartAttribName(loc, id, cfg->attributedefs[id]);
+            ataPrintSmartAttribName(loc, id, cfg->attributedefs);
             while (*loc && *loc==' ') loc++;
             
             // has the user asked for us to print raw values?
-            if (isattoff(id, cfg->monitorattflags+64, 0)) {
+            if (isattoff(id, &cfg->monitorattflags, 0, MONITOR_RAWPRINT)) {
               // get raw values (as a string) and add to printout
               char rawstring[64];
               ataPrintSmartAttribRawValue(rawstring, curval.vendor_attributes+i, cfg->attributedefs);
@@ -1587,23 +1607,23 @@ int parsetoken(char *token,cfgfile *cfg){
   case 'i':
     // ignore failure of usage attribute
     val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255);
-    isattoff(val,cfg->monitorattflags,1);
+    isattoff(val, &cfg->monitorattflags, 1, MONITOR_FAILUSE);
     break;
   case 'I':
     // ignore attribute for tracking purposes
     val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255);
-    isattoff(val,cfg->monitorattflags+32,1);
+    isattoff(val, &cfg->monitorattflags, 1, MONITOR_IGNORE);
     break;
   case 'r':
     // print raw value when tracking
     val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255);
-    isattoff(val,cfg->monitorattflags+64,1);
+    isattoff(val, &cfg->monitorattflags, 1, MONITOR_RAWPRINT);
     break;
   case 'R':
     // track changes in raw value (forces printing of raw value)
     val=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 1, 255);
-    isattoff(val,cfg->monitorattflags+64,1);
-    isattoff(val,cfg->monitorattflags+96,1);
+    isattoff(val, &cfg->monitorattflags, 1, MONITOR_RAWPRINT);
+    isattoff(val, &cfg->monitorattflags, 1, MONITOR_RAW);
     break;
   case 'm':
     // send email to address that follows
@@ -1624,7 +1644,7 @@ int parsetoken(char *token,cfgfile *cfg){
     // non-default vendor-specific attribute meaning
     if ((arg=strtok(NULL,delim)) == NULL) {
       missingarg = 1;
-    } else if (parse_attribute_def(arg, cfg->attributedefs)){   
+    } else if (parse_attribute_def(arg, &cfg->attributedefs)){   
       badarg = 1;
     }
     break;
@@ -1685,19 +1705,20 @@ cfgfile *createcfgentry(cfgfile *original){
   // if structure had data, copy it
   if (original)
     memcpy(add, original, sizeof(cfgfile));
-
-  // Always make this storage
-  if (
-      !(add->monitorattflags=(unsigned char *)calloc(NMONITOR*32,1)) ||
-      !(add->attributedefs=(unsigned char *)calloc(256,1))
-      ) goto badexit;
-
-  if (original){
-      memcpy(add->attributedefs,   original->attributedefs,   256);
-      memcpy(add->monitorattflags, original->monitorattflags, NMONITOR*32);
+  
+  // make private copies of these ONLY if they are in use
+  if (add->attributedefs) {
+    if (!(add->attributedefs=(unsigned char *)calloc(MAX_ATTRIBUTE_NUM,1)))
+      goto badexit;
+    memcpy(add->attributedefs, original->attributedefs, MAX_ATTRIBUTE_NUM);
+  }
+  
+  if (add->monitorattflags) {
+    if (!(add->monitorattflags=(unsigned char *)calloc(NMONITOR*32, 1)))
+      goto badexit;
+    memcpy(add->monitorattflags, original->monitorattflags, NMONITOR*32);
   }
   
-  // make private copies of these ONLY if they are used
   if (add->name &&
       !(add->name=strdup(add->name))
       ) goto badexit;
@@ -1727,19 +1748,19 @@ cfgfile *createcfgentry(cfgfile *original){
 
 // Removes config file entry, freeing all memory
 cfgfile *rmconfigentry(cfgfile *original){
-
+  
   if (!original){
     printout(LOG_CRIT,"Error - rmconfigentry() called with NULL pointer argument\n");
     exit(EXIT_NOMEM);
   }
-
-  freenonzero(original->smartthres);
-  freenonzero(original->smartval);
-  freenonzero(original->address);
-  freenonzero(original->emailcmdline);
-  freenonzero(original->name);
-  freenonzero(original->monitorattflags);
-  freenonzero(original->attributedefs);
+  
+  original->smartthres      = freenonzero(original->smartthres);
+  original->smartval        = freenonzero(original->smartval);
+  original->address         = freenonzero(original->address);
+  original->emailcmdline    = freenonzero(original->emailcmdline);
+  original->name            = freenonzero(original->name);
+  original->monitorattflags = freenonzero(original->monitorattflags);
+  original->attributedefs   = freenonzero(original->attributedefs);
   freenonzero(original);
   
   return NULL;
@@ -2280,10 +2301,8 @@ int makeconfigentries(int num, char *name, int start){
     cfg->tryscsi= (name[5]=='s');
     
     // Remove device name, if it's there, and put in correct one
-    if (cfg->name)
-      cfg->name=checkfree(cfg->name);
-    cfg->name=strdup(name);
-    if (!cfg->name) {
+    cfg->name=freenonzero(cfg->name);
+    if (!(cfg->name=strdup(name))){
       printout(LOG_CRIT,"Out of memory making device scan list, %s\n", strerror(errno));
       exit(EXIT_NOMEM);
     }
diff --git a/sm5/smartd.h b/sm5/smartd.h
index c953d10f052f83db79c0137505799caeb771c2b5..b995b7e7da00b9eae2d0aa7f6a22c1fa83887171 100644
--- a/sm5/smartd.h
+++ b/sm5/smartd.h
@@ -23,7 +23,7 @@
  */
 
 #ifndef SMARTD_H_CVSID
-#define SMARTD_H_CVSID "$Id: smartd.h,v 1.40 2003/08/11 14:31:45 ballen4705 Exp $\n"
+#define SMARTD_H_CVSID "$Id: smartd.h,v 1.41 2003/08/13 12:33:23 ballen4705 Exp $\n"
 #endif
 
 // Configuration file
@@ -54,9 +54,13 @@
 #define TRUE 0x01
 #define FALSE 0x00
 
-// Number of monitoring flags per Attribute.  See monitorattflags
-// below.
+// Number of monitoring flags per Attribute and offsets.  See
+// monitorattflags below.
 #define NMONITOR 4
+#define MONITOR_FAILUSE   0
+#define MONITOR_IGNORE    1
+#define MONITOR_RAWPRINT  2
+#define MONITOR_RAW       3
 
 // Exit codes
 #define EXIT_BADCMD    1   // command line did not parse