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