12 #include "subscribe.h"
14 static stralloc addr
= {0};
15 static stralloc line
= {0};
16 static stralloc fnnew
= {0};
17 static stralloc fn
= {0};
21 static char ssbuf
[256];
23 static substdio ssnew
;
24 static char ssnewbuf
[256];
26 static int doit(userhost
,flagadd
)
36 if (userhost
[str_chr(userhost
,'\n')]) return -8;
37 if (!stralloc_copys(&addr
,"T")) return -2;
38 if (!stralloc_cats(&addr
,userhost
)) return -2;
39 if (addr
.len
> 401) return -7;
41 j
= byte_rchr(addr
.s
,addr
.len
,'@');
42 if (j
== addr
.len
) return -6;
43 case_lowerb(addr
.s
+ j
+ 1,addr
.len
- j
- 1);
46 for (j
= 0;j
< addr
.len
;++j
)
47 h
= (h
+ (h
<< 5)) ^ (uint32
) (unsigned char) addr
.s
[j
];
50 if (!stralloc_0(&addr
)) return -2;
52 if (!stralloc_copys(&fn
,"subscribers/")) return -2;
53 if (!stralloc_catb(&fn
,&ch
,1)) return -2;
54 if (!stralloc_copy(&fnnew
,&fn
)) return -2;
55 if (!stralloc_cats(&fnnew
,"n")) return -2;
56 if (!stralloc_0(&fnnew
)) return -2;
57 if (!stralloc_0(&fn
)) return -2;
59 fdnew
= open_trunc(fnnew
.s
);
60 if (fdnew
== -1) return -4;
61 substdio_fdbuf(&ssnew
,write
,fdnew
,ssnewbuf
,sizeof(ssnewbuf
));
67 if (errno
!= error_noent
) { close(fdnew
); return -3; }
70 substdio_fdbuf(&ss
,read
,fd
,ssbuf
,sizeof(ssbuf
));
73 if (getln(&ss
,&line
,&match
,'\0') == -1) { close(fd
); close(fdnew
); return -3; }
75 if (line
.len
== addr
.len
)
76 if (!byte_diff(line
.s
,line
.len
,addr
.s
)) {
81 if (substdio_bput(&ssnew
,line
.s
,line
.len
) == -1) { close(fd
); close(fdnew
); return -4; }
87 if (flagadd
&& !flagwasthere
)
88 if (substdio_bput(&ssnew
,addr
.s
,addr
.len
) == -1) { close(fdnew
); return -4; }
90 if (substdio_flush(&ssnew
) == -1) { close(fdnew
); return -4; }
91 if (fsync(fdnew
) == -1) { close(fdnew
); return -4; }
94 if (rename(fnnew
.s
,fn
.s
) == -1) return -5;
95 return flagadd
^ flagwasthere
;
98 struct strerr subscribe_err
;
100 int subscribe(userhost
,flagadd
)
107 fdlock
= open_append("lock");
109 STRERR_SYS(-1,subscribe_err
,"unable to open lock: ")
110 if (lock_ex(fdlock
) == -1) {
112 STRERR_SYS(-1,subscribe_err
,"unable to obtain lock: ")
115 r
= doit(userhost
,flagadd
);
118 if (r
== -2) STRERR(-1,subscribe_err
,"out of memory")
119 if (r
== -3) STRERR_SYS3(-1,subscribe_err
,"unable to read ",fn
.s
,": ")
120 if (r
== -4) STRERR_SYS3(-1,subscribe_err
,"unable to write ",fnnew
.s
,": ")
121 if (r
== -5) STRERR_SYS3(-1,subscribe_err
,"unable to move temporary file to ",fn
.s
,": ")
122 if (r
== -6) STRERR(-2,subscribe_err
,"address does not contain @")
123 if (r
== -7) STRERR(-2,subscribe_err
,"address is too long")
124 if (r
== -8) STRERR(-2,subscribe_err
,"address contains newline")