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