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