int temp_nfs(void) { if (substdio_puts(subfdout, "ZNFS failure in qmail-verify.") == -1) die_write(); if (substdio_putflush(subfdout, "", 1) == -1) die_write(); return -1; }
void die_nomem(void) { cleanup(); if (substdio_puts(subfdout, "ZOut of memory in qmail-verify.") == -1) die_write(); if (substdio_putflush(subfdout, "", 1) == -1) die_write(); _exit(111); }
void die_cdb(void) { if (substdio_puts(subfdout, "ZTrouble reading users/cdb in qmail-verify.") == -1) die_write(); if (substdio_putflush(subfdout, "", 1) == -1) die_write(); _exit(111); }
/* Outputs all addresses in the table through subwrite. 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. */ unsigned long sub_sql_putsubs(struct subdbinfo *info, const char *table, unsigned long hash_lo, unsigned long hash_hi, int subwrite()) /* write function. */ { void *result; unsigned long no = 0L; char strnum[FMT_ULONG]; stralloc_copyb(¶ms[0],strnum,fmt_ulong(strnum,hash_lo)); stralloc_copyb(¶ms[1],strnum,fmt_ulong(strnum,hash_hi)); make_name(info,table?"_":0,table,0); /* main query */ stralloc_copys(&query,"SELECT address FROM "); stralloc_cat(&query,&name); stralloc_cats(&query," WHERE "); stralloc_cats(&query,sql_putsubs_where_defn); result = sql_select(info,&query,2,params); no = 0; while (sql_fetch_row(info,result,1,&addr)) { if (subwrite(addr.s,addr.len) == -1) die_write(); no++; /* count for list-list fxn */ } sql_free_result(info,result); return no; }
void temp_fail(void) { if (substdio_putflush(subfdout, "Z", 2) == -1) die_write(); qldap_free_results(q); }
int lookup_passwd(const char *local) { char username[GETPW_USERLEN]; struct stat st; const char *extension; struct passwd *pw; extension = local + str_len(local); for (; extension >= local; extension--) { if ((unsigned long)(extension - local) < sizeof(username)) if (!*extension || (*extension == *auto_break)) { byte_copy(username, extension - local, local); username[extension - local] = 0; case_lowers(username); errno = 0; pw = getpwnam(username); if (errno == error_txtbsy) return temp_sys(); if (pw && pw->pw_uid != 0) { if (stat(pw->pw_dir,&st) == 0 && st.st_uid == pw->pw_uid) { /* OK */ if (substdio_putflush(subfdout, "K", 1) == -1) die_write(); return (1); } else if (error_temp(errno)) return temp_nfs(); } } } return (0); }
int main(int argc,char **argv) { int fd; unsigned long loop; if (!*argv) _exit(0); if (!*++argv) _exit(0); scan_ulong(*argv,&loop); if (cdb_make_start(&c,1) == -1) die_write(); while (loop) { uint32_pack(key,--loop); if (cdb_make_add(&c,key,4,data,sizeof data) == -1) die_write(); } if (cdb_make_finish(&c) == -1) die_write(); _exit(0); }
main(int argc,char **argv) { char *key; int r; uint32 pos; uint32 len; unsigned long u = 0; if (!*argv) die_usage(); if (!*++argv) die_usage(); key = *argv; if (*++argv) { scan_ulong(*argv,&u); } cdb_init(&c,0); cdb_findstart(&c); for (;;) { r = cdb_findnext(&c,key,str_len(key)); if (r == -1) die_read(); if (!r) _exit(100); if (!u) break; --u; } pos = cdb_datapos(&c); len = cdb_datalen(&c); while (len > 0) { r = sizeof buf; if (r > len) r = len; if (cdb_read(&c,buf,r,pos) == -1) die_read(); if (buffer_put(buffer_1small,buf,r) == -1) die_write(); pos += r; len -= r; } if (buffer_flush(buffer_1small) == -1) die_write(); _exit(0); }
int main(int argc,char **argv) { const char *subdir; unsigned long n; int i; char strnum[FMT_ULONG]; i = getconfopt(argc,argv,options,1,0); initsub(flagsubdb); subdir = argv[i]; if (flagnumber) { n = putsubs(subdir,0L,52L,dummywrite); if (substdio_put(subfdout,strnum,fmt_ulong(strnum,n)) == -1) die_write(); if (substdio_put(subfdout,"\n",1) == -1) die_write(); } else (void) putsubs(subdir,0L,52L,subwrite); if (substdio_flush(subfdout) == -1) die_write(); closesub(); _exit(0); }
/* Searches the subscriber log and outputs via subwrite(s,len) any entry * that matches search. A '_' is search is a wildcard. Any other * non-alphanum/'.' char is replaced by a '_'. */ static void _searchlog(struct subdbinfo *info, const char *table, char *search, /* search string */ int subwrite()) /* output fxn */ { sqlite3_stmt *stmt; int res; datetime_sec when; struct datetime dt; char date[DATE822FMT]; /* SELECT (*) FROM list_slog WHERE fromline LIKE '%search%' OR address */ /* LIKE '%search%' ORDER BY tai; */ /* The '*' is formatted to look like the output of the non-mysql version */ /* This requires reading the entire table, since search fields are not */ /* indexed, but this is a rare query and time is not of the essence. */ if (!stralloc_copys(&line,"SELECT tai, edir||etype||' '||address||' '||fromline" " FROM ")) die_nomem(); if (!stralloc_cat_table(&line,info,table)) die_nomem(); if (!stralloc_cats(&line,"_slog")) die_nomem(); if (*search) { /* We can afford to wait for LIKE '%xx%' */ if (!stralloc_cats(&line," WHERE fromline LIKE '%")) die_nomem(); if (!stralloc_cats(&line,search)) die_nomem(); if (!stralloc_cats(&line,"%' OR address LIKE '%")) die_nomem(); if (!stralloc_cats(&line,search)) die_nomem(); if (!stralloc_cats(&line,"%'")) die_nomem(); } /* ordering by tai which is an index */ if (!stralloc_cats(&line," ORDER by tai")) die_nomem(); if (!stralloc_0(&line)) die_nomem(); if ((stmt = _sqlquery(info, &line)) == NULL) strerr_die2x(111,FATAL,sqlite3_errmsg((sqlite3*)info->conn)); while ((res = sqlite3_step(stmt)) != SQLITE_DONE) { if (res != SQLITE_ROW) strerr_die2x(111,FATAL,sqlite3_errmsg((sqlite3*)info->conn)); (void)scan_ulong((const char*)sqlite3_column_text(stmt,0),&when); datetime_tai(&dt,when); if (!stralloc_copyb(&line,date,date822fmt(date,&dt)-1)) die_nomem(); if (!stralloc_cats(&line,": ")) die_nomem(); if (!stralloc_catb(&line,strnum,fmt_ulong(strnum,when))) die_nomem(); if (!stralloc_cats(&line," ")) die_nomem(); if (!stralloc_catb(&line, (const char*)sqlite3_column_text(stmt,1), sqlite3_column_bytes(stmt,1))) die_nomem(); if (subwrite(line.s,line.len) == -1) die_write(); } sqlite3_finalize(stmt); }
/* Searches the subscriber log and outputs via subwrite(s,len) any entry * that matches search. A '_' is search is a wildcard. Any other * non-alphanum/'.' char is replaced by a '_'. */ void sub_sql_searchlog(struct subdbinfo *info, const char *table, char *search, /* search string */ int subwrite()) /* output fxn */ { void *result; datetime_sec when; struct datetime dt; char date[DATE822FMT]; int nparams; char strnum[FMT_ULONG]; make_name(info,table?"_":0,table,0); /* SELECT (*) FROM list_slog WHERE fromline LIKE '%search%' OR address */ /* LIKE '%search%' ORDER BY tai; */ /* The '*' is formatted to look like the output of the non-mysql version */ /* This requires reading the entire table, since search fields are not */ /* indexed, but this is a rare query and time is not of the essence. */ stralloc_copys(&query,"SELECT "); stralloc_cats(&query,sql_searchlog_select_defn); stralloc_cats(&query," FROM "); stralloc_cat(&query,&name); stralloc_cats(&query,"_slog"); if (*search) { /* We can afford to wait for LIKE '%xx%' */ stralloc_copys(¶ms[0],search); stralloc_copys(¶ms[1],search); nparams = 2; stralloc_cats(&query," WHERE "); stralloc_cats(&query,sql_searchlog_where_defn); } else nparams = 0; /* ordering by tai which is an index */ stralloc_cats(&query," ORDER by tai"); result = sql_select(info,&query,nparams,params); while (sql_fetch_row(info,result,2,params)) { stralloc_0(¶ms[0]); (void)scan_ulong(params[0].s,&when); datetime_tai(&dt,when); stralloc_copyb(¶ms[0],date,date822fmt(date,&dt)-1); stralloc_cats(¶ms[0],": "); stralloc_catb(¶ms[0],strnum,fmt_ulong(strnum,when)); stralloc_cats(¶ms[0]," "); stralloc_cat(¶ms[0],¶ms[1]); if (subwrite(params[0].s,params[0].len) == -1) die_write(); } sql_free_result(info,result); }
void doanddie(char *user, unsigned int userlen /* including 0 byte */, char *pass) { int child; int wstat; int pi[2]; close(3); if (pipe(pi) == -1) die_pipe(); if (pi[0] != 3) die_pipe(); switch(child = fork()) { case -1: die_fork(); case 0: close(pi[1]); sig_pipedefault(); execvp(*childargs,childargs); _exit(1); } close(pi[0]); substdio_fdbuf(&ssup,subwrite,pi[1],upbuf,sizeof upbuf); if (substdio_put(&ssup,user,userlen) == -1) die_write(); if (substdio_put(&ssup,pass,str_len(pass) + 1) == -1) die_write(); if (substdio_puts(&ssup,"<") == -1) die_write(); if (substdio_puts(&ssup,unique) == -1) die_write(); if (substdio_puts(&ssup,hostname) == -1) die_write(); if (substdio_put(&ssup,">",2) == -1) die_write(); if (substdio_flush(&ssup) == -1) die_write(); close(pi[1]); byte_zero(pass,str_len(pass)); byte_zero(upbuf,sizeof upbuf); if (wait_pid(&wstat,child) == -1) die(); if (wait_crashed(wstat)) die_childcrashed(); switch (wait_exitcode(wstat)) { case 0: die(); case 1: die_1(); case 2: die_2(); case 25: die_25(); case 3: die_3(); case 4: die_4(); case 5: die_5(); case 6: die_6(); case 61: die_61(); case 62: die_62(); case 7: die_7(); case 8: die_nomem(); default: die_unknown(); } die(); }
static inline int32_t get_len(char end) { char ch; int32_t len = 0; for (;;) { ch = get_ch(); if (ch == end) break; if ((ch < '0') || (ch > '9')) die_format(); if (len > 429496720) { errno = ENOMEM; die_write(); } len = len * 10 + (ch - '0'); } return len; }
/* Outputs all addresses in the table through subwrite. 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. */ static unsigned long _putsubs(struct subdbinfo *info, const char *table, unsigned long hash_lo, unsigned long hash_hi, int subwrite()) /* write function. */ { unsigned long no = 0L; sqlite3_stmt *stmt; int res; int length; const char *row; /* main query */ if (!stralloc_copys(&line,"SELECT address FROM ")) die_nomem(); if (!stralloc_cat_table(&line,info,table)) die_nomem(); if (!stralloc_cats(&line," WHERE hash BETWEEN ")) die_nomem(); if (!stralloc_catb(&line,strnum,fmt_ulong(strnum,hash_lo))) die_nomem(); if (!stralloc_cats(&line," AND ")) die_nomem(); if (!stralloc_catb(&line,strnum,fmt_ulong(strnum,hash_hi))) die_nomem(); if (!stralloc_0(&line)) die_nomem(); if ((stmt = _sqlquery(info, &line)) == NULL) strerr_die2x(111,FATAL,sqlite3_errmsg((sqlite3*)info->conn)); no = 0; while ((res = sqlite3_step(stmt)) != SQLITE_DONE) { if (res != SQLITE_ROW) strerr_die2x(111,FATAL,sqlite3_errmsg((sqlite3*)info->conn)); /* this is safe even if someone messes with the address field def */ length = sqlite3_column_bytes(stmt, 0); row = (const char*)sqlite3_column_text(stmt, 0); if (subwrite(row,length) == -1) die_write(); no++; /* count for list-list fxn */ } sqlite3_finalize(stmt); return no; }
int main() { umask(033); if (chdir(auto_qmail) == -1) strerr_die4sys(111,FATAL,"unable to chdir to ",auto_qmail,": "); fd = open_read("control/morercpthosts"); if (fd == -1) die_read(); substdio_fdbuf(&ssin,read,fd,inbuf,sizeof inbuf); fdtemp = open_trunc("control/morercpthosts.tmp"); if (fdtemp == -1) die_write(); if (cdbmss_start(&cdbmss,fdtemp) == -1) die_write(); for (;;) { if (getln(&ssin,&line,&match,'\n') != 0) die_read(); case_lowerb(line.s,line.len); while (line.len) { if (line.s[line.len - 1] == ' ') { --line.len; continue; } if (line.s[line.len - 1] == '\n') { --line.len; continue; } if (line.s[line.len - 1] == '\t') { --line.len; continue; } if (line.s[0] != '#') if (cdbmss_add(&cdbmss,line.s,line.len,"",0) == -1) die_write(); break; } if (!match) break; } if (cdbmss_finish(&cdbmss) == -1) die_write(); if (fsync(fdtemp) == -1) die_write(); if (close(fdtemp) == -1) die_write(); /* NFS stupidity */ if (rename("control/morercpthosts.tmp","control/morercpthosts.cdb") == -1) strerr_die2sys(111,FATAL,"unable to move control/morercpthosts.tmp to control/morercpthosts.cdb"); _exit(0); }
int main(int argc, char **argv) { umask(033); if (argc != 3) strerr_die1sys(111,"qmail-cdb: usage: qmail-cdb rules.cdb rules.tmp"); substdio_fdbuf(&ssin,subread,0,inbuf,sizeof inbuf); fdtemp = open_trunc(argv[2]); if (fdtemp == -1) die_write(argv[2]); if (cdb_make_start(&cdbm,fdtemp) == -1) die_write(argv[2]); for (;;) { if (getln(&ssin,&line,&match,'\n') != 0) die_read(); case_lowerb(line.s,line.len); while (line.len) { if (line.s[line.len - 1] == ' ') { --line.len; continue; } if (line.s[line.len - 1] == '\n') { --line.len; continue; } if (line.s[line.len - 1] == '\t') { --line.len; continue; } if (line.s[0] != '#') if (cdb_make_add(&cdbm,line.s,line.len,"",0) == -1) die_write(argv[2]); break; } if (!match) break; } if (cdb_make_finish(&cdbm) == -1) die_write(argv[2]); if (fsync(fdtemp) == -1) die_write(argv[2]); if (close(fdtemp) == -1) die_write(argv[2]); /* NFS stupidity */ if (rename(argv[2],argv[1]) == -1) strerr_die5sys(111, FATAL, "unable to move ", argv[2], " to ", argv[1]); return 0; }
int std_subscribe(const char *dir, const char *subdir, const char *userhost, int flagadd, const char *comment, const char *event, int forcehash) /* add (flagadd=1) or remove (flagadd=0) userhost from the subscr. database */ /* dbname. Comment is e.g. the subscriber from line or name. It is added to */ /* the log. Event is the action type, e.g. "probe", "manual", etc. The */ /* direction (sub/unsub) is inferred from flagadd. Returns 1 on success, 0 */ /* on failure. If flagmysql is set and the file "sql" is found in the */ /* directory dbname, it is parsed and a mysql db is assumed. if forcehash is */ /* >=0 it is used in place of the calculated hash. This makes it possible to */ /* add addresses with a hash that does not exist. forcehash has to be 0..99. */ /* for unsubscribes, the address is only removed if forcehash matches the */ /* actual hash. This way, ezmlm-manage can be prevented from touching certain*/ /* addresses that can only be removed by ezmlm-unsub. Usually, this would be */ /* used for sublist addresses (to avoid removal) and sublist aliases (to */ /* prevent users from subscribing them (although the cookie mechanism would */ /* prevent the resulting duplicate message from being distributed. */ { int fdlock; unsigned int j; unsigned char ch,lcch; int match; int flagwasthere; if (userhost[str_chr(userhost,'\n')]) strerr_die2x(100,FATAL,ERR_ADDR_NL); if (!stralloc_copys(&addr,"T")) die_nomem(); if (!stralloc_cats(&addr,userhost)) die_nomem(); if (addr.len > 401) strerr_die2x(100,FATAL,ERR_ADDR_LONG); j = byte_rchr(addr.s,addr.len,'@'); if (j == addr.len) strerr_die2x(100,FATAL,ERR_ADDR_AT); case_lowerb(addr.s + j + 1,addr.len - j - 1); if (!stralloc_copy(&lcaddr,&addr)) die_nomem(); case_lowerb(lcaddr.s + 1,j - 1); /* make all-lc version of address */ if (forcehash >= 0 && forcehash <= 52) { ch = lcch = 64 + (unsigned char) forcehash; } else { ch = 64 + subhashsa(&addr); lcch = 64 + subhashsa(&lcaddr); } if (!stralloc_0(&addr)) die_nomem(); if (!stralloc_0(&lcaddr)) die_nomem(); std_makepath(&fn,dir,subdir,"/subscribers/",lcch); std_makepath(&fnlock,dir,subdir,"/lock",0); if (!stralloc_copyb(&fnnew,fn.s,fn.len-1)) die_nomem(); /* code later depends on fnnew = fn + 'n' */ if (!stralloc_cats(&fnnew,"n")) die_nomem(); if (!stralloc_0(&fnnew)) die_nomem(); fdlock = lockfile(fnlock.s); /* do lower case hashed version first */ fdnew = open_trunc(fnnew.s); if (fdnew == -1) die_write(); substdio_fdbuf(&ssnew,write,fdnew,ssnewbuf,sizeof(ssnewbuf)); flagwasthere = 0; fd = open_read(fn.s); if (fd == -1) { if (errno != error_noent) { close(fdnew); die_read(); } } else { substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf)); for (;;) { if (getln(&ss,&line,&match,'\0') == -1) { close(fd); close(fdnew); die_read(); } if (!match) break; if (line.len == addr.len) if (!case_diffb(line.s,line.len,addr.s)) { flagwasthere = 1; if (!flagadd) continue; } if (substdio_bput(&ssnew,line.s,line.len) == -1) { close(fd); close(fdnew); die_write(); } } close(fd); } if (flagadd && !flagwasthere) if (substdio_bput(&ssnew,addr.s,addr.len) == -1) { close(fdnew); die_write(); } if (substdio_flush(&ssnew) == -1) { close(fdnew); die_write(); } if (fsync(fdnew) == -1) { close(fdnew); die_write(); } close(fdnew); if (rename(fnnew.s,fn.s) == -1) strerr_die6sys(111,FATAL,ERR_MOVE,fnnew.s," to ",fn.s,": "); if ((ch == lcch) || flagwasthere) { close(fdlock); if (flagadd ^ flagwasthere) { if (!stralloc_0(&addr)) die_nomem(); logaddr(dir,subdir,event,addr.s+1,comment); return 1; } return 0; } /* If unsub and not found and hashed differ, OR */ /* sub and not found (so added with new hash) */ /* do the 'case-dependent' hash */ fn.s[fn.len - 2] = ch; fnnew.s[fnnew.len - 3] = ch; fdnew = open_trunc(fnnew.s); if (fdnew == -1) die_write(); substdio_fdbuf(&ssnew,write,fdnew,ssnewbuf,sizeof(ssnewbuf)); fd = open_read(fn.s); if (fd == -1) { if (errno != error_noent) { close(fdnew); die_read(); } } else { substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf)); for (;;) { if (getln(&ss,&line,&match,'\0') == -1) { close(fd); close(fdnew); die_read(); } if (!match) break; if (line.len == addr.len) if (!case_diffb(line.s,line.len,addr.s)) { flagwasthere = 1; continue; /* always want to remove from case-sensitive hash */ } if (substdio_bput(&ssnew,line.s,line.len) == -1) { close(fd); close(fdnew); die_write(); } } close(fd); } if (substdio_flush(&ssnew) == -1) { close(fdnew); die_write(); } if (fsync(fdnew) == -1) { close(fdnew); die_write(); } close(fdnew); if (rename(fnnew.s,fn.s) == -1) strerr_die6sys(111,FATAL,ERR_MOVE,fnnew.s," to ",fn.s,": "); close(fdlock); if (flagadd ^ flagwasthere) { if (!stralloc_0(&addr)) die_nomem(); logaddr(dir,subdir,event,addr.s+1,comment); return 1; } return 0; }
int main(int argc, char **argv) { int match; unsigned int at; log_init(STDERR, ~256, 0); if (read_controls(ctrls) == -1) die_control(); q = 0; do { if (getln(&ssin, &line, &match, '\0') != 0) { if (errno != error_timeout) die_read(); cleanup(); continue; } if (!match) { cleanup(); /* other side closed pipe */ break; } logit(32, "qmail-verfiy: verifying %S\n", &line); at = byte_rchr(line.s,line.len,'@'); if (at >= line.len) { if (substdio_puts(subfdout, "DSorry, address must " "include host name. (#5.1.3)") == -1) die_write(); if (substdio_putflush(subfdout, "", 1) == -1) die_write(); continue; } switch (lookup(&line)) { case 0: if (localdelivery()) { /* * Do the local address lookup. */ line.s[at] = '\0'; if (lookup_cdb(line.s) == 1) break; if (lookup_passwd(line.s) == 1) break; } /* Sorry, no mailbox here by that name. */ if (substdio_puts(subfdout, "DSorry, no mailbox here by that name. " "(#5.1.1)") == -1) die_write(); if (substdio_putflush(subfdout, "", 1) == -1) die_write(); break; case 1: default: break; } } while (1); return 0; }
void putflush(void) { if (buffer_flush(buffer_1) == -1) die_write(); }
void put(char *buf,off_t len) { if (buffer_put(buffer_1,buf,len) == -1) die_write(); }
int lookup(stralloc *mail) { const char *attrs[] = { LDAP_ISACTIVE, 0 }; char *f; int done; int status; int rv; if (q == 0) { q = qldap_new(); if (q == 0) die_nomem(); rv = qldap_open(q); if (rv != OK) die_temp(); rv = qldap_bind(q, 0, 0); if (rv != OK) die_temp(); } /* * this handles the "catch all" and "-default" extension * but also the normal eMail address. * Code handels also mail addresses with multiple '@' safely. * at = index to last @ sign in mail address * escaped = ldap escaped mailaddress * len = length of escaped mailaddress * i = position of current '-' or '@' */ done = 0; do { f = filter_mail(mail->s, &done); if (f == (char *)0) die_nomem(); logit(16, "ldapfilter: '%s'\n", f); /* do the search for the email address */ rv = qldap_lookup(q, f, attrs); switch (rv) { case OK: break; /* something found */ case TIMEOUT: /* temporary error but give up so that the * ldap server can recover */ die_timeout(); case TOOMANY: #ifdef DUPEALIAS if (substdio_putflush(subfdout, "K", 1) == -1) die_write(); qldap_free_results(q); #else /* admin error, also temporary */ temp_fail(); #endif return (-1); case FAILED: /* ... again temporary */ temp_fail(); return (-1); case NOSUCH: break; } } while (rv != OK && !done); /* reset filter_mail */ filter_mail(0, 0); /* nothing found, try a local lookup or a alias delivery */ if (rv == NOSUCH) { qldap_free_results(q); return (0); } /* check if the ldap entry is active */ rv = qldap_get_status(q, &status); if (rv != OK) { temp_fail(); return (-1); } if (status == STATUS_BOUNCE) { /* Mailaddress is administratively disabled. (#5.2.1) */ if (substdio_puts(subfdout, "DMailaddress is administratively disabled. " "(#5.2.1)") == -1) die_write(); if (substdio_putflush(subfdout, "", 1) == -1) die_write(); qldap_free_results(q); return (1); } else if (status == STATUS_DELETE) { /* Sorry, no mailbox here by that name. (#5.1.1) */ if (substdio_puts(subfdout, "DSorry, no mailbox here by that name. " "(#5.1.1)") == -1) die_write(); if (substdio_putflush(subfdout, "", 1) == -1) die_write(); qldap_free_results(q); return (1); } /* OK */ if (substdio_putflush(subfdout, "K", 1) == -1) die_write(); qldap_free_results(q); return (1); }
int main(int argc,char **argv) { unsigned long ttl; struct stat st; int i; int j; int k; char ch; if (!*argv) die_usage(); if (!*++argv) die_usage(); fn = *argv; if (!*++argv) die_usage(); fnnew = *argv; if (!*++argv) die_usage(); if (str_diff(*argv,"add")) die_usage(); if (!*++argv) die_usage(); if (str_equal(*argv,"ns")) mode = '.'; else if (str_equal(*argv,"childns")) mode = '&'; else if (str_equal(*argv,"host")) mode = '='; else if (str_equal(*argv,"host6")) mode = '6'; else if (str_equal(*argv,"alias")) mode = '+'; else if (str_equal(*argv,"alias6")) mode = '3'; else if (str_equal(*argv,"mx")) mode = '@'; else die_usage(); if (!*++argv) die_usage(); if (!dns_domain_fromdot(&target,*argv,str_len(*argv))) nomem(); if (!*++argv) die_usage(); if (mode == '6' || mode == '3') { if (!ip6_scan(*argv,targetip6)) die_usage(); } else { if (!ip4_scan(*argv,targetip)) die_usage(); } umask(077); fd = open_read(fn); if (fd == -1) die_read(); if (fstat(fd,&st) == -1) die_read(); buffer_init(&b,buffer_unixread,fd,bspace,sizeof bspace); fdnew = open_trunc(fnnew); if (fdnew == -1) die_write(); if (fchmod(fdnew,st.st_mode & 0644) == -1) die_write(); buffer_init(&bnew,buffer_unixwrite,fdnew,bnewspace,sizeof bnewspace); switch(mode) { case '.': case '&': ttl = TTL_NS; for (i = 0;i < 26;++i) { ch = 'a' + i; if (!stralloc_copyb(&f[0],&ch,1)) nomem(); if (!stralloc_cats(&f[0],".ns.")) nomem(); if (!dns_domain_todot_cat(&f[0],target)) nomem(); if (!dns_domain_fromdot(&names[i],f[0].s,f[0].len)) nomem(); } break; case '+': case '=': case '6': case '3': ttl = TTL_POSITIVE; break; case '@': ttl = TTL_POSITIVE; for (i = 0;i < 26;++i) { ch = 'a' + i; if (!stralloc_copyb(&f[0],&ch,1)) nomem(); if (!stralloc_cats(&f[0],".mx.")) nomem(); if (!dns_domain_todot_cat(&f[0],target)) nomem(); if (!dns_domain_fromdot(&names[i],f[0].s,f[0].len)) nomem(); } break; } while (match) { if (getln(&b,&line,&match,'\n') == -1) die_read(); put(line.s,line.len); if (line.len && !match) put("\n",1); while (line.len) { ch = line.s[line.len - 1]; if ((ch != ' ') && (ch != '\t') && (ch != '\n')) break; --line.len; } if (!line.len) continue; if (line.s[0] == '#') continue; j = 1; for (i = 0;i < NUMFIELDS;++i) { if (j >= line.len) { if (!stralloc_copys(&f[i],"")) nomem(); } else { k = byte_chr(line.s + j,line.len - j,':'); if (!stralloc_copyb(&f[i],line.s + j,k)) nomem(); j += k + 1; } } switch(mode) { case '.': case '&': if (line.s[0] == mode) { if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (dns_domain_equal(d1,target)) { if (byte_chr(f[2].s,f[2].len,'.') >= f[2].len) { if (!stralloc_cats(&f[2],".ns.")) nomem(); if (!stralloc_catb(&f[2],f[0].s,f[0].len)) nomem(); } if (!dns_domain_fromdot(&d2,f[2].s,f[2].len)) nomem(); if (!stralloc_0(&f[3])) nomem(); if (!scan_ulong(f[3].s,&ttl)) ttl = TTL_NS; for (i = 0;i < 26;++i) if (dns_domain_equal(d2,names[i])) { used[i] = 1; break; } } } break; case '=': if (line.s[0] == '=') { if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (dns_domain_equal(d1,target)) strerr_die2x(100,FATAL,"host name already used"); if (!stralloc_0(&f[1])) nomem(); if (ip4_scan(f[1].s,ip)) if (byte_equal(ip,4,targetip)) strerr_die2x(100,FATAL,"IP address already used"); } break; case '6': if (line.s[0] == '6') { if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (dns_domain_equal(d1,target)) strerr_die2x(100,FATAL,"host name already used"); if (!stralloc_0(&f[1])) nomem(); if (ip6_scan(f[1].s,ip6)) if (byte_equal(ip,16,targetip6)) strerr_die2x(100,FATAL,"IPv6 address already used"); } break; case '@': if (line.s[0] == '@') { if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem(); if (dns_domain_equal(d1,target)) { if (byte_chr(f[2].s,f[2].len,'.') >= f[2].len) { if (!stralloc_cats(&f[2],".mx.")) nomem(); if (!stralloc_catb(&f[2],f[0].s,f[0].len)) nomem(); } if (!dns_domain_fromdot(&d2,f[2].s,f[2].len)) nomem(); if (!stralloc_0(&f[4])) nomem(); if (!scan_ulong(f[4].s,&ttl)) ttl = TTL_POSITIVE; for (i = 0;i < 26;++i) if (dns_domain_equal(d2,names[i])) { used[i] = 1; break; } } } break; } } if (!stralloc_copyb(&f[0],&mode,1)) nomem(); if (!dns_domain_todot_cat(&f[0],target)) nomem(); if (!stralloc_cats(&f[0],":")) nomem(); if (mode == '6' || mode == '3') { if (!stralloc_catb(&f[0],ip6str,ip6_fmt_flat(ip6str,targetip6))) nomem(); } else { if (!stralloc_catb(&f[0],ipstr,ip4_fmt(ipstr,targetip))) nomem(); } switch(mode) { case '.': case '&': case '@': for (i = 0;i < 26;++i) if (!used[i]) break; if (i >= 26) strerr_die2x(100,FATAL,"too many records for that domain"); ch = 'a' + i; if (!stralloc_cats(&f[0],":")) nomem(); if (!stralloc_catb(&f[0],&ch,1)) nomem(); if (mode == '@') if (!stralloc_cats(&f[0],":")) nomem(); break; } if (!stralloc_cats(&f[0],":")) nomem(); if (!stralloc_catb(&f[0],strnum,fmt_ulong(strnum,ttl))) nomem(); if (!stralloc_cats(&f[0],"\n")) nomem(); put(f[0].s,f[0].len); if (buffer_flush(&bnew) == -1) die_write(); if (fsync(fdnew) == -1) die_write(); if (close(fdnew) == -1) die_write(); /* NFS dorks */ if (rename(fnnew,fn) == -1) strerr_die6sys(111,FATAL,"unable to move ",fnnew," to ",fn,": "); _exit(0); }
void put(const char *buf,unsigned int len) { if (buffer_putalign(&bnew,buf,len) == -1) die_write(); }
void put(char *buf,unsigned int len) { if (buffer_put(buffer_1small,buf,len) == -1) die_write(); }
int main(int argc, char **argv, char **envp) { char ch; struct cdbmake cm; array_t data = ARRAY_INIT(1); int32_t dlen; int fd; uint32_t i; array_t key = ARRAY_INIT(1); int32_t klen; char *path; char *tmp; if (!*argv || !*++argv) usage(); path = *argv; if (!*++argv) usage(); tmp = *argv; /* Create the temporary file and start the cdb creation process with it. */ fd = open("test.cdb", O_CREAT | O_TRUNC | O_WRONLY, 0644); if (fd == -1) strerr_die4sys(111, FATAL, "unable to create ", tmp, ": "); if (cdbmake_start(&cm, fd) == -1) strerr_die2sys(111, FATAL, "cdbmake initialization failed: "); for (;;) { /* Skip over new lines and require the first character to be '+'. */ ch = get_ch(); if (ch == '\n') break; if (ch != '+') die_format(); /* Read the key length. */ klen = get_len(','); if (klen == -1) die_format(); /* Read the data length. */ dlen = get_len(':'); if (dlen == -1) die_format(); /* Truncate the key array and load it with the key from the cdb record. */ array_trunc(&key); for (i = 0; i < klen; i++) { ch = get_ch(); array_append(&key, &ch, 1); } /* Verify the separator is ->. */ if ((get_ch() != '-') || (get_ch() != '>')) die_format(); /* Truncate the data array and load it with the data from the cdb record. */ array_trunc(&data); for (i = 0; i < dlen; i++) { ch = get_ch(); array_append(&data, &ch, 1); } /* The line is valid, so add it to the cdb file and check that it ends with * a new line. */ if (cdbmake_add(&cm, array_start(&key), klen, array_start(&data), dlen) == -1) die_write(); if (get_ch() != '\n') die_format(); } /* Finish the cdb file, sync it to disk, close it, and finally rename it to * the target path. */ if (cdbmake_finish(&cm) == -1) die_write(); if (fsync(fd) == -1) die_write(); if (close(fd) == -1) die_write(); if (rename(tmp, path) == -1) strerr_die6sys(111, FATAL, "unable to rename ", tmp, " to ", path, ": "); _exit(0); }
int lookup_cdb(const char *mail) { int fd; int flagwild; int r; if (!stralloc_copys(&lower, "!")) die_nomem(); if (!stralloc_cats(&lower, mail)) die_nomem(); if (!stralloc_0(&lower)) die_nomem(); case_lowerb(lower.s, lower.len); fd = open_read("users/cdb"); if (fd == -1) if (errno != error_noent) die_cdb(); if (fd != -1) { uint32 dlen; unsigned int i; cdb_init(&cdb, fd); r = cdb_seek(&cdb, "", 0, &dlen); if (r != 1) die_cdb(); if (!stralloc_ready(&wildchars, (unsigned int) dlen)) die_nomem(); wildchars.len = dlen; if (cdb_bread(&cdb, wildchars.s, wildchars.len) == -1) die_cdb(); i = lower.len; flagwild = 0; do { /* i > 0 */ if (!flagwild || i == 1 || byte_chr(wildchars.s, wildchars.len, lower.s[i - 1]) < wildchars.len) { r = cdb_seek(&cdb,lower.s,i,&dlen); if (r == -1) die_cdb(); if (r == 1) { /* OK */ if (substdio_putflush(subfdout, "K", 1) == -1) die_write(); cdb_free(&cdb); close(fd); return (1); } } --i; flagwild = 1; } while (i); close(fd); } return (0); }