/*--------------------------------------------------------------------------*\

    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 <time.h>
#include <fcntl.h>
#include <sys/file.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"
#include <unistd.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;
char    SenderID[80];
#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;

/* ****************************************************************************** */
/*
 * Ablage von Information in die Datei /var/spool/fax/etc/xferlog
 */
static void write_xferlog_info(
char *path,	/* Path der Log Datei */
char *start, 	/* zB. 10/10/1997 15:19 */
char *cmd, 	/* zB.: "SEND" */
char *commid, 	/* zB.: "00000002" */
char *device, 	/* zB.: "cui2" */
char *jobid, 	/* zB.: "108" */
char *jobtag, 	/* zB.: "" */
char *user, 	/* zB.: "root at Jimlinux.pds.de" */
char *dest, 	/* zB.: "855675" */
char *csi, 	/* zB.: "" */
unsigned int params, 	/* zB.: 65535 */
int npages, 	/* zB.: 0 */
char *duration, /* zB.: "0:33" */
char *conntime, /* zB.: "0:00" */
char *status 	/* zB.: "Unknown Problem (Check Modem Power)" */
)
{
int fd;
char record[600];
char buf[200];
int i;
char c;
char* cp;

record[0]=0;

    fd = open("/var/spool/fax/etc/xferlog", O_RDWR|O_CREAT|O_APPEND, 0644);

    if (fd < 0) return;

	strcat(record,start);			// $ 1 = time

	sprintf(buf,"\t%s", cmd);		// $ 2 = SEND|RECV|POLL|PAGE
	strcat(record,buf);

	sprintf(buf,"\t%s", commid);		// $ 3 = commid
	strcat(record,buf);

	sprintf(buf,"\t%s", device);		// $ 4 = device
	strcat(record,buf);

	sprintf(buf,"\t%s", jobid);		// $ 5 = jobid
	strcat(record,buf);

	i = 0;
	for (cp = jobtag; c = *cp; cp++) {
	    if (i == sizeof (buf)-2)		// truncate string
		break;
	    if (c == '\t')			// tabs are field delimiters
		c = ' ';
	    else if (c == '"')			// escape quote marks
		buf[i++] = '\\';
	    buf[i++] = c;
	}
	buf[i] = '\0';

	strcat(record,"\t\"");	
	strcat(record,buf);			// $ 6 = jobtag	
	strcat(record,"\"");	

	sprintf(buf,"\t%s", user);		// $ 7 = sender
	strcat(record,buf);

	sprintf(buf,"\t\"%s\"", dest);		// $ 8 = dest
	strcat(record,buf);

	sprintf(buf,"\t\"%s\"", csi);		// $ 9 = csi
	strcat(record,buf);

	sprintf(buf,"\t%u", params);		// $10 = encoded params
	strcat(record,buf);

	sprintf(buf,"\t%d", npages);		// $11 = npages
	strcat(record,buf);

	sprintf(buf,"\t%s", duration);		// $12 = duration
	strcat(record,buf);

	sprintf(buf,"\t%s", conntime);		// $13 = conntime
	strcat(record,buf);

	sprintf(buf,"\t\"%s\"", status);	// $14 = status
	strcat(record,buf);

	strcat(record,"\n");

	flock(fd, LOCK_EX);
	write(fd, record, strlen(record));
	close(fd);				// implicit unlock

}
/* ****************************************************************************** */
/*--------------------------------------------------------------------------*\
 * 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);
//    SetupB3Config( &B3conf, FAX_TIFF_FORMAT);

    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 ((strstr(Message, "NCPI")!=NULL) && (strstr(Message, "default")==NULL))
	{ char *p;

	  if ((p=strchr(Message, '>'))!=NULL)
	  {
	    strcpy(SenderID, &p[1]);
	    if ((p=strchr(SenderID, '<'))!=NULL)
	      *p = 0;
	    printf("JIM HAT IHN:%s\n", SenderID);
	    fprintf(ProtocolFile,"JIM HAT IHN:%s\n", SenderID);
	  }
	}
	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/isdnrecv.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;
}



void GetNextSeqName(char *Filename)
{ FILE *fp;
  unsigned int seqf=1;
  char val[256];

  if ((fp = fopen("/var/spool/fax/recvq/seqf", "r+")) == NULL)
    if ((fp = fopen("/var/spool/fax/recvq/seqf", "w+")) == NULL)
      return;

  if (fread(val, 1, sizeof(val), fp) > 1)
    seqf = atoi(val);
  sprintf(Filename, "/var/spool/fax/recvq/fax%05d.sff", seqf);
  seqf++;
  fseek(fp, 0, 0);
  fprintf(fp, "%d\n", seqf);
  fclose(fp);

}
    
char    Filename[80];
//char    SenderID[80];
extern _cmsg __far     *CMSG;
/*--------------------------------------------------------------------------*\
 * 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");
*/
    GetNextSeqName(Filename);

    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");

    Listen(0x1FFF03FF);

    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	
    }
//    strcpy(SenderID, GetCallingPartyNumber(Slot[SlotNr]));
    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 -----*/
}




#ifdef DEBUG
void CloseProtFile(void)
{
    CAPI_PROTOCOL_TEXT("***** In exit routine *****\n");
    fclose(ProtocolFile);
}
#endif



#define DAEMON

/*--------------------------------------------------------------------------*\
 * main: Init & exit functions
\*--------------------------------------------------------------------------*/
int main(int argc, char *argv[]) 
{ int i, ret;

#ifdef DAEMON
  pid_t pid;


   switch(pid = fork())
   {
      case 0    :
                  setpgrp();
                  freopen("/dev/null", "r", stdin);
                  freopen("/dev/null", "w", stdout);
                  break;
      case -1   :
                  printf("fork failed!\n");
                  return(-1);
      default   :
                  printf("Programm gestartet (PROZESS-NR=%d)\n", pid);
                  return(0);
   }
#endif

    for(i=0; i<maxSlots; i++)
      Slot[i] = INVALID_CONNECTION_ID;

    if (! RegisterCAPI ()) return 1;
    atexit (ReleaseCAPI);

#ifdef DAEMON
    signal(SIGTERM, SIG_IGN);
    signal(SIGINT, SIG_IGN);
    signal(SIGHUP, SIG_IGN);
#else    
    signal(SIGINT, ctrlchandler);
#endif
    InitConnectionIDHandling ();


#ifdef DEBUG
    if (! Prot_Init(argv[argc-1])) return 2;
    atexit (CloseProtFile);
#endif

#ifdef __linux__
    init_tty();
    atexit (restore_tty);
#endif
    atexit(Hangup);

    ShowChannels();
//    ret = SendFax(argv[1], argv[2]);
    for(;;) 
    {
      ret = ReceiveFax(0);
      if (ret==0)
      { char cmd[1024];

	  sprintf(cmd, "/var/spool/fax/bin/sff2tiff %s \"%s\" >/dev/null 2>/dev/null", 
	          Filename, SenderID);
          system(cmd);


	{
	time_t zeitstempel;
	char tbuf[80];

	zeitstempel= time(0);
        strftime(tbuf, sizeof (tbuf), "%D %H:%M", localtime(&zeitstempel));

	write_xferlog_info(
 	"/var/spool/fax/etc/xferlog",
	tbuf,
	"IFAX",
	"00000000",
	"cuix",
	"108",
	"",
	"   ",
    	senderID,
	"",
	0,
	10,
	"0:00",
	"0:00",
	"Receive Fax over the CAPI Interface: OK"	
	);

	}


      }
      else
      { struct timespec tspec;

	  tspec.tv_sec=10;
	  tspec.tv_nsec=1000;
	  nanosleep(&tspec, NULL);
      }
      Hangup();
    }
//    Hangup();

#ifdef DEBUG
    fclose(ProtocolFile);
#endif
    return (ret);
}
