Import ezmlm-idx 0.40
[ezmlm] / ezmlm-limit.c
diff --git a/ezmlm-limit.c b/ezmlm-limit.c
new file mode 100644 (file)
index 0000000..9e21774
--- /dev/null
@@ -0,0 +1,134 @@
+/*$Id: ezmlm-limit.c,v 1.2 1999/10/31 18:58:48 lindberg Exp $*/
+/*$Name: ezmlm-idx-040 $*/
+
+#include <sys/types.h>
+#include "stralloc.h"
+#include "substdio.h"
+#include "readwrite.h"
+#include "strerr.h"
+#include "sig.h"
+#include "lock.h"
+#include "getconf.h"
+#include "fmt.h"
+#include "now.h"
+#include "sgetopt.h"
+#include "error.h"
+#include "errtxt.h"
+#include "idx.h"
+
+#define FATAL "ezmlm-limit: fatal: "
+#define INFO "ezmlm-limit: info: "
+
+unsigned long deltasecs = LIMSECS;     /* interval to test over (seconds) */
+unsigned long deltanum = LIMMSG;       /* max no messages in interval */
+                                       /* see idx.h. Usually 30 msg/3600 secs*/
+int flagd = 0;                         /* =0 create modpost, =1 ignore */
+                                       /* excess, =2 defer excess */
+int flagmod;                           /* list moderated */
+int flagloop;
+char *fn = TXT_LOOPNUM;
+
+void die_usage()
+{
+  strerr_die1x(100,
+       "ezmlm-limit: usage: ezmlm-limit [-f file] [-dDF] [-n messages]"
+       " [-t secs] dir");
+}
+
+void die_nomem() { strerr_die2x(111,FATAL,ERR_NOMEM); }
+
+void die_new() { strerr_die4sys(111,FATAL,ERR_WRITE,fn,": "); }
+
+stralloc line = {0};
+
+substdio ssnew;
+char newbuf[16];
+
+char strnum[FMT_ULONG];
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+  char *dir;
+  int opt;
+  unsigned int pos;
+  unsigned long num, loopnum, when;
+  unsigned long loopwhen = 0L;
+  unsigned long numwhen = 0L;
+  int fd,fdlock;
+
+  (void) umask(022);
+  sig_pipeignore();
+  when = (unsigned long) now();
+
+  while ((opt = getopt(argc,argv,"dDf:Fn:t:")) != opteof)
+    switch(opt) {
+      case 'd': flagd = 1; break;
+      case 'D': flagd = 0; break;
+      case 'f': if (optarg && *optarg) fn = optarg; break;
+      case 'F': fn = TXT_LOOPNUM;
+      case 'n':
+                if (optarg)
+                  scan_ulong(optarg,&deltanum);
+                break;
+      case 't':
+                if (optarg)
+                  scan_ulong(optarg,&deltasecs);
+                break;
+      default:
+       die_usage();
+  }
+
+  dir = argv[optind++];
+  if (!dir) die_usage();
+
+  if (chdir(dir) == -1)
+    strerr_die4sys(111,FATAL,ERR_SWITCH,dir,": ");
+
+  if (argv[optind])
+    die_usage();       /* avoid common error of putting options after dir */
+  if ((flagmod = getconf_line(&line,"modpost",0,FATAL,dir)))
+    _exit(0);          /* already mod */
+                       /* lock for num and for writing loopnum */
+  fdlock = open_append("lock");
+  if (fdlock == -1)
+    strerr_die4sys(111,FATAL,ERR_OPEN,dir,"/lock: ");
+  if (lock_ex(fdlock) == -1)
+    strerr_die4sys(111,FATAL,ERR_OBTAIN,dir,"/lock: ");
+
+  if (!getconf_line(&line,"num",0,FATAL,dir))
+    _exit(99);                                         /* no msgs */
+  if(!stralloc_0(&line)) die_nomem();
+  pos = scan_ulong(line.s,&num);                       /* current msg */
+  if ((flagloop = getconf_line(&line,fn,0,FATAL,dir))) {
+    if(!stralloc_0(&line)) die_nomem();
+    pos = scan_ulong(line.s,&loopnum);                 /* msg when written */
+    if (line.s[pos] == ':')
+      scan_ulong(line.s+pos+1,&loopwhen);              /* time written */
+  }
+  if (!flagloop || loopwhen + deltasecs < when || loopwhen > when) {
+                                       /* loopnum too old, bad or not there */
+      fd = open_trunc(fn);             /* no need to write crash-proof */
+      if (fd == -1) die_new();
+      substdio_fdbuf(&ssnew,write,fd,newbuf,sizeof(newbuf));
+      if (substdio_put(&ssnew,strnum,fmt_ulong(strnum,num)) == -1) die_new();
+      if (substdio_puts(&ssnew,":") == -1) die_new();
+      if (substdio_put(&ssnew,strnum,fmt_ulong(strnum,when)) == -1) die_new();
+      if (substdio_puts(&ssnew,"\n") == -1) die_new();
+      if (substdio_flush(&ssnew) == -1) die_new();
+      close(fd);
+  } else if (num >= loopnum + deltanum) {      /* excess messages */
+    if (!flagd) {
+      if ((fd = open_append("modpost")) == -1) /* create dir/modpost */
+         strerr_die3sys(111,FATAL,ERR_WRITE,"subpost:");
+      else {
+        close(fd);
+        unlink(fn);
+        strerr_die2x(0,INFO,ERR_EXCESS_MOD);
+      }
+    } else
+        strerr_die2x(111,FATAL,ERR_EXCESS_DEFER);
+  }
+  _exit(0);
+}