chiark / gitweb /
Debianization and various other fixes.
[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 }