Import ezmlm-idx 0.40
[ezmlm] / ezmlm-tstdig.c
diff --git a/ezmlm-tstdig.c b/ezmlm-tstdig.c
new file mode 100644 (file)
index 0000000..dc073ea
--- /dev/null
@@ -0,0 +1,176 @@
+/*$Id: ezmlm-tstdig.c,v 1.17 1999/03/20 16:43:42 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 "getconf.h"
+#include "env.h"
+#include "fmt.h"
+#include "now.h"
+#include "lock.h"
+#include "sgetopt.h"
+#include "errtxt.h"
+#include "idx.h"
+
+#define FATAL "ezmlm-tstdig: fatal: "
+
+void die_usage()
+{
+  strerr_die1x(100,"ezmlm-tstdig: usage: ezmlm-tstdig [-k kbytes] [-m messages] [-t hours] dir");
+}
+
+void die_nomem() { strerr_die2x(111,FATAL,ERR_NOMEM); }
+
+stralloc line = {0};
+
+substdio ssnum;
+char numbuf[16];
+
+char strnum[FMT_ULONG];
+
+int flaglocal = 0;
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+  char *dir;
+  char *local;
+  char *def;
+  int opt;
+  unsigned int pos;
+  unsigned long num, digsize, dignum;
+  unsigned long cumsize = 0L;
+  unsigned long deltanum = 0L;
+  unsigned long deltawhen = 0L;
+  unsigned long deltasize = 0L;
+  unsigned long when, tsttime, digwhen;
+  int fd,fdlock;
+
+  (void) umask(022);
+  sig_pipeignore();
+  when = (unsigned long) now();
+
+  while ((opt = getopt(argc,argv,"k:t:m:vV")) != opteof)
+    switch(opt) {
+      case 'k':
+                if (optarg)
+                  scan_ulong(optarg,&deltasize);
+                break;
+      case 't':
+                if (optarg)    /* hours */
+                  scan_ulong(optarg,&deltawhen);
+                break;
+      case 'm':
+                if (optarg)
+                  scan_ulong(optarg,&deltanum);
+                break;
+      case 'v':
+      case 'V': strerr_die2x(0,"ezmlm-tstdig version: ",EZIDX_VERSION);
+      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 (!getconf_line(&line,"num",0,FATAL,dir))
+    _exit(99);         /* no msgs no shirt -> no digest */
+  if(!stralloc_0(&line)) die_nomem();
+  pos = scan_ulong(line.s,&num);
+  if (line.s[pos] == ':')
+    scan_ulong(line.s+pos+1,&cumsize);
+
+  if (getconf_line(&line,"dignum",0,FATAL,dir)) {
+    if(!stralloc_0(&line)) die_nomem();
+    pos = scan_ulong(line.s,&dignum);
+    if (line.s[pos] == ':')
+      pos += 1 + scan_ulong(line.s+pos+1,&digsize);
+    if (line.s[pos] == ':')
+      scan_ulong(line.s+pos+1,&digwhen);
+  } else {
+    dignum = 0L;       /* no file, not done any digest */
+    digsize = 0L;      /* nothing digested */
+    digwhen = 0L;      /* will force a digest, but the last one was eons  */
+                       /* ago. ezmlm-get sends it out only if there are   */
+                       /* messages. This is as it should for new lists.   */
+  }
+  local = env_get("LOCAL");
+  if (local && *local) {                       /* in editor or manager */
+    def = env_get("DEFAULT");
+    if (def && *def) {                         /* qmail>=1.02 and manager */
+      if (!case_starts(def,"dig") || case_starts(def,"digest-"))
+        _exit(0);
+    } else {                           /* older qmail versions or editor */
+      if (!getconf_line(&line,"inlocal",0,FATAL,dir)) {
+       flaglocal = 1;
+      } else {
+       pos = str_len(local);
+       if (pos <= line.len) {          /* maybe qmail>=1.02 and editor */
+         flaglocal = 1;                /* editor and qmail>=1.02. No harm */
+                                       /* if we're wrong */
+       } else {                        /* older qmail */
+         if (case_diffb(local,line.len,line.s))        /* local */
+           flaglocal = 1;              /* minimal harm */
+          else if (pos < line.len +4 ||        /* in manager and non-digest */
+               !case_starts(local+line.len,"-dig"))
+           _exit(0);
+          else if (case_starts(local+line.len,"-digest-"))
+           _exit(0);
+       }
+      }
+    }
+  }
+
+  if (!deltawhen && !deltasize && !deltanum) _exit(0);
+  if ((deltawhen && ((digwhen + deltawhen * 3600L) <= when)) ||
+      (deltasize && ((digsize + (deltasize << 2)) <= cumsize)) ||
+      (deltanum && ((dignum + deltanum) <= num))) {    /* digest! */
+    if (flaglocal) {   /* avoid multiple digests. Of course, ezmlm-tstdig*/
+                       /* belongs in ezmlm-digest, but it's too late ....*/
+      fdlock = open_append("lock");
+      if (fdlock == -1)
+        strerr_die2sys(111,FATAL,ERR_OPEN_LOCK);
+      if (lock_ex(fdlock) == -1) {
+        close(fdlock);
+        strerr_die2sys(111,FATAL,ERR_OBTAIN_LOCK);
+      }
+      getconf_line(&line,"tstdig",0,dir,FATAL);
+      if (!stralloc_0(&line)) die_nomem();
+      scan_ulong(line.s,&tsttime);     /* give digest 1 h to complete */
+                                       /* nobody does digests more often */
+      if ((tsttime + 3600L < when) || (tsttime <= digwhen)) {
+        fd = open_trunc("tstdign");
+        if (fd == -1)
+          strerr_die6sys(111,FATAL,ERR_CREATE,dir,"/","tstdign",": ");
+        substdio_fdbuf(&ssnum,write,fd,numbuf,sizeof(numbuf));
+        if (substdio_put(&ssnum,strnum,fmt_ulong(strnum,when)) == -1)
+          strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/","tstdign",": ");
+        if (substdio_puts(&ssnum,"\n") == -1)
+          strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/","tstdign",": ");
+        if (substdio_flush(&ssnum) == -1)
+          strerr_die6sys(111,FATAL,ERR_FLUSH,dir,"/","tstdign",": ");
+        if (fsync(fd) == -1)
+          strerr_die6sys(111,FATAL,ERR_SYNC,dir,"/","tstdign",": ");
+        if (close(fd) == -1)
+          strerr_die6sys(111,FATAL,ERR_CLOSE,dir,"/","tstdign",": ");
+        if (rename("tstdign","tstdig") == -1)
+          strerr_die4sys(111,FATAL,ERR_MOVE,"tstdign",": ");
+        _exit(0);
+      }
+    } else
+        _exit(0);
+  }
+  _exit(99);
+}
+