Removed -(no)push and -(no)forward flags from send, spost and whatnow.
[mmh] / uip / whatnow.c
1 /*
2 ** whatnow.c -- the WhatNow shell
3 **
4 ** This code is Copyright (c) 2002, by the authors of nmh.  See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
7 **
8 **  The inclusion of attachments is eased by
9 **  using the header field name mechanism added to anno and send.
10 **  The header field name for attachments is predefined.
11 **
12 **  Several commands have been added at the whatnow prompt:
13 **
14 **        cd [ directory ]        This option works just like the shell's
15 **                                cd command and lets the user change the
16 **                                directory from which attachments are
17 **                                taken so that long path names are not
18 **                                needed with every file.
19 **
20 **        ls [ ls-options ]       This option works just like the normal
21 **                                ls command and exists to allow the user
22 **                                to verify file names in the directory.
23 **
24 **        pwd                     This option works just like the normal
25 **                                pwd command and exists to allow the user
26 **                                to verify the directory.
27 **
28 **        attach files            This option attaches the named files to
29 **                                the draft.
30 **
31 **        alist                   This option lists the attachments on the
32 **                                draft.
33 **
34 **        detach files            This option removes attachments from the
35 **        detach -n numbers       draft.  This can be done by file name or
36 **                                by attachment number.
37 */
38
39 #include <h/mh.h>
40 #include <fcntl.h>
41 #include <signal.h>
42 #include <h/mime.h>
43 #include <h/utils.h>
44
45 static struct swit whatnowswitches[] = {
46 #define EDITRSW  0
47         { "editor editor", 0 },
48 #define NEDITSW  1
49         { "noedit", 0 },
50 #define PRMPTSW  2
51         { "prompt string", 4 },
52 #define VERSIONSW  3
53         { "version", 0 },
54 #define HELPSW  4
55         { "help", 0 },
56         { NULL, 0 }
57 };
58
59 /*
60 ** Options at the "whatnow" prompt
61 */
62 static struct swit aleqs[] = {
63 #define EDITSW  0
64         { "edit [<editor> <switches>]", 0 },
65 #define REFILEOPT  1
66         { "refile [<switches>] +folder", 0 },
67 #define DISPSW  2
68         { "display", 0 },
69 #define LISTSW  3
70         { "list", 0 },
71 #define SENDSW  4
72         { "send [<switches>]", 0 },
73 #define QUITSW  5
74         { "quit", 0 },
75 #define DELETESW  6
76         { "delete", 0 },
77 #define CDCMDSW  7
78         { "cd [directory]", 0 },
79 #define PWDCMDSW  8
80         { "pwd", 0 },
81 #define LSCMDSW  9
82         { "ls", 0 },
83 #define ATTACHCMDSW  10
84         { "attach", 0 },
85 #define DETACHCMDSW  11
86         { "detach [-n]", 0 },
87 #define ALISTCMDSW  12
88         { "alist", 0 },
89         { NULL, 0 }
90 };
91
92 static char *myprompt = "\nWhat now? ";
93
94 /*
95 ** static prototypes
96 */
97 static int editfile(char **, char **, char *, int, struct msgs *,
98         char *, char *, int);
99 static int sendfile(char **, char *);
100 static int refile(char **, char *);
101 static int removefile(char *);
102 static void writelscmd(char *, int, char **);
103 static void writesomecmd(char *buf, int bufsz, char *cmd, char *trailcmd, char **argp);
104 static FILE* popen_in_dir(const char *dir, const char *cmd, const char *type);
105 static int system_in_dir(const char *dir, const char *cmd);
106
107
108 #ifdef HAVE_LSTAT
109 static int copyf(char *, char *);
110 #endif
111
112
113 int
114 main(int argc, char **argv)
115 {
116         int nedit = 0, use = 0;
117         char *cp;
118         char *ed = NULL, *drft = NULL, *msgnam = NULL;
119         char buf[BUFSIZ], prompt[BUFSIZ];
120         char **argp, **arguments;
121         struct stat st;
122         char cwd[MAXPATHLEN + 1];  /* current working directory */
123         char file[MAXPATHLEN + 1];  /* file name buffer */
124         char shell[MAXPATHLEN + 1];  /* shell response buffer */
125         FILE *f;  /* read pointer for bgnd proc */
126         int n;  /* set on -n to detach command */
127
128 #ifdef LOCALE
129         setlocale(LC_ALL, "");
130 #endif
131
132         invo_name = mhbasename(argv[0]);
133
134         /* read user profile/context */
135         context_read();
136
137         arguments = getarguments(invo_name, argc, argv, 1);
138         argp = arguments;
139
140         /*
141         ** Get the initial current working directory.
142         */
143
144         if (!getcwd(cwd, sizeof (cwd))) {
145                 adios("getcwd", "could not get working directory");
146         }
147
148         while ((cp = *argp++)) {
149                 if (*cp == '-') {
150                         switch (smatch(++cp, whatnowswitches)) {
151                         case AMBIGSW:
152                                 ambigsw(cp, whatnowswitches);
153                                 done(1);
154                         case UNKWNSW:
155                                 adios(NULL, "-%s unknown", cp);
156
157                         case HELPSW:
158                                 snprintf(buf, sizeof(buf),
159                                                 "%s [switches] [file]",
160                                                 invo_name);
161                                 print_help(buf, whatnowswitches, 1);
162                                 done(1);
163                         case VERSIONSW:
164                                 print_version(invo_name);
165                                 done(1);
166
167                         case EDITRSW:
168                                 if (!(ed = *argp++) || *ed == '-')
169                                         adios(NULL, "missing argument to %s",
170                                                         argp[-2]);
171                                 nedit = 0;
172                                 continue;
173                         case NEDITSW:
174                                 nedit++;
175                                 continue;
176
177                         case PRMPTSW:
178                                 if (!(myprompt = *argp++) || *myprompt == '-')
179                                         adios(NULL, "missing argument to %s",
180                                                         argp[-2]);
181                                 continue;
182
183                         }
184                 }
185                 if (drft)
186                         adios(NULL, "only one draft at a time!");
187                 else
188                         drft = cp;
189         }
190
191         if ((!drft && !(drft = getenv("mhdraft"))) || !*drft)
192                 drft = getcpy(m_draft(seq_cur));
193
194         msgnam = (cp = getenv("mhaltmsg")) && *cp ? getcpy(cp) : NULL;
195
196         if ((cp = getenv("mhuse")) && *cp)
197                 use = atoi(cp);
198
199         if (!ed && (!(ed = getenv("mheditor")) || !*ed)) {
200                 ed = NULL;
201                 nedit++;
202         }
203
204         /* start editing the draft, unless -noedit was given */
205         if (!nedit && editfile(&ed, NULL, drft, use, NULL, msgnam, NULL, 1)
206                         < 0)
207                 done(1);
208
209         snprintf(prompt, sizeof(prompt), myprompt, invo_name);
210         for (;;) {
211                 if (!(argp = getans(prompt, aleqs))) {
212                         unlink(altmsglink);
213                         done(1);
214                 }
215                 switch (smatch(*argp, aleqs)) {
216                 case DISPSW:
217                         /* display the msg being replied to or distributed */
218                         if (msgnam) {
219                                 snprintf(buf, sizeof buf, "%s '%s'",
220                                                 listproc, msgnam);
221                                 system(buf);
222                         } else {
223                                 advise(NULL, "no alternate message to display");
224                         }
225                         break;
226
227                 case EDITSW:
228                         /* Call an editor on the draft file */
229                         if (*++argp)
230                                 ed = *argp++;
231                         if (editfile(&ed, argp, drft, NOUSE, NULL,
232                                         msgnam, NULL, 1) == NOTOK)
233                                 done(1);
234                         break;
235
236                 case LISTSW:
237                         /* display the draft file */
238                         snprintf(buf, sizeof buf, "%s '%s'", listproc, drft);
239                         system(buf);
240                         break;
241
242                 case QUITSW:
243                         /* quit */
244                         if (stat(drft, &st) != NOTOK) {
245                                 advise(NULL, "draft left on %s", drft);
246                         }
247                         done(1);
248
249                 case DELETESW:
250                         /* Delete draft and exit */
251                         removefile(drft);
252                         done(1);
253
254                 case SENDSW:
255                         /* Send draft */
256                         sendfile(++argp, drft);
257                         break;
258
259                 case REFILEOPT:
260                         /* Refile the draft */
261                         if (refile(++argp, drft) == 0) {
262                                 done(0);
263                         }
264                         break;
265
266                 case CDCMDSW:
267                         /*
268                         ** Change the working directory for attachments
269                         **
270                         ** Run the directory through the user's shell
271                         ** so that we can take advantage of any syntax
272                         ** that the user is accustomed to.  Read back
273                         ** the absolute path.
274                         */
275
276                         if (*(argp+1) == NULL) {
277                                 sprintf(buf, "$SHELL -c \"cd;pwd\"");
278                         } else {
279                                 writesomecmd(buf, BUFSIZ, "cd", "pwd", argp);
280                         }
281                         if ((f = popen_in_dir(cwd, buf, "r"))) {
282                                 fgets(cwd, sizeof (cwd), f);
283
284                                 if (strchr(cwd, '\n'))
285                                         *strchr(cwd, '\n') = '\0';
286
287                                 pclose(f);
288                         } else {
289                                 advise("popen", "could not get directory");
290                         }
291
292                         break;
293
294                 case PWDCMDSW:
295                         /* Print the working directory for attachments */
296                         printf("%s\n", cwd);
297                         break;
298
299                 case LSCMDSW:
300                         /*
301                         ** List files in the current attachment working
302                         ** directory
303                         **
304                         ** Use the user's shell so that we can take
305                         ** advantage of any syntax that the user is
306                         ** accustomed to.
307                         */
308                         writelscmd(buf, sizeof(buf), argp);
309                         system_in_dir(cwd, buf);
310                         break;
311
312                 case ALISTCMDSW:
313                         /*
314                         ** List attachments on current draft.
315                         */
316                         snprintf(buf, sizeof buf, "anno -list -comp '%s' "
317                                         "-number all -text IGNORE '%s'",
318                                         attach_hdr, drft);
319                         if (system(buf) != 0) {
320                                 advise(NULL, "Could not list attachment headers.");
321                         }
322                         break;
323
324                 case ATTACHCMDSW:
325                         /*
326                         ** Attach files to current draft.
327                         */
328
329                         if (*(argp+1) == NULL) {
330                                 advise(NULL, "attach command requires file argument(s).");
331                                 break;
332                         }
333
334                         /*
335                         ** Build a command line that causes the user's
336                         ** shell to list the file name arguments.
337                         ** This handles and wildcard expansion, tilde
338                         ** expansion, etc.
339                         */
340                         writelscmd(buf, sizeof(buf), argp);
341
342                         /*
343                         ** Read back the response from the shell,
344                         ** which contains a number of lines with one
345                         ** file name per line.  Remove off the newline.
346                         ** Determine whether we have an absolute or
347                         ** relative path name.  Prepend the current
348                         ** working directory to relative path names.
349                         ** Add the attachment annotation to the draft.
350                         */
351                         if ((f = popen_in_dir(cwd, buf, "r"))) {
352                                 char buf[BUFSIZ];
353
354                                 while (fgets(shell, sizeof(shell), f)) {
355                                         *(strchr(shell, '\n')) = '\0';
356
357                                         if (*shell == '/')
358                                                 sprintf(file, "%s", shell);
359                                         else {
360                                                 sprintf(file, "%s/%s", cwd,
361                                                                 shell);
362                                         }
363                                         snprintf(buf, sizeof buf,
364                                                         "anno -nodate -append "
365                                                         "-comp '%s' -text '%s'"
366                                                         " '%s'",
367                                                         attach_hdr, file,
368                                                         drft);
369                                         if (system(buf) != 0) {
370                                                 advise(NULL, "Could not add attachment header.");
371                                         }
372                                 }
373
374                                 pclose(f);
375                         } else {
376                                 advise("popen", "could not get file from shell");
377                         }
378
379                         break;
380
381                 case DETACHCMDSW:
382                         /*
383                         ** Detach files from current draft.
384                         **
385                         ** Scan the arguments for a -n.  Mixed file
386                         ** names and numbers aren't allowed, so this
387                         ** catches a -n anywhere in the argument list.
388                         */
389                         for (n = 0, arguments = argp + 1;
390                                         *arguments != NULL;
391                                         arguments++) {
392                                 if (strcmp(*arguments, "-n") == 0) {
393                                                 n = 1;
394                                                 break;
395                                 }
396                         }
397
398                         /*
399                         ** A -n was found so interpret the arguments as
400                         ** attachment numbers.  Decrement any remaining
401                         ** argument number that is greater than the one
402                         ** just processed after processing each one so
403                         ** that the numbering stays correct.
404                         */
405                         if (n == 1) {
406                                 for (arguments=argp+1; *arguments;
407                                                 arguments++) {
408                                         if (strcmp(*arguments, "-n") == 0)
409                                                 continue;
410
411                                         if (**arguments != '\0') {
412                                                 char buf[BUFSIZ];
413
414                                                 n = atoi(*arguments);
415                                                 snprintf(buf, sizeof buf, "anno -delete -comp '%s' -number '%d' '%s'", attach_hdr, n, drft);
416                                                 if (system(buf) != 0) {
417                                                         advise(NULL, "Could not delete attachment header.");
418                                                 }
419
420                                                 for (argp=arguments+1; *argp;
421                                                                 argp++) {
422                                                         if (atoi(*argp) > n) {
423                                                                 if (atoi(*argp) == 1)
424                                                                         *argp = "";
425                                                                 else
426                                                                         sprintf(*argp, "%d", atoi(*argp) - 1);
427                                                         }
428                                                 }
429                                         }
430                                 }
431                                 break;
432                         }
433                         /* else */
434
435                         /*
436                         ** The arguments are interpreted as file names.
437                         ** Run them through the user's shell for wildcard
438                         ** expansion and other goodies.  Do this from
439                         ** the current working directory if the argument
440                         ** is not an absolute path name (does not begin
441                         ** with a /).
442                         **
443                         ** We feed all the file names to the shell at
444                         ** once, otherwise you can't provide a file name
445                         ** with a space in it.
446                         */
447                         writelscmd(buf, sizeof(buf), argp);
448                         if ((f = popen_in_dir(cwd, buf, "r"))) {
449                                 while (fgets(shell, sizeof (shell), f)) {
450                                         *(strchr(shell, '\n')) = '\0';
451                                         snprintf(buf, sizeof buf,
452                                                         "anno -delete -comp "
453                                                         "'%s' -text '%s' '%s'",
454                                                         attach_hdr, shell,
455                                                         drft);
456                                         if (system(buf) != 0) {
457                                                 advise(NULL, "Could not delete attachment header.");
458                                         }
459                                 }
460                                 pclose(f);
461                         } else {
462                                 advise("popen", "could not get file from shell");
463                         }
464
465                         break;
466
467                 default:
468                         /* Unknown command */
469                         advise(NULL, "say what?");
470                         break;
471                 }
472         }
473         /*NOTREACHED*/
474 }
475
476
477
478 /*
479 ** Build a command line of the form $SHELL -c "cd 'cwd'; cmd argp ... ;
480 ** trailcmd".
481 */
482 static void
483 writesomecmd(char *buf, int bufsz, char *cmd, char *trailcmd, char **argp)
484 {
485         char *cp;
486         /*
487         ** Note that we do not quote -- the argp from the user
488         ** is assumed to be quoted as they desire. (We can't treat
489         ** it as pure literal as that would prevent them using ~,
490         ** wildcards, etc.) The buffer produced by this function
491         ** should be given to popen_in_dir() or system_in_dir() so
492         ** that the current working directory is set correctly.
493         */
494         int ln = snprintf(buf, bufsz, "$SHELL -c \"%s", cmd);
495         /*
496         ** NB that some snprintf() return -1 on overflow rather than the
497         ** new C99 mandated 'number of chars that would have been written'
498         */
499         /*
500         ** length checks here and inside the loop allow for the
501         ** trailing ';', trailcmd, '"' and NUL
502         */
503         int trailln = strlen(trailcmd) + 3;
504         if (ln < 0 || ln + trailln > bufsz)
505                 adios(NULL, "arguments too long");
506
507         cp = buf + ln;
508
509         while (*++argp) {
510                 ln = strlen(*argp);
511                 /* +1 for leading space */
512                 if (ln + trailln + 1 > bufsz - (cp-buf))
513                         adios(NULL, "arguments too long");
514                 *cp++ = ' ';
515                 memcpy(cp, *argp, ln+1);
516                 cp += ln;
517         }
518         if (*trailcmd) {
519                 *cp++ = ';';
520                 strcpy(cp, trailcmd);
521                 cp += trailln - 3;
522         }
523         *cp++ = '"';
524         *cp = 0;
525 }
526
527 /*
528 ** Build a command line that causes the user's shell to list the file name
529 ** arguments.  This handles and wildcard expansion, tilde expansion, etc.
530 */
531 static void
532 writelscmd(char *buf, int bufsz, char **argp)
533 {
534         writesomecmd(buf, bufsz, "ls", "", argp);
535 }
536
537 /*
538 ** Like system(), but run the command in directory dir.
539 ** This assumes the program is single-threaded!
540 */
541 static int
542 system_in_dir(const char *dir, const char *cmd)
543 {
544         char olddir[BUFSIZ];
545         int r;
546         if (getcwd(olddir, sizeof(olddir)) == 0)
547                 adios("getcwd", "could not get working directory");
548         if (chdir(dir) != 0)
549                 adios("chdir", "could not change working directory");
550         r = system(cmd);
551         if (chdir(olddir) != 0)
552                 adios("chdir", "could not change working directory");
553         return r;
554 }
555
556 /* ditto for popen() */
557 static FILE*
558 popen_in_dir(const char *dir, const char *cmd, const char *type)
559 {
560         char olddir[BUFSIZ];
561         FILE *f;
562         if (getcwd(olddir, sizeof(olddir)) == 0)
563                 adios("getcwd", "could not get working directory");
564         if (chdir(dir) != 0)
565                 adios("chdir", "could not change working directory");
566         f = popen(cmd, type);
567         if (chdir(olddir) != 0)
568                 adios("chdir", "could not change working directory");
569         return f;
570 }
571
572
573 /*
574 ** EDIT
575 */
576
577 static int  reedit = 0;  /* have we been here before? */
578 static char *edsave = NULL;  /* the editor we used previously */
579
580
581 static int
582 editfile(char **ed, char **arg, char *file, int use, struct msgs *mp,
583         char *altmsg, char *cwd, int save_editor)
584 {
585         int pid, status, vecp;
586         char altpath[BUFSIZ], linkpath[BUFSIZ];
587         char *cp, *vec[MAXARGS];
588         struct stat st;
589
590 #ifdef HAVE_LSTAT
591         int slinked = 0;
592 #endif /* HAVE_LSTAT */
593
594         /* Was there a previous edit session? */
595         if (reedit) {
596                 if (!*ed) {  /* no explicit editor */
597                         *ed = edsave;  /* so use the previous one */
598                         if (!(cp = mhbasename(*ed)))
599                                 cp = *ed;
600
601                         /* unless we've specified it via "editor-next" */
602                         cp = concat(cp, "-next", NULL);
603                         if ((cp = context_find(cp)))
604                                 *ed = cp;
605                 }
606         } else if (!*ed) {
607                 /* set initial editor */
608                 *ed = defaulteditor;
609         }
610
611         if (altmsg) {
612                 if (!mp || *altmsg == '/' || !cwd)
613                         strncpy(altpath, altmsg, sizeof(altpath));
614                 else
615                         snprintf(altpath, sizeof(altpath), "%s/%s",
616                                         mp->foldpath, altmsg);
617                 if (!cwd)
618                         strncpy(linkpath, altmsglink, sizeof(linkpath));
619                 else
620                         snprintf(linkpath, sizeof(linkpath), "%s/%s",
621                                         cwd, altmsglink);
622                 unlink(linkpath);
623 #ifdef HAVE_LSTAT
624                 if (link(altpath, linkpath) == NOTOK) {
625                         symlink(altpath, linkpath);
626                         slinked = 1;
627                 } else {
628                         slinked = 0;
629                 }
630 #else /* not HAVE_LSTAT */
631                 link(altpath, linkpath);
632 #endif /* not HAVE_LSTAT */
633         }
634
635         context_save();  /* save the context file */
636         fflush(stdout);
637
638         switch (pid = fork()) {
639         case NOTOK:
640                 advise("fork", "unable to");
641                 status = NOTOK;
642                 break;
643
644         case OK:
645                 if (cwd)
646                         chdir(cwd);
647                 if (altmsg) {
648                         if (mp)
649                                 m_putenv("mhfolder", mp->foldpath);
650                         m_putenv("editalt", altpath);
651                 }
652
653                 vecp = 0;
654                 vec[vecp++] = mhbasename(*ed);
655                 if (arg)
656                         while (*arg)
657                                 vec[vecp++] = *arg++;
658                 vec[vecp++] = file;
659                 vec[vecp] = NULL;
660
661                 execvp(*ed, vec);
662                 fprintf(stderr, "unable to exec ");
663                 perror(*ed);
664                 _exit(-1);
665
666         default:
667                 if ((status = pidwait(pid, NOTOK))) {
668                         if (((status & 0xff00) != 0xff00) &&
669                                         (!reedit || (status & 0x00ff))) {
670                                 if (!use && (status & 0xff00) && (rename(file, cp = m_backup(file)) != NOTOK)) {
671                                         advise(NULL, "problems with edit--draft left in %s", cp);
672                                 } else {
673                                         advise(NULL, "problems with edit--%s preserved", file);
674                                 }
675                         }
676                         status = -2;  /* maybe "reedit ? -2 : -1"? */
677                         break;
678                 }
679
680                 reedit++;
681 #ifdef HAVE_LSTAT
682                 if (altmsg && mp && !is_readonly(mp) && (slinked ?
683                                 lstat (linkpath, &st) != NOTOK &&
684                                 S_ISREG(st.st_mode) &&
685                                 copyf(linkpath, altpath) == NOTOK :
686                                 stat(linkpath, &st) != NOTOK &&
687                                 st.st_nlink == 1 &&
688                                 (unlink(altpath) == NOTOK ||
689                                 link(linkpath, altpath) == NOTOK)))
690                         advise(linkpath, "unable to update %s from", altmsg);
691 #else /* HAVE_LSTAT */
692                 if (altmsg && mp && !is_readonly(mp) &&
693                                 stat(linkpath, &st) != NOTOK &&
694                                 st.st_nlink == 1 &&
695                                 (unlink(altpath) == NOTOK ||
696                                 link(linkpath, altpath) == NOTOK))
697                         advise(linkpath, "unable to update %s from", altmsg);
698 #endif /* HAVE_LSTAT */
699         }
700
701         /* normally, we remember which editor we used */
702         if (save_editor)
703                 edsave = getcpy(*ed);
704
705         *ed = NULL;
706         if (altmsg)
707                 unlink(linkpath);
708
709         return status;
710 }
711
712
713 #ifdef HAVE_LSTAT
714 static int
715 copyf(char *ifile, char *ofile)
716 {
717         int i, in, out;
718         char buffer[BUFSIZ];
719
720         if ((in = open(ifile, O_RDONLY)) == NOTOK)
721                 return NOTOK;
722         if ((out = open(ofile, O_WRONLY | O_TRUNC)) == NOTOK) {
723                 admonish(ofile, "unable to open and truncate");
724                 close(in);
725                 return NOTOK;
726         }
727
728         while ((i = read(in, buffer, sizeof(buffer))) > OK)
729                 if (write(out, buffer, i) != i) {
730                         advise(ofile, "may have damaged");
731                         i = NOTOK;
732                         break;
733                 }
734
735         close(in);
736         close(out);
737         return i;
738 }
739 #endif /* HAVE_LSTAT */
740
741
742 /*
743 ** SEND
744 */
745
746 static int
747 sendfile(char **arg, char *file)
748 {
749         pid_t child_id;
750         int vecp;
751         char *vec[MAXARGS];
752
753         context_save();  /* save the context file */
754         fflush(stdout);
755
756         switch (child_id = fork()) {
757         case NOTOK:
758                 advise(NULL, "unable to fork, so sending directly...");
759                 /* fall */
760         case OK:
761                 vecp = 0;
762                 vec[vecp++] = invo_name;
763                 if (arg)
764                         while (*arg)
765                                 vec[vecp++] = *arg++;
766                 vec[vecp++] = file;
767                 vec[vecp] = NULL;
768
769                 execvp("send", vec);
770                 fprintf(stderr, "unable to exec ");
771                 perror("send");
772                 _exit(-1);
773
774         default:
775                 if (pidwait(child_id, OK) == 0)
776                         done(0);
777                 return 1;
778         }
779 }
780
781
782 /*
783 ** refile msg into another folder
784 */
785 static int
786 refile(char **arg, char *file)
787 {
788         pid_t pid;
789         register int vecp;
790         char *vec[MAXARGS];
791
792         vecp = 0;
793         vec[vecp++] = "refile";
794         vec[vecp++] = "-nolink";  /* override bad .mh_profile defaults */
795         vec[vecp++] = "-file";
796         vec[vecp++] = file;
797
798         while (arg && *arg) {
799                 vec[vecp++] = *arg++;
800         }
801         vec[vecp] = NULL;
802
803         context_save();  /* save the context file */
804         fflush(stdout);
805
806         switch (pid = fork()) {
807         case -1:
808                 advise("fork", "unable to");
809                 return -1;
810
811         case 0:
812                 execvp(*vec, vec);
813                 fprintf(stderr, "unable to exec ");
814                 perror(*vec);
815                 _exit(-1);
816
817         default:
818                 return (pidwait(pid, -1));
819         }
820 }
821
822
823 /*
824 ** Remove the draft file
825 */
826
827 static int
828 removefile(char *drft)
829 {
830         if (unlink(drft) == NOTOK)
831                 adios(drft, "unable to unlink");
832
833         return OK;
834 }