/* Copyright (C) 1999 Beau Kuiper

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */

#include "ftpd.h"

#define OUTBUFSIZE	1024

void control_timeout(int num)
{
	signal(SIGALRM, control_timeout);
}

int ftp_write(FTPSTATE *peer, int bare, int messnum, char *fmt, ...)
{ 
	int error, outlen, errornum, count;
	va_list printfargs;
	char number[10];
	int logstartpos = STRLENGTH(peer->outbuffer);

	/* Make the output string, and store it in the buffer */
	if (!bare)
	{
		number[0] = messnum / 100 + '0';
		number[1] = messnum % 100 / 10 + '0';
		number[2] = messnum % 10 + '0';
		number[3] = ' ';
		string_cat(&(peer->outbuffer), number, 4);
	}

	va_start(printfargs, fmt);
	outlen = vsnprintf(NULL, 0, fmt, printfargs);
	va_end(printfargs);
	
	va_start(printfargs, fmt);
	string_catvprintf(&(peer->outbuffer), outlen, fmt, printfargs);
	va_end(printfargs);

	if (!bare)
		log_addentry(MYLOG_RESPONSE, peer, STRTOCHAR(peer->outbuffer) + logstartpos);

	/* add the end-of-line chars to the string */
	string_cat(&(peer->outbuffer), "\r\n", 2);
	outlen = STRLENGTH(peer->outbuffer);

	/* dump the buffer if it is full enough or if end of response! */
	error = 0; errornum = 0;
	if ((!bare) || (outlen > BUFFERSIZE))
	{
		count = 0;
		signal(SIGALRM, control_timeout);

		/* make sure all data is written! */
		while ((count < outlen) && (error != -1))
		{
			alarm(peer->timeout);
			error = write(peer->remotefd, STRTOCHAR(peer->outbuffer) + count, outlen - count);
			count += error;
		}
		string_clear(&(peer->outbuffer));
		errornum = errno;
		alarm(0);
	}
	
	if (error == -1)
	{
		log_giveentry(MYLOG_LOGIN, peer, safe_snprintf("Dropping connection, reason: %s", strerror(errornum)));
 		exit(0);
	}
	
	return(FALSE);
}
