[10779] | 1 | #include "ckcsym.h" |
---|
[20080] | 2 | |
---|
[10779] | 3 | #ifndef NOICP |
---|
| 4 | #ifndef NOSCRIPT |
---|
[20080] | 5 | char *loginv = "Script Command, 8.0.032, 20 Dec 2001"; |
---|
[10779] | 6 | |
---|
[20080] | 7 | /* C K U S C R -- expect-send script implementation */ |
---|
[10779] | 8 | |
---|
| 9 | /* |
---|
[20080] | 10 | Copyright (C) 1985, 2002, |
---|
| 11 | Trustees of Columbia University in the City of New York. |
---|
| 12 | All rights reserved. See the C-Kermit COPYING.TXT file or the |
---|
| 13 | copyright text in the ckcmai.c module for disclaimer and permissions. |
---|
[10779] | 14 | |
---|
| 15 | Original (version 1, 1985) author: Herm Fischer, Encino, CA. |
---|
| 16 | Contributed to Columbia University in 1985 for inclusion in C-Kermit 4.0. |
---|
[20080] | 17 | Maintained since 1985 by Frank da Cruz, Columbia University, |
---|
[10779] | 18 | fdc@columbia.edu. |
---|
| 19 | |
---|
| 20 | The module takes a UUCP-style script of the "expect send [expect send] ..." |
---|
| 21 | format. It is intended to operate similarly to the way the common |
---|
| 22 | UUCP L.sys login entries work. Conditional responses are supported: |
---|
| 23 | expect[-send-expect[...]], as with UUCP. The send keyword EOT sends a |
---|
| 24 | Control-d, and the keyword BREAK sends a break. Letters prefixed |
---|
| 25 | by '~' are '~b' backspace, '~s' space, '~n' linefeed, '~r' return, '~x' xon, |
---|
| 26 | '~t' tab, '~q' ? (not allowed on kermit command lines), '~' ~, '~'', |
---|
| 27 | '~"', '~c' don't append return, '~o[o[o]]' octal character. As with |
---|
| 28 | some uucp systems, sent strings are followed by ~r (not ~n) unless they |
---|
| 29 | end with ~c. Null expect strings (e.g., ~0 or --) cause a short |
---|
| 30 | delay, and are useful for sending sequences requiring slight pauses. |
---|
| 31 | |
---|
| 32 | This module calls externally defined system-dependent functions for |
---|
[20080] | 33 | communications i/o, as defined in ckcplm.txt, the C-Kermit Program Logic |
---|
[10779] | 34 | Manual, and thus should be portable to all systems that implement those |
---|
| 35 | functions, and where alarm() and signal() work as they do in UNIX. |
---|
| 36 | */ |
---|
| 37 | #include "ckcdeb.h" |
---|
| 38 | #include <signal.h> |
---|
| 39 | #ifdef NT |
---|
| 40 | #include <setjmpex.h> |
---|
| 41 | #else /* NT */ |
---|
| 42 | #include <setjmp.h> |
---|
| 43 | #endif /* NT */ |
---|
| 44 | #include "ckcasc.h" |
---|
| 45 | #include "ckcker.h" |
---|
| 46 | #include "ckuusr.h" |
---|
| 47 | #include "ckcnet.h" |
---|
| 48 | #include "ckcsig.h" |
---|
| 49 | |
---|
| 50 | _PROTOTYP( VOID flushi, (void) ); |
---|
| 51 | _PROTOTYP( static VOID myflsh, (void) ); |
---|
| 52 | _PROTOTYP( static int sequenc, (void) ); |
---|
| 53 | _PROTOTYP( static VOID recvseq, (void) ); |
---|
| 54 | _PROTOTYP( static int outseq, (void) ); |
---|
| 55 | |
---|
| 56 | #ifdef MAC |
---|
| 57 | #define signal msignal |
---|
| 58 | #define SIGTYP long |
---|
| 59 | #define alarm malarm |
---|
| 60 | #define SIG_IGN 0 |
---|
| 61 | #define SIGALRM 1 |
---|
| 62 | #define SIGINT 2 |
---|
| 63 | SIGTYP (*msignal(int type, SIGTYP (*func)(int)))(int); |
---|
| 64 | #endif /* MAC */ |
---|
| 65 | |
---|
| 66 | #ifdef AMIGA |
---|
| 67 | #define signal asignal |
---|
| 68 | #define alarm aalarm |
---|
| 69 | #define SIGALRM (_NUMSIG+1) |
---|
| 70 | #define SIGTYP void |
---|
| 71 | SIGTYP (*asignal(int type, SIGTYP (*func)(int)))(int); |
---|
| 72 | unsigned aalarm(unsigned); |
---|
| 73 | #endif /* AMIGA */ |
---|
| 74 | |
---|
| 75 | #ifdef STRATUS |
---|
| 76 | /* VOS doesn't have alarm(), but it does have some things we can work with. */ |
---|
| 77 | /* however, we have to catch all the signals in one place to do this, so */ |
---|
| 78 | /* we intercept the signal() routine and call it from our own replacement. */ |
---|
| 79 | #define signal vsignal |
---|
| 80 | #define alarm valarm |
---|
| 81 | SIGTYP (*vsignal(int type, SIGTYP (*func)(int)))(int); |
---|
| 82 | int valarm(int interval); |
---|
| 83 | #endif /* STRATUS */ |
---|
| 84 | |
---|
| 85 | extern int sessft; |
---|
| 86 | extern int local, flow, seslog, mdmtyp, msgflg, duplex, backgrd, secho, quiet; |
---|
[20080] | 87 | extern int network, nettype, ttnproto; |
---|
[10779] | 88 | extern long speed; |
---|
| 89 | extern char ttname[]; |
---|
| 90 | |
---|
| 91 | #ifdef NTSIG |
---|
| 92 | extern int TlsIndex; |
---|
| 93 | #endif /* NTSIG */ |
---|
[20080] | 94 | #ifdef IKSD |
---|
| 95 | extern int inserver; |
---|
| 96 | #endif /* IKSD */ |
---|
[10779] | 97 | |
---|
[20080] | 98 | static int is_tn = 0; /* Do Telnet negotiations */ |
---|
| 99 | |
---|
[10779] | 100 | #ifndef NOSPL |
---|
| 101 | #ifdef DCMDBUF |
---|
| 102 | extern struct cmdptr *cmdstk; |
---|
| 103 | #else |
---|
| 104 | extern struct cmdptr cmdstk[]; |
---|
| 105 | #endif /* DCMDBUF */ |
---|
| 106 | extern int techo, cmdlvl; |
---|
| 107 | extern int mecho; |
---|
| 108 | #endif /* NOSPL */ |
---|
| 109 | |
---|
| 110 | static int scr_echo; /* Whether to echo script commands */ |
---|
| 111 | |
---|
| 112 | static int exp_alrm = 15; /* Time to wait for expect string */ |
---|
| 113 | #define SND_ALRM 15 /* Time to allow for sending string */ |
---|
[20080] | 114 | #define NULL_EXP 2 /* Time to pause on null expect strg*/ |
---|
[10779] | 115 | #define DEL_MSEC 300 /* Milliseconds to pause on ~d */ |
---|
| 116 | |
---|
[20080] | 117 | #define SBUFL 512 |
---|
| 118 | static char seq_buf[SBUFL+2], *s; /* expect-send sequence buffer */ |
---|
[10779] | 119 | static int got_it, no_cr; |
---|
| 120 | |
---|
| 121 | /* Connect state parent/child communication signal handlers */ |
---|
| 122 | |
---|
| 123 | #ifdef COMMENT |
---|
| 124 | #ifdef CK_POSIX_SIG |
---|
| 125 | static sigjmp_buf alrmrng; |
---|
| 126 | #else |
---|
| 127 | static jmp_buf alrmrng; |
---|
| 128 | #endif /* CK_POSIX_SIG */ |
---|
| 129 | #else |
---|
| 130 | static ckjmpbuf alrmrng; |
---|
| 131 | #endif /* COMMENT */ |
---|
| 132 | |
---|
| 133 | static SIGTYP |
---|
| 134 | #ifdef CK_ANSIC |
---|
| 135 | scrtime(int foo) /* modem read failure handler, */ |
---|
[20080] | 136 | #else |
---|
[10779] | 137 | scrtime(foo) int foo; /* Alarm handler */ |
---|
| 138 | #endif /* CK_ANSIC */ |
---|
| 139 | /* scrtime */ { |
---|
| 140 | |
---|
| 141 | #ifdef BEBOX |
---|
[20080] | 142 | #ifdef BE_DR_7 |
---|
[10779] | 143 | alarm_expired(); |
---|
[20080] | 144 | #endif /* BE_DR_7 */ |
---|
[10779] | 145 | #endif /* BEBOX */ |
---|
| 146 | #ifdef NTSIG |
---|
| 147 | if (foo == SIGALRM) |
---|
| 148 | PostAlarmSigSem(); |
---|
| 149 | else |
---|
| 150 | PostCtrlCSem(); |
---|
| 151 | #else /* NTSIG */ |
---|
| 152 | #ifdef NT |
---|
| 153 | cklongjmp(ckjaddr(alrmrng),1); |
---|
| 154 | #else /* NT */ |
---|
| 155 | cklongjmp(alrmrng,1); |
---|
| 156 | #endif /* NT */ |
---|
| 157 | #endif /* NTSIG */ |
---|
| 158 | SIGRETURN; |
---|
| 159 | } |
---|
| 160 | |
---|
| 161 | /* |
---|
| 162 | Sequence interpreter -- pick up next sequence from command string, |
---|
| 163 | decode escapes and place into seq_buf. |
---|
| 164 | |
---|
| 165 | If string contains a ~d (delay) then sequenc() returns a 1 expecting |
---|
| 166 | to be called again after the ~d executes. |
---|
| 167 | */ |
---|
| 168 | static int |
---|
| 169 | sequenc() { |
---|
| 170 | int i; |
---|
| 171 | char c, oct_char; |
---|
| 172 | |
---|
| 173 | no_cr = 0; /* output needs cr appended */ |
---|
[20080] | 174 | for (i = 0; i < SBUFL; ) { |
---|
[10779] | 175 | if (*s == '\0' || *s == '-' || isspace(*s) ) { /* done */ |
---|
| 176 | seq_buf[i] = '\0'; |
---|
| 177 | return(0) ; |
---|
| 178 | } |
---|
| 179 | if (*s == '~') { /* escape character */ |
---|
| 180 | s++; |
---|
| 181 | switch (c = *s) { |
---|
| 182 | case 'n': seq_buf[i++] = LF; break; |
---|
| 183 | case 'r': seq_buf[i++] = CR; break; |
---|
| 184 | case 't': seq_buf[i++] = '\t'; break; |
---|
| 185 | case 'b': seq_buf[i++] = '\b'; break; |
---|
| 186 | case 'q': seq_buf[i++] = '?'; break; |
---|
| 187 | #ifdef COMMENT |
---|
| 188 | /* The default case should catch these now... */ |
---|
| 189 | case '~': seq_buf[i++] = '~'; break; |
---|
| 190 | case '-': seq_buf[i++] = '-'; break; |
---|
| 191 | #endif /* COMMENT */ |
---|
| 192 | case '\'': seq_buf[i++] = '\''; break; |
---|
| 193 | case '\"': seq_buf[i++] = '\"'; break; |
---|
| 194 | case 's': seq_buf[i++] = ' '; break; |
---|
| 195 | case 'x': seq_buf[i++] = '\021'; break; |
---|
| 196 | case 'c': no_cr = 1; break; |
---|
| 197 | case 'd': { /* send what we have & then */ |
---|
| 198 | seq_buf[i] = '\0'; /* expect to send rest after */ |
---|
| 199 | no_cr = 1; /* sender delays a little */ |
---|
| 200 | s++; |
---|
| 201 | return(1); |
---|
| 202 | } |
---|
| 203 | case 'w': { /* wait count */ |
---|
| 204 | exp_alrm = 15; /* default to 15 sec */ |
---|
[20080] | 205 | if (isdigit(*(s+1))) { |
---|
[10779] | 206 | s++; |
---|
| 207 | exp_alrm = *s & 15; |
---|
| 208 | if (isdigit(*(s+1)) ) { |
---|
| 209 | s++; |
---|
| 210 | exp_alrm = exp_alrm * 10 + (*s & 15); |
---|
| 211 | } |
---|
| 212 | } |
---|
| 213 | break; |
---|
| 214 | } |
---|
| 215 | default: |
---|
| 216 | if ( isdigit(c) ) { /* octal character */ |
---|
| 217 | oct_char = (char) (c & 7); /* most significant digit */ |
---|
| 218 | if (isdigit( *(s+1) ) ) { |
---|
| 219 | s++; |
---|
| 220 | oct_char = (char) ((oct_char<<3) | ( *s & 7 )); |
---|
| 221 | if (isdigit( *(s+1) ) ) { |
---|
| 222 | s++; |
---|
| 223 | oct_char = (char) ((oct_char<<3) | ( *s & 7 )); |
---|
| 224 | } |
---|
| 225 | } |
---|
| 226 | seq_buf[i++] = oct_char; |
---|
| 227 | break; |
---|
| 228 | } else seq_buf[i++] = *s; /* Treat ~ as quote */ |
---|
| 229 | } |
---|
| 230 | } else seq_buf[i++] = *s; /* Plain old character */ |
---|
| 231 | s++; |
---|
| 232 | } |
---|
| 233 | seq_buf[i] = '\0'; |
---|
| 234 | return(0); /* end of space, return anyway */ |
---|
| 235 | } |
---|
| 236 | |
---|
| 237 | |
---|
| 238 | /* Output buffering for "recvseq" and "flushi" */ |
---|
| 239 | |
---|
| 240 | #define MAXBURST 256 /* maximum size of input burst */ |
---|
| 241 | static CHAR conbuf[MAXBURST]; /* buffer to hold output for console */ |
---|
| 242 | static int concnt = 0; /* number of characters buffered */ |
---|
| 243 | static CHAR sesbuf[MAXBURST]; /* buffer to hold output for session log */ |
---|
| 244 | static int sescnt = 0; /* number of characters buffered */ |
---|
| 245 | |
---|
| 246 | static VOID |
---|
| 247 | myflsh() { |
---|
| 248 | if (concnt > 0) { |
---|
| 249 | conxo(concnt, (char *) conbuf); |
---|
| 250 | concnt = 0; |
---|
| 251 | } |
---|
| 252 | if (sescnt > 0) { |
---|
[20080] | 253 | logstr((char *) sesbuf, sescnt); |
---|
[10779] | 254 | sescnt = 0; |
---|
| 255 | } |
---|
| 256 | } |
---|
| 257 | |
---|
| 258 | /* these variables are used to pass data between the recvseq() */ |
---|
| 259 | /* and the dorseq(). They are necessary because in some versions */ |
---|
| 260 | /* dorseq() is executed in a separate thread and data cannot be */ |
---|
| 261 | /* passed by parameter. */ |
---|
| 262 | |
---|
| 263 | static char *rseqe, * rseqgot, * rseqtrace ; |
---|
| 264 | static int rseql; |
---|
| 265 | |
---|
| 266 | static SIGTYP |
---|
| 267 | #ifdef CK_ANSIC |
---|
| 268 | dorseq(void * threadinfo) |
---|
| 269 | #else /* CK_ANSIC */ |
---|
| 270 | dorseq(threadinfo) VOID * threadinfo; |
---|
| 271 | #endif /* CK_ANSIC */ |
---|
| 272 | /* dorseq */ { |
---|
| 273 | int i, x; |
---|
| 274 | int burst = 0; /* chars remaining in input burst */ |
---|
| 275 | |
---|
| 276 | #ifdef NTSIG |
---|
[20080] | 277 | setint(); |
---|
[10779] | 278 | if (threadinfo) { /* Thread local storage... */ |
---|
| 279 | TlsSetValue(TlsIndex,threadinfo); |
---|
| 280 | } |
---|
| 281 | #endif /* NTSIG */ |
---|
[20080] | 282 | #ifdef CK_LOGIN |
---|
| 283 | #ifdef NT |
---|
| 284 | #ifdef IKSD |
---|
| 285 | if (inserver) |
---|
| 286 | setntcreds(); |
---|
| 287 | #endif /* IKSD */ |
---|
| 288 | #endif /* NT */ |
---|
| 289 | #endif /* CK_LOGIN */ |
---|
[10779] | 290 | |
---|
| 291 | while (!got_it) { |
---|
| 292 | for (i = 0; i < rseql-1; i++) rseqgot[i] = rseqgot[i+1]; |
---|
| 293 | x = ttinc(0); /* Read a character */ |
---|
| 294 | debug(F101,"recvseq","",x); |
---|
| 295 | if (x < 0) { |
---|
| 296 | #ifdef NTSIG |
---|
| 297 | ckThreadEnd(threadinfo); |
---|
| 298 | #endif /* NTSIG */ |
---|
| 299 | SIGRETURN; /* Check for error */ |
---|
| 300 | } |
---|
| 301 | #ifdef NETCONN |
---|
| 302 | #ifdef TNCODE |
---|
| 303 | /* Check for telnet protocol negotiation */ |
---|
[20080] | 304 | if (((x & 0xff) == IAC) && is_tn) { /* Telnet negotiation */ |
---|
[10779] | 305 | myflsh(); |
---|
| 306 | burst = 0; |
---|
| 307 | switch (tn_doop((CHAR)(x & 0xff),duplex,ttinc)) { |
---|
| 308 | case 2: duplex = 0; continue; |
---|
| 309 | case 1: duplex = 1; |
---|
| 310 | default: continue; |
---|
| 311 | } |
---|
| 312 | } |
---|
| 313 | #endif /* TNCODE */ |
---|
| 314 | #endif /* NETCONN */ |
---|
| 315 | rseqgot[rseql-1] = (char) (x & 0x7f); /* Got a character */ |
---|
| 316 | burst--; /* One less waiting */ |
---|
| 317 | if (scr_echo) conbuf[concnt++] = rseqgot[rseql-1]; /* Buffer it */ |
---|
| 318 | if (seslog) /* Log it in session log */ |
---|
| 319 | #ifdef UNIX |
---|
| 320 | if (sessft != 0 || rseqgot[rseql-1] != '\r') |
---|
| 321 | #else |
---|
| 322 | #ifdef OSK |
---|
| 323 | if (sessft != 0 || rseqgot[rseql-1] != '\012') |
---|
| 324 | #endif /* OSK */ |
---|
| 325 | #endif /* UNIX */ |
---|
[20080] | 326 | if (rseqgot[rseql-1]) /* Filter out NULs */ |
---|
| 327 | sesbuf[sescnt++] = rseqgot[rseql-1]; |
---|
| 328 | if ((int)strlen(rseqtrace) < SBUFL-2 ) |
---|
[10779] | 329 | strcat(rseqtrace,dbchr(rseqgot[rseql-1])); |
---|
| 330 | got_it = (!strncmp(rseqe, rseqgot, rseql)); |
---|
| 331 | if (burst <= 0) { /* Flush buffered output */ |
---|
| 332 | myflsh(); |
---|
| 333 | if ((burst = ttchk()) < 0) { /* Get size of next input burst */ |
---|
| 334 | #ifdef NTSIG |
---|
| 335 | ckThreadEnd(threadinfo); |
---|
| 336 | #endif /* NTSIG */ |
---|
| 337 | SIGRETURN; |
---|
| 338 | } |
---|
| 339 | /* prevent overflow of "conbuf" and "sesbuf" */ |
---|
| 340 | if (burst > MAXBURST) |
---|
| 341 | burst = MAXBURST; |
---|
| 342 | } |
---|
[20080] | 343 | } |
---|
[10779] | 344 | #ifdef NTSIG |
---|
| 345 | ckThreadEnd(threadinfo); |
---|
| 346 | #endif /* NTSIG */ |
---|
| 347 | SIGRETURN; |
---|
| 348 | } |
---|
| 349 | |
---|
| 350 | static SIGTYP |
---|
| 351 | #ifdef CK_ANSIC |
---|
| 352 | failrseq(void * threadinfo) |
---|
| 353 | #else /* CK_ANSIC */ |
---|
[20080] | 354 | failrseq(threadinfo) VOID * threadinfo; |
---|
[10779] | 355 | #endif /* CK_ANSIC */ |
---|
| 356 | /* failrseq */ { |
---|
[20080] | 357 | got_it = 0; /* Timed out here */ |
---|
[10779] | 358 | SIGRETURN; |
---|
| 359 | } |
---|
| 360 | |
---|
| 361 | /* |
---|
| 362 | Receive sequence -- see if expected response comes, |
---|
| 363 | return success (or failure) in got_it. |
---|
[20080] | 364 | */ |
---|
[10779] | 365 | static VOID |
---|
| 366 | recvseq() { |
---|
| 367 | char *e, got[7], trace[SBUFL]; |
---|
| 368 | int i, l; |
---|
[20080] | 369 | |
---|
[10779] | 370 | sequenc(); |
---|
| 371 | l = (int)strlen(e=seq_buf); /* no more than 7 chars allowed */ |
---|
| 372 | if (l > 7) { |
---|
| 373 | e += l-7; |
---|
| 374 | l = 7; |
---|
| 375 | } |
---|
| 376 | tlog(F111,"expecting sequence",e,(long) l); |
---|
| 377 | if (l == 0) { /* null sequence, delay a little */ |
---|
| 378 | sleep (NULL_EXP); |
---|
| 379 | got_it = 1; |
---|
| 380 | tlog(F100,"got it (null sequence)","",0L); |
---|
| 381 | return; |
---|
| 382 | } |
---|
| 383 | *trace = '\0'; |
---|
| 384 | for (i = 0; i < 7; i++) got[i]='\0'; |
---|
| 385 | |
---|
| 386 | rseqtrace = trace; |
---|
| 387 | rseqe = e; |
---|
| 388 | rseqgot = got; |
---|
| 389 | rseql = l; |
---|
| 390 | |
---|
| 391 | alrm_execute(ckjaddr(alrmrng), exp_alrm, scrtime, dorseq, failrseq); |
---|
| 392 | |
---|
| 393 | tlog(F110,"received sequence: ",trace,0L); |
---|
| 394 | tlog(F101,"returning with got-it code","",(long) got_it); |
---|
| 395 | myflsh(); /* Flush buffered output */ |
---|
| 396 | return; |
---|
| 397 | } |
---|
| 398 | |
---|
| 399 | /* |
---|
| 400 | Output A Sequence starting at pointer s, |
---|
| 401 | return 0 if okay, |
---|
| 402 | 1 if failed to read (modem hangup or whatever) |
---|
| 403 | */ |
---|
| 404 | static int oseqret = 0; /* Return code for outseq */ |
---|
| 405 | /* Out here to prevent clobbering */ |
---|
| 406 | /* by longjmp. */ |
---|
| 407 | |
---|
| 408 | static SIGTYP |
---|
| 409 | #ifdef CK_ANSIC |
---|
| 410 | dooseq(void * threadinfo) |
---|
| 411 | #else /* CK_ANSIC */ |
---|
[20080] | 412 | dooseq(threadinfo) VOID * threadinfo; |
---|
[10779] | 413 | #endif /* CK_ANSIC */ |
---|
| 414 | { |
---|
| 415 | int l; |
---|
| 416 | char *sb; |
---|
| 417 | #ifdef TCPSOCKET |
---|
[20080] | 418 | extern int tn_nlm, tn_b_nlm; |
---|
[10779] | 419 | #endif /* TCPSOCKET */ |
---|
| 420 | |
---|
| 421 | #ifdef NTSIG |
---|
[20080] | 422 | setint(); |
---|
[10779] | 423 | if (threadinfo) { /* Thread local storage... */ |
---|
| 424 | TlsSetValue(TlsIndex,threadinfo); |
---|
| 425 | } |
---|
| 426 | #endif /* NTSIG */ |
---|
[20080] | 427 | #ifdef CK_LOGIN |
---|
| 428 | #ifdef NT |
---|
| 429 | #ifdef IKSD |
---|
| 430 | if (inserver) |
---|
| 431 | setntcreds(); |
---|
| 432 | #endif /* IKSD */ |
---|
| 433 | #endif /* NT */ |
---|
| 434 | #endif /* CK_LOGIN */ |
---|
[10779] | 435 | |
---|
| 436 | l = (int)strlen(seq_buf); |
---|
| 437 | tlog(F111,"sending sequence ",seq_buf,(long) l); |
---|
| 438 | |
---|
| 439 | if (!strcmp(seq_buf,"EOT")) { |
---|
| 440 | ttoc(dopar('\004')); |
---|
| 441 | if (scr_echo) conol("<EOT>"); |
---|
[20080] | 442 | if (seslog && duplex) |
---|
| 443 | logstr("<EOT>",5); |
---|
[10779] | 444 | } else if (!strcmp(seq_buf,"BREAK") || |
---|
| 445 | !strcmp(seq_buf,"\\b") || |
---|
| 446 | !strcmp(seq_buf,"\\B")) { |
---|
| 447 | ttsndb(); |
---|
| 448 | if (scr_echo) conol("<BREAK>"); |
---|
[20080] | 449 | if (seslog) |
---|
| 450 | logstr("{BREAK}",7); |
---|
[10779] | 451 | } else { |
---|
| 452 | if (l > 0) { |
---|
| 453 | for ( sb = seq_buf; *sb; sb++) |
---|
| 454 | *sb = dopar(*sb); /* add parity */ |
---|
| 455 | ttol((CHAR *)seq_buf,l); /* send it */ |
---|
[20080] | 456 | if (scr_echo && duplex) { |
---|
| 457 | #ifndef NOLOCAL |
---|
| 458 | #ifdef OS2 |
---|
| 459 | { /* Echo to emulator */ |
---|
| 460 | char *s = seq_buf; |
---|
| 461 | while (*s) { |
---|
| 462 | scriptwrtbuf((USHORT)*s); |
---|
| 463 | } |
---|
| 464 | } |
---|
| 465 | #endif /* OS2 */ |
---|
| 466 | #endif /* NOLOCAL */ |
---|
| 467 | conxo(l,seq_buf); |
---|
| 468 | } |
---|
[10779] | 469 | if (seslog && duplex) /* log it */ |
---|
[20080] | 470 | logstr(seq_buf,strlen(seq_buf)); |
---|
[10779] | 471 | } |
---|
| 472 | if (!no_cr) { |
---|
| 473 | ttoc( dopar(CR) ); |
---|
| 474 | #ifdef TCPSOCKET |
---|
[20080] | 475 | if (is_tn) { |
---|
| 476 | if (!TELOPT_ME(TELOPT_BINARY) && tn_nlm != TNL_CR) |
---|
[10779] | 477 | ttoc((char)((tn_nlm == TNL_CRLF) ? |
---|
| 478 | dopar(LF) : dopar(NUL))); |
---|
[20080] | 479 | else if (TELOPT_ME(TELOPT_BINARY) && |
---|
[10779] | 480 | (tn_b_nlm == TNL_CRLF || tn_b_nlm == TNL_CRNUL)) |
---|
| 481 | ttoc((char)((tn_b_nlm == TNL_CRLF) ? |
---|
| 482 | dopar(LF) : dopar(NUL))); |
---|
| 483 | } |
---|
| 484 | #endif /* TCPSOCKET */ |
---|
| 485 | if (seslog && duplex) |
---|
[20080] | 486 | logchar(dopar(CR)); |
---|
[10779] | 487 | } |
---|
[20080] | 488 | } |
---|
[10779] | 489 | #ifdef NTSIG |
---|
| 490 | ckThreadEnd(threadinfo); |
---|
| 491 | #endif /* NTSIG */ |
---|
| 492 | SIGRETURN; |
---|
| 493 | } |
---|
| 494 | |
---|
| 495 | SIGTYP |
---|
| 496 | #ifdef CK_ANSIC |
---|
| 497 | failoseq(void * threadinfo) |
---|
| 498 | #else /* CK_ANSIC */ |
---|
[20080] | 499 | failoseq(threadinfo) VOID * threadinfo; |
---|
[10779] | 500 | #endif /* CK_ANSIC */ |
---|
| 501 | /* failoseq */ { |
---|
[20080] | 502 | oseqret = -1; /* else -- alarm rang */ |
---|
[10779] | 503 | SIGRETURN; |
---|
| 504 | } |
---|
| 505 | |
---|
| 506 | static int |
---|
| 507 | outseq() { |
---|
| 508 | int delay; |
---|
| 509 | |
---|
| 510 | oseqret = 0; /* Initialize return code */ |
---|
| 511 | while(1) { |
---|
[20080] | 512 | delay = sequenc(); |
---|
[10779] | 513 | alrm_execute( ckjaddr(alrmrng), SND_ALRM, scrtime, dooseq, failoseq ) ; |
---|
| 514 | |
---|
[20080] | 515 | if (!delay) |
---|
[10779] | 516 | return(oseqret); |
---|
| 517 | #ifndef MAC |
---|
| 518 | msleep(DEL_MSEC); /* delay, loop to next send */ |
---|
| 519 | #endif /* MAC */ |
---|
| 520 | } |
---|
| 521 | } |
---|
| 522 | |
---|
| 523 | |
---|
| 524 | /* L O G I N -- (historical misnomer) Execute the SCRIPT command */ |
---|
| 525 | |
---|
| 526 | int |
---|
| 527 | dologin(cmdstr) char *cmdstr; { |
---|
| 528 | |
---|
| 529 | #ifdef OS2 |
---|
| 530 | #ifdef NT |
---|
| 531 | SIGTYP (* savealm)(int); /* Save incoming alarm function */ |
---|
| 532 | #else /* NT */ |
---|
| 533 | SIGTYP (* volatile savealm)(int); /* Save incoming alarm function */ |
---|
| 534 | #endif /* NT */ |
---|
| 535 | #else /* OS2 */ |
---|
| 536 | SIGTYP (*savealm)(); /* Save incoming alarm function */ |
---|
| 537 | #endif /* OS2 */ |
---|
| 538 | char *e; |
---|
| 539 | |
---|
| 540 | s = cmdstr; /* Make global to this module */ |
---|
| 541 | |
---|
| 542 | tlog(F100,loginv,"",0L); |
---|
| 543 | |
---|
| 544 | if (speed < 0L) speed = ttgspd(); |
---|
| 545 | if (ttopen(ttname,&local,mdmtyp,0) < 0) { |
---|
[20080] | 546 | ckmakmsg(seq_buf,SBUFL,"Sorry, can't open ",ttname,NULL,NULL); |
---|
[10779] | 547 | perror(seq_buf); |
---|
| 548 | return(0); |
---|
| 549 | } |
---|
| 550 | /* Whether to echo script commands ... */ |
---|
| 551 | scr_echo = (!quiet && !backgrd && secho); |
---|
| 552 | #ifndef NOSPL |
---|
| 553 | if (scr_echo && cmdlvl > 1) { |
---|
| 554 | if (cmdstk[cmdlvl].src == CMD_TF) |
---|
| 555 | scr_echo = techo; |
---|
| 556 | if (cmdstk[cmdlvl].src == CMD_MD) |
---|
| 557 | scr_echo = mecho; |
---|
| 558 | } |
---|
| 559 | #endif /* NOSPL */ |
---|
| 560 | if (scr_echo) { |
---|
| 561 | #ifdef NETCONN |
---|
| 562 | if (network) |
---|
| 563 | printf("Executing SCRIPT to host %s.\n",ttname); |
---|
| 564 | else |
---|
| 565 | #endif /* NETCONN */ |
---|
| 566 | printf("Executing SCRIPT through %s, speed %ld.\n",ttname,speed); |
---|
| 567 | } |
---|
[20080] | 568 | #ifdef TNCODE |
---|
| 569 | /* TELNET input must be scanned for IAC */ |
---|
| 570 | is_tn = (local && network && IS_TELNET()) || |
---|
| 571 | (!local && sstelnet); |
---|
| 572 | #endif /* TNCODE */ |
---|
| 573 | |
---|
[10779] | 574 | *seq_buf = 0; |
---|
[20080] | 575 | for (e = s; *e; e++) ckstrncat(seq_buf,dbchr(*e),SBUFL); |
---|
[10779] | 576 | #ifdef COMMENT |
---|
| 577 | /* Skip this because it tends to contain a password... */ |
---|
| 578 | if (scr_echo) printf("SCRIPT string: %s\n",seq_buf); |
---|
| 579 | #endif /* COMMENT */ |
---|
| 580 | tlog(F110,"SCRIPT string: ",seq_buf, 0L); |
---|
| 581 | |
---|
[20080] | 582 | /* Condition console terminal and communication line... */ |
---|
[10779] | 583 | |
---|
| 584 | if (ttvt(speed,flow) < 0) { |
---|
| 585 | printf("Sorry, Can't condition communication line\n"); |
---|
| 586 | return(0); |
---|
| 587 | } |
---|
| 588 | /* Save initial timer interrupt value */ |
---|
| 589 | savealm = signal(SIGALRM,SIG_IGN); |
---|
| 590 | |
---|
| 591 | flushi(); /* Flush stale input */ |
---|
| 592 | |
---|
| 593 | /* start expect - send sequence */ |
---|
| 594 | |
---|
| 595 | while (*s) { /* While not done with buffer */ |
---|
| 596 | |
---|
| 597 | while (*s && isspace(*s)) s++; /* Skip over separating whitespaces */ |
---|
| 598 | /* Gather up expect sequence */ |
---|
| 599 | got_it = 0; |
---|
| 600 | recvseq(); |
---|
| 601 | |
---|
| 602 | while (!got_it) { /* Have it yet? */ |
---|
| 603 | if (*s++ != '-') /* No, is there a conditional send? */ |
---|
| 604 | goto failret; /* No, return failure */ |
---|
| 605 | flushi(); /* Yes, flush out input buffer */ |
---|
| 606 | if (outseq()) /* If unable to send, */ |
---|
| 607 | goto failret; /* return failure. */ |
---|
| 608 | if (*s++ != '-') /* If no conditional response here, */ |
---|
| 609 | goto failret; /* return failure. */ |
---|
| 610 | recvseq(); /* All OK, read response from host. */ |
---|
| 611 | } /* Loop back and check got_it */ |
---|
| 612 | |
---|
| 613 | while (*s && !isspace(*s++) ) ; /* Skip over conditionals */ |
---|
| 614 | while (*s && isspace(*s)) s++; /* Skip over separating whitespaces */ |
---|
| 615 | flushi(); /* Flush */ |
---|
| 616 | if (*s) if (outseq()) goto failret; /* If any */ |
---|
| 617 | } |
---|
| 618 | signal(SIGALRM,savealm); |
---|
| 619 | if (scr_echo) printf("Script successful.\n"); |
---|
| 620 | tlog(F100,"Script successful.","",0L); |
---|
| 621 | return(1); |
---|
| 622 | |
---|
| 623 | failret: |
---|
| 624 | signal(SIGALRM,savealm); |
---|
| 625 | if (scr_echo) printf("Sorry, script failed\n"); |
---|
| 626 | tlog(F100,"Script failed","",0L); |
---|
| 627 | return(0); |
---|
| 628 | } |
---|
| 629 | |
---|
| 630 | /* F L U S H I -- Flush, but log, SCRIPT input buffer */ |
---|
| 631 | |
---|
| 632 | VOID |
---|
| 633 | flushi() { |
---|
| 634 | int n, x; |
---|
| 635 | if ( |
---|
| 636 | seslog /* Logging session? */ |
---|
| 637 | || scr_echo /* Or console echoing? */ |
---|
| 638 | #ifdef NETCONN |
---|
| 639 | #ifdef TNCODE |
---|
| 640 | /* TELNET input must be scanned for IAC */ |
---|
[20080] | 641 | || is_tn |
---|
[10779] | 642 | #endif /* TNCODE */ |
---|
| 643 | #endif /* NETCONN */ |
---|
| 644 | ) { |
---|
| 645 | if ((n = ttchk()) < 0) /* Yes, anything in buffer? */ |
---|
| 646 | return; |
---|
| 647 | if (n > MAXBURST) n = MAXBURST; /* Make sure not too much, */ |
---|
| 648 | myflsh(); /* and that buffers are empty. */ |
---|
| 649 | while (n-- > 0) { |
---|
| 650 | x = ttinc(0); /* Collect a character */ |
---|
| 651 | #ifdef NETCONN |
---|
| 652 | #ifdef TNCODE |
---|
| 653 | /* Check for telnet protocol negotiation */ |
---|
| 654 | if (is_tn && ((x & 0xff) == IAC) ) { |
---|
| 655 | myflsh(); /* Sync output */ |
---|
| 656 | switch (tn_doop((CHAR)(x & 0xff),duplex,ttinc)) { |
---|
| 657 | case 2: duplex = 0; break; |
---|
| 658 | case 1: duplex = 1; |
---|
| 659 | default: break; |
---|
| 660 | } |
---|
| 661 | |
---|
| 662 | /* Recalculate flush count */ |
---|
| 663 | if ((n = ttchk()) < 0) |
---|
| 664 | return; |
---|
| 665 | if (n > MAXBURST) n = MAXBURST; |
---|
| 666 | continue; |
---|
| 667 | } |
---|
| 668 | #endif /* TNCODE */ |
---|
| 669 | #endif /* NETCONN */ |
---|
| 670 | if (scr_echo) conbuf[concnt++] = (CHAR) x; /* buffer for console */ |
---|
| 671 | if (seslog) |
---|
| 672 | #ifdef UNIX |
---|
| 673 | if (sessft != 0 || x != '\r') |
---|
| 674 | #else |
---|
| 675 | #ifdef OSK |
---|
| 676 | if (sessft != 0 || x != '\012') |
---|
| 677 | #endif /* OSK */ |
---|
| 678 | #endif /* UNIX */ |
---|
| 679 | sesbuf[sescnt++] = (CHAR) x; /* buffer for session log */ |
---|
| 680 | } |
---|
| 681 | myflsh(); |
---|
| 682 | } else ttflui(); /* Otherwise just flush. */ |
---|
| 683 | } |
---|
| 684 | |
---|
| 685 | #else /* NOSCRIPT */ |
---|
| 686 | char *loginv = "Script Command Disabled"; |
---|
| 687 | #endif /* NOSCRIPT */ |
---|
| 688 | #endif /* NOICP */ |
---|