summaryrefslogtreecommitdiffstats
path: root/usr.sbin/pkg_install/lib
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1995-07-30 09:33:31 +0000
committerjkh <jkh@FreeBSD.org>1995-07-30 09:33:31 +0000
commit782b43871131b7fd0a0f0d61e0259ba53abdc148 (patch)
tree9b729bf55edeb4c5048aa69b7ef53bbc088bbb51 /usr.sbin/pkg_install/lib
parente01c747916f2222da20856e1a7ff37577fa76eb9 (diff)
downloadFreeBSD-src-782b43871131b7fd0a0f0d61e0259ba53abdc148.zip
FreeBSD-src-782b43871131b7fd0a0f0d61e0259ba53abdc148.tar.gz
Totally eliminate the dependency on libftp (which will be removed from the
FreeBSD source tree) and switch to the internal ftp routines developed by Poul-Henning and used in sysinstall.
Diffstat (limited to 'usr.sbin/pkg_install/lib')
-rw-r--r--usr.sbin/pkg_install/lib/file.c86
-rw-r--r--usr.sbin/pkg_install/lib/ftp.c440
-rw-r--r--usr.sbin/pkg_install/lib/ftp.h29
3 files changed, 505 insertions, 50 deletions
diff --git a/usr.sbin/pkg_install/lib/file.c b/usr.sbin/pkg_install/lib/file.c
index 55ba9d5..c8f4988 100644
--- a/usr.sbin/pkg_install/lib/file.c
+++ b/usr.sbin/pkg_install/lib/file.c
@@ -1,5 +1,5 @@
#ifndef lint
-static const char *rcsid = "$Id: file.c,v 1.11 1995/06/24 10:12:59 asami Exp $";
+static const char *rcsid = "$Id: file.c,v 1.12 1995/07/30 01:44:44 ache Exp $";
#endif
/*
@@ -23,7 +23,7 @@ static const char *rcsid = "$Id: file.c,v 1.11 1995/06/24 10:12:59 asami Exp $";
*/
#include "lib.h"
-#include <FtpLibrary.h>
+#include "ftp.h"
#include <pwd.h>
/* Quick check to see if a file exists */
@@ -161,52 +161,26 @@ fileURLFilename(char *fname, char *where, int max)
return fname;
}
-/*
- * Callback functions for fileGetURL - GetIO is called on I/O requests
- * and GetAbort when the transfer aborts.
- */
-
-/* Something they can use to keep track of the action */
-Boolean connectionAborted = FALSE;
-
-static int
-_fileGetIO(FTP *ftp, int n, char *s )
-{
- printf("In IO: %s\n", s);
- return 0;
-}
-
-static int
-_fileGetAbort(FTP *ftp, int n, char *s )
-{
- /* No access or not found, exclude network or host unreachable */
- if (abs(n) == 550 && FtpBadReply550(s)) {
- connectionAborted = TRUE;
- return 1;
- }
- return 0;
-}
-
#define HOSTNAME_MAX 64
-
/*
- * Try and fetch a file by URL, returning the name of the local
- * copy if fetched successfully.
+ * Try and fetch a file by URL, returning the fd of open
+ * file if fetched successfully.
*/
char *
fileGetURL(char *fname)
{
- static char out[FILENAME_MAX];
- char *cp;
char host[HOSTNAME_MAX], file[FILENAME_MAX], dir[FILENAME_MAX];
- char pword[HOSTNAME_MAX + 40], *uname;
+ char pword[HOSTNAME_MAX + 40], *uname, *cp;
+ static char tmpl[40];
struct passwd *pw;
- FTP *ftp;
- int i;
+ FTP_t ftp;
+ int fd, fd2, i;
+ char ch;
if (!isURL(fname))
return NULL;
+ ftp = FtpInit();
cp = fileURLHost(fname, host, HOSTNAME_MAX);
if (!*cp) {
whinge("URL `%s' has bad host part!", fname);
@@ -219,10 +193,6 @@ fileGetURL(char *fname)
return NULL;
}
- FtpSetErrorHandler(&FtpInit, _fileGetAbort);
- FtpSetFlag(&FtpInit, FTP_REST);
- FtpSetTimeout(&FtpInit, 60); /* XXX this may be too short */
-
/* Maybe change to ftp if this doesn't work */
uname = "anonymous";
@@ -237,7 +207,10 @@ fileGetURL(char *fname)
if (Verbose)
printf("Trying to fetch %s from %s.\n", file, host);
- FtpLogin(&ftp, host, uname, pword, NULL);
+ FtpOpen(ftp, host, uname, pword);
+ /* XXX - Currently undocumented - XXX */
+ if (getenv("FTP_PASSIVE"))
+ FtpPassive(ftp, TRUE);
strcpy(dir, file);
for (i = strlen(dir); i && dir[i] != '/'; i--);
@@ -245,18 +218,31 @@ fileGetURL(char *fname)
if (dir[0])
FtpChdir(ftp, dir);
- FtpBinary(ftp);
-
+ FtpBinary(ftp, TRUE);
+ fd = FtpGet(ftp, basename_of(file));
+ if (fd < 0) {
+ whinge("Unable to get `%s' over ftp!", file);
+ return NULL;
+ }
if ((cp = getenv("PKG_TMPDIR")) != NULL)
- sprintf(out, "%s/instpkg-XXXXXX.tgz", cp);
+ sprintf(tmpl, "%s/instpkg-XXXXXX.tgz", cp);
else
- strcpy(out, "/var/tmp/instpkg-XXXXXX.tgz");
-
- FtpGet(ftp, basename_of(file), out);
- FtpBye(ftp);
- if (connectionAborted)
+ strcpy(tmpl, "/var/tmp/instpkg-XXXXXX.tgz");
+ cp = mktemp(tmpl);
+ if (!cp) {
+ whinge("Unable to make temporary filename from template: %s!", tmpl);
return NULL;
- return out;
+ }
+ fd2 = open(cp, O_CREAT | O_WRONLY);
+ if (fd2 < 0) {
+ whinge("Unable to create a temporary file for ftp: %s", tmpl);
+ return NULL;
+ }
+ while (read(fd, &ch, 1) == 1)
+ write(fd, &ch, 1);
+ FtpEof(ftp);
+ FtpClose(ftp);
+ return tmpl;
}
char *
diff --git a/usr.sbin/pkg_install/lib/ftp.c b/usr.sbin/pkg_install/lib/ftp.c
new file mode 100644
index 0000000..99c34d4
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/ftp.c
@@ -0,0 +1,440 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ *
+ * $Id: ftp.c,v 1.14 1995/06/11 19:29:55 rgrimes Exp $
+ *
+ * Return values have been sanitized:
+ * -1 error, but you (still) have a session.
+ * -2 error, your session is dead.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include "ftp.h"
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+/* Handy global for us to stick the port # */
+int FtpPort;
+
+#ifndef STANDALONE_FTP
+#include "sysinstall.h"
+#endif /*STANDALONE_FTP*/
+
+static void
+debug(FTP_t ftp, const char *fmt, ...)
+{
+ char p[BUFSIZ];
+ va_list ap;
+ va_start(ap, fmt);
+#ifdef STANDALONE_FTP
+ strcpy(p,"LIBFTP: ");
+ (void) vsnprintf(p+strlen(p), sizeof p - strlen(p), fmt, ap);
+ va_end(ap);
+ write(ftp->fd_debug,p,strlen(p));
+#else
+ if (isDebug()) {
+ (void) vsnprintf(p, sizeof p - strlen(p), fmt, ap);
+ msgDebug(p);
+ }
+#endif
+}
+
+static int
+writes(int fd, char *s)
+{
+ int i = strlen(s);
+ if (i != write(fd,s,i))
+ return -2;
+ return 0;
+}
+
+static __inline char*
+get_a_line(FTP_t ftp)
+{
+ static char buf[BUFSIZ];
+ int i,j;
+
+ for(i=0;i<BUFSIZ;) {
+ j = read(ftp->fd_ctrl,buf+i,1);
+ if (j != 1)
+ return 0;
+ if (buf[i] == '\r' || buf[i] == '\n') {
+ if (!i)
+ continue;
+ buf[i] = '\0';
+ debug(ftp, "received <%s>\n",buf);
+ return buf;
+ }
+ i++;
+ }
+ return buf;
+}
+
+static int
+get_a_number(FTP_t ftp, char **q)
+{
+ char *p;
+ int i = -1,j;
+
+ while(1) {
+ p = get_a_line(ftp);
+ if (!p)
+ return -2;
+ if (!(isdigit(p[0]) && isdigit(p[1]) && isdigit(p[2])))
+ continue;
+ if (i == -1 && p[3] == '-') {
+ i = strtol(p, 0, 0);
+ continue;
+ }
+ if (p[3] != ' ' && p[3] != '\t')
+ continue;
+ j = strtol(p, 0, 0);
+ if (i == -1) {
+ if (q) *q = p+4;
+ return j;
+ } else if (j == i) {
+ if (q) *q = p+4;
+ return j;
+ }
+ }
+}
+
+static int
+zap(FTP_t ftp)
+{
+ int i;
+
+ i = writes(ftp->fd_ctrl,"QUIT\r\n");
+ if (isDebug())
+ msgDebug("Zapping ftp connection on %d returns %d\n", ftp->fd_ctrl, i);
+ close(ftp->fd_ctrl); ftp->fd_ctrl = -1;
+ close(ftp->fd_xfer); ftp->fd_xfer = -1;
+ ftp->state = init;
+ return -2;
+}
+
+static int
+botch(FTP_t ftp, char *func, char *state)
+{
+ debug(ftp, "Botch: %s called outside state %s\n",func,state);
+ return -2;
+}
+
+static int
+cmd(FTP_t ftp, const char *fmt, ...)
+{
+ char p[BUFSIZ];
+ int i;
+
+ va_list ap;
+ va_start(ap, fmt);
+ (void) vsnprintf(p, sizeof p, fmt, ap);
+ va_end(ap);
+
+ debug(ftp, "send <%s>\n",p);
+ strcat(p,"\r\n");
+ if (writes(ftp->fd_ctrl,p))
+ return -2;
+ i = get_a_number(ftp,0);
+ return i;
+}
+
+FTP_t
+FtpInit()
+{
+ FTP_t ftp;
+
+ ftp = malloc(sizeof *ftp);
+ if (!ftp)
+ return ftp;
+ memset(ftp, 0, sizeof *ftp);
+ ftp->fd_ctrl = -1;
+ ftp->fd_xfer = -1;
+ ftp->fd_debug = -1;
+ ftp->state = init;
+ return ftp;
+}
+
+#ifdef STANDALONE_FTP
+void
+FtpDebug(FTP_t ftp, int i)
+{
+ ftp->fd_debug = i;
+}
+#endif
+
+int
+FtpOpen(FTP_t ftp, char *host, char *user, char *passwd)
+{
+ struct hostent *he = NULL;
+ struct sockaddr_in sin;
+ int s;
+ unsigned long temp;
+ int i;
+
+ if (ftp->state != init)
+ return botch(ftp,"FtpOpen","init");
+
+ if (!user)
+ user = "ftp";
+
+ if (!passwd)
+ passwd = "??@??(FreeBSD:libftp)"; /* XXX */
+
+ debug(ftp, "FtpOpen(ftp, %s, %s, %s)\n", host, user, passwd);
+
+ temp = inet_addr(host);
+ if (temp != INADDR_NONE) {
+ debug(ftp, "Using dotted IP address `%s'\n", host);
+ ftp->addrtype = sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = temp;
+ }
+ else {
+ debug(ftp, "Trying to resolve `%s'\n", host);
+ he = gethostbyname(host);
+ if (!he) {
+ debug(ftp, "Lookup of `%s' failed!\n", host);
+ return zap(ftp);
+ }
+ ftp->addrtype = sin.sin_family = he->h_addrtype;
+ bcopy(he->h_addr, (char *)&sin.sin_addr, he->h_length);
+ }
+
+ sin.sin_port = htons(FtpPort ? FtpPort : 21);
+
+ if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0)
+ {
+ debug(ftp, "Socket open failed: %s (%i)\n", strerror(errno), errno);
+ return zap(ftp);
+ }
+
+ if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ debug(ftp,"Connection failed: %s (%i)\n", strerror(errno), errno);
+ (void)close(s);
+ return zap(ftp);
+ }
+
+ ftp->fd_ctrl = s;
+
+ debug(ftp, "open (%d)\n",get_a_number(ftp,0));
+
+ i = cmd(ftp,"USER %s",user);
+ if (i >= 300 && i < 400)
+ i = cmd(ftp,"PASS %s",passwd);
+ if (i >= 299 || i < 0) {
+ close(ftp->fd_ctrl); ftp->fd_ctrl = -1;
+ return zap(ftp);
+ }
+ ftp->state = isopen;
+ return 0;
+}
+
+void
+FtpClose(FTP_t ftp)
+{
+ if (ftp->state != init)
+ return;
+
+ if (ftp->state != isopen)
+ botch(ftp,"FtpClose","open or init");
+
+ debug(ftp, "FtpClose(ftp)\n");
+ zap(ftp);
+}
+
+int
+FtpChdir(FTP_t ftp, char *dir)
+{
+ int i;
+ if (ftp->state != isopen)
+ return botch(ftp,"FtpChdir","open");
+ i = cmd(ftp,"CWD %s",dir);
+ if (i < 0)
+ return i;
+ else if (i != 250)
+ return -1;
+ return 0;
+}
+
+int
+FtpGet(FTP_t ftp, char *file)
+{
+ int i,s;
+ char *q;
+ unsigned char addr[64];
+ struct sockaddr_in sin;
+ u_long a;
+
+ debug(ftp, "FtpGet(ftp,%s)\n",file);
+ if (ftp->state != isopen)
+ return botch(ftp,"FtpGet","open");
+ if(ftp->binary) {
+ i = cmd(ftp,"TYPE I");
+ if (i < 0)
+ return zap(ftp);
+ if (i > 299)
+ return -1;
+ } else {
+ return -1;
+ }
+
+ if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0)
+ return zap(ftp);
+
+ if (ftp->passive) {
+ debug(ftp, "send <%s>\n","PASV");
+ if (writes(ftp->fd_ctrl,"PASV\r\n"))
+ return zap(ftp);
+ i = get_a_number(ftp,&q);
+ if (i < 0)
+ return zap(ftp);
+ if (i != 227)
+ return zap(ftp);
+ while (*q && !isdigit(*q))
+ q++;
+ if (!*q)
+ return zap(ftp);
+ q--;
+ for(i=0;i<6;i++) {
+ q++;
+ addr[i] = strtol(q,&q,10);
+ }
+
+ sin.sin_family = ftp->addrtype;
+ bcopy(addr, (char *)&sin.sin_addr, 4);
+ bcopy(addr+4, (char *)&sin.sin_port, 2);
+ debug(ftp, "Opening active socket to %s : %u\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
+
+ debug(ftp, "Connecting to %s:%u\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
+ if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ (void)close(s);
+ debug(ftp, "connect: %s (%d)\n", strerror(errno), errno);
+ return -1;
+ }
+ ftp->fd_xfer = s;
+ i = cmd(ftp,"RETR %s",file);
+ if (i < 0) {
+ close(s);
+ return zap(ftp);
+ }
+ else if (i > 299) {
+ if (isDebug())
+ msgDebug("FTP: No such file %s, moving on.\n", file);
+ close(s);
+ return -1;
+ }
+ ftp->state = xfer;
+ return s;
+ } else {
+ i = sizeof sin;
+ getsockname(ftp->fd_ctrl,(struct sockaddr *)&sin,&i);
+ sin.sin_port = 0;
+ i = sizeof sin;
+ if (bind(s,(struct sockaddr *)&sin, i) < 0) {
+ close (s);
+ debug(ftp,"bind failed %d\n",errno);
+ return zap(ftp);
+ }
+ getsockname(s,(struct sockaddr *)&sin,&i);
+ if (listen(s,1) < 0) {
+ close (s);
+ debug(ftp,"listen failed %d\n",errno);
+ return zap(ftp);
+ }
+ a = ntohl(sin.sin_addr.s_addr);
+ i = cmd(ftp,"PORT %d,%d,%d,%d,%d,%d",
+ (a >> 24) & 0xff,
+ (a >> 16) & 0xff,
+ (a >> 8) & 0xff,
+ a & 0xff,
+ (ntohs(sin.sin_port) >> 8) & 0xff,
+ ntohs(sin.sin_port) & 0xff);
+ if (i != 200)
+ return -1;
+ i = cmd(ftp,"RETR %s",file);
+ if (i < 0) {
+ close(s);
+ return zap(ftp);
+ }
+ else if (i > 299) {
+ if (isDebug())
+ msgDebug("FTP: No such file %s, moving on.\n", file);
+ close(s);
+ return -1;
+ }
+ ftp->fd_xfer = accept(s, 0, 0);
+ if (ftp->fd_xfer < 0) {
+ close(s);
+ return zap(ftp);
+ }
+ ftp->state = xfer;
+ close(s);
+ return(ftp->fd_xfer);
+ }
+}
+
+int
+FtpEOF(FTP_t ftp)
+{
+ int i;
+
+ if (ftp->state != xfer)
+ return botch(ftp,"FtpEOF","xfer");
+ debug(ftp, "FtpEOF(ftp)\n");
+ close(ftp->fd_xfer); ftp->fd_xfer = -1;
+ ftp->state = isopen;
+ i = get_a_number(ftp,0);
+ if (i < 0)
+ return zap(ftp);
+ else if (i != 250 && i != 226)
+ return -1;
+ else
+ return 0;
+}
+
+#ifdef STANDALONE_FTP
+
+/* main.c */
+int
+main(int argc, char **argv)
+{
+ FTP_t ftp;
+ int i;
+ char c;
+
+ ftp = FtpInit();
+ if (!ftp)
+ err(1, "FtpInit()");
+
+ FtpDebug(ftp, 1);
+ i = FtpOpen(ftp, "freefall.cdrom.com", "ftp", "phk-libftp@");
+ FtpBinary(ftp, 1);
+ FtpPassive(ftp, 0);
+ FtpChdir(ftp, "/pub");
+ FtpChdir(ftp, "FreeBSD");
+ i = FtpGet(ftp, "README");
+ while (1 == read(i, &c, 1))
+ putchar(c);
+ FtpEOF(ftp);
+ return 0;
+}
+
+#endif /*STANDALONE_FTP*/
diff --git a/usr.sbin/pkg_install/lib/ftp.h b/usr.sbin/pkg_install/lib/ftp.h
new file mode 100644
index 0000000..f1e35d6
--- /dev/null
+++ b/usr.sbin/pkg_install/lib/ftp.h
@@ -0,0 +1,29 @@
+#ifndef _FTP_H_INCLUDE
+#define _FTP_H_INCLUDE
+
+typedef struct {
+ enum {init, isopen, xfer} state;
+ int fd_ctrl;
+ int fd_xfer;
+ int fd_debug;
+ int binary;
+ int passive;
+ int addrtype;
+ char *host;
+ char *file;
+} *FTP_t;
+
+FTP_t FtpInit();
+int FtpOpen(FTP_t, char *host, char *user, char *passwd);
+#define FtpBinary(ftp,bool) { (ftp)->binary = (bool); }
+#define FtpPassive(ftp,bool) { (ftp)->passive = (bool); }
+#ifndef STANDALONE_FTP
+#define FtpDebug(ftp, bool) { (ftp)->fd_debug = (bool); }
+#endif
+int FtpChdir(FTP_t, char *);
+int FtpGet(FTP_t, char *);
+int FtpEOF(FTP_t);
+void FtpClose(FTP_t);
+
+#endif
+/* _FTP_H_INCLUDE */
OpenPOWER on IntegriCloud