chiark / gitweb /
Debianization and various other fixes.
[ezmlm] / ezmlm-tstdig.c
1 /*$Id: ezmlm-tstdig.c,v 1.17 1999/03/20 16:43:42 lindberg Exp $*/
2 /*$Name: ezmlm-idx-040 $*/
3
4 #include <sys/types.h>
5 #include "stralloc.h"
6 #include "substdio.h"
7 #include "readwrite.h"
8 #include "strerr.h"
9 #include "sig.h"
10 #include "getconf.h"
11 #include "env.h"
12 #include "fmt.h"
13 #include "now.h"
14 #include "lock.h"
15 #include "sgetopt.h"
16 #include "errtxt.h"
17 #include "idx.h"
18
19 #define FATAL "ezmlm-tstdig: fatal: "
20
21 void die_usage()
22 {
23   strerr_die1x(100,"ezmlm-tstdig: usage: ezmlm-tstdig [-k kbytes] [-m messages] [-t hours] dir");
24 }
25
26 void die_nomem() { strerr_die2x(111,FATAL,ERR_NOMEM); }
27
28 stralloc line = {0};
29
30 substdio ssnum;
31 char numbuf[16];
32
33 char strnum[FMT_ULONG];
34
35 int flaglocal = 0;
36
37 void main(argc,argv)
38 int argc;
39 char **argv;
40 {
41   char *dir;
42   char *local;
43   char *def;
44   int opt;
45   unsigned int pos;
46   unsigned long num, digsize, dignum;
47   unsigned long cumsize = 0L;
48   unsigned long deltanum = 0L;
49   unsigned long deltawhen = 0L;
50   unsigned long deltasize = 0L;
51   unsigned long when, tsttime, digwhen;
52   int fd,fdlock;
53
54   (void) umask(022);
55   sig_pipeignore();
56   when = (unsigned long) now();
57
58   while ((opt = getopt(argc,argv,"k:t:m:vV")) != opteof)
59     switch(opt) {
60       case 'k':
61                 if (optarg)
62                   scan_ulong(optarg,&deltasize);
63                 break;
64       case 't':
65                 if (optarg)     /* hours */
66                   scan_ulong(optarg,&deltawhen);
67                 break;
68       case 'm':
69                 if (optarg)
70                   scan_ulong(optarg,&deltanum);
71                 break;
72       case 'v':
73       case 'V': strerr_die2x(0,"ezmlm-tstdig version: ",EZIDX_VERSION);
74       default:
75         die_usage();
76     }
77
78
79   dir = argv[optind++];
80   if (!dir) die_usage();
81
82   if (chdir(dir) == -1)
83     strerr_die4sys(111,FATAL,ERR_SWITCH,dir,": ");
84
85   if (argv[optind])
86     die_usage();        /* avoid common error of putting options after dir */
87   if (!getconf_line(&line,"num",0,FATAL,dir))
88     _exit(99);          /* no msgs no shirt -> no digest */
89   if(!stralloc_0(&line)) die_nomem();
90   pos = scan_ulong(line.s,&num);
91   if (line.s[pos] == ':')
92     scan_ulong(line.s+pos+1,&cumsize);
93
94   if (getconf_line(&line,"dignum",0,FATAL,dir)) {
95     if(!stralloc_0(&line)) die_nomem();
96     pos = scan_ulong(line.s,&dignum);
97     if (line.s[pos] == ':')
98       pos += 1 + scan_ulong(line.s+pos+1,&digsize);
99     if (line.s[pos] == ':')
100       scan_ulong(line.s+pos+1,&digwhen);
101   } else {
102     dignum = 0L;        /* no file, not done any digest */
103     digsize = 0L;       /* nothing digested */
104     digwhen = 0L;       /* will force a digest, but the last one was eons  */
105                         /* ago. ezmlm-get sends it out only if there are   */
106                         /* messages. This is as it should for new lists.   */
107   }
108   local = env_get("LOCAL");
109   if (local && *local) {                        /* in editor or manager */
110     def = env_get("DEFAULT");
111     if (def && *def) {                          /* qmail>=1.02 and manager */
112       if (!case_starts(def,"dig") || case_starts(def,"digest-"))
113         _exit(0);
114     } else {                            /* older qmail versions or editor */
115       if (!getconf_line(&line,"inlocal",0,FATAL,dir)) {
116         flaglocal = 1;
117       } else {
118         pos = str_len(local);
119         if (pos <= line.len) {          /* maybe qmail>=1.02 and editor */
120           flaglocal = 1;                /* editor and qmail>=1.02. No harm */
121                                         /* if we're wrong */
122         } else {                        /* older qmail */
123           if (case_diffb(local,line.len,line.s))        /* local */
124             flaglocal = 1;              /* minimal harm */
125           else if (pos < line.len +4 || /* in manager and non-digest */
126                 !case_starts(local+line.len,"-dig"))
127             _exit(0);
128           else if (case_starts(local+line.len,"-digest-"))
129             _exit(0);
130         }
131       }
132     }
133   }
134
135   if (!deltawhen && !deltasize && !deltanum) _exit(0);
136   if ((deltawhen && ((digwhen + deltawhen * 3600L) <= when)) ||
137       (deltasize && ((digsize + (deltasize << 2)) <= cumsize)) ||
138       (deltanum && ((dignum + deltanum) <= num))) {     /* digest! */
139     if (flaglocal) {    /* avoid multiple digests. Of course, ezmlm-tstdig*/
140                         /* belongs in ezmlm-digest, but it's too late ....*/
141       fdlock = open_append("lock");
142       if (fdlock == -1)
143         strerr_die2sys(111,FATAL,ERR_OPEN_LOCK);
144       if (lock_ex(fdlock) == -1) {
145         close(fdlock);
146         strerr_die2sys(111,FATAL,ERR_OBTAIN_LOCK);
147       }
148       getconf_line(&line,"tstdig",0,dir,FATAL);
149       if (!stralloc_0(&line)) die_nomem();
150       scan_ulong(line.s,&tsttime);      /* give digest 1 h to complete */
151                                         /* nobody does digests more often */
152       if ((tsttime + 3600L < when) || (tsttime <= digwhen)) {
153         fd = open_trunc("tstdign");
154         if (fd == -1)
155           strerr_die6sys(111,FATAL,ERR_CREATE,dir,"/","tstdign",": ");
156         substdio_fdbuf(&ssnum,write,fd,numbuf,sizeof(numbuf));
157         if (substdio_put(&ssnum,strnum,fmt_ulong(strnum,when)) == -1)
158           strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/","tstdign",": ");
159         if (substdio_puts(&ssnum,"\n") == -1)
160           strerr_die6sys(111,FATAL,ERR_WRITE,dir,"/","tstdign",": ");
161         if (substdio_flush(&ssnum) == -1)
162           strerr_die6sys(111,FATAL,ERR_FLUSH,dir,"/","tstdign",": ");
163         if (fsync(fd) == -1)
164           strerr_die6sys(111,FATAL,ERR_SYNC,dir,"/","tstdign",": ");
165         if (close(fd) == -1)
166           strerr_die6sys(111,FATAL,ERR_CLOSE,dir,"/","tstdign",": ");
167         if (rename("tstdign","tstdig") == -1)
168           strerr_die4sys(111,FATAL,ERR_MOVE,"tstdign",": ");
169         _exit(0);
170       }
171     } else
172         _exit(0);
173   }
174   _exit(99);
175 }
176