2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
21 #include <sys/types.h>
29 #include <boost/scoped_array.hpp>
31 #include "logread.hxx"
36 logread::logread(string filename, bool _goto_end)
38 this->filename = filename;
45 /// Reset line state engine
52 line_complete = false;
55 /// Skip initial content. Useful when parsing /var/log/messages
56 void logread::goto_end()
59 if (stat(filename.c_str(), &my_stat) == 0) {
60 logsize = my_stat.st_size;
61 logsize_old = logsize;
68 // check if size changed
69 if (check_changed()) {
70 if (logsize > logsize_old) {
71 string logChanges = getLogChanges();
74 extractSingeLine (logChanges);
75 line_complete == true ? processLine() : processUnfinishedLine();
76 } while (!logChanges.empty());
78 reset(); // file got truncated
80 logsize_old = logsize;
84 /// Check if file is modified
85 bool logread::check_changed()
90 if (stat(filename.c_str(), &my_stat) == 0
91 && my_stat.st_size != logsize)
93 logsize = my_stat.st_size;
100 /// Get changed content since last read
101 string logread::getLogChanges()
104 ifstream log( filename.c_str(), ifstream::in );
105 if ( !log.is_open() )
109 int size = logsize-logsize_old;
111 boost::scoped_array<char> read_buffer( new char[ size + 1 ] );
112 log.seekg( logsize_old, fstream::beg );
113 if ( log.rdstate() != fstream::goodbit )
114 throw runtime_error("can't seek in file " + filename);
115 log.read( read_buffer.get(), size );
116 if ( log.rdstate() != fstream::goodbit )
117 throw runtime_error("error reading from file " + filename);
120 read_buffer[size] = 0;
121 string changes( read_buffer.get() );
126 /// Extract a single line from input buffer
127 void logread::extractSingeLine(string &input)
129 string::size_type rtn_pos, copysize;
133 line_complete = false;
137 rtn_pos = input.find("\n", 0);
139 // complete line or even multi-line
140 if (rtn_pos != string::npos)
143 copysize = input.length();
145 line.append (input.c_str(), copysize);
147 // Erase data from the input buffer
148 if (rtn_pos == string::npos) // no return found
149 input.erase (0, copysize);
151 // also erase the return
152 input.erase (0, copysize+1);
153 line_complete = true;
160 class logread_syslog : public logread
163 logread_syslog() : logread("messages", false) {};
167 cout << "finished: " << line << endl;
170 void processUnfinishedLine()
172 cout << "unfinished: " << line << endl;
178 logread_syslog messages;