1: char *loginv = "Script Command, V2.0(007) 5 Jul 85"; 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: extern int local, speed, flow, seslog, mdmtyp; 37: extern char ttname[]; 38: extern CHAR dopar(); 39: static char * chstr(); 40: 41: static int EXP_ALRM = 15; /* Time to wait for expect string */ 42: #define SND_ALRM 15 /* Time to allow for sending string */ 43: #define NULL_EXP 2 /* Time to pause on null expect strg*/ 44: #define DEL_MSEC 300 /* milliseconds to pause on ~d */ 45: 46: #define SBUFL 300 /* Login Sequence buffer */ 47: static char seq_buf[SBUFL], *s; 48: static int got_it, no_cr; 49: 50: /* connect state parent/child communication signal handlers */ 51: 52: static jmp_buf alrmRng; /* Envir ptr for connect errors */ 53: 54: scrtime() { /* modem read failure handler, */ 55: longjmp(alrmRng,1); /* notifies parent process to stop */ 56: } 57: 58: 59: /* 60: Sequence interpreter -- pick up next sequence from command string, 61: decode escapes and place into seq_buf 62: 63: If string contains a ~d (delay) then sequenc returns a 1 expecting 64: to be called again after the ~d executes. 65: */ 66: static 67: sequenc() { 68: 69: int i; 70: char c, oct_char; 71: 72: no_cr = 0; /* output needs cr appended */ 73: 74: for (i=0; i<SBUFL; ) { 75: if (*s == '\0' || *s == '-' || isspace(*s) ) { /* done */ 76: seq_buf[i] = '\0'; 77: return(0) ; 78: } 79: 80: if (*s == '~') { /* escape character */ 81: switch (c = *(++s) ) { 82: case 'n': seq_buf[i++] = '\n'; break; 83: case 'r': seq_buf[i++] = '\r'; break; 84: case 't': seq_buf[i++] = '\t'; break; 85: case 'b': seq_buf[i++] = '\b'; break; 86: case 'q': seq_buf[i++] = '?'; break; 87: case '~': seq_buf[i++] = '~'; break; 88: case '\'': seq_buf[i++] = '\''; break; 89: case '\"': seq_buf[i++] = '\"'; break; 90: case 's': seq_buf[i++] = ' '; break; 91: case 'x': seq_buf[i++] = '\021'; break; 92: case 'c': no_cr = 1; break; 93: case 'd': { /* send what we have and then */ 94: seq_buf[i] = '\0'; /* expect to send rest after */ 95: no_cr = 1; /* sender delays a little */ 96: s++; 97: return(1); 98: } 99: case 'w': { /* wait count */ 100: EXP_ALRM = 15; /* default to 15 sec */ 101: if ( isdigit( *(s+1) ) ) { 102: EXP_ALRM = (*(++s)) & 15; 103: if ( isdigit( *(s+1) ) ) { 104: EXP_ALRM = EXP_ALRM*10 + ( (*(++s)) & 15 ); 105: } 106: } 107: break; 108: } 109: default: 110: if ( isdigit(c) ) { /* octal character */ 111: oct_char = (c & 7); /* most significant digit */ 112: if (isdigit( *(s+1) ) ) { 113: oct_char = (oct_char<<3) | ( (*(++s)) & 7 ) ; 114: if (isdigit( *(s+1) ) ) { 115: oct_char = (oct_char<<3) | ( (*(++s)) & 7 ) ; 116: } 117: } 118: seq_buf[i++] = oct_char; 119: break; 120: } 121: } 122: } 123: else seq_buf[i++] = *s; /* plain old character */ 124: s++; 125: } 126: seq_buf[i] = '\0'; 127: return(0); /* end of space, return anyway */ 128: } 129: 130: 131: /* 132: Receive sequence -- see if expected response comes return success 133: (or failure) in got_it 134: */ 135: static 136: recvSeq() { 137: 138: char *e, got[7], trace[300]; 139: int i, l; 140: 141: sequenc(); 142: l = strlen(e=seq_buf); /* no more than 7 chars allowed */ 143: if (l > 7) { 144: e += l-7; 145: l = 7; 146: } 147: 148: tlog(F111,"expecting sequence",e,(long) l); 149: if (l == 0) { /* null sequence, just delay a little */ 150: sleep (NULL_EXP); 151: got_it = 1; 152: tlog(F100,"got it (null sequence)","",0l); 153: return; 154: } 155: *trace = '\0'; 156: for (i=0; i<7; i++) got[i]='\0'; 157: 158: signal(SIGALRM,scrtime); /* did we get it? */ 159: if (!setjmp(alrmRng)) { /* not timed out yet */ 160: alarm(EXP_ALRM); 161: while (!got_it) { 162: for (i=0; i<(l-1); i++) got[i] = got[i+1]; /* shift over one */ 163: got[l-1] = ttinc(0) & 0177; /* next char */ 164: if (strlen(trace) < sizeof(trace)-2 ) 165: strcat(trace,chstr(got[l-1])); 166: got_it = (!strncmp(seq_buf, got, l) ) ; 167: } 168: } else got_it = 0; /* timed out here */ 169: 170: alarm(0); 171: signal(SIGALRM,SIG_IGN); 172: tlog(F110,"received sequence: ",trace,0l); 173: tlog(F101,"returning with got-it code","",(long) got_it); 174: return; 175: } 176: 177: 178: /* 179: Output A Sequence starting at pointer s, 180: return 0 if okay, 181: 1 if failed to read (modem hangup or whatever) 182: */ 183: static int 184: outSeq() { 185: char *sb; 186: int l; 187: int delay; 188: int retCode = 0; 189: 190: while(1) { 191: delay = sequenc(); 192: l = strlen(seq_buf); 193: tlog(F111,"sending sequence ",seq_buf,(long) l); 194: signal(SIGALRM,scrtime); 195: if (!setjmp(alrmRng)) { 196: alarm(SND_ALRM); 197: if (!strcmp(seq_buf,"EOT")) ttoc(dopar('\004')); 198: else if (!strcmp(seq_buf,"BREAK")) ttsndb(); 199: else { 200: if (l > 0) { 201: for ( sb=seq_buf; *sb; sb++) *sb = dopar(*sb); 202: ttol(seq_buf,l); /* with parity */ 203: } 204: if (!no_cr) ttoc( dopar('\r') ); 205: } 206: } 207: else retCode |= -1; /* else -- alarm rang */ 208: alarm(0); 209: signal(SIGALRM,SIG_IGN); 210: if (!delay) return ( retCode ); 211: msleep(DEL_MSEC); /* delay, and loop to next stuff to send */ 212: } 213: } 214: 215: 216: /* L O G I N -- Login to remote system */ 217: 218: login(cmdstr) char *cmdstr; { 219: 220: int (*saveAlm)(); /* save incomming alarm function */ 221: char *e; 222: 223: s = cmdstr; /* make global to ckuscr.c */ 224: 225: tlog(F100,loginv,"",0l); 226: 227: if (!local) { 228: printf("Sorry, you must 'set line' first\n"); 229: return(-2); 230: } 231: if (speed < 0) { 232: printf("Sorry, you must 'set speed' first\n"); 233: return(-2); 234: } 235: if (ttopen(ttname,&local,mdmtyp) < 0) { 236: sprintf(seq_buf,"Sorry, can't open %s",ttname); 237: perror(seq_buf); 238: return(-2); 239: } 240: printf("Executing script thru %s, speed %d.\r\n",ttname,speed); 241: *seq_buf=0; 242: for (e=s; *e; e++) strcat(seq_buf, chstr(*e) ); 243: printf("The logon string is: %s\r\n",seq_buf); 244: tlog(F110,"Logon command string: ",seq_buf, 0l); 245: 246: /* Condition console terminal and communication line */ 247: 248: if (ttvt(speed,flow) < 0) { 249: printf("Sorry, Can't condition communication line\n"); 250: return(-2); 251: } 252: /* save initial timer interrupt value */ 253: saveAlm = signal(SIGALRM,SIG_IGN); 254: 255: ttflui(); /* flush stale input */ 256: 257: /* cont'd... */ 258: 259: 260: /* ...login, cont'd */ 261: 262: /* start expect - send sequence */ 263: 264: while (*s) { /* while not done with buffer */ 265: 266: while (*s && isspace(*s)) s++; /* skip over separating whitespaces */ 267: /* gather up expect sequence */ 268: got_it = 0; 269: recvSeq(); 270: 271: while (!got_it) { 272: /* no, is there a conditional send */ 273: if (*s++ != '-') goto failRet; /* no -- return failure */ 274: 275: /* start of conditional send */ 276: ttflui(); /* flush out input buffer */ 277: if (outSeq()) goto failRet; /* if unable to send! */ 278: 279: if (*s++ != '-') goto failRet; /* must have condit respon.*/ 280: recvSeq(); 281: } /* loop back and check got_it */ 282: 283: while (*s && !isspace(*s++) ) ; /* skip over conditionals */ 284: while (*s && isspace(*s)) s++; /* skip over separating whitespaces */ 285: ttflui(); /* Flush */ 286: if (*s) if (outSeq()) goto failRet; /* if any */ 287: } 288: signal(SIGALRM,saveAlm); 289: printf("Logged on!\r\n"); 290: tlog(F100,"Logged on!","",0l); 291: return(0); 292: 293: failRet: 294: signal(SIGALRM,saveAlm); 295: printf("Sorry, logon failed\r\n"); 296: tlog(F100,"Logon failed","",0l); 297: return(-2); 298: } 299: 300: 301: /* C H S T R -- Make printable string from a character */ 302: 303: static char * 304: chstr(c) char c; { 305: static char sc[4]; 306: 307: if (c < SP) sprintf(sc, "^%c",ctl(c) ); 308: else sprintf(sc, "%c", c); 309: 310: return(sc); 311: }