/*         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", 't' )) == (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];

   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, "dscandir: file = %s cname = %s", dp->d_name, cname );
      if ( strncmp( cname, dp->d_name, len ) == SAME ) {
         printmsg( 4, "dscandir: match!!" );
         strcpy(cfile, dp->d_name);
         closedir( dirp );
         return( -1 );
      }
   }
   closedir( dirp );
   return( 0 );

}
