2424#include < sys/types.h>
2525#include < dirent.h>
2626#include < sys/stat.h>
27+ #include < fcntl.h>
28+ #include < errno.h>
2729
2830using namespace AliceO2 ::InfoLogger;
2931
@@ -34,8 +36,12 @@ void print_usage()
3436 printf (" Options: \n " );
3537 printf (" -s [severity] Possible values: Info (default), Error, Fatal, Warning, Debug.\n " );
3638 printf (" -o[key]=[value] Set a message field. Valid keys: context (Facility, Role, System, Detector, Partition, Run) and message options (Severity, Level, ErrorCode, SourceFile, SourceLine).\n " );
37- printf (" -x If set, reads data coming on stdin line by line.\n " );
39+ printf (" -x If set, read data coming on stdin line by line.\n " );
3840 printf (" and transmit them as messages (1 line = 1 message).\n " );
41+ printf (" -f [file] Same as -x, but from a file.\n " );
42+ printf (" -c When -f selected, create a FIFO (mkfifo) to read from. It is removed after use.\n " );
43+ printf (" -l When -f selected, loop over file continuously.\n " );
44+ printf (" -v Verbose mode (file operations, etc).\n " );
3945 printf (" -h This help.\n " );
4046}
4147
@@ -145,7 +151,12 @@ pid_t findPipeProcess()
145151int main (int argc, char ** argv)
146152{
147153
148- int optFromStdin = 0 ; // 1 if logging from stdin, 0 when taking input from command line
154+ int optFromFile = 0 ; // 1 if logging from a file (stdin or pipe), 0 when taking input from command line
155+ int inputFd = -1 ; // file descriptor used for input, if any
156+ std::string inputPath = " " ; // path to file to read from, if any
157+ bool createFifo = 0 ; // if set, create a FIFO
158+ bool loopInput = 0 ; // if set, loop on file (useful for fifo mode)
159+ bool verbose = 0 ; // if set, prints messages about file operations
149160
150161 InfoLogger::InfoLoggerMessageOption msgOptions = InfoLogger::undefinedMessageOption;
151162 msgOptions.severity = InfoLogger::Severity::Info;
@@ -157,7 +168,7 @@ int main(int argc, char** argv)
157168 char option;
158169
159170 // read options
160- while ((option = getopt (argc, argv, " s:xo:h " )) != -1 ) {
171+ while ((option = getopt (argc, argv, " s:xo:hf:clv " )) != -1 ) {
161172 switch (option) {
162173
163174 case ' s' : {
@@ -171,7 +182,8 @@ int main(int argc, char** argv)
171182 } break ;
172183
173184 case ' x' : {
174- optFromStdin = 1 ;
185+ optFromFile = 1 ;
186+ inputFd = fileno (stdin);
175187 // try to find process sending messages to stdin
176188 pid_t pid = findPipeProcess ();
177189 if (pid != 0 ) {
@@ -193,6 +205,23 @@ int main(int argc, char** argv)
193205 break;
194206*/
195207
208+ case ' c' : {
209+ createFifo = 1 ;
210+ } break ;
211+
212+ case ' l' : {
213+ loopInput = 1 ;
214+ } break ;
215+
216+ case ' v' : {
217+ verbose = 1 ;
218+ } break ;
219+
220+ case ' f' : {
221+ inputPath = optarg;
222+ optFromFile = 1 ;
223+ } break ;
224+
196225 case ' h' :
197226 print_usage ();
198227 return 0 ;
@@ -221,25 +250,83 @@ int main(int argc, char** argv)
221250
222251 // todo: catch exceptions
223252
224- // also read from stdin if option set */
225- if (optFromStdin) {
226- LineBuffer lb; // buffer for input lines
227- std::string msg;
228- int eof;
253+ // also read from file if option set */
254+ if (optFromFile) {
255+
256+ if (createFifo) {
257+ bool isOk = 0 ;
258+ int err = 0 ;
259+ if (mkfifo (inputPath.c_str (), 0666 )) {
260+ err = errno;
261+ if (err == EEXIST) {
262+ // is the existing file a fifo ?
263+ struct stat statbuf;
264+ if (stat (inputPath.c_str (), &statbuf) == 0 ) {
265+ if (S_ISFIFO (statbuf.st_mode )) {
266+ // the FIFO already exists
267+ isOk = 1 ;
268+ }
269+ }
270+ }
271+ } else {
272+ if (verbose) printf (" FIFO %s created\n " , inputPath.c_str ());
273+ isOk = 1 ;
274+ }
275+ if (!isOk) {
276+ printf (" Failed to create FIFO %s : %s\n " , inputPath.c_str (), strerror (err));
277+ return -1 ;
278+ }
279+ }
229280
230- // read lines from stdin until EOF, and send them as log messages
231281 for (;;) {
232- eof = lb.appendFromFileDescriptor (fileno (stdin), -1 );
282+
283+ if (inputFd < 0 ) {
284+ inputFd = open (inputPath.c_str (), O_RDONLY);
285+ if (inputFd < 0 ) {
286+ printf (" Failed to open %s : %s\n " , inputPath.c_str (), strerror (errno));
287+ return -1 ;
288+ }
289+ if (verbose) printf (" Input file opened = %d\n " ,inputFd);
290+ }
291+
292+ LineBuffer lb; // buffer for input lines
293+ std::string msg;
294+ int eof;
295+
296+ // read lines from stdin until EOF, and send them as log messages
233297 for (;;) {
234- if (lb.getNextLine (msg)) {
235- // no line left
298+ eof = lb.appendFromFileDescriptor (inputFd, -1 );
299+ for (;;) {
300+ if (lb.getNextLine (msg)) {
301+ // no line left
302+ break ;
303+ }
304+ // infoLogger_msg_xt(UNDEFINED_STRING,UNDEFINED_INT,UNDEFINED_INT,facility,severity,level,msg);
305+ theLog->log (msgOptions, msgContext, " %s" , msg.c_str ());
306+ }
307+ if (eof)
236308 break ;
237- }
238- // infoLogger_msg_xt(UNDEFINED_STRING,UNDEFINED_INT,UNDEFINED_INT,facility,severity,level,msg);
239- theLog->log (msgOptions, msgContext, " %s" , msg.c_str ());
240309 }
241- if (eof)
310+
311+ if (inputFd>0 ) {
312+ if (verbose) printf (" Input file closed\n " );
313+ close (inputFd);
314+ inputFd = -1 ;
315+ }
316+
317+ if (!loopInput) {
242318 break ;
319+ }
320+ }
321+
322+ }
323+
324+ // remove fifo after use
325+ if (createFifo) {
326+ if (unlink (inputPath.c_str ())) {
327+ printf (" Failed to remove %s\n " , inputPath.c_str ());
328+ } else {
329+ if (verbose) printf (" FIFO %s removed\n " , inputPath.c_str ());
243330 }
244331 }
245332
0 commit comments