diff options
Diffstat (limited to 'release/sysinstall/ftp_strat.c')
-rw-r--r-- | release/sysinstall/ftp_strat.c | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/release/sysinstall/ftp_strat.c b/release/sysinstall/ftp_strat.c new file mode 100644 index 0000000..fe017fe --- /dev/null +++ b/release/sysinstall/ftp_strat.c @@ -0,0 +1,262 @@ +/* + * The new sysinstall program. + * + * This is probably the last attempt in the `sysinstall' line, the next + * generation being slated to essentially a complete rewrite. + * + * $Id: ftp_strat.c,v 1.6.2.25 1995/06/07 09:53:14 jkh Exp $ + * + * Copyright (c) 1995 + * Jordan Hubbard. All rights reserved. + * Copyright (c) 1995 + * Gary J Palmer. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * verbatim and that no modifications are made prior to this + * point in the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Jordan Hubbard + * for the FreeBSD Project. + * 4. The name of Jordan Hubbard or the FreeBSD project may not be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include "sysinstall.h" +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/param.h> +#include <sys/wait.h> +#include <netdb.h> +#include "ftp.h" + +Boolean ftpInitted; +static FTP_t ftp; +extern int FtpPort; + +int +mediaSetFtpUserPass(char *str) +{ + char *user, *pass; + + dialog_clear(); + if ((user = msgGetInput(getenv(FTP_USER), "Please enter the username you wish to login as")) != NULL) + variable_set2(FTP_USER, user); + if ((pass = msgGetInput(getenv(FTP_PASS), "Please enter the password for this user.\nWARNING: This password will echo on the screen!")) != NULL) + variable_set2(FTP_PASS, pass); + dialog_clear(); + return 0; +} + +static Boolean +get_new_host(Device *dev) +{ + Boolean i; + char *oldTitle = MenuMediaFTP.title; + Device *netDev = dev->private; + + MenuMediaFTP.title = "Connection timed out - please select another site"; + i = mediaSetFTP(NULL); + MenuMediaFTP.title = oldTitle; + if (i) { + char *cp = getenv(FTP_USER); + + if (cp && *cp) + (void)mediaSetFtpUserPass(NULL); + netDev->flags |= OPT_LEAVE_NETWORK_UP; + (*dev->shutdown)(dev); + i = (*dev->init)(dev); + netDev->flags &= ~OPT_LEAVE_NETWORK_UP; + } + return i; +} + +static Boolean HasDistsDir; + +Boolean +mediaInitFTP(Device *dev) +{ + int i, retries, max_retries = MAX_FTP_RETRIES; + char *cp, *hostname, *dir; + char *user, *login_name, password[80], url[BUFSIZ]; + Device *netDevice = (Device *)dev->private; + + if (ftpInitted) + return TRUE; + + if (!(*netDevice->init)(netDevice)) + return FALSE; + + if ((ftp = FtpInit()) == NULL) { + msgConfirm("FTP initialisation failed!"); + goto punt; + } + if (isDebug()) + msgDebug("Initialized FTP library.\n"); + + cp = getenv("ftp"); + if (!cp) + goto punt; + if (isDebug()) + msgDebug("Attempting to open connection for: %s\n", cp); + hostname = getenv(VAR_HOSTNAME); + if (strncmp("ftp://", cp, 6) != NULL) { + msgConfirm("Invalid URL: %s\n(A URL must start with `ftp://' here)", cp); + goto punt; + } + strncpy(url, cp, BUFSIZ); + if (isDebug()) + msgDebug("Using URL `%s'\n", url); + hostname = url + 6; + if ((cp = index(hostname, ':')) != NULL) { + *(cp++) = '\0'; + FtpPort = strtol(cp, 0, 0); + } + else + FtpPort = 21; + if ((dir = index(cp ? cp : hostname, '/')) != NULL) + *(dir++) = '\0'; + if (isDebug()) { + msgDebug("hostname = `%s'\n", hostname); + msgDebug("dir = `%s'\n", dir ? dir : "/"); + msgDebug("port # = `%d'\n", FtpPort); + } + msgNotify("Looking up host %s..", hostname); + if ((gethostbyname(hostname) == NULL) && (inet_addr(hostname) == INADDR_NONE)) { + msgConfirm("Cannot resolve hostname `%s'! Are you sure that your\nname server, gateway and network interface are configured?", hostname); + goto punt; + } + user = getenv(FTP_USER); + if (!user || !*user) { + snprintf(password, BUFSIZ, "installer@%s", hostname); + login_name = "anonymous"; + } + else { + login_name = user; + strcpy(password, getenv(FTP_PASS) ? getenv(FTP_PASS) : login_name); + } + retries = i = 0; + if (OptFlags & (OPT_FTP_RESELECT + OPT_FTP_ABORT)) + max_retries = 0; +retry: + if (i && ++retries > max_retries) { + if ((OptFlags & OPT_FTP_ABORT) || !get_new_host(dev)) + return FALSE; + retries = 0; + } + msgNotify("Logging in as %s..", login_name); + if ((i = FtpOpen(ftp, hostname, login_name, password)) != 0) { + if (OptFlags & OPT_NO_CONFIRM) + msgNotify("Couldn't open FTP connection to %s\n", hostname); + else + msgConfirm("Couldn't open FTP connection to %s\n", hostname); + goto retry; + } + + FtpPassive(ftp, (OptFlags & OPT_FTP_PASSIVE) ? 1 : 0); + FtpBinary(ftp, 1); + if (dir && *dir != '\0') { + msgNotify("CD to distribution in ~ftp/%s", dir); + if ((i = FtpChdir(ftp, dir)) == -2) + goto retry; + } + if (!FtpChdir(ftp, "dists")) { + HasDistsDir = TRUE; + FtpChdir(ftp, ".."); /* Hope this works! :-( */ + } + else + HasDistsDir = FALSE; + if (isDebug()) + msgDebug("leaving mediaInitFTP!\n"); + ftpInitted = TRUE; + return TRUE; + +punt: + FtpClose(ftp); + ftp = NULL; + (*netDevice->shutdown)(netDevice); + return FALSE; +} + +int +mediaGetFTP(Device *dev, char *file, Attribs *dist_attrs) +{ + int fd; + int nretries = 0, max_retries = MAX_FTP_RETRIES; + Boolean inDists = FALSE; + + if (OptFlags & (OPT_FTP_RESELECT + OPT_FTP_ABORT) || dev->flags & OPT_EXPLORATORY_GET) + max_retries = 1; + + while ((fd = FtpGet(ftp, file)) < 0) { + /* If a hard fail, try to "bounce" the ftp server to clear it */ + if (fd == -2 || ++nretries > max_retries) { + if ((OptFlags & OPT_FTP_ABORT) || (dev->flags & OPT_EXPLORATORY_GET)) + return -1; + else if (!get_new_host(dev)) + return -2; + nretries = 0; + continue; + } + if (HasDistsDir) { + if (!inDists) { + FtpChdir(ftp, "dists"); + inDists = TRUE; + } + else { + FtpChdir(ftp, ".."); + inDists = FALSE; + } + } + } + if (inDists) + FtpChdir(ftp, ".."); + return fd; +} + +Boolean +mediaCloseFTP(Device *dev, int fd) +{ + FtpEOF(ftp); + if (!close(fd)) + return (TRUE); + return FALSE; +} + +void +mediaShutdownFTP(Device *dev) +{ + Device *netdev = (Device *)dev->private; + + if (!ftpInitted) + return; + + if (ftp != NULL) { + FtpClose(ftp); + ftp = NULL; + } + (*netdev->shutdown)(netdev); + ftpInitted = FALSE; +} |