#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <setjmp.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/ftp.h>
#include "ftpd.h"
#include "cmdimp.h"

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/multiuser.h>
#include <libraries/multiuser.h>

#define MAXHOSTNAMELEN 60
int gethostname(char *,int);

char Buf[1024];			// sprintf buffer
struct muBase *muBase;
struct muUserInfo *UserInfo;	// Info over huidig ingeloggde user

void yyparse(void);

extern char cbuf[];

int	data;
jmp_buf	errcatch, urgcatch;
int	logged_in;
int askpasswd;
char *pw;
int	timeout = 900;    /* timeout after 15 minutes of inactivity */
int	maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
int	guest;
int	type;
int	form;
int	stru;			/* avoid C keyword */
int	mode;
int	usedefault=1;		/* for data transfers */
int	pdata = -1;		/* for passive mode */
int	transflag;
long file_size;
long byte_count;

struct	sockaddr_in ctrl_addr;
struct	sockaddr_in data_source;
struct	sockaddr_in data_dest;
struct	sockaddr_in his_addr;
struct	sockaddr_in pasv_addr;

#if !defined(CMASK) || CMASK == 0
#undef CMASK
#define CMASK 027
#endif

int	defumask = CMASK;		/* default umask value */
char	tmpline[7];
char	hostname[MAXHOSTNAMELEN];
char	remotehost[MAXHOSTNAMELEN];

void socketflush(long socket)
{
}

int socketvprintf(long socket,char *fmt,va_list args)
{
	int x;
	
	x=vsprintf(Buf,fmt,args);
	send(socket,Buf,strlen(Buf),0);
	
	return x;
}
	
int socketprintf(long socket,char *fmt,...)
{
	va_list ap;
	int x;
	
	va_start(ap,fmt);
	x=socketvprintf(socket,fmt,ap);
	va_end(ap);
	
	return x;
}

int socketstdprintf(char *fmt,...)
{
	va_list ap;
	int x;
	
	va_start(ap,fmt);
	x=vprintf(fmt,ap);
	va_end(ap);
	
	return x;
}
	
int socketputs(long socket,char *s)
{
	send(socket,s,strlen(s),0);

	return 0;
}

int socketputchar(long socket,char c)
{
	send(socket,&c,1,0);
	
	return 0;
}


int socketgetchar(long socket)
{
	char c;
	
	if(recv(socket,(char *)&c,1,0)==-1) return EOF;
	
	return (int)c;
}

void fatal(char *s)
{
	reply(451, "Error in server: %s\n", s);
	reply(221, "Closing connection due to server error.");
}

void reply(int n,char *fmt,...)
{
	va_list ap;
	
	printf("%d ", n);
	va_start(ap,fmt);
	vprintf(fmt,ap);
	va_end(ap);
	puts("\r\n");
}

void lreply(int n,char *fmt,...)
{
	va_list ap;
	
	printf("%d- ",n);
	va_start(ap,fmt);
	vprintf(fmt,ap);
	va_end(ap);
	puts("\r\n");
}

void ack(char *s)
{
	reply(250, "%s command successful.", s);
}

void nack(char *s)
{
	reply(502, "%s command not implemented.", s);
}

void perror_reply(int code,char *string)
{
	if (errno < sys_nerr)
		reply(code, "%s: %s.", string, sys_errlist[errno]);
	else
		reply(code, "%s: unknown error %d.", string, errno);
}	

void yyerror(char *s)
{
	char *cp;

	if (cp = index(cbuf,'\n'))
		*cp = '\0';
	reply(500, "'%s': command not understood.", cbuf);
}

void end_login(void)
{
	pw = NULL;
	logged_in = 0;
	guest = 0;
}

void CloseMultiUser(void) {
	if(UserInfo) muFreeUserInfo(UserInfo);
	if(muBase) CloseLibrary((struct Library *)muBase);
}

void main(void)
{
	char *hn;
	long addrlen;
	
	if(server_socket==-1) exit(20);
	
	// Openen multiuser library
	atexit(CloseMultiUser);
	muBase=(struct muBase *)OpenLibrary(MULTIUSERNAME,MULTIUSERVERSION);
	if(muBase && !(UserInfo=muAllocUserInfo())) exit(1);
	
	addrlen = sizeof (his_addr);
	if (getpeername(0,(struct sockaddr *)&his_addr, &addrlen) < 0)
	{
		exit(1);
	}
	addrlen = sizeof (ctrl_addr);
	if (getsockname(0,(struct sockaddr *)&ctrl_addr, &addrlen) < 0)
	{
		exit(1);
	}
	data_source.sin_port=htons(ntohs(ctrl_addr.sin_port)-1);
	
	data = pdata = -1;
	type = TYPE_A;
	form = FORM_N;
	stru = STRU_F;
	mode = MODE_S;
	tmpline[0] = '\0';
	
	hn=getenv("HOSTNAME");
	if(hn) strncpy(hostname,hn,sizeof(hostname));
	else strcpy(hostname,"unknown");
	free(hn);
	
	reply(220, "%s FTP server (AMIGA 1.0) ready.", hostname);
	(void) setjmp(errcatch);
	for (;;)
		yyparse();	
}
