int main (int argc, const char * const *argv, const char * const *envp) { int opt; int wtmp =0; progname =*argv; while ((opt =getopt(argc, argv, "wV")) != opteof) { switch(opt) { case 'w': wtmp =1; break; case 'V': strerr_warn1("$Id: cb399098f794012a7f5e6a3a7090b2d53b86c08c $", 0); case '?': usage(); } } argv +=optind; if (! argv || ! *argv) usage(); if (utmp_logout(*argv) == -1) strerr_die4x(111, WARNING, "unable to logout line ", *argv, " in utmp: no such entry"); if (wtmp) if (wtmp_logout(*argv) == -1) strerr_die4sys(111, WARNING, "unable to logout line ", *argv, " in wtmp: "); _exit(0); }
int read_old_config(void) { unsigned char ch; int fdin; int match; /* for edit, try to get args from dir/config */ dirplusmake("/config"); if ((fdin = open_read(dirplus.s)) == -1) { if (errno != error_noent) die_read(); return 0; } else { substdio_fdbuf(&sstext,read,fdin,textbuf,sizeof(textbuf)); for (;;) { if (getln(&sstext,&line,&match,'\n') == -1) die_read(); if (!match) break; if (line.s[0] == '#') continue; if (line.len == 1) break; if (line.s[1] != ':') break; line.s[line.len - 1] = '\0'; switch (ch = line.s[0]) { case 'X': if (euid > 0 && !flags['c' - 'a'] && (cfname.len == 0)) stralloc_copys(&cfname,line.s+2); break; /* for safety: ignore if root */ case 'T': stralloc_copys(&dot,line.s+2); break; case 'L': stralloc_copys(&local,line.s+2); break; case 'H': stralloc_copys(&host,line.s+2); break; case 'C': stralloc_copys(&code,line.s+2); break; case 'F': stralloc_copys(&oldflags,line.s+2); break; case 'D': break; /* no reason to check */ default: if (ch == '0' || (ch >= '3' && ch <= '9')) { if (usecfg && popt[ch - '0'].len == 0) stralloc_copys(&popt[ch-'0'],line.s+2); } else strerr_die4x(111,FATAL,MSG1(ERR_SYNTAX,dirplus.s),": ",line.s+2); break; } } close(fdin); } return 1; }
void load_config(const char *dir) { load_flags(dir); switch(slurp("key",&key,512)) { case -1: strerr_die4sys(111,FATAL,ERR_READ,dir,"/key: "); case 0: strerr_die4x(100,FATAL,dir,"/key",ERR_NOEXIST); } /* There are problems with using getconf_line to fetch the ezmlmrc * pointer, since the alt location for "ezmlmrc" turns out to be the * whole ezmlmrc file itself. */ switch (slurp("ezmlmrc",&ezmlmrc,64)) { case -1: strerr_die4sys(111,FATAL,ERR_READ,dir,"/ezmlmrc: "); case 0: ezmlmrc.len = 0; } ezmlmrc.len = byte_chr(ezmlmrc.s,ezmlmrc.len,'\n'); getconf_line(&outhost,"outhost",1,dir); getconf_line(&outlocal,"outlocal",1,dir); if (!stralloc_copy(&local,&outlocal)) die_nomem(); getconf_line(&listid,"listid",0,dir); if (getconf_line(&charset,"charset",0,dir)) { if (charset.len >= 2 && charset.s[charset.len - 2] == ':') { if (charset.s[charset.len - 1] == 'B' || charset.s[charset.len - 1] == 'Q') { flagcd = charset.s[charset.len - 1]; charset.s[charset.len - 2] = '\0'; } } } else if (!stralloc_copys(&charset,TXT_DEF_CHARSET)) die_nomem(); if (!stralloc_0(&charset)) die_nomem(); // FIXME: need to handle escapes in mailinglist getconf_line(&mailinglist,"mailinglist",1,dir); }
static void load_config(void) { load_flags(); key.len = 0; switch(slurp("key",&key,512)) { case -1: strerr_die2sys(111,FATAL,MSG1(ERR_READ,"key")); case 0: strerr_die4x(100,FATAL,listdir,"/key",MSG(ERR_NOEXIST)); } /* There are problems with using getconf_line to fetch the ezmlmrc * pointer, since the alt location for "ezmlmrc" turns out to be the * whole ezmlmrc file itself. */ switch (slurp("ezmlmrc",&ezmlmrc,64)) { case -1: strerr_die2sys(111,FATAL,MSG1(ERR_READ,"ezmlmrc")); case 0: ezmlmrc.len = 0; } ezmlmrc.len = byte_chr(ezmlmrc.s,ezmlmrc.len,'\n'); getconf_line(&outhost,"outhost",1); getconf_line(&outlocal,"outlocal",1); if (!stralloc_copy(&local,&outlocal)) die_nomem(); getconf_line(&listid,"listid",0); if (getconf_line(&charset,"charset",0)) { if (charset.len >= 2 && charset.s[charset.len - 2] == ':') { if (charset.s[charset.len - 1] == 'B' || charset.s[charset.len - 1] == 'Q') { flagcd = charset.s[charset.len - 1]; charset.s[charset.len - 2] = '\0'; } } } else if (!stralloc_copys(&charset,TXT_DEF_CHARSET)) die_nomem(); if (!stralloc_0(&charset)) die_nomem(); }
static void forward(const char *rcpt) { char buf[4096]; const char *dtline; const char *err; int r; if (qmail_open(&qq,0) == -1) strerr_die2sys(111,FATAL,MSG(ERR_QMAIL_QUEUE)); if ((dtline = env_get("DTLINE")) != 0) qmail_puts(&qq,dtline); while ((r = read(0,buf,sizeof buf)) > 0) qmail_put(&qq,buf,r); if (r == -1) strerr_die2sys(111,FATAL,MSG(ERR_READ_STDIN)); qmail_from(&qq,sender); qmail_to(&qq,rcpt); if (*(err = qmail_close(&qq)) != '\0') strerr_die4x(111,FATAL,MSG(ERR_TMP_QMAIL_QUEUE),": ",err + 1); strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0; substdio_puts(subfderr,"qp "); substdio_puts(subfderr,strnum); substdio_putsflush(subfderr,"\n"); ++did_forward; }
void fail(qldap *q, const char *f, int r) { qldap_free(q); strerr_die4x(111, FATAL, f ,": ", qldap_err_str(r)); }
void usage () { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); }
void makedir(const char *s) { if (mkdir(s,0755) == -1) if (errno != error_exist) strerr_die4x(111,FATAL,ERR_CREATE,s,": "); }
void sendnotice(const char *d) /* sends file pointed to by d to the address in the return-path of the */ /* message. */ { unsigned int x,y; const char *err; if (qmail_open(&qq, (stralloc *) 0) == -1) strerr_die2sys(111,FATAL,MSG(ERR_QMAIL_QUEUE)); fd = open_read(d); if (fd == -1) strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,d)); substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf)); if (getln(&sstext,&line,&match,'\n') == -1) die_read(); if (!match) die_read(); if (!case_startb(line.s,line.len,"return-path:")) die_read(); x = 12 + byte_chr(line.s + 12,line.len-12,'<'); y = byte_rchr(line.s + x,line.len-x,'>'); if (x != line.len && x+y != line.len) { if (!stralloc_copyb(&to,line.s+x+1, y-1)) die_nomem(); if (!stralloc_0(&to)) die_nomem(); } else die_read(); hdr_add2s("Mailing-List: ",MSG(TXT_MAILING_LIST)); if (listid.len > 0) hdr_add2("List-ID: ",listid.s,listid.len); hdr_datemsgid(when+msgnum++); hdr_from("-help"); hdr_subject(MSG(SUB_RETURNED_POST)); hdr_add2s("To: ",to.s); if (flagmime) { hdr_mime(CTYPE_MULTIPART); hdr_boundary(0); hdr_ctype(CTYPE_TEXT); hdr_transferenc(); } else qmail_puts(&qq,"\n\n"); copy(&qq,"text/top",flagcd); copy(&qq,"text/mod-timeout",flagcd); if (flagcd == 'B') { encodeB("",0,&line,2); qmail_put(&qq,line.s,line.len); } if (flagmime) { hdr_boundary(0); hdr_ctype(CTYPE_MESSAGE); qmail_puts(&qq,"\n"); } if (seek_begin(fd) == -1) strerr_die2sys(111,FATAL,MSG1(ERR_SEEK,d)); substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf)); if (qmail_copy(&qq,&sstext,-1) != 0) die_read(); close (fd); if (flagmime) hdr_boundary(1); if (!stralloc_copy(&line,&outlocal)) die_nomem(); if (!stralloc_cats(&line,"-return-@")) die_nomem(); if (!stralloc_cat(&line,&outhost)) die_nomem(); if (!stralloc_0(&line)) die_nomem(); qmail_from(&qq,line.s); /* sender */ qmail_to(&qq,to.s); if (*(err = qmail_close(&qq)) != '\0') strerr_die4x(111,FATAL,MSG(ERR_TMP_QMAIL_QUEUE),": ", err + 1); strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0; strerr_warn2("ezmlm-clean: info: qp ",strnum,0); }
void fatalx(const char *m0, const char *m1) { strerr_die4x(111, FATAL, m0, ": ", m1); }
int main(int argc,char **argv) { char strnum[FMT_ULONG]; char *action; char *dtline; char *nhost; const char *err; unsigned int i; int match; int opt; sig_pipeignore(); opt = getconfopt(argc,argv,options,1,0); if (!(split = argv[opt])) split = "split"; if (flagdo) { sender = get_sender(); if (!sender) die_sender(); if (!*sender) strerr_die2x(100,FATAL,MSG(ERR_BOUNCE)); if (!sender[str_chr(sender,'@')]) strerr_die2x(100,FATAL,MSG(ERR_ANONYMOUS)); if (str_equal(sender,"#@[]")) strerr_die2x(100,FATAL,MSG(ERR_BOUNCE)); action = env_get("DEFAULT"); if (!action) strerr_die2x(100,FATAL,MSG(ERR_NODEFAULT)); if (!stralloc_copys(&target,sender)) die_nomem(); if (action[0]) { i = str_chr(action,'-'); if (action[i]) { action[i] = '\0'; if (!stralloc_copys(&target,action + i + 1)) die_nomem(); i = byte_rchr(target.s,target.len,'='); if (i < target.len) target.s[i] = '@'; } } if (!stralloc_0(&target)) die_nomem(); if (case_diffs(action,ACTION_SUBSCRIBE) && case_diffs(action,ALT_SUBSCRIBE) && case_diffs(action,ACTION_UNSUBSCRIBE) && case_diffs(action,ALT_UNSUBSCRIBE)) _exit(0); /* not for us */ if (findname()) { /* new sender */ if (!stralloc_copy(&from,&outlocal)) die_nomem(); if (!stralloc_cats(&from,"-return-@")) die_nomem(); if (!stralloc_cat(&from,&outhost)) die_nomem(); if (!stralloc_0(&from)) die_nomem(); nhost = name.s + str_rchr(name.s,'@'); /* name must have '@'*/ *(nhost++) = '\0'; if (!stralloc_copys(&to,name.s)) die_nomem(); /* local */ if (!stralloc_append(&to,'-')) die_nomem(); /* - */ if (!stralloc_cats(&to,action)) die_nomem(); /* subscribe */ if (!stralloc_append(&to,'-')) die_nomem(); /* - */ if (target.s[i = str_rchr(target.s,'@')]) target.s[i] = '='; if (!stralloc_cats(&to,target.s)) die_nomem(); /* target */ if (!stralloc_append(&to,'@')) die_nomem(); /* - */ if (!stralloc_cats(&to,nhost)) die_nomem(); /* host */ if (!stralloc_0(&to)) die_nomem(); dtline = env_get("DTLINE"); if (!dtline) strerr_die2x(100,FATAL,MSG(ERR_NODTLINE)); if (qmail_open(&qq) == -1) strerr_die2sys(111,FATAL,MSG(ERR_QMAIL_QUEUE)); qmail_puts(&qq,dtline); /* delivered-to */ if (qmail_copy(&qq,subfdin,0) != 0) strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT)); qmail_from(&qq,from.s); qmail_to(&qq,to.s); if (*(err = qmail_close(&qq)) != '\0') strerr_die4x(111,FATAL,MSG(ERR_TMP_QMAIL_QUEUE),": ",err + 1); strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0; strerr_die3x(99,INFO,"qp ",strnum); } _exit(0); } else { for (;;) { if (getln(subfdin,&line,&match,'\n') == -1) strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT)); if (!match) break; if (line.len == 1) continue; /* ignore blank lines */ if (line.s[0] == '#') continue; /* ignore comments */ if (!stralloc_copy(&target,&line)) die_nomem(); target.s[target.len - 1] = '\0'; (void) findname(); if (!stralloc_cats(&name,": ")) die_nomem(); if (!stralloc_cats(&name,target.s)) die_nomem(); if (!stralloc_append(&name,'\n')) die_nomem(); if (substdio_put(subfdout,name.s,name.len) == -1) strerr_die2sys(111,FATAL,MSG(ERR_WRITE_STDOUT)); } if (substdio_flush(subfdout) == -1) strerr_die2sys(111,FATAL,MSG(ERR_FLUSH_STDOUT)); _exit(0); } (void)argc; }
static void fatalmx(char *m0) { strerr_die4x(111, NAME, id, FATAL, m0); }
static void die_nomem() { strerr_die4x(111, NAME, id, FATAL, "out of memory."); }
int main(int argc,char **argv) { unsigned long maxmsgsize = 0L; unsigned long minmsgsize = 0L; unsigned long msgsize = 0L; char linetype = ' '; char *cp, *cpstart, *cpafter; const char *dir; const char *err; const char *sender; unsigned int len; int match; getconfopt(argc,argv,options,-1,&dir); if (dir) { startup(dir); flagparsemime = 1; /* only if dir do we have mimeremove/reject */ if (getconf_line(&line,"msgsize",0)) { if (!stralloc_0(&line)) die_nomem(); len = scan_ulong(line.s,&maxmsgsize); if (line.s[len] == ':') scan_ulong(line.s+len+1,&minmsgsize); } if (flagforward) { if (!stralloc_copys(&mydtline,"Delivered-To: command forwarder for ")) die_nomem(); if (!stralloc_catb(&mydtline,outlocal.s,outlocal.len)) die_nomem(); if (!stralloc_cats(&mydtline,"@")) die_nomem(); if (!stralloc_catb(&mydtline,outhost.s,outhost.len)) die_nomem(); if (!stralloc_cats(&mydtline,"\n")) die_nomem(); } } else { flagtook = 1; /* if no "dir" we can't get outlocal/outhost */ flagforward = 0; /* nor forward requests */ } sender = get_sender(); if (!sender) die_sender(); if (!*sender) strerr_die2x(100,FATAL,MSG(ERR_BOUNCE)); if (flagparsemime) { /* set up MIME parsing */ if (getconf(&mimeremove,"mimekeep",0)) mimeremoveflag = 1; else getconf(&mimeremove,"mimeremove",0); constmap_init(&mimeremovemap,mimeremove.s,mimeremove.len,0); getconf(&mimereject,"mimereject",0); constmap_init(&mimerejectmap,mimereject.s,mimereject.len,0); } if (flagheaderreject && dir) { getconf(&headerreject,"headerreject",0); constmap_init(&headerrejectmap,headerreject.s,headerreject.len,0); } for (;;) { if (getln(&ssin,&line,&match,'\n') == -1) strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT)); if (!match) break; if (flagheaderreject && dir) if (constmap(&headerrejectmap,line.s,byte_chr(line.s,line.len,':'))) strerr_die2x(100,FATAL,MSG(ERR_MAILING_LIST)); if (line.len == 1) break; cp = line.s; len = line.len; if ((*cp == ' ' || *cp == '\t')) { switch(linetype) { case 'T': if (!stralloc_catb(&to,cp,len-1)) die_nomem(); break; case 'S': if (!stralloc_catb(&subject,cp,len-1)) die_nomem(); break; case 'C': if (!stralloc_catb(&content,cp,len-1)) die_nomem(); break; case 'P': if (!stralloc_catb(&precd,cp,len-1)) die_nomem(); break; default: break; } } else { if (!flagtook && (case_startb(cp,len,"to:") || case_startb(cp,len,"cc:"))) { linetype = 'T'; /* cat so that To/Cc don't overwrite */ if (!stralloc_catb(&to,line.s + 3,line.len - 4)) die_nomem(); } else if ((flagneedsubject || flagrejectcommands) && case_startb(cp,len,"subject:")) { if (!stralloc_copyb(&subject,cp+8,len-9)) die_nomem(); linetype = 'S'; } else if (case_startb(cp,len,"content-type:")) { if (!stralloc_copyb(&content,cp+13,len-14)) die_nomem(); linetype = 'C'; } else if (case_startb(cp,len,"precedence:")) { if (!stralloc_copyb(&precd,cp+11,len-12)) die_nomem(); linetype = 'P'; } else { if (flagforward && line.len == mydtline.len) { if (!byte_diff(line.s,line.len,mydtline.s)) strerr_die2x(100,FATAL,MSG(ERR_LOOPING)); } linetype = ' '; } } } if (precd.len >= 4 && (!case_diffb(precd.s + precd.len - 4,4,"junk") || !case_diffb(precd.s + precd.len - 4,4,"bulk"))) strerr_die1x(99,MSG(ERR_JUNK)); /* ignore precedence junk/bulk */ cp = subject.s; len = subject.len; while (len && (cp[len-1] == ' ' || cp[len-1] == '\t')) --len; while (len && ((*cp == ' ') || (*cp == '\t'))) { ++cp; --len; } flaghavesubject = 1; if (flagbody) if ((len > 9 && case_starts(cp,"subscribe")) || (len > 11 && case_starts(cp,"unsubscribe"))) flaghavecommand = 1; switch(len) { case 0: flaghavesubject = 0; break; case 4: if (!case_diffb("help",4,cp)) flaghavecommand = 1; break; case 6: /* Why can't they just leave an empty subject empty? */ if (!case_diffb("(null)",6,cp)) flaghavesubject = 0; else if (!case_diffb("(none)",6,cp)) flaghavesubject = 0; else if (!case_diffb("remove",6,cp)) flaghavecommand = 1; break; case 9: if (!case_diffb("subscribe",9,cp)) flaghavecommand = 1; break; case 11: if (!case_diffb("unsubscribe",11,cp)) flaghavecommand = 1; break; case 12: if (!case_diffb("(no subject)",12,cp)) flaghavesubject = 0; break; default: break; } if (!flagtook && !getto(&to)) strerr_die2x(exitquiet,FATAL,MSG(ERR_NO_ADDRESS)); if (flagneedsubject && !flaghavesubject) strerr_die2x(100,FATAL,MSG(ERR_NO_SUBJECT)); if (flagrejectcommands && flaghavecommand) { if (flagforward) { /* flagforward => forward */ if (qmail_open(&qq) == -1) /* open queue */ strerr_die2sys(111,FATAL,MSG(ERR_QMAIL_QUEUE)); qmail_put(&qq,mydtline.s,mydtline.len); if (seek_begin(0) == -1) strerr_die2sys(111,FATAL,MSG(ERR_SEEK_INPUT)); if (qmail_copy(&qq,&ssin2,copylines) != 0) strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT)); if (!stralloc_copy(&to,&outlocal)) die_nomem(); if (!stralloc_cats(&to,"-request@")) die_nomem(); if (!stralloc_cat(&to,&outhost)) die_nomem(); if (!stralloc_0(&to)) die_nomem(); qmail_from(&qq,sender); qmail_to(&qq,to.s); if (*(err = qmail_close(&qq)) == '\0') { strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0; strerr_die2x(99,"ezmlm-request: info: forward qp ",strnum); } else strerr_die4x(111,FATAL,MSG(ERR_TMP_QMAIL_QUEUE),": ",err + 1); } else strerr_die2x(100,FATAL,MSG(ERR_SUBCOMMAND)); } if (content.len) { /* MIME header */ cp = content.s; len = content.len; while (len && (*cp == ' ' || *cp == '\t')) { ++cp; --len; } cpstart = cp; if (*cp == '"') { /* might be commented */ ++cp; cpstart = cp; while (len && *cp != '"') { ++cp; --len; } } else { while (len && *cp != ' ' && *cp != '\t' && *cp != ';') { ++cp; --len; } } if (flagparsemime) if ((!!constmap(&mimeremovemap,cpstart,cp-cpstart) ^ mimeremoveflag) || constmap(&mimerejectmap,cpstart,cp-cpstart)) { *(cp) = (char) 0; strerr_die2x(100,FATAL,MSG1(ERR_BAD_TYPE,cpstart)); } cpafter = content.s+content.len; while((cp += byte_chr(cp,cpafter-cp,';')) != cpafter) { ++cp; while (cp < cpafter && (*cp == ' ' || *cp == '\t')) ++cp; if (case_startb(cp,cpafter - cp,"boundary=")) { cp += 9; /* after boundary= */ if (cp < cpafter && *cp == '"') { ++cp; cpstart = cp; while (cp < cpafter && *cp != '"') ++cp; if (cp == cpafter) strerr_die1x(100,MSG(ERR_MIME_QUOTE)); } else { cpstart = cp; while (cp < cpafter && *cp != ';' && *cp != ' ' && *cp != '\t') ++cp; } if (!stralloc_copys(&boundary,"--")) die_nomem(); if (!stralloc_catb(&boundary,cpstart,cp-cpstart)) die_nomem(); break; } } /* got boundary, now parse for parts */ } for (;;) { if (getln(&ssin,&line,&match,'\n') == -1) strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT)); if (!match) break; if (line.len == 1) { flagcheck = 0; continue; /* Doesn't do continuation lines. _very_ unusual, and worst */ /* case one slips through that shouldn't have */ } else if (flagcheck && case_startb(line.s,line.len,"content-type:")) { cp = line.s + 13; len = line.len - 14; /* zap '\n' */ while (*cp == ' ' || *cp == '\t') { ++cp; --len; } cpstart = cp; if (*cp == '"') { /* quoted */ ++cp; cpstart = cp; while (len && *cp != '"') { ++cp; --len; } } else { /* not quoted */ while (len && *cp != ' ' && *cp != '\t' && *cp != ';') { ++cp; --len; } } if (flagparsemime && constmap(&mimerejectmap,cpstart,cp-cpstart)) { *cp = '\0'; strerr_die2x(100,FATAL,MSG1(ERR_BAD_PART,cpstart)); } } else if (boundary.len && *line.s == '-' && line.len > boundary.len && !str_diffn(line.s,boundary.s,boundary.len)) { flagcheck = 1; } else { if (!msgsize && flagbody) if (case_startb(line.s,line.len,"subscribe") || case_startb(line.s,line.len,"unsubscribe")) strerr_die2x(100,FATAL,MSG(ERR_BODYCOMMAND)); if (!flagcheck) { msgsize += line.len; if (maxmsgsize && msgsize > maxmsgsize) { strnum[fmt_ulong(strnum,maxmsgsize)] = 0; strerr_die2x(100,FATAL,MSG1(ERR_MAX_SIZE,strnum)); } } } } if (msgsize < minmsgsize) { strnum[fmt_ulong(strnum,minmsgsize)] = 0; strerr_die2x(100,FATAL,MSG1(ERR_MIN_SIZE,strnum)); } _exit(0); }
void setuidgid_usage() { strerr_die4x(100, "usage: ", progname, USAGE_SETUIDGID, "\n"); }
int findname(void) /* returns 1 if a matching line was found, 0 otherwise. name will contain */ /* the correct list address in either case */ { char *cpat,*cp1,*cp2,*cplast; const char *cpname; unsigned long u; unsigned char hash,hash_hi,hash_lo; unsigned int pos,pos_name,pos_hi; int fd,match; /* make case insensitive hash */ flagfound = 0; /* default */ cpname = ""; /* default */ if (!stralloc_copy(&lctarget,&target)) die_nomem(); case_lowerb(lctarget.s,lctarget.len -1); hash = subhashs(lctarget.s); /* make domain pointer */ cpat = lctarget.s + str_chr(lctarget.s,'@'); if (!*cpat) strerr_die4x(100,FATAL,ERR_ADDR_AT,": ",target.s); cplast = cpat + str_len(cpat) - 1; if (*cplast == '.') --cplast; /* annonying special case */ cp1 = cpat + byte_rchr(cpat,cplast - cpat, '.'); if (cp1 != cplast) { /* got one '.' */ if (!stralloc_copyb(&domain,cp1 + 1, cplast - cp1)) die_nomem(); cp2 = cpat + byte_rchr(cpat, cp1 - cpat,'.'); if (cp2 == cp1) cp2 = cpat; ++cp2; if (!stralloc_append(&domain,".")) die_nomem(); if (!stralloc_catb(&domain,cp2, cp1 - cp2)) die_nomem(); } else /* no '.' */ if (!stralloc_copyb(&domain,cpat + 1,cplast - cpat)) die_nomem(); if (!stralloc_0(&domain)) die_nomem(); if ((fd = open_read(split)) == -1) strerr_die4sys(111,FATAL,ERR_OPEN,split,": "); substdio_fdbuf(&sssp,read,fd,spbuf,(int) sizeof(spbuf)); lineno = 0; for (;;) { /* dom:hash_lo:hash_hi:listaddress */ if (getln(&sssp,&line,&match,'\n') == -1) strerr_die4sys(111,FATAL,ERR_READ,split,": "); lineno++; if (!match) break; if (line.s[0] == '#') continue; /* comment */ line.s[line.len - 1] = '\0'; /* no need to allow \0 in lines */ if (!line.s[pos = str_chr(line.s,':')]) continue; /* usually blank line */ line.s[pos] = '\0'; if (pos == 0 || /* no domain */ (case_starts(domain.s,line.s))) { /* or matching domain */ if (!line.s[++pos]) die_syntax(); pos_hi = pos + str_chr(line.s + pos,':'); if (!line.s[pos_hi]) die_syntax(); pos_hi++; (void) scan_ulong(line.s + pos, &u); /* scan_uint() not in ezmlm */ hash_lo = (unsigned char) u; (void) scan_ulong(line.s + pos_hi, &u); hash_hi = (unsigned char) u; pos_name = pos_hi + str_chr(line.s + pos_hi,':'); if (pos_hi == pos_name) hash_hi = 52L; /* default hi = 52 */ if (line.s[pos_name]) pos_name++; if (hash > hash_hi || hash < hash_lo) continue; /* not us */ cpname = line.s + pos_name; while (*cpname && /* isolate name */ (*cpname == ' ' || *cpname == '\t')) cpname++; pos = line.len - 2; while (pos && (line.s[pos] == '\n' || line.s[pos] == ' ' || line.s[pos] == '\t')) line.s[pos--] = '\0'; break; } } close(fd); if (*cpname) { if (!stralloc_copys(&name,cpname)) die_nomem(); if (byte_chr(name.s,name.len,'@') == name.len) { /* local sublist */ if (!stralloc_append(&name,"@")) die_nomem(); if (!stralloc_cat(&name,&outhost)) die_nomem(); } if (!stralloc_0(&name)) die_nomem(); return 1; } else { /* match without name or no match =>this list */ if (!stralloc_copy(&name,&outlocal)) die_nomem(); if (!stralloc_append(&name,"@")) die_nomem(); if (!stralloc_cat(&name,&outhost)) die_nomem(); if (!stralloc_0(&name)) die_nomem(); return 0; } }
void envuidgid_usage() { strerr_die4x(100, "usage: ", progname, USAGE_ENVUIDGID, "\n"); }
void main(int argc,char **argv) { char *sender; char *def; char *local; char *action; int flaginheader; int flagcomment; int flaggoodfield; int flagdone; int fd, fdlock; int match; const char *err; char encin = '\0'; unsigned int start,confnum; unsigned int pos,i; int child; int opt; char *cp,*cpnext,*cpfirst,*cplast,*cpafter; (void) umask(022); sig_pipeignore(); when = now(); if (!stralloc_copys(&sendopt,"-")) die_nomem(); opt = getconfopt(argc,argv,options,1,&dir); sender = get_sender(); if (!sender) strerr_die2x(100,FATAL,MSG(ERR_NOSENDER)); local = env_get("LOCAL"); if (!local) strerr_die2x(100,FATAL,MSG(ERR_NOLOCAL)); def = env_get("DEFAULT"); if (!def) strerr_die2x(100,FATAL,MSG(ERR_NODEFAULT)); if (!*sender) strerr_die2x(100,FATAL,MSG(ERR_BOUNCE)); if (!sender[str_chr(sender,'@')]) strerr_die2x(100,FATAL,MSG(ERR_ANONYMOUS)); if (str_equal(sender,"#@[]")) strerr_die2x(100,FATAL,MSG(ERR_BOUNCE)); /* local should be >= def, but who knows ... */ cp = local + str_len(local) - str_len(def) - 2; if (cp < local) die_badformat(); action = local + byte_rchr(local,cp - local,'-'); if (action == cp) die_badformat(); action++; if (!action[0]) die_badformat(); if (!str_start(action,ACTION_ACCEPT) && !str_start(action,ACTION_REJECT)) die_badformat(); start = str_chr(action,'-'); if (!action[start]) die_badformat(); confnum = 1 + start + str_chr(action + start + 1,'.'); if (!action[confnum]) die_badformat(); confnum += 1 + str_chr(action + confnum + 1,'.'); if (!action[confnum]) die_badformat(); if (!stralloc_copyb(&fnbase,action+start+1,confnum-start-1)) die_nomem(); if (!stralloc_0(&fnbase)) die_nomem(); cookie(hash,key.s,key.len,fnbase.s,"","a"); if (byte_diff(hash,COOKIE,action+confnum+1)) die_badformat(); fdlock = lockfile("mod/lock"); switch(checkfile(fnbase.s)) { case 0: strerr_die2x(100,FATAL,MSG(ERR_MOD_TIMEOUT)); case -1: /* only error if new request != action taken */ if (str_start(action,ACTION_ACCEPT)) strerr_die2x(0,INFO,MSG(ERR_MOD_ACCEPTED)); else strerr_die2x(100,FATAL,MSG(ERR_MOD_ACCEPTED)); case -2: if (str_start(action,ACTION_REJECT)) strerr_die2x(0,INFO,MSG(ERR_MOD_REJECTED)); else strerr_die2x(100,FATAL,MSG(ERR_MOD_REJECTED)); default: break; } /* Here, we have an existing filename in fnbase with the complete path */ /* from the current dir in fnmsg. */ if (str_start(action,ACTION_REJECT)) { if (qmail_open(&qq, (stralloc *) 0) == -1) strerr_die2sys(111,FATAL,MSG(ERR_QMAIL_QUEUE)); /* Build recipient from msg return-path */ fd = open_read(fnmsg.s); if (fd == -1) { if (errno != error_noent) strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,fnmsg.s)); else strerr_die2x(100,FATAL,MSG(ERR_MOD_TIMEOUT)); } substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf)); if (getln(&sstext,&line,&match,'\n') == -1 || !match) strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT)); maketo(); /* extract SENDER from return-path */ /* Build message */ hdr_add2s("Mailing-List: ",MSG(TXT_MAILING_LIST)); if (listid.len > 0) hdr_add2("List-ID: ",listid.s,listid.len); hdr_datemsgid(when); hdr_from("-owner"); if (replyto) hdr_add2s("Reply-To: ",replyto); hdr_add2s("To: ",to.s); hdr_subject(MSG(SUB_RETURNED_POST)); if (flagmime) { hdr_mime(CTYPE_MULTIPART); hdr_boundary(0); hdr_ctype(CTYPE_TEXT); hdr_transferenc(); } copy(&qq,"text/top",flagcd); copy(&qq,"text/mod-reject",flagcd); flagcomment = 0; flaginheader = 1; if (!stralloc_copys(&text,"")) die_nomem(); if (!stralloc_ready(&text,1024)) die_nomem(); for (;;) { /* copy moderator's rejection comment */ if (getln(subfdin,&line,&match,'\n') == -1) strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT)); if (!match) break; if (flaginheader) { if (case_startb(line.s,line.len,"Content-Transfer-Encoding:")) { pos = 26; while (line.s[pos] == ' ' || line.s[pos] == '\t') ++pos; if (case_startb(line.s+pos,line.len-pos,"base64")) encin = 'B'; else if (case_startb(line.s+pos,line.len-pos,"quoted-printable")) encin = 'Q'; } if (line.len == 1) flaginheader = 0; } else if (!stralloc_cat(&text,&line)) die_nomem(); } /* got body */ if (encin) { if (encin == 'B') decodeB(text.s,text.len,&line); else decodeQ(text.s,text.len,&line); if (!stralloc_copy(&text,&line)) die_nomem(); } cp = text.s; cpafter = text.s + text.len; if (!stralloc_copys(&line,"\n>>>>> -------------------- >>>>>\n")) die_nomem(); flaggoodfield = 0; flagdone = 0; while ((cpnext = cp + byte_chr(cp,cpafter-cp,'\n')) != cpafter) { i = byte_chr(cp,cpnext-cp,'%'); if (i <= 5 && cpnext-cp-i >= 3) { /* max 5 "quote characters" and space for %%% */ if (cp[i+1] == '%' && cp[i+2] == '%') { if (!flaggoodfield) { /* Start tag */ if (!stralloc_copyb("ed,cp,i)) die_nomem(); /* quote chars*/ flaggoodfield = 1; cp = cpnext + 1; cpfirst = cp; continue; } else { /* end tag */ if (flagdone) /* 0 no comment lines, 1 comment line */ flagdone = 2; /* 2 at least 1 comment line & end tag */ break; } } } if (flaggoodfield) { cplast = cpnext - 1; if (*cplast == '\r') /* CRLF -> '\n' for base64 encoding */ *cplast = '\n'; else ++cplast; /* NUL is now ok, so the test for it was removed */ flagdone = 1; i = cplast - cp + 1; if (quoted.len && quoted.len <= i && !str_diffn(cp,quoted.s,quoted.len)) { /* quote chars */ if (!stralloc_catb(&line,cp+quoted.len,i-quoted.len)) die_nomem(); } else if (!stralloc_catb(&line,cp,i)) die_nomem(); /* no quote chars */ } cp = cpnext + 1; } if (flagdone == 2) { if (!stralloc_cats(&line,"<<<<< -------------------- <<<<<\n")) die_nomem(); code_qput(line.s,line.len); } if (flagcd == 'B') { encodeB("",0,&line,2); qmail_put(&qq,line.s,line.len); } if (flagmime) { hdr_boundary(0); hdr_ctype(CTYPE_MESSAGE); } qmail_puts(&qq,"\n"); if (seek_begin(fd) == -1) strerr_die2sys(111,FATAL,MSG1(ERR_SEEK,fnmsg.s)); substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf)); if (qmail_copy(&qq,&sstext,-1) != 0) strerr_die2sys(111,FATAL,MSG1(ERR_READ,fnmsg.s)); close(fd); if (flagmime) hdr_boundary(1); if (!stralloc_copy(&line,&outlocal)) die_nomem(); if (!stralloc_cats(&line,"-return-@")) die_nomem(); if (!stralloc_cat(&line,&outhost)) die_nomem(); if (!stralloc_0(&line)) die_nomem(); qmail_from(&qq,line.s); if (to.len) qmail_to(&qq,to.s); if (!stralloc_copys(&fnnew,"mod/rejected/")) die_nomem(); if (!stralloc_cats(&fnnew,fnbase.s)) die_nomem(); if (!stralloc_0(&fnnew)) die_nomem(); /* this is strictly to track what happended to a message to give informative */ /* messages to the 2nd-nth moderator that acts on the same message. Since */ /* this isn't vital we ignore errors. Also, it is no big ideal if unlinking */ /* the old file fails. In the worst case it gets acted on again. If we issue */ /* a temp error the reject will be redone, which is slightly worse. */ if (*(err = qmail_close(&qq)) == '\0') { fd = open_trunc(fnnew.s); if (fd != -1) close(fd); unlink(fnmsg.s); strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0; strerr_die2x(0,"ezmlm-moderate: info: qp ",strnum); } else strerr_die4x(111,FATAL,MSG(ERR_TMP_QMAIL_QUEUE),": ",err + 1); } else if (str_start(action,ACTION_ACCEPT)) { fd = open_read(fnmsg.s); if (fd == -1) { if (errno !=error_noent) strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,fnmsg.s)); else /* shouldn't happen since we've got lock */ strerr_die3x(100,FATAL,fnmsg.s,MSG(ERR_MOD_TIMEOUT)); } substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf)); /* read "Return-Path:" line */ if (getln(&sstext,&line,&match,'\n') == -1 || !match) strerr_die2sys(111,FATAL,MSG(ERR_READ_INPUT)); maketo(); /* extract SENDER to "to" */ env_put2("SENDER",to.s); /* set SENDER */ if (seek_begin(fd) == -1) /* rewind, since we read an entire buffer */ strerr_die2sys(111,FATAL,MSG1(ERR_SEEK,fnmsg.s)); if ((child = wrap_fork()) == 0) { close(0); dup(fd); /* make fnmsg.s stdin */ if (argc > opt + 1) wrap_execvp((const char **)argv + opt); else if (argc > opt) wrap_execsh(argv[opt]); else wrap_execbin("/ezmlm-send", &sendopt, dir); } /* parent */ close(fd); wrap_exitcode(child); if (!stralloc_copys(&fnnew,"mod/accepted/")) die_nomem(); if (!stralloc_cats(&fnnew,fnbase.s)) die_nomem(); if (!stralloc_0(&fnnew)) die_nomem(); /* ignore errors */ fd = open_trunc(fnnew.s); if (fd != -1) close(fd); unlink(fnmsg.s); _exit(0); } }
void usage() { strerr_die4x(100, "usage: ", progname, USAGE_MAIN, "\n"); }
void main(int argc,char **argv) { char *def; char *local; const char *action = ""; char *psz; const char *err; int fd; unsigned int i,j; int flagremote; int match; int goodexit = 0; /* exit code for normal exit */ /* in manager this will be set to 0 */ unsigned long from,u,to,issue,prevmax; unsigned long mno = 0; unsigned long chunk; unsigned long subs = 0; unsigned int pos,pos1; unsigned int len; int opt; char outformat = 0; msgentry *msgtable; subentry *subtable; authentry *authtable; dateentry *datetable; struct datetime dt; char date[DATE822FMT]; (void) umask(022); sig_pipeignore(); when = now(); datetime_tai(&dt,when); opt = getconfopt(argc,argv,options,1,0); initsub(0); if (flagformat != 0) if (FORMATS[str_chr(FORMATS,flagformat[0])]) outformat = flagformat[0]; if (outformat == 0) { outformat = (getconf_line(&line,"digformat",0) && FORMATS[str_chr(FORMATS,line.s[0])]) ? line.s[0] : DEFAULT_FORMAT; } /* code to activate digest (-digest-code)*/ if ((digestcode = argv[opt]) == 0) { if (getconf_line(&digestcodefile,"digestcode",0) && digestcodefile.len > 0) { if (!stralloc_0(&digestcodefile)) die_nomem(); digestcode = digestcodefile.s; } } /* ignore any extra args */ if (!stralloc_copy(&subject,&outlocal)) die_nomem(); /* for subjects */ if (!stralloc_copy(&listname,&outlocal)) die_nomem(); /* for content disp */ local = env_get("LOCAL"); def = env_get("DEFAULT"); sender = get_sender(); if (local && *local) { /* in editor local = outlocal */ if (!sender) strerr_die2x(100,FATAL,MSG(ERR_NOSENDER)); if (!*sender) strerr_die2x(100,FATAL,MSG(ERR_BOUNCE)); if (str_equal(sender,"#@[]")) strerr_die2x(100,FATAL,MSG(ERR_BOUNCE)); if (!sender[str_chr(sender,'@')]) strerr_die2x(100,FATAL,MSG(ERR_ANONYMOUS)); if (def) { if (*def) { action = def; goodexit = 99; } else _exit(0); /* list-@host should do -help from manager */ } else { /* editor */ act = AC_DIGEST; /* on list-@host ! */ flageditor = 1; /* to avoid Mailing-list error on sublists */ /* when running out of dir/editor. */ } if (case_starts(action,"dig")) { action += 3; if (action[0] == '-' || action [0] == '.') { action++; if (!digestcode) strerr_die2x(100,FATAL,MSG(ERR_BAD_DIGCODE)); len = str_len(digestcode); if (len <= str_len(action) && case_startb(action,len,digestcode)) { if (FORMATS[str_chr(FORMATS,*(action+len))]) outformat = *(action+len); act = AC_DIGEST; } else strerr_die2x(100,FATAL,MSG(ERR_BAD_DIGCODE)); } } } else /* Command line operation */ act = AC_DIGEST; /* Things we deal with. If anything else just die with success! */ /* At the moment this is -index, -thread, and -get. */ /* If flagdo = 0 we only service -dig commands. This is to support*/ /* "secret" lists that are still archived and digested. -c on */ /* cmd line. */ if (act == AC_NONE) { if (case_equals(action,ACTION_DIGEST)) { act = AC_GET; /* list-digest@ => msg since last digest */ action = ACTION_GET; } else if (case_starts(action,ACTION_GET) || case_starts(action,ALT_GET)) act = AC_GET; else if (case_starts(action,ACTION_INDEX) || case_starts(action,ALT_INDEX)) act = AC_INDEX; else if (case_starts(action,ACTION_THREAD) || case_starts(action,ALT_THREAD)) act = AC_THREAD; } if (act == AC_NONE) /* not for us. Pass the buck. */ _exit(0); if (act != AC_INDEX) { /* need to do header processing */ if(!getconf(&digheaders,"digheaders",0)) { if(!stralloc_copys(&digheaders,digsz)) die_nomem(); if (!stralloc_0(&digheaders)) die_nomem(); psz = digheaders.s; while (*psz) { if (*psz == '\\') *psz = '\0'; ++psz; } } if (!constmap_init(&digheadersmap,digheaders.s,digheaders.len,0)) die_nomem(); } if (act != AC_DIGEST) { if (!flagdo) /* only do digests */ strerr_die2x(100,FATAL,MSG(ERR_NOCMD)); if (flagpublic < 0) flagpublic = !getconf_isset("modgetonly") && getconf_isset("public"); if (!flagpublic) { /* This all to take care of non-public lists. They should*/ /* still do digests, but do other things only for */ /* moderators that have remote access. Since this is rare*/ /* efforts have been made to keep everything that's not */ /* needed elsewhere in here. */ getconf_line(&moddir,"modsub",0); flagremote = getconf_line(&line,"remote",0); if (!flagremote) strerr_die2x(100,FATAL,MSG(ERR_NOT_PUBLIC)); if (!moddir.len) { if (line.len) { if (!stralloc_copy(&moddir,&line)) die_nomem(); } else { if (!stralloc_copys(&moddir,"mod")) die_nomem(); } } if (!stralloc_0(&moddir)) die_nomem(); ismod = issub(moddir.s,sender,&mod); if (!ismod) /* sender = moderator? */ strerr_die2x(100,FATAL,MSG(ERR_NOT_PUBLIC)); } } if (act == AC_DIGEST) { workdir = "digest"; if (!stralloc_cats(&outlocal,"-digest")) die_nomem(); if (getconf_line(&line,"chunk",0)) { if (!stralloc_0(&line)) die_nomem(); (void) scan_ulong(line.s,&chunk); /* same chunk as main list */ if (chunk == 0) /* limit range to 1-53 */ chunk = 1L; else if (chunk > 52) chunk = 52L; } else { chunk = 0L; } } else workdir = "."; if (!flagarchived) strerr_die2x(100,FATAL,MSG(ERR_NOT_ARCHIVED)); if (qmail_open(&qq) == -1) strerr_die2sys(111,FATAL,MSG(ERR_QMAIL_QUEUE)); set_cpnum(""); /* default for <#n#> replacement */ switch (act) { case AC_DIGEST: /* -dig{.|-}'digestcode'[f] returns an rfc1153 digest */ /* of messages from the archive. Messages */ /* dignum+1 through the last message received by the list are processed and */ /* dignum is updated to the last message processed. digissue is advanced. */ get_num(); /* max = last successful message */ to = max; lockup(); /* another digest could corrupt dignum */ /* but will be saved only if flagdigrange==0 */ if(getconf_line(&num,"dignum",0)) { if(!stralloc_0(&num)) die_nomem(); pos = scan_ulong(num.s,&prevmax); if (num.s[pos] == ':') pos++; pos += 1 + scan_ulong(num.s+pos,&cumsize); /* last cumsize */ if (num.s[pos] == ':') pos++; scan_ulong(num.s+pos,&digwhen); /* last reg dig */ } else { prevmax = 0L; cumsize = 0L; digwhen = 0L; } mno = prevmax + 1L; if(!max || mno > max) /* if a digest-list is "sending" the request, */ /* don't make noise: errors go to postmaster!*/ strerr_die2x(goodexit,FATAL,MSG(ERR_EMPTY_DIGEST)); szmsgnum[fmt_ulong(szmsgnum,mno)] = '\0'; set_cpnum(szmsgnum); /* for copy */ /* prepare subject to get entropy for tagmsg*/ if (!stralloc_cats(&subject," Digest ")) die_nomem(); if (!stralloc_catb(&subject,date,date822fmt(date,&dt)-1)) die_nomem(); /* skip trailing in date '\n' */ if (!stralloc_cats(&subject," Issue ")) die_nomem(); if (getconf_line(&num,"digissue",0)) { if(!stralloc_0(&num)) die_nomem(); scan_ulong(num.s,&issue); issue++; } else { issue = 1; } if (!stralloc_catb(&subject,strnum,fmt_ulong(strnum,issue))) die_nomem(); /* use the subject as entropy */ if (!stralloc_copy(&line,&subject)) die_nomem(); if (!stralloc_0(&line)) die_nomem(); if (!stralloc_ready(&seed,HASHLEN+1)) die_nomem(); seed.len = HASHLEN + 1; seed.s[HASHLEN] = '\0'; makehash(line.s,line.len,seed.s); if (chunk) { /* only if slaves are used */ qmail_puts(&qq,"Ezauth: "); qmail_put(&qq,seed.s,HASHLEN); qmail_puts(&qq,"\n"); } doheaders(); qmail_puts(&qq,"To: "); if (!quote("ed,&listname)) die_nomem(); qmail_put(&qq,quoted.s,quoted.len); qmail_puts(&qq,"@"); qmail_put(&qq,outhost.s,outhost.len); qmail_puts(&qq,"\n"); if (flagindexed && (outformat != NATIVE)) idx_mkthreads(&msgtable,&subtable,&authtable,&datetable, mno,to,max,flaglocked); else idx_mklist(&msgtable,&subtable,&authtable,mno,to); digest(msgtable,subtable,authtable,mno,to,&subject,AC_DIGEST,outformat); write_ulong(issue,0L,0L,"digissue","digissuen"); write_ulong(max,cumsizen, (unsigned long) when,"dignum","dignumn"); break; case AC_GET: /* -get[-|\.][[num].num2] copies archive num-num2. num & num2 are adjusted */ /* to be > 0 and <= last message, to num2 >= num and to num2-num <= MAXGET. */ zapnonsub(ACTION_GET); /* restrict to subs if requested */ tosender(); /* for rfc1153 */ if (!stralloc_cats(&subject," Digest of: ")) die_nomem(); if (!stralloc_cats(&subject,action)) die_nomem(); to = 0; pos = str_len(ACTION_GET); if (!case_starts(action,ACTION_GET)) pos = str_len(ALT_GET); if (FORMATS[str_chr(FORMATS,action[pos])]) { outformat = action[pos]; ++pos; } /* optional - or . after '-get' */ if (action[pos] == '-' || action[pos] == '.') pos++; get_num(); /* max = last successful message */ /* accept any separator. It may be */ /* the terminal '\n', but then */ /* scan will = 0 on the \0 so should*/ /* be safe */ if (!max) strerr_die2x(100,FATAL,MSG(ERR_EMPTY_LIST)); szmsgnum[fmt_ulong(szmsgnum,max)] = '\0'; set_cpnum(szmsgnum); /* for copy this is the latest message arch'd*/ doheaders(); if(action[pos += scan_ulong(action + pos,&u)]) scan_ulong(action + pos + 1, &to); if (u == 0 && to == 0) { /* default: messages since last */ /* digest, or last MAXGET if too many */ to= max; u = dignum(); if (u == 0) { /* no digest => last up to HISTGET msgs */ to = max; if (max > HISTGET) u = max - HISTGET; else u = 1; } if (to - u >= MAXGET) u = to - MAXGET + 1; /* max MAXGET */ } else if (u > max) { if (to) { /* -get.999999_x returns 30 and msg since last*/ to = max; /* digest 30*/ u = dignum(); if (u > HISTGET) u -= HISTGET; else u = 1; if (to - u >= MAXGET) u = to - MAXGET + 1; } else u = max; } if (u == 0) u = 1; /* -get.5 => 1-5 */ if (to < u) to = u; /* -get23_2 => 23 */ if (to >= u + MAXGET) to = u + MAXGET - 1; /* no more than MAXGET at a time */ if (to > max) to = max; if (flagindexed && (outformat != NATIVE)) /* fake out threading */ idx_mkthreads(&msgtable,&subtable,&authtable,&datetable, u,to,max,0); else idx_mklist(&msgtable,&subtable,&authtable,u,to); digest(msgtable,subtable,authtable,u,to,&subject,AC_GET,outformat); break; case AC_INDEX: /* -index[f][#|-|\.][[num][.num2] Show subject index for messages num-num2 in*/ /* sets of 100. */ /* Default last 2 sets. num and num2 are made reasonable as for get. num2 is */ /* limited to num+MAXINDEX to limit the amount of data sent. */ if (!flagindexed) strerr_die2x(100,FATAL,MSG(ERR_NOT_INDEXED)); zapnonsub(ACTION_INDEX); /* restrict to subs if requested */ to = 0; pos = str_len(ACTION_INDEX); if (!case_starts(action,ACTION_INDEX)) pos = str_len(ALT_INDEX); if (FORMATS[str_chr(FORMATS,action[pos])]) { outformat = action[pos]; /* ignored, but be nice ... */ ++pos; } get_num(); /* max = last successful message */ if (!max) strerr_die2x(100,FATAL,MSG(ERR_EMPTY_LIST)); szmsgnum[fmt_ulong(szmsgnum,max)] = '\0'; set_cpnum(szmsgnum); /* for copy this is the latest message arch'd*/ doheaders(); tosender(); if (!stralloc_cats(&subject," Result of: ")) die_nomem(); if (!stralloc_cats(&subject,action)) die_nomem(); presub(1,1,&subject,AC_INDEX,outformat); if (action[pos] == '-' || action[pos] == '.') pos++; if(action[pos += scan_ulong(action + pos,&u)]) scan_ulong(action + pos + 1, &to); if (u == 0 && to == 0) { to = max; u = max - 100; } if (u <= 0) u = 1; if (u > max) u = max; if (to < u) to = u; if (to > u + MAXINDEX) to = u+MAXINDEX; /* max MAXINDEX index files */ if (to > max) to = max; u /= 100; to /= 100; while (u <= to) { if (!stralloc_copys(&fn,"archive/")) die_nomem(); if (!stralloc_catb(&fn,strnum,fmt_ulong(strnum,u))) die_nomem(); if (!stralloc_cats(&fn,"/index")) die_nomem(); if (!stralloc_0(&fn)) die_nomem(); if (u == max/100) /* lock if last index file in archive */ lockup(); fd = open_read(fn.s); if (fd == -1) if (errno != error_noent) strerr_die2sys(111,FATAL,MSG1(ERR_OPEN,fn.s)); else code_qputs(MSG(TXT_NOINDEX)); else { substdio_fdbuf(&sstext,read,fd,textbuf,sizeof(textbuf)); for (;;) { if (getln(&sstext,&line,&match,'\n') == -1) strerr_die2sys(111,FATAL,MSG1(ERR_READ,fn.s)); if (match) { if (line.s[0] != '\t') { /* subject line */ pos = byte_chr(line.s,line.len,' '); pos1 = 0; if (pos && pos != line.len && line.s[pos - 1] == ':') pos1 = pos + HASHLEN + 1; /* after hash */ if (pos1 >= line.len) { /* bad! */ pos = 0; pos1 = 0; /* output as is */ } if (!stralloc_copyb(&line2,line.s,pos)) die_nomem(); if (!stralloc_catb(&line2,line.s+pos1,line.len-pos1)) die_nomem(); } else { pos = byte_chr(line.s,line.len,';'); if (pos + HASHLEN + 1 < line.len && pos > 15 && line.s[pos + 1] != ' ') { if (!stralloc_copyb(&line2,line.s,pos - 15)) die_nomem(); pos++; if (!stralloc_catb(&line2,line.s + pos + HASHLEN, line.len - pos - HASHLEN)) die_nomem(); } else /* old format - no author hash */ if (!stralloc_copyb(&line2,line.s,line.len)) die_nomem(); } code_qput(line2.s,line2.len); } else break; } close(fd); } if (u == max/100) /* unlock if last index in archive file */ unlock(); u++; } normal_bottom(outformat); postmsg(outformat); break; case AC_THREAD: /* -thread[f][-|.]num returns messages with subject matching message */ /* 'num' in the subject index. If 'num' is not in[1..last_message] an error */ /* message is returned. */ if (!flagindexed) strerr_die2x(100,FATAL,MSG(ERR_NOT_INDEXED)); zapnonsub(ACTION_THREAD); /* restrict to subs if requested*/ get_num(); /* max = last successful message */ if (!max) strerr_die2x(100,FATAL,MSG(ERR_EMPTY_LIST)); szmsgnum[fmt_ulong(szmsgnum,max)] = '\0'; set_cpnum(szmsgnum); /* for copy this is the latest message arch'd*/ doheaders(); tosender(); /* for rfc1153 */ if (!stralloc_cats(&subject," Digest of: ")) die_nomem(); if (!stralloc_cats(&subject,action)) die_nomem(); to = 0; pos = str_len(ACTION_THREAD); if (!case_starts(action,ACTION_THREAD)) pos = str_len(ALT_THREAD); if (FORMATS[str_chr(FORMATS,action[pos])]) { outformat = action[pos]; ++pos; } if (action[pos] == '-' || action[pos] == '.') pos++; if(action[pos += scan_ulong(action + pos,&u)]) scan_ulong(action + pos + 1, &to); if(u == 0 || u > max) { hdr_add2("Subject: ",subject.s,subject.len); qmail_puts(&qq,"\n"); copy(&qq,"text/get-bad",flagcd); } else { /* limit range to at most u-THREAD_BEFORE to u+THREAD_AFTER */ if (u > THREAD_BEFORE) from = u-THREAD_BEFORE; else from = 1L; if (u + THREAD_AFTER > max) { idx_mkthread(&msgtable,&subtable,&authtable,from,max,u,max,0); digest(msgtable,subtable,authtable,from,max,&subject, AC_THREAD,outformat); } else { idx_mkthread(&msgtable,&subtable,&authtable, from,u+THREAD_AFTER,u,max,0); digest(msgtable,subtable,authtable,from,u+THREAD_AFTER, &subject,AC_THREAD,outformat); } } break; default: /* This happens if the initial check at the beginning of 'main' */ /* matches something that isn't matched here. Conversely, just */ /* adding an action here is not enough - it has to be added to the */ /* initial check as well. */ strerr_die2x(100,FATAL, "Program error: I'm supposed to deal with this but I didn't"); } if (!stralloc_copy(&line,&outlocal)) die_nomem(); if (act == AC_DIGEST) { if (chunk) { if (!stralloc_cats(&line,"-return-g-")) die_nomem(); } else if (!stralloc_cats(&line,"-return-")) die_nomem(); strnum[fmt_ulong(strnum,mno)] = '\0'; if (!stralloc_cats(&line,strnum)) die_nomem(); if (!stralloc_cats(&line,"-@")) die_nomem(); if (!stralloc_cat(&line,&outhost)) die_nomem(); if (!stralloc_cats(&line,"-@[]")) die_nomem(); } else { if (!stralloc_cats(&line,"-return-@")) die_nomem(); if (!stralloc_cat(&line,&outhost)) die_nomem(); } if (!stralloc_0(&line)) die_nomem(); qmail_from(&qq,line.s); if (act == AC_DIGEST) { /* Do recipients */ tagmsg(mno,seed.s,"d",hashout,qq.msgbytes,chunk); if (chunk) { if (!stralloc_copys(&line,"T")) die_nomem(); if (!stralloc_cat(&line,&outlocal)) die_nomem(); if (!stralloc_cats(&line,"-s-d-")) die_nomem(); if (!stralloc_catb(&line,hashout,COOKIE)) die_nomem(); if (!stralloc_cats(&line,"-")) die_nomem(); if (!stralloc_cats(&line,strnum)) die_nomem(); if (!stralloc_cats(&line,"-")) die_nomem(); if (!stralloc_copys(&line2,"@")) die_nomem(); if (!stralloc_cat(&line2,&outhost)) die_nomem(); if (!stralloc_0(&line2)) die_nomem(); j = 0; for (i = 0; i <= 52; i += chunk) { /* To slaves */ qmail_put(&qq,line.s,line.len); schar[0] = '0' + i / 10; schar[1] = '0' + (i % 10); qmail_put(&qq,schar,3); j += (chunk - 1); if (j > 52) j = 52; schar[0] = '0' + j / 10; schar[1] = '0' + (j % 10); qmail_put(&qq,schar,2); qmail_put(&qq,line2.s,line2.len); } } else subs = putsubs(workdir,0L,52L,&subto); } else { /* if local is set, sender is checked */ if (ismod) qmail_to(&qq,mod.s); else qmail_to(&qq,sender); } if (*(err = qmail_close(&qq)) == '\0') { /* Done. Skip rest. */ if (act == AC_DIGEST) { if (chunk) (void) logmsg(mno,0L,0L,2); else (void) logmsg(mno,0L,subs,4); } closesub(); /* close db connection */ unlock(); /* NOP if nothing locked */ strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0; strerr_die2x(goodexit,"ezmlm-get: info: qp ",strnum); } else { /* failed. Reset last msg & issue for digest */ if(act == AC_DIGEST) { issue--; write_ulong(issue,0L,0L,"digissue","digissuen"); write_ulong(prevmax,cumsize,(unsigned long) digwhen,"dignum","dignumn"); } unlock(); /* NOP if nothing locked */ strerr_die4x(111,FATAL,MSG(ERR_TMP_QMAIL_QUEUE),": ",err + 1); } }
void envdir_usage() { strerr_die4x(100, "usage: ", progname, USAGE_ENVDIR, "\n"); }
void usage() { if (!lsb) strerr_die4x(100, "usage: ", progname, USAGE, "\n"); strerr_die4x(2, "usage: ", progname, USAGELSB, "\n"); }
void pgrphack_usage() { strerr_die4x(100, "usage: ", progname, USAGE_PGRPHACK, "\n"); }
static void die_syntax(stralloc *line) { if (!stralloc_0(line)) die_nomem(); strerr_die4x(100,FATAL,MSG1(ERR_SYNTAX,TXT_EZCRONRC),": ",line->s); }
void setlock_usage() { strerr_die4x(100, "usage: ", progname, USAGE_SETLOCK, "\n"); }
int main(int argc,char **argv) { char *action; const char *err; unsigned int i; int act = AC_NONE; /* desired action */ unsigned int actlen = 0;/* str_len of above */ (void) umask(022); sig_pipeignore(); when = now(); getconfopt(argc,argv,options,1,&dir); initsub(0); sender = get_sender(); if (!sender) die_sender(); action = env_get("DEFAULT"); if (!action) strerr_die2x(100,FATAL,MSG(ERR_NODEFAULT)); if (!*sender) strerr_die2x(100,FATAL,MSG(ERR_BOUNCE)); if (!sender[str_chr(sender,'@')]) strerr_die2x(100,FATAL,MSG(ERR_ANONYMOUS)); if (str_equal(sender,"#@[]")) strerr_die2x(100,FATAL,MSG(ERR_BOUNCE)); action = set_workdir(action); stralloc_copys(&target,sender); if (action[0]) { i = str_chr(action,'-'); if (action[i]) { action[i] = 0; stralloc_copys(&target,action + i + 1); i = byte_rchr(target.s,target.len,'='); if (i < target.len) target.s[i] = '@'; } } stralloc_0(&target); set_cptarget(target.s); /* for copy() */ make_verptarget(); act = get_act_ismod(action,&actlen); stralloc_copy(&from,&outlocal); stralloc_cats(&from,"-return-@"); stralloc_cat(&from,&outhost); stralloc_0(&from); if (qmail_open(&qq) == -1) strerr_die2sys(111,FATAL,MSG(ERR_QMAIL_QUEUE)); msg_headers(act); if (act == AC_SUBSCRIBE) do_subscribe(action); else if (act == AC_SC) do_sc(action); else if (str_start(action,ACTION_RC)) do_rc_tc(action,ACTION_RC); else if(str_start(action,ACTION_TC)) do_rc_tc(action,ACTION_TC); else if (act == AC_UNSUBSCRIBE) do_unsubscribe(action); else if (str_start(action,ACTION_UC)) do_uc(action); else if (str_start(action,ACTION_VC)) do_vc_wc(action,ACTION_VC); else if (str_start(action,ACTION_WC)) do_vc_wc(action,ACTION_WC); else if (act == AC_LIST || act == AC_LISTN) do_list(act); else if (act == AC_LOG) do_log(action,actlen); else if (act == AC_EDIT) do_edit(action); else if (str_start(action,ACTION_ED)) do_ed(action); else if (act == AC_GET) do_get(action); else if (case_starts(action,ACTION_QUERY) || case_starts(action,ALT_QUERY)) do_query(); else if (case_starts(action,ACTION_INFO) || case_starts(action,ALT_INFO)) do_info(); else if (case_starts(action,ACTION_FAQ) || case_starts(action,ALT_FAQ)) do_faq(); else if (ismod && (act == AC_HELP)) do_mod_help(); else do_help(); err = qmail_close(&qq); closesub(); if (*err != '\0') strerr_die4x(111,FATAL,MSG(ERR_TMP_QMAIL_QUEUE),": ",err + 1); strnum[fmt_ulong(strnum,qmail_qp(&qq))] = 0; strerr_die3x(0,INFO,"qp ",strnum); }
void softlimit_usage() { strerr_die4x(100, "usage: ", progname, USAGE_SOFTLIMIT, "\n"); }
void syntaxerror(const char *why) { strnum[fmt_ulong(strnum,linenum)] = 0; strerr_die4x(111,FATAL,"unable to parse data line ",strnum,why); }
int main(int argc, char **argv) { enum { unset, uid, mail, filter } mode = unset; qldap *q, *qpw; struct passwd *pw; char *passwd = 0, *value = 0; char *bindpw = 0, *binddn = 0; char *f, *s; int opt, r, done, status, id; unsigned int j, slen; unsigned long size, count, maxsize; const char *attrs[] = { LDAP_MAIL, LDAP_MAILALTERNATE, LDAP_UID, LDAP_QMAILUID, LDAP_QMAILGID, LDAP_ISACTIVE, LDAP_MAILHOST, LDAP_MAILSTORE, LDAP_HOMEDIR, LDAP_QUOTA_SIZE, LDAP_QUOTA_COUNT, LDAP_FORWARDS, LDAP_PROGRAM, LDAP_MODE, LDAP_REPLYTEXT, LDAP_DOTMODE, LDAP_MAXMSIZE, LDAP_OBJECTCLASS, #if 0 LDAP_GROUPCONFIRM, LDAP_GROUPMEMONLY, LDAP_GROUPCONFRIMTEXT, LDAP_GROUPMODERATTEXT, LDAP_GROUPMODERATDN, LDAP_GROUPMODERAT822, LDAP_GROUPMEMBERDN, LDAP_GROUPMEMBER822, LDAP_GROUPMEMBERFILTER, #endif LDAP_PASSWD, 0}; while ((opt = getopt(argc, argv, "d:D:u:m:p:f:w:")) != opteof) switch (opt) { case 'd': if (env_put2("LOGLEVEL", optarg) == 0) strerr_die2sys(1, FATAL, "setting loglevel: "); break; case 'D': binddn = optarg; break; case 'u': if (value != 0) usage(); value = optarg; mode = uid; break; case 'm': if (value != 0) usage(); value = optarg; mode = mail; break; case 'f': if (value != 0) usage(); value = optarg; mode = filter; break; case 'p': if (geteuid() != 0) strerr_die2x(1, FATAL, "only the superuser may comapre passwords"); passwd = optarg; break; case 'w': bindpw = optarg; break; default: usage(); } if (argc != optind) usage(); if (bindpw && !binddn) usage(); log_init(STDERR, -1, 0); if (read_controls(ctrls) != 0) strerr_die2sys(111, FATAL, "unable to read controls: "); q = qldap_new(); if (q == 0) strerr_die2sys(111, FATAL, "qldap_new failed: "); qpw = qldap_new(); if (qpw == 0) strerr_die2sys(111, FATAL, "qldap_new failed: "); r = qldap_open(q); if (r != OK) fail(q, "qldap_open", r); r = qldap_open(qpw); if (r != OK) fail(qpw, "qldap_open", r); r = qldap_bind(q, binddn, bindpw); if (r != OK) fail(q, "qldap_bind", r); if (passwd == 0 || mode != uid || qldap_need_rebind() != 0) attrs[sizeof(attrs)/4 - 2] = 0; /* password */ done = 0; f = 0; do { switch (mode) { case mail: f = filter_mail(value, &done); if (value == 0) strerr_die2sys(1, FATAL, "building filter: "); break; case uid: f = filter_uid(value); done = 1; if (value == 0) strerr_die2sys(1, FATAL, "building filter: "); break; case filter: f = value; break; default: usage(); } output(subfdout, "Searching ldap for: %s\nunder dn: %s\n", f, qldap_basedn()); r = qldap_filter(q, f, attrs, qldap_basedn(), SCOPE_SUBTREE); if (r != OK) fail(q, "qldap_filter", r); r = qldap_count(q); switch (r) { case -1: fail(q, "qldap_count", FAILED); case 0: output(subfdout, "No entries found.\n"); qldap_free(q); /* TODO hook for local lookups. */ return 0; case 1: output(subfdout, "Found %i entry:\n", r); break; default: output(subfdout, "Found %i entries:\n", r); if (mode == uid || mode == uid) { output(subfdout, "Uh-oh: multiple entries found but " "should be unique!\n"); passwd = 0; } break; } output(subfdout, "\n"); } while (r == 0 && !done); r = qldap_first(q); if (r != OK) fail(q, "qldap_first", r);; do { r = qldap_get_dn(q, &dn); if (r != OK) fail(q, "qldap_get_dn", r); output(subfdout, "dn: %s\n" "-------------------------------------------------------\n", dn.s); r = qldap_get_attr(q, LDAP_OBJECTCLASS, &foo, MULTI_VALUE); if (r != OK) fail(q, "qldap_get_attr(" LDAP_OBJECTCLASS ")", r); unescape(foo.s, &bar); s = bar.s; slen = bar.len-1; for(;;) { output(subfdout, "%s: %s\n",LDAP_OBJECTCLASS ,s); j = byte_chr(s,slen,0); if (j++ >= slen) break; s += j; slen -= j; } r = qldap_get_attr(q, LDAP_MAIL, &foo, SINGLE_VALUE); if (r != OK) fail(q, "qldap_get_attr(" LDAP_MAIL ")", r); output(subfdout, "%s: %s\n", LDAP_MAIL, foo.s); r = qldap_get_attr(q, LDAP_MAILALTERNATE, &foo, MULTI_VALUE); if (r != OK && r != NOSUCH) fail(q, "qldap_get_attr(" LDAP_MAILALTERNATE ")", r); if (r == OK) { unescape(foo.s, &bar); s = bar.s; slen = bar.len-1; for(;;) { output(subfdout, "%s: %s\n", LDAP_MAILALTERNATE, s); j = byte_chr(s,slen,0); if (j++ >= slen) break; s += j; slen -= j; } } r = qldap_get_user(q, &foo); if (r != OK && r != NOSUCH) fail(q, "qldap_get_user", r); if (r == OK) output(subfdout, "%s: %s\n", LDAP_UID, foo.s); else output(subfdout, "%s: undefined " "(forward only account required)\n", LDAP_UID); r = qldap_get_status(q, &status); if (r != OK) fail(q, "qldap_get_status", r); switch (status) { case STATUS_BOUNCE: output(subfdout, "%s: %s\n", LDAP_ISACTIVE, ISACTIVE_BOUNCE); break; case STATUS_NOACCESS: output(subfdout, "%s: %s\n", LDAP_ISACTIVE, ISACTIVE_NOACCESS); break; case STATUS_OK: output(subfdout, "%s: %s\n", LDAP_ISACTIVE, ISACTIVE_ACTIVE); break; case STATUS_UNDEF: output(subfdout, "%s: %s\n", LDAP_ISACTIVE, "undefined -> active"); break; default: strerr_warn2(WARN, "qldap_get_status returned unknown status", 0); } r = qldap_get_attr(q, LDAP_MAILHOST, &foo, SINGLE_VALUE); if (r != OK && r != NOSUCH) fail(q, "qldap_get_attr(" LDAP_MAILHOST ")", r); if (r == OK) { output(subfdout, "%s: %s\n", LDAP_MAILHOST, foo.s); /* * TODO we could check if we are in cluster mode and * if we would redirect to a differnet host */ } else output(subfdout, "%s: undefined\n", LDAP_MAILHOST); /* get the path of the maildir or mbox */ r = qldap_get_mailstore(q, &foo, &bar); switch (r) { case OK: output(subfdout, "homeDirectory: %s\n", foo.s); if (bar.len > 0) output(subfdout, "aliasEmpty: %s\n", bar.s); else output(subfdout, "aliasEmpty: using default\n"); break; case NEEDED: output(subfdout, "forward only delivery via alias user\n"); pw = getpwnam(auto_usera); if (!pw) strerr_die4x(100, FATAL, "Aiiieeeee, now alias user '", auto_usera, "'found in /etc/passwd."); output(subfdout, "alias user: %s\n", pw->pw_name); output(subfdout, "alias user uid: %i\n", pw->pw_uid); output(subfdout, "alias user gid: %i\n", pw->pw_gid); output(subfdout, "alias user home: %s\n", pw->pw_dir); output(subfdout, "alias user aliasempty: %s\n", ALIASDEVNULL); /* get the forwarding addresses */ r = qldap_get_attr(q, LDAP_FORWARDS, &foo, MULTI_VALUE); if (r != OK) fail(q, "qldap_get_attr(" LDAP_FORWARDS ") for forward only user", r); unescape(foo.s, &bar); s = bar.s; slen = bar.len-1; for(;;) { output(subfdout, "%s: %s\n", LDAP_FORWARDS, s); j = byte_chr(s,slen,0); if (j++ >= slen) break; s += j; slen -= j; } goto next; default: fail(q, "qldap_get_mailstore", r); } r = qldap_get_dotmode(q, &foo); if (r != OK) fail(q, "qldap_get_dotmode", r); output(subfdout, "%s: %s\n", LDAP_DOTMODE, foo.s); r = qldap_get_uid(q, &id); if (r != OK) fail(q, "qldap_get_uid", r); output(subfdout, "%s: %i\n", LDAP_QMAILUID, id); r = qldap_get_gid(q, &id); if (r != OK) fail(q, "qldap_get_gid", r); output(subfdout, "%s: %i\n", LDAP_QMAILGID, id); r = qldap_get_quota(q, &size, &count, &maxsize); if (r != OK) fail(q, "qldap_get_quota", r); output(subfdout, "%s: %u%s\n", LDAP_QUOTA_SIZE, size, size==0?" (unlimited)":""); output(subfdout, "%s: %u%s\n", LDAP_QUOTA_COUNT, count, count==0?" (unlimited)":""); output(subfdout, "%s: %u%s\n", LDAP_MAXMSIZE, maxsize, maxsize==0?" (unlimited)":""); r = qldap_get_attr(q, LDAP_MODE, &foo, MULTI_VALUE); if (r != OK && r != NOSUCH) fail(q, "qldap_get_attr(" LDAP_MODE ")", r); if (r == OK) { unescape(foo.s, &bar); s = bar.s; slen = bar.len-1; for(;;) { if (case_diffs(MODE_FORWARD, s) && case_diffs(MODE_REPLY, s) && case_diffs(MODE_NOLOCAL, s) && case_diffs(MODE_NOMBOX, s) && case_diffs(MODE_NOFORWARD, s) && case_diffs(MODE_NOPROG, s) && case_diffs(MODE_LOCAL, s) && case_diffs(MODE_FORWARD, s) && case_diffs(MODE_PROG, s) && case_diffs(MODE_NOREPLY, s)) strerr_warn4(WARN, "undefined mail delivery mode: ", s," (ignored).", 0); else if (!case_diffs(MODE_FORWARD, s)) strerr_warn4(WARN, "mail delivery mode: ", s," should not be used " "(used internally).", 0); output(subfdout, "%s: %s\n", LDAP_MODE, s); j = byte_chr(s,slen,0); if (j++ >= slen) break; s += j; slen -= j; } } r = qldap_get_attr(q, LDAP_FORWARDS, &foo, MULTI_VALUE); if (r != OK && r != NOSUCH) fail(q, "qldap_get_attr(" LDAP_FORWARDS ")", r); if (r == OK) { unescape(foo.s, &bar); s = bar.s; slen = bar.len-1; for(;;) { output(subfdout, "%s: %s\n", LDAP_FORWARDS, s); j = byte_chr(s,slen,0); if (j++ >= slen) break; s += j; slen -= j; } } r = qldap_get_attr(q, LDAP_PROGRAM, &foo, MULTI_VALUE); if (r != OK && r != NOSUCH) fail(q, "qldap_get_attr(" LDAP_PROGRAM ")", r); if (r == OK) { unescape(foo.s, &bar); s = bar.s; slen = bar.len-1; for(;;) { output(subfdout, "%s: %s\n", LDAP_PROGRAM, s); j = byte_chr(s,slen,0); if (j++ >= slen) break; s += j; slen -= j; } } r = qldap_get_attr(q, LDAP_REPLYTEXT, &foo, SINGLE_VALUE); if (r != OK && r != NOSUCH) fail(q, "qldap_get_attr(" LDAP_REPLYTEXT ")", r); if (r == OK) output(subfdout, "%s:\n=== begin ===\n%s\n" "=== end ===\n", LDAP_REPLYTEXT, foo.s); else output(subfdout, "%s: undefined\n", LDAP_REPLYTEXT); if (mode == uid && passwd != 0) { if (qldap_need_rebind() == 0) { r = qldap_get_attr(q, LDAP_PASSWD, &foo, SINGLE_VALUE); if (r != OK) fail(q, "qldap_get_attr(" LDAP_PASSWD ")", r); r = cmp_passwd(passwd, foo.s); } else { r = qldap_rebind(qpw, dn.s, passwd); switch (r) { case OK: r = OK; break; case LDAP_BIND_AUTH: r = BADPASS; break; default: break; } } output(subfdout, "\nPASSWORD COMPARE was %s.\n", r == OK?"successful":"NOT successful"); if (r != OK) output(subfdout, "\terror was: %s\n", qldap_err_str(r)); } next: r = qldap_next(q); output(subfdout, "\n\n"); } while (r == OK); if (r != NOSUCH) fail(q, "qldap_next", r); qldap_free(q); return 0; }