chiark / gitweb /
Debianization and various other fixes.
[ezmlm] / sub_std / issub.c
1 /*$Id: issub.c,v 1.4 1999/10/12 23:38:36 lindberg Exp $*/
2 /*$Name: ezmlm-idx-040 $*/
3 #include "stralloc.h"
4 #include "getln.h"
5 #include "readwrite.h"
6 #include "substdio.h"
7 #include "open.h"
8 #include "byte.h"
9 #include "case.h"
10 #include "strerr.h"
11 #include "error.h"
12 #include "uint32.h"
13 #include "fmt.h"
14 #include "subscribe.h"
15 #include "errtxt.h"
16
17 static void die_nomem(fatal)
18 char *fatal;
19 {
20   strerr_die2x(111,fatal,ERR_NOMEM);
21 }
22
23 static stralloc addr = {0};
24 static stralloc lcaddr = {0};
25 static stralloc line = {0};
26 static stralloc quoted = {0};
27 static stralloc fn = {0};
28 static substdio ss;
29 static char ssbuf[512];
30 static char szh[FMT_ULONG];
31
32 char *issub(dbname,userhost,tab,fatal)
33 /* Returns (char *) to match if userhost is in the subscriber database     */
34 /* dbname, 0 otherwise. dbname is a base directory for a list and may NOT  */
35 /* be NULL        */
36 /* NOTE: The returned pointer is NOT VALID after a subsequent call to issub!*/
37
38 char *dbname;           /* directory to basedir */
39 char *userhost;
40 char *tab;              /* override table name */
41 char *fatal;
42
43 {
44
45   int fd;
46   unsigned int j;
47   uint32 h,lch;
48   char ch,lcch;
49   int match;
50
51     if (!stralloc_copys(&addr,"T")) die_nomem(fatal);
52     if (!stralloc_cats(&addr,userhost)) die_nomem(fatal);
53
54     j = byte_rchr(addr.s,addr.len,'@');
55     if (j == addr.len) return (char *) 0;
56     case_lowerb(addr.s + j + 1,addr.len - j - 1);
57     if (!stralloc_copy(&lcaddr,&addr)) die_nomem(fatal);
58     case_lowerb(lcaddr.s + 1,j - 1);    /* totally lc version of addr */
59
60     h = 5381;
61     lch = h;                    /* make hash for both for backwards comp */
62     for (j = 0;j < addr.len;++j) {      /* (lcaddr.len == addr.len) */
63       h = (h + (h << 5)) ^ (uint32) (unsigned char) addr.s[j];
64       lch = (lch + (lch << 5)) ^ (uint32) (unsigned char) lcaddr.s[j];
65     }
66     ch = 64 + (h % 53);
67     lcch = 64 + (lch % 53);
68
69     if (!stralloc_0(&addr)) die_nomem(fatal);
70     if (!stralloc_0(&lcaddr)) die_nomem(fatal);
71     if (!stralloc_copys(&fn,dbname)) die_nomem(fatal);
72     if (!stralloc_cats(&fn,"/subscribers/")) die_nomem(fatal);
73     if (!stralloc_catb(&fn,&lcch,1)) die_nomem(fatal);
74     if (!stralloc_0(&fn)) die_nomem(fatal);
75
76     fd = open_read(fn.s);
77     if (fd == -1) {
78       if (errno != error_noent)
79         strerr_die4sys(111,fatal,ERR_OPEN,fn.s,": ");
80     } else {
81       substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf));
82
83       for (;;) {
84         if (getln(&ss,&line,&match,'\0') == -1)
85           strerr_die4sys(111,fatal,ERR_READ,fn.s,": ");
86         if (!match) break;
87         if (line.len == lcaddr.len)
88           if (!case_diffb(line.s,line.len,lcaddr.s))
89             { close(fd); return line.s+1; }
90       }
91
92       close(fd);
93     }
94         /* here if file not found or (file found && addr not there) */
95
96     if (ch == lcch) return (char *) 0;
97
98         /* try case sensitive hash for backwards compatibility */
99     fn.s[fn.len - 2] = ch;
100     fd = open_read(fn.s);
101     if (fd == -1) {
102       if (errno != error_noent)
103         strerr_die4sys(111,fatal,ERR_OPEN,fn.s,": ");
104       return (char *) 0;
105     }
106     substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf));
107
108     for (;;) {
109       if (getln(&ss,&line,&match,'\0') == -1)
110         strerr_die4sys(111,fatal,ERR_READ,fn.s,": ");
111       if (!match) break;
112       if (line.len == addr.len)
113         if (!case_diffb(line.s,line.len,addr.s))
114           { close(fd); return line.s+1; }
115     }
116
117     close(fd);
118
119     return (char *) 0;
120 }