This commit is contained in:
Graeme Walker 2002-08-16 12:00:00 +00:00
parent 38eb15ca53
commit 0a46d723c5
194 changed files with 5471 additions and 2794 deletions

View File

@ -1,6 +1,19 @@
E-MailRelay Change Log E-MailRelay Change Log
====================== ======================
0.9.9 -> 1.0.0
--------------
* Briefer "--help" output; works with "--verbose".
* Option to listen on a specific network interface ("--interface").
* Option for an external address verifier program ("--verifier").
* Some Linux Standard Base stuff added to the "init.d" script.
* Pid files world-readable and deleted on abnormal termination.
* Compiles with gcc 3.0 and intel 6.0.
* Autoconf tweak for MacOS X.
* Corrected the "Received:" typo [bug-id 572236].
* EHLO response parsing is now case-insensitive [bug-id 561522].
* Fewer missing-secrets warnings [bug-id 564987].
0.9.8 -> 0.9.9 0.9.8 -> 0.9.9
-------------- --------------
* More flexible logging options ("--verbose" and "--debug" work better). * More flexible logging options ("--verbose" and "--debug" work better).

19
INSTALL
View File

@ -1,16 +1,20 @@
Introduction Introduction
============ ============
What follows are generic installation instructions for doing a standard GNU What follows are generic installation instructions for doing a standard GNU
"./configure; make; make install" installation from source under Linux, FreeBSD "./configure; make; make install" installation from source under Linux, FreeBSD
etc. The Windows installation instructions are in a separate document. etc. The Windows installation instructions are in a separate document.
Note that a non-standard "configure" switch is available, "--enable-fhs", A non-standard "configure" switch is available, "--enable-fhs", which overrides
which overrides all other directory modifiers, forcing compliance with the File all other directory modifiers, forcing compliance with the File Hierarchy Standard.
Hierarchy Standard. There are also a set of variables which can be defined on This switch is used in building the RPMs, and may become the default in future
the "configure" command line for controlling all the installation directories releases.
in more detail, augmenting the standard command-line switches like "--sbindir"
and "--libexecdir". For more information refer to the E-MailRelay reference There are also a set of variables which can be defined on the "configure" command
document. line for controlling all the installation directories in more detail, augmenting
the standard command-line switches like "--sbindir" and "--libexecdir". For more
information refer to the E-MailRelay reference document under
"Files and directories".
The E-MailRelay user guide describes what needs to be done after the "make The E-MailRelay user guide describes what needs to be done after the "make
install" in order to get the emailrelay daemon to start up at boot-time, install" in order to get the emailrelay daemon to start up at boot-time,
@ -18,6 +22,7 @@ automatically forward e-mail and bounce failed mail.
Basic Installation Basic Installation
================== ==================
The `configure' shell script attempts to guess correct values for The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package. those values to create a `Makefile' in each directory of the package.

View File

@ -21,4 +21,6 @@ SUBDIRS = src bin lib doc
e_doc_DATA = NEWS README changelog.gz e_doc_DATA = NEWS README changelog.gz
CLEANFILES = changelog.gz CLEANFILES = changelog.gz
changelog.gz: ChangeLog changelog.gz: ChangeLog
if test -n "$(GZIP)" ; then $(GZIP) -c $< > changelog.tmp && mv changelog.tmp changelog.gz ; fi if test -n "$(GZIP)" ; then $(GZIP) -c $(top_srcdir)/ChangeLog > changelog.tmp && mv changelog.tmp changelog.gz ; fi
uninstall-local:
-rmdir $(DESTDIR)$(e_docdir) 2>/dev/null

View File

@ -79,6 +79,7 @@ POST_UNINSTALL = :
AR = @AR@ AR = @AR@
AWK = @AWK@ AWK = @AWK@
CC = @CC@ CC = @CC@
COMPILER_VERSION = @COMPILER_VERSION@
CXX = @CXX@ CXX = @CXX@
GZIP = @GZIP@ GZIP = @GZIP@
HAVE_DOXYGEN = @HAVE_DOXYGEN@ HAVE_DOXYGEN = @HAVE_DOXYGEN@
@ -346,7 +347,7 @@ install-data: install-data-recursive
install-am: all-am install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-recursive install: install-recursive
uninstall-am: uninstall-e_docDATA uninstall-am: uninstall-e_docDATA uninstall-local
uninstall: uninstall-recursive uninstall: uninstall-recursive
all-am: Makefile $(DATA) config.h all-am: Makefile $(DATA) config.h
all-redirect: all-recursive-am all-redirect: all-recursive-am
@ -398,12 +399,15 @@ maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
dvi-am dvi check check-am installcheck-am installcheck all-recursive-am \ dvi-am dvi check check-am installcheck-am installcheck all-recursive-am \
install-exec-am install-exec install-data-am install-data install-am \ install-exec-am install-exec install-data-am install-data install-am \
install uninstall-am uninstall all-redirect all-am all installdirs-am \ install uninstall-local uninstall-am uninstall all-redirect all-am all \
installdirs mostlyclean-generic distclean-generic clean-generic \ installdirs-am installdirs mostlyclean-generic distclean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean clean-generic maintainer-clean-generic clean mostlyclean distclean \
maintainer-clean
changelog.gz: ChangeLog changelog.gz: ChangeLog
if test -n "$(GZIP)" ; then $(GZIP) -c $< > changelog.tmp && mv changelog.tmp changelog.gz ; fi if test -n "$(GZIP)" ; then $(GZIP) -c $(top_srcdir)/ChangeLog > changelog.tmp && mv changelog.tmp changelog.gz ; fi
uninstall-local:
-rmdir $(DESTDIR)$(e_docdir) 2>/dev/null
# Tell versions [3.59,3.63) of GNU make to not export all variables. # Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded. # Otherwise a system limit (for SysV at least) may be exceeded.

8
NEWS
View File

@ -1,7 +1 @@
no news
To do...
* optionally enforce authentication by clients
* OS-X port
* better windows gui (esp. client side)
* sample pre-processor script for spamassassin

9
README
View File

@ -12,8 +12,8 @@ than to a local postmaster. Because of this functional simplicity it is
extremely easy to configure, typically only requiring the address of the extremely easy to configure, typically only requiring the address of the
next-hop SMTP server to be put on the command line. next-hop SMTP server to be put on the command line.
C++ source code is available for Linux, FreeBSD and Windows. Distribution is C++ source code is available for Linux, FreeBSD (etc) and Windows.
under the GNU General Public License. Distribution is under the GNU General Public License.
Quick start Quick start
----------- -----------
@ -78,11 +78,12 @@ and ported to Windows 98 using:
The code has also been built successfully on: The code has also been built successfully on:
* Windows NT 4.0 * Windows NT 4.0
* MacOS X
* FreeBSD on Intel hardware
* Solaris 8, using gcc, on Sparc hardware
* Linux on Alpha hardware (Debian 2.2) * Linux on Alpha hardware (Debian 2.2)
* Linux on Sparc hardware * Linux on Sparc hardware
* Linux on RS6000 PPC hardware * Linux on RS6000 PPC hardware
* FreeBSD on Intel hardware
* Solaris, using gcc, on Sparc hardware
Feedback Feedback

View File

@ -18,6 +18,62 @@ dnl Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
dnl dnl
dnl === dnl ===
dnl derived from lars brinkhoff...
AC_DEFUN(ACLOCAL_TYPE_SOCKLEN_T,
[AC_CACHE_CHECK([for socklen_t], aclocal_cv_type_socklen_t,
[
AC_TRY_COMPILE(
[#include <sys/types.h>
#include <sys/socket.h>],
[socklen_t len = 42; return len;],
aclocal_cv_type_socklen_t=yes,
aclocal_cv_type_socklen_t=no)
])
if test $aclocal_cv_type_socklen_t = yes; then
AC_DEFINE(HAVE_SOCKLEN_T, 1,[Define if socklen_t type definition in sys/socket.h])
else
AC_DEFINE(HAVE_SOCKLEN_T, 0,[Define if socklen_t type definition in sys/socket.h])
fi
])
AC_DEFUN([ACLOCAL_CHECK_GMTIME_R],
[AC_CACHE_CHECK([for gmtime_r], aclocal_cv_gmtime_r,
[
AC_TRY_COMPILE(
[#include <time.h>],
[gmtime_r((time_t*)0,(struct tm*)0) ;],
aclocal_cv_gmtime_r=yes ,
aclocal_cv_gmtime_r=no )
])
if test $aclocal_cv_gmtime_r = yes; then
AC_DEFINE(HAVE_GMTIME_R,1,[Define if gmtime_r in time.h])
else
AC_DEFINE(HAVE_GMTIME_R,0,[Define if gmtime_r in time.h])
fi
])
AC_DEFUN([ACLOCAL_CHECK_LOCALTIME_R],
[AC_CACHE_CHECK([for localtime_r], aclocal_cv_localtime_r,
[
AC_TRY_COMPILE(
[#include <time.h>],
[localtime_r((time_t*)0,(struct tm*)0) ;],
aclocal_cv_localtime_r=yes ,
aclocal_cv_localtime_r=no )
])
if test $aclocal_cv_localtime_r = yes; then
AC_DEFINE(HAVE_LOCALTIME_R,1,[Define if localtime_r in time.h])
else
AC_DEFINE(HAVE_LOCALTIME_R,0,[Define if localtime_r in time.h])
fi
])
AC_DEFUN([ACLOCAL_COMPILER_VERSION],
[
COMPILER_VERSION=`$CXX --version 2>/dev/null | sed 's/\./ /;s/\..*//;s/ /\./;s/ .*//;s/^/gcc/'`
AC_SUBST(COMPILER_VERSION)
])
AC_DEFUN([ENABLE_FHS], AC_DEFUN([ENABLE_FHS],
[ [
if test "$enable_fhs" = "yes" if test "$enable_fhs" = "yes"

56
aclocal.m4 vendored
View File

@ -30,6 +30,62 @@ dnl Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
dnl dnl
dnl === dnl ===
dnl derived from lars brinkhoff...
AC_DEFUN(ACLOCAL_TYPE_SOCKLEN_T,
[AC_CACHE_CHECK([for socklen_t], aclocal_cv_type_socklen_t,
[
AC_TRY_COMPILE(
[#include <sys/types.h>
#include <sys/socket.h>],
[socklen_t len = 42; return len;],
aclocal_cv_type_socklen_t=yes,
aclocal_cv_type_socklen_t=no)
])
if test $aclocal_cv_type_socklen_t = yes; then
AC_DEFINE(HAVE_SOCKLEN_T, 1,[Define if socklen_t type definition in sys/socket.h])
else
AC_DEFINE(HAVE_SOCKLEN_T, 0,[Define if socklen_t type definition in sys/socket.h])
fi
])
AC_DEFUN([ACLOCAL_CHECK_GMTIME_R],
[AC_CACHE_CHECK([for gmtime_r], aclocal_cv_gmtime_r,
[
AC_TRY_COMPILE(
[#include <time.h>],
[gmtime_r((time_t*)0,(struct tm*)0) ;],
aclocal_cv_gmtime_r=yes ,
aclocal_cv_gmtime_r=no )
])
if test $aclocal_cv_gmtime_r = yes; then
AC_DEFINE(HAVE_GMTIME_R,1,[Define if gmtime_r in time.h])
else
AC_DEFINE(HAVE_GMTIME_R,0,[Define if gmtime_r in time.h])
fi
])
AC_DEFUN([ACLOCAL_CHECK_LOCALTIME_R],
[AC_CACHE_CHECK([for localtime_r], aclocal_cv_localtime_r,
[
AC_TRY_COMPILE(
[#include <time.h>],
[localtime_r((time_t*)0,(struct tm*)0) ;],
aclocal_cv_localtime_r=yes ,
aclocal_cv_localtime_r=no )
])
if test $aclocal_cv_localtime_r = yes; then
AC_DEFINE(HAVE_LOCALTIME_R,1,[Define if localtime_r in time.h])
else
AC_DEFINE(HAVE_LOCALTIME_R,0,[Define if localtime_r in time.h])
fi
])
AC_DEFUN([ACLOCAL_COMPILER_VERSION],
[
COMPILER_VERSION=`$CXX --version 2>/dev/null | sed 's/\./ /;s/\..*//;s/ /\./;s/ .*//;s/^/gcc/'`
AC_SUBST(COMPILER_VERSION)
])
AC_DEFUN([ENABLE_FHS], AC_DEFUN([ENABLE_FHS],
[ [
if test "$enable_fhs" = "yes" if test "$enable_fhs" = "yes"

View File

@ -37,9 +37,12 @@ emailrelay: emailrelay.sh
cp emailrelay.sh emailrelay cp emailrelay.sh emailrelay
chmod ugo+x emailrelay chmod ugo+x emailrelay
install-data-local: install-data-local: install-e_examplesDATA install-e_initSCRIPTS
chmod ugo+x $(DESTDIR)$(e_examplesdir)/emailrelay-notify.sh chmod ugo+x $(DESTDIR)$(e_examplesdir)/emailrelay-notify.sh
chmod ugo+x $(DESTDIR)$(e_examplesdir)/emailrelay-resubmit.sh chmod ugo+x $(DESTDIR)$(e_examplesdir)/emailrelay-resubmit.sh
chmod ugo+x $(DESTDIR)$(e_examplesdir)/emailrelay-deliver.sh chmod ugo+x $(DESTDIR)$(e_examplesdir)/emailrelay-deliver.sh
chmod ugo+x $(DESTDIR)$(e_examplesdir)/emailrelay-process.sh chmod ugo+x $(DESTDIR)$(e_examplesdir)/emailrelay-process.sh
uninstall-local:
-rmdir $(DESTDIR)$(e_examplesdir) 2>/dev/null

View File

@ -79,6 +79,7 @@ POST_UNINSTALL = :
AR = @AR@ AR = @AR@
AWK = @AWK@ AWK = @AWK@
CC = @CC@ CC = @CC@
COMPILER_VERSION = @COMPILER_VERSION@
CXX = @CXX@ CXX = @CXX@
GZIP = @GZIP@ GZIP = @GZIP@
HAVE_DOXYGEN = @HAVE_DOXYGEN@ HAVE_DOXYGEN = @HAVE_DOXYGEN@
@ -232,7 +233,8 @@ install-data: install-data-am
install-am: all-am install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am install: install-am
uninstall-am: uninstall-e_initSCRIPTS uninstall-e_examplesDATA uninstall-am: uninstall-e_initSCRIPTS uninstall-e_examplesDATA \
uninstall-local
uninstall: uninstall-am uninstall: uninstall-am
all-am: Makefile $(SCRIPTS) $(DATA) all-am: Makefile $(SCRIPTS) $(DATA)
all-redirect: all-am all-redirect: all-am
@ -274,10 +276,10 @@ maintainer-clean: maintainer-clean-am
uninstall-e_examplesDATA install-e_examplesDATA tags distdir \ uninstall-e_examplesDATA install-e_examplesDATA tags distdir \
check-TESTS info-am info dvi-am dvi check check-am installcheck-am \ check-TESTS info-am info dvi-am dvi check check-am installcheck-am \
installcheck install-exec-am install-exec install-data-local \ installcheck install-exec-am install-exec install-data-local \
install-data-am install-data install-am install uninstall-am uninstall \ install-data-am install-data install-am install uninstall-local \
all-redirect all-am all installdirs mostlyclean-generic \ uninstall-am uninstall all-redirect all-am all installdirs \
distclean-generic clean-generic maintainer-clean-generic clean \ mostlyclean-generic distclean-generic clean-generic \
mostlyclean distclean maintainer-clean maintainer-clean-generic clean mostlyclean distclean maintainer-clean
.sh_.sh: .sh_.sh:
@ -288,12 +290,15 @@ emailrelay: emailrelay.sh
cp emailrelay.sh emailrelay cp emailrelay.sh emailrelay
chmod ugo+x emailrelay chmod ugo+x emailrelay
install-data-local: install-data-local: install-e_examplesDATA install-e_initSCRIPTS
chmod ugo+x $(DESTDIR)$(e_examplesdir)/emailrelay-notify.sh chmod ugo+x $(DESTDIR)$(e_examplesdir)/emailrelay-notify.sh
chmod ugo+x $(DESTDIR)$(e_examplesdir)/emailrelay-resubmit.sh chmod ugo+x $(DESTDIR)$(e_examplesdir)/emailrelay-resubmit.sh
chmod ugo+x $(DESTDIR)$(e_examplesdir)/emailrelay-deliver.sh chmod ugo+x $(DESTDIR)$(e_examplesdir)/emailrelay-deliver.sh
chmod ugo+x $(DESTDIR)$(e_examplesdir)/emailrelay-process.sh chmod ugo+x $(DESTDIR)$(e_examplesdir)/emailrelay-process.sh
uninstall-local:
-rmdir $(DESTDIR)$(e_examplesdir) 2>/dev/null
# Tell versions [3.59,3.63) of GNU make to not export all variables. # Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded. # Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT: .NOEXPORT:

View File

@ -23,6 +23,10 @@
# #
awk="gawk" awk="gawk"
if test "`echo a | ${awk} '{print}'`" != "a"
then
awk="nawk"
fi 2>/dev/null
# PreFilter() # PreFilter()
# Removes banner comments (including legalese) from the top of the file. # Removes banner comments (including legalese) from the top of the file.

View File

@ -59,7 +59,7 @@ Auth()
Content() Content()
{ {
echo "To:" ${USER}@localhost echo "To:" ${USER}@`uname -n`
echo "Subject: test message from process" $$ echo "Subject: test message from process" $$
echo "From: tester" echo "From: tester"
echo "" echo ""
@ -75,7 +75,7 @@ Envelope()
echo "X-MailRelay-Content: 8bit" echo "X-MailRelay-Content: 8bit"
echo "X-MailRelay-From: me" echo "X-MailRelay-From: me"
echo "X-MailRelay-ToCount: 1" echo "X-MailRelay-ToCount: 1"
echo "X-MailRelay-To-Remote:" ${USER}@localhost echo "X-MailRelay-To-Remote:" ${USER}@`uname -n`
echo "X-MailRelay-Authentication: anon" echo "X-MailRelay-Authentication: anon"
echo "X-MailRelay-Client: 127.0.0.1" echo "X-MailRelay-Client: 127.0.0.1"
echo "X-MailRelay-End: 1" echo "X-MailRelay-End: 1"

View File

@ -24,27 +24,201 @@
# A shell-script wrapper for E-MailRelay designed for # A shell-script wrapper for E-MailRelay designed for
# use in the SysV-init system (/etc/init.d). # use in the SysV-init system (/etc/init.d).
# #
# usage: emailrelay { start [<emailrelay-switches>] | stop } # See also: LSB, start_daemon (lsb), startproc (suse),
# install_initd (lsb), insserv (suse)
# #
# usage: emailrelay { start [<emailrelay-switches>] | stop | restart | force-reload | status }
#
# LSB comment block
#
### BEGIN INIT INFO
# Provides: emailrelay
# Required-Start: $network
# Required-Stop: $network
# Default-Start: 3 4 5
# Default-Stop: 3 4 5
# Description: E-MailRelay store-and-forward Message Transfer Agent.
### END INIT INFO
# choose an infrastructure style
#
if test -f /etc/rc.status
then
style="suse"
. /etc/rc.status
elif test -f /lib/lsb/init-functions
then
style="lsb"
. /lib/lsb/init-functions
else
style="unix"
fi
# configuration # configuration
# #
switches=""
sbin="/sbin"
var_run="/var/run" var_run="/var/run"
emailrelay="__SBIN_DIR__/emailrelay" emailrelay="__SBIN_DIR__/emailrelay"
switches=""
# configuration fallback
#
if test \! -d "${var_run}" ; then var_run="/tmp" ; fi if test \! -d "${var_run}" ; then var_run="/tmp" ; fi
if test \! -x "${emailrelay}" ; then emailrelay="emailrelay" ; fi if test \! -x "${emailrelay}" ; then emailrelay="./emailrelay" ; fi
# initialisation
#
pid_file="${var_run}/emailrelay.pid" pid_file="${var_run}/emailrelay.pid"
PATH="${PATH}:/sbin:/bin:/usr/bin"
# 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>_exit() -- exit with saved errno
function unix_reset()
{
unix_errno="0"
}
function unix_message()
{
echo -n "${1}"
}
function unix_status()
{
unix_errno="$?"
if test "${1}" = "-v" -a "${unix_errno}" -eq 0
then
echo " ... done"
fi
if test "${1}" = "-v" -a "${unix_errno}" -ne 0
then
echo " ... failed"
fi
}
function unix_startproc()
{
$@
}
function unix_killproc()
{
if test -f "${pid_file}" && test "`cat ${pid_file}`" != ""
then
kill "`cat ${pid_file}`"
rm -f "${pid_file}" 2>/dev/null
fi
return 0
}
function unix_checkproc()
{
if test -f "${pid_file}" && test "`cat ${pid_file}`" != "" && kill -0 "`cat ${pid_file}`" 2>/dev/null
then
return 0
elif test -f "${pid_file}"
then
return 1
else
return 3
fi
}
function unix_exit()
{
exit "${unix_errno}"
}
##
function suse_reset()
{
rc_reset
}
function suse_message()
{
echo -n "${1}"
}
function suse_status()
{
rc_status $@
}
function suse_startproc()
{
startproc $@
}
function suse_killproc()
{
killproc $@
}
function suse_checkproc()
{
checkproc $@
}
function suse_exit()
{
rc_exit
}
##
function lsb_reset()
{
lsb_errno="0"
lsb_text=""
}
function lsb_message()
{
lsb_text="$@"
}
function lsb_status()
{
lsb_errno=$?
if test "${lsb_errno}" -eq 0 -a "${1}" = "-v"
then
log_success_msg "${lsb_text}: done"
elif test "${1}" = "-v"
then
log_failure_msg "${lsb_text}: failed"
fi
}
function lsb_startproc()
{
start_daemon "`basename \"${1}\"`"
}
function lsb_killproc()
{
killproc "`basename \"${1}\"`"
}
function lsb_checkproc()
{
base="`basename \"${1}\"`"
pids="`pidofproc \"${base}\" | sed 's/ *$//'`"
test "${pids}" != ""
}
function lsb_exit()
{
exit ${lsb_errno}
}
# check the command line # check the command line
# #
usage="{ start | stop }" usage="{ start [<server-switches>] | stop | restart | force-reload | status }"
if test $# -eq 0 if test $# -eq 0
then then
echo usage: `basename $0` "${usage}" >&2 echo usage: `basename $0` "${usage}" >&2
@ -53,25 +227,44 @@ fi
# process the command line # process the command line
# #
if test "${1}" = "start" ${style}_reset
then case "${1}" in
# "start"
#
shift
rm -f "${pid_file}" 2>/dev/null
${emailrelay} --as-server --pid-file "${pid_file}" ${switches} $@
elif test "${1}" = "stop" start)
then shift
# "stop" ${style}_message "Starting E-MailRelay server"
# ${style}_startproc ${emailrelay} --as-server --pid-file "${pid_file}" ${switches} $@
if test -f "${pid_file}" && test "`cat ${pid_file}`" != "" ${style}_status -v
then ;;
kill "`cat ${pid_file}`"
fi
else stop)
echo usage: `basename $0` "${usage}" >&2 ${style}_message "Shutting down E-MailRelay"
exit 2 ${style}_killproc "${emailrelay}"
fi ${style}_status -v
;;
restart|force-reload)
shift
$0 stop
$0 start $@
${style}_status
;;
reload)
echo usage: `basename $0` reload: not implemented >&2
exit 3
;;
status)
${style}_message "Checking for E-MailRelay"
${style}_checkproc "${emailrelay}"
${style}_status -v
;;
*)
echo usage: `basename $0` "${usage}" >&2
exit 2
;;
esac
${style}_exit

View File

@ -26,15 +26,22 @@
# Only does one sustitution per line. Directives which start the line are # Only does one sustitution per line. Directives which start the line are
# multi-line. Those within a line are one-line, expanded in-place. # multi-line. Those within a line are one-line, expanded in-place.
# #
# The "-t" switch can be used to suppress expansion of files # The "-t" switch can be used to suppress expansion where the included
# with an extension of ".html". # file has an extension of ".html".
# #
# Bugs: Does not do nested expansion. Only supports one include statement # In edit mode (--edit) the exit value is 0 (shell true) if the file is
# per line. # modified. This allows for recursive expansion using a shell while loop.
# #
# usage: expand.sh [-a <awk>] [-t] # usage: expand.sh [-a <awk>] [-t] { --edit <file> | [<file> ...] }
# #
Usage()
{
echo usage: `basename $0` '[-a <awk>] [-t] { --edit <file> | [<file> ...] }' >&2
}
tmp="/tmp/`basename $0`.$$.tmp"
awk="gawk" awk="gawk"
if test "${1}" = "-a" if test "${1}" = "-a"
then then
@ -50,40 +57,64 @@ then
expand_html="0" expand_html="0"
fi fi
${awk} -v expand_html="${expand_html}" -v cat="${awk} '{print}'" ' edit="0"
{ if test "${1}" = "--edit"
line = $0 then
if( match(line,"#include#[^#]*#") ) shift
{ edit="1"
rstart = RSTART if test $# -ne 1 ; then Usage ; exit 1 ; fi
directive = substr(line,RSTART,RLENGTH) fi
path = substr(line,RSTART+9,RLENGTH-10)
if( !expand_html && match(path,".html$") ) Expand()
{
${awk} -v expand_html="${expand_html}" -v cat="${awk} '{print}'" '
BEGIN { modified = 0 }
{
line = $0
if( match(line,"#include#[^#]*#") )
{ {
print line rstart = RSTART
} directive = substr(line,RSTART,RLENGTH)
else path = substr(line,RSTART+9,RLENGTH-10)
{
head = substr(line,1,rstart-1) if( !expand_html && match(path,".html$") )
if( match(head,"^[[:space:]]*$") )
{ {
system( cat " " path ) print line
} }
else else
{ {
getline text <path modified = 1
if( length(text) == 0 ) head = substr(line,1,rstart-1)
printf( "expand.sh: warning: line %d: empty text sustitution for %s\n" , NR , path ) >"/dev/fd/2" if( match(head,"^[[:space:]]*$") )
sub( directive , text , line ) {
print line system( cat " " path )
}
else
{
getline text <path
if( length(text) == 0 )
printf( "expand.sh: warning: line %d: empty text sustitution for %s\n" , NR , path ) >"/dev/fd/2"
sub( directive , text , line )
print line
}
} }
} }
else
{
print line
}
} }
else END { exit ! modified }
{ ' $@
print line
}
} }
' $@
if test "${edit}" -eq 1
then
# (use cp rather than mv here to protect read-only files)
Expand $@ > "${tmp}" && cp "${tmp}" "${1}"
rc=$? ; rm -f "${tmp}" 2>/dev/null ; exit "${rc}"
else
Expand $@
true
fi

View File

@ -70,7 +70,6 @@ Main()
BEGIN { BEGIN {
if( full ) if( full )
{ {
colour = "#ffffff"
dtd_name = "-//W3C//DTD HTML 4.01//EN" dtd_name = "-//W3C//DTD HTML 4.01//EN"
dtd_ref = "http://www.w3.org/TR/html4/strict.dtd" dtd_ref = "http://www.w3.org/TR/html4/strict.dtd"
printf( "<!DOCTYPE HTML PUBLIC \"%s\" \"%s\">\n" , dtd_name , dtd_ref ) printf( "<!DOCTYPE HTML PUBLIC \"%s\" \"%s\">\n" , dtd_name , dtd_ref )
@ -81,7 +80,7 @@ Main()
if( length(stylesheet) ) if( length(stylesheet) )
printf( " <link rel=\"stylesheet\" href=\"%s\" type=\"text/css\">\n" , stylesheet ) printf( " <link rel=\"stylesheet\" href=\"%s\" type=\"text/css\">\n" , stylesheet )
printf( " </head>\n" ) printf( " </head>\n" )
printf( " <body bgcolor=\"%s\">\n" , colour ) printf( " <body>\n" )
printf( " <!-- index:0::::%s -->\n" , title ) printf( " <!-- index:0::::%s -->\n" , title )
printf( " <div class=\"div-main\">\n" ) printf( " <div class=\"div-main\">\n" )
} }
@ -161,37 +160,37 @@ Main()
# item-outer # item-outer
else if( match(type,"^item-outer,1[:,]") ) else if( match(type,"^item-outer,1[:,]") )
printf( " <ul>\n <li>%s</li>\n" , etail ) printf( " <ul>\n <li>%s\n" , etail )
else if( match(type,"^item-outer[:,]") ) else if( match(type,"^item-outer[:,]") )
printf( " <li>%s</li>\n" , etail ) printf( " </li>\n <li>%s\n" , etail )
else if( match(type,"^item-outer-end[:,]") ) else if( match(type,"^item-outer-end[:,]") )
printf( " </ul>\n" , etail ) printf( " </li>\n </ul>\n" , etail )
# item-inner # item-inner
else if( match(type,"^item-inner,1[:,]") ) else if( match(type,"^item-inner,1[:,]") )
printf( " <ul>\n <li>%s</li>\n" , etail ) printf( " <ul>\n <li>%s</li>\n" , etail )
else if( match(type,"^item-inner[:,]") ) else if( match(type,"^item-inner[:,]") )
printf( " <li>%s</li>\n" , etail ) printf( " <li>%s</li>\n" , etail )
else if( match(type,"^item-inner-end[:,]") ) else if( match(type,"^item-inner-end[:,]") )
printf( " </ul>\n" , etail ) printf( " </ul>\n" , etail )
# item-name # item-name
else if( match(type,"^item-name,1[:,]") ) else if( match(type,"^item-name,1[:,]") )
printf( " <dl>\n <dt>%s</dt>\n" , etail ) printf( " <dl>\n <dt>%s</dt>\n" , etail )
else if( match(type,"^item-name[:,]") ) else if( match(type,"^item-name[:,]") )
printf( " <dt>%s</dt>\n" , etail ) printf( " <dt>%s</dt>\n" , etail )
else if( match(type,"^item-name-end[:,]") ) else if( match(type,"^item-name-end[:,]") )
printf( " </dl>\n" , etail ) printf( " </dl>\n" , etail )
# item-detail # item-detail
else if( match(type,"^item-detail,1[:,]") ) else if( match(type,"^item-detail,1[:,]") )
printf( " <dd>\n <p>\n %s\n" , etail ) printf( " <dd>\n %s\n" , etail )
else if( match(type,"^item-detail[:,]") ) else if( match(type,"^item-detail[:,]") )
printf( " %s\n" , etail ) printf( " %s\n" , etail )
else if( match(type,"^item-detail-end[:,]") ) else if( match(type,"^item-detail-end[:,]") )
printf( " </p>\n </dd>\n" ) printf( " </dd>\n" )
else if( match(type,"^item-detail-blank[:,]") ) else if( match(type,"^item-detail-blank[:,]") )
printf( " </p>\n <p>\n" ) printf( " <p class=\"p-break\"></p>\n" )
# code # code
else if( match(type,"^code,1[:,]") ) else if( match(type,"^code,1[:,]") )
@ -239,7 +238,7 @@ Main()
# image # image
else if( match(type,"^image[:,]") ) else if( match(type,"^image[:,]") )
printf( "<img src=\"%s\">\n" , tail ) printf( "<img src=\"%s\" alt=\"%s\">\n" , tail , "image" )
# blank # blank
else if( match(type,"^blank[:,]") ) else if( match(type,"^blank[:,]") )

View File

@ -104,7 +104,7 @@ Main()
is_author = 0 is_author = 0
is_html = 0 is_html = 0
is_code = match( line , "^" tab ) is_code = match( line , "^" tab )
is_item_outer = match( line , "^+ " ) is_item_outer = match( line , "^\\+ " )
is_item_inner = match( line , "^ - " ) is_item_inner = match( line , "^ - " )
} }
@ -119,7 +119,7 @@ Main()
} }
else if( is_image ) else if( is_image )
{ {
sub( "^<<" , "" , line ) sub( "^[[:space:]]*<<" , "" , line )
sub( ">>[[:space:]]*$" , "" , line ) sub( ">>[[:space:]]*$" , "" , line )
tagOutputRaw( line , "image" ) tagOutputRaw( line , "image" )
} }
@ -148,7 +148,7 @@ Main()
} }
else if( is_item_outer ) else if( is_item_outer )
{ {
sub( "^+ " , "" , line ) sub( "^\\+ " , "" , line )
tagOutput( line , "item-outer" ) tagOutput( line , "item-outer" )
} }
else if( is_item_inner ) else if( is_item_inner )
@ -213,14 +213,15 @@ Main()
# #
Number() Number()
{ {
${awk} -v item_tag="${1}" -v ignore_1="${2}" -v ignore_2="${3}" -v ignore_3="${4}" ' ${awk} -v item_tag="${1}" -v ignore_1="${2}" -v ignore_2="${3}" -v ignore_3="${4}" -v ignore_4="${5}" '
function ignore_line( line ) function ignore_line( line )
{ {
i_0 = match( line , "^ignore" ) i_0 = match( line , "^ignore" )
i_1 = length(ignore_1) && match( line , "^" ignore_1 "[:,]" ) i_1 = length(ignore_1) && match( line , "^" ignore_1 "[:,]" )
i_2 = length(ignore_2) && match( line , "^" ignore_2 "[:,]" ) i_2 = length(ignore_2) && match( line , "^" ignore_2 "[:,]" )
i_3 = length(ignore_3) && match( line , "^" ignore_3 "[:,]" ) i_3 = length(ignore_3) && match( line , "^" ignore_3 "[:,]" )
return i_0 || i_1 || i_2 || i_3 i_4 = length(ignore_3) && match( line , "^" ignore_4 "[:,]" )
return i_0 || i_1 || i_2 || i_3 || i_4
} }
BEGIN { BEGIN {
n = 1 n = 1
@ -327,8 +328,8 @@ Cat ${file} | \
Number "item-outer" "item-inner" "blank" | \ Number "item-outer" "item-inner" "blank" | \
Number "item-inner" "blank" | \ Number "item-inner" "blank" | \
Number "item-numbered" | \ Number "item-numbered" | \
Number "item-name" "item-detail" "blank" "item-detail-blank" | \ Number "item-name" "item-detail" "blank" "item-detail-blank" "code" | \
Number "item-detail" "item-detail-blank" | \ Number "item-detail" "item-detail-blank" "code" | \
Number "code" "blank" "image" | \ Number "code" "blank" "image" | \
Number "footer" "blank" "image" | \ Number "footer" "blank" "image" | \
Number "citation" "blank" | \ Number "citation" "blank" | \

View File

@ -6,15 +6,18 @@
/* Define if you have the `glob' function. */ /* Define if you have the `glob' function. */
#undef HAVE_GLOB #undef HAVE_GLOB
/* have reentrant gmtime */ /* Define if gmtime_r in time.h */
#undef HAVE_GMTIME_R #undef HAVE_GMTIME_R
/* have reentrant localtime */ /* Define if localtime_r in time.h */
#undef HAVE_LOCALTIME_R #undef HAVE_LOCALTIME_R
/* Define if you have the <ndir.h> header file, and it defines `DIR'. */ /* Define if you have the <ndir.h> header file, and it defines `DIR'. */
#undef HAVE_NDIR_H #undef HAVE_NDIR_H
/* Define if socklen_t type definition in sys/socket.h */
#undef HAVE_SOCKLEN_T
/* Define if you have the <sys/dir.h> header file, and it defines `DIR'. */ /* Define if you have the <sys/dir.h> header file, and it defines `DIR'. */
#undef HAVE_SYS_DIR_H #undef HAVE_SYS_DIR_H

978
configure vendored

File diff suppressed because it is too large Load Diff

15
configure.ac Executable file → Normal file
View File

@ -20,8 +20,8 @@ dnl ===
dnl dnl
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
AC_INIT(src/main/gsmtp.h) AC_INIT(src/gsmtp/gsmtp.h)
AM_INIT_AUTOMAKE(emailrelay,0.9.9) AM_INIT_AUTOMAKE(emailrelay,1.0.0)
AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(config.h)
dnl === dnl ===
@ -37,6 +37,7 @@ AC_CHECK_PROGS(AR,ar gar)
AC_CHECK_PROGS(GZIP,gzip) AC_CHECK_PROGS(GZIP,gzip)
AC_CHECK_PROG(HAVE_DOXYGEN,doxygen,yes) AC_CHECK_PROG(HAVE_DOXYGEN,doxygen,yes)
AC_CHECK_PROG(HAVE_MAN2HTML,man2html,yes) AC_CHECK_PROG(HAVE_MAN2HTML,man2html,yes)
ACLOCAL_COMPILER_VERSION
dnl === dnl ===
dnl check for libraries... dnl check for libraries...
@ -55,11 +56,9 @@ AC_CHECK_HEADERS(unistd.h)
AC_CHECK_HEADERS(sys/time.h) AC_CHECK_HEADERS(sys/time.h)
AC_CHECK_FUNCS(glob) AC_CHECK_FUNCS(glob)
AC_LANG_CPLUSPLUS AC_LANG_CPLUSPLUS
dnl check for *_r() declarations -- using ac_check_funcs ACLOCAL_TYPE_SOCKLEN_T
dnl is no good here since they may be in the library but ACLOCAL_CHECK_GMTIME_R
dnl not the header (depending on preprocessor switches) ACLOCAL_CHECK_LOCALTIME_R
AC_EGREP_HEADER(localtime_r,time.h,[AC_DEFINE(HAVE_LOCALTIME_R,1,[have reentrant localtime])])
AC_EGREP_HEADER(gmtime_r,time.h,[AC_DEFINE(HAVE_GMTIME_R,1,[have reentrant gmtime])])
dnl === dnl ===
dnl directory tweaking... dnl directory tweaking...
@ -89,5 +88,5 @@ SET_MAKE=""
dnl === dnl ===
dnl generate files... dnl generate files...
dnl dnl
AC_OUTPUT(Makefile src/Makefile src/glib/Makefile src/gnet/Makefile src/main/Makefile src/win32/Makefile lib/Makefile lib/gcc2.95/Makefile lib/msvc6.0/Makefile bin/Makefile doc/Makefile) AC_OUTPUT(Makefile src/Makefile src/glib/Makefile src/gnet/Makefile src/gsmtp/Makefile src/main/Makefile src/win32/Makefile lib/Makefile lib/gcc2.95/Makefile lib/msvc6.0/Makefile bin/Makefile doc/Makefile)

View File

@ -24,8 +24,9 @@ man_files_out=emailrelay.1.gz emailrelay-passwd.1.gz emailrelay-poke.1.gz emailr
html_files_in=doxygen_header.html html_files_in=doxygen_header.html
html_files_thru=index.html $(stylesheet) 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_out=readme.html developer.html reference.html userguide.html windows.html emailrelay-man.html changelog.html
png_files=gsmtp-classes.png gnet-classes.png
EXTRA_DIST = $(man_files_in) $(txt_files) $(html_files_in) $(html_files_thru) EXTRA_DIST = $(man_files_in) $(txt_files) $(html_files_in) $(html_files_thru) $(png_files)
noinst_SCRIPTS = .dox noinst_SCRIPTS = .dox
e_man1_DATA = $(man_files_out) e_man1_DATA = $(man_files_out)
e_doc_DATA = $(txt_files) $(html_files_out) $(html_files_thru) e_doc_DATA = $(txt_files) $(html_files_out) $(html_files_thru)
@ -45,7 +46,7 @@ converter_helper3=$(top_builddir)/bin/expand.sh
converter_helper3_src=$(top_srcdir)/bin/expand.sh_ converter_helper3_src=$(top_srcdir)/bin/expand.sh_
.txt.html: .txt.html:
$(converter) -a "$(AWK)" $< $(stylesheet) > $*.html $(converter) -a "$(AWK)" $(top_srcdir)/doc/$*.txt $(stylesheet) > $*.html
$(filter): $(filter_src) $(filter): $(filter_src)
cp $(filter_src) $(filter) cp $(filter_src) $(filter)
@ -71,7 +72,7 @@ $(converter_helper3): $(converter_helper3_src)
if test "$(HAVE_DOXYGEN)" = "yes" ; then cat $(top_srcdir)/src/main/doxygen.cfg | sed "s:__TOP_SRC__:$(top_srcdir):g" | sed "s:__TOP_BUILD__:$(top_builddir):g" | doxygen - && touch .dox ; else echo no doxygen ; fi if test "$(HAVE_DOXYGEN)" = "yes" ; then cat $(top_srcdir)/src/main/doxygen.cfg | sed "s:__TOP_SRC__:$(top_srcdir):g" | sed "s:__TOP_BUILD__:$(top_builddir):g" | doxygen - && touch .dox ; else echo no doxygen ; fi
emailrelay-man.html: emailrelay.1 emailrelay-man.html: emailrelay.1
if test "$(HAVE_MAN2HTML)" = "yes" ; then man2html $< > emailrelay-man.html ; fi if test "$(HAVE_MAN2HTML)" = "yes" ; then man2html emailrelay.1 > emailrelay-man.html ; fi
developer.html reference.html userguide.html: $(converter) developer.html reference.html userguide.html: $(converter)
@ -82,21 +83,22 @@ changelog.html: $(top_srcdir)/ChangeLog $(converter)
$(converter) -a "$(AWK)" $(top_srcdir)/ChangeLog $(stylesheet) > changelog.html $(converter) -a "$(AWK)" $(top_srcdir)/ChangeLog $(stylesheet) > changelog.html
emailrelay.1.gz : emailrelay.1 emailrelay.1.gz : emailrelay.1
if test -n "$(GZIP)" ; then $(GZIP) -c $< > emailrelay.1.gz ; fi if test -n "$(GZIP)" ; then $(GZIP) -c $(top_srcdir)/doc/emailrelay.1 > emailrelay.1.gz ; fi
emailrelay-passwd.1.gz : emailrelay-passwd.1 emailrelay-passwd.1.gz : emailrelay-passwd.1
if test -n "$(GZIP)" ; then $(GZIP) -c $< > emailrelay-passwd.1.gz ; fi if test -n "$(GZIP)" ; then $(GZIP) -c $(top_srcdir)/doc/emailrelay-passwd.1 > emailrelay-passwd.1.gz ; fi
emailrelay-submit.1.gz : emailrelay-submit.1 emailrelay-submit.1.gz : emailrelay-submit.1
if test -n "$(GZIP)" ; then $(GZIP) -c $< > emailrelay-submit.1.gz ; fi if test -n "$(GZIP)" ; then $(GZIP) -c $(top_srcdir)/doc/emailrelay-submit.1 > emailrelay-submit.1.gz ; fi
emailrelay-poke.1.gz: emailrelay-poke.1 emailrelay-poke.1.gz: emailrelay-poke.1
if test -n "$(GZIP)" ; then $(GZIP) -c $< > emailrelay-poke.1.gz ; fi if test -n "$(GZIP)" ; then $(GZIP) -c $(top_srcdir)/doc/emailrelay-poke.1 > emailrelay-poke.1.gz ; fi
install-data-local: install-data-local: install-e_docDATA install-e_man1DATA
$(mkinstalldirs) $(DESTDIR)$(e_docdir)/doxygen $(mkinstalldirs) $(DESTDIR)$(e_docdir)/doxygen
if test "$(HAVE_DOXYGEN)" = "yes" ; then for file in doxygen/* ; do $(INSTALL) $$file $(DESTDIR)$(e_docdir)/$$file ; done ; fi if test "$(HAVE_DOXYGEN)" = "yes" ; then for file in doxygen/* ; do $(INSTALL) $$file $(DESTDIR)$(e_docdir)/$$file ; done ; fi
uninstall-local: uninstall-local:
-rm -f $(DESTDIR)$(e_docdir)/html/* 2>/dev/null -rmdir $(DESTDIR)$(e_docdir)/doxygen 2>/dev/null
-rmdir $(DESTDIR)$(e_docdir) 2>/dev/null

View File

@ -79,6 +79,7 @@ POST_UNINSTALL = :
AR = @AR@ AR = @AR@
AWK = @AWK@ AWK = @AWK@
CC = @CC@ CC = @CC@
COMPILER_VERSION = @COMPILER_VERSION@
CXX = @CXX@ CXX = @CXX@
GZIP = @GZIP@ GZIP = @GZIP@
HAVE_DOXYGEN = @HAVE_DOXYGEN@ HAVE_DOXYGEN = @HAVE_DOXYGEN@
@ -103,8 +104,9 @@ man_files_out = emailrelay.1.gz emailrelay-passwd.1.gz emailrelay-poke.1.gz emai
html_files_in = doxygen_header.html html_files_in = doxygen_header.html
html_files_thru = index.html $(stylesheet) 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_out = readme.html developer.html reference.html userguide.html windows.html emailrelay-man.html changelog.html
png_files = gsmtp-classes.png gnet-classes.png
EXTRA_DIST = $(man_files_in) $(txt_files) $(html_files_in) $(html_files_thru) EXTRA_DIST = $(man_files_in) $(txt_files) $(html_files_in) $(html_files_thru) $(png_files)
noinst_SCRIPTS = .dox noinst_SCRIPTS = .dox
e_man1_DATA = $(man_files_out) e_man1_DATA = $(man_files_out)
e_doc_DATA = $(txt_files) $(html_files_out) $(html_files_thru) e_doc_DATA = $(txt_files) $(html_files_out) $(html_files_thru)
@ -272,7 +274,7 @@ maintainer-clean-generic clean mostlyclean distclean maintainer-clean
.txt.html: .txt.html:
$(converter) -a "$(AWK)" $< $(stylesheet) > $*.html $(converter) -a "$(AWK)" $(top_srcdir)/doc/$*.txt $(stylesheet) > $*.html
$(filter): $(filter_src) $(filter): $(filter_src)
cp $(filter_src) $(filter) cp $(filter_src) $(filter)
@ -298,7 +300,7 @@ $(converter_helper3): $(converter_helper3_src)
if test "$(HAVE_DOXYGEN)" = "yes" ; then cat $(top_srcdir)/src/main/doxygen.cfg | sed "s:__TOP_SRC__:$(top_srcdir):g" | sed "s:__TOP_BUILD__:$(top_builddir):g" | doxygen - && touch .dox ; else echo no doxygen ; fi if test "$(HAVE_DOXYGEN)" = "yes" ; then cat $(top_srcdir)/src/main/doxygen.cfg | sed "s:__TOP_SRC__:$(top_srcdir):g" | sed "s:__TOP_BUILD__:$(top_builddir):g" | doxygen - && touch .dox ; else echo no doxygen ; fi
emailrelay-man.html: emailrelay.1 emailrelay-man.html: emailrelay.1
if test "$(HAVE_MAN2HTML)" = "yes" ; then man2html $< > emailrelay-man.html ; fi if test "$(HAVE_MAN2HTML)" = "yes" ; then man2html emailrelay.1 > emailrelay-man.html ; fi
developer.html reference.html userguide.html: $(converter) developer.html reference.html userguide.html: $(converter)
@ -309,23 +311,24 @@ changelog.html: $(top_srcdir)/ChangeLog $(converter)
$(converter) -a "$(AWK)" $(top_srcdir)/ChangeLog $(stylesheet) > changelog.html $(converter) -a "$(AWK)" $(top_srcdir)/ChangeLog $(stylesheet) > changelog.html
emailrelay.1.gz : emailrelay.1 emailrelay.1.gz : emailrelay.1
if test -n "$(GZIP)" ; then $(GZIP) -c $< > emailrelay.1.gz ; fi if test -n "$(GZIP)" ; then $(GZIP) -c $(top_srcdir)/doc/emailrelay.1 > emailrelay.1.gz ; fi
emailrelay-passwd.1.gz : emailrelay-passwd.1 emailrelay-passwd.1.gz : emailrelay-passwd.1
if test -n "$(GZIP)" ; then $(GZIP) -c $< > emailrelay-passwd.1.gz ; fi if test -n "$(GZIP)" ; then $(GZIP) -c $(top_srcdir)/doc/emailrelay-passwd.1 > emailrelay-passwd.1.gz ; fi
emailrelay-submit.1.gz : emailrelay-submit.1 emailrelay-submit.1.gz : emailrelay-submit.1
if test -n "$(GZIP)" ; then $(GZIP) -c $< > emailrelay-submit.1.gz ; fi if test -n "$(GZIP)" ; then $(GZIP) -c $(top_srcdir)/doc/emailrelay-submit.1 > emailrelay-submit.1.gz ; fi
emailrelay-poke.1.gz: emailrelay-poke.1 emailrelay-poke.1.gz: emailrelay-poke.1
if test -n "$(GZIP)" ; then $(GZIP) -c $< > emailrelay-poke.1.gz ; fi if test -n "$(GZIP)" ; then $(GZIP) -c $(top_srcdir)/doc/emailrelay-poke.1 > emailrelay-poke.1.gz ; fi
install-data-local: install-data-local: install-e_docDATA install-e_man1DATA
$(mkinstalldirs) $(DESTDIR)$(e_docdir)/doxygen $(mkinstalldirs) $(DESTDIR)$(e_docdir)/doxygen
if test "$(HAVE_DOXYGEN)" = "yes" ; then for file in doxygen/* ; do $(INSTALL) $$file $(DESTDIR)$(e_docdir)/$$file ; done ; fi if test "$(HAVE_DOXYGEN)" = "yes" ; then for file in doxygen/* ; do $(INSTALL) $$file $(DESTDIR)$(e_docdir)/$$file ; done ; fi
uninstall-local: uninstall-local:
-rm -f $(DESTDIR)$(e_docdir)/html/* 2>/dev/null -rmdir $(DESTDIR)$(e_docdir)/doxygen 2>/dev/null
-rmdir $(DESTDIR)$(e_docdir) 2>/dev/null
# Tell versions [3.59,3.63) of GNU make to not export all variables. # Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded. # Otherwise a system limit (for SysV at least) may be exceeded.

View File

@ -3,15 +3,12 @@ E-MailRelay Developer guide
Module structure Module structure
---------------- ----------------
There are two C++ libraries in the E-MailRelay code: "glib" provides low-level There are three C++ libraries in the E-MailRelay code: "glib" provides low-level
classes for file-system abstraction, date and time representation, string classes for file-system abstraction, date and time representation, string
utility functions, logging, command line parsing etc., and "gnet" provides utility functions, logging, command line parsing etc., "gnet" provides network
network classes using the Berkley socket and Winsock APIs. Both libraries classes using the Berkley socket and Winsock APIs, and "gsmtp" contains SMTP and
are portable between POSIX-like systems (eg. Linux) and Windows. message-store classes. All three libraries are portable between POSIX-like
systems (eg. Linux) and Windows.
The application-level classes are implemented within the "GSmtp" and "Main"
namespaces. The key interfaces in the "GSmtp" namespace are "ClientProtocol",
"ServerProtocol" and "MessageStore".
Under Windows there is an additional library for event handling. Windows has Under Windows there is an additional library for event handling. Windows has
historically built network event processing on top of the GUI event system, historically built network event processing on top of the GUI event system,
@ -38,8 +35,8 @@ another for immediate forwarding ("ProtocolMessageForward").
The protocol and message-store functionality are brought together by the The protocol and message-store functionality are brought together by the
high-level "GSmtp::Server" and "GSmtp::Client" classes. high-level "GSmtp::Server" and "GSmtp::Client" classes.
Simplified class diagrams for the *GNet* [graphics/gnet-classes.png] and Simplified class diagrams for the *GNet* [gnet-classes.png] and
*GSmtp* [graphics/gsmtp-classes.png] namespaces are available. *GSmtp* [gsmtp-classes.png] namespaces are available.
Directory structure Directory structure
------------------- -------------------
@ -57,6 +54,10 @@ Directory structure
A network library using Berkley sockets or Winsock. A network library using Berkley sockets or Winsock.
# src/gsmtp
An SMTP library.
# src/win32 # src/win32
Additional classes for windows event processing. Additional classes for windows event processing.
@ -87,9 +88,9 @@ For a quick bottom-up tour of the code take a look at the following headers:
* src/gnet/gaddress.h * src/gnet/gaddress.h
* src/gnet/gsocket.h * src/gnet/gsocket.h
* src/gnet/gserver.h * src/gnet/gserver.h
* src/main/gmessagestore.h * src/smtp/gmessagestore.h
* src/main/gserverprotocol.h * src/smtp/gserverprotocol.h
* src/main/gsmtpserver.h * src/smtp/gsmtpserver.h
Portability Portability
----------- -----------

View File

@ -58,13 +58,13 @@ server.
Enables the administration interface and specifies its listening port number. Enables the administration interface and specifies its listening port number.
.TP .TP
.B \-q,--as-client \fIhost:port\fR .B \-q,--as-client \fIhost:port\fR
Equivalent to \fI--log\fR \fI--no-syslog\fR \fI--no-daemon\fR \fI--dont-serve\fR \fI--forward\fR \fI--forward-to\fR. Runs as a client, forwarding spooled mail to <host>: equivalent to \fI--log\fR \fI--no-syslog\fR \fI--no-daemon\fR \fI--dont-serve\fR \fI--forward\fR \fI--forward-to\fR.
.TP .TP
.B \-y,--as-proxy \fIhost:port\fR .B \-y,--as-proxy \fIhost:port\fR
Equivalent to \fI--log\fR \fI--close-stderr\fR \fI--immediate\fR \fI--forward-to\fR. Runs as a proxy: equivalent to \fI--log\fR \fI--close-stderr\fR \fI--immediate\fR \fI--forward-to\fR.
.TP .TP
.B \-d,--as-server .B \-d,--as-server
Equivalent to \fI--log\fR \fI--close-stderr\fR. Runs as a server: equivalent to \fI--log\fR \fI--close-stderr\fR.
.TP .TP
.B \-C,--client-auth \fIfile\fR .B \-C,--client-auth \fIfile\fR
Enables authentication with remote server, using the given secrets file. Enables authentication with remote server, using the given secrets file.
@ -75,14 +75,20 @@ Closes the standard error stream after start-up.
.B \-U,--connection-timeout \fItime\fR .B \-U,--connection-timeout \fItime\fR
Sets the timeout (in seconds) when connecting to a remote server (default is 40). Sets the timeout (in seconds) when connecting to a remote server (default is 40).
.TP .TP
.B \-g,--debug
Generates debug-level logging (if compiled-in).
.TP
.B \-D,--domain \fIfqdn\fR .B \-D,--domain \fIfqdn\fR
Sets an override for the host's fully qualified domain name. Sets an override for the host's fully qualified domain name.
.TP .TP
.B \-X,--dont-listen
Dont listen for smtp connections (usually used with \fI--admin\fR).
.TP
.B \-x,--dont-serve .B \-x,--dont-serve
Stops the process acting as a server (usually used with \fI--forward\fR). Dont act as a server (usually used with \fI--forward\fR).
.TP .TP
.B \-z,--filter \fIprogram\fR .B \-z,--filter \fIprogram\fR
Defines a mail pre-processor. Defines a mail processor program.
.TP .TP
.B \-f,--forward .B \-f,--forward
Forwards stored mail on startup (requires \fI--forward-to\fR). Forwards stored mail on startup (requires \fI--forward-to\fR).
@ -96,8 +102,11 @@ Displays help text and exits.
.B \-m,--immediate .B \-m,--immediate
Forwards each message as soon as it is received (requires \fI--forward-to\fR). Forwards each message as soon as it is received (requires \fI--forward-to\fR).
.TP .TP
.B \-I,--interface \fIip-address\fR
Listen on a specific interface.
.TP
.B \-l,--log .B \-l,--log
Writes log information on standard error (if open) and syslog (if not disabled). Writes log information on standard error and syslog.
.TP .TP
.B \-L,--log-time .B \-L,--log-time
Adds a timestamp to the logging output. Adds a timestamp to the logging output.
@ -124,68 +133,33 @@ Sets the response timeout (in seconds) when talking to a remote server (default
Enables authentication of remote clients, using the given secrets file. Enables authentication of remote clients, using the given secrets file.
.TP .TP
.B \-s,--spool-dir \fIdir\fR .B \-s,--spool-dir \fIdir\fR
Specifies the spool directory (default is \fI/usr/local/var/spool/emailrelay\fR). Specifies the spool directory (default is \fI/var/spool/emailrelay\fR).
.TP .TP
.B \-u,--user \fIusername\fR .B \-u,--user \fIusername\fR
Names the effective user to switch to when started as root (default is \fIdaemon\fR). Names the effective user to switch to when started as root (default is \fIdaemon\fR).
.TP .TP
.B \-v,--verbose .B \-v,--verbose
Generates more verbose logging (if compiled-in and logging enabled and stderr open). Generates more verbose output (works with \fI--help\fR and \fI--log\fR).
.TP
.B \-Z,--verifier \fIprogram\fR
Defines an external address verifier program.
.TP .TP
.B \-V,--version .B \-V,--version
Displays version information and exits. Displays version information and exits.
.SH FILES .SH FILES
GNU style... GNU style...
.br .br
/usr/local/libexec/emailrelay-passwd
.br
/usr/local/libexec/emailrelay-poke
.br
/usr/local/libexec/emailrelay /usr/local/libexec/emailrelay
.br .br
/usr/local/libexec/emailrelay-notify.sh
.br
/usr/local/libexec/emailrelay-deliver.sh /usr/local/libexec/emailrelay-deliver.sh
.br .br
/usr/local/libexec/emailrelay-notify.sh
.br
/usr/local/libexec/emailrelay-poke
.br
/usr/local/libexec/emailrelay-process.sh /usr/local/libexec/emailrelay-process.sh
.br .br
/usr/local/sbin/emailrelay-submit /usr/local/libexec/emailrelay-resubmit.sh
.br
/usr/local/sbin/emailrelay
.br
/usr/local/share/emailrelay/doc/developer.txt
.br
/usr/local/share/emailrelay/doc/reference.txt
.br
/usr/local/share/emailrelay/doc/userguide.txt
.br
/usr/local/share/emailrelay/doc/windows.txt
.br
/usr/local/share/emailrelay/doc/readme.html
.br
/usr/local/share/emailrelay/doc/developer.html
.br
/usr/local/share/emailrelay/doc/reference.html
.br
/usr/local/share/emailrelay/doc/userguide.html
.br
/usr/local/share/emailrelay/doc/windows.html
.br
/usr/local/share/emailrelay/doc/emailrelay-man.html
.br
/usr/local/share/emailrelay/doc/index.html
.br
/usr/local/share/emailrelay/doc/changelog.html
.br
/usr/local/share/emailrelay/doc/emailrelay.css
.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/man/man1/emailrelay.1.gz
.br .br
/usr/local/man/man1/emailrelay-passwd.1.gz /usr/local/man/man1/emailrelay-passwd.1.gz
.br .br
@ -193,51 +167,59 @@ GNU style...
.br .br
/usr/local/man/man1/emailrelay-submit.1.gz /usr/local/man/man1/emailrelay-submit.1.gz
.br .br
/usr/local/var/spool/emailrelay/emailrelay.*.envelope /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 .br
/usr/local/var/spool/emailrelay/emailrelay.*.content /usr/local/var/spool/emailrelay/emailrelay.*.content
.br
/usr/local/var/spool/emailrelay/emailrelay.*.envelope
.LP .LP
FHS style... FHS style...
.br .br
/usr/lib/emailrelay-passwd /etc/init.d/emailrelay
.br .br
/usr/lib/emailrelay-poke /usr/lib/emailrelay/emailrelay-poke
.br
/usr/sbin/emailrelay-submit
.br .br
/usr/sbin/emailrelay /usr/sbin/emailrelay
.br .br
/usr/share/doc/emailrelay/examples/emailrelay-notify.sh /usr/sbin/emailrelay-passwd
.br .br
/usr/share/doc/emailrelay/examples/emailrelay-deliver.sh /usr/sbin/emailrelay-submit
.br
/usr/share/doc/emailrelay/examples/emailrelay-process.sh
.br
/usr/share/doc/emailrelay/developer.txt
.br
/usr/share/doc/emailrelay/reference.txt
.br
/usr/share/doc/emailrelay/userguide.txt
.br
/usr/share/doc/emailrelay/windows.txt
.br
/usr/share/doc/emailrelay/readme.html
.br
/usr/share/doc/emailrelay/developer.html
.br
/usr/share/doc/emailrelay/reference.html
.br
/usr/share/doc/emailrelay/userguide.html
.br
/usr/share/doc/emailrelay/windows.html
.br
/usr/share/doc/emailrelay/emailrelay-man.html
.br
/usr/share/doc/emailrelay/index.html
.br
/usr/share/doc/emailrelay/changelog.html
.br
/usr/share/doc/emailrelay/emailrelay.css
.br .br
/usr/share/doc/emailrelay/NEWS /usr/share/doc/emailrelay/NEWS
.br .br
@ -245,7 +227,37 @@ FHS style...
.br .br
/usr/share/doc/emailrelay/changelog.gz /usr/share/doc/emailrelay/changelog.gz
.br .br
/usr/share/man/man1/emailrelay.1.gz /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 .br
/usr/share/man/man1/emailrelay-passwd.1.gz /usr/share/man/man1/emailrelay-passwd.1.gz
.br .br
@ -253,11 +265,11 @@ FHS style...
.br .br
/usr/share/man/man1/emailrelay-submit.1.gz /usr/share/man/man1/emailrelay-submit.1.gz
.br .br
/etc/init.d/emailrelay /usr/share/man/man1/emailrelay.1.gz
.br
/var/spool/emailrelay/emailrelay.*.envelope
.br .br
/var/spool/emailrelay/emailrelay.*.content /var/spool/emailrelay/emailrelay.*.content
.br
/var/spool/emailrelay/emailrelay.*.envelope
.SH SEE ALSO .SH SEE ALSO
E-MailRelay user guide E-MailRelay user guide
.br .br

View File

@ -8,6 +8,7 @@ div.two-column-content
div.two-column-menu div.two-column-menu
{ {
color: inherit ;
background-color: #eee ; background-color: #eee ;
position: absolute ; position: absolute ;
@ -28,7 +29,9 @@ div.two-column-menu
body body
{ {
font-family: verdana, arial, helvetica, sans-serif ; font-family: verdana, arial, helvetica, sans-serif ;
background-color: white ;
color: #000 ;
background-color: #fff ;
} }
div.div-main div.div-main
@ -39,7 +42,8 @@ div.div-main
div.div-toc div.div-toc
{ {
background: #eee ; color: inherit ;
background-color: #eee ;
} }
p.p-toc p.p-toc
@ -55,7 +59,8 @@ div.div-pre
{ {
margin-left: 3% ; margin-left: 3% ;
/* font-size: smaller ; */ /* smaller is unreadable on ie5 */ /* font-size: smaller ; */ /* smaller is unreadable on ie5 */
background: #eee ; color: inherit ;
background-color: #eee ;
padding: 0.5em ; padding: 0.5em ;
border: none ; border: none ;
} }
@ -64,6 +69,7 @@ h1
{ {
text-align: center ; text-align: center ;
color: #09c ; color: #09c ;
background-color: inherit ;
} }
img img
@ -74,22 +80,25 @@ img
h2 h2
{ {
color: #09c ; color: #09c ;
background-color: inherit ;
} }
p p
{ {
font: verdana, arial, helvetica, sans-serif ; font-family: verdana, arial, helvetica, sans-serif ;
text-align: justify ; text-align: justify ;
} }
a.a-toc a.a-toc
{ {
color: #09c ; color: #09c ;
background-color: inherit ;
text-decoration: none ; text-decoration: none ;
} }
a.a-toc:hover a.a-toc:hover
{ {
color: #09c ;
background-color: #ccc ; background-color: #ccc ;
} }
@ -107,20 +116,24 @@ a.a-href
a.a-href:link a.a-href:link
{ {
color: #09c ; color: #09c ;
background-color: inherit ;
} }
a.a-href:visited a.a-href:visited
{ {
color: #07a ; color: #07a ;
background-color: inherit ;
} }
a.a-href:hover a.a-href:hover
{ {
color: #09c ;
background-color: #eee ; background-color: #eee ;
} }
div.two-column-header div.two-column-header
{ {
color: inherit ;
background-color: #eee ; background-color: #eee ;
border-style: solid ; border-style: solid ;

BIN
doc/gnet-classes.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
doc/gsmtp-classes.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -8,15 +8,15 @@
<div class="div-main"> <div class="div-main">
<h1>E-MailRelay Documentation</h1> <h1>E-MailRelay Documentation</h1>
<ul> <ul>
<li><a href="readme.html">Readme</a></li> <li><a class="a-href" href="readme.html">Readme</a></li>
<li><a href="changelog.html">Change log</a></li> <li><a class="a-href" href="changelog.html">Change log</a></li>
<li><a href="userguide.html">User guide</a></li> <li><a class="a-href" href="userguide.html">User guide</a></li>
<li><a href="reference.html">Reference manual</a></li> <li><a class="a-href" href="reference.html">Reference manual</a></li>
<li><a href="windows.html">Windows installation guide</a></li> <li><a class="a-href" href="windows.html">Windows installation guide</a></li>
<li><a href="developer.html">Notes for developers</a></li> <li><a class="a-href" href="developer.html">Notes for developers</a></li>
<li><a href="doxygen/index.html">Source code documentation</a> (generated by <a href="http://www.doxygen.org">doxygen</a>, if available)</li> <li><a class="a-href" href="doxygen/index.html">Source code documentation</a> (generated by <a class="a-href" href="http://www.doxygen.org">doxygen</a>, if available)</li>
<li><a href="emailrelay-man.html">Man page</a> (generated by man2html, if available)</li> <li><a class="a-href" href="emailrelay-man.html">Man page</a> (generated by man2html, if available)</li>
<li><a href="http://emailrelay.sourceforge.net">Web site</a></li> <li><a class="a-href" href="http://emailrelay.sourceforge.net">Web site</a></li>
</ul> </ul>
</div> </div>
</body> </body>

View File

@ -13,18 +13,17 @@ The "emailrelay" program supports the following command-line usage:
emailrelay [<switch> [<switch> ...]] emailrelay [<switch> [<switch> ...]]
where <switch> is: where <switch> is:
# --admin (-a) # --admin (-a)
Enables the administration interface and specifies its listening port number. Enables the administration interface and specifies its listening port number.
# --as-client (-q) # --as-client (-q)
Equivalent to "--log --no-syslog --no-daemon --dont-serve --forward --forward-to". Runs as a client, forwarding spooled mail to <host>: equivalent to "--log --no-syslog --no-daemon --dont-serve --forward --forward-to".
# --as-proxy (-y) # --as-proxy (-y)
Equivalent to "--log --close-stderr --immediate --forward-to". Runs as a proxy: equivalent to "--log --close-stderr --immediate --forward-to".
# --as-server (-d) # --as-server (-d)
Equivalent to "--log --close-stderr". Runs as a server: equivalent to "--log --close-stderr".
# --client-auth (-C) # --client-auth (-C)
Enables authentication with remote server, using the given secrets file. Enables authentication with remote server, using the given secrets file.
@ -35,14 +34,20 @@ where <switch> is:
# --connection-timeout (-U) # --connection-timeout (-U)
Sets the timeout (in seconds) when connecting to a remote server (default is 40). Sets the timeout (in seconds) when connecting to a remote server (default is 40).
# --debug (-g)
Generates debug-level logging (if compiled-in).
# --domain (-D) # --domain (-D)
Sets an override for the host's fully qualified domain name. Sets an override for the host's fully qualified domain name.
# --dont-listen (-X)
Dont listen for smtp connections (usually used with --admin).
# --dont-serve (-x) # --dont-serve (-x)
Stops the process acting as a server (usually used with --forward). Dont act as a server (usually used with --forward).
# --filter (-z) # --filter (-z)
Defines a mail pre-processor. Defines a mail processor program.
# --forward (-f) # --forward (-f)
Forwards stored mail on startup (requires --forward-to). Forwards stored mail on startup (requires --forward-to).
@ -56,8 +61,11 @@ where <switch> is:
# --immediate (-m) # --immediate (-m)
Forwards each message as soon as it is received (requires --forward-to). Forwards each message as soon as it is received (requires --forward-to).
# --interface (-I)
Listen on a specific interface.
# --log (-l) # --log (-l)
Writes log information on standard error (if open) and syslog (if not disabled). Writes log information on standard error and syslog.
# --log-time (-L) # --log-time (-L)
Adds a timestamp to the logging output. Adds a timestamp to the logging output.
@ -84,13 +92,16 @@ where <switch> is:
Enables authentication of remote clients, using the given secrets file. Enables authentication of remote clients, using the given secrets file.
# --spool-dir (-s) # --spool-dir (-s)
Specifies the spool directory (default is "/usr/local/var/spool/emailrelay"). Specifies the spool directory (default is "/var/spool/emailrelay").
# --user (-u) # --user (-u)
Names the effective user to switch to when started as root (default is "daemon"). Names the effective user to switch to when started as root (default is "daemon").
# --verbose (-v) # --verbose (-v)
Generates more verbose logging (if compiled-in and logging enabled and stderr open). Generates more verbose output (works with --help and --log).
# --verifier (-Z)
Defines an external address verifier program.
# --version (-V) # --version (-V)
Displays version information and exits. Displays version information and exits.
@ -181,6 +192,29 @@ SMTP issues
re-encode 8-bit messages into 7-bit messages if the next-hop server re-encode 8-bit messages into 7-bit messages if the next-hop server
does not. does not.
Address validation
------------------
An address supplied to the SMTP commands "RCPT" and "VRFY" is normally accepted
if it contains an at sign, or if it is some sort of local "postmaster" address
(as described above). However, this behaviour can be modified by using an external
verifier program, using the "--verifier" command-line switch.
The verifier program is passed a command-line containing the full address, the
user-name part of the address, the host-name part, the local host's fully
qualified domain name, and the current "MAIL" command's "FROM:" address or the
empty string for the "VRFY" command.
For valid local mailbox addresses the verifier is expected to write two lines to
the standard output -- the full name associated with the mailbox, and the
canonical mailbox name -- and then exit with a value of zero. For valid non-local
addresses the first line of output should be empty, the second line should be
copied from the first command-line argument, and the exit value should be one.
For invalid addresses the exit value should be greater than one, and anything
written to the standard output is taken as the failure reason.
(Only the few few thousand characters are read from the verifier's standard
output stream; any more is thrown away.)
Administration interface Administration interface
------------------------ ------------------------
If enabled, the server will provide a network interface for performing If enabled, the server will provide a network interface for performing
@ -198,31 +232,31 @@ functionality of storage daemon and forwarding client. This might be useful
in systems which are low on memory: the memory footprint of "telnet" or in systems which are low on memory: the memory footprint of "telnet" or
"emailrelay-poke" will be much smaller than "emailrelay --as-client". "emailrelay-poke" will be much smaller than "emailrelay --as-client".
Mail pre-processing Mail processing
------------------- ---------------
The "--filter" command-line switch allows you to specify a pre-processor program The "--filter" command-line switch allows you to specify a mail processor program
which operates on mail messages as they pass through the E-MailRelay system. The which operates on mail messages as they pass through the E-MailRelay system. The
pre-processor program is run as soon as the mail message has been stored in the mail processor program is run as soon as the mail message has been stored in the
spool directory, with the full path of the content file specified on the command spool directory, with the full path of the content file specified on the command
line. line.
This can be combined with the "--immediate" (or "--as-proxy") switch to implement This can be combined with the "--immediate" (or "--as-proxy") switch to implement
personal mail pre-processing, without replacing or reconfiguring the system's personal mail processing, without replacing or reconfiguring the system's
default MTA. default MTA.
For example, the following command will start a proxy server on port 10025 For example, the following command will start a proxy server on port 10025 which
which pre-processes mail using the specified filter program, and then processes mail using the specified filter program, and then forwards the mail on
forwards the mail on to the system's default MTA (on port 25): to the system's default MTA (on port 25):
emailrelay --as-proxy localhost:smtp --port 10025 --no-syslog \ emailrelay --as-proxy localhost:smtp --port 10025 --no-syslog \
--filter ${HOME}/.emailrelay/filter \ --filter ${HOME}/.emailrelay/filter \
--spool-dir ${HOME}/.emailrelay/spool --spool-dir ${HOME}/.emailrelay/spool
The pre-processor program should terminate with an exit code of zero to indicate The mail processor program should terminate with an exit code of zero to indicate
success. An exit code of 100 can be used to cancel all further processing of the success. An exit code of 100 can be used to cancel all further processing of the
message, and any other non-zero exit code is used to indicate an error. message, and any other non-zero exit code is used to indicate an error.
For example, the following pre-processor shell script examines the client's For example, the following mail processor shell script examines the client's
IP address and conditionally dumps the message into "sendmail" (using the IP address and conditionally dumps the message into "sendmail" (using the
sendmail command-line interface rather than SMTP): sendmail command-line interface rather than SMTP):
@ -239,14 +273,14 @@ sendmail command-line interface rather than SMTP):
fi fi
exit 0 exit 0
An example pre-processor script which does simple rot-13 masking of messages is An example mail processor script which does simple rot-13 masking of messages is
also provided in the distribution ("share/emailrelay/emailrelay-process.sh"). also provided in the distribution ("share/emailrelay/emailrelay-process.sh").
This could be used as a template for a more sophisticated message encryption This could be used as a template for a more sophisticated message encryption
system. system.
Security issues Security issues
--------------- ---------------
A major security concern is the use of an external mail pre-processor (using the A major security concern is the use of an external mail processor (using the
"--filter" switch), and so the following precautions are taken: "--filter" switch), and so the following precautions are taken:
# effective userid # effective userid
@ -261,13 +295,13 @@ A major security concern is the use of an external mail pre-processor (using the
# execution environment # execution environment
The pre-processor runs with an almost empty set of environment variables ("PATH" The mail processor runs with an almost empty set of environment variables ("PATH"
and "IFS"), and with no open file descriptors other than "stdin"/"stdout"/"stderr" and "IFS"), and with no open file descriptors other than "stdin"/"stdout"/"stderr"
open onto "/dev/null". open onto "/dev/null".
# configuration # configuration
The pre-processor filename has to be configured using a full path, so there is The mail processor filename has to be configured using a full path, so there is
no dependence on the current working directory or the PATH environment variable. no dependence on the current working directory or the PATH environment variable.
Security issues which relate to the SMTP protocol itself are beyond the scope of Security issues which relate to the SMTP protocol itself are beyond the scope of
@ -284,7 +318,7 @@ Some other points are:
* Strings are dynamically allocated, so buffer overflow/truncation issues are avoided. * Strings are dynamically allocated, so buffer overflow/truncation issues are avoided.
* By default connections to the SMTP and administrative ports will be rejected if they come from remote machines. * By default connections to the SMTP and administrative ports will be rejected if they come from remote machines.
* No configuration parameters can be changed through the administrative interface. * No configuration parameters can be changed through the administrative interface.
* No exec(), system() or popen() calls are used other than execve() to spawn the mail pre-processor. * No exec(), system() or popen() calls are used other than execve() to spawn the mail processor.
* The submit utility is installed as set-group-id with group ownership of "daemon". * The submit utility is installed as set-group-id with group ownership of "daemon".
Authentication Authentication
@ -339,7 +373,7 @@ least make sure that the secrets file has tight permissions, and that the
passwords in it are not also used for anything important (such as root access). passwords in it are not also used for anything important (such as root access).
On the server side authentication is advertised in the response to the SMTP On the server side authentication is advertised in the response to the SMTP
"EHLO" command if the "--auth-server" command line switch is used, but "EHLO" command if the "--auth-server" command-line switch is used, but
authentication by the client is optional. If the client does authenticate then authentication by the client is optional. If the client does authenticate then
the authenticated user-id is stored with the message and then passed on to a the authenticated user-id is stored with the message and then passed on to a
next-hop server using an "AUTH=userid" parameter on the SMTP "MAIL FROM" next-hop server using an "AUTH=userid" parameter on the SMTP "MAIL FROM"
@ -362,80 +396,99 @@ from a particular IP address is allowed. This type of POP-before-SMTP
authentication can be done outside the E-MailRelay system by POP/IMAP utilities authentication can be done outside the E-MailRelay system by POP/IMAP utilities
such as "fetchmail". such as "fetchmail".
Installation directories Application notes
------------------------ -----------------
# *Mutt* [http://www.mutt.org]
Mutt can be configured to use the E-MailRelay 'submit' program rather than
"sendmail" with an entry in the ".muttrc" file like this:
set sendmail="/usr/local/libexec/emailrelay-submit"
# *Spam Assassin* [http://spamassassin.taint.org]
The E-MailRelay server can use Spam Assasin to mark potential spam by having
a small shell script which calls spamassassin's "spamc" program installed
as the E-MailRelay mail processor (using the "--filter" command-line switch).
The shell script would look something like this:
#!/bin/sh
tmp="`basename $0`.$$.tmp"
cat ${1} | spamc > ${tmp} && mv ${tmp} ${1}
Files and directories
---------------------
By default "make install" installs files in the following locations: By default "make install" installs files in the following locations:
* /usr/local/libexec/emailrelay-poke
* /usr/local/libexec/emailrelay-notify.sh
* /usr/local/libexec/emailrelay-deliver.sh
* /usr/local/libexec/emailrelay-resubmit.sh
* /usr/local/libexec/emailrelay * /usr/local/libexec/emailrelay
* /usr/local/libexec/emailrelay-deliver.sh
* /usr/local/libexec/emailrelay-notify.sh
* /usr/local/libexec/emailrelay-poke
* /usr/local/libexec/emailrelay-process.sh * /usr/local/libexec/emailrelay-process.sh
* /usr/local/sbin/emailrelay * /usr/local/libexec/emailrelay-resubmit.sh
* /usr/local/sbin/emailrelay-passwd
* /usr/local/sbin/emailrelay-submit
* /usr/local/var/spool/emailrelay/*
* /usr/local/share/emailrelay/doc/developer.txt
* /usr/local/share/emailrelay/doc/reference.txt
* /usr/local/share/emailrelay/doc/userguide.txt
* /usr/local/share/emailrelay/doc/windows.txt
* /usr/local/share/emailrelay/doc/readme.html
* /usr/local/share/emailrelay/doc/developer.html
* /usr/local/share/emailrelay/doc/reference.html
* /usr/local/share/emailrelay/doc/userguide.html
* /usr/local/share/emailrelay/doc/windows.html
* /usr/local/share/emailrelay/doc/emailrelay-man.html
* /usr/local/share/emailrelay/doc/index.html
* /usr/local/share/emailrelay/doc/changelog.html
* /usr/local/share/emailrelay/doc/emailrelay.css
* /usr/local/share/emailrelay/doc/NEWS
* /usr/local/share/emailrelay/doc/README
* /usr/local/share/emailrelay/doc/changelog.gz
* /usr/local/share/emailrelay/doc/doxygen/*
* /usr/local/man/man1/emailrelay.1.gz
* /usr/local/man/man1/emailrelay-passwd.1.gz * /usr/local/man/man1/emailrelay-passwd.1.gz
* /usr/local/man/man1/emailrelay-poke.1.gz * /usr/local/man/man1/emailrelay-poke.1.gz
* /usr/local/man/man1/emailrelay-submit.1.gz * /usr/local/man/man1/emailrelay-submit.1.gz
* /usr/local/man/man1/emailrelay.1.gz
* /usr/local/sbin/emailrelay
* /usr/local/sbin/emailrelay-passwd
* /usr/local/sbin/emailrelay-submit
* /usr/local/share/emailrelay/doc/NEWS
* /usr/local/share/emailrelay/doc/README
* /usr/local/share/emailrelay/doc/changelog.gz
* /usr/local/share/emailrelay/doc/changelog.html
* /usr/local/share/emailrelay/doc/developer.html
* /usr/local/share/emailrelay/doc/developer.txt
* /usr/local/share/emailrelay/doc/emailrelay.css
* /usr/local/share/emailrelay/doc/index.html
* /usr/local/share/emailrelay/doc/readme.html
* /usr/local/share/emailrelay/doc/reference.html
* /usr/local/share/emailrelay/doc/reference.txt
* /usr/local/share/emailrelay/doc/userguide.html
* /usr/local/share/emailrelay/doc/userguide.txt
* /usr/local/share/emailrelay/doc/windows.html
* /usr/local/share/emailrelay/doc/windows.txt
* /usr/local/var/spool/emailrelay/emailrelay.*.content
* /usr/local/var/spool/emailrelay/emailrelay.*.envelope
This directory structure is constrained by the GNU/"autoconf" conventions rather This directory structure is constrained by the GNU/"autoconf" conventions rather
than the Filesystem Hierarchy Standard (FHS). than the Filesystem Hierarchy Standard (FHS).
To force FHS compliance you can use the "--enable-fhs" switch when running To force FHS compliance you can use the "--enable-fhs" switch when running
"configure". This results in the following file locations: "configure". This results in the following file locations:
* /etc/init.d/emailrelay
* /usr/lib/emailrelay/emailrelay-poke * /usr/lib/emailrelay/emailrelay-poke
* /usr/sbin/emailrelay * /usr/sbin/emailrelay
* /usr/sbin/emailrelay-passwd * /usr/sbin/emailrelay-passwd
* /usr/sbin/emailrelay-submit * /usr/sbin/emailrelay-submit
* /usr/share/doc/emailrelay/examples/emailrelay-notify.sh
* /usr/share/doc/emailrelay/examples/emailrelay-deliver.sh
* /usr/share/doc/emailrelay/examples/emailrelay-resubmit.sh
* /usr/share/doc/emailrelay/examples/emailrelay-process.sh
* /usr/share/doc/emailrelay/developer.txt
* /usr/share/doc/emailrelay/reference.txt
* /usr/share/doc/emailrelay/userguide.txt
* /usr/share/doc/emailrelay/windows.txt
* /usr/share/doc/emailrelay/readme.html
* /usr/share/doc/emailrelay/developer.html
* /usr/share/doc/emailrelay/reference.html
* /usr/share/doc/emailrelay/userguide.html
* /usr/share/doc/emailrelay/windows.html
* /usr/share/doc/emailrelay/emailrelay-man.html
* /usr/share/doc/emailrelay/index.html
* /usr/share/doc/emailrelay/changelog.html
* /usr/share/doc/emailrelay/emailrelay.css
* /usr/share/doc/emailrelay/NEWS * /usr/share/doc/emailrelay/NEWS
* /usr/share/doc/emailrelay/README * /usr/share/doc/emailrelay/README
* /usr/share/doc/emailrelay/changelog.gz * /usr/share/doc/emailrelay/changelog.gz
* /usr/share/doc/emailrelay/doxygen/* * /usr/share/doc/emailrelay/changelog.html
* /usr/share/man/man1/emailrelay.1.gz * /usr/share/doc/emailrelay/developer.html
* /usr/share/doc/emailrelay/developer.txt
* /usr/share/doc/emailrelay/emailrelay.css
* /usr/share/doc/emailrelay/examples/emailrelay-deliver.sh
* /usr/share/doc/emailrelay/examples/emailrelay-notify.sh
* /usr/share/doc/emailrelay/examples/emailrelay-process.sh
* /usr/share/doc/emailrelay/examples/emailrelay-resubmit.sh
* /usr/share/doc/emailrelay/index.html
* /usr/share/doc/emailrelay/readme.html
* /usr/share/doc/emailrelay/reference.html
* /usr/share/doc/emailrelay/reference.txt
* /usr/share/doc/emailrelay/userguide.html
* /usr/share/doc/emailrelay/userguide.txt
* /usr/share/doc/emailrelay/windows.html
* /usr/share/doc/emailrelay/windows.txt
* /usr/share/man/man1/emailrelay-passwd.1.gz * /usr/share/man/man1/emailrelay-passwd.1.gz
* /usr/share/man/man1/emailrelay-poke.1.gz * /usr/share/man/man1/emailrelay-poke.1.gz
* /usr/share/man/man1/emailrelay-submit.1.gz * /usr/share/man/man1/emailrelay-submit.1.gz
* /var/spool/emailrelay/* * /usr/share/man/man1/emailrelay.1.gz
* /etc/init.d/emailrelay * /var/spool/emailrelay/emailrelay.*.content
* /var/spool/emailrelay/emailrelay.*.envelope
For finer control of the directory structure the following variables For finer control of the directory structure the following variables
can be specified on the "configure" command line (but note that the can be specified on the "configure" command-line (but note that the
"--enable-fhs" will override them): "--enable-fhs" will override them):
* e_sbindir * e_sbindir
* e_libexecdir * e_libexecdir
@ -451,12 +504,26 @@ and create the E-MailRelay spool directory as "/tmp/spool" rather than
"/usr/local/var/spool/emailrelay". "/usr/local/var/spool/emailrelay".
The default spool directory path which is built into the executables and scripts The default spool directory path which is built into the executables and scripts
comes from "configure", via the makefiles. So if you re-run "configure" with a comes from "configure", via the makefiles. So after running "configure" with a
different spool directory you should also do a "make clean" in at least different spool directory do a "make clean" in at least "src/main" and "bin".
"src/main" and "bin".
Even though the "--enable-fhs" switch overrides all other directory specifiers
during the build process, it is still possible to change the installation
root directory using "make install DESTDIR=<root>" or "DESTDIR=<root> make -e install".
However this will not affect the default spool directory path built into the
scripts and executables; the spool directory path will have to be explicitly
defined at run-time.
For example, building with "configure --enable-fhs ; make ; make install DESTDIR=/root"
would create a spool directory "/root/var/spool/emailrelay", but the server
run as "/root/usr/sbin/emailrelay --as-server" would use a expect a spool directory
of "/var/spool/emailrelay". This could be fixed by either adding
"--spool-dir /root/var/spool/emailrelay" to the server command-line, or by
creating the "/var/spool/emailrelay" directory manually.
The "emailrelay" script in "init.d" creates a pid file in "/var/run" if the The "emailrelay" script in "init.d" creates a pid file in "/var/run" if the
directory exists, or in "/tmp" otherwise. directory exists, or in "/tmp" otherwise.
Copyright (C) 2001-2002 Graeme Walker <graeme_walker@users.sourceforge.net>. All rights reserved. Copyright (C) 2001-2002 Graeme Walker <graeme_walker@users.sourceforge.net>. All rights reserved.

View File

@ -94,7 +94,7 @@ The standard installation of E-MailRelay (using "make install") puts most of
the files into the right places, but it does not set things up so that the the files into the right places, but it does not set things up so that the
daemon starts at boot time, or that e-mail gets forwarded automatically when daemon starts at boot time, or that e-mail gets forwarded automatically when
you connect to the Internet. You have to do those bits yourself because of the you connect to the Internet. You have to do those bits yourself because of the
differences between the various GNU/Linux distributions. differences between the various operating systems and distributions.
Many systems, including the most popular GNU/Linux distributions, use the Many systems, including the most popular GNU/Linux distributions, use the
System-V mechanism for starting daemons at boot time. The directory System-V mechanism for starting daemons at boot time. The directory
@ -106,6 +106,10 @@ links point back into the start/stop script in the parent directory, using a
numeric part of the link name determines the order in which the links are numeric part of the link name determines the order in which the links are
called. called.
If you cannot use a GUI front-end as provided by GNOME and KDE, or a
command-line utility like "insserv", "chkconfig" or "/usr/lib/lsb/install_initd",
then you can follow the steps below to set up the necessary symbolic links.
Before you start you will need to know where your "init.d" directory can be Before you start you will need to know where your "init.d" directory can be
found and what your default run level is: found and what your default run level is:
@ -137,8 +141,6 @@ daemons compete for the standard SMTP listening port):
$ cd /etc/init.d/rc5.d $ cd /etc/init.d/rc5.d
$ rm *sendmail $ rm *sendmail
(There are also KDE and GNOME GUIs which you can use to do the latter steps.)
Triggering onward delivery Triggering onward delivery
-------------------------- --------------------------
This section assumes that you are using "pppd" to establish your dial-up This section assumes that you are using "pppd" to establish your dial-up
@ -160,7 +162,7 @@ If you find "sendmail -q" then it should be sufficient to replace it with this:
where you substitute your ISP's SMTP server address for <myisp>. where you substitute your ISP's SMTP server address for <myisp>.
Or if your "ip-up" calls out to "ip-up.local" then create a two-line Or if your "ip-up" calls out to "ip-up.local" then create a two-line
"ip-up.local" script: "ip-up.local" script like this:
$ cd /etc/ppp $ cd /etc/ppp
$ cat << EOF > ip-up.local $ cat << EOF > ip-up.local

View File

@ -18,6 +18,7 @@ In summary, the Windows installation process is as follows:
* Create a spool directory under "<windir>\spool", eg. "c:\win98\spool\emailrelay". * Create a spool directory under "<windir>\spool", eg. "c:\win98\spool\emailrelay".
* Configure your e-mail client (eg. Outlook) to use SMTP on the local machine for outgoing e-mail. * Configure your e-mail client (eg. Outlook) to use SMTP on the local machine for outgoing e-mail.
* Run the forwarding client from the taskbar/desktop shortcut once connected to the Internet. * Run the forwarding client from the taskbar/desktop shortcut once connected to the Internet.
* Optionally register the server as a COM component using the "-regserver" command-line switch.
These steps are explained in more detail below. These steps are explained in more detail below.
@ -68,29 +69,37 @@ Once the server is configured the next step is to create an icon on the desktop
you are connected to the Internet. you are connected to the Internet.
You can do this by simply dragging the E-MailRelay executable file from the You can do this by simply dragging the E-MailRelay executable file from the
"Program Files\emailrelay" folder onto the desktop. Then right click on the "Program Files\emailrelay" folder onto the desktop. Then right click on the new
new icon and select "Properties" from the pop-up menu. icon and select "Properties" from the pop-up menu.
Again the "Target" box should contain the path of the E-MailRelay executable, Again the "Target" box should contain the path of the E-MailRelay executable,
and you should add configuration options at the end, separated by a space. and you should add configuration options at the end, separated by a space. As a
As a minumum you will need to add "--as-client myisp:smtp", where "myisp" minumum you will need to add "--as-client myisp:smtp", where "myisp" is replaced
is replaced with the hostname of your ISP's SMTP server. with the hostname of your ISP's SMTP server.
Preparation Preparation
----------- -----------
To complete the installation you should create a spool directory to hold To complete the installation you should create a spool directory to hold your
your e-mail messages while you are off-line. By default E-MailRelay will e-mail messages while you are off-line. By default E-MailRelay will look for a
look for a directory "<windir>\spool\emailrelay", where "<windir>" is the directory "<windir>\spool\emailrelay", where "<windir>" is the path of your main
path of your main windows directory, typically "c:\win98" for Windows 98. windows directory, typically "c:\win98" for Windows 98.
Finally you will need to configure your e-mail client program to use Finally you will need to configure your e-mail client program to use the local
the local E-MailRelay server for outgoing mail. Where it asks for the E-MailRelay server for outgoing mail. Where it asks for the name of the SMTP
name of the SMTP server for outgoing mail you should tell it to use server for outgoing mail you should tell it to use "localhost" or "127.0.0.1".
"localhost" or "127.0.0.1".
COM registration
----------------
The server can be optionally registered as a COM component by running the
executable with the "-regserver" command line switch. The COM interface may
allow stored messages to be forwarded to any remote server, so consider the
security implications before doing the COM registration. Refer to the reference
guide for more details.
Uninstall Uninstall
--------- ---------
There are no DLLs or registry entries to clean up: just delete the files under If you have ever registered the executable as a COM component, then deregister it
using the "-unregserver" command-line switch. Then just delete the files under
"Program Files\emailrelay" and "<windir>\spool\emailrelay", and remove any "Program Files\emailrelay" and "<windir>\spool\emailrelay", and remove any
taskbar, desktop or "Start->Programs->StartUp" shortcuts. taskbar, desktop or "Start->Programs->StartUp" shortcuts.

View File

@ -1,12 +1,14 @@
Summary: Simple e-mail message transfer agent using SMTP Summary: Simple e-mail message transfer agent using SMTP
Name: emailrelay Name: emailrelay
Version: 0.9.9 Version: 1.0.0
Release: 1 Release: 1
Copyright: GPL Copyright: GPL
Group: System Environment/Daemons Group: System Environment/Daemons
Source: http://emailrelay.sourceforge.net/.../emailrelay-src-0.9.9.tar.gz Source: http://emailrelay.sourceforge.net/.../emailrelay-src-1.0.0.tar.gz
BuildRoot: /tmp/emailrelay-install BuildRoot: /tmp/emailrelay-install
%define prefix /usr
%description %description
E-MailRelay is a simple SMTP store-and-forward message transfer agent (MTA). E-MailRelay is a simple SMTP store-and-forward message transfer agent (MTA).
It runs as an SMTP server, storing e-mail in a local spool directory, and It runs as an SMTP server, storing e-mail in a local spool directory, and
@ -17,8 +19,8 @@ than to a local postmaster. Because of this functional simplicity it is
extremely easy to configure, typically only requiring the address of the extremely easy to configure, typically only requiring the address of the
next-hop SMTP server to be put on the command line. next-hop SMTP server to be put on the command line.
C++ source code is available for Linux, FreeBSD and Windows. Distribution is C++ source code is available for Linux, FreeBSD (etc) and Windows.
under the GNU General Public License. Distribution is under the GNU General Public License.
%prep %prep
%setup %setup
@ -30,43 +32,49 @@ make HAVE_DOXYGEN=no HAVE_MAN2HTML=no
%install %install
make install destdir=$RPM_BUILD_ROOT DESTDIR=$RPM_BUILD_ROOT HAVE_DOXYGEN=no HAVE_MAN2HTML=no make install destdir=$RPM_BUILD_ROOT DESTDIR=$RPM_BUILD_ROOT HAVE_DOXYGEN=no HAVE_MAN2HTML=no
%post
test -f /usr/lib/lsb/install_initd && cd /etc/init.d && /usr/lib/lsb/install_initd emailrelay
%preun
test $1 -eq 0 && test -f /usr/lib/lsb/remove_initd && cd /etc/init.d && /usr/lib/lsb/remove_initd emailrelay
%clean %clean
rm -rf $RPM_BUILD_ROOT rm -rf $RPM_BUILD_ROOT
%files %files
/usr/lib/emailrelay/emailrelay-poke
/usr/sbin/emailrelay
/usr/sbin/emailrelay-passwd
/usr/sbin/emailrelay-submit
/usr/share/doc/emailrelay/examples/emailrelay-process.sh
/usr/share/doc/emailrelay/examples/emailrelay-notify.sh
/usr/share/doc/emailrelay/examples/emailrelay-deliver.sh
/usr/share/doc/emailrelay/examples/emailrelay-resubmit.sh
/usr/share/doc/emailrelay/developer.txt
/usr/share/doc/emailrelay/reference.txt
/usr/share/doc/emailrelay/userguide.txt
/usr/share/doc/emailrelay/windows.txt
/usr/share/doc/emailrelay/readme.html
/usr/share/doc/emailrelay/developer.html
/usr/share/doc/emailrelay/reference.html
/usr/share/doc/emailrelay/userguide.html
/usr/share/doc/emailrelay/windows.html
/usr/share/doc/emailrelay/index.html
/usr/share/doc/emailrelay/changelog.html
/usr/share/doc/emailrelay/emailrelay.css
/usr/share/doc/emailrelay/NEWS
/usr/share/doc/emailrelay/README
/usr/share/doc/emailrelay/changelog.gz
/usr/share/doc/emailrelay/doxygen
/usr/share/man/man1/emailrelay.1.gz
/usr/share/man/man1/emailrelay-passwd.1.gz
/usr/share/man/man1/emailrelay-poke.1.gz
/usr/share/man/man1/emailrelay-submit.1.gz
/etc/init.d/emailrelay /etc/init.d/emailrelay
%{prefix}/lib/emailrelay/emailrelay-poke
%{prefix}/sbin/emailrelay
%{prefix}/sbin/emailrelay-passwd
%{prefix}/sbin/emailrelay-submit
%{prefix}/share/doc/emailrelay/NEWS
%{prefix}/share/doc/emailrelay/README
%{prefix}/share/doc/emailrelay/changelog.gz
%{prefix}/share/doc/emailrelay/changelog.html
%{prefix}/share/doc/emailrelay/developer.html
%{prefix}/share/doc/emailrelay/developer.txt
%{prefix}/share/doc/emailrelay/emailrelay.css
%{prefix}/share/doc/emailrelay/examples/emailrelay-deliver.sh
%{prefix}/share/doc/emailrelay/examples/emailrelay-notify.sh
%{prefix}/share/doc/emailrelay/examples/emailrelay-process.sh
%{prefix}/share/doc/emailrelay/examples/emailrelay-resubmit.sh
%{prefix}/share/doc/emailrelay/index.html
%{prefix}/share/doc/emailrelay/readme.html
%{prefix}/share/doc/emailrelay/reference.html
%{prefix}/share/doc/emailrelay/reference.txt
%{prefix}/share/doc/emailrelay/userguide.html
%{prefix}/share/doc/emailrelay/userguide.txt
%{prefix}/share/doc/emailrelay/windows.html
%{prefix}/share/doc/emailrelay/windows.txt
%{prefix}/share/man/man1/emailrelay-passwd.1.gz
%{prefix}/share/man/man1/emailrelay-poke.1.gz
%{prefix}/share/man/man1/emailrelay-submit.1.gz
%{prefix}/share/man/man1/emailrelay.1.gz
/var/spool/emailrelay/
%changelog %changelog
* Mon Sep 24 2001 Graeme Walker <graeme_walker@users.sourceforge.net> * Wed Jul 3 2002 Graeme Walker <graeme_walker@users.sourceforge.net>
- Initial version. - Initial version.

View File

@ -79,6 +79,7 @@ POST_UNINSTALL = :
AR = @AR@ AR = @AR@
AWK = @AWK@ AWK = @AWK@
CC = @CC@ CC = @CC@
COMPILER_VERSION = @COMPILER_VERSION@
CXX = @CXX@ CXX = @CXX@
GZIP = @GZIP@ GZIP = @GZIP@
HAVE_DOXYGEN = @HAVE_DOXYGEN@ HAVE_DOXYGEN = @HAVE_DOXYGEN@

View File

@ -79,6 +79,7 @@ POST_UNINSTALL = :
AR = @AR@ AR = @AR@
AWK = @AWK@ AWK = @AWK@
CC = @CC@ CC = @CC@
COMPILER_VERSION = @COMPILER_VERSION@
CXX = @CXX@ CXX = @CXX@
GZIP = @GZIP@ GZIP = @GZIP@
HAVE_DOXYGEN = @HAVE_DOXYGEN@ HAVE_DOXYGEN = @HAVE_DOXYGEN@

View File

@ -20,7 +20,7 @@
// //
// sstream // sstream
// //
// Forwards compatibility from ostrstream to std::stringstream. // Forwards compatibility from ostrstream to std::ostringstream.
// //
#ifndef G_STD_SSTREAM_H #ifndef G_STD_SSTREAM_H
@ -31,30 +31,31 @@
namespace std namespace std
{ {
class stringstream : public ostrstream class ostringstream : public ostrstream
{ {
public: public:
stringstream() ; ostringstream() ;
stringstream( char * , size_t ) ; ostringstream( char * , size_t ) ;
std::string str() const ; std::string str() const ;
} ; } ;
typedef ostringstream stringstream ;
} ; } ;
inline inline
std::stringstream::stringstream() std::ostringstream::ostringstream()
{ {
} }
inline inline
std::stringstream::stringstream( char * p , size_t n ) : std::ostringstream::ostringstream( char * p , size_t n ) :
ostrstream(p,static_cast<int>(n)) ostrstream(p,static_cast<int>(n))
{ {
} }
inline inline
std::string std::stringstream::str() const std::string std::ostringstream::str() const
{ {
std::stringstream * This = const_cast<std::stringstream*>(this) ; std::ostringstream * This = const_cast<std::ostringstream*>(this) ;
ostrstream * base = This ; ostrstream * base = This ;
(*base) << '\0' ; (*base) << '\0' ;
char * p = base->str() ; char * p = base->str() ;

View File

@ -79,6 +79,7 @@ POST_UNINSTALL = :
AR = @AR@ AR = @AR@
AWK = @AWK@ AWK = @AWK@
CC = @CC@ CC = @CC@
COMPILER_VERSION = @COMPILER_VERSION@
CXX = @CXX@ CXX = @CXX@
GZIP = @GZIP@ GZIP = @GZIP@
HAVE_DOXYGEN = @HAVE_DOXYGEN@ HAVE_DOXYGEN = @HAVE_DOXYGEN@

View File

@ -30,6 +30,8 @@ namespace std
using ::rand ; using ::rand ;
using ::srand ; using ::srand ;
using ::getenv ; using ::getenv ;
using ::free ;
using ::malloc ;
} ; } ;
#endif #endif

View File

@ -16,4 +16,4 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# #
SUBDIRS = glib gnet main win32 SUBDIRS = glib gnet gsmtp main win32

View File

@ -79,6 +79,7 @@ POST_UNINSTALL = :
AR = @AR@ AR = @AR@
AWK = @AWK@ AWK = @AWK@
CC = @CC@ CC = @CC@
COMPILER_VERSION = @COMPILER_VERSION@
CXX = @CXX@ CXX = @CXX@
GZIP = @GZIP@ GZIP = @GZIP@
HAVE_DOXYGEN = @HAVE_DOXYGEN@ HAVE_DOXYGEN = @HAVE_DOXYGEN@
@ -96,7 +97,7 @@ e_man1dir = @e_man1dir@
e_sbindir = @e_sbindir@ e_sbindir = @e_sbindir@
e_spooldir = @e_spooldir@ e_spooldir = @e_spooldir@
SUBDIRS = glib gnet main win32 SUBDIRS = glib gnet gsmtp main win32
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES = CONFIG_CLEAN_FILES =

View File

@ -16,7 +16,9 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# #
EXTRA_DIST=garg_win32.cpp \ EXTRA_DIST=\
garg_win32.cpp \
gcleanup_win32.cpp \
gdaemon_win32.cpp \ gdaemon_win32.cpp \
gdatetime_win32.cpp \ gdatetime_win32.cpp \
gdirectory_win32.cpp \ gdirectory_win32.cpp \
@ -24,9 +26,11 @@ EXTRA_DIST=garg_win32.cpp \
glogoutput_win32.cpp \ glogoutput_win32.cpp \
gprocess_win32.cpp \ gprocess_win32.cpp \
gfile_win32.cpp \ gfile_win32.cpp \
gregistry_win32.cpp \
gregistry.h \
md5c.c \ md5c.c \
md5.h md5.h
INCLUDES = -I$(top_srcdir)/lib/gcc2.95 INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION)
noinst_LIBRARIES = libglib.a noinst_LIBRARIES = libglib.a
libglib_a_SOURCES = \ libglib_a_SOURCES = \
garg.cpp \ garg.cpp \
@ -34,9 +38,9 @@ libglib_a_SOURCES = \
garg_unix.cpp \ garg_unix.cpp \
gassert.h \ gassert.h \
gconvert.h \ gconvert.h \
gcredentials.h \ gcleanup.h \
gcleanup_unix.cpp \
gdaemon.h \ gdaemon.h \
gdaemon.cpp \
gdaemon_unix.cpp \ gdaemon_unix.cpp \
gdate.cpp \ gdate.cpp \
gdate.h \ gdate.h \
@ -68,10 +72,13 @@ libglib_a_SOURCES = \
gnoncopyable.h \ gnoncopyable.h \
gpath.cpp \ gpath.cpp \
gpath.h \ gpath.h \
gpidfile.cpp \
gpidfile.h \
gprocess.h \ gprocess.h \
gprocess_unix.cpp \ gprocess_unix.cpp \
groot.cpp \ groot.cpp \
groot.h \ groot.h \
gsetter.h \
gstatemachine.h \ gstatemachine.h \
gstr.cpp \ gstr.cpp \
gstr.h \ gstr.h \

View File

@ -79,6 +79,7 @@ POST_UNINSTALL = :
AR = @AR@ AR = @AR@
AWK = @AWK@ AWK = @AWK@
CC = @CC@ CC = @CC@
COMPILER_VERSION = @COMPILER_VERSION@
CXX = @CXX@ CXX = @CXX@
GZIP = @GZIP@ GZIP = @GZIP@
HAVE_DOXYGEN = @HAVE_DOXYGEN@ HAVE_DOXYGEN = @HAVE_DOXYGEN@
@ -96,11 +97,11 @@ e_man1dir = @e_man1dir@
e_sbindir = @e_sbindir@ e_sbindir = @e_sbindir@
e_spooldir = @e_spooldir@ e_spooldir = @e_spooldir@
EXTRA_DIST = garg_win32.cpp gdaemon_win32.cpp gdatetime_win32.cpp gdirectory_win32.cpp gfs_win32.cpp glogoutput_win32.cpp gprocess_win32.cpp gfile_win32.cpp md5c.c md5.h EXTRA_DIST = garg_win32.cpp gcleanup_win32.cpp gdaemon_win32.cpp gdatetime_win32.cpp gdirectory_win32.cpp gfs_win32.cpp glogoutput_win32.cpp gprocess_win32.cpp gfile_win32.cpp gregistry_win32.cpp gregistry.h md5c.c md5.h
INCLUDES = -I$(top_srcdir)/lib/gcc2.95 INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION)
noinst_LIBRARIES = libglib.a noinst_LIBRARIES = libglib.a
libglib_a_SOURCES = garg.cpp garg.h garg_unix.cpp gassert.h gconvert.h gcredentials.h gdaemon.h gdaemon.cpp gdaemon_unix.cpp gdate.cpp gdate.h gdatetime.cpp gdatetime.h gdatetime_unix.cpp gdebug.h gdef.h gdirectory.cpp gdirectory.h gdirectory_unix.cpp gexception.cpp gexception.h gfile.cpp gfile.h gfile_unix.cpp gfs.h gfs_unix.cpp ggetopt.cpp ggetopt.h glog.cpp glog.h glogoutput.cpp glogoutput.h glogoutput_unix.cpp gmd5.cpp gmd5.h gmemory.h gnoncopyable.h gpath.cpp gpath.h gprocess.h gprocess_unix.cpp groot.cpp groot.h gstatemachine.h gstr.cpp gstr.h gstrings.h gtime.cpp gtime.h libglib_a_SOURCES = garg.cpp garg.h garg_unix.cpp gassert.h gconvert.h gcleanup.h gcleanup_unix.cpp gdaemon.h gdaemon_unix.cpp gdate.cpp gdate.h gdatetime.cpp gdatetime.h gdatetime_unix.cpp gdebug.h gdef.h gdirectory.cpp gdirectory.h gdirectory_unix.cpp gexception.cpp gexception.h gfile.cpp gfile.h gfile_unix.cpp gfs.h gfs_unix.cpp ggetopt.cpp ggetopt.h glog.cpp glog.h glogoutput.cpp glogoutput.h glogoutput_unix.cpp gmd5.cpp gmd5.h gmemory.h gnoncopyable.h gpath.cpp gpath.h gpidfile.cpp gpidfile.h gprocess.h gprocess_unix.cpp groot.cpp groot.h gsetter.h gstatemachine.h gstr.cpp gstr.h gstrings.h gtime.cpp gtime.h
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../../config.h CONFIG_HEADER = ../../config.h
@ -113,11 +114,11 @@ CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@ LDFLAGS = @LDFLAGS@
LIBS = @LIBS@ LIBS = @LIBS@
libglib_a_LIBADD = libglib_a_LIBADD =
libglib_a_OBJECTS = garg.o garg_unix.o gdaemon.o gdaemon_unix.o gdate.o \ libglib_a_OBJECTS = garg.o garg_unix.o gcleanup_unix.o gdaemon_unix.o \
gdatetime.o gdatetime_unix.o gdirectory.o gdirectory_unix.o \ gdate.o gdatetime.o gdatetime_unix.o gdirectory.o gdirectory_unix.o \
gexception.o gfile.o gfile_unix.o gfs_unix.o ggetopt.o glog.o \ gexception.o gfile.o gfile_unix.o gfs_unix.o ggetopt.o glog.o \
glogoutput.o glogoutput_unix.o gmd5.o gpath.o gprocess_unix.o groot.o \ glogoutput.o glogoutput_unix.o gmd5.o gpath.o gpidfile.o \
gstr.o gtime.o gprocess_unix.o groot.o gstr.o gtime.o
CXXFLAGS = @CXXFLAGS@ CXXFLAGS = @CXXFLAGS@
CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX) CXXLD = $(CXX)
@ -227,97 +228,93 @@ distdir: $(DISTFILES)
fi; \ fi; \
done done
garg.o: garg.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \ garg.o: garg.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \
../../lib/gcc2.95/sstream ../../lib/gcc2.95/xlocale \ ../../lib/gcc2.95/sstream ../../lib/gcc2.95/limits garg.h \
../../lib/gcc2.95/limits garg.h gpath.h gstrings.h gstr.h \ gpath.h gstrings.h gstr.h gexception.h gdebug.h glogoutput.h \
gexception.h gdebug.h glogoutput.h glog.h gassert.h glog.h gassert.h
garg_unix.o: garg_unix.cpp gdef.h ../../config.h \ garg_unix.o: garg_unix.cpp gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits garg.h \ ../../lib/gcc2.95/limits garg.h gdebug.h glogoutput.h glog.h \
gdebug.h glogoutput.h glog.h gassert.h gassert.h
gdaemon.o: gdaemon.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \ gcleanup_unix.o: gcleanup_unix.cpp gdef.h ../../config.h \
../../lib/gcc2.95/sstream ../../lib/gcc2.95/xlocale \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/limits gdaemon.h gexception.h gpath.h \ ../../lib/gcc2.95/limits gcleanup.h gpath.h gstrings.h \
gstrings.h groot.h gprocess.h gnoncopyable.h gexception.h gprocess.h groot.h gnoncopyable.h glog.h
gdaemon_unix.o: gdaemon_unix.cpp gdef.h ../../config.h \ gdaemon_unix.o: gdaemon_unix.cpp gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gdaemon.h \ ../../lib/gcc2.95/limits gdaemon.h gexception.h gpidfile.h \
gexception.h gpath.h gstrings.h gprocess.h gpath.h gstrings.h gprocess.h
gdate.o: gdate.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \ gdate.o: gdate.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \
../../lib/gcc2.95/sstream ../../lib/gcc2.95/xlocale \ ../../lib/gcc2.95/sstream ../../lib/gcc2.95/limits gdate.h \
../../lib/gcc2.95/limits gdate.h gdatetime.h gexception.h \ gdatetime.h gexception.h gdebug.h glogoutput.h glog.h gassert.h
gdebug.h glogoutput.h glog.h gassert.h
gdatetime.o: gdatetime.cpp gdef.h ../../config.h \ gdatetime.o: gdatetime.cpp gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gdatetime.h \ ../../lib/gcc2.95/limits gdatetime.h gexception.h gstr.h \
gexception.h gstr.h gstrings.h gassert.h glogoutput.h glog.h gstrings.h gassert.h glogoutput.h glog.h
gdatetime_unix.o: gdatetime_unix.cpp gdef.h ../../config.h \ gdatetime_unix.o: gdatetime_unix.cpp gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gdatetime.h \ ../../lib/gcc2.95/limits gdatetime.h gexception.h
gexception.h
gdirectory.o: gdirectory.cpp gdef.h ../../config.h \ gdirectory.o: gdirectory.cpp gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gdirectory.h \ ../../lib/gcc2.95/limits gdirectory.h gpath.h gstrings.h \
gpath.h gstrings.h gexception.h gfs.h glog.h gexception.h gfs.h glog.h
gdirectory_unix.o: gdirectory_unix.cpp gdef.h ../../config.h \ gdirectory_unix.o: gdirectory_unix.cpp gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gdirectory.h \ ../../lib/gcc2.95/limits gdirectory.h gpath.h gstrings.h \
gpath.h gstrings.h gexception.h gfs.h gfile.h gdebug.h \ gexception.h gfs.h gfile.h gdebug.h glogoutput.h glog.h \
glogoutput.h glog.h gassert.h gassert.h
gexception.o: gexception.cpp gdef.h ../../config.h \ gexception.o: gexception.cpp gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gexception.h ../../lib/gcc2.95/limits gexception.h
gfile.o: gfile.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \ gfile.o: gfile.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \
../../lib/gcc2.95/sstream ../../lib/gcc2.95/xlocale \ ../../lib/gcc2.95/sstream ../../lib/gcc2.95/limits gfile.h \
../../lib/gcc2.95/limits gfile.h gpath.h gstrings.h \ gpath.h gstrings.h gexception.h gprocess.h glog.h
gexception.h gprocess.h glog.h
gfile_unix.o: gfile_unix.cpp gdef.h ../../config.h \ gfile_unix.o: gfile_unix.cpp gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gfile.h \ ../../lib/gcc2.95/limits gfile.h gpath.h gstrings.h \
gpath.h gstrings.h gexception.h gprocess.h gexception.h gprocess.h
gfs_unix.o: gfs_unix.cpp gdef.h ../../config.h \ gfs_unix.o: gfs_unix.cpp gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gfs.h ../../lib/gcc2.95/limits gfs.h
ggetopt.o: ggetopt.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \ ggetopt.o: ggetopt.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \
../../lib/gcc2.95/sstream ../../lib/gcc2.95/xlocale \ ../../lib/gcc2.95/sstream ../../lib/gcc2.95/limits glog.h \
../../lib/gcc2.95/limits glog.h gstrings.h gstr.h gexception.h \ gstrings.h gstr.h gexception.h ggetopt.h garg.h gassert.h \
ggetopt.h garg.h gassert.h glogoutput.h gdebug.h glogoutput.h gdebug.h
glog.o: glog.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \ glog.o: glog.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \
../../lib/gcc2.95/sstream ../../lib/gcc2.95/xlocale \ ../../lib/gcc2.95/sstream ../../lib/gcc2.95/limits glog.h \
../../lib/gcc2.95/limits glog.h glogoutput.h glogoutput.h
glogoutput.o: glogoutput.cpp gdef.h ../../config.h \ glogoutput.o: glogoutput.cpp gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits glogoutput.h \ ../../lib/gcc2.95/limits glogoutput.h glog.h
glog.h
glogoutput_unix.o: glogoutput_unix.cpp gdef.h ../../config.h \ glogoutput_unix.o: glogoutput_unix.cpp gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits glogoutput.h \ ../../lib/gcc2.95/limits glogoutput.h glog.h
glog.h
gmd5.o: gmd5.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \ gmd5.o: gmd5.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \
../../lib/gcc2.95/sstream ../../lib/gcc2.95/xlocale \ ../../lib/gcc2.95/sstream ../../lib/gcc2.95/limits gmd5.h \
../../lib/gcc2.95/limits gmd5.h gexception.h gstr.h gstrings.h \ gexception.h gstr.h gstrings.h gassert.h glogoutput.h glog.h \
gassert.h glogoutput.h glog.h md5.h md5c.c md5.h md5c.c
gpath.o: gpath.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \ gpath.o: gpath.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \
../../lib/gcc2.95/sstream ../../lib/gcc2.95/xlocale \ ../../lib/gcc2.95/sstream ../../lib/gcc2.95/limits gpath.h \
../../lib/gcc2.95/limits gpath.h gstrings.h gfs.h gstr.h \ gstrings.h gfs.h gstr.h gexception.h gdebug.h glogoutput.h \
gexception.h gdebug.h glogoutput.h glog.h gassert.h glog.h gassert.h
gpidfile.o: gpidfile.cpp gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/limits gpidfile.h gexception.h gpath.h \
gstrings.h gprocess.h gcleanup.h gfile.h gdebug.h glogoutput.h \
glog.h gassert.h
gprocess_unix.o: gprocess_unix.cpp gdef.h ../../config.h \ gprocess_unix.o: gprocess_unix.cpp gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gprocess.h \ ../../lib/gcc2.95/limits gprocess.h gexception.h gpath.h \
gexception.h gpath.h gstrings.h gassert.h glogoutput.h glog.h \ gstrings.h gassert.h glogoutput.h glog.h gfs.h
gfs.h
groot.o: groot.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \ groot.o: groot.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \
../../lib/gcc2.95/sstream ../../lib/gcc2.95/xlocale \ ../../lib/gcc2.95/sstream ../../lib/gcc2.95/limits groot.h \
../../lib/gcc2.95/limits groot.h gprocess.h gexception.h \ gprocess.h gexception.h gpath.h gstrings.h gnoncopyable.h \
gpath.h gstrings.h gnoncopyable.h gdebug.h glogoutput.h glog.h \
gassert.h
gstr.o: gstr.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \
../../lib/gcc2.95/sstream ../../lib/gcc2.95/xlocale \
../../lib/gcc2.95/limits gstr.h gexception.h gstrings.h \
gdebug.h glogoutput.h glog.h gassert.h gdebug.h glogoutput.h glog.h gassert.h
gstr.o: gstr.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \
../../lib/gcc2.95/sstream ../../lib/gcc2.95/limits gstr.h \
gexception.h gstrings.h gdebug.h glogoutput.h glog.h gassert.h
gtime.o: gtime.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \ gtime.o: gtime.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \
../../lib/gcc2.95/sstream ../../lib/gcc2.95/xlocale \ ../../lib/gcc2.95/sstream ../../lib/gcc2.95/limits gtime.h \
../../lib/gcc2.95/limits gtime.h gexception.h gdatetime.h \ gexception.h gdatetime.h gassert.h glogoutput.h glog.h
gassert.h glogoutput.h glog.h
info-am: info-am:
info: info-am info: info-am

View File

@ -77,16 +77,24 @@ void G::Arg::parse( HINSTANCE hinstance , const std::string & command_line )
setPrefix() ; setPrefix() ;
} }
bool G::Arg::contains( const std::string & sw , size_t sw_args ) const void G::Arg::reparse( const std::string & command_line )
{ {
return find( sw , sw_args , NULL ) ; while( m_array.size() > 1U )
m_array.pop_back() ;
G::Str::splitIntoTokens( command_line , m_array , " \t" ) ;
} }
bool G::Arg::find( const std::string & sw , size_t sw_args , size_t * index_p ) const bool G::Arg::contains( const std::string & sw , size_t sw_args , bool cs ) const
{
return find( cs , sw , sw_args , NULL ) ;
}
bool G::Arg::find( bool cs , const std::string & sw , size_t sw_args ,
size_t * index_p ) const
{ {
for( size_t i = 1 ; i < m_array.size() ; i++ ) // start from v[1] for( size_t i = 1 ; i < m_array.size() ; i++ ) // start from v[1]
{ {
if( sw == m_array[i] && (i+sw_args) < m_array.size() ) if( match(cs,sw,m_array[i]) && (i+sw_args) < m_array.size() )
{ {
if( index_p != NULL ) if( index_p != NULL )
*index_p = i ; *index_p = i ;
@ -96,10 +104,19 @@ bool G::Arg::find( const std::string & sw , size_t sw_args , size_t * index_p )
return false ; return false ;
} }
//static
bool G::Arg::match( bool cs , const std::string & s1 , const std::string & s2 )
{
return
cs ?
s1 == s2 :
Str::upper(s1) == Str::upper(s2) ;
}
void G::Arg::remove( const std::string & sw , size_t sw_args ) void G::Arg::remove( const std::string & sw , size_t sw_args )
{ {
size_t i = 0U ; size_t i = 0U ;
const bool found = find( sw , sw_args , &i ) ; const bool found = find( true , sw , sw_args , &i ) ;
if( found ) if( found )
removeAt( i , sw_args ) ; removeAt( i , sw_args ) ;
} }
@ -119,7 +136,7 @@ void G::Arg::removeAt( size_t sw_index , size_t sw_args )
size_t G::Arg::index( const std::string & sw , size_t sw_args ) const size_t G::Arg::index( const std::string & sw , size_t sw_args ) const
{ {
size_t i = 0U ; size_t i = 0U ;
const bool found = find( sw , sw_args , &i ) ; const bool found = find( true , sw , sw_args , &i ) ;
return found ? i : 0U ; return found ? i : 0U ;
} }

View File

@ -31,7 +31,7 @@
namespace G namespace G
{ {
class Arg ; class Arg ;
} ; }
// Class: G::Arg // Class: G::Arg
// Description: A class which holds a represention of the // Description: A class which holds a represention of the
@ -57,8 +57,14 @@ public:
// //
// Parses the given command line, splitting // Parses the given command line, splitting
// it up into an array of tokens. // it up into an array of tokens.
// The program name is automatically // The full exe name is automatically
// added as the first token (cf. argv[0]). // added as the first token (cf. argv[0]).
void reparse( const std::string & command_line ) ;
// Reinitialises the object with the given
// command-line. The command-line should not
// contain the program name: the v(0) value
// and prefix() are unchanged.
~Arg() ; ~Arg() ;
// Destructor. // Destructor.
@ -81,11 +87,12 @@ public:
// be used in main() outside of the outermost try // be used in main() outside of the outermost try
// block. // block.
bool contains( const std::string & sw , size_t sw_args = 0U ) const ; bool contains( const std::string & sw ,
// Returns true if the command line size_t sw_args = 0U , bool case_sensitive = true ) const ;
// contains the given switch with enough // Returns true if the command line
// command line arguments left to satisfy // contains the given switch with enough
// the given number of switch arguments. // command line arguments left to satisfy
// the given number of switch arguments.
size_t index( const std::string & sw , size_t sw_args = 0U ) const ; size_t index( const std::string & sw , size_t sw_args = 0U ) const ;
// Returns the index of the given switch. // Returns the index of the given switch.
@ -109,8 +116,9 @@ public:
private: private:
static std::string moduleName( HINSTANCE h ) ; static std::string moduleName( HINSTANCE h ) ;
bool find( const std::string & sw , size_t sw_args , size_t *index_p ) const ; bool find( bool , const std::string & , size_t , size_t * ) const ;
void setPrefix() ; void setPrefix() ;
static bool match( bool , const std::string & , const std::string & ) ;
private: private:
typedef std::vector<std::string GAllocator(std::string) > Array ; typedef std::vector<std::string GAllocator(std::string) > Array ;

57
src/glib/gcleanup.h Normal file
View File

@ -0,0 +1,57 @@
//
// Copyright (C) 2001-2002 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.
//
// ===
//
// gcleanup.h
//
#ifndef G_CLEANUP_H
#define G_CLEANUP_H
#include "gdef.h"
#include "gpath.h"
#include "gexception.h"
namespace G
{
class Cleanup ;
}
// Class: G::Cleanup
// Description: An interface for registering cleanup functions
// which are called when the process terminates abnormally.
//
class G::Cleanup
{
public:
G_EXCEPTION( Error , "cleanup error" ) ;
static void add( void (*fn)(const char*) , const char * arg ) ;
// Adds the given handler to the list which
// are to be called when the process
// terminates abnormally. The handler
// function must be fully reentrant.
// The 'arg' pointer is kept.
private:
Cleanup() ; // not implemeneted
} ;
#endif

154
src/glib/gcleanup_unix.cpp Normal file
View File

@ -0,0 +1,154 @@
//
// Copyright (C) 2001-2002 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.
//
// ===
//
// gcleanup_unix.cpp
//
#include "gdef.h"
#include "gcleanup.h"
#include "gprocess.h"
#include "groot.h"
#include "glog.h"
#include <signal.h>
namespace G
{
class CleanupImp ;
}
// Class: G::CleanupImp
// Description: A private implementation class used by G::Cleanup.
//
class G::CleanupImp
{
public:
static void add( void (*fn)(const char*) , const char * ) ;
private:
static void init() ;
static void install( int , void (*fn)(int) ) ;
static void installHandler( int ) ;
static void installDefault( int ) ;
static void callHandlers() ;
static void handler_( int ) ;
static bool ignored( int ) ;
private:
typedef Cleanup::Error Error ;
struct Link // A private linked-list structure used by G::CleanupImp.
{
void (*fn)(const char*) ;
const char * arg ;
Link * next ;
} ;
static Link * m_head ;
static Link * m_tail ;
} ;
G::CleanupImp::Link * G::CleanupImp::m_head = NULL ;
G::CleanupImp::Link * G::CleanupImp::m_tail = NULL ;
// ===
void G::Cleanup::add( void (*fn)(const char*) , const char * arg )
{
CleanupImp::add( fn , arg ) ;
}
// ===
void G::CleanupImp::init()
{
installHandler( SIGTERM ) ;
installHandler( SIGINT ) ;
installHandler( SIGHUP ) ;
installHandler( SIGPIPE ) ;
installHandler( SIGQUIT ) ;
//installHandler( SIGUSR1 ) ;
//installHandler( SIGUSR2 ) ;
}
void G::CleanupImp::add( void (*fn)(const char*) , const char * arg )
{
Link * p = new Link ;
p->fn = fn ;
p->arg = arg ;
p->next = NULL ;
// (this bit should be protected from signals)
if( m_head == NULL ) init() ;
if( m_tail != NULL ) m_tail->next = p ;
m_tail = p ;
if( m_head == NULL ) m_head = p ;
}
void G::CleanupImp::installHandler( int signum )
{
if( ignored(signum) )
G_DEBUG( "G::CleanupImp::installHandler: signal " << signum << " is ignored" ) ;
else
install( signum , handler_ ) ;
}
void G::CleanupImp::installDefault( int signum )
{
install( signum , NULL ) ;
}
bool G::CleanupImp::ignored( int signum )
{
static struct ::sigaction zero_action ;
struct ::sigaction action( zero_action ) ;
if( ::sigaction( signum , NULL , &action ) )
throw Error( "sigaction" ) ;
return action.sa_handler == SIG_IGN ;
}
void G::CleanupImp::install( int signum , void (*fn)(int) )
{
static struct ::sigaction zero_action ;
struct ::sigaction action( zero_action ) ;
action.sa_handler = fn ? fn : SIG_DFL ;
if( ::sigaction( signum , &action , NULL ) && fn != NULL )
throw Error( "sigaction" ) ;
}
void G::CleanupImp::callHandlers()
{
G::Root claim_root ;
for( const Link * p = m_head ; p != NULL ; p = p->next )
{
(*(p->fn))(p->arg) ;
}
}
void G::CleanupImp::handler_( int signum )
{
try
{
callHandlers() ;
installDefault( signum ) ;
::raise( signum ) ;
}
catch(...)
{
}
}

View File

@ -18,16 +18,14 @@
// //
// === // ===
// //
// gevent_unix.cpp // gcleanup_win32.cpp
// //
#include "gdef.h" #include "gdef.h"
#include "gnet.h" #include "gcleanup.h"
#include "geventloop.h"
#include "gselect.h"
GNet::EventLoop * GNet::EventLoop::create() void G::Cleanup::add( void (*)(const char*) , const char * )
{ {
return new Select ; // not implemented
} }

View File

@ -44,11 +44,11 @@ Tout Convert( const Tin & in )
Tout out = in ; Tout out = in ;
Tin copy = out ; Tin copy = out ;
if( in != copy ) if( in != copy )
throw ConvertOverflow( std::stringstream() << in ) ; throw ConvertOverflow( std::ostringstream() << in ) ;
return out ; return out ;
} }
} ; }
#endif #endif

View File

@ -1,79 +0,0 @@
//
// Copyright (C) 2001-2002 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.
//
// ===
//
// gcredentials.h
//
#ifndef G_CREDENTIALS_H
#define G_CREDENTIALS_H
#include "gdef.h"
namespace G
{
// Class: credentials
// Description: A class template which can be used to provide
// controlled access to public methods in a class. Note that
// all the constructors are private, but the template-parameter
// class is declared as a friend. (Because all the methods
// are private you will not see much in the doxygen output;
// have a look at the header.)
//
// Usage:
/// struct Foo
/// {
/// void methodForBar( const credentials<Bar> & ) ;
/// } ;
///
/// void Bar::fn()
/// {
/// Foo foo ;
/// foo.methodForBar( "" ) ;
/// }
//
template <class T>
class credentials
{
friend T ;
credentials() ;
// Private default constructor.
credentials( const char * ) ;
// Implicit private constructor.
} ;
template <class T>
inline
credentials<T>::credentials()
{
}
template <class T>
inline
credentials<T>::credentials( const char * )
{
}
} ;
#endif

View File

@ -1,75 +0,0 @@
//
// Copyright (C) 2001-2002 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.
//
// ===
//
// gdaemon.cpp
//
#include "gdef.h"
#include "gdaemon.h"
#include "groot.h"
#include "gprocess.h"
//static
void G::Daemon::PidFile::check( const G::Path & pid_file )
{
if( pid_file != G::Path() && !pid_file.isAbsolute() )
throw G::Daemon::BadPidFile(std::string("must be an absolute path: ")+pid_file.str()) ;
}
//static
void G::Daemon::PidFile::test( const G::Path & pid_file )
{
if( pid_file != G::Path() )
{
std::ofstream tester( pid_file.str().c_str() ) ;
if( !tester.good() )
throw G::Daemon::BadPidFile(std::string("cannot create file: ")+pid_file.str()) ;
}
}
//static
void G::Daemon::PidFile::create( const G::Path & pid_file )
{
if( pid_file != G::Path() )
{
std::ofstream file( pid_file.str().c_str() ) ;
file << G::Process::Id() << std::endl ;
if( !file.good() )
throw G::Daemon::BadPidFile(std::string("cannot create file: ")+pid_file.str()) ;
}
}
G::Daemon::PidFile::PidFile() :
m_valid(false)
{
}
G::Daemon::PidFile::PidFile( const G::Path & path ) :
m_path(path) ,
m_valid(true)
{
}
void G::Daemon::PidFile::commit()
{
if( m_valid )
create( m_path ) ;
}

View File

@ -26,6 +26,7 @@
#include "gdef.h" #include "gdef.h"
#include "gexception.h" #include "gexception.h"
#include "gpidfile.h"
#include "gpath.h" #include "gpath.h"
#include <sys/types.h> #include <sys/types.h>
#include <string> #include <string>
@ -33,7 +34,7 @@
namespace G namespace G
{ {
class Daemon ; class Daemon ;
} ; }
// Class: G::Daemon // Class: G::Daemon
// Description: A class for deamonising the calling process. // Description: A class for deamonising the calling process.
@ -46,19 +47,6 @@ class G::Daemon
{ {
public: public:
G_EXCEPTION( CannotFork , "cannot fork" ) ; G_EXCEPTION( CannotFork , "cannot fork" ) ;
G_EXCEPTION( BadPidFile , "invalid pid file" ) ;
class PidFile // Used by G::Daemon::detach().
{
public: explicit PidFile( const Path & pid_file ) ;
public: PidFile() ;
public: void commit() ;
private: Path m_path ;
private: bool m_valid ;
friend class Daemon ;
private: static void check( const Path & ) ;
private: static void test( const Path & ) ;
private: static void create( const Path & ) ;
} ;
static void detach() ; static void detach() ;
// Detaches from the parent environment. // Detaches from the parent environment.
@ -66,24 +54,19 @@ public:
// _exit()ing the parent, and calling // _exit()ing the parent, and calling
// setsid() in the child. // setsid() in the child.
static void detach( const Path & pid_file ) ;
// An overload which writes the new process-id
// to a file. The path must be absolute.
// Throws BadPidFile on error.
static void detach( PidFile & pid_file ) ; static void detach( PidFile & pid_file ) ;
// An overload which allows for a delayed write // An overload which allows for a delayed write
// of the new process-id to a file. The path // of the new process-id to a file.
// must be absolute.
// //
// A delayed write is useful for network daemons // A delayed write is useful for network daemons
// which open a listening port. You do not want // which open a listening port. A second instance
// a second instance, which will fail on startup, // of the process will fail on startup, and should
// to overwrite the pid file of the running // not overwrite the pid file of the running
// server. In this situation call PidFile::commit() // server. In this situation PidFile::commit()
// just before entering the event loop. // should be called just before entering the event
// loop.
// //
// Throws BadPidFile on error. // Throws PidFile::Error on error.
private: private:
Daemon() ; Daemon() ;

View File

@ -25,21 +25,10 @@
#include "gdaemon.h" #include "gdaemon.h"
#include "gprocess.h" #include "gprocess.h"
//static
void G::Daemon::detach( const Path & pid_file )
{
PidFile::check( pid_file ) ;
PidFile::test( pid_file ) ;
detach() ;
PidFile::create( pid_file ) ;
}
//static //static
void G::Daemon::detach( PidFile & pid_file ) void G::Daemon::detach( PidFile & pid_file )
{ {
PidFile::check( pid_file.m_path ) ; pid_file.check() ; // absolute path
detach() ; detach() ;
} }

View File

@ -25,12 +25,6 @@
#include "gdaemon.h" #include "gdaemon.h"
#include "gprocess.h" #include "gprocess.h"
//static
void G::Daemon::detach( const Path & )
{
detach() ;
}
//static //static
void G::Daemon::detach( PidFile & ) void G::Daemon::detach( PidFile & )
{ {

View File

@ -86,7 +86,7 @@ void G::Date::init( const G::DateTime::BrokenDownTime & tm )
std::string G::Date::string( Format format ) const std::string G::Date::string( Format format ) const
{ {
std::stringstream ss ; std::ostringstream ss ;
if( format == yyyy_mm_dd_slash ) if( format == yyyy_mm_dd_slash )
ss << m_year << "/" << m_month << "/" << m_day ; ss << m_year << "/" << m_month << "/" << m_day ;
else else
@ -104,7 +104,7 @@ int G::Date::monthday() const
std::string G::Date::monthdayString() const std::string G::Date::monthdayString() const
{ {
std::stringstream ss ; std::ostringstream ss ;
ss << m_day ; ss << m_day ;
return ss.str() ; return ss.str() ;
} }
@ -173,7 +173,7 @@ int G::Date::year() const
std::string G::Date::yearString() const std::string G::Date::yearString() const
{ {
std::stringstream ss ; std::ostringstream ss ;
ss << m_year ; ss << m_year ;
return ss.str() ; return ss.str() ;
} }

View File

@ -34,7 +34,7 @@
namespace G namespace G
{ {
class Date ; class Date ;
} ; }
// Class: G::Date // Class: G::Date
// Description: A date (dd/mm/yyyy) class. // Description: A date (dd/mm/yyyy) class.

View File

@ -81,7 +81,7 @@ std::string G::DateTime::offsetString( Offset offset )
unsigned int hh = offset.second / 3600U ; unsigned int hh = offset.second / 3600U ;
unsigned int mm = (offset.second / 60U) % 60 ; unsigned int mm = (offset.second / 60U) % 60 ;
std::stringstream ss ; std::ostringstream ss ;
char sign = (offset.first || (hh==0&&mm==0)) ? '+' : '-' ; char sign = (offset.first || (hh==0&&mm==0)) ? '+' : '-' ;
ss << sign << (hh/10U) << (hh%10U) << (mm/10) << (mm%10) ; ss << sign << (hh/10U) << (hh%10U) << (mm/10) << (mm%10) ;
return ss.str() ; return ss.str() ;

View File

@ -32,7 +32,7 @@
namespace G namespace G
{ {
class DateTime ; class DateTime ;
} ; }
// Class: G::DateTime // Class: G::DateTime
// Description: A low-level static class used by Date and Time. // Description: A low-level static class used by Date and Time.

View File

@ -26,11 +26,11 @@
std::tm * G::DateTime::gmtime_r( const std::time_t * t , std::tm * p ) std::tm * G::DateTime::gmtime_r( const std::time_t * t , std::tm * p )
{ {
return std::gmtime_r(t,p) ; return ::gmtime_r(t,p) ;
} }
std::tm * G::DateTime::localtime_r( const std::time_t * t , std::tm * p ) std::tm * G::DateTime::localtime_r( const std::time_t * t , std::tm * p )
{ {
return std::localtime_r(t,p) ; return ::localtime_r(t,p) ;
} }

View File

@ -40,26 +40,24 @@
#if ! HAVE_GMTIME_R #if ! HAVE_GMTIME_R
#include <ctime> #include <ctime>
namespace std inline struct tm * gmtime_r( const time_t * tp , struct tm * tm_p )
{ {
inline struct tm * gmtime_r( const time_t * tp , struct tm * tm_p ) * tm_p = * gmtime( tp ) ;
{ return tm_p ;
* tm_p = * gmtime( tp ) ; }
return tm_p ;
}
} ;
#endif #endif
#if ! HAVE_LOCALTIME_R #if ! HAVE_LOCALTIME_R
#include <ctime> #include <ctime>
namespace std inline struct tm * localtime_r( const time_t * tp , struct tm * tm_p )
{ {
inline struct tm * localtime_r( const time_t * tp , struct tm * tm_p ) * tm_p = * localtime( tp ) ;
{ return tm_p ;
* tm_p = * localtime( tp ) ; }
return tm_p ; #endif
}
} ; #if ! HAVE_SOCKLEN_T
typedef int socklen_t ;
#endif #endif
#if ! defined( G_UNIX ) #if ! defined( G_UNIX )
@ -119,7 +117,7 @@
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <xlocale> //#include <xlocale>
#include <limits> #include <limits>
#include <memory> #include <memory>
#include <exception> #include <exception>
@ -141,6 +139,7 @@
typedef int ssize_t ; typedef int ssize_t ;
typedef int uid_t ; typedef int uid_t ;
typedef int gid_t ; typedef int gid_t ;
typedef unsigned int pid_t ;
#endif #endif
// STL portability macros (no longer necessary) // STL portability macros (no longer necessary)
@ -155,7 +154,7 @@
// Modify compiler error handling // Modify compiler error handling
// //
#if G_COMPILER_IS_MICROSOFT #ifdef G_COMPILER_IS_MICROSOFT
#pragma warning( disable : 4100 ) // unused formal parameter #pragma warning( disable : 4100 ) // unused formal parameter
#pragma warning( disable : 4355 ) // 'this' in initialiser list #pragma warning( disable : 4355 ) // 'this' in initialiser list
#pragma warning( disable : 4511 ) // cannot create default copy ctor #pragma warning( disable : 4511 ) // cannot create default copy ctor

View File

@ -35,7 +35,7 @@ namespace G
class DirectoryIteratorImp ; class DirectoryIteratorImp ;
class Directory ; class Directory ;
class DirectoryIterator ; class DirectoryIterator ;
} ; }
// Class: G::Directory // Class: G::Directory
// Description: An encapsulation of a file system directory // Description: An encapsulation of a file system directory

View File

@ -34,7 +34,7 @@
namespace G namespace G
{ {
class DirectoryIteratorImp ; class DirectoryIteratorImp ;
} ; }
bool G::Directory::valid( bool for_creation ) const bool G::Directory::valid( bool for_creation ) const
{ {
@ -96,7 +96,7 @@ public:
private: private:
void operator=( const DirectoryIteratorImp & ) ; void operator=( const DirectoryIteratorImp & ) ;
DirectoryIteratorImp( const DirectoryIteratorImp & ) ; DirectoryIteratorImp( const DirectoryIteratorImp & ) ;
static int onError( const char * path , int errno ) ; static int onError( const char * path , int errno_ ) ;
} ; } ;
// === // ===
@ -172,14 +172,13 @@ G::DirectoryIteratorImp::DirectoryIteratorImp( const Directory &dir ,
int flags = 0 | GLOB_ERR ; int flags = 0 | GLOB_ERR ;
int error = ::glob( wild_path.pathCstr() , flags , onError , &m_glob ) ; int error = ::glob( wild_path.pathCstr() , flags , onError , &m_glob ) ;
if( error ) if( error || m_glob.gl_pathv == NULL )
{ {
G_DEBUG( "G::DirectoryIteratorImp::ctor: glob() error: " << error ) ; G_DEBUG( "G::DirectoryIteratorImp::ctor: glob() error: " << error ) ;
m_error = true ; m_error = true ;
} }
else else
{ {
G_ASSERT( m_glob.gl_pathv != NULL ) ;
G_ASSERT( m_glob.gl_pathc == 0 || m_glob.gl_pathv[0] != NULL ) ; G_ASSERT( m_glob.gl_pathc == 0 || m_glob.gl_pathv[0] != NULL ) ;
} }
} }

View File

@ -281,7 +281,7 @@ std::string G::DirectoryIteratorImp::modificationTimeString() const
const DWORD & hi = m_context.ftLastWriteTime.dwHighDateTime ; const DWORD & hi = m_context.ftLastWriteTime.dwHighDateTime ;
const DWORD & lo = m_context.ftLastWriteTime.dwLowDateTime ; const DWORD & lo = m_context.ftLastWriteTime.dwLowDateTime ;
std::stringstream ss ; std::ostringstream ss ;
ss << hi << std::setw(8) << std::setfill('0') << lo ; ss << hi << std::setw(8) << std::setfill('0') << lo ;
return ss.str() ; return ss.str() ;
} }

View File

@ -38,11 +38,11 @@ G::Exception::Exception( const std::string & what ) :
{ {
} }
G::Exception::~Exception() G::Exception::~Exception() throw()
{ {
} }
const char * G::Exception::what() const const char * G::Exception::what() const throw()
{ {
return m_what.c_str() ; return m_what.c_str() ;
} }

View File

@ -31,7 +31,7 @@
namespace G namespace G
{ {
class Exception ; class Exception ;
} ; }
// Class: G::Exception // Class: G::Exception
// Description: A general-purpose exception class derived from std::exception // Description: A general-purpose exception class derived from std::exception
@ -52,10 +52,10 @@ public:
explicit Exception( const std::string & what ) ; explicit Exception( const std::string & what ) ;
// Constructor. // Constructor.
virtual ~Exception() ; virtual ~Exception() throw() ;
// Destructor. // Destructor.
virtual const char * what() const ; virtual const char * what() const throw() ;
// Override from std::exception. // Override from std::exception.
void prepend( const char * context ) ; void prepend( const char * context ) ;
@ -79,7 +79,7 @@ public:
// This method allows a derived-class exception // This method allows a derived-class exception
// to be constructed and thrown on one // to be constructed and thrown on one
// line using iostream formatting. // line using iostream formatting.
// Eg. throw Error( std::stringstream() << a << b ) ; // Eg. throw Error( std::ostringstream() << a << b ) ;
} ; } ;
#define G_EXCEPTION( class_name , description ) class class_name : public G::Exception { public: class_name() { m_what = description ; } public: explicit class_name ( std::ostream & stream ) { m_what = description ; append(stream) ; } public: explicit class_name( const char * more ) { m_what = description ; append(more) ; } public: explicit class_name( const std::string & more ) { m_what = description ; append(more) ; } } #define G_EXCEPTION( class_name , description ) class class_name : public G::Exception { public: class_name() { m_what = description ; } public: explicit class_name ( std::ostream & stream ) { m_what = description ; append(stream) ; } public: explicit class_name( const char * more ) { m_what = description ; append(more) ; } public: explicit class_name( const std::string & more ) { m_what = description ; append(more) ; } }

View File

@ -33,7 +33,7 @@ namespace G
{ {
class File ; class File ;
class DirectoryIteratorImp ; class DirectoryIteratorImp ;
} ; }
// Class: G::File // Class: G::File
// Description: A simple static class for dealing with files. // Description: A simple static class for dealing with files.

View File

@ -54,7 +54,7 @@ std::string G::File::sizeString( const Path & path )
if( 0 != ::stat( path.pathCstr() , &statbuf ) ) if( 0 != ::stat( path.pathCstr() , &statbuf ) )
return std::string() ; return std::string() ;
std::stringstream ss ; std::ostringstream ss ;
ss << statbuf.st_size ; ss << statbuf.st_size ;
return ss.str() ; return ss.str() ;
} }

View File

@ -29,7 +29,7 @@
namespace G namespace G
{ {
class FileSystem ; class FileSystem ;
} ; }
// Class: G::FileSystem // Class: G::FileSystem
// Description: Provides information about the // Description: Provides information about the

View File

@ -28,6 +28,7 @@
#include "ggetopt.h" #include "ggetopt.h"
#include "gassert.h" #include "gassert.h"
#include "gdebug.h" #include "gdebug.h"
#include <sstream>
G::GetOpt::GetOpt( const Arg & args_in , const std::string & spec , G::GetOpt::GetOpt( const Arg & args_in , const std::string & spec ,
char sep_major , char sep_minor , char escape ) : char sep_major , char sep_minor , char escape ) :
@ -46,18 +47,25 @@ void G::GetOpt::parseSpec( const std::string & spec , char sep_major , char sep_
for( Strings::iterator p = outer.begin() ; p != outer.end() ; ++p ) for( Strings::iterator p = outer.begin() ; p != outer.end() ; ++p )
{ {
if( (*p).empty() ) continue ;
StringArray inner ; StringArray inner ;
std::string ws_minor( 1U , sep_minor ) ; std::string ws_minor( 1U , sep_minor ) ;
G::Str::splitIntoFields( *p , inner , ws_minor , escape ) ; G::Str::splitIntoFields( *p , inner , ws_minor , escape ) ;
if( inner.size() != 5U ) if( inner.size() != 6U )
throw InvalidSpecification(std::stringstream() << "\"" << *p << "\" (" << ws_minor << ")") ; {
std::ostringstream ss ;
ss << "\"" << *p << "\" (" << ws_minor << ")" ;
throw InvalidSpecification( ss.str() ) ;
}
bool valued = G::Str::toUInt( inner[3U] ) != 0U ; bool valued = G::Str::toUInt( inner[3U] ) != 0U ;
addSpec( inner[1U] , inner[0U].at(0U) , inner[1U] , inner[2U] , valued , inner[4U] ) ; unsigned int level = G::Str::toUInt( inner[5U] ) ;
addSpec( inner[1U] , inner[0U].at(0U) , inner[1U] , inner[2U] , valued , inner[4U] , level ) ;
} }
} }
void G::GetOpt::addSpec( const std::string & sort_key , char c , const std::string & name , void G::GetOpt::addSpec( const std::string & sort_key , char c , const std::string & name ,
const std::string & description , bool valued , const std::string & value_description ) const std::string & description , bool valued , const std::string & value_description ,
unsigned int level )
{ {
if( c == '\0' ) if( c == '\0' )
throw InvalidSpecification() ; throw InvalidSpecification() ;
@ -65,17 +73,22 @@ void G::GetOpt::addSpec( const std::string & sort_key , char c , const std::stri
const bool debug = true ; const bool debug = true ;
if( debug ) if( debug )
{ {
G_DEBUG( "G::GetOpt::addSpec: " std::ostringstream ss ;
ss
<< "G::GetOpt::addSpec: "
<< "sort-key=" << sort_key << ": " << "sort-key=" << sort_key << ": "
<< "char=" << c << ": " << "char=" << c << ": "
<< "name=" << name << ": " << "name=" << name << ": "
<< "description=" << description << ": " << "description=" << description << ": "
<< "valued=" << (valued?"true":"false") << ": " << "valued=" << (valued?"true":"false") << ": "
<< "value-description=" << value_description ) ; << "value-description=" << value_description << ": "
<< "level=" << level ;
G_DEBUG( ss.str() ) ;
} }
std::pair<SwitchSpecMap::iterator,bool> rc = std::pair<SwitchSpecMap::iterator,bool> rc =
m_spec_map.insert( std::make_pair(sort_key,SwitchSpec(c,name,description,valued,value_description)) ) ; m_spec_map.insert( std::make_pair( sort_key ,
SwitchSpec(c,name,description,valued,value_description,level) ) ) ;
if( ! rc.second ) if( ! rc.second )
throw InvalidSpecification("duplication") ; throw InvalidSpecification("duplication") ;
@ -115,28 +128,41 @@ size_t G::GetOpt::wrapDefault()
return 79U ; return 79U ;
} }
//static
size_t G::GetOpt::tabDefault()
{
return 30U ;
}
//static
G::GetOpt::Level G::GetOpt::levelDefault()
{
return Level(99U) ;
}
//static //static
size_t G::GetOpt::widthLimit( size_t w ) size_t G::GetOpt::widthLimit( size_t w )
{ {
return (w != 0U && w < 50U) ? 50U : w ; return (w != 0U && w < 50U) ? 50U : w ;
} }
void G::GetOpt::showUsage( std::ostream & stream , const std::string & args ) const void G::GetOpt::showUsage( std::ostream & stream , const std::string & args , bool verbose ) const
{ {
showUsage( stream , m_args.prefix() , args ) ; showUsage( stream , m_args.prefix() , args , verbose ? levelDefault() : Level(1U) ) ;
} }
void G::GetOpt::showUsage( std::ostream & stream , const std::string & exe , const std::string & args , void G::GetOpt::showUsage( std::ostream & stream , const std::string & exe , const std::string & args ,
size_t tab_stop , size_t width ) const Level level , size_t tab_stop , size_t width ) const
{ {
stream stream
<< usageSummary(exe,args,width) << std::endl << usageSummary(exe,args,level,width) << std::endl
<< usageHelp(tab_stop,width) ; << usageHelp(level,tab_stop,width,false) ;
} }
std::string G::GetOpt::usageSummary( const std::string & exe , const std::string & args , size_t width ) const std::string G::GetOpt::usageSummary( const std::string & exe , const std::string & args ,
Level level , size_t width ) const
{ {
std::string s = std::string("usage: ") + exe + " " + usageSummarySwitches() + args ; std::string s = std::string("usage: ") + exe + " " + usageSummarySwitches(level) + args ;
if( width != 0U ) if( width != 0U )
{ {
return G::Str::wrap( s , "" , " " , widthLimit(width) ) ; return G::Str::wrap( s , "" , " " , widthLimit(width) ) ;
@ -147,19 +173,28 @@ std::string G::GetOpt::usageSummary( const std::string & exe , const std::string
} }
} }
std::string G::GetOpt::usageSummarySwitches() const std::string G::GetOpt::usageSummarySwitches( Level level ) const
{ {
return usageSummaryPartOne() + usageSummaryPartTwo() ; return usageSummaryPartOne(level) + usageSummaryPartTwo(level) ;
} }
std::string G::GetOpt::usageSummaryPartOne() const //static
bool G::GetOpt::visible( SwitchSpecMap::const_iterator p , Level level , bool exact )
{
return
exact ?
( !(*p).second.hidden && (*p).second.level == level.level ) :
( !(*p).second.hidden && (*p).second.level <= level.level ) ;
}
std::string G::GetOpt::usageSummaryPartOne( Level level ) const
{ {
// summarise the single-character switches, excluding those which take a value // summarise the single-character switches, excluding those which take a value
std::stringstream ss ; std::ostringstream ss ;
bool first = true ; bool first = true ;
for( SwitchSpecMap::const_iterator p = m_spec_map.begin() ; p != m_spec_map.end() ; ++p ) for( SwitchSpecMap::const_iterator p = m_spec_map.begin() ; p != m_spec_map.end() ; ++p )
{ {
if( !(*p).second.valued && !(*p).second.hidden ) if( !(*p).second.valued && visible(p,level,false) )
{ {
if( first ) if( first )
ss << "[-" ; ss << "[-" ;
@ -173,13 +208,13 @@ std::string G::GetOpt::usageSummaryPartOne() const
return s ; return s ;
} }
std::string G::GetOpt::usageSummaryPartTwo() const std::string G::GetOpt::usageSummaryPartTwo( Level level ) const
{ {
std::stringstream ss ; std::ostringstream ss ;
const char * sep = "" ; const char * sep = "" ;
for( SwitchSpecMap::const_iterator p = m_spec_map.begin() ; p != m_spec_map.end() ; ++p ) for( SwitchSpecMap::const_iterator p = m_spec_map.begin() ; p != m_spec_map.end() ; ++p )
{ {
if( !(*p).second.hidden ) if( visible(p,level,false) )
{ {
ss << sep << "[" ; ss << sep << "[" ;
if( (*p).second.name.length() ) if( (*p).second.name.length() )
@ -203,17 +238,18 @@ std::string G::GetOpt::usageSummaryPartTwo() const
return ss.str() ; return ss.str() ;
} }
std::string G::GetOpt::usageHelp( size_t tab_stop , size_t width ) const std::string G::GetOpt::usageHelp( Level level , size_t tab_stop , size_t width , bool exact ) const
{ {
return usageHelpCore( " " , tab_stop , widthLimit(width) ) ; return usageHelpCore( " " , level , tab_stop , widthLimit(width) , exact ) ;
} }
std::string G::GetOpt::usageHelpCore( const std::string & prefix , size_t tab_stop , size_t width ) const std::string G::GetOpt::usageHelpCore( const std::string & prefix , Level level ,
size_t tab_stop , size_t width , bool exact ) const
{ {
std::string result ; std::string result ;
for( SwitchSpecMap::const_iterator p = m_spec_map.begin() ; p != m_spec_map.end() ; ++p ) for( SwitchSpecMap::const_iterator p = m_spec_map.begin() ; p != m_spec_map.end() ; ++p )
{ {
if( !(*p).second.hidden ) if( visible(p,level,exact) )
{ {
std::string line( prefix ) ; std::string line( prefix ) ;
line.append( "-" ) ; line.append( "-" ) ;

View File

@ -35,7 +35,7 @@
namespace G namespace G
{ {
class GetOpt ; class GetOpt ;
} ; }
// Class: G::GetOpt // Class: G::GetOpt
// Description: A command line switch parser. // Description: A command line switch parser.
@ -45,6 +45,8 @@ class G::GetOpt
{ {
public: public:
typedef std::vector<std::string GAllocator(std::string) > StringArray ; typedef std::vector<std::string GAllocator(std::string) > StringArray ;
struct Level // Used by G::GetOpt for extra type safety.
{ unsigned int level ; explicit Level(unsigned int l) : level(l) {} } ;
G_EXCEPTION( InvalidSpecification , "invalid options specification string" ) ; G_EXCEPTION( InvalidSpecification , "invalid options specification string" ) ;
GetOpt( const Arg & arg , const std::string & spec , GetOpt( const Arg & arg , const std::string & spec ,
@ -58,9 +60,12 @@ public:
// <switch-description> // <switch-description>
// <value-type> -- 0 is none, and 1 is a string // <value-type> -- 0 is none, and 1 is a string
// <value-description> // <value-description>
// <level>
// //
// If the switch-description field is empty // If the switch-description field is empty or
// then the switch is hidden. // if the level is zero then the switch is hidden.
// By convention main-stream switches should have
// a level of 1, and obscure ones level 2 and above.
Arg args() const ; Arg args() const ;
// Returns all the non-switch command-line arguments. // Returns all the non-switch command-line arguments.
@ -71,28 +76,39 @@ public:
static size_t wrapDefault() ; static size_t wrapDefault() ;
// Returns a default word-wrapping width. // Returns a default word-wrapping width.
static size_t tabDefault() ;
// Returns a default tab-stop.
static Level levelDefault() ;
// Returns the default level.
std::string usageSummary( const std::string & exe , const std::string & args , std::string usageSummary( const std::string & exe , const std::string & args ,
size_t wrap_width = wrapDefault() ) const ; Level level = levelDefault() , size_t wrap_width = wrapDefault() ) const ;
// Returns a one-line usage summary, as // Returns a one-line usage summary, as
// "usage: <exe> <usageSummarySwitches()> <args>" // "usage: <exe> <usageSummarySwitches()> <args>"
std::string usageSummarySwitches() const ; std::string usageSummarySwitches( Level level = levelDefault() ) const ;
// Returns the one-line summary of switches. Does _not_ // Returns the one-line summary of switches. Does _not_
// include the usual "usage: <exe>" prefix // include the usual "usage: <exe>" prefix
// or non-switch arguments. // or non-switch arguments.
std::string usageHelp( size_t tab_stop = 30U , size_t wrap_width = wrapDefault() ) const ; std::string usageHelp( Level level = levelDefault() ,
// Returns a multi-line string giving help on each switch. size_t tab_stop = tabDefault() , size_t wrap_width = wrapDefault() ,
bool level_exact = false ) const ;
// Returns a multi-line string giving help on each switch.
void showUsage( std::ostream & stream , const std::string & exe , void showUsage( std::ostream & stream , const std::string & exe ,
const std::string & args , size_t tab_stop = 30U , const std::string & args , Level level = levelDefault() ,
size_t tab_stop = tabDefault() ,
size_t wrap_width = wrapDefault() ) const ; size_t wrap_width = wrapDefault() ) const ;
// Streams out multi-line usage text using // Streams out multi-line usage text using
// usageSummary() and usageHelp(). // usageSummary() and usageHelp().
void showUsage( std::ostream & stream , const std::string & args ) const ; void showUsage( std::ostream & stream , const std::string & args , bool verbose ) const ;
// Streams out multi-line usage text using // Streams out multi-line usage text using
// usageSummary() and usageHelp(). // usageSummary() and usageHelp(). Shows
// only level one switches if 'verbose'
// is false.
bool hasErrors() const ; bool hasErrors() const ;
// Returns true if there are errors. // Returns true if there are errors.
@ -126,7 +142,7 @@ public:
// value-based switch. // value-based switch.
private: private:
struct SwitchSpec struct SwitchSpec // A private implementation structure used by G::GetOpt.
{ {
char c ; char c ;
std::string name ; std::string name ;
@ -134,11 +150,12 @@ private:
bool valued ; bool valued ;
bool hidden ; bool hidden ;
std::string value_description ; std::string value_description ;
unsigned int level ;
SwitchSpec(char c_,const std::string &name_,const std::string &description_, SwitchSpec(char c_,const std::string &name_,const std::string &description_,
bool v_,const std::string &vd_) : bool v_,const std::string &vd_,unsigned int level_) :
c(c_) , name(name_) , description(description_) , c(c_) , name(name_) , description(description_) ,
valued(v_) , hidden(description_.empty()) , valued(v_) , hidden(description_.empty()||level_==0U) ,
value_description(vd_) {} value_description(vd_) , level(level_) {}
} ; } ;
typedef std::map<std::string,SwitchSpec GLessAllocator(char,SwitchSpec) > SwitchSpecMap ; typedef std::map<std::string,SwitchSpec GLessAllocator(char,SwitchSpec) > SwitchSpecMap ;
typedef std::pair<bool,std::string> Value ; typedef std::pair<bool,std::string> Value ;
@ -147,7 +164,8 @@ private:
void operator=( const GetOpt & ) ; void operator=( const GetOpt & ) ;
GetOpt( const GetOpt & ) ; GetOpt( const GetOpt & ) ;
void parseSpec( const std::string & spec , char , char , char ) ; void parseSpec( const std::string & spec , char , char , char ) ;
void addSpec( const std::string & sort_key , char c , const std::string & name , const std::string & , bool valued , const std::string & ) ; void addSpec( const std::string & , char c , const std::string & ,
const std::string & , bool , const std::string & , unsigned int ) ;
size_t parseArgs( const Arg & args_in ) ; size_t parseArgs( const Arg & args_in ) ;
bool isOldSwitch( const std::string & arg ) const ; bool isOldSwitch( const std::string & arg ) const ;
bool isNewSwitch( const std::string & arg ) const ; bool isNewSwitch( const std::string & arg ) const ;
@ -166,10 +184,11 @@ private:
void remove( size_t n ) ; void remove( size_t n ) ;
bool valid( const std::string & ) const ; bool valid( const std::string & ) const ;
bool valid( char c ) const ; bool valid( char c ) const ;
std::string usageSummaryPartOne() const ; std::string usageSummaryPartOne( Level ) const ;
std::string usageSummaryPartTwo() const ; std::string usageSummaryPartTwo( Level ) const ;
std::string usageHelpCore( const std::string & , size_t , size_t ) const ; std::string usageHelpCore( const std::string & , Level , size_t , size_t , bool ) const ;
static size_t widthLimit( size_t ) ; static size_t widthLimit( size_t ) ;
static bool visible( SwitchSpecMap::const_iterator , Level , bool ) ;
private: private:
SwitchSpecMap m_spec_map ; SwitchSpecMap m_spec_map ;

View File

@ -28,7 +28,7 @@
namespace G namespace G
{ {
class LogImp ; class LogImp ;
} ; }
// Class: LogImp // Class: LogImp
// Description: An implementation class used by Log. // Description: An implementation class used by Log.
@ -36,22 +36,22 @@ namespace G
class G::LogImp class G::LogImp
{ {
public: public:
static std::stringstream &s() ; static std::ostringstream &s() ;
static bool active() ; static bool active() ;
static void empty() ; static void empty() ;
static const char *m_file ; static const char *m_file ;
static int m_line ; static int m_line ;
static std::stringstream *m_ss ; static std::ostringstream *m_ss ;
} ; } ;
const char *G::LogImp::m_file = NULL ; const char *G::LogImp::m_file = NULL ;
std::stringstream *G::LogImp::m_ss = NULL ; std::ostringstream *G::LogImp::m_ss = NULL ;
int G::LogImp::m_line = 0 ; int G::LogImp::m_line = 0 ;
std::stringstream &G::LogImp::s() std::ostringstream & G::LogImp::s()
{ {
if( m_ss == NULL ) if( m_ss == NULL )
m_ss = new std::stringstream ; m_ss = new std::ostringstream ;
return *m_ss ; return *m_ss ;
} }
@ -59,7 +59,7 @@ void G::LogImp::empty()
{ {
delete m_ss ; delete m_ss ;
m_ss = NULL ; m_ss = NULL ;
m_ss = new std::stringstream ; m_ss = new std::ostringstream ;
} }
bool G::LogImp::active() bool G::LogImp::active()
@ -86,16 +86,7 @@ G::Log::End G::Log::end( G::Log::Severity severity )
G::Log::Stream & G::Log::stream() G::Log::Stream & G::Log::stream()
{ {
if( G::LogImp::active() ) return G::LogImp::s() ;
{
return G::LogImp::s() ;
}
else
{
static char buffer[3] ;
static std::stringstream dummy( buffer , sizeof(buffer) ) ;
return dummy ;
}
} }
void G::Log::onEnd( G::Log::Severity severity ) void G::Log::onEnd( G::Log::Severity severity )
@ -104,10 +95,9 @@ void G::Log::onEnd( G::Log::Severity severity )
{ {
G::LogOutput::output( severity , G::LogImp::m_file , G::LogImp::m_line , G::LogOutput::output( severity , G::LogImp::m_file , G::LogImp::m_line ,
G::LogImp::s().str().c_str() ) ; G::LogImp::s().str().c_str() ) ;
// empty the stream
G::LogImp::empty() ;
} }
G::LogImp::empty() ; // empty the stream
G::LogImp::m_file = NULL ; G::LogImp::m_file = NULL ;
G::LogImp::m_line = 0 ; G::LogImp::m_line = 0 ;
} }

View File

@ -29,7 +29,7 @@
namespace G namespace G
{ {
class Log ; class Log ;
} ; }
// Class: G::Log // Class: G::Log
// Description: A static class for doing iostream-based logging. // Description: A static class for doing iostream-based logging.
@ -82,7 +82,7 @@ namespace G
{ {
return stream ; return stream ;
} }
} ; }
namespace G namespace G
{ {
@ -93,7 +93,7 @@ namespace G
G::Log::onEnd( end.m_s ) ; G::Log::onEnd( end.m_s ) ;
return stream ; return stream ;
} }
} ; }
namespace G namespace G
{ {
@ -103,7 +103,7 @@ namespace G
G::Log::setFile( file ) ; G::Log::setFile( file ) ;
G::Log::setLine( line ) ; G::Log::setLine( line ) ;
} }
} ; }
// Macros: G_LOG, G_LOG_S, G_DEBUG, G_WARNING, G_ERROR // Macros: G_LOG, G_LOG_S, G_DEBUG, G_WARNING, G_ERROR
// The debug macro is for debugging during development. The log macro // The debug macro is for debugging during development. The log macro
@ -113,7 +113,7 @@ namespace G
// then warning/error messages should also get raised by some another // then warning/error messages should also get raised by some another
// independent means. // independent means.
// //
#define G_LOG_OUTPUT( expr , severity ) { G::Log::stream() << G::Log::Line(__FILE__,__LINE__) << expr << G::Log::end(severity) ; } #define G_LOG_OUTPUT( expr , severity ) do { G::Log::stream() << G::Log::Line(__FILE__,__LINE__) << expr << G::Log::end(severity) ; } while(0)
#if defined(_DEBUG) && ! defined(G_NO_DEBUG) #if defined(_DEBUG) && ! defined(G_NO_DEBUG)
#define G_DEBUG( expr ) G_LOG_OUTPUT( expr , G::Log::s_Debug ) #define G_DEBUG( expr ) G_LOG_OUTPUT( expr , G::Log::s_Debug )
#else #else

View File

@ -30,7 +30,7 @@
namespace G namespace G
{ {
class LogOutput ; class LogOutput ;
} ; }
// Class: G::LogOutput // Class: G::LogOutput
// Description: Controls and implements low-level logging output, as used by the Log interface. // Description: Controls and implements low-level logging output, as used by the Log interface.

View File

@ -46,7 +46,7 @@ namespace
return m ; return m ;
} }
} ; }
void G::LogOutput::rawOutput( G::Log::Severity severity , const char *message ) void G::LogOutput::rawOutput( G::Log::Severity severity , const char *message )
{ {

View File

@ -27,12 +27,6 @@
#include <cstdlib> // getenv #include <cstdlib> // getenv
static HANDLE source() ; static HANDLE source() ;
#if ! defined(RegisterEventSource)
static void RegisterEventSource( const char * , const char * ) {}
static void DeregisterEventSource( HANDLE ) {}
static void ReportEvent( HANDLE , DWORD , int , DWORD , const char * ,
size_t , int , const char ** , const char * ) {}
#endif
void G::LogOutput::cleanup() void G::LogOutput::cleanup()
{ {
@ -90,9 +84,7 @@ void G::LogOutput::rawOutput( G::Log::Severity severity , const char *message )
void G::LogOutput::init() void G::LogOutput::init()
{ {
#if defined(RegisterEventSource)
m_handle = ::source() ; m_handle = ::source() ;
#endif
} }
static HANDLE source() static HANDLE source()

View File

@ -31,7 +31,7 @@
namespace G namespace G
{ {
class Md5 ; class Md5 ;
} ; }
// Class: G::Md5 // Class: G::Md5
// Description: MD5 class. // Description: MD5 class.

View File

@ -29,7 +29,7 @@
namespace G namespace G
{ {
class noncopyable ; class noncopyable ;
} ; }
// Class: G::noncopyable // Class: G::noncopyable
// Description: A noncopyable base class (a la boost). // Description: A noncopyable base class (a la boost).

View File

@ -32,7 +32,7 @@
namespace G namespace G
{ {
class Path ; class Path ;
} ; }
// Class: G::Path // Class: G::Path
// Description: A Path object represents a file system // Description: A Path object represents a file system
@ -86,7 +86,7 @@ public:
// eg. c:foo\bar.exe -> c:foo // eg. c:foo\bar.exe -> c:foo
// eg. c:\foo\bar.exe -> c:\foo // eg. c:\foo\bar.exe -> c:\foo
// eg. c:bar.exe -> c: // eg. c:bar.exe -> c:
// eg. c:\file -> c:\ // eg. c:\file -> c:\ .
// eg. c:\ -> <empty> // eg. c:\ -> <empty>
// eg. c: -> <empty> // eg. c: -> <empty>
// eg. \foo\bar.exe -> \foo // eg. \foo\bar.exe -> \foo
@ -105,8 +105,8 @@ public:
void removeExtension() ; void removeExtension() ;
// Modifies the path by removing any extension. // Modifies the path by removing any extension.
// However, the extension returned by extension() // However, the extension returned by extension() is
// is unchanged. // unchanged.
void setExtension( const std::string & extension ) ; void setExtension( const std::string & extension ) ;
// Replaces the extension. Any leading dot in the // Replaces the extension. Any leading dot in the
@ -177,6 +177,6 @@ namespace G
path.streamOut( stream ) ; path.streamOut( stream ) ;
return stream ; return stream ;
} }
} ; }
#endif #endif

128
src/glib/gpidfile.cpp Normal file
View File

@ -0,0 +1,128 @@
//
// Copyright (C) 2001-2002 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.
//
// ===
//
// gpidfile.cpp
//
#include "gdef.h"
#include "gpidfile.h"
#include "gprocess.h"
#include "gcleanup.h"
#include "gfile.h"
#include "gdebug.h"
#include <cstdlib> // std::malloc()
#include <cstring> // std::strdup()
#include <fstream>
#include <fcntl.h>
namespace
{
// strdup() not in std:: ?
char * strdup_( const char * p )
{
p = p ? p : "" ;
char * buffer = static_cast<char*>( std::malloc( std::strlen(p) + 1U ) ) ;
std::strcpy( buffer , p ) ;
return buffer ;
}
}
//static
void G::PidFile::create( const Path & pid_file )
{
if( pid_file != Path() )
{
G_DEBUG( "G::PidFile::create: \"" << pid_file << "\"" ) ;
Process::Umask readable(Process::Umask::Readable) ;
std::ofstream file( pid_file.str().c_str() ) ;
file << Process::Id() << std::endl ;
if( !file.good() )
throw Error(std::string("cannot create file: ")+pid_file.str()) ;
Cleanup::add( cleanup , strdup_(pid_file.str().c_str()) ) ; // (leaks)
}
}
//static
bool G::PidFile::mine( const char * path )
{
// reentrant implementation...
Process::Id this_pid ;
Process::Id file_pid( path ) ;
return this_pid == file_pid ;
}
//static
void G::PidFile::cleanup( const char * path )
{
// reentrant implementation...
try
{
if( path && *path && mine(path) )
std::remove( path ) ;
}
catch(...)
{
}
}
// ===
G::PidFile::PidFile()
{
}
G::PidFile::~PidFile()
{
if( valid() )
cleanup( m_path.pathCstr() ) ;
}
G::PidFile::PidFile( const Path & path ) :
m_path(path)
{
}
void G::PidFile::init( const Path & path )
{
m_path = path ;
}
void G::PidFile::check()
{
if( valid() && ! m_path.isAbsolute() )
throw Error(std::string("must be an absolute path: ")+m_path.str()) ;
}
void G::PidFile::commit()
{
if( valid() )
create( m_path ) ;
}
G::Path G::PidFile::path() const
{
return m_path ;
}
bool G::PidFile::valid() const
{
return m_path != Path() ;
}

93
src/glib/gpidfile.h Normal file
View File

@ -0,0 +1,93 @@
//
// Copyright (C) 2001-2002 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.
//
// ===
//
// gpidfile.h
//
#ifndef G_PIDFILE_H
#define G_PIDFILE_H
#include "gdef.h"
#include "gexception.h"
#include "gpath.h"
#include <sys/types.h>
#include <string>
namespace G
{
class PidFile ;
class Daemon ;
}
// Class: G::PidFile
// Description: A class for creating pid files.
// See also: G::Daemon
//
class G::PidFile
{
public:
G_EXCEPTION( Error , "invalid pid file" ) ;
static void cleanup( const char * path ) ;
// Deletes the specified pid file if it
// contains this process's id.
//
// Reentrant implementation.
explicit PidFile( const Path & pid_file_path ) ;
// Constructor. The path should normally be
// an absolute path. Use commit() to actually
// create the file.
PidFile() ;
// Default constructor. Constructs a
// do-nothing object. Initialise with init().
void init( const Path & pid_file_path ) ;
// Used after default construction.
~PidFile() ;
// Destructor. Calls cleanup() to delete
// the file.
void commit() ;
// Creates the file.
void check() ;
// Throws an exception if the path is not
// absolute.
Path path() const ;
// Returns the path as supplied to the constructor
// or init().
private:
Path m_path ;
private:
PidFile( const PidFile & ) ; // not implemented
void operator=( const PidFile & ) ; // not implemented
static bool mine( const char * path ) ; // reentrant
static void create( const Path & pid_file ) ;
bool valid() const ;
} ;
#endif

View File

@ -27,6 +27,7 @@
#include "gdef.h" #include "gdef.h"
#include "gexception.h" #include "gexception.h"
#include "gpath.h" #include "gpath.h"
#include "gstrings.h"
#include <iostream> #include <iostream>
#include <sys/types.h> #include <sys/types.h>
#include <string> #include <string>
@ -34,7 +35,7 @@
namespace G namespace G
{ {
class Process ; class Process ;
} ; }
// Class: G::Process // Class: G::Process
// Description: A static interface for doing things with processes. // Description: A static interface for doing things with processes.
@ -52,18 +53,19 @@ public:
G_EXCEPTION( UidError , "cannot set uid" ) ; G_EXCEPTION( UidError , "cannot set uid" ) ;
G_EXCEPTION( GidError , "cannot set gid" ) ; G_EXCEPTION( GidError , "cannot set gid" ) ;
G_EXCEPTION( Insecure , "refusing to exec() while the user-id is zero" ) ; G_EXCEPTION( Insecure , "refusing to exec() while the user-id is zero" ) ;
G_EXCEPTION( InvalidId , "invalid process-id string" ) ;
G_EXCEPTION( PipeError , "pipe error" ) ;
enum Who { Parent , Child } ; enum Who { Parent , Child } ;
class IdImp ; class IdImp ;
class Id // Process-id class. class Id // Process-id class.
{ {
public: Id() ; public: Id() ;
public: ~Id() ; public: explicit Id( std::istream & ) ;
public: Id( const Id & other ) ; public: explicit Id( const char * pid_file_path ) ; // (re-entrant ctor)
public: Id & operator=( const Id & rhs ) ;
public: bool operator==( const Id & other ) const ;
public: std::string str() const ; public: std::string str() const ;
private: IdImp * m_imp ; public: bool operator==( const Id & ) const ;
private: pid_t m_pid ;
friend class Process ; friend class Process ;
} ; } ;
struct Identity // Used by G::Process::beSpecial(). struct Identity // Used by G::Process::beSpecial().
@ -74,6 +76,17 @@ public:
explicit Identity( const std::string & login_name ) ; explicit Identity( const std::string & login_name ) ;
std::string str() const ; std::string str() const ;
} ; } ;
class Umask // Used to temporarily modify the process umask.
{
public: enum Mode { Readable , Tighter , Tightest } ;
public: explicit Umask( Mode ) ;
public: ~Umask() ;
public: static void set( Mode ) ;
private: Umask( const Umask & ) ; // not implemented
private: void operator=( const Umask & ) ; // not implemented
private: class UmaskImp ;
private: UmaskImp * m_imp ;
} ;
class NoThrow // An overload discriminator for Process. class NoThrow // An overload discriminator for Process.
{} ; {} ;
@ -83,9 +96,6 @@ public:
static void closeStderr() ; static void closeStderr() ;
// Closes stderr. // Closes stderr.
static void setUmask( bool tightest = true ) ;
// Sets a tight umask.
static void cd( const Path & dir ) ; static void cd( const Path & dir ) ;
// Changes directory. // Changes directory.
@ -98,12 +108,15 @@ public:
static Who fork( Id & child ) ; static Who fork( Id & child ) ;
// Forks a child process. Returns the child // Forks a child process. Returns the child
// pid to the parent. // pid by reference to the parent.
static int spawn( Identity nobody , const Path & exe , const std::string & arg , int error_return = 127 ) ; static int spawn( Identity nobody , const Path & exe , const Strings & args ,
// Runs a command in an unprivileged child process. Returns the std::string * pipe_result_p = NULL , int error_return = 127 ) ;
// child process's exit code, or 'error_return' on error. // Runs a command in an unprivileged child process. Returns the
// The identity should have come from beOrdinary(). // child process's exit code, or 'error_return' on error.
// If the 'pipe_result_p' pointer is supplied then a pipe
// is used to read the first bit of whatever the child process
// writes to stdout. The identity should have come from beOrdinary().
static int errno_() ; static int errno_() ;
// Returns the process's current 'errno' value. // Returns the process's current 'errno' value.
@ -112,6 +125,8 @@ public:
// Aquires special privileges (either root // Aquires special privileges (either root
// or suid). The parameter must have come from // or suid). The parameter must have come from
// a previous call to beOrdinary(). // a previous call to beOrdinary().
//
// See also class G::Root.
static Identity beOrdinary( Identity nobody , bool change_group = true ) ; static Identity beOrdinary( Identity nobody , bool change_group = true ) ;
// Revokes special privileges (root or suid). // Revokes special privileges (root or suid).
@ -122,13 +137,16 @@ public:
// parameter is ignored. Returns the old // parameter is ignored. Returns the old
// identity, which can be passed to // identity, which can be passed to
// beSpecial(). // beSpecial().
//
// See also class G::Root.
private: private:
Process() ; Process() ;
static int wait( const Id & child ) ; static int wait( const Id & child ) ;
static int wait( const Id & child , int error_return ) ; static int wait( const Id & child , int error_return ) ;
static void execCore( const Path & , const std::string & ) ; static void execCore( const Path & , const Strings & ) ;
static void beNobody( Identity ) ; static void beNobody( Identity ) ;
static void closeFiles( int ) ;
} ; } ;
namespace G namespace G
@ -139,12 +157,19 @@ namespace G
return stream << id.str() ; return stream << id.str() ;
} }
inline
std::istream & operator>>( std::istream & stream , G::Process::Id & id )
{
id = G::Process::Id( stream ) ;
return stream ;
}
inline inline
std::ostream & operator<<( std::ostream & stream , const G::Process::Identity & identity ) std::ostream & operator<<( std::ostream & stream , const G::Process::Identity & identity )
{ {
return stream << identity.str() ; return stream << identity.str() ;
} }
} ; }
#endif #endif

View File

@ -34,6 +34,38 @@
#include <pwd.h> // getpwnam() #include <pwd.h> // getpwnam()
#include <unistd.h> // setuid() etc #include <unistd.h> // setuid() etc
namespace
{
void noCloseOnExec( int fd )
{
::fcntl( fd , F_SETFD , 0 ) ;
}
}
namespace G
{
class Pipe ;
}
// Class: G::Pipe
// Description: A private implementation class used by G::Process.
//
class G::Pipe
{
public:
explicit Pipe( bool active ) ;
~Pipe() ;
void inChild() ; // writer
void inParent() ; // reader
int fd() const ;
void dup() ; // onto stdout
std::string read() ; // size-limited
private:
G_EXCEPTION( Error , "pipe error" ) ;
int m_fds[2] ;
int m_fd ;
} ;
// Class: G::Process::IdImp // Class: G::Process::IdImp
// Description: A private implementation class used by G::Process. // Description: A private implementation class used by G::Process.
// //
@ -58,24 +90,25 @@ bool G::Process::cd( const Path & dir , NoThrow )
return 0 == ::chdir( dir.str().c_str() ) ; return 0 == ::chdir( dir.str().c_str() ) ;
} }
//static
void G::Process::setUmask( bool tightest )
{
mode_t new_mode = tightest ? 0177 : 0117 ; // tightest => -rw-------
(void) ::umask( new_mode ) ;
}
//static //static
void G::Process::closeStderr() void G::Process::closeStderr()
{ {
::close( STDERR_FILENO ) ; ::close( STDERR_FILENO ) ;
::open( G::FileSystem::nullDevice() , O_WRONLY ) ; ::open( G::FileSystem::nullDevice() , O_WRONLY ) ;
::fcntl( STDERR_FILENO , F_SETFD , 0 ) ; // close-on-exec false noCloseOnExec( STDERR_FILENO ) ;
} }
//static //static
void G::Process::closeFiles( bool keep_stderr ) void G::Process::closeFiles( bool keep_stderr )
{ {
closeFiles( keep_stderr ? STDERR_FILENO : -1 ) ;
}
//static
void G::Process::closeFiles( int keep )
{
G_ASSERT( keep == -1 || keep >= STDERR_FILENO ) ;
int n = 256U ; int n = 256U ;
long rc = ::sysconf( _SC_OPEN_MAX ) ; long rc = ::sysconf( _SC_OPEN_MAX ) ;
if( rc > 0L ) if( rc > 0L )
@ -83,10 +116,8 @@ void G::Process::closeFiles( bool keep_stderr )
for( int fd = 0 ; fd < n ; fd++ ) for( int fd = 0 ; fd < n ; fd++ )
{ {
if( !keep_stderr || fd != STDERR_FILENO ) if( fd != keep )
{
::close( fd ) ; ::close( fd ) ;
}
} }
// reopen standard fds to prevent accidental use // reopen standard fds to prevent accidental use
@ -95,13 +126,13 @@ void G::Process::closeFiles( bool keep_stderr )
// //
::open( G::FileSystem::nullDevice() , O_RDONLY ) ; ::open( G::FileSystem::nullDevice() , O_RDONLY ) ;
::open( G::FileSystem::nullDevice() , O_WRONLY ) ; ::open( G::FileSystem::nullDevice() , O_WRONLY ) ;
if( !keep_stderr ) if( keep != STDERR_FILENO )
{ {
::open( G::FileSystem::nullDevice() , O_WRONLY ) ; ::open( G::FileSystem::nullDevice() , O_WRONLY ) ;
::fcntl( STDERR_FILENO , F_SETFD , 0 ) ; // close-on-exec false
} }
::fcntl( STDIN_FILENO , F_SETFD , 0 ) ; // close-on-exec false noCloseOnExec( STDIN_FILENO ) ;
::fcntl( STDOUT_FILENO , F_SETFD , 0 ) ; // close-on-exec false noCloseOnExec( STDOUT_FILENO ) ;
noCloseOnExec( STDERR_FILENO ) ;
} }
G::Process::Who G::Process::fork() G::Process::Who G::Process::fork()
@ -117,7 +148,7 @@ G::Process::Who G::Process::fork( Id & child_pid )
if( ok ) if( ok )
{ {
if( rc != 0 ) if( rc != 0 )
child_pid.m_imp->m_pid = rc ; child_pid.m_pid = rc ;
} }
else else
{ {
@ -132,7 +163,7 @@ int G::Process::wait( const Id & child_pid )
for(;;) for(;;)
{ {
G_DEBUG( "G::Process::wait: waiting" ) ; G_DEBUG( "G::Process::wait: waiting" ) ;
int rc = ::waitpid( child_pid.m_imp->m_pid , &status , 0 ) ; int rc = ::waitpid( child_pid.m_pid , &status , 0 ) ;
if( rc == -1 && errno_() == EINTR ) if( rc == -1 && errno_() == EINTR )
{ {
; // signal in parent -- keep waiting ; // signal in parent -- keep waiting
@ -140,7 +171,9 @@ int G::Process::wait( const Id & child_pid )
else if( rc == -1 ) else if( rc == -1 )
{ {
int error = errno_() ; int error = errno_() ;
throw WaitError( std::stringstream() << "errno=" << error ) ; std::ostringstream ss ;
ss << "errno=" << error ;
throw WaitError( ss.str() ) ;
} }
else else
{ {
@ -152,7 +185,9 @@ int G::Process::wait( const Id & child_pid )
if( ! WIFEXITED(status) ) if( ! WIFEXITED(status) )
{ {
// uncaught signal or stopped // uncaught signal or stopped
throw ChildError( std::stringstream() << "status=" << status ) ; std::ostringstream ss ;
ss << "status=" << status ;
throw ChildError( ss.str() ) ;
} }
const int exit_status = WEXITSTATUS(status) ; const int exit_status = WEXITSTATUS(status) ;
@ -177,7 +212,8 @@ int G::Process::errno_()
return errno ; // not ::errno or std::errno for gcc2.95 return errno ; // not ::errno or std::errno for gcc2.95
} }
int G::Process::spawn( Identity nobody , const G::Path & exe , const std::string & arg , int error_return ) int G::Process::spawn( Identity nobody , const Path & exe , const Strings & args ,
std::string * pipe_result_p , int error_return )
{ {
if( exe.isRelative() ) if( exe.isRelative() )
throw InvalidPath( exe.str() ) ; throw InvalidPath( exe.str() ) ;
@ -185,28 +221,36 @@ int G::Process::spawn( Identity nobody , const G::Path & exe , const std::string
if( ::geteuid() == 0U || nobody.uid == 0U ) if( ::geteuid() == 0U || nobody.uid == 0U )
throw Insecure() ; throw Insecure() ;
Pipe pipe( pipe_result_p != NULL ) ;
Id child_pid ; Id child_pid ;
if( fork(child_pid) == Child ) if( fork(child_pid) == Child )
{ {
beNobody( nobody ) ; try
G_ASSERT( ::getuid() != 0U && ::geteuid() != 0U ) ; {
closeFiles() ; beNobody( nobody ) ;
execCore( exe , arg ) ; G_ASSERT( ::getuid() != 0U && ::geteuid() != 0U ) ;
pipe.inChild() ;
closeFiles( pipe.fd() ) ;
pipe.dup() ; // dup() onto stdout
execCore( exe , args ) ;
}
catch(...)
{
}
::_exit( error_return ) ; ::_exit( error_return ) ;
return error_return ; // pacify the compiler
} }
else else
{ {
return wait( child_pid , error_return ) ; pipe.inParent() ;
int exit_status = wait( child_pid , error_return ) ;
if( pipe_result_p != NULL ) *pipe_result_p = pipe.read() ;
return exit_status ;
} }
} }
void G::Process::execCore( const G::Path & exe , const std::string & arg ) void G::Process::execCore( const G::Path & exe , const Strings & args )
{ {
char * argv[3U] ;
argv[0U] = const_cast<char*>( exe.pathCstr() ) ;
argv[1U] = arg.empty() ? static_cast<char*>(NULL) : const_cast<char*>(arg.c_str()) ;
argv[2U] = NULL ;
char * env[3U] ; char * env[3U] ;
std::string path( "PATH=/usr/bin:/bin" ) ; // no "." std::string path( "PATH=/usr/bin:/bin" ) ; // no "."
std::string ifs( "IFS= \t\n" ) ; std::string ifs( "IFS= \t\n" ) ;
@ -214,9 +258,17 @@ void G::Process::execCore( const G::Path & exe , const std::string & arg )
env[1U] = const_cast<char*>( ifs.c_str() ) ; env[1U] = const_cast<char*>( ifs.c_str() ) ;
env[2U] = NULL ; env[2U] = NULL ;
::execve( exe.str().c_str() , argv , env ) ; char ** argv = new char* [ args.size() + 2U ] ;
argv[0U] = const_cast<char*>( exe.pathCstr() ) ;
unsigned int argc = 1U ;
for( Strings::const_iterator arg_p = args.begin() ; arg_p != args.end() ; ++arg_p , argc++ )
argv[argc] = const_cast<char*>(arg_p->c_str()) ;
argv[argc] = NULL ;
::execve( exe.str().c_str() , argv , env ) ;
const int error = errno_() ; const int error = errno_() ;
delete [] argv ;
G_WARNING( "G::Process::exec: execve() returned: errno=" << error << ": " << exe ) ; G_WARNING( "G::Process::exec: execve() returned: errno=" << error << ": " << exe ) ;
} }
@ -232,8 +284,8 @@ void G::Process::beSpecial( Identity identity , bool change_group )
Identity old_identity ; Identity old_identity ;
(void) ::seteuid( identity.uid ) ; (void) ::seteuid( identity.uid ) ;
if( change_group) (void) ::setegid( identity.gid ) ; if( change_group) (void) ::setegid( identity.gid ) ;
(void) old_identity.str() ; // pacify the compiler //G_DEBUG( "G::Process::beSpecial: " << old_identity << " -> " << Identity() ) ;
G_DEBUG( "G::Process::beSpecial: " << old_identity << " -> " << Identity() ) ; old_identity.uid = 0 ; // pacify the compiler
} }
G::Process::Identity G::Process::beOrdinary( Identity nobody , bool change_group ) G::Process::Identity G::Process::beOrdinary( Identity nobody , bool change_group )
@ -252,7 +304,7 @@ G::Process::Identity G::Process::beOrdinary( Identity nobody , bool change_group
if( ::seteuid( ::getuid() ) ) throw UidError() ; if( ::seteuid( ::getuid() ) ) throw UidError() ;
if( change_group && ::setegid( ::getgid() ) ) throw GidError() ; if( change_group && ::setegid( ::getgid() ) ) throw GidError() ;
} }
G_DEBUG( "G::Process::beOrdinary: " << special_identity << " -> " << Identity() ) ; //G_DEBUG( "G::Process::beOrdinary: " << special_identity << " -> " << Identity() ) ;
return special_identity ; return special_identity ;
} }
@ -269,40 +321,42 @@ void G::Process::beNobody( Identity nobody )
// === // ===
G::Process::Id::Id() : m_imp(NULL) G::Process::Id::Id()
{ {
m_imp = new IdImp ; m_pid = ::getpid() ;
m_imp->m_pid = ::getpid() ;
} }
G::Process::Id::~Id() G::Process::Id::Id( const char * path ) :
m_pid(0)
{ {
delete m_imp ; // reentrant implementation suitable for a signal handler...
int fd = ::open( path ? path : "" , O_RDONLY ) ;
char buffer[10] ;
ssize_t rc = ::read( fd , buffer , sizeof(buffer) ) ;
for( const char * p = buffer ; rc > 0 && *p >= '0' && *p <= '9' ; p++ , rc-- )
{
m_pid *= 10 ;
m_pid += ( *p - '0' ) ;
}
} }
G::Process::Id::Id( const Id & other ) : G::Process::Id::Id( std::istream & stream )
m_imp(NULL)
{ {
m_imp = new IdImp ; stream >> m_pid ;
m_imp->m_pid = other.m_imp->m_pid ; if( !stream.good() )
} throw Process::InvalidId() ;
G::Process::Id & G::Process::Id::operator=( const Id & rhs )
{
m_imp->m_pid = rhs.m_imp->m_pid ;
return *this ;
} }
std::string G::Process::Id::str() const std::string G::Process::Id::str() const
{ {
std::stringstream ss ; std::ostringstream ss ;
ss << m_imp->m_pid ; ss << m_pid ;
return ss.str() ; return ss.str() ;
} }
bool G::Process::Id::operator==( const Id & rhs ) const bool G::Process::Id::operator==( const Id & other ) const
{ {
return m_imp->m_pid == rhs.m_imp->m_pid ; return m_pid == other.m_pid ;
} }
// === // ===
@ -322,7 +376,7 @@ G::Process::Identity::Identity( const std::string & name ) :
::passwd * pw = ::getpwnam( name.c_str() ) ; ::passwd * pw = ::getpwnam( name.c_str() ) ;
if( pw == NULL ) if( pw == NULL )
throw Process::NoSuchUser(name) ; throw Process::NoSuchUser(name) ;
G_DEBUG( "G::Process::Identity: " << name << "=" << pw->pw_uid << "/" << pw->pw_gid ) ; //G_DEBUG( "G::Process::Identity: " << name << "=" << pw->pw_uid << "/" << pw->pw_gid ) ;
uid = pw->pw_uid ; uid = pw->pw_uid ;
gid = pw->pw_gid ; gid = pw->pw_gid ;
} }
@ -330,8 +384,95 @@ G::Process::Identity::Identity( const std::string & name ) :
std::string G::Process::Identity::str() const std::string G::Process::Identity::str() const
{ {
std::stringstream ss ; std::ostringstream ss ;
ss << uid << "/" << gid ; ss << uid << "/" << gid ;
return ss.str() ; return ss.str() ;
} }
// ===
class G::Process::Umask::UmaskImp
{
public:
mode_t m_old_mode ;
} ;
G::Process::Umask::Umask( Mode mode ) :
m_imp(new UmaskImp)
{
m_imp->m_old_mode =
::umask( mode==Readable?0133:(mode==Tighter?0117:0177) ) ;
}
G::Process::Umask::~Umask()
{
(void) ::umask( m_imp->m_old_mode ) ;
delete m_imp ;
}
//static
void G::Process::Umask::set( Mode mode )
{
// Tightest: -rw-------
// Tighter: -rw-rw----
// Readable: -rw-r--r--
::umask( mode==Readable?0133:(mode==Tighter?0117:0177) ) ;
}
// ===
G::Pipe::Pipe( bool active ) :
m_fd(-1)
{
m_fds[0] = m_fds[1] = -1 ;
if( active && ::pipe( m_fds ) < 0 )
throw Error() ;
G_DEBUG( "G::Pipe::ctor: " << m_fds[0] << " " << m_fds[1] ) ;
}
G::Pipe::~Pipe()
{
if( m_fds[0] >= 0 ) ::close( m_fds[0] ) ;
if( m_fds[1] >= 0 ) ::close( m_fds[1] ) ;
}
void G::Pipe::inChild()
{
::close( m_fds[0] ) ;
m_fds[0] = -1 ;
m_fd = m_fds[1] ; // writer
}
void G::Pipe::inParent()
{
::close( m_fds[1] ) ;
m_fds[1] = -1 ;
m_fd = m_fds[0] ; // reader
}
int G::Pipe::fd() const
{
return m_fd ;
}
void G::Pipe::dup()
{
if( m_fd != -1 && m_fd != STDOUT_FILENO )
{
if( ::dup2(m_fd,STDOUT_FILENO) != STDOUT_FILENO )
throw Error() ;
::close( m_fd ) ;
m_fd = -1 ;
m_fds[1] = -1 ;
noCloseOnExec( STDOUT_FILENO ) ;
}
}
std::string G::Pipe::read()
{
char buffer[4096] ;
int rc = m_fd == -1 ? 0 : ::read( m_fd , buffer , sizeof(buffer) ) ;
if( rc < 0 ) throw Error("read") ;
return std::string(buffer,rc) ;
}

View File

@ -23,20 +23,36 @@
#include "gdef.h" #include "gdef.h"
#include "gprocess.h" #include "gprocess.h"
#include "gexception.h"
#include "gstr.h"
#include "glog.h" #include "glog.h"
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <process.h> #include <process.h>
#include <direct.h> #include <direct.h>
#include <io.h> #include <io.h>
#include <fcntl.h>
namespace G namespace G
{ {
const int STDERR_FILENO = 2 ; const int STDERR_FILENO = 2 ;
const int SC_OPEN_MAX = 256 ; // 32 in limits.h !? const int SC_OPEN_MAX = 256 ; // 32 in limits.h !?
class Pipe ;
} ; } ;
// === class G::Pipe
{
public:
G_EXCEPTION( Error , "pipe error" ) ;
explicit Pipe( bool active ) ;
~Pipe() ;
int fd() const ;
std::string read() ;
private:
bool m_active ;
int m_fds[2] ;
int m_fd_writer ;
} ;
class G::Process::IdImp class G::Process::IdImp
{ {
@ -46,42 +62,86 @@ public:
// === // ===
G::Process::Id::Id() : m_imp(NULL) G::Pipe::Pipe( bool active ) :
m_active(active) ,
m_fd_writer(-1)
{ {
m_imp = new IdImp ; m_fds[0] = m_fds[1] = -1 ;
m_imp->m_pid = static_cast<unsigned int>(::_getpid()) ; // or ::GetCurrentProcessId() if( m_active )
{
int rc = ::_pipe( m_fds , 256 , _O_BINARY | _O_NOINHERIT ) ;
if( rc < 0 ) throw Error() ;
m_fd_writer = ::_dup( m_fds[1] ) ; // inherited
::_close( m_fds[1] ) ;
m_fds[1] = -1 ;
}
} }
G::Process::Id::~Id() G::Pipe::~Pipe()
{ {
delete m_imp ; if( m_active )
{
::_close( m_fds[0] ) ;
::_close( m_fds[1] ) ;
::_close( m_fd_writer ) ;
}
} }
G::Process::Id::Id( const Id & other ) : int G::Pipe::fd() const
m_imp(NULL)
{ {
m_imp = new IdImp ; return m_fd_writer ;
m_imp->m_pid = other.m_imp->m_pid ;
} }
G::Process::Id & G::Process::Id::operator=( const Id & rhs ) std::string G::Pipe::read()
{ {
m_imp->m_pid = rhs.m_imp->m_pid ; if( ! m_active ) return std::string() ;
return *this ; ::_close( m_fd_writer ) ;
char buffer[4096] ;
int rc = m_fds[0] == -1 ? 0 : ::_read( m_fds[0] , buffer , sizeof(buffer) ) ;
if( rc < 0 ) throw Error() ;
return std::string( buffer , rc ) ;
}
// ===
G::Process::Id::Id()
{
m_pid = static_cast<unsigned int>(::_getpid()) ; // or ::GetCurrentProcessId()
}
G::Process::Id::Id( const char * path ) :
m_pid(0)
{
std::ifstream file( path ? path : "" ) ;
file >> m_pid ;
if( !file.good() )
m_pid = 0 ;
}
G::Process::Id::Id( std::istream & stream )
{
stream >> m_pid ;
if( !stream.good() )
throw Process::InvalidId() ;
} }
std::string G::Process::Id::str() const std::string G::Process::Id::str() const
{ {
std::stringstream ss ; std::ostringstream ss ;
ss << m_imp->m_pid ; ss << m_pid ;
return ss.str() ; return ss.str() ;
} }
bool G::Process::Id::operator==( const Id & rhs ) const bool G::Process::Id::operator==( const Id & rhs ) const
{ {
return m_imp->m_pid == rhs.m_imp->m_pid ; return m_pid == rhs.m_pid ;
} }
// not implemented...
//G::Process::Id::Id( const char * pid_file_path ) {}
// ===
void G::Process::closeFiles( bool keep_stderr ) void G::Process::closeFiles( bool keep_stderr )
{ {
const int n = SC_OPEN_MAX ; const int n = SC_OPEN_MAX ;
@ -92,12 +152,6 @@ void G::Process::closeFiles( bool keep_stderr )
} }
} }
void G::Process::setUmask( bool )
{
// _umask() is available but not very useful
; // no-op
}
void G::Process::closeStderr() void G::Process::closeStderr()
{ {
int fd = STDERR_FILENO ; int fd = STDERR_FILENO ;
@ -115,21 +169,33 @@ bool G::Process::cd( const Path & dir , NoThrow )
return 0 == ::_chdir( dir.str().c_str() ) ; return 0 == ::_chdir( dir.str().c_str() ) ;
} }
int G::Process::spawn( Identity , const Path & exe , const std::string & arg , int G::Process::spawn( Identity , const Path & exe , const Strings & args_ ,
int error_return ) std::string * pipe_result_p , int error_return )
{ {
// open file descriptors are inherited across ::_spawn() -- // open file descriptors are inherited across ::_spawn() --
// no fcntl() is available to set close-on-exec -- but see // no fcntl() is available to set close-on-exec -- but see
// also ::CreateProcess() // also ::CreateProcess()
const char * argv [3U] ; Strings args( args_ ) ; // non-const copy
argv[0U] = exe.pathCstr() ; Pipe pipe( pipe_result_p != NULL ) ;
argv[1U] = arg.c_str() ; if( pipe_result_p != NULL )
argv[2U] = NULL ; args.push_front( Str::fromInt(pipe.fd()) ) ; // kludge -- child must write on specific fd passed as argv[1]
char ** argv = new char* [ args.size() + 2U ] ;
argv[0U] = const_cast<char*>( exe.pathCstr() ) ;
unsigned int argc = 1U ;
for( Strings::const_iterator arg_p = args.begin() ; arg_p != args.end() ; ++arg_p , argc++ )
argv[argc] = const_cast<char*>(arg_p->c_str()) ;
argv[argc] = NULL ;
const int mode = _P_WAIT ; const int mode = _P_WAIT ;
::_flushall() ; ::_flushall() ;
int rc = ::_spawnv( mode , exe.str().c_str() , argv ) ; int rc = ::_spawnv( mode , exe.str().c_str() , argv ) ;
delete [] argv ;
if( pipe_result_p != NULL )
*pipe_result_p = pipe.read() ;
return rc < 0 ? error_return : rc ; return rc < 0 ? error_return : rc ;
} }
@ -171,3 +237,19 @@ std::string G::Process::Identity::str() const
return "0/0" ; return "0/0" ;
} }
// ===
G::Process::Umask::Umask( G::Process::Umask::Mode ) :
m_imp(0)
{
}
G::Process::Umask::~Umask()
{
}
void G::Process::Umask::set( G::Process::Umask::Mode )
{
// not implemented
}

168
src/glib/gregistry.h Normal file
View File

@ -0,0 +1,168 @@
//
// Copyright (C) 2001-2002 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.
//
// ===
//
// gregistry.h
//
#ifndef G_REGISTRY_H
#define G_REGISTRY_H
#include "gdef.h"
#include "gexception.h"
#include <string>
namespace G
{
class RegistryKey ;
class RegistryKeyImp ;
class RegistryValue ;
}
// Class: G::RegistryKey
// Description: Used to navigate the system registry. Works with
// the G::RegistryValue class to get and set values.
// See also: G::RegistryValue
//
class G::RegistryKey
{
public:
G_EXCEPTION( InvalidHandle , "registry handle error" ) ;
G_EXCEPTION( RemoveError , "registry removal error" ) ;
G_EXCEPTION( Error , "registry error" ) ;
struct NoThrow // Overload discriminator for G::RegistryKey.
{} ;
static RegistryKey currentUser() ;
// Returns a key for the current-user "hive".
static RegistryKey localMachine() ;
// Returns a key for the local-machine "hive".
static RegistryKey classes() ;
// Returns a key for the classes-root "hive".
~RegistryKey() ;
// Destructor.
RegistryKey create( std::string sub_path , bool & created ) const ;
// Opens or creates a sub-key.
RegistryKey create( const std::string & sub_path ) const ;
// Opens or creates a sub-key.
RegistryKey open( const std::string & sub_path ) const ;
// Opens an existing sub-key. Throws if non-existant.
RegistryKey open( const std::string & sub_path , const NoThrow & ) const ;
// Opens an existing sub-key. Returns
// an invalid key on error (eg. if non-existant).
bool valid() const ;
// Returns true if a valid key.
// (Invalid keys are only created
// by the NoThrow overload of
// open().)
RegistryKey( const RegistryKey & ) ;
// Copy ctor.
void operator=( const RegistryKey & ) ;
// Assignment operator.
void remove( const std::string & sub_path ) const ;
// Removes the named sub-key.
// Throws on error.
void remove( const std::string & sub_path , const NoThrow & ) const ;
// Removes the named sub-key.
// Ignores errors.
const RegistryKeyImp & imp() const ;
// Used by RegistryValue.
private:
typedef RegistryKeyImp Imp ;
RegistryKey( const Imp & , bool ) ;
void down() ;
RegistryKey open( std::string , bool ) const ;
void remove( const std::string & , bool ) const ;
private:
Imp * m_imp ;
bool m_is_root ;
} ;
// Class: G::RegistryValue
// Description: Works with G::RegistryKey to get and set
// registry values.
// See also: G::RegistryKey
//
class G::RegistryValue
{
public:
G_EXCEPTION( InvalidHandle , "registry handle error" ) ;
G_EXCEPTION( ValueError , "registry value error" ) ;
G_EXCEPTION( InvalidType , "registry type error" ) ;
G_EXCEPTION( MissingValue , "missing registry value" ) ;
explicit RegistryValue( const RegistryKey & hkey ,
const std::string & name = std::string() ) ;
// Constructor.
std::string getString() const ;
// Returns a string value. Throws if the value
// does not exist, or if it is not a string type.
std::string getString( const std::string & defolt ) const ;
// Returns a string. Returns the supplied default
// value if it does not exist.
bool getBool() const ;
// Returns a boolean value. Throws if the value
// does not exist.
g_uint32_t getDword() const ;
// Returns an unsigned 32-bit value. Throws if the value
// does not exist.
void set( const std::string & ) ;
// Stores a string value.
void set( const char * ) ;
// Stores a string value.
void set( bool ) ;
// Stores a boolean value.
void set( g_uint32_t ) ;
// Stores an unsigned 32-bit value.
private:
std::string getString( const std::string & defolt , bool ) const ;
std::pair<g_uint32_t,size_t> getInfo() const ;
std::string getData( g_uint32_t & type , bool & ) const ;
size_t get( char * , size_t ) const ;
private:
const RegistryKey & m_hkey ;
std::string m_key_name ;
} ;
#endif

View File

@ -0,0 +1,347 @@
//
// Copyright (C) 2001-2002 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.
//
// ===
//
// gregistry_win32.cpp
//
#include "gdef.h"
#include "gregistry.h"
#include "gstr.h"
#include "gpath.h"
#include "gdebug.h"
#include "gassert.h"
#include "glog.h"
#include <sstream>
class G::RegistryKeyImp
{
public:
HKEY m_key ;
unsigned long m_ref_count ;
explicit RegistryKeyImp( HKEY k ) : m_key(k) , m_ref_count(1UL) {}
} ;
// ===
G::RegistryKey::RegistryKey( const Imp & imp , bool is_root ) :
m_imp( new Imp(imp) ) ,
m_is_root(is_root)
{
m_imp->m_ref_count = 1UL ;
}
G::RegistryKey::RegistryKey( const RegistryKey & other ) :
m_imp( other.m_imp ) ,
m_is_root( other.m_is_root )
{
m_imp->m_ref_count++ ;
}
bool G::RegistryKey::valid() const
{
return m_imp->m_key != 0 ;
}
void G::RegistryKey::operator=( const RegistryKey & other )
{
down() ;
m_imp = other.m_imp ;
m_imp->m_ref_count++ ;
}
const G::RegistryKeyImp & G::RegistryKey::imp() const
{
return *m_imp ;
}
G::RegistryKey::~RegistryKey()
{
down() ;
}
void G::RegistryKey::down()
{
m_imp->m_ref_count-- ;
if( m_imp->m_ref_count == 0U && !m_is_root && m_imp->m_key != 0 )
{
G_DEBUG( "G::RegistryKey::down: closing " << m_imp->m_key ) ;
::RegCloseKey( m_imp->m_key ) ;
delete m_imp ;
m_imp = NULL ;
}
}
G::RegistryKey G::RegistryKey::create( const std::string & path ) const
{
bool is_new = false ;
return create( path , is_new ) ;
}
G::RegistryKey G::RegistryKey::create( std::string path , bool & is_new ) const
{
if( !valid() ) throw InvalidHandle() ;
G::Str::replaceAll( path , "/" , "\\" ) ;
is_new = false ;
HKEY new_key = 0 ;
DWORD disposition = 0 ;
LONG rc = ::RegCreateKeyEx( m_imp->m_key , path.c_str() , 0 ,
NULL , // ???
REG_OPTION_NON_VOLATILE ,
KEY_ALL_ACCESS , NULL ,
&new_key ,
&disposition ) ;
if( rc != ERROR_SUCCESS )
{
if( new_key != 0 )
::RegCloseKey(new_key) ;
G_DEBUG( "G::RegistryKey::create: failed to create \"" << path << "\"" ) ;
throw Error( path ) ;
}
is_new = disposition == REG_CREATED_NEW_KEY ;
G_DEBUG( "G::RegistryKey::create: " << new_key << ": \"" << path << "\"" << (is_new?" [created]":"") ) ;
return RegistryKey( Imp(new_key) , false ) ;
}
G::RegistryKey G::RegistryKey::open( const std::string & path , const NoThrow & ) const
{
return open( path , false ) ;
}
G::RegistryKey G::RegistryKey::open( const std::string & path ) const
{
return open( path , true ) ;
}
G::RegistryKey G::RegistryKey::open( std::string path , bool do_throw ) const
{
if( !valid() )
{
if( do_throw )
throw InvalidHandle() ;
G_DEBUG( "G::RegistryKey::open: failed to open \"" << path << "\"" ) ;
return RegistryKey( Imp(0) , false ) ;
}
else
{
G::Str::replaceAll( path , "/" , "\\" ) ;
HKEY new_key = 0 ;
LONG rc = ::RegOpenKeyEx( m_imp->m_key , path.c_str() , 0 ,
KEY_ALL_ACCESS , &new_key ) ;
G_ASSERT( (rc == ERROR_SUCCESS) == (new_key != 0) ) ;
if( rc == ERROR_SUCCESS )
{
G_DEBUG( "G::RegistryKey::open: " << new_key << ": \"" << path << "\"" ) ;
}
else
{
if( new_key != 0 ) ::RegCloseKey(new_key) ;
if( do_throw ) throw Error( path ) ;
new_key = 0 ;
G_DEBUG( "G::RegistryKey::open: failed to open \"" << path << "\"" ) ;
}
return RegistryKey( Imp(new_key) , false ) ;
}
}
void G::RegistryKey::remove( const std::string & sub_key , const NoThrow & ) const
{
remove( sub_key , false ) ;
}
void G::RegistryKey::remove( const std::string & sub_key ) const
{
remove( sub_key , true ) ;
}
void G::RegistryKey::remove( const std::string & sub_key , bool do_throw ) const
{
if( !valid() )
{
if( do_throw )
throw InvalidHandle() ;
G_DEBUG( "G::RegistryKey::remove: failed to remove \"" << sub_key << "\"" ) ;
}
else
{
LONG rc = ::RegDeleteKey( m_imp->m_key , sub_key.c_str() ) ;
if( rc == ERROR_SUCCESS )
{
G_DEBUG( "G::RegistryKey::remove: removed \"" << sub_key << "\"" ) ;
}
else
{
if( do_throw )
throw RemoveError( sub_key ) ;
G_DEBUG( "G::RegistryKey::remove: failed to remove \"" << sub_key << "\"" ) ;
}
}
}
G::RegistryKey G::RegistryKey::currentUser()
{
return RegistryKey( Imp(HKEY_CURRENT_USER) , true ) ;
}
G::RegistryKey G::RegistryKey::localMachine()
{
return RegistryKey( Imp(HKEY_LOCAL_MACHINE) , true ) ;
}
G::RegistryKey G::RegistryKey::classes()
{
return RegistryKey( Imp(HKEY_CLASSES_ROOT) , true ) ;
}
// ===
G::RegistryValue::RegistryValue( const RegistryKey & hkey ,
const std::string & key_name ) :
m_hkey(hkey) ,
m_key_name(key_name)
{
if( ! hkey.valid() )
throw InvalidHandle( key_name ) ;
}
std::string G::RegistryValue::getString( const std::string & defolt ) const
{
return getString( defolt , false ) ;
}
std::string G::RegistryValue::getString() const
{
return getString( std::string() , true ) ;
}
std::string G::RegistryValue::getString( const std::string & defolt ,
bool do_throw ) const
{
DWORD type = 0 ;
bool exists = true ;
std::string result = getData( type , exists ) ;
if( !exists && do_throw )
{
throw MissingValue( m_key_name ) ;
}
else if( !exists )
{
return defolt ;
}
else if( type != REG_SZ && type != REG_EXPAND_SZ )
{
throw InvalidType( m_key_name ) ;
}
else
{
G::Str::trimRight( result , std::string(1U,'\0') ) ;
return result ;
}
}
std::string G::RegistryValue::getData( g_uint32_t & type , bool & exists ) const
{
exists = true ;
std::pair<DWORD,size_t> info = getInfo() ;
if( info.second == 0U )
{
exists = false ;
return std::string() ;
}
type = info.first ;
size_t buffer_size = info.second + 1U ;
char * buffer = new char [buffer_size] ;
try
{
buffer_size = get( buffer , buffer_size ) ;
}
catch(...)
{
delete [] buffer ;
throw ;
}
std::string result( buffer , buffer_size ) ;
delete [] buffer ;
return result ;
}
size_t G::RegistryValue::get( char * buffer , size_t buffer_size ) const
{
DWORD type = 0 ;
unsigned long size = buffer_size ;
LONG rc = ::RegQueryValueEx( m_hkey.imp().m_key , m_key_name.c_str() , 0 ,
&type , reinterpret_cast<unsigned char*>(buffer) , &size ) ;
if( rc != ERROR_SUCCESS )
{
std::ostringstream ss ;
ss << "get: RegQueryValueEx(" << m_key_name << "): " << rc ;
throw ValueError( ss.str() ) ;
}
return static_cast<size_t>(size) ;
}
std::pair<g_uint32_t,size_t> G::RegistryValue::getInfo() const
{
std::pair<DWORD,size_t> result( 0 , 0 ) ;
unsigned long size = 0 ;
LONG rc = ::RegQueryValueEx( m_hkey.imp().m_key , m_key_name.c_str() , 0 ,
&result.first , NULL , &size ) ;
if( rc != ERROR_SUCCESS && rc != ERROR_FILE_NOT_FOUND )
{
std::ostringstream ss ;
ss << "RegQueryValueEx(\"" << m_key_name << "\"): " << rc ;
throw ValueError( ss.str() ) ;
}
if( rc == ERROR_FILE_NOT_FOUND )
size = 0 ; // just in case
result.second = static_cast<size_t>(size) ;
return result ;
}
void G::RegistryValue::set( const char * p )
{
set( std::string(p?p:"") ) ;
}
void G::RegistryValue::set( const std::string & s )
{
DWORD type = REG_SZ ;
LONG rc = ::RegSetValueEx( m_hkey.imp().m_key , m_key_name.c_str() , 0 ,
type , reinterpret_cast<const BYTE*>(s.c_str()) ,
s.length() + 1U ) ;
if( rc != ERROR_SUCCESS )
throw ValueError( "RegSetValueEx" ) ;
}

View File

@ -31,7 +31,7 @@
namespace G namespace G
{ {
class Root ; class Root ;
} ; }
// Class: G::Root // Class: G::Root
// Description: A class which aquires special privileges. // Description: A class which aquires special privileges.

View File

@ -18,16 +18,49 @@
// //
// === // ===
// //
// gevent_win32.cpp // gsetter.h
// //
#include "gdef.h" #ifndef G_SETTER_H
#include "gnet.h" #define G_SETTER_H
#include "geventloop.h"
#include "gwinsock.h"
GNet::EventLoop * GNet::EventLoop::create() #include "gdef.h"
#include "gnoncopyable.h"
namespace G
{ {
return new Winsock ; class Setter ;
} }
// Class: G::Setter
// Description: A class to Manage a boolean flag
// while in scope.
//
class G::Setter : public G:: noncopyable
{
public:
explicit Setter( bool & b ) ;
// Constructor. Sets the flag.
~Setter() ;
// Destructor. Resets the flag.
private:
bool & m_b ;
} ;
inline
G::Setter::Setter( bool & b ) :
m_b(b)
{
m_b = true ;
}
inline
G::Setter::~Setter()
{
m_b = false ;
}
#endif

View File

@ -143,7 +143,7 @@ public:
// Sets the current state. Returns the old state. // Sets the current state. Returns the old state.
private: private:
struct Transition struct Transition // A private structure used by G::StateMachine<>.
{ {
State from ; State from ;
State to ; State to ;
@ -216,7 +216,7 @@ State StateMachine<T,State,Event,Arg>::apply( T & t , Event event , const Arg &
// look up in the multimap keyed on current-state + event // look up in the multimap keyed on current-state + event
// //
State state = m_state ; State state = m_state ;
Map::iterator p = m_map.find(event) ; typename Map::iterator p = m_map.find(event) ;
for( ; p != m_map.end() && (*p).first == event ; ++p ) for( ; p != m_map.end() && (*p).first == event ; ++p )
{ {
if( (*p).second.from == m_any || (*p).second.from == m_state ) if( (*p).second.from == m_any || (*p).second.from == m_state )
@ -248,7 +248,7 @@ State StateMachine<T,State,Event,Arg>::apply( T & t , Event event , const Arg &
return m_any ; return m_any ;
} }
} ; // namespace } // namespace
#endif #endif

View File

@ -30,7 +30,6 @@
#include <climits> #include <climits>
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <xlocale>
bool G::Str::replace( std::string &s , const std::string &from , bool G::Str::replace( std::string &s , const std::string &from ,
const std::string &to , size_t *pos_p ) const std::string &to , size_t *pos_p )
@ -214,16 +213,23 @@ unsigned short G::Str::toUShort( const std::string &s , bool limited )
return ushort_val ; return ushort_val ;
} }
std::string G::Str::fromInt( int i )
{
std::ostringstream ss ;
ss << i ;
return ss.str() ;
}
std::string G::Str::fromUInt( unsigned int n ) std::string G::Str::fromUInt( unsigned int n )
{ {
std::stringstream ss ; std::ostringstream ss ;
ss << n ; ss << n ;
return ss.str() ; return ss.str() ;
} }
std::string G::Str::fromULong( unsigned long ul ) std::string G::Str::fromULong( unsigned long ul )
{ {
std::stringstream ss ; std::ostringstream ss ;
ss << ul ; ss << ul ;
return ss.str() ; return ss.str() ;
} }
@ -236,6 +242,13 @@ void G::Str::toLower( std::string &s )
} }
} }
std::string G::Str::lower( const std::string &s )
{
std::string result = s ;
toLower( result ) ;
return result ;
}
void G::Str::toUpper( std::string &s ) void G::Str::toUpper( std::string &s )
{ {
for( std::string::iterator p = s.begin() ; p != s.end() ; ++p ) for( std::string::iterator p = s.begin() ; p != s.end() ; ++p )
@ -244,6 +257,13 @@ void G::Str::toUpper( std::string &s )
} }
} }
std::string G::Str::upper( const std::string &s )
{
std::string result = s ;
toUpper( result ) ;
return result ;
}
std::string G::Str::toPrintableAscii( char c , char escape ) std::string G::Str::toPrintableAscii( char c , char escape )
{ {
if( c == escape ) if( c == escape )
@ -334,7 +354,7 @@ std::string G::Str::wrap( std::string text , const std::string & prefix_1 ,
const std::string & prefix_2 , size_t width ) const std::string & prefix_2 , size_t width )
{ {
std::string ws( " \t\n" ) ; std::string ws( " \t\n" ) ;
std::stringstream ss ; std::ostringstream ss ;
for( bool first_line = true ; text.length() ; first_line = false ) for( bool first_line = true ; text.length() ; first_line = false )
{ {
const size_t prefix_length = const size_t prefix_length =

View File

@ -119,6 +119,9 @@ public:
// Exception: Overflow // Exception: Overflow
// Exception: InvalidFormat // Exception: InvalidFormat
static std::string fromInt( int i ) ;
// Converts int 'i' to a string.
static std::string fromUInt( unsigned int ) ; static std::string fromUInt( unsigned int ) ;
// Converts from unsigned int to a decimal string. // Converts from unsigned int to a decimal string.
@ -133,6 +136,14 @@ public:
// Replaces all uppercase characters in string 's' by // Replaces all uppercase characters in string 's' by
// lowercase characters. // lowercase characters.
static std::string upper( const std::string &s ) ;
// Returns a copy of 's' in which all lowercase characters
// have been replaced by uppercase characters.
static std::string lower( const std::string &s ) ;
// Returns a copy of 's' in which all uppercase characters
// have been replaced by lowercase characters.
static std::string toPrintableAscii( char c , char escape = '\\' ) ; static std::string toPrintableAscii( char c , char escape = '\\' ) ;
// Returns a printable, 7-bit-ascii string representing the given // Returns a printable, 7-bit-ascii string representing the given
// character. Typical return values include "\\", "\n", // character. Typical return values include "\\", "\n",

View File

@ -36,7 +36,7 @@ namespace G
// //
typedef std::list<std::string GAllocator(std::string) > Strings ; typedef std::list<std::string GAllocator(std::string) > Strings ;
} ; }
#endif #endif

View File

@ -83,7 +83,7 @@ unsigned int G::Time::seconds() const
std::string G::Time::hhmmss( const char * sep ) std::string G::Time::hhmmss( const char * sep )
{ {
if( sep == NULL ) sep = "" ; if( sep == NULL ) sep = "" ;
std::stringstream ss ; std::ostringstream ss ;
ss << (m_hh/10U) << (m_hh%10U) << sep << (m_mm/10U) << (m_mm%10U) << sep << (m_ss/10U) << (m_ss%10U) ; ss << (m_hh/10U) << (m_hh%10U) << sep << (m_mm/10U) << (m_mm%10U) << sep << (m_ss/10U) << (m_ss%10U) ;
return ss.str() ; return ss.str() ;
} }
@ -91,7 +91,7 @@ std::string G::Time::hhmmss( const char * sep )
std::string G::Time::hhmm( const char * sep ) std::string G::Time::hhmm( const char * sep )
{ {
if( sep == NULL ) sep = "" ; if( sep == NULL ) sep = "" ;
std::stringstream ss ; std::ostringstream ss ;
ss << (m_hh/10U) << (m_hh%10U) << sep << (m_mm/10U) << (m_mm%10U) ; ss << (m_hh/10U) << (m_hh%10U) << sep << (m_mm/10U) << (m_mm%10U) ;
return ss.str() ; return ss.str() ;
} }

View File

@ -32,7 +32,7 @@
namespace G namespace G
{ {
class Time ; class Time ;
} ; }
// Class: G::Time // Class: G::Time
// Description: A simple time-of-day (hh/mm/ss) class. // Description: A simple time-of-day (hh/mm/ss) class.

View File

@ -17,15 +17,15 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# #
EXTRA_DIST=gclient_win32.cpp \ EXTRA_DIST=\
gclient_win32.cpp \
gdescriptor_win32.cpp \ gdescriptor_win32.cpp \
gevent_win32.cpp \ geventloop_win32.cpp \
glocal_win32.cpp \ glocal_win32.cpp \
grequest.cpp \ grequest.cpp \
gresolve_win32.cpp \ gresolve_win32.cpp \
gsocket_win32.cpp \ gsocket_win32.cpp
gwinsock.cpp INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib
INCLUDES = -I$(top_srcdir)/lib/gcc2.95 -I$(top_srcdir)/src/glib
noinst_LIBRARIES = libgnet.a noinst_LIBRARIES = libgnet.a
libgnet_a_SOURCES = gaddress_ipv4.cpp \ libgnet_a_SOURCES = gaddress_ipv4.cpp \
gclient.cpp \ gclient.cpp \
@ -33,8 +33,8 @@ libgnet_a_SOURCES = gaddress_ipv4.cpp \
gconnection.cpp \ gconnection.cpp \
gdescriptor_unix.cpp \ gdescriptor_unix.cpp \
geventloop.cpp \ geventloop.cpp \
geventloop_unix.cpp \
geventhandler.cpp \ geventhandler.cpp \
gevent_unix.cpp \
geventserver.cpp \ geventserver.cpp \
glinebuffer.cpp \ glinebuffer.cpp \
glocal_unix.cpp \ glocal_unix.cpp \
@ -43,7 +43,6 @@ libgnet_a_SOURCES = gaddress_ipv4.cpp \
gresolve.cpp \ gresolve.cpp \
gresolve_ipv4.cpp \ gresolve_ipv4.cpp \
gresolve_unix.cpp \ gresolve_unix.cpp \
gselect.cpp \
gserver.cpp \ gserver.cpp \
gsocket.cpp \ gsocket.cpp \
gsocket_unix.cpp \ gsocket_unix.cpp \
@ -62,8 +61,6 @@ libgnet_a_SOURCES = gaddress_ipv4.cpp \
gnet.h \ gnet.h \
grequest.h \ grequest.h \
gresolve.h \ gresolve.h \
gselect.h \
gserver.h \ gserver.h \
gsocket.h \ gsocket.h \
gtimer.h \ gtimer.h
gwinsock.h

View File

@ -79,6 +79,7 @@ POST_UNINSTALL = :
AR = @AR@ AR = @AR@
AWK = @AWK@ AWK = @AWK@
CC = @CC@ CC = @CC@
COMPILER_VERSION = @COMPILER_VERSION@
CXX = @CXX@ CXX = @CXX@
GZIP = @GZIP@ GZIP = @GZIP@
HAVE_DOXYGEN = @HAVE_DOXYGEN@ HAVE_DOXYGEN = @HAVE_DOXYGEN@
@ -96,11 +97,11 @@ e_man1dir = @e_man1dir@
e_sbindir = @e_sbindir@ e_sbindir = @e_sbindir@
e_spooldir = @e_spooldir@ e_spooldir = @e_spooldir@
EXTRA_DIST = gclient_win32.cpp gdescriptor_win32.cpp gevent_win32.cpp glocal_win32.cpp grequest.cpp gresolve_win32.cpp gsocket_win32.cpp gwinsock.cpp EXTRA_DIST = gclient_win32.cpp gdescriptor_win32.cpp geventloop_win32.cpp glocal_win32.cpp grequest.cpp gresolve_win32.cpp gsocket_win32.cpp
INCLUDES = -I$(top_srcdir)/lib/gcc2.95 -I$(top_srcdir)/src/glib INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib
noinst_LIBRARIES = libgnet.a noinst_LIBRARIES = libgnet.a
libgnet_a_SOURCES = gaddress_ipv4.cpp gclient.cpp gclient_unix.cpp gconnection.cpp gdescriptor_unix.cpp geventloop.cpp geventhandler.cpp gevent_unix.cpp geventserver.cpp glinebuffer.cpp glocal_unix.cpp glocal.cpp gmonitor.cpp gresolve.cpp gresolve_ipv4.cpp gresolve_unix.cpp gselect.cpp gserver.cpp gsocket.cpp gsocket_unix.cpp gtimer.cpp gaddress.h gclient.h gconnection.h gdescriptor.h gevent.h geventloop.h geventhandler.h geventserver.h glinebuffer.h glocal.h gmonitor.h gnet.h grequest.h gresolve.h gselect.h gserver.h gsocket.h gtimer.h gwinsock.h libgnet_a_SOURCES = gaddress_ipv4.cpp gclient.cpp gclient_unix.cpp gconnection.cpp gdescriptor_unix.cpp geventloop.cpp geventloop_unix.cpp geventhandler.cpp geventserver.cpp glinebuffer.cpp glocal_unix.cpp glocal.cpp gmonitor.cpp gresolve.cpp gresolve_ipv4.cpp gresolve_unix.cpp gserver.cpp gsocket.cpp gsocket_unix.cpp gtimer.cpp gaddress.h gclient.h gconnection.h gdescriptor.h gevent.h geventloop.h geventhandler.h geventserver.h glinebuffer.h glocal.h gmonitor.h gnet.h grequest.h gresolve.h gserver.h gsocket.h gtimer.h
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../../config.h CONFIG_HEADER = ../../config.h
@ -114,10 +115,10 @@ LDFLAGS = @LDFLAGS@
LIBS = @LIBS@ LIBS = @LIBS@
libgnet_a_LIBADD = libgnet_a_LIBADD =
libgnet_a_OBJECTS = gaddress_ipv4.o gclient.o gclient_unix.o \ libgnet_a_OBJECTS = gaddress_ipv4.o gclient.o gclient_unix.o \
gconnection.o gdescriptor_unix.o geventloop.o geventhandler.o \ gconnection.o gdescriptor_unix.o geventloop.o geventloop_unix.o \
gevent_unix.o geventserver.o glinebuffer.o glocal_unix.o glocal.o \ geventhandler.o geventserver.o glinebuffer.o glocal_unix.o glocal.o \
gmonitor.o gresolve.o gresolve_ipv4.o gresolve_unix.o gselect.o \ gmonitor.o gresolve.o gresolve_ipv4.o gresolve_unix.o gserver.o \
gserver.o gsocket.o gsocket_unix.o gtimer.o gsocket.o gsocket_unix.o gtimer.o
CXXFLAGS = @CXXFLAGS@ CXXFLAGS = @CXXFLAGS@
CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX) CXXLD = $(CXX)
@ -228,160 +229,139 @@ distdir: $(DISTFILES)
done done
gaddress_ipv4.o: gaddress_ipv4.cpp ../../src/glib/gdef.h ../../config.h \ gaddress_ipv4.o: gaddress_ipv4.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ ../../lib/gcc2.95/limits gnet.h gaddress.h \
gaddress.h ../../src/glib/gexception.h \ ../../src/glib/gexception.h ../../src/glib/gconvert.h \
../../src/glib/gconvert.h ../../src/glib/gstrings.h \ ../../src/glib/gstrings.h ../../src/glib/gstr.h \
../../src/glib/gstr.h ../../src/glib/gassert.h \ ../../src/glib/gassert.h ../../src/glib/glogoutput.h \
../../src/glib/glogoutput.h ../../src/glib/glog.h \ ../../src/glib/glog.h ../../src/glib/gdebug.h
../../src/glib/gdebug.h
gclient.o: gclient.cpp ../../src/glib/gdef.h ../../config.h \ gclient.o: gclient.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ ../../lib/gcc2.95/limits gnet.h gaddress.h \
gaddress.h ../../src/glib/gexception.h gsocket.h gevent.h \ ../../src/glib/gexception.h gsocket.h gevent.h geventloop.h \
geventloop.h geventhandler.h ../../src/glib/gcredentials.h \ geventhandler.h ../../src/glib/gdatetime.h gdescriptor.h \
../../src/glib/gdatetime.h gdescriptor.h gresolve.h \ gresolve.h ../../src/glib/groot.h ../../src/glib/gprocess.h \
../../src/glib/groot.h ../../src/glib/gprocess.h \
../../src/glib/gpath.h ../../src/glib/gstrings.h \ ../../src/glib/gpath.h ../../src/glib/gstrings.h \
../../src/glib/gnoncopyable.h gmonitor.h gclient.h \ ../../src/glib/gnoncopyable.h gmonitor.h gclient.h \
gconnection.h gserver.h gselect.h ../../src/glib/gdebug.h \ gconnection.h gserver.h ../../src/glib/gdebug.h \
../../src/glib/glogoutput.h ../../src/glib/glog.h \ ../../src/glib/glogoutput.h ../../src/glib/glog.h \
../../src/glib/gassert.h ../../src/glib/gassert.h
gclient_unix.o: gclient_unix.cpp ../../src/glib/gdef.h ../../config.h \ gclient_unix.o: gclient_unix.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ ../../lib/gcc2.95/limits gnet.h gclient.h gaddress.h \
gclient.h gaddress.h ../../src/glib/gexception.h gconnection.h \ ../../src/glib/gexception.h gconnection.h gsocket.h gevent.h \
gsocket.h gevent.h geventloop.h geventhandler.h \ geventloop.h geventhandler.h ../../src/glib/gdatetime.h \
../../src/glib/gcredentials.h ../../src/glib/gdatetime.h \
gdescriptor.h gdescriptor.h
gconnection.o: gconnection.cpp ../../src/glib/gdef.h ../../config.h \ gconnection.o: gconnection.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ ../../lib/gcc2.95/limits gnet.h gconnection.h gaddress.h \
gconnection.h gaddress.h ../../src/glib/gexception.h ../../src/glib/gexception.h
gdescriptor_unix.o: gdescriptor_unix.cpp ../../src/glib/gdef.h \ gdescriptor_unix.o: gdescriptor_unix.cpp ../../src/glib/gdef.h \
../../config.h ../../lib/gcc2.95/iostream \ ../../config.h ../../lib/gcc2.95/iostream \
../../lib/gcc2.95/sstream ../../lib/gcc2.95/xlocale \ ../../lib/gcc2.95/sstream ../../lib/gcc2.95/limits gnet.h \
../../lib/gcc2.95/limits gnet.h gdescriptor.h gdescriptor.h
gevent_unix.o: gevent_unix.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \
geventloop.h geventhandler.h ../../src/glib/gcredentials.h \
../../src/glib/gdatetime.h ../../src/glib/gexception.h \
gdescriptor.h gselect.h gevent.h
geventhandler.o: geventhandler.cpp ../../src/glib/gdef.h ../../config.h \ geventhandler.o: geventhandler.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ ../../lib/gcc2.95/limits gnet.h geventhandler.h \
geventhandler.h ../../src/glib/gcredentials.h \
../../src/glib/gdatetime.h ../../src/glib/gexception.h \ ../../src/glib/gdatetime.h ../../src/glib/gexception.h \
gdescriptor.h geventloop.h ../../src/glib/gdebug.h \ gdescriptor.h geventloop.h ../../src/glib/gdebug.h \
../../src/glib/glogoutput.h ../../src/glib/glog.h \ ../../src/glib/glogoutput.h ../../src/glib/glog.h \
../../src/glib/gassert.h ../../src/glib/gassert.h
geventloop.o: geventloop.cpp ../../src/glib/gdef.h ../../config.h \ geventloop.o: geventloop.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ ../../lib/gcc2.95/limits gnet.h geventloop.h geventhandler.h \
geventloop.h geventhandler.h ../../src/glib/gcredentials.h \
../../src/glib/gdatetime.h ../../src/glib/gexception.h \ ../../src/glib/gdatetime.h ../../src/glib/gexception.h \
gdescriptor.h ../../src/glib/gdebug.h \ gdescriptor.h ../../src/glib/gdebug.h \
../../src/glib/glogoutput.h ../../src/glib/glog.h \ ../../src/glib/glogoutput.h ../../src/glib/glog.h \
../../src/glib/gassert.h ../../src/glib/gassert.h
geventloop_unix.o: geventloop_unix.cpp ../../src/glib/gdef.h \
../../config.h ../../lib/gcc2.95/iostream \
../../lib/gcc2.95/sstream ../../lib/gcc2.95/limits gnet.h \
../../src/glib/gnoncopyable.h gevent.h geventloop.h \
geventhandler.h ../../src/glib/gdatetime.h \
../../src/glib/gexception.h gdescriptor.h ../../src/glib/gstr.h \
../../src/glib/gstrings.h ../../src/glib/gsetter.h gtimer.h \
../../src/glib/gdebug.h ../../src/glib/glogoutput.h \
../../src/glib/glog.h ../../src/glib/gassert.h
geventserver.o: geventserver.cpp ../../src/glib/gdef.h ../../config.h \ geventserver.o: geventserver.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ ../../lib/gcc2.95/limits gnet.h geventserver.h gserver.h \
geventserver.h gserver.h gsocket.h gaddress.h \ gsocket.h gaddress.h ../../src/glib/gexception.h gevent.h \
../../src/glib/gexception.h gevent.h geventloop.h \ geventloop.h geventhandler.h ../../src/glib/gdatetime.h \
geventhandler.h ../../src/glib/gcredentials.h \ gdescriptor.h gconnection.h ../../src/glib/glog.h
../../src/glib/gdatetime.h gdescriptor.h gconnection.h \
gselect.h ../../src/glib/glog.h
glinebuffer.o: glinebuffer.cpp ../../src/glib/gdef.h ../../config.h \ glinebuffer.o: glinebuffer.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ ../../lib/gcc2.95/limits gnet.h glinebuffer.h \
glinebuffer.h ../../src/glib/gstrings.h ../../src/glib/gdebug.h \ ../../src/glib/gstrings.h ../../src/glib/gdebug.h \
../../src/glib/glogoutput.h ../../src/glib/glog.h \ ../../src/glib/glogoutput.h ../../src/glib/glog.h \
../../src/glib/gassert.h ../../src/glib/gassert.h
glocal.o: glocal.cpp ../../src/glib/gdef.h ../../config.h \ glocal.o: glocal.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits glocal.h \ ../../lib/gcc2.95/limits glocal.h gnet.h gaddress.h \
gnet.h gaddress.h ../../src/glib/gexception.h \ ../../src/glib/gexception.h ../../src/glib/gdebug.h \
../../src/glib/gdebug.h ../../src/glib/glogoutput.h \ ../../src/glib/glogoutput.h ../../src/glib/glog.h \
../../src/glib/glog.h ../../src/glib/gassert.h ../../src/glib/gassert.h
glocal_unix.o: glocal_unix.cpp ../../src/glib/gdef.h ../../config.h \ glocal_unix.o: glocal_unix.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits glocal.h \ ../../lib/gcc2.95/limits glocal.h gnet.h gaddress.h \
gnet.h gaddress.h ../../src/glib/gexception.h gresolve.h \ ../../src/glib/gexception.h gresolve.h ../../src/glib/glog.h
../../src/glib/glog.h
gmonitor.o: gmonitor.cpp ../../src/glib/gdef.h ../../config.h \ gmonitor.o: gmonitor.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ ../../lib/gcc2.95/limits gnet.h gmonitor.h \
gmonitor.h gclient.h gaddress.h ../../src/glib/gexception.h \ ../../src/glib/gnoncopyable.h gclient.h gaddress.h \
gconnection.h gsocket.h gevent.h geventloop.h geventhandler.h \ ../../src/glib/gexception.h gconnection.h gsocket.h gevent.h \
../../src/glib/gcredentials.h ../../src/glib/gdatetime.h \ geventloop.h geventhandler.h ../../src/glib/gdatetime.h \
gdescriptor.h gserver.h gselect.h ../../src/glib/gassert.h \ gdescriptor.h gserver.h ../../src/glib/gassert.h \
../../src/glib/glogoutput.h ../../src/glib/glog.h ../../src/glib/glogoutput.h ../../src/glib/glog.h
gresolve.o: gresolve.cpp ../../src/glib/gdef.h ../../config.h \ gresolve.o: gresolve.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gresolve.h \ ../../lib/gcc2.95/limits gresolve.h gnet.h gaddress.h \
gnet.h gaddress.h ../../src/glib/gexception.h gsocket.h \ ../../src/glib/gexception.h gsocket.h gevent.h geventloop.h \
gevent.h geventloop.h geventhandler.h \ geventhandler.h ../../src/glib/gdatetime.h gdescriptor.h \
../../src/glib/gcredentials.h ../../src/glib/gdatetime.h \ ../../src/glib/gstr.h ../../src/glib/gstrings.h \
gdescriptor.h ../../src/glib/gstr.h ../../src/glib/gstrings.h \
../../src/glib/gdebug.h ../../src/glib/glogoutput.h \ ../../src/glib/gdebug.h ../../src/glib/glogoutput.h \
../../src/glib/glog.h ../../src/glib/gassert.h ../../src/glib/glog.h ../../src/glib/gassert.h
gresolve_ipv4.o: gresolve_ipv4.cpp ../../src/glib/gdef.h ../../config.h \ gresolve_ipv4.o: gresolve_ipv4.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gresolve.h \ ../../lib/gcc2.95/limits gresolve.h gnet.h gaddress.h \
gnet.h gaddress.h ../../src/glib/gexception.h ../../src/glib/gexception.h
gresolve_unix.o: gresolve_unix.cpp ../../src/glib/gdef.h ../../config.h \ gresolve_unix.o: gresolve_unix.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gresolve.h \ ../../lib/gcc2.95/limits gresolve.h gnet.h gaddress.h \
gnet.h gaddress.h ../../src/glib/gexception.h gsocket.h \ ../../src/glib/gexception.h gsocket.h gevent.h geventloop.h \
gevent.h geventloop.h geventhandler.h \ geventhandler.h ../../src/glib/gdatetime.h gdescriptor.h \
../../src/glib/gcredentials.h ../../src/glib/gdatetime.h \ ../../src/glib/gstr.h ../../src/glib/gstrings.h \
gdescriptor.h ../../src/glib/gstr.h ../../src/glib/gstrings.h \
../../src/glib/gdebug.h ../../src/glib/glogoutput.h \ ../../src/glib/gdebug.h ../../src/glib/glogoutput.h \
../../src/glib/glog.h ../../src/glib/gassert.h ../../src/glib/glog.h ../../src/glib/gassert.h
gselect.o: gselect.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gselect.h \
gnet.h gevent.h geventloop.h geventhandler.h \
../../src/glib/gcredentials.h ../../src/glib/gdatetime.h \
../../src/glib/gexception.h gdescriptor.h ../../src/glib/gstr.h \
../../src/glib/gstrings.h gtimer.h ../../src/glib/gdebug.h \
../../src/glib/glogoutput.h ../../src/glib/glog.h \
../../src/glib/gassert.h
gserver.o: gserver.cpp ../../src/glib/gdef.h ../../config.h \ gserver.o: gserver.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ ../../lib/gcc2.95/limits gnet.h gserver.h gsocket.h gaddress.h \
gserver.h gsocket.h gaddress.h ../../src/glib/gexception.h \ ../../src/glib/gexception.h gevent.h geventloop.h \
gevent.h geventloop.h geventhandler.h \ geventhandler.h ../../src/glib/gdatetime.h gdescriptor.h \
../../src/glib/gcredentials.h ../../src/glib/gdatetime.h \ gconnection.h ../../src/glib/groot.h ../../src/glib/gprocess.h \
gdescriptor.h gconnection.h gselect.h ../../src/glib/groot.h \ ../../src/glib/gpath.h ../../src/glib/gstrings.h \
../../src/glib/gprocess.h ../../src/glib/gpath.h \ ../../src/glib/gnoncopyable.h gmonitor.h gclient.h \
../../src/glib/gstrings.h ../../src/glib/gnoncopyable.h \ ../../src/glib/gdebug.h ../../src/glib/glogoutput.h \
gmonitor.h gclient.h ../../src/glib/gdebug.h \ ../../src/glib/glog.h ../../src/glib/gassert.h \
../../src/glib/glogoutput.h ../../src/glib/glog.h \ ../../src/glib/gmemory.h
../../src/glib/gassert.h ../../src/glib/gmemory.h
gsocket.o: gsocket.cpp ../../src/glib/gdef.h ../../config.h \ gsocket.o: gsocket.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ ../../lib/gcc2.95/limits gnet.h ../../src/glib/gassert.h \
../../src/glib/gassert.h ../../src/glib/glogoutput.h \ ../../src/glib/glogoutput.h ../../src/glib/glog.h gsocket.h \
../../src/glib/glog.h gsocket.h gaddress.h \ gaddress.h ../../src/glib/gexception.h gevent.h geventloop.h \
../../src/glib/gexception.h gevent.h geventloop.h \ geventhandler.h ../../src/glib/gdatetime.h gdescriptor.h \
geventhandler.h ../../src/glib/gcredentials.h \
../../src/glib/gdatetime.h gdescriptor.h \
../../src/glib/gmemory.h ../../src/glib/gdebug.h ../../src/glib/gmemory.h ../../src/glib/gdebug.h
gsocket_unix.o: gsocket_unix.cpp ../../src/glib/gdef.h ../../config.h \ gsocket_unix.o: gsocket_unix.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gnet.h \ ../../lib/gcc2.95/limits gnet.h gsocket.h gaddress.h \
gsocket.h gaddress.h ../../src/glib/gexception.h gevent.h \ ../../src/glib/gexception.h gevent.h geventloop.h \
geventloop.h geventhandler.h ../../src/glib/gcredentials.h \ geventhandler.h ../../src/glib/gdatetime.h gdescriptor.h \
../../src/glib/gdatetime.h gdescriptor.h \
../../src/glib/gdebug.h ../../src/glib/glogoutput.h \ ../../src/glib/gdebug.h ../../src/glib/glogoutput.h \
../../src/glib/glog.h ../../src/glib/gassert.h ../../src/glib/glog.h ../../src/glib/gassert.h
gtimer.o: gtimer.cpp ../../src/glib/gdef.h ../../config.h \ gtimer.o: gtimer.cpp ../../src/glib/gdef.h ../../config.h \
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \ ../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gtimer.h \ ../../lib/gcc2.95/limits gtimer.h gnet.h \
gnet.h ../../src/glib/gdatetime.h ../../src/glib/gexception.h \ ../../src/glib/gdatetime.h ../../src/glib/gexception.h gevent.h \
gevent.h geventloop.h geventhandler.h \ geventloop.h geventhandler.h gdescriptor.h \
../../src/glib/gcredentials.h gdescriptor.h \
../../src/glib/gdebug.h ../../src/glib/glogoutput.h \ ../../src/glib/gdebug.h ../../src/glib/glogoutput.h \
../../src/glib/glog.h ../../src/glib/gassert.h ../../src/glib/glog.h ../../src/glib/gassert.h

View File

@ -34,7 +34,7 @@ namespace GNet
{ {
class Address ; class Address ;
class AddressImp ; class AddressImp ;
} ; }
// Class: GNet::Address // Class: GNet::Address
// //
@ -100,6 +100,12 @@ public:
// //
// See also validString(). // See also validString().
Address( const std::string & host_or_ip , unsigned int port ) ;
// Constructor taking a host-name/ip-address and
// a port number.
//
// Throws an exception if an invalid string.
~Address() ; ~Address() ;
// Destructor. // Destructor.

View File

@ -43,6 +43,7 @@ public:
explicit AddressImp( unsigned int port ) ; // (not in_port_t -- see validPort(), setPort() etc) explicit AddressImp( unsigned int port ) ; // (not in_port_t -- see validPort(), setPort() etc)
explicit AddressImp( const servent & s ) ; explicit AddressImp( const servent & s ) ;
explicit AddressImp( const std::string & s ) ; explicit AddressImp( const std::string & s ) ;
AddressImp( const std::string & s , unsigned int port ) ;
AddressImp( unsigned int port , Address::Localhost ) ; AddressImp( unsigned int port , Address::Localhost ) ;
AddressImp( const hostent & h , unsigned int port ) ; AddressImp( const hostent & h , unsigned int port ) ;
AddressImp( const hostent & h , const servent & s ) ; AddressImp( const hostent & h , const servent & s ) ;
@ -79,6 +80,8 @@ private:
static char m_port_separator ; static char m_port_separator ;
} ; } ;
// ===
char GNet::AddressImp::m_port_separator = ':' ; char GNet::AddressImp::m_port_separator = ':' ;
void GNet::AddressImp::init() void GNet::AddressImp::init()
@ -141,12 +144,24 @@ GNet::AddressImp::AddressImp( const AddressImp & other )
m_inet = other.m_inet ; m_inet = other.m_inet ;
} }
GNet::AddressImp::AddressImp( const std::string & s , unsigned int port )
{
init() ;
std::string reason ;
if( ! setAddress( s + m_port_separator + "0" , reason ) )
throw Address::BadString( reason + ": " + s ) ;
setPort( port ) ;
}
GNet::AddressImp::AddressImp( const std::string & s ) GNet::AddressImp::AddressImp( const std::string & s )
{ {
init() ; init() ;
std::string reason ; std::string reason ;
if( ! setAddress( s , reason ) ) if( ! setAddress( s , reason ) )
throw Address::BadString( s ) ; throw Address::BadString( reason + ": " + s ) ;
} }
bool GNet::AddressImp::setAddress( const std::string & display_string , std::string & reason ) bool GNet::AddressImp::setAddress( const std::string & display_string , std::string & reason )
@ -187,7 +202,7 @@ void GNet::AddressImp::setHost( const hostent & h )
std::string GNet::AddressImp::displayString() const std::string GNet::AddressImp::displayString() const
{ {
std::stringstream ss ; std::ostringstream ss ;
ss << hostString() ; ss << hostString() ;
ss << m_port_separator << port() ; ss << m_port_separator << port() ;
return ss.str() ; return ss.str() ;
@ -195,7 +210,7 @@ std::string GNet::AddressImp::displayString() const
std::string GNet::AddressImp::hostString() const std::string GNet::AddressImp::hostString() const
{ {
std::stringstream ss ; std::ostringstream ss ;
ss << ::inet_ntoa(m_inet.sin_addr) ; ss << ::inet_ntoa(m_inet.sin_addr) ;
return ss.str() ; return ss.str() ;
} }
@ -347,7 +362,7 @@ GNet::Address::Address( const servent & s ) :
{ {
} }
GNet::Address::Address( const sockaddr *addr , int len ) : GNet::Address::Address( const sockaddr * addr , int len ) :
m_imp( new AddressImp(addr,len) ) m_imp( new AddressImp(addr,len) )
{ {
} }
@ -362,6 +377,11 @@ GNet::Address::Address( const std::string & s ) :
{ {
} }
GNet::Address::Address( const std::string & s , unsigned int port ) :
m_imp( new AddressImp(s,port) )
{
}
GNet::Address::~Address() GNet::Address::~Address()
{ {
delete m_imp ; delete m_imp ;

View File

@ -39,12 +39,12 @@ namespace
const int c_retries = 10 ; // number of retries when using a priviledged local port number const int c_retries = 10 ; // number of retries when using a priviledged local port number
const int c_port_start = 512 ; const int c_port_start = 512 ;
const int c_port_end = 1024 ; const int c_port_end = 1024 ;
} ; }
namespace GNet namespace GNet
{ {
class ClientResolver ; class ClientResolver ;
} ; }
// Class: GNet::ClientResolver // Class: GNet::ClientResolver
// Description: A resolver class which calls ClientImp::resolveCon() when done. // Description: A resolver class which calls ClientImp::resolveCon() when done.

View File

@ -36,7 +36,7 @@ namespace GNet
{ {
class Client ; class Client ;
class ClientImp ; class ClientImp ;
} ; }
// Class: GNet::Client // Class: GNet::Client
// Description: An application-level class for making an outgoing connection // Description: An application-level class for making an outgoing connection

View File

@ -31,7 +31,7 @@
namespace GNet namespace GNet
{ {
class Connection ; class Connection ;
} ; }
// Class: GNet::Connection // Class: GNet::Connection
// Description: An interface which provides address information // Description: An interface which provides address information

View File

@ -36,7 +36,7 @@ namespace GNet
Descriptor Descriptor__invalid() ; Descriptor Descriptor__invalid() ;
// Returns an invalid network descriptor. // Returns an invalid network descriptor.
} ; }
#endif #endif

View File

@ -81,7 +81,7 @@ std::string GNet::EventHandlerList::asString() const
std::string GNet::EventHandlerList::asString( const EventHandlerListImp & list ) const std::string GNet::EventHandlerList::asString( const EventHandlerListImp & list ) const
{ {
std::stringstream ss ; std::ostringstream ss ;
const char * sep = "" ; const char * sep = "" ;
for( List::const_iterator p = list.begin() ; p != list.end() ; ++p ) for( List::const_iterator p = list.begin() ; p != list.end() ; ++p )
{ {

View File

@ -26,7 +26,6 @@
#include "gdef.h" #include "gdef.h"
#include "gnet.h" #include "gnet.h"
#include "gcredentials.h"
#include "gdatetime.h" #include "gdatetime.h"
#include "gdescriptor.h" #include "gdescriptor.h"
#include <list> #include <list>
@ -38,7 +37,7 @@ namespace GNet
class EventHandlerListItem ; class EventHandlerListItem ;
class EventHandlerList ; class EventHandlerList ;
class TimerList ; class TimerList ;
} ; }
// Class: GNet::EventHandler // Class: GNet::EventHandler
// Description: A pseudo-abstract base class for classes // Description: A pseudo-abstract base class for classes
@ -99,7 +98,7 @@ namespace GNet
{ {
typedef std::list< EventHandlerListItem GAllocator(EventHandlerListItem) > typedef std::list< EventHandlerListItem GAllocator(EventHandlerListItem) >
EventHandlerListImp ; EventHandlerListImp ;
} ; }
// Class: GNet::EventHandlerList // Class: GNet::EventHandlerList
// Description: A class which can be used in the implemention // Description: A class which can be used in the implemention

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