Main Page | Class List | Directories | File List | Class Members | File Members

spamc.c File Reference

#include "config.h"
#include "version.h"
#include "libspamc.h"
#include "utils.h"
#include "spamc.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "getopt.h"
#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 <arpa/inet.h>

Go to the source code of this file.

Functions

void check_malloc (void *ptr)
void print_version (void)
static void usg (char *str)
void print_usage (void)
int read_args (int argc, char **argv, int *max_size, char **username, int *extratype, struct transport *ptrn)
int combine_args (char *config_file, int argc, char **argv, int *combo_argc, char **combo_argv)
void get_output_fd (int *fd)
int get_current_user (char **username)
int main (int argc, char *argv[])

Variables

int flags = SPAMC_RAW_MODE | SPAMC_SAFE_FALLBACK
int use_exit_code = 0
char ** exec_argv
static int timeout = 600


Function Documentation

void check_malloc void *  ptr  ) 
 

Definition at line 105 of file spamc.c.

References EX_OSERR, flags, libspamc_log(), and LOG_ERR.

Referenced by combine_args(), and main().

00106 {
00107     if(ptr == NULL) {
00108         libspamc_log(flags, LOG_ERR,
00109                       "Error allocating memory using malloc\n");
00110         /* this is really quite serious.  we can't do anything. die */
00111         exit(EX_OSERR);
00112     }
00113 }

int combine_args char *  config_file,
int  argc,
char **  argv,
int *  combo_argc,
char **  combo_argv
 

Definition at line 521 of file spamc.c.

References check_malloc(), EX_CONFIG, and EX_OK.

Referenced by main().

00523 {
00524     FILE *config;
00525     char option[100];
00526     int i, count = 0;
00527     char *tok = NULL;
00528     int is_user_defined_p = 1;
00529 
00530     if (config_file == NULL) {
00531       config_file = CONFIG_FILE;
00532       is_user_defined_p = 0;
00533     }
00534 
00535     if((config = fopen(config_file, "r")) == NULL) {
00536         if (is_user_defined_p == 1) { /* if the config file was user defined we should issue an error */
00537             fprintf(stderr,"Failed to open config file: %s\n", config_file);
00538         }
00539         return EX_CONFIG;
00540     }
00541 
00542     while(!(feof(config)) && (fgets(option, 100, config))) {
00543 
00544         count++; /* increment the line counter */
00545 
00546         if(option[0] == '#' || option[0] == '\n') {
00547             continue;
00548         }
00549 
00550         tok = option;
00551         while((tok = strtok(tok, " ")) != NULL) {
00552        if(tok[0] == '\n')
00553           break;
00554             for(i=strlen(tok); i>0; i--) {
00555                 if(tok[i] == '\n')
00556                     tok[i] = '\0';
00557             }
00558             combo_argv[*combo_argc] = strdup(tok);
00559             check_malloc(combo_argv[*combo_argc]);
00560             /* TODO: leaked.  not a big deal since spamc exits quickly */
00561             tok = NULL;
00562             *combo_argc+=1;
00563         }
00564     }
00565 
00566     fclose(config);
00567 
00568     /* note: not starting at 0, that's the command name */
00569     for(i=1; i<argc; i++) {
00570         combo_argv[*combo_argc] = strdup(argv[i]);
00571         check_malloc(combo_argv[*combo_argc]);
00572         /* TODO: leaked.  not a big deal since spamc exits quickly */
00573         *combo_argc+=1;
00574     }
00575     return EX_OK;
00576 }

int get_current_user char **  username  ) 
 

Determines the username of the uid spamc is running under.

If the program's caller didn't identify the user to run as, use the current user for this. Note that we're not talking about UNIX perm- issions, but giving SpamAssassin a username so it can do per-user configuration (whitelists & the like).

Allocates memory for the username, returns EX_OK if successful.

Definition at line 653 of file spamc.c.

References EX_NOTSPAM, EX_OK, EX_OSERR, flags, and SPAMC_CHECK_ONLY.

Referenced by main().

00654 {
00655 #ifndef _WIN32
00656     struct passwd *curr_user;
00657 #endif
00658 
00659     if (*username != NULL) {
00660         *username = strdup(*username);
00661         if (username == NULL)
00662             goto fail;
00663         goto pass;
00664     }
00665 
00666 #ifndef _WIN32
00667     
00668     /* Get the passwd information for the effective uid spamc is running
00669      * under. Setting errno to zero is recommended in the manpage.
00670      */
00671     errno = 0;
00672     curr_user = getpwuid(geteuid());
00673     if (curr_user == NULL) {
00674         perror("getpwuid() failed");
00675         goto fail;
00676     }
00677     
00678     /* Since "curr_user" points to static library data, we don't wish to
00679      * risk some other part of the system overwriting it, so we copy the 
00680      * username to our own buffer -- then this won't arise as a problem.
00681      */
00682     *username = strdup(curr_user->pw_name);
00683     if (*username == NULL) {
00684         goto fail;
00685     }
00686 
00687 #endif
00688 
00689 pass:
00690     return EX_OK;
00691     
00692 fail:
00693     /* FIXME: The handling of SPAMC_CHECK_ONLY should probably be moved to 
00694      *        the end of main()
00695      */
00696     if (flags & SPAMC_CHECK_ONLY) {
00697         printf("0/0\n");
00698         return EX_NOTSPAM;
00699     }
00700     return EX_OSERR;
00701 }

void get_output_fd int *  fd  ) 
 

Definition at line 579 of file spamc.c.

References EX_OSERR, exec_argv, flags, libspamc_log(), LOG_CRIT, LOG_ERR, STDIN_FILENO, and STDOUT_FILENO.

Referenced by main().

00580 {
00581 #ifndef _WIN32
00582     int pipe_fds[2];
00583     pid_t pid;
00584 #endif
00585 
00586     if (*fd != -1)
00587         return;
00588     
00589     /* If we aren't told to feed our output to an external app, we simply
00590      * write to stdout.
00591      */
00592     if (exec_argv == NULL) {
00593         *fd = STDOUT_FILENO;
00594         return;
00595     }
00596     
00597 #ifndef _WIN32
00598     /* Create a pipe for communication between child and parent. */
00599     if (pipe(pipe_fds)) {
00600         libspamc_log(flags, LOG_ERR, "pipe creation failed: %m");
00601         exit(EX_OSERR);
00602     }
00603     
00604     pid = fork();
00605     if (pid < 0) {
00606         libspamc_log(flags, LOG_ERR, "fork failed: %m");
00607         exit(EX_OSERR);
00608     }
00609     else if (pid == 0) {
00610         /* This is the child process:
00611          * Normally you'd expect the parent process here, however that would
00612          * screw up an invoker waiting on the death of the parent. So instead,
00613          * we fork a child to feed the data and have the parent exec the new
00614          * program.
00615          */
00616         close(pipe_fds[0]);
00617         *fd = pipe_fds[1];
00618         return;
00619     }
00620     
00621     /* This is the parent process (see above) */
00622     close(pipe_fds[1]);
00623     if (dup2(pipe_fds[0], STDIN_FILENO)) {
00624         libspamc_log(flags, LOG_ERR, "redirection of stdin failed: %m");
00625         exit(EX_OSERR);
00626     }
00627     /* No point in leaving extra fds lying around. */
00628     close(pipe_fds[0]);
00629     
00630     /* Now execute the command specified. */
00631     execv(exec_argv[0], exec_argv);
00632     
00633     /* Whoa, something failed... */
00634     libspamc_log(flags, LOG_ERR, "exec failed: %m");
00635 #else
00636     libspamc_log(flags, LOG_CRIT, "THIS MUST NOT HAPPEN AS -e IS NOT SUPPORTED UNDER WINDOWS.");
00637 #endif
00638     exit(EX_OSERR);
00639 }

int main int  argc,
char *  argv[]
 

Definition at line 705 of file spamc.c.

References check_malloc(), combine_args(), EX_NOHOST, EX_OK, EX_SOFTWARE, EX_TEMPFAIL, EX_TOOBIG, flags, full_write(), get_current_user(), get_output_fd(), message::is_spam, message::max_len, message_cleanup(), message_dump(), message_filter(), MESSAGE_NONE, message_read(), message_tell(), message_write(), message::out, message::outbuf, message::priv, message::raw, read_args(), SPAMC_CHECK_ONLY, SPAMC_LEARN, SPAMC_MESSAGE_CLASS_HAM, SPAMC_MESSAGE_CLASS_SPAM, SPAMC_PING, SPAMC_RANDOMIZE_HOSTS, SPAMC_REMOVE_LOCAL, SPAMC_REMOVE_REMOTE, SPAMC_REPORT, SPAMC_REPORT_IFSPAM, SPAMC_REPORT_MSG, SPAMC_SAFE_FALLBACK, SPAMC_SET_LOCAL, SPAMC_SET_REMOTE, SPAMC_SYMBOLS, STDIN_FILENO, STDOUT_FILENO, timeout, message::timeout, transport_init(), transport_setup(), message::type, and use_exit_code.

00706 {
00707     int max_size;
00708     char *username;
00709     struct transport trans;
00710     struct message m;
00711     int out_fd = -1;
00712     int result = EX_SOFTWARE;
00713     int ret = EX_SOFTWARE;
00714     int extratype = 0;
00715     int islearned = 0;
00716     int isreported = 0;
00717 
00718     /* these are to hold CLI and config options combined, to be passed
00719      * to read_args() */
00720     char *combo_argv[24];
00721     int combo_argc;
00722 
00723     int i;
00724     char *config_file = NULL;
00725 
00726     transport_init(&trans);
00727 
00728 #ifdef LIBSPAMC_UNIT_TESTS
00729     /* unit test support; divert execution.  will not return */
00730     do_libspamc_unit_tests();
00731 #endif
00732 
00733 #ifndef _WIN32
00734     openlog("spamc", LOG_CONS | LOG_PID, LOG_MAIL);
00735     signal(SIGPIPE, SIG_IGN);
00736 #endif
00737 
00738     /* set some defaults */
00739     max_size = 500 * 1024;
00740     username = NULL;
00741  
00742     combo_argc = 1;
00743     combo_argv[0] = strdup(argv[0]);
00744     check_malloc(combo_argv[0]);
00745     /* TODO: leaked.  not a big deal since spamc exits quickly */
00746  
00747     for(i=0; i<argc; i++) {
00748        if(strncmp(argv[i], "-F", 2) == 0) {
00749           config_file = argv[i+1];
00750           break;
00751        }
00752     }
00753  
00754     if((combine_args(config_file, argc, argv, &combo_argc, combo_argv)) == EX_OK)
00755     {
00756       /* Parse the combined arguments of command line and config file */
00757       if ((ret = read_args(combo_argc, combo_argv, &max_size, &username, 
00758                           &extratype, &trans)) != EX_OK)
00759       {
00760         if (ret == EX_TEMPFAIL)
00761          ret = EX_OK;
00762         goto finish;
00763       }
00764     }
00765     else {
00766       /* parse only command line arguments (default behaviour) */
00767       if((ret = read_args(argc, argv, &max_size, &username, 
00768                          &extratype, &trans)) != EX_OK)
00769       {
00770         if(ret == EX_TEMPFAIL)
00771          ret = EX_OK;
00772         goto finish;
00773       }
00774     }
00775  
00776     ret = get_current_user(&username);
00777     if (ret != EX_OK)
00778         goto finish;
00779         
00780     if ((flags & SPAMC_RANDOMIZE_HOSTS) != 0) {
00781         /* we don't need strong randomness; this is just so we pick
00782          * a random host for loadbalancing.
00783          */
00784         srand(getpid() ^ time(NULL));
00785     }
00786 
00787     /**********************************************************************
00788      * SET UP TRANSPORT
00789      *
00790      * This takes the user parameters and digs up what it can about how
00791      * we connect to the spam daemon. Mainly this involves lookup up the
00792      * hostname and getting the IP addresses to connect to.
00793      */
00794     m.type = MESSAGE_NONE;
00795     m.out = NULL;
00796     m.outbuf = NULL;
00797     m.raw = NULL;
00798     m.priv = NULL;
00799     m.max_len = max_size;
00800     m.timeout = timeout;
00801     m.is_spam = EX_NOHOST;      /* default err code if can't reach the daemon */
00802 #ifdef _WIN32
00803     setmode(STDIN_FILENO, O_BINARY);
00804     setmode(STDOUT_FILENO, O_BINARY);
00805 #endif
00806     ret = transport_setup(&trans, flags);
00807 
00808     if (ret == EX_OK) {
00809 
00810         ret = message_read(STDIN_FILENO, flags, &m);
00811 
00812         if (ret == EX_OK) {
00813 
00814             if (flags & SPAMC_LEARN) {
00815               int msg_class = 0;
00816               unsigned int tellflags = 0;
00817               unsigned int didtellflags = 0;
00818 
00819               if ((extratype == 0) || (extratype == 1)) {
00820                 if (extratype == 0) {
00821                   msg_class = SPAMC_MESSAGE_CLASS_SPAM;
00822                 }
00823                 else {
00824                   msg_class = SPAMC_MESSAGE_CLASS_HAM;
00825                 }
00826                 tellflags |= SPAMC_SET_LOCAL;
00827               }
00828               else {
00829                 tellflags |= SPAMC_REMOVE_LOCAL;
00830               }
00831 
00832               ret = message_tell(&trans, username, flags, &m, msg_class,
00833                                  tellflags, &didtellflags);
00834 
00835               if (ret == EX_OK) {
00836                 if ((extratype == 0) || (extratype == 1)) {
00837                   if (didtellflags & SPAMC_SET_LOCAL) {
00838                     islearned = 1;
00839                   }
00840                 }
00841                 else {
00842                   if (didtellflags & SPAMC_REMOVE_LOCAL) {
00843                     islearned = 1;
00844                   }
00845                 }
00846               }
00847             }
00848             else if (flags & SPAMC_REPORT_MSG) {
00849               int msg_class = 0;
00850               unsigned int tellflags = 0;
00851               unsigned int didtellflags = 0;
00852 
00853               if (extratype == 0) {
00854                 msg_class = SPAMC_MESSAGE_CLASS_SPAM;
00855                 tellflags |= SPAMC_SET_REMOTE;
00856                 tellflags |= SPAMC_SET_LOCAL;
00857               }
00858               else {
00859                 msg_class = SPAMC_MESSAGE_CLASS_HAM;
00860                 tellflags |= SPAMC_SET_LOCAL;
00861                 tellflags |= SPAMC_REMOVE_REMOTE;
00862               }
00863 
00864               ret = message_tell(&trans, username, flags, &m, msg_class,
00865                                  tellflags, &didtellflags);
00866 
00867               if (ret == EX_OK) {
00868                 if (extratype == 0) {
00869                   if (didtellflags & SPAMC_SET_REMOTE) {
00870                     isreported = 1;
00871                   }
00872                 }
00873                 else {
00874                   if (didtellflags & SPAMC_REMOVE_REMOTE) {
00875                     isreported = 1;
00876                   }
00877                 }
00878               }
00879             }
00880             else {
00881               ret = message_filter(&trans, username, flags, &m);
00882             }
00883 
00884             free(username); username = NULL;
00885             
00886             if (ret == EX_OK) {
00887 
00888                 get_output_fd(&out_fd);
00889 
00890                 if (flags & SPAMC_LEARN) {
00891                     if (islearned == 1) {
00892                         printf("Message successfully un/learned\n");
00893                     }
00894                     else {
00895                         printf("Message was already un/learned\n");
00896                     }
00897                     message_cleanup(&m);
00898                     goto finish;
00899                 }
00900                 else if (flags & SPAMC_REPORT_MSG) {
00901                     if (isreported == 1) {
00902                         printf("Message successfully reported/revoked\n");
00903                     }
00904                     else {
00905                         printf("Unable to report/revoke message\n");
00906                     }
00907                     message_cleanup(&m);
00908                     goto finish;
00909                 }
00910                 else if (message_write(out_fd, &m) >= 0) {
00911                     result = m.is_spam;
00912                     if ((flags & SPAMC_CHECK_ONLY) && result != EX_TOOBIG) {
00913                         message_cleanup(&m);
00914                         ret = result;
00915                     }
00916                     else {
00917                         message_cleanup(&m);
00918                         if (use_exit_code && result != EX_TOOBIG) {
00919                             ret = result;
00920                         }
00921                     }
00922                     goto finish;
00923                 }
00924             }
00925         }
00926     }
00927     free(username);
00928 
00929 /* FAIL: */
00930 #if 1
00931     result = m.is_spam;
00932     if (ret != EX_OK) {
00933         result = ret;
00934     }
00935 #endif
00936     if (flags & (SPAMC_LEARN|SPAMC_PING) ) {
00937         get_output_fd(&out_fd);
00938         message_cleanup(&m);
00939     }
00940     else {
00941         if (flags & (SPAMC_CHECK_ONLY | SPAMC_REPORT | SPAMC_REPORT_IFSPAM)) {
00942             get_output_fd(&out_fd);
00943             full_write(out_fd, 1, "0/0\n", 4);
00944         }
00945         else if (flags & SPAMC_SYMBOLS) {
00946             /* bug 4991: -y should only output a blank line on connection failure */
00947             get_output_fd(&out_fd);
00948             full_write(out_fd, 1, "\n", 1);
00949         }
00950         else {
00951             /* bug 5412: spamc -x should not output the message on error */
00952             if ((flags & SPAMC_SAFE_FALLBACK) || result == EX_TOOBIG) {
00953                 get_output_fd(&out_fd);
00954                 message_dump(STDIN_FILENO, out_fd, &m);
00955             }
00956             /* else, do NOT get_output_fd() (bug 5478) */
00957         }
00958 
00959         message_cleanup(&m);
00960         if (ret == EX_TOOBIG) {
00961             ret = EX_OK;    /* too big always means exit(0) -- bug 5412 */
00962         }
00963         else if (flags & SPAMC_SAFE_FALLBACK) {
00964             ret = EX_OK;
00965         }
00966         else if (use_exit_code) {
00967             ret = result;
00968         }
00969     }
00970     
00971 finish:
00972 #ifdef _WIN32
00973     WSACleanup();
00974 #endif
00975     return ret;
00976 }

void print_usage void   ) 
 

Definition at line 131 of file spamc.c.

References print_version(), and usg().

Referenced by read_args().

00132 {
00133     print_version();
00134     usg("\n");
00135     usg("Usage: spamc [options] [-e command [args]] < message\n");
00136     usg("\n");
00137     usg("Options:\n");
00138 
00139     usg("  -d, --dest host[,host2]\n"
00140         "                      Specify one or more hosts to connect to.\n"
00141         "                      [default: localhost]\n");
00142     usg("  -H , --randomize    Randomize IP addresses for the looked-up\n"
00143         "                      hostname.\n");
00144     usg("  -p, --port port     Specify port for connection to spamd.\n"
00145         "                      [default: 783]\n");
00146 #ifdef SPAMC_SSL
00147     usg("  -S, --ssl           Use SSL to talk to spamd.\n");
00148 #endif
00149 #ifndef _WIN32
00150     usg("  -U, --socket path   Connect to spamd via UNIX domain sockets.\n");
00151 #endif
00152     usg("  -F, --config path   Use this configuration file.\n");
00153     usg("  -t, --timeout timeout\n"
00154         "                      Timeout in seconds for communications to\n"
00155         "                      spamd. [default: 600]\n");
00156     usg("  --connect-retries retries\n"
00157         "                      Try connecting to spamd this many times\n"
00158         "                      [default: 3]\n");
00159     usg("  --retry-sleep sleep Sleep for this time between attempts to\n"
00160         "                      connect to spamd, in seconds [default: 1]\n");
00161     usg("  -s, --max-size size Specify maximum message size, in bytes.\n"
00162         "                      [default: 500k]\n");
00163     usg("  -u, --username username\n"
00164         "                      User for spamd to process this message under.\n"
00165         "                      [default: current user]\n");
00166 
00167     usg("  -L, --learntype learntype\n"
00168         "                      Learn message as spam, ham or forget to\n"
00169         "                      forget or unlearn the message.\n");
00170 
00171     usg("  -C, --reporttype reporttype\n"
00172         "                      Report message to collaborative filtering\n"
00173         "                      databases.  Report type should be 'report' for\n"
00174         "                      spam or 'revoke' for ham.\n");
00175 
00176     usg("  -B, --bsmtp         Assume input is a single BSMTP-formatted\n"
00177         "                      message.\n");
00178 
00179     usg("  -c, --check         Just print the summary line and set an exit\n"
00180         "                      code.\n");
00181     usg("  -y, --tests         Just print the names of the tests hit.\n");
00182     usg("  -r, --full-spam     Print full report for messages identified as\n"
00183         "                      spam.\n");
00184     usg("  -R, --full          Print full report for all messages.\n");
00185     usg("  --headers           Rewrite only the message headers.\n");
00186     usg("  -E, --exitcode      Filter as normal, and set an exit code.\n");
00187 
00188     usg("  -x, --no-safe-fallback\n"
00189         "                      Don't fallback safely.\n");
00190     usg("  -l, --log-to-stderr Log errors and warnings to stderr.\n");
00191 #ifndef _WIN32
00192     usg("  -e, --pipe-to command [args]\n"
00193         "                      Pipe the output to the given command instead\n"
00194         "                      of stdout. This must be the last option.\n");
00195 #endif
00196     usg("  -h, --help          Print this help message and exit.\n");
00197     usg("  -V, --version       Print spamc version and exit.\n");
00198     usg("  -K                  Keepalive check of spamd.\n");
00199 #ifdef HAVE_ZLIB_H
00200     usg("  -z                  Compress mail message sent to spamd.\n");
00201 #endif
00202     usg("  -f                  (Now default, ignored.)\n");
00203 
00204     usg("\n");
00205 }

void print_version void   ) 
 

Definition at line 116 of file spamc.c.

Referenced by print_usage(), and read_args().

00117 {
00118     printf("%s version %s\n", "SpamAssassin Client", VERSION_STRING);
00119 #ifdef SPAMC_SSL
00120     printf("  compiled with SSL support (%s)\n", OPENSSL_VERSION_TEXT);
00121 #endif
00122 }

int read_args int  argc,
char **  argv,
int *  max_size,
char **  username,
int *  extratype,
struct transport ptrn
 

Does the command line parsing for argv[].

Returns EX_OK or EX_TEMPFAIL if successful. EX_TEMPFAIL is a kludge for the cases where we want in main to return immediately; we can't exit() because on Windows WSACleanup() needs to be called.

Definition at line 215 of file spamc.c.

References transport::connect_retries, EX_OK, EX_OSERR, EX_TEMPFAIL, EX_USAGE, exec_argv, flags, transport::hostname, libspamc_log(), LOG_ERR, no_argument, optional_argument, transport::port, print_usage(), print_version(), required_argument, transport::retry_sleep, transport::socketpath, SPAMC_BSMTP_MODE, SPAMC_CHECK_ONLY, spamc_getopt_long(), SPAMC_HEADERS, SPAMC_LEARN, SPAMC_LOG_TO_STDERR, SPAMC_MAX_MESSAGE_LEN, SPAMC_MODE_MASK, spamc_optarg, spamc_optind, SPAMC_PING, SPAMC_RANDOMIZE_HOSTS, SPAMC_REPORT, SPAMC_REPORT_IFSPAM, SPAMC_REPORT_MSG, SPAMC_SAFE_FALLBACK, SPAMC_SSLV2, SPAMC_SSLV3, SPAMC_SYMBOLS, SPAMC_USE_SSL, SPAMC_USE_ZLIB, timeout, TRANSPORT_TCP, TRANSPORT_UNIX, transport::type, and use_exit_code.

Referenced by main().

00218 {
00219 #ifndef _WIN32
00220     const char *opts = "-BcrRd:e:fyp:t:s:u:L:C:xzSHU:ElhVKF:0:1:2";
00221 #else
00222     const char *opts = "-BcrRd:fyp:t:s:u:L:C:xzSHElhVKF:0:1:2";
00223 #endif
00224     int opt;
00225     int ret = EX_OK;
00226     int longind = 1;
00227 
00228     static struct option longoptions[] = {
00229        { "dest" , required_argument, 0, 'd' },
00230        { "randomize", no_argument, 0, 'H' },
00231        { "port", required_argument, 0, 'p' },
00232        { "ssl", optional_argument, 0, 'S' },
00233        { "socket", required_argument, 0, 'U' },
00234        { "config", required_argument, 0, 'F' },
00235        { "timeout", required_argument, 0, 't' },
00236        { "connect-retries", required_argument, 0, 0 },
00237        { "retry-sleep", required_argument, 0, 1 },
00238        { "max-size", required_argument, 0, 's' },
00239        { "username", required_argument, 0, 'u' },
00240        { "learntype", required_argument, 0, 'L' },
00241        { "reporttype", required_argument, 0, 'C' },
00242        { "bsmtp", no_argument, 0, 'B' },
00243        { "check", no_argument, 0, 'c' },
00244        { "tests", no_argument, 0, 'y' },
00245        { "full-spam", no_argument, 0, 'r' },
00246        { "full", no_argument, 0, 'R' },
00247        { "headers", no_argument, 0, 2 },
00248        { "exitcode", no_argument, 0, 'E' },
00249        { "no-safe-fallback", no_argument, 0, 'x' },
00250        { "log-to-stderr", no_argument, 0, 'l' },
00251        { "pipe-to", required_argument, 0, 'e' },
00252        { "help", no_argument, 0, 'h' },
00253        { "version", no_argument, 0, 'V' },
00254        { "compress", no_argument, 0, 'z' },
00255        { 0, 0, 0, 0} /* last element _must_ be all zeroes */
00256     };
00257     
00258     while ((opt = spamc_getopt_long(argc, argv, opts, longoptions, 
00259                 &longind)) != -1)
00260     {
00261         switch (opt)
00262         {
00263             case 'B':
00264             {
00265                 flags = (flags & ~SPAMC_MODE_MASK) | SPAMC_BSMTP_MODE;
00266                 break;
00267             }
00268             case 'c':
00269             {
00270                 flags |= SPAMC_CHECK_ONLY;
00271                 break;
00272             }
00273             case 'd':
00274             {
00275                 ptrn->type = TRANSPORT_TCP;
00276                 ptrn->hostname = spamc_optarg;        /* fix the ptr to point to this string */
00277                 break;
00278             }
00279 #ifndef _WIN32
00280             case 'e':
00281             {
00282                 int i, j;
00283                 
00284                 /* Allocate memory for the necessary pointers needed to 
00285                  * store the remaining arguments.
00286                  */
00287                 exec_argv = malloc(sizeof(*exec_argv) * (argc - spamc_optind + 2));
00288                 if (exec_argv == NULL) {
00289                     return EX_OSERR;
00290                 }
00291                 
00292                 for (i = 0, j = spamc_optind - 1; j < argc; i++, j++) {
00293                     exec_argv[i] = argv[j];
00294                 }
00295                 exec_argv[i] = NULL;
00296                 
00297                 return EX_OK;
00298             }
00299 #endif
00300             case 'f':
00301             {
00302                 /* obsolete, backwards compat */
00303                 break;
00304             }
00305             case 'K':
00306             {
00307                 flags |= SPAMC_PING;
00308                 break;
00309             }
00310             case 'l':
00311             {
00312                 flags |= SPAMC_LOG_TO_STDERR;
00313                 break;
00314             }
00315             case 'H':
00316             {
00317                 flags |= SPAMC_RANDOMIZE_HOSTS;
00318                 break;
00319             }
00320             case 'p':
00321             {
00322                 ptrn->port = (unsigned short)atoi(spamc_optarg);
00323                 break;
00324             }
00325             case 'r':
00326             {
00327                 flags |= SPAMC_REPORT_IFSPAM;
00328                 break;
00329             }
00330             case 'E':
00331             {
00332                 use_exit_code = 1;
00333                 break;
00334             }
00335             case 'R':
00336             {
00337                 flags |= SPAMC_REPORT;
00338                 break;
00339             }
00340             case 's':
00341             {
00342                 *max_size = atoi(spamc_optarg);
00343                 break;
00344             }
00345 #ifdef SPAMC_SSL
00346             case 'S':
00347             {
00348                 flags |= SPAMC_USE_SSL;
00349                 if (!spamc_optarg || (strcmp(spamc_optarg,"sslv23") == 0)) {
00350                   /* this is the default */
00351                 }
00352                 else if (strcmp(spamc_optarg,"sslv2") == 0) {
00353                   flags |= SPAMC_SSLV2;
00354                 }
00355                 else if (strcmp(spamc_optarg,"sslv3") == 0) {
00356                   flags |= SPAMC_SSLV3;
00357                 }
00358                 else if (strcmp(spamc_optarg,"tlsv1") == 0) {
00359                   flags |= (SPAMC_SSLV2 | SPAMC_SSLV3);
00360                 }
00361                 else {
00362                     libspamc_log(flags, LOG_ERR, "Please specifiy a legal ssl version (%s)", spamc_optarg);
00363                     ret = EX_USAGE;
00364                 }
00365                 break;
00366             }
00367 #endif
00368             case 't':
00369             {
00370                 timeout = atoi(spamc_optarg);
00371                 break;
00372             }
00373             case 'u':
00374             {
00375                 *username = spamc_optarg;
00376                 break;
00377             }
00378             case 'L':
00379             {
00380                 flags |= SPAMC_LEARN;
00381                 if (strcmp(spamc_optarg,"spam") == 0) {
00382                     *extratype = 0;
00383                 }
00384                 else if (strcmp(spamc_optarg,"ham") == 0) {
00385                     *extratype = 1;
00386                 }
00387                 else if (strcmp(spamc_optarg,"forget") == 0) {
00388                     *extratype = 2;
00389                 }
00390                 else {
00391                     libspamc_log(flags, LOG_ERR, "Please specifiy a legal learn type");
00392                     ret = EX_USAGE;
00393                 }
00394                 break;
00395             }
00396         case 'C':
00397             {
00398                 flags |= SPAMC_REPORT_MSG;
00399                 if (strcmp(spamc_optarg,"report") == 0) {
00400                     *extratype = 0;
00401                 }
00402                 else if (strcmp(spamc_optarg,"revoke") == 0) {
00403                     *extratype = 1;
00404                 }
00405                 else {
00406                     libspamc_log(flags, LOG_ERR, "Please specifiy a legal report type");
00407                     ret = EX_USAGE;
00408                 }
00409                 break;
00410             }
00411 #ifndef _WIN32
00412             case 'U':
00413             {
00414                 ptrn->type = TRANSPORT_UNIX;
00415                 ptrn->socketpath = spamc_optarg;
00416                 break;
00417             }
00418 #endif
00419             case 'x':
00420             {
00421                 flags &= (~SPAMC_SAFE_FALLBACK);
00422                 break;
00423             }
00424             case 'y':
00425             {
00426                 flags |= SPAMC_SYMBOLS;
00427                 break;
00428             }
00429             
00430             case '?':
00431             case ':':
00432             {
00433                 libspamc_log(flags, LOG_ERR, "invalid usage");
00434                 ret = EX_USAGE;
00435                 /* FALLTHROUGH */
00436             }
00437             case 'h':
00438             {
00439                 print_usage();
00440                 if (ret == EX_OK)
00441                     ret = EX_TEMPFAIL;
00442                 return(ret);
00443             }
00444             case 'V':
00445             {
00446                 print_version();
00447                 return(EX_TEMPFAIL);
00448             }
00449             case 'z':
00450             {
00451 #ifdef HAVE_ZLIB_H
00452                 flags |= SPAMC_USE_ZLIB;
00453 #else
00454                 libspamc_log(flags, LOG_ERR, "spamc -z support not available");
00455                 ret = EX_USAGE;
00456 #endif
00457                 break;
00458             }
00459             case 0:
00460             {
00461                 ptrn->connect_retries = atoi(spamc_optarg);
00462                 break;
00463             }
00464             case 1:
00465             {
00466                 ptrn->retry_sleep = atoi(spamc_optarg);
00467                 break;
00468             }
00469             case 2:
00470             {
00471                 flags |= SPAMC_HEADERS;
00472                 break;
00473             }
00474         }
00475     }
00476 
00477     if (*max_size > SPAMC_MAX_MESSAGE_LEN) {
00478         libspamc_log(flags, LOG_ERR, "-s parameter is beyond max of %d",
00479                         SPAMC_MAX_MESSAGE_LEN);
00480         ret = EX_USAGE;
00481     }
00482 
00483     /* learning action has to block some parameters */
00484     if (flags & SPAMC_LEARN) {
00485         if (flags & SPAMC_CHECK_ONLY) {
00486             libspamc_log(flags, LOG_ERR, "Learning excludes check only");
00487             ret = EX_USAGE;
00488         }
00489         if (flags & SPAMC_PING) {
00490             libspamc_log(flags, LOG_ERR, "Learning excludes ping");
00491             ret = EX_USAGE;
00492         }
00493         if (flags & SPAMC_REPORT_IFSPAM) {
00494             libspamc_log(flags, LOG_ERR, "Learning excludes report if spam");
00495             ret = EX_USAGE;
00496         }
00497         if (flags & SPAMC_REPORT) {
00498             libspamc_log(flags, LOG_ERR, "Learning excludes report");
00499             ret = EX_USAGE;
00500         }
00501         if (flags & SPAMC_SYMBOLS) {
00502             libspamc_log(flags, LOG_ERR, "Learning excludes symbols");
00503             ret = EX_USAGE;
00504         }
00505         if (flags & SPAMC_REPORT_MSG) {
00506             libspamc_log(flags, LOG_ERR, "Learning excludes reporting to collaborative filtering databases");
00507             ret = EX_USAGE;
00508         }
00509     }
00510     return ret;
00511 }

static void usg char *  str  )  [static]
 

Definition at line 125 of file spamc.c.

Referenced by print_usage().

00126 {
00127     printf("%s", str);
00128 }


Variable Documentation

char** exec_argv
 

Definition at line 99 of file spamc.c.

Referenced by get_output_fd(), and read_args().

int flags = SPAMC_RAW_MODE | SPAMC_SAFE_FALLBACK
 

Definition at line 93 of file spamc.c.

Referenced by check_malloc(), get_current_user(), get_output_fd(), main(), process_message(), and read_args().

int timeout = 600 [static]
 

Definition at line 101 of file spamc.c.

Referenced by main(), and read_args().

int use_exit_code = 0
 

Definition at line 96 of file spamc.c.

Referenced by main(), and read_args().


© sourcejam.com 2005-2008