/* 
 * TEE.C - external command.
 *
 * clone from 4nt tee command
 *
 * 01 Sep 1999 - Paolo Pantaleo <paolopan@freemail.it>
 *     started 
 *
 *
 */


#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <malloc.h>



#define TEE_BUFFER_SIZE 8192

/*these are function that emulate the ones used in cmd*/

/*many of them are just copied in this file from their
original location*/

VOID ConOutPuts (LPTSTR szText)
{
	DWORD dwWritten;

	WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), szText, _tcslen(szText), &dwWritten, NULL);
	WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), _T("\n"), 1, &dwWritten, NULL);
}


VOID ConErrPrintf (LPTSTR szFormat, ...)
{
	DWORD dwWritten;
	TCHAR szOut[4096];
	va_list arg_ptr;

	va_start (arg_ptr, szFormat);
	_vstprintf (szOut, szFormat, arg_ptr);
	va_end (arg_ptr);

	WriteFile (GetStdHandle (STD_ERROR_HANDLE), szOut, _tcslen(szOut), &dwWritten, NULL);
}



VOID error_sfile_not_found (LPTSTR f)
{
	ConErrPrintf (_T("Error opening file") _T(" - %s\n"), f);
}




VOID ConErrPuts (LPTSTR szText)
{
	ConErrPrintf(_T("%s\n"),szText );
}


INT main (int argc,char **p)
{
	/*reading/writing buffer*/
	TCHAR buff[TEE_BUFFER_SIZE];

	/*handle for file and console*/
	HANDLE hConsoleIn,hConsoleOut;
	
	/*bytes written by WriteFile and ReadFile*/
	DWORD dwRead,dwWritten;


	BOOL bRet,bAppend=FALSE;


	/*command line parsing stuff*/
	LPTSTR tmp;
	INT i;
	BOOL bQuote;

	/*file list implementation*/	
	LPTSTR *files;
	INT iFileCounter=0;
	HANDLE *hFile;

	/*used to remove '"' (if any)*/
	INT add;

	DWORD dw;


	if (argc < 2)
		return 1;

	if (_tcsncmp (p[1], _T("/?"), 2) == 0)
	{
		ConOutPuts (_T("Copy standard input to both standard output and a file.\n"
		               "\n"
		               "TEE [/A] file...\n"
		               "\n"
		               "  file  One or more files that will receive output.\n"
		               "  /A    Append output to files.\n"));
		return 0;
	}

	files = malloc(sizeof(LPTSTR)*argc);
	hFile = malloc(sizeof(HANDLE)*argc);

	hConsoleIn=GetStdHandle(STD_INPUT_HANDLE);
	hConsoleOut=GetStdHandle(STD_OUTPUT_HANDLE);

	/*parse command line for /a and file name(s)*/
	for(i=1;i <argc;i++)
	{
		bQuote=FALSE;
		add=0;

		if(_tcsnicmp(p[i],_T("/a"),2) == 0)
		{
			bAppend = TRUE;
			continue;
		}

		/*remove quote if any*/
		if (p[i][0] == _T('"'))
		{
			tmp = _tcschr (p[i]+1, _T('"'));
			if (tmp != 0)
			{
				add = 1;
				*tmp= _T('\0');
			}
		}

		/*add filename to array of filename*/
/*
		if(  iFileCounter >= sizeof(files) / sizeof(*files)  )
		{
			ConErrPrintf("too many files, maximum is %d\n",sizeof(files) / sizeof(*files));			
			return 1;
		}
		*/

		files[iFileCounter++]= p[i]+add;
	}

	/*open file(s)*/
	for(i=0;i<iFileCounter;i++)
	{	
		//l=0;
		hFile[i] = CreateFile(files[i],GENERIC_WRITE,
			0,NULL,
			OPEN_ALWAYS,
			FILE_ATTRIBUTE_NORMAL,NULL);

		if (hFile[i] == INVALID_HANDLE_VALUE)
		{
			error_sfile_not_found (files[i]);

			for(i=0;i<iFileCounter;i++)
				CloseHandle (hFile[i]);

			free (files);
			free (hFile);

			return 1;
		}

		/*set append mode*/
		if (bAppend)
		{
			if (GetFileType (hFile[i]) == FILE_TYPE_DISK)
			{
				dw = SetFilePointer (hFile[i],0,NULL,FILE_END);
				if (dw == 0xFFFFFFFF)
				{
					ConErrPrintf(_T("error moving to end of file %s"),files[i]);

					for(i=0;i<iFileCounter;i++)
						CloseHandle (hFile[i]);

					free (files);
					free (hFile);

					return 1;
				}

				ConErrPrintf(_T("SetFilePointer() = %d\n"),dw);
			}
		}
	}

	/*read and write*/
	do
	{
		bRet = ReadFile(hConsoleIn,buff,sizeof(buff),&dwRead,NULL);

		if (dwRead>0 && bRet)
		{
			for(i=0;i<iFileCounter;i++)
				WriteFile(hFile[i],buff,dwRead,&dwWritten,NULL);

			WriteFile(hConsoleOut,buff,dwRead,&dwWritten,NULL);
		}
	} while(dwRead>0 && bRet);

	for(i=0;i<iFileCounter;i++)
		CloseHandle (hFile[i]);

	free (files);
	free (hFile);

	return 0;
}

/* EOF */
