📄 ckuscr.c
字号:
#include "ckcsym.h"#ifndef NOICP#ifndef NOSCRIPTchar *loginv = "Script Command, 7.0.030, 21 Oct 1998";/* C K U S C R -- expect-send script implementation *//* Copyright (C) 1985, 2000, Trustees of Columbia University in the City of New York. All rights reserved. See the C-Kermit COPYING.TXT file or the copyright text in the ckcmai.c module for disclaimer and permissions. Original (version 1, 1985) author: Herm Fischer, Encino, CA. Contributed to Columbia University in 1985 for inclusion in C-Kermit 4.0. Maintained since 1985 by Frank da Cruz, Columbia University, fdc@columbia.edu. The module takes a UUCP-style script of the "expect send [expect send] ..." format. It is intended to operate similarly to the way the common UUCP L.sys login entries work. Conditional responses are supported: expect[-send-expect[...]], as with UUCP. The send keyword EOT sends a Control-d, and the keyword BREAK sends a break. Letters prefixed by '~' are '~b' backspace, '~s' space, '~n' linefeed, '~r' return, '~x' xon, '~t' tab, '~q' ? (not allowed on kermit command lines), '~' ~, '~'', '~"', '~c' don't append return, '~o[o[o]]' octal character. As with some uucp systems, sent strings are followed by ~r (not ~n) unless they end with ~c. Null expect strings (e.g., ~0 or --) cause a short delay, and are useful for sending sequences requiring slight pauses. This module calls externally defined system-dependent functions for communications i/o, as defined in CKCPLM.DOC, the C-Kermit Program Logic Manual, and thus should be portable to all systems that implement those functions, and where alarm() and signal() work as they do in UNIX.*/#include "ckcdeb.h"#include <signal.h>#ifdef NT#include <setjmpex.h>#else /* NT */#include <setjmp.h>#endif /* NT */#include "ckcasc.h"#include "ckcker.h"#include "ckuusr.h"#include "ckcnet.h"#include "ckcsig.h"_PROTOTYP( VOID flushi, (void) );_PROTOTYP( static VOID myflsh, (void) );_PROTOTYP( static int sequenc, (void) );_PROTOTYP( static VOID recvseq, (void) );_PROTOTYP( static int outseq, (void) );#ifdef MAC#define signal msignal#define SIGTYP long#define alarm malarm#define SIG_IGN 0#define SIGALRM 1#define SIGINT 2SIGTYP (*msignal(int type, SIGTYP (*func)(int)))(int);#endif /* MAC */#ifdef AMIGA#define signal asignal#define alarm aalarm#define SIGALRM (_NUMSIG+1)#define SIGTYP voidSIGTYP (*asignal(int type, SIGTYP (*func)(int)))(int);unsigned aalarm(unsigned);#endif /* AMIGA */#ifdef STRATUS/* VOS doesn't have alarm(), but it does have some things we can work with. *//* however, we have to catch all the signals in one place to do this, so *//* we intercept the signal() routine and call it from our own replacement. */#define signal vsignal#define alarm valarmSIGTYP (*vsignal(int type, SIGTYP (*func)(int)))(int);int valarm(int interval);#endif /* STRATUS */extern int sessft;extern int local, flow, seslog, mdmtyp, msgflg, duplex, backgrd, secho, quiet;extern int network, ttnproto;extern long speed;extern char ttname[];#ifdef NTSIGextern int TlsIndex;#endif /* NTSIG */#ifdef IKSDextern int inserver;#endif /* IKSD */static int is_tn = 0; /* Do Telnet negotiations */#ifndef NOSPL#ifdef DCMDBUFextern struct cmdptr *cmdstk;#elseextern struct cmdptr cmdstk[];#endif /* DCMDBUF */extern int techo, cmdlvl;extern int mecho;#endif /* NOSPL */static int scr_echo; /* Whether to echo script commands */static int exp_alrm = 15; /* Time to wait for expect string */#define SND_ALRM 15 /* Time to allow for sending string */#define NULL_EXP 2 /* Time to pause on null expect strg*/#define DEL_MSEC 300 /* Milliseconds to pause on ~d */#define SBUFL 512static char seq_buf[SBUFL], *s; /* expect-send sequence buffer */static int got_it, no_cr;/* Connect state parent/child communication signal handlers */#ifdef COMMENT#ifdef CK_POSIX_SIGstatic sigjmp_buf alrmrng;#elsestatic jmp_buf alrmrng;#endif /* CK_POSIX_SIG */#elsestatic ckjmpbuf alrmrng;#endif /* COMMENT */static SIGTYP#ifdef CK_ANSICscrtime(int foo) /* modem read failure handler, */#elsescrtime(foo) int foo; /* Alarm handler */#endif /* CK_ANSIC *//* scrtime */ {#ifdef BEBOX#ifdef BE_DR_7 alarm_expired();#endif /* BE_DR_7 */#endif /* BEBOX */#ifdef NTSIG if (foo == SIGALRM) PostAlarmSigSem(); else PostCtrlCSem();#else /* NTSIG */#ifdef NT cklongjmp(ckjaddr(alrmrng),1);#else /* NT */ cklongjmp(alrmrng,1);#endif /* NT */#endif /* NTSIG */ SIGRETURN;}/* Sequence interpreter -- pick up next sequence from command string, decode escapes and place into seq_buf. If string contains a ~d (delay) then sequenc() returns a 1 expecting to be called again after the ~d executes.*/static intsequenc() { int i; char c, oct_char; no_cr = 0; /* output needs cr appended */ for (i = 0; i < SBUFL; ) { if (*s == '\0' || *s == '-' || isspace(*s) ) { /* done */ seq_buf[i] = '\0'; return(0) ; } if (*s == '~') { /* escape character */ s++; switch (c = *s) { case 'n': seq_buf[i++] = LF; break; case 'r': seq_buf[i++] = CR; break; case 't': seq_buf[i++] = '\t'; break; case 'b': seq_buf[i++] = '\b'; break; case 'q': seq_buf[i++] = '?'; break;#ifdef COMMENT/* The default case should catch these now... */ case '~': seq_buf[i++] = '~'; break; case '-': seq_buf[i++] = '-'; break;#endif /* COMMENT */ case '\'': seq_buf[i++] = '\''; break; case '\"': seq_buf[i++] = '\"'; break; case 's': seq_buf[i++] = ' '; break; case 'x': seq_buf[i++] = '\021'; break; case 'c': no_cr = 1; break; case 'd': { /* send what we have & then */ seq_buf[i] = '\0'; /* expect to send rest after */ no_cr = 1; /* sender delays a little */ s++; return(1); } case 'w': { /* wait count */ exp_alrm = 15; /* default to 15 sec */ if (isdigit(*(s+1))) { s++; exp_alrm = *s & 15; if (isdigit(*(s+1)) ) { s++; exp_alrm = exp_alrm * 10 + (*s & 15); } } break; } default: if ( isdigit(c) ) { /* octal character */ oct_char = (char) (c & 7); /* most significant digit */ if (isdigit( *(s+1) ) ) { s++; oct_char = (char) ((oct_char<<3) | ( *s & 7 )); if (isdigit( *(s+1) ) ) { s++; oct_char = (char) ((oct_char<<3) | ( *s & 7 )); } } seq_buf[i++] = oct_char; break; } else seq_buf[i++] = *s; /* Treat ~ as quote */ } } else seq_buf[i++] = *s; /* Plain old character */ s++; } seq_buf[i] = '\0'; return(0); /* end of space, return anyway */}/* Output buffering for "recvseq" and "flushi" */#define MAXBURST 256 /* maximum size of input burst */static CHAR conbuf[MAXBURST]; /* buffer to hold output for console */static int concnt = 0; /* number of characters buffered */static CHAR sesbuf[MAXBURST]; /* buffer to hold output for session log */static int sescnt = 0; /* number of characters buffered */static VOIDmyflsh() { if (concnt > 0) { conxo(concnt, (char *) conbuf); concnt = 0; } if (sescnt > 0) { logstr((char *) sesbuf, sescnt); sescnt = 0; }}/* these variables are used to pass data between the recvseq() *//* and the dorseq(). They are necessary because in some versions *//* dorseq() is executed in a separate thread and data cannot be *//* passed by parameter. */static char *rseqe, * rseqgot, * rseqtrace ;static int rseql;static SIGTYP#ifdef CK_ANSICdorseq(void * threadinfo)#else /* CK_ANSIC */dorseq(threadinfo) VOID * threadinfo;#endif /* CK_ANSIC *//* dorseq */ { int i, x; int burst = 0; /* chars remaining in input burst */#ifdef NTSIG setint(); if (threadinfo) { /* Thread local storage... */ TlsSetValue(TlsIndex,threadinfo); }#endif /* NTSIG */#ifdef CK_LOGIN#ifdef NT#ifdef IKSD if (inserver) setntcreds();#endif /* IKSD */#endif /* NT */#endif /* CK_LOGIN */ while (!got_it) { for (i = 0; i < rseql-1; i++) rseqgot[i] = rseqgot[i+1]; x = ttinc(0); /* Read a character */ debug(F101,"recvseq","",x); if (x < 0) {#ifdef NTSIG ckThreadEnd(threadinfo);#endif /* NTSIG */ SIGRETURN; /* Check for error */ }#ifdef NETCONN#ifdef TNCODE/* Check for telnet protocol negotiation */ if (((x & 0xff) == IAC) && is_tn) { /* Telnet negotiation */ myflsh(); burst = 0; switch (tn_doop((CHAR)(x & 0xff),duplex,ttinc)) { case 2: duplex = 0; continue; case 1: duplex = 1; default: continue; } }#endif /* TNCODE */#endif /* NETCONN */ rseqgot[rseql-1] = (char) (x & 0x7f); /* Got a character */ burst--; /* One less waiting */ if (scr_echo) conbuf[concnt++] = rseqgot[rseql-1]; /* Buffer it */ if (seslog) /* Log it in session log */#ifdef UNIX if (sessft != 0 || rseqgot[rseql-1] != '\r')#else#ifdef OSK if (sessft != 0 || rseqgot[rseql-1] != '\012')#endif /* OSK */#endif /* UNIX */ if (rseqgot[rseql-1]) /* Filter out NULs */ sesbuf[sescnt++] = rseqgot[rseql-1]; if ((int)strlen(rseqtrace) < SBUFL-2 ) strcat(rseqtrace,dbchr(rseqgot[rseql-1])); got_it = (!strncmp(rseqe, rseqgot, rseql)); if (burst <= 0) { /* Flush buffered output */ myflsh(); if ((burst = ttchk()) < 0) { /* Get size of next input burst */#ifdef NTSIG ckThreadEnd(threadinfo);#endif /* NTSIG */ SIGRETURN; } /* prevent overflow of "conbuf" and "sesbuf" */ if (burst > MAXBURST) burst = MAXBURST; } }#ifdef NTSIG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -