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