X-Git-Url: https://git.distorted.org.uk/~mdw/ezmlm/blobdiff_plain/5b62e993b0af39700031c2875d7f6654e6a02850..f8beb284087c279acfb30506f5bb32baa4949b44:/ezmlm-tstdig.c diff --git a/ezmlm-tstdig.c b/ezmlm-tstdig.c new file mode 100644 index 0000000..dc073ea --- /dev/null +++ b/ezmlm-tstdig.c @@ -0,0 +1,176 @@ +/*$Id: ezmlm-tstdig.c,v 1.17 1999/03/20 16:43:42 lindberg Exp $*/ +/*$Name: ezmlm-idx-040 $*/ + +#include +#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); +} +