TELNETD.C
上传用户:sunrenlu
上传日期:2022-06-13
资源大小:1419k
文件大小:6k
源码类别:

操作系统开发

开发平台:

DOS

  1. /*
  2.  * TELNET Server
  3.  *
  4.  * Copyright (c) 1990, 1999 Erick Engelke
  5.  */
  6. #include <net.h>
  7. #include <rtos.h>
  8. #include <telnetd.h>
  9. #include <stdio.h>
  10. #include <mem.h>
  11. #include <string.h>
  12. #define IO_ST_INIT 0
  13. #define IO_ST_NORM 1 /* normal chars */
  14. #define TEL_SE     240
  15. #define TEL_IP     244  /* interrupt process */
  16. #define TEL_AYT    246  /* are you there */
  17. #define TEL_WILL   251
  18. #define TEL_WONT   252
  19. #define TEL_DO    253
  20. #define TEL_DONT   254
  21. #define TEL_IAC    255
  22. #define LAST_MODE  6
  23. #define OPT_ECHO 1
  24. #define OPT_SUPPRESS_GA 3
  25. #define OPT_TERM_TYPE 24
  26. static void send_iac( teld_str *t, BYTE cmd, BYTE opt)
  27. {
  28.     static char io_data[3];
  29.     io_data[0] = TEL_IAC;
  30.     io_data[1] = cmd;
  31.     io_data[2] = opt;
  32.     sock_write( &t->teld_socket, io_data, 3 );
  33. }
  34. static int io_pre_get( teld_str *t )
  35. {
  36.     tcp_Socket *s = &t->teld_socket;
  37.     unsigned char ch;
  38.     if ( t->teld_iostate == IO_ST_INIT )
  39.         t->teld_iostate = IO_ST_NORM;
  40.     while (sock_dataready(s)) {
  41.         sock_fastread( s, &ch, 1 );
  42.         switch ( t->teld_iostate ) {
  43.     case IO_ST_NORM:
  44.     if (ch != TEL_IAC)
  45. return( ch );
  46.                     t->teld_iostate = TEL_IAC;
  47.     break;
  48.             case TEL_IAC :
  49.                     t->teld_iostate = IO_ST_NORM;      /* assume last */
  50.     if (ch == TEL_IAC)  /* byte stuffed */
  51. return( ch );
  52.                     if (ch >= TEL_IP )
  53.                         t->teld_iostate = ch;
  54.     break; /* loose all others */
  55.             case TEL_IP  :
  56.                     t->teld_iostate = IO_ST_NORM;
  57.                     return( 3 );         /* control break */
  58.             case TEL_AYT :
  59.                     t->teld_iostate = IO_ST_NORM;
  60.                     sock_puts( s, "[YES]");
  61.                     break;
  62.     case TEL_WILL:
  63.     case TEL_WONT:
  64.     case TEL_DO:
  65.     case TEL_DONT :
  66.                     if ( ch == OPT_TERM_TYPE ) t->teld_iostate = ch;
  67.                     else t->teld_iostate = IO_ST_NORM;
  68.     break;
  69.             case OPT_TERM_TYPE :
  70.                     if ( ch >= TEL_SE ) t->teld_iostate = ch;
  71.                     break;
  72.     default :
  73.                     t->teld_iostate = IO_ST_NORM;
  74.                     break;
  75. }
  76.     }
  77.     rt_sleep( 0 );
  78.     return( 0 );
  79. }
  80. /******************************************************************/
  81. teld_str *teld_listen( int port )
  82. {
  83.     teld_str *t;
  84.     tcp_Socket *s;
  85.     t = kcalloc( sizeof( teld_str ), 1 );
  86.     if ( t == NULL ) return( NULL );
  87.     if ( port == 0 ) port = TELNETPORT;
  88.     s = &t->teld_socket;
  89.     do {
  90.         tcp_listen( s, port, 0L, 0, NULL, 0 );
  91.         while ( ! sock_established( s )) {
  92.             if ( tcp_tick( s ) == NULL ) goto retry;
  93.             rt_sleep( 250 );
  94.         }
  95.         /* we are connected */
  96.         t->teld_connected = 1;
  97.         t->teld_iostate = IO_ST_INIT;
  98.         sock_mode( s, TCP_MODE_NONAGLE );
  99.         send_iac( t, TEL_WILL, OPT_ECHO );
  100.         return( t );
  101. retry:
  102.         sock_abort( s );
  103.     } while ( 1 );
  104. }
  105. /*
  106.  * teld_write - returns 0 on failure
  107.  */
  108. int teld_write( teld_str *t, char *buffer, int len )
  109. {
  110.     tcp_Socket *s;
  111.     if ( t->teld_connected == 0 ) return( 0 );
  112.     s = &t->teld_socket;
  113.     sock_write( s, buffer, len );
  114.     return( tcp_tick( s ) != 0);
  115. }
  116. int teld_puts( teld_str *t, char *s )
  117. {
  118.     return( teld_write( t, s, strlen( s)));
  119. }
  120. char teld_putch( teld_str *t, char x )
  121. {
  122.     return( teld_write( t, &x, 1 ) ? x : 0 );
  123. }
  124. /*
  125.  * teld_getc - returns character or 255 on connection failed
  126.  */
  127. BYTE teld_getc( teld_str *t )
  128. {
  129.     if ( ! tcp_tick( &t->teld_socket ))
  130.         t->teld_connected = 0;
  131.     if ( t->teld_connected == 0 )
  132.         return( 255 );
  133.     return( io_pre_get( t ));
  134. }
  135. int teld_iswaiting( teld_str *t )
  136. {
  137.     tcp_Socket *s;
  138.     s = &t->teld_socket;
  139.     if (tcp_tick( s ) == NULL ) t->teld_connected = 0;
  140.     if ( t->teld_connected == 0 ) return( 1 );  /* EOT is waiting */
  141.     return(sock_rbused( s ));
  142. }
  143. char *teld_getstring( teld_str *t, char *buf, int maxlen, long timeout, char dispchar )
  144. {
  145.     long now, whenever;
  146.     int len;
  147.     BYTE ch;
  148.     if ( timeout > 0 ) {
  149.         dos_enter();
  150.         now = time( NULL );
  151.         dos_exit();
  152.         whenever = now + timeout;
  153.     }
  154.     len = 0;
  155.     do {
  156.         buf[ len ] = 0;
  157.         /* reached max len */
  158.         if ( len == (maxlen - 1 )) {
  159.             return( buf );
  160.         }
  161.         if ( teld_iswaiting( t ) ) {
  162.             ch = teld_getc( t );
  163.             if ( ch == 255 ) {
  164.                 /* EOT */
  165.                 return( NULL );
  166.             }
  167.             if ( ch == 13 ) {
  168.                 buf[ len ] = 0;
  169.                 teld_puts( t, "rn");
  170.                 return( buf );
  171.             }
  172.             if (( ch == 8 ) || ( ch == 127 )) {
  173.                 if ( len > 0 ) {
  174.                     len--;
  175.                     teld_puts( t, "10 10" ); /* BS SP BS */
  176.                 } else
  177.                     teld_putch( t, 7 ); /* bell */
  178.             } else if ( ( ch == 0 ) || ( ch == 10 )) {
  179.                 /* do nothing */
  180.             } else {
  181.                 /* normal char */
  182.                 buf[ len++ ] = ch;
  183.                 /* handle normal or password type entries */
  184.                 teld_putch( t, dispchar ? dispchar : ch );
  185.             }
  186.             rt_sleep( 0 );      /* there may be more chars to process */
  187.         } else {
  188.             /* nothing to do.. so we do almost nothing */
  189.             rt_sleep( 10 );
  190.             /* look for timeout */
  191.             if ( timeout != 0 ) {
  192.                 dos_enter();
  193.                 now = time( NULL );
  194.                 dos_exit();
  195.                 if ( now >= whenever ) {
  196.                     return( NULL );
  197.                 }
  198.             }
  199.         }
  200.     } while ( 1 );
  201. }
  202. char *teld_getpassword( teld_str *t, char *buf, int maxlen, long timeout )
  203. {
  204.     return teld_getstring( t, buf, maxlen, timeout, '*' );
  205. }
  206. /*
  207.  * teld_gets - returns string on success
  208.  *           - returns NULL on closed session or on timeout reached
  209.  *           - timeout = 0 means never
  210.  */
  211. char *teld_gets( teld_str *t, char *buf, int maxlen, long timeout )
  212. {
  213.     return teld_getstring( t, buf, maxlen, timeout, 0 );
  214. }
  215. void teld_close( teld_str *t )
  216. {
  217.     tcp_Socket *s;
  218.     if ( t != NULL ) {
  219.         s = &t->teld_socket;
  220.         sock_close( s );
  221.         while ( tcp_tick( s ))
  222.             rt_sleep( 250 );
  223.         kfree( t );
  224.     }
  225. }