Commit | Line | Data |
---|---|---|
f8beb284 MW |
1 | #include "error.h" |
2 | #include "strerr.h" | |
3 | #include "readwrite.h" | |
4 | #include "str.h" | |
5 | #include "fmt.h" | |
6 | #include "stralloc.h" | |
7 | #include "open.h" | |
8 | #include "substdio.h" | |
9 | #include "case.h" | |
10 | #include "errtxt.h" | |
11 | #include "subscribe.h" | |
12 | #include "qmail.h" | |
13 | #include <mysql.h> | |
14 | ||
15 | static substdio ssin; | |
16 | static char inbuf[512]; | |
17 | char strnum[FMT_ULONG]; | |
18 | static stralloc line = {0}; | |
19 | static stralloc domains = {0}; | |
20 | static stralloc quoted = {0}; | |
21 | static stralloc fn = {0}; | |
22 | ||
23 | static void die_nomem(fatal) | |
24 | char *fatal; | |
25 | { | |
26 | strerr_die2x(111,fatal,ERR_NOMEM); | |
27 | } | |
28 | ||
29 | static void die_write(fatal) | |
30 | char *fatal; | |
31 | { | |
32 | strerr_die3x(111,fatal,ERR_WRITE,"stdout"); | |
33 | } | |
34 | ||
35 | unsigned long putsubs(dbname,hash_lo,hash_hi, | |
36 | subwrite,flagsql,fatal) | |
37 | /* Outputs all userhostesses in 'dbname' to stdout. If userhost is not null */ | |
38 | /* that userhost is excluded. 'dbname' is the base directory name. For the */ | |
39 | /* mysql version, dbname is the directory where the file "sql" with mysql */ | |
40 | /* access info is found. If this file is not present or if flagmysql is not */ | |
41 | /* set, the routine falls back to the old database style. subwrite must be a*/ | |
42 | /* function returning >=0 on success, -1 on error, and taking arguments */ | |
43 | /* (char* string, unsigned int length). It will be called once per address */ | |
44 | /* and should take care of newline or whatever needed for the output form. */ | |
45 | ||
46 | char *dbname; /* database base dir */ | |
47 | unsigned long hash_lo; | |
48 | unsigned long hash_hi; | |
49 | int subwrite(); /* write function. */ | |
50 | int flagsql; | |
51 | char *fatal; /* fatal error string */ | |
52 | ||
53 | { | |
54 | MYSQL_RES *result; | |
55 | MYSQL_ROW row; | |
56 | char *table = (char *) 0; | |
57 | unsigned long *lengths; | |
58 | ||
59 | unsigned int i; | |
60 | int fd; | |
61 | unsigned long no = 0L; | |
62 | int match; | |
63 | unsigned int pos = 0; | |
64 | unsigned int hashpos; | |
65 | char *ret = (char *) 0; | |
66 | ||
67 | if (!flagsql || (ret = opensql(dbname,&table))) { | |
68 | if (flagsql && *ret) strerr_die2x(111,fatal,ret); | |
69 | /* fallback to local db */ | |
70 | if (!stralloc_copys(&fn,dbname)) die_nomem(fatal); | |
71 | if (!stralloc_catb(&fn,"/subscribers/?",15)) die_nomem(fatal); | |
72 | /* NOTE: Also copies terminal '\0' */ | |
73 | hashpos = fn.len - 2; | |
74 | if (hash_lo > 52) hash_lo = 52; | |
75 | if (hash_hi > 52) hash_hi = 52; | |
76 | if (hash_hi < hash_lo) hash_hi = hash_lo; | |
77 | ||
78 | for (i = hash_lo;i <= hash_hi;++i) { | |
79 | fn.s[hashpos] = 64 + i; /* hash range 0-52 */ | |
80 | fd = open_read(fn.s); | |
81 | if (fd == -1) { | |
82 | if (errno != error_noent) | |
83 | strerr_die4sys(111,fatal,ERR_READ,fn.s,": "); | |
84 | } else { | |
85 | substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf)); | |
86 | for (;;) { | |
87 | if (getln(&ssin,&line,&match,'\0') == -1) | |
88 | strerr_die4sys(111,fatal,ERR_READ,fn.s,": "); | |
89 | if (!match) | |
90 | break; | |
91 | if (subwrite(line.s + 1,line.len - 2) == -1) die_write(fatal); | |
92 | no++; | |
93 | } | |
94 | close(fd); | |
95 | } | |
96 | } | |
97 | return no; | |
98 | ||
99 | } else { /* SQL Version */ | |
100 | ||
101 | /* main query */ | |
102 | if (!stralloc_copys(&line,"SELECT address FROM ")) | |
103 | die_nomem(fatal); | |
104 | if (!stralloc_cats(&line,table)) die_nomem(fatal); | |
105 | if (!stralloc_cats(&line," WHERE hash BETWEEN ")) die_nomem(fatal); | |
106 | if (!stralloc_catb(&line,strnum,fmt_ulong(strnum,hash_lo))) | |
107 | die_nomem(fatal); | |
108 | if (!stralloc_cats(&line," AND ")) die_nomem(fatal); | |
109 | if (!stralloc_catb(&line,strnum,fmt_ulong(strnum,hash_hi))) | |
110 | die_nomem(fatal); | |
111 | if (mysql_real_query((MYSQL *) psql,line.s,line.len)) /* query */ | |
112 | strerr_die2x(111,fatal,mysql_error((MYSQL *) psql)); | |
113 | if (!(result = mysql_use_result((MYSQL *) psql))) | |
114 | strerr_die2x(111,fatal,mysql_error((MYSQL *) psql)); | |
115 | no = 0; | |
116 | while ((row = mysql_fetch_row(result))) { | |
117 | /* this is safe even if someone messes with the address field def */ | |
118 | if (!(lengths = mysql_fetch_lengths(result))) | |
119 | strerr_die2x(111,fatal,mysql_error((MYSQL *) psql)); | |
120 | if (subwrite(row[0],lengths[0]) == -1) die_write(fatal); | |
121 | no++; /* count for list-list fxn */ | |
122 | } | |
123 | if (!mysql_eof(result)) | |
124 | strerr_die2x(111,fatal,mysql_error((MYSQL *) psql)); | |
125 | mysql_free_result(result); | |
126 | return no; | |
127 | } | |
128 | } |