ckuscr.c
上传用户:dufan58
上传日期:2007-01-05
资源大小:3407k
文件大小:18k
源码类别:

通讯/手机编程

开发平台:

Windows_Unix

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