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.
This commit is contained in:
parent
d8003c2a59
commit
4366f12ca2
|
@ -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);
|
||||
|
||||
if ((cp = getenv("PKG_TMPDIR")) != NULL)
|
||||
sprintf(out, "%s/instpkg-XXXXXX.tgz", cp);
|
||||
else
|
||||
strcpy(out, "/var/tmp/instpkg-XXXXXX.tgz");
|
||||
|
||||
FtpGet(ftp, basename_of(file), out);
|
||||
FtpBye(ftp);
|
||||
if (connectionAborted)
|
||||
FtpBinary(ftp, TRUE);
|
||||
fd = FtpGet(ftp, basename_of(file));
|
||||
if (fd < 0) {
|
||||
whinge("Unable to get `%s' over ftp!", file);
|
||||
return NULL;
|
||||
return out;
|
||||
}
|
||||
if ((cp = getenv("PKG_TMPDIR")) != NULL)
|
||||
sprintf(tmpl, "%s/instpkg-XXXXXX.tgz", cp);
|
||||
else
|
||||
strcpy(tmpl, "/var/tmp/instpkg-XXXXXX.tgz");
|
||||
cp = mktemp(tmpl);
|
||||
if (!cp) {
|
||||
whinge("Unable to make temporary filename from template: %s!", tmpl);
|
||||
return NULL;
|
||||
}
|
||||
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 *
|
||||
|
|
|
@ -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*/
|
|
@ -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 */
|
Loading…
Reference in New Issue