You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by ms...@apache.org on 2004/01/08 02:13:56 UTC
svn commit: rev 6099 - in incubator/spamassassin/trunk: . spamd
Author: mss
Date: Mon Jan 5 18:36:44 2004
New Revision: 6099
Added:
incubator/spamassassin/trunk/spamd/README.Win
incubator/spamassassin/trunk/spamd/binaries.mk.win
incubator/spamassassin/trunk/spamd/config.h.win
incubator/spamassassin/trunk/spamd/getopt.c
incubator/spamassassin/trunk/spamd/getopt.h
Modified:
incubator/spamassassin/trunk/Makefile.PL
incubator/spamassassin/trunk/spamd/libspamc.c
incubator/spamassassin/trunk/spamd/libspamc.h
incubator/spamassassin/trunk/spamd/spamc.c
incubator/spamassassin/trunk/spamd/utils.c
incubator/spamassassin/trunk/spamd/utils.h
Log:
Added a modified version of Sidney's Native Windows Patch(tm). build/configure is now enabled.
Modified: incubator/spamassassin/trunk/Makefile.PL
==============================================================================
--- incubator/spamassassin/trunk/Makefile.PL (original)
+++ incubator/spamassassin/trunk/Makefile.PL Mon Jan 5 18:36:44 2004
@@ -1,3 +1,4 @@
+#!/usr/bin/perl
require 5.6.1;
use strict;
@@ -6,7 +7,7 @@
use ExtUtils::MakeMaker 5.45;
-use constant RUNNING_ON_WINDOWS => ($^O =~ /^(?:mswin|dos|os2)/oi);
+use constant RUNNING_ON_WINDOWS => ($^O =~ /^(mswin|dos|os2)/oi);
my @ATT_KEYS = (
@@ -149,11 +150,6 @@
my @datafiles = map { s,^rules/,,; $_ } (<rules/*.cf>);
my $datafiles = join(' ', (grep { /^[0-6][0-9]_/ } @datafiles), qw(user_prefs.template triplets.txt languages));
-# Only build spamd and spamc on non-Windows platforms
-my @SPAMD_EXE_FILES = ();
-if (!RUNNING_ON_WINDOWS) {
- @SPAMD_EXE_FILES = ('spamd/spamc$(EXE_EXT)', 'spamd/spamd');
-}
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
@@ -163,7 +159,8 @@
'EXE_FILES' => [
'spamassassin', 'sa-learn',
- @SPAMD_EXE_FILES
+ 'spamd/spamc$(EXE_EXT)',
+ 'spamd/spamd',
],
'MAN1PODS' => {
@@ -206,6 +203,7 @@
'spamassassin', 'sa-learn',
'spamd/spamd', 'spamd/spamc$(EXE_EXT)',
'spamd/libspamc.so', 'spamd/libsslspamc.so',
+ 'spamd/*.o', 'spamd/*.obj',
'spamd/binaries.mk', 'spamd/config.h', 'spamd/config.status',
'spamd/config.cache', 'spamd/config.log', 'spamd/autom4te.cache',
'qmail/qmail-spamc',
@@ -295,6 +293,15 @@
}
+# Windows platforms need some adjustments
+if (RUNNING_ON_WINDOWS) {
+ # Don't build spamd
+ delete $makefile{EXE_FILES}['spamd/spamd'];
+ # And require Net::DNS v0.44
+ #$makefile{PREREQ_PM}{Net::DNS} = 0.44;
+}
+
+
$makefile{'macro'}{'ENABLE_SSL'} = yesno($opt{'enable_ssl'});
if (!defined $opt{'contact_address'}) {
@@ -337,6 +344,8 @@
use vars qw(
$MY_GLOBALS_ARE_SANE
+ $RUNNING_ON_WINDOWS
+
@REPOSITORIES
$MACRO_RE
@@ -378,6 +387,9 @@
# To assign or own macros we'll follow the first assignment string we find;
# normally " = ".
$EQ = undef;
+
+ # Inherit our Windows-Flag.
+ $RUNNING_ON_WINDOWS = ::RUNNING_ON_WINDOWS;
}
# Unset $SELF to avoid any leaking memory.
@@ -432,8 +444,10 @@
# If it is omitted, the value set in the current EU::MM instance is used.
sub macro_def {
my($name, $val) = (@_, undef);
+ my $MUST_NOT_HAPPEN = "THIS MUST NOT HAPPEN. PLEASE REPORT A BUG VIA <http://bugzilla.spamassassin.org>";
+ die $MUST_NOT_HAPPEN unless defined $name;
+ die $MUST_NOT_HAPPEN unless defined $EQ;
$val = $SELF->{$name} unless defined $val;
- die unless defined $EQ;
return $name . $EQ . $val;
}
@@ -705,6 +719,33 @@
_set_macro_PERL_yesno('TAINT');
}
+# This routine sets the value for PREPROCESS.
+#
+# There are no parameters.
+#
+# If PREPROCESS wasn't set at the command line, it chooses our default
+# perl-called preprocessor.
+sub _set_macro_PREPROCESS {
+
+ return if get_macro('PREPROCESS');
+ set_macro('PREPROCESS', join(' ', macro_ref('PERL'), qq{build/preprocessor}));
+}
+
+# This routine sets the value for CONFIGURE (spamc only).
+#
+# There are no parameters.
+#
+# If CONFIGURE wasn't set at the command line, it chooses our default
+# perl-wrapped configure.
+sub _set_macro_CONFIGURE {
+
+ return if get_macro('CONFIGURE');
+ set_macro('CONFIGURE', join(' ', macro_ref('PERL'), qq{build/configure}));
+}
+
+
+
+
# Override the libscan routine so it skips SVN/CVS stuff and some common
# patch/backup extensions.
@@ -748,8 +789,6 @@
}
-
-
# Now override the constants routine to add our own macros.
sub MY::constants {
my $self = shift;
@@ -800,6 +839,7 @@
}
}
}
+ push(@code, qq{});
# Add some additional target dirs
{
@@ -814,6 +854,7 @@
# ... and add it to the Makefile.
push(@code, qq{});
+ push(@code, qq{# Where to install config files});
push(@code, macro_def('SYSCONFDIR'));
foreach my $r (@REPOSITORIES) {
push(@code, macro_def($r . 'SYSCONFDIR'));
@@ -841,46 +882,56 @@
# Add it to the Makefile.
push(@code, qq{});
+ push(@code, qq{# Some details about our Perl});
foreach my $m (qw(BIN VERSION WARN TAINT)) {
push(@code, macro_def('PERL_' . $m));
}
}
- clean_MY_globals($self);
- return join("\n", @code);
-}
+ # Set the preprocessor and configure scripts
+ {
+ _set_macro_PREPROCESS;
+ _set_macro_CONFIGURE;
-sub MY::postamble {
- my $self = shift;
- my @code = ();
- init_MY_globals($self);
+ # Add it to the Makefile.
+ push(@code, qq{});
+ push(@code, macro_def('PREPROCESS'));
+ push(@code, macro_def('CONFIGURE'));
+ }
- my($repository);
- $repository = uc($SELF->{INSTALLDIRS}) || 'SITE';
+ # Set some additional helper/shortcut macros.
+ {
+ my($repository);
+ $repository = uc($SELF->{INSTALLDIRS}) || 'SITE';
- foreach my $macro (qw(PREFIX SYSCONFDIR)) {
- push(@code, macro_def('I_' . $macro,
+ foreach my $macro (qw(PREFIX SYSCONFDIR)) {
+ push(@code, macro_def('I_' . $macro,
macro_ref($repository . $macro)));
- }
- foreach my $macro (qw(DATA CONF LIB)) {
- push(@code, macro_def('I_' . $macro . 'DIR',
+ }
+ foreach my $macro (qw(DATA CONF LIB)) {
+ push(@code, macro_def('I_' . $macro . 'DIR',
macro_ref('INSTALL' . repository($repository) . $macro)));
- if ($mm_has_destdir) {
- push(@code, macro_def('B_' . $macro . 'DIR',
- macro_ref('DESTINSTALL' . repository($repository) . $macro)));
- } else {
- push(@code, macro_def('B_' . $macro . 'DIR',
- macro_ref('I_' . $macro . 'DIR')));
+ if ($mm_has_destdir) {
+ push(@code, macro_def('B_' . $macro . 'DIR',
+ macro_ref('DESTINSTALL' . repository($repository) . $macro)));
+ } else {
+ push(@code, macro_def('B_' . $macro . 'DIR',
+ macro_ref('I_' . $macro . 'DIR')));
+ }
}
}
- my $code = join("\n", @code);
- @code = (); # free mem
+ clean_MY_globals($self);
+ return join("\n", @code);
+}
- $code .= <<' EOD';
+sub MY::postamble {
+ my $self = shift;
+ my $code = "";
+ init_MY_globals($self);
-PREPROCESS = $(PERL) build/preprocessor
+ $code .= <<' EOD';
FIXVARS = -Mvars \
-DVERSION="$(VERSION)" \
@@ -904,29 +955,25 @@
sa-learn: sa-learn.raw
$(PREPROCESS) $(FIXBYTES) $(FIXVARS) $(FIXBANG) -m$(PERM_RWX) -i$? -o$@
+
+spamd/binaries.mk:
+ $(CONFIGURE) --srcdir="spamd" --prefix="$(I_PREFIX)" --sysconfdir="$(I_SYSCONFDIR)" --datadir="$(I_DATADIR)" --enable-ssl="$(ENABLE_SSL)"
+
spamd/spamd: spamd/spamd.raw
$(PREPROCESS) $(FIXBYTES) $(FIXVARS) $(FIXBANG) -m$(PERM_RWX) -i$? -o$@
spamd/libspamc.so: spamd/binaries.mk $(SPAMC_SOURCES)
$(MAKE) -f spamd/binaries.mk $@
-spamd/libspamc.dll: spamd/binaries.mk $(SPAMC_SOURCES)
- $(MAKE) -f spamd/binaries.mk $@
-
spamd/spamc$(EXE_EXT): spamd/binaries.mk $(SPAMC_SOURCES)
$(MAKE) -f spamd/binaries.mk $@
spamd/libsslspamc.so: spamd/binaries.mk $(SPAMC_SOURCES)
$(MAKE) -f spamd/binaries.mk $@
-spamd/libsslspamc.dll: spamd/binaries.mk $(SPAMC_SOURCES)
- $(MAKE) -f spamd/binaries.mk $@
-
qmail/qmail-spamc: spamd/binaries.mk $(SPAMC_SOURCES)
$(MAKE) -f spamd/binaries.mk $@
-spamd/binaries.mk: spamd/configure
- cd spamd; ./configure --prefix="$(I_PREFIX)" --sysconfdir="$(I_SYSCONFDIR)" --datadir="$(I_DATADIR)" --enable-ssl="$(ENABLE_SSL)"
conf__install:
-$(MKPATH) $(B_CONFDIR)
Added: incubator/spamassassin/trunk/spamd/README.Win
==============================================================================
--- (empty file)
+++ incubator/spamassassin/trunk/spamd/README.Win Mon Jan 5 18:36:44 2004
@@ -0,0 +1,97 @@
+Building Spamd/Spamc under Windows
+----------------------------------
+
+Spamd currently does not run under Windows, but spamc does.
+
+Spamd does work when built and run in the Cygwin unix emulation
+environment, and a pure Windows spamc can be used with it. You can
+also run a pure Windows spamc that communicates with spamd running on
+any network accessible computer. The unix sockets option is not
+supported under Windows, so only TCP/IP can be used. As of this
+writing SSL has not been tested with the Windows spamc.
+
+Building spamc for Windows requires a lot more than running it. If all
+you want to do is run spamc without the full SpamAssassin on your
+Windows machine, it is easier if you can get a binary executable from
+someone else who has built it.
+
+System Requirements
+-------------------
+
+This has only been tested with Microsoft Visual C++ 6.0. There is a
+good chance it will just work with later versions of VC++, but some
+installation files would have to be changed to use with any other
+compiler.
+
+In addition to VC++ you also have to have installed a Windows version
+of Perl and the modules that are listed as required in the general
+SpamAssassin documentation. So far the only Windows version of perl
+this has been tested with is ActivePerl.
+
+To run the spamc executable once it is built you do not need to have
+VC++ or perl installed.
+
+Spamc requires spamd to be running on some system that it can talk to
+using tcp/ip over a network or on the same machine. The test cases in
+the build process will only work if spamd has been installed under
+Cygwin on the same computer.
+
+Building
+--------
+
+To build such a combined setup, first install SpamAssassin under
+Cygwin by unpacking the source files into some directory, for example,
+/usr/local/src/spamassassin, then in a Cygwin bash shell
+
+ cd /usr/local/src/spamassassin
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+This assumes that you have already installed perl and all necessary
+perl modules as described elsewhere in the SpamAssassin install
+documentation.
+
+Now that you have a working SpamAssassin under Cygwin you can use that
+to test the spamc that you will build under Windows. To set that up,
+first create a Windows environment variable in the System control
+panel. The variable is named
+
+ SPAMD_SCRIPT
+
+and set it to
+
+SPAMD_SCRIPT=start \cygwin\bin\perl -w -T /bin/spamd -x -s stderr --syslog-socket none
+
+where "\cygwin\bin\perl" is the path of the Cygwin perl executable
+file in the Windows directory system, and "/bin/spamd" is the path of
+the spamd executable that you installed under Cygwin. Be sure to
+substitute the correct path names for your installation if they are
+different from this example.
+
+Now you are ready to build SpamAssassin under Windows. Unpack the
+SpamAssassin source tree into a different directory than you used for
+building the Cygwin version, for example C:\spamassassin\. Then in a
+Windows command shell do the following.
+
+First, make sure that the environment is set up for running VC++. In
+VC++ 6.0 there is a batch file created during installation that sets
+the environment. In a typical installation that would be found at
+
+"\Program Files\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT"
+
+Also make sure that the SPAMD_SCRIPT environment variable is set in
+your command shell as described above.
+
+Then use the commands
+
+ cd \spamasassin
+ perl Makefile.PL
+ nmake
+ nmake test
+ nmake install
+
+That's it. You should now have two working versions of SpamAssassin,
+one under Cygwin and one under Windows.
+
Added: incubator/spamassassin/trunk/spamd/binaries.mk.win
==============================================================================
--- (empty file)
+++ incubator/spamassassin/trunk/spamd/binaries.mk.win Mon Jan 5 18:36:44 2004
@@ -0,0 +1,17 @@
+CC = @@CC@@
+CFLAGS = @@CFLAGS@@
+SSLCFLAGS = @@SSLCFLAGS@@
+
+LIBS = @@LIBS@@
+SSLLIBS = @@SSLLIBS@@
+
+SPAMC_FILES = @@SPAMC_FILES@@
+LIBSPAMC_FILES = @@LIBSPAMC_FILES@@
+
+
+all: spamd/spamc.exe
+
+spamd/spamc.exe: $(SPAMC_FILES) $(LIBSPAMC_FILES)
+ cd spamd
+ $(CC) $(SSLCFLAGS) $(CFLAGS) $(SPAMC_FILES) $(LIBSPAMC_FILES) $(LIBS) $(SSLLIBS)
+
Added: incubator/spamassassin/trunk/spamd/config.h.win
==============================================================================
--- (empty file)
+++ incubator/spamassassin/trunk/spamd/config.h.win Mon Jan 5 18:36:44 2004
@@ -0,0 +1,169 @@
+/* config.h. Generated by configure. */
+/* config.h.in. Generated from configure.in by autoheader. */
+
+/* #undef CCDLFLAGS */
+
+/* #undef LDDLFLAGS */
+
+#define HAVE_SHUT_RD 1
+
+#define HAVE_H_ERRNO 1
+
+#define HAVE_OPTARG 1
+
+/* #undef in_addr_t */
+
+#define HAVE_INADDR_NONE 1
+
+#ifndef _WIN32
+#define HAVE_EX__MAX 1
+#endif
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#define HAVE_GETOPT_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `crypto' library (-lcrypto). */
+/* #undef HAVE_LIBCRYPTO */
+
+/* Define to 1 if you have the `dl' library (-ldl). */
+/* #undef HAVE_LIBDL */
+
+/* Define to 1 if you have the `inet' library (-linet). */
+/* #undef HAVE_LIBINET */
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+/* #undef HAVE_LIBNSL */
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define to 1 if you have the `ssl' library (-lssl). */
+/* #undef HAVE_LIBSSL */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+/* #undef HAVE_OPENSSL_CRYPTO_H */
+
+#ifndef _WIN32
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+#endif
+
+/* Define to 1 if you have the `shutdown' function. */
+#define HAVE_SHUTDOWN 1
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strtod' function. */
+#define HAVE_STRTOD 1
+
+/* Define to 1 if you have the `strtol' function. */
+#define HAVE_STRTOL 1
+
+#ifndef _WIN32
+/* Define to 1 if you have the <sysexits.h> header file. */
+#define HAVE_SYSEXITS_H 1
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define to 1 if you have the <sys/errno.h> header file. */
+#define HAVE_SYS_ERRNO_H 1
+#endif
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+#ifndef _WIN32
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+#endif
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME ""
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING ""
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION ""
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define to `unsigned long' if <sys/types.h> does not define. */
+/* #undef in_addr_t */
+
+/* Define to `long' if <sys/types.h> does not define. */
+/* #undef off_t */
+/* #define off_t long */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+#define pid_t int
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
Added: incubator/spamassassin/trunk/spamd/getopt.c
==============================================================================
--- (empty file)
+++ incubator/spamassassin/trunk/spamd/getopt.c Mon Jan 5 18:36:44 2004
@@ -0,0 +1,231 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000-2004 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * Portions of this software are based upon public domain software
+ * originally written at the National Center for Supercomputing Applications,
+ * University of Illinois, Urbana-Champaign.
+ */
+
+#ifdef WIN32
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#define OPTERRCOLON (1)
+#define OPTERRNF (2)
+#define OPTERRARG (3)
+
+char *optarg;
+int optreset = 0;
+int optind = 1;
+int opterr = 1;
+int optopt;
+
+static int
+optiserr(int argc, char * const *argv, int oint, const char *optstr,
+ int optchr, int err)
+{
+ if(opterr)
+ {
+ fprintf(stderr, "Error in argument %d, char %d: ", oint, optchr+1);
+ switch(err)
+ {
+ case OPTERRCOLON:
+ fprintf(stderr, ": in flags\n");
+ break;
+ case OPTERRNF:
+ fprintf(stderr, "option not found %c\n", argv[oint][optchr]);
+ break;
+ case OPTERRARG:
+ fprintf(stderr, "no argument for option %c\n", argv[oint][optchr]);
+ break;
+ default:
+ fprintf(stderr, "unknown\n");
+ break;
+ }
+ }
+ optopt = argv[oint][optchr];
+ return('?');
+}
+
+
+
+int
+getopt(int argc, char* const *argv, const char *optstr)
+{
+ static int optchr = 0;
+ static int dash = 0; /* have already seen the - */
+
+ char *cp;
+
+ if (optreset)
+ optreset = optchr = dash = 0;
+ if(optind >= argc)
+ return(EOF);
+ if(!dash && (argv[optind][0] != '-'))
+ return(EOF);
+ if(!dash && (argv[optind][0] == '-') && !argv[optind][1])
+ {
+ /*
+ * use to specify stdin. Need to let pgm process this and
+ * the following args
+ */
+ return(EOF);
+ }
+ if((argv[optind][0] == '-') && (argv[optind][1] == '-'))
+ {
+ /* -- indicates end of args */
+ optind++;
+ return(EOF);
+ }
+ if(!dash)
+ {
+ assert((argv[optind][0] == '-') && argv[optind][1]);
+ dash = 1;
+ optchr = 1;
+ }
+
+ /* Check if the guy tries to do a -: kind of flag */
+ assert(dash);
+ if(argv[optind][optchr] == ':')
+ {
+ dash = 0;
+ optind++;
+ return(optiserr(argc, argv, optind-1, optstr, optchr, OPTERRCOLON));
+ }
+ if(!(cp = strchr(optstr, argv[optind][optchr])))
+ {
+ int errind = optind;
+ int errchr = optchr;
+
+ if(!argv[optind][optchr+1])
+ {
+ dash = 0;
+ optind++;
+ }
+ else
+ optchr++;
+ return(optiserr(argc, argv, errind, optstr, errchr, OPTERRNF));
+ }
+ if(cp[1] == ':')
+ {
+ dash = 0;
+ optind++;
+ if(optind == argc)
+ return(optiserr(argc, argv, optind-1, optstr, optchr, OPTERRARG));
+ optarg = argv[optind++];
+ return(*cp);
+ }
+ else
+ {
+ if(!argv[optind][optchr+1])
+ {
+ dash = 0;
+ optind++;
+ }
+ else
+ optchr++;
+ return(*cp);
+ }
+ assert(0);
+ return(0);
+}
+
+#ifdef TESTGETOPT
+int
+ main (int argc, char **argv)
+ {
+ int c;
+ extern char *optarg;
+ extern int optind;
+ int aflg = 0;
+ int bflg = 0;
+ int errflg = 0;
+ char *ofile = NULL;
+
+ while ((c = getopt(argc, argv, "abo:")) != EOF)
+ switch (c) {
+ case 'a':
+ if (bflg)
+ errflg++;
+ else
+ aflg++;
+ break;
+ case 'b':
+ if (aflg)
+ errflg++;
+ else
+ bflg++;
+ break;
+ case 'o':
+ ofile = optarg;
+ (void)printf("ofile = %s\n", ofile);
+ break;
+ case '?':
+ errflg++;
+ }
+ if (errflg) {
+ (void)fprintf(stderr,
+ "usage: cmd [-a|-b] [-o <filename>] files...\n");
+ exit (2);
+ }
+ for ( ; optind < argc; optind++)
+ (void)printf("%s\n", argv[optind]);
+ return 0;
+ }
+
+#endif /* TESTGETOPT */
+
+#endif /* WIN32 */
Added: incubator/spamassassin/trunk/spamd/getopt.h
==============================================================================
--- (empty file)
+++ incubator/spamassassin/trunk/spamd/getopt.h Mon Jan 5 18:36:44 2004
@@ -0,0 +1,73 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000-2004 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ * Portions of this software are based upon public domain software
+ * originally written at the National Center for Supercomputing Applications,
+ * University of Illinois, Urbana-Champaign.
+ */
+
+#ifndef GETOPT_H
+#define GETOPT_H
+
+#ifdef WIN32
+
+extern char *optarg;
+extern int optreset;
+extern int optind;
+extern int opterr;
+extern int optopt;
+int getopt(int argc, char* const *argv, const char *optstr);
+
+#endif /* WIN32 */
+
+#endif /* GETOPT_H */
Modified: incubator/spamassassin/trunk/spamd/libspamc.c
==============================================================================
--- incubator/spamassassin/trunk/spamd/libspamc.c (original)
+++ incubator/spamassassin/trunk/spamd/libspamc.c Mon Jan 5 18:36:44 2004
@@ -10,18 +10,26 @@
#include "libspamc.h"
#include "utils.h"
-#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
+#ifdef _WIN32
+/* simple macro that works for single strings without %m */
+#define syslog(x, y) fprintf(stderr, #y "\n")
+#define strcasecmp stricmp
+#define sleep Sleep
+#else
#include <syslog.h>
+#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
+#define closesocket(x) close(x)
+#endif
#ifdef HAVE_SYSEXITS_H
#include <sysexits.h>
@@ -173,11 +181,20 @@
}
#ifdef DO_CONNECT_DEBUG_SYSLOGS
+#ifndef _WIN32
syslog (DEBUG_LEVEL, "dbg: create socket(%s)", typename);
+#else
+ fprintf (stderr, "dbg: create socket(%s)\n", typename);
+#endif
#endif
- if ( (*psock = socket(type, SOCK_STREAM, proto)) < 0 )
- {
+ if ( (*psock = socket(type, SOCK_STREAM, proto))
+#ifndef _WIN32
+ < 0
+#else
+ == INVALID_SOCKET
+#endif
+ ) {
int origerr;
/*--------------------------------------------------------
@@ -185,9 +202,13 @@
* this is pretty much fatal. Translate the error reason
* into something the user can understand.
*/
+#ifndef _WIN32
origerr = errno; /* take a copy before syslog() */
-
syslog (LOG_ERR, "socket(%s) to spamd failed: %m", typename);
+#else
+ origerr = WSAGetLastError();
+ printf ("socket(%s) to spamd failed: %d\n", typename, origerr);
+#endif
switch (origerr)
{
@@ -221,15 +242,26 @@
if ( type == PF_INET
&& setsockopt(*psock, 0, TCP_NODELAY, &one, sizeof one) != 0 )
{
- switch(errno)
+ int origerrno;
+#ifndef _WIN32
+ origerr = errno;
+#else
+ origerrno = WSAGetLastError();
+#endif
+ switch(origerr)
{
case EBADF:
case ENOTSOCK:
case ENOPROTOOPT:
case EFAULT:
+#ifndef _WIN32
syslog(LOG_ERR,
"setsockopt(TCP_NODELAY) failed: %m");
- close (*psock);
+#else
+ fprintf(stderr,
+ "setsockopt(TCP_NODELAY) failed: %d\n", origerr));
+#endif
+ closesocket (*psock);
return EX_SOFTWARE;
default:
@@ -253,6 +285,7 @@
static int
try_to_connect_unix (struct transport *tp, int *sockptr)
{
+#ifndef _WIN32
int mysock, status, origerr;
struct sockaddr_un addrbuf;
int ret;
@@ -295,10 +328,12 @@
syslog(LOG_ERR, "connect(AF_UNIX) to spamd %s failed: %m",
addrbuf.sun_path);
-
- close(mysock);
+ closesocket(mysock);
return translate_connect_errno(origerr);
+#else
+ return EX_OSERR;
+#endif
}
/*
@@ -323,7 +358,13 @@
#ifdef DO_CONNECT_DEBUG_SYSLOGS
for (numloops = 0; numloops < tp->nhosts; numloops++)
{
- syslog(LOG_ERR, "dbg: %d/%d: %s",
+#ifndef _WIN32
+ syslog(LOG_ERR,
+ "dbg: %d/%d: %s",
+#else
+ fprintf(stderr,
+ "dbg: %d/%d: %s\n",
+#endif
numloops+1, tp->nhosts, inet_ntoa(tp->hosts[numloops]));
}
#endif
@@ -352,8 +393,13 @@
ipaddr = inet_ntoa(addrbuf.sin_addr);
#ifdef DO_CONNECT_DEBUG_SYSLOGS
- syslog (DEBUG_LEVEL,
+#ifndef _WIN32
+ syslog(DEBUG_LEVEL,
"dbg: connect(AF_INET) to spamd at %s (try #%d of %d)",
+#else
+ fprintf(stderr,
+ "dbg: connect(AF_INET) to spamd at %s (try #%d of %d\)\n",
+#endif
ipaddr,
numloops+1,
MAX_CONNECT_RETRIES);
@@ -363,20 +409,33 @@
if (status != 0)
{
+#ifndef _WIN32
+ origerr = errno;
syslog (LOG_ERR,
"connect(AF_INET) to spamd at %s failed, retrying (#%d of %d): %m",
ipaddr, numloops+1, MAX_CONNECT_RETRIES);
-
- close(mysock);
+#else
+ origerr = WSAGetLastError();
+ fprintf (stderr,
+ "connect(AF_INET) to spamd at %s failed, retrying (#%d of %d): %d\n",
+ ipaddr, numloops+1, MAX_CONNECT_RETRIES, origerr);
+#endif
+ closesocket(mysock);
sleep(CONNECT_RETRY_SLEEP);
}
else
{
#ifdef DO_CONNECT_DEBUG_SYSLOGS
+#ifndef _WIN32
syslog(DEBUG_LEVEL,
"dbg: connect(AF_INET) to spamd at %s done",
ipaddr);
+#else
+ fprintf(stderr,
+ "dbg: connect(AF_INET) to spamd at %s done\n",
+ ipaddr);
+#endif
#endif
*sockptr = mysock;
@@ -384,7 +443,13 @@
}
}
- syslog (LOG_ERR, "connection attempt to spamd aborted after %d retries",
+#ifndef _WIN32
+ syslog (LOG_ERR,
+ "connection attempt to spamd aborted after %d retries",
+#else
+ fprintf(stderr,
+ "connection attempt to spamd aborted after %d retries\n",
+#endif
MAX_CONNECT_RETRIES);
return translate_connect_errno(origerr);
@@ -411,7 +476,7 @@
message_read_raw(int fd, struct message *m){
clear_message(m);
if((m->raw=malloc(m->max_len+1))==NULL) return EX_OSERR;
- m->raw_len=full_read(fd, m->raw, m->max_len+1, m->max_len+1);
+ m->raw_len=full_read(fd, 1, m->raw, m->max_len+1, m->max_len+1);
if(m->raw_len<=0){
free(m->raw); m->raw=NULL; m->raw_len=0;
return EX_IOERR;
@@ -434,7 +499,7 @@
if((m->raw=malloc(m->max_len+1))==NULL) return EX_OSERR;
/* Find the DATA line */
- m->raw_len=full_read(fd, m->raw, m->max_len+1, m->max_len+1);
+ m->raw_len=full_read(fd, 1, m->raw, m->max_len+1, m->max_len+1);
if(m->raw_len<=0){
free(m->raw); m->raw=NULL; m->raw_len=0;
return EX_IOERR;
@@ -506,7 +571,12 @@
return message_read_bsmtp(fd, m);
default:
- syslog(LOG_ERR, "message_read: Unknown mode %d\n", flags&SPAMC_MODE_MASK);
+#ifndef _WIN32
+ syslog(LOG_ERR, "message_read: Unknown mode %d",
+#else
+ fprintf(stderr, "message_read: Unknown mode %d\n",
+#endif
+ flags&SPAMC_MODE_MASK);
return EX_USAGE;
}
}
@@ -519,10 +589,14 @@
if (m->priv->flags&SPAMC_CHECK_ONLY) {
if(m->is_spam==EX_ISSPAM || m->is_spam==EX_NOTSPAM){
- return full_write(fd, m->out, m->out_len);
+ return full_write(fd, 1, m->out, m->out_len);
} else {
- syslog(LOG_ERR, "oops! SPAMC_CHECK_ONLY is_spam: %d\n", m->is_spam);
+#ifndef _WIN32
+ syslog(LOG_ERR, "oops! SPAMC_CHECK_ONLY is_spam: %d", m->is_spam);
+#else
+ fprintf(stderr, "oops! SPAMC_CHECK_ONLY is_spam: %d\n", m->is_spam);
+#endif
return -1;
}
}
@@ -530,17 +604,17 @@
/* else we're not in CHECK_ONLY mode */
switch(m->type){
case MESSAGE_NONE:
- syslog(LOG_ERR, "Cannot write this message, it's MESSAGE_NONE!\n");
+ syslog(LOG_ERR, "Cannot write this message, it's MESSAGE_NONE!");
return -1;
case MESSAGE_ERROR:
- return full_write(fd, m->raw, m->raw_len);
+ return full_write(fd, 1, m->raw, m->raw_len);
case MESSAGE_RAW:
- return full_write(fd, m->out, m->out_len);
+ return full_write(fd, 1, m->out, m->out_len);
case MESSAGE_BSMTP:
- total=full_write(fd, m->pre, m->pre_len);
+ total=full_write(fd, 1, m->pre, m->pre_len);
for(i=0; i<m->out_len; ){
jlimit = (off_t) (sizeof(buffer)/sizeof(*buffer)-4);
for(j=0; i < (off_t) m->out_len &&
@@ -557,12 +631,16 @@
buffer[j++]=m->out[i++];
}
}
- total+=full_write(fd, buffer, j);
+ total+=full_write(fd, 1, buffer, j);
}
- return total+full_write(fd, m->post, m->post_len);
+ return total+full_write(fd, 1, m->post, m->post_len);
default:
- syslog(LOG_ERR, "Unknown message type %d\n", m->type);
+#ifndef _WIN32
+ syslog(LOG_ERR, "Unknown message type %d", m->type);
+#else
+ fprintf(stderr, "Unknown message type %d\n", m->type);
+#endif
return -1;
}
}
@@ -574,9 +652,13 @@
if(m!=NULL && m->type!=MESSAGE_NONE) {
message_write(out_fd, m);
}
- while((bytes=full_read(in_fd, buf, 8192, 8192))>0){
- if (bytes!=full_write(out_fd, buf, bytes)) {
+ while((bytes=full_read(in_fd, 1, buf, 8192, 8192))>0){
+ if (bytes!=full_write(out_fd, 1, buf, bytes)) {
+#ifndef _WIN32
syslog(LOG_ERR, "oops! message_dump of %d returned different", bytes);
+#else
+ fprintf(stderr, "oops! message_dump of %d returned different\n", bytes);
+#endif
}
}
}
@@ -596,7 +678,7 @@
if(flags&SPAMC_USE_SSL) {
bytesread = ssl_timeout_read (ssl, buf+len, 1);
} else {
- bytesread = fd_timeout_read (sock, buf+len, 1);
+ bytesread = fd_timeout_read (sock, 0, buf+len, 1);
}
if(buf[len]=='\n') {
@@ -614,7 +696,11 @@
}
}
+#ifndef _WIN32
syslog(LOG_ERR, "spamd responded with line of %d bytes, dying", len);
+#else
+ fprintf(stderr, "spamd responded with line of %d bytes, dying\n", len);
+#endif
failureval = EX_TOOBIG;
failure:
@@ -693,30 +779,48 @@
m->score = _locale_safe_string_to_float (s_str, 20);
m->threshold = _locale_safe_string_to_float (t_str, 20);
+ /* set bounds on these to ensure no buffer overflow in the sprintf */
+ if (m->score > 1e10)
+ m->score = 1e10;
+ else if (m->score < -1e10)
+ m->score = -1e10;
+ if (m->threshold > 1e10)
+ m->threshold = 1e10;
+ else if (m->threshold < -1e10)
+ m->threshold = -1e10;
+
/* Format is "Spam: x; y / x" */
m->is_spam=strcasecmp("true", is_spam) == 0 ? EX_ISSPAM: EX_NOTSPAM;
if(flags&SPAMC_CHECK_ONLY) {
- m->out_len=snprintf (m->out, m->max_len+EXPANSION_ALLOWANCE,
+ m->out_len=sprintf (m->out,
"%.1f/%.1f\n", m->score, m->threshold);
}
else if ((flags & SPAMC_REPORT_IFSPAM && m->is_spam == EX_ISSPAM)
|| (flags & SPAMC_REPORT))
{
- m->out_len=snprintf (m->out, m->max_len+EXPANSION_ALLOWANCE,
+ m->out_len=sprintf (m->out,
"%.1f/%.1f\n", m->score, m->threshold);
}
return EX_OK;
} else if(sscanf(buf, "Content-length: %d", &m->content_length) == 1) {
if (m->content_length < 0) {
+#ifndef _WIN32
syslog(LOG_ERR, "spamd responded with bad Content-length '%s'", buf);
+#else
+ fprintf(stderr, "spamd responded with bad Content-length '%s'\n", buf);
+#endif
return EX_PROTOCOL;
}
return EX_OK;
}
+#ifndef _WIN32
syslog(LOG_ERR, "spamd responded with bad header '%s'", buf);
+#else
+ fprintf(stderr, "spamd responded with bad header '%s'\n", buf);
+#endif
return EX_PROTOCOL;
}
@@ -733,7 +837,7 @@
int response;
int failureval;
SSL_CTX* ctx;
- SSL* ssl;
+ SSL* ssl = NULL;
SSL_METHOD *meth;
if (flags&SPAMC_USE_SSL) {
@@ -760,25 +864,35 @@
/* Build spamd protocol header */
if(flags & SPAMC_CHECK_ONLY)
- len=snprintf(buf, bufsiz, "CHECK %s\r\n", PROTOCOL_VERSION);
+ strcpy(buf, "CHECK ");
else if(flags & SPAMC_REPORT_IFSPAM)
- len=snprintf(buf, bufsiz, "REPORT_IFSPAM %s\r\n", PROTOCOL_VERSION);
+ strcpy(buf, "REPORT_IFSPAM ");
else if(flags & SPAMC_REPORT)
- len=snprintf(buf, bufsiz, "REPORT %s\r\n", PROTOCOL_VERSION);
+ strcpy(buf, "REPORT ");
else if(flags & SPAMC_SYMBOLS)
- len=snprintf(buf, bufsiz, "SYMBOLS %s\r\n", PROTOCOL_VERSION);
+ strcpy(buf, "SYMBOLS ");
else
- len=snprintf(buf, bufsiz, "PROCESS %s\r\n", PROTOCOL_VERSION);
+ strcpy(buf, "PROCESS ");
+
+ len = strlen(buf);
+ if(len+strlen(PROTOCOL_VERSION)+2 >= bufsiz){ free(m->out); m->out=m->msg; m->out_len=m->msg_len; return EX_OSERR; }
- if(len<0 || len >= bufsiz){ free(m->out); m->out=m->msg; m->out_len=m->msg_len; return EX_OSERR; }
- if(username!=NULL){
- len+=i=snprintf(buf+len, bufsiz-len, "User: %s\r\n", username);
- if(i<0 || len >= bufsiz){ free(m->out); m->out=m->msg; m->out_len=m->msg_len; return EX_OSERR; }
- }
- len+=i=snprintf(buf+len, bufsiz-len, "Content-length: %d\r\n", m->msg_len);
- if(i<0 || len >= bufsiz){ free(m->out); m->out=m->msg; m->out_len=m->msg_len; return EX_OSERR; }
- len+=i=snprintf(buf+len, bufsiz-len, "\r\n");
- if(i<0 || len >= bufsiz){ free(m->out); m->out=m->msg; m->out_len=m->msg_len; return EX_OSERR; }
+ strcat(buf, PROTOCOL_VERSION);
+ strcat(buf, "\r\n");
+ len = strlen(buf);
+
+ if(username!=NULL) {
+ if (strlen(username)+8 >= (bufsiz - len)) { free(m->out); m->out=m->msg; m->out_len=m->msg_len; return EX_OSERR; }
+ strcpy(buf+len, "User: ");
+ strcat(buf+len, username);
+ strcat(buf+len, "\r\n");
+ len += strlen(buf+len);
+ }
+ if ((m->msg_len > 9999999) || ((len + 27) >= (bufsiz - len))) {
+ free(m->out); m->out=m->msg; m->out_len=m->msg_len;
+ return EX_OSERR;
+ }
+ len += sprintf(buf+len, "Content-length: %d\r\n\r\n", m->msg_len);
libspamc_timeout = m->timeout;
@@ -790,7 +904,7 @@
if ( rc != EX_OK )
{
free(m->out); m->out=m->msg; m->out_len=m->msg_len;
- return i;
+ return EX_OSERR;
}
if(flags&SPAMC_USE_SSL) {
@@ -808,8 +922,8 @@
SSL_write(ssl, m->msg, m->msg_len);
#endif
} else {
- full_write(sock, buf, len);
- full_write(sock, m->msg, m->msg_len);
+ full_write(sock, 0, buf, len);
+ full_write(sock, 0, m->msg, m->msg_len);
shutdown(sock, SHUT_WR);
}
@@ -818,14 +932,22 @@
if (failureval != EX_OK) { goto failure; }
if(sscanf(buf, "SPAMD/%18s %d %*s", versbuf, &response)!=2) {
+#ifndef _WIN32
syslog(LOG_ERR, "spamd responded with bad string '%s'", buf);
+#else
+ fprintf(stderr, "spamd responded with bad string '%s'\n", buf);
+#endif
failureval = EX_PROTOCOL; goto failure;
}
versbuf[19] = '\0';
version = _locale_safe_string_to_float (versbuf, 20);
if (version < 1.0) {
+#ifndef _WIN32
syslog(LOG_ERR, "spamd responded with bad version string '%s'", versbuf);
+#else
+ fprintf(stderr, "spamd responded with bad version string '%s'\n", versbuf);
+#endif
failureval = EX_PROTOCOL; goto failure;
}
@@ -848,7 +970,7 @@
len = 0; /* overwrite those headers */
if (flags&SPAMC_CHECK_ONLY) {
- close(sock); sock = -1;
+ closesocket(sock); sock = -1;
if (m->is_spam == EX_TOOBIG) {
/* We should have gotten headers back... Damnit. */
failureval = EX_PROTOCOL; goto failure;
@@ -874,7 +996,7 @@
m->max_len+EXPANSION_ALLOWANCE+1-m->out_len,
m->max_len+EXPANSION_ALLOWANCE+1-m->out_len);
} else{
- len = full_read (sock, m->out+m->out_len,
+ len = full_read (sock, 0, m->out+m->out_len,
m->max_len+EXPANSION_ALLOWANCE+1-m->out_len,
m->max_len+EXPANSION_ALLOWANCE+1-m->out_len);
}
@@ -886,12 +1008,16 @@
m->out_len+=len;
shutdown(sock, SHUT_RD);
- close(sock); sock = -1;
+ closesocket(sock); sock = -1;
}
libspamc_timeout = 0;
if(m->out_len!=m->content_length) {
+#ifndef _WIN32
syslog(LOG_ERR, "failed sanity check, %d bytes claimed, %d bytes seen",
+#else
+ fprintf(stderr, "failed sanity check, %d bytes claimed, %d bytes seen\n",
+#endif
m->content_length, m->out_len);
failureval = EX_PROTOCOL; goto failure;
}
@@ -901,7 +1027,7 @@
failure:
free(m->out); m->out=m->msg; m->out_len=m->msg_len;
if (sock != -1) {
- close(sock);
+ closesocket(sock);
}
libspamc_timeout = 0;
@@ -936,7 +1062,7 @@
FAIL:
if(flags&SPAMC_CHECK_ONLY){
- full_write(out_fd, "0/0\n", 4);
+ full_write(out_fd, 1, "0/0\n", 4);
message_cleanup(&m);
return EX_NOTSPAM;
} else {
@@ -1032,14 +1158,26 @@
struct hostent *hp = 0;
char **addrp;
+#ifdef _WIN32
+ // Start Winsock up
+ WSADATA wsaData;
+ int nCode;
+ if ((nCode = WSAStartup(MAKEWORD(1, 1), &wsaData)) != 0) {
+ printf("WSAStartup() returned error code %d\n", nCode);
+ return EX_OSERR;
+ }
+
+#endif
+
assert(tp != 0);
switch ( tp->type )
{
+#ifndef _WIN32
case TRANSPORT_UNIX:
assert(tp->socketpath != 0);
return EX_OK;
-
+#endif
case TRANSPORT_LOCALHOST:
tp->hosts[0].s_addr = inet_addr("127.0.0.1");
tp->nhosts = 1;
@@ -1050,7 +1188,11 @@
{
int origherr = h_errno; /* take a copy before syslog() */
+#ifndef _WIN32
syslog (LOG_ERR, "gethostbyname(%s) failed: h_errno=%d",
+#else
+ fprintf (stderr, "gethostbyname(%s) failed: h_errno=%d\n",
+#endif
tp->hostname, origherr);
switch (origherr)
{
@@ -1094,7 +1236,11 @@
for (addrp = hp->h_addr_list; *addrp; addrp++)
{
if (tp->nhosts >= TRANSPORT_MAX_HOSTS-1) {
+#ifndef _WIN32
syslog (LOG_ERR, "hit limit of %d hosts, ignoring remainder", TRANSPORT_MAX_HOSTS-1);
+#else
+ fprintf (stderr, "hit limit of %d hosts, ignoring remainder\n", TRANSPORT_MAX_HOSTS-1);
+#endif
break;
}
@@ -1148,13 +1294,14 @@
char inputstr[99], cmpbuf1[99], cmpbuf2[99];
float output;
- snprintf (inputstr, 99, "%f", input);
+ /* sprintf instead of snprintf is safe here because it is only a controlled test */
+ sprintf (inputstr, "%f", input);
output = _locale_safe_string_to_float (inputstr, 99);
if (input == output) { return; }
/* could be a rounding error. print as string and compare those */
- snprintf (cmpbuf1, 98, "%f", input);
- snprintf (cmpbuf2, 98, "%f", output);
+ sprintf (cmpbuf1, "%f", input);
+ sprintf (cmpbuf2, "%f", output);
if (!strcmp (cmpbuf1, cmpbuf2)) { return; }
printf ("FAIL: input=%f != output=%f\n", input, output);
Modified: incubator/spamassassin/trunk/spamd/libspamc.h
==============================================================================
--- incubator/spamassassin/trunk/spamd/libspamc.h (original)
+++ incubator/spamassassin/trunk/spamd/libspamc.h Mon Jan 5 18:36:44 2004
@@ -9,11 +9,38 @@
#ifndef LIBSPAMC_H
#define LIBSPAMC_H 1
+#include <stdio.h>
#include <sys/types.h>
+#ifdef _WIN32
+#include <winsock.h>
+#else
+#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
-#include <netdb.h>
-#include <stdio.h>
+#endif
+
+#ifdef _WIN32
+#define EX_OK 0
+#define EX_USAGE 64
+#define EX_DATAERR 65
+#define EX_NOINPUT 66
+#define EX_NOUSER 67
+#define EX_NOHOST 68
+#define EX_UNAVAILABLE 69
+#define EX_SOFTWARE 70
+#define EX_OSERR 71
+#define EX_OSFILE 72
+#define EX_CANTCREAT 73
+#define EX_IOERR 74
+#define EX_TEMPFAIL 75
+#define EX_PROTOCOL 76
+#define EX_NOPERM 77
+#define EX_CONFIG 78
+
+#define STDIN_FILENO 0
+#define STDOUT_FILENO 1
+
+#endif
#define EX_NOTSPAM 0
#define EX_ISSPAM 1
Modified: incubator/spamassassin/trunk/spamd/spamc.c
==============================================================================
--- incubator/spamassassin/trunk/spamd/spamc.c (original)
+++ incubator/spamassassin/trunk/spamd/spamc.c Mon Jan 5 18:36:44 2004
@@ -9,17 +9,21 @@
#include "libspamc.h"
#include "utils.h"
-#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#ifdef _WIN32
+#define syslog(x, y) fprintf(stderr, #y "\n")
+#else
#include <syslog.h>
+#include <unistd.h>
+#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
-#include <netdb.h>
#include <arpa/inet.h>
+#endif
#ifdef HAVE_SYSEXITS_H
#include <sysexits.h>
@@ -48,13 +52,19 @@
|| (defined(__sgi)) /* IRIX */ \
|| (defined(__osf__)) /* Digital UNIX */ \
|| (defined(hpux) || defined(__hpux)) /* HPUX */ \
- || (defined(_WIN32) || defined(__CYGWIN__)) /* CygWin, Win32 */
+ || (defined(__CYGWIN__)) /* CygWin, Win32 */
extern int optind;
extern char *optarg;
#endif
+#ifdef _WIN32
+#include "getopt.h"
+char* __progname = "spamc";
+#endif
+
+
/* safe fallback defaults to on now - CRH */
int flags = SPAMC_RAW_MODE | SPAMC_SAFE_FALLBACK;
@@ -93,7 +103,13 @@
{
int opt, i, j;
- while(-1 != (opt = getopt(argc,argv,"-BcrRd:e:fhyp:t:s:u:xSHU:")))
+ while(-1 != (opt = getopt(argc,argv,
+#ifndef _WIN32
+ "-BcrRd:e:fhyp:t:s:u:xSHU:"
+#else
+ "-BcrRd:fhyp:t:s:u:xSH"
+#endif
+)))
{
switch(opt)
{
@@ -102,12 +118,14 @@
flags |= SPAMC_RANDOMIZE_HOSTS;
break;
}
+#ifndef _WIN32
case 'U':
{
ptrn->type = TRANSPORT_UNIX;
ptrn->socketpath = optarg;
break;
}
+#endif
case 'B':
{
flags = (flags & ~SPAMC_MODE_MASK) | SPAMC_BSMTP_MODE;
@@ -139,6 +157,7 @@
ptrn->hostname = optarg; /* fix the ptr to point to this string */
break;
}
+#ifndef _WIN32
case 'e':
{
if((exec_argv=malloc(sizeof(*exec_argv)*(argc-optind+2)))==NULL)
@@ -149,6 +168,7 @@
exec_argv[i]=NULL;
return EX_OK;
}
+#endif
case 'p':
{
ptrn->port = atoi(optarg);
@@ -210,6 +230,7 @@
*fd=STDOUT_FILENO;
return;
}
+#ifndef _WIN32
if(pipe(fds)){
syslog(LOG_ERR, "pipe creation failed: %m");
exit(EX_OSERR);
@@ -237,6 +258,9 @@
close(fds[0]); /* no point in leaving extra fds lying around */
execv(exec_argv[0], exec_argv);
syslog(LOG_ERR, "exec failed: %m");
+#else
+ fprintf(stderr, "exec failed: %d\n", errno);
+#endif
exit(EX_OSERR);
}
@@ -256,8 +280,10 @@
do_libspamc_unit_tests();
#endif
+#ifndef _WIN32
openlog ("spamc", LOG_CONS|LOG_PID, LOG_MAIL);
signal (SIGPIPE, SIG_IGN);
+#endif
read_args(argc,argv, &max_size, &username, &trans);
@@ -274,6 +300,7 @@
* to our own buffer - then this won't arise as a problem.
*/
+#ifndef _WIN32
if(NULL == username)
{
static char userbuf[256];
@@ -289,6 +316,7 @@
userbuf[sizeof userbuf - 1] = '\0';
username = userbuf;
}
+#endif
if ((flags & SPAMC_RANDOMIZE_HOSTS) != 0) {
/* we don't need strong randomness; this is just so we pick
@@ -304,57 +332,59 @@
* we connect to the spam daemon. Mainly this involves lookup up the
* hostname and getting the IP addresses to connect to.
*/
- if ( (ret = transport_setup(&trans, flags)) != EX_OK )
- goto FAIL;
-
-
+ if ( (ret = transport_setup(&trans, flags)) == EX_OK ) {
out_fd=-1;
m.type = MESSAGE_NONE;
m.max_len = max_size;
m.timeout = timeout;
ret=message_read(STDIN_FILENO, flags, &m);
- if(ret!=EX_OK) goto FAIL;
+ if(ret==EX_OK) {
ret=message_filter(&trans, username, flags, &m);
- if(ret!=EX_OK) goto FAIL;
+ if(ret==EX_OK) {
get_output_fd(&out_fd);
- if(message_write(out_fd, &m)<0) {
- goto FAIL;
- }
+ if(message_write(out_fd, &m)>=0) {
result = m.is_spam;
if ((flags&SPAMC_CHECK_ONLY) && result != EX_TOOBIG) {
message_cleanup (&m);
- return result;
+ ret = result;
} else {
message_cleanup (&m);
+ }
+#ifdef _WIN32
+ WSACleanup();
+#endif
return ret;
}
+ }
+ }
+ }
-FAIL:
+ FAIL:
get_output_fd(&out_fd);
result = m.is_spam;
if((flags&SPAMC_CHECK_ONLY) && result != EX_TOOBIG) {
/* probably, the write to stdout failed; we can still report exit code */
message_cleanup (&m);
- return result;
-
+ ret = result;
} else if(flags&SPAMC_CHECK_ONLY || flags&SPAMC_REPORT || flags&SPAMC_REPORT_IFSPAM) {
- full_write(out_fd, "0/0\n", 4);
+ full_write(out_fd, 1, "0/0\n", 4);
message_cleanup (&m);
- return EX_NOTSPAM;
-
+ ret = EX_NOTSPAM;
} else {
message_dump(STDIN_FILENO, out_fd, &m);
message_cleanup (&m);
if (ret == EX_TOOBIG) {
- return 0;
+ ret = 0;
} else if (flags & SPAMC_SAFE_FALLBACK) {
- return EX_OK;
- } else {
- return ret;
+ ret = EX_OK;
}
}
+#ifdef _WIN32
+ WSACleanup();
+#endif
+ return ret;
}
Modified: incubator/spamassassin/trunk/spamd/utils.c
==============================================================================
--- incubator/spamassassin/trunk/spamd/utils.c (original)
+++ incubator/spamassassin/trunk/spamd/utils.c Mon Jan 5 18:36:44 2004
@@ -6,12 +6,15 @@
* "License".
*/
+#ifndef _WIN32
#include <unistd.h>
+#include <sys/uio.h>
+#else
+typedef int ssize_t;
+#endif
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
-#include <sys/uio.h>
-#include <unistd.h>
#include <stdio.h>
#include "utils.h"
@@ -25,7 +28,7 @@
/* Apr 24, 2003 sjf: made full_read and full_write void* params */
/* -------------------------------------------------------------------------- */
-
+#ifndef _WIN32
typedef void sigfunc(int); /* for signal handlers */
sigfunc* sig_catch(int sig, void (*f)(int))
@@ -41,23 +44,38 @@
static void catch_alrm(int x) {
UNUSED_VARIABLE(x);
}
+#endif
ssize_t
-fd_timeout_read (int fd, void *buf, size_t nbytes)
+fd_timeout_read (int fd, char fdflag, void *buf, size_t nbytes)
{
ssize_t nred;
+ int origerr;
+#ifndef _WIN32
sigfunc* sig;
sig = sig_catch(SIGALRM, catch_alrm);
if (libspamc_timeout > 0) {
alarm(libspamc_timeout);
}
+#endif
do {
+ if (fdflag) {
nred = read (fd, buf, nbytes);
- } while(nred < 0 && errno == EAGAIN);
+ origerr = errno;
+ } else {
+ nred = recv (fd, buf, nbytes, 0);
+#ifndef _WIN32
+ origerr = errno;
+#else
+ origerr = WSAGetLastError();
+#endif
+ }
+ } while(nred < 0 && origerr == EWOULDBLOCK);
- if(nred < 0 && errno == EINTR)
+#ifndef _WIN32
+ if(nred < 0 && origerr == EINTR)
errno = ETIMEDOUT;
if (libspamc_timeout > 0) {
@@ -66,6 +84,7 @@
/* restore old signal handler */
sig_catch(SIGALRM, sig);
+#endif
return nred;
}
@@ -74,7 +93,6 @@
ssl_timeout_read (SSL *ssl, void *buf, int nbytes)
{
int nred;
- sigfunc* sig;
#ifndef SPAMC_SSL
UNUSED_VARIABLE(ssl);
@@ -82,10 +100,14 @@
UNUSED_VARIABLE(nbytes);
#endif
+#ifndef _WIN32
+ sigfunc* sig;
+
sig = sig_catch(SIGALRM, catch_alrm);
if (libspamc_timeout > 0) {
alarm(libspamc_timeout);
}
+#endif
do {
#ifdef SPAMC_SSL
@@ -93,8 +115,9 @@
#else
nred = 0; /* never used */
#endif
- } while(nred < 0 && errno == EAGAIN);
+ } while(nred < 0 && errno == EWOULDBLOCK);
+#ifndef _WIN32
if(nred < 0 && errno == EINTR)
errno = ETIMEDOUT;
@@ -104,6 +127,7 @@
/* restore old signal handler */
sig_catch(SIGALRM, sig);
+#endif
return nred;
}
@@ -111,14 +135,14 @@
/* -------------------------------------------------------------------------- */
int
-full_read (int fd, void *vbuf, int min, int len)
+full_read (int fd, char fdflag, void *vbuf, int min, int len)
{
unsigned char *buf = (unsigned char *)vbuf;
int total;
int thistime;
for (total = 0; total < min; ) {
- thistime = fd_timeout_read (fd, buf+total, len-total);
+ thistime = fd_timeout_read (fd, fdflag, buf+total, len-total);
if (thistime < 0) {
return -1;
@@ -156,17 +180,27 @@
}
int
-full_write (int fd, const void *vbuf, int len)
+full_write (int fd, char fdflag, const void *vbuf, int len)
{
const unsigned char *buf = (const unsigned char *)vbuf;
int total;
int thistime;
+ int origerr;
for (total = 0; total < len; ) {
+ if (fdflag) {
thistime = write (fd, buf+total, len-total);
-
+ origerr = errno;
+ } else {
+ thistime = send (fd, buf+total, len-total, 0);
+#ifndef _WIN32
+ origerr = errno;
+#else
+ origerr = WSAGetLastError();
+#endif
+ }
if (thistime < 0) {
- if(EINTR == errno || EAGAIN == errno) continue;
+ if(EINTR == origerr || EWOULDBLOCK == origerr) continue;
return thistime; /* always an error for writes */
}
total += thistime;
Modified: incubator/spamassassin/trunk/spamd/utils.h
==============================================================================
--- incubator/spamassassin/trunk/spamd/utils.h (original)
+++ incubator/spamassassin/trunk/spamd/utils.h Mon Jan 5 18:36:44 2004
@@ -15,13 +15,65 @@
typedef int SSL_CTX;
typedef int SSL_METHOD;
#endif
+#ifdef _WIN32
+#include <winsock.h>
+typedef int ssize_t;
+//
+// BSD-compatible socket error codes for Win32
+//
-ssize_t fd_timeout_read (int fd, void *, size_t );
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define EINPROGRESS WSAEINPROGRESS
+#define EALREADY WSAEALREADY
+#define ENOTSOCK WSAENOTSOCK
+#define EDESTADDRREQ WSAEDESTADDRREQ
+#define EMSGSIZE WSAEMSGSIZE
+#define EPROTOTYPE WSAEPROTOTYPE
+#define ENOPROTOOPT WSAENOPROTOOPT
+#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+#define EOPNOTSUPP WSAEOPNOTSUPP
+#define EPFNOSUPPORT WSAEPFNOSUPPORT
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#define EADDRINUSE WSAEADDRINUSE
+#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+#define ENETDOWN WSAENETDOWN
+#define ENETUNREACH WSAENETUNREACH
+#define ENETRESET WSAENETRESET
+#define ECONNABORTED WSAECONNABORTED
+#define ECONNRESET WSAECONNRESET
+#define ENOBUFS WSAENOBUFS
+#define EISCONN WSAEISCONN
+#define ENOTCONN WSAENOTCONN
+#define ESHUTDOWN WSAESHUTDOWN
+#define ETOOMANYREFS WSAETOOMANYREFS
+#define ETIMEDOUT WSAETIMEDOUT
+#define ECONNREFUSED WSAECONNREFUSED
+#define ELOOP WSAELOOP
+// #define ENAMETOOLONG WSAENAMETOOLONG
+#define EHOSTDOWN WSAEHOSTDOWN
+#define EHOSTUNREACH WSAEHOSTUNREACH
+// #define ENOTEMPTY WSAENOTEMPTY
+#define EPROCLIM WSAEPROCLIM
+#define EUSERS WSAEUSERS
+#define EDQUOT WSAEDQUOT
+#define ESTALE WSAESTALE
+#define EREMOTE WSAEREMOTE
+
+// NOTE: these are not errno constants in UNIX!
+#define HOST_NOT_FOUND WSAHOST_NOT_FOUND
+#define TRY_AGAIN WSATRY_AGAIN
+#define NO_RECOVERY WSANO_RECOVERY
+#define NO_DATA WSANO_DATA
+
+#endif
+
+ssize_t fd_timeout_read (int fd, char fdflag, void *, size_t );
int ssl_timeout_read (SSL *ssl, void *, int );
/* these are fd-only, no SSL support */
-int full_read(int fd, void *buf, int min, int len);
+int full_read(int fd, char fdflag, void *buf, int min, int len);
int full_read_ssl(SSL *ssl, unsigned char *buf, int min, int len);
-int full_write(int fd, const void *buf, int len);
+int full_write(int fd, char fdflag, const void *buf, int len);
#endif