#include "dialup.h"

extern BPTR			mystderr;
extern const UBYTE 		*prgname;
extern struct IOExtSer		*serialIOReq;
extern struct timerequest	*timereq;
extern BPTR			repfile;
extern UBYTE			*rxbuffer;
extern LONG			arg[];
extern struct argspec		argtab[];

BOOL
take( UBYTE *varbuf )
{
	UBYTE rgcnt;

	if ( *(UBYTE *)arg[A_MSC] )
          VERIFY ( sendEx( (UBYTE *)arg[A_MSC], (UBYTE *)arg[A_MOK], 3 ) ); /* set modem config (usually a RESET) */
	if ( !arg[A_NDI] )
          VERIFY ( sendEx( "AT&D0", (UBYTE *)arg[A_MOK], 2 ) ); /* ignore DTR ? */

	/* wait for A_RGS rings without timeout */
	do
		for(rgcnt = 0; rgcnt < *((LONG *)arg[A_RGS]); rgcnt++)
			if ( !expectFromSer( (UBYTE *)arg[A_MRG], *((LONG *)arg[A_RGS]) > 0 && rgcnt == 0 ? 0x7FFFFFFF : 3) )
				break;
	while ( rgcnt < *((LONG *)arg[A_RGS]) && !strstr(rxbuffer, BREAKSTR) ); /* count again, if timeout (not enough rings) but no user break */

	VERIFY ( !strstr(rxbuffer, BREAKSTR) );
	VERIFY ( sendEx( (UBYTE *)arg[A_MOH], (UBYTE *)arg[A_MAC], *(LONG *)arg[A_MCT] ) );	/* take call */
	VERIFY ( checkconnect(varbuf) );

	_OK_;
}


BOOL
connect(UBYTE *varbuf)
{
	UBYTE PNidx = 0;
	UBYTE lastPNidx = 0;
	UBYTE **PNA;

	PNA = (UBYTE **)arg[A_PN];

	if ( *(UBYTE *)arg[A_MSC] )
            VERIFY ( sendEx( (UBYTE *)arg[A_MSC], (UBYTE *)arg[A_MOK], 3 ) ); /* set modem config (usually a RESET) */
	if ( !arg[A_NDI] )
            VERIFY ( sendEx( "AT&D0", (UBYTE *)arg[A_MOK], 2 ) ); /* ignore DTR ? */

	loop	/* redial loop */
	{
		if ( !arg[A_NRC] || arg[A_AA] ) /* reconnect or autoanswer ? */
		{
			sprintf(varbuf, (UBYTE *)arg[A_MAAC], *((LONG *)arg[A_RGS]) );
			VERIFY ( sendEx( varbuf, (UBYTE *)arg[A_MOK], 2 ) );
		};

		/* dial or enter local analog loopback: */
		if ( arg[A_TEST] )
                    sprintf(varbuf, "%s",  (UBYTE *)arg[A_MTC]);
		else if ( *PNA[PNidx] == '!' )
                    sprintf(varbuf, "%s",  PNA[PNidx] + 1 );
		else if ( ABBREV( PNA[PNidx], "AT" ) )
                    sprintf(varbuf, "%s",  PNA[PNidx] );
		else
                    sprintf(varbuf, "ATD%s", PNA[PNidx] );

		VERIFY ( sendLine( varbuf ) );
		sprintf(varbuf, "%s|%s|%s|%s", arg[A_MLB], arg[A_MNC], arg[A_MAC], arg[A_MLD]);
		VERIFY ( expectFromSer( varbuf, arg[A_TEST] ? 5 : *(LONG *)arg[A_MCT] ) );

		if ( ! sStrMatch(rxbuffer, (UBYTE *)arg[A_MLB], varbuf ) )
                   break;	/* Do not redial if anything else than BUSY */

		DisplayBeep(NULL);
		/* switch to next number */
		if ( !PNA[++PNidx] )
		{
			PNidx = 0;
			if ( *(LONG *)arg[A_RDD] == 0 ) _FAIL_;	/* no redial of the number(s) at all! */
		};

		if ( !arg[A_NRC] || arg[A_AA] ) /* reconnect or autoanswer ? */
		{ /* set modem to not auto answer during wait: */
			sprintf(varbuf, (UBYTE *)arg[A_MAAC], 0 );
			VERIFY ( sendEx( varbuf, (UBYTE *)arg[A_MOK], 2 ) );
		};

		if ( strcmp(PNA[lastPNidx], PNA[PNidx]) == 0 || PNidx == 0) /* same number or first one again? Then wait a bit. */
                    VERIFY ( expectFromSer( NULL, *(LONG *)arg[A_RDD] ) );
		lastPNidx = PNidx;
		};

	/* What did modem say: */
	if ( sStrMatch(rxbuffer, (UBYTE *)arg[A_MLD], varbuf ) )
	{
		msg("Sorry! Modem doesn't get a dialtone.");
		_FAIL_;
	}
	else
            VERIFY ( checkconnect( varbuf ) );
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
        /* If a WBW is defined, do the wait with a dummy Expect */
        if ( arg[A_WBW] && *(LONG *)arg[A_WBW] > 0 )
            expectFromSer( NULL, *(LONG *)arg[A_WBW] );

        /* If a WUS is defined, send it */
	if ( arg[A_WUS] && *((UBYTE *)arg[A_WUS]) )
            VERIFY ( sendWUSSer( (UBYTE *)arg[A_WUS] ) );

        /* If a LIP is defined, get it */
	if ( arg[A_LIP] && *((UBYTE *)arg[A_LIP]) )
        {
	/* handle login prompt */
	    if ( arg[A_TEST] )
            {
		sprintf(varbuf, "\n\n**TEST: %s", arg[A_LIP] == argtab[A_LIP].deflt ? "Login:" : (UBYTE *)arg[A_LIP]);
		VERIFY ( sendToSer( varbuf ) );
	    };  /* the "while (!" is mine                             was LTO here */
            VERIFY ( exSend( (UBYTE *)arg[A_LIP], *((LONG *)arg[A_LTO]), (UBYTE *)arg[A_LIN] ) );
            /*    VERIFY ( sendToSer( (UBYTE *)arg[A_WUS] ) ); */
	};
	
	/* handle password prompt */
	if ( arg[A_PWP] && *((UBYTE *)arg[A_PWP]) )
	{
		if ( arg[A_TEST] )
		{
			sprintf(varbuf, "\n\n**TEST: %s", arg[A_PWP] == argtab[A_PWP].deflt ? "Password:" : (UBYTE *)arg[A_PWP]);
			VERIFY ( sendToSer( varbuf) );
		};
		VERIFY ( exSend( (UBYTE *)arg[A_PWP], 10, (UBYTE *)arg[A_PW] ) );
	};

	/* handle second login prompt */
	if ( arg[A_SLIN] && *((UBYTE *)arg[A_SLIN]) )
	{
		if ( arg[A_TEST] )
		{
			sprintf(varbuf, "\n\n**TEST: %s", arg[A_SLIP] == argtab[A_SLIP].deflt ? "2. Login:" : (UBYTE *)arg[A_SLIP]);
			VERIFY ( sendToSer( varbuf) );
		};
		VERIFY ( exSend( (UBYTE *)arg[A_SLIP], *((LONG *)arg[A_LTO]), (UBYTE *)arg[A_SLIN] ) );
	};

	/* handle snd pw prompt */
	if ( arg[A_SPW] && *((UBYTE *)arg[A_SPW]) )
	{
		if ( arg[A_TEST] )
		{
			sprintf(varbuf, "\n\n**TEST: %s", arg[A_SPWP] == argtab[A_SPWP].deflt ? "2. Password:" : (UBYTE *)arg[A_SPWP]);
			VERIFY ( sendToSer( varbuf) );
		};
		VERIFY ( exSend( (UBYTE *)arg[A_SPWP], 10, (UBYTE *)arg[A_SPW] ) );
	};

	/* check remote response for successful login: */
	if ( arg[A_LOK] && *((UBYTE *)arg[A_LOK])  )
	{
		if ( arg[A_TEST] )
		{
			sprintf(varbuf, "\n\n**TEST: %s", (UBYTE *)arg[A_LOK]);
			VERIFY ( sendToSer( varbuf) );
		};
		VERIFY ( expectFromSer( (UBYTE *)arg[A_LOK], *((LONG *)arg[A_LOT]) ) );

		if ( repfile ) Write(repfile, WS("\n"));
	};

	_OK_;
}

BOOL
hangup(UBYTE *varbuf)
	{
	if ( carrier() )
	{
		VERIFY ( commandmode(varbuf) );
		VERIFY ( dropline(varbuf) );
	}
	else
	{
		VERIFY ( sendEx( (UBYTE *)arg[A_MRC], "?*\r", 3) )
		Delay(25);
	}		

	if ( arg[A_AA])
	{
		if ( arg[A_MSC] && *(UBYTE *)arg[A_MSC] ) VERIFY ( sendEx( (UBYTE *)arg[A_MSC], (UBYTE *)arg[A_MOK], 3 ) ); /* set modem *connect* config (usually a RESET) */
		sprintf(varbuf, (UBYTE *)arg[A_MAAC], *(LONG *)arg[A_RGS] );	/* modem autoanswer */
		VERIFY ( sendEx( varbuf, (UBYTE *)arg[A_MOK], 2 ) );
		if ( !arg[A_NDI] ) VERIFY ( sendEx( "AT&D0", (UBYTE *)arg[A_MOK], 2 ) ) ;	/* ignore DTR  */
	}
	else
	{
		if ( arg[A_MSC] && *(UBYTE *)arg[A_MSH] ) VERIFY ( sendEx( (UBYTE *)arg[A_MSH], (UBYTE *)arg[A_MOK], 3 ) ); /* set modem hangup config (usually a RESET) */
		if ( !arg[A_NRC] )
		{
			sprintf(varbuf, (UBYTE *)arg[A_MAAC], 0 ); /* set modem to not auto answer: */
			VERIFY ( sendEx( varbuf, (UBYTE *)arg[A_MOK], 2 ) );
		}
		if ( !arg[A_NDI] ) VERIFY ( sendEx( "AT&D2", (UBYTE *)arg[A_MOK], 2 ) ); /* honor DTR again: */
	}

	_OK_;
}

BOOL
commandmode(UBYTE *varbuf)
{
	BPTR temp = repfile;

	Delay(50); /* send +++ : */
	VERIFY ( sendToSer( (UBYTE *)arg[A_MOC] ) );
	sprintf(varbuf, "%s|%s", (UBYTE *)arg[A_MOK], arg[A_MNC]);
	repfile = NULL;
	if ( !expectFromSer( (UBYTE *) varbuf, 3 ) )
	{
		repfile = temp;
		VERIFY ( sendEx( (UBYTE *)arg[A_MRC], (UBYTE *)arg[A_MOK], 2 ) );  /* maybe already offline ? */
	}
	else repfile = temp;
	_OK_;
}

BOOL
dropline(UBYTE *varbuf)
{
	if ( !arg[A_TEST] )	/* hangup line (ATH0) */
		VERIFY ( sendEx( (UBYTE *)arg[A_MHC], (UBYTE *)arg[A_MOK], 2 ) )
	else
	{
		sprintf( varbuf, "%s|%s", (UBYTE *)arg[A_MOK], arg[A_MNC]);
		VERIFY ( sendEx( (UBYTE *)arg[A_MTO], varbuf, 2 ) );
	};

	_OK_;
}


BOOL
query(UBYTE *varbuf)
{
	BOOL connected = carrier();

	if ( connected )
            VERIFY ( commandmode(varbuf) );
	VERIFY ( sendEx( (UBYTE *)arg[A_MQC], (UBYTE *)arg[A_MOK], 8 ) );
	if ( connected )
            VERIFY ( sendEx( (UBYTE *)arg[A_MLC], (UBYTE *)arg[A_MAC], 2 ) );

	_OK_;
}


BOOL
checkconnect(UBYTE *buf)
{
	UBYTE *anycon;

	if ( !(anycon = sStrMatch(rxbuffer, (UBYTE *)arg[A_MAC], buf ) ) )
	{
		msg(rxbuffer);
		_FAIL_;
        }
	else
	{
		if ( arg[A_CS] && !sStrMatch(rxbuffer, (UBYTE *)arg[A_CS], buf) )
			msg("Modem handshake result:\n %s", anycon);
		_OK_;
	};
}

