From 6e8bdf3efe4ac9ccc679a21f9e486463f300d53e Mon Sep 17 00:00:00 2001 From: chrfranke <chrfranke@4ea69e1a-61f1-4043-bf83-b5c94c648137> Date: Wed, 7 Apr 2004 20:55:46 +0000 Subject: [PATCH] Added option -c FILE, --configfile=FILE to smartd git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@1654 4ea69e1a-61f1-4043-bf83-b5c94c648137 --- sm5/CHANGELOG | 5 ++++- sm5/smartd.8.in | 18 ++++++++++++++++-- sm5/smartd.c | 49 +++++++++++++++++++++++++++++++++++++------------ sm5/smartd.cpp | 49 +++++++++++++++++++++++++++++++++++++------------ 4 files changed, 94 insertions(+), 27 deletions(-) diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG index 8c01d7bc3..7ff2960d2 100644 --- a/sm5/CHANGELOG +++ b/sm5/CHANGELOG @@ -1,6 +1,6 @@ CHANGELOG for smartmontools -$Id: CHANGELOG,v 1.393 2004/04/07 16:41:42 card_captor Exp $ +$Id: CHANGELOG,v 1.394 2004/04/07 20:55:32 chrfranke Exp $ The most recent version of this file is: http://cvs.sourceforge.net/viewcvs.py/smartmontools/sm5/CHANGELOG?sortby=date&view=markup @@ -27,6 +27,9 @@ NOTES FOR FUTURE RELEASES: see TODO file. <ADDITIONS TO THE CHANGE LOG SHOULD BE ADDED JUST BELOW HERE, PLEASE> + [CF] Added option -c FILE, --configfile=FILE to smartd to specify + an alternate configuration FILE or '-' for standard input. + [KS] configure.in now searches for -lnsl and -lsocket for Solaris. [CF] Win32/native smartd: Added thread to combine several syslog output diff --git a/sm5/smartd.8.in b/sm5/smartd.8.in index 66eb0f66e..2725736c2 100644 --- a/sm5/smartd.8.in +++ b/sm5/smartd.8.in @@ -1,7 +1,7 @@ .ig Copyright (C) 2002-4 Bruce Allen <smartmontools-support@lists.sourceforge.net> -$Id: smartd.8.in,v 1.52 2004/04/07 16:53:45 ballen4705 Exp $ +$Id: smartd.8.in,v 1.53 2004/04/07 20:55:46 chrfranke 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 @@ -113,6 +113,20 @@ start-up. OPTIONS Long options are not supported on all systems. Use \fB\'smartd \-h\'\fP to see the available options. +.TP +.B \-c FILE, \-\-configfile=FILE +Use FILE instead of \fB/etc/smartd.conf\fP to read the configuration +directives. If the FILE does not exist, \fBsmartd\fP will print an +error message and exit. Therefore, '-c /etc/smartd.conf' can be +used to enforce the existence of the default configuration file. + +By specifying '-' as FILE, the configuration is read from standard +input. This is useful for commands like: +.nf +.B echo /dev/hdb -m user@home -M test | smartd -c - -q onecheck +.fi +to perform ad hoc checks without a configuration file. + .TP .B \-d, \-\-debug Runs \fBsmartd\fP in "debug" mode. In this mode, it displays status @@ -1588,4 +1602,4 @@ smartmontools home page at \fBhttp://smartmontools.sourceforge.net/\fP . .SH CVS ID OF THIS PAGE: -$Id: smartd.8.in,v 1.52 2004/04/07 16:53:45 ballen4705 Exp $ +$Id: smartd.8.in,v 1.53 2004/04/07 20:55:46 chrfranke Exp $ diff --git a/sm5/smartd.c b/sm5/smartd.c index 6d48a9cca..1bbaa8de5 100644 --- a/sm5/smartd.c +++ b/sm5/smartd.c @@ -98,7 +98,7 @@ int getdomainname(char *, int); /* no declaration in header files! */ extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *escalade_c_cvsid, *knowndrives_c_cvsid, *os_XXXX_c_cvsid, *scsicmds_c_cvsid, *utility_c_cvsid; -static const char *filenameandversion="$Id: smartd.c,v 1.307 2004/04/07 19:27:33 ballen4705 Exp $"; +static const char *filenameandversion="$Id: smartd.c,v 1.308 2004/04/07 20:55:31 chrfranke Exp $"; #ifdef NEED_SOLARIS_ATA_CODE extern const char *os_solaris_ata_s_cvsid; #endif @@ -109,7 +109,7 @@ extern const char *syslog_win32_c_cvsid; extern const char *int64_vc6_c_cvsid; #endif #endif -const char *smartd_c_cvsid="$Id: smartd.c,v 1.307 2004/04/07 19:27:33 ballen4705 Exp $" +const char *smartd_c_cvsid="$Id: smartd.c,v 1.308 2004/04/07 20:55:31 chrfranke Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SMARTD_H_CVSID #ifdef SYSLOG_H_CVSID @@ -139,6 +139,10 @@ static char* configfile = SMARTMONTOOLS_SYSCONFDIR "/" CONFIGFILENAME ; #else static char* configfile = "./" CONFIGFILENAME ; #endif +// configuration file "name" if read from stdin +static /*const*/ char * const configfile_stdin = "<stdin>"; +// allocated memory for alternate configuration file name +static char* configfile_alt = NULL; // command-line: when should we exit? static int quit=0; @@ -409,6 +413,9 @@ void Goodbye(void){ // delete PID file, if one was created RemovePidFile(); + // remove alternate configfile name + configfile_alt=FreeNonZero(configfile_alt, -1,__LINE__,filenameandversion); + // useful for debugging -- have we managed memory correctly? if (debugmode || (bytes && exitstatus!=EXIT_NOMEM)) PrintOut(LOG_INFO, "Memory still allocated for devices at exit is %lld bytes.\n", bytes); @@ -967,8 +974,10 @@ void Directives() { arguments to the option opt or NULL on failure. */ const char *GetValidArgList(char opt) { switch (opt) { + case 'c': + return "<FILE_NAME>, -"; case 's': - return "valid_regular_expresssion"; + return "valid_regular_expression"; case 'l': return "daemon, local0, local1, local2, local3, local4, local5, local6, local7"; case 'q': @@ -988,6 +997,8 @@ const char *GetValidArgList(char opt) { void Usage (void){ PrintOut(LOG_INFO,"Usage: smartd [options]\n\n"); #ifdef HAVE_GETOPT_LONG + PrintOut(LOG_INFO," -c NAME|-, --configfile=NAME|-\n"); + PrintOut(LOG_INFO," Read configuration file NAME or stdin [default is %s]\n\n", configfile); PrintOut(LOG_INFO," -d, --debug\n"); PrintOut(LOG_INFO," Start smartd in debug mode\n\n"); PrintOut(LOG_INFO," -D, --showdirectives\n"); @@ -1015,6 +1026,7 @@ void Usage (void){ PrintOut(LOG_INFO," -V, --version, --license, --copyright\n"); PrintOut(LOG_INFO," Print License, Copyright, and version information\n"); #else + PrintOut(LOG_INFO," -c NAME|- Read configuration file NAME or stdin [default is %s]\n", configfile); PrintOut(LOG_INFO," -d Start smartd in debug mode\n"); PrintOut(LOG_INFO," -D Print the configuration file Directives and exit\n"); PrintOut(LOG_INFO," -h Display this help and exit\n"); @@ -2902,7 +2914,8 @@ int ParseConfigLine(int entry, int lineno,char *line){ // clean up utility for ParseConfigFile() void cleanup(FILE **fpp){ if (*fpp){ - fclose(*fpp); + if (*fpp != stdin) + fclose(*fpp); *fpp=NULL; } @@ -2925,14 +2938,18 @@ int ParseConfigFile(){ char line[MAXLINELEN+2]; char fullline[MAXCONTLINE+1]; - // Open config file, if it exists - fp=fopen(configfile,"r"); - if (fp==NULL && errno!=ENOENT){ - // file exists but we can't read it - PrintOut(LOG_CRIT,"%s: Unable to open configuration file %s\n", - strerror(errno),configfile); - return -1; + // Open config file, if it exists and is not <stdin> + if (configfile != configfile_stdin) { + fp=fopen(configfile,"r"); + if (fp==NULL && (errno!=ENOENT || configfile_alt)) { + // file exists but we can't read it or it should exist due to '-c' option + PrintOut(LOG_CRIT,"%s: Unable to open configuration file %s\n", + strerror(errno),configfile); + return -1; + } } + else // read from stdin ('-c -' option) + fp = stdin; // No configuration file found -- use fake one if (fp==NULL) { @@ -3085,11 +3102,12 @@ void ParseOpts(int argc, char **argv){ char *tailptr; long lchecktime; // Please update GetValidArgList() if you edit shortopts - const char *shortopts = "l:q:dDi:p:r:Vh?"; + const char *shortopts = "c:l:q:dDi:p:r:Vh?"; #ifdef HAVE_GETOPT_LONG char *arg; // Please update GetValidArgList() if you edit longopts struct option longopts[] = { + { "configfile", required_argument, 0, 'c' }, { "logfacility", required_argument, 0, 'l' }, { "quit", required_argument, 0, 'q' }, { "debug", no_argument, 0, 'd' }, @@ -3217,6 +3235,13 @@ void ParseOpts(int argc, char **argv){ s=CheckFree(s, __LINE__,filenameandversion); } break; + case 'c': + // alternate configuration file + if (strcmp(optarg,"-")) + configfile=configfile_alt=CustomStrDup(optarg, 1, __LINE__,filenameandversion); + else // read from stdin + configfile=configfile_stdin; + break; case 'p': // output file with PID number pid_file=CustomStrDup(optarg, 1, __LINE__,filenameandversion); diff --git a/sm5/smartd.cpp b/sm5/smartd.cpp index fccb06ed1..a28f54489 100644 --- a/sm5/smartd.cpp +++ b/sm5/smartd.cpp @@ -98,7 +98,7 @@ int getdomainname(char *, int); /* no declaration in header files! */ extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *escalade_c_cvsid, *knowndrives_c_cvsid, *os_XXXX_c_cvsid, *scsicmds_c_cvsid, *utility_c_cvsid; -static const char *filenameandversion="$Id: smartd.cpp,v 1.307 2004/04/07 19:27:33 ballen4705 Exp $"; +static const char *filenameandversion="$Id: smartd.cpp,v 1.308 2004/04/07 20:55:31 chrfranke Exp $"; #ifdef NEED_SOLARIS_ATA_CODE extern const char *os_solaris_ata_s_cvsid; #endif @@ -109,7 +109,7 @@ extern const char *syslog_win32_c_cvsid; extern const char *int64_vc6_c_cvsid; #endif #endif -const char *smartd_c_cvsid="$Id: smartd.cpp,v 1.307 2004/04/07 19:27:33 ballen4705 Exp $" +const char *smartd_c_cvsid="$Id: smartd.cpp,v 1.308 2004/04/07 20:55:31 chrfranke Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SMARTD_H_CVSID #ifdef SYSLOG_H_CVSID @@ -139,6 +139,10 @@ static char* configfile = SMARTMONTOOLS_SYSCONFDIR "/" CONFIGFILENAME ; #else static char* configfile = "./" CONFIGFILENAME ; #endif +// configuration file "name" if read from stdin +static /*const*/ char * const configfile_stdin = "<stdin>"; +// allocated memory for alternate configuration file name +static char* configfile_alt = NULL; // command-line: when should we exit? static int quit=0; @@ -409,6 +413,9 @@ void Goodbye(void){ // delete PID file, if one was created RemovePidFile(); + // remove alternate configfile name + configfile_alt=FreeNonZero(configfile_alt, -1,__LINE__,filenameandversion); + // useful for debugging -- have we managed memory correctly? if (debugmode || (bytes && exitstatus!=EXIT_NOMEM)) PrintOut(LOG_INFO, "Memory still allocated for devices at exit is %lld bytes.\n", bytes); @@ -967,8 +974,10 @@ void Directives() { arguments to the option opt or NULL on failure. */ const char *GetValidArgList(char opt) { switch (opt) { + case 'c': + return "<FILE_NAME>, -"; case 's': - return "valid_regular_expresssion"; + return "valid_regular_expression"; case 'l': return "daemon, local0, local1, local2, local3, local4, local5, local6, local7"; case 'q': @@ -988,6 +997,8 @@ const char *GetValidArgList(char opt) { void Usage (void){ PrintOut(LOG_INFO,"Usage: smartd [options]\n\n"); #ifdef HAVE_GETOPT_LONG + PrintOut(LOG_INFO," -c NAME|-, --configfile=NAME|-\n"); + PrintOut(LOG_INFO," Read configuration file NAME or stdin [default is %s]\n\n", configfile); PrintOut(LOG_INFO," -d, --debug\n"); PrintOut(LOG_INFO," Start smartd in debug mode\n\n"); PrintOut(LOG_INFO," -D, --showdirectives\n"); @@ -1015,6 +1026,7 @@ void Usage (void){ PrintOut(LOG_INFO," -V, --version, --license, --copyright\n"); PrintOut(LOG_INFO," Print License, Copyright, and version information\n"); #else + PrintOut(LOG_INFO," -c NAME|- Read configuration file NAME or stdin [default is %s]\n", configfile); PrintOut(LOG_INFO," -d Start smartd in debug mode\n"); PrintOut(LOG_INFO," -D Print the configuration file Directives and exit\n"); PrintOut(LOG_INFO," -h Display this help and exit\n"); @@ -2902,7 +2914,8 @@ int ParseConfigLine(int entry, int lineno,char *line){ // clean up utility for ParseConfigFile() void cleanup(FILE **fpp){ if (*fpp){ - fclose(*fpp); + if (*fpp != stdin) + fclose(*fpp); *fpp=NULL; } @@ -2925,14 +2938,18 @@ int ParseConfigFile(){ char line[MAXLINELEN+2]; char fullline[MAXCONTLINE+1]; - // Open config file, if it exists - fp=fopen(configfile,"r"); - if (fp==NULL && errno!=ENOENT){ - // file exists but we can't read it - PrintOut(LOG_CRIT,"%s: Unable to open configuration file %s\n", - strerror(errno),configfile); - return -1; + // Open config file, if it exists and is not <stdin> + if (configfile != configfile_stdin) { + fp=fopen(configfile,"r"); + if (fp==NULL && (errno!=ENOENT || configfile_alt)) { + // file exists but we can't read it or it should exist due to '-c' option + PrintOut(LOG_CRIT,"%s: Unable to open configuration file %s\n", + strerror(errno),configfile); + return -1; + } } + else // read from stdin ('-c -' option) + fp = stdin; // No configuration file found -- use fake one if (fp==NULL) { @@ -3085,11 +3102,12 @@ void ParseOpts(int argc, char **argv){ char *tailptr; long lchecktime; // Please update GetValidArgList() if you edit shortopts - const char *shortopts = "l:q:dDi:p:r:Vh?"; + const char *shortopts = "c:l:q:dDi:p:r:Vh?"; #ifdef HAVE_GETOPT_LONG char *arg; // Please update GetValidArgList() if you edit longopts struct option longopts[] = { + { "configfile", required_argument, 0, 'c' }, { "logfacility", required_argument, 0, 'l' }, { "quit", required_argument, 0, 'q' }, { "debug", no_argument, 0, 'd' }, @@ -3217,6 +3235,13 @@ void ParseOpts(int argc, char **argv){ s=CheckFree(s, __LINE__,filenameandversion); } break; + case 'c': + // alternate configuration file + if (strcmp(optarg,"-")) + configfile=configfile_alt=CustomStrDup(optarg, 1, __LINE__,filenameandversion); + else // read from stdin + configfile=configfile_stdin; + break; case 'p': // output file with PID number pid_file=CustomStrDup(optarg, 1, __LINE__,filenameandversion); -- GitLab