char *dialv = "Dialing functions CTOS Version-2.00, May 92";

/*  C K D I A L  --  Dialing program for connection to remote system */

/*
 Author: Herm Fischer, Litton Data Systems, Van Nuys CA (HFISCHER@USC-ECLB)
*/ 

/* modified for CTOS C2.0 by Joel Dunn, UNC-CH, October 1986 */
/*
   * modified to add support for RACAL modem by Doug Drury - ITT-FSC,
     May 1991

   * modified to remove forced tone dialing from hayes modem
     December 1991
*/
#include "ctermi.h"
#include "ctcmd.h"

extern int local, speed, flow, mdmtyp, techo;
extern char ttname[], sesfil[];

#define HAYES 1			/* for mdmtyp settings */
#define VENTEL 2
#define HAYESNV 3		/* internal use, non-verbal V0 setting */
#define RACAL 4			

struct keytab mdmtab[] = {		/* Modem types for command parsing */
    "direct",	0, 0,
    "hayes",	HAYES, 0,
    "ventel",	VENTEL, 0,
    "racal",    RACAL, 0
};
int nmdm = (sizeof(mdmtab) / sizeof(struct keytab));

#define DIALING 4		/* for ttvt parameter */
#define CONNECT 5

#define CONNECTED 1		/* for completion status */
#define FAILED	  2
#define BUSY	  3

static int tries = 0;

#define LBUFL 100
static char lbuf[LBUFL];
static char *lbp;

static
stripp(s) char *s; {	/* parity stripper aid */
    for ( ; *s ; *s++ &= 0177 );
}

/*  D I A L  --  Dial up the remote system */

dial(telnbr) char *telnbr; {

    char c;
    char *i;
    int waitct, status;
    char errmsg[50], *erp;
    int augMdm;		/* mdmtyp with switch settings added */
    int mdmEcho = 0;	/* assume modem does not echo */
    int n,m;

	if (!mdmtyp) {
	    printf("Sorry, you must 'set modem' first\n");
	    return(-2);
	}
	augMdm = mdmtyp;	/* internal use, to add dialer switches info*/

	if (!local) {
	    printf("Sorry, you must 'set line' first\n");
	    return(-2);
	}
	if (speed < 0) {
	    printf("Sorry, you must 'set speed' first\n");
	    return(-2);
        } 
        
	if (ttopen(ttname,local,mdmtyp) < 0) {/* Open, no wait for carrier */
	    erp = errmsg;
	    sprintf(erp,"Sorry, can't open %s",ttname);
	    perror(errmsg);
	    return(-2);
    	}
/* cont'd... */
					/* interdigit waits for tone dial */
/* ...dial, cont'd */


	waitct = 1*strlen(telnbr) ;	/* compute time to dial worst case */
	switch (augMdm) {
	    case HAYES:
	    case HAYESNV:
		waitct += 35;		/* dial tone + carrier waits + slop */
		for (i=telnbr; *i; i++) if (*i == ',') waitct += 2;
		break;
	    case VENTEL:
		waitct += 10;		/* guess actual time for dialtones */
		waitct += 10;	/* ventel's apparent patience for carrier */
		for (i=telnbr; *i; i++) if (*i == '%') waitct += 5;
		break;
	    case RACAL:
		waitct += 35;
		break;
	    }
       if (techo) {
       printf("Dialing thru %s, speed %d, number %s.\r\n",ttname,speed,telnbr);
       printf("The timeout for completing the call is %d seconds.\r\n",waitct);
       }
/* Condition console terminal and communication line */	    
/* place line into "clocal" dialing state */
if ( ttpkt(speed,flow) < 0 )  {
    printf("Sorry, Can't condition communication line\n");
    return(-2);
	}

/* Put modem into command state */

ttflui();			/* flush input buffer if any */

#define OKAY 1			/* modem attention attempt status */
#define IGNORE 2
#define GOT_O -2
#define GOT_A -3

switch (augMdm) {
    case HAYES:
    case HAYESNV:
	while(tries++ < 4) {
	    ttol("AT\r",3);	/* signal for attention, look for response */
		delay(10);	/* give modem a chance to echo */
	    status = 0;
	    while ( status <= 0 ) {
		switch (ttinc(0) & 0177) {
		    case 'A':			/* echoing, ignore */
			status = GOT_A;
			break;
		    case 'T':
			if (status == GOT_A) {
			    mdmEcho = 1;	/* expect echoing later */
			    status = 0;
			    break;
			}
			status = IGNORE;
			break;
		    case '\n':
		    case '\r':
			status = 0;
			break;
		    case '0':			/* numeric result code */
			augMdm = HAYESNV;	/* nonverbal result codes */
			status = OKAY;
			break;
		    case 'O':			/* maybe English result code*/
			status = GOT_O;
			break;
		    case 'K':
			if (status == GOT_O) {
			    augMdm = HAYES;
			    status = OKAY;
			    break;
			}			/* else its default anyway */
		    default:
			status = IGNORE;
			break;
		    }
		}
	    if (status == OKAY) break;
	    if (status == IGNORE) ttflui();
	    delay(10);		/* wait before retrying */
	}
        if (status == OKAY) break;
        printf("Sorry, can't initialize modem\n");
	ttpkt(speed,flow);		/* cancel dialing state ioctl */
    return(-2);

/* cont'd... */
					/* interdigit waits for tone dial */
/* ...dial, cont'd */

    case VENTEL:
	ttoc('\r');		/* Put Ventel into command mode */
	delay(10);
	ttoc('\r');
	delay(10);
	ttoc('\r');
	while( (ttinc(0) & 0177) != '$');
	break;

    case RACAL:
        for (n=0; n < LBUFL; n++) lbuf[n] = '\0';
        lbuf[0] = 0005;
        lbuf[1] = '\r';
	ttol(lbuf,2);	/* Get 's attention */

        for (n=0; n < LBUFL; n++) lbuf[n] = '\0';
        n = ttinl(lbuf,LBUFL,waitct,'*'); /* look for prompt    */ 
        if (n < 0) {    
            printf("Sorry, can't initialize modem\n");
            status = FAILED;
            ttpkt(speed,flow);
            return(-2);
        }
	break;		   		/* Got modems attention! */
 
    default:
	exit(0);		/* should never get here */
    }
    delay(10);			/* give things settling time */

/* Dial the number */

switch (augMdm) {
    case HAYES:
    case HAYESNV:		  
        sprintf(lbuf,"AT D %s\r",telnbr);
	break;
    case VENTEL:
	sprintf(lbuf,"<K%s\r>",telnbr);
	break;
    case RACAL:
	sprintf(lbuf,"D\r");  /* just send dial command modem will */
	break;                /* prompt for number                 */
    }

    ttflui();			/* clear out stuff from waking modem up */
    ttol(lbuf,strlen(lbuf));	/* send dialing string */
    ttflui();			/* clear out stuff from dialing */

/* cont'd... */
/* interdigit waits for tone dial */
/* ...dial, cont'd */


/* Check for connection */

    status = 0;
    while (status == 0) {
      switch (augMdm) {
	case HAYES:
	    for (n = 0; n < LBUFL; n++) lbuf[n] = '\0';
	    n = ttinl(lbuf,LBUFL,waitct,'\n');
	    if (n > 2) {
		lbp = lbuf;
		while ((*lbp == '\r') || (*lbp == '\n')) lbp++;
		stripp(lbp);
		if (strncmp(lbp,"CONNECT",7) == 0) status = CONNECTED;
		else if (strncmp(lbp,"BUSY",4) == 0) status = BUSY;
		else if (strncmp(lbp,"NO ",3) == 0) status = FAILED;
	    }
	    else if (n < 0) status = FAILED;
	    break;

	case HAYESNV:
	    c = ttinc(0) & 0177;
	    if (mdmEcho) {		/* sponge up dialing string */
		mdmEcho = c!='\r';	/* until return is echoed */
		break;
	    }
	    if	    (c == '1') status = CONNECTED;
	    else if (c == '5') status = CONNECTED;
	    else if (c == '9') status = CONNECTED;
	    else if (c == '7') status = BUSY;
	    else if (c == '3') status = FAILED;
	    else if (c == '4') status = FAILED;
	    else if (c == '6') status = FAILED;
	    else if (c == '8') status = FAILED;
	    break;

	case VENTEL:
	    delay(waitct*10);		/* time to allow for connecting */ 
	    if ( (ttinc(0) & 0177) == '!') status = CONNECTED;
	    break;

	case RACAL:
            printf("\n");
  	    for (n=0; n < LBUFL; n++) lbuf[n] = '\0';
	    n = ttinl(lbuf,LBUFL,waitct,'?'); /* look for NUMBER? prompt */
                    
            for (n = 0; n < LBUFL; n++) { 
                if (lbuf[n] == 'N') break;
	    }                            
            for (m=0; lbuf[n] != '\0'; n++) {
                lbuf[m] = lbuf[n];        
                m++;
            }
	    lbp=lbuf;
	    stripp(lbp);
            if (strncmp(lbp,"NUMBER?",7) != 0) {
		status = FAILED;	/* didn't get the NUMBER? prompt */
		break;
	    }
	    sprintf(lbuf, "%s\r", telnbr); 
	    ttflui();
	    ttol(lbuf,strlen(lbuf));	/* now DIAL */
	    ttflui();

            for (n=0; n < LBUFL; n++) lbuf[n] = '\0';
	    n = ttinl(lbuf,LBUFL,waitct,'!'); /* look for ON LINE! */
            
            for (n = 0; n < LBUFL; n++) {
	        if (lbuf[n] == '!') break;
	    }
	    for (m=0, n=n-7; m < 8; m++) {
                 lbuf[m] = lbuf[n];
                 n++;
            }
            lbp = lbuf;
            stripp(lbp);     
            if (!strncmp(lbp, "ON LINE!", 8)) status = CONNECTED; 
	    else status = FAILED;  
	    break;
	}
    }
	
/* Place line into modem-control (non-clocal) state */

    if (status == 0) printf("Sorry, Can't get response from modem\r\n");
    else if (status == CONNECTED) printf("Connected!\n");
    else if (status == FAILED) printf("Sorry, No Carrier\r\n");
    else if (status == BUSY) printf("Sorry, Line Busy\r\n");
    else printf("Failed to complete call\r\n");

    ttpkt(speed,flow);		/* cancel dialing state ioctl */
    return((status==CONNECTED) ? 0 : -2);
}
