* logrunner.c
* (c) Peter Roozemaal, feb 2003
*
- * $Id: logrunner.cpp,v 1.4 2007-10-27 08:46:21 arjen Exp $
+ * $Id: logrunner.cpp,v 1.6 2007-12-10 16:12:37 arjen Exp $
*
* 1) compile,
* 2) Add 'logfile' elements to the gnucomo configuration file
"<hostname> is the gnucomo data collection server\n"
"Options are:\n"
" -1: one-shot; stop after a single pass over one of the configured logfiles\n"
+ " -c <name>: specify alternative configuration name, default is \'gnucomo\'\n"
+ " -l <file>: Read input from logfile <file>.\n"
" -p <number>: set IP port number to connect to\n"
- " -c <file>: specify alternative configuration file, default is \'logrunner.conf\'\n"
+ " -s <file>: Use <file> as the status file instead of the default.\n"
+ " -v Verbose output\n"
"If no hostname is specified, logrunner sends output to stdout\n";
class LogFile {
void add_filter(String filter_expression)
{
filter.push_back(filter_expression);
- std::cerr << "add_filter, filter size is " << filter.size() << "\n";
}
void do_file();
static std::list<LogFile> logs_to_run;
String confname = "gnucomo";
-static const char* statusname = "/var/lib/logrunner.status";
-static const char* newstatusname = "/var/lib/logrunner.status.new";
+static char* statusname = "/var/lib/logrunner.status";
+static char* newstatusname = "/var/lib/logrunner.status.new";
static const char *hostname = NULL;
static int port = 2996; /* random magic number */
static int out_stream = 1;
static int oneshot = 0;
+static int verbose = 0;
static int something_has_changed = 0;
void xml_header(String type)
{
+ struct hostent *host;
char buffer[256];
*buffer = 0;
gethostname(buffer, sizeof(buffer));
- xsend("<?xml version='1.0'?>\n");
+
+ // Try to obtain the official name of the host (FQDN)
+
+ host = gethostbyname(buffer);
+ if (host != NULL)
+ {
+ strcpy(buffer, host->h_name);
+ }
+
+ xsend("<?xml version='1.0'?>\n");
xsend("<gcmt:message xmlns:gcmt=\"http://gnucomo.org/transport/\">\n");
xsend("<gcmt:header>\n<gcmt:hostname>");
xsend(buffer);
close(fd);
fd = -1;
}
- std::cerr << "@@@ logfile: logrotate detected: " << name << "\n";
+ if (verbose)
+ {
+ std::cerr << "@@@ logfile: logrotate detected: " << name << "\n";
+ }
inode = statinfo.st_ino;
position = 0;
}
std::cerr << "!!! logfile: open failed: " << name << ", " << strerror(errno) << "\n";
return;
}
- std::cerr << "*** logfile: opened: " << name;
- std::cerr << "\n*** logfile: resumed read from position ";
- std::cerr << (long) lseek(fd, position, SEEK_SET) << "\n";
- std::cerr << "This logfile has " << filter.size() << " filters.\n";
+ lseek(fd, position, SEEK_SET);
+
+ if (verbose)
+ {
+ std::cerr << "*** logfile: opened: " << name;
+ std::cerr << "\n*** logfile: resumed read from position ";
+ std::cerr << position << "\n";
+ std::cerr << "This logfile has " << filter.size() << " filters.\n";
+ }
}
copy_data();
{
char buffer[4096];
int ndata;
+ String logline("");
/* read data and dump to output */
- ndata = read(fd, buffer, sizeof(buffer));
+ ndata = read(fd, buffer, sizeof(buffer)-1);
if ( ndata > 0 )
{
xml_header(type);
// Another line found - make the split.
*nextline++ = '\0';
- String logline(line);
+ logline += line;
- // See if have to select the host and apply filters to this log entry
+ // See if we have to select the host and apply filters to this log entry
bool filtered_out = false;
write(out_stream, logline, ~logline);
write(out_stream, "</gcmt:raw>\n", 12);
}
- else
+ else if (verbose)
{
- std::cerr << logline << " is filtred out.\n";
+ std::cerr << logline << " is filtered out.\n";
}
line = nextline;
+ logline = "";
+ }
+ else
+ {
+ // We have a buffer full of data but no newline.
+ // Flush the buffer into logline and continue reading.
+
+ nextline[0] = '\0';
+ logline += line;
+ line = nextline;
}
}
if (line != nextline)
}
position += ndata - (nextline - line);
ndata -= line - buffer;
- ndata += read(fd, buffer + (nextline - line), sizeof(buffer) - (nextline - line));
+ ndata += read(fd, buffer + (nextline - line), sizeof(buffer) - 1 - (nextline - line));
}
xml_footer();
something_has_changed = 1;
std::list<LogFile>::iterator lf = logs_to_run.begin();
while (lf != logs_to_run.end())
{
- std::cerr << "Write status for " << lf->pathname() << "\n";
+ if (verbose)
+ {
+ std::cerr << "Write status for " << lf->pathname() << "\n";
+ }
statusfile << lf->status() << "\n";
lf++;
}
{
if (lf->pathname() == String(buffer))
{
- std::cerr << "Read status for " << lf->pathname() << "\n";
+ if (verbose)
+ {
+ std::cerr << "Read status for " << lf->pathname() << "\n";
+ }
lf->update_status(ino, pos);
}
lf++;
logfilename = cfg.find_parameter("logfile", "name", l);
while (logfilename != String(""))
{
- std::cerr << "Configuration for logfile " << logfilename << "\n";
logfiletype = cfg.find_parameter("logfile", "type", l);
fromhost = cfg.find_parameter("logfile", "fromhost", l);
- std::cerr << "LogFile " << logfilename << " of type " << logfiletype << " from host " << fromhost << "\n";
+ if (verbose)
+ {
+ std::cerr << "LogFile " << logfilename << " of type "
+ << logfiletype << " from host " << fromhost << "\n";
+ }
LogFile lf(logfilename, logfiletype, fromhost);
String exp = cfg.find_parameter("logfile", "filter", l, f);
while (exp != "")
{
- std::cerr << "Adding filter " << exp << "\n";
lf.add_filter(exp);
f++;
}
logs_to_run.push_back(lf);
- std::cerr << "Logfile added to list.\n";
l++;
logfilename = cfg.find_parameter("logfile", "name", l);
- std::cerr << "Next logfile = " << logfilename << "\n";
}
}
void process_options(int argc, char* argv[])
{
- const char* const options = "1c:p:";
+ const char* const options = "1c:l:p:s:v";
int opt;
+ String logfilename;
+
opt = getopt(argc, argv, options);
while ( opt != -1 )
{
case 'c':
confname = strdup(optarg);
break;
+ case 'l':
+ logfilename = optarg;
+ break;
case 'p':
port = atoi(optarg);
break;
+ case 's':
+ statusname = strdup(optarg);
+ newstatusname = (char *)malloc(strlen(statusname) + 6);
+ strcpy(newstatusname, statusname);
+ strcat(newstatusname, ".new");
+ break;
+ case 'v':
+ verbose = 1;
+ break;
default:
fputs(usage, stderr);
exit(2);
fputs(usage, stderr);
exit(2);
}
+
+ if (logfilename)
+ {
+ LogFile lf(logfilename, String("system log"), String(""));
+ logs_to_run.push_back(lf);
+ }
}
int main(int argc, char* argv[])
exit(1);
}
- read_config(cfg);
+ if (logs_to_run.empty())
+ {
+ read_config(cfg);
+ }
read_status();
set_signal_handler();
std::list<LogFile>::iterator lf = logs_to_run.begin();
while (lf != logs_to_run.end() && !(something_has_changed && oneshot))
{
- std::cerr << "Scanning logfile " << lf->pathname() << "\n";
lf->do_file();
lf++;
}