This commit is contained in:
Graeme Walker 2003-07-05 12:00:00 +00:00
parent 7f88cace83
commit c7cbeb435a
68 changed files with 1883 additions and 699 deletions

View File

@ -1,6 +1,16 @@
E-MailRelay Change Log
======================
1.1.0 -> 1.1.1
--------------
* Restored the fix for building with gcc2.96.
* Support for MinGW builds on Windows.
* More reasonable size of the "--help --verbose" message box on Windows.
* Windows "--icon" switch changed from "-i" to "-c" to avoid conflicting with "--interface".
* Shows "next server address" correctly in the configuration report when using "--forward-to".
* Fix for "make install" when "man2html" is not available.
* Updated init script.
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].

8
README
View File

@ -28,7 +28,7 @@ spool directory using "--spool-dir".
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:
emailrelay --as-proxy smarthost:smtp --filter $HOME/bin/addsig --spooldir $HOME/tmp
emailrelay --as-proxy smarthost:smtp --filter $HOME/bin/addsig --spool-dir $HOME/tmp
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
@ -38,11 +38,11 @@ by the address of the target SMTP server.
For example, to start a storage daemon listening on port 10025 use a command
like this:
emailrelay --as-server --port 10025 --spooldir $HOME/tmp
emailrelay --as-server --port 10025 --spool-dir $HOME/tmp
And then to forward the spooled mail to "smarthost" run somthing like this:
emailrelay --as-client smarthost:smtp --spooldir $HOME/tmp
emailrelay --as-client smarthost:smtp --spool-dir $HOME/tmp
By default E-MailRelay will reject connections from remote machines. To
allow connections from anywhere use the "--remote-clients" switch.
@ -94,6 +94,8 @@ The code has also been built successfully on:
* Solaris 8 using WorkShop 5.0
* Linux using intel c++ 6.0
* Windows NT 4.0 using MSVC 6.0
* Windows NT 4.0 using Cygwin (DLL 1.3.22) and gcc 3.2
* Windows NT 4.0 using MinGW 2.0.0 and gcc 3.2
Feedback

View File

@ -94,12 +94,13 @@ AC_DEFUN([ACLOCAL_CHECK_BUGGY_CTIME],
])
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
dnl gcc -- maps gcc2.96 onto gcc2.95
dnl
AC_DEFUN([ACLOCAL_COMPILER_VERSION],
[
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/' | sed 's/gcc2.96/gcc2.95/'`
if test -z "${COMPILER_VERSION}"
then
COMPILER_VERSION=`$CXX -V 2>&1 | sed q | grep WorkShop | sed 's/[^0-9]*//;s/[ \.].*//;s/^/sunpro/'`

5
aclocal.m4 vendored
View File

@ -107,12 +107,13 @@ AC_DEFUN([ACLOCAL_CHECK_BUGGY_CTIME],
])
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
dnl gcc -- maps gcc2.96 onto gcc2.95
dnl
AC_DEFUN([ACLOCAL_COMPILER_VERSION],
[
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/' | sed 's/gcc2.96/gcc2.95/'`
if test -z "${COMPILER_VERSION}"
then
COMPILER_VERSION=`$CXX -V 2>&1 | sed q | grep WorkShop | sed 's/[^0-9]*//;s/[ \.].*//;s/^/sunpro/'`

View File

@ -21,23 +21,31 @@
#
# emailrelay
#
# A shell-script wrapper for E-MailRelay designed for
# use in the SysV-init system (/etc/init.d).
# A shell-script wrapper for E-MailRelay designed for use in the SysV-init
# system (/etc/init.d).
#
# See also: LSB, start_daemon (lsb), startproc (suse),
# install_initd (lsb), insserv (suse),
# /usr/share/doc/initscripts*/sysvinitfiles (redhat)
# Additional command-line switches for the emailrelay daemon are sourced
# from the file "/etc/emailrelay.conf" if it exists. Uncommented lines in this
# file have "--" prepended to them and then they are pasted onto the command
# line.
#
# usage: emailrelay { start [<emailrelay-switches>] | stop | restart | force-reload | status }
# usage: emailrelay { start | stop | restart | force-reload | status }
#
# See also: LSB, start_daemon (lsb), startproc (suse), install_initd (lsb),
# insserv (suse), /usr/share/doc/initscripts*/sysvinitfiles (redhat)
#
##
# RedHat comment block...
#
# chkconfig: 345 80 20
# description: E-MailRelay is a store-and-forward Message Transfer Agent.
# description: E-MailRelay is a SMTP proxy and store-and-forward MTA.
# pidfile: /var/run/emailrelay.pid
# processname: emailrelay
#
##
##
# LSB comment block...
#
@ -50,8 +58,9 @@
# Required-Stop: $network
# Default-Start: 345 3 4 5
# Default-Stop: 345 3 4 5
# Description: E-MailRelay store-and-forward Message Transfer Agent.
# Description: E-MailRelay SMTP proxy and store-and-forward MTA.
### END INIT INFO
##
# choose an infrastructure style
#
@ -71,229 +80,240 @@ else
style="unix"
fi
# configuration
# script configuration
#
switches=""
sbin="/sbin"
var_run="/var/run"
emailrelay="__SBIN_DIR__/emailrelay"
emailrelay="__SBIN_DIR__/emailrelay" # (absolute path required in some environments)
if test \! -d "${var_run}" ; then var_run="/tmp" ; fi
if test \! -x "${emailrelay}" ; then emailrelay="./emailrelay" ; fi
if test \! -x "${emailrelay}" ; then emailrelay="`pwd`/emailrelay" ; fi
pid_file="${var_run}/emailrelay.pid"
PATH="${PATH}:/sbin:/bin:/usr/bin"
cfg_file="/etc/emailrelay.conf"
# server configuration
#
start_switches="--as-server --pid-file ${pid_file} `cat \"${cfg_file}\" 2>/dev/null | egrep -v '^#|^ *$' | sed 's/^/--/'`"
# functions...
#
# <style>_reset() -- initialise
# <style>_message() -- do echo -n
# <style>_status() [-v] -- save errno and say ok/failed for -v
# <style>_startproc() -- start the server
# <style>_killproc() -- kill the server
# <style>_checkproc() -- return true if running
# <style>_cmd_stop() -- stop command
# <style>_cmd_start() -- stop command
# <style>_cmd_restarted() -- called after stop/start
# <style>_cmd_status() -- status command
# <style>_exit() -- exit with saved errno
function unix_reset()
unix_reset()
{
unix_errno="0"
}
function unix_message()
unix_cmd_start()
{
echo -n "${1}"
}
function unix_status()
{
shift
"$@"
unix_errno="$?"
if test "${1}" = "-v" -a "${unix_errno}" -eq 0
if test "${unix_errno}" -eq 0
then
echo " ... done"
fi
if test "${1}" = "-v" -a "${unix_errno}" -ne 0
then
else
echo " ... failed"
fi
}
function unix_startproc()
{
$@
}
function unix_killproc()
unix_cmd_stop()
{
echo -n "${1}"
if test -f "${pid_file}" && test "`cat ${pid_file}`" != ""
then
kill "`cat ${pid_file}`"
rm -f "${pid_file}" 2>/dev/null
fi
return 0
echo " ... done"
unix_errno="0" # (could do better)
}
function unix_checkproc()
unix_cmd_restarted()
{
unix_errno="$?"
}
unix_cmd_status()
{
echo -n "${1}"
if test -f "${pid_file}" && test "`cat ${pid_file}`" != "" && kill -0 "`cat ${pid_file}`" 2>/dev/null
then
return 0
echo " ... running"
unix_errno="0"
elif test -f "${pid_file}"
then
return 1
echo " ... failed"
unix_errno="1"
else
return 3
echo " ... not running"
unix_errno="3"
fi
}
function unix_exit()
unix_exit()
{
exit "${unix_errno}"
}
##
function redhat_reset()
redhat_reset()
{
redhat_errno="0"
}
function redhat_message()
redhat_cmd_start()
{
echo -n "${1}"
}
function redhat_status()
{
redhat_errno="$?"
if test "${1}" = "-v" -a "${redhat_errno}" -eq 0
then
success
fi
if test "${1}" = "-v" -a "${redhat_errno}" -ne 0
then
failure
fi
}
function redhat_startproc()
{
shift
initlog -q --cmd="$*"
redhat_errno="$?"
#touch /var/lock/subsys/emailrelay
return ${redhat_errno}
if test "${redhat_errno}" -eq 0 ; then success ; else failure ; fi
}
function redhat_killproc()
redhat_cmd_stop()
{
echo -n "${1}"
killproc "`basename ${emailrelay}`"
redhat_errno="$?"
#rm -f /var/lock/subsys/emailrelay
return ${redhat_errno}
if test "${redhat_errno}" -eq 0 ; then success ; else failure ; fi
}
function redhat_checkproc()
redhat_cmd_restarted()
{
redhat_errno="$?"
}
redhat_cmd_status()
{
echo -n "${1}"
if test -f "${pid_file}" && test "`cat ${pid_file}`" != "" && kill -0 "`cat ${pid_file}`" 2>/dev/null
then
return 0
redhat_errno="0"
elif test -f "${pid_file}"
then
return 1
redhat_errno="1"
else
return 3
redhat_errno="3"
fi
if test "${redhat_errno}" -eq 0 ; then success ; else failure ; fi
}
function redhat_exit()
redhat_exit()
{
exit "${redhat_errno}"
}
##
function suse_reset()
suse_reset()
{
rc_reset
}
function suse_message()
suse_cmd_start()
{
echo -n "${1}"
shift
startproc "$@"
rc_status -v
}
function suse_status()
suse_cmd_stop()
{
rc_status $@
echo -n "${1}"
killproc "${2}"
rc_status -v
}
function suse_startproc()
suse_cmd_restarted()
{
startproc $@
rc_status
}
function suse_killproc()
suse_cmd_status()
{
killproc $@
echo -n "${1}"
checkproc "${2}"
rc_status -v
}
function suse_checkproc()
{
checkproc $@
}
function suse_exit()
suse_exit()
{
rc_exit
}
##
function lsb_reset()
lsb_reset()
{
lsb_errno="0"
lsb_text=""
}
function lsb_message()
{
lsb_text="$@"
}
function lsb_status()
lsb_cmd_start()
{
lsb_text="${1}"
shift
start_daemon "$@"
lsb_errno=$?
if test "${lsb_errno}" -eq 0 -a "${1}" = "-v"
if test "${lsb_errno}" -eq 0
then
log_success_msg "${lsb_text}: done"
elif test "${1}" = "-v"
then
log_failure_msg "${lsb_text}: failed"
log_success_msg "${lsb_text}"
else
log_failure_msg "${lsb_text}"
fi
}
function lsb_startproc()
lsb_cmd_stop()
{
start_daemon $@
lsb_text="${1}"
killproc "`basename \"${2}\"`"
lsb_errno=$?
if test "${lsb_errno}" -eq 0
then
log_success_msg "${lsb_text}"
else
log_failure_msg "${lsb_text}"
fi
}
function lsb_killproc()
lsb_cmd_restarted()
{
killproc "`basename \"${1}\"`"
lsb_errno="$?"
}
function lsb_checkproc()
lsb_cmd_status()
{
base="`basename \"${1}\"`"
lsb_text="${1}"
base="`basename \"${2}\"`"
pids="`pidofproc \"${base}\" | sed 's/ *$//'`"
test "${pids}" != ""
if test "${pids}" != ""
then
lsb_errno="0"
log_success_msg "${lsb_text}"
else
lsb_errno="1"
log_failure_msg "${lsb_text}"
fi
}
function lsb_exit()
lsb_exit()
{
exit ${lsb_errno}
}
# check the command line
#
usage="{ start [<server-switches>] | stop | restart | force-reload | status }"
usage="{ start | stop | restart | force-reload | status }"
if test $# -eq 0
then
echo usage: `basename $0` "${usage}" >&2
@ -307,22 +327,18 @@ case "${1}" in
start)
shift
${style}_message "Starting E-MailRelay server"
${style}_startproc ${emailrelay} --as-server --pid-file "${pid_file}" ${switches} $@
${style}_status -v
${style}_cmd_start "Starting E-MailRelay server" ${emailrelay} ${start_switches} "$@"
;;
stop)
${style}_message "Shutting down E-MailRelay"
${style}_killproc "${emailrelay}"
${style}_status -v
${style}_cmd_stop "Shutting down E-MailRelay" "${emailrelay}"
;;
restart|force-reload)
shift
$0 stop
$0 start $@
${style}_status
$0 start "$@"
${style}_cmd_restarted
;;
reload)
@ -331,9 +347,7 @@ case "${1}" in
;;
status)
${style}_message "Checking for E-MailRelay"
${style}_checkproc "${emailrelay}"
${style}_status -v
${style}_cmd_status "Checking for E-MailRelay" "${emailrelay}"
;;
*)

4
configure vendored
View File

@ -1459,7 +1459,7 @@ fi
# Define the identity of the package.
PACKAGE=emailrelay
VERSION=1.1
VERSION=1.1.1
cat >>confdefs.h <<_ACEOF
@ -3274,7 +3274,7 @@ 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/' | sed 's/gcc2.96/gcc2.95/'`
if test -z "${COMPILER_VERSION}"
then
COMPILER_VERSION=`$CXX -V 2>&1 | sed q | grep WorkShop | sed 's/[^0-9]*//;s/[ \.].*//;s/^/sunpro/'`

View File

@ -21,7 +21,7 @@ dnl Process this file with autoconf to produce a configure script.
dnl
AC_INIT(src/gsmtp/gsmtp.h)
AM_INIT_AUTOMAKE(emailrelay,1.1)
AM_INIT_AUTOMAKE(emailrelay,1.1.1)
AM_CONFIG_HEADER(config.h)
dnl ===

View File

@ -23,8 +23,8 @@ txt_files=developer.txt reference.txt userguide.txt windows.txt
man_files_in=emailrelay.1 emailrelay-passwd.1 emailrelay-poke.1 emailrelay-submit.1
man_files_out=emailrelay.1.gz emailrelay-passwd.1.gz emailrelay-poke.1.gz emailrelay-submit.1.gz
html_files_in=doxygen_header.html
html_files_thru=index.html $(stylesheet)
html_files_out=readme.html developer.html reference.html userguide.html windows.html emailrelay-man.html changelog.html
html_files_thru=index.html emailrelay-man.html $(stylesheet)
html_files_out=readme.html developer.html reference.html userguide.html windows.html changelog.html
png_files=gsmtp-classes.png gnet-classes.png
EXTRA_DIST = $(man_files_in) $(txt_files) $(html_files_in) $(html_files_thru) $(png_files)

View File

@ -98,8 +98,8 @@ txt_files = developer.txt reference.txt userguide.txt windows.txt
man_files_in = emailrelay.1 emailrelay-passwd.1 emailrelay-poke.1 emailrelay-submit.1
man_files_out = emailrelay.1.gz emailrelay-passwd.1.gz emailrelay-poke.1.gz emailrelay-submit.1.gz
html_files_in = doxygen_header.html
html_files_thru = index.html $(stylesheet)
html_files_out = readme.html developer.html reference.html userguide.html windows.html emailrelay-man.html changelog.html
html_files_thru = index.html emailrelay-man.html $(stylesheet)
html_files_out = readme.html developer.html reference.html userguide.html windows.html changelog.html
png_files = gsmtp-classes.png gnet-classes.png
EXTRA_DIST = $(man_files_in) $(txt_files) $(html_files_in) $(html_files_thru) $(png_files)

434
doc/emailrelay-man.html Normal file
View File

@ -0,0 +1,434 @@
Content-type: text/html
<HTML><HEAD><TITLE>Manpage of EMAILRELAY</TITLE>
</HEAD><BODY>
<H1>EMAILRELAY</H1>
Section: User Commands (1)<BR>Updated: local<BR><A HREF="#index">Index</A>
<A HREF="http://localhost/cgi-bin/man/man2html">Return to Main Contents</A><HR>
<A NAME="lbAB">&nbsp;</A>
<H2>NAME</H2>
emailrelay - e-mail transfer agent
<A NAME="lbAC">&nbsp;</A>
<H2>SYNOPSIS</H2>
<B>emailrelay</B>
[OPTIONS]
<P>
<B>emailrelay </B>
--as-server
<P>
<B>emailrelay</B>
--as-client
<I>server-address</I>
<P>
<B>emailrelay</B>
--as-proxy
<I>server-address</I>
<A NAME="lbAD">&nbsp;</A>
<H2>DESCRIPTION</H2>
<I>emailrelay</I>
is an simple e-mail message transfer agent. It does store-and-forward
mail relay to a fixed next-hop server, without any routing.
<P>
It runs in two main modes: a storage daemon
(<I>--as-server</I>)
and a forwarding
agent
(<I>--as-client</I>).
The storage daemon is an SMTP server which stores e-mail
messages in a local spool directory. The forwarding agent acts as an
SMTP client, which passes the spooled e-mail messages on to the next
SMTP server in the chain.
<P>
It can also run in a third mode, as a proxy server
(<I>--as-proxy</I>).
In this mode all messages are forwarded immediately to the next-hop
server.
<A NAME="lbAE">&nbsp;</A>
<H2>OPTIONS</H2>
<DL COMPACT>
<DT><B>-a,--admin </B><I>admin-port</I>
<DD>
Enables the administration interface and specifies its listening port number.
<DT><B>-q,--as-client </B><I>host:port</I>
<DD>
Runs as a client, forwarding spooled mail to &lt;host&gt;: equivalent to <I>--log</I> <I>--no-syslog</I> <I>--no-daemon</I> <I>--dont-serve</I> <I>--forward</I> <I>--forward-to</I>.
<DT><B>-y,--as-proxy </B><I>host:port</I>
<DD>
Runs as a proxy: equivalent to <I>--log</I> <I>--close-stderr</I> <I>--immediate</I> <I>--forward-to</I>.
<DT><B>-d,--as-server </B>
<DD>
Runs as a server: equivalent to <I>--log</I> <I>--close-stderr</I> <I>--postmaster</I>.
<DT><B>-C,--client-auth </B><I>file</I>
<DD>
Enables authentication with remote server, using the given secrets file.
<DT><B>-e,--close-stderr </B>
<DD>
Closes the standard error stream after start-up.
<DT><B>-U,--connection-timeout </B><I>time</I>
<DD>
Sets the timeout (in seconds) when connecting to a remote server (default is 40).
<DT><B>-g,--debug </B>
<DD>
Generates debug-level logging (if compiled-in).
<DT><B>-D,--domain </B><I>fqdn</I>
<DD>
Sets an override for the host's fully qualified domain name.
<DT><B>-X,--dont-listen </B>
<DD>
Dont listen for smtp connections (usually used with <I>--admin</I>).
<DT><B>-x,--dont-serve </B>
<DD>
Dont act as a server (usually used with <I>--forward</I>).
<DT><B>-z,--filter </B><I>program</I>
<DD>
Defines a mail processor program.
<DT><B>-f,--forward </B>
<DD>
Forwards stored mail on startup (requires <I>--forward-to</I>).
<DT><B>-o,--forward-to </B><I>host:port</I>
<DD>
Specifies the remote smtp server (required by <I>--forward</I> and <I>--admin</I>).
<DT><B>-h,--help </B>
<DD>
Displays help text and exits.
<DT><B>-m,--immediate </B>
<DD>
Forwards each message as soon as it is received (requires <I>--forward-to</I>).
<DT><B>-I,--interface </B><I>ip-address</I>
<DD>
Listen on a specific interface.
<DT><B>-l,--log </B>
<DD>
Writes log information on standard error and syslog.
<DT><B>-L,--log-time </B>
<DD>
Adds a timestamp to the logging output.
<DT><B>-t,--no-daemon </B>
<DD>
Does not detach from the terminal.
<DT><B>-n,--no-syslog </B>
<DD>
Disables syslog output.
<DT><B>-i,--pid-file </B><I>pid-file</I>
<DD>
Records the daemon process-id in the given file.
<DT><B>-O,--poll </B><I>period</I>
<DD>
Enables polling with the specified period (requires <I>--forward-to</I>).
<DT><B>-p,--port </B><I>port</I>
<DD>
Specifies the smtp listening port number.
<DT><B>-P,--postmaster </B>
<DD>
Deliver to postmaster and reject all other local mailbox addresses.
<DT><B>-r,--remote-clients </B>
<DD>
Allows remote clients to connect.
<DT><B>-T,--response-timeout </B><I>time</I>
<DD>
Sets the response timeout (in seconds) when talking to a remote server (default is 1800).
<DT><B>-S,--server-auth </B><I>file</I>
<DD>
Enables authentication of remote clients, using the given secrets file.
<DT><B>-s,--spool-dir </B><I>dir</I>
<DD>
Specifies the spool directory (default is <I>/var/spool/emailrelay</I>).
<DT><B>-u,--user </B><I>username</I>
<DD>
Names the effective user to switch to when started as root (default is <I>daemon</I>).
<DT><B>-v,--verbose </B>
<DD>
Generates more verbose output (works with <I>--help</I> and <I>--log</I>).
<DT><B>-Z,--verifier </B><I>program</I>
<DD>
Defines an external address verifier program.
<DT><B>-V,--version </B>
<DD>
Displays version information and exits.
</DL>
<A NAME="lbAF">&nbsp;</A>
<H2>FILES</H2>
GNU style...
<BR>
/usr/local/libexec/emailrelay
<BR>
/usr/local/libexec/emailrelay-deliver.sh
<BR>
/usr/local/libexec/emailrelay-notify.sh
<BR>
/usr/local/libexec/emailrelay-poke
<BR>
/usr/local/libexec/emailrelay-process.sh
<BR>
/usr/local/libexec/emailrelay-resubmit.sh
<BR>
/usr/local/man/man1/emailrelay-passwd.1.gz
<BR>
/usr/local/man/man1/emailrelay-poke.1.gz
<BR>
/usr/local/man/man1/emailrelay-submit.1.gz
<BR>
/usr/local/man/man1/emailrelay.1.gz
<BR>
/usr/local/sbin/emailrelay
<BR>
/usr/local/sbin/emailrelay-passwd
<BR>
/usr/local/sbin/emailrelay-submit
<BR>
/usr/local/share/emailrelay/doc/NEWS
<BR>
/usr/local/share/emailrelay/doc/README
<BR>
/usr/local/share/emailrelay/doc/changelog.gz
<BR>
/usr/local/share/emailrelay/doc/changelog.html
<BR>
/usr/local/share/emailrelay/doc/developer.html
<BR>
/usr/local/share/emailrelay/doc/developer.txt
<BR>
/usr/local/share/emailrelay/doc/emailrelay.css
<BR>
/usr/local/share/emailrelay/doc/index.html
<BR>
/usr/local/share/emailrelay/doc/readme.html
<BR>
/usr/local/share/emailrelay/doc/reference.html
<BR>
/usr/local/share/emailrelay/doc/reference.txt
<BR>
/usr/local/share/emailrelay/doc/userguide.html
<BR>
/usr/local/share/emailrelay/doc/userguide.txt
<BR>
/usr/local/share/emailrelay/doc/windows.html
<BR>
/usr/local/share/emailrelay/doc/windows.txt
<BR>
/usr/local/var/spool/emailrelay/emailrelay.*.content
<BR>
/usr/local/var/spool/emailrelay/emailrelay.*.envelope
<P>
FHS style...
<BR>
/etc/init.d/emailrelay
<BR>
/usr/lib/emailrelay/emailrelay-poke
<BR>
/usr/sbin/emailrelay
<BR>
/usr/sbin/emailrelay-passwd
<BR>
/usr/sbin/emailrelay-submit
<BR>
/usr/share/doc/emailrelay/NEWS
<BR>
/usr/share/doc/emailrelay/README
<BR>
/usr/share/doc/emailrelay/changelog.gz
<BR>
/usr/share/doc/emailrelay/changelog.html
<BR>
/usr/share/doc/emailrelay/developer.html
<BR>
/usr/share/doc/emailrelay/developer.txt
<BR>
/usr/share/doc/emailrelay/emailrelay.css
<BR>
/usr/share/doc/emailrelay/examples/emailrelay-deliver.sh
<BR>
/usr/share/doc/emailrelay/examples/emailrelay-notify.sh
<BR>
/usr/share/doc/emailrelay/examples/emailrelay-process.sh
<BR>
/usr/share/doc/emailrelay/examples/emailrelay-resubmit.sh
<BR>
/usr/share/doc/emailrelay/index.html
<BR>
/usr/share/doc/emailrelay/readme.html
<BR>
/usr/share/doc/emailrelay/reference.html
<BR>
/usr/share/doc/emailrelay/reference.txt
<BR>
/usr/share/doc/emailrelay/userguide.html
<BR>
/usr/share/doc/emailrelay/userguide.txt
<BR>
/usr/share/doc/emailrelay/windows.html
<BR>
/usr/share/doc/emailrelay/windows.txt
<BR>
/usr/share/man/man1/emailrelay-passwd.1.gz
<BR>
/usr/share/man/man1/emailrelay-poke.1.gz
<BR>
/usr/share/man/man1/emailrelay-submit.1.gz
<BR>
/usr/share/man/man1/emailrelay.1.gz
<BR>
/var/spool/emailrelay/emailrelay.*.content
<BR>
/var/spool/emailrelay/emailrelay.*.envelope
<A NAME="lbAG">&nbsp;</A>
<H2>SEE ALSO</H2>
E-MailRelay user guide
<BR>
E-MailRelay reference
<BR>
<B><A HREF="http://localhost/cgi-bin/man/man2html?1+emailrelay-submit">emailrelay-submit</A></B>(1),
<B><A HREF="http://localhost/cgi-bin/man/man2html?1+emailrelay-poke">emailrelay-poke</A></B>(1),
<B><A HREF="http://localhost/cgi-bin/man/man2html?1+emailrelay-passwd">emailrelay-passwd</A></B>(1),
<B><A HREF="http://localhost/cgi-bin/man/man2html?3+syslog">syslog</A></B>(3),
<B><A HREF="http://localhost/cgi-bin/man/man2html?8+pppd">pppd</A></B>(8),
<B><A HREF="http://localhost/cgi-bin/man/man2html?7+init.d">init.d</A></B>(7)
<A NAME="lbAH">&nbsp;</A>
<H2>AUTHOR</H2>
Graeme Walker, mailto:<A HREF="mailto:graeme_walker@users.sourceforge.net">graeme_walker@users.sourceforge.net</A>
<P>
<HR>
<A NAME="index">&nbsp;</A><H2>Index</H2>
<DL>
<DT><A HREF="#lbAB">NAME</A><DD>
<DT><A HREF="#lbAC">SYNOPSIS</A><DD>
<DT><A HREF="#lbAD">DESCRIPTION</A><DD>
<DT><A HREF="#lbAE">OPTIONS</A><DD>
<DT><A HREF="#lbAF">FILES</A><DD>
<DT><A HREF="#lbAG">SEE ALSO</A><DD>
<DT><A HREF="#lbAH">AUTHOR</A><DD>
</DL>
<HR>
This document was created by
<A HREF="http://localhost/cgi-bin/man/man2html">man2html</A>,
using the manual pages.<BR>
Time: 12:51:06 GMT, July 05, 2003
</BODY>
</HTML>
<!-- Copyright (C) 2001-2003 Graeme Walker <graeme_walker@users.sourceforge.net>. All rights reserved. -->

View File

@ -37,7 +37,7 @@ emailrelay \- e-mail transfer agent
is an simple e-mail message transfer agent. It does store-and-forward
mail relay to a fixed next-hop server, without any routing.
.LP
It runs in two main modes: a storage deamon
It runs in two main modes: a storage daemon
.RI ( --as-server )
and a forwarding
agent

View File

@ -307,13 +307,15 @@ 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:"
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.
authentication secrets file if a trusted IP address. Under Windows there is an
additional command line argument: (1) is the file descriptor which must be
used instead of stdout, (2) is the full address, etc.
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

View File

@ -62,7 +62,7 @@ spool directory using "--spool-dir".
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:
emailrelay --as-proxy smarthost:smtp --filter $HOME/bin/addsig --spooldir $HOME/tmp
emailrelay --as-proxy smarthost:smtp --filter $HOME/bin/addsig --spool-dir $HOME/tmp
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
@ -72,11 +72,11 @@ by the address of the target SMTP server.
For example, to start a storage daemon listening on port 10025 use a command
like this:
emailrelay --as-server --port 10025 --spooldir $HOME/tmp
emailrelay --as-server --port 10025 --spool-dir $HOME/tmp
And then to forward the spooled mail to "smarthost" run somthing like this:
emailrelay --as-client smarthost:smtp --spooldir $HOME/tmp
emailrelay --as-client smarthost:smtp --spool-dir $HOME/tmp
By default E-MailRelay will reject connections from remote machines. To
allow connections from anywhere use the "--remote-clients" switch.

View File

@ -22,6 +22,10 @@ In summary, the Windows installation process is as follows:
These steps are explained in more detail below.
On versions of Windows that support services you could also try using Microsoft's
"srvany.exe" utility to run emailrelay as a service; you will need to add the
"--hidden" and "--no-daemon" switches to the E-MailRelay command-line for this.
Unpacking
---------
To start the installation process you will need to extract the files from

View File

@ -1,10 +1,10 @@
Summary: Simple e-mail message transfer agent using SMTP
Name: emailrelay
Version: 1.1
Version: 1.1.1
Release: 1
Copyright: GPL
Group: System Environment/Daemons
Source: http://emailrelay.sourceforge.net/.../emailrelay-src-1.1.tar.gz
Source: http://emailrelay.sourceforge.net/.../emailrelay-src-1.1.1.tar.gz
BuildRoot: /tmp/emailrelay-install
%define prefix /usr

View File

@ -109,7 +109,7 @@ then
echo "install: no input file specified"
exit 1
else
:
true
fi
if [ x"$dir_arg" != x ]; then
@ -120,7 +120,7 @@ if [ x"$dir_arg" != x ]; then
instcmd=:
chmodcmd=""
else
instcmd=$mkdirprog
instcmd=mkdir
fi
else
@ -128,9 +128,9 @@ else
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f "$src" ] || [ -d "$src" ]
if [ -f $src -o -d $src ]
then
:
true
else
echo "install: $src does not exist"
exit 1
@ -141,7 +141,7 @@ else
echo "install: no destination specified"
exit 1
else
:
true
fi
# If destination is a directory, append the input filename; if your system
@ -151,7 +151,7 @@ else
then
dst="$dst"/`basename $src`
else
:
true
fi
fi
@ -164,7 +164,7 @@ dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
@ -183,7 +183,7 @@ while [ $# -ne 0 ] ; do
then
$mkdirprog "${pathcomp}"
else
:
true
fi
pathcomp="${pathcomp}/"
@ -194,10 +194,10 @@ if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
@ -216,7 +216,7 @@ else
then
dstfile=`basename $dst`
else
:
true
fi
# Make a temp file name in the proper directory.
@ -235,10 +235,10 @@ else
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.

69
missing
View File

@ -1,6 +1,6 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
# Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc.
# Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc.
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
@ -78,7 +78,7 @@ Supported PROGRAM values:
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing 0.4 - GNU automake"
echo "missing 0.3 - GNU automake"
;;
-*)
@ -87,12 +87,7 @@ Supported PROGRAM values:
exit 1
;;
aclocal*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
aclocal)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
@ -102,11 +97,6 @@ WARNING: \`$1' is missing on your system. You should only need it if
;;
autoconf)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`${configure_ac}'. You might want to install the
@ -116,11 +106,6 @@ WARNING: \`$1' is missing on your system. You should only need it if
;;
autoheader)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acconfig.h' or \`${configure_ac}'. You might want
@ -139,12 +124,7 @@ WARNING: \`$1' is missing on your system. You should only need it if
touch $touch_files
;;
automake*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
automake)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
@ -155,34 +135,6 @@ WARNING: \`$1' is missing on your system. You should only need it if
while read f; do touch "$f"; done
;;
autom4te)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is needed, and you do not seem to have it handy on your
system. You might have modified some files without having the
proper tools for further handling them.
You can get \`$1Help2man' as part of \`Autoconf' from any GNU
archive site."
file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
if test -f "$file"; then
touch $file
else
test -z "$file" || exec >$file
echo "#! /bin/sh"
echo "# Created by GNU Automake missing as a replacement of"
echo "# $ $@"
echo "exit 0"
chmod +x $file
exit 1
fi
;;
bison|yacc)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
@ -237,11 +189,6 @@ WARNING: \`$1' is missing on your system. You should only need it if
;;
help2man)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
fi
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a dependency of a manual page. You may need the
@ -293,23 +240,23 @@ WARNING: \`$1' is missing on your system. You should only need it if
# Look for gnutar/gtar before invocation to avoid ugly error
# messages.
if (gnutar --version > /dev/null 2>&1); then
gnutar "$@" && exit 0
gnutar ${1+"$@"} && exit 0
fi
if (gtar --version > /dev/null 2>&1); then
gtar "$@" && exit 0
gtar ${1+"$@"} && exit 0
fi
firstarg="$1"
if shift; then
case "$firstarg" in
*o*)
firstarg=`echo "$firstarg" | sed s/o//`
tar "$firstarg" "$@" && exit 0
tar "$firstarg" ${1+"$@"} && exit 0
;;
esac
case "$firstarg" in
*h*)
firstarg=`echo "$firstarg" | sed s/h//`
tar "$firstarg" "$@" && exit 0
tar "$firstarg" ${1+"$@"} && exit 0
;;
esac
fi

View File

@ -4,53 +4,9 @@
# Created: 1993-05-16
# Public domain
# $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $
errstatus=0
dirmode=""
usage="\
Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
# process command line arguments
while test $# -gt 0 ; do
case "${1}" in
-h | --help | --h* ) # -h for help
echo "${usage}" 1>&2; exit 0 ;;
-m ) # -m PERM arg
shift
test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; }
dirmode="${1}"
shift ;;
-- ) shift; break ;; # stop option processing
-* ) echo "${usage}" 1>&2; exit 1 ;; # unknown option
* ) break ;; # first non-opt arg
esac
done
for file
do
if test -d "$file"; then
shift
else
break
fi
done
case $# in
0) exit 0 ;;
esac
case $dirmode in
'')
if mkdir -p -- . 2>/dev/null; then
echo "mkdir -p -- $*"
exec mkdir -p -- "$@"
fi ;;
*)
if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
echo "mkdir -m $dirmode -p -- $*"
exec mkdir -m "$dirmode" -p -- "$@"
fi ;;
esac
for file
do
@ -66,24 +22,13 @@ do
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp"
echo "mkdir $pathcomp"
mkdir "$pathcomp" || lasterr=$?
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
else
if test ! -z "$dirmode"; then
echo "chmod $dirmode $pathcomp"
lasterr=""
chmod "$dirmode" "$pathcomp" || lasterr=$?
if test ! -z "$lasterr"; then
errstatus=$lasterr
fi
fi
fi
if test ! -d "$pathcomp"; then
errstatus=$lasterr
fi
fi
pathcomp="$pathcomp/"
@ -92,8 +37,4 @@ done
exit $errstatus
# Local Variables:
# mode: shell-script
# sh-indentation: 3
# End:
# mkinstalldirs ends here

View File

@ -18,3 +18,4 @@
##
#
SUBDIRS = glib gnet gsmtp main win32
EXTRA_DIST = mingw.mak mingw-common.mak

View File

@ -93,6 +93,7 @@ install_sh = @install_sh@
#
#
SUBDIRS = glib gnet gsmtp main win32
EXTRA_DIST = mingw.mak mingw-common.mak
subdir = src
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h

View File

@ -24,6 +24,7 @@ EXTRA_DIST=\
gdatetime_win32.cpp \
gdirectory_win32.cpp \
gfs_win32.cpp \
gidentity_win32.cpp \
glogoutput_win32.cpp \
gmd5_aladdin.cpp \
gprocess_win32.cpp \
@ -31,7 +32,8 @@ EXTRA_DIST=\
gregistry_win32.cpp \
gregistry.h \
md5c.c \
md5.h
md5.h \
mingw.mak
INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION)
noinst_LIBRARIES = libglib.a
libglib_a_SOURCES = \
@ -63,6 +65,8 @@ libglib_a_SOURCES = \
gfs_unix.cpp \
ggetopt.cpp \
ggetopt.h \
gidentity.h \
gidentity_unix.cpp \
glog.cpp \
glog.h \
glogoutput.cpp \

View File

@ -99,6 +99,7 @@ EXTRA_DIST = \
gdatetime_win32.cpp \
gdirectory_win32.cpp \
gfs_win32.cpp \
gidentity_win32.cpp \
glogoutput_win32.cpp \
gmd5_aladdin.cpp \
gprocess_win32.cpp \
@ -106,7 +107,8 @@ EXTRA_DIST = \
gregistry_win32.cpp \
gregistry.h \
md5c.c \
md5.h
md5.h \
mingw.mak
INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION)
noinst_LIBRARIES = libglib.a
@ -139,6 +141,8 @@ libglib_a_SOURCES = \
gfs_unix.cpp \
ggetopt.cpp \
ggetopt.h \
gidentity.h \
gidentity_unix.cpp \
glog.cpp \
glog.h \
glogoutput.cpp \
@ -179,8 +183,8 @@ am_libglib_a_OBJECTS = garg.$(OBJEXT) garg_unix.$(OBJEXT) \
gdatetime.$(OBJEXT) gdatetime_unix.$(OBJEXT) \
gdirectory.$(OBJEXT) gdirectory_unix.$(OBJEXT) \
gexception.$(OBJEXT) gfile.$(OBJEXT) gfile_unix.$(OBJEXT) \
gfs_unix.$(OBJEXT) ggetopt.$(OBJEXT) glog.$(OBJEXT) \
glogoutput.$(OBJEXT) glogoutput_unix.$(OBJEXT) \
gfs_unix.$(OBJEXT) ggetopt.$(OBJEXT) gidentity_unix.$(OBJEXT) \
glog.$(OBJEXT) glogoutput.$(OBJEXT) glogoutput_unix.$(OBJEXT) \
gmd5_rsa.$(OBJEXT) gpath.$(OBJEXT) gpidfile.$(OBJEXT) \
gprocess_unix.$(OBJEXT) groot.$(OBJEXT) gslot.$(OBJEXT) \
gstr.$(OBJEXT) gtime.$(OBJEXT)
@ -202,7 +206,8 @@ am__depfiles_maybe = depfiles
@AMDEP_TRUE@ ./$(DEPDIR)/gdirectory_unix.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/gexception.Po ./$(DEPDIR)/gfile.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/gfile_unix.Po ./$(DEPDIR)/gfs_unix.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/ggetopt.Po ./$(DEPDIR)/glog.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/ggetopt.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/gidentity_unix.Po ./$(DEPDIR)/glog.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/glogoutput.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/glogoutput_unix.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/gmd5_rsa.Po ./$(DEPDIR)/gpath.Po \
@ -262,6 +267,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gfile_unix.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gfs_unix.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ggetopt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gidentity_unix.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_unix.Po@am__quote@

View File

@ -98,9 +98,16 @@
// Include main o/s headers
//
#if defined( G_WINDOWS )
#if defined( G_WINDOWS ) && defined( G_MINGW )
#define __USE_W32_SOCKETS
#include <windows.h>
#include <shellapi.h>
#include <sys/stat.h>
#include <unistd.h>
#elif defined( G_WINDOWS )
#include <windows.h>
#include <shellapi.h>
#include <direct.h>
#else
#include <unistd.h>
#include <sys/stat.h>
@ -145,7 +152,9 @@
typedef int ssize_t ;
typedef int uid_t ;
typedef int gid_t ;
typedef unsigned int pid_t ;
#if ! defined( G_MINGW )
typedef unsigned int pid_t ;
#endif
#endif
// Modify compiler error handling

130
src/glib/gidentity.h Normal file
View File

@ -0,0 +1,130 @@
//
// 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.
//
// ===
//
// gidentity.h
//
#ifndef G_IDENTITY_H
#define G_IDENTITY_H
#include "gdef.h"
#include "gexception.h"
#include <string>
#include <iostream>
namespace G
{
class Identity ;
class IdentityUser ;
}
// Class: Identity
// Description: A very low-level interface to getpwnam() and the get/set/e/uid/gid functions.
// See also: Process, Root
//
class G::Identity
{
public:
G_EXCEPTION( NoSuchUser , "no such user" ) ;
G_EXCEPTION( UidError , "cannot set uid" ) ;
G_EXCEPTION( GidError , "cannot set gid" ) ;
explicit Identity( const std::string & login_name ) ;
// Constructor for the named identity.
// Throws if NoSuchUser.
static Identity effective() ;
// Returns the current effective identity.
static Identity real() ;
// Returns the calling process's real identity.
static Identity root() ;
// Returns the superuser identity.
static Identity invalid() ;
// Returns an invalid identity.
bool isRoot() const ;
// Returns true if the userid is zero.
std::string str() const ;
// Returns a string representation.
void setRealUser( bool do_throw = true ) ;
// Sets the real userid.
void setEffectiveUser( bool do_throw = true ) ;
// Sets the effective userid.
void setRealGroup( bool do_throw = true ) ;
// Sets the real group id.
void setEffectiveGroup( bool do_throw = true ) ;
// Sets the effective group id.
bool operator==( const Identity & ) const ;
// Comparison operator.
bool operator!=( const Identity & ) const ;
// Comparison operator.
private:
Identity() ; // no throw
private:
uid_t m_uid ;
gid_t m_gid ;
} ;
// Class: IdentityUser
// Description: A convenience class which, when used as a private base,
// can improve readability when calling Identity 'set' methods.
//
class G::IdentityUser
{
protected:
static void setRealUserTo( Identity , bool do_throw = true ) ;
// Sets the real userid.
static void setEffectiveUserTo( Identity , bool do_throw = true ) ;
// Sets the effective userid.
static void setRealGroupTo( Identity , bool do_throw = true ) ;
// Sets the real group id.
static void setEffectiveGroupTo( Identity , bool do_throw = true ) ;
// Sets the effective group id.
private:
IdentityUser() ; // not implemented
} ;
namespace G
{
inline
std::ostream & operator<<( std::ostream & stream , const G::Identity & identity )
{
return stream << identity.str() ;
}
}
#endif

139
src/glib/gidentity_unix.cpp Normal file
View File

@ -0,0 +1,139 @@
//
// 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.
//
// ===
//
// gidentity_unix.cpp
//
// Note that gcc requires -D_BSD_SOURCE for seteuid().
//
#include "gdef.h"
#include "gidentity.h"
#include <sstream>
#include <pwd.h> // getpwnam()
G::Identity::Identity() :
m_uid(static_cast<uid_t>(-1)) ,
m_gid(static_cast<gid_t>(-1))
{
}
G::Identity::Identity( const std::string & name ) :
m_uid(static_cast<uid_t>(-1)) ,
m_gid(static_cast<gid_t>(-1))
{
::passwd * pw = ::getpwnam( name.c_str() ) ;
if( pw == NULL ) throw NoSuchUser(name) ;
m_uid = pw->pw_uid ;
m_gid = pw->pw_gid ;
}
G::Identity G::Identity::effective()
{
G::Identity id ;
id.m_uid = ::geteuid() ;
id.m_gid = ::getegid() ;
return id ;
}
G::Identity G::Identity::real()
{
G::Identity id ;
id.m_uid = ::getuid() ;
id.m_gid = ::getgid() ;
return id ;
}
G::Identity G::Identity::invalid()
{
return G::Identity() ;
}
G::Identity G::Identity::root()
{
G::Identity id ;
id.m_uid = 0 ;
id.m_gid = 0 ;
return id ;
}
std::string G::Identity::str() const
{
std::ostringstream ss ;
ss << m_uid << "/" << m_gid ;
return ss.str() ;
}
bool G::Identity::isRoot() const
{
return m_uid == 0 ;
}
bool G::Identity::operator==( const Identity & other ) const
{
return m_uid == other.m_uid && m_gid == other.m_gid ;
}
bool G::Identity::operator!=( const Identity & other ) const
{
return ! operator==( other ) ;
}
void G::Identity::setEffectiveUser( bool do_throw )
{
if( ::seteuid(m_uid) && do_throw ) throw UidError() ;
}
void G::Identity::setRealUser( bool do_throw )
{
if( ::setuid(m_uid) && do_throw ) throw UidError() ;
}
void G::Identity::setEffectiveGroup( bool do_throw )
{
if( ::setegid(m_gid) && do_throw ) throw GidError() ;
}
void G::Identity::setRealGroup( bool do_throw )
{
if( ::setgid(m_gid) && do_throw ) throw GidError() ;
}
// ===
void G::IdentityUser::setRealUserTo( Identity id , bool do_throw )
{
id.setRealUser( do_throw ) ;
}
void G::IdentityUser::setEffectiveUserTo( Identity id , bool do_throw )
{
id.setEffectiveUser( do_throw ) ;
}
void G::IdentityUser::setRealGroupTo( Identity id , bool do_throw )
{
id.setRealGroup( do_throw ) ;
}
void G::IdentityUser::setEffectiveGroupTo( Identity id , bool do_throw )
{
id.setEffectiveGroup( do_throw ) ;
}

View File

@ -0,0 +1,113 @@
//
// 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.
//
// ===
//
// gidentity_win32.cpp
//
#include "gdef.h"
#include "gidentity.h"
#include <sstream>
G::Identity::Identity() :
m_uid(0) ,
m_gid(0)
{
}
G::Identity::Identity( const std::string & ) :
m_uid(0) ,
m_gid(0)
{
}
G::Identity G::Identity::effective()
{
return G::Identity() ;
}
G::Identity G::Identity::real()
{
return G::Identity() ;
}
G::Identity G::Identity::invalid()
{
return G::Identity() ;
}
G::Identity G::Identity::root()
{
return G::Identity() ;
}
std::string G::Identity::str() const
{
return "-1/-1" ;
}
bool G::Identity::isRoot() const
{
return false ;
}
bool G::Identity::operator==( const Identity & other ) const
{
return true ;
}
bool G::Identity::operator!=( const Identity & other ) const
{
return false ;
}
void G::Identity::setEffectiveUser( bool do_throw )
{
}
void G::Identity::setRealUser( bool do_throw )
{
}
void G::Identity::setEffectiveGroup( bool do_throw )
{
}
void G::Identity::setRealGroup( bool do_throw )
{
}
// ===
void G::IdentityUser::setRealUserTo( Identity , bool )
{
}
void G::IdentityUser::setEffectiveUserTo( Identity , bool )
{
}
void G::IdentityUser::setRealGroupTo( Identity , bool )
{
}
void G::IdentityUser::setEffectiveGroupTo( Identity , bool )
{
}

View File

@ -26,6 +26,7 @@
#include "gdef.h"
#include "gexception.h"
#include "gidentity.h"
#include "gpath.h"
#include "gstrings.h"
#include <iostream>
@ -41,17 +42,15 @@ namespace G
// Description: A static interface for doing things with processes.
// See also: G::Daemon
//
class G::Process
class G::Process : private G::IdentityUser
{
public:
G_EXCEPTION( CannotFork , "cannot fork()" ) ;
G_EXCEPTION( CannotChroot , "cannot chroot()" ) ;
G_EXCEPTION( CannotChangeDirectory , "cannot cd()" ) ;
G_EXCEPTION( WaitError , "cannot wait()" ) ;
G_EXCEPTION( ChildError , "child process terminated abnormally or stopped" ) ;
G_EXCEPTION( InvalidPath , "invalid executable path -- must be absolute" ) ;
G_EXCEPTION( NoSuchUser , "no such user" ) ;
G_EXCEPTION( UidError , "cannot set uid" ) ;
G_EXCEPTION( GidError , "cannot set gid" ) ;
G_EXCEPTION( Insecure , "refusing to exec() while the user-id is zero" ) ;
G_EXCEPTION( InvalidId , "invalid process-id string" ) ;
G_EXCEPTION( PipeError , "pipe error" ) ;
@ -68,14 +67,6 @@ public:
private: pid_t m_pid ;
friend class Process ;
} ;
struct Identity // Used by G::Process::beSpecial().
{
uid_t uid ;
gid_t gid ;
Identity() ;
explicit Identity( const std::string & login_name ) ;
std::string str() const ;
} ;
class Umask // Used to temporarily modify the process umask.
{
public: enum Mode { Readable , Tighter , Tightest } ;
@ -103,6 +94,9 @@ public:
// Changes directory. Returns false on
// error.
static void chroot( const Path & dir ) ;
// Does a chroot. Throws on error, or if not implemented.
static Who fork() ;
// Forks a child process.
@ -121,22 +115,26 @@ public:
static int errno_() ;
// Returns the process's current 'errno' value.
static void beSpecial( Identity special , bool change_group = true ) ;
// Aquires special privileges (either root
// or suid). The parameter must have come from
// a previous call to beOrdinary().
static Identity beOrdinary( Identity nobody , bool change_group = true ) ;
// Revokes special privileges (root or suid).
//
// If really root (as opposed to suid root)
// then the effective id is changed to that
// passed in.
//
// If suid (including suid-root), then the effective
// id is changed to the real id, and the parameter
// is ignored.
//
// Returns the old identity, which can be passed to
// beSpecial().
//
// See also class G::Root.
static Identity beOrdinary( Identity nobody , bool change_group = true ) ;
// Revokes special privileges (root or suid).
// If really root (as opposed to suid root)
// then the effective id is changed to that
// passed in. If suid, then the effective
// id is changed to the real id, and the
// parameter is ignored. Returns the old
// identity, which can be passed to
// beSpecial().
static void beSpecial( Identity special , bool change_group = true ) ;
// Re-aquires special privileges (either root
// or suid). The parameter must have come from
// a previous call to beOrdinary().
//
// See also class G::Root.
@ -163,12 +161,6 @@ namespace G
id = G::Process::Id( stream ) ;
return stream ;
}
inline
std::ostream & operator<<( std::ostream & stream , const G::Process::Identity & identity )
{
return stream << identity.str() ;
}
}
#endif

View File

@ -23,6 +23,7 @@
#include "gdef.h"
#include "gprocess.h"
#include "gidentity.h"
#include "gassert.h"
#include "gfs.h"
#include "glog.h"
@ -31,7 +32,6 @@
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h> // open()
#include <pwd.h> // getpwnam()
#include <unistd.h> // setuid() etc
namespace
@ -90,6 +90,19 @@ bool G::Process::cd( const Path & dir , NoThrow )
return 0 == ::chdir( dir.str().c_str() ) ;
}
//static
void G::Process::chroot( const Path & dir )
{
cd( dir ) ;
if( 0 != ::chroot( dir.str().c_str() ) )
{
int error = errno_() ;
G_DEBUG( "G::Process::chroot: " << error ) ;
throw CannotChroot( dir.str() ) ;
}
cd( "/" ) ;
}
//static
void G::Process::closeStderr()
{
@ -218,7 +231,7 @@ int G::Process::spawn( Identity nobody , const Path & exe , const Strings & args
if( exe.isRelative() )
throw InvalidPath( exe.str() ) ;
if( ::geteuid() == 0U || nobody.uid == 0U )
if( Identity::effective().isRoot() || nobody.isRoot() )
throw Insecure() ;
Pipe pipe( pipe_result_p != NULL ) ;
@ -274,48 +287,41 @@ void G::Process::execCore( const G::Path & exe , const Strings & args )
void G::Process::beSpecial( Identity identity , bool change_group )
{
// try to change our effective id -- this
// will only work if our real uid is root, or if
// the executable is suid (assuming the
// o/s supports the saved-suid feature)
//
// gcc requires -D_BSD_SOURCE for seteuid()
//
Identity old_identity ;
G_IGNORE ::seteuid( identity.uid ) ;
if( change_group) G_IGNORE ::setegid( identity.gid ) ;
//G_DEBUG( "G::Process::beSpecial: " << old_identity << " -> " << Identity() ) ;
old_identity.uid = 0 ; // pacify the compiler
const bool do_throw = false ; // only works if really root or if executable is suid
setEffectiveUserTo( identity , do_throw ) ;
if( change_group) setEffectiveGroupTo( identity , do_throw ) ;
}
G::Process::Identity G::Process::beOrdinary( Identity nobody , bool change_group )
G::Identity G::Process::beOrdinary( Identity nobody , bool change_group )
{
Identity special_identity ;
if( ::getuid() == 0 )
Identity special_identity( Identity::effective() ) ;
if( Identity::real().isRoot() )
{
if( ::seteuid(0) ) throw UidError("0") ; // first
if( change_group && ::setegid(nobody.gid) ) throw GidError(nobody.str()) ; // second
if( ::seteuid(nobody.uid) ) throw UidError(nobody.str()) ; // third
setEffectiveUserTo( Identity::root() ) ;
if( change_group )
setEffectiveGroupTo( nobody ) ;
setEffectiveUserTo( nobody ) ;
}
else
{
// switch our effective id back to our real id --
// ie. turn off the effects of a suid executable
if( ::seteuid( ::getuid() ) ) throw UidError() ;
if( change_group && ::setegid( ::getgid() ) ) throw GidError() ;
setEffectiveUserTo( Identity::real() ) ;
if( change_group )
setEffectiveGroupTo( Identity::real() ) ;
}
//G_DEBUG( "G::Process::beOrdinary: " << special_identity << " -> " << Identity() ) ;
return special_identity ;
}
void G::Process::beNobody( Identity nobody )
{
if( ::getuid() == 0 )
// this private method is only used before an exec()
// so the effective ids are lost anyway -- the
// Identity will only be valid if getuid() is zero
if( Identity::real().isRoot() )
{
// set the *real* userid
if( ::seteuid(0) ) throw UidError("0") ; // first
if( ::setgid(nobody.gid) ) throw GidError(nobody.str()) ; // second
if( ::setuid(nobody.uid) ) throw UidError(nobody.str()) ; // third
setEffectiveUserTo( Identity::root() ) ;
setRealGroupTo( nobody ) ;
setRealUserTo( nobody ) ;
}
}
@ -361,36 +367,6 @@ bool G::Process::Id::operator==( const Id & other ) const
// ===
G::Process::Identity::Identity() :
uid(::geteuid()) ,
gid(::getegid())
{
}
G::Process::Identity::Identity( const std::string & name ) :
uid(static_cast<uid_t>(-1)) ,
gid(static_cast<gid_t>(-1))
{
if( ::getuid() == 0 )
{
::passwd * pw = ::getpwnam( name.c_str() ) ;
if( pw == NULL )
throw Process::NoSuchUser(name) ;
//G_DEBUG( "G::Process::Identity: " << name << "=" << pw->pw_uid << "/" << pw->pw_gid ) ;
uid = pw->pw_uid ;
gid = pw->pw_gid ;
}
}
std::string G::Process::Identity::str() const
{
std::ostringstream ss ;
ss << uid << "/" << gid ;
return ss.str() ;
}
// ===
class G::Process::Umask::UmaskImp // A private implementation class used by G::Process::Umask.
{
public:

View File

@ -29,14 +29,13 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <process.h>
#include <direct.h>
#include <io.h>
#include <fcntl.h>
namespace G
{
const int STDERR_FILENO = 2 ;
const int SC_OPEN_MAX = 256 ; // 32 in limits.h !?
const int g_stderr_fileno = 2 ;
const int g_sc_open_max = 256 ; // 32 in limits.h !?
class Pipe ;
} ;
@ -144,17 +143,17 @@ bool G::Process::Id::operator==( const Id & rhs ) const
void G::Process::closeFiles( bool keep_stderr )
{
const int n = SC_OPEN_MAX ;
const int n = g_sc_open_max ;
for( int fd = 0 ; fd < n ; fd++ )
{
if( !keep_stderr || fd != STDERR_FILENO )
if( !keep_stderr || fd != g_stderr_fileno )
::_close( fd ) ;
}
}
void G::Process::closeStderr()
{
int fd = STDERR_FILENO ;
int fd = g_stderr_fileno ;
::_close( fd ) ;
}
@ -208,7 +207,7 @@ int G::Process::spawn( Identity , const Path & exe , const Strings & args_ ,
return rc < 0 ? error_return : rc ;
}
G::Process::Identity G::Process::beOrdinary( Identity identity , bool )
G::Identity G::Process::beOrdinary( Identity identity , bool )
{
// not implemented
return identity ;
@ -228,25 +227,6 @@ void G::Process::beSpecial( Identity , bool )
// ===
G::Process::Identity::Identity() :
uid(0) ,
gid(0)
{
}
G::Process::Identity::Identity( const std::string & ) :
uid(0) ,
gid(0)
{
}
std::string G::Process::Identity::str() const
{
return "0/0" ;
}
// ===
G::Process::Umask::Umask( G::Process::Umask::Mode ) :
m_imp(0)
{

View File

@ -27,8 +27,8 @@
#include "gdebug.h"
G::Root * G::Root::m_this = NULL ;
G::Process::Identity G::Root::m_special ;
G::Process::Identity G::Root::m_nobody ;
G::Identity G::Root::m_special( G::Identity::invalid() ) ;
G::Identity G::Root::m_nobody( G::Identity::invalid() ) ;
G::Root::Root( bool change_group ) :
m_change_group(change_group)
@ -63,12 +63,12 @@ G::Root::~Root()
//static
void G::Root::init( const std::string & nobody )
{
m_nobody = Process::Identity( nobody ) ;
m_nobody = nobody.empty() ? Identity::invalid() : Identity(nobody) ;
m_special = Process::beOrdinary( m_nobody ) ;
}
//static
G::Process::Identity G::Root::nobody()
G::Identity G::Root::nobody()
{
return m_nobody ;
}

View File

@ -25,7 +25,7 @@
#define G_ROOT_H
#include "gdef.h"
#include "gprocess.h"
#include "gidentity.h"
#include "gnoncopyable.h"
namespace G
@ -35,7 +35,7 @@ namespace G
// Class: G::Root
// Description: A class which aquires special privileges.
// The implementation uses G::Process.
// The implementation uses G::Process and G::Identity.
//
class G::Root : private G::noncopyable
{
@ -54,14 +54,14 @@ public:
// gives a non-privileged username which
// is used if the real user-id is root.
static Process::Identity nobody() ;
static Identity nobody() ;
// Returns the 'nobody' identity.
// Precondition: init() called
private:
static Root * m_this ;
static Process::Identity m_special ;
static Process::Identity m_nobody ;
static Identity m_special ;
static Identity m_nobody ;
bool m_change_group ;
} ;

62
src/glib/mingw.mak Normal file
View File

@ -0,0 +1,62 @@
#
## 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.
##
#
#
# mingw.mak
#
mk_sources=\
garg.cpp \
garg_win32.cpp \
gcleanup_win32.cpp \
gdaemon_win32.cpp \
gdate.cpp \
gdatetime.cpp \
gdatetime_win32.cpp \
gdirectory.cpp \
gdirectory_win32.cpp \
gexception.cpp \
gfile.cpp \
gfile_win32.cpp \
gfs_win32.cpp \
ggetopt.cpp \
gidentity_win32.cpp \
glog.cpp \
glogoutput.cpp \
glogoutput_win32.cpp \
gmd5_rsa.cpp \
gpath.cpp \
gpidfile.cpp \
gprocess_win32.cpp \
gregistry_win32.cpp \
groot.cpp \
gslot.cpp \
gstr.cpp \
gtime.cpp
mk_target=glib.a
all: $(mk_target)
include ../mingw-common.mak
$(mk_target): $(mk_objects)
$(mk_ar) $(mk_target) $(mk_objects)

View File

@ -27,7 +27,8 @@ EXTRA_DIST=\
gresolve_win32.cpp \
gsocket_win32.cpp \
gaddress_ipv6.cpp \
gresolve_ipv6.cpp
gresolve_ipv6.cpp \
mingw.mak
INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib
noinst_LIBRARIES = libgnet.a
libgnet_a_SOURCES = gaddress_ipv4.cpp \

View File

@ -102,7 +102,8 @@ EXTRA_DIST = \
gresolve_win32.cpp \
gsocket_win32.cpp \
gaddress_ipv6.cpp \
gresolve_ipv6.cpp
gresolve_ipv6.cpp \
mingw.mak
INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib
noinst_LIBRARIES = libgnet.a

55
src/gnet/mingw.mak Normal file
View File

@ -0,0 +1,55 @@
#
## 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.
##
#
#
# mingw.mak
#
mk_sources=\
gaddress_ipv4.cpp \
gclient.cpp \
gclient_win32.cpp \
gconnection.cpp \
gdescriptor_win32.cpp \
geventhandler.cpp \
geventloop.cpp \
geventloop_win32.cpp \
geventserver.cpp \
glinebuffer.cpp \
glocal.cpp \
glocal_win32.cpp \
gmonitor.cpp \
grequest.cpp \
gresolve.cpp \
gresolve_ipv4.cpp \
gresolve_win32.cpp \
gserver.cpp \
gsocket.cpp \
gsocket_win32.cpp \
gtimer.cpp
mk_target=gnet.a
all: $(mk_target)
include ../mingw-common.mak
$(mk_target): $(mk_objects)
$(mk_ar) $(mk_target) $(mk_objects)

View File

@ -20,7 +20,8 @@
EXTRA_DIST=\
gmessagestore_win32.cpp \
gsasl_cyrus.cpp
gsasl_cyrus.cpp \
mingw.mak
INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib -I$(top_srcdir)/src/gnet -DG_SPOOLDIR=\"$(e_spooldir)\"

View File

@ -95,7 +95,8 @@ install_sh = @install_sh@
EXTRA_DIST = \
gmessagestore_win32.cpp \
gsasl_cyrus.cpp
gsasl_cyrus.cpp \
mingw.mak
INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib -I$(top_srcdir)/src/gnet -DG_SPOOLDIR=\"$(e_spooldir)\"

View File

@ -29,6 +29,7 @@
#include "gmessagestore.h"
#include "gdatetime.h"
#include "gexception.h"
#include "gprocess.h"
#include "gnoncopyable.h"
#include "gslot.h"
#include "groot.h"
@ -45,8 +46,16 @@ namespace GSmtp
// Class: GSmtp::FileStore
// Description: A concrete implementation of the MessageStore
// interface, dealing in flat files. Passes out unique sequence
// numbers, filesystem paths and i/o streams to NewMessageImp.
// interface, dealing in paired flat files.
//
// The implementation puts separate envelope and content files
// in the spool directory. The content file is written first.
// The presence of a matching envelope file is used to indicate
// that the content file is valid and that it has been commited
// to the care of the SMTP system for delivery.
//
// Passes out unique sequence numbers, filesystem paths and
// i/o streams to NewMessageImp.
//
class GSmtp::FileStore : public GSmtp::MessageStore
{

View File

@ -41,13 +41,6 @@ namespace GSmtp
// Description: A class which allows SMTP messages
// (envelope+content) to be stored and retrieved.
//
// The implementation puts separate envelope and content
// files in a spool directory. The content file is
// written first. The presence of a matching envelope
// file is used to indicate that the content file
// is valid and that it has been commited to the
// care of the SMTP system for delivery.
//
// See also: NewMessage, StoredMessage, ProtocolMessage
//
class GSmtp::MessageStore

54
src/gsmtp/mingw.mak 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.
##
#
#
# mingw.mak
#
mk_sources=\
gadminserver.cpp \
gbase64.cpp \
gclientprotocol.cpp \
gfilestore.cpp \
gmessagestore.cpp \
gmessagestore_win32.cpp \
gnewfile.cpp \
gnewmessage.cpp \
gprotocolmessage.cpp \
gprotocolmessageforward.cpp \
gprotocolmessagestore.cpp \
gsasl_native.cpp \
gsecrets.cpp \
gserverprotocol.cpp \
gsmtpclient.cpp \
gsmtpserver.cpp \
gstoredfile.cpp \
gstoredmessage.cpp \
gverifier.cpp \
gxtext.cpp
mk_target=gsmtp.a
all: $(mk_target)
include ../mingw-common.mak
$(mk_target): $(mk_objects)
$(mk_ar) $(mk_target) $(mk_objects)

View File

@ -22,7 +22,6 @@
AM_INSTALL_PROGRAM_FLAGS=-s
EXTRA_DIST=\
commandline_win32.cpp \
common.dsp \
doxygen.cfg \
doxygen.h \
@ -53,16 +52,18 @@ e_libexec_PROGRAMS = emailrelay-poke
e_spool_DATA =
emailrelay_SOURCES = \
main.cpp \
commandline.cpp \
commandline.h \
configuration.cpp \
configuration.h \
legal.cpp \
legal.h \
main.cpp \
output.cpp \
output.h \
run.cpp \
run.h \
commandline.cpp \
commandline_unix.cpp \
commandline.h
mingw.mak
emailrelay_LDADD = \
$(top_builddir)/src/gsmtp/libgsmtp.a \

View File

@ -97,7 +97,6 @@ install_sh = @install_sh@
AM_INSTALL_PROGRAM_FLAGS = -s
EXTRA_DIST = \
commandline_win32.cpp \
common.dsp \
doxygen.cfg \
doxygen.h \
@ -129,16 +128,18 @@ e_libexec_PROGRAMS = emailrelay-poke
e_spool_DATA =
emailrelay_SOURCES = \
main.cpp \
commandline.cpp \
commandline.h \
configuration.cpp \
configuration.h \
legal.cpp \
legal.h \
main.cpp \
output.cpp \
output.h \
run.cpp \
run.h \
commandline.cpp \
commandline_unix.cpp \
commandline.h
mingw.mak
emailrelay_LDADD = \
@ -168,9 +169,8 @@ e_sbin_PROGRAMS = emailrelay$(EXEEXT) emailrelay-submit$(EXEEXT) \
emailrelay-passwd$(EXEEXT)
PROGRAMS = $(e_libexec_PROGRAMS) $(e_sbin_PROGRAMS)
am_emailrelay_OBJECTS = main.$(OBJEXT) configuration.$(OBJEXT) \
legal.$(OBJEXT) run.$(OBJEXT) commandline.$(OBJEXT) \
commandline_unix.$(OBJEXT)
am_emailrelay_OBJECTS = commandline.$(OBJEXT) configuration.$(OBJEXT) \
legal.$(OBJEXT) main.$(OBJEXT) output.$(OBJEXT) run.$(OBJEXT)
emailrelay_OBJECTS = $(am_emailrelay_OBJECTS)
emailrelay_DEPENDENCIES = $(top_builddir)/src/gsmtp/libgsmtp.a \
$(top_builddir)/src/glib/libglib.a \
@ -199,11 +199,10 @@ LIBS = @LIBS@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/commandline.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/commandline_unix.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/configuration.Po ./$(DEPDIR)/legal.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/main.Po ./$(DEPDIR)/passwd.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/poke.Po ./$(DEPDIR)/run.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/submit.Po
@AMDEP_TRUE@ ./$(DEPDIR)/main.Po ./$(DEPDIR)/output.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/passwd.Po ./$(DEPDIR)/poke.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/run.Po ./$(DEPDIR)/submit.Po
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
@ -299,10 +298,10 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/commandline.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/commandline_unix.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/configuration.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/legal.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/passwd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poke.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run.Po@am__quote@

View File

@ -32,15 +32,18 @@
#include "gdebug.h"
//static
std::string Main::CommandLine::switchSpec()
std::string Main::CommandLine::switchSpec( bool is_windows )
{
std::string dir = GSmtp::MessageStore::defaultDirectory().str() ;
std::ostringstream ss ;
ss
<< osSwitchSpec() << "|"
<< "q!as-client!runs as a client, forwarding spooled mail to <host>: equivalent to \"--log --no-syslog --no-daemon --dont-serve --forward --forward-to\"!" << "1!host:port!1|"
<< (is_windows?switchSpec_windows():switchSpec_unix()) << "|"
<< "q!as-client!runs as a client, forwarding spooled mail to <host>: "
<< "equivalent to \"--log --no-syslog --no-daemon --dont-serve --forward --forward-to\"!"
<< "1!host:port!1|"
<< "d!as-server!runs as a server: equivalent to \"--log --close-stderr --postmaster\"!0!!1|"
<< "y!as-proxy!runs as a proxy: equivalent to \"--log --close-stderr --immediate --forward-to\"!1!host:port!1|"
<< "y!as-proxy!runs as a proxy: equivalent to \"--log --close-stderr --immediate --forward-to\"!"
<< "1!host:port!1|"
<< "v!verbose!generates more verbose output (works with --help and --log)!0!!1|"
<< "h!help!displays help text and exits!0!!1|"
<< ""
@ -54,15 +57,18 @@ std::string Main::CommandLine::switchSpec()
<< "L!log-time!adds a timestamp to the logging output!0!!3|"
<< "S!server-auth!enables authentication of remote clients, using the given secrets file!1!file!3|"
<< "e!close-stderr!closes the standard error stream after start-up!0!!3|"
<< "a!admin!enables the administration interface and specifies its listening port number!1!admin-port!3|"
<< "a!admin!enables the administration interface and specifies its listening port number!"
<< "1!admin-port!3|"
<< "x!dont-serve!dont act as a server (usually used with --forward)!0!!3|"
<< "X!dont-listen!dont listen for smtp connections (usually used with --admin)!0!!3|"
<< "z!filter!defines a mail processor program!1!program!3|"
<< "D!domain!sets an override for the host's fully qualified domain name!1!fqdn!3|"
<< "f!forward!forwards stored mail on startup (requires --forward-to)!0!!3|"
<< "o!forward-to!specifies the remote smtp server (required by --forward and --admin)!1!host:port!3|"
<< "T!response-timeout!sets the response timeout (in seconds) when talking to a remote server (default is 1800)!1!time!3|"
<< "U!connection-timeout!sets the timeout (in seconds) when connecting to a remote server (default is 40)!1!time!3|"
<< "T!response-timeout!sets the response timeout (in seconds) when talking to a remote server "
<< "(default is 1800)!1!time!3|"
<< "U!connection-timeout!sets the timeout (in seconds) when connecting to a remote server "
<< "(default is 40)!1!time!3|"
<< "m!immediate!forwards each message as soon as it is received (requires --forward-to)!0!!3|"
<< "I!interface!listen on a specific interface!1!ip-address!3|"
<< "i!pid-file!records the daemon process-id in the given file!1!pid-file!3|"
@ -74,10 +80,40 @@ std::string Main::CommandLine::switchSpec()
return ss.str() ;
}
Main::CommandLine::CommandLine( const G::Arg & arg , const std::string & version ) :
m_version(version) ,
m_arg(arg) ,
m_getopt( m_arg , switchSpec() , '|' , '!' , '^' )
//static
std::string Main::CommandLine::switchSpec_unix()
{
std::ostringstream ss ;
ss
<< "l!log!writes log information on standard error and syslog!0!!2|"
<< "t!no-daemon!does not detach from the terminal!0!!3|"
<< "u!user!names the effective user to switch to when started as root "
<< "(default is \"daemon\")!1!username!3|"
<< "n!no-syslog!disables syslog output!0!!3"
;
return ss.str() ;
}
//static
std::string Main::CommandLine::switchSpec_windows()
{
std::ostringstream ss ;
ss
<< "l!log!writes log information on standard error and event log!0!!2|"
<< "t!no-daemon!use an ordinary window, not the system tray!0!!3|"
<< "n!no-syslog!dont use the event log!0!!3|"
<< "c!icon!selects the application icon!1!0^|1^|2^|3!3|"
<< "H!hidden!hides the application window (requires --no-daemon)!0!!3"
;
return ss.str() ;
}
Main::CommandLine::CommandLine( Output & output , const G::Arg & arg , const std::string & spec ,
const std::string & version ) :
m_output(output) ,
m_version(version) ,
m_arg(arg) ,
m_getopt( m_arg , spec , '|' , '!' , '^' )
{
}
@ -98,7 +134,7 @@ bool Main::CommandLine::hasUsageErrors() const
void Main::CommandLine::showUsage( bool e ) const
{
Show show( e ) ;
Show show( m_output , e ) ;
G::GetOpt::Level level = G::GetOpt::Level(2U) ;
std::string introducer = G::GetOpt::introducerDefault() ;
@ -108,9 +144,8 @@ void Main::CommandLine::showUsage( bool e ) const
introducer = std::string("abbreviated ") + introducer ;
size_t tab_stop = 33U ;
size_t columns = ttyColumns() ;
m_getopt.showUsage( show.s() , m_arg.prefix() , "" ,
introducer , level , tab_stop , columns ) ;
introducer , level , tab_stop , m_output.columns() ) ;
}
bool Main::CommandLine::contains( const std::string & name ) const
@ -189,27 +224,27 @@ bool Main::CommandLine::hasSemanticError() const
void Main::CommandLine::showSemanticError( bool e ) const
{
Show show( e ) ;
Show show( m_output , e ) ;
show.s() << m_arg.prefix() << ": usage error: " << semanticError() << std::endl ;
}
void Main::CommandLine::showUsageErrors( bool e ) const
{
Show show( e ) ;
Show show( m_output , e ) ;
m_getopt.showErrors( show.s() , m_arg.prefix() ) ;
showShortHelp( e ) ;
}
void Main::CommandLine::showArgcError( bool e ) const
{
Show show( e ) ;
Show show( m_output , e ) ;
show.s() << m_arg.prefix() << ": usage error: too many non-switch arguments" << std::endl ;
showShortHelp( e ) ;
}
void Main::CommandLine::showShortHelp( bool e ) const
{
Show show( e ) ;
Show show( m_output , e ) ;
const std::string & exe = m_arg.prefix() ;
show.s()
<< std::string(exe.length()+2U,' ')
@ -218,7 +253,7 @@ void Main::CommandLine::showShortHelp( bool e ) const
void Main::CommandLine::showHelp( bool e ) const
{
Show show( e ) ;
Show show( m_output , e ) ;
showBanner( e ) ;
show.s() << std::endl ;
showUsage( e ) ;
@ -228,7 +263,7 @@ void Main::CommandLine::showHelp( bool e ) const
void Main::CommandLine::showExtraHelp( bool e ) const
{
Show show( e ) ;
Show show( m_output , e ) ;
const std::string & exe = m_arg.prefix() ;
show.s() << std::endl ;
@ -261,34 +296,60 @@ void Main::CommandLine::showExtraHelp( bool e ) const
void Main::CommandLine::showNoop( bool e ) const
{
Show show( e ) ;
Show show( m_output , e ) ;
show.s() << m_arg.prefix() << ": no messages to send" << std::endl ;
}
void Main::CommandLine::showBanner( bool e ) const
{
Show show( e ) ;
Show show( m_output , e ) ;
show.s()
<< "E-MailRelay V" << m_version << std::endl ;
}
void Main::CommandLine::showCopyright( bool e ) const
{
Show show( e ) ;
Show show( m_output , e ) ;
show.s() << Legal::copyright() << std::endl ;
}
void Main::CommandLine::showWarranty( bool e ) const
{
Show show( e ) ;
Show show( m_output , e ) ;
show.s() << Legal::warranty("","\n") ;
}
void Main::CommandLine::showVersion( bool e ) const
{
Show show( e ) ;
Show show( m_output , e ) ;
showBanner( e ) ;
showWarranty( e ) ;
showCopyright( e ) ;
}
// ===
Main::CommandLine::Show * Main::CommandLine::Show::m_this = NULL ;
Main::CommandLine::Show::Show( Output & output , bool e ) :
m_output(output) ,
m_e(e)
{
if( m_this == NULL )
m_this = this ;
}
std::ostream & Main::CommandLine::Show::s()
{
return m_this->m_ss ;
}
Main::CommandLine::Show::~Show()
{
if( m_this == this )
{
m_this = NULL ;
m_output.output( m_ss.str() , m_e ) ;
}
}

View File

@ -28,6 +28,7 @@
#include "gsmtp.h"
#include "garg.h"
#include "configuration.h"
#include "output.h"
#include "ggetopt.h"
#include <string>
#include <iostream>
@ -44,8 +45,12 @@ namespace Main
class Main::CommandLine
{
public:
CommandLine( const G::Arg & arg , const std::string & version ) ;
// Constructor.
static std::string switchSpec( bool is_windows ) ;
// Returns an o/s-specific G::GetOpt switch specification string.
CommandLine( Main::Output & output , const G::Arg & arg , const std::string & spec ,
const std::string & version ) ;
// Constructor.
Configuration cfg() const ;
// Returns a Configuration object.
@ -93,13 +98,13 @@ private:
void showWarranty( bool error_stream ) const ;
void showShortHelp( bool error_stream ) const ;
std::string semanticError() const ;
static std::string switchSpec() ;
static std::string osSwitchSpec() ; // o/s-specific
unsigned int ttyColumns() const ; // o/s-specific
void showUsage( bool e ) const ;
void showExtraHelp( bool error_stream ) const ;
static std::string switchSpec_unix() ;
static std::string switchSpec_windows() ;
private:
Output & m_output ;
std::string m_version ;
G::Arg m_arg ;
G::GetOpt m_getopt ;
@ -107,14 +112,15 @@ private:
public:
class Show // A private implementation class used by Main::CommandLine.
{
public: explicit Show( bool e ) ;
public: Show( Main::Output & , bool e ) ;
public: std::ostream & s() ;
public: ~Show() ;
private: static Show * m_this ;
private: class Imp ;
private: Imp * m_imp ;
private: Show( const Show & ) ; // not implemented
private: void operator=( const Show & ) ; // not implemented
private: std::ostringstream m_ss ;
private: Main::Output & m_output ;
private: bool m_e ;
private: static Show * m_this ;
} ;
} ;

View File

@ -1,84 +0,0 @@
//
// 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.
//
// ===
//
// commandline_unix.cpp
//
#include "gdef.h"
#include "gsmtp.h"
#include "commandline.h"
#include "gstr.h"
#include <iostream>
// Class: Main::CommandLine::ShowImp
// Description: A private implementation class used by Main::CommandLine::Show.
//
class Main::CommandLine::Show::Imp
{
public:
bool m_e ;
explicit Imp( bool b ) : m_e(b) {}
} ;
//static
std::string Main::CommandLine::osSwitchSpec()
{
std::ostringstream ss ;
ss
<< "l!log!writes log information on standard error and syslog!0!!2|"
<< "t!no-daemon!does not detach from the terminal!0!!3|"
<< "u!user!names the effective user to switch to when started as root (default is \"daemon\")!1!username!3|"
<< "n!no-syslog!disables syslog output!0!!3"
;
return ss.str() ;
}
Main::CommandLine::Show::Show( bool e ) :
m_imp( new Imp(e) )
{
}
std::ostream & Main::CommandLine::Show::s()
{
return m_imp->m_e ? std::cerr : std::cout ;
}
Main::CommandLine::Show::~Show()
{
delete m_imp ;
}
unsigned int Main::CommandLine::ttyColumns() const
{
const unsigned int default_ = 79U ;
try
{
const char * p = std::getenv( "COLUMNS" ) ;
if( p == NULL )
return default_ ;
else
return G::Str::toUInt(p) ;
}
catch( std::exception & )
{
return default_ ;
}
}

View File

@ -1,88 +0,0 @@
//
// 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.
//
// ===
//
// commandline_win32.cpp
//
#include "gdef.h"
#include "gsmtp.h"
#include "commandline.h"
#include <sstream>
Main::CommandLine::Show * Main::CommandLine::Show::m_this = NULL ;
class Main::CommandLine::Show::Imp
{
public:
std::ostringstream m_ss ;
} ;
// ===
//static
std::string Main::CommandLine::osSwitchSpec()
{
// (could use empty descriptions for some switches so that they
// do not appear in the "--help" listing, but that might be
// confusing)
std::ostringstream ss ;
ss
<< "l!log!writes log information on standard error and event log!0!!2|"
<< "t!no-daemon!use an ordinary window, not the system tray!0!!3|"
<< "n!no-syslog!dont use the event log!0!!3|"
<< "I!icon!selects the application icon!1!0^|1^|2^|3!3|"
<< "H!hidden!hides the application window (requires --no-daemon)!0!!3"
;
return ss.str() ;
}
unsigned int Main::CommandLine::ttyColumns() const
{
return 120U ;
}
// ===
Main::CommandLine::Show::Show( bool ) :
m_imp( new Imp )
{
if( m_this == NULL )
{
m_this = this ;
}
}
std::ostream & Main::CommandLine::Show::s()
{
return m_this->m_imp->m_ss ;
}
Main::CommandLine::Show::~Show()
{
if( m_this == this )
{
m_this = NULL ;
::MessageBox( NULL , m_imp->m_ss.str().c_str() , "E-MailRelay" , MB_OK ) ;
}
delete m_imp ;
}

View File

@ -217,6 +217,10 @@ SOURCE=..\glib\ggetopt.cpp
# End Source File
# Begin Source File
SOURCE=..\glib\gidentity_win32.cpp
# End Source File
# Begin Source File
SOURCE=..\gnet\glinebuffer.cpp
# End Source File
# Begin Source File

View File

@ -63,7 +63,7 @@ std::string Main::Configuration::str( const std::string & p , const std::string
ss
<< p << "listening port: " << (doServing()?G::Str::fromUInt(port()):na()) << eol
<< p << "listening interface: " << (doServing()?any(interface_()):na()) << eol
<< p << "next server address: " << (doForwarding()?serverAddress():na()) << eol
<< p << "next server address: " << ((doForwarding()||doPolling())?serverAddress():na()) << eol
<< p << "spool directory: " << spoolDir() << eol
<< p << "immediate forwarding? " << yn(immediate()) << eol
<< p << "mail processor: " << (useFilter()?filter():na()) << eol

View File

@ -3,7 +3,7 @@
# General configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = E-MailRelay
PROJECT_NUMBER = 1.1
PROJECT_NUMBER = 1.1.1
OUTPUT_DIRECTORY =
OUTPUT_LANGUAGE = English
EXTRACT_ALL = YES

View File

@ -95,7 +95,7 @@ SOURCE=.\commandline.cpp
# End Source File
# Begin Source File
SOURCE=.\commandline_win32.cpp
SOURCE=.\output.cpp
# End Source File
# Begin Source File

View File

@ -91,6 +91,16 @@ BEGIN
WS_VSCROLL
END
IDD_DIALOG2 DIALOG DISCARDABLE 0, 0, 423, 193
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,191,172,50,14
EDITTEXT IDC_EDIT1,7,7,409,163,ES_MULTILINE | ES_AUTOVSCROLL |
ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | WS_HSCROLL
END
/////////////////////////////////////////////////////////////////////////////
//
@ -107,6 +117,14 @@ BEGIN
TOPMARGIN, 7
BOTTOMMARGIN, 183
END
IDD_DIALOG2, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 416
TOPMARGIN, 7
BOTTOMMARGIN, 186
END
END
#endif // APSTUDIO_INVOKED

View File

@ -23,16 +23,41 @@
#include "gdef.h"
#include "gsmtp.h"
#include "gstr.h"
#include "garg.h"
#include "run.h"
#include "commandline.h"
#include <exception>
struct App : public Main::Output
{
void output( const std::string & text , bool e )
{
std::ostream & s = e ? std::cerr : std::cout ;
s << text << std::flush ;
}
unsigned int columns()
{
const unsigned int default_ = 79U ;
try
{
const char * p = std::getenv( "COLUMNS" ) ;
return p == NULL ? default_ : G::Str::toUInt(p) ;
}
catch( std::exception & )
{
return default_ ;
}
}
} ;
int main( int argc , char * argv [] )
{
try
{
G::Arg arg( argc , argv ) ;
Main::Run main( arg ) ;
App app ;
Main::Run main( app , arg , Main::CommandLine::switchSpec(false) ) ;
if( main.prepare() )
main.run() ;
return EXIT_SUCCESS ;

49
src/main/mingw.mak Normal file
View File

@ -0,0 +1,49 @@
#
## 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.
##
#
#
# mingw.mak
#
mk_sources=\
commandline.cpp \
configuration.cpp \
legal.cpp \
output.cpp \
run.cpp \
winapp.cpp \
winform.cpp \
winmain.cpp \
winmenu.cpp
libs=../gsmtp/gsmtp.a ../gnet/gnet.a ../win32/gwin32.a ../glib/glib.a
syslibs=-lgdi32 -lwsock32
rc=emailrelay.rc
res=$(rc:.rc=.o)
mk_target=emailrelay.exe
all: $(mk_target)
include ../mingw-common.mak
$(mk_target): $(mk_objects) $(res) $(libs)
$(mk_gcc) $(mk_gcc_flags) -o $(mk_target) $(mk_objects) $(res) $(libs) $(syslibs)

30
src/main/output.cpp Normal file
View File

@ -0,0 +1,30 @@
//
// 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.
//
// ===
//
// output.cpp
//
#include "gdef.h"
#include "output.h"
Main::Output::~Output()
{
}

56
src/main/output.h Normal file
View File

@ -0,0 +1,56 @@
//
// 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.
//
// ===
//
// output.h
//
#ifndef G_MAIN_OUTPUT_H
#define G_MAIN_OUTPUT_H
#include "gdef.h"
#include <string>
namespace Main
{
class Output ;
}
// Class: Main::Output
// Description: An abstract interface for generating output.
// The implementation is controlled from main()/WinMain().
//
class Main::Output
{
public:
virtual unsigned int columns() = 0 ;
// Returns the output line width.
virtual void output( const std::string & , bool error ) = 0 ;
// Outputs the given string.
virtual ~Output() ;
// Destructor.
private:
void operator=( const Output & ) ; // not implemented
} ;
#endif

View File

@ -1,22 +1,3 @@
//
// 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.
//
// ===
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by emailrelay.rc
@ -42,7 +23,7 @@
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 109
#define _APS_NEXT_RESOURCE_VALUE 110
#define _APS_NEXT_COMMAND_VALUE 40006
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101

View File

@ -50,10 +50,12 @@
//static
std::string Main::Run::versionNumber()
{
return "1.1" ;
return "1.1.1" ;
}
Main::Run::Run( const G::Arg & arg ) :
Main::Run::Run( Main::Output & output , const G::Arg & arg , const std::string & switch_spec ) :
m_output(output) ,
m_switch_spec(switch_spec) ,
m_arg(arg)
{
}
@ -331,7 +333,7 @@ const Main::CommandLine & Main::Run::cl() const
// lazy evaluation so that the constructor doesnt throw
if( m_cl.get() == NULL )
{
const_cast<Run*>(this)->m_cl <<= new CommandLine( m_arg , versionNumber() ) ;
const_cast<Run*>(this)->m_cl <<= new CommandLine( m_output , m_arg , m_switch_spec , versionNumber() ) ;
}
return *m_cl.get() ;
}

View File

@ -28,6 +28,7 @@
#include "gsmtp.h"
#include "configuration.h"
#include "commandline.h"
#include "output.h"
#include "geventloop.h"
#include "gtimer.h"
#include "glogoutput.h"
@ -55,7 +56,8 @@ namespace Main
/// int main( int argc , char ** argv )
/// {
/// G::Arg arg( argc , argv ) ;
/// Main::Run run( arg ) ;
/// Output output ;
/// Main::Run run( output , arg , CommandLine::switchSpec() ) ;
/// if( run.prepare() )
/// run.run() ;
/// return 0 ;
@ -64,7 +66,7 @@ namespace Main
class Main::Run : private GNet::TimeoutHandler
{
public:
explicit Run( const G::Arg & arg ) ;
Run( Output & output , const G::Arg & arg , const std::string & switch_spec ) ;
// Constructor.
virtual ~Run() ;
@ -108,6 +110,8 @@ private:
std::string doPoll() ;
private:
Output & m_output ;
std::string m_switch_spec ;
std::auto_ptr<CommandLine> m_cl ;
std::auto_ptr<G::LogOutput> m_log_output ;
std::auto_ptr<GSmtp::Client> m_client ;

View File

@ -26,10 +26,54 @@
#include "winmenu.h"
#include "gwindow.h"
#include "glog.h"
#include "gstr.h"
#include "gmemory.h"
#include "gcontrol.h"
#include "gdialog.h"
#include "gassert.h"
#include "resource.h"
namespace Main
{
class Box ;
} ;
class Main::Box : public GGui::Dialog
{
public:
Box( GGui::ApplicationBase & app , const G::Strings & text ) ;
bool run() ;
private:
bool onInit() ;
private:
GGui::EditBox m_edit ;
G::Strings m_text ;
} ;
Main::Box::Box( GGui::ApplicationBase & app , const G::Strings & text ) :
GGui::Dialog( app , false ) ,
m_edit( *this , IDC_EDIT1 ) ,
m_text( text )
{
}
bool Main::Box::onInit()
{
G_DEBUG( "Main::Box::onInit" ) ;
m_edit.set( m_text ) ;
return true ;
}
bool Main::Box::run()
{
GGui::Dialog & base = *this ;
bool rc = base.run( IDD_DIALOG2 ) ;
G_DEBUG( "Main::Box::run: " << rc ) ;
return rc ;
}
// ===
Main::WinApp::WinApp( HINSTANCE h , HINSTANCE p , const char * name ) :
GGui::ApplicationBase( h , p , name ) ,
m_use_tray(false) ,
@ -39,6 +83,10 @@ Main::WinApp::WinApp( HINSTANCE h , HINSTANCE p , const char * name ) :
{
}
Main::WinApp::~WinApp()
{
}
void Main::WinApp::init( const Configuration & cfg )
{
m_use_tray = cfg.daemon() ;
@ -205,3 +253,24 @@ void Main::WinApp::setStatus( const std::string & s1 , const std::string & s2 )
::SetWindowText( handle() , message.c_str() ) ;
}
unsigned int Main::WinApp::columns()
{
return 1000U ;
}
void Main::WinApp::output( const std::string & text , bool )
{
G::Strings text_lines ;
G::Str::splitIntoFields( text , text_lines , "\r\n" ) ;
if( text_lines.size() > 20U )
{
Box box( *this , text_lines ) ;
if( ! box.run() )
messageBox( text ) ;
}
else
{
messageBox( text ) ;
}
}

View File

@ -30,6 +30,7 @@
#include "gtray.h"
#include "winform.h"
#include "configuration.h"
#include "output.h"
#include <memory>
namespace Main
@ -37,16 +38,44 @@ namespace Main
class WinApp ;
}
class Main::WinApp : public GGui::ApplicationBase
// Class: Main::WinApp
// Description: An application class instantiated in WinMain()
// and containing a Main::WinForm object. WinMain() sets up
// slot/signal links from Main::Run to Main::WinApp. Derives
// from Main::Output so that Main::CommandLine can call
// output() to throw up message boxes.
//
class Main::WinApp : public GGui::ApplicationBase , public Main::Output
{
public:
G_EXCEPTION( Error , "application error" ) ;
WinApp( HINSTANCE h , HINSTANCE p , const char * name ) ;
// Constructor. Initialise with init().
virtual ~WinApp() ;
// Destructor.
void init( const Main::Configuration & cfg ) ;
// Initialises the object after construction.
void output( const std::string & message , bool error ) ;
// Puts up a message box. See Main::Output.
unsigned int columns() ;
// See Main::Output.
bool confirm() ;
// Puts up a confirmation message box.
void formOk() ;
// Called from the form's ok button handler.
void formDone() ;
// Called from the form's nc-destroy message handler.
void onRunEvent( std::string , std::string , std::string ) ;
// Slot for Main::Run::signal().
private:
void doOpen() ;

View File

@ -18,7 +18,7 @@
//
// ===
//
// main_win32.cpp
// winmain.cpp
//
#include "gdef.h"
@ -27,6 +27,7 @@
#include "gslot.h"
#include "gexception.h"
#include "winapp.h"
#include "commandline.h"
#include "run.h"
int WINAPI WinMain( HINSTANCE hinstance , HINSTANCE previous ,
@ -40,7 +41,7 @@ int WINAPI WinMain( HINSTANCE hinstance , HINSTANCE previous ,
try
{
Main::Run run( arg ) ;
Main::Run run( app , arg , Main::CommandLine::switchSpec(true) ) ;
if( run.prepare() )
{
const bool visible = ! run.cfg().daemon() ;

65
src/mingw-common.mak Normal file
View File

@ -0,0 +1,65 @@
#
## 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.
##
#
#
# mingw-common.mak
#
# Included by "mingw.mak" files.
#
mk_bin=/mingw/bin/
mk_ar=ar rc
mk_rc=$(mk_bin)windres
mk_rm_f=rm -f
mk_objects=$(mk_sources:.cpp=.o)
mk_gcc=$(mk_bin)g++
mk_gcc_flags=-mno-cygwin -g
mk_defines=-DG_WIN32 -DG_MINGW
mk_includes=-I../glib -I../gnet -I../gsmtp -I../win32
mk_cpp_flags=$(mk_defines) $(mk_includes)
.SUFFIXES: .rc .i
.cpp.o:
$(mk_gcc) $(mk_gcc_flags) $(mk_cpp_flags) -c $*.cpp
.cpp.i:
$(mk_gcc) $(mk_gcc_flags) $(mk_cpp_flags) -E $*.cpp > $*.i
.rc.o:
$(mk_rc) --include-dir . -i $*.rc -o $*.o
_all:
cd glib && make -f mingw.mak && cd ..
cd gnet && make -f mingw.mak && cd ..
cd gsmtp && make -f mingw.mak && cd ..
cd win32 && make -f mingw.mak && cd ..
cd main && make -f mingw.mak && cd ..
_clean:
cd glib && make -f mingw.mak clean && cd ..
cd gnet && make -f mingw.mak clean && cd ..
cd gsmtp && make -f mingw.mak clean && cd ..
cd win32 && make -f mingw.mak clean && cd ..
cd main && make -f mingw.mak clean && cd ..
clean::
$(mk_rm_f) $(mk_objects) $(mk_target)

22
src/mingw.mak Normal file
View File

@ -0,0 +1,22 @@
#
## 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.
##
#
include mingw-common.mak
all: all_
clean: clean_

View File

@ -44,5 +44,6 @@ EXTRA_DIST = \
gwindow.cpp \
gwindow.h \
gwinhid.cpp \
gwinhid.h
gwinhid.h \
mingw.mak

View File

@ -119,7 +119,8 @@ EXTRA_DIST = \
gwindow.cpp \
gwindow.h \
gwinhid.cpp \
gwinhid.h
gwinhid.h \
mingw.mak
subdir = src/win32
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs

View File

@ -190,7 +190,7 @@ LRESULT GGui::Cracker::crack( UINT message , WPARAM wparam ,
{
G_DEBUG( "Cracker::onDrop" ) ;
HDROP hdrop = reinterpret_cast<HDROP>(wparam) ;
int count = ::DragQueryFile( hdrop , -1 , NULL , 0 ) ;
int count = ::DragQueryFile( hdrop , 0xFFFFFFFF , NULL , 0 ) ;
G::Strings list ;
for( int i = 0 ; i < count ; i++ )
{
@ -263,37 +263,37 @@ LRESULT GGui::Cracker::crack( UINT message , WPARAM wparam ,
case WM_LBUTTONDOWN:
{
return doMouseButton( onLeftMouseButtonDown , Mouse_Left ,
return doMouseButton( &Cracker::onLeftMouseButtonDown , Mouse_Left ,
Mouse_Down , message , wparam , lparam ) ;
}
case WM_LBUTTONUP:
{
return doMouseButton( onLeftMouseButtonUp , Mouse_Left ,
return doMouseButton( &Cracker::onLeftMouseButtonUp , Mouse_Left ,
Mouse_Up , message , wparam , lparam ) ;
}
case WM_MBUTTONDOWN:
{
return doMouseButton( onMiddleMouseButtonDown , Mouse_Middle ,
return doMouseButton( &Cracker::onMiddleMouseButtonDown , Mouse_Middle ,
Mouse_Down , message , wparam , lparam ) ;
}
case WM_MBUTTONUP:
{
return doMouseButton( onMiddleMouseButtonUp , Mouse_Middle ,
return doMouseButton( &Cracker::onMiddleMouseButtonUp , Mouse_Middle ,
Mouse_Up , message , wparam , lparam ) ;
}
case WM_RBUTTONDOWN:
{
return doMouseButton( onRightMouseButtonDown , Mouse_Right ,
return doMouseButton( &Cracker::onRightMouseButtonDown , Mouse_Right ,
Mouse_Down , message , wparam , lparam ) ;
}
case WM_RBUTTONUP:
{
return doMouseButton( onRightMouseButtonUp , Mouse_Right ,
return doMouseButton( &Cracker::onRightMouseButtonUp , Mouse_Right ,
Mouse_Up , message , wparam , lparam ) ;
}

View File

@ -300,7 +300,8 @@ bool GGui::Dialog::run( const char * f_name )
if( rc == -1 )
{
G_DEBUG( "GGui::Dialog::run: cannot create dialog box" ) ;
int error = ::GetLastError() ;
G_DEBUG( "GGui::Dialog::run: cannot create dialog box: " << error ) ;
return false ;
}
else if( rc == 0 )

47
src/win32/mingw.mak Normal file
View File

@ -0,0 +1,47 @@
#
## 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.
##
#
#
# mingw.mak
#
mk_sources=\
gappbase.cpp \
gappinst.cpp \
gcontrol.cpp \
gcracker.cpp \
gdc.cpp \
gdialog.cpp \
gpump.cpp \
gpump_dialog.cpp \
gscmap.cpp \
gtray.cpp \
gwinbase.cpp \
gwindow.cpp \
gwinhid.cpp
mk_target=gwin32.a
all: $(mk_target)
include ../mingw-common.mak
$(mk_target): $(mk_objects)
$(mk_ar) $(mk_target) $(mk_objects)