/*
 * smartctl.c
 *
 * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
 *
 * 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 Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * You should have received a copy of the GNU General Public License
 * (for example COPYING); if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */


#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/hdreg.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <string.h>
#include "smartctl.h"
#include "atacmds.h"
#include "ataprint.h"
#include "scsicmds.h"
#include "scsiprint.h"

unsigned char driveinfo               = FALSE;
unsigned char checksmart              = FALSE;
unsigned char smartvendorattrib       = FALSE;
unsigned char generalsmartvalues      = FALSE;
unsigned char smartselftestlog        = FALSE;
unsigned char smarterrorlog           = FALSE;
unsigned char smartdisable            = FALSE;
unsigned char smartenable             = FALSE;
unsigned char smartstatus             = FALSE;
unsigned char smartexeoffimmediate    = FALSE;
unsigned char smartshortselftest      = FALSE;
unsigned char smartextendselftest     = FALSE;
unsigned char smartshortcapselftest   = FALSE;
unsigned char smartextendcapselftest  = FALSE;
unsigned char smartselftestabort      = FALSE;
unsigned char smartautoofflineenable  = FALSE;
unsigned char smartautoofflinedisable = FALSE;


/*  void Usage (void) 
	prints help information for command syntax */



void Usage ( void)
{

   printf( "smartctl version %i.%i - S.M.A.R.T. Control Program\n", 
            VERSION_MAJOR, VERSION_MINOR);
   printf( "useage: smartctl -[opts] [device]\n");
   printf( "Read Only Commands:\n");
   printf( "\t\t%c\t\tShow All S.M.A.R.T. Information (ATA and SCSI)\n", 
            SMARTVERBOSEALL);
   printf( "\t\t%c\t\tShow General S.M.A.R.T. Attributes (ATA Only)\n",
            GENERALSMARTVALUES);
   printf( "\t\t%c\t\tShow Vendor S.M.A.R.T. Attributes (ATA Only)\n", 
            SMARTVENDORATTRIB);
   printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Error Log (ATA Only\n", 
            SMARTERRORLOG);
   printf( "\t\t%c\t\tShow S.M.A.R.T. Drive SelfTest Log (ATA Only)\n", 
            SMARTSELFTESTLOG);
   printf( "\t\t%c\t\tShow S.M.A.R.T. Drive Info (ATA and SCSI)\n", DRIVEINFO);
   printf( "\t\t%c\t\tCheck S.M.A.R.T. Status (ATA and SCSI)\n", CHECKSMART);
   printf( "\n");
   printf( "Enable / Disable Commands:\n");
   printf( "\t\t%c\t\tEnable S.M.A.R.T. data collection (ATA and SCSI)\n", 
            SMARTENABLE);
   printf( "\t\t%c\t\tDisable S.M.A.R.T.data collection (ATA and SCSI)\n", 
            SMARTDISABLE);
   printf( "\t\t%c\t\tEnable S.M.A.R.T. Automatic Offline Test (ATA Only)\n", 
            SMARTAUTOOFFLINEENABLE);
   printf( "\t\t%c\t\tDisable S.M.A.R.T. Automatic Offline Test (ATA Only)\n", 
            SMARTAUTOOFFLINEDISABLE);
   printf( "\n");
   printf( "Test Commands:\n");
   printf( "\t\t%c\t\tExecute Off-line data collectioni(ATA Only)\n",
            SMARTEXEOFFIMMEDIATE);
   printf( "\t\t%c\t\tExecute Short Self Test (ATA Only)\n", 
            SMARTSHORTSELFTEST );
   printf( "\t\t%c\t\tExecute Short Self Test (Captive Mode) (ATA Only)\n",
            SMARTSHORTCAPSELFTEST );
   printf( "\t\t%c\t\tExecute Extended Self Test (ATA Only)\n", 
            SMARTEXTENDSELFTEST );
   printf( "\t\t%c\t\tExecute Extended Self Test (Captive Mode)(ATA Only)\n", 
            SMARTEXTENDCAPSELFTEST );
   printf( "\t\t%c\t\tExecute Self Test Abort (ATA Only)\n", 
            SMARTSELFTESTABORT );
}
	

/*  void ParseOpts ( chars *opts) 
	Takes command options and sets features to be run */	

void ParseOpts ( char *opts)
{
   int i = 0;
   char options[255];
	
   strcpy ( (char *) &options, opts);

   if ( options[0] != '-' )
   {
      Usage();
      exit (-1);
   }

   for (i = 1; options[i] != '\0'; i++ )
   {
       switch (options[i])
       {
           case DRIVEINFO :
              driveinfo  = TRUE;
              break;		
           case CHECKSMART :
              driveinfo  = TRUE;
              checksmart = TRUE;		
              break;
           case SMARTVERBOSEALL :
              driveinfo = TRUE;
              checksmart = TRUE;
              generalsmartvalues = TRUE;
              smartvendorattrib = TRUE;
              smarterrorlog = TRUE;
              smartselftestlog = TRUE;
              break;
           case SMARTVENDORATTRIB :
              smartvendorattrib = TRUE;
              break;
           case GENERALSMARTVALUES :
              generalsmartvalues = TRUE;
              break;
           case SMARTERRORLOG :
              smarterrorlog = TRUE;
              break;
           case SMARTSELFTESTLOG :
              smartselftestlog = TRUE;
              break;
           case SMARTDISABLE :
              smartdisable = TRUE;
              break;
           case SMARTENABLE :
              smartenable   = TRUE;
              break;
           case SMARTAUTOOFFLINEENABLE: 
              smartautoofflineenable = TRUE;
              break;
           case SMARTAUTOOFFLINEDISABLE:
              smartautoofflinedisable = TRUE;
              break;
           case SMARTEXEOFFIMMEDIATE:
              smartexeoffimmediate = TRUE;
              break;
           case SMARTSHORTSELFTEST :
              smartshortselftest = TRUE;
              break;
           case SMARTEXTENDSELFTEST :
              smartextendselftest = TRUE;
              break;
           case SMARTSHORTCAPSELFTEST:
              smartshortcapselftest = TRUE;
              break;
           case SMARTEXTENDCAPSELFTEST:
              smartextendcapselftest = TRUE;
              break;
           case SMARTSELFTESTABORT:
              smartselftestabort = TRUE;
              break;
           default:
              Usage();
              exit (-1);	
      }

      if ( (smartexeoffimmediate + smartshortselftest +
            smartextendselftest + smartshortcapselftest +
            smartextendcapselftest ) > 1)
      {
          Usage();
          printf ("\n ERROR: smartctl can only run a single test at a time \n");
          exit(-1);
      }
   }
}

/* Main Program */

int main (int argv, char **argc)
{
	
   int fd;
   char *options, *device;
	
   if ( argv != 3 )
   {
      Usage();
      exit (-1);
   }
	
   options = *(argc+1);
   device = *(argc+2);
	
   ParseOpts ( options);
	
   /* open device */
   fd = open ( device, O_RDWR );

   if ( fd < 0) 
   {
	perror ( "Device open failed");
	exit(-1);
   }
	
   if ( device[5] == 'h')
        ataPrintMain (fd );
   else if (device[5] == 's')
        scsiPrintMain (fd);
   else 
        Usage();

   return 0;
}
