This commit is contained in:
Graeme Walker 2003-05-18 12:00:00 +00:00
parent ae6c79ec56
commit 7f88cace83
206 changed files with 5749 additions and 3420 deletions

View File

@ -1,6 +1,21 @@
E-MailRelay Change Log E-MailRelay Change Log
====================== ======================
1.0.2 -> 1.1.0
--------------
* In proxy mode unexpected client-side disconnects and timeouts do not leave ".bad" files [see also bug-id 659039].
* By default proxy mode does not interpret addresses for local delivery ("--postmaster").
* Polling option added ("--poll") to rescan the spool directory periodically.
* New special exit code (103) for the pre-processor to trigger immediate polling; 100 to 107 now reserved.
* Orphaned zero-length content files are deleted properly if the server-side dialogue is cut short.
* The "--interface" switch applies to the "--admin" interface too.
* Improved internal event architecture using slot/signal design pattern, and fewer singleton classes.
* Event notification available through the administration interface.
* New "--hidden" switch for Windows.
* Syslog output includes process-id.
* Support for Sun WorkShop 5.0 added.
* Documentation overhaul.
1.0.0 -> 1.0.2 1.0.0 -> 1.0.2
-------------- --------------
* Support for trusted IP addresses, allowing certain clients to avoid authentication. * Support for trusted IP addresses, allowing certain clients to avoid authentication.
@ -39,7 +54,7 @@ E-MailRelay Change Log
* More flexible logging options ("--verbose" and "--debug" work better). * More flexible logging options ("--verbose" and "--debug" work better).
* File Hierarchy Standard (FHS) option for "configure" ("--enable-fhs"). * File Hierarchy Standard (FHS) option for "configure" ("--enable-fhs").
* FHS-compatible RPMs. * FHS-compatible RPMs.
* Spool files writeable by preprocessor when server started as root. * Spool files writeable by pre-processor when server started as root.
* Default directories in executables and scripts come from "configure". * Default directories in executables and scripts come from "configure".
* The "init.d" script is renamed "emailrelay" (was "emailrelay.sh"). * The "init.d" script is renamed "emailrelay" (was "emailrelay.sh").
* Man pages are gzipped when installed. * Man pages are gzipped when installed.
@ -52,7 +67,7 @@ E-MailRelay Change Log
0.9.7 -> 0.9.8 0.9.7 -> 0.9.8
-------------- --------------
* Fix for running preprocessor ("--filter") as root. * Fix for running pre-processor ("--filter") as root.
* Ignore bogus "AUTH=LOGIN" lines in EHLO response. * Ignore bogus "AUTH=LOGIN" lines in EHLO response.
* Submit utility improved to work with mutt. * Submit utility improved to work with mutt.
* Installation of submit man page. * Installation of submit man page.
@ -101,7 +116,7 @@ Windows fixes and improvements...
0.9.2 -> 0.9.3 0.9.2 -> 0.9.3
-------------- --------------
* Proxy mode ("--immediate" and "--as-proxy"). * Proxy mode ("--immediate" and "--as-proxy").
* Message preprocessing ("--filter"). * Message pre-processing ("--filter").
* Message store classes better separated using abstract interfaces. * Message store classes better separated using abstract interfaces.
* Improved notification script, with MIME encoding. * Improved notification script, with MIME encoding.
* Builds with old 2.91 version of gcc. * Builds with old 2.91 version of gcc.

36
INSTALL
View File

@ -1,24 +1,30 @@
Introduction Introduction
============ ============
What follows are generic installation instructions for doing a standard GNU What follows are generic installation instructions for doing a
"./configure; make; make install" installation from source under Linux, FreeBSD GNU-style "./configure; make; make install-strip" installation from
etc. The Windows installation instructions are in a separate document. source under Linux, FreeBSD etc. The Windows installation instructions
are in a separate document.
A non-standard "configure" switch is available, "--enable-fhs", which overrides The E-MailRelay "configure" script provides a few extra switches,
all other directory modifiers, forcing compliance with the File Hierarchy Standard. which are shown in the output of "./configure --help". The most
This switch is used in building the RPMs, and may become the default in future important of these is "--enable-fhs", which overrides all other
releases. directory modifiers, forcing compliance with the File Hierarchy
Standard. This switch is used in building the RPMs, and may become the
default in future releases.
There are also a set of variables which can be defined on the "configure" command There are also a set of variables which can be defined on the
line for controlling all the installation directories in more detail, augmenting "configure" command line for controlling all the installation
the standard command-line switches like "--sbindir" and "--libexecdir". For more directories in more detail, augmenting the standard command-line
information refer to the E-MailRelay reference document under switches like "--sbindir" and "--libexecdir". For more information
"Files and directories". refer to the E-MailRelay reference document under "Files and directories".
The E-MailRelay user guide describes what needs to be done after the "make If compiling with something other than "gcc" then check for any
install" in order to get the emailrelay daemon to start up at boot-time, compiler-specific help in the relevant lib/<compiler> directory.
automatically forward e-mail and bounce failed mail.
The E-MailRelay user guide describes what needs to be done after the
"make install" in order to get the emailrelay daemon to start up at
boot-time, automatically forward e-mail and bounce failed mail.
Basic Installation Basic Installation
================== ==================

View File

@ -1,21 +1,22 @@
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> ## Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# ##
# This program is free software; you can redistribute it and/or ## This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License ## modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either ## as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later ## version 2 of the License, or (at your option) any later
# version. ## version.
# ##
# This program is distributed in the hope that it will be useful, ## This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of ## but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. ## GNU General Public License for more details.
# ##
# You should have received a copy of the GNU General Public License ## You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software ## along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# ##
#
EXTRA_DIST = emailrelay.spec ChangeLog EXTRA_DIST = emailrelay.spec ChangeLog
SUBDIRS = src bin lib doc SUBDIRS = src bin lib doc
e_doc_DATA = NEWS README changelog.gz e_doc_DATA = NEWS README changelog.gz

View File

@ -90,24 +90,8 @@ e_sbindir = @e_sbindir@
e_spooldir = @e_spooldir@ e_spooldir = @e_spooldir@
install_sh = @install_sh@ install_sh = @install_sh@
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> #
#
# 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.
#
EXTRA_DIST = emailrelay.spec ChangeLog EXTRA_DIST = emailrelay.spec ChangeLog
SUBDIRS = src bin lib doc SUBDIRS = src bin lib doc
e_doc_DATA = NEWS README changelog.gz e_doc_DATA = NEWS README changelog.gz

93
README
View File

@ -3,66 +3,69 @@ E-MailRelay Readme
Abstract Abstract
-------- --------
E-MailRelay is a simple SMTP store-and-forward message transfer agent (MTA). E-MailRelay is a simple SMTP proxy and store-and-forward message transfer agent
It runs as an SMTP server, storing e-mail in a local spool directory, and (MTA). When running as a proxy all e-mail messages can be passed through a
then forwarding the stored messages to the next SMTP server on request. user-defined program, such as a spam filter, which can drop, re-address or edit
It can also run as a proxy server, forwarding (and optionally pre-processing) messages as they pass through. When running as a store-and-forward MTA incoming
e-mail as soon as it is received. It does not do any message routing, other messages are stored in a local spool directory, and then forwarded to the next
than to a local postmaster. Because of this functional simplicity it is SMTP server on request.
extremely easy to configure, typically only requiring the address of the
next-hop SMTP server to be put on the command line.
C++ source code is available for Linux, FreeBSD (etc) and Windows. Because of its functional simplicity E-MailRelay is easy to configure, typically
only requiring the address of the target SMTP server to be put on the command
line.
C++ source code is available for Linux, FreeBSD, MacOS X etc, and Windows.
Distribution is under the GNU General Public License. Distribution is under the GNU General Public License.
Quick start Quick start
----------- -----------
E-MailRelay can be built and installed from source using the ususal To run the program as a proxy use the "--as-proxy" command-line switch, followed by the
"./configure ; make ; make install" incantation. The program runs as an SMTP address of the target SMTP server. If you want to edit or filter e-mail as it passes
server daemon using the "emailrelay --as-server" command, and stored mail is through the proxy then specify your pre-processor program with the "--filter" switch.
forwarded to the next-hop server by running "emailrelay --as-client <isp-mail-server>:smtp". You can optionally change the listening port number using "--port" and the
spool directory using "--spool-dir".
The "--as-server" command is typically run automatically at boot time, using For example, to start up a local proxy which passes messages to some "addsig" script
the boot scripts under "/etc/init.d" or "/sbin/init.d", while the "--as-client" and then forwards them to an MTA running on "smarthost", use a command like this:
command is normally put into pppd's "ip-up" script ("/etc/ppp/ip-up")
in place of "sendmail -q".
The program can also run as a proxy server ("--as-proxy") so that e-mail emailrelay --as-proxy smarthost:smtp --filter $HOME/bin/addsig --spooldir $HOME/tmp
messages are forwarded immediately to the next-hop server -- usually the local
system's default MTA. This can be usefully combined with a mail pre-processor
program by using the "--filter" switch.
The program requires a writeable spool directory to store e-mail messages. To use E-MailRelay as a store-and-forward MTA use the "--as-server" switch
The directory defaults to "/usr/local/var/spool/emailrelay", but it to start the storage daemon in the background. And then trigger delivery of
can be changed by using the "--spool-dir" switch. spooled messages by running emailrelay with the "--as-client" switch, followed
by the address of the target SMTP server.
By default the server will try to listen on TCP port 25. If another SMTP For example, to start a storage daemon listening on port 10025 use a command
server is running then it will fail to start up, with a "cannot bind" error like this:
message. The port number can be changed by using the "--port" switch.
To test the program out without a full installation: emailrelay --as-server --port 10025 --spooldir $HOME/tmp
(1) run the server as "emailrelay --no-daemon --no-syslog --log --spool-dir ${HOME} --port 10025 &"
(2) reconfigure your e-mail client to use port 10025 rather than 25 ("smtp") And then to forward the spooled mail to "smarthost" run somthing like this:
(3) send some test messages to addressees on the Internet
(4) connect to the Internet emailrelay --as-client smarthost:smtp --spooldir $HOME/tmp
(5) forward the stored messages using "emailrelay --spool-dir ${HOME} --as-client <your-isp-smtp-host>:smtp"
(6) clean up with "killall emailrelay ; rm ${HOME}/emailrelay.*" By default E-MailRelay will reject connections from remote machines. To
allow connections from anywhere use the "--remote-clients" switch.
For more information on the command-line options refer to the reference guide
or run:
emailrelay --help --verbose
Documentation Documentation
------------- -------------
The following documentation is provided in the source distribution: The following documentation is provided:
* README -- this document * README -- this document
* COPYING -- the GNU General Public License * COPYING -- the GNU General Public License
* INSTALL -- build & install instructions (including the generic GNU text) * INSTALL -- build & install instructions (including the generic GNU text)
* AUTHORS -- authors, credits and additional copyrights * AUTHORS -- authors, credits and additional copyrights
* copyright -- main copyright and GPL reference * copyright -- main copyright and GPL reference
* doc/userguide.txt -- user guide * userguide.txt -- user guide
* doc/reference.txt -- reference document * reference.txt -- reference document
* ChangeLog -- change log for releases * ChangeLog -- change log for releases
Additional documents, including source-code documentation generated by Source code documentation will be generated when building from source if
doxygen (www.doxygen.org), is available in a separate package, "doxygen" is available.
"emailrelay-doc".
Configurations Configurations
-------------- --------------
@ -78,21 +81,23 @@ and ported to Windows 98 using:
Recent releases were developed on SuSE Linux 8.0 and Recent releases were developed on SuSE Linux 8.0 and
RedHat Linux 8.0 using: RedHat Linux 8.0 using:
* gcc 2.95.3 and 3.2 * gcc 2.95.3 and gcc 3.2
* autoconf 2.53 * autoconf 2.53
The code has also been built successfully on: The code has also been built successfully on:
* Windows NT 4.0
* MacOS X * MacOS X
* FreeBSD on Intel hardware * FreeBSD on Intel hardware
* Solaris 8, using gcc, on Sparc hardware
* Linux on Alpha hardware (Debian 2.2) * Linux on Alpha hardware (Debian 2.2)
* Linux on Sparc hardware * Linux on Sparc hardware
* Linux on RS6000 PPC hardware * Linux on RS6000 PPC hardware
* Solaris 8 using gcc on Sparc hardware
* Solaris 8 using WorkShop 5.0
* Linux using intel c++ 6.0
* Windows NT 4.0 using MSVC 6.0
Feedback Feedback
-------- --------
Please feel free to email the author at Please feel free to e-mail the author at
"mailto:graeme_walker@users.sourceforge.net". "mailto:graeme_walker@users.sourceforge.net".

View File

@ -73,18 +73,64 @@ AC_DEFUN([ACLOCAL_CHECK_LOCALTIME_R],
fi fi
]) ])
dnl gcc version dnl buggy ctime
dnl sunpro5 ctime + unistd.h doesnt compile -- fix with time.h first
dnl
AC_DEFUN([ACLOCAL_CHECK_BUGGY_CTIME],
[AC_CACHE_CHECK([for buggy ctime], aclocal_cv_buggy_ctime,
[
AC_TRY_COMPILE(
[#include <ctime>
#include <unistd.h>],
[] ,
aclocal_cv_buggy_ctime=no ,
aclocal_cv_buggy_ctime=yes )
])
if test $aclocal_cv_buggy_ctime = yes; then
AC_DEFINE(HAVE_BUGGY_CTIME,1,[Define if <ctime> requires <time.h>])
else
AC_DEFINE(HAVE_BUGGY_CTIME,0,[Define if <ctime> requires <time.h>])
fi
])
dnl compiler name and version
dnl used for -Ilib/<version> -- only needed for pre 3.0 gcc dnl used for -Ilib/<version> -- only needed for pre 3.0 gcc
dnl dnl
AC_DEFUN([ACLOCAL_COMPILER_VERSION], AC_DEFUN([ACLOCAL_COMPILER_VERSION],
[ [
changequote(<<,>>) changequote(<<,>>)
COMPILER_VERSION=`$CXX --version 2>/dev/null | sed q | sed 's/[^0-9 .]*//g;s/\./ /g;s/^ *//;s/ /./;s/ .*//;s/^/gcc/'` COMPILER_VERSION=`$CXX --version 2>/dev/null | sed q | sed 's/[^0-9 .]*//g;s/\./ /g;s/^ *//;s/ /./;s/ .*//;s/^/gcc/'`
if test -z "${COMPILER_VERSION}"
then
COMPILER_VERSION=`$CXX -V 2>&1 | sed q | grep WorkShop | sed 's/[^0-9]*//;s/[ \.].*//;s/^/sunpro/'`
fi
changequote([,]) changequote([,])
AC_SUBST(COMPILER_VERSION) AC_SUBST(COMPILER_VERSION)
]) ])
dnl fhs dnl enable-debug
dnl
AC_DEFUN([ENABLE_DEBUG],
[
if test "$enable_debug" = "yes"
then
AC_DEFINE(_DEBUG,1,[Define to enable extra debug messages at compile-time])
fi
])
dnl with-workshop
dnl
AC_DEFUN([WITH_WORKSHOP],
[
if test "$with_workshop" = "yes"
then
chmod +x lib/sunpro5/xar
AR="`pwd`/lib/sunpro5/xar --cxx \"$CXX\""
AC_SUBST(AR)
fi
])
dnl enable-fhs
dnl dnl
AC_DEFUN([ENABLE_FHS], AC_DEFUN([ENABLE_FHS],
[ [

50
aclocal.m4 vendored
View File

@ -86,18 +86,64 @@ AC_DEFUN([ACLOCAL_CHECK_LOCALTIME_R],
fi fi
]) ])
dnl gcc version dnl buggy ctime
dnl sunpro5 ctime + unistd.h doesnt compile -- fix with time.h first
dnl
AC_DEFUN([ACLOCAL_CHECK_BUGGY_CTIME],
[AC_CACHE_CHECK([for buggy ctime], aclocal_cv_buggy_ctime,
[
AC_TRY_COMPILE(
[#include <ctime>
#include <unistd.h>],
[] ,
aclocal_cv_buggy_ctime=no ,
aclocal_cv_buggy_ctime=yes )
])
if test $aclocal_cv_buggy_ctime = yes; then
AC_DEFINE(HAVE_BUGGY_CTIME,1,[Define if <ctime> requires <time.h>])
else
AC_DEFINE(HAVE_BUGGY_CTIME,0,[Define if <ctime> requires <time.h>])
fi
])
dnl compiler name and version
dnl used for -Ilib/<version> -- only needed for pre 3.0 gcc dnl used for -Ilib/<version> -- only needed for pre 3.0 gcc
dnl dnl
AC_DEFUN([ACLOCAL_COMPILER_VERSION], AC_DEFUN([ACLOCAL_COMPILER_VERSION],
[ [
changequote(<<,>>) changequote(<<,>>)
COMPILER_VERSION=`$CXX --version 2>/dev/null | sed q | sed 's/[^0-9 .]*//g;s/\./ /g;s/^ *//;s/ /./;s/ .*//;s/^/gcc/'` COMPILER_VERSION=`$CXX --version 2>/dev/null | sed q | sed 's/[^0-9 .]*//g;s/\./ /g;s/^ *//;s/ /./;s/ .*//;s/^/gcc/'`
if test -z "${COMPILER_VERSION}"
then
COMPILER_VERSION=`$CXX -V 2>&1 | sed q | grep WorkShop | sed 's/[^0-9]*//;s/[ \.].*//;s/^/sunpro/'`
fi
changequote([,]) changequote([,])
AC_SUBST(COMPILER_VERSION) AC_SUBST(COMPILER_VERSION)
]) ])
dnl fhs dnl enable-debug
dnl
AC_DEFUN([ENABLE_DEBUG],
[
if test "$enable_debug" = "yes"
then
AC_DEFINE(_DEBUG,1,[Define to enable extra debug messages at compile-time])
fi
])
dnl with-workshop
dnl
AC_DEFUN([WITH_WORKSHOP],
[
if test "$with_workshop" = "yes"
then
chmod +x lib/sunpro5/xar
AR="`pwd`/lib/sunpro5/xar --cxx \"$CXX\""
AC_SUBST(AR)
fi
])
dnl enable-fhs
dnl dnl
AC_DEFUN([ENABLE_FHS], AC_DEFUN([ENABLE_FHS],
[ [

View File

@ -1,21 +1,22 @@
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> ## Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# ##
# This program is free software; you can redistribute it and/or ## This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License ## modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either ## as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later ## version 2 of the License, or (at your option) any later
# version. ## version.
# ##
# This program is distributed in the hope that it will be useful, ## This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of ## but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. ## GNU General Public License for more details.
# ##
# You should have received a copy of the GNU General Public License ## You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software ## along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# ##
#
EXTRA_DIST = emailrelay-doxygen-filter.sh_ emailrelay-test.sh_ emailrelay-soak.sh_ emailrelay.sh_ txt2html.sh_ txt2mu.sh_ mu2html.sh_ expand.sh_ emailrelay-notify.sh_ emailrelay-resubmit.sh_ emailrelay-deliver.sh_ emailrelay-process.sh_ EXTRA_DIST = emailrelay-doxygen-filter.sh_ emailrelay-test.sh_ emailrelay-soak.sh_ emailrelay.sh_ txt2html.sh_ txt2mu.sh_ mu2html.sh_ expand.sh_ emailrelay-notify.sh_ emailrelay-resubmit.sh_ emailrelay-deliver.sh_ emailrelay-process.sh_

View File

@ -14,24 +14,8 @@
@SET_MAKE@ @SET_MAKE@
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> #
#
# 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.
#
SHELL = @SHELL@ SHELL = @SHELL@
srcdir = @srcdir@ srcdir = @srcdir@

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> # Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> # Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> # Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> # Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> # Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> # Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> # Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
@ -31,18 +31,21 @@
# Once all the servers have been killed the separate log files are # Once all the servers have been killed the separate log files are
# concatenated into the summary log file "/tmp/emailrelay-test.out". # concatenated into the summary log file "/tmp/emailrelay-test.out".
# #
# If this test takes more than a second or two then it has failed. # If this test takes more a minute then it has failed.
#
# usage: emailrelay-test.sh [-v] [-d] [<exe-dir>]
# #
# configuration # configuration
# #
exe_dir="../src/main" use_valgrind="0" ; if test "${1}" = "-v" ; then use_valgrind="1" ; shift ; fi
if test "${1}" != "" ; then exe_dir="${1}" ; fi debug="" ; if test "${1}" = "-d" ; then debug="--debug" ; shift ; fi
exe_dir="../src/main" ; if test "${1}" != "" ; then exe_dir="${1}" ; fi
exe="${exe_dir}/emailrelay" exe="${exe_dir}/emailrelay"
poke="${exe_dir}/emailrelay-poke" poke="${exe_dir}/emailrelay-poke"
null_filter="/bin/touch" null_filter="/bin/touch"
content_file="/etc/services" content_file="/etc/services"
pp="1001" # port-prefix pp="201" # port-prefix
# configuration fallback # configuration fallback
# #
@ -56,16 +59,32 @@ fi
base_dir="/tmp/`basename $0`.$$.tmp" base_dir="/tmp/`basename $0`.$$.tmp"
summary_log="/tmp/`basename $0`.out" summary_log="/tmp/`basename $0`.out"
exit_code="1" exit_code="1"
watchdog_pid=""
export MALLOC_CHECK_="2"
ulimit -c 1000000
if test "${use_valgrind}" -eq 1
then
exe="valgrind --logfile=${base_dir}/valgrind --trace-children=yes --num-callers=40 --leak-check=yes ${exe} --no-daemon"
fi
Cleanup() Cleanup()
{ {
${poke} ${pp}11 terminate
${poke} ${pp}12 terminate
${poke} ${pp}13 terminate
${poke} ${pp}14 terminate
${poke} ${pp}15 terminate
${poke} ${pp}16 terminate
sleep 2
kill `cat ${base_dir}/pid-* 2>/dev/null` 2>/dev/null kill `cat ${base_dir}/pid-* 2>/dev/null` 2>/dev/null
if test -d ${base_dir} if test -d ${base_dir}
then then
grep "MailRelay-Reason" ${base_dir}/*/*envelope*bad > "${summary_log}" 2>/dev/null grep "MailRelay-Reason" ${base_dir}/*/*envelope*bad > "${summary_log}" 2>/dev/null
grep "." ${base_dir}/log-? >> "${summary_log}" 2>/dev/null grep "." ${base_dir}/log-? >> "${summary_log}" 2>/dev/null
ls -lR ${base_dir} >> "${summary_log}" 2>/dev/null ls -lR ${base_dir} >> "${summary_log}" 2>/dev/null
diff -w ${base_dir}/store-4/*content "${content_file}" >> "${summary_log}" 2>/dev/null rm -rf ${base_dir} 2>/dev/null
fi fi
} }
@ -78,14 +97,16 @@ Trap()
RunServer() RunServer()
{ {
port_="${1}" port_="${1}"
spool_="${2}" admin_port_="${2}"
log_="${3}" spool_="${3}"
pidfile_="${4}" log_="${4}"
extra_="${5}" pidfile_="${5}"
extra_="${6}"
mkdir -p ${base_dir}/${spool_} mkdir -p ${base_dir}/${spool_}
${exe} --log --no-syslog --port ${port_} --spool-dir ${base_dir}/${spool_} \ ${exe} ${debug} --log --verbose --no-syslog --port ${port_} --spool-dir ${base_dir}/${spool_} \
--pid-file ${base_dir}/${pidfile_} ${extra_} 2> ${base_dir}/${log_} --admin ${admin_port_} --admin-terminate \
--pid-file ${base_dir}/${pidfile_} ${extra_} 2> ${base_dir}/${log_} &
} }
RunClient() RunClient()
@ -137,18 +158,21 @@ CrLf()
CheckResults() CheckResults()
{ {
if test -f ${base_dir}/store-4/*.envelope -a -f ${base_dir}/store-4/*.content store="${1}"
if test "`ls -1 ${base_dir}/${store}/emailrelay.*.content 2>/dev/null | wc -l`" -eq 2 -a \
"`ls -1 ${base_dir}/${store}/emailrelay.*.envelope 2>/dev/null | wc -l`" -eq 2
then then
exit_code="0" exit_code="0"
echo `basename $0`: succeeded echo `basename $0`: succeeded
else else
echo `basename $0`: failed: see ${summary_log} >&2 false
fi fi
} }
StartTimer() StartWatchdog()
{ {
( sleep 30 ; Cleanup ) & sleep 10 && kill `cat ${base_dir}/pid-* 2>/dev/null` 2>/dev/null &
watchdog_pid=$!
} }
CreateMessages() CreateMessages()
@ -156,6 +180,8 @@ CreateMessages()
mkdir -p ${base_dir}/store-1 mkdir -p ${base_dir}/store-1
Content | CrLf > ${base_dir}/store-1/emailrelay.0.1.content Content | CrLf > ${base_dir}/store-1/emailrelay.0.1.content
Envelope | CrLf > ${base_dir}/store-1/emailrelay.0.1.envelope Envelope | CrLf > ${base_dir}/store-1/emailrelay.0.1.envelope
Content | CrLf > ${base_dir}/store-1/emailrelay.0.2.content
Envelope | CrLf > ${base_dir}/store-1/emailrelay.0.2.envelope
} }
CreateAuth() CreateAuth()
@ -180,17 +206,48 @@ CreateAuth()
echo "CRAM-MD5 client joe ${key}" >> ${file} echo "CRAM-MD5 client joe ${key}" >> ${file}
} }
CreateFilter()
{
cat <<EOF | sed 's/^_//' > ${base_dir}/filter.sh
_#!/bin/sh
_# filter.sh
_tmp="/tmp/`basename $0`.\$\$.tmp"
_tr 'a-z' 'A-Z' < \$1 > \$tmp && mv \$tmp \$1
_exit 0
EOF
chmod +x ${base_dir}/filter.sh
}
trap "Trap ; exit" 1 2 3 13 15 trap "Trap ; exit" 1 2 3 13 15
trap "Trap 0 ; exit" 0 trap "Trap 0 ; exit" 0
StartTimer #StartWatchdog
CreateAuth CreateAuth
RunServer ${pp}1 store-2 log-1 pid-1 CreateFilter
RunServer ${pp}2 store-2 log-2 pid-2 "--admin ${pp}9 --forward-to localhost:${pp}3 --client-auth ${base_dir}/client-joe.auth"
RunServer ${pp}3 store-3 log-3 pid-3 "--immediate --forward-to localhost:${pp}4 --filter ${null_filter} --client-auth ${base_dir}/client-fred.auth --server-auth ${base_dir}/server.auth" RunServer ${pp}01 ${pp}10 store-2 log-1 pid-1
RunServer ${pp}4 store-4 log-4 pid-4 "--server-auth ${base_dir}/server.auth" RunServer ${pp}02 ${pp}12 store-2 log-2 pid-2 "--forward-to localhost:${pp}03 --client-auth ${base_dir}/client-joe.auth"
CreateMessages RunServer ${pp}03 ${pp}13 store-3 log-3 pid-3 "--immediate --forward-to localhost:${pp}04 --filter ${null_filter} --client-auth ${base_dir}/client-fred.auth --server-auth ${base_dir}/server.auth"
RunClient localhost:${pp}1 store-1 log-c pid-5 RunServer ${pp}04 ${pp}14 store-4 log-4 pid-4 "--server-auth ${base_dir}/server.auth"
RunPoke ${pp}9 log-p RunServer ${pp}05 ${pp}15 store-4 log-5 pid-5 "--poll 1 --forward-to localhost:${pp}06"
CheckResults RunServer ${pp}06 ${pp}16 store-6 log-6 pid-6 "--filter ${base_dir}/filter.sh"
CreateMessages
RunClient localhost:${pp}01 store-1 log-c pid-5
RunPoke ${pp}12 log-p
for i in 0 1 2 3 4 5 6 7 8 9
do
sleep 2
CheckResults store-6
if test $? -eq 0 ; then break ; fi
done
if test "${watchdog_pid}" != ""
then
kill "${watchdog_pid}"
fi
if test ${exit_code} -ne 0
then
echo `basename $0`: failed: see ${summary_log} >&2
fi

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> # Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
@ -18,7 +18,7 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# #
# === # ===
# #
# emailrelay # emailrelay
# #
# A shell-script wrapper for E-MailRelay designed for # A shell-script wrapper for E-MailRelay designed for

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> # Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> # Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> # Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> # Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or

View File

@ -1,5 +1,8 @@
/* config.h.in. Generated from configure.ac by autoheader. */ /* config.h.in. Generated from configure.ac by autoheader. */
/* Define if <ctime> requires <time.h> */
#undef HAVE_BUGGY_CTIME
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'. /* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
*/ */
#undef HAVE_DIRENT_H #undef HAVE_DIRENT_H
@ -83,3 +86,6 @@
/* Version number of package */ /* Version number of package */
#undef VERSION #undef VERSION
/* Define to enable extra debug messages at compile-time */
#undef _DEBUG

108
configure vendored
View File

@ -837,9 +837,15 @@ Optional Features:
--enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--disable-dependency-tracking Speeds up one-time builds --disable-dependency-tracking Speeds up one-time builds
--enable-dependency-tracking Do not reject slow dependency extractors --enable-dependency-tracking Do not reject slow dependency extractors
--enable-debug enable extra debug messages at compile-time
--enable-fhs force FHS-compliant directories, ignoring --prefix --enable-fhs force FHS-compliant directories, ignoring --prefix
etc etc
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--with-workshop use Sun WorkShop 'CC -xar' as the 'ar' tool
Some influential environment variables: Some influential environment variables:
CC C compiler command CC C compiler command
CFLAGS C compiler flags CFLAGS C compiler flags
@ -1453,7 +1459,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE=emailrelay PACKAGE=emailrelay
VERSION=1.0.2 VERSION=1.1
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
@ -3269,6 +3275,10 @@ fi
COMPILER_VERSION=`$CXX --version 2>/dev/null | sed q | sed 's/[^0-9 .]*//g;s/\./ /g;s/^ *//;s/ /./;s/ .*//;s/^/gcc/'` COMPILER_VERSION=`$CXX --version 2>/dev/null | sed q | sed 's/[^0-9 .]*//g;s/\./ /g;s/^ *//;s/ /./;s/ .*//;s/^/gcc/'`
if test -z "${COMPILER_VERSION}"
then
COMPILER_VERSION=`$CXX -V 2>&1 | sed q | grep WorkShop | sed 's/[^0-9]*//;s/[ \.].*//;s/^/sunpro/'`
fi
@ -4611,6 +4621,68 @@ _ACEOF
fi fi
echo "$as_me:$LINENO: checking for buggy ctime" >&5
echo $ECHO_N "checking for buggy ctime... $ECHO_C" >&6
if test "${aclocal_cv_buggy_ctime+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
#include "confdefs.h"
#include <ctime>
#include <unistd.h>
#ifdef F77_DUMMY_MAIN
# ifdef __cplusplus
extern "C"
# endif
int F77_DUMMY_MAIN() { return 1; }
#endif
int
main ()
{
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
aclocal_cv_buggy_ctime=no
else
echo "$as_me: failed program was:" >&5
cat conftest.$ac_ext >&5
aclocal_cv_buggy_ctime=yes
fi
rm -f conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $aclocal_cv_buggy_ctime" >&5
echo "${ECHO_T}$aclocal_cv_buggy_ctime" >&6
if test $aclocal_cv_buggy_ctime = yes; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_BUGGY_CTIME 1
_ACEOF
else
cat >>confdefs.h <<\_ACEOF
#define HAVE_BUGGY_CTIME 0
_ACEOF
fi
echo "$as_me:$LINENO: checking for gmtime_r" >&5 echo "$as_me:$LINENO: checking for gmtime_r" >&5
echo $ECHO_N "checking for gmtime_r... $ECHO_C" >&6 echo $ECHO_N "checking for gmtime_r... $ECHO_C" >&6
if test "${aclocal_cv_gmtime_r+set}" = set; then if test "${aclocal_cv_gmtime_r+set}" = set; then
@ -4734,6 +4806,37 @@ _ACEOF
fi fi
# Check whether --enable-debug or --disable-debug was given.
if test "${enable_debug+set}" = set; then
enableval="$enable_debug"
fi;
if test "$enable_debug" = "yes"
then
cat >>confdefs.h <<\_ACEOF
#define _DEBUG 1
_ACEOF
fi
# Check whether --with-workshop or --without-workshop was given.
if test "${with_workshop+set}" = set; then
withval="$with_workshop"
fi;
if test "$with_workshop" = "yes"
then
chmod +x lib/sunpro5/xar
AR="`pwd`/lib/sunpro5/xar --cxx \"$CXX\""
fi
# Check whether --enable-fhs or --disable-fhs was given. # Check whether --enable-fhs or --disable-fhs was given.
if test "${enable_fhs+set}" = set; then if test "${enable_fhs+set}" = set; then
enableval="$enable_fhs" enableval="$enable_fhs"
@ -4791,7 +4894,7 @@ fi
SET_MAKE="" SET_MAKE=""
ac_config_files="$ac_config_files Makefile src/Makefile src/glib/Makefile src/gnet/Makefile src/gsmtp/Makefile src/main/Makefile src/win32/Makefile lib/Makefile lib/gcc2.95/Makefile lib/msvc6.0/Makefile bin/Makefile doc/Makefile" ac_config_files="$ac_config_files Makefile src/Makefile src/glib/Makefile src/gnet/Makefile src/gsmtp/Makefile src/main/Makefile src/win32/Makefile lib/Makefile lib/gcc2.95/Makefile lib/msvc6.0/Makefile lib/sunpro5/Makefile bin/Makefile doc/Makefile"
cat >confcache <<\_ACEOF cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure # This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure # tests run on this system so they can be shared between configure
@ -5290,6 +5393,7 @@ do
"lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; "lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
"lib/gcc2.95/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/gcc2.95/Makefile" ;; "lib/gcc2.95/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/gcc2.95/Makefile" ;;
"lib/msvc6.0/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/msvc6.0/Makefile" ;; "lib/msvc6.0/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/msvc6.0/Makefile" ;;
"lib/sunpro5/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/sunpro5/Makefile" ;;
"bin/Makefile" ) CONFIG_FILES="$CONFIG_FILES bin/Makefile" ;; "bin/Makefile" ) CONFIG_FILES="$CONFIG_FILES bin/Makefile" ;;
"doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
"depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;

22
configure.ac Normal file → Executable file
View File

@ -1,4 +1,3 @@
dnl
dnl Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> dnl Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
dnl dnl
dnl This program is free software; you can redistribute it and/or dnl This program is free software; you can redistribute it and/or
@ -19,9 +18,10 @@ dnl
dnl === dnl ===
dnl dnl
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
dnl
AC_INIT(src/gsmtp/gsmtp.h) AC_INIT(src/gsmtp/gsmtp.h)
AM_INIT_AUTOMAKE(emailrelay,1.0.2) AM_INIT_AUTOMAKE(emailrelay,1.1)
AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(config.h)
dnl === dnl ===
@ -57,11 +57,24 @@ AC_CHECK_HEADERS(sys/time.h)
AC_CHECK_FUNCS(glob) AC_CHECK_FUNCS(glob)
AC_LANG_CPLUSPLUS AC_LANG_CPLUSPLUS
ACLOCAL_TYPE_SOCKLEN_T ACLOCAL_TYPE_SOCKLEN_T
ACLOCAL_CHECK_BUGGY_CTIME
ACLOCAL_CHECK_GMTIME_R ACLOCAL_CHECK_GMTIME_R
ACLOCAL_CHECK_LOCALTIME_R ACLOCAL_CHECK_LOCALTIME_R
dnl === dnl ===
dnl directory tweaking... dnl "--enable-debug"
dnl
AC_ARG_ENABLE(debug,AC_HELP_STRING([--enable-debug],[enable extra debug messages at compile-time]))
ENABLE_DEBUG
dnl ===
dnl "--with-workshop"
dnl
AC_ARG_WITH(workshop,AC_HELP_STRING([--with-workshop],[use Sun WorkShop 'CC -xar' as the 'ar' tool]))
WITH_WORKSHOP
dnl ===
dnl directory tweaking and "--enable-fhs" ...
dnl dnl
dnl not AC_PREFIX_DEFAULT([/usr]) dnl not AC_PREFIX_DEFAULT([/usr])
AC_ARG_ENABLE(fhs,AC_HELP_STRING([--enable-fhs],[force FHS-compliant directories, ignoring --prefix etc])) AC_ARG_ENABLE(fhs,AC_HELP_STRING([--enable-fhs],[force FHS-compliant directories, ignoring --prefix etc]))
@ -83,10 +96,11 @@ ENABLE_FHS
dnl === dnl ===
dnl attempt to fix recursive makes where make is gmake -- may break something else dnl attempt to fix recursive makes where make is gmake -- may break something else
dnl
SET_MAKE="" SET_MAKE=""
dnl === dnl ===
dnl generate files... dnl generate files...
dnl dnl
AC_OUTPUT(Makefile src/Makefile src/glib/Makefile src/gnet/Makefile src/gsmtp/Makefile src/main/Makefile src/win32/Makefile lib/Makefile lib/gcc2.95/Makefile lib/msvc6.0/Makefile bin/Makefile doc/Makefile) AC_OUTPUT(Makefile src/Makefile src/glib/Makefile src/gnet/Makefile src/gsmtp/Makefile src/main/Makefile src/win32/Makefile lib/Makefile lib/gcc2.95/Makefile lib/msvc6.0/Makefile lib/sunpro5/Makefile bin/Makefile doc/Makefile)

View File

@ -1,21 +1,22 @@
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> ## Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# ##
# This program is free software; you can redistribute it and/or ## This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License ## modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either ## as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later ## version 2 of the License, or (at your option) any later
# version. ## version.
# ##
# This program is distributed in the hope that it will be useful, ## This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of ## but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. ## GNU General Public License for more details.
# ##
# You should have received a copy of the GNU General Public License ## You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software ## along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# ##
#
stylesheet=emailrelay.css stylesheet=emailrelay.css
txt_files=developer.txt reference.txt userguide.txt windows.txt txt_files=developer.txt reference.txt userguide.txt windows.txt

View File

@ -14,24 +14,8 @@
@SET_MAKE@ @SET_MAKE@
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> #
#
# 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.
#
SHELL = @SHELL@ SHELL = @SHELL@
srcdir = @srcdir@ srcdir = @srcdir@

View File

@ -137,12 +137,6 @@ Sometimes only small parts of the implementation are system-specific. In
these cases there are three source files per header. For example, "gsocket.cpp", these cases there are three source files per header. For example, "gsocket.cpp",
"gsocket_win32.cpp" and "gsocket_unix.cpp" in the "src/gnet" directory. "gsocket_win32.cpp" and "gsocket_unix.cpp" in the "src/gnet" directory.
Porting to other compilers
--------------------------
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" and "src/gnet/gnet.h".
Compile-time features Compile-time features
--------------------- ---------------------
The following features are available to source-code hackers: The following features are available to source-code hackers:
@ -174,7 +168,7 @@ directory.
Style Style
----- -----
The commenting style used in header files is compatible with doxygen if passed The commenting style used in header files is compatible with doxygen if passed
through the simple awk-based preprocessor "emailrelay-doxygen-filter.sh". A through the simple awk-based pre-processor "emailrelay-doxygen-filter.sh". A
"make" in the "doc" directory will run doxygen if it is found on your path. "make" in the "doc" directory will run doxygen if it is found on your path.
Patterns Patterns
@ -183,7 +177,7 @@ Gang-of-four Design Patterns (ISBN 0-201-63361-2):
+ Factory method + Factory method
- GNet::EventSources::create() - GNet::EventLoop::create()
- GNet::Server::newPeer() - GNet::Server::newPeer()
- GSmtp::MessageStore::newMessage() - GSmtp::MessageStore::newMessage()
@ -197,8 +191,7 @@ Gang-of-four Design Patterns (ISBN 0-201-63361-2):
- G::LogOutput - G::LogOutput
- GGui::ApplicationInstance - GGui::ApplicationInstance
- GNet::EventSources - GNet::EventLoop
- GSmtp::MessageStore
+ Facade + Facade
@ -226,19 +219,18 @@ Lakos' Large Scale C++ Software Design patterns (ISBN 0-201-63362-0):
- GSmtp::ProtocolMessage - GSmtp::ProtocolMessage
- GSmtp::ServerProtocol::Sender - GSmtp::ServerProtocol::Sender
- GSmtp::ClientProtocol::Sender - GSmtp::ClientProtocol::Sender
- GSmtp::ClientProtocol::Callback
- GSmtp::ProtocolMessage::Callback
- GSmtp::Client::ClientCallback
Meyer's More Effective C++ patterns (ISBN 0-201-63371-X): Meyer's More Effective C++ patterns (ISBN 0-201-63371-X):
+ Reference counting (Item 29) + Reference counting (Item 29)
- GSmtp::MessageStore::Iterator - GSmtp::MessageStore::Iterator
- G::Slot0
+ Lazy evaluation (Item 17) + Lazy evaluation (Item 17)
- GNet::EventHandlerList::list() - GNet::EventHandlerList::list()
- G::Date::weekday()
Other patterns: Other patterns:
@ -246,6 +238,15 @@ Other patterns:
- GSmtp::ServerProtocol - GSmtp::ServerProtocol
+ Slot/signal
- G::Slot0
- G::Signal0
+ Exception-safe assignment using swap
- G::Slot0
Idioms Idioms
------ ------
The "<<=" operator defined in "src/glib/gmemory.h" is used idiomatically The "<<=" operator defined in "src/glib/gmemory.h" is used idiomatically
@ -253,4 +254,5 @@ to reassign a std::auto_ptr<>.
Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>. All rights reserved. Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>. All rights reserved.

View File

@ -1,4 +1,3 @@
.\"
.\" Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> .\" Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
.\" .\"
.\" This program is free software; you can redistribute it and/or .\" This program is free software; you can redistribute it and/or

View File

@ -1,4 +1,3 @@
.\"
.\" Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> .\" Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
.\" .\"
.\" This program is free software; you can redistribute it and/or .\" This program is free software; you can redistribute it and/or

View File

@ -1,4 +1,3 @@
.\"
.\" Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> .\" Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
.\" .\"
.\" This program is free software; you can redistribute it and/or .\" This program is free software; you can redistribute it and/or
@ -29,7 +28,7 @@ emailrelay-submit \- a submission utility for E-MailRelay
.RI [ to-address \ ...] .RI [ to-address \ ...]
.SH DESCRIPTION .SH DESCRIPTION
.I emailrelay-submit .I emailrelay-submit
is a utility which reads an RFC822 email message from the standard is a utility which reads an RFC822 e-mail message from the standard
input, with SMTP envelope recipient addresses passed on the input, with SMTP envelope recipient addresses passed on the
command-line, and writes it into the command-line, and writes it into the
.B E-MailRelay .B E-MailRelay

View File

@ -1,4 +1,3 @@
.\"
.\" Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> .\" Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
.\" .\"
.\" This program is free software; you can redistribute it and/or .\" This program is free software; you can redistribute it and/or
@ -64,7 +63,7 @@ Runs as a client, forwarding spooled mail to <host>: equivalent to \fI--log\fR \
Runs as a proxy: equivalent to \fI--log\fR \fI--close-stderr\fR \fI--immediate\fR \fI--forward-to\fR. Runs as a proxy: equivalent to \fI--log\fR \fI--close-stderr\fR \fI--immediate\fR \fI--forward-to\fR.
.TP .TP
.B \-d,--as-server .B \-d,--as-server
Runs as a server: equivalent to \fI--log\fR \fI--close-stderr\fR. Runs as a server: equivalent to \fI--log\fR \fI--close-stderr\fR \fI--postmaster\fR.
.TP .TP
.B \-C,--client-auth \fIfile\fR .B \-C,--client-auth \fIfile\fR
Enables authentication with remote server, using the given secrets file. Enables authentication with remote server, using the given secrets file.
@ -120,9 +119,15 @@ Disables syslog output.
.B \-i,--pid-file \fIpid-file\fR .B \-i,--pid-file \fIpid-file\fR
Records the daemon process-id in the given file. Records the daemon process-id in the given file.
.TP .TP
.B \-O,--poll \fIperiod\fR
Enables polling with the specified period (requires \fI--forward-to\fR).
.TP
.B \-p,--port \fIport\fR .B \-p,--port \fIport\fR
Specifies the smtp listening port number. Specifies the smtp listening port number.
.TP .TP
.B \-P,--postmaster
Deliver to postmaster and reject all other local mailbox addresses.
.TP
.B \-r,--remote-clients .B \-r,--remote-clients
Allows remote clients to connect. Allows remote clients to connect.
.TP .TP

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -11,7 +11,7 @@
<li><a class="a-href" href="readme.html">Readme</a></li> <li><a class="a-href" href="readme.html">Readme</a></li>
<li><a class="a-href" href="changelog.html">Change log</a></li> <li><a class="a-href" href="changelog.html">Change log</a></li>
<li><a class="a-href" href="userguide.html">User guide</a></li> <li><a class="a-href" href="userguide.html">User guide</a></li>
<li><a class="a-href" href="reference.html">Reference manual</a></li> <li><a class="a-href" href="reference.html">Reference</a></li>
<li><a class="a-href" href="windows.html">Windows installation guide</a></li> <li><a class="a-href" href="windows.html">Windows installation guide</a></li>
<li><a class="a-href" href="developer.html">Notes for developers</a></li> <li><a class="a-href" href="developer.html">Notes for developers</a></li>
<li><a class="a-href" href="doxygen/index.html">Source code documentation</a> (generated by <a class="a-href" href="http://www.doxygen.org">doxygen</a>, if available)</li> <li><a class="a-href" href="doxygen/index.html">Source code documentation</a> (generated by <a class="a-href" href="http://www.doxygen.org">doxygen</a>, if available)</li>

View File

@ -23,7 +23,7 @@ where <switch> is:
Runs as a proxy: equivalent to "--log --close-stderr --immediate --forward-to". Runs as a proxy: equivalent to "--log --close-stderr --immediate --forward-to".
# --as-server (-d) # --as-server (-d)
Runs as a server: equivalent to "--log --close-stderr". Runs as a server: equivalent to "--log --close-stderr --postmaster".
# --client-auth (-C) # --client-auth (-C)
Enables authentication with remote server, using the given secrets file. Enables authentication with remote server, using the given secrets file.
@ -79,9 +79,15 @@ where <switch> is:
# --pid-file (-i) # --pid-file (-i)
Records the daemon process-id in the given file. Records the daemon process-id in the given file.
# --poll (-O)
Enables polling with the specified period (requires --forward-to).
# --port (-p) # --port (-p)
Specifies the smtp listening port number. Specifies the smtp listening port number.
# --postmaster (-P)
Deliver to postmaster and reject all other local mailbox addresses.
# --remote-clients (-r) # --remote-clients (-r)
Allows remote clients to connect. Allows remote clients to connect.
@ -106,11 +112,14 @@ where <switch> is:
# --version (-V) # --version (-V)
Displays version information and exits. Displays version information and exits.
Under Windows there are a few differences. Use "--help --verbose"
to see the complete list.
If no command-line switches are supplied at all then the default If no command-line switches are supplied at all then the default
behaviour is: behaviour is:
* to run as a daemon, detached from the terminal * to run as a daemon, detached from the terminal
* listen on the standard SMTP port (25) * listen on the standard SMTP port (25)
* store e-mail messages in "/usr/local/var/spool/emailrelay" * store e-mail messages in "/usr/local/var/spool/emailrelay" or "/var/spool/emailrelay"
* reject connections from remote clients * reject connections from remote clients
* disable the administration interface * disable the administration interface
* generate no logging or diagnostic messages * generate no logging or diagnostic messages
@ -121,7 +130,7 @@ the standard error stream is closed.
To foward spooled messages to the ISP the command-line switch "--as-client" To foward spooled messages to the ISP the command-line switch "--as-client"
is provided to run the program... is provided to run the program...
* in foreground, exiting when all spooled mail has been processed * in foreground, exiting when all spooled mail has been processed
* forwarding spooled mail from "/usr/local/var/spool/emailrelay" * forwarding spooled mail from "/usr/local/var/spool/emailrelay" or "/var/spool/emailrelay"
* without listening on any port * without listening on any port
* with error, warning and information messages sent to stderr * with error, warning and information messages sent to stderr
* without using syslog * without using syslog
@ -134,9 +143,9 @@ file contains parameters relevant to the SMTP dialogue, and the content file
contains the RFC822 headers and body text. contains the RFC822 headers and body text.
The filenames used in the message store have a prefix of "emailrelay", followed The filenames used in the message store have a prefix of "emailrelay", followed
by a process-id and sequence number, followed by "envelope" or "content". The by a process-id, timestamp and sequence number, followed by "envelope" or
envelope files then have an additional suffix to implement a simple locking "content". The envelope files then have an additional suffix to implement a
scheme. simple locking scheme.
The envelope suffixes are: The envelope suffixes are:
* ".new" -- while the envelope is first being written * ".new" -- while the envelope is first being written
@ -159,18 +168,16 @@ SMTP issues
# Local delivery: # Local delivery:
Recipient addresses like "postmaster", "postmaster@localhost" and "postmaster@fqdn" In server mode (ie. with "--postmaster") recipient addresses like "postmaster",
(where "fqdn" is the host's fully qualified domain name) are treated as the local "postmaster@localhost" and "postmaster@fqdn" (where "fqdn" is the host's fully
postmaster, resulting in local delivery rather than mail forwarding. qualified domain name) are treated as the local postmaster, resulting in local
delivery rather than mail forwarding. Recipient addresses other than "postmaster"
Recipient addresses (other than "postmaster" addresses) with no "at" sign (@) or addresses with no "at" sign (@) or ending in "@localhost" will be rejected at the
ending in "@localhost" will be rejected at the time the message is submitted by the time the message is submitted by the client.
e-mail front-end. This is in line with E-MailRelay's intended purpose as a simple
mail relay, rather than a fully-fledged routing MTA.
Delivery of mail to a local "postmaster" is a feature of E-MailRelay which is Delivery of mail to a local "postmaster" is a feature of E-MailRelay which is
provided for completeness and for comformance to the SMTP specification. provided for completeness and for comformance to the SMTP specification. But
Note that the E-MailRelay daemon does not actually deliver mail to the postmaster note that the E-MailRelay daemon does not actually deliver mail to the postmaster
mailbox. All it does is create an envelope and content file in the spool mailbox. All it does is create an envelope and content file in the spool
directory with a ".local" suffix. Some external system, such as a shell directory with a ".local" suffix. Some external system, such as a shell
script run from cron calling "procmail", should be used to process the script run from cron calling "procmail", should be used to process the
@ -192,94 +199,43 @@ SMTP issues
re-encode 8-bit messages into 7-bit messages if the next-hop server re-encode 8-bit messages into 7-bit messages if the next-hop server
does not. does not.
Address validation
------------------
An address supplied to the SMTP commands "RCPT" and "VRFY" is normally accepted
if it contains an at sign, or if it is some sort of local "postmaster" address
(as described above). However, this behaviour can be modified by using an external
verifier program, using the "--verifier" command-line switch.
The verifier program is passed a command-line containing the full address, the
user-name part of the address, the host-name part, the local host's fully
qualified domain name, the current "MAIL" command's "FROM:" address or the
empty string for the "VRFY" command, the IP address of the client connection,
the authentication mechanism used by the client ("NONE" if trusted), and either
the authentication name or the fourth field from authentication secrets file if
a trusted IP address.
For valid local mailbox addresses the verifier is expected to write two lines to
the standard output -- the full name associated with the mailbox, and the
canonical mailbox name -- and then exit with a value of zero. For valid non-local
addresses the first line of output should be empty, the second line should be
copied from the first command-line argument, and the exit value should be one.
For invalid addresses the exit value should be greater than one, and anything
written to the standard output is taken as the failure reason.
(Only the few few thousand characters are read from the verifier's standard
output stream; any more is thrown away.)
In this simple example script all addresses are accepted as long as they contain
an at sign. This has the effect of removing the normal "postmaster" functionality,
which is in any case not very useful when running in proxy mode:
#!/bin/sh
# verifier.sh
# An address verifier script for E-MailRelay.
address="${1}"
user="${2}"
host="${3}"
if test "${address}" != "${user}@${host}" ; then exit 2 ; fi
echo "${address}"
echo "${address}" # again
exit 1 # accept
As another example, the following address verifier script accepts all recipient
addresses by default, but rejects remote addresses if the client has bypassed
authentication by connecting on a trusted IP address:
#!/bin/sh
# verifier.sh
# An address verifier script for E-MailRelay.
host="$3"
local_domain="$4"
auth_mechanism="$7"
if test "${auth_mechanism}" = "NONE" -a "${host}" != "${local_domain}"
then
echo "cannot relay without authentication"
exit 2 # reject the recipient address
fi
echo "${address}"
echo "${address}" # again
exit 1 # accept the recipient address
Administration interface Administration interface
------------------------ ------------------------
If enabled, the server will provide a network interface for performing If enabled with the "--admin" command line switch, the E-MailRelay server will
administration tasks. This is a simple command-line interface which is provide a network interface for performing administration tasks. This is a
compatible with "telnet". simple command-line interface which is compatible with "telnet":
Currently the only supported commands are "flush" and "info". The "flush" command $ emailrelay --as-server --port 125 --forward-to localhost:25 --admin 10026
is used to forward spooled mail to the configured next-hop SMTP server. The $ telnet localhost 10026
next-hop server address must have been defined on the "emailrelay" command E-MailRelay> help
line at start-up using the "--forward-to" switch; it cannot be specified through E-MailRelay> quit
the administration interface.
The "flush" command allows you to run a single process which combines the The "flush" command is used to get the E-MailRelay server to forward spooled
functionality of storage daemon and forwarding client. This might be useful mail to the next SMTP server, as an alternative to running "emailrelay --as-client"
in systems which are low on memory: the memory footprint of "telnet" or as a separate process. In proxy mode it is a way of getting the proxy
"emailrelay-poke" will be much smaller than "emailrelay --as-client". server to scan the spool-directory for new messages.
The utility program "emailrelay-poke" can be used to issue the "flush"
command to an E-MailRelay server. For example:
$ emailrelay --as-server --port 125 --forward-to localhost:25 --admin 10026
$ emailrelay-poke 10026
$ echo $?
To use the "flush" command the next SMTP server address must have been defined
on the "emailrelay" command line at start-up using the "--forward-to" switch.
Also, the "list" command lists the messages in the spool directory, the "info"
command provides network status information and activity statistics, and the
"notify" command enables asynchronous event notification.
Mail processing Mail processing
--------------- ---------------
The "--filter" command-line switch allows you to specify a mail processor program The "--filter" command-line switch allows you to specify a mail pre-processor
which operates on mail messages as they pass through the E-MailRelay system. The program which operates on mail messages as they pass through the E-MailRelay
mail processor program is run as soon as the mail message has been stored in the system. The mail pre-processor program is run as soon as the mail message has been
spool directory, with the full path of the content file specified on the command stored in the spool directory, with the full path of the content file specified
line. on the command line.
This can be combined with the "--immediate" (or "--as-proxy") switch to implement
personal mail processing, without replacing or reconfiguring the system's
default MTA.
For example, the following command will start a proxy server on port 10025 which For example, the following command will start a proxy server on port 10025 which
processes mail using the specified filter program, and then forwards the mail on processes mail using the specified filter program, and then forwards the mail on
@ -289,13 +245,26 @@ to the system's default MTA (on port 25):
--filter ${HOME}/.emailrelay/filter \ --filter ${HOME}/.emailrelay/filter \
--spool-dir ${HOME}/.emailrelay/spool --spool-dir ${HOME}/.emailrelay/spool
The mail processor program should terminate with an exit code of zero to indicate The pre-processor program should terminate with an exit code of zero to indicate
success. An exit code of 100 can be used to cancel all further processing of the success, or a value between 1 and 99 to indicate failure. Exit codes between
message, and any other non-zero exit code is used to indicate an error. 100 and 107 are reserved for special processing: 100 is used to cancel all
further processing of the message, and 103 has the effect of immediately expiring
any "--poll" timer.
For example, the following mail processor shell script examines the client's The pre-processor program can edit any part of the message's envelope file or
IP address and conditionally dumps the message into "sendmail" (using the content file: E-MailRelay remembers nothing about the message while the
sendmail command-line interface rather than SMTP): pre-processor is running, except the filename. But if the message is deleted
by the pre-processor then E-MailRelay will be upset, unless the exit code
is 100.
If the pre-processor program creates new messages in the spool directory then
they may not be processed immediately, or they may be completely ignored. To get
E-MailRelay to pick up new messages in the spool directory use the "--poll"
switch, or run "emailrelay --as-client" from within the pre-processor program.
As an example, the following shell script examines the client's IP address and
conditionally dumps the message into "sendmail" (using the sendmail command-line
interface rather than SMTP):
#!/bin/sh #!/bin/sh
# #
@ -310,15 +279,92 @@ sendmail command-line interface rather than SMTP):
fi fi
exit 0 exit 0
An example mail processor script which does simple rot-13 masking of messages is The first thing this script does is convert the path of the content file which
also provided in the distribution ("share/emailrelay/emailrelay-process.sh"). it is given, into the corresponding envelope file. It then extracts the client's
This could be used as a template for a more sophisticated message encryption IP address out of the envelope file using "awk". If this matches then it pipes the
system. message content into sendmail, deletes the message and exits with a value of 100.
The exit value of 100 tells E-MailRelay to forget the message, and not to
complain about the files disappearing.
A more complex example script which does rot-13 masking is also provided in the
distribution ("emailrelay-process.sh"). This does some simple MIME encoding, and
could be used as a template for more sophisticated message encryption.
Some points to note when writing "--filter" programs:
* The standard input and output are not used; the content filename is passed on the command line.
* Programs run with a reduced set of environment variables.
* The E-MailRelay process is completely blocked while the "--filter" program runs.
* E-MailRelay files use CR-LF line terminators, as required by the RFCs.
Address verification
--------------------
In proxy mode all addresses supplied to the SMTP commands "RCPT" and "VRFY" are
accepted by E-MailRelay as valid. In server mode (or more accurately when
"--postmater" is in effect) addresses are accepted if they contain an at sign
or if they are some sort of local "postmaster" address, as described in the SMTP
section above.
However, this behaviour can be modified by using an external verifier program,
using the "--verifier" command-line switch.
The verifier program is passed a command-line containing: (1) the full address,
(2) the user-name part of the address, (3) the host-name part, (4) the local
host's fully qualified domain name, (5) the current "MAIL" command's "FROM:"
address or the empty string for the "VRFY" command, (6) the IP address of the
client connection, (7) the authentication mechanism used by the client ("NONE"
if trusted), and (8) either the authentication name or the fourth field from
authentication secrets file if a trusted IP address.
For valid local mailbox addresses the verifier is expected to write two lines to
the standard output -- the full name associated with the mailbox, and the
canonical mailbox name -- and then exit with a value of zero. For valid non-local
addresses the first line of output should be empty, the second line should be
copied from the first command-line argument, and the exit value should be one.
For invalid addresses the exit value should be greater than one, and anything
written to the standard output is taken as the failure reason. (Only the few
few thousand characters are read from the verifier's standard output stream;
any more is thrown away.)
In this simple example script all addresses are accepted as long as they contain
an at sign. This is equivalent to removing the "--postmaster" command-line
switch:
#!/bin/sh
# verifier.sh
address="${1}"
user="${2}"
host="${3}"
if test "${address}" != "${user}@${host}" ; then exit 2 ; fi
echo "${address}"
echo "${address}" # again
exit 1 # accept
As another example, this verifier script accepts all recipient addresses by
default, but rejects remote addresses if the client has bypassed authentication
by connecting on a trusted IP address:
#!/bin/sh
# verifier.sh
host="$3"
local_domain="$4"
auth_mechanism="$7"
if test "${auth_mechanism}" = "NONE" -a "${host}" != "${local_domain}"
then
echo "cannot relay without authentication"
exit 2 # reject the recipient address
fi
echo "${address}"
echo "${address}" # again
exit 1 # accept the recipient address
If this verifier script is used with a suitable "--server-auth" file then it can
be used to prevent open relay without restricting authenticated clients.
Security issues Security issues
--------------- ---------------
A major security concern is the use of an external mail processor (using the A significant security concern is the use of external mail pre-processors and
"--filter" switch), and so the following precautions are taken: address verifiers (using the "--filter" and "--verifier" switches), and so the
following precautions are taken:
# effective userid # effective userid
@ -332,14 +378,14 @@ A major security concern is the use of an external mail processor (using the
# execution environment # execution environment
The mail processor runs with an almost empty set of environment variables ("PATH" The mail pre-processor runs with an almost empty set of environment variables
and "IFS"), and with no open file descriptors other than "stdin"/"stdout"/"stderr" ("PATH" and "IFS"), and with no open file descriptors other than "stdin"/"stdout"/"stderr"
open onto "/dev/null". open onto "/dev/null".
# configuration # configuration
The mail processor filename has to be configured using a full path, so there is The mail pre-processor filename has to be configured using a full path, so there
no dependence on the current working directory or the PATH environment variable. is no dependence on the current working directory or the PATH environment variable.
Security issues which relate to the SMTP protocol itself are beyond the scope of Security issues which relate to the SMTP protocol itself are beyond the scope of
this document, but RFC2821 makes the following observation: "SMTP mail is this document, but RFC2821 makes the following observation: "SMTP mail is
@ -355,7 +401,7 @@ Some other points are:
* Strings are dynamically allocated, so buffer overflow/truncation issues are avoided. * Strings are dynamically allocated, so buffer overflow/truncation issues are avoided.
* By default connections to the SMTP and administrative ports will be rejected if they come from remote machines. * By default connections to the SMTP and administrative ports will be rejected if they come from remote machines.
* No configuration parameters can be changed through the administrative interface. * No configuration parameters can be changed through the administrative interface.
* No exec(), system() or popen() calls are used other than execve() to spawn the mail processor and address verifier. * No exec(), system() or popen() calls are used other than execve() to spawn the mail pre-processor and/or address verifier.
* The submit utility is installed as set-group-id with group ownership of "daemon". * The submit utility is installed as set-group-id with group ownership of "daemon".
Authentication Authentication
@ -375,16 +421,27 @@ fields: "mechanism", "client-or-server", "userid", and "secret". The "mechanism"
field must be "LOGIN" or "CRAM-MD5" (case-insensitive); the "client-or-server" field must be "LOGIN" or "CRAM-MD5" (case-insensitive); the "client-or-server"
field must be "client" or "server"; the "userid" field is xtext-encoded user field must be "client" or "server"; the "userid" field is xtext-encoded user
identifier; and the "secret" field is the xtext-encoded "LOGIN" password or identifier; and the "secret" field is the xtext-encoded "LOGIN" password or
"CRAM-MD5" key. The "xtext" encoding scheme is defined in RFC1891. The "CRAM-MD5" key.
"CRAM-MD5" keys can be generated using the "emailrelay-passwd" utility.
A client-side secrets file should contain at least one "LOGIN client" or The "xtext" encoding scheme is defined properly in RFC1891, but basically it
"CRAM-MD5 client" entry. A server-side secrets file should contain zero or says that non alphanumeric characters should be represented in hexadecimal as
more "LOGIN server" or "CRAM-MD5 server" entries. The same secrets file may "+XX".
be specified for both "--auth-client" and "--auth-server" switches.
For example, the following secrets file defines "jsmith" as the username to be The client-side secrets file specified with "--auth-client" is used when
used when E-MailRelay authenticates with a next-hop server, and defines two E-MailRelay talks to a remove server. The file should contain at least one
"LOGIN client" or "CRAM-MD5 client" entry.
A server-side secrets file specified with "--auth-server" is used when a remote
client tries to authenticate with E-MailRelay. The file should normally contain
several "LOGIN server" or "CRAM-MD5 server" entries.
The same secrets file may be specified for both "--auth-client" and
"--auth-server" switches.
The "CRAM-MD5" keys can be generated using the "emailrelay-passwd" utility.
As an example, the following secrets file defines "jsmith" as the username to be
used when E-MailRelay authenticates with a remote SMTP server, and defines two
usernames ("user1" and "user2") which can be used by clients when they usernames ("user1" and "user2") which can be used by clients when they
authenticate with the E-MailRelay server: authenticate with the E-MailRelay server:
@ -409,18 +466,12 @@ and then send them unencypted over a network. This is a bad thing. You should at
least make sure that the secrets file has tight permissions, and that the least make sure that the secrets file has tight permissions, and that the
passwords in it are not also used for anything important (such as root access). passwords in it are not also used for anything important (such as root access).
On the server side authentication is advertised in the response to the SMTP On the server side authentication is advertised by E-MailRealy in the response
"EHLO" command if the "--auth-server" command-line switch is used, and to the SMTP "EHLO" command if the "--auth-server" command-line switch is used.
authentication by the client is mandatory unless the client's IP address is Authentication by the client is mandatory unless the client's IP address is
configured as a trusted address. If the client does authenticate then configured as a trusted address. If the client does authenticate then the
the authenticated user-id is stored with the message and then passed on to a authenticated user-id is stored with the message and then passed on to the next
next-hop server using an "AUTH=userid" parameter on the SMTP "MAIL FROM" SMTP server using an "AUTH=userid" parameter on the SMTP "MAIL FROM" command.
command. If the client does not to authenticate then the submitted messages
will be forwarded using "AUTH=<>" on the "MAIL FROM" command. Note that any
"AUTH=userid" information on incoming submitted messages is ignored and
discarded: it is the authorised userid from the AUTH command which is
propagated, not the userid from the incoming "MAIL FROM" command's "AUTH="
parameter.
Trusted IP addresses are configured with lines in the secrets file having "NONE" Trusted IP addresses are configured with lines in the secrets file having "NONE"
in the first field, "server" in the second field, a wildcarded IP address in in the first field, "server" in the second field, a wildcarded IP address in
@ -428,11 +479,21 @@ the third field, and an arbitrary keyword in the fourth field. The keyword
is passed to any external address verifier program specified by the "--verifier" is passed to any external address verifier program specified by the "--verifier"
command-line switch. command-line switch.
On the client side authentication is performed when the client has connected to For example this secrets file allows any client connecting from the 192.168.0.0
domain to connect without authentication desipte the "--auth-server" switch:
#
# emailrelay secrets file
#
NONE server 192.168.0.* localdomain
LOGIN server user1 secret
LOGIN server user2 e+3Dmc2
On the client side authentication is performed when E-MailRelay has connected to
a server which supports the AUTH extension with the LOGIN or CRAM-MD5 mechanism. a server which supports the AUTH extension with the LOGIN or CRAM-MD5 mechanism.
If client authentication is enabled (with the "--auth-client" switch) but the If client authentication is enabled (with the "--auth-client" switch) but the
server does not support the AUTH extension, or does not support the LOGIN or server does not support the AUTH extension, or does not support the LOGIN or
CRAM-MD5 mechanism, then the client will fail the first message and terminate CRAM-MD5 mechanism, then E-MailRelay will fail the first message and terminate
with an error message. with an error message.
Note that some ISPs require separate POP/IMAP authentication before SMTP access Note that some ISPs require separate POP/IMAP authentication before SMTP access
@ -449,21 +510,39 @@ Application notes
set sendmail="/usr/local/libexec/emailrelay-submit" set sendmail="/usr/local/libexec/emailrelay-submit"
or
set sendmail="/usr/sbin/emailrelay-submit"
This puts the messages in the E-MailRelay spool-directory, but note that in
proxy mode they will be ignored unless you use "--poll". Or you could use
"--admin" plus "flush"/"emailrelay-poke".
# *Spam Assassin* [http://spamassassin.taint.org] # *Spam Assassin* [http://spamassassin.taint.org]
The E-MailRelay server can use Spam Assasin to mark potential spam by having The E-MailRelay server can use Spam Assassin to mark potential spam by having
a small shell script which calls spamassassin's "spamc" program installed a small shell script which calls spamassassin's "spamc" program installed
as the E-MailRelay mail processor (using the "--filter" command-line switch). as the E-MailRelay mail pre-processor (using the "--filter" command-line switch).
The shell script would look something like this: Your "--filter" shell script would look something like this:
#!/bin/sh #!/bin/sh
tmp="`basename $0`.$$.tmp" tmp="/tmp/`basename $0`.$$.tmp"
cat ${1} | spamc > ${tmp} && mv ${tmp} ${1} pre="dos2unix"
post="unix2dos"
${pre} < ${1} | spamc > ${tmp}
if test $? -eq 0 ; then ${post} < ${tmp} > ${1} ; fi
rm -f ${tmp} 2>/dev/null
exit 0
This just pipes the content file into "spamc", using "dos2unix" to remove
carriage-returns. The output is saved in a temporary file, and then put back
into the content file using "unix2dos" to restore the carriage-returns.
Files and directories Files and directories
--------------------- ---------------------
By default "make install" installs files in the following locations: Following a normal build from source, a "make install" puts files in the
following locations:
* /usr/local/libexec/emailrelay * /usr/local/libexec/emailrelay
* /usr/local/libexec/emailrelay-deliver.sh * /usr/local/libexec/emailrelay-deliver.sh
* /usr/local/libexec/emailrelay-notify.sh * /usr/local/libexec/emailrelay-notify.sh
@ -499,7 +578,8 @@ This directory structure is constrained by the GNU/"autoconf" conventions rather
than the Filesystem Hierarchy Standard (FHS). than the Filesystem Hierarchy Standard (FHS).
To force FHS compliance you can use the "--enable-fhs" switch when running To force FHS compliance you can use the "--enable-fhs" switch when running
"configure". This results in the following file locations: "configure", as is done for the RPMs. This results in the following file
locations:
* /etc/init.d/emailrelay * /etc/init.d/emailrelay
* /usr/lib/emailrelay/emailrelay-poke * /usr/lib/emailrelay/emailrelay-poke
* /usr/sbin/emailrelay * /usr/sbin/emailrelay
@ -558,15 +638,15 @@ However this will not affect the default spool directory path built into the
scripts and executables; the spool directory path will have to be explicitly scripts and executables; the spool directory path will have to be explicitly
defined at run-time. defined at run-time.
For example, building with "configure --enable-fhs ; make ; make install DESTDIR=/root" For example, building with "configure --enable-fhs ; make ; make install DESTDIR=/export"
would create a spool directory "/root/var/spool/emailrelay", but the server would create a spool directory "/export/var/spool/emailrelay", but the server
run as "/root/usr/sbin/emailrelay --as-server" would expect a spool directory run as "/export/usr/sbin/emailrelay --as-server" would expect a spool directory of
of "/var/spool/emailrelay". This could be fixed by either adding "/var/spool/emailrelay". The fix is to add "--spool-dir /export/var/spool/emailrelay"
"--spool-dir /root/var/spool/emailrelay" to the server command-line, or by to the emailrelay command-line.
creating the "/var/spool/emailrelay" directory manually.
The "emailrelay" start/stop script in "init.d" creates a pid file in "/var/run"
if the directory exists, or in "/tmp" otherwise.
The "emailrelay" script in "init.d" creates a pid file in "/var/run" if the
directory exists, or in "/tmp" otherwise.

View File

@ -3,112 +3,114 @@ E-MailRelay User Guide
What is it? What is it?
----------- -----------
E-MailRelay is a simple store-and-forward e-mail transfer agent. It's a program E-MailRelay is a simple store-and-forward message transfer agent and proxy server.
which runs in the background and accepts e-mail from front-ends (KMail, Outlook, It runs on Unix-like operating systems (including Linux), and on Windows.
Netscape etc.), stores the messages on the hard disk, and when next connected
to the Internet forwards them to a next SMTP server for onward delivery.
The E-MailRelay program ("emailrelay") can run in two main modes: a storage When used as proxy server the E-MailRelay program ("emailrelay") runs in the
daemon, or a forwarding agent. As a storage daemon it waits for connections background and accepts e-mail from front-ends (KMail, Outlook etc.) or from
from your e-mail front-end and stores the mail which it receives in a spool the outside world, using the SMTP protocol. As soon as an e-mail message is
directory. As a forwarding agent it pulls messages out of the spool directory received it is forwarded on to the next SMTP server for onward delivery. This
and passes them on to a remote server -- typically an ISP mail server. becomes more useful when you add in your own message processing: as each
message is received it can be passed one of your programs for editing,
filtering, encypting etc.
E-MailRelay uses the Simple Message Transfer Protocol (SMTP). When running as a When used as a store-and-forward transfer agent E-MailRelay runs in two modes:
storage daemon it acts as an SMTP server, and when running as a forwarding the storage daemon part, and the forwarding agent. The storage daemon
agent it acts as an SMTP client. waits for incoming mail and stores anything it receives in a spool directory.
As a forwarding agent E-MailRelay pulls messages out of the spool directory
The program can also run as a proxy server. In this mode e-mails submitted at and passes them on to a remote server -- perhaps your ISP mail server.
the server interface are passed on to the next server immediately, without
spooling. This can be useful when combined with mail pre-processing to do things
like encryption, message archiving, addition of digital signatures, etc.
E-MailRelay runs on GNU/Linux, FreeBSD, Solaris and Windows.
What it's not What it's not
------------- -------------
With a dial-up connection E-MailRelay does not get involved in processing E-MailRelay is not a routing MTA. It forwards e-mail to a pre-configured SMTP
incoming e-mail messages; it only operates on outgoing messages. Incoming e-mail server, regardless of any message addressing or DNS redirects.
messages will probably be retrieved from your ISP by your e-mail front-end
program, using the POP3 or IMAP protocols.
E-MailRelay is not a routing MTA. It is designed to be used in situations where E-MailRelay does not do POP3 or IMAP protocols. Many ISPs accept outgoing e-mail
all outgoing e-mail message go out over the dial-up connection, so it is not an using SMTP, but deliver mail to you using POP3 or IMAP. In this case E-MailRelay
appropriate choice if you send e-mail to other people who use the same machine does not get involved in processing incoming e-mail messages; it only operates
or to people who are on the same local area network. on outgoing messages. Incoming e-mail messages will probably be retrieved from
your ISP direcly by your e-mail front-end program.
Also be careful with programs like "fetchmail" which will fetch incoming mail E-MailRelay is not a delivery agent. Some programs like "fetchmail" send
using POP3 or IMAP, but then use a local SMTP server to deliver to local locally-addressed e-mail to the local SMTP server in order to deliver them to
mailboxes. E-MailRelay does not act as a delivery agent, so if your local SMTP local mailboxes. E-MailRelay will not normally do this.
server is E-MailRelay then your incoming e-mail will bounce back out.
Why use it? Why use it?
----------- -----------
The motivation for developing E-MailRelay is that e-mail store-and-forward E-MailRelay is a simple tool that does SMTP. For simple tasks it is likely
using SMTP is conceptually a very simple thing, but most popular MTAs are to be easier to understand and configure than a more general purpose MTA.
complex. E-MailRelay just stores messages and then forwards them on to your
ISP, whereas a fully-featured MTA does clever things with address re-writing,
message routing, local delivery, loop detection, fancy DNS lookups etc.
In particular the configuration of some popular MTAs is notoriously complex E-MailRelay is designed to be policy-free, so that you can implement your own
and arcane, whereas the only thing the E-MailRelay system needs is the name of policies for message retries, bounces, local mailbox delivery, spam filtering
your ISP's mail server. etc. through external scripts.
Because E-MailRelay can act as a proxy server, it may be useful handling Typical applications of E-MailRelay include:
incoming mail from a permanent Internet connection. In this configuration the * spam filtering and virus checking incoming mail
pre-processing feature could be used for spam filtering or virus checking. * adding digital signatures or legal disclaimers to outgoing mail
* doing store-and-forward for outgoing mail across a dial-up internet connection
For outgoing mail pre-processing could be used to compensate for features, such * adding authentication where the existing infrastructure does not support it
as encryption, which are not available in your e-mail client program. Or it * simple proxying on a firewall host or DMZ
could be used to enforce formatting or legal requirements for all outgoing mail.
Running E-MailRelay Running E-MailRelay
------------------- -------------------
To run E-MailRelay as a storage daemon use the command: To run the program as a proxy use the "--as-proxy" command-line switch, followed by the
address of the target SMTP server. If you want to edit or filter e-mail as it passes
through the proxy then specify your pre-processor program with the "--filter" switch.
You can optionally change the listening port number using "--port" and the
spool directory using "--spool-dir".
emailrelay --as-server For example, to start up a local proxy which passes messages to some "addsig" script
and then forwards them to an MTA running on "smarthost", use a command like this:
To run E-MailRelay as a forwarding agent (once connected to the Internet), use emailrelay --as-proxy smarthost:smtp --filter $HOME/bin/addsig --spooldir $HOME/tmp
a command like this:
emailrelay --as-client mail.myisp.net:smtp To use E-MailRelay as a store-and-forward MTA use the "--as-server" switch
to start the storage daemon in the background. And then trigger delivery of
spooled messages by running emailrelay with the "--as-client" switch, followed
by the address of the target SMTP server.
where "mail.myisp.net" is replaced with the name of your ISP's SMTP server. For example, to start a storage daemon listening on port 10025 use a command
like this:
To run E-MailRelay as a personal proxy server (on port 10025) to the system's emailrelay --as-server --port 10025 --spooldir $HOME/tmp
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 And then to forward the spooled mail to "smarthost" run somthing like this:
where "mailfilter" is a program which you have written to do the appropriate emailrelay --as-client smarthost:smtp --spooldir $HOME/tmp
mail processing.
By default E-MailRelay will reject connections from remote machines. To
allow connections from anywhere use the "--remote-clients" switch.
For more information on the command-line options refer to the reference guide For more information on the command-line options refer to the reference guide
or run: or run:
emailrelay --help emailrelay --help --verbose
Starting the daemon at boot-time Starting the daemon at boot-time
-------------------------------- --------------------------------
The standard installation of E-MailRelay (using "make install") puts most of The standard installation of E-MailRelay (using "make install") puts most of the
the files into the right places, but it does not set things up so that the files into the right places, but it does not set things up so that the daemon
daemon starts at boot time, or that e-mail gets forwarded automatically when starts at boot time. You have to do that yourself because of the differences
you connect to the Internet. You have to do those bits yourself because of the between the various operating systems and distributions.
differences between the various operating systems and distributions.
Many systems, including the most popular GNU/Linux distributions, use the Many systems provide GUI programs and command-line tools to make the necessary
System-V mechanism for starting daemons at boot time. The directory links into the boot system: "ksysv" (KDE), "redhat-config-services", "insserv"
"/etc/init.d" (or "/sbin/init.d") contains a start/stop script for each daemon (Suse), "chkconfig" (Redhat), "install_initd" (LSB) are examples.
process, and then symbolic links in the "rc<N>.d" subdirectories control which
scripts are run when entering or leaving a particular run-level (<N>). The
links point back into the start/stop script in the parent directory, using a
"S" prefix for the starting link, and a "K" prefix for the stopping link. The
numeric part of the link name determines the order in which the links are
called.
If you cannot use a GUI front-end as provided by GNOME and KDE, or a If you do not have a suitable configuration tool you can set up the links
command-line utility like "insserv", "chkconfig" or "/usr/lib/lsb/install_initd", manually as described below.
then you can follow the steps below to set up the necessary symbolic links.
The "System-V" boot system has a base directory "/etc/init.d" (or "/sbin/init.d")
containing a start/stop script for each daemon process, and then symbolic links
in the "rc<N>.d" subdirectories control which scripts are run when entering or
leaving a particular run-level (<N>). The links point back into the start/stop
script in the parent directory, using a "S" prefix for the starting link, and a
"K" prefix for the stopping link. The numeric part of the link name determines
the order in which the links are called.
So the goal is to set up symbolic links to the "emailrelay" start/stop script
(not the binary) which "make install" will have put in "/etc/init.d" or
"/usr/local/libexec".
Before you start you will need to know where your "init.d" directory can be Before you start you will need to know where your "init.d" directory can be
found and what your default run level is: found and what your default run level is:
@ -117,8 +119,8 @@ found and what your default run level is:
$ runlevel | awk '{print $2}' $ runlevel | awk '{print $2}'
Assuming these are "/etc/init.d" and "5" you should (as root) copy the Assuming these are "/etc/init.d" and "5" you should (as root) copy the
E-MailRelay start/stop script into "/etc/init.d" (if it is not already E-MailRelay start/stop script into "/etc/init.d" (if it is not already installed
installed there): there):
$ cp /usr/local/libexec/emailrelay /etc/init.d $ cp /usr/local/libexec/emailrelay /etc/init.d
@ -143,6 +145,10 @@ daemons compete for the standard SMTP listening port):
Triggering onward delivery Triggering onward delivery
-------------------------- --------------------------
If you are using E-MailRelay to store and forward e-mail over a dial-up link to
the internet, then you will need to set things up so that the dialler tells
E-MailRelay when to start forwarding.
This section assumes that you are using "pppd" to establish your dial-up This section assumes that you are using "pppd" to establish your dial-up
Internet connection. (Note that KDE's "kppp" and Red Hat's "rp3" are graphical Internet connection. (Note that KDE's "kppp" and Red Hat's "rp3" are graphical
front-ends to the underlying "pppd" daemon.) front-ends to the underlying "pppd" daemon.)
@ -162,47 +168,52 @@ If you find "sendmail -q" then it should be sufficient to replace it with this:
where you substitute your ISP's SMTP server address for <myisp>. where you substitute your ISP's SMTP server address for <myisp>.
Or if your "ip-up" calls out to "ip-up.local" then create a two-line Or if your "ip-up" calls out to "ip-up.local" then create a two-line
"ip-up.local" script like this: "/etc/ppp/ip-up.local" script like this:
$ cd /etc/ppp
$ cat << EOF > ip-up.local
#!/bin/sh #!/bin/sh
exec /usr/local/sbin/emailrelay --as-client <myisp>:smtp exec /usr/local/sbin/emailrelay --as-client <myisp>:smtp
EOF
$ chmod +x ip-up.local If you create "ip-up.local" yourself remember to make it executable.
Notification of failed e-mails Notification of failed e-mails
------------------------------ ------------------------------
If e-mail messages become corrupted or inaccessible within the spool directory If e-mail messages become corrupted or inaccessible within the spool directory
then they will get failed within the E-MailRelay system. In order to get failed then they will get failed within the E-MailRelay system, with the envelope files
e-mails to 'bounce' back into your in-tray you will need to run the in the spool directory ending up with a ".bad" suffix.
"emailrelay-notify.sh" script (as "root") periodically. Note that this script
requires that you have "procmail" installed on your system to act as a
"delivery agent".
There are not many ways in which an e-mail can fail within the E-MailRelay If you are not too worried about getting failed mail to bounce, or if you do not
system. If everything is set up correctly then perhaps the most likely case is have a suitable delivery agent, then a simple check in your ".profile" script
that you have run out of disk space. If you are not too worried about getting for "*.bad" files in the spool directory may be sufficient:
failed mail to bounce, or if you do not have a suitable delivery agent, then
a simple check in your ".profile" script for "*.bad" files in the spool
directory may be sufficient:
$ cat <<EOF >> ~/.profile if test -f /var/spool/emailrelay/*.envelope.bad
if test -f /var/spool/emailrelay/*.envelope.bad ; then echo Failed mail >&2 ; fi then
EOF echo Failed mail >&2
fi
If you want failed e-mails to be retried a few times before bouncing back into This will warn you that something failed, but you will have to look at the
your in-tray, you can run the "emailrelay-resubmit.sh" script. This simply failure reason written into the envelope files, and at the log files, to
removes the ".bad" suffix from files in the spool directory, as long as they find out what went wrong.
have not been retried too many times already.
Or you can get failed e-mails to 'bounce' back into your in-tray by running the
"emailrelay-notify.sh" script as "root" periodically. But note that this is
only approporiate if you are using E-MailRelay for outgoing traffic, and it
assumes that you have "procmail" installed on your system to act as a "delivery
agent".
If you want failed e-mails to be retried a few times you can run the
"emailrelay-resubmit.sh" script periodically. This simply removes the ".bad"
suffix from files in the spool directory, as long as they have not been retried
too many times already.
Logging Logging
------- -------
The E-MailRelay program uses the "syslog" system to issue warnings and error messages, If the "--log" switch is used then E-MailRelay program issues warnings and error
using the "LOG_MAIL" facility. The "syslog" system is configured through the messages to the "syslog" system using the "LOG_MAIL" facility. Under Windows NT
"/etc/syslog.conf" file (try "man syslog.conf"), and in most cases you will find it writes to the "Application" event log.
that "LOG_MAIL" warnings and errors are directed to an appropriate log file (perhaps
"/var/log/messages"). The "syslog" system is configured through the "/etc/syslog.conf" file (try
"man syslog.conf"), and in most cases you will find that "LOG_MAIL" warnings and
errors are directed to an appropriate log file (perhaps "/var/log/messages").
To get a file which will accumulate all E-MailRelay log messages (and messages To get a file which will accumulate all E-MailRelay log messages (and messages
from all other mail programs), add a line like this to "/etc/syslog.conf": from all other mail programs), add a line like this to "/etc/syslog.conf":
@ -297,10 +308,10 @@ from cygwin/bash on Win98 keeps stderr open (albeit with dreadful performance),
whereas the standard command prompt does not. If necessary the environment whereas the standard command prompt does not. If necessary the environment
variable "GLOGOUTPUT_FILE" can be defined as the name of a log file. variable "GLOGOUTPUT_FILE" can be defined as the name of a log file.
Preventing public mail relay Preventing open mail relay
---------------------------- --------------------------
If you are running E-MailRelay as a server with a permanent connection to the If you are running E-MailRelay as a server with a permanent connection to the
Internet it is important to prevent public mail relay. By default public mail Internet it is important to prevent open mail relay. By default public mail
relaying is not possible because E-MailRelay does not accept IP connections from relaying is not possible because E-MailRelay does not accept IP connections from
remote clients. However, if the "--remote-clients" switch is used then you need remote clients. However, if the "--remote-clients" switch is used then you need
to be more careful. One option is to require all clients to authenticate, by to be more careful. One option is to require all clients to authenticate, by
@ -312,38 +323,11 @@ mechanism of "NONE". Refer to the reference guide for more information.
Taking it one stage further, you may want to allow clients to connect from any Taking it one stage further, you may want to allow clients to connect from any
IP address without authentication, but only allow them to send mail to local IP address without authentication, but only allow them to send mail to local
users. You can do this by requiring authentication with the "--server-auth" users. You can do this by requiring authentication with the "--server-auth"
switch but then exempting all clients from authentication with a "NONE server *.*.*.* x" switch but then exempt all clients from authentication with a "NONE server *.*.*.* x"
line in the secrets file. To complete the solution you must have an address line in the secrets file. To complete the solution you must have an address
verifier script ("--verifier") which rejects remote addresses if the client has verifier script ("--verifier") which rejects remote addresses if the client has
not authenticated. Again, refer to the reference guide for further details. not authenticated. Again, refer to the reference guide for further details.
Glossary
--------
# ISP
Internet Service Provider.
# MTA
Message Transfer Agent. Something which accepts incoming e-mail messages
and passes them on either to a local user, or to another MTA. A sophisticated
MTA program, which is widely used on the Internet, is "sendmail".
# SMTP
Simple Message Transfer Protocol. A set of rules which dictate how
e-mail messages are passed from one part of the e-mail system to the next.
The protocol rules are set out in the document "RFC2821".
# POP3
Post Office Protocol 3. A protocol for fetching incoming e-mail messages.
Many e-mail front-ends will fetch messages directly from an ISP using the POP
protocol, or a program like "fetchmail" may do it on their behalf.
# IMAP
Internet Message Access Protocol. A newer alternative to POP3.
# PPP
Point to Point Protocol. A low-level protocol used in dial-up connections
to an ISP. Usually implemented by the "pppd" program on GNU/Linux.

View File

@ -5,7 +5,8 @@ Introduction
------------ ------------
E-MailRelay was originally developed on Linux and so most of the documentation E-MailRelay was originally developed on Linux and so most of the documentation
relates to Unix-like operating systems rather than Microsoft Windows. This relates to Unix-like operating systems rather than Microsoft Windows. This
document provides some help on Windows installation and setup. document provides some help on installing and setting up E-MailRelay as a
store-and-forward MTA on Windows.
Quick start Quick start
------------ ------------
@ -18,7 +19,6 @@ In summary, the Windows installation process is as follows:
* Create a spool directory under "<windir>\spool", eg. "c:\win98\spool\emailrelay". * Create a spool directory under "<windir>\spool", eg. "c:\win98\spool\emailrelay".
* Configure your e-mail client (eg. Outlook) to use SMTP on the local machine for outgoing e-mail. * Configure your e-mail client (eg. Outlook) to use SMTP on the local machine for outgoing e-mail.
* Run the forwarding client from the taskbar/desktop shortcut once connected to the Internet. * Run the forwarding client from the taskbar/desktop shortcut once connected to the Internet.
* Optionally register the server as a COM component using the "-regserver" command-line switch.
These steps are explained in more detail below. These steps are explained in more detail below.
@ -105,4 +105,5 @@ taskbar, desktop or "Start->Programs->StartUp" shortcuts.
Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>. All rights reserved. Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>. All rights reserved.

View File

@ -1,25 +1,27 @@
Summary: Simple e-mail message transfer agent using SMTP Summary: Simple e-mail message transfer agent using SMTP
Name: emailrelay Name: emailrelay
Version: 1.0.2 Version: 1.1
Release: 1 Release: 1
Copyright: GPL Copyright: GPL
Group: System Environment/Daemons Group: System Environment/Daemons
Source: http://emailrelay.sourceforge.net/.../emailrelay-src-1.0.2.tar.gz Source: http://emailrelay.sourceforge.net/.../emailrelay-src-1.1.tar.gz
BuildRoot: /tmp/emailrelay-install BuildRoot: /tmp/emailrelay-install
%define prefix /usr %define prefix /usr
%description %description
E-MailRelay is a simple SMTP store-and-forward message transfer agent (MTA). E-MailRelay is a simple SMTP proxy and store-and-forward message transfer agent
It runs as an SMTP server, storing e-mail in a local spool directory, and (MTA). When running as a proxy all e-mail messages can be passed through a
then forwarding the stored messages to the next SMTP server on request. user-defined program, such as a spam filter, which can drop, re-address or edit
It can also run as a proxy server, forwarding (and optionally pre-processing) messages as they pass through. When running as a store-and-forward MTA incoming
e-mail as soon as it is received. It does not do any message routing, other messages are stored in a local spool directory, and then forwarded to the next
than to a local postmaster. Because of this functional simplicity it is SMTP server on request.
extremely easy to configure, typically only requiring the address of the
next-hop SMTP server to be put on the command line.
C++ source code is available for Linux, FreeBSD (etc) and Windows. Because of its functional simplicity E-MailRelay is easy to configure, typically
only requiring the address of the target SMTP server to be put on the command
line.
C++ source code is available for Linux, FreeBSD, MacOS X etc, and Windows.
Distribution is under the GNU General Public License. Distribution is under the GNU General Public License.
%prep %prep
@ -30,13 +32,13 @@ Distribution is under the GNU General Public License.
make HAVE_DOXYGEN=no HAVE_MAN2HTML=no make HAVE_DOXYGEN=no HAVE_MAN2HTML=no
%install %install
make install destdir=$RPM_BUILD_ROOT DESTDIR=$RPM_BUILD_ROOT HAVE_DOXYGEN=no HAVE_MAN2HTML=no make install-strip destdir=$RPM_BUILD_ROOT DESTDIR=$RPM_BUILD_ROOT HAVE_DOXYGEN=no HAVE_MAN2HTML=no
%post %post
test -f /usr/lib/lsb/install_initd && cd /etc/init.d && /usr/lib/lsb/install_initd emailrelay test -f /usr/lib/lsb/install_initd && cd /etc/init.d && /usr/lib/lsb/install_initd emailrelay || true
%preun %preun
test $1 -eq 0 && test -f /usr/lib/lsb/remove_initd && cd /etc/init.d && /usr/lib/lsb/remove_initd emailrelay test $1 -eq 0 && test -f /usr/lib/lsb/remove_initd && cd /etc/init.d && /usr/lib/lsb/remove_initd emailrelay || true
%clean %clean
rm -rf $RPM_BUILD_ROOT rm -rf $RPM_BUILD_ROOT
@ -75,6 +77,6 @@ rm -rf $RPM_BUILD_ROOT
%changelog %changelog
* Wed Jul 3 2003 Graeme Walker <graeme_walker@users.sourceforge.net> * Wed Jul 3 2002 Graeme Walker <graeme_walker@users.sourceforge.net>
- Initial version. - Initial version.

View File

@ -1,19 +1,20 @@
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> ## Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# ##
# This program is free software; you can redistribute it and/or ## This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License ## modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either ## as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later ## version 2 of the License, or (at your option) any later
# version. ## version.
# ##
# This program is distributed in the hope that it will be useful, ## This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of ## but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. ## GNU General Public License for more details.
# ##
# You should have received a copy of the GNU General Public License ## You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software ## along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# ##
SUBDIRS = gcc2.95 msvc6.0 #
SUBDIRS = gcc2.95 msvc6.0 sunpro5

View File

@ -90,25 +90,9 @@ e_sbindir = @e_sbindir@
e_spooldir = @e_spooldir@ e_spooldir = @e_spooldir@
install_sh = @install_sh@ install_sh = @install_sh@
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> #
# SUBDIRS = gcc2.95 msvc6.0 sunpro5
# 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.
#
SUBDIRS = gcc2.95 msvc6.0
subdir = lib subdir = lib
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h CONFIG_HEADER = $(top_builddir)/config.h

View File

@ -1,21 +1,22 @@
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> ## Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# ##
# This program is free software; you can redistribute it and/or ## This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License ## modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either ## as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later ## version 2 of the License, or (at your option) any later
# version. ## version.
# ##
# This program is distributed in the hope that it will be useful, ## This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of ## but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. ## GNU General Public License for more details.
# ##
# You should have received a copy of the GNU General Public License ## You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software ## along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# ##
#
EXTRA_DIST = iostream limits sstream xlocale EXTRA_DIST = iostream limits sstream xlocale

View File

@ -14,24 +14,8 @@
@SET_MAKE@ @SET_MAKE@
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> #
#
# 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.
#
SHELL = @SHELL@ SHELL = @SHELL@
srcdir = @srcdir@ srcdir = @srcdir@

View File

@ -1,4 +1,4 @@
// //
// Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> // Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
@ -30,7 +30,7 @@
namespace std namespace std
{ {
typedef ::ios ios_base ; typedef ::ios ios_base ;
} ; }
#endif #endif

View File

@ -1,4 +1,4 @@
// //
// Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> // Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
@ -27,7 +27,7 @@
namespace std namespace std
{ {
#include <limits.h> #include <limits.h>
} ; }
#endif #endif

View File

@ -1,4 +1,4 @@
// //
// Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> // Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
@ -39,7 +39,7 @@ namespace std
std::string str() const ; std::string str() const ;
} ; } ;
typedef ostringstream stringstream ; typedef ostringstream stringstream ;
} ; }
inline inline
std::ostringstream::ostringstream() std::ostringstream::ostringstream()

View File

@ -1,4 +1,4 @@
// //
// Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> // Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or

View File

@ -1,20 +1,22 @@
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> ## Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# ##
# This program is free software; you can redistribute it and/or ## This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License ## modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either ## as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later ## version 2 of the License, or (at your option) any later
# version. ## version.
# ##
# This program is distributed in the hope that it will be useful, ## This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of ## but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. ## GNU General Public License for more details.
# ##
# You should have received a copy of the GNU General Public License ## You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software ## along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# ##
#
EXTRA_DIST = cstdio cstdlib cstring ctime cmath
EXTRA_DIST = cstdio cstdlib cstring ctime

View File

@ -14,24 +14,8 @@
@SET_MAKE@ @SET_MAKE@
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> #
#
# 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.
#
SHELL = @SHELL@ SHELL = @SHELL@
srcdir = @srcdir@ srcdir = @srcdir@
@ -109,7 +93,7 @@ e_sbindir = @e_sbindir@
e_spooldir = @e_spooldir@ e_spooldir = @e_spooldir@
install_sh = @install_sh@ install_sh = @install_sh@
EXTRA_DIST = cstdio cstdlib cstring ctime EXTRA_DIST = cstdio cstdlib cstring ctime cmath
subdir = lib/msvc6.0 subdir = lib/msvc6.0
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h CONFIG_HEADER = $(top_builddir)/config.h

43
lib/msvc6.0/cmath Normal file
View File

@ -0,0 +1,43 @@
//
// Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// 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.
//
// ===
//
// cmath
//
#ifndef G_PORT_CMATH_H
#define G_PORT_CMATH_H
#include <math.h>
namespace std
{
using ::sin ;
using ::cos ;
using ::tan ;
using ::asin ;
using ::acos ;
using ::atan ;
using ::sqrt ;
using ::log ;
using ::log10 ;
}
#endif

View File

@ -1,4 +1,4 @@
// //
// Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> // Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
@ -31,7 +31,7 @@ namespace std
using ::rename ; using ::rename ;
using ::sscanf ; using ::sscanf ;
using ::sprintf ; using ::sprintf ;
} ; }
#endif #endif

View File

@ -1,4 +1,4 @@
// //
// Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> // Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
@ -32,6 +32,6 @@ namespace std
using ::getenv ; using ::getenv ;
using ::free ; using ::free ;
using ::malloc ; using ::malloc ;
} ; }
#endif #endif

View File

@ -1,4 +1,4 @@
// //
// Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> // Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
@ -38,7 +38,7 @@ namespace std
using ::strstr ; using ::strstr ;
using ::strspn ; using ::strspn ;
using ::strcspn ; using ::strcspn ;
} ; }
#endif #endif

View File

@ -1,4 +1,4 @@
// //
// Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> // Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
@ -35,7 +35,7 @@ namespace std
using ::mktime ; using ::mktime ;
using ::_tzset ; using ::_tzset ;
using ::strftime ; using ::strftime ;
} ; }
#endif #endif

20
lib/sunpro5/Makefile.am Normal file
View File

@ -0,0 +1,20 @@
#
## Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
##
## 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.
##
#
EXTRA_DIST = xar

216
lib/sunpro5/Makefile.in Normal file
View File

@ -0,0 +1,216 @@
# Makefile.in generated by automake 1.6.3 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ../..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_HEADER = $(INSTALL_DATA)
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
EXEEXT = @EXEEXT@
OBJEXT = @OBJEXT@
PATH_SEPARATOR = @PATH_SEPARATOR@
AMTAR = @AMTAR@
AR = @AR@
AWK = @AWK@
CC = @CC@
COMPILER_VERSION = @COMPILER_VERSION@
CXX = @CXX@
DEPDIR = @DEPDIR@
GZIP = @GZIP@
HAVE_DOXYGEN = @HAVE_DOXYGEN@
HAVE_MAN2HTML = @HAVE_MAN2HTML@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
MAKE = @MAKE@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
STRIP = @STRIP@
VERSION = @VERSION@
am__include = @am__include@
am__quote = @am__quote@
e_docdir = @e_docdir@
e_examplesdir = @e_examplesdir@
e_initdir = @e_initdir@
e_libexecdir = @e_libexecdir@
e_man1dir = @e_man1dir@
e_sbindir = @e_sbindir@
e_spooldir = @e_spooldir@
install_sh = @install_sh@
#
#
EXTRA_DIST = xar
subdir = lib/sunpro5
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
DIST_SOURCES =
DIST_COMMON = Makefile.am Makefile.in
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu lib/sunpro5/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
uninstall-info-am:
tags: TAGS
TAGS:
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ../..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@list='$(DISTFILES)'; for file in $$list; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic mostlyclean-am
distclean: distclean-am
distclean-am: clean-am distclean-generic
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am:
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic
uninstall-am: uninstall-info-am
.PHONY: all all-am check check-am clean clean-generic distclean \
distclean-generic distdir dvi dvi-am info info-am install \
install-am install-data install-data-am install-exec \
install-exec-am install-info install-info-am install-man \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-generic uninstall uninstall-am uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

16
lib/sunpro5/xar Normal file
View File

@ -0,0 +1,16 @@
#!/bin/sh
#
# xar
#
# A replacement for 'ar' that does 'CC -xar' ignoring
# autoconf's bogus "cru" switches.
#
# For example:
# $ chmod +x lib/sunpro5/xar
# $ ./configure --enable-whatever AR=`pwd`/lib/sunpro5/xar
#
CC="CC"
if test -x "${CXX}" ; then CC="${CXX}" ; fi
if test "${1}" = "--cxx" ; then CC="${2}" ; shift ; shift ; fi
shift # get rid of "cru" flags
exec ${CC} -xar -o "$@"

View File

@ -1,19 +1,20 @@
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> ## Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# ##
# This program is free software; you can redistribute it and/or ## This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License ## modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either ## as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later ## version 2 of the License, or (at your option) any later
# version. ## version.
# ##
# This program is distributed in the hope that it will be useful, ## This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of ## but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. ## GNU General Public License for more details.
# ##
# You should have received a copy of the GNU General Public License ## You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software ## along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# ##
#
SUBDIRS = glib gnet gsmtp main win32 SUBDIRS = glib gnet gsmtp main win32

View File

@ -90,24 +90,8 @@ e_sbindir = @e_sbindir@
e_spooldir = @e_spooldir@ e_spooldir = @e_spooldir@
install_sh = @install_sh@ install_sh = @install_sh@
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> #
#
# 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.
#
SUBDIRS = glib gnet gsmtp main win32 SUBDIRS = glib gnet gsmtp main win32
subdir = src subdir = src
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs

View File

@ -1,21 +1,22 @@
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> ## Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# ##
# This program is free software; you can redistribute it and/or ## This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License ## modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either ## as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later ## version 2 of the License, or (at your option) any later
# version. ## version.
# ##
# This program is distributed in the hope that it will be useful, ## This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of ## but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. ## GNU General Public License for more details.
# ##
# You should have received a copy of the GNU General Public License ## You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software ## along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# ##
#
EXTRA_DIST=\ EXTRA_DIST=\
garg_win32.cpp \ garg_win32.cpp \
gcleanup_win32.cpp \ gcleanup_win32.cpp \
@ -24,6 +25,7 @@ EXTRA_DIST=\
gdirectory_win32.cpp \ gdirectory_win32.cpp \
gfs_win32.cpp \ gfs_win32.cpp \
glogoutput_win32.cpp \ glogoutput_win32.cpp \
gmd5_aladdin.cpp \
gprocess_win32.cpp \ gprocess_win32.cpp \
gfile_win32.cpp \ gfile_win32.cpp \
gregistry_win32.cpp \ gregistry_win32.cpp \
@ -66,7 +68,7 @@ libglib_a_SOURCES = \
glogoutput.cpp \ glogoutput.cpp \
glogoutput.h \ glogoutput.h \
glogoutput_unix.cpp \ glogoutput_unix.cpp \
gmd5.cpp \ gmd5_rsa.cpp \
gmd5.h \ gmd5.h \
gmemory.h \ gmemory.h \
gnoncopyable.h \ gnoncopyable.h \
@ -79,6 +81,8 @@ libglib_a_SOURCES = \
groot.cpp \ groot.cpp \
groot.h \ groot.h \
gsetter.h \ gsetter.h \
gslot.cpp \
gslot.h \
gstatemachine.h \ gstatemachine.h \
gstr.cpp \ gstr.cpp \
gstr.h \ gstr.h \

View File

@ -90,24 +90,8 @@ e_sbindir = @e_sbindir@
e_spooldir = @e_spooldir@ e_spooldir = @e_spooldir@
install_sh = @install_sh@ install_sh = @install_sh@
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> #
#
# 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.
#
EXTRA_DIST = \ EXTRA_DIST = \
garg_win32.cpp \ garg_win32.cpp \
gcleanup_win32.cpp \ gcleanup_win32.cpp \
@ -116,6 +100,7 @@ EXTRA_DIST = \
gdirectory_win32.cpp \ gdirectory_win32.cpp \
gfs_win32.cpp \ gfs_win32.cpp \
glogoutput_win32.cpp \ glogoutput_win32.cpp \
gmd5_aladdin.cpp \
gprocess_win32.cpp \ gprocess_win32.cpp \
gfile_win32.cpp \ gfile_win32.cpp \
gregistry_win32.cpp \ gregistry_win32.cpp \
@ -159,7 +144,7 @@ libglib_a_SOURCES = \
glogoutput.cpp \ glogoutput.cpp \
glogoutput.h \ glogoutput.h \
glogoutput_unix.cpp \ glogoutput_unix.cpp \
gmd5.cpp \ gmd5_rsa.cpp \
gmd5.h \ gmd5.h \
gmemory.h \ gmemory.h \
gnoncopyable.h \ gnoncopyable.h \
@ -172,6 +157,8 @@ libglib_a_SOURCES = \
groot.cpp \ groot.cpp \
groot.h \ groot.h \
gsetter.h \ gsetter.h \
gslot.cpp \
gslot.h \
gstatemachine.h \ gstatemachine.h \
gstr.cpp \ gstr.cpp \
gstr.h \ gstr.h \
@ -193,9 +180,10 @@ am_libglib_a_OBJECTS = garg.$(OBJEXT) garg_unix.$(OBJEXT) \
gdirectory.$(OBJEXT) gdirectory_unix.$(OBJEXT) \ gdirectory.$(OBJEXT) gdirectory_unix.$(OBJEXT) \
gexception.$(OBJEXT) gfile.$(OBJEXT) gfile_unix.$(OBJEXT) \ gexception.$(OBJEXT) gfile.$(OBJEXT) gfile_unix.$(OBJEXT) \
gfs_unix.$(OBJEXT) ggetopt.$(OBJEXT) glog.$(OBJEXT) \ gfs_unix.$(OBJEXT) ggetopt.$(OBJEXT) glog.$(OBJEXT) \
glogoutput.$(OBJEXT) glogoutput_unix.$(OBJEXT) gmd5.$(OBJEXT) \ glogoutput.$(OBJEXT) glogoutput_unix.$(OBJEXT) \
gpath.$(OBJEXT) gpidfile.$(OBJEXT) gprocess_unix.$(OBJEXT) \ gmd5_rsa.$(OBJEXT) gpath.$(OBJEXT) gpidfile.$(OBJEXT) \
groot.$(OBJEXT) gstr.$(OBJEXT) gtime.$(OBJEXT) gprocess_unix.$(OBJEXT) groot.$(OBJEXT) gslot.$(OBJEXT) \
gstr.$(OBJEXT) gtime.$(OBJEXT)
libglib_a_OBJECTS = $(am_libglib_a_OBJECTS) libglib_a_OBJECTS = $(am_libglib_a_OBJECTS)
DEFS = @DEFS@ DEFS = @DEFS@
@ -216,10 +204,12 @@ am__depfiles_maybe = depfiles
@AMDEP_TRUE@ ./$(DEPDIR)/gfile_unix.Po ./$(DEPDIR)/gfs_unix.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gfile_unix.Po ./$(DEPDIR)/gfs_unix.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/ggetopt.Po ./$(DEPDIR)/glog.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/ggetopt.Po ./$(DEPDIR)/glog.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/glogoutput.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/glogoutput.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/glogoutput_unix.Po ./$(DEPDIR)/gmd5.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/glogoutput_unix.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/gpath.Po ./$(DEPDIR)/gpidfile.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gmd5_rsa.Po ./$(DEPDIR)/gpath.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/gpidfile.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/gprocess_unix.Po ./$(DEPDIR)/groot.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/gprocess_unix.Po ./$(DEPDIR)/groot.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/gstr.Po ./$(DEPDIR)/gtime.Po @AMDEP_TRUE@ ./$(DEPDIR)/gslot.Po ./$(DEPDIR)/gstr.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/gtime.Po
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX) CXXLD = $(CXX)
@ -275,11 +265,12 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glog.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glogoutput.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glogoutput.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glogoutput_unix.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glogoutput_unix.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gmd5.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gmd5_rsa.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpath.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpath.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpidfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpidfile.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gprocess_unix.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gprocess_unix.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/groot.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/groot.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gslot.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gstr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gstr.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtime.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtime.Po@am__quote@

View File

@ -126,7 +126,7 @@ void G::Arg::removeAt( size_t sw_index , size_t sw_args )
G_ASSERT( sw_index > 0U && sw_index < m_array.size() ) ; G_ASSERT( sw_index > 0U && sw_index < m_array.size() ) ;
if( sw_index > 0U && sw_index < m_array.size() ) if( sw_index > 0U && sw_index < m_array.size() )
{ {
Array::iterator p = m_array.begin() + sw_index ; StringArray::iterator p = m_array.begin() + sw_index ;
p = m_array.erase( p ) ; p = m_array.erase( p ) ;
for( size_t i = 0U ; i < sw_args && p != m_array.end() ; i++ ) for( size_t i = 0U ; i < sw_args && p != m_array.end() ; i++ )
p = m_array.erase( p ) ; p = m_array.erase( p ) ;

View File

@ -25,6 +25,7 @@
#define G_ARG_H #define G_ARG_H
#include "gdef.h" #include "gdef.h"
#include "gstrings.h"
#include <vector> #include <vector>
#include <string> #include <string>
@ -121,8 +122,7 @@ private:
static bool match( bool , const std::string & , const std::string & ) ; static bool match( bool , const std::string & , const std::string & ) ;
private: private:
typedef std::vector<std::string GAllocator(std::string) > Array ; StringArray m_array ;
Array m_array ;
std::string m_prefix ; std::string m_prefix ;
} ; } ;

View File

@ -28,6 +28,12 @@
#include "glog.h" #include "glog.h"
#include <signal.h> #include <signal.h>
extern "C"
{
void gcleanup_unix_handler_( int signum ) ;
typedef void (*Handler)( int ) ;
}
namespace G namespace G
{ {
class CleanupImp ; class CleanupImp ;
@ -40,14 +46,13 @@ class G::CleanupImp
{ {
public: public:
static void add( void (*fn)(const char*) , const char * ) ; static void add( void (*fn)(const char*) , const char * ) ;
static void installDefault( int ) ;
static void callHandlers() ;
private: private:
static void init() ; static void init() ;
static void install( int , void (*fn)(int) ) ; static void install( int , Handler ) ;
static void installHandler( int ) ; static void installHandler( int ) ;
static void installDefault( int ) ;
static void callHandlers() ;
static void handler_( int ) ;
static bool ignored( int ) ; static bool ignored( int ) ;
private: private:
@ -104,7 +109,7 @@ void G::CleanupImp::installHandler( int signum )
if( ignored(signum) ) if( ignored(signum) )
G_DEBUG( "G::CleanupImp::installHandler: signal " << signum << " is ignored" ) ; G_DEBUG( "G::CleanupImp::installHandler: signal " << signum << " is ignored" ) ;
else else
install( signum , handler_ ) ; install( signum , gcleanup_unix_handler_ ) ;
} }
void G::CleanupImp::installDefault( int signum ) void G::CleanupImp::installDefault( int signum )
@ -121,7 +126,7 @@ bool G::CleanupImp::ignored( int signum )
return action.sa_handler == SIG_IGN ; return action.sa_handler == SIG_IGN ;
} }
void G::CleanupImp::install( int signum , void (*fn)(int) ) void G::CleanupImp::install( int signum , Handler fn )
{ {
static struct sigaction zero_action ; static struct sigaction zero_action ;
struct sigaction action( zero_action ) ; struct sigaction action( zero_action ) ;
@ -139,12 +144,13 @@ void G::CleanupImp::callHandlers()
} }
} }
void G::CleanupImp::handler_( int signum ) extern "C"
void gcleanup_unix_handler_( int signum )
{ {
try try
{ {
callHandlers() ; G::CleanupImp::callHandlers() ;
installDefault( signum ) ; G::CleanupImp::installDefault( signum ) ;
::raise( signum ) ; ::raise( signum ) ;
} }
catch(...) catch(...)

View File

@ -41,7 +41,7 @@ void G::Daemon::detach()
::_exit( 0 ) ; ::_exit( 0 ) ;
setsid() ; setsid() ;
(void) Process::cd( "/" , Process::NoThrow() ) ; G_IGNORE Process::cd( "/" , Process::NoThrow() ) ;
if( Process::fork() == Process::Parent ) if( Process::fork() == Process::Parent )
::_exit( 0 ) ; ::_exit( 0 ) ;

View File

@ -24,8 +24,7 @@
#include "gdef.h" #include "gdef.h"
#include "gdate.h" #include "gdate.h"
#include "gdebug.h" #include "gdebug.h"
#include <sys/types.h> #include <ctime>
#include <time.h>
#include <iomanip> #include <iomanip>
//static //static
@ -45,6 +44,11 @@ G::Date::Date()
init( G::DateTime::utc(G::DateTime::now()) ) ; init( G::DateTime::utc(G::DateTime::now()) ) ;
} }
G::Date::Date( G::DateTime::EpochTime t )
{
init( G::DateTime::utc(t) ) ;
}
G::Date::Date( G::DateTime::EpochTime t , const LocalTime & ) G::Date::Date( G::DateTime::EpochTime t , const LocalTime & )
{ {
init( G::DateTime::local(t) ) ; init( G::DateTime::local(t) ) ;
@ -88,12 +92,21 @@ std::string G::Date::string( Format format ) const
{ {
std::ostringstream ss ; std::ostringstream ss ;
if( format == yyyy_mm_dd_slash ) if( format == yyyy_mm_dd_slash )
ss << m_year << "/" << m_month << "/" << m_day ; {
ss << yyyy() << "/" << mm() << "/" << dd() ;
}
else if( format == yyyy_mm_dd )
{
ss << yyyy() << mm() << dd() ;
}
else if( format == mm_dd )
{
ss << mm() << dd() ;
}
else else
ss {
<< m_year G_ASSERT( !"enum error" ) ;
<< std::setw(2) << std::setfill('0') << m_month }
<< std::setw(2) << std::setfill('0') << m_day ;
return ss.str() ; return ss.str() ;
} }
@ -102,10 +115,17 @@ int G::Date::monthday() const
return m_day ; return m_day ;
} }
std::string G::Date::monthdayString() const std::string G::Date::dd() const
{ {
std::ostringstream ss ; std::ostringstream ss ;
ss << m_day ; ss << std::setw(2) << std::setfill('0') << m_day ;
return ss.str() ;
}
std::string G::Date::mm() const
{
std::ostringstream ss ;
ss << std::setw(2) << std::setfill('0') << m_month ;
return ss.str() ; return ss.str() ;
} }
@ -132,7 +152,7 @@ G::Date::Weekday G::Date::weekday() const
return m_weekday ; return m_weekday ;
} }
std::string G::Date::weekdayString( bool brief ) const std::string G::Date::weekdayName( bool brief ) const
{ {
if( weekday() == sunday ) return brief ? "Sun" : "Sunday" ; if( weekday() == sunday ) return brief ? "Sun" : "Sunday" ;
if( weekday() == monday ) return brief ? "Mon" : "Monday" ; if( weekday() == monday ) return brief ? "Mon" : "Monday" ;
@ -149,7 +169,7 @@ G::Date::Month G::Date::month() const
return Month(m_month) ; return Month(m_month) ;
} }
std::string G::Date::monthString( bool brief ) const std::string G::Date::monthName( bool brief ) const
{ {
if( month() == january ) return brief ? "Jan" : "January" ; if( month() == january ) return brief ? "Jan" : "January" ;
if( month() == february ) return brief ? "Feb" : "February" ; if( month() == february ) return brief ? "Feb" : "February" ;
@ -171,10 +191,10 @@ int G::Date::year() const
return m_year ; return m_year ;
} }
std::string G::Date::yearString() const std::string G::Date::yyyy() const
{ {
std::ostringstream ss ; std::ostringstream ss ;
ss << m_year ; ss << std::setw(4) << std::setfill('0') << m_year ;
return ss.str() ; return ss.str() ;
} }

View File

@ -27,8 +27,7 @@
#include "gdef.h" #include "gdef.h"
#include "gdatetime.h" #include "gdatetime.h"
#include "gdebug.h" #include "gdebug.h"
#include <sys/types.h> #include <ctime>
#include <time.h>
#include <string> #include <string>
namespace G namespace G
@ -54,7 +53,7 @@ public:
august , september , october , november , december } ; august , september , october , november , december } ;
enum Format enum Format
{ yyyy_mm_dd_slash , yyyy_mm_dd } ; { yyyy_mm_dd_slash , yyyy_mm_dd , mm_dd } ;
static int yearUpperLimit() ; static int yearUpperLimit() ;
// Returns the smallest supported year value. // Returns the smallest supported year value.
@ -73,6 +72,10 @@ public:
Date( const G::DateTime::BrokenDownTime & tm ) ; Date( const G::DateTime::BrokenDownTime & tm ) ;
// Constructor for the specified date. // Constructor for the specified date.
explicit Date( G::DateTime::EpochTime t ) ;
// Constructor for the date in the UTC
// timezone as at the given epoch time.
Date( G::DateTime::EpochTime t , const LocalTime & ) ; Date( G::DateTime::EpochTime t , const LocalTime & ) ;
// Constructor for the date in the local // Constructor for the date in the local
// timezone as at the given epoch time. // timezone as at the given epoch time.
@ -86,27 +89,34 @@ public:
Weekday weekday() const ; Weekday weekday() const ;
// Returns the day of the week. // Returns the day of the week.
std::string weekdayString( bool brief = false ) const ; std::string weekdayName( bool brief = false ) const ;
// Returns an english string representation of // Returns an english string representation of
// the day of the week. // the day of the week.
// (Was weekdayString().)
int monthday() const ; int monthday() const ;
// Returns the day of the month. // Returns the day of the month.
std::string monthdayString() const ; std::string dd() const ;
// Returns a string representation of the day of the month. // Returns the day of the month as a two-digit decimal string.
// (Was monthdayString().)
Month month() const ; Month month() const ;
// Returns the month. // Returns the month.
std::string monthString( bool brief = false ) const ; std::string monthName( bool brief = false ) const ;
// Returns the month as a string (in english). // Returns the month as a string (in english).
// (Was monthString().)
std::string mm() const ;
// Returns the month as a two-digit decimal string.
int year() const ; int year() const ;
// Returns the year. // Returns the year.
std::string yearString() const ; std::string yyyy() const ;
// Returns the year as a string. // Returns the year as a four-digit decimal string.
// (Was yearString().)
Date & operator++() ; Date & operator++() ;
// Increments the date by one day. // Increments the date by one day.

View File

@ -27,9 +27,12 @@
#include "gassert.h" #include "gassert.h"
#include <sstream> #include <sstream>
const time_t minute = 60U ; namespace
const time_t hour = 60U * minute ; {
const time_t day = 24U * hour ; const std::time_t minute = 60U ;
const std::time_t hour = 60U * minute ;
const std::time_t day = 24U * hour ;
}
G::DateTime::EpochTime G::DateTime::now() G::DateTime::EpochTime G::DateTime::now()
{ {
@ -42,8 +45,8 @@ G::DateTime::EpochTime G::DateTime::epochTime( const BrokenDownTime & bdt_in )
BrokenDownTime bdt( bdt_in ) ; BrokenDownTime bdt( bdt_in ) ;
EpochTime start = std::mktime( &bdt ) ; // localtime EpochTime start = std::mktime( &bdt ) ; // localtime
// iterate over all timezones // iterate over all timezones -- brute force for now
const time_t delta = minute * 30U ; const std::time_t delta = minute * 30U ;
for( EpochTime t = (start-day-delta) ; t <= (start+day+delta) ; t += delta ) for( EpochTime t = (start-day-delta) ; t <= (start+day+delta) ; t += delta )
{ {
if( equivalent( t , bdt_in ) ) if( equivalent( t , bdt_in ) )

View File

@ -76,7 +76,7 @@ private:
static bool same( const BrokenDownTime & , const BrokenDownTime & ) ; static bool same( const BrokenDownTime & , const BrokenDownTime & ) ;
static std::tm * gmtime_r( const std::time_t * , std::tm * ) ; static std::tm * gmtime_r( const std::time_t * , std::tm * ) ;
static std::tm * localtime_r( const std::time_t * , std::tm * ) ; static std::tm * localtime_r( const std::time_t * , std::tm * ) ;
DateTime() ; DateTime() ; // not implemented
} ; } ;
#endif #endif

View File

@ -38,20 +38,27 @@
#include <config.h> #include <config.h>
#if ! HAVE_GMTIME_R #if HAVE_BUGGY_CTIME
#include <time.h>
#include <ctime> #include <ctime>
inline struct tm * gmtime_r( const time_t * tp , struct tm * tm_p ) #endif
#if ! HAVE_GMTIME_R || ! HAVE_LOCALTIME_R
#include <ctime>
#endif
#if ! HAVE_GMTIME_R
inline std::tm * gmtime_r( const std::time_t * tp , std::tm * tm_p )
{ {
* tm_p = * gmtime( tp ) ; * tm_p = * std::gmtime( tp ) ;
return tm_p ; return tm_p ;
} }
#endif #endif
#if ! HAVE_LOCALTIME_R #if ! HAVE_LOCALTIME_R
#include <ctime> inline std::tm * localtime_r( const std::time_t * tp , std::tm * tm_p )
inline struct tm * localtime_r( const time_t * tp , struct tm * tm_p )
{ {
* tm_p = * localtime( tp ) ; * tm_p = * std::localtime( tp ) ;
return tm_p ; return tm_p ;
} }
#endif #endif
@ -113,14 +120,13 @@
// pre-compilation) // pre-compilation)
// //
#include <cstddef> #include <cstddef>
#include <iostream> #include <exception>
#include <fstream> #include <fstream>
#include <sstream> #include <iostream>
#include <string>
//#include <xlocale>
#include <limits> #include <limits>
#include <memory> #include <memory>
#include <exception> #include <sstream>
#include <string>
// Define fixed-size types // Define fixed-size types
// //
@ -142,19 +148,9 @@
typedef unsigned int pid_t ; typedef unsigned int pid_t ;
#endif #endif
// STL portability macros (no longer necessary)
//
#if 1
#define GAllocator(T)
#define GLessAllocator(T1,T2)
#else
#define GAllocator(T) ,std::allocator<T>
#define GLessAllocator(T1,T2) ,std::allocator<T1>,std::less<T2>
#endif
// Modify compiler error handling // Modify compiler error handling
// //
#ifdef G_COMPILER_IS_MICROSOFT #if defined(G_COMPILER_IS_MICROSOFT)
#pragma warning( disable : 4100 ) // unused formal parameter #pragma warning( disable : 4100 ) // unused formal parameter
#pragma warning( disable : 4355 ) // 'this' in initialiser list #pragma warning( disable : 4355 ) // 'this' in initialiser list
#pragma warning( disable : 4511 ) // cannot create default copy ctor #pragma warning( disable : 4511 ) // cannot create default copy ctor
@ -163,5 +159,15 @@
#pragma warning( disable : 4275 ) // dll-interface stuff in <complex> #pragma warning( disable : 4275 ) // dll-interface stuff in <complex>
#endif #endif
// A macro to explicitly ignore a function's return value.
// Some compilers complain when return values are ignored, and
// others complain when using a c-style cast...
//
#if 1
#define G_IGNORE
#else
#define G_IGNORE (void)
#endif
#endif #endif

View File

@ -92,7 +92,7 @@ private:
// Class: G::DirectoryIterator // Class: G::DirectoryIterator
// Description: An iterator for Directory. // Description: An iterator for Directory.
// The iteration model is // The iteration model is
/// while(iter.more()) { (void)iter.file() ; } /// while(iter.more()) { (void)iter.filePath() ; }
// //
class G::DirectoryIterator class G::DirectoryIterator
{ {

View File

@ -96,7 +96,6 @@ public:
private: private:
void operator=( const DirectoryIteratorImp & ) ; void operator=( const DirectoryIteratorImp & ) ;
DirectoryIteratorImp( const DirectoryIteratorImp & ) ; DirectoryIteratorImp( const DirectoryIteratorImp & ) ;
static int onError( const char * path , int errno_ ) ;
} ; } ;
// === // ===
@ -148,8 +147,7 @@ G::DirectoryIterator::~DirectoryIterator()
// === // ===
//static extern "C" int gdirectory_unix_on_error_( const char * , int )
int G::DirectoryIteratorImp::onError( const char * , int )
{ {
const int abort = 1 ; const int abort = 1 ;
return abort ; return abort ;
@ -171,7 +169,7 @@ G::DirectoryIteratorImp::DirectoryIteratorImp( const Directory &dir ,
G_DEBUG( "G::DirectoryIteratorImp::ctor: glob(\"" << wild_path << "\")" ) ; G_DEBUG( "G::DirectoryIteratorImp::ctor: glob(\"" << wild_path << "\")" ) ;
int flags = 0 | GLOB_ERR ; int flags = 0 | GLOB_ERR ;
int error = ::glob( wild_path.pathCstr() , flags , onError , &m_glob ) ; int error = ::glob( wild_path.pathCstr() , flags , gdirectory_unix_on_error_ , &m_glob ) ;
if( error || m_glob.gl_pathv == NULL ) if( error || m_glob.gl_pathv == NULL )
{ {
G_DEBUG( "G::DirectoryIteratorImp::ctor: glob() error: " << error ) ; G_DEBUG( "G::DirectoryIteratorImp::ctor: glob() error: " << error ) ;

View File

@ -39,7 +39,7 @@ bool G::Directory::valid( bool for_creation ) const
DWORD attributes = ::GetFileAttributes( m_path.pathCstr() ) ; DWORD attributes = ::GetFileAttributes( m_path.pathCstr() ) ;
if( attributes == 0xFFFFFFFF ) if( attributes == 0xFFFFFFFF )
{ {
(void)::GetLastError() ; G_IGNORE ::GetLastError() ;
return false ; return false ;
} }
return ( attributes & FILE_ATTRIBUTE_DIRECTORY ) != 0 ; return ( attributes & FILE_ATTRIBUTE_DIRECTORY ) != 0 ;

View File

@ -83,7 +83,6 @@ public:
} ; } ;
#define G_EXCEPTION( class_name , description ) class class_name : public G::Exception { public: class_name() { m_what = description ; } public: explicit class_name ( std::ostream & stream ) { m_what = description ; append(stream) ; } public: explicit class_name( const char * more ) { m_what = description ; append(more) ; } public: explicit class_name( const std::string & more ) { m_what = description ; append(more) ; } } #define G_EXCEPTION( class_name , description ) class class_name : public G::Exception { public: class_name() { m_what = description ; } public: explicit class_name ( std::ostream & stream ) { m_what = description ; append(stream) ; } public: explicit class_name( const char * more ) { m_what = description ; append(more) ; } public: explicit class_name( const std::string & more ) { m_what = description ; append(more) ; } }
#define G_EXCEPTION_ G_EXCEPTION
#endif #endif

View File

@ -62,9 +62,10 @@ std::string G::File::sizeString( g_uint32_t hi , g_uint32_t lo )
std::string s ; std::string s ;
while( n != 0 ) while( n != 0 )
{ {
size_t i = n % 10U ; int i = static_cast<int>( n % 10 ) ;
s.insert( 0U , 1U , '0' + i ) ; char c = static_cast<char>( '0' + i ) ;
n /= 10U ; s.insert( 0U , 1U , c ) ;
n /= 10 ;
} }
return s ; return s ;
} }

View File

@ -44,7 +44,6 @@ namespace G
class G::GetOpt class G::GetOpt
{ {
public: public:
typedef std::vector<std::string GAllocator(std::string) > StringArray ;
struct Level // Used by G::GetOpt for extra type safety. struct Level // Used by G::GetOpt for extra type safety.
{ unsigned int level ; explicit Level(unsigned int l) : level(l) {} } ; { unsigned int level ; explicit Level(unsigned int l) : level(l) {} } ;
G_EXCEPTION( InvalidSpecification , "invalid options specification string" ) ; G_EXCEPTION( InvalidSpecification , "invalid options specification string" ) ;
@ -162,9 +161,9 @@ private:
valued(v_) , hidden(description_.empty()||level_==0U) , valued(v_) , hidden(description_.empty()||level_==0U) ,
value_description(vd_) , level(level_) {} value_description(vd_) , level(level_) {}
} ; } ;
typedef std::map<std::string,SwitchSpec GLessAllocator(char,SwitchSpec) > SwitchSpecMap ; typedef std::map<std::string,SwitchSpec> SwitchSpecMap ;
typedef std::pair<bool,std::string> Value ; typedef std::pair<bool,std::string> Value ;
typedef std::map<char,Value GLessAllocator(char,Value) > SwitchMap ; typedef std::map<char,Value> SwitchMap ;
void operator=( const GetOpt & ) ; void operator=( const GetOpt & ) ;
GetOpt( const GetOpt & ) ; GetOpt( const GetOpt & ) ;

View File

@ -31,7 +31,7 @@ namespace G
} }
// Class: LogImp // Class: LogImp
// Description: An implementation class used by Log. // Description: An implementation class used by G::Log.
// //
class G::LogImp class G::LogImp
{ {

View File

@ -61,7 +61,7 @@ public:
// Returns an End object which can be used to close off a quantum // Returns an End object which can be used to close off a quantum
// of logging. (The End::op<<() function calls G::Log::onEnd().) // of logging. (The End::op<<() function calls G::Log::onEnd().)
static Stream &stream() ; static Stream & stream() ;
// Returns a stream for streaming messages into. // Returns a stream for streaming messages into.
static void onEnd( Severity s ) ; static void onEnd( Severity s ) ;
@ -77,8 +77,7 @@ private:
namespace G namespace G
{ {
inline inline
std::ostream &operator<<( std::ostream &stream , std::ostream & operator<<( std::ostream & stream , const G::Log::Line & )
const G::Log::Line & )
{ {
return stream ; return stream ;
} }
@ -87,10 +86,9 @@ namespace G
namespace G namespace G
{ {
inline inline
std::ostream &operator<<( std::ostream &stream , std::ostream & operator<<( std::ostream & stream , const G::Log::End & end )
const G::Log::End &end )
{ {
G::Log::onEnd( end.m_s ) ; G::Log::onEnd( end.m_s ) ;
return stream ; return stream ;
} }
} }
@ -98,7 +96,7 @@ namespace G
namespace G namespace G
{ {
inline inline
G::Log::Line::Line( const char *file , int line ) G::Log::Line::Line( const char * file , int line )
{ {
G::Log::setFile( file ) ; G::Log::setFile( file ) ;
G::Log::setLine( line ) ; G::Log::setLine( line ) ;
@ -113,7 +111,12 @@ namespace G
// then warning/error messages should also get raised by some another // then warning/error messages should also get raised by some another
// independent means. // independent means.
// //
#define G_LOG_OUTPUT( expr , severity ) do { G::Log::stream() << G::Log::Line(__FILE__,__LINE__) << expr << G::Log::end(severity) ; } while(0) // (The G_LOG_OUTPUT implementation uses separate statements because
// some compilers dont do Koenig lookup with nested classes. They
// look for ::operator<<() or G::X::operator<<() rather than
// G::operator<<().)
//
#define G_LOG_OUTPUT( expr , severity ) do { G::Log::Stream & s_ = G::Log::stream() ; G::operator<<( s_ , G::Log::Line(__FILE__,__LINE__) ) ; s_ << expr ; G::operator<<( s_ , G::Log::end(severity) ) ; } while(0)
#if defined(_DEBUG) && ! defined(G_NO_DEBUG) #if defined(_DEBUG) && ! defined(G_NO_DEBUG)
#define G_DEBUG( expr ) G_LOG_OUTPUT( expr , G::Log::s_Debug ) #define G_DEBUG( expr ) G_LOG_OUTPUT( expr , G::Log::s_Debug )
#else #else

View File

@ -30,7 +30,8 @@
G::LogOutput * G::LogOutput::m_this = NULL ; G::LogOutput * G::LogOutput::m_this = NULL ;
G::LogOutput::LogOutput( const std::string & prefix , bool enabled , bool summary_log , G::LogOutput::LogOutput( const std::string & prefix , bool enabled , bool summary_log ,
bool verbose_log , bool debug , bool level , bool timestamp , bool strip ) : bool verbose_log , bool debug , bool level , bool timestamp , bool strip ,
bool use_syslog , SyslogFacility syslog_facility ) :
m_prefix(prefix) , m_prefix(prefix) ,
m_enabled(enabled) , m_enabled(enabled) ,
m_summary_log(summary_log) , m_summary_log(summary_log) ,
@ -38,7 +39,8 @@ G::LogOutput::LogOutput( const std::string & prefix , bool enabled , bool summar
m_debug(debug) , m_debug(debug) ,
m_level(level) , m_level(level) ,
m_strip(strip) , m_strip(strip) ,
m_syslog(false) , m_syslog(use_syslog) ,
m_facility(syslog_facility) ,
m_time(0) , m_time(0) ,
m_timestamp(timestamp) , m_timestamp(timestamp) ,
m_handle(0) , m_handle(0) ,
@ -57,6 +59,7 @@ G::LogOutput::LogOutput( bool enabled_and_summary , bool verbose_and_debug ) :
m_level(false) , m_level(false) ,
m_strip(false) , m_strip(false) ,
m_syslog(false) , m_syslog(false) ,
m_facility(User) ,
m_time(0) , m_time(0) ,
m_timestamp(false) , m_timestamp(false) ,
m_handle(0) , m_handle(0) ,
@ -86,22 +89,6 @@ bool G::LogOutput::enable( bool enabled )
return was_enabled ; return was_enabled ;
} }
void G::LogOutput::timestamp()
{
m_timestamp = true ;
}
void G::LogOutput::syslog()
{
syslog( User ) ;
}
void G::LogOutput::syslog( SyslogFacility facility )
{
m_syslog = true ;
m_facility = facility ;
}
//static //static
void G::LogOutput::output( Log::Severity severity , const char * file , unsigned int line , const char * text ) void G::LogOutput::output( Log::Severity severity , const char * file , unsigned int line , const char * text )
{ {

View File

@ -45,7 +45,8 @@ public:
LogOutput( const std::string & prefix , bool output , bool with_logging , LogOutput( const std::string & prefix , bool output , bool with_logging ,
bool with_verbose_logging , bool with_debug , bool with_level , bool with_verbose_logging , bool with_debug , bool with_level ,
bool with_timestamp , bool strip_context ) ; bool with_timestamp , bool strip_context ,
bool use_syslog , SyslogFacility syslog_facility = User ) ;
// Constructor. If there is no LogOutput object, // Constructor. If there is no LogOutput object,
// or if 'output' is false, then there is no // or if 'output' is false, then there is no
// output of any sort. Otherwise at least // output of any sort. Otherwise at least
@ -78,16 +79,6 @@ public:
// Enables or disables output. // Enables or disables output.
// Returns the previous setting. // Returns the previous setting.
void syslog() ;
// Enables logging to the syslog system under Unix.
void timestamp() ;
// Enables timestamping.
void syslog( SyslogFacility facility ) ;
// Enables logging to the syslog system under Unix,
// using the specified facility.
static void output( G::Log::Severity s , const char *file , unsigned line , const char *text ) ; static void output( G::Log::Severity s , const char *file , unsigned line , const char *text ) ;
// Generates output if there is an existing // Generates output if there is an existing
// LogOutput object which is enabled. Uses rawOutput(). // LogOutput object which is enabled. Uses rawOutput().

View File

@ -28,23 +28,26 @@
namespace namespace
{ {
int decode( G::LogOutput::SyslogFacility facility )
{
if( facility == G::LogOutput::User ) return LOG_USER ;
if( facility == G::LogOutput::Daemon ) return LOG_DAEMON ;
if( facility == G::LogOutput::Mail ) return LOG_MAIL ;
if( facility == G::LogOutput::Cron ) return LOG_CRON ;
// etc...
return LOG_USER ;
}
int decode( G::Log::Severity severity )
{
if( severity == G::Log::s_Warning ) return LOG_WARNING ;
if( severity == G::Log::s_Error ) return LOG_ERR ;
if( severity == G::Log::s_LogSummary ) return LOG_INFO ;
if( severity == G::Log::s_LogVerbose ) return LOG_INFO ;
return LOG_CRIT ;
}
int mode( G::LogOutput::SyslogFacility facility , G::Log::Severity severity ) int mode( G::LogOutput::SyslogFacility facility , G::Log::Severity severity )
{ {
int m = 0 ; return decode(facility) | decode(severity) ;
if( facility == G::LogOutput::User ) m |= LOG_USER ;
else if( facility == G::LogOutput::Daemon ) m |= LOG_DAEMON ;
else if( facility == G::LogOutput::Mail ) m |= LOG_MAIL ;
else if( facility == G::LogOutput::Cron ) m |= LOG_CRON ;
// etc...
if( severity == G::Log::s_Warning ) m |= LOG_WARNING ;
else if( severity == G::Log::s_Error ) m |= LOG_ERR ;
else if( severity == G::Log::s_LogSummary ) m |= LOG_INFO ;
else if( severity == G::Log::s_LogVerbose ) m |= LOG_INFO ;
else m |= LOG_CRIT ;
return m ;
} }
} }
@ -59,9 +62,13 @@ void G::LogOutput::rawOutput( G::Log::Severity severity , const char *message )
void G::LogOutput::init() void G::LogOutput::init()
{ {
if( m_syslog )
::openlog( NULL , LOG_PID , decode(m_facility) ) ;
} }
void G::LogOutput::cleanup() void G::LogOutput::cleanup()
{ {
if( m_syslog )
::closelog() ;
} }

View File

@ -65,7 +65,7 @@ void G::LogOutput::rawOutput( G::Log::Severity severity , const char *message )
// (assume suitable string resources of 1001..1003) // (assume suitable string resources of 1001..1003)
DWORD id = 0x400003E9L ; DWORD id = 0x400003E9L ;
DWORD type = EVENTLOG_INFORMATION_TYPE ; WORD type = EVENTLOG_INFORMATION_TYPE ;
if( severity == Log::s_Warning ) if( severity == Log::s_Warning )
{ {
id = 0x800003EAL ; id = 0x800003EAL ;
@ -78,7 +78,7 @@ void G::LogOutput::rawOutput( G::Log::Severity severity , const char *message )
} }
const char * p[] = { message , NULL } ; const char * p[] = { message , NULL } ;
(void) ::ReportEvent( m_handle, type, 0, id, NULL, 1, 0, p, NULL ) ; G_IGNORE ::ReportEvent( m_handle, type, 0, id, NULL, 1, 0, p, NULL ) ;
} }
} }

192
src/glib/gmd5_aladdin.cpp Normal file
View File

@ -0,0 +1,192 @@
//
// Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// 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.
//
// ===
//
// gmd5_aladdin.cpp
//
#include "gdef.h"
#include "gmd5.h"
#include "gstr.h"
#include "gstrings.h"
#include "gassert.h"
#include "md5.h"
namespace
{
void init( md5_state_t & context )
{
::md5_init( &context ) ;
}
void update( md5_state_t & context , const std::string & input )
{
char * p = const_cast<char*>(input.c_str()) ;
int size = static_cast<int>( input.size() ) ;
::md5_append( &context , reinterpret_cast<unsigned char*>(p) , size ) ;
}
std::string final( md5_state_t & context )
{
const size_t L = 16U ; // output size
unsigned char buffer[L] ;
::md5_finish( &context , buffer ) ;
const char * buffer_p = reinterpret_cast<char *>(buffer) ;
return std::string( buffer_p , L ) ;
}
std::string writeOut( const md5_state_t & context )
{
G_ASSERT( sizeof context.abcd[0] <= sizeof(unsigned long) ) ;
return
G::Str::fromULong( context.abcd[0] ) + "." +
G::Str::fromULong( context.abcd[1] ) + "." +
G::Str::fromULong( context.abcd[2] ) + "." +
G::Str::fromULong( context.abcd[3] ) ;
}
void readIn( md5_state_t & context , G::Strings & s )
{
static md5_state_t zero_context ;
context = zero_context ;
context.count[0] = 0x200 ; // magic number -- see cyrus sasl lib/md5.c
G_ASSERT( context.count[1] == 0 ) ;
context.abcd[0] = G::Str::toULong(s.front()) ; s.pop_front() ;
context.abcd[1] = G::Str::toULong(s.front()) ; s.pop_front() ;
context.abcd[2] = G::Str::toULong(s.front()) ; s.pop_front() ;
context.abcd[3] = G::Str::toULong(s.front()) ; s.pop_front() ;
G_ASSERT( context.buf[0] == 0 ) ;
}
}
std::string G::Md5::xor_( const std::string & s1 , const std::string & s2 )
{
G_ASSERT( s1.length() == s2.length() ) ;
std::string::const_iterator p1 = s1.begin() ;
std::string::const_iterator p2 = s2.begin() ;
std::string result ;
for( ; p1 != s1.end() ; ++p1 , ++p2 )
{
unsigned char c1 = static_cast<unsigned char>(*p1) ;
unsigned char c2 = static_cast<unsigned char>(*p2) ;
unsigned char c = c1 ^ c2 ;
result.append( 1U , static_cast<char>(c) ) ;
}
return result ;
}
std::string G::Md5::key64( std::string k )
{
const size_t B = 64U ;
if( k.length() > B )
k = digest(k) ;
if( k.length() < B )
k.append( std::string(B-k.length(),'\0') ) ;
G_ASSERT( k.length() == B ) ;
return k ;
}
std::string G::Md5::ipad()
{
const size_t B = 64U ;
return std::string( B , '\066' ) ; // 00110110 = 00,110,110
}
std::string G::Md5::opad()
{
const size_t B = 64U ;
return std::string( B , '\134' ) ; // 01011100 = 01,011,100
}
std::string G::Md5::mask( const std::string & k )
{
std::string k64 = key64( k ) ;
return mask( k64 , ipad() ) + "." + mask( k64 , opad() ) ;
}
std::string G::Md5::mask( const std::string & k64 , const std::string & pad )
{
md5_state_t context ;
init( context ) ;
update( context , xor_(k64,pad) ) ;
return writeOut( context ) ;
}
std::string G::Md5::hmac( const std::string & masked_key , const std::string & input , Masked )
{
G::Strings part_list ;
G::Str::splitIntoTokens( masked_key , part_list , "." ) ;
if( part_list.size() != 8U )
throw InvalidMaskedKey( masked_key ) ;
md5_state_t inner_context ;
md5_state_t outer_context ;
readIn( inner_context , part_list ) ;
readIn( outer_context , part_list ) ;
update( inner_context , input ) ;
update( outer_context , final(inner_context) ) ;
return final( outer_context ) ;
}
std::string G::Md5::hmac( const std::string & k , const std::string & input )
{
std::string k64 = key64( k ) ;
return digest( xor_(k64,opad()) , digest(xor_(k64,ipad()),input) ) ;
}
std::string G::Md5::digest( const std::string & input )
{
return digest( input , NULL ) ;
}
std::string G::Md5::digest( const std::string & input_1 , const std::string & input_2 )
{
return digest( input_1 , &input_2 ) ;
}
std::string G::Md5::digest( const std::string & input_1 , const std::string * input_2 )
{
md5_state_t context ;
init( context ) ;
update( context , input_1 ) ;
if( input_2 != NULL )
update( context , *input_2 ) ;
return final( context ) ;
}
std::string G::Md5::printable( const std::string & input )
{
G_ASSERT( input.length() == 16U ) ;
std::string result ;
const char * hex = "0123456789abcdef" ;
const size_t n = input.length() ;
for( size_t i = 0U ; i < n ; i++ )
{
unsigned char c = static_cast<unsigned char>(input.at(i)) ;
result.append( 1U , hex[(c>>4U)&0x0F] ) ;
result.append( 1U , hex[(c>>0U)&0x0F] ) ;
}
return result ;
}
// Source-file inclusion is not nice, but it means that the "md5.c"
// file can be left in its pristine state but still benefit (?) from
// portability tweaks in "gdef.h" etc.
//
#include "md5.c"

View File

@ -18,7 +18,7 @@
// //
// === // ===
// //
// gmd5.cpp // gmd5_rsa.cpp
// //
#include "gdef.h" #include "gdef.h"

View File

@ -52,7 +52,8 @@ void G::PidFile::create( const Path & pid_file )
G_DEBUG( "G::PidFile::create: \"" << pid_file << "\"" ) ; G_DEBUG( "G::PidFile::create: \"" << pid_file << "\"" ) ;
Process::Umask readable(Process::Umask::Readable) ; Process::Umask readable(Process::Umask::Readable) ;
std::ofstream file( pid_file.str().c_str() ) ; std::ofstream file( pid_file.str().c_str() ) ;
file << Process::Id() << std::endl ; Process::Id pid ;
file << pid.str() << std::endl ;
if( !file.good() ) if( !file.good() )
throw Error(std::string("cannot create file: ")+pid_file.str()) ; throw Error(std::string("cannot create file: ")+pid_file.str()) ;
Cleanup::add( cleanup , strdup_(pid_file.str().c_str()) ) ; // (leaks) Cleanup::add( cleanup , strdup_(pid_file.str().c_str()) ) ; // (leaks)

View File

@ -282,8 +282,8 @@ void G::Process::beSpecial( Identity identity , bool change_group )
// gcc requires -D_BSD_SOURCE for seteuid() // gcc requires -D_BSD_SOURCE for seteuid()
// //
Identity old_identity ; Identity old_identity ;
(void) ::seteuid( identity.uid ) ; G_IGNORE ::seteuid( identity.uid ) ;
if( change_group) (void) ::setegid( identity.gid ) ; if( change_group) G_IGNORE ::setegid( identity.gid ) ;
//G_DEBUG( "G::Process::beSpecial: " << old_identity << " -> " << Identity() ) ; //G_DEBUG( "G::Process::beSpecial: " << old_identity << " -> " << Identity() ) ;
old_identity.uid = 0 ; // pacify the compiler old_identity.uid = 0 ; // pacify the compiler
} }
@ -391,7 +391,7 @@ std::string G::Process::Identity::str() const
// === // ===
class G::Process::Umask::UmaskImp class G::Process::Umask::UmaskImp // A private implementation class used by G::Process::Umask.
{ {
public: public:
mode_t m_old_mode ; mode_t m_old_mode ;
@ -406,7 +406,7 @@ G::Process::Umask::Umask( Mode mode ) :
G::Process::Umask::~Umask() G::Process::Umask::~Umask()
{ {
(void) ::umask( m_imp->m_old_mode ) ; G_IGNORE ::umask( m_imp->m_old_mode ) ;
delete m_imp ; delete m_imp ;
} }

View File

@ -169,6 +169,11 @@ bool G::Process::cd( const Path & dir , NoThrow )
return 0 == ::_chdir( dir.str().c_str() ) ; return 0 == ::_chdir( dir.str().c_str() ) ;
} }
int G::Process::errno_()
{
return errno ;
}
int G::Process::spawn( Identity , const Path & exe , const Strings & args_ , int G::Process::spawn( Identity , const Path & exe , const Strings & args_ ,
std::string * pipe_result_p , int error_return ) std::string * pipe_result_p , int error_return )
{ {
@ -179,7 +184,9 @@ int G::Process::spawn( Identity , const Path & exe , const Strings & args_ ,
Strings args( args_ ) ; // non-const copy Strings args( args_ ) ; // non-const copy
Pipe pipe( pipe_result_p != NULL ) ; Pipe pipe( pipe_result_p != NULL ) ;
if( pipe_result_p != NULL ) if( pipe_result_p != NULL )
args.push_front( Str::fromInt(pipe.fd()) ) ; // kludge -- child must write on specific fd passed as argv[1] args.push_front( Str::fromInt(pipe.fd()) ) ; // kludge -- child must write on fd passed as argv[1]
G_DEBUG( "G::Process::spawn: \"" << exe << "\": \"" << Str::join(args,"\",\"") << "\"" ) ;
char ** argv = new char* [ args.size() + 2U ] ; char ** argv = new char* [ args.size() + 2U ] ;
argv[0U] = const_cast<char*>( exe.pathCstr() ) ; argv[0U] = const_cast<char*>( exe.pathCstr() ) ;
@ -191,7 +198,9 @@ int G::Process::spawn( Identity , const Path & exe , const Strings & args_ ,
const int mode = _P_WAIT ; const int mode = _P_WAIT ;
::_flushall() ; ::_flushall() ;
int rc = ::_spawnv( mode , exe.str().c_str() , argv ) ; int rc = ::_spawnv( mode , exe.str().c_str() , argv ) ;
int error = errno_() ;
delete [] argv ; delete [] argv ;
G_DEBUG( "G::Process::spawn: _spawnv(): rc=" << rc << ": errno=" << error ) ;
if( pipe_result_p != NULL ) if( pipe_result_p != NULL )
*pipe_result_p = pipe.read() ; *pipe_result_p = pipe.read() ;
@ -211,7 +220,6 @@ void G::Process::beSpecial( Identity , bool )
} }
// not implemented... // not implemented...
// int G::Process::errno_()
// Who G::Process::fork() {} // Who G::Process::fork() {}
// Who G::Process::fork( Id & child ) {} // Who G::Process::fork( Id & child ) {}
// void G::Process::exec( const Path & exe , const std::string & arg ) {} // void G::Process::exec( const Path & exe , const std::string & arg ) {}

View File

@ -159,6 +159,7 @@ private:
std::pair<g_uint32_t,size_t> getInfo() const ; std::pair<g_uint32_t,size_t> getInfo() const ;
std::string getData( g_uint32_t & type , bool & ) const ; std::string getData( g_uint32_t & type , bool & ) const ;
size_t get( char * , size_t ) const ; size_t get( char * , size_t ) const ;
void set( g_uint32_t type , const void * p , size_t n ) ;
private: private:
const RegistryKey & m_hkey ; const RegistryKey & m_hkey ;

View File

@ -259,6 +259,30 @@ std::string G::RegistryValue::getString( const std::string & defolt ,
} }
} }
g_uint32_t G::RegistryValue::getDword() const
{
DWORD type = 0 ;
bool exists = true ;
std::string data = getData( type , exists ) ;
if( !exists ) throw MissingValue( m_key_name ) ;
if( type != REG_DWORD ) throw InvalidType( m_key_name ) ;
if( data.length() != 4U ) throw ValueError( m_key_name ) ;
g_uint32_t result = 0UL ;
for( int i = 3 ; i >= 0 ; i-- )
{
result *= 256UL ;
result += static_cast<unsigned char>(data[i]) ;
}
return result ;
}
bool G::RegistryValue::getBool() const
{
g_uint32_t n = getDword() ;
if( n != 0UL && n != 1UL ) throw ValueError( m_key_name ) ;
return !!n ;
}
std::string G::RegistryValue::getData( g_uint32_t & type , bool & exists ) const std::string G::RegistryValue::getData( g_uint32_t & type , bool & exists ) const
{ {
exists = true ; exists = true ;
@ -334,14 +358,25 @@ void G::RegistryValue::set( const char * p )
void G::RegistryValue::set( const std::string & s ) void G::RegistryValue::set( const std::string & s )
{ {
DWORD type = REG_SZ ; set( REG_SZ , reinterpret_cast<const void*>(s.c_str()) , s.length()+1U ) ;
}
LONG rc = ::RegSetValueEx( m_hkey.imp().m_key , m_key_name.c_str() , 0 , void G::RegistryValue::set( bool b )
type , reinterpret_cast<const BYTE*>(s.c_str()) , {
s.length() + 1U ) ; g_uint32_t n = b ? 1UL : 0UL ;
set( n ) ;
}
void G::RegistryValue::set( g_uint32_t n )
{
set( REG_DWORD , reinterpret_cast<const void*>(&n) , 4UL ) ;
}
void G::RegistryValue::set( g_uint32_t type , const void * vp , size_t n )
{
const BYTE * p = reinterpret_cast<const BYTE*>(vp) ;
LONG rc = ::RegSetValueEx( m_hkey.imp().m_key , m_key_name.c_str() , 0 , type , p , n ) ;
if( rc != ERROR_SUCCESS ) if( rc != ERROR_SUCCESS )
throw ValueError( "RegSetValueEx" ) ; throw ValueError( "RegSetValueEx" ) ;
} }

View File

@ -37,7 +37,7 @@ namespace G
// Description: A class which aquires special privileges. // Description: A class which aquires special privileges.
// The implementation uses G::Process. // The implementation uses G::Process.
// //
class G::Root : private noncopyable class G::Root : private G::noncopyable
{ {
public: public:
explicit Root( bool change_group = true ) ; explicit Root( bool change_group = true ) ;

View File

@ -33,10 +33,10 @@ namespace G
} }
// Class: G::Setter // Class: G::Setter
// Description: A class to Manage a boolean flag // Description: A class to manage a boolean flag
// while in scope. // while in scope.
// //
class G::Setter : public G:: noncopyable class G::Setter : public G::noncopyable
{ {
public: public:
explicit Setter( bool & b ) ; explicit Setter( bool & b ) ;

54
src/glib/gslot.cpp Normal file
View File

@ -0,0 +1,54 @@
//
// Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// 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.
//
// ===
//
// gslot.cpp
//
#include "gdef.h"
#include "gslot.h"
G::SlotBase::~SlotBase()
{
}
G::SlotBase::SlotBase() : m_ref_count(1UL)
{
}
void G::SlotBase::up()
{
m_ref_count++ ;
}
void G::SlotBase::down()
{
m_ref_count-- ;
if( m_ref_count == 0UL )
delete this ;
}
// ===
void G::SignalImp::check( const SlotBase * p )
{
if( p != NULL )
throw AlreadyConnected() ;
}

415
src/glib/gslot.h Normal file
View File

@ -0,0 +1,415 @@
//
// Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// 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.
//
// ===
//
// gslot.h
//
// Inspired by libsigc++, but simplified by:
// * not doing multicast
// * not detecting dangling references
// * not supporting global function callbacks
// * using only void returns
//
// The key to the implementation is that SlotImp<> is
// templated on the callback parameter P and the callback
// sink class T, but Slot<> is templated only on P, so
// the event-source class does not need to know the type
// of the event-sink. The SlotOp<> classes are used to
// resolve this mismatch, by downcasting to the T-specific
// SlotImp<> class. The Slot<> classes are reference-counting
// handles to SlotImp<> (via SlotBase), with an additional
// function pointer for the relevant SlotOp<> downcasting
// method.
//
// The overloaded template function slot<>() creates
// a Slot<> handle, passing it a suitable SlotBase body
// and casting function. The dynamic type of the SlotBase
// reference is a SlotImp<> class which knows about the
// specific sink class T, and the casting function knows
// how to access the derived class. The combination of
// SlotBase polymorphism and casting function isolates the
// slot class from the sink class.
//
// Usage:
/// class Source
/// {
/// public:
/// Signal1<int> m_signal ;
/// private:
/// void Source::raiseEvent()
/// {
/// int n = 123 ;
/// m_signal.emit( n ) ;
/// }
/// } ;
///
/// class Sink
/// {
/// public:
/// void onEvent( int n ) ;
/// Sink( Source & source )
/// {
/// source.m_signal.connect( slot(*this,&Sink::onEvent) ) ;
/// }
/// } ;
//
#ifndef G_SLOT_H
#define G_SLOT_H
#include "gdef.h"
#include "gexception.h"
#include "gnoncopyable.h"
namespace G
{
// Class: SlotBase
// Description: Part of the slot/signal system.
// Used as a base class to all SlotImp<> classes
// allowing them to be used as bodies to the
// Slot<> reference-counting handle.
//
class SlotBase
{
public:
virtual ~SlotBase() ;
// Destructor.
SlotBase() ;
// Default constuctor.
void up() ;
// Increments the reference count.
void down() ;
// Decrements the reference count
// and does "delete this" on zero.
private:
SlotBase( const SlotBase & ) ; // not implemented
void operator=( const SlotBase & ) ; // not implemented
private:
unsigned long m_ref_count ;
} ;
// Class: SignalImp
// Description: Part of the slot/signal system.
// A static helper class used by Signal<> classes.
//
class SignalImp
{
public:
G_EXCEPTION( AlreadyConnected , "signal already connected to a slot" ) ;
static void check( const SlotBase * p ) ;
private:
SignalImp() ; // not implemented
} ;
template <class T>
inline
void swap_( T & t1 , T & t2 ) // no std::swap in gcc2.95
{
T temp( t1 ) ;
t1 = t2 ;
t2 = temp ;
}
// ===
// Class: SlotImp0
// Description: Part of the slot/signal system.
// An implementation class for Slot0<>. An instance
// is created by the slot<>()
//
template <class T>
class SlotImp0 : public SlotBase
{
T & m_object ;
void (T::*m_fn)() ;
public:
SlotImp0( T & object , void (T::*fn)() ) : m_object(object) , m_fn(fn) {}
void callback() { (m_object.*m_fn)() ; }
} ;
// Class: SlotOp0
// Description: Part of the slot/signal system.
//
template <class T>
class SlotOp0
{
public:
static void callback( SlotBase * imp )
{ static_cast<SlotImp0<T>*>(imp)->callback() ; }
} ;
// Class: Slot0
// Description: Part of the slot/signal system.
//
class Slot0
{
SlotBase * m_imp ;
void (*m_op)( SlotBase * ) ;
public:
Slot0() : m_imp(0) , m_op(0) {}
Slot0( SlotBase * imp , void (*op)(SlotBase*) ) : m_imp(imp) , m_op(op) {}
~Slot0() { if( m_imp ) m_imp->down() ; }
void callback() { if( m_imp ) (*m_op)( m_imp ) ; }
Slot0( const Slot0 & other ) : m_imp(other.m_imp) , m_op(other.m_op) { if(m_imp) m_imp->up() ; }
void swap( Slot0 & rhs ) { swap_(m_imp,rhs.m_imp) ; swap_(m_op,rhs.m_op) ; }
void operator=( const Slot0 & rhs ) { Slot0 tmp(rhs) ; swap(tmp) ; }
const SlotBase * base() const { return m_imp ; }
} ;
// Class: Signal0
// Description: Part of the slot/signal system.
//
class Signal0 : public noncopyable
{
Slot0 m_slot ;
public:
Signal0() {}
void emit() { m_slot.callback() ; }
void connect( Slot0 slot ) { SignalImp::check(m_slot.base()) ; m_slot = slot ; }
void disconnect() { m_slot = Slot0() ; }
} ;
// Function: slot
// Description: Part of the slot/signal system.
//
template <class T>
inline
Slot0 slot( T & object , void (T::*fn)() )
{
return Slot0( new SlotImp0<T>(object,fn) , SlotOp0<T>::callback ) ;
}
// ===
// Class: SlotImp1
// Description: Part of the slot/signal system.
//
template <class T, class P>
class SlotImp1 : public SlotBase
{
T & m_object ;
void (T::*m_fn)( P ) ;
public:
SlotImp1( T & object , void (T::*fn)(P) ) : m_object(object) , m_fn(fn) {}
void callback( P p ) { (m_object.*m_fn)(p) ; }
} ;
// Class: SlotOp1
// Description: Part of the slot/signal system.
//
template <class T, class P>
class SlotOp1
{
public:
static void callback( SlotBase * imp , P p )
{ static_cast<SlotImp1<T,P>*>(imp)->callback( p ) ; }
} ;
// Class: Slot1
// Description: Part of the slot/signal system.
//
template <class P>
class Slot1
{
SlotBase * m_imp ;
void (*m_op)( SlotBase * , P ) ;
public:
Slot1() : m_imp(0) , m_op(0) {}
Slot1( SlotBase * imp , void (*op)(SlotBase*,P) ) : m_imp(imp) , m_op(op) {}
~Slot1() { if( m_imp ) m_imp->down() ; }
void callback( P p ) { if( m_imp ) (*m_op)( m_imp , p ) ; }
Slot1( const Slot1<P> & other ) : m_imp(other.m_imp) , m_op(other.m_op) { if(m_imp) m_imp->up() ; }
void swap( Slot1<P> & rhs ) { swap_(m_imp,rhs.m_imp) ; swap_(m_op,rhs.m_op) ; }
void operator=( const Slot1<P> & rhs ) { Slot1 tmp(rhs) ; swap(tmp) ; }
const SlotBase * base() const { return m_imp ; }
} ;
// Class: Signal1
// Description: Part of the slot/signal system.
//
template <class P>
class Signal1 : public noncopyable
{
Slot1<P> m_slot ;
public:
Signal1() {}
void emit( P p ) { m_slot.callback( p ) ; }
void connect( Slot1<P> slot ) { SignalImp::check(m_slot.base()) ; m_slot = slot ; }
void disconnect() { m_slot = Slot1<P>() ; }
} ;
// Function: slot
// Description: Part of the slot/signal system.
//
template <class T,class P>
inline
Slot1<P> slot( T & object , void (T::*fn)(P) )
{
return Slot1<P>( new SlotImp1<T,P>(object,fn) , SlotOp1<T,P>::callback ) ;
}
// ===
// Class: SlotImp2
// Description: Part of the slot/signal system.
//
template <class T, class P1, class P2>
class SlotImp2 : public SlotBase
{
T & m_object ;
void (T::*m_fn)( P1 , P2 ) ;
public:
SlotImp2( T & object , void (T::*fn)(P1,P2) ) : m_object(object) , m_fn(fn) {}
void callback( P1 p1 , P2 p2 ) { (m_object.*m_fn)(p1,p2) ; }
} ;
// Class: SlotOp2
// Description: Part of the slot/signal system.
//
template <class T, class P1 , class P2>
class SlotOp2
{
public:
static void callback( SlotBase * imp , P1 p1 , P2 p2 )
{ static_cast<SlotImp2<T,P1,P2>*>(imp)->callback( p1 , p2 ) ; }
} ;
// Class: Slot2
// Description: Part of the slot/signal system.
//
template <class P1, class P2>
class Slot2
{
SlotBase * m_imp ;
void (*m_op)( SlotBase * , P1 , P2 ) ;
public:
Slot2() : m_imp(0) , m_op(0) {}
Slot2( SlotBase * imp , void (*op)(SlotBase*,P1,P2) ) : m_imp(imp) , m_op(op) {}
~Slot2() { if( m_imp ) m_imp->down() ; }
void callback( P1 p1 , P2 p2 ) { if( m_imp ) (*m_op)( m_imp , p1 , p2 ) ; }
Slot2( const Slot2<P1,P2> & other ) : m_imp(other.m_imp) , m_op(other.m_op) { if(m_imp) m_imp->up() ; }
void swap( Slot2<P1,P2> & rhs ) { swap_(m_imp,rhs.m_imp) ; swap_(m_op,rhs.m_op) ; }
void operator=( const Slot2<P1,P2> & rhs ) { Slot2 tmp(rhs) ; swap(tmp) ; }
const SlotBase * base() const { return m_imp ; }
} ;
// Class: Signal2
// Description: Part of the slot/signal system.
//
template <class P1, class P2>
class Signal2 : public noncopyable
{
Slot2<P1,P2> m_slot ;
public:
Signal2() {}
void emit( P1 p1 , P2 p2 ) { m_slot.callback( p1 , p2 ) ; }
void connect( Slot2<P1,P2> slot ) { SignalImp::check(m_slot.base()) ; m_slot = slot ; }
void disconnect() { m_slot = Slot2<P1,P2>() ; }
} ;
// Function: slot
// Description: Part of the slot/signal system.
//
template <class T, class P1, class P2>
inline
Slot2<P1,P2> slot( T & object , void (T::*fn)(P1,P2) )
{
return Slot2<P1,P2>( new SlotImp2<T,P1,P2>(object,fn) , SlotOp2<T,P1,P2>::callback ) ;
}
// ===
// Class: SlotImp3
// Description: Part of the slot/signal system.
//
template <class T, class P1, class P2, class P3>
class SlotImp3 : public SlotBase
{
T & m_object ;
void (T::*m_fn)( P1 , P2 , P3 ) ;
public:
SlotImp3( T & object , void (T::*fn)(P1,P2,P3) ) : m_object(object) , m_fn(fn) {}
void callback( P1 p1 , P2 p2 , P3 p3 ) { (m_object.*m_fn)(p1,p2,p3) ; }
} ;
// Class: SlotOp3
// Description: Part of the slot/signal system.
//
template <class T, class P1 , class P2, class P3>
class SlotOp3
{
public:
static void callback( SlotBase * imp , P1 p1 , P2 p2 , P3 p3 )
{ static_cast<SlotImp3<T,P1,P2,P3>*>(imp)->callback( p1 , p2 , p3 ) ; }
} ;
// Class: Slot3
// Description: Part of the slot/signal system.
//
template <class P1, class P2, class P3>
class Slot3
{
SlotBase * m_imp ;
void (*m_op)( SlotBase * , P1 , P2 , P3 ) ;
public:
Slot3() : m_imp(0) , m_op(0) {}
Slot3( SlotBase * imp , void (*op)(SlotBase*,P1,P2,P3) ) : m_imp(imp) , m_op(op) {}
~Slot3() { if( m_imp ) m_imp->down() ; }
void callback( P1 p1 , P2 p2 , P3 p3 ) { if( m_imp ) (*m_op)( m_imp , p1 , p2 , p3 ) ; }
Slot3( const Slot3<P1,P2,P3> & other ) : m_imp(other.m_imp) , m_op(other.m_op) { if(m_imp) m_imp->up() ; }
void swap( Slot3<P1,P2,P3> & rhs ) { swap_(m_imp,rhs.m_imp) ; swap_(m_op,rhs.m_op) ; }
void operator=( const Slot3<P1,P2,P3> & rhs ) { Slot3 tmp(rhs) ; swap(tmp) ; }
const SlotBase * base() const { return m_imp ; }
} ;
// Class: Signal3
// Description: Part of the slot/signal system.
//
template <class P1, class P2, class P3>
class Signal3 : public noncopyable
{
Slot3<P1,P2,P3> m_slot ;
public:
Signal3() {}
void emit( P1 p1 , P2 p2 , P3 p3 ) { m_slot.callback( p1 , p2 , p3 ) ; }
void connect( Slot3<P1,P2,P3> slot ) { SignalImp::check(m_slot.base()) ; m_slot = slot ; }
void disconnect() { m_slot = Slot3<P1,P2,P3>() ; }
} ;
// Function: slot
// Description: Part of the slot/signal system.
//
template <class T, class P1, class P2, class P3>
inline
Slot3<P1,P2,P3> slot( T & object , void (T::*fn)(P1,P2,P3) )
{
return Slot3<P1,P2,P3>( new SlotImp3<T,P1,P2,P3>(object,fn) , SlotOp3<T,P1,P2,P3>::callback ) ;
}
} // namespace
#endif

View File

@ -152,7 +152,7 @@ private:
Transition(State s1,State s2,Action a,State s3) : Transition(State s1,State s2,Action a,State s3) :
from(s1) , to(s2) , alt(s3) , action(a) {} from(s1) , to(s2) , alt(s3) , action(a) {}
} ; } ;
typedef std::multimap<Event,Transition GLessAllocator(Event,Transition) > Map ; typedef std::multimap<Event,Transition> Map ;
Map m_map ; Map m_map ;
State m_state ; State m_state ;
State m_end ; State m_end ;

View File

@ -115,7 +115,7 @@ bool G::Str::isUShort( const std::string & s )
{ {
try try
{ {
(void) toUShort(s) ; G_IGNORE toUShort(s) ;
} }
catch( Overflow & ) catch( Overflow & )
{ {
@ -132,7 +132,7 @@ bool G::Str::isUInt( const std::string & s )
{ {
try try
{ {
(void) toUInt(s) ; G_IGNORE toUInt(s) ;
} }
catch( Overflow & ) catch( Overflow & )
{ {
@ -149,7 +149,7 @@ bool G::Str::isULong( const std::string & s )
{ {
try try
{ {
(void) toULong(s) ; G_IGNORE toULong(s) ;
} }
catch( Overflow & ) catch( Overflow & )
{ {
@ -238,7 +238,7 @@ void G::Str::toLower( std::string &s )
{ {
for( std::string::iterator p = s.begin() ; p != s.end() ; ++p ) for( std::string::iterator p = s.begin() ; p != s.end() ; ++p )
{ {
*p = ::tolower( *p ) ; *p = static_cast<char>( ::tolower(*p) ) ;
} }
} }
@ -253,7 +253,7 @@ void G::Str::toUpper( std::string &s )
{ {
for( std::string::iterator p = s.begin() ; p != s.end() ; ++p ) for( std::string::iterator p = s.begin() ; p != s.end() ; ++p )
{ {
*p = ::toupper( *p ) ; *p = static_cast<char>( ::toupper(*p) ) ;
} }
} }

View File

@ -45,7 +45,6 @@ class G::Str
public: public:
G_EXCEPTION( Overflow , "conversion error: over/underflow" ) ; G_EXCEPTION( Overflow , "conversion error: over/underflow" ) ;
G_EXCEPTION( InvalidFormat, "conversion error: invalid format" ) ; G_EXCEPTION( InvalidFormat, "conversion error: invalid format" ) ;
typedef std::vector<std::string GAllocator(std::string) > StringArray ;
static bool replace( std::string &s , static bool replace( std::string &s ,
const std::string &from , const std::string &to , const std::string &from , const std::string &to ,
@ -207,7 +206,7 @@ public:
bool discard_bogus_escapes = true ) ; bool discard_bogus_escapes = true ) ;
// Overload for vector<string>. // Overload for vector<string>.
static std::string join( const G::Strings & strings , const std::string & sep ) ; static std::string join( const Strings & strings , const std::string & sep ) ;
// Concatenates a set of strings. // Concatenates a set of strings.
static std::string join( const StringArray & strings , const std::string & sep ) ; static std::string join( const StringArray & strings , const std::string & sep ) ;

View File

@ -24,8 +24,10 @@
#ifndef G_STRINGS_H #ifndef G_STRINGS_H
#define G_STRINGS_H #define G_STRINGS_H
#include "gdef.h"
#include <string> #include <string>
#include <list> #include <list>
#include <vector>
namespace G namespace G
{ {
@ -34,7 +36,12 @@ namespace G
// Description: A std::list of std::strings. // Description: A std::list of std::strings.
// See also: Str // See also: Str
// //
typedef std::list<std::string GAllocator(std::string) > Strings ; typedef std::list<std::string> Strings ;
// Typedef: StringArray
// Description: A std::vector of std::strings.
//
typedef std::vector<std::string> StringArray ;
} }

View File

@ -80,7 +80,7 @@ unsigned int G::Time::seconds() const
return m_ss ; return m_ss ;
} }
std::string G::Time::hhmmss( const char * sep ) std::string G::Time::hhmmss( const char * sep ) const
{ {
if( sep == NULL ) sep = "" ; if( sep == NULL ) sep = "" ;
std::ostringstream ss ; std::ostringstream ss ;
@ -88,7 +88,7 @@ std::string G::Time::hhmmss( const char * sep )
return ss.str() ; return ss.str() ;
} }
std::string G::Time::hhmm( const char * sep ) std::string G::Time::hhmm( const char * sep ) const
{ {
if( sep == NULL ) sep = "" ; if( sep == NULL ) sep = "" ;
std::ostringstream ss ; std::ostringstream ss ;
@ -96,3 +96,11 @@ std::string G::Time::hhmm( const char * sep )
return ss.str() ; return ss.str() ;
} }
std::string G::Time::ss() const
{
std::ostringstream ss ;
ss << (m_ss/10U) << (m_ss%10U) ;
return ss.str() ;
}

View File

@ -44,17 +44,17 @@ public:
class LocalTime // An overload discriminator class for Time constructors. class LocalTime // An overload discriminator class for Time constructors.
{} ; {} ;
Time() ;
// Constructor, using UTC, for now.
explicit Time( const G::DateTime::BrokenDownTime & tm ) ; explicit Time( const G::DateTime::BrokenDownTime & tm ) ;
// Constructor for the given broken-down time. // Constructor for the given broken-down time.
explicit Time( G::DateTime::EpochTime t ) ; explicit Time( G::DateTime::EpochTime t ) ;
// Constructor for the given epoch time. // Constructor, using UTC, for the given epoch time.
Time() ;
// Constructor for now.
Time( G::DateTime::EpochTime t , const LocalTime & ) ; Time( G::DateTime::EpochTime t , const LocalTime & ) ;
// Localtime constructor for the given epoch time. // Constructor, using the local timezone, for the given epoch time.
explicit Time( const LocalTime & ) ; explicit Time( const LocalTime & ) ;
// Localtime constructor for now. // Localtime constructor for now.
@ -68,12 +68,15 @@ public:
unsigned int seconds() const ; unsigned int seconds() const ;
// Returns the seconds (0 <= s <= 61 [sic]). // Returns the seconds (0 <= s <= 61 [sic]).
std::string hhmmss( const char * sep = NULL ) ; std::string hhmmss( const char * sep = NULL ) const ;
// Returns a hhmmss string. // Returns a hhmmss string.
std::string hhmm( const char * sep = NULL ) ; std::string hhmm( const char * sep = NULL ) const ;
// Returns a hhmm string. // Returns a hhmm string.
std::string ss() const ;
// Returns the seconds as a two-digit decimal seconds.
private: private:
unsigned int m_hh ; unsigned int m_hh ;
unsigned int m_mm ; unsigned int m_mm ;

View File

@ -1,22 +1,23 @@
// /*
// Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
//
// This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version 2 of the License, or (at your option) any later
// version. version.
//
// This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// === */
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
*/ */

View File

@ -1,21 +1,22 @@
# #
# Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net> ## Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>
# ##
# This program is free software; you can redistribute it and/or ## This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License ## modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either ## as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later ## version 2 of the License, or (at your option) any later
# version. ## version.
# ##
# This program is distributed in the hope that it will be useful, ## This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of ## but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. ## GNU General Public License for more details.
# ##
# You should have received a copy of the GNU General Public License ## You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software ## along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# ##
#
EXTRA_DIST=\ EXTRA_DIST=\
gclient_win32.cpp \ gclient_win32.cpp \
@ -24,7 +25,9 @@ EXTRA_DIST=\
glocal_win32.cpp \ glocal_win32.cpp \
grequest.cpp \ grequest.cpp \
gresolve_win32.cpp \ gresolve_win32.cpp \
gsocket_win32.cpp gsocket_win32.cpp \
gaddress_ipv6.cpp \
gresolve_ipv6.cpp
INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib
noinst_LIBRARIES = libgnet.a noinst_LIBRARIES = libgnet.a
libgnet_a_SOURCES = gaddress_ipv4.cpp \ libgnet_a_SOURCES = gaddress_ipv4.cpp \

Some files were not shown because too many files have changed in this diff Show More