summaryrefslogtreecommitdiff
path: root/tools/ltgrey.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/ltgrey.c')
-rw-r--r--tools/ltgrey.c153
1 files changed, 153 insertions, 0 deletions
diff --git a/tools/ltgrey.c b/tools/ltgrey.c
new file mode 100644
index 0000000..afdb4c1
--- /dev/null
+++ b/tools/ltgrey.c
@@ -0,0 +1,153 @@
+#include <iostream>
+#include <stdlib.h> /* for exit(), atoi() */
+
+#include "libltgrey.h"
+#include "utils.h"
+#include "qq_exit_codes.h"
+
+using namespace std;
+pid_t mypid;
+string progname;
+
+#define exeunt exit
+
+// forward reference:
+void scan(const string progid, const string p, const int copies=1);
+
+int main(int _argc, char** _argv){
+ mypid = getpid();
+ int argc(_argc);
+ char** argv(_argv);
+ const string dirname("/var/qmail/greylist");
+ whatsit foo(argv[0], dirname); argc--; argv++;
+ int scanmode(0);
+ int copies(1);
+ int penalty(0);
+ int stain(0);
+ int check(0);
+ while (argc > 0) {
+ string arg = argv[0]; argc--; argv++;
+ if (prefix(arg, "-scan")) {
+ scanmode++;
+ } else if (prefix(arg, "-copy")) {
+ copies++;
+ } else if (prefix(arg, "-verbose")) {
+ foo.verbosity++;
+ } else if (prefix(arg, "-check")) {
+ check++;
+ } else if (prefix(arg, "-penalize")
+ || prefix(arg, "-penalty")) {
+ if (!argc){
+ cerr << "Option '" << arg << "' requires an argument" << endl;
+ exeunt(ex_syserr);
+ }
+ penalty = atoi(*argv++); argc--;
+ } else if (prefix(arg, "-stain")) {
+ if (!argc){
+ cerr << "Option '" << arg << "' requires an argument" << endl;
+ exeunt(ex_syserr);
+ }
+ stain = atoi(*argv++); argc--;
+ } else if (prefix(arg, "-suffix")) {
+ if (!argc){
+ cerr << "Option '" << arg << "' requires an argument" << endl;
+ exeunt(ex_syserr);
+ }
+ foo.suffix += *argv++; argc--;
+ } else {
+ cerr << "Unrecognized arg: " << arg << endl;
+ exeunt(ex_syserr);
+ }
+ }
+ if (foo.setup()) return ex_syserr;
+
+ if (scanmode) {
+ scan(foo.progid, dirname, copies);
+ return 0;
+ }
+
+ int sts = foo.doit(penalty, stain);
+ if (sts == ex_syserr) return sts;
+ if (!check) return ex_good;
+
+// check mode ... perform some extra checks.
+// Probably a better design would be to
+// (a) make more thorough DNS checks, and
+// (b) move all the DNS checking to a separate module
+
+ int dns = foo.check_dns();
+ if (dns == ex_syserr || dns == ex_spam) return dns;
+ exeunt(sts);
+}
+
+//////////////////////////////////////////////////////////////////////
+// requires apt-get install libboost-filesystem-dev:
+#include <boost/filesystem.hpp>
+#include <iomanip>
+#include <sys/types.h> /* for stat(), getaddrinfo() */
+#include <sys/stat.h> /* for stat() */
+#include <unistd.h> /* for stat() */
+#include <stdio.h> /* for perror */
+#include <sstream>
+
+const int minute(60);
+const int hour(60*minute);
+const int day(24*hour);
+
+const int minimum_age(15*minute);
+const int maximum_age(32*day);
+const int probation(4*hour);
+
+void scan(const string progid, const string p, const int copies){
+ timeval now;
+ gettimeofday(&now, NULL);
+ using namespace boost::filesystem;
+
+ if (is_directory(p)) {
+ for (directory_iterator itr(p); itr!=directory_iterator(); ++itr) {
+ string basename = itr->path().filename();
+ for (int ii = 0; ii < copies; ii++)
+ cout << setw(20) << left << basename << ' '; // display filename only
+ if (is_regular_file(itr->status())) {
+// cout << " [" << file_size(itr->path()) << ']';
+ struct stat mystat;
+ string fn = p + "/" + basename;
+ int rslt = stat(fn.c_str(), &mystat);
+ if (rslt != 0){
+ cerr << progid << ": stat failed for '"
+ << fn << "' : ";
+ perror(0);
+ }
+ int mod_age = now.tv_sec - mystat.st_mtime;
+ int ac_age = now.tv_sec - mystat.st_atime;
+ cout << setw(10) << time_out(mod_age)
+ << " " << setw(10) << time_out(ac_age);
+ if (0) {
+
+ } else if (mod_age < 0) {
+ cout << " penalty";
+ } else if (mod_age < ac_age) {
+ cout << " parole";
+ } else if (mod_age - ac_age < minimum_age // early bird, or completely unused
+ && mod_age > probation) { // did not diligently resubmit
+ cout << " disprobation";
+ if (mod_age != ac_age) cout << "!";
+ } else if (mod_age < minimum_age) {
+ cout << " young";
+ if (mod_age != ac_age) cout << "!";
+ } else if (mod_age == ac_age) {
+ cout << " unused";
+ } else if (mod_age > maximum_age) {
+ cout << " expired";
+ } else {
+ cout << " OK";
+ }
+ }
+ cout << '\n';
+ }
+ }
+ else {
+ // starting point is not a directory:
+ cout << (exists(p) ? "Found: " : "Not found: ") << p << '\n';
+ }
+}