summaryrefslogtreecommitdiffstats
path: root/usr.sbin/sysinstall/ftp.c
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1995-05-24 09:00:58 +0000
committerjkh <jkh@FreeBSD.org>1995-05-24 09:00:58 +0000
commit744d6a5236154ffd1d180e6840f33a03b278f5b6 (patch)
tree950b9e3cd767f4528ac7f27b7809a368cf47d34c /usr.sbin/sysinstall/ftp.c
parent33ee1a22eddb8029d1051a4c04f35b72dcc1e6da (diff)
downloadFreeBSD-src-744d6a5236154ffd1d180e6840f33a03b278f5b6.zip
FreeBSD-src-744d6a5236154ffd1d180e6840f33a03b278f5b6.tar.gz
Sync to latest ftp-capable sysinstall. We're getting there!
Diffstat (limited to 'usr.sbin/sysinstall/ftp.c')
-rw-r--r--usr.sbin/sysinstall/ftp.c442
1 files changed, 264 insertions, 178 deletions
diff --git a/usr.sbin/sysinstall/ftp.c b/usr.sbin/sysinstall/ftp.c
index 4a908e5..278afa1 100644
--- a/usr.sbin/sysinstall/ftp.c
+++ b/usr.sbin/sysinstall/ftp.c
@@ -1,3 +1,15 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "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$
+ *
+ */
+
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
@@ -9,228 +21,292 @@
#include <stdarg.h>
#include <string.h>
#include <errno.h>
+#include <ctype.h>
#include "ftp.h"
+#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);
- (void) vsnprintf(p, sizeof p, fmt, ap);
- va_end(ap);
-
-#if 0
- write(ftp->fd_debug,p,strlen(p));
+ char p[BUFSIZ];
+ va_list ap;
+ va_start(ap, fmt);
+ (void) vsnprintf(p, sizeof p, fmt, ap);
+ va_end(ap);
+
+#ifdef STANDALONE_FTP
+ write(ftp->fd_debug,p,strlen(p));
#else
- msgDebug(p);
+ msgDebug(p);
#endif
}
static int
writes(int fd, char *s)
{
- int i = strlen(s);
- if (i != write(fd,s,i))
- return errno ? errno : -1;
- return 0;
+ int i = strlen(s);
+ if (i != write(fd,s,i))
+ return errno ? errno : -1;
+ return 0;
}
static 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,"LIBFTP: received <%s>\n",buf);
- return buf;
- }
- i++;
+ 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,"LIBFTP: received <%s>\n",buf);
+ return buf;
}
+ i++;
+ }
+ return buf;
}
-int
-get_a_number(FTP_t ftp)
+static int
+get_a_number(FTP_t ftp, char **q)
{
- char *p;
-
- while(1) {
- p = get_a_line(ftp);
- if (p[3] != ' ' && p[3] != ' ')
- continue;
- return atoi(p);
+ char *p;
+ int i = -1,j;
+
+ while(1) {
+ p = get_a_line(ftp);
+ if (!(isdigit(p[0]) && isdigit(p[1]) && isdigit(p[2])))
+ continue;
+ if (i == -1 && p[3] == '-') {
+ i = atoi(p);
+ continue;
+ }
+ if (p[3] != ' ' && p[3] != '\t')
+ continue;
+ j = atoi(p);
+ if (i == -1) {
+ if (q) *q = p+4;
+ return j;
+ } else if (j == i) {
+ if (q) *q = p+4;
+ return j;
}
+ }
+}
+
+static int
+botch(FTP_t ftp, char *func, char *state)
+{
+ debug(ftp,"LIBFTP: Botch: %s called outside state %s\n",func,state);
+ writes(ftp->fd_ctrl,"QUIT\r\n");
+ close(ftp->fd_ctrl); ftp->fd_ctrl = -1;
+ close(ftp->fd_xfer); ftp->fd_xfer = -1;
+ ftp->state = init;
+ return -1;
}
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,"LIBFTP: send <%s>\n",p);
- if (writes(ftp->fd_ctrl,p))
- return -1;
- if (writes(ftp->fd_ctrl,"\r\n"))
- return -1;
- i = get_a_number(ftp);
- debug(ftp, "LIBFTP: got %d\n",i);
- return i;
+ char p[BUFSIZ];
+ int i;
+
+ va_list ap;
+ va_start(ap, fmt);
+ (void) vsnprintf(p, sizeof p, fmt, ap);
+ va_end(ap);
+
+ debug(ftp,"LIBFTP: send <%s>\n",p);
+ strcat(p,"\r\n");
+ if (writes(ftp->fd_ctrl,p))
+ return -1;
+ i = get_a_number(ftp,0);
+ debug(ftp, "LIBFTP: got %d\n",i);
+ 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_debug = -1;
+ FTP_t ftp;
+
+ ftp = malloc(sizeof *ftp);
+ if (!ftp)
return ftp;
+ memset(ftp, 0, sizeof *ftp);
+ ftp->fd_ctrl = -1;
+ ftp->fd_debug = -1;
+ ftp->state = init;
+ return ftp;
}
-#if 0
+
+#ifdef STANDALONE_FTP
void
FtpDebug(FTP_t ftp, int i)
{
- ftp->fd_debug = i;
+ ftp->fd_debug = i;
}
#endif
+
int
FtpOpen(FTP_t ftp, char *host, char *user, char *passwd)
{
-
- struct hostent *he, hdef;
- struct servent *se, sdef;
- struct sockaddr_in sin;
- int s;
- char a,*p,buf[BUFSIZ];
- unsigned long temp;
-
- if (!user)
- user = "ftp";
-
- if (!passwd)
- passwd = "??@??(FreeBSD:libftp)"; /* XXX */
-
- msgDebug("FtpOpen(ftp, %s, %s, %s)\n", host, user, passwd);
-
- temp = inet_addr(host);
- if (temp != INADDR_NONE)
+ struct hostent *he = NULL;
+ struct sockaddr_in sin;
+ int s;
+ unsigned long temp;
+ extern unsigned long inet_addr(char *);
+ 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)
{
- msgDebug("Using dotted IP address `%s'\n", host);
- ftp->addrtype = sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = temp;
- } else {
- msgDebug("Trying to resolve `%s'\n", host);
- he = gethostbyname(host);
- if (!he)
- {
- msgDebug("Lookup of `%s' failed!\n", host);
- return ENOENT;
- }
- ftp->addrtype = sin.sin_family = he->h_addrtype;
- bcopy(he->h_addr, (char *)&sin.sin_addr, he->h_length);
+ debug(ftp,"Lookup of `%s' failed!\n", host);
+ return ENOENT;
}
-
- sin.sin_port = htons(21);
-
- if ((s = socket(he->h_addrtype, SOCK_STREAM, 0)) < 0)
- return s;
-
- if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
- (void)close(s);
- return -1;
- }
-
- ftp->fd_ctrl = s;
-
- debug(ftp, "LIBFTP: open (%d)\n",get_a_number(ftp));
-
- cmd(ftp,"USER %s",user);
- cmd(ftp,"PASS %s",passwd);
- return 0;
-
- fail:
- close(ftp->fd_ctrl);
- ftp->fd_ctrl = -1;
+ ftp->addrtype = sin.sin_family = he->h_addrtype;
+ bcopy(he->h_addr, (char *)&sin.sin_addr, he->h_length);
+ }
+
+ sin.sin_port = htons(21);
+
+ if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0)
+ {
+ debug("Socket open failed: %s (%i)\n", strerror(errno), errno);
+ return s;
+ }
+
+ if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ debug("Connection failed: %s (%i)\n", strerror(errno), errno);
+ (void)close(s);
return -1;
+ }
+
+ ftp->fd_ctrl = s;
+
+ debug(ftp, "LIBFTP: open (%d)\n",get_a_number(ftp,0));
+
+ i = cmd(ftp,"USER %s",user);
+ i = cmd(ftp,"PASS %s",passwd);
+ ftp->state = isopen;
+ return 0;
+
+ fail:
+ close(ftp->fd_ctrl);
+ ftp->fd_ctrl = -1;
+ return -1;
+}
+
+void
+FtpClose(FTP_t ftp)
+{
+ if (ftp->state != isopen)
+ botch(ftp,"FtpClose","open");
+
+ writes(ftp->fd_ctrl,"QUIT\r\n");
+ close(ftp->fd_ctrl); ftp->fd_ctrl = -1;
+ close(ftp->fd_xfer); ftp->fd_xfer = -1;
+ ftp->state = init;
}
int
FtpChdir(FTP_t ftp, char *dir)
{
- cmd(ftp,"CWD %s",dir);
- return 0;
+ int i;
+ if (ftp->state != isopen)
+ return botch(ftp,"FtpChdir","open");
+ i = cmd(ftp,"CWD %s",dir);
+ return 0;
}
int
FtpGet(FTP_t ftp, char *file)
{
- int fd,i,j,s;
- char p[BUFSIZ],*q;
- unsigned char addr[6];
- struct sockaddr_in sin;
-
- if(ftp->binary) {
- cmd(ftp,"TYPE I");
- } else {
- return -1;
+ int i,s;
+ char *q;
+ unsigned char addr[6];
+ struct sockaddr_in sin;
+
+ if (ftp->state != isopen)
+ return botch(ftp,"FtpGet","open");
+ if(ftp->binary) {
+ i = cmd(ftp,"TYPE I");
+ if (i > 299)
+ return -1;
+ } else {
+ return -1;
+ }
+ if(ftp->passive) {
+ if (writes(ftp->fd_ctrl,"PASV\r\n"))
+ return -1;
+ i = get_a_number(ftp,&q);
+ if (i != 227)
+ return -1;
+ while (*q && !isdigit(*q))
+ q++;
+ if (!*q)
+ return -1;
+ q--;
+ for(i=0;i<6;i++) {
+ q++;
+ addr[i] = strtol(q,&q,10);
}
- if(ftp->passive) {
- if (writes(ftp->fd_ctrl,"PASV\r\n"))
- return -1;
- q = get_a_line(ftp);
- if (strncmp(q,"227 ",4))
- return -1;
- q = strchr(q,'(');
- if (!q)
- return -1;
- for(i=0;i<6;i++) {
- q++;
- addr[i] = strtol(q,&q,10);
- debug(ftp,"ADDR[%d] = %d (%c)\n",i,addr[i],*q);
- }
- if (*q != ')')
- return -1;
-
- sin.sin_family = ftp->addrtype;
- bcopy(addr, (char *)&sin.sin_addr, 4);
- bcopy(addr+4, (char *)&sin.sin_port, 2);
- if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0)
- return -1;
- debug(ftp,"Getsocket = %d\n",s);
-
- if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
- (void)close(s);
- debug(ftp,"connect, errno = %d\n",errno);
- return -1;
- }
- cmd(ftp,"RETR %s",file);
- return s;
- } else {
- return -1;
+
+ sin.sin_family = ftp->addrtype;
+ bcopy(addr, (char *)&sin.sin_addr, 4);
+ bcopy(addr+4, (char *)&sin.sin_port, 2);
+ if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0)
+ return -1;
+
+ if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ (void)close(s);
+ debug(ftp,"connect, errno = %d\n",errno);
+ return -1;
}
+
+ i = cmd(ftp,"RETR %s",file);
+ if (i > 299)
+ return -1;
+ ftp->state = xfer;
+ return s;
+ } else {
+ return -1;
+ }
}
int
FtpEOF(FTP_t ftp)
{
- get_a_number(ftp);
+ if (ftp->state != xfer)
+ return botch(ftp,"FtpEOF","xfer");
+ ftp->state = isopen;
+ return get_a_number(ftp,0);
}
#ifdef STANDALONE_FTP
@@ -240,25 +316,35 @@ FtpEOF(FTP_t ftp)
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, "ref", "ftp", "phk-libftp@");
- if (i) err(1,"FtpOpen(%d)",i);
- FtpBinary(ftp,1);
- FtpPassive(ftp,1);
- FtpChdir(ftp,"/pub");
- FtpChdir(ftp,"CTM");
- i = FtpGet(ftp,"README_CTM_MOVED");
- while(1 == read(i,&c,1))
- putchar(c);
- FtpEOF(ftp);
- return 0;
+ FTP_t ftp;
+ int i;
+ char c;
+
+ ftp = FtpInit();
+ if (!ftp) err(1,"FtpInit()");
+
+ FtpDebug(ftp,1);
+ i = FtpOpen(ftp, "ref.tfs.com", "ftp", "phk-libftp@");
+ if (i) err(1,"FtpOpen(%d)",i);
+ FtpBinary(ftp,1);
+ FtpPassive(ftp,1);
+ FtpChdir(ftp,"/pub");
+ FtpChdir(ftp,"CTM");
+ i = FtpGet(ftp,"README_CTM_MOVED");
+ while(1 == read(i,&c,1))
+ putchar(c);
+ FtpEOF(ftp);
+ FtpClose(ftp);
+ i = FtpOpen(ftp, "freefall.cdrom.com", "ftp", "phk-libftp@");
+ FtpBinary(ftp,1);
+ FtpPassive(ftp,1);
+ 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*/
OpenPOWER on IntegriCloud