Import ezmlm-idx 0.40
[ezmlm] / ezmlm-limit.c
1 /*$Id: ezmlm-limit.c,v 1.2 1999/10/31 18:58:48 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 "lock.h"
11 #include "getconf.h"
12 #include "fmt.h"
13 #include "now.h"
14 #include "sgetopt.h"
15 #include "error.h"
16 #include "errtxt.h"
17 #include "idx.h"
18
19 #define FATAL "ezmlm-limit: fatal: "
20 #define INFO "ezmlm-limit: info: "
21
22 unsigned long deltasecs = LIMSECS; /* interval to test over (seconds) */
23 unsigned long deltanum = LIMMSG; /* max no messages in interval */
24 /* see idx.h. Usually 30 msg/3600 secs*/
25 int flagd = 0; /* =0 create modpost, =1 ignore */
26 /* excess, =2 defer excess */
27 int flagmod; /* list moderated */
28 int flagloop;
29 char *fn = TXT_LOOPNUM;
30
31 void die_usage()
32 {
33 strerr_die1x(100,
34 "ezmlm-limit: usage: ezmlm-limit [-f file] [-dDF] [-n messages]"
35 " [-t secs] dir");
36 }
37
38 void die_nomem() { strerr_die2x(111,FATAL,ERR_NOMEM); }
39
40 void die_new() { strerr_die4sys(111,FATAL,ERR_WRITE,fn,": "); }
41
42 stralloc line = {0};
43
44 substdio ssnew;
45 char newbuf[16];
46
47 char strnum[FMT_ULONG];
48
49 void main(argc,argv)
50 int argc;
51 char **argv;
52 {
53 char *dir;
54 int opt;
55 unsigned int pos;
56 unsigned long num, loopnum, when;
57 unsigned long loopwhen = 0L;
58 unsigned long numwhen = 0L;
59 int fd,fdlock;
60
61 (void) umask(022);
62 sig_pipeignore();
63 when = (unsigned long) now();
64
65 while ((opt = getopt(argc,argv,"dDf:Fn:t:")) != opteof)
66 switch(opt) {
67 case 'd': flagd = 1; break;
68 case 'D': flagd = 0; break;
69 case 'f': if (optarg && *optarg) fn = optarg; break;
70 case 'F': fn = TXT_LOOPNUM;
71 case 'n':
72 if (optarg)
73 scan_ulong(optarg,&deltanum);
74 break;
75 case 't':
76 if (optarg)
77 scan_ulong(optarg,&deltasecs);
78 break;
79 default:
80 die_usage();
81 }
82
83 dir = argv[optind++];
84 if (!dir) die_usage();
85
86 if (chdir(dir) == -1)
87 strerr_die4sys(111,FATAL,ERR_SWITCH,dir,": ");
88
89 if (argv[optind])
90 die_usage(); /* avoid common error of putting options after dir */
91 if ((flagmod = getconf_line(&line,"modpost",0,FATAL,dir)))
92 _exit(0); /* already mod */
93 /* lock for num and for writing loopnum */
94 fdlock = open_append("lock");
95 if (fdlock == -1)
96 strerr_die4sys(111,FATAL,ERR_OPEN,dir,"/lock: ");
97 if (lock_ex(fdlock) == -1)
98 strerr_die4sys(111,FATAL,ERR_OBTAIN,dir,"/lock: ");
99
100 if (!getconf_line(&line,"num",0,FATAL,dir))
101 _exit(99); /* no msgs */
102 if(!stralloc_0(&line)) die_nomem();
103 pos = scan_ulong(line.s,&num); /* current msg */
104 if ((flagloop = getconf_line(&line,fn,0,FATAL,dir))) {
105 if(!stralloc_0(&line)) die_nomem();
106 pos = scan_ulong(line.s,&loopnum); /* msg when written */
107 if (line.s[pos] == ':')
108 scan_ulong(line.s+pos+1,&loopwhen); /* time written */
109 }
110 if (!flagloop || loopwhen + deltasecs < when || loopwhen > when) {
111 /* loopnum too old, bad or not there */
112 fd = open_trunc(fn); /* no need to write crash-proof */
113 if (fd == -1) die_new();
114 substdio_fdbuf(&ssnew,write,fd,newbuf,sizeof(newbuf));
115 if (substdio_put(&ssnew,strnum,fmt_ulong(strnum,num)) == -1) die_new();
116 if (substdio_puts(&ssnew,":") == -1) die_new();
117 if (substdio_put(&ssnew,strnum,fmt_ulong(strnum,when)) == -1) die_new();
118 if (substdio_puts(&ssnew,"\n") == -1) die_new();
119 if (substdio_flush(&ssnew) == -1) die_new();
120 close(fd);
121 } else if (num >= loopnum + deltanum) { /* excess messages */
122 if (!flagd) {
123 if ((fd = open_append("modpost")) == -1) /* create dir/modpost */
124 strerr_die3sys(111,FATAL,ERR_WRITE,"subpost:");
125 else {
126 close(fd);
127 unlink(fn);
128 strerr_die2x(0,INFO,ERR_EXCESS_MOD);
129 }
130 } else
131 strerr_die2x(111,FATAL,ERR_EXCESS_DEFER);
132 }
133 _exit(0);
134 }