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