X-Git-Url: http://git.marmaro.de/?p=mmh;a=blobdiff_plain;f=uip%2Fspost.c;h=b8ae562984c347eaf98b85af944d6e89ca1da7a9;hp=cc163ac0b2fa672a72350163eb36a3f563bd5eec;hb=a87df3543d3bc128ba4079d1f95638476ba5ca50;hpb=5b792c4424571f05bc2008e3109797d18d7d00d1 diff --git a/uip/spost.c b/uip/spost.c index cc163ac..b8ae562 100644 --- a/uip/spost.c +++ b/uip/spost.c @@ -15,59 +15,27 @@ #include #include #include -#include #include +#include +#include +#include +#include #define MAX_SM_FIELD 1476 /* < largest hdr field sendmail will accept */ -#define FCCS 10 /* max number of fccs allowed */ - -struct swit switches[] = { -#define FILTSW 0 - { "filter filterfile", 0 }, -#define NFILTSW 1 - { "nofilter", 0 }, -#define FRMTSW 2 - { "format", 0 }, -#define NFRMTSW 3 - { "noformat", 0 }, -#define REMVSW 4 - { "remove", 0 }, -#define NREMVSW 5 - { "noremove", 0 }, -#define VERBSW 6 + +static struct swit switches[] = { +#define VERBSW 0 { "verbose", 0 }, -#define NVERBSW 7 - { "noverbose", 0 }, -#define WATCSW 8 - { "watch", 0 }, -#define NWATCSW 9 - { "nowatch", 0 }, -#define BACKSW 10 - { "backup", 0 }, -#define NBACKSW 11 - { "nobackup", 0 }, -#define ALIASW 12 - { "alias aliasfile", 0 }, -#define NALIASW 13 - { "noalias", 0 }, -#define WIDTHSW 14 - { "width columns", 0 }, -#define VERSIONSW 15 - { "version", 0 }, -#define HELPSW 16 +#define NVERBSW 1 + { "noverbose", 2 }, +#define VERSIONSW 2 + { "Version", 0 }, +#define HELPSW 3 { "help", 0 }, -#define DEBUGSW 17 +#define DEBUGSW 4 { "debug", -5 }, -#define DISTSW 18 +#define DISTSW 5 { "dist", -4 }, /* interface from dist */ -#define PUSHSW 19 /* fork to sendmail then exit */ - { "push", -4 }, -#define NPUSHSW 20 /* exec sendmail */ - { "nopush", -6 }, -#define LIBSW 21 - { "library directory", -7 }, -#define ANNOSW 22 - { "idanno number", -6 }, { NULL, 0 } }; @@ -79,11 +47,9 @@ struct swit switches[] = { #define HSUB 0x0004 /* Subject: header */ #define HTRY 0x0008 /* try to send to addrs on header */ #define HBCC 0x0010 /* don't output this header */ -#define HMNG 0x0020 /* mung this header */ -#define HNGR 0x0040 /* no groups allowed in this header */ -#define HFCC 0x0080 /* FCC: type header */ -#define HNIL 0x0100 /* okay for this header not to have addrs */ -#define HIGN 0x0200 /* ignore this header */ +#define HFCC 0x0020 /* FCC: type header */ +#define HIGN 0x0040 /* ignore this header */ +#define HDCC 0x0080 /* DCC: type header */ /* flags for headers->set */ #define MFRM 0x0001 /* we've seen a From: */ @@ -92,6 +58,7 @@ struct swit switches[] = { #define MVIS 0x0008 /* we've seen sighted addrs */ #define MINV 0x0010 /* we've seen blind addrs */ #define MRDT 0x0020 /* we've seen a Resent-Date: */ +#define MFMM 0x0040 /* The Mail is From a Alternative-Mailbox Addresse */ struct headers { char *value; @@ -99,51 +66,47 @@ struct headers { unsigned int set; }; - static struct headers NHeaders[] = { { "Return-Path", HBAD, 0 }, { "Received", HBAD, 0 }, - { "Reply-To", HADR|HNGR, 0 }, - { "From", HADR|HNGR, MFRM }, + { "Reply-To", HADR, 0 }, + { "From", HADR, MFRM }, { "Sender", HADR|HBAD, 0 }, { "Date", HNOP, MDAT }, { "Subject", HSUB, 0 }, { "To", HADR|HTRY, MVIS }, - { "cc", HADR|HTRY, MVIS }, - { "Bcc", HADR|HTRY|HBCC|HNIL, MINV }, + { "Cc", HADR|HTRY, MVIS }, + { "Dcc", HADR|HTRY|HDCC, MINV }, + { "Bcc", HADR|HTRY|HBCC, MINV }, { "Message-Id", HBAD, 0 }, { "Fcc", HFCC, 0 }, + { "Envelope-From", HIGN, 0 }, { NULL, 0, 0 } }; static struct headers RHeaders[] = { - { "Resent-Reply-To", HADR|HNGR, 0 }, - { "Resent-From", HADR|HNGR, MRFM }, + { "Resent-Reply-To", HADR, 0 }, + { "Resent-From", HADR, MRFM }, { "Resent-Sender", HADR|HBAD, 0 }, { "Resent-Date", HNOP, MRDT }, { "Resent-Subject", HSUB, 0 }, { "Resent-To", HADR|HTRY, MVIS }, { "Resent-Cc", HADR|HTRY, MVIS }, + { "Resent-Dcc", HADR|HTRY|HDCC, MINV }, { "Resent-Bcc", HADR|HTRY|HBCC, MINV }, { "Resent-Message-Id", HBAD, 0 }, { "Resent-Fcc", HFCC, 0 }, { "Reply-To", HADR, 0 }, { "Fcc", HIGN, 0 }, + { "Envelope-From", HIGN, 0 }, { NULL, 0, 0 } }; -static short fccind = 0; /* index into fccfold[] */ - -static int badmsg = 0; /* message has bad semantics */ -static int verbose = 0; /* spell it out */ -static int debug = 0; /* debugging post */ -static int rmflg = 1; /* remove temporary file when done */ -static int watch = 0; /* watch the delivery process */ -static int backflg = 0; /* rename input file as *.bak when done */ -static int pushflg = 0; /* if going to fork to sendmail */ +static int badmsg = 0; +static int verbose = 0; +static int debug = 0; static int aliasflg = 0; /* if going to process aliases */ -static int outputlinelen=72; static unsigned msgflags = 0; /* what we've seen */ @@ -151,64 +114,47 @@ static enum { normal, resent } msgstate = normal; -static char tmpfil[] = "/tmp/pstXXXXXX"; +static char *tmpfil; -static char from[BUFSIZ]; /* my network address */ -static char signature[BUFSIZ]; /* my signature */ -static char *filter = NULL; /* the filter for BCC'ing */ static char *subject = NULL; /* the subject field for BCC'ing */ -static char *fccfold[FCCS]; /* foldernames for FCC'ing */ +static char fccs[BUFSIZ] = ""; +struct mailname *bccs = NULL; /* list of the bcc recipients */ +struct mailname *recipients = NULL; /* list of the recipients */ +size_t recipientsc = 0; +struct mailname *sender = NULL; static struct headers *hdrtab; /* table for the message we're doing */ static FILE *out; /* output (temp) file */ -extern char *sendmail; - -/* -** external prototypes -*/ -extern char *getfullname(void); -extern char *getusername(void); - -extern boolean draft_from_masquerading; /* defined in mts.c */ - /* ** static prototypes */ static void putfmt(char *, char *, FILE *); -static void start_headers(void); static void finish_headers(FILE *); static int get_header(char *, struct headers *); static void putadr(char *, struct mailname *); static int putone(char *, int, int); -static void insert_fcc(struct headers *, unsigned char *); -static void file(char *); +static void process_fcc(char *); static void fcc(char *, char *); - -#if 0 -static void die(char *, char *, ...); -static void make_bcc_file(void); -#endif +static void process_bccs(char *); +static size_t do_aliasing(struct mailname *, struct mailname **); int main(int argc, char **argv) { - int state, i, pid, compnum; + enum state state; + struct field f = free_field; + int compnum; char *cp, *msg = NULL, **argp, **arguments; - char *sargv[16], buf[BUFSIZ], name[NAMESZ]; + char **sargv, buf[BUFSIZ]; FILE *in; -#ifdef LOCALE setlocale(LC_ALL, ""); -#endif invo_name = mhbasename(argv[0]); - /* foil search of user profile/context */ - if (context_foil(NULL) == -1) - done(1); + context_read(); - mts_init(invo_name); arguments = getarguments(invo_name, argc, argv, 0); argp = arguments; @@ -217,19 +163,19 @@ main(int argc, char **argv) switch (smatch(++cp, switches)) { case AMBIGSW: ambigsw(cp, switches); - done(1); + exit(EX_USAGE); case UNKWNSW: - adios(NULL, "-%s unknown", cp); + adios(EX_USAGE, NULL, "-%s unknown", cp); case HELPSW: snprintf(buf, sizeof(buf), "%s [switches] file", invo_name); print_help(buf, switches, 1); - done(1); + exit(argc == 2 ? EX_OK : EX_USAGE); case VERSIONSW: print_version(invo_name); - done(1); + exit(argc == 2 ? EX_OK : EX_USAGE); case DEBUGSW: debug++; @@ -239,412 +185,336 @@ main(int argc, char **argv) msgstate = resent; continue; - case FILTSW: - if (!(filter = *argp++) || *filter == '-') - adios(NULL, "missing argument to %s", - argp[-2]); - continue; - case NFILTSW: - filter = NULL; - continue; - - case REMVSW: - rmflg++; - continue; - case NREMVSW: - rmflg = 0; - continue; - - case BACKSW: - backflg++; - continue; - case NBACKSW: - backflg = 0; - continue; - case VERBSW: verbose++; continue; case NVERBSW: verbose = 0; continue; - - case WATCSW: - watch++; - continue; - case NWATCSW: - watch = 0; - continue; - - case PUSHSW: - pushflg++; - continue; - case NPUSHSW: - pushflg = 0; - continue; - - case ALIASW: - if (!(cp = *argp++) || *cp == '-') - adios(NULL, "missing argument to %s", - argp[-2]); - aliasflg = 1; - if ((state = alias(cp)) != AK_OK) - adios(NULL, "aliasing error in file %s - %s", cp, akerror(state) ); - continue; - case NALIASW: - aliasflg = 0; - continue; - - case WIDTHSW: - if (!(cp = *argp++) || *cp == '-') - adios(NULL, "missing argument to %s", - argp[-2]); - outputlinelen = atoi(cp); - if (outputlinelen <= 10) - outputlinelen = 72; - continue; - - case LIBSW: - if (!(cp = *argp++) || *cp == '-') - adios(NULL, "missing argument to %s", - argp[-2]); - /* create a minimal context */ - if (context_foil(cp) == -1) - done(1); - continue; - - case ANNOSW: - /* -idanno switch ignored */ - if (!(cp = *argp++) || *cp == '-') - adios(NULL, "missing argument to %s", - argp[-2]); - continue; } } - if (msg) - adios(NULL, "only one message at a time!"); - else + if (msg) { + adios(EX_USAGE, NULL, "only one message at a time!"); + } else { msg = cp; + } } - if (!msg) - adios(NULL, "usage: %s [switches] file", invo_name); + if (!msg) { + adios(EX_USAGE, NULL, "usage: %s [switches] file", invo_name); + } - if ((in = fopen(msg, "r")) == NULL) - adios(msg, "unable to open"); + if ((in = fopen(msg, "r")) == NULL) { + adios(EX_IOERR, msg, "unable to open"); + } - start_headers(); if (debug) { verbose++; out = stdout; + } else { + tmpfil = getcpy(m_mktemp2("/tmp/", invo_name, NULL, &out)); } - else { -#ifdef HAVE_MKSTEMP - if ((out = fdopen( mkstemp(tmpfil), "w" )) == NULL ) - adios(tmpfil, "unable to create"); -#else - mktemp(tmpfil); - if ((out = fopen(tmpfil, "w")) == NULL) - adios(tmpfil, "unable to create"); - chmod(tmpfil, 0600); -#endif + + /* check for "Aliasfile:" profile entry */ + if ((cp = context_find("Aliasfile"))) { + char *dp, **ap; + + aliasflg = 1; + for (ap=brkstring(dp=getcpy(cp), " ", "\n"); ap && *ap; + ap++) { + if ((state = alias(etcpath(*ap))) != AK_OK) { + adios(EX_IOERR, NULL, "aliasing error in file %s: %s", + *ap, akerror(state)); + } } + } - hdrtab = (msgstate == normal) ? NHeaders : RHeaders; - for (compnum = 1, state = FLD;;) { - switch (state = m_getfld(state, name, buf, sizeof(buf), in)) { - case FLD: - compnum++; - putfmt(name, buf, out); - continue; + hdrtab = (msgstate == normal) ? NHeaders : RHeaders; - case FLDPLUS: + for (compnum = 1, state = FLD2;;) { + switch (state = m_getfld2(state, &f, in)) { + case FLD2: compnum++; - cp = add(buf, cp); - while (state == FLDPLUS) { - state = m_getfld(state, name, buf, - sizeof(buf), in); - cp = add(buf, cp); - } - putfmt(name, cp, out); - free(cp); + putfmt(f.name, f.value, out); continue; - case BODY: + case BODY2: finish_headers(out); - fprintf(out, "\n%s", buf); - while (state == BODY) { - state = m_getfld(state, name, buf, - sizeof(buf), in); - fputs(buf, out); + fprintf(out, "\n%s", f.value); + while ((state = m_getfld2(state, &f, in)) == BODY2) { + fputs(f.value, out); } break; - case FILEEOF: + case FILEEOF2: finish_headers(out); break; - case LENERR: - case FMTERR: - adios(NULL, "message format error in component #%d", + case LENERR2: + case FMTERR2: + case IOERR2: + adios(EX_DATAERR, NULL, "message format error in component #%d", compnum); default: - adios(NULL, "getfld() returned %d", state); + adios(EX_SOFTWARE, NULL, "getfld() returned %d", state); } break; } - fclose(in); - if (backflg) { - strncpy(buf, m_backup(msg), sizeof(buf)); - if (rename(msg, buf) == NOTOK) - advise(buf, "unable to rename %s to", msg); - } if (debug) { - done(0); + struct mailname *i = recipients; + /* stop here */ + puts("----EOM----"); + while (i) { + fputs(i->m_mbox, stdout); + if (i->m_host) { + fputs("@", stdout); + fputs(i->m_host, stdout); + } + fputs("\n", stdout); + i = i->m_next; + mnfree(recipients); + recipients = i; + } + exit(EX_OK); } - else - fclose(out); - file(tmpfil); + fclose(out); + + /* process Fcc */ + if (*fccs) { + fcc(tmpfil, fccs); + } + + if (bccs) { + process_bccs(tmpfil); + if (!(msgflags & MVIS)) { + /* only Bcc rcpts: we're finished here */ + unlink(tmpfil); + exit(EX_OK); + } + } /* ** re-open the temp file, unlink it and exec sendmail, giving it ** the msg temp file as std in. */ - if (freopen(tmpfil, "r", stdin) == NULL) - adios(tmpfil, "can't reopen for sendmail"); - if (rmflg) - unlink(tmpfil); + if (!freopen(tmpfil, "r", stdin)) { + adios(EX_IOERR, tmpfil, "can't reopen for sendmail"); + } + unlink(tmpfil); + + if (recipientsc == 0) { + adios(EX_DATAERR, NULL, "message has no recipients"); + } + + sargv = mh_xmalloc(sizeof(char **) * (recipientsc + 4)); argp = sargv; *argp++ = "send-mail"; - *argp++ = "-m"; /* send to me too */ - *argp++ = "-t"; /* read msg for recipients */ *argp++ = "-i"; /* don't stop on "." */ - if (watch || verbose) + if (verbose) { *argp++ = "-v"; - *argp = NULL; + } - if (pushflg && !(watch || verbose)) { - /* fork to a child to run sendmail */ - for (i=0; (pid = vfork()) == NOTOK && i < 5; i++) - sleep(5); - switch (pid) { - case NOTOK: - fprintf(verbose ? stdout : stderr, - "%s: can't fork to %s\n", - invo_name, sendmail); - exit(-1); - case OK: - /* we're the child .. */ - break; - default: - exit(0); + while (recipients != NULL) { + cp = getcpy(recipients->m_mbox); + if (recipients->m_host) { + cp = add("@", cp); + cp = add(recipients->m_host, cp); } + *argp++ = cp; + cp = NULL; + recipients = recipients->m_next; + } + *argp = NULL; + execvp(sendmail, sargv); + + if (errno == E2BIG) { + adios(EX_DATAERR, sendmail, "too much arguments, probably to much recipients"); } - execv(sendmail, sargv); - adios(sendmail, "can't exec"); - return 0; /* dead code to satisfy the compiler */ + + adios(EX_OSERR, sendmail, "can't exec"); + return -1; } + /* DRAFT GENERATION */ static void putfmt(char *name, char *str, FILE *out) { int i; - char *cp, *pp; struct headers *hdr; + struct mailname addr_start, *addr_end; + size_t addrc = 0; + ssize_t ret; - while (*str == ' ' || *str == '\t') + addr_end = &addr_start; + addr_end->m_next = NULL; + + /* remove leading whitespace */ + while (*str==' ' || *str=='\t') { str++; + } if ((i = get_header(name, hdrtab)) == NOTOK) { + /* no header we would care for */ + if (mh_strcasecmp(name, attach_hdr)==0) { + return; + } + if (mh_strcasecmp(name, sign_hdr)==0) { + return; + } + if (mh_strcasecmp(name, enc_hdr)==0) { + return; + } + /* push it through */ fprintf(out, "%s: %s", name, str); return; } - + /* it's one of the interesting headers */ hdr = &hdrtab[i]; - if (hdr->flags & HIGN) + + if (hdr->flags & HIGN || strcmp(str, "\n")==0) { return; + } + if (hdr->flags & HBAD) { advise(NULL, "illegal header line -- %s:", name); badmsg++; return; } - msgflags |= hdr->set; - if (hdr->flags & HSUB) - subject = subject ? add(str, add("\t", subject)) : - getcpy(str); + msgflags |= hdr->set; if (hdr->flags & HFCC) { - if ((cp = strrchr(str, '\n'))) - *cp = 0; - for (cp = pp = str; (cp = strchr(pp, ',')); pp = cp) { - *cp++ = 0; - insert_fcc(hdr, pp); - } - insert_fcc(hdr, pp); + process_fcc(str); return; } -#ifdef notdef + if (hdr->flags & HSUB) { + subject = getcpy(str); + } + + if (!(hdr->flags & HADR)) { + fprintf(out, "%s: %s", name, str); + return; + } + + if ((ret = getmboxes(str, &addr_end)) < 0) { + adios(EX_DATAERR, NULL, "can't parse address: %s", str); + } + + addrc += ret; + + if (aliasflg) { + addrc += do_aliasing(&addr_start, &addr_end); + } + if (hdr->flags & HBCC) { - insert_bcc(str); + addr_end->m_next = bccs; + bccs = addr_start.m_next; return; } -#endif /* notdef */ - - if (*str != '\n' && *str != '\0') { - if (aliasflg && hdr->flags & HTRY) { - /* - ** this header contains address(es) that we have to do - ** alias expansion on. Because of the saved state in - ** getname we have to put all the addresses into a - ** list. We then let putadr munch on that list, - ** possibly expanding aliases. - **/ - register struct mailname *f = 0; - register struct mailname *mp = 0; - - while ((cp = getname(str))) { - mp = getm( cp, NULL, 0, AD_HOST, NULL); - if (f == 0) { - f = mp; - mp->m_next = mp; - } else { - mp->m_next = f->m_next; - f->m_next = mp; - f = mp; + + if (hdr->set & MFRM) { + struct mailname *mp = NULL; + struct mailname *my = NULL; + + /* needed because the address parser holds global state */ + ismymbox(NULL); + + for ( mp = addr_start.m_next; mp; mp = mp->m_next) { + if (ismymbox(mp)) { + msgflags |= MFMM; + if (my == NULL) { + my = mp; } } - f = mp->m_next; mp->m_next = 0; - putadr( name, f ); - } else { - /* - ** The author(s) of spost decided that alias - ** substitution wasn't necessary for the non-HTRY - ** headers. Unfortunately, one of those headers - ** is "From:", and having alias substitution - ** work on that is extremely useful for someone - ** with a lot of POP3 email accounts or aliases. - ** post supports aliasing of "From:"... - ** - ** Since "From:"-processing is incompletely - ** implemented in this unsupported and - ** undocumented spost backend, I'm not - ** going to take the time to implement my new - ** draft-From:-based email address masquerading. - ** If I do ever implement it here, I'd almost - ** certainly want to implement "From:" line - ** alias processing as well. - ** -- Dan Harkless - */ - fprintf(out, "%s: %s", name, str ); } - } -} - -static void -start_headers(void) -{ - char *cp; - char sigbuf[BUFSIZ]; + if (addrc > 1) { + sender = my; + } + } - strncpy(from, getusername(), sizeof(from)); + if (!(hdr->flags & HDCC)) { + putadr(name, addr_start.m_next); + } - if ((cp = getfullname()) && *cp) { - strncpy(sigbuf, cp, sizeof(sigbuf)); - snprintf(signature, sizeof(signature), "%s <%s>", - sigbuf, from); - } else - snprintf(signature, sizeof(signature), "%s", from); + if (hdr->flags & HTRY) { + addr_end->m_next = recipients; + recipients = addr_start.m_next; + recipientsc += i; + } } +/* +** Add yet missing headers. +*/ static void finish_headers(FILE *out) { - switch (msgstate) { - case normal: - if (!(msgflags & MDAT)) - fprintf(out, "Date: %s\n", dtimenow(0)); - - if (msgflags & MFRM) { - /* - ** There was already a From: in the draft. - ** Don't add one. - */ - if (!draft_from_masquerading) - /* - ** mts.conf didn't contain - ** "masquerade:[...]draft_from[...]" - ** so we'll reveal the user's - ** actual account@thismachine - ** address in a Sender: header - ** (and use it as the envelope - ** From: later). - */ - fprintf(out, "Sender: %s\n", from); - } else - fprintf(out, "From: %s\n", signature); - -#ifdef notdef - if (!(msgflags & MVIS)) - fprintf(out, "Bcc: Blind Distribution List: ;\n"); -#endif /* notdef */ - break; + char *cp; + char from[BUFSIZ]; /* my network address */ + char signature[BUFSIZ]; /* my signature */ + char *resentstr = (msgstate == resent) ? "Resent-" : ""; - case resent: - if (!(msgflags & MRDT)) - fprintf(out, "Resent-Date: %s\n", dtimenow(0)); - if (msgflags & MRFM) { - /* - ** There was already a Resent-From: in draft. - ** Don't add one. - */ - if (!draft_from_masquerading) - /* - ** mts.conf didn't contain - ** "masquerade:[...]draft_from[...]" - ** so we'll reveal the user's - ** actual account@thismachine - ** address in a Sender: header - ** (and use it as the envelope - ** From: later). - */ - fprintf(out, "Resent-Sender: %s\n", - from); - } else - /* Construct a Resent-From: header. */ - fprintf(out, "Resent-From: %s\n", signature); -#ifdef notdef - if (!(msgflags & MVIS)) - fprintf(out, "Resent-Bcc: Blind Re-Distribution List: ;\n"); -#endif /* notdef */ - break; + if (!(msgflags & MDAT)) { + fprintf(out, "%sDate: %s\n", resentstr, dtimenow()); } - if (badmsg) - adios(NULL, "re-format message and try again"); + if (sender != NULL) { + snprintf(signature, sizeof(signature), "%s", sender->m_text); + } else if ((cp = context_find("Default-From")) != NULL) { + snprintf(signature, sizeof(signature), "%s", cp); + } else { + snprintf(from, sizeof(from), "%s@%s", getusername(), LocalName()); + if ((cp = getfullname()) && *cp) { + snprintf(signature, sizeof(signature), "%s <%s>", cp, from); + } else { + snprintf(signature, sizeof(signature), "%s", from); + } + } + if (!(msgflags & MFRM)) { + fprintf(out, "%sFrom: %s\n", resentstr, signature); + } else { + /* + ** Add a Sender: header because the From: header could + ** be fake or contain multiple addresses. + */ + if (!(msgflags & MFMM) || sender != NULL) { + fprintf(out, "%sSender: %s\n", resentstr, signature); + } + } + if (!(msgflags & MVIS)) { + fprintf(out, "%sBcc: undisclosed-recipients:;\n", resentstr); + } + if (badmsg) { + unlink(tmpfil); + adios(EX_DATAERR, NULL, "re-format message and try again"); + } } +/* +** Return index of the requested header in the table, or NOTOK if missing. +*/ static int get_header(char *header, struct headers *table) { struct headers *h; - for (h = table; h->value; h++) - if (!mh_strcasecmp(header, h->value)) + for (h=table; h->value; h++) { + if (mh_strcasecmp(header, h->value)==0) { return (h - table); - + } + } return NOTOK; } @@ -657,9 +527,9 @@ get_header(char *header, struct headers *table) static void putadr(char *name, struct mailname *nl) { - register struct mailname *mp, *mp2; - register int linepos; - register char *cp; + struct mailname *mp; + char *cp; + int linepos; int namelen; fprintf(out, "%s: ", name); @@ -671,58 +541,41 @@ putadr(char *name, struct mailname *nl) fprintf(out, "\n%s: ", name); linepos = namelen; } - if (mp->m_nohost) { - /* a local name - see if it's an alias */ - cp = akvalue(mp->m_mbox); - if (cp == mp->m_mbox) - /* wasn't an alias - use what the user typed */ - linepos = putone(mp->m_text, linepos, namelen); - else - /* an alias - expand it */ - while ((cp = getname(cp))) { - if (linepos > MAX_SM_FIELD) { - fprintf(out, "\n%s: ", name); - linepos = namelen; - } - mp2 = getm( cp, NULL, 0, AD_HOST, NULL); - if (akvisible()) { - mp2->m_pers = getcpy(mp->m_mbox); - linepos = putone( adrformat(mp2), linepos, namelen ); - } else { - linepos = putone( mp2->m_text, linepos, namelen ); - } - mnfree( mp2 ); - } + if (mp->m_ingrp) { + if (mp->m_gname != NULL) { + cp = getcpy(mp->m_gname); + cp = add(";", cp); + linepos = putone(cp, linepos, namelen); + free(cp); + cp = NULL; + } } else { - /* not a local name - use what the user typed */ - linepos = putone( mp->m_text, linepos, namelen ); + linepos = putone(mp->m_text, linepos, namelen); } - mp2 = mp; mp = mp->m_next; - mnfree( mp2 ); } - putc( '\n', out ); + putc('\n', out); } static int putone(char *adr, int pos, int indent) { - register int len; + int len; static int linepos; - len = strlen( adr ); - if (pos == indent) + len = strlen(adr); + if (pos == indent) { linepos = pos; - else if (linepos+len > outputlinelen) { - fprintf( out, ",\n%*s", indent, ""); + } else if (linepos+len > OUTPUTLINELEN) { + fprintf(out, ",\n%*s", indent, ""); linepos = indent; pos += indent + 2; } else { - fputs( ", ", out ); + fputs(", ", out); linepos += 2; pos += 2; } - fputs( adr, out ); + fputs(adr, out); linepos += len; return (pos+len); @@ -730,180 +583,137 @@ putone(char *adr, int pos, int indent) static void -insert_fcc(struct headers *hdr, unsigned char *pp) -{ - unsigned char *cp; - - for (cp = pp; isspace(*cp); cp++) - continue; - for (pp += strlen(pp) - 1; pp > cp && isspace(*pp); pp--) - continue; - if (pp >= cp) - *++pp = 0; - if (*cp == 0) - return; - - if (fccind >= FCCS) - adios(NULL, "too many %ss", hdr->value); - fccfold[fccind++] = getcpy(cp); -} - -#if 0 -/* BCC GENERATION */ - -static void -make_bcc_file(void) +process_fcc(char *str) { - pid_t child_id; - int fd, i, status; - char *vec[6]; - FILE * in, *out; - -#ifdef HAVE_MKSTEMP - fd = mkstemp(bccfil); - if (fd == -1 || (out = fdopen(fd, "w")) == NULL) - adios(bccfil, "unable to create"); -#else - mktemp(bccfil); - if ((out = fopen(bccfil, "w")) == NULL) - adios(bccfil, "unable to create"); -#endif - chmod(bccfil, 0600); - - fprintf(out, "Date: %s\n", dtimenow(0)); - if (msgflags & MFRM) { - /* There was already a From: in the draft. Don't add one. */ - if (!draft_from_masquerading) - /* - ** mts.conf didn't contain "masquerade:[...]draft_from[...]" - ** so we'll reveal the user's actual account@thismachine - ** address in a Sender: header (and use it as the envelope - ** From: later). - */ - fprintf(out, "Sender: %s\n", from); - } else - /* Construct a From: header. */ - fprintf(out, "From: %s\n", signature); - if (subject) - fprintf(out, "Subject: %s", subject); - fprintf(out, "BCC:\n\n------- Blind-Carbon-Copy\n\n"); - fflush(out); - - if (filter == NULL) { - if ((fd = open(tmpfil, O_RDONLY)) == NOTOK) - adios(NULL, "unable to re-open"); - cpydgst(fd, fileno(out), tmpfil, bccfil); - close(fd); - } else { - vec[0] = mhbasename(mhlproc); - - for (i = 0; (child_id = vfork()) == NOTOK && i < 5; i++) - sleep(5); - switch (child_id) { - case NOTOK: - adios("vfork", "unable to"); - - case OK: - dup2(fileno(out), 1); - - i = 1; - vec[i++] = "-forward"; - vec[i++] = "-form"; - vec[i++] = filter; - vec[i++] = tmpfil; - vec[i] = NULL; - - execvp(mhlproc, vec); - adios(mhlproc, "unable to exec"); + char *cp, *pp; + int state = 0; + if (strlen(str)+strlen(fccs) > sizeof fccs /2) { + adios(EX_DATAERR, NULL, "Too much Fcc data"); + } + /* todo: better have three states: SEPARATOR, PLUS, WORD */ + for (cp=pp=str; *cp; cp++) { + switch (*cp) { + case ' ': + case '\t': + case '\n': + case ',': + if (state != 0) { + state = 0; + *cp = '\0'; + if (*pp=='+' || *pp=='@') { + strcat(fccs, " "); + } else { + strcat(fccs, " +"); + } + strcat(fccs, pp); + } + break; default: - if (status = pidwait(child_id, OK)) - admonish(NULL, "%s lost (status=0%o)", - vec[0], status); + if (state == 0) { + state = 1; + pp = cp; + } break; } } - - fseek(out, 0L, SEEK_END); - fprintf(out, "\n------- End of Blind-Carbon-Copy\n"); - fclose(out); } -#endif /* if 0 */ -/* FCC INTERACTION */ static void -file(char *path) +fcc(char *file, char *folders) { - int i; + int status; + char cmd[BUFSIZ]; - if (fccind == 0) - return; - - for (i = 0; i < fccind; i++) - fcc(path, fccfold[i]); + if (verbose) { + printf("%sFcc: %s\n", msgstate == resent ? "Resent-" : "", + folders); + fflush(stdout); + } + if (100+strlen(file)+strlen(folders) > sizeof cmd) { + adios(EX_DATAERR, NULL, "Too much Fcc data"); + } + /* hack: read from /dev/null and refile(1) won't question us */ + snprintf(cmd, sizeof cmd, "m_next) { + bccdraft = getcpy(m_mktemp2("/tmp/", invo_name, NULL, &out)); + fprintf(out, "To: %s\n", mp->m_text); + fprintf(out, "Subject: [BCC] %s", subject ? subject : ""); + fprintf(out, "%s: %s\n", attach_hdr, origmsg); + fprintf(out, "------------\n"); + fclose(out); - case OK: - snprintf(fold, sizeof(fold), "%s%s", - *folder == '+' || *folder == '@' ? "" : "+", folder); - execlp(fileproc, mhbasename(fileproc), - "-link", "-file", file, fold, NULL); - _exit(-1); - - default: - if ((status = pidwait(child_id, OK))) { - if (!verbose) - fprintf(stderr, " %sFcc %s: ", - msgstate == resent ? - "Resent-" : "", folder); - fprintf(verbose ? stdout : stderr, " errored (0%o)\n", - status); + if (execprogl("send", "send", bccdraft, (char *)NULL) != 0) { + admonish(invo_name, "Problems to send Bcc to %s", + mp->m_text); + unlink(bccdraft); } } - - fflush(stdout); } - -#if 0 - /* -** TERMINATION -*/ - -static void -die(char *what, char *fmt, ...) + * Do aliasing on a mailname linked list + * Begin at start->m_next + * End if m_next == NULL + * **end is set to the new end. + * Return the number of new mainames in the list + */ + +static size_t +do_aliasing(struct mailname *start, struct mailname **end) { - va_list ap; - - va_start(ap, fmt); - advertise(what, NULL, fmt, ap); - va_end(ap); - - done(1); + struct mailname *prev, *cur; + char *cp; + size_t i = 0; + ssize_t e; + + prev = start; + cur = prev->m_next; + + while (cur != NULL) { + if (cur->m_nohost) { + cp = akvalue(cur->m_mbox); + if (strcmp(cp, cur->m_mbox) != 0) { + prev->m_next = cur->m_next; + if ((e = getmboxes(cp, &prev)) < 0) { + goto error; + } + i += e; + i -= 1; + mnfree(cur); + } else { + prev = cur; + } + } else { + prev = cur; + } + cur = prev->m_next; + } + *end = prev; + return i; +error: + adios(EX_CONFIG, NULL, "can't parse alias %s: %s", cur->m_mbox, cp); + return 0; /* not reached */ } -#endif