diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG
index 834f014f3cd944b86307759724f60fe04b9c59b0..0a7c02ab00e97034f92933751c2c5c7664d07333 100644
--- a/sm5/CHANGELOG
+++ b/sm5/CHANGELOG
@@ -1,6 +1,6 @@
 CHANGELOG for smartmontools
 
-$Id: CHANGELOG,v 1.13 2002/10/22 11:40:52 ballen4705 Exp $
+$Id: CHANGELOG,v 1.14 2002/10/22 16:49:15 ballen4705 Exp $
 
 Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 
@@ -29,6 +29,16 @@ NOTES FOR NEXT RELEASE:
 
 smartmontools-5.0-11
 
+    smartctl now returns sensible values (bitmask).  See smartctl.h
+    for the values.  I may add some additional values as time goes on,
+    so this is prelimiary.
+
+    The SMART status check now uses the correct ATA call.  If failure
+    is detected we search through attributes to list the failed ones.
+    If the SMART status check shows GOOD, we then look to see if their
+    are any usage attributes or prefail attributes have failed at any
+    time.  If so we print them.
+
     Modified function that prints vendor attributes to say if the
     attribute has currently failed or has ever failed.
 
diff --git a/sm5/ataprint.c b/sm5/ataprint.c
index 41bbcde8ff7d822276349f8c5eba6d2675285b75..d946656d38de67899925546ec760235d8700aed8 100644
--- a/sm5/ataprint.c
+++ b/sm5/ataprint.c
@@ -28,7 +28,7 @@
 #include "smartctl.h"
 #include "extern.h"
 
-const char *CVSid4="$Id: ataprint.c,v 1.22 2002/10/22 15:37:15 ballen4705 Exp $\n"
+const char *CVSid4="$Id: ataprint.c,v 1.23 2002/10/22 16:49:16 ballen4705 Exp $\n"
 	           "\t" CVSID2 "\t" CVSID3 "\t" CVSID6 ;
 
 // Function for printing ASCII byte-swapped strings, skipping white
@@ -401,7 +401,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values data,
       
       // is this currently failed, or has it ever failed?
       if (failednow)
-	status="FAILED NOW!";
+	status="FAILED_NOW!";
       else if (failedever)
 	status="In_the_past";
       else
@@ -412,7 +412,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values data,
       
       // printing line for each valid attribute
       type=disk->status.flag.prefailure?"Pre-fail":"Old_age";
-      printf(" 0x%04x   %.3i   %.3i   %.3i    %-9s%-13s", 
+      printf(" 0x%04x   %.3i   %.3i   %.3i    %-9s%-12s", 
 	     disk->status.all, disk->current, disk->worst,
 	     thre->threshold, type, status);
       
@@ -819,13 +819,15 @@ struct ata_smart_thresholds smartthres;
 struct ata_smart_errorlog smarterror;
 struct ata_smart_selftestlog smartselftest;
 
-void ataPrintMain (int fd){
+int ataPrintMain (int fd){
   int timewait,code;
+  int returnval=0;
   
   // Start by getting Drive ID information.  We need this, to know if SMART is supported.
   if (ataReadHDIdentity(fd,&drive)){
     printf("Smartctl: Hard Drive Read Identity Failed\n\n");
-  }
+    returnval|=FAILID;
+}
   
   // Print most drive identity information if requested
   if (driveinfo){
@@ -839,7 +841,7 @@ void ataPrintMain (int fd){
     printf("                  Checking to be sure by trying SMART ENABLE command.\n");
     if (ataEnableSmart(fd)){
       printf("                  No SMART functionality found. Sorry.\n");
-      exit(0);
+      return returnval|FAILSMART;
     }
     else
       printf("                  SMART appears to work.  Continuing.\n"); 
@@ -864,6 +866,7 @@ void ataPrintMain (int fd){
   if (smartenable){
     if (ataEnableSmart(fd)) {
       printf("Smartctl: SMART Enable Failed.\n\n");
+      returnval|=FAILSMART;
     }
     else
       printf("SMART Enabled.\n");
@@ -872,56 +875,72 @@ void ataPrintMain (int fd){
   // From here on, every command requires that SMART be enabled...
   if (!ataDoesSmartWork(fd)) {
     printf("SMART Disabled. Use option -%c to enable it.\n", SMARTENABLE );
-    exit(0);
+    return returnval;
   }
   
   // Turn off SMART on device
   if (smartdisable){    
     if (ataDisableSmart(fd)) {
       printf( "Smartctl: SMART Disable Failed.\n\n");
+      returnval|=FAILSMART;
     }
     printf("SMART Disabled. Use option -%c to enable it.\n",SMARTENABLE);
-    exit (0);		
+    return returnval;		
   }
   
   // Let's ALWAYS issue this command to get the SMART status
   code=ataSmartStatus2(fd);
-
+  if (code==-1)
+    returnval|=FAILSMART;
+  
   // Enable/Disable Auto-save attributes
   if (smartautosaveenable){
-    if (ataEnableAutoSave(fd))
+    if (ataEnableAutoSave(fd)){
       printf( "Smartctl: SMART Enable Attribute Autosave Failed.\n\n");
+      returnval|=FAILSMART;
+    }
     else
       printf("SMART Attribute Autosave Enabled.\n");
   }
   if (smartautosavedisable){
-    if (ataDisableAutoSave(fd))
+    if (ataDisableAutoSave(fd)){
       printf( "Smartctl: SMART Disable Attribute Autosave Failed.\n\n");
+      returnval|=FAILSMART;
+    }
     else
       printf("SMART Attribute Autosave Disabled.\n");
   }
   
   // for everything else read values and thresholds are needed
-  if (ataReadSmartValues(fd, &smartval))
+  if (ataReadSmartValues(fd, &smartval)){
     printf("Smartctl: SMART Values Read Failed.\n\n");
-  if (ataReadSmartThresholds(fd, &smartthres))
+    returnval|=FAILSMART;
+  }
+  if (ataReadSmartThresholds(fd, &smartthres)){
     printf("Smartctl: SMART Thresholds Read Failed.\n\n");
-  
+    returnval|=FAILSMART;
+  }
+
   // Enable/Disable Off-line testing
   if (smartautoofflineenable){
-    if (!isSupportAutomaticTimer (smartval)){
+    if (!isSupportAutomaticTimer(smartval)){
       printf("Device does not support SMART Automatic Timers.\n\n");
     }
-    if (ataEnableAutoOffline (fd))
+    if (ataEnableAutoOffline(fd)){
       printf( "Smartctl: SMART Enable Automatic Offline Failed.\n\n");
+      returnval|=FAILSMART;
+    }
     else
       printf ("SMART Automatic Offline Testing Enabled every four hours.\n");
   }
   if (smartautoofflinedisable){
-    if (!isSupportAutomaticTimer (smartval))
-      printf("Device does not support SMART Automatic Timers.\n\n");		
-    if (ataDisableAutoOffline (fd))
+    if (!isSupportAutomaticTimer(smartval)){
+      printf("Device does not support SMART Automatic Timers.\n\n");
+    }
+    if (ataDisableAutoOffline(fd)){
       printf("Smartctl: SMART Disable Automatic Offline Failed.\n\n");
+      returnval|=FAILSMART;
+    }
     else
       printf("SMART Automatic Offline Testing Disabled.\n");
   }
@@ -936,25 +955,24 @@ void ataPrintMain (int fd){
       printf("SMART overall-health self-assessment test result: FAILED!\n"
 	     "Drive failure expected in less than 24 hours. SAVE ALL DATA\n");
       if (ataCheckSmart(smartval, smartthres,1)){
-	printf("SMART prefailure attributes shown below are below threshold.\n"
-	       "Use -%c option to investigate\n",SMARTVENDORATTRIB);
-
-	printf("Below is a list of failing attributes.\nUse -%c option to investigate.\n",
-	       SMARTVENDORATTRIB);
+	returnval|=FAILATTR;
+	printf("Failed attributes:\n");
 	PrintSmartAttribWithThres(smartval, smartthres,1);
-	printf("\n");
       }
-      else
-	printf("Unable to confirm any failing attributes.\n");
+      else {
+	printf("No failing attributes found.\n");
+      }      
+      printf("\n");
+      returnval|=FAILSTATUS;
     }
     else {
       printf("SMART overall-health self-assessment test result: PASSED\n");
       if (ataCheckSmart(smartval, smartthres,0)){
-	printf("Note: SMART attributes shown below are below threshold now or were in the past.\n"
-	       "Use -%c option to investigate\n",SMARTVENDORATTRIB);
+	printf("Marginal attributes:\n");
 	PrintSmartAttribWithThres(smartval, smartthres,2);
-	printf("\n");
+	returnval|=FAILAGE;
       }
+      printf("\n");
     }
   }
   
@@ -965,26 +983,34 @@ void ataPrintMain (int fd){
   // Print vendor-specific attributes
   if (smartvendorattrib)
     PrintSmartAttribWithThres(smartval, smartthres,0);
-	
+  
   // Print SMART error log
   if (smarterrorlog){
-    if (!isSmartErrorLogCapable(smartval))
+    if (!isSmartErrorLogCapable(smartval)){
       printf("Device does not support Error Logging\n");
+      returnval|=FAILSMART;
+    }
     else {
-      if (ataReadErrorLog(fd, &smarterror))
+      if (ataReadErrorLog(fd, &smarterror)){
 	printf("Smartctl: SMART Errorlog Read Failed\n");
+	returnval|=FAILSMART;
+      }
       else
 	ataPrintSmartErrorlog(smarterror);
     }
   }
-
+  
   // Print SMART self-test log
   if (smartselftestlog){
-    if (!isSmartErrorLogCapable(smartval))
+    if (!isSmartErrorLogCapable(smartval)){
       printf("Device does not support Self Test Logging\n");
+      returnval|=FAILSMART;
+    }
     else {
-      if(ataReadSelfTestLog(fd, &smartselftest))
+      if(ataReadSelfTestLog(fd, &smartselftest)){
 	printf("Smartctl: SMART Self Test Log Read Failed\n");
+	returnval|=FAILSMART;
+      }
       else
 	ataPrintSmartSelfTestlog(smartselftest); 
     } 
@@ -992,24 +1018,23 @@ void ataPrintMain (int fd){
   
   // START OF THE TESTING SECTION OF THE CODE.  IF NO TESTING, RETURN
   if (testcase==-1)
-    return;
+    return returnval;
 
   printf("\n=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n");
 
-  
   // if doing a self-test, be sure it's supported by the hardware
   if (testcase==OFFLINE_FULL_SCAN &&  !isSupportExecuteOfflineImmediate(smartval)){
     printf("ERROR: device does not support Execute Off-Line Immediate function.\n\n");
-    exit(-1);
+    return returnval|=FAILSMART;
   }
   else if (!isSupportSelfTest(smartval)){
     printf ("ERROR: device does not support Self-Test functions.\n\n");
-    exit(-1);
+    return returnval|=FAILSMART;
   }
   
   // Now do the test
   if (ataSmartTest(fd, testcase))
-    exit(-1);
+    return returnval|=FAILSMART;
   
   // Tell user how long test will take to complete  
   if ((timewait=TestTime(smartval,testcase))){ 
@@ -1019,5 +1044,5 @@ void ataPrintMain (int fd){
     if (testcase!=SHORT_CAPTIVE_SELF_TEST && testcase!=EXTEND_CAPTIVE_SELF_TEST)
       printf ("Use smartctl -%c to abort test.\n", SMARTSELFTESTABORT);	
   }    
-  return;
+  return returnval;
 }
diff --git a/sm5/ataprint.cpp b/sm5/ataprint.cpp
index c856e73aa7d3f05e9170c01678dc27fad122ac96..b0a492e29bc680c4839c4a6ffad4fdb9de0c7b0b 100644
--- a/sm5/ataprint.cpp
+++ b/sm5/ataprint.cpp
@@ -28,7 +28,7 @@
 #include "smartctl.h"
 #include "extern.h"
 
-const char *CVSid4="$Id: ataprint.cpp,v 1.22 2002/10/22 15:37:15 ballen4705 Exp $\n"
+const char *CVSid4="$Id: ataprint.cpp,v 1.23 2002/10/22 16:49:16 ballen4705 Exp $\n"
 	           "\t" CVSID2 "\t" CVSID3 "\t" CVSID6 ;
 
 // Function for printing ASCII byte-swapped strings, skipping white
@@ -401,7 +401,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values data,
       
       // is this currently failed, or has it ever failed?
       if (failednow)
-	status="FAILED NOW!";
+	status="FAILED_NOW!";
       else if (failedever)
 	status="In_the_past";
       else
@@ -412,7 +412,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values data,
       
       // printing line for each valid attribute
       type=disk->status.flag.prefailure?"Pre-fail":"Old_age";
-      printf(" 0x%04x   %.3i   %.3i   %.3i    %-9s%-13s", 
+      printf(" 0x%04x   %.3i   %.3i   %.3i    %-9s%-12s", 
 	     disk->status.all, disk->current, disk->worst,
 	     thre->threshold, type, status);
       
@@ -819,13 +819,15 @@ struct ata_smart_thresholds smartthres;
 struct ata_smart_errorlog smarterror;
 struct ata_smart_selftestlog smartselftest;
 
-void ataPrintMain (int fd){
+int ataPrintMain (int fd){
   int timewait,code;
+  int returnval=0;
   
   // Start by getting Drive ID information.  We need this, to know if SMART is supported.
   if (ataReadHDIdentity(fd,&drive)){
     printf("Smartctl: Hard Drive Read Identity Failed\n\n");
-  }
+    returnval|=FAILID;
+}
   
   // Print most drive identity information if requested
   if (driveinfo){
@@ -839,7 +841,7 @@ void ataPrintMain (int fd){
     printf("                  Checking to be sure by trying SMART ENABLE command.\n");
     if (ataEnableSmart(fd)){
       printf("                  No SMART functionality found. Sorry.\n");
-      exit(0);
+      return returnval|FAILSMART;
     }
     else
       printf("                  SMART appears to work.  Continuing.\n"); 
@@ -864,6 +866,7 @@ void ataPrintMain (int fd){
   if (smartenable){
     if (ataEnableSmart(fd)) {
       printf("Smartctl: SMART Enable Failed.\n\n");
+      returnval|=FAILSMART;
     }
     else
       printf("SMART Enabled.\n");
@@ -872,56 +875,72 @@ void ataPrintMain (int fd){
   // From here on, every command requires that SMART be enabled...
   if (!ataDoesSmartWork(fd)) {
     printf("SMART Disabled. Use option -%c to enable it.\n", SMARTENABLE );
-    exit(0);
+    return returnval;
   }
   
   // Turn off SMART on device
   if (smartdisable){    
     if (ataDisableSmart(fd)) {
       printf( "Smartctl: SMART Disable Failed.\n\n");
+      returnval|=FAILSMART;
     }
     printf("SMART Disabled. Use option -%c to enable it.\n",SMARTENABLE);
-    exit (0);		
+    return returnval;		
   }
   
   // Let's ALWAYS issue this command to get the SMART status
   code=ataSmartStatus2(fd);
-
+  if (code==-1)
+    returnval|=FAILSMART;
+  
   // Enable/Disable Auto-save attributes
   if (smartautosaveenable){
-    if (ataEnableAutoSave(fd))
+    if (ataEnableAutoSave(fd)){
       printf( "Smartctl: SMART Enable Attribute Autosave Failed.\n\n");
+      returnval|=FAILSMART;
+    }
     else
       printf("SMART Attribute Autosave Enabled.\n");
   }
   if (smartautosavedisable){
-    if (ataDisableAutoSave(fd))
+    if (ataDisableAutoSave(fd)){
       printf( "Smartctl: SMART Disable Attribute Autosave Failed.\n\n");
+      returnval|=FAILSMART;
+    }
     else
       printf("SMART Attribute Autosave Disabled.\n");
   }
   
   // for everything else read values and thresholds are needed
-  if (ataReadSmartValues(fd, &smartval))
+  if (ataReadSmartValues(fd, &smartval)){
     printf("Smartctl: SMART Values Read Failed.\n\n");
-  if (ataReadSmartThresholds(fd, &smartthres))
+    returnval|=FAILSMART;
+  }
+  if (ataReadSmartThresholds(fd, &smartthres)){
     printf("Smartctl: SMART Thresholds Read Failed.\n\n");
-  
+    returnval|=FAILSMART;
+  }
+
   // Enable/Disable Off-line testing
   if (smartautoofflineenable){
-    if (!isSupportAutomaticTimer (smartval)){
+    if (!isSupportAutomaticTimer(smartval)){
       printf("Device does not support SMART Automatic Timers.\n\n");
     }
-    if (ataEnableAutoOffline (fd))
+    if (ataEnableAutoOffline(fd)){
       printf( "Smartctl: SMART Enable Automatic Offline Failed.\n\n");
+      returnval|=FAILSMART;
+    }
     else
       printf ("SMART Automatic Offline Testing Enabled every four hours.\n");
   }
   if (smartautoofflinedisable){
-    if (!isSupportAutomaticTimer (smartval))
-      printf("Device does not support SMART Automatic Timers.\n\n");		
-    if (ataDisableAutoOffline (fd))
+    if (!isSupportAutomaticTimer(smartval)){
+      printf("Device does not support SMART Automatic Timers.\n\n");
+    }
+    if (ataDisableAutoOffline(fd)){
       printf("Smartctl: SMART Disable Automatic Offline Failed.\n\n");
+      returnval|=FAILSMART;
+    }
     else
       printf("SMART Automatic Offline Testing Disabled.\n");
   }
@@ -936,25 +955,24 @@ void ataPrintMain (int fd){
       printf("SMART overall-health self-assessment test result: FAILED!\n"
 	     "Drive failure expected in less than 24 hours. SAVE ALL DATA\n");
       if (ataCheckSmart(smartval, smartthres,1)){
-	printf("SMART prefailure attributes shown below are below threshold.\n"
-	       "Use -%c option to investigate\n",SMARTVENDORATTRIB);
-
-	printf("Below is a list of failing attributes.\nUse -%c option to investigate.\n",
-	       SMARTVENDORATTRIB);
+	returnval|=FAILATTR;
+	printf("Failed attributes:\n");
 	PrintSmartAttribWithThres(smartval, smartthres,1);
-	printf("\n");
       }
-      else
-	printf("Unable to confirm any failing attributes.\n");
+      else {
+	printf("No failing attributes found.\n");
+      }      
+      printf("\n");
+      returnval|=FAILSTATUS;
     }
     else {
       printf("SMART overall-health self-assessment test result: PASSED\n");
       if (ataCheckSmart(smartval, smartthres,0)){
-	printf("Note: SMART attributes shown below are below threshold now or were in the past.\n"
-	       "Use -%c option to investigate\n",SMARTVENDORATTRIB);
+	printf("Marginal attributes:\n");
 	PrintSmartAttribWithThres(smartval, smartthres,2);
-	printf("\n");
+	returnval|=FAILAGE;
       }
+      printf("\n");
     }
   }
   
@@ -965,26 +983,34 @@ void ataPrintMain (int fd){
   // Print vendor-specific attributes
   if (smartvendorattrib)
     PrintSmartAttribWithThres(smartval, smartthres,0);
-	
+  
   // Print SMART error log
   if (smarterrorlog){
-    if (!isSmartErrorLogCapable(smartval))
+    if (!isSmartErrorLogCapable(smartval)){
       printf("Device does not support Error Logging\n");
+      returnval|=FAILSMART;
+    }
     else {
-      if (ataReadErrorLog(fd, &smarterror))
+      if (ataReadErrorLog(fd, &smarterror)){
 	printf("Smartctl: SMART Errorlog Read Failed\n");
+	returnval|=FAILSMART;
+      }
       else
 	ataPrintSmartErrorlog(smarterror);
     }
   }
-
+  
   // Print SMART self-test log
   if (smartselftestlog){
-    if (!isSmartErrorLogCapable(smartval))
+    if (!isSmartErrorLogCapable(smartval)){
       printf("Device does not support Self Test Logging\n");
+      returnval|=FAILSMART;
+    }
     else {
-      if(ataReadSelfTestLog(fd, &smartselftest))
+      if(ataReadSelfTestLog(fd, &smartselftest)){
 	printf("Smartctl: SMART Self Test Log Read Failed\n");
+	returnval|=FAILSMART;
+      }
       else
 	ataPrintSmartSelfTestlog(smartselftest); 
     } 
@@ -992,24 +1018,23 @@ void ataPrintMain (int fd){
   
   // START OF THE TESTING SECTION OF THE CODE.  IF NO TESTING, RETURN
   if (testcase==-1)
-    return;
+    return returnval;
 
   printf("\n=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n");
 
-  
   // if doing a self-test, be sure it's supported by the hardware
   if (testcase==OFFLINE_FULL_SCAN &&  !isSupportExecuteOfflineImmediate(smartval)){
     printf("ERROR: device does not support Execute Off-Line Immediate function.\n\n");
-    exit(-1);
+    return returnval|=FAILSMART;
   }
   else if (!isSupportSelfTest(smartval)){
     printf ("ERROR: device does not support Self-Test functions.\n\n");
-    exit(-1);
+    return returnval|=FAILSMART;
   }
   
   // Now do the test
   if (ataSmartTest(fd, testcase))
-    exit(-1);
+    return returnval|=FAILSMART;
   
   // Tell user how long test will take to complete  
   if ((timewait=TestTime(smartval,testcase))){ 
@@ -1019,5 +1044,5 @@ void ataPrintMain (int fd){
     if (testcase!=SHORT_CAPTIVE_SELF_TEST && testcase!=EXTEND_CAPTIVE_SELF_TEST)
       printf ("Use smartctl -%c to abort test.\n", SMARTSELFTESTABORT);	
   }    
-  return;
+  return returnval;
 }
diff --git a/sm5/ataprint.h b/sm5/ataprint.h
index f76076f8c2c94b9312ee69bad6583c454e934cbe..09cfaa87b9cc95845eefbc2d215aecf2f8cdd085 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.8 2002/10/22 11:40:52 ballen4705 Exp $\n"
+#define CVSID2 "$Id: ataprint.h,v 1.9 2002/10/22 16:49:16 ballen4705 Exp $\n"
 #endif
 
 #include <stdio.h>
@@ -58,6 +58,6 @@ void ataPseudoCheckSmart (struct ata_smart_values ,
 /* prints 20 character string */
 void ataPrintSmartAttribName (unsigned char id);
 
-void ataPrintMain ( int fd );
+int ataPrintMain ( int fd );
 
 #endif
diff --git a/sm5/smartctl.8 b/sm5/smartctl.8
index 51bdca369e3d4af7e35d3bfd98fcf75cba1158c2..a5659bae192eb4bd8ded8256c9f50620f3f12cba 100644
--- a/sm5/smartctl.8
+++ b/sm5/smartctl.8
@@ -1,6 +1,6 @@
 \# Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 \#
-\# $Id: smartctl.8,v 1.13 2002/10/22 12:53:20 ballen4705 Exp $
+\# $Id: smartctl.8,v 1.14 2002/10/22 16:49:16 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
@@ -15,7 +15,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 SMARTCTL 8  "$Date: 2002/10/22 12:53:20 $" "smartmontools-5.0"
+.TH SMARTCTL 8  "$Date: 2002/10/22 16:49:16 $" "smartmontools-5.0"
 .SH NAME
 smartctl \- S.M.A.R.T. control utility 
 .SH SYNOPSIS
@@ -315,6 +315,18 @@ the S.M.A.R.T. error log., which can be seen with the '\-l' option.
 shows the vendor attributes, when the disk stores its power-on time
 internally in minutes rather than hours.
 
+.PP
+.SH RETURN VALUES
+
+The return values of smartctl are defined by a bitmask.  For the
+moment this only works on ATA disks.  The different bits in the return
+value are as follows.  Bit 0: Command line did not parse.  Bit 1:
+Device open failed.  Bit 2: SMART command to disk failed.  Bit 3:
+SMART status check returned "DISK FAILING".  Bit 4: SMART status check
+returned "DISK OK" but we found prefail attributes <= threshold.  Bit
+5: SMART status check returned "DISK OK" but we found that some (usage
+or prefail) attributes have been <= threshold at some time in the
+past. Bit 6: Unable to get Device IDENTITY information. 
 .PP
 .SH AUTHOR
 Bruce Allen
@@ -389,4 +401,4 @@ Please let us know if there is an on\-line source for this document.
 
 .SH
 CVS ID OF THIS PAGE:
-$Id: smartctl.8,v 1.13 2002/10/22 12:53:20 ballen4705 Exp $
+$Id: smartctl.8,v 1.14 2002/10/22 16:49:16 ballen4705 Exp $
diff --git a/sm5/smartctl.c b/sm5/smartctl.c
index 9652f404261a0927bfb8155ce053e2f48bab1c77..3e17e69704e931e95d9569940565756eb75b3ab9 100644
--- a/sm5/smartctl.c
+++ b/sm5/smartctl.c
@@ -37,7 +37,7 @@
 #include "scsiprint.h"
 
 extern const char *CVSid1, *CVSid2, *CVSid4, *CVSid5; 
-const char* CVSid6="$Id: smartctl.c,v 1.13 2002/10/22 09:50:54 ballen4705 Exp $\n"
+const char* CVSid6="$Id: smartctl.c,v 1.14 2002/10/22 16:49:16 ballen4705 Exp $\n"
 "\t" CVSID1 "\t" CVSID2 "\t" CVSID4 "\t" CVSID5 "\t" CVSID6 ;
 
 unsigned char driveinfo               = FALSE;
@@ -201,7 +201,7 @@ void ParseOpts (int argc, char** argv){
       break;
     default:
       Usage();
-      exit (-1);	
+      exit(FAILCMD);	
     }
     
     if ( (smartexeoffimmediate + smartshortselftest +
@@ -209,7 +209,7 @@ void ParseOpts (int argc, char** argv){
 	  smartextendcapselftest +smartselftestabort ) > 1){
       Usage();
       printf ("\nERROR: smartctl can only run a single test (or abort) at a time.\n\n");
-      exit(-1);
+      exit(FAILCMD);
     }
   }
 }
@@ -217,14 +217,14 @@ void ParseOpts (int argc, char** argv){
 /* Main Program */
 
 int main (int argc, char **argv){
-  int fd;
+  int fd,retval=0;
   char *device;
   
   printf("smartctl version %d.%d-%d Copyright (C) 2002 Bruce Allen\n",RELEASE_MAJOR,RELEASE_MINOR,SMARTMONTOOLS_VERSION);
   printf("Home page of smartctl is %s\n",PROJECTHOME);
   
   // Part input arguments
-  ParseOpts (argc,argv);
+  ParseOpts(argc,argv);
   
   // Print Copyright/License info if needed
   if (printcopyleft){
@@ -234,29 +234,31 @@ int main (int argc, char **argv){
     printf("See http://www.gnu.org for further details.\n\n");
     printf("CVS version IDs of files used to build this code are:\n%s%s%s%s%s",CVSid1,CVSid2,CVSid4,CVSid5,CVSid6);
     if (argc==2)
-      exit(0);
- }
-
+      return 0;
+  }
+  
   // Further argument checking
-  if ( argc != 3 ){
+  if (argc != 3){
     Usage();
-    exit (-1);
+    return FAILCMD;
   }
-    
+  
   // open device - read-only mode is enough to issue needed commands
-  fd = open ( device=argv[2], O_RDONLY );
+  fd = open(device=argv[2], O_RDONLY);
   
-  if ( fd < 0) {
-    perror ( "Device open failed");
-    exit(-1);
+  if (fd< 0) {
+    perror ("Smartctl device open failed:");
+    return FAILDEV;
   }
   
-  if ( device[5] == 'h')
-    ataPrintMain (fd );
+  if (device[5] == 'h')
+    retval=ataPrintMain(fd );
   else if (device[5] == 's')
     scsiPrintMain (fd);
-  else 
+  else {
     Usage();
-  
-  return 0;
+    return FAILCMD;
+  }
+
+  return retval;
 }
diff --git a/sm5/smartctl.cpp b/sm5/smartctl.cpp
index f57b2fba35e1f4b99cd7b79722c6c0d2b6bc28c3..467badd2bea195ed5d13593967522b62e65974d3 100644
--- a/sm5/smartctl.cpp
+++ b/sm5/smartctl.cpp
@@ -37,7 +37,7 @@
 #include "scsiprint.h"
 
 extern const char *CVSid1, *CVSid2, *CVSid4, *CVSid5; 
-const char* CVSid6="$Id: smartctl.cpp,v 1.13 2002/10/22 09:50:54 ballen4705 Exp $\n"
+const char* CVSid6="$Id: smartctl.cpp,v 1.14 2002/10/22 16:49:16 ballen4705 Exp $\n"
 "\t" CVSID1 "\t" CVSID2 "\t" CVSID4 "\t" CVSID5 "\t" CVSID6 ;
 
 unsigned char driveinfo               = FALSE;
@@ -201,7 +201,7 @@ void ParseOpts (int argc, char** argv){
       break;
     default:
       Usage();
-      exit (-1);	
+      exit(FAILCMD);	
     }
     
     if ( (smartexeoffimmediate + smartshortselftest +
@@ -209,7 +209,7 @@ void ParseOpts (int argc, char** argv){
 	  smartextendcapselftest +smartselftestabort ) > 1){
       Usage();
       printf ("\nERROR: smartctl can only run a single test (or abort) at a time.\n\n");
-      exit(-1);
+      exit(FAILCMD);
     }
   }
 }
@@ -217,14 +217,14 @@ void ParseOpts (int argc, char** argv){
 /* Main Program */
 
 int main (int argc, char **argv){
-  int fd;
+  int fd,retval=0;
   char *device;
   
   printf("smartctl version %d.%d-%d Copyright (C) 2002 Bruce Allen\n",RELEASE_MAJOR,RELEASE_MINOR,SMARTMONTOOLS_VERSION);
   printf("Home page of smartctl is %s\n",PROJECTHOME);
   
   // Part input arguments
-  ParseOpts (argc,argv);
+  ParseOpts(argc,argv);
   
   // Print Copyright/License info if needed
   if (printcopyleft){
@@ -234,29 +234,31 @@ int main (int argc, char **argv){
     printf("See http://www.gnu.org for further details.\n\n");
     printf("CVS version IDs of files used to build this code are:\n%s%s%s%s%s",CVSid1,CVSid2,CVSid4,CVSid5,CVSid6);
     if (argc==2)
-      exit(0);
- }
-
+      return 0;
+  }
+  
   // Further argument checking
-  if ( argc != 3 ){
+  if (argc != 3){
     Usage();
-    exit (-1);
+    return FAILCMD;
   }
-    
+  
   // open device - read-only mode is enough to issue needed commands
-  fd = open ( device=argv[2], O_RDONLY );
+  fd = open(device=argv[2], O_RDONLY);
   
-  if ( fd < 0) {
-    perror ( "Device open failed");
-    exit(-1);
+  if (fd< 0) {
+    perror ("Smartctl device open failed:");
+    return FAILDEV;
   }
   
-  if ( device[5] == 'h')
-    ataPrintMain (fd );
+  if (device[5] == 'h')
+    retval=ataPrintMain(fd );
   else if (device[5] == 's')
     scsiPrintMain (fd);
-  else 
+  else {
     Usage();
-  
-  return 0;
+    return FAILCMD;
+  }
+
+  return retval;
 }
diff --git a/sm5/smartctl.h b/sm5/smartctl.h
index d8ec2f2b2689a08648b0d263729c8117754c8a19..41d7ead978cdb634051888565a2650183476d52a 100644
--- a/sm5/smartctl.h
+++ b/sm5/smartctl.h
@@ -26,7 +26,7 @@
 #define __SMARTCTL_H_
 
 #ifndef CVSID6
-#define CVSID6 "$Id: smartctl.h,v 1.7 2002/10/22 09:44:55 ballen4705 Exp $\n"
+#define CVSID6 "$Id: smartctl.h,v 1.8 2002/10/22 16:49:16 ballen4705 Exp $\n"
 #endif
 
 /* Defines for command line options */ 
@@ -57,4 +57,28 @@
 #define TRUE 0x01
 #define FALSE 0x00
 
+// Return codes (bitmask)
+
+// command line did not parse
+#define FAILCMD   (0x01<<0)
+
+// device open failed
+#define FAILDEV   (0x01<<1)
+        
+// smart command failed
+#define FAILSMART (0x01<<2)
+
+// SMART STATUS returned FAILURE
+#define FAILSTATUS (0x01<<3)
+
+// Attributes found <= threshold with prefail=1
+#define FAILATTR (0x01<<4)
+
+// SMART STATUS returned GOOD but age attributes failed or prefail
+// attributes have failed in the past
+#define FAILAGE (0x01<<5)
+
+// Device ID failed
+#define FAILID (0x01<<6)
+
 #endif