DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T f

⟦5a05eba8e⟧ TextFile

    Length: 10020 (0x2724)
    Types: TextFile
    Names: »ftp.c«

Derivation

└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
    └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« 
        └─⟦de7628f85⟧ 
            └─⟦this⟧ »isode-6.0/ftam-ftp/ftp.c« 

TextFile

/* ftp.c - FTP client */

#ifndef lint
static	char *rcsid = "$Header: /f/osi/ftam-ftp/RCS/ftp.c,v 7.0 89/11/23 21:55:04 mrose Rel $"; /* from UCB 4.11 7/26/83 */
#endif

/* 
 * $Header: /f/osi/ftam-ftp/RCS/ftp.c,v 7.0 89/11/23 21:55:04 mrose Rel $
 *
 *
 * $Log:	ftp.c,v $
 * Revision 7.0  89/11/23  21:55:04  mrose
 * Release 6.0
 * 
 */

/*
 *				  NOTICE
 *
 *	The MITRE Corporation (hereafter MITRE) makes this software available 
 *	on an "as is" basis.  No guarantees, either explicit or implied, are 
 *	given as to performance or suitability.  
 *
 */

/*
 *	Shamelessly taken from UCB
 */

#include "config.h"
#include <sys/param.h>
#include <sys/ioctl.h>
#include "internet.h"
#include <sys/time.h>

#include <arpa/ftp.h>

#include <stdio.h>
#include <errno.h>
#include <varargs.h>

#include "ftp_var.h"
#include "general.h"
#include "logger.h"
void	advise ();

#ifndef NOTOK
#define NOTOK (-1)
#define OK	0
#define DONE	1
#endif /* NOTOK */

int	verbose = 0;

struct	sockaddr_in hisctladdr;
struct	sockaddr_in data_addr;
int	data = -1;
int	connected = 0;
struct	sockaddr_in myctladdr;

FILE	*cin, *cout;
int	dataconn();


ftp_init()
{ /* default ftp communication values */

	(void)strcpy(typename, "ascii"), type = TYPE_A;
        (void)strcpy(formname, "non-print"), form = FORM_N;
        (void)strcpy(modename, "stream"), mode = MODE_S;
        (void)strcpy(structname, "file"), stru = STRU_F;
        (void)strcpy(bytename, "8"), bytesize = 8;
	ftp_directory = 0;
	ftp_error = ftp_error_buffer;
	verbose = isatty (fileno (stderr));
}

hookup(host, port)
	char *host;
	int port;
{
	register struct hostent *hp;
	int s, len;

	bzero((char *)&hisctladdr, sizeof (hisctladdr));
	hp = gethostbyname(host);
	if (hp == NULL) {
#ifdef	h_addr
	        static char *addrs = NULL;
#endif
		static struct hostent def;
		static struct in_addr defaddr;
		static char namebuf[128];
		u_long inet_addr();

		defaddr.s_addr = inet_addr(host);
		if (defaddr.s_addr == -1) {
			(void)sprintf(ftp_error, "%s: Unknown host.", host);
			return (NOTOK);
		}
		(void)strcpy(namebuf, host);
		def.h_name = namebuf;
		hostname = namebuf;
#ifdef	h_addr
		def.h_addr_list = &addrs;
#endif
		def.h_addr = (char *)&defaddr;
		def.h_length = sizeof (struct in_addr);
		def.h_addrtype = AF_INET;
		def.h_aliases = 0;
		hp = &def;
	}
	hostname = hp->h_name;
	hisctladdr.sin_family = hp->h_addrtype;
	s = socket(hp->h_addrtype, SOCK_STREAM, 0);
	if (s < 0) {
		(void)sprintf(ftp_error,"ftp: socket %s",
			(errno <= sys_nerr)? sys_errlist[errno]:"");
		return (NOTOK);
	}
	if (bind(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
		(void)sprintf(ftp_error,"ftp: bind %s",
			(errno <= sys_nerr)? sys_errlist[errno]:"");
		goto bad;
	}
	inaddr_copy (hp, &hisctladdr);
	hisctladdr.sin_port = htons ((u_short) port);
	if (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
		(void)sprintf(ftp_error,"ftp: connect %s",
			(errno <= sys_nerr)? sys_errlist[errno]:"");
		goto bad;
	}
	len = sizeof (myctladdr);
	if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
		(void)sprintf(ftp_error,"ftp: getsockname %s",
			(errno <= sys_nerr)? sys_errlist[errno]:"");
		goto bad;
	}
	cin = fdopen(s, "r");
	cout = fdopen(s, "w");
	if (cin == NULL || cout == NULL) {
		(void)sprintf(ftp_error, "ftp: fdopen failed.");
		if (cin)
			(void)fclose(cin);
		if (cout)
			(void)fclose(cout);
		goto bad;
	}
	(void) getreply(0); 		/* read startup message from server */
	connected = 1;
	return (OK);
bad:
	(void)close(s);
	return (NOTOK);
}

login(user,pass,acct)
	char *user, *pass, *acct;
{
	int n;

	if (!user){
		(void)sprintf(ftp_error, "Username required");
		return(NOTOK);
	}
	n = command("USER %s", user);
	if (n == CONTINUE){
		if (!pass){
			(void)sprintf(ftp_error, "Password required");
			return(NOTOK);
		}
		n = command("PASS %s", pass);
	}
	if (n == CONTINUE) {
		if (!acct){
			(void)sprintf(ftp_error, "Account required");
			return(NOTOK);
		}
		n = command("ACCT %s", acct);
	}
	if (n != COMPLETE) {
		(void)sprintf(ftp_error, "Login failed.");
		return (NOTOK);
	}
	return (OK);
}

#ifndef	lint
command(va_alist)
va_dcl
{
    int	    val;
    va_list ap;

    va_start (ap);

    val = _command (ap);

    va_end (ap);

    return val;
}

_command(ap)
va_list ap;
{
    char buffer[BUFSIZ];

	if (cout == NULL) {
		(void)sprintf(ftp_error,"No control connection for command %s",
			(errno <= sys_nerr)? sys_errlist[errno]:"");
		return (NOTOK);
	}

	_asprintf (buffer, NULLCP, ap);
	fprintf (cout, "%s\r\n", buffer);
	(void) fflush(cout);
	if (verbose)
	    advise (LLOG_DEBUG, NULLCP, "<--- %s", buffer);
	return (getreply(!strcmp(buffer, "QUIT")));
}
#else
/* VARARGS1 */

command (fmt)
char   *fmt;
{
    return command (fmt);
}
#endif

#include <ctype.h>

getreply(expecteof)
	int expecteof;
{
	register int c, n;
	register int code, dig;
	int originalcode = 0, continuation = 0;
	char *mesg;

	mesg = ftp_error_buffer;
	for (;;) {
		dig = n = code = 0;
		while ((c = getc(cin)) != '\n') {
			dig++;
			if (c == EOF) {
				if (expecteof)
					return (0);
				lostpeer();
				advise (LLOG_EXCEPTIONS,NULLCP,"getreply: %s",
					ftp_error_buffer);
				return(1);
				/* exit(1); */
			}
			if (c != '\r') *mesg++ = c;
			else *mesg = '\0';
			if (dig < 4 && isdigit(c))
				code = code * 10 + (c - '0');
			if (dig == 4 && c == '-')
				continuation++;
			if (n == 0)
				n = c;
		}
		if (continuation && code != originalcode) {
			if (originalcode == 0)
				originalcode = code;
			continue;
		}
		if (verbose)
		    advise (LLOG_DEBUG,NULLCP,"---> %s",
			    ftp_error_buffer);
		return (n - '0');
	}
}

/*
 *  sendrequest and recvrequest routines have been modified to send the
 *  appropriate remote command then open and return a file descriptor (socket).
 *  The FTAM code treats this as though it were a local file (which
 *  is about what FTP does)
 */
int
sendrequest(cmd, /* local, */ remote)
	char *cmd, /* *local, */ *remote;
{
	int dout;
	int expectingreply = 0;

	if (initconn())
		goto bad;
	if (remote) {
		if (command("%s %s", cmd, remote) != PRELIM)
			goto bad;
	} else
		if (command("%s", cmd) != PRELIM)
			goto bad;
	expectingreply++; /* got preliminary reply, expecting final reply */
	dout = dataconn("w");
	if (dout == NOTOK)
		goto bad;
	return(dout);

bad:
	if (data >= 0)
		(void) close(data), data = -1;
        if (expectingreply) {
                (void) getreply(0);
                expectingreply = 0;
        }
        return(NOTOK);
}

int
recvrequest(cmd, /* local,*/ remote)
	char *cmd, /* *local,*/ *remote;
{
	int din;
	int expectingreply = 0;

	if (initconn())
		goto bad;
	if (remote) {
		if (command("%s %s", cmd, remote) != PRELIM)
			goto bad;
	} else
		if (command("%s", cmd) != PRELIM)
			goto bad;
	expectingreply++;   /* got preliminary reply, expecting final reply */
	din = dataconn("r");
	if (din == NOTOK)
		goto bad;
	return(din);
bad:
	if (data >= 0)
		(void) close(data), data = -1;
	if (expectingreply) {
		(void) getreply(0);
		expectingreply = 0;
	}
	return(NOTOK);
}

/*
 * Need to start a listen on the data channel
 * before we send the command, otherwise the
 * server's connect may fail.
 */
int sendport = -1;

initconn()
{
	register char *p, *a;
	int result, len;
#ifdef	BSD43
	int	on = 1;
#endif

noport:
	data_addr = myctladdr;
	if (sendport)
		data_addr.sin_port = 0;	/* let system pick one */ 
	if (data != -1)
		(void) close (data);
	data = socket(AF_INET, SOCK_STREAM, 0);
	if (data < 0) {
		(void)sprintf(ftp_error,"ftp: socket %s",
			(errno <= sys_nerr)? sys_errlist[errno]:"");
		return (NOTOK);
	}
	if (!sendport)
#ifndef	BSD43
		if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *) 0, 0) < 0) {
#else
		if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on) < 0) {
#endif
		(void)sprintf(ftp_error,"ftp: setsockopt (reuse address) %s",
			(errno <= sys_nerr)? sys_errlist[errno]:"");
			goto bad;
		}
	if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
		(void)sprintf(ftp_error,"ftp: bind %s",
			(errno <= sys_nerr)? sys_errlist[errno]:"");
		goto bad;
	}
	if (options & SO_DEBUG &&
#ifndef	BSD43
	    setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *) 0, 0) < 0)
#else
	    setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *) &on, on) < 0)
#endif
		(void)sprintf(ftp_error,"ftp: setsockopt (ignoreg) %s",
			(errno <= sys_nerr)? sys_errlist[errno]:"");
	len = sizeof (data_addr);
	if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
		(void)sprintf(ftp_error,"ftp: getsockname  %s",
			(errno <= sys_nerr)? sys_errlist[errno]:"");
		goto bad;
	}
	if (listen(data, 1) < 0) {
		(void)sprintf(ftp_error,"ftp: listen  %s",
			(errno <= sys_nerr)? sys_errlist[errno]:"");
		goto bad;
	}
	if (sendport) {
		a = (char *)&data_addr.sin_addr;
		p = (char *)&data_addr.sin_port;
#define	UC(b)	(((int)b)&0xff)
		result =
		    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]));
		if (result == ERROR && sendport == -1) {
			sendport = 0;
			goto noport;
		}
		return ((result == COMPLETE)?OK:NOTOK);
	}
	return (OK);
bad:
	(void) close(data), data = -1;
	return (NOTOK);
}

/*ARGSUSED */
int
dataconn(modeX)
	char *modeX;
{
	struct sockaddr_in from;
	int s, fromlen = sizeof (from);

	s = accept(data, (struct sockaddr *) &from, &fromlen);
	if (s < 0) {
		(void)sprintf(ftp_error,"ftp: accept  %s",
			(errno <= sys_nerr)? sys_errlist[errno]:"");
		(void) close(data), data = -1;
		return (NOTOK);
	}
	(void) close(data);
	data = s;
	return (data);
}

lostpeer()
{
 
        if (connected) {
                if (cout != NULL) {
                        (void)shutdown(fileno(cout), 1+1);
                        (void)fclose(cout);
                        cout = NULL;
                }
                if (data >= 0) {
                        (void) shutdown(data, 1+1);
                        (void) close(data);
                        data = -1;
                }
                connected = 0;
        }
}