/***************************************************************************** * HPT --- FTN NetMail/EchoMail Tosser ***************************************************************************** * Copyright (C) 1997-1999 * * Matthias Tichy * * Fido: 2:2433/1245 2:2433/1247 2:2432/605.14 * Internet: mtt@tichy.de * * Grimmestr. 12 Buchholzer Weg 4 * 33098 Paderborn 40472 Duesseldorf * Germany Germany * * This file is part of HPT. * * HPT is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * HPT is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HPT; see the file COPYING. If not, write to the Free * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ***************************************************************************** * $Id: hpt.c,v 1.170.2.1 2003/12/27 21:42:43 d_sergienko Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #ifdef HAS_IO_H #include #endif #ifdef HAS_UNISTD_H #include #endif #if defined(HAS_SYS_SYSEXITS_H) #include #endif #if defined(HAS_SYSEXITS_H) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include "version.h" #include "cvsdate.h" #include "pkt.h" #include "global.h" #include "hpt.h" #include "toss.h" #include "scan.h" #include "fcommon.h" #include "post.h" #include "link.h" #include "areafix.h" #include "query.h" #include "stat.h" #ifdef DO_PERL #include "hptperl.h" #endif #ifdef _MSC_VER #ifdef DO_PERL #include "delayimp.h" /* This is the failure hook, dliNotify = {dliFailLoadLib|dliFailGetProc} */ #if defined(__cplusplus) extern "C" #endif extern PfnDliHook #if (_MSC_VER>=1300) __pfnDliFailureHook2; #else __pfnDliFailureHook; #endif #endif #endif s_log *hpt_log = NULL; s_message **msgToSysop = NULL; s_query_areas *queryAreasHead = NULL; char *scanParmA; char *scanParmF; char force = 0; /* kn: I've really tried not to break it. FIXME: if there is pack and scan options on cmd line - one set of options are lost */ int processExportOptions(int *i, int argc, char **argv) { int rc = 0; while ((*i) < argc-1) { if (argv[(*i)+1][0] == '-' && (argv[(*i)+1][1] == 'w' || argv[(*i)+1][1] == 'W')) { noHighWaters = 1; (*i)++; continue; } /* endif */ if (argv[(*i)+1][0] == '-' && (argv[(*i)+1][1] == 'f' || argv[(*i)+1][1] == 'F')) { if (stricmp(argv[(*i)+1], "-f") == 0) { (*i)++; scanParmF = argv[(*i)+1]; } else { scanParmF = argv[(*i)+1]+2; } /* endif */ rc |= 2; (*i)++; continue; } else if (argv[(*i)+1][0] == '-' && (argv[(*i)+1][1] == 'a' || argv[(*i)+1][1] == 'A')) { if (stricmp(argv[(*i)+1], "-a") == 0) { (*i)++; scanParmA = argv[(*i)+1]; } else { scanParmA = argv[(*i)+1]+2; } /* endif */ rc |= 4; (*i)++; continue; } /* endif */ break; } /* endwhile */ return rc != 0 ? rc : 1; } void start_help(void) { fprintf(stdout,"%s",versionStr); fprintf(stdout,"\nUsage: hpt [-c config] [options]\n"); fprintf(stdout," hpt toss - tossing mail\n"); fprintf(stdout," hpt toss -b[f] - tossing mail from badarea [force]\n"); fprintf(stdout," hpt scan - scanning echomail\n"); fprintf(stdout," hpt scan -w - scanning echomail without highwaters\n"); fprintf(stdout," hpt scan -a - scanning echomail from areas matching \n"); fprintf(stdout," hpt scan -f [filename] - scan only listed areas in this file.\n"); fprintf(stdout," hpt post [options] file - posting a mail (for details run \"hpt post -h\")\n"); fprintf(stdout," hpt pack - packing netmail\n"); fprintf(stdout," hpt pack -a - packing netmail from areas matching \n"); fprintf(stdout," hpt pack -f [filename] - pack netmail only from areas listed in this file\n"); fprintf(stdout," hpt link [areamask] - links messages\n"); fprintf(stdout," hpt link -j [areamask] - link jam areas using CRC (more quickly)\n"); fprintf(stdout," hpt afix [ command] - process areafix\n"); fprintf(stdout," hpt qupd - update queue file and do some areafix jobs\n"); fprintf(stdout," hpt qrep - make report based on information from queue file\n"); fprintf(stdout," hpt relink - refresh area subscription\n"); fprintf(stdout," hpt pause - set pause for links who don't poll our system\n"); fprintf(stdout," hpt -q [options] - quiet mode (no screen output)\n"); } int processCommandLine(int argc, char **argv) { int i = 0; if (argc == 1) start_help(); while (i < argc-1) { i++; if (0 == stricmp(argv[i], "toss")) { cmToss = 1; if (i < argc-1) { if (stricmp(argv[i+1], "-b") == 0) { cmToss = 2; break; } else if (stricmp(argv[i+1], "-bf") == 0) { cmToss = 2; force = 1; break; } } continue; } else if (stricmp(argv[i], "scan") == 0) { cmScan = processExportOptions(&i, argc, argv); continue; } else if (stricmp(argv[i], "pack") == 0) { cmPack = processExportOptions(&i, argc, argv); continue; } else if (stricmp(argv[i], "link") == 0) { if (i < argc-1 && stricmp(argv[i+1], "-j") == 0) { i++; linkJamByCRC = 1; } if (i < argc-1) { i++; xstrcat(&linkName,argv[i]); } cmLink = 1; continue; } else if (stricmp(argv[i], "afix") == 0) { if (i < argc-1) { i++; string2addr(argv[i], &afixAddr); if (i < argc-1) { i++; xstrcat(&afixCmd,argv[i]); } else printf("parameter missing after \"%s\"!\n", argv[i]); } cmAfix = 1; continue; } else if (stricmp(argv[i], "afix!") == 0) { if (i < argc-1) { i++; string2addr(argv[i], &afixAddr); if (i < argc-1) { i++; xstrcat(&afixCmd,argv[i]); } else printf("parameter missing after \"%s\"!\n", argv[i]); } cmAfix = 1; cmNotifyLink = 1; continue; } else if (stricmp(argv[i], "post") == 0) { ++i; post(argc, (unsigned*)&i, argv); } else if (stricmp(argv[i], "relink") == 0) { i++; relink(argv[i]); } else if (stricmp(argv[i], "qupd") == 0) { cmQueue |= 2; } else if (stricmp(argv[i], "qrep") == 0) { cmQueue |= 4; } else if (stricmp(argv[i], "-c") == 0) { i++; if (argv[i]!=NULL) xstrcat(&cfgFile, argv[i]); else printf("parameter missing after \"%s\"!\n", argv[i-1]); continue; } else if (stricmp(argv[i], "-q") == 0) { quiet = 1; continue; } else if (stricmp(argv[i], "-h") == 0) { start_help(); return 1; } else if (stricmp(argv[i], "pause") == 0) { cmPause = 1; continue; } else { printf("Unrecognized commandline option \"%s\"!\n", argv[i]); return EX_USAGE; } } /* endwhile */ return argc; } void allDiff(char *nam, char *var, ...) { va_list ap; char *ptr; struct diffCmp { char *name; char *var; } *diffData; int ncmp, i, j; for (va_start(ap, var), ncmp = 1; va_arg(ap, char *) != NULL; ) { ptr = va_arg(ap, char *); /* variable may be set ti NULL */ ncmp++; } diffData = safe_malloc(ncmp * sizeof(struct diffCmp)); diffData[0].name = nam; diffData[0].var = var; for (va_start(ap, var), i=1; ilockfile!=NULL && fexist(config->lockfile)) { if ((f = fopen(config->lockfile, "rt"))==NULL) { fprintf(stderr,"Can't open file: \"%s\"\n",config->lockfile); exit_hpt("Can't open lock-file",0); } fscanf(f, "%lu\n", &pid); fclose(f); /* Checking process PID */ #ifdef __OS2__ if (DosKillProcess(DKP_PROCESSTREE, pid) == ERROR_NOT_DESCENDANT) { #elif UNIX if (kill(pid, 0) == 0) { #else if (stat(config->lockfile, &stat_file) != -1) { time_cur = time(NULL); locklife = (time_cur - stat_file.st_mtime)/60; } if (locklife < 180) { #endif fprintf(stderr,"lock file found! exit...\n"); disposeConfig(config); exit(1); } else { remove(config->lockfile); createLockFile(config->lockfile); } } else if (config->lockfile!=NULL) createLockFile(config->lockfile); #endif if (config->lockfile) { lock_fd = lockFile(config->lockfile, config->advisoryLock); if( lock_fd < 0 ) { disposeConfig(config); exit(EX_CANTCREAT); } } /* open Logfile */ if (config->logFileDir) { xstrscat(&buff, config->logFileDir, LogFileName, NULL); hpt_log = openLog(buff, versionStr, config); if (hpt_log && quiet) hpt_log->logEcho=0; /* Don't display messages */ nfree(buff); } else fprintf(stderr,"logFileDir not defined, there will be no log created!\n"); if (config->addrCount == 0) exit_hpt("at least one addr must be defined",1); if (config->linkCount == 0) exit_hpt("at least one link must be specified",1); if (config->outbound == NULL) exit_hpt("you must set outbound in fidoconfig first",1); if (config->tempOutbound == NULL) exit_hpt("you must set tempOutbound in fidoconfig first",1); if (config->inbound == NULL && config->protInbound == NULL) exit_hpt("you must set Inbound or protInbound in fidoconfig first",1); if (config->tempInbound == NULL) exit_hpt("you must set tempInbound in fidoconfig first",1); if (config->msgBaseDir==NULL) exit_hpt("No msgBaseDir specified in config file!",1); if (config->dupeHistoryDir==NULL) exit_hpt("No dupeHistoryDir specified in config file!",1); if (config->dupeArea.areaName==NULL) exit_hpt("you must define DupeArea!",1); if (config->dupeArea.fileName==NULL) exit_hpt("DupeArea can not be passthrough!",1); if (config->badArea.areaName==NULL) exit_hpt("you must define BadArea!",1); if (config->badArea.fileName==NULL) exit_hpt("BadArea can not be passthrough!",1); if (config->netMailAreaCount>0) { if (config->netMailAreas[0].fileName==NULL) exit_hpt("First NetmailArea can not be passthrough!",1); } else exit_hpt("You must define NetmailArea!",1); allDiff ( "Inbound", config->inbound, "tempInbound", config->tempInbound, "protInbound", config->protInbound, "localInbound", config->localInbound, "outbound", config->outbound, "tempOutbound", config->tempOutbound, NULL); /* load recoding tables */ initCharsets(); if (config->outtab) getctab(outtab, (unsigned char*) config->outtab); if (config->intab) getctab(intab, (unsigned char*) config->intab); w_log(LL_START, "Start"); } int isFreeSpace(char *path) { unsigned long sp; sp = fc_GetDiskFreeSpace(path); if (sp < config->minDiskFreeSpace*1024) { fprintf(stderr, "no free space in %s! (needed %d mb, available %d mb).\n", path, config->minDiskFreeSpace, (unsigned)(sp/1024)); exit_hpt("no free disk space!",0); } return 0; } #ifdef _MSC_VER #ifdef DO_PERL FARPROC WINAPI ourhook(unsigned dliNotify,PDelayLoadInfo pdli) { /* print error message and exit */ char msg[128]; memset(msg,0,sizeof(msg)); sprintf(msg,"Loading of %s failed - exiting ",pdli->szDll); w_log(LL_CRIT,msg); /* standart deinit sequence */ /* deinit SMAPI */ MsgCloseApi(); w_log(LL_STOP, "End"); closeLog(hpt_log); doneCharsets(); nfree(versionStr); if (config->lockfile) { close(lock_fd); remove(config->lockfile); } disposeConfig(config); nfree(cfgFile); exit(EX_UNAVAILABLE); return 0; } #endif #endif int main(int argc, char **argv) { struct _minf m; unsigned int i, rc; #if defined ( __NT__ ) #define TITLESIZE 256 char *title=NULL, oldtitle[ TITLESIZE ]; #endif versionStr = GenVersionStr( "hpt", VER_MAJOR, VER_MINOR, VER_PATCH, VER_BRANCH, cvs_date ); rc = processCommandLine(argc, argv); if ((rc==1 || rc==EX_USAGE) && config!=NULL) if (config->lockfile) { close(lock_fd); remove(config->lockfile); disposeConfig(config); doneCharsets(); } if (rc==1){ nfree(versionStr); exit(EX_OK); } if (rc==EX_USAGE){ nfree(versionStr); exit(EX_USAGE); } if (config==NULL) processConfig(); #if defined ( __NT__ ) if (config->setConsoleTitle) { GetConsoleTitleA( oldtitle, TITLESIZE ); if( versionStr ){ xstrscat( &title, "Highly Portable Tosser ", versionStr+4, NULL); /* versionStr is "hpt ..." */ SetConsoleTitleA( title ); nfree(title); }else SetConsoleTitleA( "Highly Portable Tosser" ); } #endif /* check for free space */ if (config->minDiskFreeSpace) { isFreeSpace(config->tempInbound); if (stricmp(config->msgBaseDir,"passthrough")!=0) isFreeSpace(config->msgBaseDir); for (i=0; ilinkCount; i++) { if (config->links[i].msgBaseDir && stricmp(config->links[i].msgBaseDir,"passthrough")!=0) isFreeSpace(config->links[i].msgBaseDir); } } if ( initSMAPI == -1 ) { /* init SMAPI */ initSMAPI = 0; m.req_version = 2; m.def_zone = (UINT16) config->addr[0].zone; if (MsgOpenApi(&m) != 0) { exit_hpt("MsgApiOpen Error",1); } } #ifdef _MSC_VER #ifdef DO_PERL #if _MSC_VER>=1300 __pfnDliFailureHook2=ourhook; #else __pfnDliFailureHook=ourhook; #endif /* attempt to start Perl */ PerlStart(); #endif #endif msgToSysop = (s_message**) safe_malloc(config->addrCount * sizeof(s_message*)); for (i = 0; i < config->addrCount; i++) { /* Some results of wrong patching ? A memleak anyway * msgToSysop[i] = (s_message*)malloc(sizeof(s_message)); */ msgToSysop[i] = NULL; } tossTempOutbound(config->tempOutbound); if (1 == cmToss) toss(); if (cmToss == 2) tossFromBadArea(force); if (cmScan == 1) scanExport(SCN_ALL | SCN_ECHOMAIL, NULL); if (cmScan & 2) scanExport(SCN_FILE | SCN_ECHOMAIL, scanParmF); if ((cmScan & 4) && scanParmA) scanExport(SCN_NAME | SCN_ECHOMAIL, scanParmA); if (cmAfix == 1) afix(afixAddr, afixCmd); nfree(afixCmd); if (cmPack == 1) scanExport(SCN_ALL | SCN_NETMAIL, NULL); if (cmPack & 2) scanExport(SCN_FILE | SCN_NETMAIL, scanParmF); if ((cmPack & 4) && scanParmA) scanExport(SCN_NAME | SCN_NETMAIL, scanParmA); if (cmLink == 1) { if (linkName && (strstr(linkName,"*")||strstr(linkName,"?"))) { for (i=0; i < config->echoAreaCount; i++) if (patimat(config->echoAreas[i].areaName, linkName)) linkAreas(config->echoAreas[i].areaName); for (i=0; i < config->localAreaCount; i++) if (patimat(config->localAreas[i].areaName, linkName)) linkAreas(config->localAreas[i].areaName); for (i=0; i < config->netMailAreaCount; i++) if (patimat(config->netMailAreas[i].areaName, linkName)) linkAreas(config->netMailAreas[i].areaName); } else linkAreas(linkName); } nfree(linkName); #ifdef DO_PERL perldone(); #endif writeMsgToSysop(); for (i = 0; i < config->addrCount; i++) { if (msgToSysop[i]) freeMsgBuffers(msgToSysop[i]); nfree(msgToSysop[i]); } if (cmPause || config->autoPassive) autoPassive(); if (cmQueue & 2) af_QueueUpdate(); if (cmQueue & 4) af_QueueReport(); /* save forward requests info */ af_CloseQuery(); nfree(msgToSysop); #ifdef ADV_STAT if (config->advStatisticsFile != NULL) upd_stat(config->advStatisticsFile); #endif /* deinit SMAPI */ MsgCloseApi(); w_log(LL_STOP, "End"); closeLog(); doneCharsets(); nfree(versionStr); if (config->lockfile) { FreelockFile(config->lockfile ,lock_fd); } #if defined ( __NT__ ) if (config->setConsoleTitle) SetConsoleTitleA(oldtitle); #endif disposeConfig(config); nfree(cfgFile); return 0; }