|
|
1.1 ! root 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: [email protected]. ! 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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.