diff --git a/ChangeLog b/ChangeLog index 92d852a..37e6deb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,13 @@ Change Log ========== +0.9.3 -> 0.9.4 +-------------- +* Fixed memory leak when no "--log" switch. +* Windows build is more "gui" and less "command-line". +* "Info" command added to the administration interface. +* Doxygen files removed from binary RPM. + 0.9.2 -> 0.9.3 -------------- * Proxy mode (--immediate and --as-proxy) diff --git a/NEWS b/NEWS index c6b9fd5..adb9015 100644 --- a/NEWS +++ b/NEWS @@ -1,2 +1,6 @@ -no news +to do +----- +* more-native windows port (system tray, registry etc) +* Mac OSX build +* setuid() security diff --git a/bin/Makefile.am b/bin/Makefile.am index 502a8ec..f2755d8 100644 --- a/bin/Makefile.am +++ b/bin/Makefile.am @@ -1,7 +1,7 @@ -noinst_SCRIPTS = emailrelay-doxygen-filter.sh emailrelay-test.sh +noinst_SCRIPTS = emailrelay-doxygen-filter.sh emailrelay-test.sh emailrelay-soak.sh libexec_SCRIPTS = emailrelay.sh pkgdata_DATA = emailrelay-notify.sh emailrelay-deliver.sh emailrelay-process.sh -EXTRA_DIST = emailrelay-doxygen-filter.sh_ emailrelay-test.sh_ emailrelay.sh_ txt2html.sh_ emailrelay-notify.sh_ emailrelay-deliver.sh_ emailrelay-process.sh_ +EXTRA_DIST = emailrelay-doxygen-filter.sh_ emailrelay-test.sh_ emailrelay-soak.sh_ emailrelay.sh_ txt2html.sh_ emailrelay-notify.sh_ emailrelay-deliver.sh_ emailrelay-process.sh_ CLEANFILES = $(noinst_SCRIPTS) $(libexec_SCRIPTS) $(pkgdata_DATA) TESTS = emailrelay-test.sh SUFFIXES = .sh_ .sh diff --git a/bin/Makefile.in b/bin/Makefile.in index 12bd3f4..f4f218e 100644 --- a/bin/Makefile.in +++ b/bin/Makefile.in @@ -69,10 +69,10 @@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ VERSION = @VERSION@ -noinst_SCRIPTS = emailrelay-doxygen-filter.sh emailrelay-test.sh +noinst_SCRIPTS = emailrelay-doxygen-filter.sh emailrelay-test.sh emailrelay-soak.sh libexec_SCRIPTS = emailrelay.sh pkgdata_DATA = emailrelay-notify.sh emailrelay-deliver.sh emailrelay-process.sh -EXTRA_DIST = emailrelay-doxygen-filter.sh_ emailrelay-test.sh_ emailrelay.sh_ txt2html.sh_ emailrelay-notify.sh_ emailrelay-deliver.sh_ emailrelay-process.sh_ +EXTRA_DIST = emailrelay-doxygen-filter.sh_ emailrelay-test.sh_ emailrelay-soak.sh_ emailrelay.sh_ txt2html.sh_ emailrelay-notify.sh_ emailrelay-deliver.sh_ emailrelay-process.sh_ CLEANFILES = $(noinst_SCRIPTS) $(libexec_SCRIPTS) $(pkgdata_DATA) TESTS = emailrelay-test.sh SUFFIXES = .sh_ .sh diff --git a/bin/emailrelay-soak.sh_ b/bin/emailrelay-soak.sh_ new file mode 100644 index 0000000..1953909 --- /dev/null +++ b/bin/emailrelay-soak.sh_ @@ -0,0 +1,161 @@ +#!/bin/sh +# +# Copyright (C) 2001 Graeme Walker +# +# 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 for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# === +# +# emailrelay-soak.sh +# +# Soak tests the E-MailRelay system. +# + +# configuration +# +exe="../src/main/emailrelay" +pp="1001" # port prefix +null_filter="/bin/touch" +as_client="--no-syslog --no-daemon --dont-serve --forward --forward-to" # no --log +as_server="--log" # no --close-stderr +as_proxy="--log --immediate --forward-to" # no --close-stderr +content="/etc/passwd" + +# configuration fallback +# +if test \! -f "${exe}" +then + exe="../emailrelay" +fi +if test \! -f "${null_filter}" +then + null_filter="/usr/bin/touch" +fi + +# initialisation +# +base_dir="/tmp/`basename $0`.$$.tmp" +mkdir "${base_dir}" +trap "rm -rf ${base_dir} 2>/dev/null ; killall emailrelay ; exit" 0 1 2 3 13 15 + +Content() +{ + echo "To:" ${USER}@localhost + echo "Subject: test message from process" $$ + echo "From: tester" + echo "" + for i in 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + do + cat "${content}" + done +} + +Envelope() +{ + echo "X-MailRelay-Format: #2821.2" + echo "X-MailRelay-Content: 8bit" + echo "X-MailRelay-From: me" + echo "X-MailRelay-ToCount: 1" + echo "X-MailRelay-To-Remote:" ${USER}@localhost + echo "X-MailRelay-End: 1" +} + +CrLf() +{ + sed 's/$/£/' | tr '£' '\r' +} + +CreateMessage() +{ + spool_dir="${1}" + + Content | CrLf > ${spool_dir}/emailrelay.$$.1.content + Envelope | CrLf > ${spool_dir}/emailrelay.$$.1.envelope +} + +RunClient() +{ + to_address="${1}" + spool_dir="${2}" + + ${exe} ${as_client} ${to_address} --spool-dir ${spool_dir} +} + +Send() +{ + to_address="${1}" + + dir="${base_dir}/spool-send" + mkdir -p "${dir}" + + CreateMessage "${dir}" + RunClient "${to_address}" "${dir}" +} + +RunServer() +{ + port="${1}" + spool_dir="${2}" + log="${3}" + pid_file="${4}" + + if test "`echo ${pid_file} | grep '^/'`" = "" + then + pid_file="`pwd`/${pid_file}" + fi + + mkdir -p "${spool_dir}" + ${exe} ${as_server} --port ${port} --spool-dir ${spool_dir} \ + --pid-file ${pid_file} \ + --admin `expr ${port} + 100` --forward-to localhost:smtp --no-syslog 2> "${log}" +} + +RunProxy() +{ + port="${1}" + to_address="${2}" + spool_dir="${3}" + log="${4}" + pid_file="${5}" + + if test "`echo ${pid_file} | grep '^/'`" = "" + then + pid_file="`pwd`/${pid_file}" + fi + + mkdir -p "${spool_dir}" + ${exe} ${as_proxy} ${to_address} --port ${port} --spool-dir ${spool_dir} \ + --pid-file ${pid_file} \ + --admin `expr ${port} + 100` --no-syslog 2> "${log}" +} + +killall emailrelay + +RunServer ${pp}3 ${base_dir}/spool-3 server-2.out server-2.pid +RunProxy ${pp}1 localhost:${pp}3 ${base_dir}/spool-1 proxy.out proxy.pid +RunServer ${pp}2 ${base_dir}/spool-2 server-1.out server-1.pid + +sleep 1 # to allow pid files time to be written +echo ps -l -p `cat server-2.pid` -p `cat server-1.pid` -p `cat proxy.pid` +ps -l -p `cat server-2.pid` -p `cat server-1.pid` -p `cat proxy.pid` + +while true +do + Send localhost:${pp}1 + Send localhost:${pp}2 + echo -n . +done + diff --git a/bin/emailrelay-test.sh_ b/bin/emailrelay-test.sh_ index 6fd9aac..fe710bd 100644 --- a/bin/emailrelay-test.sh_ +++ b/bin/emailrelay-test.sh_ @@ -21,7 +21,7 @@ # # emailrelay-test.sh # -# Test the E-MailRelay system. +# Tests the E-MailRelay system. # # Creates four temporary spool directories under /tmp and runs # four emailrelay servers to bucket-brigade a test message from one to @@ -34,9 +34,22 @@ # If this test takes more than a second or two then it has failed. # +# configuration +# exe="../src/main/emailrelay" poke="../src/main/emailrelay-poke" +null_filter="/bin/touch" pp="1001" # port-prefix + +# configuration fallback +# +if test \! -f ${null_filter} +then + null_filter="/usr/bin/touch" +fi + +# initialisation +# base_dir="/tmp/`basename $0`.$$.tmp" exit_code="1" @@ -144,7 +157,7 @@ trap "Trap 0 ; exit" 0 StartTimer RunServer ${pp}1 store-2 log-1 pid-1 RunServer ${pp}2 store-2 log-2 pid-2 "--admin ${pp}9 --forward-to localhost:${pp}3" -RunServer ${pp}3 store-3 log-3 pid-3 "--immediate --forward-to localhost:${pp}4 --filter /bin/touch" +RunServer ${pp}3 store-3 log-3 pid-3 "--immediate --forward-to localhost:${pp}4 --filter ${null_filter}" RunServer ${pp}4 store-4 log-4 pid-4 CreateMessages RunClient localhost:${pp}1 store-1 log-c pid-5 diff --git a/configure b/configure index bd442e5..b41249a 100755 --- a/configure +++ b/configure @@ -691,7 +691,7 @@ fi PACKAGE=emailrelay -VERSION=0.9.3 +VERSION=0.9.4 if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } diff --git a/configure.in b/configure.in index d63198c..1fc695e 100644 --- a/configure.in +++ b/configure.in @@ -39,7 +39,7 @@ dnl === dnl Process this file with autoconf to produce a configure script. AC_INIT(src/main/gsmtp.h) -AM_INIT_AUTOMAKE(emailrelay,0.9.3) +AM_INIT_AUTOMAKE(emailrelay,0.9.4) AM_CONFIG_HEADER(config.h) dnl === diff --git a/doc/Makefile.am b/doc/Makefile.am old mode 100755 new mode 100644 diff --git a/doc/developer.txt b/doc/developer.txt index 36eb1ec..eabf145 100644 --- a/doc/developer.txt +++ b/doc/developer.txt @@ -9,9 +9,9 @@ utility functions, logging, command line parsing etc., and "gnet" provides network classes using the Berkley socket and Winsock APIs. Both libraries are portable between POSIX-like systems (eg. Linux) and Windows. -The application-level classes are implemented within the "GSmtp" namespace. -The key interfaces in this namespace are "ClientProtocol", "ServerProtocol" and -"MessageStore". +The application-level classes are implemented within the "GSmtp" and "Main" +namespaces. The key interfaces in the "GSmtp" namespace are "ClientProtocol", +"ServerProtocol" and "MessageStore". Under Windows there is an additional library for event handling. Windows has historically built network event processing on top of the GUI event system, @@ -137,16 +137,10 @@ these cases there are three source files per header. For example, "gsocket.cpp", Porting to other compilers -------------------------- -If trying a port using a good ANSI C++ compiler then start by removing files -from the "lib/gcc2.95" directory (or edit makefiles to remove the include path), -and then review the following header files: "src/glib/gdef.h", -"src/gnet/gnet.h", "src/glib/gmemory.h". - -The unix (ie. POSIX-like) implementation of the directory iteration class -uses glob(). This functionality is only used by the message store code in -the "src/main" directory. If glob() presents a porting challenge then -the filename matching could be removed from the directory iterator and -moved into the message store class. +If porting to a good ANSI C++ compiler then start by removing files from the +"lib/gcc2.95" directory (or edit makefiles to remove the include path), and then +review the following header files: "src/glib/gdef.h", "src/gnet/gnet.h", +"src/glib/gmemory.h". IPv6 ---- diff --git a/doc/index.html b/doc/index.html old mode 100755 new mode 100644 diff --git a/doc/reference.txt b/doc/reference.txt index 04d06cb..143c6c0 100644 --- a/doc/reference.txt +++ b/doc/reference.txt @@ -175,6 +175,11 @@ must have been defined on the "emailrelay" command line at start-up using the "--forward-to" switch; it cannot be specified through the administration interface. +The "flush" command allows you to run a single process which combines the +functionality of storage daemon and forwarding client. This might be useful +in systems which are low on memory: the memory footprint of "telnet" or +"emailrelay-poke" will be much smaller than "emailrelay --as-client". + Mail pre-processing ------------------- The "--filter" command-line switch allows you to specify a pre-processor program diff --git a/doc/userguide.txt b/doc/userguide.txt index 02c3a0e..2f2e356 100644 --- a/doc/userguide.txt +++ b/doc/userguide.txt @@ -49,16 +49,14 @@ In particular the configuration of some popular MTAs is notoriously complex and arcane, whereas the only thing the E-MailRelay system needs is the name of your ISP's mail server. -With the move away from dial-up Internet connections a simple store-and-forward -MTA like E-MailRelay becomes more relevant to mobile computers and PDAs which -need to store mail while away from the network. +Even with the move away from dial-up Internet connections a simple +store-and-forward MTA like E-MailRelay may still be useful for mobile computers +and PDAs which need to store mail while away from the network. -The source code for E-MailRelay is well-structured, portable ANSI C++, without -any third-party library dependencies. It could therefore be the basis for other -SMTP projects such as, for example, an anonymising remailer or an encryption -gateway. E-MailRelay is well suited to gateway applications (sitting between -local e-mail clients and a local routing MTA) because of its functional -simplicity. +E-MailRelay can also pre-process the e-mail messages which pass through it. This +could be used to compensate for features, such as encryption, which are not +available in your e-mail client program, or it could be used to enforce +formatting or legal requirements for all outgoing mail. Running E-MailRelay ------------------- @@ -73,19 +71,13 @@ a command like this: where "mail.myisp.net" is replaced with the name of your ISP's SMTP server. -(E-MailRelay can also combine the two roles of storage daemon and forwarding -client in one process. In this mode the storage service is always available, -but the forwarding activity has to be triggered via the "administration" -interface. The administration interface is a command-line network service -compatible with telnet. The interface must be enabled using the "--admin" -command line switch, specifying the listening port number.) - To run E-MailRelay as a personal proxy server (on port 10025) to the system's -default server use a command like this: +default MTA use a command something like this: emailrelay --as-proxy localhost:smtp --no-syslog --port 10025 --filter ${HOME}/.emailrelay/mailfilter --spool-dir ${HOME}/.emailrelay/spool -where 'mailfilter' is a program which does the appropriate mail processing. +where "mailfilter" is a program which you have written to do the appropriate +mail processing. For more information on the command-line options refer to the reference guide or run: diff --git a/emailrelay.spec b/emailrelay.spec index fd18594..f46974b 100644 --- a/emailrelay.spec +++ b/emailrelay.spec @@ -1,10 +1,10 @@ Summary: Simple e-mail message transfer agent using SMTP Name: emailrelay -Version: 0.9.3 +Version: 0.9.4 Release: 1 Copyright: GPL Group: System Environment/Daemons -Source: http://emailrelay.sourceforge.net/.../emailrelay-src-0.9.3.tar.gz +Source: http://emailrelay.sourceforge.net/.../emailrelay-src-0.9.4.tar.gz BuildRoot: /tmp/emailrelay-install %description @@ -25,10 +25,10 @@ under the GNU General Public License. %build ./configure -make +make HAVE_DOXYGEN=no %install -make install destdir=$RPM_BUILD_ROOT DESTDIR=$RPM_BUILD_ROOT +make install destdir=$RPM_BUILD_ROOT DESTDIR=$RPM_BUILD_ROOT HAVE_DOXYGEN=no %clean rm -rf $RPM_BUILD_ROOT diff --git a/lib/gcc2.95/sstream b/lib/gcc2.95/sstream index 09ff6ce..93bf158 100644 --- a/lib/gcc2.95/sstream +++ b/lib/gcc2.95/sstream @@ -47,7 +47,7 @@ std::stringstream::stringstream() inline std::stringstream::stringstream( char * p , size_t n ) : - ostrstream( p , n ) + ostrstream(p,static_cast(n)) { } diff --git a/src/glib/Makefile.am b/src/glib/Makefile.am index d36f01c..6678dab 100644 --- a/src/glib/Makefile.am +++ b/src/glib/Makefile.am @@ -24,8 +24,7 @@ EXTRA_DIST=garg_win32.cpp \ gfs_win32.cpp \ glogoutput_win32.cpp \ gprocess_win32.cpp \ - gfile_win32.cpp \ - gnumber.cpp + gfile_win32.cpp INCLUDES = -I$(top_srcdir)/lib/gcc2.95 noinst_LIBRARIES = libglib.a libglib_a_SOURCES = \ @@ -61,7 +60,6 @@ libglib_a_SOURCES = \ glogoutput.h \ glogoutput_unix.cpp \ gmemory.h \ - gnumber.h \ gpath.cpp \ gpath.h \ gprocess.h \ diff --git a/src/glib/Makefile.in b/src/glib/Makefile.in index b478e20..f7b6bf3 100644 --- a/src/glib/Makefile.in +++ b/src/glib/Makefile.in @@ -89,11 +89,11 @@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ VERSION = @VERSION@ -EXTRA_DIST = garg_win32.cpp gdaemon_win32.cpp gdatetime_win32.cpp gdirectory_win32.cpp gfs_win32.cpp glogoutput_win32.cpp gprocess_win32.cpp gfile_win32.cpp gnumber.cpp +EXTRA_DIST = garg_win32.cpp gdaemon_win32.cpp gdatetime_win32.cpp gdirectory_win32.cpp gfs_win32.cpp glogoutput_win32.cpp gprocess_win32.cpp gfile_win32.cpp INCLUDES = -I$(top_srcdir)/lib/gcc2.95 noinst_LIBRARIES = libglib.a -libglib_a_SOURCES = garg.cpp garg.h garg_unix.cpp gassert.h gconvert.h gdaemon.h gdaemon_unix.cpp gdate.cpp gdate.h gdatetime.cpp gdatetime.h gdatetime_unix.cpp gdebug.h gdef.h gdirectory.cpp gdirectory.h gdirectory_unix.cpp gexception.cpp gexception.h gfile.cpp gfile.h gfile_unix.cpp gfs.h gfs_unix.cpp ggetopt.cpp ggetopt.h glog.cpp glog.h glogoutput.cpp glogoutput.h glogoutput_unix.cpp gmemory.h gnumber.h gpath.cpp gpath.h gprocess.h gprocess_unix.cpp gstr.cpp gstr.h gstrings.h gtime.cpp gtime.h +libglib_a_SOURCES = garg.cpp garg.h garg_unix.cpp gassert.h gconvert.h gdaemon.h gdaemon_unix.cpp gdate.cpp gdate.h gdatetime.cpp gdatetime.h gdatetime_unix.cpp gdebug.h gdef.h gdirectory.cpp gdirectory.h gdirectory_unix.cpp gexception.cpp gexception.h gfile.cpp gfile.h gfile_unix.cpp gfs.h gfs_unix.cpp ggetopt.cpp ggetopt.h glog.cpp glog.h glogoutput.cpp glogoutput.h glogoutput_unix.cpp gmemory.h gpath.cpp gpath.h gprocess.h gprocess_unix.cpp gstr.cpp gstr.h gstrings.h gtime.cpp gtime.h mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = ../../config.h diff --git a/src/glib/gdef.h b/src/glib/gdef.h index f4d6f3d..a270646 100644 --- a/src/glib/gdef.h +++ b/src/glib/gdef.h @@ -34,7 +34,7 @@ // Autoconf stuff // - #if HAVE_CONFIG_H + #if defined(HAVE_CONFIG_H) #include @@ -82,48 +82,26 @@ #define G_WINDOWS #endif - // Define the compiler and its capabilities + // Define the compiler // #if defined( _MSC_VER ) #define G_COMPILER_IS_MICROSOFT 1 - // #define G_COMPILER_HAS_... 0 #endif #if defined( __GNUC__ ) #define G_COMPILER_IS_GNU 1 - // #define G_COMPILER_HAS_... 1 #endif - // Modify compiler error handling for system headers - // - #if defined( G_COMPILER_IS_MICROSOFT ) - #pragma warning( disable : 4514 ) // don't reenable - #pragma warning( push , 3 ) - #pragma warning( disable : 4201 ) - #pragma warning( disable : 4514 ) // again - #pragma warning( disable : 4663 4018 4146 4018 ) - #pragma warning( disable : 4244 4100 4512 4511 ) - #endif - - // Include main operating-system headers + // Include main o/s headers // #if defined( G_WINDOWS ) #include #include #else #include - #include // ?? + #include #endif - // Restore complier error handling - // - #if defined( G_COMPILER_IS_MICROSOFT ) - #pragma warning( default : 4201 ) - #pragma warning( default : 4663 4018 4146 4018 ) - #pragma warning( default : 4244 4100 4512 4511 ) - #pragma warning( pop ) - #endif - - // Define Windows-style types (under Unix these + // Define Windows-style types (under unix these // are only used for unimplemented declarations) // #if ! defined( G_WINDOWS ) diff --git a/src/glib/gdirectory_win32.cpp b/src/glib/gdirectory_win32.cpp index 1169ccc..009c1a8 100644 --- a/src/glib/gdirectory_win32.cpp +++ b/src/glib/gdirectory_win32.cpp @@ -24,9 +24,9 @@ #include "gdef.h" #include "gdirectory.h" #include "gfs.h" -#include "gnumber.h" #include "gdebug.h" #include "glog.h" +#include namespace G { @@ -186,8 +186,8 @@ bool G::DirectoryIteratorImp::more() if( m_first ) { m_first = false ; - if( ::strcmp(m_context.cFileName,".") && - ::strcmp(m_context.cFileName,"..") ) + if( std::string(m_context.cFileName) == "." || + std::string(m_context.cFileName) == ".." ) return true ; G_DEBUG( "G::DirectoryIteratorImp::more: ignoring " << m_context.cFileName); @@ -214,8 +214,8 @@ bool G::DirectoryIteratorImp::more() } // go round again if . or .. - if( ::strcmp(m_context.cFileName,".") && - ::strcmp(m_context.cFileName,"..") ) + if( std::string(m_context.cFileName) != "." && + std::string(m_context.cFileName) != ".." ) { G_DEBUG( "G::DirectoryIteratorImp::more: " << m_context.cFileName ) ; break ; @@ -277,12 +277,12 @@ std::string G::DirectoryIteratorImp::modificationTimeString() const return std::string() ; } - char buffer[50U] ; - ::sprintf( buffer , "%lX%08lX" , - (unsigned long)m_context.ftLastWriteTime.dwHighDateTime , - (unsigned long)m_context.ftLastWriteTime.dwLowDateTime ) ; + const DWORD & hi = m_context.ftLastWriteTime.dwHighDateTime ; + const DWORD & lo = m_context.ftLastWriteTime.dwLowDateTime ; - return std::string(buffer) ; + std::stringstream ss ; + ss << hi << std::setw(8) << std::setfill('0') << lo ; + return ss.str() ; } std::string G::DirectoryIteratorImp::sizeString() const @@ -292,7 +292,11 @@ std::string G::DirectoryIteratorImp::sizeString() const return std::string( "0" ) ; } - Number size( m_context.nFileSizeHigh , m_context.nFileSizeLow ) ; - return size.displayString() ; + const DWORD & hi = m_context.nFileSizeHigh ; + const DWORD & lo = m_context.nFileSizeLow ; + + std::stringstream ss ; + ss << hi << std::setw(8) << std::setfill('0') << lo ; + return ss.str() ; } diff --git a/src/glib/ggetopt.cpp b/src/glib/ggetopt.cpp index a8ec3ac..a3fa027 100644 --- a/src/glib/ggetopt.cpp +++ b/src/glib/ggetopt.cpp @@ -29,11 +29,6 @@ #include "gassert.h" #include "gdebug.h" -static void GetOpt__pushBack( void * out , const std::string & s ) -{ - reinterpret_cast(out)->push_back(s) ; -} - G::GetOpt::GetOpt( const Arg & args_in , const std::string & spec , char sep_major , char sep_minor , char escape ) : m_args(args_in) @@ -53,13 +48,14 @@ void G::GetOpt::parseSpec( const std::string & spec , char sep_major , char sep_ void G::GetOpt::parseOldSpec( const std::string & spec ) { + unsigned int ordinal = 1U ; for( size_t i = 0U ; i < spec.length() ; i++ ) { char c = spec.at(i) ; if( c != ':' ) { bool valued = (i+1U) < spec.length() && spec.at(i+1U) == ':' ; - addSpec( c , valued ) ; + addSpec( ordinal++ , c , valued ) ; } } } @@ -70,6 +66,8 @@ void G::GetOpt::parseNewSpec( const std::string & spec , char sep_major , Strings outer ; std::string ws_major( 1U , sep_major ) ; G::Str::splitIntoFields( spec , outer , ws_major , escape , false ) ; + + unsigned int ordinal = 1U ; for( Strings::iterator p = outer.begin() ; p != outer.end() ; ++p ) { StringArray inner ; @@ -78,23 +76,34 @@ void G::GetOpt::parseNewSpec( const std::string & spec , char sep_major , if( inner.size() != 5U ) throw InvalidSpecification(std::stringstream() << "\"" << *p << "\" (" << ws_minor << ")") ; bool valued = G::Str::toUInt( inner[3U] ) != 0U ; - addSpec( inner[0U].at(0U) , inner[1U] , inner[2U] , valued , inner[4U] ) ; + addSpec( ordinal++ , inner[0U].at(0U) , inner[1U] , inner[2U] , valued , inner[4U] ) ; } } -void G::GetOpt::addSpec( char c , bool valued ) +void G::GetOpt::addSpec( unsigned int ordinal , char c , bool valued ) { - addSpec( c , std::string() , std::string() , valued , std::string() ) ; + addSpec( ordinal , c , std::string() , std::string() , valued , std::string() ) ; } -void G::GetOpt::addSpec( char c , const std::string & name , const std::string & description , +void G::GetOpt::addSpec( unsigned int ordinal , char c , const std::string & name , const std::string & description , bool valued , const std::string & value_description ) { if( c == '\0' ) throw InvalidSpecification() ; + const bool debug = true ; + if( debug ) + { + G_DEBUG( "G::GetOpt::addSpec: #" << ordinal << ": " + << "char=" << c << ": " + << "name=" << name << ": " + << "description=" << description << ": " + << "valued=" << (valued?"true":"false") << ": " + << "value-description=" << value_description ) ; + } + std::pair rc = - m_spec_map.insert( std::make_pair(c,SwitchSpec(c,name,description,valued,value_description)) ) ; + m_spec_map.insert( std::make_pair(ordinal,SwitchSpec(c,name,description,valued,value_description)) ) ; if( ! rc.second ) throw InvalidSpecification("duplication") ; @@ -107,11 +116,12 @@ bool G::GetOpt::valued( const std::string & name ) const bool G::GetOpt::valued( char c ) const { - SwitchSpecMap::const_iterator p = m_spec_map.find( c ) ; - if( p == m_spec_map.end() ) - return false ; - else - return (*p).second.valued ; + for( SwitchSpecMap::const_iterator p = m_spec_map.begin() ; p != m_spec_map.end() ; ++p ) + { + if( (*p).second.c == c ) + return (*p).second.valued ; + } + return false ; } char G::GetOpt::key( const std::string & name ) const @@ -120,7 +130,7 @@ char G::GetOpt::key( const std::string & name ) const { if( (*p).second.name == name ) { - return (*p).first ; + return (*p).second.c ; } } G_DEBUG( "G::GetOpt::key: " << name << " not found" ) ; @@ -177,7 +187,7 @@ std::string G::GetOpt::usageSummaryPartOne() const if( first ) ss << "[-" ; first = false ; - ss << (*p).first ; + ss << (*p).second.c ; } } @@ -201,7 +211,7 @@ std::string G::GetOpt::usageSummaryPartTwo() const } else { - ss << "-" << (*p).first ; + ss << "-" << (*p).second.c ; } if( (*p).second.valued ) { @@ -230,7 +240,7 @@ std::string G::GetOpt::usageHelpCore( const std::string & prefix , size_t tab_st { std::string line( prefix ) ; line.append( "-" ) ; - line.append( 1U , (*p).first ) ; + line.append( 1U , (*p).second.c ) ; if( (*p).second.name.length() ) { @@ -458,15 +468,24 @@ void G::GetOpt::show( std::ostream &stream , std::string prefix ) const { char c = (*p).first ; Value v = (*p).second ; + bool valued = v.first ; + std::string value = v.second ; - SwitchSpecMap::const_iterator q = m_spec_map.find( c ) ; std::string name ; - if( q != m_spec_map.end() ) - name = (*q).second.name ; + for( SwitchSpecMap::const_iterator q = m_spec_map.begin() ; q != m_spec_map.end() ; ++q ) + { + if( (*q).second.c == c ) + { + name = (*q).second.name ; + break ; + } + } - stream << prefix << "--" << name ; - if( v.first ) - stream << " = \"" << v.second << "\"" ; + stream << prefix << "-" << c ; + if( !name.empty() ) + stream << ",--" << name ; + if( valued ) + stream << " = \"" << value << "\"" ; stream << std::endl ; } } @@ -504,7 +523,12 @@ bool G::GetOpt::valid( const std::string & name ) const bool G::GetOpt::valid( char c ) const { - return m_spec_map.find( c ) != m_spec_map.end() ; + for( SwitchSpecMap::const_iterator p = m_spec_map.begin() ; p != m_spec_map.end() ; ++p ) + { + if( (*p).second.c == c ) + return true ; + } + return false ; } diff --git a/src/glib/ggetopt.h b/src/glib/ggetopt.h index 08844ad..37ba002 100644 --- a/src/glib/ggetopt.h +++ b/src/glib/ggetopt.h @@ -137,7 +137,7 @@ private: hidden(description_.empty()) , valued(v_) , value_description(vd_) {} } ; - typedef std::map SwitchSpecMap ; + typedef std::map SwitchSpecMap ; typedef std::pair Value ; typedef std::map SwitchMap ; @@ -146,8 +146,8 @@ private: void parseSpec( const std::string & spec , char , char , char ) ; void parseOldSpec( const std::string & spec ) ; void parseNewSpec( const std::string & spec , char , char , char ) ; - void addSpec( char c , bool valued ) ; - void addSpec( char c , const std::string & name , const std::string & , bool valued , const std::string & ) ; + void addSpec( unsigned int ordinal , char c , bool valued ) ; + void addSpec( unsigned int ordinal , char c , const std::string & name , const std::string & , bool valued , const std::string & ) ; size_t parseArgs( const Arg & args_in ) ; bool isOldSwitch( const std::string & arg ) const ; bool isNewSwitch( const std::string & arg ) const ; diff --git a/src/glib/glogoutput.cpp b/src/glib/glogoutput.cpp index 9b0fbc7..3258caa 100644 --- a/src/glib/glogoutput.cpp +++ b/src/glib/glogoutput.cpp @@ -57,12 +57,12 @@ void G::LogOutput::itoa( char *out , unsigned int n ) if( n == 0U ) { - out[0] = '0' ; - out[1] = '\0' ; + out[0U] = '0' ; + out[1U] = '\0' ; } else { - char buffer[15] ; + char buffer[15U] ; char *p = buffer + sizeof(buffer) - 1 ; *p-- = '\0' ; @@ -72,7 +72,7 @@ void G::LogOutput::itoa( char *out , unsigned int n ) n /= 10U ; } - ::strcpy( out , p+1 ) ; + std::strcpy( out , p+1 ) ; } } @@ -84,7 +84,7 @@ void G::LogOutput::output( G::Log::Severity severity , const char *text ) if( severity != G::Log::s_Debug || m_this->m_verbose ) { m_this->rawOutput( severity , text ? text : "" ) ; - if( text && text[0] && text[std::strlen(text)-1] != '\n' ) + if( text && text[0U] && text[std::strlen(text)-1U] != '\n' ) m_this->rawOutput( severity , "\n" ) ; } } @@ -100,11 +100,11 @@ void G::LogOutput::output( G::Log::Severity severity , const char *file, unsigne if( m_this == NULL || !m_this->m_enabled ) return ; - char buffer[500] ; - buffer[0] = '\0' ; + char buffer[500U] ; + buffer[0U] = '\0' ; if( severity == G::Log::s_Debug ) fileAndLine( buffer , sizeof(buffer) , file , line ) ; - std::strncat( buffer + std::strlen(buffer) , text , sizeof(buffer) - 1 - std::strlen(buffer) ) ; + std::strncat( buffer + std::strlen(buffer) , text , sizeof(buffer) - 1U - std::strlen(buffer) ) ; output( severity , buffer ) ; } @@ -121,33 +121,33 @@ void G::LogOutput::onAssert() //static void G::LogOutput::fileAndLine( char *buffer , size_t size , const char *file , int line ) { - const char *forward = ::strrchr( file , '/' ) ; - const char *back = ::strrchr( file , '\\' ) ; + const char *forward = std::strrchr( file , '/' ) ; + const char *back = std::strrchr( file , '\\' ) ; const char *last = forward > back ? forward : back ; const char *basename = last ? (last+1) : file ; - std::strncat( buffer+std::strlen(buffer) , basename , size-std::strlen(buffer)-1 ) ; - std::strncat( buffer+std::strlen(buffer) , "(" , size-std::strlen(buffer)-1 ) ; - char b[15] ; - itoa( b , line ) ; - std::strncat( buffer+std::strlen(buffer) , b , size-std::strlen(buffer)-1 ) ; - std::strncat( buffer+std::strlen(buffer) , "): " , size-std::strlen(buffer)-1 ) ; + std::strncat( buffer+std::strlen(buffer) , basename , size-std::strlen(buffer)-1U ) ; + std::strncat( buffer+std::strlen(buffer) , "(" , size-std::strlen(buffer)-1U ) ; + char b[15U] ; + itoa( b , line ) ; // (implemented above) + std::strncat( buffer+std::strlen(buffer) , b , size-std::strlen(buffer)-1U ) ; + std::strncat( buffer+std::strlen(buffer) , "): " , size-std::strlen(buffer)-1U ) ; } void G::LogOutput::assertion( const char *file , unsigned line , bool test , const char *test_string ) { if( !test ) { - char buffer[100] ; + char buffer[100U] ; std::strcpy( buffer , "Assertion error: " ) ; - size_t size = sizeof(buffer) - 10 ; // -10 for luck + size_t size = sizeof(buffer) - 10U ; // -10 for luck if( file ) { fileAndLine( buffer , size , file , line ) ; } if( test_string ) { - std::strncat( buffer+std::strlen(buffer) , test_string , size-std::strlen(buffer)-1); + std::strncat( buffer+std::strlen(buffer) , test_string , size-std::strlen(buffer)-1U); } if( instance() ) diff --git a/src/glib/gmemory.h b/src/glib/gmemory.h index a532c99..069fb08 100644 --- a/src/glib/gmemory.h +++ b/src/glib/gmemory.h @@ -27,7 +27,10 @@ #include "gdef.h" #include +// define HAVE_NONCONST_AUTOPTR +// #if HAVE_CONFIG_H + // autoconf's config.h #include #else #ifdef G_WINDOWS @@ -38,12 +41,11 @@ #endif // Template function: operator<<= -// Description: A fix for the problem of resetting -// an auto_ptr portably. MSVC6.0 does not have a reset -// method, and GCC 2.95 has a non-const assignment -// operators. This means that the MSVC code and -// the GCC code for resetting auto_ptr<>s has to -// be quite different. This operator hides +// Description: A fix for the problem of resetting an auto_ptr<> +// portably. MSVC6.0 & GCC 2.91 do not have a reset() method, +// and GCC 2.95 has a non-const assignment operators. This means +// that the MSVC code and the GCC 2.95 code for resetting +// auto_ptr<>s has to be quite different. This operator hides // those differences. // // Usage: diff --git a/src/glib/gnumber.cpp b/src/glib/gnumber.cpp deleted file mode 100644 index 545a5e9..0000000 --- a/src/glib/gnumber.cpp +++ /dev/null @@ -1,545 +0,0 @@ -// -// Copyright (C) 2001 Graeme Walker -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -// -// === -// -// gnumber.cc -// - -#include "gdef.h" -#include "gnumber.h" -#include "gdebug.h" -#include -#include -#include - -const g_uint32_t bit31 = 0x80000000L ; - -inline bool msb( g_uint32_t n ) -{ - return !!( n & bit31 ) ; -} ; - -G::Number::~Number() -{ -} - -G::Number::Number() : - m_high(0) , - m_low(0) -{ -} - -G::Number::Number( g_uint32_t n32 ) : - m_low(n32) , - m_high(0) -{ -} - -G::Number::Number( g_uint32_t high , g_uint32_t low ) : - m_low(low) , - m_high(high) -{ -} - -G::Number::Number( const Number &other ) -{ - m_low = other.m_low ; - m_high = other.m_high ; -} - -G::Number &G::Number::operator=( const Number &other ) -{ - m_low = other.m_low ; - m_high = other.m_high ; - return *this ; -} - -bool G::Number::big() const -{ - return m_high != 0 ; -} - -bool G::Number::big( long* ) const -{ - // optimise for the common case - if( sizeof(long) <= sizeof(g_uint32_t) ) - { - return m_high != 0 || m_low > LONG_MAX ; - } - - // or more generally... - Number n = LONG_MAX ; - return (*this) > n ; -} - -bool G::Number::big( unsigned long* ) const -{ - if( sizeof(unsigned long) <= sizeof(g_uint32_t) ) - { - return m_high != 0 || m_low > ULONG_MAX ; - } - - Number n = ULONG_MAX ; - return (*this) > n ; -} - -g_uint32_t G::Number::value() const -{ - if( big() ) - { - g_uint32_t rc = 0 ; - rc = ~rc ; - return rc ; - } - return m_low ; -} - -unsigned long G::Number::value( unsigned long *p ) -{ - if( big((unsigned long*)0) ) - { - if( p != NULL ) *p = ULONG_MAX ; - return ULONG_MAX ; - } - - unsigned long ul = m_high ; - ul <<= 32 ; // ignore warnings -- this is in case sizeof(long) > 32 - ul |= m_low ; - if( p != NULL ) *p = ul ; - return ul ; -} - -G::Number::operator double() -{ - double d = m_high ; - d *= static_cast(0x10000L) ; // <<=16 - d *= static_cast(0x10000L) ; // <<=16 - d += m_low ; - return d ; -} - -G::Number::operator unsigned long() -{ - return value( (unsigned long *)0 ) ; -} - -long G::Number::value( long *p ) -{ - if( big((long*)0) ) - { - if( p != NULL ) *p = LONG_MAX ; - return LONG_MAX ; - } - - long l = m_high ; - l <<= 32 ; // ignore warnings -- this is in case sizeof(long) > 32 - l |= m_low ; - if( p != NULL ) *p = l ; - return l ; -} - -G::Number &G::Number::to48bits() -{ - m_high &= 0xffff ; - return *this ; -} - -g_uint32_t G::Number::high() const -{ - return m_high ; -} - -g_uint32_t G::Number::low() const -{ - return m_low ; -} - -void G::Number::lshift( unsigned places ) -{ - if( places == 0 ) - { - } - else if( places < 32 ) - { - m_high <<= places ; - m_high |= (m_low >> (32-places)) ; - m_low <<= places ; - } - else if( places == 32 ) - { - lshift32() ; - } - else if( places < 64 ) - { - m_high = m_low ; - m_low = 0 ; - m_high <<= ( places - 32 ) ; - } - else - { - m_high = m_low = 0 ; - } -} - -void G::Number::lshift32() -{ - m_high = m_low ; - m_low = 0 ; -} - -void G::Number::rshift( unsigned places ) -{ - if( places == 0 ) - { - } - else if( places < 32 ) - { - m_low >>= places ; - m_low |= (m_high << (32-places)) ; - m_high >>= places ; - } - else if( places == 32 ) - { - rshift32() ; - } - else if( places < 64 ) - { - m_low = m_high ; - m_high = 0 ; - m_low >>= ( places - 32 ) ; - } - else - { - m_high = m_low = 0 ; - } -} - -void G::Number::rshift32() -{ - m_low = m_high ; - m_high = 0 ; -} - -G::Number G::Number::operator++(int) -{ - Number old = (*this) ; - ++(*this) ; - return old ; -} - -G::Number G::Number::operator--(int) -{ - Number old = (*this) ; - --(*this) ; - return old ; -} - -G::Number &G::Number::operator++() -{ - m_low++ ; - if( m_low == 0 ) - m_high++ ; - return *this ; -} - -G::Number &G::Number::operator--() -{ - if( m_low == 0 ) - m_high-- ; - m_low-- ; - return *this ; -} - -G::Number G::Number::operator+( const Number &other ) const -{ - Number result = (*this) ; - result += other ; - return result ; -} - -G::Number G::Number::operator-( const Number &other ) const -{ - Number result = (*this) ; - result -= other ; - return result ; -} - -G::Number G::Number::operator*( const Number &other ) const -{ - Number result = (*this) ; - result *= other ; - return result ; -} - -G::Number G::Number::operator/( g_uint16_t divisor ) const -{ - Number result = (*this) ; - result /= divisor ; - return result ; -} - -G::Number &G::Number::operator-=( const Number &other ) -{ - if( &other == this ) - { - m_high = m_low = 0 ; - return *this ; - } - - // create two's complement of other.. - Number copy = other ; - copy.m_high = ~copy.m_high ; - copy.m_low = ~copy.m_low ; - ++copy ; - - // ..and add - (*this) += copy ; - return *this ; -} - -G::Number &G::Number::operator+=( const Number &other ) -{ - if( &other == this ) - { - m_high <<= 1 ; - m_high += msb( m_low ) ; - m_low <<= 1 ; - return *this ; - } - - bool a = msb( m_low ) ; - bool b = msb( other.m_low ) ; - - g_uint32_t new_low = m_low + other.m_low ; - bool c = msb( new_low ) ; - m_low = new_low ; - - bool carry = ( a && b ) | ( (a ^ b) && !c ) ; - - m_high += other.m_high ; - if( carry ) - m_high++ ; - - return *this ; -} - -G::Number &G::Number::operator/=( g_uint16_t divisor ) -{ - Number remainder ; - Number quotient ; - divide16( (*this) , divisor , quotient , remainder ) ; - (*this) = quotient ; - return *this ; -} - -G::Number &G::Number::operator%=( g_uint16_t divisor ) -{ - Number remainder ; - Number quotient ; - divide16( (*this) , divisor , quotient , remainder ) ; - (*this) = remainder ; - return *this ; -} - -void G::Number::divide16( const Number &const_dividend , g_uint16_t divisor , Number "ient , Number &remainder ) -{ - // division is complicated by the need for a double-width - // accumulator ie. an accumulator double the width of the - // divisor -- since we restrict ourselves to using built-in - // types of 32 bits (for portability) this divisor is limited - // to 16 bits. Full 64/64 bit division must be built using - // this 64/16 bit division and a 128-bit accumulator. - - // the algorithm is basic long division -- consider dividing - // a four digit (16-bit) hex number by a one-digit (4-bit) - // hex number -- then scale the algorithm up to 64/16 bits. - - G_ASSERT( divisor != 0 ) ; - quotient = 0 ; - remainder = 0 ; - Number accumulator = 0 ; - Number dividend = const_dividend ; - - for( size_t i = 0 ; i < 4 ; i++ ) - { - // shift the dividend into the accumulator - accumulator <<= 16 ; - accumulator.m_low |= (dividend.m_high >> 16) ; - dividend <<= 16 ; - G_ASSERT( accumulator.m_high == 0 ) ; // assert 32 bit accumulator - - // shift the partial quotient into the full quotient - quotient <<= 16 ; - quotient.m_low |= (accumulator.m_low / divisor) ; - G_ASSERT( ((accumulator.m_low / divisor) >>16) == 0 ) ; // assert 16 bit partial quotient - - // set the accumulator to the partial remainder - accumulator = (accumulator.m_low % divisor) ; - G_ASSERT( (accumulator.m_low >> 16) == 0 ) ; // assert 16 bit accumulator - } - - remainder = accumulator ; -} - -G::Number &G::Number::operator*=( const Number &other ) -{ - if( &other == this ) - { - Number copy( other ) ; - operator*=( copy ) ; - return *this ; - } - - // 16 * 16 -> 32 - if( m_high == 0 && other.m_high == 0 && - m_low <= 0xffff && other.m_low <= 0xffff ) - { - m_low *= other.m_low ; - } - - // 32 * 32 -> 64 - else if( m_high == 0 && other.m_high == 0 ) - { - // four 16-bit numbers - Number a( (m_low >> 16) & 0xffff ) ; - Number b( m_low & 0xffff ) ; - Number c( (other.m_low >> 16) & 0xffff ) ; - Number d( other.m_low & 0xffff ) ; - - // one 32-bit partial product - Number bd = b ; bd *= d ; - - // two 48-bit partial products - Number cb = c ; cb *= b ; cb.lshift(16) ; - Number ad = a ; ad *= d ; ad.lshift(16) ; - - // one 64-bit partial product - Number ac = a ; ac *= c ; ac.lshift32() ; - - // 64-bit product - Number product = bd ; - product += cb ; - product += ad ; - product += ac ; - m_low = product.m_low ; - m_high = product.m_high ; - } - - // 64 * 64 -> 64 - else - { - // four 32-bit numbers - Number a( m_high ) ; - Number b( m_low ) ; - Number c( other.m_high ) ; - Number d( other.m_low ) ; - - // three 64-bit partial products - Number bd = b ; bd *= d ; - Number cb = c ; cb *= b ; cb.lshift32() ; - Number ad = a ; ad *= d ; ad.lshift32() ; - - // 64-bit product - Number product = bd ; - product += cb ; - product += ad ; - m_low = product.m_low ; - m_high = product.m_high ; - } - - return *this ; -} - -bool G::Number::operator==( const Number &other ) const -{ - return m_high == other.m_high && m_low == other.m_low ; -} - -bool G::Number::operator!=( const Number &other ) const -{ - return !( *this == other ) ; -} - -bool G::Number::operator<( const Number &other ) const -{ - if( m_high == other.m_high ) - return m_low < other.m_low ; - else - return m_high < other.m_high ; -} - -bool G::Number::operator<=( const Number &other ) const -{ - return ( *this < other ) || ( *this == other ) ; -} - -bool G::Number::operator>( const Number &other ) const -{ - return !( *this <= other ) ; -} - -bool G::Number::operator>=( const Number &other ) const -{ - return !( *this < other ) ; -} - -G::Number &G::Number::operator|=( const Number &other ) -{ - m_high |= other.m_high ; - m_low |= other.m_low ; - return *this ; -} - -G::Number &G::Number::operator<<=( unsigned places ) -{ - lshift( places ) ; - return *this ; -} - -G::Number &G::Number::operator>>=( unsigned places ) -{ - rshift( places ) ; - return *this ; -} - -std::string G::Number::displayString() const -{ - std::stringstream ss ; - if( m_high != 0 ) - { - ss << m_high ; - ss.width( 8U ) ; - ss << m_low ; - } - else - { - ss << m_low ; - } - return ss.str() ; -} - -namespace G -{ - std::ostream & operator<<( std::ostream & stream , const Number n ) - { - stream << n.displayString() ; - return stream ; - } -} ; - diff --git a/src/glib/gnumber.h b/src/glib/gnumber.h deleted file mode 100644 index df6b5fc..0000000 --- a/src/glib/gnumber.h +++ /dev/null @@ -1,213 +0,0 @@ -// -// Copyright (C) 2001 Graeme Walker -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -// -// === -// -// gnumber.h -// - -#ifndef G_NUMBER_H -#define G_NUMBER_H - -#include "gdef.h" -#include - -namespace G -{ - class Number ; -} ; - -// Class: G::Number -// Description: A Number object represents an unsigned integer -// of up to 64 bits. The implementation is very old and not complete. -// -// See also: a64l(3c), LONGLONG, uint64_t, u_longlong_t -// -class G::Number -{ -public: - Number() ; - // Default constructor. The value is set to zero. - - Number( g_uint32_t n32 ) ; - // Constructor taking one 32-bit argument. - - Number( g_uint32_t high , g_uint32_t low ) ; - // Constructor taking two 32-bit arguments. - - Number( const Number &other ) ; - // Copy constructor. - - ~Number() ; - // Destructor. - - g_uint32_t value() const ; - // Returns the numeric value. Returns the maximum - // 32-bit value if the value is too big for a g_uint32_t. - // See big(). (This behaviour is generally preferable to - // truncating the value to 32 bits since a very big - // number can suddenly become a small number. Other - // member functions are available to do truncation.) - - unsigned long value( unsigned long *ulp ) ; - // Returns (by value and reference) the value - // as an unsigned long. The value returned is - // ULONG_MAX if the number is too big for an - // unsigned long. See big(unsigned long*) and - // operator unsigned long(). - - long value( long *lp ) ; - // Returns (by value and reference) the value - // as a long integer. The value returned is - // LONG_MAX if the number is too big for a long. - // See big(long*). - - operator unsigned long() ; - // Cast operator. The value returned is ULONG_MAX if - // the number is too big for an unsigned long. See - // big(unsigned long*) and value(unsigned long*). - - operator double() ; - // Cast operator returning a double precision - // floating point value. - - bool big() const ; - // Returns true if the number is bigger than - // 32 bits. See value(). - - bool big( long *dummy ) const ; - // Returns true if the number is too big - // for a long. See operator long(). - // The dummy parameter is ignored. - - bool big( unsigned long *dummy ) const ; - // Returns true if the number is too big - // for an unsigned long. See operator - // unsigned long(). The dummy parameter - // is ignored. - - Number &operator=( const Number &other ) ; - // Assignment operator. - - Number &to48bits() ; - // Truncates the value to 48 bits. The top 16 bits - // are zeroed. - - g_uint32_t high() const ; - // Returns the most significant 32 bits. - - g_uint32_t low() const ; - // Returns the least significant 32 bits. - - Number operator+ ( const Number &addend ) const ; - // Addition operator. - - Number &operator+=( const Number &addend ) ; - // Self-addition operator. - - Number operator- ( const Number &subtrahend ) const ; - // Subtraction operator. - - Number &operator-=( const Number &subtrahend ) ; - // Self-subtraction operator. - - Number operator* ( const Number &multiplicand ) const ; - // Multiplcation operator. - - Number &operator*=( const Number &multiplicand ) ; - // Self-multiplication operator. - - Number operator/ ( g_uint16_t divisor ) const ; - // Division operator. - - Number &operator/=( g_uint16_t divisor ) ; - // Self-division operator. - - Number operator% ( g_uint16_t divisor ) const ; - // Modulo operator. - - Number &operator%=( g_uint16_t divisor ) ; - // Self-modulo operator. - - Number &operator|=( const Number &other ) ; - // Bitwise OR operator. - - void lshift( unsigned places ) ; - // Left-shifts this number by the given number of bits. - - void lshift32() ; - // Left-shifts this number 32 bits. - - void rshift( unsigned places ) ; - // Right-shifts this number by the given number of bits. - - void rshift32() ; - // Right-shifts this number 32 bits. - - Number &operator<<=( unsigned places ) ; - // Left-shift operator. - - Number &operator>>=( unsigned places ) ; - // Right-shift operator. - - Number operator++(int) ; - // Post-increment operator. - - Number operator--(int) ; - // Post-decrement operator. - - Number &operator++() ; - // Pre-increment operator. - - Number &operator--() ; - // Post-increment operator. - - bool operator==( const Number &other ) const ; - // Equality comparison operator. - - bool operator!=( const Number &other ) const ; - // Inequality comparison operator. - - bool operator<( const Number &other ) const ; - // Less-than comparison operator. - - bool operator<=( const Number &other ) const ; - // Less-than-or-equal comparison operator. - - bool operator>( const Number &other ) const ; - // Greater-than comparison operator. - - bool operator>=( const Number &other ) const ; - // Greater-than-or-equal comparison operator. - - friend std::ostream &operator<<( std::ostream &stream , const Number n ) ; - // Global function which streams out a Number object. - - std::string displayString() const ; - // Returns a printable string representation. - -private: - static void divide16( const Number ÷nd , g_uint16_t divisor , Number " , Number &rem ) ; - -private: - g_uint32_t m_high ; - g_uint32_t m_low ; -} ; - -#endif - diff --git a/src/glib/gprocess_unix.cpp b/src/glib/gprocess_unix.cpp index d6c45f2..6e97985 100644 --- a/src/glib/gprocess_unix.cpp +++ b/src/glib/gprocess_unix.cpp @@ -206,7 +206,7 @@ int G::Process::spawn( const G::Path & exe , const std::string & arg , int error bool G::Process::privileged() { - return getuid() == 0 || geteuid() == 0 ; + return ::getuid() == 0U || ::geteuid() == 0U ; } // === diff --git a/src/gnet/Makefile.am b/src/gnet/Makefile.am index 4bf2ac9..e2a120c 100644 --- a/src/gnet/Makefile.am +++ b/src/gnet/Makefile.am @@ -31,12 +31,14 @@ noinst_LIBRARIES = libgnet.a libgnet_a_SOURCES = gaddress_ipv4.cpp \ gclient.cpp \ gclient_unix.cpp \ + gconnection.cpp \ gdescriptor_unix.cpp \ gevent.cpp \ gevent_unix.cpp \ geventserver.cpp \ glinebuffer.cpp \ glocal_unix.cpp \ + gmonitor.cpp \ gresolve.cpp \ gresolve_ipv4.cpp \ gresolve_unix.cpp \ @@ -46,11 +48,13 @@ libgnet_a_SOURCES = gaddress_ipv4.cpp \ gsocket_unix.cpp \ gaddress.h \ gclient.h \ + gconnection.h \ gdescriptor.h \ gevent.h \ geventserver.h \ glinebuffer.h \ glocal.h \ + gmonitor.h \ gnet.h \ grequest.h \ gresolve.h \ diff --git a/src/gnet/Makefile.in b/src/gnet/Makefile.in index 11f988e..877878b 100644 --- a/src/gnet/Makefile.in +++ b/src/gnet/Makefile.in @@ -93,7 +93,7 @@ EXTRA_DIST = gclient_win32.cpp gdescriptor_win32.cpp gevent_win32.cpp glocal_ INCLUDES = -I$(top_srcdir)/lib/gcc2.95 -I$(top_srcdir)/src/glib noinst_LIBRARIES = libgnet.a -libgnet_a_SOURCES = gaddress_ipv4.cpp gclient.cpp gclient_unix.cpp gdescriptor_unix.cpp gevent.cpp gevent_unix.cpp geventserver.cpp glinebuffer.cpp glocal_unix.cpp gresolve.cpp gresolve_ipv4.cpp gresolve_unix.cpp gselect.cpp gserver.cpp gsocket.cpp gsocket_unix.cpp gaddress.h gclient.h gdescriptor.h gevent.h geventserver.h glinebuffer.h glocal.h gnet.h grequest.h gresolve.h gselect.h gserver.h gsocket.h gwinsock.h +libgnet_a_SOURCES = gaddress_ipv4.cpp gclient.cpp gclient_unix.cpp gconnection.cpp gdescriptor_unix.cpp gevent.cpp gevent_unix.cpp geventserver.cpp glinebuffer.cpp glocal_unix.cpp gmonitor.cpp gresolve.cpp gresolve_ipv4.cpp gresolve_unix.cpp gselect.cpp gserver.cpp gsocket.cpp gsocket_unix.cpp gaddress.h gclient.h gconnection.h gdescriptor.h gevent.h geventserver.h glinebuffer.h glocal.h gmonitor.h gnet.h grequest.h gresolve.h gselect.h gserver.h gsocket.h gwinsock.h mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = ../../config.h @@ -107,9 +107,9 @@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ libgnet_a_LIBADD = libgnet_a_OBJECTS = gaddress_ipv4.o gclient.o gclient_unix.o \ -gdescriptor_unix.o gevent.o gevent_unix.o geventserver.o glinebuffer.o \ -glocal_unix.o gresolve.o gresolve_ipv4.o gresolve_unix.o gselect.o \ -gserver.o gsocket.o gsocket_unix.o +gconnection.o gdescriptor_unix.o gevent.o gevent_unix.o geventserver.o \ +glinebuffer.o glocal_unix.o gmonitor.o gresolve.o gresolve_ipv4.o \ +gresolve_unix.o gselect.o gserver.o gsocket.o gsocket_unix.o CXXFLAGS = @CXXFLAGS@ CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) @@ -230,14 +230,19 @@ gclient.o: gclient.cpp ../../src/glib/gdef.h ../../config.h \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ gaddress.h ../../src/glib/gexception.h gsocket.h gevent.h \ - gdescriptor.h ../../src/glib/gdatetime.h gresolve.h gclient.h \ + gdescriptor.h ../../src/glib/gdatetime.h gresolve.h gmonitor.h \ + gclient.h gconnection.h gserver.h gselect.h \ ../../src/glib/gdebug.h ../../src/glib/glogoutput.h \ ../../src/glib/glog.h ../../src/glib/gassert.h gclient_unix.o: gclient_unix.cpp ../../src/glib/gdef.h ../../config.h \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ - gclient.h gaddress.h ../../src/glib/gexception.h gsocket.h \ - gevent.h gdescriptor.h + gclient.h gaddress.h ../../src/glib/gexception.h gconnection.h \ + gsocket.h gevent.h gdescriptor.h +gconnection.o: gconnection.cpp ../../src/glib/gdef.h ../../config.h \ + ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ + ../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ + gconnection.h gaddress.h ../../src/glib/gexception.h gdescriptor_unix.o: gdescriptor_unix.cpp ../../src/glib/gdef.h \ ../../config.h ../../lib/gcc2.95/iostream \ ../../lib/gcc2.95/sstream ../../lib/gcc2.95/xlocale \ @@ -256,8 +261,8 @@ geventserver.o: geventserver.cpp ../../src/glib/gdef.h ../../config.h \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ geventserver.h gserver.h gsocket.h gaddress.h \ - ../../src/glib/gexception.h gevent.h gdescriptor.h gselect.h \ - ../../src/glib/glog.h + ../../src/glib/gexception.h gevent.h gdescriptor.h \ + gconnection.h gselect.h ../../src/glib/glog.h glinebuffer.o: glinebuffer.cpp ../../src/glib/gdef.h ../../config.h \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ @@ -269,6 +274,13 @@ glocal_unix.o: glocal_unix.cpp ../../src/glib/gdef.h ../../config.h \ ../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits glocal.h \ gnet.h gaddress.h ../../src/glib/gexception.h gresolve.h \ ../../src/glib/glog.h +gmonitor.o: gmonitor.cpp ../../src/glib/gdef.h ../../config.h \ + ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ + ../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ + gmonitor.h gclient.h gaddress.h ../../src/glib/gexception.h \ + gconnection.h gsocket.h gevent.h gdescriptor.h gserver.h \ + gselect.h ../../src/glib/gassert.h ../../src/glib/glogoutput.h \ + ../../src/glib/glog.h gresolve.o: gresolve.cpp ../../src/glib/gdef.h ../../config.h \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gresolve.h \ @@ -299,9 +311,9 @@ gserver.o: gserver.cpp ../../src/glib/gdef.h ../../config.h \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ gserver.h gsocket.h gaddress.h ../../src/glib/gexception.h \ - gevent.h gdescriptor.h gselect.h ../../src/glib/gdebug.h \ - ../../src/glib/glogoutput.h ../../src/glib/glog.h \ - ../../src/glib/gassert.h + gevent.h gdescriptor.h gconnection.h gselect.h gmonitor.h \ + gclient.h ../../src/glib/gdebug.h ../../src/glib/glogoutput.h \ + ../../src/glib/glog.h ../../src/glib/gassert.h gsocket.o: gsocket.cpp ../../src/glib/gdef.h ../../config.h \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ diff --git a/src/gnet/gclient.cpp b/src/gnet/gclient.cpp index c518400..1146a27 100644 --- a/src/gnet/gclient.cpp +++ b/src/gnet/gclient.cpp @@ -27,6 +27,7 @@ #include "gsocket.h" #include "gdatetime.h" #include "gresolve.h" +#include "gmonitor.h" #include "gclient.h" #include "gdebug.h" #include "gassert.h" @@ -98,12 +99,15 @@ public: std::string startConnecting( const Address & , bool & ) ; Status connectCore( Address , std::string * , bool , unsigned int ) ; void disconnect() ; - StreamSocket & s() ; + StreamSocket & s() ; + const StreamSocket & s() const ; void run() ; void close() ; void blocked() ; bool connected() const ; void setState( State ) ; + std::pair localAddress() const ; + std::pair peerAddress() const ; private: ClientImp( const ClientImp & ) ; @@ -118,10 +122,12 @@ GNet::Client::Client( bool priviledged , bool quit_on_disconnect ) : { G_DEBUG( "Client::ctor" ) ; m_imp = new ClientImp( *this , priviledged , quit_on_disconnect ) ; + if( Monitor::instance() ) Monitor::instance()->add( *this ) ; } GNet::Client::~Client() { + if( Monitor::instance() ) Monitor::instance()->remove( *this ) ; delete m_imp ; } @@ -150,6 +156,16 @@ void GNet::Client::disconnect() m_imp->disconnect() ; } +std::pair GNet::Client::localAddress() const +{ + return m_imp->localAddress() ; +} + +std::pair GNet::Client::peerAddress() const +{ + return m_imp->peerAddress() ; +} + // === bool GNet::ClientImp::m_first = true ; @@ -186,6 +202,12 @@ GNet::StreamSocket & GNet::ClientImp::s() return *m_s ; } +const GNet::StreamSocket & GNet::ClientImp::s() const +{ + G_ASSERT( m_s != NULL ) ; + return *m_s ; +} + GNet::ClientImp::~ClientImp() { setState( Disconnected ) ; // for quit() @@ -455,6 +477,16 @@ void GNet::ClientImp::run() EventSources::instance().run() ; } +std::pair GNet::ClientImp::localAddress() const +{ + return s().getLocalAddress() ; +} + +std::pair GNet::ClientImp::peerAddress() const +{ + return s().getPeerAddress() ; +} + // === void GNet::ClientResolver::resolveCon( bool success , const Address &address , diff --git a/src/gnet/gclient.h b/src/gnet/gclient.h index cf672b5..3fee42a 100644 --- a/src/gnet/gclient.h +++ b/src/gnet/gclient.h @@ -27,6 +27,7 @@ #include "gdef.h" #include "gnet.h" #include "gaddress.h" +#include "gconnection.h" #include "gsocket.h" #include "gevent.h" #include @@ -43,7 +44,7 @@ namespace GNet // issues, and it reads incoming data. There is some support for flow-control // issues when writing data out to the server. // -class GNet::Client +class GNet::Client : public GNet:: Connection { public: explicit Client( bool priviledged = false , bool quit_on_disconnect = false ) ; @@ -87,6 +88,14 @@ public: virtual ~Client() ; // Destructor. + virtual std::pair localAddress() const ; + // Returns the local address. + // Pair.first is false on error. + + virtual std::pair peerAddress() const ; + // Returns the peer address. + // Pair.first is false on error. + protected: friend class ClientImp ; diff --git a/src/gnet/gconnection.cpp b/src/gnet/gconnection.cpp new file mode 100644 index 0000000..0e8d41c --- /dev/null +++ b/src/gnet/gconnection.cpp @@ -0,0 +1,31 @@ +// +// Copyright (C) 2001 Graeme Walker +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// === +// +// gconnection.cpp +// + +#include "gdef.h" +#include "gnet.h" +#include "gconnection.h" + +GNet::Connection::~Connection() +{ +} + diff --git a/src/gnet/gconnection.h b/src/gnet/gconnection.h new file mode 100644 index 0000000..83239f6 --- /dev/null +++ b/src/gnet/gconnection.h @@ -0,0 +1,59 @@ +// +// Copyright (C) 2001 Graeme Walker +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// === +// +// gconnection.h +// + +#ifndef G_NET_CONNECTION_H +#define G_NET_CONNECTION_H + +#include "gdef.h" +#include "gnet.h" +#include "gaddress.h" + +namespace GNet +{ + class Connection ; +} ; + +// Class: GNet::Connection +// Description: An interface which provides address information +// for a network connection. +// See also: GNet::Client, GNet::ServerPeer +// +class GNet::Connection +{ +public: + virtual std::pair localAddress() const = 0 ; + // Returns the connection's local address. + // Pair.first is false if none. + + virtual std::pair peerAddress() const = 0 ; + // Returns the connection's peer address. + // Pair.first is false if none. + + virtual ~Connection() ; + // Destructor. + +private: + void operator=( const Connection & ) ; // not implemented +} ; + +#endif diff --git a/src/gnet/gmonitor.cpp b/src/gnet/gmonitor.cpp new file mode 100644 index 0000000..7bf4e8d --- /dev/null +++ b/src/gnet/gmonitor.cpp @@ -0,0 +1,129 @@ +// +// Copyright (C) 2001 Graeme Walker +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// === +// +// gmonitor.cpp +// + +#include "gdef.h" +#include "gnet.h" +#include "gmonitor.h" +#include "gassert.h" +#include + +class GNet::MonitorImp +{ +public: + MonitorImp() ; + typedef const Client * C_p ; + typedef const ServerPeer * S_p ; + typedef std::set Clients ; + typedef std::set ServerPeers ; + Clients m_clients ; + ServerPeers m_server_peers ; + unsigned long m_client_adds ; + unsigned long m_client_removes ; + unsigned long m_server_peer_adds ; + unsigned long m_server_peer_removes ; +} ; + +GNet::MonitorImp::MonitorImp() : + m_client_adds(0UL) , + m_client_removes(0UL) , + m_server_peer_adds(0UL) , + m_server_peer_removes(0UL) +{ +} + +// === + +GNet::Monitor * GNet::Monitor::m_this = NULL ; + +GNet::Monitor::Monitor() : + m_imp( new MonitorImp ) +{ + G_ASSERT( m_this == NULL ) ; + m_this = this ; +} + +GNet::Monitor::~Monitor() +{ + delete m_imp ; + m_this = NULL ; +} + +GNet::Monitor * GNet::Monitor::instance() +{ + return m_this ; +} + +void GNet::Monitor::add( const Client & client ) +{ + m_imp->m_clients.insert( &client ) ; + m_imp->m_client_adds++ ; +} + +void GNet::Monitor::remove( const Client & client ) +{ + m_imp->m_client_removes++ ; + m_imp->m_clients.erase( &client ) ; +} + +void GNet::Monitor::add( const ServerPeer & peer ) +{ + m_imp->m_server_peer_adds++ ; + m_imp->m_server_peers.insert( & peer ) ; +} + +void GNet::Monitor::remove( const ServerPeer & peer ) +{ + m_imp->m_server_peer_removes++ ; + m_imp->m_server_peers.erase( & peer ) ; +} + +void GNet::Monitor::report( std::ostream & stream ) +{ + stream << "clients created: " << m_imp->m_client_adds << std::endl ; + stream << "client destroyed: " << m_imp->m_client_removes << std::endl ; + { + for( MonitorImp::Clients::const_iterator p = m_imp->m_clients.begin() ; + p != m_imp->m_clients.end() ; ++p ) + { + stream + << " client " << (const void *)(*p) << ": " + << (*p)->localAddress().second.displayString() << " -> " + << (*p)->peerAddress().second.displayString() << std::endl ; + } + } + + stream << "servers created: " << m_imp->m_server_peer_adds << std::endl ; + stream << "servers destroyed: " << m_imp->m_server_peer_removes << std::endl ; + + { + for( MonitorImp::ServerPeers::const_iterator p = m_imp->m_server_peers.begin() ; + p != m_imp->m_server_peers.end() ; ++p ) + { + stream + << " server " << (const void *)(*p) << ": " + << (*p)->localAddress().second.displayString() << " -> " + << (*p)->peerAddress().second.displayString() << std::endl ; + } + } +} + diff --git a/src/gnet/gmonitor.h b/src/gnet/gmonitor.h new file mode 100644 index 0000000..2a1688c --- /dev/null +++ b/src/gnet/gmonitor.h @@ -0,0 +1,79 @@ +// +// Copyright (C) 2001 Graeme Walker +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// === +// +// gmonitor.h +// + +#ifndef G_GNET_MONITOR_H +#define G_GNET_MONITOR_H + +#include "gdef.h" +#include "gnet.h" +#include "gclient.h" +#include "gserver.h" +#include + +namespace GNet +{ + class Monitor ; + class MonitorImp ; +} ; + +// Class: GNet::Monitor +// Description: A singleton for monitoring Client and ServerPeer connections. +// See also: GNet::Client, GNet::ServerPeer +// +class GNet::Monitor +{ +public: + Monitor() ; + // Default constructor. + + virtual ~Monitor() ; + // Destructor. + + static Monitor * instance() ; + // Returns the singleton pointer. Returns null if none. + + void add( const Client & client ) ; + // Adds a client. + + void remove( const Client & client ) ; + // Removes a client. + + void add( const ServerPeer & peer ) ; + // Adds a server peer. + + void remove( const ServerPeer & peer ) ; + // Removes a server peer. + + void report( std::ostream & stream ) ; + // Reports itself onto a stream. + +private: + Monitor( const Monitor & ) ; // not implemented + void operator=( const Monitor & ) ; // not implemented + +private: + static Monitor * m_this ; + MonitorImp * m_imp ; +} ; + +#endif diff --git a/src/gnet/gresolve.h b/src/gnet/gresolve.h index 06681ca..a54d3c6 100644 --- a/src/gnet/gresolve.h +++ b/src/gnet/gresolve.h @@ -110,8 +110,8 @@ public: // on success. Not implemented on all platforms. private: - void operator=( const Resolver & ) ; - Resolver( const Resolver & ) ; + void operator=( const Resolver & ) ; // not implemented + Resolver( const Resolver & ) ; // not implemented static bool resolveHost( const std::string & host_name , HostInfo & ) ; static unsigned int resolveService( const std::string & host_name , bool , std::string & ) ; diff --git a/src/gnet/gserver.cpp b/src/gnet/gserver.cpp index 4a50c20..c638557 100644 --- a/src/gnet/gserver.cpp +++ b/src/gnet/gserver.cpp @@ -24,6 +24,7 @@ #include "gdef.h" #include "gnet.h" #include "gserver.h" +#include "gmonitor.h" #include "gdebug.h" #include "gassert.h" @@ -34,12 +35,14 @@ GNet::ServerPeer::ServerPeer( StreamSocket * s , Address a ) : { G_ASSERT( m_socket != NULL ) ; G_DEBUG( "GNet::ServerPeer::ctor: fd " << m_socket->asString() << ": " << m_address.displayString() ) ; + if( Monitor::instance() ) Monitor::instance()->add(*this) ; m_socket->addReadHandler( *this ) ; } GNet::ServerPeer::~ServerPeer() { G_DEBUG( "GNet::ServerPeer::dtor: fd " << m_socket->asString() ) ; + if( Monitor::instance() ) Monitor::instance()->remove(*this) ; m_socket->dropReadHandler() ; delete m_socket ; m_socket = NULL ; @@ -93,11 +96,32 @@ bool GNet::ServerPeer::down() return m_ref_count == 0U ; } +std::pair GNet::ServerPeer::localAddress() const +{ + G_ASSERT( m_socket != NULL ) ; + return m_socket->getLocalAddress() ; +} + +std::pair GNet::ServerPeer::peerAddress() const +{ + G_ASSERT( m_socket != NULL ) ; + return m_socket->getPeerAddress() ; +} + // === -GNet::Server::Server( unsigned int listening_port ) +GNet::Server::Server( unsigned int listening_port ) : + m_socket(NULL) { - init( listening_port ) ; + try + { + init( listening_port ) ; + } + catch(...) + { + delete m_socket ; + throw ; + } } GNet::Server::Server() : diff --git a/src/gnet/gserver.h b/src/gnet/gserver.h index b253d60..25290e5 100644 --- a/src/gnet/gserver.h +++ b/src/gnet/gserver.h @@ -27,6 +27,7 @@ #include "gdef.h" #include "gnet.h" #include "gsocket.h" +#include "gconnection.h" #include "gselect.h" #include "gevent.h" #include @@ -82,8 +83,8 @@ protected: // May return NULL. private: - Server( const Server& ) ; - void operator=( const Server& ) ; + Server( const Server & ) ; // not implemented + void operator=( const Server & ) ; // not implemented virtual void readEvent() ; // see EventHandler virtual void writeEvent() ; // see EventHandler virtual void exceptionEvent() ; // see EventHandler @@ -99,7 +100,7 @@ private: // delete themselves when the connection is lost. // See also: GNet::Server, GNet::EventHandler // -class GNet::ServerPeer : public GNet:: EventHandler +class GNet::ServerPeer : public GNet:: EventHandler , public GNet:: Connection { public: ServerPeer( StreamSocket * , Address ) ; @@ -129,6 +130,14 @@ public: // log message to destinguish one connection // from another. + virtual std::pair localAddress() const ; + // Returns the local address. + // Pair.first is false on error. + + virtual std::pair peerAddress() const ; + // Returns the peer address. + // Pair.first is false on error. + protected: virtual ~ServerPeer() ; // Destructor. Note that objects will delete @@ -148,8 +157,8 @@ protected: private: void readEvent() ; - ServerPeer( const ServerPeer & ) ; - void operator=( const ServerPeer & ) ; + ServerPeer( const ServerPeer & ) ; // not implemented + void operator=( const ServerPeer & ) ; // not implemented private: unsigned int m_ref_count ; diff --git a/src/main/Makefile.am b/src/main/Makefile.am index 01ac0d6..fbe756e 100644 --- a/src/main/Makefile.am +++ b/src/main/Makefile.am @@ -24,7 +24,7 @@ AM_INSTALL_PROGRAM_FLAGS=-s # change the local-state directory from .../var to .../var/spool/emailrelay localstatedir = ${prefix}/var/spool/emailrelay -EXTRA_DIST=gmessagestore_win32.cpp emailrelay.dsp icon-32.ico empty_file doxygen.cfg emailrelay.rc +EXTRA_DIST=commandline_win32.cpp main_win32.cpp gmessagestore_win32.cpp emailrelay.dsp icon-32.ico empty_file doxygen.cfg emailrelay.rc resource.h INCLUDES = -I$(top_srcdir)/lib/gcc2.95 -I$(top_srcdir)/src/glib -I$(top_srcdir)/src/gnet sbin_PROGRAMS = emailrelay libexec_PROGRAMS = emailrelay-poke @@ -62,7 +62,14 @@ emailrelay_SOURCES = \ gstoredmessage.h \ gverifier.cpp \ gverifier.h \ - mailrelay.cpp + main_unix.cpp \ + configuration.cpp \ + configuration.h \ + run.cpp \ + run.h \ + commandline.cpp \ + commandline_unix.cpp \ + commandline.h emailrelay_poke_SOURCES=poke.c emailrelay_LDADD = $(top_builddir)/src/glib/libglib.a $(top_builddir)/src/gnet/libgnet.a diff --git a/src/main/Makefile.in b/src/main/Makefile.in index 986968d..c939279 100644 --- a/src/main/Makefile.in +++ b/src/main/Makefile.in @@ -95,12 +95,12 @@ AM_INSTALL_PROGRAM_FLAGS = -s # change the local-state directory from .../var to .../var/spool/emailrelay localstatedir = ${prefix}/var/spool/emailrelay -EXTRA_DIST = gmessagestore_win32.cpp emailrelay.dsp icon-32.ico empty_file doxygen.cfg emailrelay.rc +EXTRA_DIST = commandline_win32.cpp main_win32.cpp gmessagestore_win32.cpp emailrelay.dsp icon-32.ico empty_file doxygen.cfg emailrelay.rc resource.h INCLUDES = -I$(top_srcdir)/lib/gcc2.95 -I$(top_srcdir)/src/glib -I$(top_srcdir)/src/gnet sbin_PROGRAMS = emailrelay libexec_PROGRAMS = emailrelay-poke localstate_DATA = empty_file -emailrelay_SOURCES = gadminserver.cpp gadminserver.h gclientprotocol.cpp gclientprotocol.h gfilestore.cpp gfilestore.h gmessagestore.cpp gmessagestore.h gmessagestore_unix.cpp gnewfile.cpp gnewfile.h gnewmessage.cpp gnewmessage.h gprotocolmessage.cpp gprotocolmessage.h gprotocolmessageforward.cpp gprotocolmessageforward.h gprotocolmessagestore.cpp gprotocolmessagestore.h gserverprotocol.cpp gserverprotocol.h gsmtp.h gsmtpclient.cpp gsmtpclient.h gsmtpserver.cpp gsmtpserver.h gstoredfile.cpp gstoredfile.h gstoredmessage.cpp gstoredmessage.h gverifier.cpp gverifier.h mailrelay.cpp +emailrelay_SOURCES = gadminserver.cpp gadminserver.h gclientprotocol.cpp gclientprotocol.h gfilestore.cpp gfilestore.h gmessagestore.cpp gmessagestore.h gmessagestore_unix.cpp gnewfile.cpp gnewfile.h gnewmessage.cpp gnewmessage.h gprotocolmessage.cpp gprotocolmessage.h gprotocolmessageforward.cpp gprotocolmessageforward.h gprotocolmessagestore.cpp gprotocolmessagestore.h gserverprotocol.cpp gserverprotocol.h gsmtp.h gsmtpclient.cpp gsmtpclient.h gsmtpserver.cpp gsmtpserver.h gstoredfile.cpp gstoredfile.h gstoredmessage.cpp gstoredmessage.h gverifier.cpp gverifier.h main_unix.cpp configuration.cpp configuration.h run.cpp run.h commandline.cpp commandline_unix.cpp commandline.h emailrelay_poke_SOURCES = poke.c emailrelay_LDADD = $(top_builddir)/src/glib/libglib.a $(top_builddir)/src/gnet/libgnet.a @@ -122,7 +122,8 @@ emailrelay_OBJECTS = gadminserver.o gclientprotocol.o gfilestore.o \ gmessagestore.o gmessagestore_unix.o gnewfile.o gnewmessage.o \ gprotocolmessage.o gprotocolmessageforward.o gprotocolmessagestore.o \ gserverprotocol.o gsmtpclient.o gsmtpserver.o gstoredfile.o \ -gstoredmessage.o gverifier.o mailrelay.o +gstoredmessage.o gverifier.o main_unix.o configuration.o run.o \ +commandline.o commandline_unix.o emailrelay_DEPENDENCIES = $(top_builddir)/src/glib/libglib.a \ $(top_builddir)/src/gnet/libgnet.a emailrelay_LDFLAGS = @@ -299,6 +300,32 @@ distdir: $(DISTFILES) || cp -p $$d/$$file $(distdir)/$$file || :; \ fi; \ done +commandline.o: commandline.cpp ../../src/glib/gdef.h ../../config.h \ + ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ + ../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gsmtp.h \ + ../../src/gnet/gnet.h ../../src/glib/glog.h configuration.h \ + ../../src/glib/gpath.h ../../src/glib/gstrings.h commandline.h \ + ../../src/glib/garg.h ../../src/glib/ggetopt.h \ + ../../src/glib/gexception.h gmessagestore.h gnewmessage.h \ + gstoredmessage.h ../../src/glib/gstr.h ../../src/glib/gdebug.h \ + ../../src/glib/glogoutput.h ../../src/glib/gassert.h +commandline_unix.o: commandline_unix.cpp ../../src/glib/gdef.h \ + ../../config.h ../../lib/gcc2.95/iostream \ + ../../lib/gcc2.95/sstream ../../lib/gcc2.95/xlocale \ + ../../lib/gcc2.95/limits gsmtp.h ../../src/gnet/gnet.h \ + ../../src/glib/glog.h commandline.h ../../src/glib/garg.h \ + configuration.h ../../src/glib/gpath.h \ + ../../src/glib/gstrings.h ../../src/glib/ggetopt.h \ + ../../src/glib/gexception.h ../../src/glib/gstr.h +configuration.o: configuration.cpp ../../src/glib/gdef.h ../../config.h \ + ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ + ../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gsmtp.h \ + ../../src/gnet/gnet.h ../../src/glib/glog.h configuration.h \ + ../../src/glib/gpath.h ../../src/glib/gstrings.h commandline.h \ + ../../src/glib/garg.h ../../src/glib/ggetopt.h \ + ../../src/glib/gexception.h gmessagestore.h gnewmessage.h \ + gstoredmessage.h ../../src/glib/gstr.h ../../src/glib/gdebug.h \ + ../../src/glib/glogoutput.h ../../src/glib/gassert.h gadminserver.o: gadminserver.cpp ../../src/glib/gdef.h ../../config.h \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits \ @@ -306,12 +333,14 @@ gadminserver.o: gadminserver.cpp ../../src/glib/gdef.h ../../config.h \ gadminserver.h ../../src/gnet/gserver.h \ ../../src/gnet/gsocket.h ../../src/gnet/gaddress.h \ ../../src/glib/gexception.h ../../src/gnet/gevent.h \ - ../../src/gnet/gdescriptor.h ../../src/gnet/gselect.h \ - ../../src/gnet/glinebuffer.h ../../src/glib/gstrings.h \ - gserverprotocol.h gprotocolmessage.h gverifier.h gsmtpclient.h \ - ../../src/gnet/gclient.h gclientprotocol.h gmessagestore.h \ - gnewmessage.h gstoredmessage.h ../../src/glib/gpath.h \ - ../../src/glib/gstr.h ../../src/glib/gmemory.h + ../../src/gnet/gdescriptor.h ../../src/gnet/gconnection.h \ + ../../src/gnet/gselect.h ../../src/gnet/glinebuffer.h \ + ../../src/glib/gstrings.h gserverprotocol.h gprotocolmessage.h \ + gverifier.h gsmtpclient.h ../../src/gnet/gclient.h \ + gclientprotocol.h gmessagestore.h gnewmessage.h \ + gstoredmessage.h ../../src/glib/gpath.h \ + ../../src/gnet/gmonitor.h ../../src/glib/gstr.h \ + ../../src/glib/gmemory.h gclientprotocol.o: gclientprotocol.cpp ../../src/glib/gdef.h \ ../../config.h ../../lib/gcc2.95/iostream \ ../../lib/gcc2.95/sstream ../../lib/gcc2.95/xlocale \ @@ -378,11 +407,12 @@ gprotocolmessageforward.o: gprotocolmessageforward.cpp \ gprotocolmessagestore.h gnewmessage.h gsmtpclient.h \ ../../src/gnet/glinebuffer.h ../../src/gnet/gclient.h \ ../../src/gnet/gaddress.h ../../src/glib/gexception.h \ - ../../src/gnet/gsocket.h ../../src/gnet/gevent.h \ - ../../src/gnet/gdescriptor.h gclientprotocol.h gmessagestore.h \ - gstoredmessage.h ../../src/glib/gpath.h \ - ../../src/glib/gmemory.h ../../src/glib/gstr.h \ - ../../src/glib/gassert.h ../../src/glib/glogoutput.h + ../../src/gnet/gconnection.h ../../src/gnet/gsocket.h \ + ../../src/gnet/gevent.h ../../src/gnet/gdescriptor.h \ + gclientprotocol.h gmessagestore.h gstoredmessage.h \ + ../../src/glib/gpath.h ../../src/glib/gmemory.h \ + ../../src/glib/gstr.h ../../src/glib/gassert.h \ + ../../src/glib/glogoutput.h gprotocolmessagestore.o: gprotocolmessagestore.cpp ../../src/glib/gdef.h \ ../../config.h ../../lib/gcc2.95/iostream \ ../../lib/gcc2.95/sstream ../../lib/gcc2.95/xlocale \ @@ -412,9 +442,10 @@ gsmtpclient.o: gsmtpclient.cpp ../../src/glib/gdef.h ../../config.h \ ../../src/glib/gpath.h ../../src/glib/gstrings.h \ ../../src/glib/gstr.h ../../src/glib/gmemory.h gsmtpclient.h \ ../../src/gnet/glinebuffer.h ../../src/gnet/gclient.h \ - ../../src/gnet/gsocket.h ../../src/gnet/gevent.h \ - ../../src/gnet/gdescriptor.h gclientprotocol.h gmessagestore.h \ - gnewmessage.h gstoredmessage.h ../../src/gnet/gresolve.h \ + ../../src/gnet/gconnection.h ../../src/gnet/gsocket.h \ + ../../src/gnet/gevent.h ../../src/gnet/gdescriptor.h \ + gclientprotocol.h gmessagestore.h gnewmessage.h \ + gstoredmessage.h ../../src/gnet/gresolve.h \ ../../src/glib/gassert.h ../../src/glib/glogoutput.h gsmtpserver.o: gsmtpserver.cpp ../../src/glib/gdef.h ../../config.h \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ @@ -423,12 +454,12 @@ gsmtpserver.o: gsmtpserver.cpp ../../src/glib/gdef.h ../../config.h \ ../../src/gnet/gserver.h ../../src/gnet/gsocket.h \ ../../src/gnet/gaddress.h ../../src/glib/gexception.h \ ../../src/gnet/gevent.h ../../src/gnet/gdescriptor.h \ - ../../src/gnet/gselect.h ../../src/gnet/glinebuffer.h \ - ../../src/glib/gstrings.h gverifier.h gserverprotocol.h \ - gprotocolmessage.h gprotocolmessagestore.h gnewmessage.h \ - gprotocolmessageforward.h gsmtpclient.h \ - ../../src/gnet/gclient.h gclientprotocol.h gmessagestore.h \ - gstoredmessage.h ../../src/glib/gpath.h \ + ../../src/gnet/gconnection.h ../../src/gnet/gselect.h \ + ../../src/gnet/glinebuffer.h ../../src/glib/gstrings.h \ + gverifier.h gserverprotocol.h gprotocolmessage.h \ + gprotocolmessagestore.h gnewmessage.h gprotocolmessageforward.h \ + gsmtpclient.h ../../src/gnet/gclient.h gclientprotocol.h \ + gmessagestore.h gstoredmessage.h ../../src/glib/gpath.h \ ../../src/glib/gmemory.h ../../src/gnet/glocal.h \ ../../src/glib/gdebug.h ../../src/glib/glogoutput.h \ ../../src/glib/gassert.h @@ -455,24 +486,35 @@ gverifier.o: gverifier.cpp ../../src/glib/gdef.h ../../config.h \ ../../src/glib/gstr.h ../../src/glib/gexception.h \ ../../src/glib/gstrings.h ../../src/glib/gassert.h \ ../../src/glib/glogoutput.h -mailrelay.o: mailrelay.cpp ../../src/glib/gdef.h ../../config.h \ +main_unix.o: main_unix.cpp ../../src/glib/gdef.h ../../config.h \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gsmtp.h \ - ../../src/gnet/gnet.h ../../src/glib/glog.h gsmtpserver.h \ - ../../src/gnet/gserver.h ../../src/gnet/gsocket.h \ - ../../src/gnet/gaddress.h ../../src/glib/gexception.h \ + ../../src/gnet/gnet.h ../../src/glib/glog.h \ + ../../src/glib/garg.h run.h configuration.h \ + ../../src/glib/gpath.h ../../src/glib/gstrings.h commandline.h \ + ../../src/glib/ggetopt.h ../../src/glib/gexception.h \ ../../src/gnet/gevent.h ../../src/gnet/gdescriptor.h \ - ../../src/gnet/gselect.h ../../src/gnet/glinebuffer.h \ - ../../src/glib/gstrings.h gverifier.h gserverprotocol.h \ - gprotocolmessage.h gsmtpclient.h ../../src/gnet/gclient.h \ - gclientprotocol.h gmessagestore.h gnewmessage.h \ - gstoredmessage.h ../../src/glib/gpath.h ../../src/glib/garg.h \ - ../../src/glib/gdaemon.h ../../src/glib/gstr.h gfilestore.h \ - gnewfile.h gadminserver.h ../../src/glib/gprocess.h \ - ../../src/glib/gmemory.h ../../src/glib/ggetopt.h \ - ../../src/glib/gdebug.h ../../src/glib/glogoutput.h \ - ../../src/glib/gassert.h + ../../src/glib/gdaemon.h gmessagestore.h gnewmessage.h \ + gstoredmessage.h poke.o: poke.c +run.o: run.cpp ../../src/glib/gdef.h ../../config.h \ + ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ + ../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gsmtp.h \ + ../../src/gnet/gnet.h ../../src/glib/glog.h run.h \ + configuration.h ../../src/glib/gpath.h \ + ../../src/glib/gstrings.h commandline.h ../../src/glib/garg.h \ + ../../src/glib/ggetopt.h ../../src/glib/gexception.h \ + ../../src/gnet/gevent.h ../../src/gnet/gdescriptor.h \ + ../../src/glib/gdaemon.h gmessagestore.h gnewmessage.h \ + gstoredmessage.h gsmtpserver.h ../../src/gnet/gserver.h \ + ../../src/gnet/gsocket.h ../../src/gnet/gaddress.h \ + ../../src/gnet/gconnection.h ../../src/gnet/gselect.h \ + ../../src/gnet/glinebuffer.h gverifier.h gserverprotocol.h \ + gprotocolmessage.h gsmtpclient.h ../../src/gnet/gclient.h \ + gclientprotocol.h gfilestore.h gnewfile.h gadminserver.h \ + ../../src/gnet/gmonitor.h ../../src/glib/gprocess.h \ + ../../src/glib/gmemory.h ../../src/glib/gdebug.h \ + ../../src/glib/glogoutput.h ../../src/glib/gassert.h info-am: info: info-am diff --git a/src/main/commandline.cpp b/src/main/commandline.cpp new file mode 100644 index 0000000..b805433 --- /dev/null +++ b/src/main/commandline.cpp @@ -0,0 +1,230 @@ +// +// Copyright (C) 2001 Graeme Walker +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// === +// +// commandline.cpp +// + +#include "gdef.h" +#include "gsmtp.h" +#include "configuration.h" +#include "commandline.h" +#include "gmessagestore.h" +#include "gstr.h" +#include "gdebug.h" + +//static +std::string Main::CommandLine::switchSpec() +{ + std::string dir = GSmtp::MessageStore::defaultDirectory().str() ; + std::stringstream ss ; + ss + << "a!admin!enables the administration interface and specifies its listening port number!1!admin-port|" + << "q!as-client!equivalent to \"--no-syslog --no-daemon --log --dont-serve --forward --forward-to\"!" << "1!host:port|" + << "y!as-proxy!equivalent to \"--close-stderr --log --immediate --forward-to\"!1!host:port|" + << "d!as-server!equivalent to \"--close-stderr --log\"!0!|" + << "e!close-stderr!closes the standard error stream when daemonising!0!|" + << "x!dont-serve!stops the process acting as a server (usually used with --forward)!0!|" + << "z!filter!defines a mail pre-processor (disallowed if running as root)!1!program|" + << "f!forward!forwards stored mail on startup (requires --forward-to)!0!|" + << "o!forward-to!specifies the remote smtp server (required by --forward and --admin)!1!host:port|" + << "h!help!displays help text and exits!0!|" + << "m!immediate!forwards each message as soon as it is received (requires --forward-to)!0!|" + << "l!log!writes log information on standard error (if open) and syslog (if not disabled)!0!|" + << "t!no-daemon!does not detach from the terminal!0!|" + << "n!no-syslog!disables syslog output!0!|" + << "i!pid-file!records the daemon process-id in the given file!1!pid-file|" + << "p!port!specifies the smtp listening port number!1!port|" + << "r!remote-clients!allows remote clients to connect!0!|" + << "s!spool-dir!specifies the spool directory " << "(default is \"" << dir << "\")!1!dir|" + << "v!verbose!generates more verbose logging " << "(if compiled-in and logging enabled and stderr open)!0!|" + << "V!version!displays version information and exits!0!" + ; + return ss.str() ; +} + +Main::CommandLine::CommandLine( const G::Arg & arg , const std::string & version ) : + m_version(version) , + m_arg(arg) , + m_getopt( m_arg , switchSpec() , '|' , '!' , '^' ) +{ +} + +unsigned int Main::CommandLine::argc() const +{ + return m_getopt.args().c() ; +} + +Main::Configuration Main::CommandLine::cfg() const +{ + return Configuration( *this ) ; +} + +bool Main::CommandLine::hasUsageErrors() const +{ + return m_getopt.hasErrors() ; +} + +void Main::CommandLine::showUsage( bool e ) const +{ + Show show( e ) ; + unsigned int columns = ttyColumns() ; + m_getopt.showUsage( show.s() , m_arg.prefix() , "" , 30U , columns ) ; +} + +bool Main::CommandLine::contains( const std::string & name ) const +{ + return m_getopt.contains( name ) ; +} + +std::string Main::CommandLine::value( const std::string & name ) const +{ + return m_getopt.value( name ) ; +} + +std::string Main::CommandLine::semanticError() const +{ + if( cfg().doAdmin() && cfg().adminPort() == cfg().port() ) + { + return "the smtp listening port and the " + "admin listening port must be different" ; + } + + if( cfg().daemon() && cfg().spoolDir().isRelative() ) + { + return "in daemon mode the spool-dir must " + "be an absolute path (starting with /)" ; + } + + if( !m_getopt.contains("forward-to") && ( + m_getopt.contains("forward") || + m_getopt.contains("immediate") || + m_getopt.contains("admin") ) ) + { + return "usage error: the --forward, --immediate and --admin " + "switches require --forward-to" ; + } + + return std::string() ; +} + +bool Main::CommandLine::hasSemanticError() const +{ + return ! semanticError().empty() ; +} + +void Main::CommandLine::showSemanticError( bool e ) const +{ + Show show( e ) ; + show.s() << m_arg.prefix() << ": " << semanticError() << std::endl ; +} + +void Main::CommandLine::showUsageErrors( bool e ) const +{ + Show show( e ) ; + m_getopt.showErrors( show.s() , m_arg.prefix() ) ; + showShortHelp( e ) ; +} + +void Main::CommandLine::showArgcError( bool e ) const +{ + Show show( e ) ; + show.s() << m_arg.prefix() << ": usage error: too many non-switch arguments" << std::endl ; + showShortHelp( e ) ; +} + +void Main::CommandLine::showShortHelp( bool e ) const +{ + Show show( e ) ; + const std::string & exe = m_arg.prefix() ; + show.s() + << std::string(exe.length()+2U,' ') + << "try \"" << exe << " --help\" for more information" << std::endl ; +} + +void Main::CommandLine::showHelp( bool e ) const +{ + Show show( e ) ; + showBanner( e ) ; + show.s() << std::endl ; + showUsage( e ) ; + showExtraHelp( e ) ; + showCopyright( e ) ; +} + +void Main::CommandLine::showExtraHelp( bool e ) const +{ + Show show( e ) ; + const std::string & exe = m_arg.prefix() ; + + show.s() << std::endl ; + + show.s() + << "To start a 'storage' daemon in background..." << std::endl + << " " << exe << " --as-server" << std::endl + << std::endl ; + + show.s() + << "To forward stored mail to \"mail.myisp.co.uk\"..." << std::endl + << " " << exe << " --as-client mail.myisp.co.uk:smtp" << std::endl + << std::endl ; + + show.s() + << "To run as a proxy (on port 10025) to a local server (on port 25)..." << std::endl + << " " << exe << " --port 10025 --as-proxy localhost:25" << std::endl + << std::endl ; +} + +void Main::CommandLine::showNoop( bool e ) const +{ + Show show( e ) ; + show.s() << m_arg.prefix() << ": no messages to send" << std::endl ; +} + +void Main::CommandLine::showBanner( bool e ) const +{ + Show show( e ) ; + show.s() + << "E-MailRelay V" << m_version << std::endl ; +} + +void Main::CommandLine::showCopyright( bool e ) const +{ + Show show( e ) ; + show.s() << "Copyright (C) 2001 Graeme Walker" << std::endl ; +} + +void Main::CommandLine::showWarranty( bool e ) const +{ + Show show( e ) ; + show.s() + << "This software is provided without warranty of any kind." << std::endl + << "You may redistribure copies of this program under " << std::endl + << "the terms of the GNU General Public License." << std::endl + << "For more information refer to the file named COPYING." << std::endl ; +} + +void Main::CommandLine::showVersion( bool e ) const +{ + Show show( e ) ; + showBanner( e ) ; + showWarranty( e ) ; + showCopyright( e ) ; +} + diff --git a/src/main/commandline.h b/src/main/commandline.h new file mode 100644 index 0000000..e6120df --- /dev/null +++ b/src/main/commandline.h @@ -0,0 +1,120 @@ +// +// Copyright (C) 2001 Graeme Walker +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// === +// +// commandline.cpp +// + +#ifndef G_MAIN_COMMAND_LINE_H +#define G_MAIN_COMMAND_LINE_H + +#include "gdef.h" +#include "gsmtp.h" +#include "garg.h" +#include "configuration.h" +#include "ggetopt.h" +#include +#include + +namespace Main +{ + class CommandLine ; +} ; + +// Class: Main::CommandLine +// Description: A class which deals with the command-line interface +// to the process (both input and output). +// +class Main::CommandLine +{ +public: + CommandLine( const G::Arg & arg , const std::string & version ) ; + // Constructor. + + Configuration cfg() const ; + // Returns a Configuration object. + + bool contains( const std::string & switch_ ) const ; + // Returns true if the command line contained the give switch. + + std::string value( const std::string & switch_ ) const ; + // Returns the given switch's value. + + unsigned int argc() const ; + // Returns the number of non-switch arguments on the command line. + + bool hasUsageErrors() const ; + // Returns true if the command line has usage errors (eg. invalid switch). + + bool hasSemanticError() const ; + // Returns true if the command line has logical errors (eg. conflicting switches). + + void showUsage( bool error_stream = false ) const ; + // Writes usage info. + + void showHelp( bool error_stream = false ) const ; + // Writes help text. + + void showUsageErrors( bool error_stream = true ) const ; + // Writes the usage errors. + + void showSemanticError( bool error_stream = true ) const ; + // Writes the logic errors. + + void showArgcError( bool error_stream = true ) const ; + // Writes a too-many-arguments error message. + + void showNoop( bool error_stream = false ) const ; + // Writes a nothing-to-do message. + + void showVersion( bool error_stream = false ) const ; + // Writes the version number. + + void showBanner( bool error_stream = false ) const ; + // Writes a startup banner. + + void showCopyright( bool error_stream = false ) const ; + // Writes a copyright message. + +private: + void showWarranty( bool error_stream ) const ; + void showShortHelp( bool error_stream ) const ; + std::string semanticError() const ; + static std::string switchSpec() ; + unsigned int ttyColumns() const ; // o/s-specific + void showExtraHelp( bool error_stream ) const ; + +private: + std::string m_version ; + G::Arg m_arg ; + G::GetOpt m_getopt ; + +private: + class Show + { + public: explicit Show( bool e ) ; + public: std::ostream & s() ; + public: ~Show() ; + private: static Show * m_this ; + private: std::stringstream m_ss ; + private: bool m_e ; + } ; +} ; + +#endif diff --git a/src/main/commandline_unix.cpp b/src/main/commandline_unix.cpp new file mode 100755 index 0000000..3f906f1 --- /dev/null +++ b/src/main/commandline_unix.cpp @@ -0,0 +1,43 @@ +// +// commandline_unix.cpp +// + +#include "gdef.h" +#include "gsmtp.h" +#include "commandline.h" +#include "gstr.h" +#include + +Main::CommandLine::Show * Main::CommandLine::Show::m_this = NULL ; + +Main::CommandLine::Show::Show( bool e ) : + m_e(e) +{ +} + +std::ostream & Main::CommandLine::Show::s() +{ + return m_e ? std::cerr : std::cout ; +} + +Main::CommandLine::Show::~Show() +{ +} + +unsigned int Main::CommandLine::ttyColumns() const +{ + const unsigned int default_ = 79U ; + try + { + const char * p = std::getenv( "COLUMNS" ) ; + if( p == NULL ) + return default_ ; + else + return G::Str::toUInt(p) ; + } + catch( std::exception & ) + { + return default_ ; + } +} + diff --git a/src/main/commandline_win32.cpp b/src/main/commandline_win32.cpp new file mode 100644 index 0000000..2aa9b07 --- /dev/null +++ b/src/main/commandline_win32.cpp @@ -0,0 +1,56 @@ +// +// Copyright (C) 2001 Graeme Walker +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// === +// +// commandline_win32.cpp +// + +#include "gdef.h" +#include "gsmtp.h" +#include "commandline.h" + +Main::CommandLine::Show * Main::CommandLine::Show::m_this = NULL ; + +Main::CommandLine::Show::Show( bool ) +{ + if( m_this == NULL ) + { + m_this = this ; + } +} + +std::ostream & Main::CommandLine::Show::s() +{ + return m_this->m_ss ; +} + +Main::CommandLine::Show::~Show() +{ + if( m_this == this ) + { + m_this = NULL ; + ::MessageBox( NULL , m_ss.str().c_str() , "E-MailRelay" , MB_OK ) ; + } +} + +unsigned int Main::CommandLine::ttyColumns() const +{ + return 120U ; +} + diff --git a/src/main/configuration.cpp b/src/main/configuration.cpp new file mode 100644 index 0000000..a27ca10 --- /dev/null +++ b/src/main/configuration.cpp @@ -0,0 +1,144 @@ +// +// Copyright (C) 2001 Graeme Walker +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// === +// +// configuration.cpp +// + +#include "gdef.h" +#include "gsmtp.h" +#include "configuration.h" +#include "commandline.h" +#include "gmessagestore.h" +#include "gstr.h" +#include "gdebug.h" + +Main::Configuration::Configuration( const CommandLine & cl ) : + m_cl(cl) +{ +} + +bool Main::Configuration::log() const +{ + return + m_cl.contains("log") || + m_cl.contains("as-client") || + m_cl.contains("as-proxy") || + m_cl.contains("as-server") ; +} + +bool Main::Configuration::verbose() const +{ + return m_cl.contains("verbose") ; +} + +bool Main::Configuration::syslog() const +{ + return !m_cl.contains("no-syslog") && !m_cl.contains("as-client") ; +} + +unsigned int Main::Configuration::port() const +{ + return m_cl.contains("port") ? + G::Str::toUInt(m_cl.value("port")) : 25U ; +} + +unsigned int Main::Configuration::adminPort() const +{ + return m_cl.contains("admin") ? + G::Str::toUInt(m_cl.value("admin")) : 10025U ; +} + +bool Main::Configuration::closeStderr() const +{ + return + m_cl.contains("close-stderr") || + m_cl.contains("as-proxy") || + m_cl.contains("as-server") ; +} + +bool Main::Configuration::immediate() const +{ + return + m_cl.contains("immediate") || + m_cl.contains("as-proxy") ; +} + +bool Main::Configuration::daemon() const +{ + return !m_cl.contains("no-daemon") && !m_cl.contains("as-client") ; +} + +G::Path Main::Configuration::spoolDir() const +{ + return m_cl.contains("spool-dir") ? + G::Path(m_cl.value("spool-dir")) : + GSmtp::MessageStore::defaultDirectory() ; +} + +std::string Main::Configuration::serverAddress() const +{ + const char * key = "forward-to" ; + if( m_cl.contains("as-client") ) + key = "as-client" ; + else if( m_cl.contains("as-proxy") ) + key = "as-proxy" ; + return m_cl.contains(key) ? m_cl.value(key) : std::string() ; +} + +bool Main::Configuration::doForwarding() const +{ + return m_cl.contains("forward") || m_cl.contains("as-client") ; +} + +bool Main::Configuration::doServing() const +{ + return !m_cl.contains("dont-serve") && !m_cl.contains("as-client") ; +} + +bool Main::Configuration::allowRemoteClients() const +{ + return m_cl.contains("remote-clients") ; +} + +bool Main::Configuration::doAdmin() const +{ + return m_cl.contains("admin") ; +} + +bool Main::Configuration::usePidFile() const +{ + return m_cl.contains("pid-file") ; +} + +std::string Main::Configuration::pidFile() const +{ + return m_cl.value("pid-file") ; +} + +bool Main::Configuration::useFilter() const +{ + return m_cl.contains("filter") ; +} + +std::string Main::Configuration::filter() const +{ + return m_cl.value("filter") ; +} + diff --git a/src/main/configuration.h b/src/main/configuration.h new file mode 100644 index 0000000..34ee6de --- /dev/null +++ b/src/main/configuration.h @@ -0,0 +1,110 @@ +// +// Copyright (C) 2001 Graeme Walker +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// === +// +// configuration.h +// + +#ifndef G_MAIN_CONFIGURATION_H +#define G_MAIN_CONFIGURATION_H + +#include "gdef.h" +#include "gsmtp.h" +#include "gpath.h" +#include + +namespace Main +{ + class Configuration ; + class CommandLine ; +} ; + +// Class: Main::Configuration +// Description: An interface for returning application configuration +// information. This implementation is minimaly dependent on the +// command line in order to simplify moving to the windows registry +// (for example) in the future. +// See also: CommandLine +// +class Main::Configuration +{ +public: + explicit Configuration( const CommandLine & cl ) ; + // Constructor. The reference is kept. + + unsigned int port() const ; + // Returns the main port number. + + unsigned int adminPort() const ; + // Returns the admin port number. + + bool closeStderr() const ; + // Returns true if stderr should be closed. + + bool immediate() const ; + // Returns true if proxying. + + bool log() const ; + // Returns true if doing logging. + + bool verbose() const ; + // Returns true if doing debug-level logging. + + bool syslog() const ; + // Returns true if generating syslog events. + + bool daemon() const ; + // Returns true if running as a daemon. + + bool doForwarding() const ; + // Returns true if running as a client. + + bool doServing() const ; + // Returns true if running as a server. + + bool doAdmin() const ; + // Returns true if enabling the admin interface. + + bool allowRemoteClients() const ; + // Returns true if allowing remote clients to connect. + + G::Path spoolDir() const ; + // Returns the spool directory. + + std::string serverAddress() const ; + // Returns the downstream server's address string. + + bool usePidFile() const ; + // Returns true if writing a pid file. + + std::string pidFile() const ; + // Returns the pid file's path. + + bool useFilter() const ; + // Returns true if pre-processing. + + std::string filter() const ; + // Returns the pre-processor's path. + +private: + const CommandLine & m_cl ; +} ; + +#endif + diff --git a/src/main/doxygen.cfg b/src/main/doxygen.cfg index a2b9fb0..5bf69f2 100644 --- a/src/main/doxygen.cfg +++ b/src/main/doxygen.cfg @@ -3,7 +3,7 @@ # General configuration options #--------------------------------------------------------------------------- PROJECT_NAME = E-MailRelay -PROJECT_NUMBER = 0.9.3 +PROJECT_NUMBER = 0.9.4 OUTPUT_DIRECTORY = OUTPUT_LANGUAGE = English EXTRACT_ALL = YES @@ -99,7 +99,7 @@ TREEVIEW_WIDTH = #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- -GENERATE_LATEX = +GENERATE_LATEX = no LATEX_OUTPUT = latex COMPACT_LATEX = PAPER_TYPE = a4wide diff --git a/src/main/emailrelay.dsp b/src/main/emailrelay.dsp index 852cf50..685a24f 100644 --- a/src/main/emailrelay.dsp +++ b/src/main/emailrelay.dsp @@ -1,558 +1,382 @@ -# Microsoft Developer Studio Project File - Name="emailrelay" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=emailrelay - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "emailrelay.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "emailrelay.mak" CFG="emailrelay - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "emailrelay - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "emailrelay - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "emailrelay - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c -# ADD BASE RSC /l 0x809 /d "NDEBUG" -# ADD RSC /l 0x809 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "emailrelay - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GR /GX /ZI /Od /I "../../src/glib" /I "../../src/gnet" /I "../../lib/msvc6.0" /I "../../src/win32" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "G_WIN32" /FD /GZ /c -# SUBTRACT CPP /YX /Yc /Yu -# ADD BASE RSC /l 0x809 /d "_DEBUG" -# ADD RSC /l 0x809 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "emailrelay - Win32 Release" -# Name "emailrelay - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=..\gnet\gaddress_ipv4.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\main\gadminserver.cpp -# End Source File -# Begin Source File - -SOURCE=..\win32\gappinst.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\garg.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\garg_win32.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gclient.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gclient_win32.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\main\gclientprotocol.cpp -# End Source File -# Begin Source File - -SOURCE=..\win32\gcracker.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gdaemon_win32.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gdate.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gdatetime.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gdatetime_win32.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gdescriptor_win32.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gdirectory.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gdirectory_win32.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gevent.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gevent_win32.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\geventserver.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gexception.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gfile.cpp -# End Source File -# Begin Source File - -SOURCE=..\glib\gfile_win32.cpp -# End Source File -# Begin Source File - -SOURCE=.\gfilestore.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gfs_win32.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\ggetopt.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\glinebuffer.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\glocal_win32.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\glog.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\glogoutput.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\glogoutput_win32.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\main\gmessagestore.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\main\gmessagestore_win32.cpp -# End Source File -# Begin Source File - -SOURCE=.\gnewfile.cpp -# End Source File -# Begin Source File - -SOURCE=.\gnewmessage.cpp -# End Source File -# Begin Source File - -SOURCE=..\glib\gnumber.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gpath.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gprocess_win32.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\main\gprotocolmessage.cpp -# End Source File -# Begin Source File - -SOURCE=.\gprotocolmessageforward.cpp -# End Source File -# Begin Source File - -SOURCE=.\gprotocolmessagestore.cpp -# End Source File -# Begin Source File - -SOURCE=..\win32\gpump.cpp -# End Source File -# Begin Source File - -SOURCE=..\win32\gpump_nodialog.cpp -# End Source File -# Begin Source File - -SOURCE=..\gnet\grequest.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gresolve.cpp -# End Source File -# Begin Source File - -SOURCE=..\gnet\gresolve_ipv4.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gresolve_win32.cpp -# End Source File -# Begin Source File - -SOURCE=..\gnet\gserver.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\main\gserverprotocol.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\main\gsmtpclient.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\main\gsmtpserver.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gsocket.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gsocket_win32.cpp -# End Source File -# Begin Source File - -SOURCE=.\gstoredfile.cpp -# End Source File -# Begin Source File - -SOURCE=.\gstoredmessage.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gstr.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gtime.cpp -# End Source File -# Begin Source File - -SOURCE=.\gverifier.cpp -# End Source File -# Begin Source File - -SOURCE=..\win32\gwinbase.cpp -# End Source File -# Begin Source File - -SOURCE=..\win32\gwindow.cpp -# End Source File -# Begin Source File - -SOURCE=..\win32\gwinhid.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gwinsock.cpp -# End Source File -# Begin Source File - -SOURCE=..\..\src\main\mailrelay.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=..\..\src\gnet\gaddress.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\main\gadminserver.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\garg.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gassert.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gclient.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\main\gclientprotocol.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gconvert.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gdaemon.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gdate.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gdatetime.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gdebug.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gdef.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gdescriptor.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gdirectory.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gevent.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\geventserver.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gexception.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gfile.h -# End Source File -# Begin Source File - -SOURCE=.\gfilestore.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gfs.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\ggetopt.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\glinebuffer.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\glocal.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\glog.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\glogoutput.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gmemory.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\main\gmessagestore.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gnet.h -# End Source File -# Begin Source File - -SOURCE=.\gnewfile.h -# End Source File -# Begin Source File - -SOURCE=.\gnewmessage.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gpath.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gprocess.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\main\gprotocolmessage.h -# End Source File -# Begin Source File - -SOURCE=.\gprotocolmessageforward.h -# End Source File -# Begin Source File - -SOURCE=.\gprotocolmessagestore.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\grequest.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gresolve.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gselect.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gserver.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\main\gserverprotocol.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\main\gsmtp.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\main\gsmtpclient.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\main\gsmtpserver.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gsocket.h -# End Source File -# Begin Source File - -SOURCE=.\gstoredfile.h -# End Source File -# Begin Source File - -SOURCE=.\gstoredmessage.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gstr.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gstrings.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\glib\gtime.h -# End Source File -# Begin Source File - -SOURCE=.\gverifier.h -# End Source File -# Begin Source File - -SOURCE=..\..\src\gnet\gwinsock.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# Begin Source File - -SOURCE=.\emailrelay.rc -# End Source File -# Begin Source File - -SOURCE=".\icon-32.ico" -# End Source File -# End Group -# End Target -# End Project +# Microsoft Developer Studio Project File - Name="emailrelay" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=emailrelay - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "emailrelay.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "emailrelay.mak" CFG="emailrelay - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "emailrelay - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "emailrelay - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "emailrelay - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /W3 /GR /GX /O2 /I "../glib" /I "../gnet" /I "../win32" /I "../../lib/msvc6.0" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "G_WIN32" /D "_CONSOLE" /YX"gdef.h" /FD /c +# SUBTRACT CPP /X +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /machine:I386 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "emailrelay - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GR /GX /ZI /Od /I "../../src/glib" /I "../../src/gnet" /I "../../lib/msvc6.0" /I "../../src/win32" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "G_WIN32" /FD /GZ /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /debug /machine:I386 /pdbtype:sept +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "emailrelay - Win32 Release" +# Name "emailrelay - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\commandline.cpp +# End Source File +# Begin Source File + +SOURCE=.\commandline_win32.cpp +# End Source File +# Begin Source File + +SOURCE=.\configuration.cpp +# End Source File +# Begin Source File + +SOURCE=..\gnet\gaddress_ipv4.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\main\gadminserver.cpp +# End Source File +# Begin Source File + +SOURCE=..\win32\gappbase.cpp +# End Source File +# Begin Source File + +SOURCE=..\win32\gappinst.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\garg.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\garg_win32.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\gnet\gclient.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\gnet\gclient_win32.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\main\gclientprotocol.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\gnet\gconnection.cpp +# End Source File +# Begin Source File + +SOURCE=..\win32\gcracker.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\gdaemon_win32.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\gdate.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\gdatetime.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\gdatetime_win32.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\gnet\gdescriptor_win32.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\gdirectory.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\gdirectory_win32.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\gnet\gevent.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\gnet\gevent_win32.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\gnet\geventserver.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\gexception.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\gfile.cpp +# End Source File +# Begin Source File + +SOURCE=..\glib\gfile_win32.cpp +# End Source File +# Begin Source File + +SOURCE=.\gfilestore.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\gfs_win32.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\ggetopt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\gnet\glinebuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\gnet\glocal_win32.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\glog.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\glogoutput.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\glogoutput_win32.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\main\gmessagestore.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\main\gmessagestore_win32.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\gnet\gmonitor.cpp +# End Source File +# Begin Source File + +SOURCE=.\gnewfile.cpp +# End Source File +# Begin Source File + +SOURCE=.\gnewmessage.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\gpath.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\gprocess_win32.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\main\gprotocolmessage.cpp +# End Source File +# Begin Source File + +SOURCE=.\gprotocolmessageforward.cpp +# End Source File +# Begin Source File + +SOURCE=.\gprotocolmessagestore.cpp +# End Source File +# Begin Source File + +SOURCE=..\win32\gpump.cpp +# End Source File +# Begin Source File + +SOURCE=..\win32\gpump_nodialog.cpp +# End Source File +# Begin Source File + +SOURCE=..\gnet\grequest.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\gnet\gresolve.cpp +# End Source File +# Begin Source File + +SOURCE=..\gnet\gresolve_ipv4.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\gnet\gresolve_win32.cpp +# End Source File +# Begin Source File + +SOURCE=..\gnet\gserver.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\main\gserverprotocol.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\main\gsmtpclient.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\main\gsmtpserver.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\gnet\gsocket.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\gnet\gsocket_win32.cpp +# End Source File +# Begin Source File + +SOURCE=.\gstoredfile.cpp +# End Source File +# Begin Source File + +SOURCE=.\gstoredmessage.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\gstr.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\glib\gtime.cpp +# End Source File +# Begin Source File + +SOURCE=.\gverifier.cpp +# End Source File +# Begin Source File + +SOURCE=..\win32\gwinbase.cpp +# End Source File +# Begin Source File + +SOURCE=..\win32\gwindow.cpp +# End Source File +# Begin Source File + +SOURCE=..\win32\gwinhid.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\src\gnet\gwinsock.cpp +# End Source File +# Begin Source File + +SOURCE=.\main_win32.cpp +# End Source File +# Begin Source File + +SOURCE=.\run.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\emailrelay.rc +# End Source File +# Begin Source File + +SOURCE=".\icon-32.ico" +# End Source File +# End Group +# End Target +# End Project diff --git a/src/main/emailrelay.rc b/src/main/emailrelay.rc index f3fb07b..df3bd39 100644 --- a/src/main/emailrelay.rc +++ b/src/main/emailrelay.rc @@ -1,2 +1,93 @@ -#define IDI_ICON1 101 +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" +///////////////////////////////////////////////////////////////////////////// +// English (U.K.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. IDI_ICON1 ICON DISCARDABLE "icon-32.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 72, 62 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN + ICON "",IDC_STATIC,24,19,21,20 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 65 + TOPMARGIN, 7 + BOTTOMMARGIN, 55 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.K.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/main/gadminserver.cpp b/src/main/gadminserver.cpp index a3c15a9..c051ac4 100644 --- a/src/main/gadminserver.cpp +++ b/src/main/gadminserver.cpp @@ -18,13 +18,14 @@ // // === // -// gadmin.h +// gadminserver.cpp // #include "gdef.h" #include "gnet.h" #include "gsmtp.h" #include "gadminserver.h" +#include "gmonitor.h" #include "gstr.h" #include "gmemory.h" @@ -42,6 +43,7 @@ GSmtp::AdminPeer::AdminPeer( GNet::StreamSocket * s , GNet::Address a , AdminSer m_buffer(crlf()) , m_server_address(server_address) { + // dont prompt() here -- it confuses the poke program } void GSmtp::AdminPeer::clientDone( std::string s ) @@ -50,6 +52,8 @@ void GSmtp::AdminPeer::clientDone( std::string s ) send( "OK" ) ; else send( std::string("error: ") + s ) ; + + prompt() ; } void GSmtp::AdminPeer::onDelete() @@ -75,6 +79,12 @@ bool GSmtp::AdminPeer::processLine( const std::string & line ) else if( is(line,"HELP") ) { help() ; + prompt() ; + } + else if( is(line,"INFO") ) + { + info() ; + prompt() ; } else if( is(line,"QUIT") ) { @@ -84,6 +94,11 @@ bool GSmtp::AdminPeer::processLine( const std::string & line ) else if( line.find_first_not_of(" \r\n\t") != std::string::npos ) { send( "error: unrecognised command" ) ; + prompt() ; + } + else + { + prompt() ; } return true ; } @@ -105,7 +120,7 @@ bool GSmtp::AdminPeer::is( const std::string & line_in , const char * key ) void GSmtp::AdminPeer::help() { - send( "commands: FLUSH, HELP, QUIT" ) ; + send( "commands: FLUSH, HELP, INFO, QUIT" ) ; } void GSmtp::AdminPeer::flush( const std::string & address ) @@ -127,13 +142,33 @@ void GSmtp::AdminPeer::flush( const std::string & address ) } } +void GSmtp::AdminPeer::prompt() +{ + std::string p( "E-MailRelay> " ) ; + ssize_t rc = socket().write( p.data() , p.length() ) ; + if( rc < p.length() ) + doDelete() ; // onDelete() and "delete this" +} + void GSmtp::AdminPeer::send( std::string line ) { line.append( crlf() ) ; ssize_t rc = socket().write( line.data() , line.length() ) ; if( rc < line.length() ) - { doDelete() ; // onDelete() and "delete this" +} + +void GSmtp::AdminPeer::info() +{ + std::stringstream ss ; + if( GNet::Monitor::instance() ) + { + GNet::Monitor::instance()->report( ss ) ; + send( ss.str() ) ; + } + else + { + send( "no info" ) ; } } diff --git a/src/main/gadminserver.h b/src/main/gadminserver.h index 99cd332..2bc2a68 100644 --- a/src/main/gadminserver.h +++ b/src/main/gadminserver.h @@ -71,11 +71,13 @@ private: static bool is( const std::string & , const char * ) ; void flush( const std::string & ) ; void help() ; + void info() ; void send( std::string ) ; + static std::string crlf() ; + void prompt() ; private: GNet::LineBuffer m_buffer ; - static std::string crlf() ; AdminServer & m_server ; std::auto_ptr m_client ; std::string m_server_address ; diff --git a/src/main/gmessagestore.h b/src/main/gmessagestore.h index 2554324..4f1e3fb 100644 --- a/src/main/gmessagestore.h +++ b/src/main/gmessagestore.h @@ -111,6 +111,11 @@ public: // iterators share state. For independent iterators // call iterator() for each.) // + // Stored messages returned by the iterator are locked. + // Normally they are then processed (using + // StoredMessage::extractContentStream()) and + // then deleted (by StoredMessage::destroy()). + // // As a side effect of iteration some stored // messages may be marked as bad, or deleted (if // they have no recipients). diff --git a/src/main/gnewfile.h b/src/main/gnewfile.h index f1535a2..f79432d 100644 --- a/src/main/gnewfile.h +++ b/src/main/gnewfile.h @@ -48,11 +48,22 @@ public: G_EXCEPTION( Dangerous , "message filtering not allowed if running as a privileged process" ) ; NewFile( const std::string & from , FileStore & store ) ; + // Constructor. + virtual ~NewFile() ; + // Destructor. + virtual void addTo( const std::string & to , bool local ) ; + // Adds a 'to' address. + virtual void addText( const std::string & line ) ; + // Adds a line of content. + virtual void store() ; + // Stores the message in the message store. + virtual unsigned long id() const ; + // Returns the message's unique identifier. static void setPreprocessor( const G::Path & exe ) ; // Defines a program which is used for pre-processing diff --git a/src/main/mailrelay.cpp b/src/main/mailrelay.cpp deleted file mode 100644 index 45d95a2..0000000 --- a/src/main/mailrelay.cpp +++ /dev/null @@ -1,459 +0,0 @@ -// -// Copyright (C) 2001 Graeme Walker -// -// 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 for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -// -// === -// -// mailrelay.cpp -// - -#include "gdef.h" -#include "gsmtp.h" -#include "gsmtpserver.h" -#include "gsmtpclient.h" -#include "gevent.h" -#include "garg.h" -#include "gdaemon.h" -#include "gstr.h" -#include "gpath.h" -#include "gfilestore.h" -#include "gnewfile.h" -#include "gadminserver.h" -#include "gexception.h" -#include "gprocess.h" -#include "gmemory.h" -#include "ggetopt.h" -#include "gdebug.h" -#include -#include - -namespace -{ - class Main - { - public: - explicit Main( G::Arg & arg ) ; - void run() ; - private: - std::string versionNumber() const ; - void version() const ; - void banner() const ; - void warranty() const ; - void usage( std::ostream & s , const std::string & exe , const G::GetOpt & opt ) const ; - void help( const std::string & exe ) const ; - void shortHelp( std::ostream & stream , const std::string & exe ) const ; - void copyright() const ; - std::string switchSpec() const ; - void runCore() ; - unsigned int ttyColumns() const ; - std::string checkOptions() const ; - const G::GetOpt & opt() const ; - unsigned int optPort() const ; - unsigned int optAdminPort() const ; - bool optCloseStderr() const ; - bool optImmediate() const ; - bool optLog() const ; - bool optSyslog() const ; - bool optDaemon() const ; - bool optDoForwarding() const ; - bool optDoServing() const ; - bool optDoAdmin() const ; - bool optAllowRemoteClients() const ; - G::Path optSpoolDir() const ; - std::string optServerAddress() const ; - void doForwarding( GSmtp::MessageStore & store ) ; - void closeFiles() ; - void closeMoreFiles() ; - std::string smtpIdent() const ; - void recordPid() ; - private: - G::Arg m_arg ; - G::GetOpt * m_opt ; - } ; -} ; - -Main::Main( G::Arg & arg ) : - m_arg(arg) -{ -} - -void Main::banner() const -{ - std::cout - << "E-MailRelay V" << versionNumber() << std::endl ; -} - -void Main::copyright() const -{ - std::cout << "Copyright (C) 2001 Graeme Walker" << std::endl ; -} - -void Main::warranty() const -{ - std::cout - << "This software is provided without warranty of any kind." << std::endl - << "You may redistribure copies of this program under " << std::endl - << "the terms of the GNU General Public License." << std::endl - << "For more information refer to the file named COPYING." << std::endl ; -} - -void Main::version() const -{ - banner() ; - warranty() ; - copyright() ; -} - -std::string Main::versionNumber() const -{ - return "0.9.3" ; -} - -std::string Main::smtpIdent() const -{ - return std::string("E-MailRelay V") + versionNumber() ; -} - -unsigned int Main::ttyColumns() const -{ - const unsigned int default_ = 79U ; - try - { - const char * p = std::getenv( "COLUMNS" ) ; - if( p == NULL ) - return default_ ; - else - return G::Str::toUInt(p) ; - } - catch( std::exception & ) - { - return default_ ; - } -} - -void Main::usage( std::ostream & s , const std::string & exe , const G::GetOpt & opt ) const -{ - opt.showUsage( s , exe , "" , 30U , ttyColumns() ) ; -} - -void Main::help( const std::string & exe ) const -{ - std::cout << std::endl ; - - std::cout - << "To start a 'storage' daemon in background..." << std::endl - << " " << exe << " --as-server" << std::endl - << std::endl ; - - std::cout - << "To forward stored mail to \"mail.myisp.co.uk\"..." << std::endl - << " " << exe << " --as-client mail.myisp.co.uk:smtp" << std::endl - << std::endl ; - - std::cout - << "To run as a proxy (on port 10025) to a local server (on port 25)..." << std::endl - << " " << exe << " --port 10025 --as-proxy localhost:25" << std::endl - << std::endl ; -} - -void Main::shortHelp( std::ostream & stream , const std::string & exe ) const -{ - stream - << std::string(exe.length()+2U,' ') - << "try \"" << exe << " --help\" for more information" << std::endl ; -} - -std::string Main::switchSpec() const -{ - std::stringstream ss ; - ss - << "h!help!displays help text and exits!0!|" - << "l!log!writes log information on standard error (if open) and syslog (if not disabled)!0!|" - << "v!verbose!generates more verbose logging " - << "(if compiled-in and logging enabled and stderr open)!0!|" - << "e!close-stderr!closes the standard error stream when daemonising!0!|" - << "s!spool-dir!specifies the spool directory " - << "(default is \"" << GSmtp::MessageStore::defaultDirectory() - << "\")!1!dir|" - << "q!as-client!equivalent to \"--no-syslog --no-daemon --log --dont-serve --forward --forward-to\"!" - << "1!host:port|" - << "d!as-server!equivalent to \"--close-stderr --log\"!0!|" - << "m!immediate!forwards each message as soon as it is received (requires --forward-to)!0!|" - << "n!no-syslog!disables syslog output!0!|" - << "t!no-daemon!does not detach from the terminal!0!|" - << "x!dont-serve!stops the process acting as a server (usually used with --forward)!0!|" - << "f!forward!forwards stored mail on startup (requires --forward-to)!0!|" - << "o!forward-to!specifies the remote smtp server (required by --forward and --admin)!1!host:port|" - << "r!remote-clients!allows remote clients to connect!0!|" - << "i!pid-file!records the daemon process-id in the given file!1!pid-file|" - << "p!port!specifies the smtp listening port number!1!port|" - << "a!admin!enables the administration interface and specifies its listening port number!1!admin-port|" - << "y!as-proxy!equivalent to \"--close-stderr --log --immediate --forward-to\"!1!host:port|" - << "z!filter!defines a mail pre-processor (disallowed if running as root)!1!program|" - << "V!version!displays version information and exits!0!" - ; - return ss.str() ; -} - -const G::GetOpt & Main::opt() const -{ - G_ASSERT( m_opt != NULL ) ; - return *m_opt ; -} - -void Main::run() -{ - m_opt = new G::GetOpt( m_arg , switchSpec() , '|' , '!' , '^' ) ; - - if( opt().contains("help") ) - { - banner() ; - std::cout << std::endl ; - usage( std::cout , m_arg.prefix() , opt() ) ; - help( m_arg.prefix() ) ; - copyright() ; - } - else if( opt().hasErrors() ) - { - opt().showErrors( std::cerr , m_arg.prefix() ) ; - shortHelp( std::cerr , m_arg.prefix() ) ; - } - else if( opt().args().c() > 1U ) - { - std::cerr << m_arg.prefix() << ": usage error: too many non-switch arguments" << std::endl ; - shortHelp( std::cerr , m_arg.prefix() ) ; - } - else if( opt().contains("version") ) - { - version() ; - } - else - { - G::LogOutput debug( optLog() , opt().contains("verbose") ) ; - if( optSyslog() ) - debug.syslog(G::LogOutput::Mail) ; - - runCore() ; - } -} - -bool Main::optLog() const -{ - return - opt().contains("log") || - opt().contains("as-client") || - opt().contains("as-proxy") || - opt().contains("as-server") ; -} - -bool Main::optSyslog() const -{ - return !opt().contains("no-syslog") && !opt().contains("as-client") ; -} - -unsigned int Main::optPort() const -{ - return opt().contains("port") ? - G::Str::toUInt(opt().value("port")) : 25U ; -} - -unsigned int Main::optAdminPort() const -{ - return opt().contains("admin") ? - G::Str::toUInt(opt().value("admin")) : 10025U ; -} - -bool Main::optCloseStderr() const -{ - return - opt().contains("close-stderr") || - opt().contains("as-proxy") || - opt().contains("as-server") ; -} - -bool Main::optImmediate() const -{ - return - opt().contains("immediate") || - opt().contains("as-proxy") ; -} - -bool Main::optDaemon() const -{ - return !opt().contains("no-daemon") && !opt().contains("as-client") ; -} - -G::Path Main::optSpoolDir() const -{ - return opt().contains("spool-dir") ? - G::Path(opt().value("spool-dir")) : - GSmtp::MessageStore::defaultDirectory() ; -} - -std::string Main::optServerAddress() const -{ - const char * key = "forward-to" ; - if( opt().contains("as-client") ) - key = "as-client" ; - else if( opt().contains("as-proxy") ) - key = "as-proxy" ; - return opt().contains(key) ? opt().value(key) : std::string() ; -} - -std::string Main::checkOptions() const -{ - if( optDoAdmin() && optAdminPort() == optPort() ) - { - return "the smtp listening port and the " - "admin listening port must be different" ; - } - - if( optDaemon() && optSpoolDir().isRelative() ) - { - return "in daemon mode the spool-dir must " - "be an absolute path (starting with /)" ; - } - - if( !opt().contains("forward-to") && ( - opt().contains("forward") || - opt().contains("immediate") || - opt().contains("admin") ) ) - { - return "usage error: the --forward, --immediate and --admin " - "switches require --forward-to" ; - } - - return std::string() ; -} - -bool Main::optDoForwarding() const -{ - return opt().contains("forward") || opt().contains("as-client") ; -} - -void Main::doForwarding( GSmtp::MessageStore & store ) -{ - const bool quit_on_disconnect = true ; - GSmtp::Client client( store , quit_on_disconnect ) ; - std::string error = client.init( optServerAddress() ) ; - if( error.length() ) - throw G::Exception( error + ": " + optServerAddress() ) ; - - GNet::EventSources::instance().run() ; -} - -void Main::closeFiles() -{ - if( optDaemon() ) - { - const bool keep_stderr = true ; - G::Process::closeFiles( keep_stderr ) ; - } -} - -void Main::closeMoreFiles() -{ - if( optDaemon() && optCloseStderr() ) - G::Process::closeStderr() ; -} - -bool Main::optDoServing() const -{ - return !opt().contains("dont-serve") && !opt().contains("as-client") ; -} - -bool Main::optAllowRemoteClients() const -{ - return opt().contains("remote-clients") ; -} - -bool Main::optDoAdmin() const -{ - return opt().contains("admin") ; -} - -void Main::runCore() -{ - std::string error = checkOptions() ; - if( !error.empty() ) - throw G::Exception( error ) ; - - G::Daemon::PidFile pid_file ; - G::Process::setUmask() ; - if( optDaemon() ) - { - closeFiles() ; // before opening any sockets or message-store streams - if( opt().contains("pid-file") ) - pid_file = G::Daemon::PidFile( G::Path(opt().value("pid-file")) ) ; - G::Daemon::detach( pid_file ) ; - } - - GSmtp::FileStore store( optSpoolDir() ) ; - if( opt().contains("filter") ) - GSmtp::NewFile::setPreprocessor( G::Path(opt().value("filter")) ) ; - - std::auto_ptr event_loop( GNet::EventSources::create() ) ; - if( ! event_loop->init() ) - throw G::Exception( "cannot initialise network layer" ) ; - - if( optDoForwarding() ) - { - if( store.empty() ) - std::cerr << m_arg.prefix() << ": no messages to send" << std::endl ; - else - doForwarding( store ) ; - } - - if( optDoServing() ) - { - GSmtp::Server server( optPort() , optAllowRemoteClients() , smtpIdent() , - optImmediate() ? optServerAddress() : std::string() ) ; - - std::auto_ptr admin_server ; - if( optDoAdmin() ) - { - admin_server <<= new GSmtp::AdminServer( optAdminPort() , - optAllowRemoteClients() , optServerAddress() ) ; - } - - pid_file.commit() ; - closeMoreFiles() ; - event_loop->run() ; - } -} - -int main( int argc , char * argv [] ) -{ - G::Arg arg( argc , argv ) ; - try - { - Main main( arg ) ; - main.run() ; - return EXIT_SUCCESS ; - } - catch( std::exception & e ) - { - std::cerr << arg.prefix() << ": exception: " << e.what() << std::endl ; - } - catch( ... ) - { - std::cerr << arg.prefix() << ": unrecognised exception" << std::endl ; - } - return EXIT_FAILURE ; -} - - diff --git a/src/main/main_unix.cpp b/src/main/main_unix.cpp new file mode 100644 index 0000000..cebf1f3 --- /dev/null +++ b/src/main/main_unix.cpp @@ -0,0 +1,50 @@ +// +// Copyright (C) 2001 Graeme Walker +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// === +// +// main.cpp +// + +#include "gdef.h" +#include "gsmtp.h" +#include "garg.h" +#include "run.h" +#include + +int main( int argc , char * argv [] ) +{ + G::Arg arg( argc , argv ) ; + try + { + Main::Run main( arg ) ; + if( main.prepare() ) + main.run() ; + return EXIT_SUCCESS ; + } + catch( std::exception & e ) + { + std::cerr << arg.prefix() << ": exception: " << e.what() << std::endl ; + } + catch( ... ) + { + std::cerr << arg.prefix() << ": unrecognised exception" << std::endl ; + } + return EXIT_FAILURE ; +} + diff --git a/src/main/main_win32.cpp b/src/main/main_win32.cpp new file mode 100644 index 0000000..aea2b5a --- /dev/null +++ b/src/main/main_win32.cpp @@ -0,0 +1,110 @@ +// +// Copyright (C) 2001 Graeme Walker +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// === +// +// main_win32.cpp +// + +#include "gdef.h" +#include "gsmtp.h" +#include "run.h" +#include "gappbase.h" +#include "gexception.h" +#include "resource.h" + +namespace +{ + class App : public GGui::ApplicationBase + { + public: + App( HINSTANCE h , HINSTANCE p , const char * name ) ; + void onPaint( HDC hdc ) ; + bool onCreate() ; + DWORD windowStyle() const ; + } ; +} ; + +App::App( HINSTANCE h , HINSTANCE p , const char * name ) : + GGui::ApplicationBase( h , p , name ) +{ +} + +DWORD App::windowStyle() const +{ + return + ( GGui::Window::windowStylePopup() & ~WS_THICKFRAME ) | + WS_MINIMIZEBOX ; +} + +bool App::onCreate() +{ + GGui::Size size ; + size.dx = size.dy = 100 ; + resize( size ) ; + return true ; +} + +void App::onPaint( HDC hdc ) +{ + int dx_window = internalSize().dx ; + int dy_window = internalSize().dy ; + int dx_icon = 32 ; + int dy_icon = 32 ; + + int x = dx_window > dx_icon ? ((dx_window-dx_icon)/2) : 0 ; + int y = dy_window > dy_icon ? ((dy_window-dy_icon)/2) : 0 ; + + ::DrawIcon( hdc , x , y , + ::LoadIcon(hinstance(),MAKEINTRESOURCE(IDI_ICON1)) ) ; +} + +int WINAPI WinMain( HINSTANCE hinstance , HINSTANCE previous , + LPSTR command_line , int show ) +{ + try + { + show = SW_MINIMIZE ; + + G::Arg arg ; + arg.parse( hinstance , command_line ) ; + + App app( hinstance , previous , "E-MailRelay" ) ; + + try + { + Main::Run run( arg ) ; + if( run.prepare() ) + { + app.createWindow( show ) ; + run.run() ; + } + } + catch( std::exception & e ) + { + app.messageBox( e.what() ) ; + } + + return 0 ; + } + catch(...) + { + } + return 1 ; +} + diff --git a/src/main/resource.h b/src/main/resource.h new file mode 100644 index 0000000..0bf1fff --- /dev/null +++ b/src/main/resource.h @@ -0,0 +1,38 @@ +// +// Copyright (C) 2001 Graeme Walker +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// === +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by emailrelay.rc +// +#include +#define IDI_ICON1 101 +#define IDD_DIALOG1 101 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/main/run.cpp b/src/main/run.cpp new file mode 100644 index 0000000..d0c2c40 --- /dev/null +++ b/src/main/run.cpp @@ -0,0 +1,195 @@ +// +// Copyright (C) 2001 Graeme Walker +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// === +// +// run.cpp +// + +#include "gdef.h" +#include "gsmtp.h" +#include "run.h" +#include "gsmtpserver.h" +#include "gsmtpclient.h" +#include "gevent.h" +#include "garg.h" +#include "gdaemon.h" +#include "gfilestore.h" +#include "gnewfile.h" +#include "gadminserver.h" +#include "gmonitor.h" +#include "gprocess.h" +#include "gmemory.h" +#include "gdebug.h" +#include +#include + +//static +std::string Main::Run::versionNumber() +{ + return "0.9.4" ; +} + +Main::Run::Run( G::Arg & arg ) : + m_cl(arg,versionNumber()) +{ +} + +Main::Configuration Main::Run::cfg() const +{ + return m_cl.cfg() ; +} + +std::string Main::Run::smtpIdent() const +{ + return std::string("E-MailRelay V") + versionNumber() ; +} + +void Main::Run::closeFiles() +{ + if( cfg().daemon() ) + { + const bool keep_stderr = true ; + G::Process::closeFiles( keep_stderr ) ; + } +} + +void Main::Run::closeMoreFiles() +{ + if( cfg().daemon() && cfg().closeStderr() ) + G::Process::closeStderr() ; +} + +bool Main::Run::prepare() +{ + bool do_run = false ; + + if( m_cl.contains("help") ) + { + m_cl.showHelp( false ) ; + } + else if( m_cl.hasUsageErrors() ) + { + m_cl.showUsageErrors( true ) ; + } + else if( m_cl.contains("version") ) + { + m_cl.showVersion( false ) ; + } + else if( m_cl.argc() > 1U ) + { + m_cl.showArgcError( true ) ; + } + else if( m_cl.hasSemanticError() ) + { + m_cl.showSemanticError( true ) ; + } + else + { + do_run = true ; + } + + return do_run ; +} + +void Main::Run::run() +{ + // logging + // + G::LogOutput debug( cfg().log() , cfg().verbose() ) ; + if( cfg().syslog() ) + debug.syslog(G::LogOutput::Mail) ; + + // daemonising + // + G::Daemon::PidFile pid_file ; + G::Process::setUmask() ; + if( cfg().daemon() ) + { + closeFiles() ; // before opening any sockets or message-store streams + if( cfg().usePidFile() ) + pid_file = G::Daemon::PidFile( G::Path(cfg().pidFile()) ) ; + G::Daemon::detach( pid_file ) ; + } + + // message store singleton + // + GSmtp::FileStore store( cfg().spoolDir() ) ; + if( cfg().useFilter() ) + GSmtp::NewFile::setPreprocessor( G::Path(cfg().filter()) ) ; + + // event loop singleton + // + std::auto_ptr event_loop(GNet::EventSources::create()) ; + if( ! event_loop->init() ) + throw G::Exception( "cannot initialise network layer" ) ; + + // network monitor singleton + // + GNet::Monitor monitor ; + + // run as forwarding agent + // + if( cfg().doForwarding() ) + { + if( store.empty() ) + m_cl.showNoop( true ) ; + else + doForwarding( store , *event_loop.get() ) ; + } + + // run as storage daemon + // + if( cfg().doServing() ) + { + doServing( pid_file , *event_loop.get() ) ; + } +} + +void Main::Run::doServing( G::Daemon::PidFile & pid_file , + GNet::EventSources & event_loop ) +{ + GSmtp::Server server( cfg().port() , + cfg().allowRemoteClients() , smtpIdent() , + cfg().immediate() ? cfg().serverAddress() : std::string() ) ; + + std::auto_ptr admin_server ; + if( cfg().doAdmin() ) + { + admin_server <<= new GSmtp::AdminServer( cfg().adminPort() , + cfg().allowRemoteClients() , cfg().serverAddress() ) ; + } + + pid_file.commit() ; + closeMoreFiles() ; + + event_loop.run() ; +} + +void Main::Run::doForwarding( GSmtp::MessageStore & store , + GNet::EventSources & event_loop ) +{ + const bool quit_on_disconnect = true ; + GSmtp::Client client( store , quit_on_disconnect ) ; + std::string error = client.init( cfg().serverAddress() ) ; + if( error.length() ) + throw G::Exception( error + ": " + cfg().serverAddress() ) ; + + event_loop.run() ; +} + diff --git a/src/main/run.h b/src/main/run.h new file mode 100644 index 0000000..4f7925c --- /dev/null +++ b/src/main/run.h @@ -0,0 +1,84 @@ +// +// Copyright (C) 2001 Graeme Walker +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// === +// +// run.h +// + +#ifndef G_MAIN_RUN_H +#define G_MAIN_RUN_H + +#include "gdef.h" +#include "gsmtp.h" +#include "configuration.h" +#include "commandline.h" +#include "gevent.h" +#include "gdaemon.h" +#include "garg.h" +#include "gmessagestore.h" +#include +#include + +namespace Main +{ + class Run ; +} ; + +// Class: Main::Run +// Description: A top-level class for the process. +// Usage: +/// int main( int argc , char ** argv ) +/// { +/// G::Arg arg( argc , argv ) ; +/// Main::Run run( arg ) ; +/// if( run.prepare() ) +/// run.run() ; +/// return 0 ; +/// } +// +class Main::Run +{ +public: + explicit Run( G::Arg & arg ) ; + // Constructor. + + bool prepare() ; + // Prepares to run(). Returns + // false on error. + + void run() ; + // Runs the application. + // Precondition: prepare() returned true + +private: + static std::string versionNumber() ; + void runCore() ; + void doForwarding( GSmtp::MessageStore & , GNet::EventSources & ) ; + void doServing( G::Daemon::PidFile & , GNet::EventSources & ) ; + void closeFiles() ; + void closeMoreFiles() ; + std::string smtpIdent() const ; + void recordPid() ; + Configuration cfg() const ; + +private: + CommandLine m_cl ; +} ; + +#endif diff --git a/src/win32/Makefile.am b/src/win32/Makefile.am index bbb5f5e..4c9e910 100644 --- a/src/win32/Makefile.am +++ b/src/win32/Makefile.am @@ -18,8 +18,11 @@ # # === -EXTRA_DIST = gappinst.h \ +EXTRA_DIST = \ gappinst.cpp \ + gappinst.h \ + gappbase.cpp \ + gappbase.h \ gcracker.cpp \ gcracker.h \ gpump.cpp \ diff --git a/src/win32/Makefile.in b/src/win32/Makefile.in index 238e5cf..9aec6ea 100644 --- a/src/win32/Makefile.in +++ b/src/win32/Makefile.in @@ -89,7 +89,7 @@ PACKAGE = @PACKAGE@ RANLIB = @RANLIB@ VERSION = @VERSION@ -EXTRA_DIST = gappinst.h gappinst.cpp gcracker.cpp gcracker.h gpump.cpp gpump.h gpump_nodialog.cpp gsize.h gwinbase.cpp gwinbase.h gwindow.cpp gwindow.h gwinhid.cpp gwinhid.h +EXTRA_DIST = gappinst.cpp gappinst.h gappbase.cpp gappbase.h gcracker.cpp gcracker.h gpump.cpp gpump.h gpump_nodialog.cpp gsize.h gwinbase.cpp gwinbase.h gwindow.cpp gwindow.h gwinhid.cpp gwinhid.h mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = ../../config.h diff --git a/src/win32/gappbase.cpp b/src/win32/gappbase.cpp new file mode 100644 index 0000000..f48c766 --- /dev/null +++ b/src/win32/gappbase.cpp @@ -0,0 +1,175 @@ +// +// Copyright (C) 2001 Graeme Walker +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// === +// +// gappbase.cpp +// + +#include "gdef.h" +#include "gappbase.h" +#include "gwindow.h" +#include "gpump.h" +#include "gdebug.h" +#include "glog.h" + +GGui::ApplicationBase::ApplicationBase( HINSTANCE current , HINSTANCE previous , + const char *name ) : + ApplicationInstance(current) , + m_previous(previous) , + m_name(name) +{ +} + +GGui::ApplicationBase::~ApplicationBase() +{ +} + +bool GGui::ApplicationBase::createWindow( int show_style , bool do_show ) +{ + G_DEBUG( "GGui::ApplicationBase::createWindow" ) ; + + // first => register a window class + if( m_previous == 0 ) + { + if( !initFirst() ) + { + G_DEBUG( "GGui::ApplicationBase::init: cannot register window class" ) ; + //return false ; + } + } + + // create the main window + if( !create( className() , title() , windowStyle() , + CW_USEDEFAULT , CW_USEDEFAULT , // position (x,y) + CW_USEDEFAULT , CW_USEDEFAULT , // size + NULL , // parent window + NULL , // menu handle: 0 => use class's menu + hinstance() ) ) + { + G_DEBUG( "GGui::ApplicationBase::init: cannot create main window" ) ; + return false ; + } + + if( do_show ) + { + show( show_style ) ; + update() ; + } + + return true ; +} + +bool GGui::ApplicationBase::firstInstance() const +{ + return m_previous == 0 ; +} + +bool GGui::ApplicationBase::initFirst() +{ + UINT id = resource() ; + + G_DEBUG( "GGui::ApplicationBase::initFirst: loading main icon: id " << id ) ; + + HICON icon = id ? ::LoadIcon(hinstance(),MAKEINTRESOURCE(resource())) : 0 ; + + G_DEBUG( "GGui::ApplicationBase::initFirst: " + << "registering main window class \"" << className() + << "\", hinstance " << hinstance() ) ; + + return registerWindowClass( className() , + hinstance() , + classStyle() , + icon ? icon : GGui::Window::classIcon() , + GGui::Window::classCursor() , + backgroundBrush() , + MAKEINTRESOURCE(resource()) ) ; +} + +void GGui::ApplicationBase::close() const +{ + ::SendMessage( handle() , WM_CLOSE , 0 , 0 ) ; +} + +void GGui::ApplicationBase::run( bool with_idle ) +{ + if( with_idle ) + GGui::Pump::run( handle() , GGui::Cracker::wm_idle() ) ; + else + GGui::Pump::run() ; +} + +void GGui::ApplicationBase::onDestroy() +{ + GGui::Pump::quit() ; +} + +const char * GGui::ApplicationBase::title() const +{ + return m_name.c_str() ; +} + +const char * GGui::ApplicationBase::className() const +{ + return m_name.c_str() ; +} + +HBRUSH GGui::ApplicationBase::backgroundBrush() +{ + return GGui::Window::classBrush() ; +} + +DWORD GGui::ApplicationBase::windowStyle() const +{ + return GGui::Window::windowStyleMain() ; +} + +DWORD GGui::ApplicationBase::classStyle() const +{ + return GGui::Window::classStyle() ; +} + +UINT GGui::ApplicationBase::resource() const +{ + return 0 ; +} + +void GGui::ApplicationBase::beep() const +{ + ::MessageBeep( MB_ICONEXCLAMATION ) ; +} + +void GGui::ApplicationBase::messageBox( const std::string & message ) +{ + HWND box_parent = ::GetActiveWindow() ; // eg. a dialog box + if( box_parent == NULL ) + box_parent = handle() ; + + ::MessageBox( box_parent , message.c_str() , title() , + MB_OK | MB_ICONEXCLAMATION ) ; +} + +//static +void GGui::ApplicationBase::messageBox( const std::string & title , const std::string & message ) +{ + HWND box_parent = NULL ; + ::MessageBox( box_parent , message.c_str() , title.c_str() , + MB_OK | MB_ICONEXCLAMATION ) ; +} + + diff --git a/src/win32/gappbase.h b/src/win32/gappbase.h new file mode 100644 index 0000000..2a0b5a0 --- /dev/null +++ b/src/win32/gappbase.h @@ -0,0 +1,150 @@ +// +// Copyright (C) 2001 Graeme Walker +// +// 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 for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// === +// +// gappbase.h +// + +#ifndef G_APPBASE_H +#define G_APPBASE_H + +#include "gdef.h" +#include "gappinst.h" +#include "gwindow.h" + +namespace GGui +{ + class ApplicationBase ; +} ; + +// Class: GGui::ApplicationBase +// +// Description: A simple windows application class which +// can be used for very-simple applications on its own, +// or as a base class for the more fully-functional +// GApplication class. It has no dependence on other +// low-level classes such as GPath, GArg, and (depending +// on the build) GDialog (see "gpump_nodialog.cpp"). +// +// The application object creates and manages the application's +// main window and runs the ::GetMessage() event loop. +// +// GApplicationBase derives from GGui::Window allowing the user +// to override the default message handing for the +// main application window. +// +// See also: Application, ApplicationInstance, Pump +// +class GGui::ApplicationBase : public Window , public ApplicationInstance +{ +public: + ApplicationBase( HINSTANCE current, HINSTANCE previous, const char *name ); + // Constructor. Applications should declare + // a ApplicationBase object on the stack within + // WinMain(), and then call its createWindow() and + // run() member functions. The 'name' parameter + // is used as the window-class name and the + // title, unless title() and className() are + // overridden in the derived class. + + virtual ~ApplicationBase() ; + // Virtual destructor. + + bool createWindow( int show , bool do_show = true ) ; + // Initialisation (was init()). Creates the main + // window, etc. Returns false on error. + // Should be called from WinMain(). + + void run( bool with_idle = true ) ; + // GetMessage()/DispatchMessage() message pump. + // This should be called from WinMain(). + + void close() const ; + // Sends a close message to this application's + // main window, resulting in onClose() being + // called. + + virtual const char *title() const ; + // Overridable. Defines the main window's title. + + void messageBox( const std::string & message ) ; // not const + // Puts up a message box. + + static void messageBox( const std::string & title , const std::string & message ) ; + // Puts up a message box in the absence of a running application + // object. + +protected: + bool firstInstance() const ; + // Returns true if the constructor's 'previous' + // parameter was NULL. + + virtual void beep() const ; + // Calls ::MessageBeep(). + // + // Overridable as a simple way to keep an + // application silent or change the type of + // beep. + + virtual const char *className() const ; + // Overridable. Defines the main window's class + // name. + + virtual HBRUSH backgroundBrush() ; + // Overridable. Defines the main window class background brush. + // Overrides are typically implemented as + // "return (HBRUSH)(1+COLOR_...)". + + virtual DWORD windowStyle() const ; + // Overridable. Defines the main window's style. + // (Was called style().) + + virtual DWORD classStyle() const ; + // Overridable. Defines the main window class style. + + virtual UINT resource() const ; + // Overridable. Defines the resource id + // for the main window's icon and menu. + + virtual void onDestroy() ; + // Inherited from GGui::Window. Calls PostQuitMessage() + // so that the task terminates when its main + // window is destroyed. + + virtual bool initFirst() ; + // Called from init() for the first application + // instance. Registers the main window class. + // If resource() returns non-zero then it is used + // as the icon id. Returns false on error. + // + // May be overridden only if this base class + // implementation is called first. + +private: + ApplicationBase( const ApplicationBase &other ) ; // not implemented + void operator=( const ApplicationBase &other ) ; // not implemented + +private: + std::string m_name ; + HINSTANCE m_previous ; +} ; + +#endif + +