X-Git-Url: http://git.marmaro.de/?p=mmh;a=blobdiff_plain;f=uip%2Fspost.c;h=7b74dcc918757026cb6a6e2cce4c2bb4ea702441;hp=8c55c06e63e96ad99550ac47a515ba8ea7e71fd5;hb=80eeca1af5bc5120d9aeef933c2e162c382c9d29;hpb=40821f5c1316e9205a08375e7075909cc9968e7d diff --git a/uip/spost.c b/uip/spost.c index 8c55c06..7b74dcc 100644 --- a/uip/spost.c +++ b/uip/spost.c @@ -15,59 +15,38 @@ #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 +#define VERBSW 0 { "verbose", 0 }, -#define NVERBSW 7 +#define NVERBSW 1 { "noverbose", 0 }, -#define WATCSW 8 +#define WATCSW 2 { "watch", 0 }, -#define NWATCSW 9 +#define NWATCSW 3 { "nowatch", 0 }, -#define BACKSW 10 - { "backup", 0 }, -#define NBACKSW 11 - { "nobackup", 0 }, -#define ALIASW 12 +#define ALIASW 4 { "alias aliasfile", 0 }, -#define NALIASW 13 +#define NALIASW 5 { "noalias", 0 }, -#define WIDTHSW 14 - { "width columns", 0 }, -#define VERSIONSW 15 +#define VERSIONSW 6 { "version", 0 }, -#define HELPSW 16 +#define HELPSW 7 { "help", 0 }, -#define DEBUGSW 17 +#define DEBUGSW 8 { "debug", -5 }, -#define DISTSW 18 +#define DISTSW 9 { "dist", -4 }, /* interface from dist */ -#define PUSHSW 19 /* fork to sendmail then exit */ +#define PUSHSW 10 /* fork to sendmail then exit */ { "push", -4 }, -#define NPUSHSW 20 /* exec sendmail */ +#define NPUSHSW 11 /* exec sendmail */ { "nopush", -6 }, -#define LIBSW 21 +#define LIBSW 12 { "library directory", -7 }, -#define ANNOSW 22 - { "idanno number", -6 }, { NULL, 0 } }; @@ -79,11 +58,10 @@ 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 HNGR 0x0020 /* no groups allowed in this header */ +#define HFCC 0x0040 /* FCC: type header */ +#define HNIL 0x0080 /* okay for this header not to have addrs */ +#define HIGN 0x0100 /* ignore this header */ /* flags for headers->set */ #define MFRM 0x0001 /* we've seen a From: */ @@ -109,7 +87,7 @@ static struct headers NHeaders[] = { { "Date", HNOP, MDAT }, { "Subject", HSUB, 0 }, { "To", HADR|HTRY, MVIS }, - { "cc", HADR|HTRY, MVIS }, + { "Cc", HADR|HTRY, MVIS }, { "Bcc", HADR|HTRY|HBCC|HNIL, MINV }, { "Message-Id", HBAD, 0 }, { "Fcc", HFCC, 0 }, @@ -133,17 +111,12 @@ static struct headers RHeaders[] = { }; -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 aliasflg = 0; /* if going to process aliases */ -static int outputlinelen=72; static unsigned msgflags = 0; /* what we've seen */ @@ -151,13 +124,12 @@ static enum { normal, resent } msgstate = normal; -static char tmpfil[] = "/tmp/pstXXXXXX"; +static char tmpfil[] = "/tmp/spost-XXXXXX"; +static char bccfil[] = "/tmp/spost-bcc-XXXXXX"; -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; static struct headers *hdrtab; /* table for the message we're doing */ static FILE *out; /* output (temp) file */ @@ -165,30 +137,15 @@ 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 fcc(char *, char *); - -#if 0 -static void die(char *, char *, ...); -static void make_bcc_file(void); -#endif +static void make_bcc_draft(char *); int @@ -208,7 +165,6 @@ main(int argc, char **argv) if (context_foil(NULL) == -1) done(1); - mts_init(invo_name); arguments = getarguments(invo_name, argc, argv, 0); argp = arguments; @@ -239,29 +195,6 @@ 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; @@ -289,21 +222,12 @@ main(int argc, char **argv) argp[-2]); aliasflg = 1; if ((state = alias(cp)) != AK_OK) - adios(NULL, "aliasing error in file %s - %s", cp, akerror(state) ); + 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", @@ -312,13 +236,6 @@ main(int argc, char **argv) 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) @@ -333,22 +250,20 @@ main(int argc, char **argv) if ((in = fopen(msg, "r")) == NULL) adios(msg, "unable to open"); - start_headers(); if (debug) { verbose++; out = stdout; - } - else { + } else { #ifdef HAVE_MKSTEMP - if ((out = fdopen( mkstemp(tmpfil), "w" )) == NULL ) - adios(tmpfil, "unable to create"); + 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); + mktemp(tmpfil); + if ((out = fopen(tmpfil, "w")) == NULL) + adios(tmpfil, "unable to create"); + chmod(tmpfil, 0600); #endif - } + } hdrtab = (msgstate == normal) ? NHeaders : RHeaders; @@ -395,41 +310,46 @@ main(int argc, char **argv) } 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) { + /* stop here */ done(0); } - else - fclose(out); - file(tmpfil); + fclose(out); + + /* process Fcc */ + if (*fccs) { + fcc(tmpfil, fccs); + } + + /* process Bcc */ + if (bccs) { + make_bcc_draft(tmpfil); + } /* ** 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) + if (!freopen(tmpfil, "r", stdin)) { adios(tmpfil, "can't reopen for sendmail"); - if (rmflg) - unlink(tmpfil); + } + unlink(tmpfil); 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 (watch || verbose) { *argp++ = "-v"; + pushflg = 0; + } *argp = NULL; - if (pushflg && !(watch || verbose)) { + if (pushflg) { /* fork to a child to run sendmail */ for (i=0; (pid = fork()) == NOTOK && i < 5; i++) sleep(5); @@ -446,6 +366,25 @@ main(int argc, char **argv) exit(0); } } + + if (0 /*bccs*/) { + /* fork to a child to run sendmail */ + for (i=0; (pid = fork()) == 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 .. */ + exit(0); + default: + exit(0); + } + } + execv(sendmail, sargv); adios(sendmail, "can't exec"); return 0; /* dead code to satisfy the compiler */ @@ -464,13 +403,16 @@ putfmt(char *name, char *str, FILE *out) str++; if ((i = get_header(name, hdrtab)) == NOTOK) { + /* some boring header: push it through */ fprintf(out, "%s: %s", name, str); return; } - + /* one of the interesting headers */ hdr = &hdrtab[i]; - if (hdr->flags & HIGN) + + if (hdr->flags & HIGN) { return; + } if (hdr->flags & HBAD) { advise(NULL, "illegal header line -- %s:", name); badmsg++; @@ -478,30 +420,62 @@ putfmt(char *name, char *str, FILE *out) } msgflags |= hdr->set; - if (hdr->flags & HSUB) - subject = subject ? add(str, add("\t", subject)) : - getcpy(str); - - 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); + if (hdr->flags & HSUB) { + if (subject) { + /* concatenate mupliple subject */ + char *cp = concat(subject, "\t", str, NULL); + free(subject); + subject = cp; + } else { + subject = getcpy(str); } - insert_fcc(hdr, pp); - return; } -#ifdef notdef - if (hdr->flags & HBCC) { - insert_bcc(str); + if (hdr->flags & HFCC) { + if (strlen(str)+strlen(fccs) > sizeof fccs /2) { + adios(NULL, "Too much Fcc data"); + } + /* todo: better have three states: SEPARATOR, PLUS, WORD */ + int state = 0; + 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 (state == 0) { + state = 1; + pp = cp; + } + break; + } + } return; } -#endif /* notdef */ if (*str != '\n' && *str != '\0') { - if (aliasflg && hdr->flags & HTRY) { + if (hdr->flags & HBCC) { + struct mailname *mp = NULL; + + /* Create list of Bcc adds. */ + while ((cp = getname(str))) { + mp = getm(cp, NULL, 0, AD_HOST, NULL); + mp->m_next = bccs; /* push */ + bccs = mp; + } + } else if (aliasflg && hdr->flags & HTRY) { /* ** this header contains address(es) that we have to do ** alias expansion on. Because of the saved state in @@ -513,7 +487,7 @@ putfmt(char *name, char *str, FILE *out) register struct mailname *mp = 0; while ((cp = getname(str))) { - mp = getm( cp, NULL, 0, AD_HOST, NULL); + mp = getm(cp, NULL, 0, AD_HOST, NULL); if (f == 0) { f = mp; mp->m_next = mp; @@ -524,7 +498,7 @@ putfmt(char *name, char *str, FILE *out) } } f = mp->m_next; mp->m_next = 0; - putadr( name, f ); + putadr(name, f); } else { /* ** The author(s) of spost decided that alias @@ -545,105 +519,61 @@ putfmt(char *name, char *str, FILE *out) ** alias processing as well. ** -- Dan Harkless */ - fprintf(out, "%s: %s", name, str ); + fprintf(out, "%s: %s", name, str); } } } +/* +** Add yet missing headers. +*/ static void -start_headers(void) +finish_headers(FILE *out) { char *cp; - char sigbuf[BUFSIZ]; + char from[BUFSIZ]; /* my network address */ + char signature[BUFSIZ]; /* my signature */ + char *resentstr = (msgstate == resent) ? "Resent-" : ""; - strncpy(from, getusername(), sizeof(from)); + if (!(msgflags & MDAT)) { + fprintf(out, "%sDate: %s\n", resentstr, dtimenow(0)); + } + strncpy(from, getusername(), sizeof(from)); if ((cp = getfullname()) && *cp) { - strncpy(sigbuf, cp, sizeof(sigbuf)); - snprintf(signature, sizeof(signature), "%s <%s>", - sigbuf, from); - } else - snprintf(signature, sizeof(signature), "%s", from); -} - - -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; - - 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; + snprintf(signature, sizeof(signature), "%s <%s>", cp, from); + } else { + snprintf(signature, sizeof(signature), "%s", from); } - - if (badmsg) + if (!(msgflags & MFRM)) { + fprintf(out, "%sFrom: %s\n", resentstr, signature); + } else { + /* In case the From: header contains multiple addresses. */ + fprintf(out, "%sSender: %s\n", resentstr, from); + } + if (!(msgflags & MVIS)) { + fprintf(out, "%sBcc: Blind Distribution List: ;\n", resentstr); + } + if (badmsg) { adios(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 +587,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, *mp2; + int linepos; + char *cp; int namelen; fprintf(out, "%s: ", name); @@ -674,34 +604,37 @@ putadr(char *name, struct mailname *nl) if (mp->m_nohost) { /* a local name - see if it's an alias */ cp = akvalue(mp->m_mbox); - if (cp == 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 + } else { /* an alias - expand it */ while ((cp = getname(cp))) { if (linepos > MAX_SM_FIELD) { - fprintf(out, "\n%s: ", name); - linepos = namelen; + fprintf(out, "\n%s: ", name); + linepos = namelen; } - mp2 = getm( cp, NULL, 0, AD_HOST, NULL); + mp2 = getm(cp, NULL, 0, AD_HOST, NULL); if (akvisible()) { mp2->m_pers = getcpy(mp->m_mbox); - linepos = putone( adrformat(mp2), linepos, namelen ); + linepos = putone(adrformat(mp2), linepos, namelen); } else { - linepos = putone( mp2->m_text, linepos, namelen ); + linepos = putone(mp2->m_text, + linepos, + namelen); } - mnfree( mp2 ); + mnfree(mp2); } + } } 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 ); + mnfree(mp2); } - putc( '\n', out ); + putc('\n', out); } static int @@ -710,19 +643,19 @@ putone(char *adr, int pos, int indent) register int len; static int linepos; - len = strlen( adr ); + 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,34 +663,40 @@ putone(char *adr, int pos, int indent) static void -insert_fcc(struct headers *hdr, unsigned char *pp) +fcc(char *file, char *folders) { - 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; + int status; + char cmd[BUFSIZ]; - if (fccind >= FCCS) - adios(NULL, "too many %ss", hdr->value); - fccfold[fccind++] = getcpy(cp); + if (verbose) { + printf("%sFcc: %s\n", msgstate == resent ? "Resent-" : "", + folders); + fflush(stdout); + } + if (strlen(fileproc)+strlen(file)+strlen(folders)+100 > sizeof cmd) { + adios(NULL, "Too much Fcc data"); + } + /* hack: read from /dev/null and refile(1) won't question us */ + snprintf(cmd, sizeof cmd, "