From 21e1fe60ec3a318796f75ff21f90388acd712932 Mon Sep 17 00:00:00 2001
From: pjwilliams <pjwilliams@4ea69e1a-61f1-4043-bf83-b5c94c648137>
Date: Sat, 4 Jan 2003 17:34:16 +0000
Subject: [PATCH] Added function create_vendor_attribute_arg_list() to create a
 formatted list of arguments in vendorattributeargs[]

git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@418 4ea69e1a-61f1-4043-bf83-b5c94c648137
---
 sm5/atacmds.c    | 39 ++++++++++++++++++++++++++++++++++++++-
 sm5/atacmds.cpp  | 39 ++++++++++++++++++++++++++++++++++++++-
 sm5/atacmds.h    |  7 ++++++-
 sm5/smartctl.c   | 17 +++++++++--------
 sm5/smartctl.cpp | 17 +++++++++--------
 sm5/smartd.c     | 30 +++++++++++++++---------------
 sm5/smartd.cpp   | 30 +++++++++++++++---------------
 7 files changed, 130 insertions(+), 49 deletions(-)

diff --git a/sm5/atacmds.c b/sm5/atacmds.c
index 6d3583c13..1deb312ee 100644
--- a/sm5/atacmds.c
+++ b/sm5/atacmds.c
@@ -29,7 +29,7 @@
 #include <stdlib.h>
 #include "atacmds.h"
 
-const char *CVSid1="$Id: atacmds.c,v 1.48 2003/01/03 17:25:12 ballen4705 Exp $" CVSID1;
+const char *CVSid1="$Id: atacmds.c,v 1.49 2003/01/04 17:34:16 pjwilliams Exp $" CVSID1;
 
 // These Drive Identity tables are taken from hdparm 5.2, and are also
 // given in the ATA/ATAPI specs for the IDENTIFY DEVICE command.  Note
@@ -156,6 +156,43 @@ int parse_attribute_def(char *pair, unsigned char *defs){
   }
 }
 
+// Function to return a string containing a list of the arguments in 
+// vendorattributeargs[] separated by commas.  The strings themselves
+// contain commas, so surrounding double quotes are added for clarity.
+// This function allocates the required memory for the string and the
+// caller must use free() to free it.  Returns NULL if the required
+// memory can't be allocated.
+char *create_vendor_attribute_arg_list(void){
+  const char **ps;
+  char *s;
+  int len;
+
+  // Calculate the required number of characters
+  len = 1;                // At least one char ('\0')
+  for (ps = vendorattributeargs; *ps != NULL; ps++) {
+    len += strlen(*ps);   // For the actual argument string
+    len += 2;             // For the surrounding double quotes
+    if (*(ps+1))
+      len += 2;           // For the ", " delimiter if required
+  }
+
+  // Attempt to allocate memory for the string
+  if (!(s = (char *)malloc(len)))
+    return NULL;
+
+  // Construct the string
+  *s = '\0';
+  for (ps = vendorattributeargs; *ps != NULL; ps++) {
+    strcat(s, "\"");
+    strcat(s, *ps);
+    strcat(s, "\"");
+    if (*(ps+1))
+      strcat(s, ", ");
+  }
+
+  // Return a pointer to the string
+  return s;
+}
 
 // A replacement for perror() that sends output to our choice of
 // printing.
diff --git a/sm5/atacmds.cpp b/sm5/atacmds.cpp
index f7c0e57ee..6ee100e92 100644
--- a/sm5/atacmds.cpp
+++ b/sm5/atacmds.cpp
@@ -29,7 +29,7 @@
 #include <stdlib.h>
 #include "atacmds.h"
 
-const char *CVSid1="$Id: atacmds.cpp,v 1.48 2003/01/03 17:25:12 ballen4705 Exp $" CVSID1;
+const char *CVSid1="$Id: atacmds.cpp,v 1.49 2003/01/04 17:34:16 pjwilliams Exp $" CVSID1;
 
 // These Drive Identity tables are taken from hdparm 5.2, and are also
 // given in the ATA/ATAPI specs for the IDENTIFY DEVICE command.  Note
@@ -156,6 +156,43 @@ int parse_attribute_def(char *pair, unsigned char *defs){
   }
 }
 
+// Function to return a string containing a list of the arguments in 
+// vendorattributeargs[] separated by commas.  The strings themselves
+// contain commas, so surrounding double quotes are added for clarity.
+// This function allocates the required memory for the string and the
+// caller must use free() to free it.  Returns NULL if the required
+// memory can't be allocated.
+char *create_vendor_attribute_arg_list(void){
+  const char **ps;
+  char *s;
+  int len;
+
+  // Calculate the required number of characters
+  len = 1;                // At least one char ('\0')
+  for (ps = vendorattributeargs; *ps != NULL; ps++) {
+    len += strlen(*ps);   // For the actual argument string
+    len += 2;             // For the surrounding double quotes
+    if (*(ps+1))
+      len += 2;           // For the ", " delimiter if required
+  }
+
+  // Attempt to allocate memory for the string
+  if (!(s = (char *)malloc(len)))
+    return NULL;
+
+  // Construct the string
+  *s = '\0';
+  for (ps = vendorattributeargs; *ps != NULL; ps++) {
+    strcat(s, "\"");
+    strcat(s, *ps);
+    strcat(s, "\"");
+    if (*(ps+1))
+      strcat(s, ", ");
+  }
+
+  // Return a pointer to the string
+  return s;
+}
 
 // A replacement for perror() that sends output to our choice of
 // printing.
diff --git a/sm5/atacmds.h b/sm5/atacmds.h
index 89360a38f..c8d717b99 100644
--- a/sm5/atacmds.h
+++ b/sm5/atacmds.h
@@ -26,7 +26,7 @@
 #define _ATACMDS_H_
 
 #ifndef CVSID1
-#define CVSID1 "$Id: atacmds.h,v 1.29 2003/01/03 17:25:12 ballen4705 Exp $\n"
+#define CVSID1 "$Id: atacmds.h,v 1.30 2003/01/04 17:34:16 pjwilliams Exp $\n"
 #endif
 
 // These are the major and minor versions for smartd and smartctl
@@ -383,4 +383,9 @@ extern const char *vendorattributeargs[];
 // else 1 if there is a problem.
 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/smartctl.c b/sm5/smartctl.c
index 8e8314e68..f262f40df 100644
--- a/sm5/smartctl.c
+++ b/sm5/smartctl.c
@@ -42,7 +42,7 @@
 #include "extern.h"
 
 extern const char *CVSid1, *CVSid2, *CVSid3, *CVSid4; 
-const char* CVSid5="$Id: smartctl.c,v 1.33 2003/01/04 08:26:10 ballen4705 Exp $"
+const char* CVSid5="$Id: smartctl.c,v 1.34 2003/01/04 17:34:16 pjwilliams Exp $"
 CVSID1 CVSID2 CVSID3 CVSID4 CVSID5 CVSID6;
 
 // This is a block containing all the "control variables".  We declare
@@ -213,9 +213,9 @@ void Usage (void){
 
 /* Print an appropriate error message for option opt when given an invalid argument, optarg */
 void printbadargmessage(int opt, const char *optarg) {
-  const char **ps;
+  char *s;
 
-  pout("=======> INVALID ARGUMENT OF -%c: %s <======= \n", opt, optarg);
+  pout("=======> INVALID ARGUMENT TO -%c: %s <======= \n", opt, optarg);
   pout("=======> VALID ARGUMENTS ARE: ");
   switch (opt) {
   case 'q':
@@ -239,11 +239,12 @@ void printbadargmessage(int opt, const char *optarg) {
      pout("error, selftest");
      break;
   case 'v':
-     // Print all strings in vendorattributeargs separated by commas.  The
-     // strings themselves contain commas, so surrounding double quotes are used
-     // for clarity.
-     for (ps = vendorattributeargs; *ps != NULL; ps++)
-       pout("\"%s\"%s", *ps, *(ps+1) ? ", " : "");
+     if (!(s = create_vendor_attribute_arg_list())) {
+       pout("\nInsufficient memory to construct argument list\n");
+       break;
+     }
+     pout("%s", s);
+     free(s);
      break;
   case 't':
      pout("offline, short, long");
diff --git a/sm5/smartctl.cpp b/sm5/smartctl.cpp
index 29eb97e13..8351ea67a 100644
--- a/sm5/smartctl.cpp
+++ b/sm5/smartctl.cpp
@@ -42,7 +42,7 @@
 #include "extern.h"
 
 extern const char *CVSid1, *CVSid2, *CVSid3, *CVSid4; 
-const char* CVSid5="$Id: smartctl.cpp,v 1.33 2003/01/04 08:26:10 ballen4705 Exp $"
+const char* CVSid5="$Id: smartctl.cpp,v 1.34 2003/01/04 17:34:16 pjwilliams Exp $"
 CVSID1 CVSID2 CVSID3 CVSID4 CVSID5 CVSID6;
 
 // This is a block containing all the "control variables".  We declare
@@ -213,9 +213,9 @@ void Usage (void){
 
 /* Print an appropriate error message for option opt when given an invalid argument, optarg */
 void printbadargmessage(int opt, const char *optarg) {
-  const char **ps;
+  char *s;
 
-  pout("=======> INVALID ARGUMENT OF -%c: %s <======= \n", opt, optarg);
+  pout("=======> INVALID ARGUMENT TO -%c: %s <======= \n", opt, optarg);
   pout("=======> VALID ARGUMENTS ARE: ");
   switch (opt) {
   case 'q':
@@ -239,11 +239,12 @@ void printbadargmessage(int opt, const char *optarg) {
      pout("error, selftest");
      break;
   case 'v':
-     // Print all strings in vendorattributeargs separated by commas.  The
-     // strings themselves contain commas, so surrounding double quotes are used
-     // for clarity.
-     for (ps = vendorattributeargs; *ps != NULL; ps++)
-       pout("\"%s\"%s", *ps, *(ps+1) ? ", " : "");
+     if (!(s = create_vendor_attribute_arg_list())) {
+       pout("\nInsufficient memory to construct argument list\n");
+       break;
+     }
+     pout("%s", s);
+     free(s);
      break;
   case 't':
      pout("offline, short, long");
diff --git a/sm5/smartd.c b/sm5/smartd.c
index f0b3e4c19..a8c7728b2 100644
--- a/sm5/smartd.c
+++ b/sm5/smartd.c
@@ -50,7 +50,7 @@
 
 // CVS ID strings
 extern const char *CVSid1, *CVSid2;
-const char *CVSid6="$Id: smartd.c,v 1.92 2003/01/03 17:25:12 ballen4705 Exp $" 
+const char *CVSid6="$Id: smartd.c,v 1.93 2003/01/04 17:34:16 pjwilliams Exp $" 
 CVSID1 CVSID2 CVSID3 CVSID4 CVSID7;
 
 // global variable used for control of printing, passing arguments, etc.
@@ -934,6 +934,8 @@ void CheckDevices(atadevices_t *atadevices, scsidevices_t *scsidevices){
 
 // Print out a list of valid arguments for the Directive d
 void printoutvaliddirectiveargs(int priority, char d) {
+  char *s;
+
   switch (d) {
   case 'd':
     printout(priority, "ata, scsi");
@@ -951,6 +953,14 @@ void printoutvaliddirectiveargs(int priority, char d) {
   case 'M':
     printout(priority, "\"once\", \"daily\", \"diminishing\", \"once,test\", \"daily,test\", \"diminishing,test\"");
     break;
+  case 'v':
+    if (!(s = create_vendor_attribute_arg_list())) {
+      printout(LOG_CRIT,"Insufficient memory to construct argument list\n");
+      break;
+    }
+    printout(priority, "%s", s);
+    free(s);
+    break;
   }
 }
 
@@ -1161,20 +1171,10 @@ int parsetoken(char *token,cfgfile *cfg){
     break;
   case 'v':
     // non-default vendor-specific attribute meaning
-    arg=strtok(NULL,delim);
-    if (!arg) {
-      // user forgot argument!
-      printout(LOG_CRIT,"File %s line %d (drive %s): Directive: %s needs attribute #,action pair\n",
-	       CONFIGFILE, lineno, name, token);
-      Directives();
-      exit(1);
-    }
-    if (parse_attribute_def(arg, cfg->attributedefs)){	
-      // user argument not recognized
-      printout(LOG_CRIT,"File %s line %d (drive %s): Directive: %s argument %s not recognized\n",
-	       CONFIGFILE, lineno, name, token, arg);
-      Directives();
-      exit(1);
+    if ((arg=strtok(NULL,delim)) == NULL) {
+      missingarg = 1;
+    } else if (parse_attribute_def(arg, cfg->attributedefs)){	
+      badarg = 1;
     }
     break;
   default:
diff --git a/sm5/smartd.cpp b/sm5/smartd.cpp
index 8215860cb..bc5e32536 100644
--- a/sm5/smartd.cpp
+++ b/sm5/smartd.cpp
@@ -50,7 +50,7 @@
 
 // CVS ID strings
 extern const char *CVSid1, *CVSid2;
-const char *CVSid6="$Id: smartd.cpp,v 1.92 2003/01/03 17:25:12 ballen4705 Exp $" 
+const char *CVSid6="$Id: smartd.cpp,v 1.93 2003/01/04 17:34:16 pjwilliams Exp $" 
 CVSID1 CVSID2 CVSID3 CVSID4 CVSID7;
 
 // global variable used for control of printing, passing arguments, etc.
@@ -934,6 +934,8 @@ void CheckDevices(atadevices_t *atadevices, scsidevices_t *scsidevices){
 
 // Print out a list of valid arguments for the Directive d
 void printoutvaliddirectiveargs(int priority, char d) {
+  char *s;
+
   switch (d) {
   case 'd':
     printout(priority, "ata, scsi");
@@ -951,6 +953,14 @@ void printoutvaliddirectiveargs(int priority, char d) {
   case 'M':
     printout(priority, "\"once\", \"daily\", \"diminishing\", \"once,test\", \"daily,test\", \"diminishing,test\"");
     break;
+  case 'v':
+    if (!(s = create_vendor_attribute_arg_list())) {
+      printout(LOG_CRIT,"Insufficient memory to construct argument list\n");
+      break;
+    }
+    printout(priority, "%s", s);
+    free(s);
+    break;
   }
 }
 
@@ -1161,20 +1171,10 @@ int parsetoken(char *token,cfgfile *cfg){
     break;
   case 'v':
     // non-default vendor-specific attribute meaning
-    arg=strtok(NULL,delim);
-    if (!arg) {
-      // user forgot argument!
-      printout(LOG_CRIT,"File %s line %d (drive %s): Directive: %s needs attribute #,action pair\n",
-	       CONFIGFILE, lineno, name, token);
-      Directives();
-      exit(1);
-    }
-    if (parse_attribute_def(arg, cfg->attributedefs)){	
-      // user argument not recognized
-      printout(LOG_CRIT,"File %s line %d (drive %s): Directive: %s argument %s not recognized\n",
-	       CONFIGFILE, lineno, name, token, arg);
-      Directives();
-      exit(1);
+    if ((arg=strtok(NULL,delim)) == NULL) {
+      missingarg = 1;
+    } else if (parse_attribute_def(arg, cfg->attributedefs)){	
+      badarg = 1;
     }
     break;
   default:
-- 
GitLab