home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 3
/
Meeting_Pearls_III.iso
/
Pearls
/
tcp
/
Networking
/
TCP
/
Clients
/
MuiADT
/
src
/
ftp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-01
|
8KB
|
405 lines
/*
* This code is pretty much the unix adt distribution ftp code
* (mostly because I have no idea how to do it myself :-))
*/
#include "adt.h"
#include <exec/libraries.h>
#include <dos/dosextens.h>
#include <dos/dos.h>
#include <clib/dos_protos.h>
#include <libraries/mui.h>
#include <clib/alib_protos.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <bsdsocket.h>
#include <sys/time.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/ftp.h>
#include <arpa/telnet.h>
#include <string.h>
#include <netdb.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <ios1.h>
#include <ctype.h>
#define NBBY 8 /* number of bits in a byte */
#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */
#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
#undef BUFSIZ
#define BUFSIZ 1024
#define s_close(x) CloseSocket(x)
int sgetc(int);
char *ftp_connect(char *host, char *path);
int ftp_getreply(int);
int ftp_command(char *, ...);
void ftp_lostpeer(void);
int ftp_login(void);
int ftp_get(char *name, LONG size, char *local);
int ftp_initconn(void);
int ftp_dataconn(void);
int din, fin, fout;
FILE *dout;
BOOL connected = FALSE;
int fdata=-1, pgrp, code;
struct sockaddr_in myctladdr, data_addr;
char *login, *hostname;
extern APTR app, get_gauge;
int sgetc(int sock)
{
unsigned char c;
fd_set rd,ex;
long flgs;
int n;
struct timeval t;
t.tv_sec = 10L;
t.tv_usec = 0;
FD_ZERO(&rd);
FD_ZERO(&ex);
FD_SET(sock,&rd);
FD_SET(sock,&ex);
flgs = SIGBREAKF_CTRL_D;
WaitSelect(16,&rd,0L,&ex,&t,&flgs);
if (FD_ISSET(sock,&rd))
{ n = recv(sock, &c, 1, 0);
if (n == 1)
return c;
else return -1;
}
else return -1;
}
char *ftp_connect(char *host, char *path)
{
struct sockaddr_in server;
struct servent *sp;
struct hostent *hp;
LONG s, len;
if (connected) {
ftp_command("QUIT");
if (fout)
s_close(fout);
fout = -1;
connected = FALSE;
fdata = -1;
}
sp = getservbyname("ftp", "tcp");
if ((sp = getservbyname("ftp", "tcp")) == NULL)
return("*This site does not support FTP/TCP");
/* hp = gethostbyname(host); */
if ((hp = gethostbyname(host)) == NULL)
return("FTP can't connect : Unknown Host");
bzero((char *)&server, sizeof(server));
bcopy(hp->h_addr, (char *)&server.sin_addr, hp->h_length);
server.sin_family = hp->h_addrtype;
server.sin_port = sp->s_port;
s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0)
return(sys_errlist[errno]);
if (connect(s, (struct sockaddr const *)&server, sizeof(server)) < 0)
return(sys_errlist[errno]);
len = sizeof(myctladdr);
if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0)
return(sys_errlist[errno]);
fout = /*fdopen(s, "w")*/s;
fin = /*fdopen(s, "r")*/s;
/* if (fin == NULL || fout == NULL) {
if (fin) fclose(fin);
if (fout) fclose(fout);
return(sys_errlist[errno]);
} */
/* connected it seems */
connected = 1;
if (ftp_getreply(0) > 2) {
ftp_lostpeer();
return("Remote protocol error, startup message wrong");
}
if (!ftp_login()) {
ftp_lostpeer();
return("Connection refused");
}
/* logged in it seems */
if (ftp_command("TYPE I") != COMPLETE) {
ftp_lostpeer();
return("Remote host has closed the connection");
}
if (ftp_command("CWD %s", path) != COMPLETE) {
char message[256];
ftp_lostpeer();
sprintf(message, "Could not CD to directory \"%s\"\n", path);
return(message);
}
return(NULL);
}
int ftp_getreply(int expecteof)
{
int c, n;
int dig;
int ocode = 0, cont = 0;
for (;;) {
dig = n = code = 0;
while ((c = sgetc(fin)) != '\n') {
if (c == IAC) { /* Telnet? */
switch(c = sgetc(fin)) {
case WILL:
case WONT: {
char temp[20]; int x;
c = sgetc(fin);
x = sprintf(temp, "%c%c%c", IAC, DONT, c);
send(fout, temp, x, NULL);
break;
}
case DO:
case DONT: {
char temp[20]; int x;
c = sgetc(fin);
x = sprintf(temp, "%c%c%c", IAC, WONT, c);
send(fout, temp, x, NULL);
break;
}
default:
break;
}
continue;
}
dig++;
if (c == EOF) {
if (expecteof) {
code = 221;
return(0);
}
ftp_lostpeer();
code = 421;
return(4);
}
if (dig < 4 && isdigit(c))
code = code * 10 + (c - '0');
if (dig == 4 && c == '-') {
if (cont)
code = 0;
cont++;
}
if (n == 0)
n = c;
}
if (cont && code != ocode) {
if (ocode == 0)
ocode = code;
continue;
}
if (code == 421 || ocode == 421)
ftp_lostpeer();
return(n - '0');
}
}
/* send an FTP command */
int ftp_command(char *fmt, ...)
{
va_list args;
char comm[256];
int len;
va_start(args, fmt);
len = vsprintf(comm, fmt, args);
strcpy(&comm[len], "\r\n");
send(fout, comm, len+2, NULL);
va_end(args);
return ftp_getreply(!strncmp(fmt, "QUIT", 4));
}
void ftp_lostpeer()
{
if (connected) {
if (fout >= 0) {
shutdown(fout, 2);
fout = -1;
}
if (fdata >= 0) {
shutdown(fdata, 2);
close(fdata);
fdata = -1;
}
connected = 0;
}
}
int ftp_login()
{
int n;
hostname = getenv("HOSTNAME");
login = getenv("USERNAME");
n = ftp_command("USER ftp");
if (n == CONTINUE)
n = ftp_command("PASS %s@%s", login, hostname);
if (n == CONTINUE)
n = ftp_command("ACCT %s@%s", login, hostname);
if (n == COMPLETE)
return(1);
return(0);
}
/* return 0 on success */
int ftp_get(char *name, LONG size, char *local)
{
char *buffer;
int bytes=0, d=0, c, retval=1;
ULONG signal;
if (ftp_initconn()) {
code = -1;
return(1);
}
if (ftp_command("RETR %s", name) != PRELIM)
return(1);
din = ftp_dataconn();
if (din == NULL)
goto abort;
dout = fopen(local, "w");
if (dout == NULL)
goto abort;
buffer = malloc(BUFSIZ);
if (buffer == NULL)
goto abort;
set(get_gauge, MUIA_Gauge_Current, 0);
set(get_gauge, MUIA_Gauge_InfoText, name);
set(get_gauge, MUIA_Gauge_Max, size);
DoMethod(app, MUIM_Application_Input, &signal);
while ((c = recv(din, buffer, BUFSIZ, NULL)) > 0) {
if ((d = write(fileno(dout), buffer, c)) != c) break;
bytes += c;
if (size != 0)
set(get_gauge, MUIA_Gauge_Current, bytes);
if(DoMethod(app, MUIM_Application_Input, &signal) == ID_GetAbort) {
retval = 2;
goto abort;
}
}
if (d < c)
set(get_gauge, MUIA_Gauge_InfoText, "Error Writing file");
set(get_gauge, MUIA_Gauge_InfoText, NULL);
free(buffer);
fclose(dout);
s_close(din);
ftp_getreply(0);
return(0);
abort:
code = -1;
free(buffer);
if (fdata >= 0) {
close(fdata);
fdata = -1;
}
if (din)
s_close(din);
if (dout)
fclose(dout);
return(retval);
}
int ftp_initconn()
{
register char *p, *a;
int result;
LONG len;
data_addr = myctladdr;
data_addr.sin_port = 0;
if (fdata != -1)
close(fdata);
fdata = socket(AF_INET, SOCK_STREAM, 0);
if (fdata < 0)
return(1);
if (bind(fdata, (struct sockaddr *)&data_addr, sizeof(data_addr)) < 0)
goto bad;
len = sizeof(data_addr);
if (getsockname(fdata, (struct sockaddr *)&data_addr, &len) < 0)
goto bad;
listen(fdata, 1);
a = (char *)&data_addr.sin_addr;
p = (char *)&data_addr.sin_port;
#define UC(b) (((int)b)&0xff)
result = ftp_command("PORT %d,%d,%d,%d,%d,%d", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
return(result != COMPLETE);
bad:
close(fdata);
fdata = -1;
return(1);
}
int ftp_dataconn()
{
struct sockaddr_in from;
int s;
LONG fromlen = sizeof(from);
s = accept(fdata, (struct sockaddr *)&from, &fromlen);
if (s < 0) {
s_close(fdata);
fdata = -1;
return(NULL);
}
s_close(fdata);
fdata = s;
return(fdata);
}