/*
 *  Tee - Join pipes and make copies of input.
 *  Copyright (C) 1989, 1992, 1993 Torsten Poulin
 *
 *  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 of the License, 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.
 *
 *  The author can be contacted by s-mail at
 *    Torsten Poulin
 *    Banebrinken 99, 2, 77
 *    DK-2400 Copenhagen NV
 *    DENMARK
 *
 * $Id: Tee.c,v 37.5 93/06/21 18:13:15 Torsten Rel $
 * $Log:	Tee.c,v $
 * Revision 37.5  93/06/21  18:13:15  Torsten
 * Throughput increased by the addition of a 16k buffer.
 * Tee no longer complains when it cannot open a specified
 * output file (the message was swallowed by the pipe under
 * WShell).
 * 
 * Revision 37.4  93/02/13  16:44:20  Torsten
 * Forgot the initial '$' in the copyright tag.
 * 
 * Revision 37.3  93/02/13  16:36:57  Torsten
 * Replaced exec.library/SetSignal() with dos.library/CheckSignal().
 * Removed IGNORE switch because it seemed pretty silly.
 * 
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include "tee_rev.h"

#define OPT_TO      0
#define OPT_APPEND  1
#define BUFLEN 16384L

char const versionID[] = VERSTAG;
char const copyright[] = "$COPYRIGHT:© 1989,1992,1993 Torsten Poulin$";

struct fileList {
  struct fileList *next;
  BPTR file;
};

LONG entrypoint(VOID)
{
  struct RDArgs        *args;
  struct DosLibrary    *DOSBase;
  struct fileList *list, *p;
  BPTR *buffer;
  BPTR in, out;
  LONG rlen;
  LONG arg[2];
  LONG rc = RETURN_OK;

  if (!(DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37L)))
    return RETURN_FAIL;

  arg[OPT_TO] = arg[OPT_APPEND] = 0L;
  in = Input();
  out = Output();

  if (!(buffer = AllocVec(BUFLEN, MEMF_ANY))) {
    PrintFault(ERROR_NO_FREE_STORE, "Tee");
    rc = RETURN_FAIL;
  }
  else {
    if (args = ReadArgs("TO/M,APPEND/S", arg, NULL)) {
      if (arg[OPT_TO]) {
	UBYTE **name;
	struct fileList *newnode;
	LONG mode;
	BPTR file;
            
	mode = arg[OPT_APPEND] ? MODE_READWRITE : MODE_NEWFILE;
            
	list = NULL;
	/* Open the files */
	for (name = (UBYTE **) arg[OPT_TO]; *name; name++) {
	  if (!(file = Open(*name, mode)))
	    continue;
	  if (arg[OPT_APPEND])
	    Seek(file, 0L, OFFSET_END);

	  /* Store the filehandle */
	  if (!(newnode = AllocVec(sizeof(struct fileList), MEMF_ANY))) {
	    PrintFault(ERROR_NO_FREE_STORE, "Tee");
	    rc = RETURN_FAIL;
	    goto bail_out;
	  }
	  newnode->file = file;
	  newnode->next = list;
	  list = newnode;
	}
      }

      /* Do the copying ... */
      while ((rlen = Read(in, buffer, BUFLEN)) > 0) {
	if (CheckSignal(SIGBREAKF_CTRL_C)) {
	  rc = RETURN_WARN;
	  break;
	}
	Write(out, buffer, rlen);
	for (p = list; p; p = p->next)
	  Write(p->file, buffer, rlen);
      }
    bail_out:       
      /* Close the files and free up memory*/
      for (p = list; p; ) {
	struct fileList *remember;
                
	remember = p;
	Close(p->file);
	p = p->next;
	FreeVec(remember);
      }
      FreeArgs(args);
    }
    else {
      LONG err = IoErr();
      PrintFault(err, "Tee");
      rc = RETURN_ERROR;
    }
    FreeVec(buffer);
  }
  CloseLibrary((struct Library *) DOSBase);
  return rc;
}
