2 * The new sysinstall program.
4 * This is probably the last attempt in the `sysinstall' line, the next
5 * generation being slated to essentially a complete rewrite.
7 * $FreeBSD: src/release/sysinstall/ftp.c,v 1.37.2.8 2002/10/24 13:00:52 nyan Exp $
8 * $DragonFly: src/release/sysinstall/Attic/ftp.c,v 1.3 2003/08/06 20:23:19 rob Exp $
11 * Jordan Hubbard. All rights reserved.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer,
18 * verbatim and that no modifications are made prior to this
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
24 * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include "sysinstall.h"
39 #include <sys/socket.h>
40 #include <netinet/in.h>
41 #include <arpa/inet.h>
42 #include <sys/param.h>
48 Boolean ftpInitted = FALSE;
49 static FILE *OpenConn;
52 /* List of sub directories to look for under a given FTP server. */
54 const char *ftp_dirs[] = { ".", "releases/pc98", "snapshots/pc98",
55 "pub/FreeBSD", "pub/FreeBSD/releases/pc98",
56 "pub/FreeBSD/snapshots/pc98", NULL };
58 const char *ftp_dirs[] = { ".", "releases/i386", "snapshots/i386",
59 "pub/FreeBSD", "pub/FreeBSD/releases/i386",
60 "pub/FreeBSD/snapshots/i386", NULL };
63 /* Brings up attached network device, if any - takes FTP device as arg */
67 Device *netdev = (Device *)dev->private;
70 return DEVICE_INIT(netdev);
72 return TRUE; /* No net == happy net */
75 /* Brings down attached network device, if any - takes FTP device as arg */
79 Device *netdev = (Device *)dev->private;
82 DEVICE_SHUTDOWN(netdev);
86 mediaInitFTP(Device *dev)
88 int i, code, af, fdir;
89 char *cp, *rel, *hostname, *dir;
90 char *user, *login_name, password[80];
100 /* If we can't initialize the network, bag it! */
105 cp = variable_get(VAR_FTP_PATH);
107 if (DITEM_STATUS(mediaSetFTP(NULL)) == DITEM_FAILURE || (cp = variable_get(VAR_FTP_PATH)) == NULL) {
108 msgConfirm("Unable to get proper FTP path. FTP media not initialized.");
114 hostname = variable_get(VAR_FTP_HOST);
115 dir = variable_get(VAR_FTP_DIR);
116 if (!hostname || !dir) {
117 msgConfirm("Missing FTP host or directory specification. FTP media not initialized,");
121 user = variable_get(VAR_FTP_USER);
122 login_name = (!user || !*user) ? "anonymous" : user;
124 if (variable_get(VAR_FTP_PASS))
125 SAFE_STRCPY(password, variable_get(VAR_FTP_PASS));
126 else if (RunningAsInit)
127 sprintf(password, "installer@%s", variable_get(VAR_HOSTNAME));
132 pw = getpwuid(getuid());
133 user = pw ? pw->pw_name : "ftp";
134 sprintf(password, "%s@%s", user, variable_get(VAR_HOSTNAME));
136 af = variable_cmp(VAR_IPV6_ENABLE, "YES") ? AF_INET : AF_UNSPEC;
137 msgNotify("Logging in to %s@%s..", login_name, hostname);
138 if ((OpenConn = ftpLoginAf(hostname, af, login_name, password, FtpPort, isDebug(), &code)) == NULL) {
139 msgConfirm("Couldn't open FTP connection to %s:\n %s.", hostname, ftpErrString(code));
143 ftpPassive(OpenConn, !strcmp(variable_get(VAR_FTP_STATE), "passive"));
145 if (dir && *dir != '\0') {
146 if ((i = ftpChdir(OpenConn, dir)) != 0) {
148 msgConfirm("No such directory ftp://%s/%s\n"
149 "please check your URL and try again.", hostname, dir);
151 msgConfirm("FTP chdir to ftp://%s/%s returned error status:\n %s.", hostname, dir, ftpErrString(i));
157 * Now that we've verified that the path we're given is ok, let's try to
158 * be a bit intelligent in locating the release we are looking for. First
159 * off, if the release is specified as "__RELEASE" or "any", then just
160 * assume that the current directory is the one we want and give up.
162 rel = variable_get(VAR_RELNAME);
163 if (strcmp(rel, "__RELEASE") && strcmp(rel, "any")) {
165 * Ok, since we have a release variable, let's walk through the list
166 * of directories looking for a release directory. The first one to
167 * match wins. For each case, we chdir to ftp_dirs[fdir] first. If
168 * that fails, we skip to the next one. Otherwise, we try to chdir to
169 * rel. If it succeeds we break out. If it fails, then we go back to
170 * the base directory and try again. Lots of chdirs, but oh well. :)
172 for (fdir = 0; ftp_dirs[fdir]; fdir++) {
173 /* Avoid sending CWD . commands which confuse some ftp servers */
174 if (strcmp(ftp_dirs[fdir], ".") &&
175 (ftpChdir(OpenConn, (char *)ftp_dirs[fdir]) != 0))
177 if (ftpChdir(OpenConn, rel) == 0) {
181 else /* reset to "root" dir for a fresh try */
182 ftpChdir(OpenConn, "/");
186 * If we get here, then all of the directories we tried failed, so
187 * print out the error message and ask the user if they want to try
190 if (!msgYesNo("Warning: Can't find the `%s' distribution on this\n"
191 "FTP server. You may need to visit a different server for\n"
192 "the release you are trying to fetch or go to the Options\n"
193 "menu and to set the release name to explicitly match what's\n"
194 "available on %s (or set to \"any\").\n\n"
195 "Would you like to select another FTP server?",
197 variable_unset(VAR_FTP_PATH);
198 if (DITEM_STATUS(mediaSetFTP(NULL)) != DITEM_FAILURE)
208 if (OpenConn != NULL) {
213 variable_unset(VAR_FTP_PATH);
218 mediaGetFTP(Device *dev, char *file, Boolean probe)
222 char *try, buf[PATH_MAX];
225 msgDebug("No FTP connection open, can't get file %s\n", file);
230 while ((fp = ftpGet(OpenConn, try, 0)) == NULL) {
231 int ftperr = ftpErrno(OpenConn);
233 /* If a hard fail, try to "bounce" the ftp server to clear it */
235 if (ftperr != 421) /* Timeout? */
236 variable_unset(VAR_FTP_PATH);
237 /* If we can't re-initialize, just forget it */
238 DEVICE_SHUTDOWN(dev);
239 if (!DEVICE_INIT(dev)) {
245 variable_unset(VAR_FTP_PATH);
252 /* Try some alternatives */
253 switch (nretries++) {
255 sprintf(buf, "releases/%s", file);
260 sprintf(buf, "%s/%s", variable_get(VAR_RELNAME), file);
265 sprintf(buf, "%s/releases/%s", variable_get(VAR_RELNAME), file);
279 mediaShutdownFTP(Device *dev)
284 if (OpenConn != NULL) {