Commit | Line | Data |
---|---|---|
ee2abe03 C |
1 | char *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 | ||
36 | extern int local, speed, flow, seslog, mdmtyp; | |
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 300 /* Login Sequence buffer */ | |
47 | static char seq_buf[SBUFL], *s; | |
48 | static int got_it, no_cr; | |
49 | ||
50 | /* connect state parent/child communication signal handlers */ | |
51 | ||
52 | static jmp_buf alrmRng; /* Envir ptr for connect errors */ | |
53 | ||
54 | scrtime() { /* 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 | */ | |
66 | static | |
67 | sequenc() { | |
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 | */ | |
135 | static | |
136 | recvSeq() { | |
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 | */ | |
183 | static int | |
184 | outSeq() { | |
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 | ||
218 | login(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 | ||
293 | failRet: | |
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 | ||
303 | static char * | |
304 | chstr(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 | } |