/*
** (c) 1992 Uwe C. Schroeder, Anwendungssysteme , Augsburg, Germany
**
** 
** Permission to use, copy, and modify this software and its
** documentation for non comercial  purpose is hereby granted 
** without fee, provided that
** the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation, and that the name of Uwe C. Schroeder not be used in
** advertising or publicity pertaining to distribution of the software without
** specific, written prior permission.  Uwe Schroeder makes no representations
** about the suitability of this software for any purpose.  It is provided
** "as is" without express or implied warranty.
** This software may not be sold or distributed with commercial products
** ( this includes distribution "for users convenience" ) without prior
** written permission by the author.
**
** UWE SCHROEDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
** INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
** EVENT SHALL UWE SCHROEDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
** CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
** DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
** PERFORMANCE OF THIS SOFTWARE.
**
**
** This is a alpha release, which means, that there are still several
** known bugs.
**
** Please report bugs to:
**
**                     usys@phoenix.abg.sub.org
**
*/


#include <stdio.h>
#include <sys/types.h>
#include <sys/termio.h>
#include <fcntl.h>
#include <signal.h>
#include <setjmp.h>
#include <unistd.h>
#include <pwd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>

#include "vfax.h"

/* input file types */
#define ASCII 0
#define DVI   1
#define PS    2
#define G3    3

int debug = 0;
int local = FALSE;
int fd;
static jmp_buf timeoutbuf;

int
fcopy(in,out)
     char *in,*out;
{
  FILE *o, *i;

  if((o=fopen(out,"w+")) == (FILE *)NULL)
    return -1;

  if((i=fopen(in,"r")) == (FILE *)NULL)
    return -1;
  
  while(!feof(i))
    {
      fputc(fgetc(i),o);
    }
  fclose(i);
  fclose(o);
  return 0;
}

int
check_ftype(fname)
     char *fname;
{
  FILE *f;
  int ret;
  char buf[80];
  char head[10];


  if((f=fopen(fname,"r")) == (FILE *)NULL)
    {
      logto(0,"check_ftype: can't open input file %s \r\n",fname);
      exit(1);
    }
  if(fgets(buf,79,f) != (char *)NULL)
    {
      /* check for postscript */
      if(!strncmp(buf,"%!PS-Adobe-",11))
	ret= PS;

      /* this is not sure !! it's the magic gs writes into a faxfile */
      if(!strncmp(&buf[1],"PC RESEARCH",11))
	ret= G3;

      /* check for a dvi file */
      sprintf(head,"%c%c%c%c%c",'\367','\002','\001','\203','\222');
      if(!memcmp(buf,head,5))
        ret= DVI;
      else
	{
	  int i;
/*	  for(i=0;i<5;i++)
	    printf("TYPE: buf=%d head=%d\r\n",buf[i],head[i]);*/
	}

      ret= ASCII;
    }
  fclose(f);
  return ret;
}

int
linecount(fname)
     char *fname;
{
  FILE *f;
  int i,lc=0;
  /* count lines in file to adjust pagelength (only ascii files )*/

  if((f=fopen(fname,"r")) == (FILE *)NULL)
    {
      Debug(0,"linecount: can't open input file %s \r\n",fname);
      exit(1);
    }

  rewind(f);

  while(!feof(f)) {
    if((i=fgetc(f)) == '\n' || i == '\r')
      lc++;
  }
  Debug(2,"linecount: got %d lines\n",lc);
  rewind(f);
  return lc;
}

void
no_carrier(sig)
     int sig;
{
  logto(0,"CARRIER DOWN");
  return;
}

int 
sigALRM()
{
  longjmp(timeoutbuf, 1);
}


main(argc,argv)
     int argc;
     char *argv[];
{
  FILE *f;
  unsigned char fch[512];
  char tmp[512], tmpn[512];
  long flen;
  int sbytes=0, wbytes, c;
  int errflg = FALSE;
  int do_spool = FALSE;
  int ifntype = ASCII;
  int ex_type = EX_FAX;
  int force_type = FALSE;
  char *ex_cmd;
  char *tn, *ifn;
  Queue qt;
  struct passwd *pwd;
  extern int optind;
  extern char *optarg;
  void *sighand;
  int mq;
  FIPM msg;
  FILE *ipc_file;

  /* open IPC file */
  if((ipc_file=fopen(FAX_IPC_FILE,"r")) == (FILE *)NULL) {
    if(errno == ENOENT) 
      fprintf(stderr,"FATAL: Fax spooler not running\n");
    else
      fprintf(stderr,"FATAL: open ipc_file failed with %d\n",errno);
    exit(errno);
  }

  if(fread(&mq,sizeof(int),1,ipc_file) < 1) {
    fprintf(stderr,"FATAL: fread ipcfile failed with %d\n",errno);
    exit(errno);
  }

  fclose(ipc_file);


  setpgrp(); /* otherwise fas won't send SIGHUP */
  sighand = (void(*)())no_carrier;
  signal(SIGHUP,sighand);

  qt.mail = TRUE;
  qt.maxtries = FAX_SEND_TRIES;
  qt.retries = 0;

  /* parse parameters */
  while ((c = getopt(argc, argv, "ac:rkx:mq:d:stpgh")) != -1)
    switch (c) {
    case 'a':
      msg.mtype = 1;
      msg.mtext[0] = FM_PLAYBACK;
      if(msgsnd(mq,&msg,1,IPC_NOWAIT) < 0) {
	logto(0,"Error %d sending playback message \n",errno);
	exit(errno);
      }
      exit(0);
      break;
    case 'c':
      msg.mtype = 2;
      strncpy(msg.mtext,optarg,30);
      if(msgsnd(mq,&msg,32,IPC_NOWAIT) < 0) {
	logto(0,"Error %d sending call message \n",errno);
	exit(errno);
      }
      exit(0);
      break;
    case 'r':
      msg.mtype = 1;
      msg.mtext[0] = FM_RECFAX;
      if(msgsnd(mq,&msg,1,IPC_NOWAIT) < 0) {
	logto(0,"Error %d sending recfax message \n",errno);
	exit(errno);
      }
      exit(0);
      break;
    case 'k':
      msg.mtype = 1;
      msg.mtext[0] = FM_EXIT;
      if(msgsnd(mq,&msg,1,IPC_NOWAIT) < 0) {
	logto(0,"Error %d sending kill message \n",errno);
	exit(errno);
      }
      exit(0);
      break;
    case 'x':
      if(atoi(optarg) == 0) {
	msg.mtype = 1;
	msg.mtext[0] = FM_RELEASE;
	if(msgsnd(mq,&msg,1,IPC_NOWAIT) < 0) {
	  logto(0,"Error %d sending release message \n",errno);
	  exit(errno);
	}
      } else {
	msg.mtype = 1;
	msg.mtext[0] = FM_REINIT;
	if(msgsnd(mq,&msg,1,IPC_NOWAIT) < 0) {
	  logto(0,"Error %d sending reinit message \n",errno);
	  exit(errno);
	}
      }
      exit(0);
      break;
    case 'd':
      debug = atoi(optarg);
      break;
    case 'm':
      qt.mail = FALSE;
      break;
    case 'q':
      qt.maxtries = atoi(optarg);
      break;
    case 's':
      do_spool = TRUE;
      break;
    case 't': 
      ifntype = DVI;
      force_type = TRUE;
      break;
    case 'p': 
      ifntype = PS;
      force_type = TRUE;
      break;
    case 'g': 
      ifntype = G3;
      force_type = TRUE;
      break;
    case 'h':
    case '?':
      errflg = TRUE;;
      break;
    }
  if (errflg) usage(argv[0]);

  if(argc - optind != 2)
    usage(argv[0]);
  
  strncpy(qt.phone,argv[optind],Q_PHONE_LEN);
  ifn = argv[optind+1];

  pwd = getpwuid(getuid());

  if(!do_spool)
    {
      if((f=fopen(ifn,"r")) == (FILE *)NULL)
	{
	  logto(0,"%s: can't open input file %s \r\n",argv[0],argv[2]);
	  exit(1);
	}
      fd=open_tty(PORT);
      init_fax(fd);
      if(modem_dial(fd,tn)==0)
	{
	  logto(1,"sending file %s\r\n",ifn);
	  send_file(f);
	}
      close_tty(fd);
    }
  else /* send to spooler */
    {
      strncpy(qt.user,pwd->pw_name,Q_USER_LEN);
      queuefile(&qt, tmpn);
      strcat(tmpn,".g3");
      
      if(!force_type)
	ifntype = check_ftype(ifn);
      
      switch(ifntype){
      case G3:
	if(fcopy(ifn,tmpn)<0)
	  {
	    logto(0,"can't copy input file to %s\n",tmpn);
	    exit(1);
	  }
	break;
      case DVI:
	sprintf(tmp,"dvialw %s",ifn);
	if(system(tmp) != 0)
	  {
	    logto(0,"error converting file");
	    exit(1);
	  }
	sprintf(tmp,"cat %s-alw | gs -q -sDEVICE=dfaxhigh -dNOPAUSE -sOutputFile=%s
-",ifn,tmpn);
	if(system(tmp) != 0)
	  {
	    logto(0,"error converting file");
	    exit(1);
	  }
	sprintf(tmp,"%s-alw",ifn);
	unlink(tmp);
	break;
      case PS:
	sprintf(tmp,"cat %s | gs -q -sDEVICE=dfaxhigh -dNOPAUSE -sOutputFile=%s
-",ifn,tmpn);
	if(system(tmp) != 0)
	  {
	    logto(0,"error converting file");
	    exit(1);
	  }
	if(debug) printf("%s spooled successfully\n",ifn);
	break;
      case ASCII:
      default:
	sprintf(tmp,"gs -q -sDEVICE=dfaxhigh -dNOPAUSE -sOutputFile=%s -- gslp.ps
-b\"Uwe C. Schroeder, Anwendungssysteme\" -L%d %s",
		tmpn,linecount(ifn),ifn);
	/*
	  sprintf(tmp,"psify -sz12 -lm36 -pl%d -h\"Uwe C. Schroeder,
Anwendungssysteme\" %s | gs -q -sDEVICE=dfaxhigh -dNOPAUSE -sOutputFile=%s -",
	  linecount(ifn),ifn,tmpn);
	  */
	if(system(tmp) != 0)
	  {
	    logto(0,"error converting file");
	    exit(1);
	  }
	
	if(debug) printf("%s spooled successfully\n",ifn);
	break;
      }
    }
}

int usage(name)
     char *name;
{
  printf("\nusage: %s [-d#] [-s] telno file.g3\n",name);
  printf("\nor:    %s [-d#] -a (playback voice msgs)\n",name);
  printf("\nor:    %s [-d#] -c telno  (dial telno)\n",name);
  printf("\nor:    %s [-d#] -k  (kill spooler)\n",name);
  printf("\nor:    %s [-d#] -r  (receive fax now)\n",name);
  printf("\nor:    %s [-d#] -x0  (release tty)",name);
  printf("\nor:    %s [-d#] -x1  (reinit tty)\n",name);
  printf("where:\n\t-d# = debug\n");
  printf("\t-s  = send to spooler\n");
  printf("\t-m  = no mail notification\n");
  printf("\t-q# = max retry count\n");
  printf("\t-p  = input file is postscript\n");
  printf("\t-t  = input file is a TeX dvi format\n");
  printf("\t-g  = input file is a fax G3 format\n");
  printf("\tdefault input file type is ASCII\n");
  exit(0);
}
