1: #ifndef NOICP
   2: #ifndef NOSCRIPT
   3: char *loginv = "Script Command, 5A(015) 2 Nov 92";
   4: 
   5: /*  C K U S C R  --  Login script for logging onto remote system */
   6: 
   7: /*
   8:   Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
   9:   York.  Permission is granted to any individual or institution to use this
  10:   software as long as it is not sold for profit.  This copyright notice must be
  11:   retained.  This software may not be included in commercial products without
  12:   written permission of Columbia University.
  13: 
  14:   Original (version 1, 1985) author: Herm Fischer, Encino, CA.
  15:   Contributed to Columbia University in 1985 for inclusion in C-Kermit 4.0.
  16:   Author and maintainer since 1985: Frank da Cruz, Columbia University,
  17:   fdc@columbia.edu.
  18: */
  19: 
  20: /*
  21:   The module expects a login string of the expect send [expect send] ...
  22:   format.  It is intended to operate similarly to the way the common
  23:   uucp "L.sys" login entries work.  Conditional responses are supported
  24:   expect[-send-expect[...]] as with uucp.  The send keyword EOT sends a
  25:   control-d, and the keyword BREAK sends a break.  Letters prefixed
  26:   by '~' are '~b' backspace, '~s' space, '~n' linefeed, '~r' return, '~x' xon,
  27:   '~t' tab, '~q' ? (not allowed on kermit command lines), '~' ~, '~'',
  28:   '~"', '~c' don't append return, '~o[o[o]]' octal character.  As with
  29:   some uucp systems, sent strings are followed by ~r (not ~n) unless they
  30:   end with ~c. Null expect strings (e.g., ~0 or --) cause a short
  31:   delay, and are useful for sending sequences requiring slight pauses.
  32: 
  33:   This module calls externally defined system-dependent functions for
  34:   communications i/o, as defined in CKCPLM.DOC, the C-Kermit Program Logic
  35:   Manual, and thus should be portable to all systems that implement those
  36:   functions, and where alarm() and signal() work as they do in UNIX.
  37: */
  38: 
  39: #include "ckcdeb.h"
  40: #include <signal.h>
  41: #include <setjmp.h>
  42: #include "ckcasc.h"
  43: #include "ckcker.h"
  44: #include "ckuusr.h"
  45: #include "ckcnet.h"
  46: 
  47: _PROTOTYP( VOID flushi, (void) );
  48: 
  49: #ifdef MAC
  50: #define SIGALRM (1<<10)
  51: #undef SIGTYP               /* put in ckcdeb.h later */
  52: #define SIGTYP void
  53: #endif /* MAC */
  54: 
  55: extern int local, flow, seslog, mdmtyp, msgflg, duplex, backgrd, secho, quiet;
  56: #ifdef NETCONN
  57: extern int network, ttnproto;
  58: #endif /* NETCONN */
  59: extern long speed;
  60: extern char ttname[];
  61: 
  62: #ifndef NOSPL
  63: extern struct cmdptr cmdstk[];
  64: extern int techo, cmdlvl;
  65: extern int mecho;
  66: #endif /* NOSPL */
  67: 
  68: static int scr_echo;            /* Whether to echo script commands */
  69: 
  70: static int exp_alrm = 15;       /* Time to wait for expect string */
  71: #define SND_ALRM 15         /* Time to allow for sending string */
  72: #define NULL_EXP 2          /* Time to pause on null expect strg*/
  73: #define DEL_MSEC 300            /* milliseconds to pause on ~d */
  74: 
  75: #define SBUFL 512
  76: static char seq_buf[SBUFL], *s;     /* Login Sequence buffer */
  77: static char fls_buf[SBUFL];     /* Flush buffer */
  78: static int got_it, no_cr;
  79: 
  80: /*  connect state parent/child communication signal handlers */
  81: 
  82: static jmp_buf alrmrng;         /* Envir ptr for connect errors */
  83: 
  84: SIGTYP
  85: scrtime(foo) int foo; {         /* modem read failure handler, */
  86:     longjmp(alrmrng,1);         /* notifies parent process to stop */
  87: }
  88: 
  89: /*
  90:  Sequence interpreter -- pick up next sequence from command string,
  91:  decode escapes and place into seq_buf.
  92: 
  93:  If string contains a ~d (delay) then sequenc returns a 1 expecting
  94:  to be called again after the ~d executes.
  95: */
  96: static int
  97: sequenc() {
  98:     int i;
  99:     char c, oct_char;
 100: 
 101:     no_cr = 0;              /* output needs cr appended */
 102:     for (i = 0; i < SBUFL; ) {
 103:     if (*s == '\0' || *s == '-' || isspace(*s) ) { /* done */
 104:         seq_buf[i] = '\0';
 105:         return(0) ;
 106:     }
 107:     if (*s == '~') {        /* escape character */
 108:         s++;
 109:         switch (c = *s) {
 110:         case 'n':  seq_buf[i++] = LF; break;
 111:         case 'r':  seq_buf[i++] = CR; break;
 112:         case 't':  seq_buf[i++] = '\t'; break;
 113:         case 'b':  seq_buf[i++] = '\b'; break;
 114:         case 'q':  seq_buf[i++] = '?';  break;
 115: #ifdef COMMENT
 116: /* The default case should catch these now... */
 117:         case '~':  seq_buf[i++] = '~';  break;
 118:         case '-':  seq_buf[i++] = '-';  break;
 119: #endif /* COMMENT */
 120:         case '\'': seq_buf[i++] = '\''; break;
 121:         case '\"': seq_buf[i++] = '\"'; break;
 122:         case 's':  seq_buf[i++] = ' ';  break;
 123:         case 'x':  seq_buf[i++] = '\021'; break;
 124:         case 'c':  no_cr = 1; break;
 125:         case 'd': {         /* send what we have & then */
 126:             seq_buf[i] = '\0';      /* expect to send rest after */
 127:             no_cr = 1;          /* sender delays a little */
 128:             s++;
 129:             return(1);
 130:         }
 131:         case 'w': {         /* wait count */
 132:             exp_alrm = 15;      /* default to 15 sec */
 133:             if (isdigit(*(s+1))) {
 134:             s++;
 135:             exp_alrm = *s & 15;
 136:             if (isdigit(*(s+1)) ) {
 137:                 s++;
 138:                 exp_alrm = exp_alrm * 10 + (*s & 15);
 139:             }
 140:             }
 141:             break;
 142:         }
 143:         default:
 144:             if ( isdigit(c) ) {         /* octal character */
 145:                 oct_char = (c & 7); /* most significant digit */
 146:             if (isdigit( *(s+1) ) ) {
 147:                 s++;
 148:                 oct_char = (oct_char<<3) | ( *s & 7 ) ;
 149:                 if (isdigit( *(s+1) ) ) {
 150:                 s++;
 151:                     oct_char = (oct_char<<3) | ( *s & 7 ) ;
 152:                 }
 153:             }
 154:             seq_buf[i++] = oct_char;
 155:             break;
 156:             } else seq_buf[i++] = *s; /* Treat ~ as quote */
 157:           }
 158:     } else seq_buf[i++] = *s;   /* Plain old character */
 159:     s++;
 160:     }
 161:     seq_buf[i] = '\0';
 162:     return(0);              /* end of space, return anyway */
 163: }
 164: 
 165: /*
 166:  Receive sequence -- see if expected response comes,
 167:  return success (or failure) in got_it.
 168: */
 169: static VOID
 170: recvseq()  {
 171: 
 172:     char *e, got[7], trace[SBUFL];
 173:     int i, l, x;
 174: 
 175:     sequenc();
 176:     l = (int)strlen(e=seq_buf); /* no more than 7 chars allowed */
 177:     if (l > 7) {
 178:         e += l-7;
 179:         l = 7;
 180:     }
 181:     tlog(F111,"expecting sequence",e,(long) l);
 182:     if (l == 0) {       /* null sequence, just delay a little */
 183:         sleep (NULL_EXP);
 184:         got_it = 1;
 185:         tlog(F100,"got it (null sequence)","",0L);
 186:         return;
 187:     }
 188:     *trace = '\0';
 189:     for (i = 0; i < 7; i++) got[i]='\0';
 190: 
 191:     signal(SIGALRM,scrtime);    /* did we get it? */
 192:     if (!setjmp(alrmrng)) {     /* not timed out yet */
 193:         alarm(exp_alrm);
 194:         while (!got_it) {
 195:         for (i = 0; i < l-1; i++) got[i] = got[i+1]; /* Shift over */
 196:         x = ttinc(0);       /* Read a character */
 197:         debug(F101,"recvseq","",x);
 198:         if (x < 0) goto rcvx;   /* Check for error */
 199: #ifdef NETCONN
 200: #ifdef TNCODE
 201: /* Check for telnet protocol negotiation */
 202:         if (network &&
 203:             (ttnproto == NP_TELNET) &&
 204:             ( (x & 0xff) == IAC) ) {
 205:             switch (tn_doop((CHAR)(x & 0xff),duplex,ttinc)) {
 206:               case 2: duplex = 0; continue;
 207:               case 1: duplex = 1;
 208:               default: continue;
 209:             }
 210:         }
 211: #endif /* TNCODE */
 212: #endif /* NETCONN */
 213:         got[l-1] = x & 0x7f;    /* Got a character */
 214:         if (scr_echo) conoc(got[l-1]); /* Echo it */
 215:         if (seslog)     /* Log it in session log */
 216:           if (zchout(ZSFILE,got[l-1]) < 0) seslog = 0;
 217:         if ((int)strlen(trace) < sizeof(trace)-2 )
 218:           strcat(trace,dbchr(got[l-1]));
 219:         got_it = (!strncmp(e, got, l));
 220:         }
 221:     } else got_it = 0;      /* timed out here */
 222: rcvx:
 223:     alarm(0);
 224:     signal(SIGALRM,SIG_IGN);
 225:     tlog(F110,"received sequence: ",trace,0L);
 226:     tlog(F101,"returning with got-it code","",(long) got_it);
 227:     return;
 228: }
 229: 
 230: /*
 231:  Output A Sequence starting at pointer s,
 232:  return 0 if okay,
 233:  1 if failed to read (modem hangup or whatever)
 234: */
 235: static int oseqret = 0;         /* Return code for outseq */
 236:                     /* Out here to prevent clobbering */
 237:                     /* by longjmp. */
 238: static int
 239: outseq() {
 240:     char *sb;
 241:     int l;
 242:     int delay;
 243: 
 244:     oseqret = 0;            /* Initialize return code */
 245:     while(1) {
 246:     delay = sequenc();
 247:     l = (int)strlen(seq_buf);
 248:     tlog(F111,"sending sequence ",seq_buf,(long) l);
 249:     signal(SIGALRM,scrtime);
 250:     if (!setjmp(alrmrng)) {
 251:         alarm(SND_ALRM);
 252:         if (!strcmp(seq_buf,"EOT")) {
 253:         ttoc(dopar('\004'));
 254:         if (scr_echo) conol("<EOT>");
 255:         if (seslog && duplex) if (zsout(ZSFILE,"<EOT>") < 0)
 256:           seslog = 0;
 257:         } else if (!strcmp(seq_buf,"BREAK") ||
 258:                !strcmp(seq_buf,"\\b") ||
 259:                !strcmp(seq_buf,"\\B")) {
 260:         ttsndb();
 261:         if (scr_echo) conol("<BREAK>");
 262:         if (seslog) if (zsout(ZSFILE,"{BREAK}") < 0) seslog = 0;
 263:         } else {
 264:         if (l > 0) {
 265:             for ( sb = seq_buf; *sb; sb++)
 266:               *sb = dopar(*sb); /* add parity */
 267:             ttol((CHAR *)seq_buf,l); /* send it */
 268:             if (scr_echo && duplex) conxo(l,seq_buf);
 269:             if (seslog && duplex) /* log it */
 270:               if (zsout(ZSFILE,seq_buf) < 0)
 271:             seslog=0;
 272:         }
 273:         if (!no_cr) {
 274:             ttoc( dopar(CR) );
 275:             if (seslog && duplex)
 276:               if (zchout(ZSFILE,dopar(CR)) < 0)
 277:             seslog = 0;
 278:         }
 279:         }
 280:     } else oseqret |= -1;       /* else -- alarm rang */
 281:     alarm(0);
 282:     signal(SIGALRM,SIG_IGN);
 283:     if (!delay) return(oseqret);
 284: #ifndef MAC
 285:     msleep(DEL_MSEC);       /* delay, loop to next send */
 286: #endif /* MAC */
 287:     }
 288: }
 289: 
 290: /*  L O G I N  --  Login to remote system */
 291: 
 292: int
 293: dologin(cmdstr) char *cmdstr; {
 294: 
 295:     SIGTYP (*savealm)();        /* save incoming alarm function */
 296:     char *e;
 297: 
 298:     s = cmdstr;         /* make global to ckuscr.c */
 299: 
 300:     tlog(F100,loginv,"",0L);
 301: 
 302:     if (speed < 0L) speed = ttgspd();
 303:     if (ttopen(ttname,&local,mdmtyp,0) < 0) {
 304:         sprintf(seq_buf,"Sorry, can't open %s",ttname);
 305:         perror(seq_buf);
 306:         return(0);
 307:         }
 308:     /* Whether to echo script cmds */
 309:     scr_echo = (!quiet && !backgrd && secho);
 310: #ifndef NOSPL
 311:     if (scr_echo && cmdlvl > 1) {
 312:         if (cmdstk[cmdlvl].src == CMD_TF)
 313:           scr_echo = techo;
 314:         if (cmdstk[cmdlvl].src == CMD_MD)
 315:           scr_echo = mecho;
 316:     }
 317: #endif /* NOSPL */
 318:         if (scr_echo) {
 319: #ifdef NETCONN
 320:         if (network)
 321:           printf("Executing SCRIPT to host %s.\n",ttname);
 322:         else
 323: #endif /* NETCONN */
 324:           printf("Executing SCRIPT through %s, speed %ld.\n",ttname,speed);
 325:     }
 326:     *seq_buf=0;
 327:     for (e = s; *e; e++) strcat(seq_buf, dbchr(*e) );
 328: #ifdef COMMENT
 329: /* Skip this because it tends to contain a password... */
 330:     if (scr_echo) printf("SCRIPT string: %s\n",seq_buf);
 331: #endif /* COMMENT */
 332:     tlog(F110,"SCRIPT string: ",seq_buf, 0L);
 333: 
 334: /* Condition console terminal and communication line */
 335: 
 336:     if (ttvt(speed,flow) < 0) {
 337:         printf("Sorry, Can't condition communication line\n");
 338:         return(0);
 339:         }
 340:     /* Save initial timer interrupt value */
 341:     savealm = signal(SIGALRM,SIG_IGN);
 342: 
 343:     flushi();       /* flush stale input */
 344: 
 345: /* start expect - send sequence */
 346: 
 347:     while (*s) {        /* while not done with buffer */
 348: 
 349:     while (*s && isspace(*s)) s++;  /* skip over separating whitespaces */
 350:                     /* gather up expect sequence */
 351:     got_it = 0;
 352:     recvseq();
 353: 
 354:     while (!got_it) {       /* Have it yet? */
 355:         if (*s++ != '-')        /* No, is there a conditional send? */
 356:           goto failret;     /* No, return failure */
 357:         flushi();           /* Yes, flush out input buffer */
 358:         if (outseq())       /* If unable to send, */
 359:           goto failret;     /* return failure. */
 360:         if (*s++ != '-')        /* If no conditional response here, */
 361:           goto failret;     /* return failure. */
 362:         recvseq();          /* All OK, read response from host. */
 363:     }               /* Loop back and check got_it */
 364: 
 365:     while (*s && !isspace(*s++) ) ; /* Skip over conditionals */
 366:     while (*s && isspace(*s)) s++;  /* Skip over separating whitespaces */
 367:     flushi();           /* Flush */
 368:     if (*s) if (outseq()) goto failret; /* If any */
 369:     }
 370:     signal(SIGALRM,savealm);
 371:     if (scr_echo) printf("Script successful.\n");
 372:     tlog(F100,"Script successful.","",0L);
 373:     return(1);
 374: 
 375: failret:
 376:     signal(SIGALRM,savealm);
 377:     if (scr_echo) printf("Sorry, script failed\n");
 378:     tlog(F100,"Script failed","",0L);
 379:     return(0);
 380: }
 381: 
 382: /*  F L U S H I  --  Flush, but log, input buffer  */
 383: 
 384: VOID
 385: flushi() {
 386:     int n;
 387:     if (seslog) {           /* Logging session? */
 388:         n = ttchk();            /* Yes, anything in buffer? */
 389:         if (n > 0) {            /* If so, */
 390:         if (n > SBUFL) n = SBUFL;   /* make sure not too much, */
 391:         n = ttxin(n,(CHAR *)fls_buf); /* then read it, */
 392:         if (n > 0) if (zsout(ZSFILE,fls_buf) < 0) seslog = 0;
 393:     }
 394:     } else ttflui();            /* Otherwise just flush. */
 395: }
 396: 
 397: #ifdef MAC
 398: alarm (s) int s; {          /* Fix this later */
 399: }
 400: #endif /* MAC */
 401: #else
 402: char *loginv = "Script Command Disabled";
 403: #endif /* NOSCRIPT */
 404: #endif /* NOICP */

Defined functions

dologin defined in line 292; used 1 times
flushi defined in line 384; used 4 times
outseq defined in line 238; used 2 times
recvseq defined in line 169; used 2 times
scrtime defined in line 84; used 2 times
sequenc defined in line 96; used 2 times

Defined variables

VOID defined in line 169; never used
alrmrng defined in line 82; used 3 times
exp_alrm defined in line 70; used 5 times
fls_buf defined in line 77; used 2 times
got_it defined in line 78; used 7 times
loginv defined in line 402; used 2 times
no_cr defined in line 78; used 4 times
oseqret defined in line 235; used 3 times
s defined in line 76; used 38 times
scr_echo defined in line 68; used 12 times
seq_buf defined in line 76; used 34 times

Defined macros

DEL_MSEC defined in line 73; used 1 times
NULL_EXP defined in line 72; used 1 times
SBUFL defined in line 75; used 6 times
SIGALRM defined in line 50; used 7 times
SIGTYP defined in line 52; used 3 times
SND_ALRM defined in line 71; used 1 times
Last modified: 1992-11-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4233
Valid CSS Valid XHTML 1.0 Strict