/* * report a recipient to remote */ char * rcptto(char *to) { String *s; s = unescapespecial(bangtoat(to)); if(toline == 0) toline = s_new(); else s_append(toline, ", "); s_append(toline, s_to_c(s)); if(strchr(s_to_c(s), '@')) dBprint("RCPT TO:<%s>\r\n", s_to_c(s)); else { s_append(toline, "@"); s_append(toline, ddomain); dBprint("RCPT TO:<%s@%s>\r\n", s_to_c(s), ddomain); } alarm(10*alarmscale); switch(getreply()){ case 2: break; case 5: return Giveup; default: return Retry; } return 0; }
/* return 1 if name found in one of the files * 0 if name not found in one of the files * -1 if neither file exists */ extern int lookup(char *cp, char *local, Biobuf **lfpp, char *global, Biobuf **gfpp) { static String *file = 0; if (local) { if (file == 0) file = s_new(); abspath(local, UPASLIB, s_restart(file)); if (*lfpp != 0 || (*lfpp = sysopen(s_to_c(file), "r", 0)) != 0) { if (okfile(cp, *lfpp)) return 1; } else local = 0; } if (global) { abspath(global, UPASLIB, s_restart(file)); if (*gfpp != 0 || (*gfpp = sysopen(s_to_c(file), "r", 0)) != 0) { if (okfile(cp, *gfpp)) return 1; } else global = 0; } return (local || global)? 0 : -1; }
void info(int indent, int mno, Message *m) { int i; Message *nm; prindent(indent); print("%d%c %d ", mno, m->allocated?'*':' ', m->end - m->start); if(m->unixfrom != nil) print("uf %s ", s_to_c(m->unixfrom)); if(m->unixdate != nil) print("ud %s ", s_to_c(m->unixdate)); print("\n"); prstring(indent, "from:", m->from822); prstring(indent, "sender:", m->sender822); prstring(indent, "to:", m->to822); prstring(indent, "cc:", m->cc822); prstring(indent, "reply-to:", m->replyto822); prstring(indent, "subject:", m->subject822); prstring(indent, "date:", m->date822); prstring(indent, "filename:", m->filename); prstring(indent, "type:", m->type); prstring(indent, "charset:", m->charset); i = 1; for(nm = m->part; nm != nil; nm = nm->next){ info(indent+1, i++, nm); } }
/* * print out the parsed header */ int printheader(void) { int n, len; Field *f; Node *p; char *cp; char c[1]; n = 0; for(f = firstfield; f; f = f->next){ for(p = f->node; p; p = p->next){ if(p->s) n += dBprint("%s", s_to_c(p->s)); else { c[0] = p->c; putcrnl(c, 1); n++; } if(p->white){ cp = s_to_c(p->white); len = strlen(cp); putcrnl(cp, len); n += len; } uneaten = p->end; } putcrnl("\n", 1); n++; uneaten++; /* skip newline */ } return n; }
/* * check lower case version of address agains patterns */ static Pattern* checkaddr(char *arg) { Pattern *p; Reprog *rp; String *s; s = s_copy(arg); mklower(s_to_c(s)); for(p = patterns; p != nil; p = p->next) switch(p->type){ case Texact: if(strcmp(p->arg, s_to_c(s)) == 0){ free(s); return p; } break; case Tregexp: rp = regcomp(p->arg); if(rp == nil) continue; if(regexec(rp, s_to_c(s), nil, 0)){ free(rp); free(s); return p; } free(rp); break; } s_free(s); return 0; }
/* Transforms the address into a command. * Returns: -1 ifaddress not matched by reules * 0 ifaddress matched and ok to forward * 1 ifaddress matched and not ok to forward */ extern int rewrite(dest *dp, message *mp) { rule *rp; /* rewriting rule */ String *lower; /* lower case version of destination */ /* * Rewrite the address. Matching is case insensitive. */ lower = s_clone(dp->addr); s_tolower(s_restart(lower)); rp = findrule(lower, dp->authorized); if(rp == 0){ s_free(lower); return -1; } strcpy(s_to_c(lower), s_to_c(dp->addr)); dp->repl1 = substitute(rp->repl1, rp->subexp, mp); dp->repl2 = substitute(rp->repl2, rp->subexp, mp); dp->status = rp->type; if(debug){ fprint(2, "\t->"); if(dp->repl1) fprint(2, "%s", s_to_c(dp->repl1)); if(dp->repl2) fprint(2, "%s", s_to_c(dp->repl2)); fprint(2, "\n"); } s_free(lower); return 0; }
/* * Get the next token from `line'. The symbol `\l' is replaced by * the name of the local system. */ extern String * rule_parse(String *line, char *system, int *backl) { String *token; String *expanded; char *cp; token = s_parse(line, 0); if(token == 0) return(token); if(strchr(s_to_c(token), '\\')==0) return(token); expanded = s_new(); for(cp = s_to_c(token); *cp; cp++) { if(*cp == '\\') switch(*++cp) { case 'l': s_append(expanded, system); *backl = 1; break; case '\\': s_putc(expanded, '\\'); break; default: s_putc(expanded, '\\'); s_putc(expanded, *cp); break; } else s_putc(expanded, *cp); } s_free(token); s_terminate(expanded); return(expanded); }
/* look up a matching rule */ static rule * findrule(String *addrp, int authorized) { rule *rp; static rule defaultrule; if(rulep == 0) return &defaultrule; for (rp = rulep; rp != 0; rp = rp->next) { if(rp->type==d_auth && authorized) continue; if(rp->program == 0) rp->program = regcomp(rp->matchre->base); if(rp->program == 0) continue; memset(rp->subexp, 0, sizeof(rp->subexp)); if(debug) fprint(2, "matching %s aginst %s\n", s_to_c(addrp), rp->matchre->base); if(regexec(rp->program, s_to_c(addrp), rp->subexp, NSUBEXP)) if(s_to_c(addrp) == rp->subexp[0].s.sp) if((s_to_c(addrp) + strlen(s_to_c(addrp))) == rp->subexp[0].e.ep) return rp; } return 0; }
/* * print out a header line, expanding any domainless addresses into * address@him */ char* bprintnode(Biobuf *b, Node *p, int *cntp) { int len; *cntp = 0; if(p->s){ if(p->addr && strchr(s_to_c(p->s), '@') == nil){ if(Bprint(b, "%s@%s", s_to_c(p->s), him) < 0) return nil; *cntp += s_len(p->s) + 1 + strlen(him); } else { len = s_len(p->s); if(Bwrite(b, s_to_c(p->s), len) < 0) return nil; *cntp += len; } }else{ if(Bputc(b, p->c) < 0) return nil; ++*cntp; } if(p->white) { len = s_len(p->white); if(Bwrite(b, s_to_c(p->white), len) < 0) return nil; *cntp += len; } return p->end+1; }
static int catchalarm(void *a, char *msg) { int rv; USED(a); /* log alarms but continue */ if(strstr(msg, "alarm") != nil){ if(senders.first && senders.first->p && rcvers.first && rcvers.first->p) syslog(0, "smtpd", "note: %s->%s: %s", s_to_c(senders.first->p), s_to_c(rcvers.first->p), msg); else syslog(0, "smtpd", "note: %s", msg); rv = Atnoterecog; } else rv = Atnoteunknown; if (debug) { seek(2, 0, 2); fprint(2, "caught note: %s\n", msg); } /* kill the children if there are any */ if(pp && pp->pid > 0) { syskillpg(pp->pid); /* none can't syskillpg, so try a variant */ sleep(500); syskill(pp->pid); } return rv; }
/* * print out a parsed date */ int printdate(Node *p) { int n, sep = 0; n = dBprint("Date: %s,", s_to_c(p->s)); for(p = p->next; p; p = p->next){ if(p->s){ if(sep == 0) { dBputc(' '); n++; } if (p->next) n += dBprint("%s", s_to_c(p->s)); else n += dBprint("%s", rewritezone(s_to_c(p->s))); sep = 0; } else { dBputc(p->c); n++; sep = 1; } } n += dBprint("\r\n"); return n; }
/* send message filtering Reply-to out of messages */ void printmsg(int fd, String *msg, char *replyto, char *listname) { Field *f, *subject; Node *p; char *cp, *ocp; subject = nil; cp = s_to_c(msg); for(f = firstfield; f; f = f->next){ ocp = cp; for(p = f->node; p; p = p->next) cp = p->end+1; if(f->node->c == REPLY_TO) continue; if(f->node->c == PRECEDENCE) continue; if(f->node->c == SUBJECT){ subject = f; continue; } write(fd, ocp, cp-ocp); } printsubject(fd, subject, listname); fprint(fd, "Reply-To: %s\nPrecedence: bulk\n", replyto); write(fd, cp, s_len(msg) - (cp - s_to_c(msg))); }
/* * walk up the tree building a MVS style path */ static void mvspath(Node *node, String *path) { if(node == node->parent){ s_append(path, s_to_c(remrootpath)); return; } mvspath(node->parent, path); if(s_len(path) > 0) s_append(path, "."); s_append(path, s_to_c(node->remname)); }
/* * walk up the tree building a Unix style path */ static void unixpath(Node *node, String *path) { if(node == node->parent){ s_append(path, s_to_c(remrootpath)); return; } unixpath(node->parent, path); if(s_len(path) > 0 && strcmp(s_to_c(path), "/") != 0) s_append(path, "/"); s_append(path, s_to_c(node->remname)); }
int matcher(char *action, Pattern *p, char *message, Resub *m) { char *cp; String *s; for(cp = message; matchpat(p, cp, m); cp = m->ep) { switch(p->action) { case SaveLine: if(vflag) xprint(2, action, m); saveline(linefile, sender, m); break; case HoldHeader: case Hold: if(nflag) continue; if(vflag) xprint(2, action, m); *qdir = holdqueue; if(hflag && qname) { cp = strchr(sender, '!'); if(cp) { *cp = 0; *qname = strdup(sender); *cp = '!'; } else *qname = strdup(sender); } return 1; case Dump: if(vflag) xprint(2, action, m); *(m->ep) = 0; if(!tflag) { s = s_new(); s_append(s, sender); s = unescapespecial(s); syslog(0, "smtpd", "Dumped %s [%s] to %s", s_to_c(s), m->sp, s_to_c(s_restart(recips))); s_free(s); } tflag = 1; if(sflag) cout = opendump(sender); return 1; default: break; } } return 0; }
static void logmsg(char *action) { Link *l; if(logged) return; logged = 1; for(l = rcvers.first; l; l = l->next) syslog(0, "smtpd", "%s %s (%s/%s) (%s)", action, s_to_c(senders.last->p), him, nci->rsys, s_to_c(l->p)); }
/* * Translate the last component of the sender address. If the translation * yields the same address, replace the sender with its last component. */ extern void gateway(message *mp) { char *base; String *s; /* first remove all systems equivalent to us */ base = skipequiv(s_to_c(mp->sender)); if(base != s_to_c(mp->sender)){ s = mp->sender; mp->sender = s_copy(base); s_free(s); } }
vlong du(char *name, Dir *dir) { int fd, i, n; Dir *buf, *d; String *file; vlong nk, t; if(dir == nil) return warn(name); if((dir->qid.type&QTDIR) == 0) return dirval(dir, blkmultiple(dir->length)); fd = open(name, OREAD); if(fd < 0) return warn(name); nk = 0; while((n=dirread(fd, &buf)) > 0) { d = buf; for(i = n; i > 0; i--, d++) { if((d->qid.type&QTDIR) == 0) { nk += dufile(name, d); continue; } if(strcmp(d->name, ".") == 0 || strcmp(d->name, "..") == 0 || /* !readflg && */ seen(d)) continue; /* don't get stuck */ file = s_copy(name); s_append(file, "/"); s_append(file, d->name); t = du(s_to_c(file), d); nk += t; t = dirval(d, t); if(!sflag) printamt(t, s_to_c(file)); s_free(file); } free(buf); } if(n < 0) warn(name); close(fd); return dirval(dir, nk); }
/* output a message */ extern int m_print(message *mp, Biobuf *fp, char *remote, int mbox) { String *date, *sender; char *f[6]; int n; sender = unescapespecial(s_clone(mp->sender)); if (remote != 0){ if(print_remote_header(fp,s_to_c(sender),s_to_c(mp->date),remote) < 0){ s_free(sender); return -1; } } else { if(print_header(fp, s_to_c(sender), s_to_c(mp->date)) < 0){ s_free(sender); return -1; } } s_free(sender); if(!rmail && !mp->havedate){ /* add a date: line Date: Sun, 19 Apr 1998 12:27:52 -0400 */ date = s_copy(s_to_c(mp->date)); n = getfields(s_to_c(date), f, 6, 1, " \t"); if(n == 6) Bprint(fp, "Date: %s, %s %s %s %s %s\n", f[0], f[2], f[1], f[5], f[3], rewritezone(f[4])); } if(!rmail && !mp->havemime && isutf8(mp->body)) printutf8mime(fp); if(mp->to){ /* add the to: line */ if (Bprint(fp, "%s\n", s_to_c(mp->to)) < 0) return -1; /* add the from: line */ if (!mp->havefrom && printfrom(mp, fp) < 0) return -1; if(!mp->rfc822headers && *s_to_c(mp->body) != '\n') if (Bprint(fp, "\n") < 0) return -1; } else if(!rmail){ /* add the from: line */ if (!mp->havefrom && printfrom(mp, fp) < 0) return -1; if(!mp->rfc822headers && *s_to_c(mp->body) != '\n') if (Bprint(fp, "\n") < 0) return -1; } if (!mbox) return m_noescape(mp, fp); return m_escape(mp, fp); }
void main(int argc, char **argv) { int i; Biobuf *b; String *h; Whist *doc; ARGBEGIN{ default: usage(); case 'd': wikidir = EARGF(usage()); break; }ARGEND if(argc != 1) usage(); if((b = Bopen(argv[0], OREAD)) == nil) sysfatal("Bopen: %r"); if((doc = Brdwhist(b)) == nil) sysfatal("Brdwtxt: %r"); h = nil; for(i=0; i<doc->ndoc; i++){ print("__________________ %d ______________\n", i); if((h = pagetext(s_reset(h), doc->doc[i].wtxt, 1)) == nil) sysfatal("wiki2html: %r"); write(1, s_to_c(h), s_len(h)); } exits(0); }
/* * add warning headers of the form * X-warning: <reason> * for any headers that looked like they might be forged. * * return byte count of new headers */ static int forgedheaderwarnings(void) { int nbytes; Field *f; nbytes = 0; /* warn about envelope sender */ if(senders.last != nil && senders.last->p != nil && strcmp(s_to_c(senders.last->p), "/dev/null") != 0 && masquerade(senders.last->p, nil)) nbytes += Bprint(pp->std[0]->fp, "X-warning: suspect envelope domain\n"); /* * check Sender: field. If it's OK, ignore the others because this * is an exploded mailing list. */ for(f = firstfield; f; f = f->next) if(f->node->c == SENDER) if(masquerade(getaddr(f->node), him)) nbytes += Bprint(pp->std[0]->fp, "X-warning: suspect Sender: domain\n"); else return nbytes; /* check From: */ for(f = firstfield; f; f = f->next){ if(f->node->c == FROM && masquerade(getaddr(f->node), him)) nbytes += Bprint(pp->std[0]->fp, "X-warning: suspect From: domain\n"); } return nbytes; }
/* * rules are of the form: * <reg exp> <String> <repl exp> [<repl exp>] */ extern int getrules(void) { Biobuf *rfp; String *line; String *type; String *file; file = abspath("rewrite", UPASLIB, (String *)0); rfp = sysopen(s_to_c(file), "r", 0); if(rfp == 0) { rulep = 0; return -1; } rlastp = 0; line = s_new(); type = s_new(); while(s_getline(rfp, s_restart(line))) if(getrule(line, type, thissys) && altthissys) getrule(s_restart(line), type, altthissys); s_free(type); s_free(line); s_free(file); sysclose(rfp); return 0; }
/* * add anything that isn't already matched, all matches are lower case */ static char* add(char *pp, int argc, char **argv) { int fd, i; String *s; char *cp; Addr *a; a = nil; for(i = 0; i < argc; i++) a = readaddrs(argv[i], a); fd = open(pp, OWRITE); seek(fd, 0, 2); for(; a != nil; a = a->next){ if(checkaddr(a->val)) continue; s = simplify(a->val); cp = s_to_c(s); fprint(fd, "%q\t%q\n", cp, a->val); if(*cp == '=') newpattern(Texact, cp+1, 0); else if(*cp == '~') newpattern(Tregexp, cp+1, 0); s_free(s); } close(fd); return nil; }
/* * very dumb conversion to bang format */ static String* attobang(String *token) { char *p; String *tok; p = strchr(s_to_c(token), '@'); if(p == 0) return token; p++; tok = s_copy(p); s_append(tok, "!"); s_nappend(tok, s_to_c(token), p - s_to_c(token) - 1); return tok; }
void prstring(int indent, char *tag, String *s) { if(s == nil) return; prindent(indent+1); print("%s %s\n", tag, s_to_c(s)); }
/* get the first address from a node */ static String* getaddr(Node *p) { for(; p; p = p->next) if(p->s && p->addr) return s_copy(s_to_c(p->s)); return nil; }
/* if the mailbox exists, cat the mail to the end of it */ void appendtoarchive(char* listname, String *firstline, String *msg) { String *mbox; int fd; mbox = s_new(); mboxpath("mbox", listname, mbox, 0); if(access(s_to_c(mbox), 0) < 0) return; fd = open(s_to_c(mbox), OWRITE); if(fd < 0) return; s_append(msg, "\n"); write(fd, s_to_c(firstline), s_len(firstline)); write(fd, s_to_c(msg), s_len(msg)); }
/* loop through the translation files */ static int translate(char *name, /* name to translate */ char **namev, /* names of this system */ String *files, /* names of system alias files */ String *alias) /* where to put the alias */ { String *file = s_new(); String **fullnamev; int n, rv; rv = -1; DEBUG print("translate(%s, %s, %s)\n", name, s_to_c(files), s_to_c(alias)); /* create the full name to avoid loops (system!name) */ for(n = 0; namev[n]; n++) ; fullnamev = (String**)malloc(sizeof(String*)*(n+2)); n = 0; fullnamev[n++] = s_copy(name); for(; *namev; namev++){ fullnamev[n] = s_copy(*namev); s_append(fullnamev[n], "!"); s_append(fullnamev[n], name); n++; } fullnamev[n] = 0; /* look at system-wide names */ s_restart(files); while (s_parse(files, s_restart(file)) != 0) { if (lookup(fullnamev, file, alias)==0) { rv = 0; goto out; } } out: for(n = 0; fullnamev[n]; n++) s_free(fullnamev[n]); s_free(file); free(fullnamev); return rv; }
/* dispose of local addresses */ int cat_mail(dest *dp, message *mp) { Biobuf *fp; char *rcvr, *cp; Mlock *l; String *tmp, *s; int i, n; s = unescapespecial(s_clone(dp->repl1)); if (nflg) { if(!xflg) print("cat >> %s\n", s_to_c(s)); else print("%s\n", s_to_c(dp->addr)); s_free(s); return 0; } for(i = 0;; i++){ l = syslock(s_to_c(s)); if(l == 0) return refuse(dp, mp, "can't lock mail file", 0, 0); fp = sysopen(s_to_c(s), "al", MBOXMODE); if(fp) break; tmp = s_append(0, s_to_c(s)); s_append(tmp, ".tmp"); fp = sysopen(s_to_c(tmp), "al", MBOXMODE); if(fp){ syslog(0, "mail", "error: used %s", s_to_c(tmp)); s_free(tmp); break; } s_free(tmp); sysunlock(l); if(i >= 5) return refuse(dp, mp, "mail file cannot be opened", 0, 0); sleep(1000); } s_free(s); n = m_print(mp, fp, (char *)0, 1); if (Bprint(fp, "\n") < 0 || Bflush(fp) < 0 || n < 0){ sysclose(fp); sysunlock(l); return refuse(dp, mp, "error writing mail file", 0, 0); } sysclose(fp); sysunlock(l); rcvr = s_to_c(dp->addr); if(cp = strrchr(rcvr, '!')) rcvr = cp+1; logdelivery(dp, rcvr, mp); return 0; }
vlong dufile(char *name, Dir *d) { vlong t = blkmultiple(d->length); if(aflag || readflg) { String *file = s_copy(name); s_append(file, "/"); s_append(file, d->name); if (readflg) readfile(s_to_c(file)); t = dirval(d, t); printamt(t, s_to_c(file)); s_free(file); } return t; }