ezmlmx 0.69
ezmlmx
Loading...
Searching...
No Matches
subscribe.c
Go to the documentation of this file.
1#include <unistd.h>
2#include "str.h"
3#include "stralloc.h"
4#include "getln.h"
5#include "readwrite.h"
6#include "buffer.h"
7#include "logmsg.h"
8#include "open.h"
9#include "byte.h"
10#include "case.h"
11#include "lock.h"
12#include "error.h"
13#include "subscribe.h"
14#include "uint_t.h"
15#include "fmt.h"
16#include "errtxt.h"
17#include "logaddr.h"
18#include "idx.h"
19#include "lockfile.h"
20
21#define WHO "subscribe"
22
28
29int rename(const char *,const char *); // stdio.h
30
31static stralloc addr = {0};
32static stralloc lcaddr = {0};
33static stralloc line = {0};
34static stralloc fnnew = {0};
35static stralloc fn = {0};
36static stralloc fnlock = {0};
37
38static void die_nomem() { logmsg(WHO,111,FATAL,ERR_NOMEM); }
39static void die_read() { logmsg(WHO,111,FATAL,B(ERR_READ,fn.s)); }
40static void die_write() { logmsg(WHO,111,FATAL,B(ERR_WRITE,fnnew.s)); }
41
42static int fd;
43static buffer bi;
44static char inbuf[256];
45static int fdnew;
46static buffer bo;
47static char outbuf[256];
48
75
76int subscribe(const char *dbname,const char *userhost,int flagadd,const char *comment,
77 const char *event,int flagmysql,int forcehash,const char *tab)
78{
79 int fdlock;
80
81 unsigned int j;
82 uint32 h,lch;
83 unsigned char ch,lcch;
84 int match;
85 int flagwasthere;
86
87 if (userhost[str_chr(userhost,'\n')])
88 logmsg(WHO,100,FATAL,ERR_ADDR_NL);
89
90 if (!stralloc_copys(&addr,"T")) die_nomem();
91 if (!stralloc_cats(&addr,userhost)) die_nomem();
92 if (addr.len > 401)
93 logmsg(WHO,100,FATAL,ERR_ADDR_LONG);
94
95 j = byte_rchr(addr.s,addr.len,'@');
96 if (j == addr.len)
97 logmsg(WHO,100,FATAL,ERR_ADDR_AT);
98
99 case_lowerb(addr.s + j + 1,addr.len - j - 1);
100 if (!stralloc_copy(&lcaddr,&addr)) die_nomem();
101 case_lowerb(lcaddr.s + 1,j - 1); /* make all-lc version of address */
102
103 if (forcehash >= 0 && forcehash <= 52) {
104 ch = lcch = (unsigned char) forcehash;
105 } else {
106 h = 5381;
107 lch = h;
108 for (j = 0;j < addr.len;++j) {
109 h = (h + (h << 5)) ^ (uint32) (unsigned char) addr.s[j];
110 lch = (lch + (lch << 5)) ^ (uint32) (unsigned char) lcaddr.s[j];
111 }
112 lcch = 64 + (lch % 53);
113 ch = 64 + (h % 53);
114 }
115
116 if (!stralloc_0(&addr)) die_nomem();
117 if (!stralloc_0(&lcaddr)) die_nomem();
118 if (!stralloc_copys(&fn,dbname)) die_nomem();
119 if (!stralloc_copys(&fnlock,dbname)) die_nomem();
120
121 if (!stralloc_cats(&fn,"/subscribers/")) die_nomem();
122 if (!stralloc_catb(&fn,&lcch,1)) die_nomem();
123 if (!stralloc_copy(&fnnew,&fn)) die_nomem();
124 /* code later depends on fnnew = fn + 'n' */
125 if (!stralloc_cats(&fnnew,"n")) die_nomem();
126 if (!stralloc_cats(&fnlock,"/lock")) die_nomem();
127 if (!stralloc_0(&fnnew)) die_nomem();
128 if (!stralloc_0(&fn)) die_nomem();
129 if (!stralloc_0(&fnlock)) die_nomem();
130
131 fdlock = lockfile(fnlock.s);
132
133 /* do lower case hashed version first */
134
135 fdnew = open_trunc(fnnew.s);
136 if (fdnew == -1) die_write();
137 buffer_init(&bo,buffer_unixwrite,fdnew,outbuf,sizeof(outbuf));
138
139 flagwasthere = 0;
140
141 fd = open_read(fn.s);
142 if (fd == -1) {
143 if (errno != ENOENT) { close(fdnew); die_read(); }
144 }
145 else {
146 buffer_init(&bi,buffer_unixread,fd,inbuf,sizeof(inbuf));
147
148 for (;;) {
149 if (getln(&bi,&line,&match,'\0') == -1) {
150 close(fd); close(fdnew); die_read();
151 }
152 if (!match) break;
153 if (line.len == addr.len)
154 if (!case_diffb(line.s,line.len,addr.s)) {
155 flagwasthere = 1;
156 if (!flagadd) continue;
157 }
158 if (buffer_put(&bo,line.s,line.len) == -1) {
159 close(fd); close(fdnew); die_write();
160 }
161 }
162
163 close(fd);
164 }
165
166 if (flagadd && !flagwasthere)
167 if (buffer_put(&bo,addr.s,addr.len) == -1) {
168 close(fdnew); die_write();
169 }
170
171 if (buffer_flush(&bo) == -1) { close(fdnew); die_write(); }
172 if (fsync(fdnew) == -1) { close(fdnew); die_write(); }
173 close(fdnew);
174
175 if (rename(fnnew.s,fn.s) == -1)
176 logmsg(WHO,111,FATAL,B(ERR_MOVE,fnnew.s," to : ",fn.s));
177
178 if ((ch == lcch) || flagwasthere) {
179 close(fdlock);
180 if (flagadd ^ flagwasthere) {
181 if (!stralloc_0(&addr)) die_nomem();
182 logaddr(dbname,event,addr.s+1,comment);
183 return 1;
184 }
185 return 0;
186 }
187
188 /* If unsub and not found and hashed differ, OR */
189 /* sub and not found (so added with new hash) */
190 /* do the 'case-dependent' hash */
191
192 fn.s[fn.len - 2] = ch;
193 fnnew.s[fnnew.len - 3] = ch;
194 fdnew = open_trunc(fnnew.s);
195 if (fdnew == -1) die_write();
196 buffer_init(&bo,buffer_unixwrite,fdnew,outbuf,sizeof(outbuf));
197
198 fd = open_read(fn.s);
199 if (fd == -1) {
200 if (errno != ENOENT) { close(fdnew); die_read(); }
201 } else {
202 buffer_init(&bi,buffer_unixread,fd,inbuf,sizeof(inbuf));
203
204 for (;;) {
205 if (getln(&bi,&line,&match,'\0') == -1)
206 { close(fd); close(fdnew); die_read(); }
207 if (!match) break;
208 if (line.len == addr.len)
209 if (!case_diffb(line.s,line.len,addr.s)) {
210 flagwasthere = 1;
211 continue; /* always want to remove from case-sensitive hash */
212 }
213 if (buffer_put(&bo,line.s,line.len) == -1)
214 { close(fd); close(fdnew); die_write(); }
215 }
216
217 close(fd);
218 }
219
220 if (buffer_flush(&bo) == -1) { close(fdnew); die_write(); }
221 if (fsync(fdnew) == -1) { close(fdnew); die_write(); }
222 close(fdnew);
223
224 if (rename(fnnew.s,fn.s) == -1)
225 logmsg(WHO,111,FATAL,B(ERR_MOVE,fnnew.s," to :",fn.s));
226
227 close(fdlock);
228 if (flagadd ^ flagwasthere) {
229 if (!stralloc_0(&addr)) die_nomem();
230 logaddr(dbname,event,addr.s+1,comment);
231 return 1;
232 }
233 return 0;
234
235}
stralloc addr
Definition ezmlm-cron.c:47
int fdlock
Definition ezmlm-cron.c:73
#define WHO
Definition author.c:1
stralloc comment
stralloc fnnew
void die_nomem()
Definition getconf.c:17
char * userhost
stralloc fn
char inbuf[1024]
int rename(const char *, const char *)
char outbuf[1024]
buffer bi
buffer bo
int fd
Definition ezmlm-cgi.c:141
int match
Definition ezmlm-cgi.c:140
void logaddr(const char *dir, const char *event, const char *addr, const char *comment)
Definition log.c:30
int lockfile(const char *)
Definition lockfile.c:15
Error messages. If you translate these, I would urge you to keep the English version as well....
#define ERR_NOMEM
Definition errtxt.h:14
#define ERR_MOVE
Definition errtxt.h:29
#define ERR_ADDR_AT
Definition errtxt.h:148
#define ERR_READ
Definition errtxt.h:18
#define ERR_ADDR_LONG
Definition errtxt.h:149
#define ERR_WRITE
Definition errtxt.h:17
#define ERR_ADDR_NL
Definition errtxt.h:150
const char * logmsg(const char *dir, unsigned long num, unsigned long listno, unsigned long subs, int done)
Definition loginfo.c:32
void die_write(void)
Definition subscribe.c:41
int subscribe(const char *dbname, const char *userhost, int flagadd, const char *comment, const char *event, int flagmysql, int forcehash, const char *tab)
Definition subscribe.c:76
void die_read(void)
Definition subscribe.c:40