home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / old / ckermit4f / ckuscr.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  10KB  |  350 lines

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