
/*			dcpsys.c

			Revised edition of dcp

			Stuart Lynne May/87

			Copyright (c) Richard H. Lamb 1985, 1986, 1987
			Changes Copyright (c) Stuart Lynne 1987

*/
/* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
/* Get the next system, and other support routines  */
#include "dcp.h"
/*#define PROTOS  "trkg"*/
#define PROTOS  "g"
#define MAXLOGTRY       3

Proto Protolst[] = {  
		'g', ggetpkt, gsendpkt, gopenpk, gclosepk,
/*
	    'k', kgetpkt, ksendpkt, kopenpk, kclosepk,
	    'r', rgetpkt, rsendpkt, ropenpk, rclosepk,
	    't', tgetpkt, tsendpkt, topenpk, tclosepk,
*/
		 '0'};

#define EOTMSG "\004\r\004\r"

procref         getpkt, sendpkt, openpk, closepk;

/**/

/***************************************************************/
/***            Sub Systems             */
/*
**
**getsystem
** Process an "systems" file entry (like L.sys)
*/
getsystem()
{
	int	i;

	if ( fgets( sysline, BUFSIZ, fsys ) == (char *)NULL )
		return( 'A' );
	printmsg( 2, "%s", sysline );
		
	kflds = getargs( sysline, flds );
	strcpy( rmtname, flds[FLD_REMOTE] );
	cctime = flds[FLD_CCTIME];
	strcpy( device, flds[FLD_DEVICE] );
	
	/* strcpy( type, flds[FLD_TYPE] ); */
	strcpy( speed, flds[FLD_SPEED] );
	strcpy( proto, flds[FLD_PROTO] );
	

	if (debuglevel > 3) 
		for (i = FLD_EXPECT; i < kflds; i += 2)
			fprintf( stderr, "expect[%02d]:\t%s\nsend  [%02d]:\t%s\n",
				i, flds[i], i+1, flds[i+1] );
		
	printmsg( 2, "rmt= %s ctm= %s", rmtname, flds[FLD_CCTIME] );
	printmsg( 2, "dev= %s ", device );
	printmsg( 2, "spd= %s pro= %s", speed, proto );
	fw = (FILE *)NULL;
	if ( 
		/* (checktime( cctime )) || */
		( strcmp( Rmtname, "all" ) == SAME ) ||
		( strcmp( Rmtname, rmtname ) == SAME ) ||
	 	( (strcmp( Rmtname, "any" ) == SAME) && scandir() == 'S' ) 
	 	) 
	{
		if ( fw != (FILE *)NULL )
		  fclose( fw );	/* in case we matched with scandir */
		return( 'S' );  /* startup this system */
	}
	else
		return('G');  
}


/**/
/*
**
**checkname
** Do we know the guy ?
*/
checkname(name)
char	name[];
{
	FILE *ff;
	char line[BUFSIZ], tmp[20]; /* can change to 8 if %8s works */

	if ( ( ff = FOPEN( s_systems, "r" )) == (char *)NULL ) 
		return( FAILED );

	while ( fgets( line, BUFSIZ, ff ) != (char *)NULL ){
		sscanf( line, "%8s ", tmp );
		printmsg( 3, "rmt= %s sys= %s", name, tmp );
		if ( strncmp( tmp, line, 7 ) == 0 ) {
			fclose( ff );
			return ( OK ); /*OK I like you */
		}
	}
	fclose( ff );
	return( FAILED ); /* Who are you ? */
		
}


/**/
/*
**
**checktime
** check if we may make a call at this time 
**------------>to be implemented. Again. Didnt think it crucial
*/
checktime(xtime)
char	xtime[];
{
	return(0); /* OK go to it */
}


 
/**/
/*
**
**sysend
** end UUCP session negotiation
*/
sysend()
{
	char	msg[80];

	msg[1] = '\0';
	msgtime = 2 * MSGTIME;
	/* while (msg[1] != 'O') { */
		wmsg("OOOOOO", 2);
		if (rmsg(msg, 2) == -1) 
			goto hang;
	/*}*/
hang:
	wmsg("OOOOOO", 2);
	closeline();
	if ( remote == MASTER ) 
		return('I');
	return('A');
}


/**/
/*
**
**      delay
**
*/
/*ddelay(dtime)
int	dtime;
{
	int	i, j;
	for (i = 0; i < dtime; i++) { 
	}
}
*/

/**/
/*
**
**wmsg
** write a ^P type msg to the remote uucp
*/
wmsg(msg, syn)
int	syn;
char	msg[];
{
	int	len;
	len = strlen(msg);
	if (syn == 2) 
		swrite("\0\020", 2);
	swrite(msg, len);
	if (syn == 2) 
		swrite("\0", 1);
}


/*
**
**rmsg
** read a ^P msg from UUCP
*/
rmsg(msg, syn)
int	syn;
char	msg[];
{
	int	ii;
	char	c, cc[5];
	/* *msg0;*/
	/*msg0 = msg;*/
	c = 'a';
	if (syn == 2) {
		while ((c & 0x7f) != '\020') {
			if (sread(cc, 1, msgtime) < 1) 
				return(-1);
			c = cc[0]; /* Dont ask. MSC needs more than a byte to breathe */
			/*		printf("Hello im in rmsg c=%x\n",c); */
		}
	}
	for (ii = 0; ii < 132 && c ; ii++) {
		if (sread(cc, 1, msgtime) < 1) 
			return(-1);
		c = cc[0] & 0x7f;
		if (c == '\r' || c == '\n') 
			c = '\0';
		msg[ii] = c;
		/*if(c == '\020') msg = msg0; */
	}
	return(strlen(msg));
}



/**/
/*
**
**
**startup
**
**
*/
startup()
{
	char	msg[80], tmp1[20], tmp2[20];
	if ( remote == MASTER ) {
		msgtime = 2 * MSGTIME;
		if (rmsg(msg, 2) == -1) 
			return('Y');
		printmsg( 2, "1st msg = %s", msg );
		if (msg[5] == '=' && strncmp(&msg[6], rmtname, 7)) 
			return('Y');
			
		
		/*sprintf(msg, "S%.7s -Q0 -x%d", nodename, debuglevel);*/  /* -Q0 -x16 remote debuglevel set */
		sprintf(msg, "S%.7s", nodename);
		
		wmsg(msg, 2);
		if (rmsg(msg, 2) == -1) 
			return('Y');
		printmsg( 2, "2nd msg = %s", msg );
		if (strncmp(&msg[1], "OK", 2)) 
			return('Y');
		if (rmsg(msg, 2) == -1) 
			return('Y');
		printmsg( 2, "3rd msg = %s", msg );
		if (msg[0] != 'P' || index(&msg[1], proto[0]) == (char *)NULL) {
			wmsg("UN", 2);
			return('Y');
		}
		sprintf(msg, "U%c", proto[0]);
		wmsg(msg, 2);
		setproto(proto[0]);
		return('D');
	} else {
		msgtime = 2 * MSGTIME;
		sprintf(msg, "Shere=%s", nodename);
		wmsg(msg, 2);
		if (rmsg(msg, 2) == -1) 
			return('Y');
		sscanf(&msg[1], "%s %s %s", rmtname, tmp1, tmp2);
		sscanf(tmp2, "-x%d", &debuglevel);
		printmsg( 1, "debuglevel level = %d", debuglevel );
		printmsg( 2, "1st msg from remote = %s", msg );
		if (checkname(rmtname)) 
			return('Y');
		wmsg("ROK", 2);
		sprintf(msg, "P%s", PROTOS);
		wmsg(msg, 2);
		if (rmsg(msg, 2) == -1) 
			return('Y');
		if (msg[0] != 'U' || index(PROTOS, msg[1]) == (char *)NULL ) 
			return('Y');
		proto[0] = msg[1];
		setproto(proto[0]);
		return('R');
	}
}


/******* set the protocol **********/
setproto(pr)
char	pr;
{
	int	i;
	Proto * tproto;
	for (tproto = Protolst; tproto->type != '\0' && pr != tproto->type; tproto++) {
		printmsg( 3, "setproto: %c %c", pr, tproto->type ); 
	}
	if (tproto->type == '\0') {
		printmsg( 0, "setproto:You said I had it but I cant find it" );
		exit(1); 
	}
	getpkt = tproto->a; 
	sendpkt = tproto->b;
	openpk = tproto->c;  
	closepk = tproto->d;
}



/**/
int prefix(sh,lg)
char *sh,*lg;
{
	return( strncmp(sh,lg,strlen(sh)) == SAME);
}

int notin(sh,lg)
char *sh,*lg;
{
	while (*lg) {
		if (prefix(sh,lg++))
			return( FALSE );
	}
	return( TRUE );
}

#define MAXR 300
int expectstr( str, timeout )
char *str;
{
	static char rdvec[MAXR];
	char *rp = rdvec;
	int kr;
	char nextch;

	printmsg( 0, "wanted %s", str );
				
	if ( strcmp(str, "\"\"") == SAME ) {
		return( TRUE );
	}
	*rp = 0;
	while ( notin( str,rdvec ) ) {
		/* fprintf(stderr, "---------->%s<------\n", rdvec);/**/
		kr = sread( &nextch, 1, timeout /* 40 */ );
		/* nextch &= 0177;
		fprintf(stderr, "kr - %2d '%c'\n", kr, nextch); */
		if (kr <= 0) {
			return( FALSE );
		}
		if ((*rp = nextch & 0177) != '\0') {
			rp++;
		}
		*rp = '\0';
		if (rp >= rdvec + MAXR) {
			return( FALSE );
		}
	}
	return( TRUE );
}

int writestr(s)
	register char *s;
{
	register char last;
	register char * m;
	int nocr;
	last = '\0';
	nocr = FALSE;
	while (*s) {
		if (last == '\\') {
			switch (*s) {
			case 'd': 
			case 'D': /* delay */
               sleep(2);
               break;
            case 'c': 
            case 'C': /* end string don't output CR */
               nocr = TRUE;
               break;
            case 'r': 
            case 'R': /* carriage return */
            case 'm': 
            case 'M':
      			swrite( "\r", 1 );
               	break;
            case 'n': 
            case 'N':
      			swrite( "\n", 1 );
               	break;
            case 'b': 
            case 'B':
      			swrite( "\b", 1 );
               	break;
            case 't': 
            case 'T':
      			swrite( "\t", 1 );
               	break;
            case 's': 
            case 'S':
      			swrite( " ", 1 );
               	break;
            case 'z':
            case 'Z':
            	SIOSpeed( ++s );
            	while ( *s != '\0' && *s != '\\' ) 
            		s++;
            	if ( *s == '\\' )
            		s++;
            	break;
            default:
      			swrite( s, 1 );
			}
			last = '\0';
		}
		else if (*s != '\\') {
      		swrite( s, 1 );
			/* fputc(*s,stderr); */
		}
		else {
			last = *s;
		}
		s++;
	}
	return( nocr );
}

/***
 *   void sendthem(str)   send line of login sequence
 *         char *str;
 *
 *   return codes:  none
 */

void sendstr(str)
char *str;
{
	int nw, ns;
	int nulls;

	printmsg( 2, "sending %s", str );

#ifdef BREAK
	if (prefix("BREAK", str)) {
		sscanf(&str[5], "%1d", &nulls);
		if (nulls <= 0 || nulls > 10)
			nulls = 3;
		/* send break */
		ssendbrk(nulls);
		return;
	}
#endif

	if ( strcmp(str, "EOT") == SAME ) {
		swrite(EOTMSG, strlen(EOTMSG));
		return;
	}

	if ( strcmp(str,"\"\"") == SAME )
		*str = '\0';
		/*fprintf(stderr,"'%s'\n",str);*/
		
	if ( strcmp(str,"") != SAME ) {
		if (!writestr(str)) {
			swrite ("\r", 1);
		}
	}
	else {
		swrite("\r", 1);
	}
	return;
}

int sendexpect( s, e, timeout )
char * s;
char * e;
{
	sendstr( s );
	return( expectstr( e, timeout ) );
}

dial()
{
	int	flg, kk, jj, ll, firstflg;
	char	buf[4], *prsend;

	char *exp;
	char *alternate;
	int	ok;
	int i;

	if ( strcmp( flds[FLD_TYPE], "HAYES" ) != SAME ) {
		printmsg( 0, "dial: unsupported dialer %s", flds[FLD_TYPE] );
		return( FALSE );
	}
	
	printmsg( 3, "calling host %s", rmtname );
	if (openline(device, "2400" )) 
		return( FALSE );

	printmsg( 0, "hayes: trying 2400" );
	if ( sendexpect( "ATZ", "OK", 2 ) != TRUE ) {
		sendexpect( "\\d+++\\d", "OK", 2 );
		if ( sendexpect( "ATZ", "OK", 2 ) != TRUE ) {
			printmsg( 0, "hayes: trying 1200" );
			SIOSpeed( "1200" );
			if ( sendexpect( "ATZ", "OK", 2 ) != TRUE ) {
				sendexpect( "\\d+++\\d", "OK", 2 );
				if ( sendexpect( "ATZ", "OK", 2 ) != TRUE )
					return( FALSE);
				}
		}
	}
	printmsg( 0, "hayes: got modem response" );
	
	/*(sendstr( "\\d\\dATS7=30" );
	expectstr( "OK", 40 );*/
	
	sendstr( "\\d\\dATX4\\c" );

	if ( sendexpect( speed, "CONNECT ", 40 ) == TRUE ) {
		printmsg( 3, "hayes: got CONNECT" );
	
		if ( sread( buf, 4, 4 ) == 4 ) {
			printmsg( 3, "hayes: speed select %s", buf );
			/* set speed appropriately */
			SIOSpeed( buf );
		}
		return( TRUE );
	}
	else
		return( FALSE );
	
}


/*
**
**callup
** script processor - nothing fancy! 
*/
callup()
{
	int	flg, kk, jj, ll, firstflg;
	char	*prsend;

	char *exp;
	char *alternate;
	int	ok;
	int i;

	printmsg( 0, "calling host %s", rmtname );

	if ( strcmp( flds[FLD_TYPE], "DIR" ) != SAME ) {
		if ( dial() == FALSE )
			return( 'G' );
	}
	else if (openline(device, speed)) 
		return( 'G' );

	for (i = 6; i < kflds; i+=2) {

		exp = flds[i];
		printmsg( 2, "callup: expect %d of %d  \"%s\"", i, kflds, exp );
			
		ok = FALSE;
		while (ok != TRUE) {
		
			alternate = index( exp, '-' );
			if (alternate != (char *)NULL) 
				*alternate++ = '\0';
				
			ok = expectstr( exp, 30 );
			
			printmsg( 1, "got %s", ok != TRUE ? "?" : "that" );
			
			if ( ok == TRUE ) {
				printmsg( 0, "got that" );
				break;
			}

			if ( alternate == (char *)NULL ) {
				printmsg( 0, "LOGIN FAILED" );
				return( 'Y' );
			}
				
			exp = index( alternate, '-' );
			if ( exp != (char *)NULL )
				*exp++ = '\0';

			printmsg( 0, "send alternate" );
			
			sendstr( alternate );
		}
		
	printmsg( 2, "callup: send %d of %d  \"%s\"", i+1, kflds, flds[i+1] );
	sleep(1); /* (1)*/
	sendstr(flds[i+1]);
	}
	return('P');

}

/**/
/*
**
**      slowrite
** comunication slow write. needed for auto-baud modems
*/
/*slowrite(st)
register char	*st;
{
	int	len, j;
	char	c;
	len = strlen(st);
	printmsg( 2, "sent %s", st );
	for (j = 0; j < len; j++) {
		swrite(&st[j], 1);
		ddelay(80000);
	}
}
*/

/**/
/*
**
**scandir
**
*/

#include "ndir.h"


/*	scandir

	scan work dir for C. files matching current remote host (rmtname)

	return

		A	- abort
		Y	- can't open file
		S	- ok
		Q	- no files

*/
scandir()
{
	int	fn, len, i;
	char	cname[40], tmp[132];

	DIR *dirp;
	struct direct *dp;

	if ((dirp = opendir( spooldir )) == (DIR *)NULL ) {
		fprintf( stderr, "couldn't open dir %s\n", spooldir );
		return( 'A' );
	}
	sprintf(cname, CALLFILE, rmtname); 
	len = strlen(cname);
	while ((dp = readdir(dirp)) != (struct direct *)NULL) {
		printmsg( 4, "scandir: %s", dp->d_name );
		if ( strncmp( cname, dp->d_name, len ) == SAME ) {
			printmsg( 4, "scandir: match!!" );
			strcpy(cfile, dp->d_name);
			closedir( dirp );
			if ((fw = FOPEN( cfile, "r", 't' )) == (char *)NULL ) 
				return('Y');
			return('S');
		}
	}
	closedir( dirp );
	return('Q');

}


/**/
/*
**
**dscandir
** scan the directory
*/

dscandir()
{
	int	fn, len, i;
	char	cname[40], tmp[132];

	struct DIR *dirp;
	struct direct *dp;


	if ((dirp = opendir( spooldir )) == (DIR *)NULL ) {
		fprintf( stderr, "couldn't open dir %s\n", spooldir );
		return(0);
	}
	sprintf(cname, XQTFILE, rmtname); /* sprintf(cname,"c%.4s",rmtname); */
	len = strlen(cname);
	while ((dp = readdir(dirp)) != (struct direct *)NULL) {
		printmsg( 4, "dcxqt:dir file = %s cfile = %s", dp->d_name, cname );
		if ( strncmp( cname, dp->d_name, len ) == SAME ) {
			printmsg( 4, "scandir: match!!" );
			strcpy(cfile, dp->d_name);
			closedir( dirp );
			return( -1 );
		}
	}
	closedir( dirp );
	return( 0 );

}



