/*--------------------------------------------------------------------------*\

    FAXMAIN.C	Version 1.1					    1995 AVM

    's'+'S' Send fax
    'r'+'R' Receive fax

\*--------------------------------------------------------------------------*/
#if !defined (NDEBUG)
#define DEBUG
#define CPROT
#endif

#include <stdio.h>
#ifndef __linux__
#include <conio.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <assert.h>
#include <ctype.h>

#include "capi20.h"
#include "c20msg.h"
#include "capi.h"
#include "connect.h"
#include "contr.h"
#include "data.h"
#include "id.h"
#include "init.h"
#include "fax.h"
#ifdef __linux__
#include "linuti.h"
#endif


/*--------------------------------------------------------------------------*\
\*--------------------------------------------------------------------------*/
/*----- note: you may enter your own number here, but if you -----*/
/*-----       supply a wrong number, some PBXs may reject the  -----*/
/*-----       CAPI messages containing the wrong number -----*/
/*----- e.g.: static  char    *CallingPartyNumber = "1234567"; -----*/
static  char    *CallingPartyNumber = NULL;

static	char	CalledPartyNumberArr[40];

#ifdef DEBUG
static char	CAPI_PROT_BUF[CAPI_PROTOCOL_INIT_BUF_SIZE];
static char	ProtocolFileName[80];
static FILE	*ProtocolFile;
#endif

#define INVALID_SLOT	-1
#define maxSlots	2	/*----- this demo program handles max. -----*/
				/*----- two connections -----*/
static	ConnectionID	Slot[maxSlots];


#define B1PROTOCOL	    4
#define B2PROTOCOL	    4
#define B3PROTOCOL	    4


#define QueueSize   8

typedef struct __DataElement {
    char	    DATA[SendBlockSize];
    unsigned short  DATA_LENGTH;
    unsigned	    SENT;
} _DataElement;

typedef struct	__DataQueue {
    _DataElement    Element[QueueSize];
    unsigned	    Head;
    unsigned	    Tail;
    unsigned	    Fill;
} _DataQueue;

_DataQueue	    Queue;

static unsigned FileTransfer = FALSE; /*----- signals if filetransfer is in progress -----*/
static unsigned FileReceive  = FALSE; /*----- signals if filetransfer is in progress -----*/
static FILE	*File;
unsigned short FaxResolution = FAX_STANDARD_RESOLUTION;

/*--------------------------------------------------------------------------*\
 * Press_Key:
\*--------------------------------------------------------------------------*/
int Press_Key(void) {
    int c;

    if ((c = getch()) == 0)
	c = getch()+256;
    return c;
}

/*--------------------------------------------------------------------------*\
 * GetSlot: returns the slotnumber of the ConnectionID or INVALID_SLOT
\*--------------------------------------------------------------------------*/
int GetSlot(ConnectionID Con) {
    int     x;

    for (x=0; x<maxSlots; x++)
	if (Slot[x] == Con) return x;
    return INVALID_SLOT;
}

/*--------------------------------------------------------------------------*\
 * AllocSlot: allocates one slot, if none free returns INVALID_SLOT
\*--------------------------------------------------------------------------*/
int AllocSlot(ConnectionID Con) {
    int     x;

    for (x=0; x<maxSlots; x++)
	if (Slot[x] == INVALID_CONNECTION_ID) {
	    Slot[x] = Con;
	    return x;
	}
    return INVALID_SLOT;
}

/*--------------------------------------------------------------------------*\
 * FreeSlot: clear one slot
\*--------------------------------------------------------------------------*/
void FreeSlot(int index) {
    Slot[index] = INVALID_CONNECTION_ID;
}

/*--------------------------------------------------------------------------*\
 * MainDataAvailable: signals received data blocks
 * This function is called after a DATA_B3_INDication is received. The flag
 * DiscardData tells CAPI to free the memora area directly after the return
 * of this function when set to TRUE (1) which is the preset. When the flag
 * is set to FALSE (0) the data area MUST be freed later with ReleaseData.
 * The datahandle identifies the memory area. When reaching 7 unconfirmed
 * blocks, no more incoming data will be signaled until freeing at least
 * one block.
\*--------------------------------------------------------------------------*/
void MainDataAvailable(ConnectionID    Connection,
		       void __far      *Data,
		       unsigned short  DataLength,
		       unsigned short  DataHandle,
		       int	       *DiscardData) {

    assert (Connection != INVALID_CONNECTION_ID);


    CAPI_PROTOCOL_TEXT("***** incoming data, slot %d ID %d, size %d , handle %u *****\n",
                     GetSlot(Connection), Connection, DataLength, DataHandle);
    if ((FileReceive) && (File != NULL)) {
	fwrite(Data, 1, DataLength, File);
    }
    *DiscardData = TRUE;
}

/*--------------------------------------------------------------------------*\
 * MainDataConf: signals the successful sending of a datablock
 * This function is called after receiving a DATA_B3_CONFirmation. CAPI signals
 * that the datablock identified by DataHandle has been sent and the memory
 * area may be freed. The DataHandle is the same as specified in SendBlock.
\*--------------------------------------------------------------------------*/
void MainDataConf(ConnectionID	  Connection,
		  unsigned short  DataHandle,
		  unsigned short  Info) {

    assert (Connection != INVALID_CONNECTION_ID);


    if (Info != 0) {
        CAPI_PROTOCOL_TEXT("***** datablock slot %d ID %d handle %d NOT sent , error: 0x%04X *****\n",
			    GetSlot(Connection), Connection, DataHandle, Info);
	return;
    }
    if (FileTransfer) {

	assert (DataHandle == (unsigned short)Queue.Tail);

	Queue.Element[Queue.Tail].SENT = FALSE;
	if (++Queue.Tail >= QueueSize) Queue.Tail = 0;
	Queue.Fill--;
    }
    CAPI_PROTOCOL_TEXT("***** datablock slot %d ID %d handle %d has been sent *****\n",
                        GetSlot(Connection), Connection, DataHandle);
}

/*--------------------------------------------------------------------------*\
 * MainStateChange: signals a state change on both B-channels (connected,
 * disconnected). Whenever a channel changes his state this function is called
\*--------------------------------------------------------------------------*/
void MainStateChange(ConnectionID     Connection,
		     ConnectionState  State) {
    int     index;

    assert (Connection != INVALID_CONNECTION_ID);


    index = GetSlot(Connection);
    CAPI_PROTOCOL_TEXT("***** state change slot %d ID %d: %s *****\n", index, Connection,
						ConnectionStateString[State]);
    if (State == Disconnected) {
	FreeSlot(index);
    }
}



/*--------------------------------------------------------------------------*\
 * MainIncomingCall: signals an incoming call
 * This function will be executed if a CONNECT_INDication appears to
 * inform the user.
\*--------------------------------------------------------------------------*/
void MainIncomingCall(ConnectionID  Connection,
		      char	    *CallingPartyNumber) {

    int 	    index;
    B3_PROTO_FAXG3  B3conf;

    assert (Connection != INVALID_CONNECTION_ID);


    CAPI_PROTOCOL_TEXT("***** incoming call ,ID %d, caller: \"%s\" *****\n",Connection,CallingPartyNumber);
    index = AllocSlot(Connection);

    SetupB3Config( &B3conf, FAX_SFF_FORMAT, FaxResolution);

    if (index == INVALID_SLOT) {
        CAPI_PROTOCOL_TEXT("***** no free slot available, rejecting call... *****\n");
	AnswerCall(Connection, REJECT, 4, 4, 4, (_cstruct)&B3conf);
	return;
    }
    CAPI_PROTOCOL_TEXT("***** call assigned to slot %d *****\n", index);

    AnswerCall(Connection, ACCEPT, 4, 4, 4, (_cstruct)&B3conf);
}

#ifdef DEBUG

/*--------------------------------------------------------------------------*\
 * CAPI_PROT_HANDLE: This is a callback-function that has been specified
 * with CAPI_PROTOCOL_INIT. The first parameter is a pointer to the protocol-
 * message which is plain ASCII-text. The parameter t contains the type of
 * the message which can be CAPI_PROTOCOL_HEADER (appears only once when
 * calling CAPI_PROTOCOL_INIT), CAPI_PROTOCOL_MSG (the text contains a
 * decoded CAPI-message) and CAPI_PROTOCOL_TXT (the buffers contains a debug
 * message or a message sent with the function CAPI_PROTOCOL_TEXT).
 * If the type of the message is CAPI_PROTOCOL_MSG, the last parameter contains
 * a pointer to the decoded CAPI-message.
\*--------------------------------------------------------------------------*/
void CAPI_PROT_HANDLE(char		 *Message,
		      CAPI_PROTOCOL_TYP  t,
		      CAPI_MESSAGE	 m) {

    fprintf(ProtocolFile,"%s",Message);
    if (t != CAPI_PROTOCOL_MSG)
	puts(Message);

    if (t == CAPI_PROTOCOL_MSG) {
	_cmsg	CMSG;

	CAPI_MESSAGE_2_CMSG(&CMSG, m);
	if ((FileTransfer || FileReceive) &&
		(CMSG.Command == CAPI_DATA_B3) && (CMSG.Info == 0) &&
		(CMSG.Reason == 0) && (CMSG.Reason_B3 == 0)) {

	    return;
	}
	puts(Message);
	if (CMSG.Info != 0) {
	    printf("Info 0x%04X: %s\n",CMSG.Info,Decode_Info(CMSG.Info));
	    fprintf(ProtocolFile,"Info 0x%04X: %s\n",CMSG.Info,Decode_Info(CMSG.Info));
	}
	if (CMSG.Reason != 0) {
	    printf("Reason 0x%04X: %s\n",CMSG.Reason,Decode_Info(CMSG.Reason));
	    fprintf(ProtocolFile,"Reason 0x%04X: %s\n",CMSG.Reason,Decode_Info(CMSG.Reason));
	}
	if (CMSG.Reason_B3 != 0) {
	    printf("Reason_B3 0x%04X: %s\n",CMSG.Reason_B3,Decode_Info(CMSG.Reason_B3));
	    fprintf(ProtocolFile,"Reason_B3 0x%04X: %s\n",CMSG.Reason_B3,Decode_Info(CMSG.Reason_B3));
	}
    }

}

/*--------------------------------------------------------------------------*\
 * Prot_Init: Initialisation of the protocol
\*--------------------------------------------------------------------------*/
int Prot_Init(char *Filename) {
    char *p;

/*
    strcpy(ProtocolFileName, Filename);
    p = strrchr(ProtocolFileName, '.');
    if (p) *p = '\0';
    strcat(ProtocolFileName, ".prt");
*/
    strcpy(ProtocolFileName, "/tmp/isdnsend.prot");
    if ((ProtocolFile=fopen(ProtocolFileName, "w"))==NULL) {
        printf("Can't open protocol-file !!\n");
	return FALSE;
    }
    CAPI_PROTOCOL_INIT(CAPI_PROT_BUF, CAPI_PROT_HANDLE);
    return TRUE;
}
#endif

/*--------------------------------------------------------------------------*\
 * The following _h functions are 'h'igh level functions for the ones
 * implemented in CONNECT.C . The _h functions perform some parameter tests
 * that would cause an assert on the low-level functions.
\*--------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------*\
 * Connect_h: Asks for a number to call then executes 'Connect'
\*--------------------------------------------------------------------------*/
unsigned Connect_h(ConnectionID        *Connection,
		   char 	       *CallingPartyNumber,
		   unsigned long       Service,
		   unsigned short      B1Protocol,
		   unsigned short      B2Protocol,
		   unsigned short      B3Protocol,
		   unsigned char __far *B3Configuration) {

    if (*Connection != INVALID_CONNECTION_ID) {
	printf("Connect_h: Connection is already in use\n");
	return 0xFFFF;
    }

    printf("Enter Number to call: ");
    fflush (stdout);
    gets(CalledPartyNumberArr);

    return Connect(Connection,
		   CalledPartyNumberArr,
		   CallingPartyNumber,
		   Service,
		   B1Protocol,
		   B2Protocol,
		   B3Protocol,
		   B3Configuration);
}

/*--------------------------------------------------------------------------*\
 * Disconnect_h: high level Disconnect
\*--------------------------------------------------------------------------*/
unsigned Disconnect_h(ConnectionID Connection) {

    int 	    index;
    ConnectionState State;

    if (Connection == INVALID_CONNECTION_ID) {
	printf("Disconnect_h: ConnectionID is invalid\n");
	return 0xFFFF;
    }
    State = GetState(Connection);
    if ((State == Disconnected) || (State == D_DisconnectPending)) {
	index = GetSlot(Connection);
	printf("Disconnect_h: slot %d ID %d is disconnected\n",index, Connection);
	return 0xFFFF;
    }
    return Disconnect(Connection);
}

/*--------------------------------------------------------------------------*\
 * SendData_h: high level SendData
\*--------------------------------------------------------------------------*/
void InitQueue(void) {
    unsigned	x;

    for (x=0; x<QueueSize; x++) {
	Queue.Element[x].SENT  = FALSE;
    }
    Queue.Head = 0;
    Queue.Tail = 0;
    Queue.Fill = 0;
}

/*--------------------------------------------------------------------------*\
 * AnswerCall_h: high level AnswerCall
\*--------------------------------------------------------------------------*/
void TransferData(int index) {
    MESSAGE_EXCHANGE_ERROR  error;
    unsigned		    t;

    if (Queue.Fill > 0) {
	t = Queue.Tail;
	do {
	    if (Queue.Element[t].SENT == FALSE) {
		error = SendData(index,
				 (void __far *)Queue.Element[t].DATA,
				 Queue.Element[t].DATA_LENGTH,
				 (unsigned short)t);

		if (error != 0) {
                    printf("Error transfering data: 0x%04X !!!\n",error);
		    break;
		}
		Queue.Element[t].SENT = TRUE;
	    }
	    if (++t >= QueueSize) t = 0;
	} while (t != Queue.Head);
    }
}


int GiveFreeSlot(void)
{ int i;

  for(i=0; i<maxSlots; i++)
    if (Slot[i] == INVALID_CONNECTION_ID)
      return i;
      
  return -1;
}


/*--------------------------------------------------------------------------*\
 * SendFax: Asks for a filename and sends it as a fax
\*--------------------------------------------------------------------------*/
unsigned SendFax(char *Filename, char *FaxNumber) 
{
    int SlotNr;
    unsigned	    count;
    int 	    FAX_Format;
    B3_PROTO_FAXG3  B3conf;

//  FAX_Format = strstr(Filename, ".sff" ) ? FAX_SFF_FORMAT : FAX_ASCII_FORMAT;
    FAX_Format = FAX_SFF_FORMAT;

    SlotNr = GiveFreeSlot();
    if (SlotNr == -1)
      return 1;

//    File = fopen(Filename, "rb");
    File = fopen(Filename, "r");
    if (! File) {
        CAPI_PROTOCOL_TEXT("***** could not open file: \"%s\",errno=%d *****\n",Filename,errno);
	return 1;
    }
    CAPI_PROTOCOL_TEXT("***** opening file: \"%s\" *****\n",Filename);

    InitQueue();

    SetupB3Config( &B3conf, FAX_Format, FaxResolution);
//  Connect_h(&Slot[SlotNr], CallingPartyNumber, SPEECH, B1PROTOCOL, B2PROTOCOL,
//	      B3PROTOCOL, (_cstruct)&B3conf);
    strcpy(CalledPartyNumberArr, FaxNumber);
    Connect  (&Slot[SlotNr], CalledPartyNumberArr, CallingPartyNumber, SPEECH, 
              B1PROTOCOL, B2PROTOCOL, B3PROTOCOL, (_cstruct)&B3conf);

    do {
	Handle_CAPI_Msg();
	if (Slot[SlotNr] == INVALID_CONNECTION_ID) {
            CAPI_PROTOCOL_TEXT("***** disconnected, please try again *****\n\n");
	    fclose(File);
	    return 1;
	}
    } while (GetState(Slot[SlotNr]) != Connected);


    FileTransfer = TRUE;

    CAPI_PROTOCOL_TEXT("***** Starting datatransfer, press any key to stop *****\n");
    CAPI_PROTOCOL_TEXT("***** there is no protocol output to the screen during transfer *****\n");
    do {

	if ((! feof(File)) && (Queue.Fill < 7)) {  /*----- max. 7 outstanding blocks supported by CAPI -----*/
	    count = fread(&(Queue.Element[Queue.Head].DATA[0]), 1, SendBlockSize, File);
	    if (count > 0) {
		Queue.Element[Queue.Head].DATA_LENGTH = (unsigned short)count;
		if (++Queue.Head >= QueueSize) Queue.Head = 0;
		Queue.Fill++;
	    }
	}

	if (GetState(Slot[SlotNr]) != Connected) {
            CAPI_PROTOCOL_TEXT("***** connection broken *****\n");
            break;
        }
#ifdef WITH_KBHIT
        if (kbhit()) {
            getch();
            CAPI_PROTOCOL_TEXT("***** interrupted by user *****\n");
            break;
	}
#endif
	TransferData(SlotNr);
	Handle_CAPI_Msg();

    } while (!feof(File));

    Disconnect_h(Slot[SlotNr]);
    while ((Slot[SlotNr] != INVALID_CONNECTION_ID) && (GetState(Slot[SlotNr]) != Disconnected)) {
	Handle_CAPI_Msg();
#ifdef WITH_KBHIT
        if (kbhit()) {
            getch();
            CAPI_PROTOCOL_TEXT("***** interrupted by user *****\n");
            return 1;
	}
#endif

    };

    FileTransfer = FALSE;
    CAPI_PROTOCOL_TEXT("***** End of transfer *****\n");
    fclose(File);
    return 2;
}

/*--------------------------------------------------------------------------*\
 * ReceiveFax: Waits for incoming data and stores it to disk
\*--------------------------------------------------------------------------*/
unsigned ReceiveFax(int SlotNr) {

    char    Filename[80];
    char    *p;

    printf("The default extension for the FAX-data is .sff\n");
    printf("Enter Filename where incoming data shall be saved: ");
    fflush (stdout);
    gets(Filename);

    p = strchr(Filename, '.');
    if (p) *p = '\0';
    strcat(Filename, ".sff");


    File = fopen(Filename, "wb");
    if (! File) {
        CAPI_PROTOCOL_TEXT("***** could not open file: \"%s\" *****\n",Filename);
	return 3;
    }
    printf("opening file: \"%s\"\n\n",Filename);

    InitQueue();

    FileReceive = TRUE;

    CAPI_PROTOCOL_TEXT("***** Waiting for data , press any key to stop *****\n");
    CAPI_PROTOCOL_TEXT("***** there is no protocol output to the screen during transfer *****\n");

    printf("JIM, vor listen\n");
    Listen(0x1FFF03FF);
    printf("JIM, nach listen\n");

    while (GetState(Slot[SlotNr]) != Connected) {
	Handle_CAPI_Msg();
#ifdef WITH_KBHIT
	if (kbhit()) {
	    getch();
            CAPI_PROTOCOL_TEXT("***** interrupted by user *****\n");
	    fclose(File);
	    FileReceive = FALSE;
	    return 0;
	}
#endif
    }
    printf("JIM, nach 1. while\n");
    while (GetState(Slot[SlotNr]) != INVAL_STATE) {
	Handle_CAPI_Msg();
#ifdef WITH_KBHIT
	if (kbhit()) {
	    getch();
            CAPI_PROTOCOL_TEXT("***** interrupted by user *****\n");
	    FileReceive = FALSE;
	    fclose(File);
	    return 0;
	}
#endif
    }

    FileReceive = FALSE;
    CAPI_PROTOCOL_TEXT("***** End of FAX-receive *****\n");
    fclose(File);
    return 0;
}

void ShowChannels(void) {
    int     numController;
    int     BChannels, Contr;


    numController = GetNumController ();
    BChannels = 0;
    for (Contr=1; Contr<=numController; Contr++)
	BChannels += GetNumOfSupportedBChannels(Contr);

/*
    printf("Detected %i controllers with %i B-channels overall.\n\n",
						    numController, BChannels);
*/
}

/*--------------------------------------------------------------------------*\
 * ValidSlots: Check if connections are not completely closed yet
\*--------------------------------------------------------------------------*/
int ValidSlots(void)
{ int i;

  for(i=0; i<maxSlots; i++)
    if (Slot[i] != INVALID_CONNECTION_ID)
      return TRUE;

  return FALSE;
}
/*--------------------------------------------------------------------------*\
 * Hangup: Disconnect both channels
\*--------------------------------------------------------------------------*/
void Hangup(void) {
    int i;


    for(i=0; i<maxSlots; i++)
      if ((Slot[i] != INVALID_CONNECTION_ID) &&
		(GetState(Slot[i]) != Disconnected) &&
		(GetState(Slot[i]) != D_DisconnectPending))
	Disconnect(Slot[i]);

    do {
	Handle_CAPI_Msg();
#ifdef WITH_KBHIT
	if (kbhit()) {
	    while (kbhit()) {
		getch();
	    }
	    printf("Exit program ?  y/n ");
            fflush (stdout);
	    i = Press_Key();
	    if ((i == 'y') || (i =='Y')) {
		puts("Y");
		return;
	    }
	    puts("N");
	}
#endif
    }
    while (ValidSlots());
}

/*--------------------------------------------------------------------------*\
 * ctrlchandler: exits on CTRL-C and CTRL-BREAK
\*--------------------------------------------------------------------------*/
void ctrlchandler(int sig)
{
    signal( SIGINT, ctrlchandler );
    exit(0);
    sig = 0;	/*----- suppress warning -----*/
}




void GetJobAndNumber(char *job, char *filename, char *number)
{ FILE *fp;
  char string[1024];

  if ((fp=fopen(job, "r")) == NULL)
    return;
    
  while (fgets(string, sizeof(string), fp) != NULL)
  {
    if (string[0])
      string[strlen(string)-1] = 0;
    if (memcmp(string, "fax:", 4) == 0)
    { int i;

      for (i=strlen(string); i>0; i--)
        if (string[i] == ':')
	  break;
      strcpy(filename, &string[i+1]);  
    }
    else if (memcmp(string, "number:", 7) == 0)
      strcpy(number, &string[7]);
    else if (memcmp(string, "resolution:", 11) == 0)
    { 
      if (memcmp(&string[11], "196", 3)==0)  // HIRES mode
        FaxResolution = FAX_HIGH_RESOLUTION;
      else
        FaxResolution = FAX_STANDARD_RESOLUTION;
    }
  }

  fclose(fp);
}

#ifdef DEBUG
void CloseProtFile(void)
{
    CAPI_PROTOCOL_TEXT("***** In exit routine *****\n");
    fclose(ProtocolFile);
}
#endif


// char number[256], faxID[256];
    
void HandleConfig(char *deviceID)
{ FILE *fp;
  char string[1024];
char number[256], faxID[256];


  number[0] = faxID[0] = 0;
  sprintf(string, "etc/config.%s", deviceID);
  if ((fp=fopen(string, "r")) == NULL)
  {
    CAPI_PROTOCOL_TEXT("***** CAN'T OPEN filename=>%s< *****\n", string);
    return;
  }
  
  while (fgets(string, sizeof(string), fp) != NULL)
  {
    if (string[0])
      string[strlen(string)-1] = 0;
    if (memcmp(string, "FAXNumber:", 10) == 0)
    { int i;

      CAPI_PROTOCOL_TEXT("GOT TOKEN>%s<\n", string);
      for (i=strlen(string)-1; i>0; i--)
        if ((!isdigit(string[i])) && (string[i] != '.') && (string[i] != '+'))
	  break;
      strcpy(number, &string[i+1]);  
    }
    else if (memcmp(string, "LocalIdentifier:", 16) == 0)
    { int i, j;
    
      CAPI_PROTOCOL_TEXT("GOT TOKEN>%s<\n", string);
      for (i=strlen(string)-1; i>0; i--)
        if (string[i] == '"')
	  break;
	  
      for (j=i-1; j>0; j--)
        if (string[j] == '"')
	  break;
      
      if ((i-j) > 1)
      {
        memcpy(faxID, &string[j+1], i-j-1);
	faxID[i-j-1] = 0;
      }
    }
    else
      CAPI_PROTOCOL_TEXT("UNKNOWN TOKEN>%s<\n", string);
    
  }

  CAPI_PROTOCOL_TEXT("***** faxID=>%s< number=>%s< Resolution=>%d< *****\n", 
                     faxID, number, FaxResolution);
  SetB3Headline(faxID, number);
//  SetB3Headline("OSIcom NT via Linux", "+49 4261 9749 180");
/* 
  if (faxID[0])
    strcpy(headLine, faxID);

  if (number[0])
    strcpy(stationID, number);
*/
  fclose(fp);
}

    
/*--------------------------------------------------------------------------*\
 * main: Init & exit functions
\*--------------------------------------------------------------------------*/
int main(int argc, char *argv[]) 
{ int i, ret;
  char filename[1024], number[256], configfile[1024], deviceID[256], job[1024];

    filename[0] = number[0] = configfile[0] = deviceID[0] = job[0] = 0;
    if (argc == 1)
    {
      printf("fxsend -f filename -d number \n");
      exit(0);
    }

#ifdef DEBUG
    if (! Prot_Init(argv[argc-1])) 
      exit(0);
    atexit (CloseProtFile);
#endif

    for (i=1; i<argc; i++)
      if (strcmp(argv[i] , "-d") == 0)
        strcpy(number, argv[++i]);
      else if (strcmp(argv[i] , "-f") == 0)
        strcpy(filename, argv[++i]);
      else if (strcmp(argv[i] , "-c") == 0)
        strcpy(configfile, argv[++i]);
      else if (strcmp(argv[i] , "-m") == 0)
        strcpy(deviceID, argv[++i]);
      else if (strcmp(argv[i] , "-r") == 0)
        FaxResolution = argv[++i][0] - 48;
      else if ((strcmp(argv[i] , "-l") == 0) || (strcmp(argv[i] , "-p") == 0))
        ;
      else 
        strcpy(job, argv[i]);

    for(i=0; i<maxSlots; i++)
      Slot[i] = INVALID_CONNECTION_ID;

    if (! RegisterCAPI ()) 
    {
      CAPI_PROTOCOL_TEXT("***** Cannot register to CAPI *****\n");
      exit(0);
    };
    atexit (ReleaseCAPI);

    signal(SIGINT, ctrlchandler);

    InitConnectionIDHandling ();


#ifdef __linux__
    init_tty();
    atexit (restore_tty);
#endif

    ShowChannels();
    if ((filename[0]==0) || (number[0]==0))
    {
      GetJobAndNumber(job, filename, number);
    }

    CAPI_PROTOCOL_TEXT("***** filename=>%s< number=>%s< *****\n", filename, number);
    if ((filename[0]==0) || (number[0]==0))
      return 1;

    HandleConfig(deviceID);
    ret = SendFax(filename, number);
//    ret = ReceiveFax(0);

    Hangup();

#ifdef DEBUG
    CAPI_PROTOCOL_TEXT("***** Normal durchgelaufen *****\n");
//    fclose(ProtocolFile);
#endif
    exit (ret);
}
