Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / uip / whatnowsbr.c
1 /* whatnowsbr.c - the WhatNow shell */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: whatnowsbr.c,v 1.24 1995/12/06 21:04:47 jromine Exp $";
4 #endif  /* lint */
5
6 #include "../h/mh.h"
7 #include <stdio.h>
8 #include <signal.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11
12 #ifndef MIME
13 #define MIMEminc(a)     (a)
14 #else
15 #define MIMEminc(a)     0
16 #endif
17
18 static int      editfile(), copyf(), sendfile(), sendit(), whomfile();
19 #ifdef  MIME
20 static int      mhnfile();
21 #endif
22 /* \f */
23
24 static struct swit whatnowswitches[] = {
25 #define DFOLDSW 0
26     "draftfolder +folder", 0,
27 #define DMSGSW  1
28     "draftmessage msg", 0,
29 #define NDFLDSW 2
30     "nodraftfolder", 0,
31
32 #define EDITRSW 3
33     "editor editor", 0,
34 #define NEDITSW 4
35     "noedit", 0,
36
37 #define PRMPTSW 5
38     "prompt string", 4,
39
40 #define HELPSW  6
41     "help", 4,
42
43     NULL, 0
44 };
45
46 /* \f */
47
48 static struct swit aleqs[] = {
49 #define DISPSW  0
50     "display [<switches>]", 0,
51 #define EDITSW  1
52     "edit [<editor> <switches>]", 0,
53 #define LISTSW  2
54     "list [<switches>]", 0,
55 #define PUSHSW  3
56     "push [<switches>]", 0,
57 #define QUITSW  4
58     "quit [-delete]", 0,
59 #define REFILEOPT 5
60     "refile [<switches>] +folder", 0,
61 #define SENDSW  6
62     "send [<switches>]", 0,
63 #define WHOMSW  7
64     "whom [<switches>]", 0,
65
66     NULL, 0
67 };
68
69 /* \f */
70
71 static char *myprompt = "\nWhat now? ";
72
73 /* \f */
74
75 /* ARGSUSED */
76
77 int     WhatNow (argc, argv)
78 int     argc;
79 char  **argv;
80 {
81     int     isdf = 0,
82             nedit = 0,
83             use = 0;
84     char   *cp,
85            *dfolder = NULL,
86            *dmsg = NULL,
87            *ed = NULL,
88            *drft = NULL,
89            *msgnam = NULL,
90             buf[100],
91             prompt[BUFSIZ],
92           **ap,
93           **argp,
94            *arguments[MAXARGS];
95     struct stat st;
96
97     invo_name = r1bindex (argv[0], '/');
98     if ((cp = m_find (invo_name)) != NULL) {
99         ap = brkstring (cp = getcpy (cp), " ", "\n");
100         ap = copyip (ap, arguments);
101     }
102     else
103         ap = arguments;
104     (void) copyip (argv + 1, ap);
105     argp = arguments;
106
107 /* \f */
108
109     while (cp = *argp++) {
110         if (*cp == '-')
111             switch (smatch (++cp, whatnowswitches)) {
112                 case AMBIGSW: 
113                     ambigsw (cp, whatnowswitches);
114                     done (1);
115                 case UNKWNSW: 
116                     adios (NULLCP, "-%s unknown", cp);
117                 case HELPSW: 
118                     (void) sprintf (buf, "%s [switches] [file]", invo_name);
119                     help (buf, whatnowswitches);
120                     done (1);
121
122                 case DFOLDSW: 
123                     if (dfolder)
124                         adios (NULLCP, "only one draft folder at a time!");
125                     if (!(cp = *argp++) || *cp == '-')
126                         adios (NULLCP, "missing argument to %s", argp[-2]);
127                     dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp,
128                             *cp != '@' ? TFOLDER : TSUBCWF);
129                     continue;
130                 case DMSGSW: 
131                     if (dmsg)
132                         adios (NULLCP, "only one draft message at a time!");
133                     if (!(dmsg = *argp++) || *dmsg == '-')
134                         adios (NULLCP, "missing argument to %s", argp[-2]);
135                     continue;
136                 case NDFLDSW: 
137                     dfolder = NULL;
138                     isdf = NOTOK;
139                     continue;
140
141                 case EDITRSW: 
142                     if (!(ed = *argp++) || *ed == '-')
143                         adios (NULLCP, "missing argument to %s", argp[-2]);
144                     nedit = 0;
145                     continue;
146                 case NEDITSW: 
147                     nedit++;
148                     continue;
149
150                 case PRMPTSW:
151                     if (!(myprompt = *argp++) || *myprompt == '-')
152                         adios (NULLCP, "missing argument to %s", argp[-2]);
153                     continue;
154             }
155         if (drft)
156             adios (NULLCP, "only one draft at a time!");
157         else
158             drft = cp;
159     }
160
161 /* \f */
162
163     if (drft == NULL && (drft = getenv ("mhdraft")) == NULL || *drft == 0)
164         drft = getcpy (m_draft (dfolder, dmsg, 1, &isdf));
165     msgnam = (cp = getenv ("mhaltmsg")) && *cp ? getcpy (cp) : NULLCP;
166     if (ed == NULL && ((ed = getenv ("mheditor")) == NULL || *ed == 0))
167         ed = NULL, nedit++;
168     if ((cp = getenv ("mhuse")) && *cp)
169         use = atoi (cp);
170     if (!nedit
171             && editfile (&ed, NULLVP, drft, use, NULLMP, msgnam, NULLCP) < 0)
172         done (1);
173
174 /* \f */
175
176     (void) sprintf (prompt, myprompt, invo_name);
177     for (;;) {
178         if (!(argp = getans (prompt, aleqs))) {
179             (void) unlink (LINK);
180             done (1);
181         }
182         switch (smatch (*argp, aleqs)) {
183             case DISPSW: 
184                 if (msgnam)
185                     (void) showfile (++argp, msgnam);
186                 else
187                     advise (NULLCP, "no alternate message to display");
188                 break;
189
190             case EDITSW: 
191                 if (*++argp)
192                     ed = *argp++;
193                 if (editfile (&ed, argp, drft, NOUSE, NULLMP, msgnam, NULLCP)
194                         == NOTOK)
195                     done (1);
196                 break;
197
198             case LISTSW: 
199                 (void) showfile (++argp, drft);
200                 break;
201
202             case WHOMSW: 
203                 (void) whomfile (++argp, drft);
204                 break;
205
206             case QUITSW: 
207                 if (*++argp && (*argp[0] == 'd' ||
208                             ((*argp)[0] == '-' && (*argp)[1] == 'd'))) {
209                     if (unlink (drft) == NOTOK)
210                         adios (drft, "unable to unlink");
211                 }
212                 else
213                     if (stat (drft, &st) != NOTOK)
214                         advise (NULLCP, "draft left on %s", drft);
215                 done (1);
216
217             case PUSHSW: 
218                 if (sendfile (++argp, drft, 1))
219                     done (1);
220                 break;
221
222             case SENDSW: 
223                 (void) sendfile (++argp, drft, 0);
224                 break;
225
226             case REFILEOPT: 
227                 if (refile (++argp, drft) == 0)
228                     done (0);
229                 break;
230
231             default: 
232                 advise (NULLCP, "say what?");
233                 break;
234         }
235     }
236     /*NOTREACHED*/
237 }
238
239 /* \f   EDIT */
240
241 static int  reedit = 0;
242 static char *edsave = NULL;
243
244
245 /* ARGSUSED */
246
247 static  int editfile (ed, arg, file, use, mp, altmsg, cwd)
248 register struct msgs   *mp;
249 register char **ed,
250               **arg,
251                *file,
252                *altmsg,
253                *cwd;
254 register int    use;
255 {
256     int     pid,
257             status;
258     register int    vecp;
259     register char  *cp;
260     char    altpath[BUFSIZ],
261             linkpath[BUFSIZ],
262            *vec[MAXARGS];
263     struct stat st;
264 #ifdef BSD42
265 #ifdef  notdef
266     int     oumask;     /* PJS: for setting permissions on symlinks. */
267 #endif
268     int     slinked;
269 #endif  /* BSD42 */
270
271     if (!reedit) {              /* set initial editor */
272         if (*ed == NULL && (*ed = m_find ("editor")) == NULL)
273             *ed = sysed;
274     }
275     else
276         if (!*ed) {             /* no explicit editor */
277             *ed = edsave;
278             if ((cp = r1bindex (*ed, '/')) == NULL)
279                 cp = *ed;
280             cp = concat (cp, "-next", NULLCP);
281             if ((cp = m_find (cp)) != NULL)
282                 *ed = cp;
283         }
284
285     if (altmsg) {
286         if (mp == NULL || *altmsg == '/' || cwd == NULL)
287             (void) strcpy (altpath, altmsg);
288         else
289             (void) sprintf (altpath, "%s/%s", mp -> foldpath, altmsg);
290         if (cwd == NULL)
291             (void) strcpy (linkpath, LINK);
292         else
293             (void) sprintf (linkpath, "%s/%s", cwd, LINK);
294     }
295
296     if (altmsg) {
297         (void) unlink (linkpath);
298 #ifdef BSD42
299         if (link (altpath, linkpath) == NOTOK) {
300 #ifdef  notdef  /* I don't think permission on symlinks matters /JLR */
301             oumask = umask(0044);       /* PJS: else symlinks are world 'r' */
302 #endif
303             (void) symlink (altpath, linkpath);
304 #ifdef  notdef
305             umask(oumask);              /* PJS: else symlinks are world 'r' */
306 #endif
307             slinked = 1;
308         }
309         else
310             slinked = 0;
311 #else   /*  not BSD42 */
312         (void) link (altpath, linkpath);
313 #endif  /* not BSD42 */
314     }
315
316     m_update ();
317     (void) fflush (stdout);
318
319     switch (pid = vfork ()) {
320         case NOTOK: 
321             advise ("fork", "unable to");
322             status = NOTOK;
323             break;
324
325         case OK: 
326             if (cwd)
327                 (void) chdir (cwd);
328             if (altmsg) {
329                 if (mp)
330                     (void) m_putenv ("mhfolder", mp -> foldpath);
331                 (void) m_putenv ("editalt", altpath);
332             }
333
334             vecp = 0;
335             vec[vecp++] = r1bindex (*ed, '/');
336             if (arg)
337                 while (*arg)
338                     vec[vecp++] = *arg++;
339             vec[vecp++] = file;
340             vec[vecp] = NULL;
341
342             execvp (*ed, vec);
343             fprintf (stderr, "unable to exec ");
344             perror (*ed);
345             _exit (-1);
346
347         default: 
348             if (status = pidwait (pid, NOTOK)) {
349 #ifdef  ATTVIBUG
350                 if ((cp = r1bindex (*ed, '/'))
351                         && strcmp (cp, "vi") == 0
352                         && (status & 0x00ff) == 0)
353                     status = 0;
354                 else {
355 #endif
356                 if (((status & 0xff00) != 0xff00)
357                         && (!reedit || (status & 0x00ff)))
358                     if (!use && (status & 0xff00) &&
359                             (rename (file, cp = m_backup (file)) != NOTOK)) {
360                         advise (NULLCP, "problems with edit--draft left in %s",
361                                 cp);
362                     }
363                     else
364                         advise (NULLCP, "problems with edit--%s preserved",
365                                 file);
366                 status = -2;    /* maybe "reedit ? -2 : -1"? */
367                 break;
368 #ifdef  ATTVIBUG
369                 }
370 #endif
371             }
372
373             reedit++;
374 #ifdef BSD42
375             if (altmsg
376                     && mp
377                     && (!mp -> msgflags & READONLY)
378                     && (slinked
379                            ? lstat (linkpath, &st) != NOTOK
380                                 && (st.st_mode & S_IFMT) == S_IFREG
381                                 && copyf (linkpath, altpath) == NOTOK
382                            : stat (linkpath, &st) != NOTOK
383                                 && st.st_nlink == 1
384                                 && (unlink (altpath) == NOTOK
385                                         || link (linkpath, altpath) == NOTOK)))
386                 advise (linkpath, "unable to update %s from", altmsg);
387 #else   /* not BSD42 */
388             if (altmsg
389                     && mp
390                     && (!mp -> msgflags & READONLY)
391                     && stat (linkpath, &st) != NOTOK
392                     && st.st_nlink == 1
393                     && (unlink (altpath) == NOTOK
394                         || link (linkpath, altpath) == NOTOK))
395                 advise (linkpath, "unable to update %s from", altmsg);
396 #endif  /* not BSD42 */
397     }
398
399     edsave = getcpy (*ed);
400     *ed = NULL;
401     if (altmsg)
402         (void) unlink (linkpath);
403
404     return status;
405 }
406
407 /* \f */
408
409 #ifdef  BSD42
410 static int  copyf (ifile, ofile)
411 register char   *ifile,
412                 *ofile;
413 {
414     register int    i;
415     int     in,
416             out;
417     char    buffer[BUFSIZ];
418
419     if ((in = open (ifile, 0)) == NOTOK)
420         return NOTOK;
421     if ((out = open (ofile, 1)) == NOTOK || ftruncate (out, 0) == NOTOK) {
422         if (out != NOTOK) {
423             admonish (ofile, "unable to truncate");
424             (void) close (out);
425         }
426         (void) close (in);
427         return NOTOK;
428     }
429
430     while ((i = read (in, buffer, sizeof buffer)) > OK)
431         if (write (out, buffer, i) != i) {
432             advise (ofile, "may have damaged");
433             i = NOTOK;
434             break;
435         }
436
437     (void) close (in);
438     (void) close (out);
439
440     return i;
441 }
442 #endif  /* BSD42 */
443
444 /* \f   SEND */
445
446 static  sendfile (arg, file, pushsw)
447 register char **arg,
448                *file;
449 int     pushsw;
450 {
451     register int    child_id,
452                     i,
453                     vecp;
454     char *cp,
455          *sp,
456          *vec[MAXARGS];
457
458 #ifdef  MIME
459     if ((cp = m_find ("automhnproc"))
460             && !getenv ("NOMHNPROC")
461             && mhnfile (file)
462             && (i = editfile (&cp, NULLVP, file, NOUSE, NULLMP, NULLCP,
463                               NULLCP)))
464         return 0;
465 #endif
466
467     if (strcmp (sp = r1bindex (sendproc, '/'), "send") == 0) {
468         cp = invo_name;
469         sendit (invo_name = sp, arg, file, pushsw);
470         invo_name = cp;
471         return 1;
472     }
473
474     m_update ();
475     (void) fflush (stdout);
476
477     for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
478         sleep (5);
479     switch (child_id) {
480         case NOTOK: 
481             advise (NULLCP, "unable to fork, so sending directly...");
482         case OK: 
483             vecp = 0;
484             vec[vecp++] = invo_name;
485             if (pushsw)
486                 vec[vecp++] = "-push";
487             if (arg)
488                 while (*arg)
489                     vec[vecp++] = *arg++;
490             vec[vecp++] = file;
491             vec[vecp] = NULL;
492
493             execvp (sendproc, vec);
494             fprintf (stderr, "unable to exec ");
495             perror (sendproc);
496             _exit (-1);
497
498         default: 
499             if (pidwait (child_id, OK) == 0)
500                 done (0);
501             return 1;
502     }
503 }
504
505 /* \f */
506
507 #ifdef MIME
508 #include "../h/mhn.h"
509
510
511 static int  mhnfile (msgnam)
512 char   *msgnam;
513 {
514     int     state;
515     char    buf[BUFSIZ],
516             name[NAMESZ];
517     FILE   *fp;
518
519     if ((fp = fopen (msgnam, "r")) == NULL)
520         return 0;
521     for (state = FLD;;)
522         switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
523             case FLD:
524             case FLDPLUS:
525             case FLDEOF:
526                 if (uleq (name, VRSN_FIELD) || uprf (name, XXX_FIELD_PRF)) {
527                     (void) fclose (fp);
528                     return 0;
529                 }
530                 while (state == FLDPLUS)
531                     state = m_getfld (state, name, buf, sizeof buf, fp);
532                 break;
533
534             case BODY:
535                 do {
536                     register char *bp;
537
538                     for (bp = buf; *bp; bp++)
539                         if (*bp != ' ' && *bp != '\t' && *bp != '\n') {
540                             (void) fclose (fp);
541                             return 1;
542                         }
543
544                     state = m_getfld (state, name, buf, sizeof buf, fp);
545                 } while (state == BODY);
546                 /* and fall... */
547
548             default:
549                 (void) fclose (fp);
550                 return 0;
551         }
552 }
553 #endif /* MIME */
554
555 /* \f */
556
557 static struct swit  sendswitches[] = {
558 #define ALIASW  0
559     "alias aliasfile", 0,
560
561 #define DEBUGSW 1
562     "debug", -5,
563
564 #define ENCRSW  2
565     "encrypt",
566 #ifndef TMA
567     -7,
568 #else   /* TMA */
569     0,
570 #endif  /* TMA */
571 #define NENCRSW 3
572     "noencrypt",
573 #ifndef TMA
574     -9,
575 #else   /* TMA */
576     0,
577 #endif  /* TMA */
578
579 #define FILTSW  4
580     "filter filterfile", 0,
581 #define NFILTSW 5
582     "nofilter", 0,
583
584 #define FRMTSW  6
585     "format", 0,
586 #define NFRMTSW 7
587     "noformat", 0,
588
589 #define FORWSW  8
590     "forward", 0,
591 #define NFORWSW 9
592     "noforward", 0,
593
594 #define MIMESW  10
595     "mime", MIMEminc(-4),
596 #define NMIMESW 11
597     "nomime", MIMEminc(-6),
598
599 #define MSGDSW  12
600     "msgid", 0,
601 #define NMSGDSW 13
602     "nomsgid", 0,
603
604 #define SPSHSW  14
605     "push", 0,
606 #define NSPSHSW 15
607     "nopush", 0,
608
609 #define SPLITSW 16
610     "split seconds", MIMEminc(-5),
611
612 #define UNIQSW  17
613     "unique", -6,
614 #define NUNIQSW 18
615     "nounique", -8,
616
617 #define VERBSW  19
618     "verbose", 0,
619 #define NVERBSW 20
620     "noverbose", 0,
621
622 #define WATCSW  21
623     "watch", 0,
624 #define NWATCSW 22
625     "nowatch", 0,
626
627 #define WIDTHSW 23
628     "width columns", 0,
629
630 #define SHELPSW 24
631     "help", 4,
632
633 #define MAILSW  25
634     "mail", -4,
635 #define SAMLSW  26
636     "saml", -4,
637 #define SSNDSW  27
638     "send", -4,
639 #define SOMLSW  28
640     "soml", -4,
641
642 #define CLIESW  29
643     "client host", -6,
644 #define SERVSW  30
645     "server host", -6,
646 #define SNOOPSW 31
647     "snoop", -5,
648
649 #define SDRFSW 32
650     "draftfolder +folder", -6,
651 #define SDRMSW 33
652     "draftmessage msg", -6,
653 #define SNDRFSW 34
654     "nodraftfolder", -3,
655
656 #define QUEUESW 35
657     "queued", -6,
658
659 #define RECORSW 36
660     "record program", -6,
661 #define NRECOSW 37
662     "norecord", -8,
663
664     NULL, 0
665 };
666
667 /* \f */
668
669 extern int debugsw;             /* from sendsbr.c */
670 extern int forwsw;
671 extern int inplace;
672 extern int pushsw;
673 extern int splitsw;
674 extern int unique;
675 extern int verbsw;
676
677 extern char *altmsg;            /*  .. */
678 extern char *annotext;
679 extern char *distfile;
680
681 /* \f */
682
683 static  sendit (sp, arg, file, pushed)
684 register char  *sp,
685               **arg,
686                *file;
687 int     pushed;
688 {
689 #ifndef lint
690     int     distsw = 0;
691 #endif  /* not lint */
692     int     vecp = 1;
693     char   *cp,
694             buf[100],
695           **ap,
696           **argp,
697            *arguments[MAXARGS],
698            *vec[MAXARGS];
699     struct stat st;
700 #ifdef  UCI
701     FILE   *fp;
702 #endif  /* UCI */
703
704     if (arg)
705         (void) copyip (arg, vec);
706     if ((cp = m_find (sp)) != NULL) {
707         ap = brkstring (cp = getcpy (cp), " ", "\n");
708         ap = copyip (ap, arguments);
709     }
710     else
711         ap = arguments;
712     if (arg)
713         (void) copyip (vec, ap);
714     argp = arguments;
715
716     debugsw = 0, forwsw = 1, inplace = 0, unique = 0;
717     altmsg = annotext = distfile = NULL;
718     vec[vecp++] = "-library";
719     vec[vecp++] = getcpy (m_maildir (""));
720
721 /* \f */
722
723     while (cp = *argp++) {
724         if (*cp == '-')
725             switch (smatch (++cp, sendswitches)) {
726                 case AMBIGSW: 
727                     ambigsw (cp, sendswitches);
728                     return;
729                 case UNKWNSW: 
730                     advise (NULLCP, "-%s unknown\n", cp);
731                     return;
732                 case SHELPSW: 
733                     (void) sprintf (buf, "%s [switches]", sp);
734                     help (buf, sendswitches);
735                     return;
736
737                 case SPSHSW: 
738                     pushed++;
739                     continue;
740                 case NSPSHSW: 
741                     pushed = 0;
742                     continue;
743
744                 case SPLITSW: 
745                     if (!(cp = *argp++) || sscanf (cp, "%d", &splitsw) != 1) {
746                         advise (NULLCP, "missing argument to %s", argp[-2]);
747                         return;
748                     }
749                     continue;
750
751                 case UNIQSW: 
752                     unique++;
753                     continue;
754                 case NUNIQSW: 
755                     unique = 0;
756                     continue;
757                 case FORWSW: 
758                     forwsw++;
759                     continue;
760                 case NFORWSW: 
761                     forwsw = 0;
762                     continue;
763
764                 case VERBSW: 
765                     verbsw++;
766                     vec[vecp++] = --cp;
767                     continue;
768                 case NVERBSW:
769                     verbsw = 0;
770                     vec[vecp++] = --cp;
771                     continue;
772
773                 case DEBUGSW: 
774                     debugsw++;  /* fall */
775                 case NFILTSW: 
776                 case FRMTSW: 
777                 case NFRMTSW: 
778                 case MIMESW: 
779                 case NMIMESW: 
780                 case MSGDSW: 
781                 case NMSGDSW: 
782                 case WATCSW: 
783                 case NWATCSW: 
784                 case MAILSW: 
785                 case SAMLSW: 
786                 case SSNDSW: 
787                 case SOMLSW: 
788                 case ENCRSW: 
789                 case NENCRSW: 
790                 case SNOOPSW: 
791                 case QUEUESW: 
792                 case NRECOSW: 
793                     vec[vecp++] = --cp;
794                     continue;
795
796                 case ALIASW: 
797                 case FILTSW: 
798                 case WIDTHSW: 
799                 case CLIESW: 
800                 case SERVSW: 
801                 case RECORSW: 
802                     vec[vecp++] = --cp;
803                     if (!(cp = *argp++) || *cp == '-') {
804                         advise (NULLCP, "missing argument to %s", argp[-2]);
805                         return;
806                     }
807                     vec[vecp++] = cp;
808                     continue;
809
810                 case SDRFSW: 
811                 case SDRMSW: 
812                     if (!(cp = *argp++) || *cp == '-') {
813                         advise (NULLCP, "missing argument to %s", argp[-2]);
814                         return;
815                     }
816                 case SNDRFSW: 
817                     continue;
818             }
819         advise (NULLCP, "usage: %s [switches]", sp);
820         return;
821     }
822     if (cp = m_find ("Aliasfile")) {    /* allow Aliasfile: profile entry */
823         char *dp = NULL;
824
825         for (ap = brkstring(dp = getcpy(cp), " ", "\n"); ap && *ap; ap++) {
826             vec[vecp++] = "-alias";
827             vec[vecp++] = *ap;
828         }
829     }
830
831 /* \f */
832
833 #ifdef  TMA
834     if ((cp = getenv ("KDS")) == NULL || *cp == NULL)
835         if ((cp = m_find ("kdsproc")) && *cp)
836             (void) m_putenv ("KDS", cp);
837     if ((cp = getenv ("TMADB")) == NULL || *cp == NULL)
838         if ((cp = m_find ("tmadb")) && *cp)
839             (void) m_putenv ("TMADB", m_maildir (cp));
840 #endif  /* TMA */
841
842     if ((cp = getenv ("SIGNATURE")) == NULL || *cp == 0)
843         if ((cp = m_find ("signature")) && *cp)
844             (void) m_putenv ("SIGNATURE", cp);
845 #ifdef  UCI
846         else {
847             (void) sprintf (buf, "%s/.signature", mypath);
848             if ((fp = fopen (buf, "r")) != NULL
849                 && fgets (buf, sizeof buf, fp) != NULL) {
850                     (void) fclose (fp);
851                     if (cp = index (buf, '\n'))
852                         *cp = 0;
853                     (void) m_putenv ("SIGNATURE", buf);
854             }
855         }
856 #endif  /* UCI */
857
858     if ((annotext = getenv ("mhannotate")) == NULL || *annotext == 0)
859         annotext = NULL;
860     if ((altmsg = getenv ("mhaltmsg")) == NULL || *altmsg == 0)
861         altmsg = NULL;
862     if (annotext && ((cp = getenv ("mhinplace")) != NULL && *cp != 0))
863         inplace = atoi (cp);
864
865     if ((cp = getenv ("mhdist"))
866             && *cp
867 #ifndef lint
868             && (distsw = atoi (cp))
869 #endif  /* not lint */
870             && altmsg) {
871         vec[vecp++] = "-dist";
872         distfile = getcpy (m_scratch (altmsg, invo_name));
873         if (link (altmsg, distfile) == NOTOK)
874             adios (distfile, "unable to link %s to", altmsg);
875     }
876     else
877         distfile = NULL;
878
879     if (altmsg == NULL || stat (altmsg, &st) == NOTOK)
880         st.st_mtime = 0, st.st_dev = 0, st.st_ino = 0;
881     if (pushsw = pushed)
882         push ();
883
884     vec[0] = r1bindex (postproc, '/');
885     closefds (3);
886
887     if (sendsbr (vec, vecp, file, &st) == OK)
888         done (0);
889 }
890
891 /* \f   WHOM */
892
893 static  int whomfile (arg, file)
894 register char **arg,
895                *file;
896 {
897     int     pid;
898     register int    vecp;
899     char   *vec[MAXARGS];
900
901     m_update ();
902     (void) fflush (stdout);
903
904     switch (pid = vfork ()) {
905         case NOTOK: 
906             advise ("fork", "unable to");
907             return 1;
908
909         case OK: 
910             vecp = 0;
911             vec[vecp++] = r1bindex (whomproc, '/');
912             vec[vecp++] = file;
913             if (arg)
914                 while (*arg)
915                     vec[vecp++] = *arg++;
916             vec[vecp] = NULL;
917
918             execvp (whomproc, vec);
919             fprintf (stderr, "unable to exec ");
920             perror (whomproc);
921             _exit (-1);         /* NOTREACHED */
922
923         default: 
924             return (pidwait (pid, NOTOK) & 0377 ? 1 : 0);
925     }
926 }