From 5ad58179593b53476833f2ab4978948ccfcb89eb Mon Sep 17 00:00:00 2001 From: Chris Frey Date: Mon, 30 Apr 2012 19:38:19 -0400 Subject: [PATCH] lib: added FifoArgs API, for use in passing command line args without command line Mostly for use with applications using pppob, but may be useful elsewhere as well someday. --- src/Makefile.am | 2 + src/barry.h | 1 + src/common.h | 2 + src/fifoargs.cc | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/fifoargs.h | 112 +++++++++++++++++++++++++++++++ 5 files changed, 319 insertions(+) create mode 100644 src/fifoargs.cc create mode 100644 src/fifoargs.h diff --git a/src/Makefile.am b/src/Makefile.am index 1f3ca2e5..7f53968a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -163,6 +163,7 @@ include_barry_HEADERS = barry.h barrysync.h barrybackup.h barryalx.h \ pipe.h \ connector.h \ trim.h \ + fifoargs.h \ tzwrapper.h noinst_HEADERS = cbarry.h \ @@ -198,6 +199,7 @@ libbarry_la_SOURCES = dll.h \ builder.h builder.cc \ parser.h parser.cc \ time.h time.cc \ + fifoargs.h fifoargs.cc \ base64.h base64.cc \ bmp.h bmp-internal.h bmp.cc \ cod.h cod-internal.h cod.cc \ diff --git a/src/barry.h b/src/barry.h index 752fed7e..e5df9b23 100644 --- a/src/barry.h +++ b/src/barry.h @@ -79,6 +79,7 @@ #include "vsmartptr.h" #include "pipe.h" #include "connector.h" +#include "fifoargs.h" // Include the JDW Debug Parser classes #include "dp_codinfo.h" diff --git a/src/common.h b/src/common.h index 5c7f7aba..3ed51502 100644 --- a/src/common.h +++ b/src/common.h @@ -51,6 +51,8 @@ #define BLACKBERRY_CHARSET "WINDOWS-1252" +#define BARRY_FIFO_NAME "/tmp/barry_fifo_args" + namespace Barry { /// See also the LogLock class. diff --git a/src/fifoargs.cc b/src/fifoargs.cc new file mode 100644 index 00000000..0cd7781e --- /dev/null +++ b/src/fifoargs.cc @@ -0,0 +1,202 @@ +/// +/// \file fifoargs.cc +/// Class for passing command line arguments via fifo instead +/// of command line. +/// + +/* + Copyright (C) 2012, Net Direct Inc. (http://www.netdirect.ca/) + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License in the COPYING file at the + root directory of this project for more details. +*/ + +#include "fifoargs.h" +#include "error.h" +#include "common.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace Barry { + +////////////////////////////////////////////////////////////////////////////// +// FifoArgs class + +std::ostream& FifoArgs::Write(std::ostream &os) const +{ + if( m_pin.Valid() ) + os << "Pin " << m_pin.Str() << endl; + if( m_password.size() ) + os << "Password " << m_password << endl; + if( m_log_filename.size() ) + os << "LogFilename " << m_log_filename << endl; + if( m_use_serial_mode ) + os << "UseSerialMode" << endl; + if( m_verbose ) + os << "Verbose" << endl; + + return os; +} + +std::istream& FifoArgs::Read(std::istream &is) +{ + string line, token, arg; + + // start fresh + Clear(); + + while( getline(is, line) ) { + istringstream iss(line); + iss >> token >> ws; + + if( token == "Pin" ) + iss >> m_pin; + else if( token == "Password" ) + getline(iss, m_password); + else if( token == "LogFilename" ) + getline(iss, m_log_filename); + else if( token == "UseSerialMode" ) + m_use_serial_mode = true; + else if( token == "Verbose" ) + m_verbose = true; + } + + return is; +} + +void FifoArgs::Clear() +{ + m_pin.Clear(); + m_password.clear(); + m_log_filename.clear(); + m_use_serial_mode = false; + m_verbose = false; +} + + +////////////////////////////////////////////////////////////////////////////// +// FifoServer class + +FifoServer::FifoServer(const FifoArgs &args) + : m_args(args) + , m_created(false) +{ + int m_fifo = mkfifo(BARRY_FIFO_NAME, 0660); + if( m_fifo != 0 ) + throw ErrnoError("Cannot open Barry argument fifo", errno); + m_created = true; +} + +FifoServer::~FifoServer() +{ + Cleanup(); +} + +bool FifoServer::Serve(int timeout_sec) +{ + if( !m_created ) + return false; + + // man fifo(7) says that opening write-only in non-blocking mode + // will fail until the other side opens for read. So continue + // to attempt opens until out of time. + timeout_sec *= 4; + while( timeout_sec-- ) { + // attempt to open in non-blocking mode + int fd = open(BARRY_FIFO_NAME, O_WRONLY | O_NONBLOCK); + if( fd == -1 ) { + usleep(250000); + continue; + } + + ostringstream oss; + m_args.Write(oss); + int written = write(fd, oss.str().data(), oss.str().size()); + close(fd); + + // only success if we wrote all the data + return written == (int)oss.str().size(); + } + + // timeout + return false; +} + +void FifoServer::Cleanup() +{ + if( m_created ) { + unlink(BARRY_FIFO_NAME); + m_created = false; + } +} + + +////////////////////////////////////////////////////////////////////////////// +// FifoClient class + +FifoClient::FifoClient() +{ +} + +/// Tries to open the fifo and read the arguments from it. +/// If it fails in any way, or timeout, returns false. +bool FifoClient::Fetch(int timeout_sec) +{ + // See man fifo(7). Should always succeed, as long as + // the file exists and permissions allow. + int fd = open(BARRY_FIFO_NAME, O_RDONLY | O_NONBLOCK); + if( fd == -1 ) + return false; + + string sbuf; + timeout_sec *= 4; + while( timeout_sec-- ) { + char buf[4096]; + int r = read(fd, buf, sizeof(buf)); + + if( r == 0 ) { + // only consider this the end of file if + // we've already read something, otherwise we close + // before the server has a chance to speak up + if( sbuf.size() ) + break; + else + usleep(250000); + } + else if( r < 0 ) { + usleep(250000); + continue; + } + else { + timeout_sec++; + sbuf.append(buf, r); + } + } + close(fd); + + // parse + istringstream iss(sbuf); + m_args.Read(iss); + return true; +} + +} // Barry namespace + diff --git a/src/fifoargs.h b/src/fifoargs.h new file mode 100644 index 00000000..722145be --- /dev/null +++ b/src/fifoargs.h @@ -0,0 +1,112 @@ +/// +/// \file fifoargs.h +/// Class for passing command line arguments via fifo instead +/// of command line. +/// + +/* + Copyright (C) 2012, Net Direct Inc. (http://www.netdirect.ca/) + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License in the COPYING file at the + root directory of this project for more details. +*/ + +#ifndef __BARRY_FIFOARGS_H__ +#define __BARRY_FIFOARGS_H__ + +#include "dll.h" +#include "pin.h" +#include + +namespace Barry { + +// +// FifoArgs +// +/// Contains argument variables to be passed through the FIFO. +/// It is no coincidence that there is a close connection to this +/// set of arguments and the arguments given to the pppob program. +/// +struct BXEXPORT FifoArgs +{ + Pin m_pin; + std::string m_password; + std::string m_log_filename; + bool m_use_serial_mode; + bool m_verbose; + + FifoArgs() + : m_use_serial_mode(false) + , m_verbose(false) + { + } + + std::ostream& Write(std::ostream &os) const; + std::istream& Read(std::istream &is); + + void Clear(); +}; + +// +// FifoServer +// +/// Accepts a FifoArgs struct, and creates the necessary fifo for transfer. +/// To use, create the object, then execute the program (eg. pppob), and +/// then call Serve() with a given timeout in seconds. +/// +/// This class deletes the fifo in the destructor, or explicitly, with +/// the Cleanup() call. +/// +/// Only arguments that are valid are sent. +/// +class BXEXPORT FifoServer +{ + const FifoArgs &m_args; + bool m_created; + +public: + explicit FifoServer(const FifoArgs &args); + ~FifoServer(); + + /// Serves the given arguments through the fifo. Returns + /// false on timeout. + bool Serve(int timeout_sec); + + /// Deletes the fifo. Called automatically by destructor. + void Cleanup(); +}; + +// +// FifoClient +// +/// Searches for a fifo and opens and reads it if available. Use +/// Fetch() with a given timeout to perform the read attempt. +/// Use GetArgs() to access the filled FifoArgs struct. +/// +class BXEXPORT FifoClient +{ + FifoArgs m_args; + +public: + FifoClient(); + + /// Tries to open the fifo and read the arguments from it. + /// If it fails in any way, or timeout, returns false. + bool Fetch(int timeout_sec); + + const FifoArgs& GetArgs() const { return m_args; } +}; + +} // Barry namespace + +#endif + -- 2.11.4.GIT