Mercurial > hg > Applications > mh
diff uip/spost.c @ 0:bce86c4163a3
Initial revision
author | kono |
---|---|
date | Mon, 18 Apr 2005 23:46:02 +0900 |
parents | |
children | 441a2190cfae |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uip/spost.c Mon Apr 18 23:46:02 2005 +0900 @@ -0,0 +1,996 @@ +#ifndef lint +static char sccsid[] = "@(#)spost.c 1.6 (Berkeley) 11/2/85"; +#endif +#ifndef lint +static char ident[] = "@(#)$Id$"; +#endif /* lint */ + +/* spost.c - feed messages to sendmail */ +/* + * (This is a simpler, faster, replacement for "post" for use when "sendmail" + * is the transport system) + */ + +#include <ctype.h> +#include <stdio.h> +#include <signal.h> +#include "../h/mh.h" +#include "../h/addrsbr.h" +#include "../h/aliasbr.h" +#include "../h/dropsbr.h" +#include "../zotnet/tws.h" +#ifdef LOCALE +#include <locale.h> +#endif +#ifdef UNISTD +#include <unistd.h> +#endif + +extern char *getfullname (), *getusr (); +extern char *sendmail; + + +#define uptolow(c) ((isalpha(c) && isupper (c)) ? tolower (c) : c) + +#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 + "verbose", 0, +#define NVERBSW 7 + "noverbose", 0, + +#define WATCSW 8 + "watch", 0, +#define NWATCSW 9 + "nowatch", 0, + +#define HELPSW 10 + "help", 4, + +#define DEBUGSW 11 + "debug", -5, + +#define DISTSW 12 + "dist", -4, /* interface from dist */ + +#define BACKSW 13 + "backup", 0, +#define NBACKSW 14 + "nobackup", 0, + +#define CHKSW 15 + "check", -5, /* interface from whom */ +#define NCHKSW 16 + "nocheck", -7, /* interface from whom */ +#define WHOMSW 17 + "whom", -4, /* interface from whom */ + +#define PUSHSW 18 /* fork to sendmail then exit */ + "push", -4, +#define NPUSHSW 19 /* exec sendmail */ + "nopush", -6, + +#define ALIASW 20 + "alias aliasfile", 0, +#define NALIASW 21 + "noalias", 0, + +#define WIDTHSW 22 + "width columns", 0, + +#define LIBSW 23 + "library directory", -7, + +#define ANNOSW 24 + "idanno number", -6, + +#ifdef MIME_HEADERS +#define HENCDSW 25 + "hencode", 0, +#define NHENCDSW 26 + "nohencode", 0, +#endif /* MIME_HEADERS */ + + NULL, 0 +}; + +/* */ + +struct headers { + char *value; + + unsigned int flags; +#define HNOP 0x0000 /* just used to keep .set around */ +#define HBAD 0x0001 /* bad header - don't let it through */ +#define HADR 0x0002 /* header has an address field */ +#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 */ + + unsigned int set; +#define MFRM 0x0001 /* we've seen a From: */ +#define MDAT 0x0002 /* we've seen a Date: */ +#define MRFM 0x0004 /* we've seen a Resent-From: */ +#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: */ +}; + +/* */ + +static struct headers NHeaders[] = { + "Return-Path", HBAD, 0, + "Received", HBAD, 0, + "Reply-To", HADR | HNGR, 0, + "From", HADR | HNGR, 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, + "Message-Id", HBAD, 0, + "Fcc", HFCC, 0, + + NULL +}; + +static struct headers RHeaders[] = { + "Resent-Reply-To", HADR | HNGR, 0, + "Resent-From", HADR | HNGR, 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-Bcc", HADR | HTRY | HBCC, MINV, + "Resent-Message-Id", HBAD, 0, + "Resent-Fcc", HFCC, 0, + "Reply-To", HADR, 0, + "Fcc", HIGN, 0, + + NULL +}; + +/* */ + + +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 whomflg = 0; /* if just checking addresses */ +static int pushflg = 0; /* if going to fork to sendmail */ +static int aliasflg = -1; /* if going to process aliases */ +static int outputlinelen=72; +#ifdef MIME_HEADERS +static int hencode = -1; /* encode header in RFC-2047 style */ +#endif /* MIME_HEADERS */ + +static unsigned msgflags = 0; /* what we've seen */ + +static enum { + normal, resent +} msgstate = normal; + +static char tmpfil[] = "/tmp/pstXXXXXX"; + +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 struct headers *hdrtab; /* table for the message we're doing */ +static FILE *out; /* output (temp) file */ + +static putfmt(), start_headers(), finish_headers(), putadr(), + insert_fcc(); +static file(), fcc(); +static int get_header(), putone(); +/* MAIN */ + +/* ARGSUSED */ + +main (argc, argv) +int argc; +char *argv[]; +{ + int state, + i, + pid, + compnum; + char *cp, + *msg = NULL, + **argp = argv + 1, + *sargv[16], + buf[BUFSIZ], + name[NAMESZ], + *arguments[MAXARGS]; + FILE * in; + +#ifdef LOCALE + setlocale(LC_ALL, ""); +#endif +#ifdef JAPAN + ml_init(); +#endif /* JAPAN */ + invo_name = r1bindex (argv[0], '/'); + mts_init (invo_name); + if ((cp = m_find (invo_name)) != NULL) { + argp = copyip (brkstring (cp, " ", "\n"), arguments); + (void) copyip (argv+1, argp); + argp = arguments; + } + +/* */ + + while (cp = *argp++) { + if (*cp == '-') + switch (smatch (++cp, switches)) { + case AMBIGSW: + ambigsw (cp, switches); + done (1); + case UNKWNSW: + adios (NULLCP, "-%s unknown", cp); + case HELPSW: + (void)sprintf (buf, "%s [switches] file", invo_name); + help (buf, switches); + done (1); + + case DEBUGSW: + debug++; + continue; + + case DISTSW: + msgstate = resent; + continue; + + case WHOMSW: + whomflg++; + continue; + + case FILTSW: + if (!(filter = *argp++) || *filter == '-') + adios (NULLCP, "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 (NULLCP, "missing argument to %s", argp[-2]); + if (aliasflg < 0) + (void) alias (AliasFile);/* load default aka's */ + aliasflg = 1; + if ((state = alias(cp)) != AK_OK) + adios (NULLCP, "aliasing error in file %s - %s", + cp, akerror(state) ); + continue; + case NALIASW: + aliasflg = 0; + continue; + + case WIDTHSW: + if (!(cp = *argp++) || *cp == '-') + adios (NULLCP, "missing argument to %s", argp[-2]); + outputlinelen = atoi (cp); + if (outputlinelen <= 10) + outputlinelen = 72; + continue; + + case LIBSW: + case ANNOSW: + /* -library & -idanno switch ignored */ + if (!(cp = *argp++) || *cp == '-') + adios (NULLCP, "missing argument to %s", argp[-2]); + continue; +#ifdef MIME_HEADERS + case HENCDSW: + hencode = 1; + continue; + case NHENCDSW: + hencode = 0; + continue; +#endif /* MIME_HEADERS */ + } + if (msg) + adios (NULLCP, "only one message at a time!"); + else + msg = cp; + } + +/* */ + + if (aliasflg < 0) + (void) alias (AliasFile); /* load default aka's */ + + if (!msg) + adios (NULLCP, "usage: %s [switches] file", invo_name); + + if ((in = fopen (msg, "r")) == NULL) + adios (msg, "unable to open"); + +#ifdef MIME_HEADERS + if (hencode == -1) { + hencode = 0; + for (state = FLD;;) { + switch (state = m_getfld (state, name, buf, sizeof buf, in)) { + case FLD: + case FLDEOF: + case FLDPLUS: + if (uleq (name, "MIME-Version")) { + hencode = 1; + break; + } + continue; + + default: + break; + } + break; + } + (void) fseek (in, 0L, 0); + } +#endif /* MIME_HEADERS */ + + start_headers (); + if (debug) { + verbose++; + out = stdout; + } + else { + (void)mktemp (tmpfil); + if ((out = fopen (tmpfil, "w")) == NULL) + adios (tmpfil, "unable to create"); + (void)chmod (tmpfil, 0600); + } + + hdrtab = (msgstate == normal) ? NHeaders : RHeaders; + + for (compnum = 1, state = FLD;;) { + switch (state = m_getfld (state, name, buf, sizeof buf, in)) { +#if defined(JAPAN) || defined(MIME_HEADERS) + case FLD: + case FLDEOF: + case FLDPLUS: + compnum++; + cp = add (buf, NULLCP); + while (state == FLDPLUS) { + state = m_getfld (state, name, buf, sizeof buf, in); + cp = add (buf, cp); + } + putfmt (name, cp, out); + free (cp); + continue; +#else /* JAPAN || MIME_HEADERS */ + case FLD: + compnum++; + putfmt (name, buf, out); + continue; + + case FLDPLUS: + 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); + continue; +#endif /* JAPAN || MIME_HEADERS */ + + case BODY: + finish_headers (out); + fprintf (out, "\n%s", buf); + if(whomflg == 0) + while (state == BODY) { + state = m_getfld (state, name, buf, sizeof buf, in); + fputs (buf, out); + } + break; + + case FILEEOF: + finish_headers (out); + break; + + case LENERR: + case FMTERR: + adios (NULLCP, "message format error in component #%d", + compnum); + + default: + adios (NULLCP, "getfld() returned %d", state); + } + break; + } + +/* */ + + (void)fclose (in); + if (backflg && !whomflg) { + (void) strcpy (buf, m_backup (msg)); + if (rename (msg, buf) == NOTOK) + advise (buf, "unable to rename %s to", msg); + } + + if (debug) { + done (0); + } + else + (void)fclose (out); + + file (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) + adios (tmpfil, "can't reopen for sendmail"); + if (rmflg) + (void)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 (whomflg) + *argp++ = "-bv"; + if (watch || 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); + } + } + execv ( sendmail, sargv); + adios ( sendmail, "can't exec"); +} + +/* DRAFT GENERATION */ + +static putfmt (name, str, out) +char *name, + *str; +FILE * out; +{ + int count, + grp, + i, + keep; + char *cp, + *pp, + *qp, +#ifdef MIME_HEADERS + *origstr, +#endif /* MIME_HEADERS */ + namep[BUFSIZ]; + struct mailname *mp, + *np; + struct headers *hdr; + + while (*str == ' ' || *str == '\t') + str++; + +#ifdef MIME_HEADERS + if (hencode) { + char *ep; + if ((ep = malloc((unsigned)strlen(str)*10+1)) == NULL) + adios(NULLCP, "out of memory"); +#ifdef JAPAN + (void) ml_conv(str); +#endif /* JAPAN */ + (void) exthdr_encode(str, ep, strlen(name)+2, name); + origstr = str; + str = ep; + } +#endif /* MIME_HEADERS */ + + if ((i = get_header (name, hdrtab)) == NOTOK) { + fprintf (out, "%s: %s", name, str); + return; + } + + hdr = &hdrtab[i]; + if (hdr -> flags & HIGN) + return; + if (hdr -> flags & HBAD) { + advise (NULLCP, "illegal header line -- %s:", name); + badmsg++; + return; + } + msgflags |= hdr -> set; + + if (hdr -> flags & HSUB) + subject = subject ? add (str, add ("\t", subject)) : getcpy (str); + + if (hdr -> flags & HFCC) { + if (cp = rindex (str, '\n')) + *cp = 0; + for (cp = pp = str; cp = index (pp, ','); pp = cp) { + *cp++ = 0; + insert_fcc (hdr, pp); + } + insert_fcc (hdr, pp); + return; + } + +#ifdef notdef + if (hdr -> flags & HBCC) { + insert_bcc(str); + 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; + +#ifdef MIME_HEADERS + if (hencode) + /* encode again after format */ + (void) exthdr_decode(origstr, str); +#endif /* MIME_HEADERS */ + + while (cp = getname( str ) ) { + mp = getm( cp, NULLCP, 0, AD_HOST, NULLCP); + if (f == 0) { + f = mp; + mp->m_next = mp; + } else { + mp->m_next = f->m_next; + f->m_next = mp; + f = mp; + } + } + f = mp->m_next; mp->m_next = 0; + putadr( name, f ); + } else { + fprintf (out, "%s: %s", name, str ); + } +} + +/* */ + +static +start_headers () +{ + char *cp; + char sigbuf[BUFSIZ]; + + (void)strcpy( from, getusr() ); + + if ((cp = getfullname ()) && *cp) { + (void)strcpy (sigbuf, cp); + (void)sprintf (signature, "%s <%s>", sigbuf, from); +#ifdef MIME_HEADERS + if (hencode) { + char *ep; +#ifdef JAPAN + (void) ml_conv(signature); +#endif /* JAPAN */ + ep = getcpy (signature); + (void) exthdr_encode (ep, signature, 5, "From"); + free(ep); + } +#endif /* MIME_HEADERS */ + } + else + (void)sprintf (signature, "%s", from); +} + +/* */ + +static +finish_headers (out) + FILE * out; +{ + switch (msgstate) { + case normal: + if (!(msgflags & MDAT)) + fprintf (out, "Date: %s\n", dtimenow ()); + if (msgflags & MFRM) + 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()); + if (msgflags & MRFM) + fprintf (out, "Resent-Sender: %s\n", from); + else + 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 (badmsg) + adios (NULLCP, "re-format message and try again"); +} + +/* */ + +static int +get_header (header, table) + char *header; + struct headers *table; +{ + struct headers *h; + + for (h = table; h -> value; h++) + if (uleq (header, h -> value)) + return (h - table); + + return NOTOK; +} + +/* */ + +/* output the address list for header "name". The address list + * is a linked list of mailname structs. "nl" points to the head + * of the list. Alias substitution should be done on nl. + */ +static putadr (name, nl) +char *name; +struct mailname *nl; +{ + register struct mailname *mp, *mp2; + register int linepos; + register char *cp; + int namelen; + + fprintf (out, "%s: ", name); + namelen = strlen(name) + 2; + linepos = namelen; + + for (mp = nl; mp; ) { + if (linepos > MAX_SM_FIELD) { + 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 (strcmp(cp, mp->m_mbox) == 0) + /* 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, NULLCP, 0, AD_HOST, NULLCP); + 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 ); + } + } + } else { + /* not a local name - use what the user typed */ + linepos = putone( mp->m_text, linepos, namelen ); + } + mp2 = mp; + mp = mp->m_next; + mnfree( mp2 ); + } + putc( '\n', out ); +} + +static int putone ( adr, pos, indent ) +register char *adr; +register int pos; +int indent; +{ + register int len; + static int linepos; +#ifdef MIME_HEADERS + char name[BUFSIZ], *ep; + + if (hencode) { + if ((ep = malloc((unsigned)strlen(adr)*10+1)) == NULL) + adios(NULLCP, "out of memory"); + sprintf(name, "%*s", indent, ""); /* dummy */ + (void) exthdr_encode(adr, ep, pos, name); + len = strlen(ep); + } else +#endif /* MIME_HEADERS */ + len = strlen( adr ); + if (pos == indent) + linepos = pos; + else if ( linepos+len > outputlinelen ) { + fprintf ( out, ",\n%*s", indent, ""); +#ifdef MIME_HEADERS + if (hencode) { + (void) exthdr_encode(adr, ep, linepos, name); + len = strlen(ep); + } +#endif /* MIME_HEADERS */ + linepos = indent; + pos += indent + 2; + } + else { + fputs( ", ", out ); + linepos += 2; + pos += 2; + } +#ifdef MIME_HEADERS + if (hencode) { + char *p; + fputs(ep, out); + linepos = (p = rindex(ep, '\n')) ? (ep + len) - (p+1) : linepos + len; + free(ep); + } else { + fputs(adr, out); + linepos += len; + } +#else /* MIME_HEADERS */ + fputs( adr, out ); + + linepos += len; +#endif /* MIME_HEADERS */ + return (pos+len); +} + +/* */ + +static insert_fcc (hdr, pp) +struct headers *hdr; +char *pp; +{ + 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 (NULLCP, "too many %ss", hdr -> value); + fccfold[fccind++] = getcpy (cp); +} + +#ifdef notdef +/* BCC GENERATION */ + +static make_bcc_file () { + int fd, + i, + child_id, + status; + char *vec[6]; + FILE * in, *out; + + (void)mktemp (bccfil); + if ((out = fopen (bccfil, "w")) == NULL) + adios (bccfil, "unable to create"); + (void)chmod (bccfil, 0600); + + fprintf (out, "Date: %s\n", dtimenow ()); + fprintf (out, "From: %s\n", signature); + if (subject) + fprintf (out, "Subject: %s", subject); + fprintf (out, "BCC:\n\n------- Blind-Carbon-Copy\n\n"); + (void)fflush (out); + + if (filter == NULL) { + if ((fd = open (tmpfil, 0)) == NOTOK) + adios (NULLCP, "unable to re-open"); + cpydgst (fd, fileno (out), tmpfil, bccfil); + close (fd); + } + else { + vec[0] = r1bindex (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"); + + default: + if (status = pidwait (child_id, OK)) + admonish (NULL, "%s lost (status=0%o)", vec[0], status); + break; + } + } + + fseek (out, 0L, 2); + fprintf (out, "\n------- End of Blind-Carbon-Copy\n"); + (void)fclose (out); +} +#endif /* notdef */ + +/* FCC INTERACTION */ + +static file (path) +char *path; +{ + int i; + + if (fccind == 0) + return; + + for (i = 0; i < fccind; i++) + if (whomflg) + printf ("Fcc: %s\n", fccfold[i]); + else + fcc (path, fccfold[i]); +} + + +static fcc (file, folder) +char *file, + *folder; +{ + int i, + child_id, + status; + char fold[BUFSIZ]; + + if (verbose) + printf ("%sFcc: %s\n", msgstate == resent ? "Resent-" : "", folder); + (void)fflush (stdout); + + for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++) + sleep (5); + switch (child_id) { + case NOTOK: + if (!verbose) + fprintf (stderr, " %sFcc %s: ", + msgstate == resent ? "Resent-" : "", folder); + fprintf (verbose ? stdout : stderr, "no forks, so not ok\n"); + break; + + case OK: + (void)sprintf (fold, "%s%s", + *folder == '+' || *folder == '@' ? "" : "+", folder); + execlp (fileproc, r1bindex (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); + } + } + + (void)fflush (stdout); +} + +/* TERMINATION */ + +/* VARARGS2 */ + +static die (what, fmt, a, b, c, d) +char *what, + *fmt, + *a, + *b, + *c, + *d; +{ + adios (what, fmt, a, b, c, d); +}