Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / uip / spost.c
1 #ifndef lint
2 static char sccsid[] = "@(#)spost.c     1.6 (Berkeley) 11/2/85";
3 #endif
4 #ifndef lint
5 static char ident[] = "@(#)$Id: spost.c,v 1.8 1992/12/15 00:20:22 jromine Exp $";
6 #endif  /* lint */
7
8 /* spost.c - feed messages to sendmail */
9 /*
10  * (This is a simpler, faster, replacement for "post" for use when "sendmail"
11  * is the transport system) 
12  */
13
14 #include <ctype.h>
15 #include <stdio.h>
16 #include <signal.h>
17 #include "../h/mh.h"
18 #include "../h/addrsbr.h"
19 #include "../h/aliasbr.h"
20 #include "../h/dropsbr.h"
21 #include "../zotnet/tws.h"
22 #ifdef LOCALE
23 #include        <locale.h>
24 #endif
25
26 extern char *getfullname (), *getusr ();
27 extern char *sendmail;
28
29
30 #define uptolow(c)      ((isalpha(c) && isupper (c)) ? tolower (c) : c)
31
32 #define MAX_SM_FIELD    1476    /* < largest hdr field sendmail will accept */
33 #define FCCS            10      /* max number of fccs allowed */
34
35 /* \f */
36
37 struct swit switches[] = {
38 #define FILTSW  0
39     "filter filterfile", 0,
40 #define NFILTSW 1
41     "nofilter", 0,
42
43 #define FRMTSW  2
44     "format", 0,
45 #define NFRMTSW 3
46     "noformat", 0,
47
48 #define REMVSW  4
49     "remove", 0,
50 #define NREMVSW 5
51     "noremove", 0,
52
53 #define VERBSW  6
54     "verbose", 0,
55 #define NVERBSW 7
56     "noverbose", 0,
57
58 #define WATCSW  8
59     "watch", 0,
60 #define NWATCSW 9
61     "nowatch", 0,
62
63 #define HELPSW  10
64     "help", 4,
65
66 #define DEBUGSW 11
67     "debug", -5,
68
69 #define DISTSW  12
70     "dist", -4,                 /* interface from dist */
71
72 #define BACKSW 13
73     "backup", 0,
74 #define NBACKSW 14
75     "nobackup", 0,
76
77 #define CHKSW 15
78     "check", -5,                /* interface from whom */
79 #define NCHKSW 16
80     "nocheck", -7,              /* interface from whom */
81 #define WHOMSW 17
82     "whom", -4,                 /* interface from whom */
83
84 #define PUSHSW 18               /* fork to sendmail then exit */
85     "push", -4,
86 #define NPUSHSW 19              /* exec sendmail */
87     "nopush", -6,
88
89 #define ALIASW 20
90     "alias aliasfile", 0,
91 #define NALIASW 21
92     "noalias", 0,
93
94 #define WIDTHSW 22
95     "width columns", 0,
96
97 #define LIBSW 23
98     "library directory", -7,
99
100 #define ANNOSW  24
101     "idanno number", -6,
102
103     NULL, 0
104 };
105
106 /* \f */
107
108 struct headers {
109     char   *value;
110
111     unsigned int    flags;
112 #define HNOP    0x0000          /* just used to keep .set around */
113 #define HBAD    0x0001          /* bad header - don't let it through */
114 #define HADR    0x0002          /* header has an address field */
115 #define HSUB    0x0004          /* Subject: header */
116 #define HTRY    0x0008          /* try to send to addrs on header */
117 #define HBCC    0x0010          /* don't output this header */
118 #define HMNG    0x0020          /* mung this header */
119 #define HNGR    0x0040          /* no groups allowed in this header */
120 #define HFCC    0x0080          /* FCC: type header */
121 #define HNIL    0x0100          /* okay for this header not to have addrs */
122 #define HIGN    0x0200          /* ignore this header */
123
124     unsigned int    set;
125 #define MFRM    0x0001          /* we've seen a From: */
126 #define MDAT    0x0002          /* we've seen a Date: */
127 #define MRFM    0x0004          /* we've seen a Resent-From: */
128 #define MVIS    0x0008          /* we've seen sighted addrs */
129 #define MINV    0x0010          /* we've seen blind addrs */
130 #define MRDT    0x0020          /* we've seen a Resent-Date: */
131 };
132
133 /* \f */
134
135 static struct headers  NHeaders[] = {
136     "Return-Path", HBAD, 0,
137     "Received", HBAD, 0,
138     "Reply-To", HADR | HNGR, 0,
139     "From", HADR | HNGR, MFRM,
140     "Sender", HADR | HBAD, 0,
141     "Date", HNOP, MDAT,
142     "Subject", HSUB, 0,
143     "To", HADR | HTRY, MVIS,
144     "cc", HADR | HTRY, MVIS,
145     "Bcc", HADR | HTRY | HBCC | HNIL, MINV,
146     "Message-Id", HBAD, 0,
147     "Fcc", HFCC, 0,
148
149     NULL
150 };
151
152 static struct headers  RHeaders[] = {
153     "Resent-Reply-To", HADR | HNGR, 0,
154     "Resent-From", HADR | HNGR, MRFM,
155     "Resent-Sender", HADR | HBAD, 0,
156     "Resent-Date", HNOP, MRDT,
157     "Resent-Subject", HSUB, 0,
158     "Resent-To", HADR | HTRY, MVIS,
159     "Resent-cc", HADR | HTRY, MVIS,
160     "Resent-Bcc", HADR | HTRY | HBCC, MINV,
161     "Resent-Message-Id", HBAD, 0,
162     "Resent-Fcc", HFCC, 0,
163     "Reply-To", HADR, 0,
164     "Fcc", HIGN, 0,
165
166     NULL
167 };
168
169 /* \f */
170
171
172 static short    fccind = 0;     /* index into fccfold[] */
173
174 static int  badmsg = 0;         /* message has bad semantics */
175 static int  verbose = 0;        /* spell it out */
176 static int  debug = 0;          /* debugging post */
177 static int  rmflg = 1;          /* remove temporary file when done */
178 static int  watch = 0;          /* watch the delivery process */
179 static int  backflg = 0;        /* rename input file as *.bak when done */
180 static int  whomflg = 0;        /* if just checking addresses */
181 static int  pushflg = 0;        /* if going to fork to sendmail */
182 static int  aliasflg = -1;      /* if going to process aliases */
183 static int  outputlinelen=72;
184
185 static unsigned msgflags = 0;   /* what we've seen */
186
187 static enum {
188     normal, resent
189 } msgstate = normal;
190
191 static char tmpfil[] = "/tmp/pstXXXXXX";
192
193 static char from[BUFSIZ];       /* my network address */
194 static char signature[BUFSIZ];  /* my signature */
195 static char *filter = NULL;     /* the filter for BCC'ing */
196 static char *subject = NULL;    /* the subject field for BCC'ing */
197 static char *fccfold[FCCS];     /* foldernames for FCC'ing */
198
199 static struct headers  *hdrtab; /* table for the message we're doing */
200 static FILE *out;               /* output (temp) file */
201
202 static  putfmt(), start_headers(), finish_headers(), putadr(),
203         insert_fcc();
204 static  file(), fcc();
205 static int      get_header(), putone();
206 /* \f   MAIN */
207
208 /* ARGSUSED */
209
210 main (argc, argv)
211 int     argc;
212 char   *argv[];
213 {
214     int     state,
215             i,
216             pid,
217             compnum;
218     char   *cp,
219            *msg = NULL,
220           **argp = argv + 1,
221             *sargv[16],
222             buf[BUFSIZ],
223             name[NAMESZ],
224             *arguments[MAXARGS];
225     FILE * in;
226
227 #ifdef LOCALE
228         setlocale(LC_ALL, "");
229 #endif
230     invo_name = r1bindex (argv[0], '/');
231     mts_init (invo_name);
232     if ((cp = m_find (invo_name)) != NULL) {
233         argp = copyip (brkstring (cp, " ", "\n"), arguments);
234         (void) copyip (argv+1, argp);
235         argp = arguments;
236     }
237
238 /* \f */
239
240     while (cp = *argp++) {
241         if (*cp == '-')
242             switch (smatch (++cp, switches)) {
243                 case AMBIGSW: 
244                     ambigsw (cp, switches);
245                     done (1);
246                 case UNKWNSW: 
247                     adios (NULLCP, "-%s unknown", cp);
248                 case HELPSW: 
249                     (void)sprintf (buf, "%s [switches] file", invo_name);
250                     help (buf, switches);
251                     done (1);
252
253                 case DEBUGSW: 
254                     debug++;
255                     continue;
256
257                 case DISTSW:
258                     msgstate = resent;
259                     continue;
260
261                 case WHOMSW:
262                     whomflg++;
263                     continue;
264
265                 case FILTSW:
266                     if (!(filter = *argp++) || *filter == '-')
267                         adios (NULLCP, "missing argument to %s", argp[-2]);
268                     continue;
269                 case NFILTSW:
270                     filter = NULL;
271                     continue;
272                 
273                 case REMVSW: 
274                     rmflg++;
275                     continue;
276                 case NREMVSW: 
277                     rmflg = 0;
278                     continue;
279
280                 case BACKSW: 
281                     backflg++;
282                     continue;
283                 case NBACKSW: 
284                     backflg = 0;
285                     continue;
286
287                 case VERBSW: 
288                     verbose++;
289                     continue;
290                 case NVERBSW: 
291                     verbose = 0;
292                     continue;
293
294                 case WATCSW: 
295                     watch++;
296                     continue;
297                 case NWATCSW: 
298                     watch = 0;
299                     continue;
300                 
301                 case PUSHSW:
302                     pushflg++;
303                     continue;
304                 case NPUSHSW:
305                     pushflg = 0;
306                     continue;
307
308                 case ALIASW:
309                     if (!(cp = *argp++) || *cp == '-')
310                         adios (NULLCP, "missing argument to %s", argp[-2]);
311                     if (aliasflg < 0)
312                         (void) alias (AliasFile);/* load default aka's */
313                     aliasflg = 1;
314                     if ((state = alias(cp)) != AK_OK)
315                         adios (NULLCP, "aliasing error in file %s - %s",
316                                cp, akerror(state) );
317                     continue;
318                 case NALIASW:
319                     aliasflg = 0;
320                     continue;
321
322                 case WIDTHSW:
323                     if (!(cp = *argp++) || *cp == '-')
324                         adios (NULLCP, "missing argument to %s", argp[-2]);
325                     outputlinelen = atoi (cp);
326                     if (outputlinelen <= 10)
327                         outputlinelen = 72;
328                     continue;
329
330                 case LIBSW:
331                 case ANNOSW:
332                     /* -library & -idanno switch ignored */
333                     if (!(cp = *argp++) || *cp == '-')
334                         adios (NULLCP, "missing argument to %s", argp[-2]);
335                     continue;
336             }
337         if (msg)
338             adios (NULLCP, "only one message at a time!");
339         else
340             msg = cp;
341     }
342
343 /* \f */
344
345     if (aliasflg < 0)
346         (void) alias (AliasFile);       /* load default aka's */
347
348     if (!msg)
349         adios (NULLCP, "usage: %s [switches] file", invo_name);
350
351     if ((in = fopen (msg, "r")) == NULL)
352         adios (msg, "unable to open");
353
354     start_headers ();
355     if (debug) {
356         verbose++;
357         out = stdout;
358     }
359     else {
360             (void)mktemp (tmpfil);
361             if ((out = fopen (tmpfil, "w")) == NULL)
362                 adios (tmpfil, "unable to create");
363             (void)chmod (tmpfil, 0600);
364         }
365
366     hdrtab = (msgstate == normal) ? NHeaders : RHeaders;
367
368     for (compnum = 1, state = FLD;;) {
369         switch (state = m_getfld (state, name, buf, sizeof buf, in)) {
370             case FLD: 
371                 compnum++;
372                 putfmt (name, buf, out);
373                 continue;
374
375             case FLDPLUS: 
376                 compnum++;
377                 cp = add (buf, cp);
378                 while (state == FLDPLUS) {
379                     state = m_getfld (state, name, buf, sizeof buf, in);
380                     cp = add (buf, cp);
381                 }
382                 putfmt (name, cp, out);
383                 free (cp);
384                 continue;
385
386             case BODY: 
387                 finish_headers (out);
388                 fprintf (out, "\n%s", buf);
389                 if(whomflg == 0)
390                     while (state == BODY) {
391                         state = m_getfld (state, name, buf, sizeof buf, in);
392                         fputs (buf, out);
393                     }
394                 break;
395
396             case FILEEOF: 
397                 finish_headers (out);
398                 break;
399
400             case LENERR: 
401             case FMTERR: 
402                 adios (NULLCP, "message format error in component #%d",
403                         compnum);
404
405             default: 
406                 adios (NULLCP, "getfld() returned %d", state);
407         }
408         break;
409     }
410
411 /* \f */
412
413     (void)fclose (in);
414     if (backflg && !whomflg) {
415         (void) strcpy (buf, m_backup (msg));
416         if (rename (msg, buf) == NOTOK)
417             advise (buf, "unable to rename %s to", msg);
418     }
419
420     if (debug) {
421         done (0);
422     }
423     else
424         (void)fclose (out);
425
426     file (tmpfil);
427
428     /*
429      * re-open the temp file, unlink it and exec sendmail, giving it
430      * the msg temp file as std in.
431      */
432     if ( freopen( tmpfil, "r", stdin) == NULL)
433         adios (tmpfil, "can't reopen for sendmail");
434     if (rmflg)
435         (void)unlink (tmpfil);
436
437     argp = sargv;
438     *argp++ = "send-mail";
439     *argp++ = "-m";     /* send to me too */
440     *argp++ = "-t";     /* read msg for recipients */
441     *argp++ = "-i";     /* don't stop on "." */
442     if (whomflg)
443         *argp++ = "-bv";
444     if (watch || verbose)
445         *argp++ = "-v";
446     *argp = NULL;
447
448     if (pushflg && !(watch || verbose)) {
449         /* fork to a child to run sendmail */
450         for (i=0; (pid = vfork()) == NOTOK && i < 5; i++)
451             sleep(5);
452         switch (pid) {
453             case NOTOK:
454                 fprintf (verbose ? stdout : stderr, "%s: can't fork to %s\n",
455                          invo_name, sendmail);
456                 exit(-1);
457             case OK:
458                 /* we're the child .. */
459                 break;
460             default:
461                 exit(0);
462         }
463     }
464     execv ( sendmail, sargv);
465     adios ( sendmail, "can't exec");
466 }
467
468 /* \f   DRAFT GENERATION */
469
470 static putfmt (name, str, out)
471 char   *name,
472        *str;
473 FILE * out;
474 {
475     int     count,
476             grp,
477             i,
478             keep;
479     char   *cp,
480            *pp,
481            *qp,
482             namep[BUFSIZ];
483     struct mailname *mp,
484                    *np;
485     struct headers *hdr;
486
487     while (*str == ' ' || *str == '\t')
488         str++;
489
490     if ((i = get_header (name, hdrtab)) == NOTOK) {
491         fprintf (out, "%s: %s", name, str);
492         return;
493     }
494
495     hdr = &hdrtab[i];
496     if (hdr -> flags & HIGN)
497         return;
498     if (hdr -> flags & HBAD) {
499         advise (NULLCP, "illegal header line -- %s:", name);
500         badmsg++;
501         return;
502     }
503     msgflags |= hdr -> set;
504
505     if (hdr -> flags & HSUB)
506         subject = subject ? add (str, add ("\t", subject)) : getcpy (str);
507
508     if (hdr -> flags & HFCC) {
509         if (cp = rindex (str, '\n'))
510             *cp = 0;
511         for (cp = pp = str; cp = index (pp, ','); pp = cp) {
512             *cp++ = 0;
513             insert_fcc (hdr, pp);
514         }
515         insert_fcc (hdr, pp);
516         return;
517     }
518
519 #ifdef notdef
520     if (hdr -> flags & HBCC) {
521         insert_bcc(str);
522         return;
523     }
524 #endif  /* notdef */
525
526     if (*str != '\n' && *str != '\0')
527         if (aliasflg && hdr->flags & HTRY) {
528             /* this header contains address(es) that we have to do
529              * alias expansion on.  Because of the saved state in
530              * getname we have to put all the addresses into a list.
531              * We then let putadr munch on that list, possibly
532              * expanding aliases.
533              */
534             register struct mailname *f = 0;
535             register struct mailname *mp = 0;
536
537             while (cp = getname( str ) ) {
538                 mp = getm( cp, NULLCP, 0, AD_HOST, NULLCP);
539                 if (f == 0) {
540                     f = mp;
541                     mp->m_next = mp;
542                 } else {
543                     mp->m_next = f->m_next;
544                     f->m_next = mp;
545                     f = mp;
546                 }
547             }
548             f = mp->m_next; mp->m_next = 0;
549             putadr( name, f );
550         } else {
551             fprintf (out, "%s: %s", name, str );
552         }
553 }
554
555 /* \f */
556
557 static
558 start_headers ()
559 {
560     char   *cp;
561     char    sigbuf[BUFSIZ];
562
563     (void)strcpy( from, getusr() );
564
565     if ((cp = getfullname ()) && *cp) {
566         (void)strcpy (sigbuf, cp);
567         (void)sprintf (signature, "%s <%s>", sigbuf,  from);
568     }
569     else
570         (void)sprintf (signature, "%s",  from);
571 }
572
573 /* \f */
574
575 static
576 finish_headers (out)
577     FILE * out;
578 {
579     switch (msgstate) {
580         case normal: 
581             if (!(msgflags & MDAT))
582                 fprintf (out, "Date: %s\n", dtimenow ());
583             if (msgflags & MFRM)
584                 fprintf (out, "Sender: %s\n", from);
585             else
586                 fprintf (out, "From: %s\n", signature);
587 #ifdef notdef
588             if (!(msgflags & MVIS))
589                 fprintf (out, "Bcc: Blind Distribution List: ;\n");
590 #endif  /* notdef */
591             break;
592
593         case resent: 
594             if (!(msgflags & MRDT))
595                 fprintf (out, "Resent-Date: %s\n", dtimenow());
596             if (msgflags & MRFM)
597                 fprintf (out, "Resent-Sender: %s\n", from);
598             else
599                 fprintf (out, "Resent-From: %s\n", signature);
600 #ifdef notdef
601             if (!(msgflags & MVIS))
602                 fprintf (out, "Resent-Bcc: Blind Re-Distribution List: ;\n");
603 #endif  /* notdef */
604             break;
605     }
606
607     if (badmsg)
608         adios (NULLCP, "re-format message and try again");
609 }
610
611 /* \f */
612
613 static int
614 get_header (header, table)
615     char   *header;
616     struct headers *table;
617 {
618     struct headers *h;
619
620     for (h = table; h -> value; h++)
621         if (uleq (header, h -> value))
622             return (h - table);
623
624     return NOTOK;
625 }
626
627 /* \f */
628
629 /* output the address list for header "name".  The address list
630  * is a linked list of mailname structs.  "nl" points to the head
631  * of the list.  Alias substitution should be done on nl.
632  */
633 static putadr (name, nl)
634 char *name;
635 struct mailname *nl;
636 {
637     register struct mailname *mp, *mp2;
638     register int linepos;
639     register char *cp;
640     int namelen;
641
642     fprintf (out, "%s: ", name);
643     namelen = strlen(name) + 2;
644     linepos = namelen;
645
646     for (mp = nl; mp; ) {
647         if (linepos > MAX_SM_FIELD) {
648                 fprintf (out, "\n%s: ", name);
649                 linepos = namelen;
650         }
651         if (mp->m_nohost) {
652             /* a local name - see if it's an alias */
653             cp = akvalue(mp->m_mbox);
654             if (cp == mp->m_mbox)
655                 /* wasn't an alias - use what the user typed */
656                 linepos = putone( mp->m_text, linepos, namelen );
657             else
658                 /* an alias - expand it */
659                 while (cp = getname(cp) ) {
660                     if (linepos > MAX_SM_FIELD) {
661                             fprintf (out, "\n%s: ", name);
662                             linepos = namelen;
663                     }
664                     mp2 = getm( cp, NULLCP, 0, AD_HOST, NULLCP);
665                     if (akvisible()) {
666                         mp2->m_pers = getcpy(mp->m_mbox);
667                         linepos = putone( adrformat(mp2), linepos, namelen );
668                     } else {
669                         linepos = putone( mp2->m_text, linepos, namelen );
670                     }
671                     mnfree( mp2 );
672                 }
673         } else {
674             /* not a local name - use what the user typed */
675             linepos = putone( mp->m_text, linepos, namelen );
676         }
677         mp2 = mp;
678         mp = mp->m_next;
679         mnfree( mp2 );
680     }
681     putc( '\n', out );
682 }
683
684 static int putone ( adr, pos, indent )
685 register char *adr;
686 register int pos;
687 int indent;
688 {
689     register int len;
690     static int linepos;
691
692     len = strlen( adr );
693     if (pos == indent)
694         linepos = pos;
695     else if ( linepos+len > outputlinelen ) {
696         fprintf ( out, ",\n%*s", indent, "");
697         linepos = indent;
698         pos += indent + 2;
699     }
700     else {
701         fputs( ", ", out );
702         linepos += 2;
703         pos += 2;
704     }
705     fputs( adr, out );
706
707     linepos += len;
708     return (pos+len);
709 }
710
711 /* \f */
712
713 static  insert_fcc (hdr, pp)
714 struct  headers *hdr;
715 char   *pp;
716 {
717     char   *cp;
718
719     for (cp = pp; isspace (*cp); cp++)
720         continue;
721     for (pp += strlen (pp) - 1; pp > cp && isspace (*pp); pp--)
722         continue;
723     if (pp >= cp)
724         *++pp = 0;
725     if (*cp == 0)
726         return;
727
728     if (fccind >= FCCS)
729         adios (NULLCP, "too many %ss", hdr -> value);
730     fccfold[fccind++] = getcpy (cp);
731 }
732
733 #ifdef notdef
734 /* \f   BCC GENERATION */
735
736 static  make_bcc_file () {
737     int     fd,
738             i,
739             child_id,
740             status;
741     char   *vec[6];
742     FILE * in, *out;
743
744     (void)mktemp (bccfil);
745     if ((out = fopen (bccfil, "w")) == NULL)
746         adios (bccfil, "unable to create");
747     (void)chmod (bccfil, 0600);
748
749     fprintf (out, "Date: %s\n", dtimenow ());
750     fprintf (out, "From: %s\n", signature);
751     if (subject)
752         fprintf (out, "Subject: %s", subject);
753     fprintf (out, "BCC:\n\n------- Blind-Carbon-Copy\n\n");
754     (void)fflush (out);
755
756     if (filter == NULL) {
757         if ((fd = open (tmpfil, 0)) == NOTOK)
758             adios (NULLCP, "unable to re-open");
759         cpydgst (fd, fileno (out), tmpfil, bccfil);
760         close (fd);
761     }
762     else {
763         vec[0] = r1bindex (mhlproc, '/');
764
765         for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
766             sleep (5);
767         switch (child_id) {
768             case NOTOK: 
769                 adios ("vfork", "unable to");
770
771             case OK: 
772                 dup2 (fileno (out), 1);
773
774                 i = 1;
775                 vec[i++] = "-forward";
776                 vec[i++] = "-form";
777                 vec[i++] = filter;
778                 vec[i++] = tmpfil;
779                 vec[i] = NULL;
780
781                 execvp (mhlproc, vec);
782                 adios (mhlproc, "unable to exec");
783
784             default: 
785                 if (status = pidwait (child_id, OK))
786                     admonish (NULL, "%s lost (status=0%o)", vec[0], status);
787                 break;
788         }
789     }
790
791     fseek (out, 0L, 2);
792     fprintf (out, "\n------- End of Blind-Carbon-Copy\n");
793     (void)fclose (out);
794 }
795 #endif  /* notdef */
796
797 /* \f   FCC INTERACTION */
798
799 static  file (path)
800 char   *path;
801 {
802     int     i;
803
804     if (fccind == 0)
805         return;
806
807     for (i = 0; i < fccind; i++)
808         if (whomflg)
809             printf ("Fcc: %s\n", fccfold[i]);
810         else
811             fcc (path, fccfold[i]);
812 }
813
814
815 static fcc (file, folder)
816 char   *file,
817        *folder;
818 {
819     int     i,
820             child_id,
821             status;
822     char    fold[BUFSIZ];
823
824     if (verbose)
825         printf ("%sFcc: %s\n", msgstate == resent ? "Resent-" : "", folder);
826     (void)fflush (stdout);
827
828     for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
829         sleep (5);
830     switch (child_id) {
831         case NOTOK: 
832             if (!verbose)
833                 fprintf (stderr, "  %sFcc %s: ",
834                         msgstate == resent ? "Resent-" : "", folder);
835             fprintf (verbose ? stdout : stderr, "no forks, so not ok\n");
836             break;
837
838         case OK: 
839             (void)sprintf (fold, "%s%s",
840                     *folder == '+' || *folder == '@' ? "" : "+", folder);
841             execlp (fileproc, r1bindex (fileproc, '/'),
842                     "-link", "-file", file, fold, NULL);
843             _exit (-1);
844
845         default: 
846             if (status = pidwait (child_id, OK)) {
847                 if (!verbose)
848                     fprintf (stderr, "  %sFcc %s: ",
849                             msgstate == resent ? "Resent-" : "", folder);
850                 fprintf (verbose ? stdout : stderr,
851                         " errored (0%o)\n", status);
852             }
853     }
854
855     (void)fflush (stdout);
856 }
857
858 /* \f   TERMINATION */
859
860 /* VARARGS2 */
861
862 static die (what, fmt, a, b, c, d)
863 char   *what,
864        *fmt,
865        *a,
866        *b,
867        *c,
868        *d;
869 {
870     adios (what, fmt, a, b, c, d);
871 }