#include "error.h" #include "strerr.h" #include "readwrite.h" #include "str.h" #include "fmt.h" #include "stralloc.h" #include "open.h" #include "substdio.h" #include "case.h" #include "errtxt.h" #include "subscribe.h" #include "qmail.h" #include static substdio ssin; static char inbuf[512]; char strnum[FMT_ULONG]; static stralloc line = {0}; static stralloc domains = {0}; static stralloc quoted = {0}; static stralloc fn = {0}; static void die_nomem(fatal) char *fatal; { strerr_die2x(111,fatal,ERR_NOMEM); } static void die_write(fatal) char *fatal; { strerr_die3x(111,fatal,ERR_WRITE,"stdout"); } unsigned long putsubs(dbname,hash_lo,hash_hi, subwrite,flagsql,fatal) /* Outputs all userhostesses in 'dbname' to stdout. If userhost is not null */ /* that userhost is excluded. 'dbname' is the base directory name. For the */ /* mysql version, dbname is the directory where the file "sql" with mysql */ /* access info is found. If this file is not present or if flagmysql is not */ /* set, the routine falls back to the old database style. subwrite must be a*/ /* function returning >=0 on success, -1 on error, and taking arguments */ /* (char* string, unsigned int length). It will be called once per address */ /* and should take care of newline or whatever needed for the output form. */ char *dbname; /* database base dir */ unsigned long hash_lo; unsigned long hash_hi; int subwrite(); /* write function. */ int flagsql; char *fatal; /* fatal error string */ { MYSQL_RES *result; MYSQL_ROW row; char *table = (char *) 0; unsigned long *lengths; unsigned int i; int fd; unsigned long no = 0L; int match; unsigned int pos = 0; unsigned int hashpos; char *ret = (char *) 0; if (!flagsql || (ret = opensql(dbname,&table))) { if (flagsql && *ret) strerr_die2x(111,fatal,ret); /* fallback to local db */ if (!stralloc_copys(&fn,dbname)) die_nomem(fatal); if (!stralloc_catb(&fn,"/subscribers/?",15)) die_nomem(fatal); /* NOTE: Also copies terminal '\0' */ hashpos = fn.len - 2; if (hash_lo > 52) hash_lo = 52; if (hash_hi > 52) hash_hi = 52; if (hash_hi < hash_lo) hash_hi = hash_lo; for (i = hash_lo;i <= hash_hi;++i) { fn.s[hashpos] = 64 + i; /* hash range 0-52 */ fd = open_read(fn.s); if (fd == -1) { if (errno != error_noent) strerr_die4sys(111,fatal,ERR_READ,fn.s,": "); } else { substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf)); for (;;) { if (getln(&ssin,&line,&match,'\0') == -1) strerr_die4sys(111,fatal,ERR_READ,fn.s,": "); if (!match) break; if (subwrite(line.s + 1,line.len - 2) == -1) die_write(fatal); no++; } close(fd); } } return no; } else { /* SQL Version */ /* main query */ if (!stralloc_copys(&line,"SELECT address FROM ")) die_nomem(fatal); if (!stralloc_cats(&line,table)) die_nomem(fatal); if (!stralloc_cats(&line," WHERE hash BETWEEN ")) die_nomem(fatal); if (!stralloc_catb(&line,strnum,fmt_ulong(strnum,hash_lo))) die_nomem(fatal); if (!stralloc_cats(&line," AND ")) die_nomem(fatal); if (!stralloc_catb(&line,strnum,fmt_ulong(strnum,hash_hi))) die_nomem(fatal); if (mysql_real_query((MYSQL *) psql,line.s,line.len)) /* query */ strerr_die2x(111,fatal,mysql_error((MYSQL *) psql)); if (!(result = mysql_use_result((MYSQL *) psql))) strerr_die2x(111,fatal,mysql_error((MYSQL *) psql)); no = 0; while ((row = mysql_fetch_row(result))) { /* this is safe even if someone messes with the address field def */ if (!(lengths = mysql_fetch_lengths(result))) strerr_die2x(111,fatal,mysql_error((MYSQL *) psql)); if (subwrite(row[0],lengths[0]) == -1) die_write(fatal); no++; /* count for list-list fxn */ } if (!mysql_eof(result)) strerr_die2x(111,fatal,mysql_error((MYSQL *) psql)); mysql_free_result(result); return no; } }