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