00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "config.h"
00020 #include "version.h"
00021 #include "libspamc.h"
00022 #include "utils.h"
00023 #include "spamc.h"
00024
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <string.h>
00028
00029 #include "getopt.h"
00030
00031 #ifdef _WIN32
00032 #include <io.h>
00033 #include <fcntl.h>
00034 #include <process.h>
00035 #else
00036 #include <syslog.h>
00037 #include <unistd.h>
00038 #include <netdb.h>
00039 #include <sys/types.h>
00040 #include <sys/socket.h>
00041 #include <netinet/in.h>
00042 #include <netinet/tcp.h>
00043 #include <arpa/inet.h>
00044 #endif
00045
00046 #ifdef SPAMC_SSL
00047 #include <openssl/crypto.h>
00048 #ifndef OPENSSL_VERSION_TEXT
00049 #define OPENSSL_VERSION_TEXT "OpenSSL"
00050 #endif
00051 #endif
00052
00053 #ifdef HAVE_SYSEXITS_H
00054 #include <sysexits.h>
00055 #endif
00056 #ifdef HAVE_ERRNO_H
00057 #include <errno.h>
00058 #endif
00059 #ifdef HAVE_SYS_ERRNO_H
00060 #include <sys/errno.h>
00061 #endif
00062 #ifdef HAVE_TIME_H
00063 #include <time.h>
00064 #endif
00065 #ifdef HAVE_SYS_TIME_H
00066 #include <sys/time.h>
00067 #endif
00068 #ifdef HAVE_SIGNAL_H
00069 #include <signal.h>
00070 #endif
00071 #ifdef HAVE_PWD_H
00072 #include <pwd.h>
00073 #endif
00074
00075
00076 #if (defined(__sun__) && defined(__sparc__) && !defined(__svr4__)) \
00077 || (defined(__sgi)) \
00078 || (defined(__osf__)) \
00079 || (defined(hpux) || defined(__hpux)) \
00080 || (defined(__CYGWIN__))
00081
00082 extern int spamc_optind;
00083 extern char *spamc_optarg;
00084
00085 #endif
00086
00087 #ifdef _WIN32
00088 char *__progname = "spamc";
00089 #endif
00090
00091
00092
00093 int flags = SPAMC_RAW_MODE | SPAMC_SAFE_FALLBACK;
00094
00095
00096 int use_exit_code = 0;
00097
00098
00099 char **exec_argv;
00100
00101 static int timeout = 600;
00102
00103
00104 void
00105 check_malloc (void *ptr)
00106 {
00107 if(ptr == NULL) {
00108 libspamc_log(flags, LOG_ERR,
00109 "Error allocating memory using malloc\n");
00110
00111 exit(EX_OSERR);
00112 }
00113 }
00114
00115 void
00116 print_version(void)
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 }
00123
00124 static void
00125 usg(char *str)
00126 {
00127 printf("%s", str);
00128 }
00129
00130 void
00131 print_usage(void)
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 }
00206
00214 int
00215 read_args(int argc, char **argv,
00216 int *max_size, char **username, int *extratype,
00217 struct transport *ptrn)
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}
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;
00277 break;
00278 }
00279 #ifndef _WIN32
00280 case 'e':
00281 {
00282 int i, j;
00283
00284
00285
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
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
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
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
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 }
00512
00513
00514
00515
00516
00517
00518
00519
00520 int
00521 combine_args(char *config_file, int argc, char **argv,
00522 int *combo_argc, char **combo_argv)
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) {
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++;
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
00561 tok = NULL;
00562 *combo_argc+=1;
00563 }
00564 }
00565
00566 fclose(config);
00567
00568
00569 for(i=1; i<argc; i++) {
00570 combo_argv[*combo_argc] = strdup(argv[i]);
00571 check_malloc(combo_argv[*combo_argc]);
00572
00573 *combo_argc+=1;
00574 }
00575 return EX_OK;
00576 }
00577
00578 void
00579 get_output_fd(int *fd)
00580 {
00581 #ifndef _WIN32
00582 int pipe_fds[2];
00583 pid_t pid;
00584 #endif
00585
00586 if (*fd != -1)
00587 return;
00588
00589
00590
00591
00592 if (exec_argv == NULL) {
00593 *fd = STDOUT_FILENO;
00594 return;
00595 }
00596
00597 #ifndef _WIN32
00598
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
00611
00612
00613
00614
00615
00616 close(pipe_fds[0]);
00617 *fd = pipe_fds[1];
00618 return;
00619 }
00620
00621
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
00628 close(pipe_fds[0]);
00629
00630
00631 execv(exec_argv[0], exec_argv);
00632
00633
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 }
00640
00641
00652 int
00653 get_current_user(char **username)
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
00669
00670
00671 errno = 0;
00672 curr_user = getpwuid(geteuid());
00673 if (curr_user == NULL) {
00674 perror("getpwuid() failed");
00675 goto fail;
00676 }
00677
00678
00679
00680
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
00694
00695
00696 if (flags & SPAMC_CHECK_ONLY) {
00697 printf("0/0\n");
00698 return EX_NOTSPAM;
00699 }
00700 return EX_OSERR;
00701 }
00702
00703
00704 int
00705 main(int argc, char *argv[])
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
00719
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
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
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
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
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
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
00782
00783
00784 srand(getpid() ^ time(NULL));
00785 }
00786
00787
00788
00789
00790
00791
00792
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;
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
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
00947 get_output_fd(&out_fd);
00948 full_write(out_fd, 1, "\n", 1);
00949 }
00950 else {
00951
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
00957 }
00958
00959 message_cleanup(&m);
00960 if (ret == EX_TOOBIG) {
00961 ret = EX_OK;
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 }