www.pudn.com > tcpipstack.rar > term.c


/* 
 * usage: term [-s speed] [-l line] [-e escape-char] [-c callscript] 
 *      defaults: 
 *              speed:  38400 or 2400 
 *              line :  /dev/tty2a 
 *              escape: ~ 
 *                      escape char may be specified as three octal digits 
 * 
 *      term escapes: 
 *              escape-. or escape-CTRLD        terminate 
 *              escape-!                        escape to shell 
 *              escape-#                        send break 
 *              escape-escape                   send escape char 
 */ 
 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
 
#ifdef V7 
# include  
#else 
# if defined(__linux__) || defined(HAVE_TERMIOS) 
#  include  
#  ifndef HAVE_TERMIOS 
#   define HAVE_TERMIOS 
#  endif 
# else 
#  include  
# endif 
# ifndef SYSV 
#  define SYSV 
# endif 
#endif 
 
#define XSCRIPT 
#define XLOGFILE 
#define XCHARXLATE 
 
#ifdef B38400 
#define SPEED B38400		/* default speed */ 
#else 
#define SPEED B2400		/* default speed */ 
#endif 
 
#define LINE    "/dev/ttyS0"    /* the default line  */ 
#define ESC     '~'             /* default esc char  */ 
#define EOT     '\004'          /* ^D */ 
 
#ifndef R_OK            /* access() modes */ 
#define R_OK 4 
#define W_OK 2 
#endif 
 
char esc[2] = { ESC, '\0' }; 
 
extern void s_line();      /* set & save line characteristics   */ 
extern void r_line();      /* reset saved  line characteristics */ 
 
int wr_pid = 0;            /* writer process id */ 
int line_fd;               /* comm line file desc        */ 
int tty_fd;                /* console   file desc        */ 
char line_device[64]; 
 
#ifdef CHARXLATE 
int Termtype = 2; 
#else 
int Termtype = 0; 
#endif 
int Bit_mask = 0xFF;	   /* Strip high bit from line */ 
int Parity = 0;		   /* Add parity to line */ 
 
#ifdef LOGFILE 
FILE * lfile = 0; 
char   logfname[64] = "tty/ttylog%d"; 
char   ltbuf[10240]; 
char * ltptr = 0; 
#endif 
 
#ifdef SCRIPT 
int in_script = 0; 
char script_name[128]; 
char script_args[128]; 
struct script_sv 
{ 
   struct script_sv * next; 
   FILE * scrfd; 
   char script_args[128]; 
} 
   * saved_sc = 0; 
 
int verbose = 0; 
#endif 
 
int cleanup() 
{ 
   int status; 
   r_line(); 
   if( wr_pid ) kill(wr_pid, SIGTERM); 
   wait(&status); 
   uucp_unlock(line_device); 
#ifdef LOGFILE 
   if( lfile ) fclose(lfile); 
   lfile = 0; 
#endif 
   if( wr_pid ) fprintf(stderr, "Disconnected\r\n"); 
   exit(0); 
} 
 
void main(argc, argv) 
int argc; 
char **argv; 
{ 
   int done, status; 
   int speed = SPEED; 
   extern char *optarg; 
   extern int optind; 
   extern int getopt(), conv_speed(), conv_esc(), access(); 
   extern open_timeout(); 
 
   strcpy(line_device, LINE); 
   while((status = getopt(argc, argv,"s:l:e:rdm7pv")) != EOF) 
   { 
      switch(status) 
      { 
      case 's': 
         if((speed = conv_speed(optarg)) == EOF) 
         { 
            fprintf(stderr,"%s: invalid speed\n", optarg); 
            exit(1); 
         } 
         break; 
      case 'l': 
         strncpy(line_device, optarg, sizeof(line_device)); 
         if(access(line_device, R_OK|W_OK) == -1) 
         { 
            perror(optarg); 
            exit(2); 
         } 
         break; 
 
      case 'e': esc[0] = conv_esc(optarg); break; 
      case 'p': Parity = 1; /* FALL */ 
      case '7': Bit_mask = 0x7F; break; 
      case 'd': Termtype = 1; break; 
#ifdef CHARXLATE 
      case 'r': Termtype = 0; break; 
#endif 
#ifdef SCRIPT 
      case 'v': verbose++; break; 
#endif 
      default: 
         fprintf(stderr, 
             "usage: %s [-s speed] [-l line] [-e escape-char]\n", *argv); 
         exit(3); 
      } 
   } 
   if( optind < argc ) 
   { 
#ifdef SCRIPT 
      strcpy(script_name, argv[optind]); 
      strcat(script_name, ".sct"); 
      if(access(script_name, R_OK) == -1) 
      { 
         strcpy(script_name, "sct/"); 
         strcat(script_name, argv[optind]); 
         strcat(script_name, ".sct"); 
         if(access(script_name, R_OK) == -1) 
         { 
	    fprintf(stderr, "Cannot open '%s.sct'\n", argv[optind]); 
	    exit(4); 
	 } 
      } 
      strcpy(script_name, argv[optind]); 
      in_script = 1; 
      for(optind++, script_args[0] = '\0'; optind=1000 ) 
            { 
               lfile = 0; 
               break;; 
            } 
            continue; 
         } 
         lfile = fopen(file, "w"); 
         fd = fopen(file3, "w"); 
         if(fd) { fprintf(fd, "%d\n", lnumber+1); fclose(fd); } 
         break; 
      } 
   } 
   if( lfile ) 
      fprintf(stderr, "Logfile %s\r\n", file); 
   else 
      fprintf(stderr, "Cannot open Logfile %s\r\n", file); 
   if( ltptr && ltbuf != ltptr ) 
   { 
      fwrite(ltbuf, 1, ltptr-ltbuf, lfile); 
      ltptr = 0; 
   } 
} 
#endif 
 
typedef struct 
{ 
   char *str; 
   int  spd; 
} vspeeds; 
 
static vspeeds valid_speeds[] =  
{ 
   { "110",  B110  }, 
   { "300",  B300  }, 
   { "1200", B1200 }, 
   { "2400", B2400 }, 
   { "4800", B4800 }, 
   { "9600", B9600 }, 
#ifdef B19200 
   { "19200", B19200 }, 
#endif 
#ifdef B38400 
   { "38400", B38400 }, 
#endif 
#ifdef B57600 
   { "57600", B57600 }, 
#endif 
#ifdef B115200 
   { "115200", B115200 }, 
#endif 
   { (char *)0, 0 } 
}; 
 
/* 
 * given a desired speed string, if valid return its Bspeed value 
 * else EOF 
 */ 
int conv_speed(s) 
register char *s; 
{ 
   register vspeeds *p = &valid_speeds[0]; 
 
   if(*s == 0) return EOF; 
 
   for(; p->str != (char *)0; p++) 
      if(strncmp(s, p->str, strlen(s)) == 0) 
         return p->spd; 
   return EOF; 
} 
 
/* 
 * convert given string to char 
 *      string maybe a char, or octal digits 
 */ 
int conv_esc(s) 
register char *s; 
{ 
   register int val = 0; 
 
   if(!isdigit(*s)) 
      return *s; /* ! octal */ 
 
   /* convert octal digs */ 
   do 
   { 
      if(*s > '7' || *s < '0') 
      { 
         fprintf(stderr,"escape char must be character/octal digits\n"); 
         exit(4); 
      } 
      val = (val << 3) + (*s++ - '0'); 
   } while(isdigit(*s)); 
 
   return val; 
} 
 
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/  
#ifdef V7 
/* This is Version 7 unix code it should work on any unix machine */ 
/* If you believe that you'll believe anything :-) */ 
 
struct sgttyb tty_save, line_save, tty; 
int tty_mode = -1; 
int got_line = 0; 
 
void s_line(speed) 
{ 
   set_mode(2); 
   if(!got_line) 
   { 
      got_line = 1; 
      ioctl(line_fd, TIOCGETP, &line_save); 
   } 
   tty = line_save; 
   tty.sg_ospeed  = speed;      /* Set new speed */ 
   tty.sg_ispeed  = speed;      /* Set new speed */ 
   tty.sg_flags  |= RAW; 
   tty.sg_flags  &= ~ECHO; 
   /* Parity doesn't appear to work with Xenix tty.sg_flags |= EVENP; */ 
   /* So xmit parity is done in software */ 
   ioctl(line_fd, TIOCSETP, &tty); 
} 
 
void r_line() 
{ 
   set_mode(0); 
   if(!got_line) return; 
   ioctl(line_fd, TIOCSETP, &line_save); 
} 
 
set_mode(which) 
int which; 
{ 
    if( tty_mode == -1 ) 
    { 
       if(ioctl(tty_fd, TIOCGETP, &tty)) 
       { 
	   perror("Unable to sense terminal"); 
	   exit(1); 
       } 
       tty_save = tty; 
       tty_mode = 0; 
    } 
 
    tty = tty_save; 
    switch(which) 
    { 
    default: /* Normal cooked */ 
	    which = 0; 
	    break; 
    case 1: /* CBREAK */ 
            tty.sg_flags &= ~ECHO; 
            tty.sg_flags |= CBREAK; /* Allow break & cr/nl mapping */ 
	    break; 
    case 2: /* RAW */ 
            tty.sg_flags &= ~ECHO; 
            tty.sg_flags |= RAW; 
            break; 
    } 
    if(ioctl(tty_fd, TIOCSETP, &tty)) 
    { 
	perror("Unable to change terminal mode"); 
    } 
    else tty_mode = which; 
} 
#endif 
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ 
#ifdef SYSV 
/* This is System V unix code */ 
 
#ifdef HAVE_TERMIOS 
struct termios tty_save, line_save, tty; 
#else 
struct termio tty_save, line_save, tty; 
#endif 
static int tty_mode = -1; 
int got_line = 0; 
 
void s_line(speed) 
int speed; 
{ 
   set_mode(2); 
   if(!got_line) 
   { 
      got_line = 1; 
#ifndef HAVE_TERMIOS 
      ioctl(line_fd, TCGETA, &line_save); 
#else 
      tcgetattr(line_fd, &line_save); 
#endif 
   } 
   tty = line_save; 
 
   tty.c_iflag &= ~(IXON|IXANY|IXOFF|ISTRIP|INLCR|ICRNL|IGNCR|IUCLC); 
   tty.c_oflag &= ~(OLCUC|ONLCR|OCRNL|ONOCR|ONLRET); 
   tty.c_cflag &= ~(CBAUD|PARENB); 
   tty.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHONL|ISIG); 
 
   tty.c_iflag |= IXOFF;	/* X/Y modem will clear this */ 
   tty.c_cflag |= (speed); 
 
   tty.c_cc[VTIME] = 0; 
   tty.c_cc[VMIN]  = 1; 
 
#ifndef HAVE_TERMIOS 
   ioctl(line_fd, TCSETA, &tty); 
#else 
   tcsetattr(line_fd, TCSANOW, &tty); 
#endif 
} 
 
void r_line() 
{ 
   set_mode(0); 
   if(!got_line) return; 
#ifndef HAVE_TERMIOS 
   ioctl(line_fd, TCSETA, &line_save); 
#else 
   tcsetattr(line_fd, TCSANOW, &line_save); 
#endif 
} 
 
set_mode(which) 
int which; 
{ 
    if( tty_mode == -1 ) 
    { 
#ifndef HAVE_TERMIOS 
       if(ioctl(tty_fd, TCGETA, &tty)) 
#else 
       if(tcgetattr(tty_fd, &tty)) 
#endif 
       { 
	   perror("Unable to sense terminal"); 
	   exit(1); 
       } 
       tty_save = tty; 
       tty_mode = 0; 
    } 
 
    tty = tty_save; 
    switch(which) 
    { 
    case 0: /* Normal cooked */ 
	    break; 
    case 1: /* CBREAK */ 
	    tty.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHONL); 
	    tty.c_lflag |= ICRNL|ISIG; 
	    tty.c_cc[VTIME] = 0; 
	    tty.c_cc[VMIN]  = 1; 
	    break; 
    case 2: /* RAW */ 
	    tty.c_oflag &= ~OPOST; 
	    tty.c_iflag &= ~(ICRNL|IGNCR|INLCR); 
	    tty.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHONL|ICRNL|ISIG); 
	    tty.c_cc[VTIME] = 0; 
	    tty.c_cc[VMIN]  = 1; 
            break; 
    } 
 
#ifndef HAVE_TERMIOS 
    if(ioctl(tty_fd, TCSETA, &tty)) 
#else 
    if(tcsetattr(tty_fd, TCSANOW, &tty)) 
#endif 
    { 
	perror("Unable to change terminal mode"); 
    } 
    else tty_mode = which; 
} 
#endif 
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ 
 
fork_writer() 
{ 
#ifdef LOGFILE 
   if( lfile ) fflush(lfile); 
#endif 
   if (wr_pid = fork()) 
   { 
      if (wr_pid == -1) 
      { 
         r_line(); 
         perror("Cannot fork writer"); 
         exit(0); 
      } 
      return; 
   } 
#ifdef LOGFILE 
   if(lfile) fclose(lfile); 
   lfile = 0; 
#endif 
   signal(SIGCHLD, SIG_DFL); 
   write_tty(); 
   cleanup(); 
} 
 
write_tty() 
{ 
   char ch; 
   char was_newline = 1; 
 
   signal(SIGINT,  SIG_IGN); 
   signal(SIGQUIT, SIG_IGN); 
   signal(SIGTERM, cleanup); 
 
   while (1) { 
      read(0, &ch, 1); 
      ch &= (char)0177; 
 
      if (was_newline) { 
         if (ch == esc[0]) { 
            read(0, &ch, 1); 
            ch &= (char)0177; 
 
            switch (ch) { 
 
            case EOT: 
            case '.': 
            case '>': 
               read(0, &ch, 1); 
               exit(0); 
 
            case '!': 
               /* tell reader to pause */ 
               kill(getppid(), SIGUSR1); 
               do_shell(); 
               /* wake him up again */ 
               if( kill(getppid(), SIGUSR2) < 0 ) exit(0); 
               ch = '\377'; 
               break; 
 
            default: 
               if(ch != esc[0]) 
               { 
                  fprintf(stderr, "invalid command--use\ 
 \"~~\" to start a line with \"~\"\r\n"); 
               } 
 
            } 
         } 
      } 
 
      if (ch == '\r' || ch == '\004' || ch == '\003' || ch == '\177') 
         was_newline = 1; 
      else 
         was_newline = 0; 
 
      if( ch != '\377' ) 
      { 
	 int i; 
	 if( Parity ) 
	 { 
	    ch &= 0x7F; 
	    for(i=0; i<7; i++) if( ch & (1<=0 || errno == EINTR) && wpid!=pid) 
      ; 
 
   set_mode(2); 
   (void) signal(SIGQUIT, oqsig); 
   (void) signal(SIGINT,  oisig); 
   (void) signal(SIGTERM, otsig); 
} 
 
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ 
 
#define NCHRS 4096 
static char chrs[NCHRS]; 
 
int alarm_delay = 0; 
jmp_buf timebuf; 
int is_in    = 0; 
 
alarm_int() { if( is_in ) longjmp(timebuf, -1); } 
 
char zmodem_buf[20]; 
char *zptr=zmodem_buf; 
 
char z_request[]   =  "*\030B00"; 
char z_challange[] = "**\030B0e313233341821\r\n"; 
char z_charesp[]   =  "*\030B0331323334395b"; 
 
/* With this you become a SZModem ver 1.x 
char z_challange[] = "**\030B0e534d4201053c\r\n"; 
char z_charesp[]   =  "*\030B03424d5301";  
/* */ 
 
int paused = 0; 
 
unpause_reader() 
{ 
   paused = 0; 
} 
 
pause_reader() 
{ 
   alarm(0); is_in = 0; 
 
   write(2, "Paused\r\n", 8); 
   signal(SIGUSR1, SIG_IGN); 
   signal(SIGUSR2, unpause_reader); 
#ifdef LOGFILE 
   if( lfile ) fflush(lfile); 
#endif 
   paused = 1; 
   while(paused) pause(); 
   signal(SIGUSR2, SIG_IGN); 
   signal(SIGUSR1, pause_reader); 
   write(2, "Continue\r\n", 10); 
} 
 
read_tty() 
{ 
   register int i, n; 
   register char *p; 
 
   /* Child process */ 
   signal(SIGINT,  SIG_IGN); 
   signal(SIGQUIT, SIG_IGN); 
   signal(SIGTERM, cleanup); 
   signal(SIGUSR1, pause_reader); 
 
#ifdef SCRIPT 
   if( in_script ) 
   { 
      open_script(script_name); 
      signal(SIGINT, cleanup); 
      set_mode(1); 
      alarm_delay = 2; 
   } 
#else 
#ifdef LOGFILE 
   open_logfile(); 
#endif 
#endif 
 
   for(;;) 
   { 
      if( alarm_delay ) 
      { 
         signal(SIGALRM, alarm_int); 
         alarm(2); 
         if( setjmp(timebuf) == 0 ) 
         { 
            is_in = 1; 
            n = read(line_fd, chrs, (int)NCHRS); 
            is_in = 0; 
         } 
         else 
         { 
            chrs[0] = 0xFF; 
            n = 1; 
         } 
         alarm(0); 
         signal(SIGALRM, SIG_DFL); 
      } 
      else 
         n = read(line_fd, chrs, (int)NCHRS); 
      if( n == 0 ) 
      { 
         printf("Carrier Lost\r\n"); 
         break; 
      } 
      if( n > 0 ) 
      { 
         for(i=0;i=0 || errno == EINTR) && wpid!=pid) 
      if( wpid == wr_pid ) 
	 cleanup(); 
 
   signal(SIGCHLD, cleanup); 
 
   set_mode(2); 
   (void) signal(SIGQUIT, oqsig); 
   (void) signal(SIGINT,  oisig); 
   (void) signal(SIGTERM, otsig); 
} 
 
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ 
 
dumbch(ch) 
int ch; 
{ 
static int cr_pend = 0; 
 
   if( cr_pend ) 
   { 
      if( ch == '\n' ) putchar('\r'); 
      else { putchar('^'); putchar('M'); } 
      cr_pend = 0; 
   } 
   if( ch == '\r' ) 
      cr_pend = 1; 
   else 
   { 
      if( ch & 0x80 ) 
	 printf("M-"); 
      if( isprint(ch&0x7F) || ch == '\n' || ch == '\b' ) 
	 putchar(ch&0x7F); 
      else 
      { 
	 putchar('^'); 
	 putchar((ch ^ '@')&0x7F); 
      } 
   } 
} 
 
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ 
 
uucp_check(device) 
char * device; 
{ 
   FILE * fd; 
   char nbuf[128]; 
   char * p; 
   int i; 
 
   fd = fopen("/usr/spool/uucp", "r"); 
   if( fd == 0 ) return 1;  /* No directory assume ok */ 
   fclose(fd); 
   p = strrchr(device, '/'); 
   strcpy(nbuf, "/usr/spool/uucp/LCK.."); 
   if( p ) strcat(nbuf, p+1); 
   else    strcat(nbuf, device); 
   for(p=nbuf+21; *p; p++) if( *p>='A' && *p<='Z' ) *p = *p-'A'+'a'; 
   fd = fopen(nbuf, "r"); 
   if( fd ) 
   { 
      fscanf(fd, "%d", &i); 
      fclose(fd); 
      if( kill(i, 0) == 0 ) return 0;   /* Sorry */ 
      if( unlink(nbuf) == -1 ) return 0; 
   } 
   fd = fopen(nbuf, "w"); /* Got it! */ 
   fprintf(fd, "%10d\n", getpid()); 
   fclose(fd); 
   return 1; 
} 
 
uucp_unlock(device) 
char * device; 
{ 
   FILE * fd; 
   char nbuf[128]; 
   char * p; 
   int i; 
 
   fd = fopen("/usr/spool/uucp", "r"); 
   if( fd == 0 ) return;  /* No directory assume ok */ 
   fclose(fd); 
   p = strrchr(device, '/'); 
   strcpy(nbuf, "/usr/spool/uucp/LCK.."); 
   if( p ) strcat(nbuf, p+1); 
   else    strcat(nbuf, device); 
   for(p=nbuf+21; *p; p++) if( *p>='A' && *p<='Z' ) *p = *p-'A'+'a'; 
   fd = fopen(nbuf, "r"); 
   if( fd ) 
   { 
      fscanf(fd, "%d", &i); 
      fclose(fd); 
      if( i == getpid() || kill(i, 0) != 0 ) 
         unlink(nbuf); 
   } 
} 
 
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ 
 
#ifdef SCRIPT 
 
#define MAXMATCH 20   /* Max number of match strings at a time */ 
#define MATCHLEN 20   /* Max size of a match string */ 
static int starcount = 50; 
 
static FILE * script_file; 
static char buffer[MATCHLEN*3]; 
static int offset = sizeof(buffer)/2; 
static check_match(); 
static clear_matchtab(); 
static read_matchset(); 
static char * get_item(); 
static vdisp(); 
static script_com(); 
 
static int timeout  = 0; 
static long last_ok = 0; 
 
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ 
 
out_schar(ch) 
int ch; 
{ 
   long now; 
   int ok = 1; 
 
   if( ch != 0 ) /* Completely ignore nuls */ 
   { 
      if( ch != '\377' ) buffer[offset++] = (ch&0x7F); 
      else               buffer[offset++] = '\377'; 
      if( offset == sizeof(buffer) ) 
      { 
         offset = sizeof(buffer)/2; 
         memcpy(buffer, buffer+sizeof(buffer)/2, sizeof(buffer)/2); 
      } 
      buffer[offset] = '\0'; 
 
      ok = check_match(); 
   } 
   time(&now); 
   if( timeout && now > last_ok + timeout ) 
   { 
      printf("\r\nTimeout ... Script aborted\r\n"); 
      cleanup(); 
   } 
   return ok; 
} 
 
open_script(fname) 
char * fname; 
{ 
   char buf[200]; 
   if(script_file) close_script(); 
   strcpy(buf, fname); 
   strcat(buf, ".sct"); 
   script_file = fopen(buf, "r"); 
   if( script_file == 0 ) 
   { 
      strcpy(buf, "sct/"); 
      strcat(buf, fname); 
      strcat(buf, ".sct"); 
      script_file = fopen(buf, "r"); 
   } 
   if( script_file == 0 ) return 0; 
   time(&last_ok); 
   timeout = 10; 
   read_matchset(); 
   check_match(); 
   return 1; 
} 
 
close_script() 
{ 
   clear_matchtab(); 
   if(script_file) 
      fclose(script_file); 
   script_file = 0; 
   timeout = 0; 
} 
 
#define VALIDREC	1	/* This record is available for matching */ 
#define ALTMATCH	2	/* Is an extra match record for prev line */ 
#define SCCOM		4	/* sendstr is a script command */ 
#define UXCOM		8	/* sendstr is a unix command */ 
 
static 
struct matchrec 
{ 
   char match[MATCHLEN]; 
   int  matchlen; 
   int  maxcount; 
   char * sendstr; 
   int  flags; 
} 
   matchtab[MAXMATCH]; 
 
static int matcount; 
 
static 
check_match() 
{ 
   struct matchrec * sptr; 
   struct matchrec * mptr; 
   extern int line_fd; 
   int i,j; 
   int checked_one; 
 
Restart: 
   sptr = matchtab; 
   mptr = matchtab; 
   checked_one = 0; 
 
   for(i=0; iflags & ALTMATCH) == 0 ) sptr = mptr; 
 
      if( (sptr->flags & VALIDREC) == 0 ) continue; 
      checked_one = 1; 
      if( (mptr->matchlen == 0  
           || ( buffer[offset-mptr->matchlen] == mptr->match[0] 
              && strcmp(buffer+offset-mptr->matchlen, mptr->match) == 0 ) 
          ) 
        ) 
      { 
         time(&last_ok); 
         offset = sizeof(buffer)/2; 
         memset(buffer, 0, sizeof(buffer)); 
         if( mptr->matchlen ) vdisp(0, "\r\n"); 
         if( sptr->flags & SCCOM ) 
	    switch(script_com(sptr->sendstr)) 
	    { 
	    case 0: break; 
	    case 1: close_script(); return 0; 
	    case 2: goto Restart; 
	    } 
#if 0 
         else if( sptr->flags & UXCOM ) 
#endif 
         else 
         { 
            vdisp(0, " '"); 
            if( line_fd ) 
	    { 
	       /* Yes we want this ssslllooowww incase */ 
	       /* the other end is stupid */ 
	       /* Of course this isn't really that slow */ 
	       char ch[2]; 
	       ch[1] = '\0'; 
	       for(i=0; sptr->sendstr[i]; i++) 
	       { 
		  ch[0] = sptr->sendstr[i]; 
                  vdisp(1, ch); 
	          if(*ch == '\377') 
		     sleep(2); 
                  else 
		  { 
                     write(line_fd, ch, 1); 
#ifdef M_XENIX 
		     nap(20); 
#else 
                     usleep(20000L); 
#endif 
                  } 
	       } 
	    } 
            vdisp(0, "'\r\n"); 
         } 
         time(&last_ok); 
         if( sptr->maxcount ) 
         { 
            if( --(sptr->maxcount) == 0 ) 
            { 
               sptr->flags &= ~VALIDREC; 
            } 
         } 
         else 
	 { 
            read_matchset(); 
            goto Restart;   /* Incase this is a '- "Send"' line */ 
	 } 
         break; 
      } 
   } 
   return checked_one; 
} 
 
static 
clear_matchtab() 
{ 
   int i; 
   for(i=0; iscrfd; 
	 strcpy(script_args, p->script_args); 
	 saved_sc = p->next; 
	 free(p); 
	 continue; 
      } 
      p = lbuf; 
      while( *p == ' ' || *p == '\t' ) p++; 
      if( *p == '#' || *p == '\n' || *p == '\0' ) continue; 
#ifdef VARS 
      if( *p == '%' ) 
      if( *p == '$' ) 
#endif 
      memset(&new, 0, sizeof(new)); 
      if( *p == '*' || *p == '?' ) 
      { 
	 if( *p == '?' ) new.maxcount = 1; 
	 else            new.maxcount = starcount; 
	 p++; while( *p == ' ' || *p == '\t' ) p++; 
      } 
      else 
         keepgoing = 0; 
      saveptr = matcount; 
      do 
      { 
         if( *p == ',' ) p++; 
       
	 p = get_item(p, new.match, sizeof(new.match), 0); 
	 if( p == 0 ) 
	 { 
	    fprintf(stderr, "Syntax error:%s", lbuf); 
	    goto next_line; 
	 } 
         new.matchlen = strlen(new.match); 
	 if( new.matchlen ) 
	 { 
            if( wflg == 0 ) { vdisp(0, ""); wflg = 1; } 
            vdisp(0, " '"); 
            vdisp(1, new.match); 
            vdisp(0, "'"); 
	 } 
	 while( *p == ' ' || *p == '\t' ) p++; 
         if( matcount >= MAXMATCH ) 
            fprintf(stderr, "Too many match strings\r\n"); 
         else 
         { 
            matchtab[matcount] = new; 
            matcount++; 
            new.flags |= ALTMATCH; 
         } 
      } 
      while( *p == ','); 
 
      p = get_item(p, sbuf, sizeof(sbuf), 1); 
      if( p == 0 ) 
      { 
         fprintf(stderr, "Syntax error:%s", lbuf); 
         goto next_line; 
      } 
      if( *sbuf != '"' )  
      { 
         matchtab[saveptr].sendstr = malloc(strlen(sbuf)+1); 
         strcpy(matchtab[saveptr].sendstr, sbuf); 
         matchtab[saveptr].flags |= SCCOM; 
         while( (p = get_item(p, sbuf, sizeof(sbuf), 1)) != 0 ) 
	 { 
	    matchtab[saveptr].sendstr = realloc(matchtab[saveptr].sendstr, 
	             strlen(matchtab[saveptr].sendstr) + strlen(sbuf)+2); 
	    strcat(matchtab[saveptr].sendstr, " "); 
	    strcat(matchtab[saveptr].sendstr, sbuf); 
	 } 
      } 
      else 
      { 
         matchtab[saveptr].sendstr = malloc(strlen(sbuf)); 
         strcpy(matchtab[saveptr].sendstr, sbuf+1); 
      } 
      matchtab[saveptr].flags |= VALIDREC; 
       
next_line: ; 
   } 
   if( wflg ) vdisp(0, "\r\n"); 
} 
 
static char * 
get_item(p, buf, szbuf, itype) 
char * p; 
char * buf; 
int szbuf; 
int itype; 
{ 
   char stc; 
   while( *p == ' ' || *p == '\t' ) p++; 
   if( *p == '-' ) 
   { 
      if( itype == 0 ) buf[0] = '\0'; else buf[0] = '"'; 
      buf[1] = '\0'; 
      p++; return p; 
   } 
   else if( ( itype == 0 && *p != '"' ) || *p == '\0' ) 
   { 
      buf[0] = '\0'; return 0; 
   } 
   if( itype == 0 ) stc = *p++; 
   else { *buf++ = stc = *p++; szbuf--; } 
   while( *p ) 
   { 
      if( stc == '"' && *p == '"' ) break; 
      if( stc != '"' && (*p == ' ' || *p == '\t' || *p == '\n') ) break; 
      if( szbuf < 2+(itype&1) ) { p++; continue; ; } 
      szbuf--; 
      if( *p == '\\' && p[1] ) 
      { 
	 switch(p[1]) 
	 { 
	 case 'b': *buf++ = '\b'; break; 
	 case 'c': itype &= ~1; break; 
	 case 'd': *buf++ = '\377'; break; 
	 case 'f': *buf++ = '\f'; break; 
	 case 'n': *buf++ = '\n'; break; 
	 case 'r': *buf++ = '\r'; break; 
	 case 't': *buf++ = '\t'; break; 
	 case 'a': 
	    { 
	       char * q = script_args; 
	       while(*q) *buf++ = *q++; 
	    } 
	    break; 
	 default:  *buf++ = p[1]; break; 
	 } 
	 p+=2; 
      } 
      else 
	 *buf++ = *p++; 
   } 
   if( itype&1 && stc == '"' ) *buf++ = '\r'; 
   *buf = 0; 
   if( *p ) p++; 
   return p; 
} 
 
static 
script_com(str) 
char * str; 
{ 
extern char logfname[]; 
 
   vdisp(0, " '"); 
   vdisp(1, str); 
   vdisp(0, "'\r\n"); 
   if( strncmp("timeout=", str, 8) == 0 ) 
      timeout = atoi(str+8); 
   else if( strncmp("starcount=", str, 10) == 0 ) 
      starcount = atoi(str+10); 
   else if( strncmp("cd=", str, 3) == 0 ) 
      chdir(str+3); 
#ifdef LOGFILE 
   else if( strncmp("logfile=", str, 8) == 0 ) 
      strcpy(logfname, str+8); 
   else if( strcmp("logstart", str) == 0 ) 
   { 
      if( lfile == 0 ) { printf("\r\n"); open_logfile(); } 
   } 
   else if( strcmp("logbuf", str) == 0 ) 
      ltptr = ltbuf; 
#endif 
   else if( strncmp("con", str, 3) == 0 ) 
      return 1; 
   else if( strcmp("abort", str) == 0 ) 
   { 
      printf("\r\nAborted\r\n"); 
      cleanup(); 
   } 
   else if( strcmp("end", str) == 0 ) 
   { 
      printf("\r\nScript completed\r\n"); 
      cleanup(); 
   } 
   else if( strncmp("call ", str, 5) == 0 ) 
   { 
      struct script_sv * p; 
      char * s; 
 
      p = (struct script_sv * ) malloc(sizeof(struct script_sv)); 
      if( p == 0 ) { fprintf(stderr, "Out of memory\r\n"); return 0; } 
      p->next = saved_sc; 
      p->scrfd = script_file; 
      strcpy(p->script_args, script_args); 
      s = strchr(str+5, ' '); 
      script_file = 0; 
      if( s ) { *s = '\0'; strcpy(script_args, s+1); } 
      else *script_args = '\0'; 
 
      if( open_script(str+5) ) 
      { 
         saved_sc = p; 
	 return 2; 
      } 
      else 
      { 
         fprintf(stderr, "Cannot open '%s.sct'\r\n", str+5); 
	 script_file = p->scrfd; 
         strcpy(script_args, p->script_args); 
	 free(p); 
      } 
   } 
   else if( strcmp("nobreak", str) == 0 ) 
   { 
      set_mode(2); 
      signal(SIGINT, SIG_IGN); 
   } 
   else if( strcmp("parity", str) == 0 ) 
   { 
      Bit_mask = 0x7F; Parity=1; 
   } 
   else if( strcmp("sevenbit", str) == 0 ) 
   { 
      Bit_mask = 0x7F; 
   } 
   else if( strcmp("eightbit", str) == 0 ) 
   { 
      Bit_mask = 0xFF; 
   } 
   else if( strcmp("rawterm", str) == 0 ) 
   { 
      Termtype = 0; 
   } 
   else if( strcmp("dumbterm", str) == 0 ) 
   { 
      Termtype = 1; 
   } 
   else 
      fprintf(stderr, "< Error > Command '%s' not found!\r\n", str); 
 
   return 0; 
} 
 
static vdisp(flg, str) 
int flg; 
char * str; 
{ 
   if( verbose != 1 ) return; 
   fflush(stdout); 
   if( !flg ) fprintf(stderr, "%s", str); 
   else while( *str ) 
   { 
      int ch = *str++; 
      ch &= 0xFF; 
      if( ch >= ' ' && ch != 0x9B && ch != '\\' && ch != 0xFF) 
         fputc(ch, stderr); 
      else if( ch < ' ' ) 
         fprintf(stderr, "^%c", ch+'@'); 
      else if( ch == 0xFF ) 
         fprintf(stderr, "\\d"); 
      else 
         fprintf(stderr, "\\0x%02x", ch); 
   } 
} 
#endif