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