Removed the built-in FTP client.
authormarkus schnalke <meillo@marmaro.de>
Sat, 4 Feb 2012 10:57:16 +0000 (11:57 +0100)
committermarkus schnalke <meillo@marmaro.de>
Sat, 4 Feb 2012 10:57:16 +0000 (11:57 +0100)
That's another of these things that are not the MUA's tasks.
There are good FTP clients around, just use one of them.
We could provide an external FTP wrapper script around wget or so,
to use with nmh-access-ftp. However, I'm not sure how to deal with
message/external-body in general. Although this concept is great,
I've never seen any such message in all my email life.

acconfig.h
man/mhshow.man1
man/mhstore.man1
uip/Makefile.in
uip/ftpsbr.c [deleted file]
uip/mhparse.c

index 43e4ad8..f4ca2dd 100644 (file)
  */
 #define RPATHS  1
 
-/*
- * Compile simple ftp client into mhshow/mhstore.  This will be used by
- * mhshow/mhstore for ftp access unless you have specified another access
- * method in your .mh_profile or mhn.defaults.  Use the "nmh-access-ftp"
- * profile entry to override this.  Check mhshow(1)/mhstore(1) man page
- * for details.
- */
-#define BUILTIN_FTP 1
-
 
 /***** END USER CONFIGURATION SECTION *****/
 @TOP@
index bce55c1..f451ccb 100644 (file)
@@ -457,11 +457,6 @@ local filename
 .PP
 The program should terminate with an exit status of zero if the
 retrieval is successful, and a non-zero exit status otherwise.
-.PP
-If this entry is not provided, then
-.B mhshow
-will use a simple
-built-in FTP client to perform the retrieval.
 .SS "The Content Cache"
 When
 .B mhshow
index acf3694..ddb43f8 100644 (file)
@@ -353,11 +353,6 @@ local filename
 .PP
 The program should terminate with an exit status of zero if the
 retrieval is successful, and a non-zero exit status otherwise.
-.PP
-If this entry is not provided, then
-.B mhstore
-will use a simple
-built-in FTP client to perform the retrieval.
 .SS "The Content Cache"
 When
 .B mhstore
index ee096aa..58a82af 100644 (file)
@@ -68,7 +68,7 @@ SCMDS = inc
 # source files
 SRCS = ali.c aliasbr.c anno.c annosbr.c ap.c burst.c comp.c \
        conflict.c dist.c distsbr.c dp.c dropsbr.c flist.c fmtdump.c \
-       folder.c forw.c ftpsbr.c inc.c mmh.sh mark.c md5.c mhbuild.c \
+       folder.c forw.c inc.c mmh.sh mark.c md5.c mhbuild.c \
        mhbuildsbr.c mhcachesbr.c mhfree.c mhl.c mhlist.c mhlistsbr.c \
        mhlsbr.c mhmail.c mhmisc.c mhoutsbr.c mhparam.c mhparse.c \
        mhpath.c mhshow.c mhshowsbr.c mhstore.c mhstoresbr.c mhtest.c \
@@ -136,14 +136,14 @@ mmh: mmh.sh
 mark: mark.o $(LOCALLIBS)
        $(LINK) mark.o $(LINKLIBS)
 
-mhbuild: mhbuild.o mhbuildsbr.o mhcachesbr.o mhlistsbr.o mhoutsbr.o mhmisc.o mhfree.o mhparse.o ftpsbr.o termsbr.o md5.o $(LOCALLIBS)
-       $(LINK) mhbuild.o mhbuildsbr.o mhcachesbr.o mhlistsbr.o mhoutsbr.o mhmisc.o mhfree.o mhparse.o ftpsbr.o md5.o $(LINKLIBS) $(TERMLIB)
+mhbuild: mhbuild.o mhbuildsbr.o mhcachesbr.o mhlistsbr.o mhoutsbr.o mhmisc.o mhfree.o mhparse.o termsbr.o md5.o $(LOCALLIBS)
+       $(LINK) mhbuild.o mhbuildsbr.o mhcachesbr.o mhlistsbr.o mhoutsbr.o mhmisc.o mhfree.o mhparse.o md5.o $(LINKLIBS) $(TERMLIB)
 
 mhl: mhl.o mhlsbr.o termsbr.o $(LOCALLIBS)
        $(LINK) mhl.o mhlsbr.o termsbr.o $(LINKLIBS) $(TERMLIB)
 
-mhlist: mhlist.o mhparse.o mhcachesbr.o mhlistsbr.o mhmisc.o mhfree.o ftpsbr.o termsbr.o md5.o $(LOCALLIBS)
-       $(LINK) mhlist.o mhparse.o mhcachesbr.o mhlistsbr.o mhmisc.o mhfree.o ftpsbr.o termsbr.o md5.o $(LINKLIBS) $(TERMLIB)
+mhlist: mhlist.o mhparse.o mhcachesbr.o mhlistsbr.o mhmisc.o mhfree.o termsbr.o md5.o $(LOCALLIBS)
+       $(LINK) mhlist.o mhparse.o mhcachesbr.o mhlistsbr.o mhmisc.o mhfree.o termsbr.o md5.o $(LINKLIBS) $(TERMLIB)
 
 mhmail: mhmail.o $(LOCALLIBS)
        $(LINK) mhmail.o $(LINKLIBS)
@@ -154,14 +154,14 @@ mhparam: mhparam.o $(LOCALLIBS)
 mhpath: mhpath.o $(LOCALLIBS)
        $(LINK) mhpath.o $(LINKLIBS)
 
-mhshow: mhshow.o mhparse.o mhcachesbr.o mhshowsbr.o mhlistsbr.o mhmisc.o mhfree.o ftpsbr.o termsbr.o md5.o $(LOCALLIBS)
-       $(LINK) mhshow.o mhparse.o mhcachesbr.o mhshowsbr.o mhlistsbr.o mhmisc.o mhfree.o ftpsbr.o termsbr.o md5.o $(LINKLIBS) $(TERMLIB)
+mhshow: mhshow.o mhparse.o mhcachesbr.o mhshowsbr.o mhlistsbr.o mhmisc.o mhfree.o termsbr.o md5.o $(LOCALLIBS)
+       $(LINK) mhshow.o mhparse.o mhcachesbr.o mhshowsbr.o mhlistsbr.o mhmisc.o mhfree.o termsbr.o md5.o $(LINKLIBS) $(TERMLIB)
 
-mhstore: mhstore.o mhparse.o mhcachesbr.o mhshowsbr.o mhlistsbr.o mhstoresbr.o mhmisc.o mhfree.o ftpsbr.o termsbr.o md5.o $(LOCALLIBS)
-       $(LINK) mhstore.o mhparse.o mhcachesbr.o mhshowsbr.o mhlistsbr.o mhstoresbr.o mhmisc.o mhfree.o ftpsbr.o termsbr.o md5.o $(LINKLIBS) $(TERMLIB)
+mhstore: mhstore.o mhparse.o mhcachesbr.o mhshowsbr.o mhlistsbr.o mhstoresbr.o mhmisc.o mhfree.o termsbr.o md5.o $(LOCALLIBS)
+       $(LINK) mhstore.o mhparse.o mhcachesbr.o mhshowsbr.o mhlistsbr.o mhstoresbr.o mhmisc.o mhfree.o termsbr.o md5.o $(LINKLIBS) $(TERMLIB)
 
-mhtest: mhtest.o mhparse.o mhcachesbr.o mhoutsbr.o mhmisc.o mhfree.o ftpsbr.o termsbr.o md5.o $(LOCALLIBS)
-       $(LINK) mhtest.o mhparse.o mhcachesbr.o mhoutsbr.o mhmisc.o mhfree.o ftpsbr.o termsbr.o md5.o $(LINKLIBS) $(TERMLIB)
+mhtest: mhtest.o mhparse.o mhcachesbr.o mhoutsbr.o mhmisc.o mhfree.o termsbr.o md5.o $(LOCALLIBS)
+       $(LINK) mhtest.o mhparse.o mhcachesbr.o mhoutsbr.o mhmisc.o mhfree.o termsbr.o md5.o $(LINKLIBS) $(TERMLIB)
 
 msgchk: msgchk.o $(LOCALLIBS)
        $(LINK) msgchk.o $(LINKLIBS)
diff --git a/uip/ftpsbr.c b/uip/ftpsbr.c
deleted file mode 100644 (file)
index b37d246..0000000
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
-** ftpsbr.c -- simple FTP client library
-**
-** This code is Copyright (c) 2002, by the authors of nmh.  See the
-** COPYRIGHT file in the root directory of the nmh distribution for
-** complete copyright information.
-*/
-
-#include <h/mh.h>
-#include <h/mime.h>
-
-#ifdef HAVE_ARPA_FTP_H
-# include <arpa/ftp.h>
-#endif
-
-#define v_debug debugsw
-#define v_verbose verbosw
-
-static int ftp_fd = NOTOK;
-static int data_fd = NOTOK;
-
-static int v_noise;
-
-extern int v_debug;
-extern int v_verbose;
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <errno.h>
-
-#define start_tcp_client(res) \
-       socket(res->ai_family, res->ai_socktype, res->ai_protocol)
-
-#define join_tcp_server(fd, sock, len) \
-       connect((fd), (struct sockaddr *) (sock), len)
-
-/*
-** prototypes
-*/
-int ftp_get(char *, char *, char *, char *, char *, char *, int, int);
-int ftp_trans(char *, char *, char *, char *, char *, char *, char *,
-               int, int);
-
-/*
-** static prototypes
-*/
-static int start_tcp_server(struct sockaddr_in *, int, int, int);
-static void _asnprintf(char *, int, char *, va_list);
-static int ftp_quit(void);
-static int ftp_read(char *, char *, char *, int);
-static int initconn(void);
-static int dataconn(void);
-static int command(int arg1, ...);
-static int vcommand(int, va_list);
-static int getreply(int, int);
-
-
-static int
-start_tcp_server(struct sockaddr_in *sock, int backlog, int opt1, int opt2)
-{
-       int eindex, sd;
-
-       if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == NOTOK)
-               return NOTOK;
-
-       if (bind(sd, (struct sockaddr *) sock, sizeof *sock) == NOTOK) {
-               eindex = errno;
-               close(sd);
-               errno = eindex;
-       } else {
-               listen(sd, backlog);
-       }
-
-       return sd;
-}
-
-
-static int __len__;
-
-#define join_tcp_client(fd,sock) \
-       accept((fd), (struct sockaddr *) (sock), \
-               (__len__ = sizeof *(sock), &__len__))
-
-#define read_tcp_socket read
-#define write_tcp_socket write
-#define close_tcp_socket close
-
-static void
-_asnprintf(char *bp, int len_bp, char *what, va_list ap)
-{
-       int eindex, len;
-       char *fmt;
-
-       eindex = errno;
-
-       *bp = '\0';
-       fmt = va_arg(ap, char *);
-
-       if (fmt) {
-               vsnprintf(bp, len_bp, fmt, ap);
-               len = strlen(bp);
-               bp += len;
-               len_bp -= len;
-       }
-
-       if (what) {
-               char *s;
-
-               if (*what) {
-                       snprintf(bp, len_bp, " %s: ", what);
-                       len = strlen(bp);
-                       bp += len;
-                       len_bp -= len;
-               }
-               if ((s = strerror(eindex)))
-                       strncpy(bp, s, len_bp);
-               else
-                       snprintf(bp, len_bp, "Error %d", eindex);
-               bp += strlen(bp);
-       }
-
-       errno = eindex;
-}
-
-
-int
-ftp_get(char *host, char *user, char *password, char *cwd,
-                char *remote, char *local, int ascii, int stayopen)
-{
-       return ftp_trans(host, user, password, cwd, remote, local,
-               "RETR", ascii, stayopen);
-}
-
-
-int
-ftp_trans(char *host, char *user, char *password, char *cwd, char *remote,
-       char *local, char *cmd, int ascii, int stayopen)
-{
-       int result;
-
-       if (stayopen <= 0) {
-               result = ftp_quit();
-               if (host == NULL)
-                       return result;
-       }
-
-       if (ftp_fd == NOTOK) {
-               struct addrinfo hints, *res;
-
-               memset(&hints, 0, sizeof(hints));
-#ifdef AI_ADDRCONFIG
-               hints.ai_flags = AI_ADDRCONFIG;
-#endif
-               hints.ai_family = PF_INET;
-               hints.ai_socktype = SOCK_STREAM;
-
-               result = getaddrinfo(host, "ftp", &hints, &res);
-
-               if (result) {
-                       fprintf(stderr, "%s/ftp: %s\n",
-                                       host, gai_strerror(result));
-                       return NOTOK;
-               }
-
-               if ((ftp_fd = start_tcp_client(res)) == NOTOK) {
-                       perror(host);
-                       freeaddrinfo(res);
-                       return NOTOK;
-               }
-               if (join_tcp_server(ftp_fd, res->ai_addr, res->ai_addrlen)
-                               == NOTOK) {
-                       perror(host);
-                       freeaddrinfo(res);
-                       close_tcp_socket(ftp_fd), ftp_fd = NOTOK;
-                       return NOTOK;
-               }
-               freeaddrinfo(res);
-               getreply(1, 0);
-
-               if (v_verbose) {
-                       fprintf(stdout, "Connected to %s\n", host);
-                       fflush(stdout);
-               }
-
-               if (user) {
-                       if ((result = command (0, "USER %s", user))
-                                       == CONTINUE)
-                               result = command(1, "PASS %s", password);
-                       if (result != COMPLETE) {
-                               result = NOTOK;
-                               goto out;
-                       }
-               }
-
-               if (remote == NULL)
-                       return OK;
-       }
-
-       if (cwd && ((result = command (0, "CWD %s", cwd)) != COMPLETE
-                       && result != CONTINUE)) {
-               result = NOTOK;
-               goto out;
-       }
-
-       if (command(1, ascii ? "TYPE A" : "TYPE I") != COMPLETE) {
-               result = NOTOK;
-               goto out;
-       }
-
-       result = ftp_read(remote, local, cmd, ascii);
-
-out: ;
-       if (result != OK || !stayopen)
-               ftp_quit();
-
-       return result;
-}
-
-
-static int
-ftp_quit(void)
-{
-       int n;
-
-       if (ftp_fd == NOTOK)
-               return OK;
-
-       n = command(1, "QUIT");
-       close_tcp_socket(ftp_fd), ftp_fd = NOTOK;
-       return (n == 0 || n == COMPLETE ? OK : NOTOK);
-}
-
-static int
-ftp_read(char *remote, char *local, char *cmd, int ascii)
-{
-       int istdio = 0, istore;
-       register int cc;
-       int expectingreply = 0;
-       char buffer[BUFSIZ];
-       FILE *fp = NULL;
-
-       if (initconn() == NOTOK)
-               goto bad;
-
-       v_noise = v_verbose;
-       if (command(-1, *remote ? "%s %s" : "%s", cmd, remote) != PRELIM)
-               goto bad;
-
-       expectingreply++;
-       if (dataconn() == NOTOK) {
-bad: ;
-               if (fp && !istdio)
-                       fclose(fp);
-               if (data_fd != NOTOK)
-                       close_tcp_socket(data_fd), data_fd = NOTOK;
-               if (expectingreply)
-                       getreply(-2, 0);
-
-               return NOTOK;
-       }
-
-       istore = (strcmp(cmd, "STOR")==0);
-
-       if ((istdio = strcmp(local, "-")==0))
-               fp = istore ? stdin : stdout;
-       else
-               if ((fp = fopen(local, istore ? "r" : "w")) == NULL) {
-                       perror(local);
-                       goto bad;
-               }
-
-       if (istore) {
-               if (ascii) {
-                       int c;
-                       FILE *out;
-
-                       if (!(out = fdopen(data_fd, "w"))) {
-                               perror("fdopen");
-                               goto bad;
-                       }
-
-                       while ((c = getc(fp)) != EOF) {
-                               if (c == '\n')
-                                       putc('\r', out);
-                               if (putc(c, out) == EOF) {
-                                       perror("putc");
-                                       fclose(out);
-                                       data_fd = NOTOK;
-                                       goto bad;
-                               }
-                       }
-
-                       fclose(out);
-                       data_fd = NOTOK;
-               } else {
-                       while ((cc = fread(buffer, sizeof *buffer,
-                                       sizeof buffer, fp)) > 0)
-                               if (write_tcp_socket(data_fd, buffer, cc)
-                                               != cc) {
-                                       perror("write_tcp_socket");
-                                       goto bad;
-                               }
-
-                       close_tcp_socket(data_fd), data_fd = NOTOK;
-               }
-       } else if (ascii) {
-               int c;
-               FILE *in;
-
-               if (!(in = fdopen(data_fd, "r"))) {
-                       perror("fdopen");
-                       goto bad;
-               }
-
-               while ((c = getc(in)) != EOF) {
-                       if (c == '\r')
-                               switch (c = getc(in)) {
-                               case EOF:
-                               case '\0':
-                                       c = '\r';
-                                       break;
-
-                               case '\n':
-                                       break;
-
-                               default:
-                                       putc('\r', fp);
-                                       break;
-                               }
-
-                       if (putc(c, fp) == EOF) {
-                               perror("putc");
-                               fclose(in);
-                               data_fd = NOTOK;
-                               goto bad;
-                       }
-               }
-
-               fclose(in);
-               data_fd = NOTOK;
-       } else {
-               while ((cc = read_tcp_socket(data_fd, buffer,
-                               sizeof buffer)) > 0)
-                       if (fwrite(buffer, sizeof *buffer, cc, fp) == 0) {
-                               perror("fwrite");
-                               goto bad;
-                       }
-               if (cc < 0) {
-                       perror("read_tcp_socket");
-                       goto bad;
-               }
-
-               close_tcp_socket(data_fd), data_fd = NOTOK;
-       }
-
-       if (!istdio)
-               fclose(fp);
-
-       v_noise = v_verbose;
-       return (getreply(1, 0) == COMPLETE ? OK : NOTOK);
-}
-
-
-#define UC(b) (((int) b) & 0xff)
-
-static int
-initconn(void)
-{
-       int len;
-       register char *a, *p;
-       struct sockaddr_in in_socket;
-
-       if (getsockname(ftp_fd, (struct sockaddr *) &in_socket,
-               (len = sizeof(in_socket), &len)) == NOTOK) {
-               perror("getsockname");
-               return NOTOK;
-       }
-       in_socket.sin_port = 0;
-       if ((data_fd = start_tcp_server(&in_socket, 1, 0, 0)) == NOTOK) {
-               perror("start_tcp_server");
-               return NOTOK;
-       }
-
-       if (getsockname(data_fd, (struct sockaddr *) &in_socket,
-               (len = sizeof in_socket, &len)) == NOTOK) {
-               perror("getsockname");
-               return NOTOK;
-       }
-
-       a = (char *) &in_socket.sin_addr;
-       p = (char *) &in_socket.sin_port;
-
-       if (command(1, "PORT %d,%d,%d,%d,%d,%d",
-                       UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
-                       UC(p[0]), UC(p[1])) == COMPLETE)
-               return OK;
-
-       return NOTOK;
-}
-
-static int
-dataconn(void)
-{
-       int fd;
-       struct sockaddr_in in_socket;
-
-       if ((fd = join_tcp_client(data_fd, &in_socket)) == NOTOK) {
-               perror("join_tcp_client");
-               return NOTOK;
-       }
-       close_tcp_socket(data_fd);
-       data_fd = fd;
-
-       return OK;
-}
-
-
-static int
-command(int arg1, ...)
-{
-       int val;
-       va_list ap;
-
-       va_start(ap, arg1);
-       val = vcommand(arg1, ap);
-       va_end(ap);
-
-       return val;
-}
-
-static int
-vcommand(int complete, va_list ap)
-{
-       int len;
-       char buffer[BUFSIZ];
-
-       if (ftp_fd == NOTOK)
-               return NOTOK;
-
-       _asnprintf(buffer, sizeof(buffer), NULL, ap);
-       if (v_debug)
-               fprintf(stderr, "<--- %s\n", buffer);
-
-       strcat(buffer, "\r\n");
-       len = strlen(buffer);
-
-       if (write_tcp_socket(ftp_fd, buffer, len) != len) {
-               perror("write_tcp_socket");
-               return NOTOK;
-       }
-
-       return(getreply(complete, strcmp(buffer, "QUIT")==0));
-}
-
-
-static int
-getreply(int complete, int expecteof)
-{
-       for (;;) {
-               register int code, dig, n;
-               int continuation;
-               register char *bp;
-               char buffer[BUFSIZ];
-
-               code = dig = n = continuation = 0;
-               bp = buffer;
-
-               for (;;) {
-                       unsigned char c;
-
-                       if (read_tcp_socket(ftp_fd, &c, 1) < 1) {
-                               if (expecteof)
-                                       return OK;
-
-                               perror("read_tcp_socket");
-                               return DONE;
-                       }
-                       if (c == '\n')
-                               break;
-                       *bp++ = c != '\r' ? c : '\0';
-
-                       dig++;
-                       if (dig < 4) {
-                               if (isdigit(c))
-                                       code = code * 10 + (c - '0');
-                               else if (isspace(c))
-                                       /* XXX: naughty FTP... */
-                                       continuation++;
-                       } else
-                               if (dig == 4 && c == '-')
-                                       continuation++;
-                       if (n == 0)
-                               n = c;
-               }
-
-               if (v_debug)
-                       fprintf(stderr, "---> %s\n", buffer);
-               if (continuation)
-                       continue;
-
-               n -= '0';
-
-               if (v_noise) {
-                       fprintf(stdout, "%s\n", buffer);
-                       fflush(stdout);
-                       v_noise = 0;
-               } else
-                       if ((complete == -1 && n != PRELIM)
-                               || (complete == 0 && n != CONTINUE && n != COMPLETE)
-                               || (complete == 1 && n != COMPLETE))
-                               fprintf(stderr, "%s\n", buffer);
-
-               return n;
-       }
-}
index f667713..d2f69bc 100644 (file)
@@ -89,9 +89,6 @@ struct k2v SubApplication[] = {
 };
 
 
-/* ftpsbr.c */
-int ftp_get(char *, char *, char *, char *, char *, char *, int, int);
-
 /* mhcachesbr.c */
 int find_cache(CT, int, int *, char *, char *, int);
 
@@ -2476,6 +2473,8 @@ openFTP(CT ct, char **file)
        CE ce;
        static char *username = NULL;
        static char *password = NULL;
+       int child_id, i, vecp;
+       char *vec[9];
 
        e  = ct->c_ctexbody;
        ce = ct->c_cefile;
@@ -2483,10 +2482,8 @@ openFTP(CT ct, char **file)
        if ((ftp = context_find(nmhaccessftp)) && !*ftp)
                ftp = NULL;
 
-#ifndef BUILTIN_FTP
        if (!ftp)
                return NOTOK;
-#endif
 
        switch (openExternal(e->eb_parent, e->eb_content, ce, file, &fd)) {
        case NOTOK:
@@ -2587,61 +2584,44 @@ openFTP(CT ct, char **file)
                return NOTOK;
        }
 
-#ifdef BUILTIN_FTP
-       if (ftp)
-#endif
-       {
-               int child_id, i, vecp;
-               char *vec[9];
-
-               vecp = 0;
-               vec[vecp++] = mhbasename(ftp);
-               vec[vecp++] = e->eb_site;
-               vec[vecp++] = user;
-               vec[vecp++] = pass;
-               vec[vecp++] = e->eb_dir;
-               vec[vecp++] = e->eb_name;
-               vec[vecp++] = ce->ce_file,
-               vec[vecp++] = e->eb_mode &&
-                               !mh_strcasecmp(e->eb_mode, "ascii") ?
-                               "ascii" : "binary";
-               vec[vecp] = NULL;
-
-               fflush(stdout);
-
-               for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++)
-                       sleep(5);
-               switch (child_id) {
-               case NOTOK:
-                       adios("fork", "unable to");
-                       /* NOTREACHED */
+       vecp = 0;
+       vec[vecp++] = mhbasename(ftp);
+       vec[vecp++] = e->eb_site;
+       vec[vecp++] = user;
+       vec[vecp++] = pass;
+       vec[vecp++] = e->eb_dir;
+       vec[vecp++] = e->eb_name;
+       vec[vecp++] = ce->ce_file,
+       vec[vecp++] = e->eb_mode &&
+                       !mh_strcasecmp(e->eb_mode, "ascii") ?
+                       "ascii" : "binary";
+       vec[vecp] = NULL;
 
-               case OK:
-                       close(fileno(ce->ce_fp));
-                       execvp(ftp, vec);
-                       fprintf(stderr, "unable to exec ");
-                       perror(ftp);
-                       _exit(-1);
-                       /* NOTREACHED */
+       fflush(stdout);
 
-               default:
-                       if (pidXwait(child_id, NULL)) {
-#ifdef BUILTIN_FTP
-losing_ftp:
-#endif
-                               username = password = NULL;
-                               ce->ce_unlink = 1;
-                               return NOTOK;
-                       }
-                       break;
+       for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++)
+               sleep(5);
+       switch (child_id) {
+       case NOTOK:
+               adios("fork", "unable to");
+               /* NOTREACHED */
+
+       case OK:
+               close(fileno(ce->ce_fp));
+               execvp(ftp, vec);
+               fprintf(stderr, "unable to exec ");
+               perror(ftp);
+               _exit(-1);
+               /* NOTREACHED */
+
+       default:
+               if (pidXwait(child_id, NULL)) {
+                       username = password = NULL;
+                       ce->ce_unlink = 1;
+                       return NOTOK;
                }
+               break;
        }
-#ifdef BUILTIN_FTP
-       else if (ftp_get(e->eb_site, user, pass, e->eb_dir, e->eb_name,
-                       ce->ce_file, e->eb_mode && !mh_strcasecmp(e->eb_mode,
-                       "ascii"), 0) == NOTOK)
-               goto losing_ftp;
-#endif
 
        if (cachefile[0]) {
                if (caching)