home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / ncr9800 / ckvscr.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  15KB  |  454 lines

  1. char     *loginv = "Script Command, V2.0(007) 11 May 90";
  2.  
  3. /*  C K U S C R  --  Login script for logging onto remote system */
  4.  
  5. /**********************************************************************
  6. *                                                                     *
  7. * IVS / MCS-Kermit REL 2                                              *
  8. * source code                                                         *
  9. *                                                                     *
  10. * Change History:                                                     *
  11. *                                                                     *
  12. *                1. Modify C-Kermit(4E) source code to                *
  13. *                   produce new module for MCS/IVS-Kermit             *
  14. *                   ORIGINAL RELEASE                                  *
  15. *                   June 22, 1990                                     *
  16. *                                                                     *
  17. *                                                                     *
  18. ***********************************************************************/
  19.  
  20. /*
  21.  This module should work under all versions of NCR-VRX.  It calls externally
  22.  defined system-depended functions for i/o.
  23.  
  24.  The module expects a login string of the expect send [expect send] ...
  25.  format.  It is intended to operate similarly to the way the common
  26.  uucp "L.sys" login entries work.  Conditional responses are supported
  27.  expect[-send-expect[...]] as with uucp.  The send keyword EOT sends a
  28.  control-d, and the keyword BREAK sends a break.  Letters prefixed
  29.  by '~' are '~b' backspace, '~s' space, '~n' linefeed, '~r' return, '~x' xon,
  30.  '~t' tab, '~q' ? (not allowed on kermit command lines), '~' ~, '~'',
  31.  '~"', '~c' don't append return, '~o[o[o]]' octal character.  As with
  32.  some uucp systems, sent strings are followed by ~r (not ~n) unless they
  33.  end with ~c. Null expect strings (e.g., ~0 or --) cause a short
  34.  delay, and are useful for sending sequences requiring slight pauses.
  35.  
  36.  Author: Herm Fischer (HFISCHER@USC-ECLB)
  37.  Contributed to Columbia University for inclusion in C-Kermit.
  38.  Copyright (C) 1985, Herman Fischer, 16400 Ventura Blvd, Encino CA 91436
  39.  Permission is granted to any individual or institution to use, copy, or
  40.  redistribute this software so long as it is not sold for profit, provided this
  41.  copyright notice is retained.
  42. */
  43.  
  44. #include "ckcdeb.h"
  45. #include <stdio.h>
  46. #include <ctype.h>
  47. #include <signal.h>
  48. #include <setjmp.h>
  49. #include "ckcker.h"
  50. #include "kermisc.h"
  51. #ifdef MCS_FLAG
  52. #include "mcs.h"
  53. #endif
  54.  
  55. extern int     local, speed, flow, seslog, mdmtyp, quiet, duplex, deblog;
  56. extern char    ttname[];
  57. extern CHAR    dopar();
  58. static char    *chstr();
  59.  
  60. static int     EXP_ALRM = 15;           /* Time to wait for expect string */
  61. #define SND_ALRM        15              /* Time to allow for sending string */
  62. #define NULL_EXP        2               /* Time to pause on null expect strg*/
  63. #define DEL_MSEC        300             /* milliseconds to pause on ~d */
  64.  
  65. #define SBUFL 512
  66. static char     seq_buf[SBUFL], *s;         /* Login Sequence buffer */
  67. static char     fls_buf[SBUFL];             /* Flush buffer */
  68. static int     got_it, no_cr;
  69.  
  70. /*  connect state parent/child communication signal handlers */
  71.  
  72. static jmp_buf alrmRng;         /* Envir ptr for connect errors */
  73.  
  74. scrtime()
  75. {                             /* modem read failure handler, */
  76.      longjmp(alrmRng, 1);         /* notifies parent process to stop */
  77. }
  78.  
  79.  
  80. /*
  81.  Sequence interpreter -- pick up next sequence from command string,
  82.  decode escapes and place into seq_buf
  83.  
  84.  If string contains a ~d (delay) then sequenc returns a 1 expecting
  85.  to be called again after the ~d executes.
  86. */
  87. static
  88. sequenc()
  89. {
  90.  
  91.      int     i;
  92.      char     c, oct_char;
  93.  
  94.      no_cr = 0;                          /* output needs cr appended */
  95.  
  96.      for (i = 0; i < SBUFL; ) {
  97.           if (*s == '\0' || *s == '-' || isspace(*s) ) { /* done */
  98.                seq_buf[i] = '\0';
  99.                return(0) ;
  100.           }
  101.  
  102.           if (*s == '~') {                /* escape character */
  103.                switch (c = *(++s) ) {
  104.                case 'n':
  105.                     seq_buf[i++] = '\n';
  106.                     break;
  107.                case 'r':
  108.                     seq_buf[i++] = '\r';
  109.                     break;
  110.                case 't':
  111.                     seq_buf[i++] = '\t';
  112.                     break;
  113.                case 'b':
  114.                     seq_buf[i++] = '\b';
  115.                     break;
  116.                case 'q':
  117.                     seq_buf[i++] = '?';
  118.                     break;
  119.                case '~':
  120.                     seq_buf[i++] = '~';
  121.                     break;
  122.                case '\'':
  123.                     seq_buf[i++] = '\'';
  124.                     break;
  125.                case '\"':
  126.                     seq_buf[i++] = '\"';
  127.                     break;
  128.                case 's':
  129.                     seq_buf[i++] = ' ';
  130.                     break;
  131.                case 'x':
  132.                     seq_buf[i++] = '\021';
  133.                     break;
  134.                case 'c':
  135.                     no_cr = 1;
  136.                     break;
  137.                case 'd':
  138.                      {                     /* send what we have & then */
  139.                          /* expect to send rest after */
  140.                          seq_buf[i] = '\0';
  141.                           /* sender delays a little */
  142.                          no_cr = 1;
  143.                          s++;
  144.                          return(1);
  145.                     }
  146.                case 'w':
  147.                      {                     /* wait count */
  148.                          EXP_ALRM = 15;              /* default to 15 sec */
  149.                          if ( isdigit( *(s + 1) ) ) {
  150.                               EXP_ALRM = (*(++s)) &
  151.                                   15;
  152.                               if ( isdigit( *(s +
  153.                                   1) ) ) {
  154.                                    EXP_ALRM = EXP_ALRM
  155.                                        *10 + ( (*(++s)) &
  156.                                        15 );
  157.                               }
  158.                          }
  159.                          break;
  160.                     }
  161.                default:
  162.                     if ( isdigit(c) ) {         /* octal character */
  163.                          oct_char = (c & 7);     /* most significant digit */
  164.                          if (isdigit( *(s + 1) ) ) {
  165.                               oct_char = (oct_char
  166.                                   << 3) | ( (*(++s)) &
  167.                                   7 ) ;
  168.                               if (isdigit( *(s + 1) ) ) {
  169.                                    oct_char = (oct_char
  170.                                        << 3) | ( (*(++s)) &
  171.                                        7 ) ;
  172.                               }
  173.                          }
  174.                          seq_buf[i++] = oct_char;
  175.                          break;
  176.                     }
  177.                }
  178.           } else
  179.                seq_buf[i++] = *s;         /* plain old character */
  180.           s++;
  181.      }
  182.      seq_buf[i] = '\0';
  183.      return(0);                  /* end of space, return anyway */
  184. }
  185.  
  186.  
  187. /*
  188.  Receive sequence -- see if expected response comes return success
  189.  (or failure) in got_it
  190. */
  191. static
  192. recvSeq()
  193. {
  194.  
  195.      char     *e, got[7], trace[SBUFL];
  196.      int     i, l;
  197.  
  198.      sequenc();
  199.      l = strlen(e = seq_buf);          /* no more than 7 chars allowed */
  200.      if (l > 7) {
  201.           e += l - 7;
  202.           l = 7;
  203.      }
  204.      tlog(F111, "expecting sequence", e, (long) l);
  205.      if (l == 0) {           /* null sequence, just delay a little */
  206.           sleep (NULL_EXP);
  207.           got_it = 1;
  208.           tlog(F100, "got it (null sequence)", "", 0l);
  209.           return;
  210.      }
  211.      *trace = '\0';
  212.      for (i = 0; i < 7; i++)
  213.           got[i] = '\0';
  214.  
  215.      SIGNAL(SIGALRM, scrtime);        /* did we get it? */
  216.      if (!setjmp(alrmRng)) { /* not timed out yet */
  217.           ALARM(EXP_ALRM);
  218.           while (!got_it) {
  219.                for (i = 0; i < (l - 1); i++)
  220.                     got[i] = got[i+1]; /* shift over one */
  221.                got[l-1] = ttinc(0) & 0177;             /* next char */
  222.                if (seslog)             /* Log in session log */
  223.                     zchout(ZSFILE, got[l-1]);
  224.                if (strlen(trace) < sizeof(trace) - 2 )
  225.                     strcat(trace, chstr(got[l-1]));
  226.                got_it = (!strncmp(seq_buf, got, l) ) ;
  227.           }
  228.      } else
  229.           got_it = 0;              /* timed out here */
  230.  
  231.      ALARM(0);
  232.      SIGNAL(SIGALRM, SIG_IGN);
  233.      tlog(F110, "received sequence: ", trace, 0l);
  234.      tlog(F101, "returning with got-it code", "", (long) got_it);
  235.      return;
  236. }
  237.  
  238.  
  239. /*
  240.  Output A Sequence starting at pointer s,
  241.  return 0 if okay,
  242.  1 if failed to read (modem hangup or whatever)
  243. */
  244. static int
  245. outSeq()
  246. {
  247.      char     *sb;
  248.      int     l;
  249.      int     delay;
  250.      int     retCode = 0;
  251.  
  252.      while (1) {
  253.           delay = sequenc();
  254.           l = strlen(seq_buf);
  255.           tlog(F111, "sending sequence ", seq_buf, (long) l);
  256.           SIGNAL(SIGALRM, scrtime);
  257.           if (!setjmp(alrmRng)) {
  258.                ALARM(SND_ALRM);
  259.                if (!strcmp(seq_buf, "EOT")) {
  260.                     ttoc(dopar('\004'));
  261.                     if (seslog && duplex)
  262.                          zsout(ZSFILE, "{EOT}");
  263.                } else if (!strcmp(seq_buf, "BREAK")) {
  264.                     ttsndb();
  265.                     zsout(ZSFILE, "{BREAK}");
  266.                } else {
  267.                     if (l > 0) {
  268.                          for ( sb = seq_buf; *sb; sb++)
  269.                               *sb = dopar(*sb);
  270.                          ttol(seq_buf, l);                /* with parity */
  271.                          if (seslog && duplex)
  272.                               zsout(ZSFILE, seq_buf);
  273.                     }
  274.                     if (!no_cr) {
  275.                          ttoc( dopar('\r') );
  276.                          if (seslog && duplex)
  277.                               zchout(ZSFILE, dopar('\r'));
  278.                     }
  279.                }
  280.           } else
  281.                retCode |= -1;             /* else -- alarm rang */
  282.           ALARM(0);
  283.           SIGNAL(SIGALRM, SIG_IGN);
  284.           if (!delay)
  285.                return ( retCode );
  286.           msleep(DEL_MSEC);       /* delay, and loop to next stuff to send */
  287.      }
  288. }
  289.  
  290.  
  291. /*  L O G I N  --  Login to remote system */
  292.  
  293. login(cmdstr)
  294. char     *cmdstr;
  295. {
  296.  
  297.      SIGTYP (*saveAlm)();    /* save incoming alarm function */
  298.      char     *e;
  299.  
  300.      s = cmdstr;                     /* make global to ckuscr.c */
  301.  
  302.      tlog(F100, loginv, "", 0l);
  303.  
  304.      if (!local) {
  305. #ifndef MCS_FLAG
  306.           printf("Sorry, you must 'set line' first\n");
  307. #else
  308.           mcs_printf("Sorry, you must 'set line' first\n");
  309. #endif
  310.           return(-2);
  311.      }
  312.      if (speed < 0) {
  313. #ifndef MCS_FLAG
  314.           printf("Sorry, you must 'set speed' first\n");
  315. #else
  316.           mcs_printf("Sorry, you must 'set speed' first\n");
  317. #endif
  318.           return(-2);
  319.      }
  320.      if (ttopen(ttname, &local, mdmtyp) < 0) {
  321.           sprintf(seq_buf, "Sorry, can't open %s", ttname);
  322.           perror(seq_buf);
  323.           return(-2);
  324.      }
  325. #ifndef MCS_FLAG
  326.      if (!quiet)
  327.           printf("Executing script thru %s, speed %d.\r\n", ttname,
  328.                speed);
  329. #else
  330.      if (!quiet) {
  331.           sprintf(print_str,"Executing script thru %s, speed %d.\r\n", ttname,
  332.                speed);
  333.           mcs_printf(print_str);
  334.      }
  335. #endif
  336.      *seq_buf = 0;
  337.      for (e = s; *e; e++)
  338.           strcat(seq_buf, chstr(*e) );
  339. #ifndef MCS_FLAG
  340.      if (!quiet)
  341.           printf("Script string: %s\r\n", seq_buf);
  342. #else
  343.      if (!quiet) {
  344.        sprintf(print_str,"Script string: %s\r\n", seq_buf);
  345.        mcs_printf(print_str);
  346.      }
  347. #endif
  348.      tlog(F110, "Script string: ", seq_buf, 0l);
  349.  
  350.      /* Condition console terminal and communication line */
  351.  
  352.      if (ttvt(speed, flow) < 0) {
  353. #ifndef MCS_FLAG
  354.           printf("Sorry, Can't condition communication line\n");
  355. #else
  356.           mcs_printf("Sorry, Can't condition communication line\n");
  357. #endif
  358.           return(-2);
  359.      }
  360.      /* save initial timer interrupt value */
  361.      saveAlm = SIGNAL(SIGALRM, SIG_IGN);
  362.  
  363.      flushi();               /* flush stale input */
  364.  
  365.      /* start expect - send sequence */
  366.  
  367.      while (*s) {                /* while not done with buffer */
  368.  
  369.           while (*s && isspace(*s))
  370.                s++;  /* skip over separating whitespaces */
  371.           /* gather up expect sequence */
  372.           got_it = 0;
  373.           recvSeq();
  374.  
  375.           while (!got_it) {
  376.                /* no, is there a conditional send */
  377.                if (*s++ != '-')
  378.                     goto failRet;      /* no -- return failure */
  379.  
  380.                /* start of conditional send */
  381.                flushi();                           /* flush out input buffer */
  382.                if (outSeq())
  383.                     goto failRet;         /* if unable to send! */
  384.  
  385.                if (*s++ != '-')
  386.                     goto failRet;      /* must have condit respon.*/
  387.                recvSeq();
  388.           }       /* loop back and check got_it */
  389.  
  390.           while (*s && !isspace(*s++) )
  391.                ; /* Skip over conditionals */
  392.           while (*s && isspace(*s))
  393.                s++;  /* Skip over separating whitespaces */
  394.           flushi();                       /* Flush */
  395.           if (*s)
  396.                if (outSeq())
  397.                     goto failRet; /* If any */
  398.      }
  399.      SIGNAL(SIGALRM, saveAlm);
  400.      if (!quiet)
  401. #ifndef MCS_FLAG
  402.           printf("Script successful.\r\n");
  403. #else
  404.           mcs_printf("Script successful.\r\n");
  405. #endif
  406.      tlog(F100, "Script successful.", "", 0l);
  407.      return(0);
  408.  
  409. failRet:
  410.      SIGNAL(SIGALRM, saveAlm);
  411. #ifndef MCS_FLAG
  412.      printf("Sorry, script failed\r\n");
  413. #else
  414.      mcs_printf("Sorry, script failed\r\n");
  415. #endif
  416.      tlog(F100, "Script failed", "", 0l);
  417.      return(-2);
  418. }
  419.  
  420.  
  421. /*  C H S T R  --  Make printable string from a character */
  422.  
  423. static char     *
  424. chstr(c)
  425. char     c;
  426. {
  427.      static char     sc[4];
  428.  
  429.      if (c < SP)
  430.           sprintf(sc, "^%c", ctl(c) );
  431.      else
  432.           sprintf(sc, "%c", c);
  433.  
  434.      return(sc);
  435. }
  436.  
  437.  
  438. /*  F L U S H I  --  Flush, but log, input buffer  */
  439.  
  440. flushi()
  441. {
  442.      int     n;
  443.      if (seslog) {                       /* Logging session? */
  444.           n = ttchk();                    /* Yes, anything in buffer? */
  445.           if (n > 0) {                    /* If so, */
  446.                if (n > SBUFL)
  447.                     n = SBUFL;   /* make sure not too much, */
  448.                n = ttxin(n, fls_buf);       /* then read it, */
  449.                zsout(ZSFILE, fls_buf);      /* and log it. */
  450.           }
  451.      } else
  452.           ttflui();                    /* Otherwise just flush. */
  453. }
  454.