libassa-3.5.1/0000775000076400007640000000000011757571327010170 500000000000000libassa-3.5.1/assa/0000775000076400007640000000000011757571324011114 500000000000000libassa-3.5.1/assa/Pipe.h0000644000076400007640000000535310321630770012071 00000000000000// -*- c++ -*- //------------------------------------------------------------------------------ // $Id: Pipe.h,v 1.3 2005/10/08 02:42:00 vlg Exp $ //------------------------------------------------------------------------------ // Pipe.h //------------------------------------------------------------------------------ // Copyright (C) 1997-2002 Vladislav Grinchenko // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. //------------------------------------------------------------------------------ #ifndef PIPE_H #define PIPE_H #include #include #include "assa/Logger.h" namespace ASSA { /** @file Pipe.h * A wrapper around UNIX popen()/pclose() standard library calls. */ class Pipe { public: /** * A no-op constructor */ Pipe (); /** * Destructor calls close () first in an attempt to close opened pipe. */ ~Pipe (); /** * Starts a subshell and feed it the string cmd_ to be executed. * The pipe is created and attached to the standard input or standard * output of the subprocess, according to whether type_ is either "r" * (read) or "w" (write). The other end of the pipe is returned to the * calling code as a standard I/O stream, FILE, ready for buffered use * with fprintf(), fscanf(), fgets, etc. * * @see Fork * @param cmd_ command to execute * @param type_ "w" for write pipe and "r" for read pipe * @return pointer to a standard I/O stream. In case of error, * NULL is returned with errno set to indicate the type of error * encountered. */ FILE* open (const string& cmd_, const string& type_); /** * Close the pipe. The subprocess' status is collected to ensure * that the child process have finished. * * @return 0 on success; -1 on error. */ int close (); /** * Kill subprocess with SIGTERM. You should most probably call * close() afterwards to collect child process' status. * * @see close() * @return 0 on success, -1 if kill(2) failed. */ int kill (); /** Get subprocess' PID. */ pid_t pid () const; /** Get pipe's standard I/O file pointer */ FILE* fp () const; /** Get pipe's file descriptor */ int fd () const; private: Pipe (const Pipe&); Pipe& operator= (const Pipe&); private: /** * A standard I/O stream descriptor */ FILE* m_fp; /** * Supbrocess' PID */ pid_t m_child_pid; }; inline pid_t Pipe::pid () const { return m_child_pid; } inline int Pipe::fd () const { return fileno (m_fp); } inline FILE* Pipe::fp () const { return m_fp; } } // end namespace ASSA #endif // PIPE_H libassa-3.5.1/assa/UNIXAddress.cpp0000644000076400007640000000305510457565336013634 00000000000000// -*- c++ -*- //------------------------------------------------------------------------------ // UNIXAddress.C //------------------------------------------------------------------------------ // Copyright (C) 1997-2002 Vladislav Grinchenko // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. //------------------------------------------------------------------------------ // Created: 03/22/99 //------------------------------------------------------------------------------ #include "assa/UNIXAddress.h" #if !defined (WIN32) using namespace ASSA; UNIXAddress:: UNIXAddress (const char* socket_name_) { trace("UNIXAddress::UNIXAddress(char* name_)"); size_t len; m_address.sun_family = AF_UNIX; if ( (len = strlen(socket_name_)) > sizeof(m_address.sun_path) ) { EL((ASSAERR,"Socket path name is too long (%d bytes)\n", len)); setstate (Address::badbit); } strcpy (m_address.sun_path, socket_name_); } UNIXAddress:: UNIXAddress (SA* saddr_) { trace("UNIXAddress::UNIXAddress(SA_UN*)"); SA_UN* sa_un = (SA_UN*) saddr_; m_address.sun_family = AF_UNIX; size_t len = strlen(sa_un->sun_path); if ( len > sizeof (m_address.sun_path) - 1 ) { EL((ASSAERR,"Socket path name is too long (%d bytes)\n", len)); setstate (Address::badbit); } strcpy(m_address.sun_path, sa_un->sun_path); } #endif /* !def WIN32 */ libassa-3.5.1/assa/PriorityQueue_STLPQ.h0000644000076400007640000000744407573542761015031 00000000000000// -*- c++ -*- //------------------------------------------------------------------------------ // PriorityQueue_STLPQ.h //------------------------------------------------------------------------------ // Copyright (c) 1999 by Vladislav Grinchenko // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. //------------------------------------------------------------------------------ // Created: 09/29/1999 //------------------------------------------------------------------------------ #ifndef PRIORITY_QUEUE_STLPQ_H #define PRIORITY_QUEUE_STLPQ_H #include #include #include #include using namespace std; #include "assa/Timer.h" namespace ASSA { /** @file PriorityQueue_STLPQ.h Priority Queue implementation based on STL priority_queue. */ template< class T, class Compare > class PriorityQueue_STLPQ : public PriorityQueue_Impl< T, Compare > { public: ~PriorityQueue_STLPQ (); void insert (const T&); T pop (); const T& top () const; bool remove (const int); size_t size (); void dump (); private: priority_queue, Compare> m_queue; }; template< class T, class Compare> inline PriorityQueue_STLPQ:: ~PriorityQueue_STLPQ () { trace("PriorityQueue_STLPQ::~PriorityQueue_STLPQ"); while ( m_queue.size () ) { delete m_queue.top (); m_queue.pop (); } } template< class T, class Compare> inline void PriorityQueue_STLPQ:: insert (const T& t_) { trace("PriorityQueue_STLPQ::insert"); m_queue.push (t_); } template< class T, class Compare> inline T PriorityQueue_STLPQ:: pop () { trace("PriorityQueue_STLPQ::pop"); T t = m_queue.top (); m_queue.pop (); return t; } template< class T, class Compare> inline const T& PriorityQueue_STLPQ:: top () const { trace("PriorityQueue_STLPQ::top"); return (const T&) m_queue.top (); } /******************************************************************************* STL priority queue doesn't allow to remove arbitrary element from the queue. Only top element can be removed. To search for the element, I extract top one, and if it doesn't match my search, put it into list<>. When either found or reached end of queue, I restore all elements in the list<> back to the priority queue. This needs rethinking! *******************************************************************************/ template< class T, class Compare> bool PriorityQueue_STLPQ:: remove (const int id_) { trace("PriorityQueue_STLPQ::remove"); list t_list; register Timer* t_ptr = 0; register int cnt = 0; while (m_queue.size () > 0) { t_ptr = m_queue.top (); if (t_ptr->getHandler ()-> id() == id_) { delete t_ptr; cnt++; } else { t_list.push_back (t_ptr); } m_queue.pop (); } // Restore queue list::iterator i; for (i = t_list.begin (); i != t_list.end (); i++) { m_queue.push (*i); } return cnt; } template< class T, class Compare> inline size_t PriorityQueue_STLPQ:: size () { return m_queue.size (); } template< class T, class Compare> inline void PriorityQueue_STLPQ:: dump () { trace("PriorityQueue_STLPQ::dump"); list t_list; register Timer* t_ptr = 0; DL((TRACE,"======TimerQueue start=======\n")); while (m_queue.size () > 0) { t_ptr = m_queue.top (); t_ptr->dump (); t_list.push_back (t_ptr); } DL((TRACE,"======TimerQueue end=========\n")); list::iterator i; for (i = t_list.begin (); i != t_list.end (); i++) { m_queue.push (*i); } } } // end namespace ASSA #endif /* PRIORITY_QUEUE_STLPQ_H */ libassa-3.5.1/assa/IniFile.cpp0000644000076400007640000001445510301247600013043 00000000000000// -*- c++ -*- //------------------------------------------------------------------------------ // $Id: IniFile.cpp,v 1.7 2005/08/19 03:18:24 vlg Exp $ //------------------------------------------------------------------------------ // IniFile.cpp //------------------------------------------------------------------------------ // Copyright (C) 2003,2004 Vladislav Grinchenko // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // Date: Sat Sep 6 00:17:52 EDT 2003 //------------------------------------------------------------------------------ #include #include #include using namespace ASSA; IniFile:: IniFile (const string& fname_) : m_fname (fname_), m_section_pttrn ("\\[[a-zA-Z0-9]+.*] *$"), m_tuple_pttrn ("^[ \t]*[a-zA-Z0-9]+.* *= *.*"), m_comment_pttrn ("^#.*$") { trace_with_mask ("IniFile::IniFile", INIFILE); } IniFile:: ~IniFile () { trace_with_mask ("IniFile::~IniFile", INIFILE); m_config.clear (); } int IniFile:: load () { trace_with_mask ("IniFile::load", INIFILE); const int size = 1024; char inbuf [size]; string line; string name; string value; int ret = -1; m_stream.open (m_fname.c_str (), std::ios::in); if (!m_stream) { goto done; } while (m_stream) { m_stream.getline (inbuf, size, '\n'); DL((INIFILE,"Input: \"%s\"\n", inbuf)); if (::strlen (inbuf) == 0 || m_comment_pttrn.match (inbuf) == 0) { continue; } line = inbuf; if (m_section_pttrn.match (inbuf) == 0) { if (trim_section_name (line) < 0) { goto done; } m_config.push_back (sect_type (line, std::list ())); } else if (m_tuple_pttrn.match (inbuf) == 0) { if (Utils::split_pair (line, '=', name, value) < 0) { goto done; } Utils::trim_sides (name); Utils::trim_sides (value); m_config.back ().second.push_back (tuple_type (name, value)); } else { goto done; } } /** From N.M.Josuttis, "The C++ Standard Library", Sec. 13.9 File Access: "Clear eofbit and failbit set due to the end-of-file. Note that after the processing of a file, clear() must be called to clear the state flags that are set at end-of-file. This is required because the stream object is used for multiple files. open() NEVER clears any state flags. Thus, if a stream was not in a good state, after closing and reopening it, you still have to call clear() to get to a good state. This is also the case, if you open a different file." */ ret = 0; done: if (ret < 0) { DL((INIFILE, "Parse error: illegal syntax!\n")); } m_stream.clear (); m_stream.close (); return ret; } int IniFile:: sync (const string& fname_) { trace_with_mask ("IniFile::sync(fname)", INIFILE); ::unlink (fname_.c_str ()); m_stream.open (fname_.c_str (), std::ios::app | std::ios::out); if (!m_stream) { EL((INIFILE,"Failed to open(\"%s\", app|out)\n", fname_.c_str ())); return -1; } const_config_iterator i = m_config.begin (); const_tuple_iterator j; while (i != m_config.end ()) { m_stream << "[" << (*i).first << "]\n"; j = (*i).second.begin (); while (j != (*i).second.end ()) { m_stream << (*j).first << "=" << (*j).second << "\n"; j++; } m_stream << "\n"; i++; } m_stream.clear (); m_stream.close (); return 0; } void IniFile:: dump () const { trace_with_mask ("IniFile::dump", INIFILE); const_config_iterator i = m_config.begin (); const_tuple_iterator j; DL((INIFILE,"============= Start =================\n")); while (i != m_config.end ()) { DL((INIFILE, "[%s]\n", (*i).first.c_str ())); j = (*i).second.begin (); while (j != (*i).second.end ()) { DL((INIFILE, " %s=\%s\n", (*j).first.c_str (), (*j).second.c_str ())); j++; } i++; } DL((INIFILE,"============== End =================\n")); } string IniFile:: get_value (const string& section_, const string& name_) const { const_config_iterator i = m_config.begin (); const_tuple_iterator j; string ret (""); while (i != m_config.end ()) { if ((*i).first == section_) { j = (*i).second.begin (); while (j != (*i).second.end ()) { if ((*j).first == name_) { ret = (*j).second; break; } j++; } } i++; } return ret; } void IniFile:: add_section (const string& section_) { const_config_iterator i = find_section (section_); if (i == m_config.end ()) { m_config.push_back (sect_type (section_, std::list ())); } } IniFile::config_iterator IniFile:: find_section (const string& section_) { config_iterator i = m_config.begin (); while (i != m_config.end ()) { if ((*i).first == section_) { return (i); } i++; } return m_config.end (); } IniFile::const_config_iterator IniFile:: find_section (const string& section_) const { const_config_iterator i = m_config.begin (); while (i != m_config.end ()) { if ((*i).first == section_) { return (i); } i++; } return m_config.end (); } int IniFile:: set_pair (const string& section_, const tuple_type& newkey_) { trace_with_mask ("IniFile::set_pair", INIFILE); config_iterator i = find_section (section_); if (i == sect_end ()) { DL((INIFILE,"Section [%s] is not found!\n", section_.c_str ())); return -1; } tuple_iterator j = (*i).second.begin (); while (j != (*i).second.end ()) { if ((*j).first == newkey_.first) { (*j).second = newkey_.second; return 0; } j++; } (*i).second.push_back (newkey_); return 0; } int IniFile:: drop_section (const string& section_) { trace_with_mask ("IniFile::drop_section", INIFILE); config_iterator i = find_section (section_); if (i == sect_end ()) { DL((INIFILE,"Section [%s] is not found!\n", section_.c_str ())); return -1; } m_config.erase (i); return 0; } int IniFile:: drop_pair (const string& section_, const string& name_) { trace_with_mask ("IniFile::drop_pair", INIFILE); config_iterator i = find_section (section_); if (i == sect_end ()) { DL((INIFILE,"Section [%s] is not found!\n", section_.c_str ())); return -1; } tuple_iterator j = (*i).second.begin (); while (j != (*i).second.end ()) { if ((*j).first == name_) { (*i).second.erase (j); return 0; } j++; } return -1; } libassa-3.5.1/assa/xdrIOBuffer.h0000644000076400007640000001041010406157646013353 00000000000000// -*- c++ -*- //------------------------------------------------------------------------------ // xdrIOBuffer.h //------------------------------------------------------------------------------ // Copyright (c) 2000,2005 by Vladislav Grinchenko // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. //------------------------------------------------------------------------------ // Created: 04/03/2000 //------------------------------------------------------------------------------ #ifndef XDR_IO_BUFFER_H #define XDR_IO_BUFFER_H #include "assa/Assure.h" #include "assa/Socket.h" #include "assa/IPv4Socket.h" #include namespace ASSA { /** @file xdrIOBuffer.h * * This class allows to read XDR-encoded data from Socket stream asynchronously * and then read from it as if from a stream of intermixed strings, integers * and floats. Data are XDR-decoded on a fly. * * Testing xdrIOBuffer object in conditional statement will produce * false if: * * - Not entire buffer has been read yet. * - Socket stream exceptional condition occured. * * Thus, data accumulation and data decoding functions are separated. * * Initially, buffer is in waiting state. In this state, * xdrIOBuffer object waits for bytes from the Socket stream. * * When buffer object becomes full, the state is switched to * xmitted. Now, an application code can read data * from the buffer. The data will be XDR-decoded. * * xdrIOBuffer object yields TRUE in conditional statements only * in xmitted state. In other words, buffer is TRUE if * it is full, and FALSE otherwise. * * xdrIOBuffer can be used only once. You cannot "rewind", and therefore * reuse it. */ class xdrIOBuffer { public: /** @enum state_t */ enum state_t { waiting, xmitted, parsed, error }; /** Constructor. */ xdrIOBuffer (u_int len_); /** Destructor. */ ~xdrIOBuffer (); /** Copy constructor */ xdrIOBuffer (const xdrIOBuffer& rhs_); /** Assign operator. */ xdrIOBuffer& operator= (const xdrIOBuffer& rhs_); /** Read raw data from Socket nonblocking and * store into internal buffer. */ friend Socket& operator>>(Socket& src_, xdrIOBuffer& dest_); /** Read and XDR-decode STL string from the buffer. */ xdrIOBuffer& operator>>(std::string&); /** Read and XDR-decode an integer from the buffer. */ xdrIOBuffer& operator>>(int&); /** Read and XDR-decode a float from the buffer. */ xdrIOBuffer& operator>>(float&); /** Convertion to void* (for testing where bool is required). */ operator void*() const; /** Give verbal interpretation of object's state. */ string get_state () const; /** Return number of bytes in xdrIOBuffer. In waiting state it's bytes transmitted so far. In xmitted state, number of bytes left to decode. */ int size () const; /** Return buffer (maximum expected/allowable) size. */ int buffer_size () const; /** Return pointer to the first byte of xdrIOBuffer. */ const char* str () const; /** Clear up the internal buffer and reset state to waiting. */ void reset (); /** Dump object's internal state to the log file */ void dump () const; protected: /// Copy object from argument void copy (const xdrIOBuffer&); private: /// Buffer char* m_buf; /// Buffer size and maximum expected size int m_sz; /// Pointer for next I/O operation into the buffer char* m_ptr; /// Object state state_t m_state; }; inline xdrIOBuffer:: xdrIOBuffer (const xdrIOBuffer& rhs_) { trace_with_mask("xdrIOBuffer::xdrIOBuffer(xdrIOBuffer&)", XDRBUFTRACE); copy (rhs_); } inline xdrIOBuffer:: operator void*() const { trace_with_mask("xdrIOBuffer::opt void*()", XDRBUFTRACE); return (m_state == waiting || m_state == parsed) ? (void *)0 // bad state : (void *)(-1); // good state } inline int xdrIOBuffer:: size () const { return (m_ptr - m_buf); } inline int xdrIOBuffer:: buffer_size () const { return (m_sz); } inline const char* xdrIOBuffer:: str () const { return ((const char*) m_buf); } } // end namespace ASSA #endif /* XDR_IO_BUFFER_H */ libassa-3.5.1/assa/Socket.cpp0000644000076400007640000003661510505540745012772 00000000000000// -*- c++ -*- //------------------------------------------------------------------------------ // $Id: Socket.cpp,v 1.13 2006/09/24 17:35:33 vlg Exp $ //------------------------------------------------------------------------------ // Socket.C //------------------------------------------------------------------------------ // Copyright (c) 1999,2005 by Vladislav Grinchenko // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. //------------------------------------------------------------------------ // Created: 03/22/99 //------------------------------------------------------------------------ #include #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__CYGWIN32__) # include #endif #if defined (__NetBSD__) # include # include #endif #if defined (WIN32) # define O_NONBLOCK 04000 typedef unsigned int socklen_t; #endif #include "assa/Socket.h" #include "assa/XDRHack.h" using namespace ASSA; const int ASSA::Socket::PGSIZE = 4096; /** There can be bytes already stored in the Streambuf buffer, in addition to bytes that arrived and are ready for reading in the socket buffer (kernel address space). Sum of these two numbers is the true number of bytes available for immediate reading. */ int Socket:: getBytesAvail (void) const { trace_with_mask("Socket::getBytesAvail",SOCKTRACE); Socket* This = (Socket*) this; u_long ba = 0; int ret = 0; #if defined(WIN32) ret = ioctlsocket (m_fd, FIONREAD, &ba); #else ret = ioctl (m_fd, FIONREAD, &ba); #endif if (ret == -1) { EL((ASSAERR,"ioctl(2) failed with ret: %d\n", ret)); return ret; } ba += This->rdbuf ()->in_avail (); DL((SOCKTRACE,"%ld bytes available for reading\n", ba)); return (int(ba)); } Socket& Socket:: flush () { if (good () && rdbuf ()) { if (rdbuf ()->pubsync () == EOF) { setstate (badbit); } } return (*this); } int Socket:: set_option (int level_, int optname_, int val_) { int ret = setsockopt (m_fd, level_, optname_, (const char*) &val_, sizeof (val_)); if (ret < 0) { setstate (Socket::failbit); } return ret; } /** This is a private function used only by class Socket. The only value for flags_ is O_NONBLOCK. */ int Socket:: set_fd_options (long flags_) { trace_with_mask("Socket::set_fd_options",SOCKTRACE); int val; int ret; #if defined (WIN32) u_long set_nonblock = 1; if ((val = ioctlsocket (m_fd, FIONBIO, &set_nonblock)) == 0) { m_nonblocking = true; return 0; } return -1; #else // POSIX/UNIX if ((val = ::fcntl (m_fd, F_GETFL, 0)) < 0) { return -1; } val |= flags_; // turn flags on DL ((SOCKTRACE,"Set flags fcntl(%d, %s)\n", m_fd, decode_fcntl_flags (val).c_str ())); ret = ::fcntl (m_fd, F_SETFL, val); val = ::fcntl (m_fd, F_GETFL, 0); DL ((SOCKTRACE,"Flags are set to %s via fcntl(25)\n", decode_fcntl_flags (val).c_str ())); return (ret); #endif } /** This is a private function used only by class Socket. The only value for flags_ is O_NONBLOCK - set the socket back to the blocking mode. */ int Socket:: clear_fd_options (long flags_) { trace_with_mask("Socket::clear_fd_options",SOCKTRACE); long oldflags; long newflags; int ret; #if defined (WIN32) u_long set_block = 0; if ((ret = ioctlsocket (m_fd, FIONBIO, &set_block)) == 0) { m_nonblocking = false; return 0; } return -1; #else if ((oldflags = ::fcntl (m_fd, F_GETFL, 0)) < 0) { return -1; } newflags = oldflags & ~flags_; // clear flags DL ((SOCKTRACE,"Set flags fcntl(%d, %s)\n", m_fd, decode_fcntl_flags (newflags).c_str ())); ret = ::fcntl (m_fd, F_SETFL, newflags); newflags = ::fcntl (m_fd, F_GETFL, 0); DL ((SOCKTRACE,"Flags are set to %s via fcntl(%d)\n", decode_fcntl_flags (newflags).c_str ())); return (ret); #endif } bool Socket:: turnOptionOn (opt_t opt_) { trace_with_mask("Socket::turnOptionOn",SOCKTRACE); if (nonblocking == opt_) return set_fd_options (O_NONBLOCK); int optname; if (reuseaddr == opt_) optname = SO_REUSEADDR; else { EL((ASSAERR,"Invalid socket option\n")); return false; } return set_option (SOL_SOCKET, optname, 1) == 0; } bool Socket:: turnOptionOff (opt_t opt_) { trace_with_mask("Socket::turnOptionOff",SOCKTRACE); if (nonblocking == opt_) return clear_fd_options (O_NONBLOCK); int optname; if (reuseaddr == opt_) optname = SO_REUSEADDR; else { EL((ASSAERR,"Invalid socket option\n")); return false; } return set_option (SOL_SOCKET, optname, 0) == 0; } bool Socket:: setOption (opt_t opt_, int arg_) { trace_with_mask("Socket::setOption(,)",SOCKTRACE); int optname; if (nonblocking == opt_) { return (arg_ == 1) ? set_fd_options (O_NONBLOCK) : clear_fd_options (O_NONBLOCK); } if (rcvlowat == opt_) { optname = SO_RCVLOWAT; } else if (sndlowat == opt_) { optname = SO_SNDLOWAT; } else { EL((ASSAERR,"Invalid socket option\n")); return false; } return set_option (SOL_SOCKET, optname, arg_) == 0; } int Socket:: getOption (opt_t opt_) const { trace_with_mask("Socket::getOption",SOCKTRACE); int optval = 0; if (nonblocking == opt_) { #if defined (WIN32) return (m_nonblocking ? 1 : 0); #else if ((optval = ::fcntl (m_fd, F_GETFL, 0)) < 0) { return -1; } return ((optval & O_NONBLOCK) == O_NONBLOCK ? 1 : 0); #endif } int optname; int level = SOL_SOCKET; bool bin = false; socklen_t len = sizeof (optval); int ret; if (rcvlowat == opt_) { optname = SO_RCVLOWAT; } else if (sndlowat == opt_) { optname = SO_SNDLOWAT; } else if (reuseaddr == opt_) { optname = SO_REUSEADDR; bin = true; } else { EL((ASSAERR,"Invalid socket option\n")); return (-1); } #if defined (__CYGWIN32__) || defined (WIN32) ret = getsockopt (m_fd, level, optname, (char*) &optval, (int*)&len); #else // posix/unix ret = getsockopt (m_fd, level, optname, (char*) &optval, &len); #endif if (ret < 0) { return (-1); } if (bin) { return (ret == 0 ? 0 : 1); } return (ret); } int Socket:: ignore(int n_, int delim_) { trace_with_mask("Socket::ignore",SOCKTRACE); register int b; register int count = 0; register char c; if (n_ == INT_MAX && delim_ == EOF) { char buf[PGSIZE]; while ((b = read (buf, PGSIZE))) { count += b; } setstate (Socket::eofbit|Socket::failbit); return count; } for (; n_; n_--, count++) { if ( (b = read (&c, 1)) == 0 ) { setstate (Socket::eofbit|Socket::failbit); break; } if ( c == delim_ ) break; } return count; } //----------------------------------------------------------------------------- // Input operators //----------------------------------------------------------------------------- /** From xdr_simple(3N) man page: "xdr_char() translates between C characters and their external representations. Note: encoded characters are not packed, and occupy 4 bytes each." From SunOS 5.3 Network Interfaces Programmer's Guide, "XDR Protocol Specification": "The representation of all items requires a multipe of four bytes (or 32 bits) of data. ... The n bytes are followed by enough (0 to 3) residual zero bytes, r, to make the total byte count a multiple of four." The implication if this is that even though we transerfer 1 byte, we still have to allocate and transfer 4 bytes to hold it. */ Socket& Socket:: operator>>(char& n_) { int c = 0; int len = sizeof (int); XDR xdrs; xdrmem_create (&xdrs, (caddr_t) &c, len, XDR_DECODE); if (read ((char* ) &c, len) == len) { xdr_char (&xdrs, &n_); } else { setstate (Socket::eofbit|Socket::failbit); } xdr_destroy(&xdrs); return *this; } /** For format explanation, see comment to operator<<(string&) */ Socket& Socket:: operator>> (std::string& s_) { char c = 0; size_t n = 0; s_ = ""; (*this) >> n; if (n == 0) { return *this; } size_t len = n; while (len-- && read (&c, 1) == 1) { s_ += c; } ignore (4 - n % 4); return *this; } Socket& Socket:: operator>> (short& n_) { short val; if (read ((char*) &val, sizeof(short)) == sizeof(short)) { n_ = (short) ntohs ((short)val); } else { setstate (Socket::eofbit|Socket::failbit); } return *this; } Socket& Socket:: operator>> (unsigned short& n_) { u_short val; if (read ((char*) &val, sizeof(u_short)) == sizeof(u_short)) { n_ = (u_short) ntohs ((u_short)val); } else { setstate (Socket::eofbit|Socket::failbit); } return *this; } #define LONGEST long /* On 64-bit platforms, sizeof (long) = 8 bytes. * ntohl()/htonh() operats only on int32_t types which is 4 bytes long * everywhere. So, for 64-bit longs we need to process twice as much * and swapt data accordingly. */ #define READ_INT(TYPE) \ Socket& Socket::operator>>(TYPE& n_) \ {\ LONGEST val;\ int typesz = sizeof(TYPE);\ if (read ( (char* ) &val, typesz) == typesz) {\ if (sizeof(int32_t) <= typesz) {\ n_ = (TYPE) ntohl (val); \ }\ else {\ if (Socket::is_little_endian ()) {\ *((int32_t*)(&n_)+1) = ntohl (*((int32_t*)(&val)) );\ *((int32_t*)(&n_) ) = ntohl (*((int32_t*)(&val))+1);\ }\ else {\ *((int32_t*)(&n_) ) = ntohl (*((int32_t*)(&val)) );\ *((int32_t*)(&n_)+1) = ntohl (*((int32_t*)(&val))+1);\ }\ }\ }\ else {\ setstate (Socket::eofbit|Socket::failbit);\ }\ return *this;\ } READ_INT(int); READ_INT(unsigned int); READ_INT(long); READ_INT(unsigned long); Socket& Socket:: operator>> (float& n_) { float val; XDR xdrs; xdrmem_create (&xdrs, (caddr_t) &val, sizeof(float), XDR_DECODE); if (read ((char*) &val, sizeof(float)) == sizeof(float)) { xdr_float (&xdrs, &n_); } else { setstate (Socket::eofbit|Socket::failbit); } xdr_destroy (&xdrs); return *this; } Socket& Socket:: operator>> (double& n_) { double val = 0; XDR xdrs; xdrmem_create (&xdrs, (caddr_t) &val, sizeof(double), XDR_DECODE); if (read ((char*) &val, sizeof(double)) == sizeof(double)) { xdr_double (&xdrs, &n_); } else { setstate (Socket::eofbit|Socket::failbit); } xdr_destroy (&xdrs); return *this; } //----------------------------------------------------------------------------- // Output operators //----------------------------------------------------------------------------- Socket& Socket:: operator<< (char n_) { /* See comment to operator>>(char n_) */ int buf = 0; int len = sizeof (int); XDR xdrs; xdrmem_create (&xdrs, (caddr_t) &buf, len, XDR_ENCODE); xdr_char (&xdrs, &n_); if (write ((const char*) &buf, len) != len) { (Socket::eofbit|Socket::failbit); } xdr_destroy (&xdrs); return *this; } /** XDR STRING representation: (from RFC 1832 - http://www.faqs.org/rfcs/rfc1832.html) 0 1 2 3 4 5 ... +-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+ | length n |byte0|byte1|...| n-1 | 0 |...| 0 | +-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+ |<-------4 bytes------->|<------n bytes------>|<---r bytes--->| |<----n+r (where (n+r) mod 4 = 0)---->| If n is not a multiple of four, then the n bytes are followed by enough (0 to 3) residual zero bytes, r, to make the total byte count a multiple of four. In other words, (4 - n % 4) == r. We follow the format, but send data bytes as-is - no conversion is required. We also pad data with r bytes. */ Socket& Socket:: operator<< (const std::string& s_) { static const char pad [4] = { 0, 0, 0, 0 }; (*this) << s_.length (); int ret = write (s_.c_str (), s_.length ()); if ( ret != s_.length () ) { setstate (Socket::eofbit|Socket::failbit); } size_t r = 4 - s_.length() % 4; if (r) { if (write (pad, r) != r) { setstate (Socket::eofbit|Socket::failbit); } } return *this; } Socket& Socket:: operator<< (short n_) { short val = (short) htons((short)n_); if (write ((const char*) &val, sizeof(short)) != sizeof(short)) { setstate (Socket::eofbit|Socket::failbit); } return *this; } Socket& Socket:: operator<< (unsigned short n_) { u_short val = (u_short) htons((u_short)n_); if (write ((const char*) &val, sizeof(u_short)) != sizeof(u_short)) { setstate (Socket::eofbit|Socket::failbit); } return *this; } #define WRITE_INT(TYPE) \ Socket& Socket::operator<< (TYPE n_) \ { \ LONGEST val;\ int typesz = sizeof(TYPE);\ if (sizeof(int32_t) <= typesz) {\ val = (TYPE) ntohl (n_); \ }\ else {\ if (Socket::is_little_endian ()) {\ *((int32_t*)(&val)+1) = htonl (*((int32_t*)(&n_)) );\ *((int32_t*)(&val) ) = htonl (*((int32_t*)(&n_))+1);\ }\ else {\ *((int32_t*)(&val) ) = htonl (*((int32_t*)(&n_)) );\ *((int32_t*)(&val)+1) = htonl (*((int32_t*)(&n_))+1);\ }\ }\ if (write ((const char*) &val, typesz) != typesz) {\ setstate (Socket::eofbit|Socket::failbit);\ }\ return *this;\ } WRITE_INT(int); WRITE_INT(unsigned int); WRITE_INT(long); WRITE_INT(unsigned long); Socket& Socket:: operator<< (float n_) { float buf, f = n_; XDR xdrs; xdrmem_create (&xdrs, (caddr_t) &buf, sizeof(float), XDR_ENCODE); xdr_float (&xdrs, &f); int ret = write ((const char*) &buf, sizeof(float)); xdr_destroy (&xdrs); if ( ret != sizeof(float) ) { setstate (Socket::eofbit|Socket::failbit); } return *this; } Socket& Socket:: operator<< (double n_) { double buf, f = n_; XDR xdrs; xdrmem_create (&xdrs, (caddr_t) &buf, sizeof(double), XDR_ENCODE); xdr_double (&xdrs, &f); int ret = write ((const char*) &buf, sizeof(double)); xdr_destroy (&xdrs); if ( ret != sizeof(double) ) { setstate (Socket::eofbit|Socket::failbit); } return *this; } void Socket:: dumpState (void) const { trace_with_mask("Socket::dumpState",SOCKTRACE); char state_set[] = "[ set]\n"; char state_not_set[] = "[not set]\n"; std::ostringstream msg; msg << "\n"; msg << "\tTesting good() ....... "; if (this->good ()) msg << state_set; else msg << state_not_set; msg << "\tTesting eof() ........ "; if (this->eof ()) msg << state_set; else msg << state_not_set; msg << "\tTesting fail() ....... "; if (this->fail ()) msg << state_set; else msg << state_not_set; msg << "\tTesting bad() ........ "; if (this->bad ()) msg << state_set; else msg << state_not_set; msg << "\tTesting !() .......... "; if ( !(*this) ) msg << state_set; else msg << state_not_set; msg << "\tTesting void *() ..... "; if ( *this ) msg << state_set; else msg << state_not_set; msg << "\tTesting nonblocking... "; if (getOption (nonblocking) == 1) msg << state_set; else msg << state_not_set; /*--- Terminate stream buffer ---*/ msg << std::ends; DL((SOCKTRACE,"%s\n", msg.str ().c_str ())); } bool Socket:: is_little_endian () { union { char c [sizeof (short)]; short v; } endian_u; endian_u.v = 256; return (endian_u.c [0] == 0); } string Socket:: decode_fcntl_flags (long mask_) { string answer; #if !defined (WIN32) if (mask_ & O_RDONLY) { answer = "O_RDONLY|"; // 000000 } if (mask_ & O_WRONLY) { answer += "O_WRONLY|"; // 000001 } if (mask_ & O_RDWR) { answer += "O_RDWR|"; // 000002 } if (mask_ & O_APPEND) { answer += "O_APPEND|"; // 001000 } if (mask_ & O_NONBLOCK) { answer += "O_NONBLOCK|";// 004000 } if (mask_ & O_SYNC) { answer += "O_SYNC|"; // 010000 } if (mask_ & O_ASYNC) { // 020000 answer += "O_ASYNC|"; } answer.erase (answer.end () - 1); #endif return answer; } libassa-3.5.1/assa/CommonUtils.cpp0000644000076400007640000001137510457565335014017 00000000000000// -*- c++ -*- //------------------------------------------------------------------------------ // $Id: CommonUtils.cpp,v 1.10 2006/07/20 02:30:53 vlg Exp $ //------------------------------------------------------------------------------ // CommonUtils.cpp //------------------------------------------------------------------------------ // Copyright (C) 1997-2003 Vladislav Grinchenko // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. //------------------------------------------------------------------------------ #include #include #include #include #include // getcwd(3) #ifdef WIN32 static char *home_dir = "."; /* we feel (no|every)where at home */ #else # include #endif #include "assa/Logger.h" #include "assa/CommonUtils.h" void ASSA::Utils:: split (const char* src_, std::vector& vec_) { std::istringstream input (src_); vec_.erase (vec_.begin (), vec_.end ()); std::string token; while (input >> token) { vec_.push_back (token); } } int ASSA::Utils:: split_pair (const string& text_, char sep_, string& lhs_, string& rhs_) { int pos = 0; if ((pos = text_.find (sep_)) == string::npos) { return -1; } lhs_ = text_.substr (0, pos); rhs_ = text_.substr (pos+1, text_.size ()); pos = rhs_.size () -1; if (rhs_[0] == '"' || rhs_[0] == '\'') { rhs_[0] = ' '; } if (rhs_[pos] == '"' || rhs_[pos] == '\'') { rhs_[pos] = ' '; } return 0; } int ASSA::Utils:: ltrim (std::string& text_, const std::string& delim_) { std::string::size_type idx; idx = text_.find_first_of (delim_); if (idx != std::string::npos) { text_.replace (0, idx+1, ""); return 0; } return -1; } int ASSA::Utils:: rtrim (std::string& text_, const std::string& delim_) { std::string::size_type idx; idx = text_.find_last_of (delim_); if (idx != std::string::npos) { text_.replace (idx, text_.size (), ""); return 0; } return -1; } void ASSA::Utils:: trim_sides (std::string& text_) { std::string::size_type idx; idx = text_.find_first_not_of (" \t"); if (idx != std::string::npos) { text_.replace (0, idx, ""); } idx = text_.find_last_not_of (" \t"); if (idx != std::string::npos) { text_.replace (idx + 1, text_.size (), ""); } } void ASSA::Utils:: find_and_replace_char (std::string& text_, char src_, char dest_) { string::iterator pos = text_.begin (); while (pos != text_.end ()) { if ((*pos) == src_) { (*pos) = dest_; } pos++; } } std::string ASSA::Utils:: strenv (const char* in) { char b [1024]; char* ret = b; char* r = ret; if (*in == '~') { // '~' OR '~/' if ( *(in+1) == 0 || *(in+1) == '/' ) { in++; strcpy (ret, getenv ("HOME") ? getenv ("HOME") : ""); r += strlen (ret); } else { in++; char lname [256]; char* lp = lname; const char* sp = strchr (in, '/'); // find first '/' in string if ( sp ) { while (in != sp) *lp++ = *in++; *lp = 0; } else { while (*in) *lp++ = *in++; *lp = 0; } #ifdef WIN32 strcpy (ret, home_dir); r += strlen (ret); #else // lookup user's home directory in /etc/passwd file struct passwd* p = getpwnam (lname); if ( p ) { strcpy (ret, p->pw_dir ? p->pw_dir : ""); r += strlen (ret); } #endif } } while (*in) { if (*in == '$') { char varname [80]; if (*++in == '(') { ++in; const char *end = strchr (in,')'); if (!end) break; strncpy (varname, in, end-in); varname [end-in] = '\0'; in = end+1; } else if (*in == '{') { const char *end = strchr (in,'}'); if (!end) break; strncpy (varname, in, end-in); varname [end-in] = '\0'; in = end+1; } else { char* vp = varname; while (isalnum (*in) || *in == '_' ) { // letter OR digit *vp++ = *in++; } *vp = '\0'; } char* ep = ::getenv (varname); while (ep && *ep) *r++ = *ep++; continue; } else if (*in == '\\' && *(in+1)) { in++; // allow escaped dollar signs } *r++ = *in++; } *r = '\0'; return ret; } std::string ASSA::Utils:: get_cwd_name (void) { std::string ret; int size = 256; char* chr_ptr = 0; while (true) { chr_ptr = new char [size]; if (::getcwd (chr_ptr, size-1) != NULL) { ret = chr_ptr; delete [] chr_ptr; return ret; } if (errno != ERANGE) { return ret; // Any error other then a path name too long // for the buffer is bad news. } delete [] chr_ptr; size += 256; } } libassa-3.5.1/assa/SigSet.h0000644000076400007640000000673310457565336012414 00000000000000// -*- c++ -*- //------------------------------------------------------------------------------ // SigSet.h //------------------------------------------------------------------------------ // Copyright (c) 1997 by Vladislav Grinchenko // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. //------------------------------------------------------------------------------ #ifndef _SigSet_h #define _SigSet_h // System includes // #include #include namespace ASSA { #if !defined(WIN32) /** @file SigSet.h SigSet is a wrapper for UNIX sigset_t structure that provides all manipulators on this structure as well. The conversoin operator that converts SigSet to a pointer to the internal sigset_t data member for direct use with C-library functions can be used as follows: SigSet source; sigset_t* targetp; targetp = source; Because lvalue is expected to be of the type sigset_t*, and there is a conversion operator defined for SigSet, the conversion happens automatically. Another example would be to use it in conjunction with 'struct sigaction': struct sigaction action; SigSet siganls_to_block; // manipulat signal set in some meaningful way action.sa_mask = *signals_to_block; */ class SigSet { public: /** Default constructor creates SigSet object with an empty signal set. */ SigSet(); /** Copy constructor from source_. */ SigSet(sigset_t* source_); /** Destructor */ ~SigSet(); /** This function initializes a signal set to be empty, no signals in it. @return 0 on success, -1 on error, with errno set to error number. */ int empty (void); /** This function initializes a signal set to be full; all the signals defined by POSIX will be in the set. @return 0 on success, -1 on error, with errno set to error number. */ int fill(void); /** This function adds the signal numbered signo_ to the set. @return 0 on success, -1 on error, with errno set to error number. */ int add(int signo_); /** This function removes the signal signo_ from the set. @return 0 on success, -1 on error, with errno set to error number. */ int del(int signo_); /** Use this function to tell whether the signal signo_ is in the set. @return 0 on success, -1 on error, with errno set to error number. */ int is_member(int signo_); /** Conversion operator to sigset_t structure. @return pointer to the internal sigset_t structure. */ operator sigset_t *(); private: /** POSIX signal set */ sigset_t m_sigset; }; inline SigSet:: SigSet() { (int) sigemptyset(&m_sigset); } inline SigSet:: SigSet(sigset_t* s_) { m_sigset = *s_; } inline SigSet:: ~SigSet() { /* no-op */ } inline int SigSet:: empty(void) { return sigemptyset(&m_sigset); } inline int SigSet:: fill(void) { return sigfillset(&m_sigset); } inline int SigSet:: add(int signo_) { return sigaddset(&m_sigset,signo_); } inline int SigSet:: del(int signo_) { return sigdelset(&m_sigset,signo_); } inline int SigSet:: is_member(int signo_) { return sigismember(&m_sigset,signo_); } inline SigSet:: operator sigset_t *() { return &m_sigset; } #endif // !defined(WIN32) } // end namespace ASSA #endif /* _SigSet_h */ libassa-3.5.1/assa/CmdLineOpts.h0000644000076400007640000002134010323072352013345 00000000000000// -*- c++ -*- //------------------------------------------------------------------------------ // $Id: CmdLineOpts.h,v 1.7 2005/10/12 02:28:58 vlg Exp $ //------------------------------------------------------------------------------ // CmdLineOpts.h //------------------------------------------------------------------------------ // Copyright (C) 2000,2005 Vladislav Grinchenko // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. //------------------------------------------------------------------------------ #ifndef CMD_LINE_OPTS_H #define CMD_LINE_OPTS_H #include "assa/Assure.h" #include #include using std::string; using std::vector; namespace ASSA { class CmdLineOpts; /** @file CmdLineOpts.h Class to handle processing command-line options. */ /** * Option class. This class is a helper class of CmdLineOpts class. * It is not used by any other class and cannot be instantiated. */ class Option { public: friend class CmdLineOpts; /** @enum type_t Option type. Each option, except for flags has a value following it on the command line. Following types are supported: */ enum type_t { string_t=0, /**< Convert argument to STL string */ int_t, /**< Convert argument to int */ uint_t, /**< Convert argument to unsigned int */ long_t, /**< Convert argument to long */ ulong_t, /**< Convert argument to unsinged long */ double_t, /**< Convert argument to double */ float_t, /**< Convert argument to float */ flag_t, /**< No argument; bool value is flipped. */ func_t, /**< Convert argument to function */ func_one_t, /**< Convert argument to function with one argument */ none_t }; private: /// Private default constructor Option (); /// Private constructor Option (char shopt_, const string& lopt_, type_t type_, void* val_); /// Write object state to the log file void dump () const; /// Return the type of the Option object const char* type_c_str (); private: /// One-letter option name char m_short_name; /// Long option name string m_long_name; /// Option type type_t m_type; /// Pointer to the option value void* m_val; }; inline Option::Option () : m_short_name (' '), m_long_name (""), m_type (none_t), m_val (NULL) { /* empty */ } inline Option::Option (char shopt_, const string& lopt_, type_t type_, void* val_) : m_short_name (shopt_), m_long_name (lopt_), m_type (type_), m_val (val_) { trace_with_mask("Option::Option", CMDLINEOPTS); } /*----------------------------------------------------------------------------*/ class IniFile; /** Class CmdLineOpts. CmdLineOpts class parsers the command line arguments. It is a base class, and to use it, it has to be inherited from. See "ASSA Library User's Guide" for further details. */ class CmdLineOpts { public: typedef void (* OPTS_FUNC) (void); typedef void (* OPTS_FUNC_ONE) (const string&); typedef vector