UNIX/LINUX network programming 2
(°£´ÜÇÑ telnet client ÇÁ·Î±×·¥ÀÇ ±¸Çö)

    Àü¿µÁØ(Çѱ¹Ç×°ø´ëÇб³ ÄÄÇ»ÅÍ°øÇаú)
    Hitel ID : MonaC
    E-mail : monac@ee.korea.ac.kr

     

 

1. ÅÚ³Ý ÇÁ·ÎÅäÄÝ

    ÅÚ³ÝÀº ÀÎÅÍ³Ý »çÀÇ ´Ù¸¥ ÄÄÇ»ÅÍ·Î ·Î±×ÀÎÀ» ÇÒ ¼ö ÀÖ°Ô ÇÏ´Â ÇÁ·ÎÅäÄÝÀÌ´Ù.
    Åڳݿ¡¼­ Ŭ¶óÀ̾ðÆ®´Â ÀÔ·Â µð¹ÙÀ̽º(Å°º¸µå)¿Í Ãâ·Â µð¹ÙÀ̽º(¸ð´ÏÅÍ)¸¦ °¡Áö¸ç, ÅÚ³Ý ¼­¹ö ÇÁ·Î±×·¥À» ¶ç¿ì°í ÀÖ´Â ¿ø°Ý È£½ºÆ®¿¡ ·Î±×ÀÎ ÇÑ´Ù. À̶§ ¿ø°Ý È£½ºÆ®ÀÇ ÀԷ°ú Ãâ·ÂÀº Ŭ¶óÀ̾ðÆ®ÀÇ ÀԷ°ú Ãâ·ÂÀ¸·Î ´ëÄ¡µÈ´Ù. ÅÚ³Ý ÇÁ·ÎÅäÄÝÀÇ ±âº» ¸ñÇ¥´Â ÅÚ³Ý µ¥¸ó°ú ÅÚ³Ý Å¬¶óÀ̾ðÆ®¸¦ ÅëÇÑ ¿ø°Ý ·Î±×ÀÎÀÌÁö¸¸ ¸¹Àº ´Ù¸¥ ¿ëµµ·Î »ç¿ëµÉ ¼öµµ ÀÖ´Ù.

 

2. ÅÚ³Ý ¸í·É¾î

    ÅÚ³Ý ÇÁ·ÎÅäÄÝÀº ¼­¹ö¿Í Ŭ¶óÀ̾ðÆ® ¼­·Î¸¦ Á¦¾îÇϱâ À§ÇÏ¿© ¸¹Àº ¸í·É¾î¸¦ »ç¿ëÇÑ´Ù. ÀÌ·¯ÇÑ ¸í·É¾î´Â IAC(interpret as command)¹®ÀÚ ´ÙÀ½¿¡ º¸³»Áø´Ù.
    IAC´Â ¾Æ½ºÅ° ÄÚµå 255¹øÀÌ´Ù.

     

    À̸§   ascii¹øÈ£                     ÀǹÌ

    SE      240    End of subnegotiation parameters.
    NOP    241    No operation Data mark. Indicates the position of a Synch
                       event within the data stream.
    DM     242    This should always be accompanied by a TCP urgent
                       notification.
    BRK   243     Break. Indicates that the "break" or "attention" key was hit.
    IP      244     Suspend, interrupt or abort the process to which the NVT is
                       connected.
    AO     245    Abort output. Allows the current process to run to completion
                       but donot send its output to the user.
    AYT    246    Are you there. Send back to the NVT some visible evidence
                       that the AYT was received.
    EC     247     Erase character. The receiver should delete the last preceding
                       undeleted character from the data stream.
    EL     248     Erase line. Delete characters from the data stream back to but
                       not including the previous CRLF.
    GA    249      Go ahead. Used, under certain circumstances, to tell the
                       other end that it can transmit.
    SB    250      Subnegotiation of the indicated option follows.
    WILL  251     Indicates the desire to begin performing, or confirmation that
                       you are now performing, the indicated option.
    WONT 252    Indicates the refusal to perform, or continue performing, the
                       indicated option.
    DO    253     Indicates the request that the other party perform, or
                       confirmation that you are expecting the other party to perform,
                       the indicated option.    
    DONT 254    Indicates the demand that the other party stop performing, or
                       confirmation that you are no longer expecting the other party
                       to perform, the indicated option.
    IAC    255     Interpret as command.


    < ǥ1 telnet commands >

 

3. ÅÚ³Ý ¿É¼Ç

    ¶ÇÇÑ ¿©·¯ °¡Áö »óŸ¦ ¼³Á¤Çϱâ À§ÇÑ ¿É¼ÇÀÌ ÀÖ´Ù. ÀÌ ¿É¼ÇµéÀº ¾ðÁ¦µçÁö Àç¼³Á¤µÉ ¼ö ÀÖÀ¸¸ç, ¼­¹ö³ª Ŭ¶óÀ̾ðÆ® ¾î´À ÂÊ¿¡¼­µµ ¼³Á¤ÇÒ ¼ö ÀÖ´Ù. ¿É¼ÇÀÇ Á¤È®ÇÑ ½ºÆåÀº °¢°¢ÀÇ rpc¸¦ Âü°í ÇÏ¿©¾ß ÇÑ´Ù.

     

    ascii¹øÈ£      À̸§                              RFC¹øÈ£

    1               echo                               857
    3               suppress go ahead           858
    5               status                              859
    6               timing mark                      860
    24              terminal type                   1091
    31              window size                    1073
    32              terminal speed                1079
    33              remote flow control          1372
    34              linemode                        1184
    36              environment variables      1408


    < Ç¥2 Áß¿äÇÑ ¿É¼ÇµéÀÇ rfc¹øÈ£>

    ¿É¼ÇÀº Ŭ¶óÀ̾ðÆ®³ª ¼­¹ö ¾î´À ÇÑÂÊ¿¡¼­ ¿ä±¸¸¦ ÇÏ¿©, ´Ù¸¥ ÇÑ ÂÊ¿¡¼­ ±×°Í¿¡ ÀÀ´äÇÏ´Â ÇüÅ·Π¼³Á¤µÈ´Ù. ¿É¼ÇÀ» ¿ä±¸ÇÒ ¶§´Â

     

    IAC, <¿ä±¸ÀÇ ÇüÅÂ>,<¿É¼Ç>

     

    ÀÇ Â÷·Ê·Î Äڵ带 º¸³»¸ç, ÀÀ´ä ¶ÇÇÑ °°Àº ¹æ½ÄÀÌ´Ù.
    ¿ä±¸ÀÇ ÇüÅ´ ´ÙÀ½ÀÇ 4°¡Áö°¡ ÀÖ´Ù.

     

    ±âÈ£       ascii¹øÈ£     ¿ä±¸ÀÇ ÇüÅÂ

    Will        251            ¿É¼ÇÀ» »ç¿ëÇÏ°Ú´Ù.
    DO        252            (»ó´ë¹æ¿¡°Ô) ¿É¼ÇÀ» »ç¿ëÇ϶ó.
    WONT    253            ¿É¼ÇÀ» »ç¿ëÇÏÁö ¾Ê°Ú´Ù.
    DONT    254            (»ó´ë¹æ¿¡°Ô) ¿É¼ÇÀ» »ç¿ëÇÏÁö ¸¶¶ó

     

    WILLÀ̳ª WONT´Â ¿É¼ÇÀ» ¿ä±¸ÇÏ´Â ÂÊÀÌ ±× ¿É¼ÇÀ» »ç¿ë ¶Ç´Â »ç¿ëÇÏÁö ¾Ê°Ú´Ù´Â ¶æÀ̸ç, DO³ª DONT´Â »ó´ë¹æÃø¿¡ ¿É¼ÇÀ» »ç¿ë ¶Ç´Â »ç¿ëÇÏÁö ¸»¶ó°í ¿ä±¸ÇÏ´Â °ÍÀÌ´Ù.

    ÇÑÂÊ¿¡¼­ ¿ä±¸¸¦ ÇÏ¸é »ó´ë¹æÀº ÀÀ´äÀ» ÇØ¾ß ÇÑ´Ù. ¿ä±¸¿Í ÀÀ´äÀÇ Á¶ÇÕÀº ´ÙÀ½ÀÇ °æ¿ì¸¸ÀÌ °¡´ÉÇÏ´Ù.

     

    ¿ä±¸          ÀÀ´ä           ÀÀ´äÀÇ ÀǹÌ

    WILL         DO             ¿É¼Ç »ç¿ëÀ» Çã¶ôÇÑ´Ù.
    WILL         DONT         ¿É¼Ç »ç¿ëÀ» Çã¶ôÇÏÁö ¾Ê´Â´Ù.
    DO           WILL           ¿É¼ÇÀ» »ç¿ëÇÏ°Ú´Ù.
    DO           WONT         ¿É¼ÇÀ» »ç¿ëÇÒ ¼ö ¾ø´Ù.
    WONT       DONT         ¿É¼ÇÀ» »ç¿ëÇÏÁö ¾Ê°Ú´Ù.
    DONT       WONT         ¿É¼ÇÀ» »ç¿ëÇÏÁö ¸¶¶ó.

     

    SB¸í·É¾î´Â Çϳª ÀÌ»óÀÇ ¿É¼ÇÀ» ÇÊ¿ä·Î ÇÒ ¶§ »ç¿ëµÈ´Ù. Å͹̳ΠŸÀÔÀ̳ª, Å͹̳ÎÀÇ Å©±â µîÀ» º¸³»°í ¹Þ´Âµ¥ »ç¿ëµÈ´Ù.

    ÅÚ³Ý Å¬¶óÀ̾ðÆ®·Î ÅÚ³ÝÀÇ ¿É¼Ç Çù»ó °úÁ¤À» »ìÆ캸ÀÚ.

     

    monac:~$telnet
    telnet> toggle options
    Will show option processing.
    telnet> open localhost
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    SENT DO SUPPRESS GO AHEAD
    SENT WILL TERMINAL TYPE
    SENT WILL NAWS
    SENT WILL TSPEED
    SENT WILL LFLOW
    SENT WILL LINEMODE
    SENT WILLOLD-ENVIRON
    SENT DO STATUS
    SENT WILL XDISPLOC
    RCVD DO TERMINAL TYPE
    RCVD DO TSPEED
    RCVD DO XDISPLOC
    RCVD DO NEW-ENVIRON
    SENT WONT NEW-ENVIRON
    RCVD WILL SUPPRESS GO AHEAD
    RCVD DO NAWS
    SENT IAC SB NAWS 0 80 (80) 0 25 (25)
    RCVD DO LFLOW
    RCVD DONT LINEMODE
    RCVD DONT OLD-ENVIRON
    RCVD WILL STATUS
    RCVD IAC SB TERMINAL-SPEED SEND
    SENT IAC SB TERMINAL-SPEED IS 9600,9600
    RCVD IAC SB X-DISPLAY-LOCATION SEND
    SENT IAC SB X-DISPLAY-LOCATION IS "monac:0.0"
    RCVD IAC SB TERMINAL-TYPE SEND
    SENT IAC SB TERMINAL-TYPE IS "XTERM"
    RCVD DO ECHO
    SENT WONT ECHO
    RCVD WILL ECHO
    SENT DO ECHO
    Debian GNU/Linux 1.3 monac.hackers.org
    Monac login: Connection closed by foreign host.


    Áö¸é °ü°è»ó ¿É¼Ç¿¡ ´ëÇÑ ÀÚ¼¼ÇÑ ¼³¸íÀº »ý·«ÇÑ´Ù. ¼Ò½º¸¦ ºÐ¼®Çϸ鼭 °£´ÜÇÑ ¼³¸íÀ» ´õ
    ÷°¡Çϵµ·Ï ÇÏ°Ú´Ù. ÇÁ·ÎÅäÄÝ¿¡ ´ëÇÑ ÀÚ¼¼ÇÑ ½ºÆåÀº RFC¸¦ Âü°íÇϱ⠹ٶõ´Ù.

 

4. ÅÚ³Ý Å¬¶óÀ̾ðÆ®

    ÇÁ·Î±×·¥ÀÇ ¼Ò½º´Â ÇÁ·ÎÅäÄÝÀ» ó¸®ÇÏ´Â protocal.c¿Í ±× ¿ÜÀÇ ¸ðµç ÇÔ¼ö°¡ Æ÷ÇÔµÈ telnet
    ·Î ³ª´µ¾îÁ® ÀÖ´Ù. µÎ ÆÄÀÏ¿¡ °øÅëÀ¸·Î ÇÊ¿äÇÑ ÇÔ¼ö´Â telnet.h¿¡¼­ ¼±¾ðµÇ¾ú´Ù.
    ¾Æ·¡ÀÇ ¼³¸íÀº ÇÁ·Î±×·¥ ¼Ò½º¸¦ º¸¸é¼­ Àо±â ¹Ù¶õ´Ù.

    ÅÚ³Ý Å¬¶óÀ̾ðÆ®°¡ ÇØ¾ß ÇÒ ÀÏÀº ±âº»ÀûÀ¸·Î ´ÙÀ½°ú °°´Ù.

    -¼­¹ö·ÎÀÇ stream socket ¿¬°áÀ» ÇÑ´Ù.
    -¼ÒÄÏ°ú »ç¿ëÀڷκÎÅÍ µ¥ÀÌÅ͸¦ ÀÐ°í ¾´´Ù.
    -ÀÐÀº µ¥ÀÌÅ͸¦ ÆĽÌÇÏ¿© ÇÁ·ÎÅäÄÝÀ» ó¸®ÇÑ´Ù.

¼ÒÄÏ ¿¬°á ¹× Ãʱ⠼³Á¤

    ¼­¹ö¿Í ¼ÒÄÏÀ» ¿¬°áÇÏ´Â °úÁ¤Àº ´Ù¸¥ stream socketÀ» ÀÌ¿ëÇÏ´Â ÇÁ·Î±×·¥°ú º°Â÷ÀÌÁ¡ÀÌ ¾ø
    ´Ù. ¿ì¸®´Â ¸í·ÉÇàÀ¸·ÎºÎÅÍ ÁÖ¼Ò¿Í Æ÷Æ®¸¦ ÀԷ¹ްí, ±×°ÍÀ¸·Î ¼­¹ö¿Í ¼ÒÄÏ ¿¬°áÀ» ½ÃµµÇÑ´Ù. ÀÌ·¯ÇÑ °úÁ¤Àº main()ÇÔ¼ö¿¡¼­ 󸮵ȴÙ.
    ±â¼úÀûÀÎ ¼³¸íÀº Áö³­ È£ÀÇ °­Á¿¡¼­ ÀÚ¼¼ÇÏ°Ô ´Ù·ç¾úÀ¸¹Ç·Î ¿©±â¼­´Â »ý·«ÇÑ´Ù.

    ¼Ò½ºÀÇ main()¿¡¼­ ºÒ¸®¾îÁö´Â init_system()ÇÔ¼ö¸¦ »ìÆ캸ÀÚ.
    ÀÌ ÇÔ¼ö¿¡¼­´Â read_buf, write_buf ±¸Á¶Ã¼¸¦ ÃʱâÈ­ÇÏ°í, SIGPIPE¸¦ À§ÇÑ ½Ã±×³Î Çڵ鷯¸¦
    ¼³Ä¡, ¼ÒÄÏÀ» nonblock »óÅ·Π¼³Á¤, ±×¸®°í Å͹̳ÎÀ» ¼¼ÆÃÇÑ´Ù. Read_buf, write_buf±¸Á¶Ã¼¿¡ ´ëÇؼ­´Â µÚ¿¡¼­ ¼³¸íÇÏ°Ú´Ù
    ¿ì¸®´Â ÇÁ·Î¼¼¼­°¡ ºí·°µÇ´Â °ÍÀ» ¸·±â À§ÇØ ¼ÒÄÏÀ» nonblock »óÅ·Π¸¸µç´Ù.
    ºí·ÏÀº ´ÙÀ½ÀÇ °æ¿ì¿¡ ÀϾ´Ù.

    -¼ÒÄÏ¿¡ read()¸¦ È£ÃâÇߴµ¥ ÀÐÀ» µ¥ÀÌÅÍ°¡ ¾øÀ» ¶§.
    -¼ÒÄÏ¿¡ write()¸¦ È£ÃâÇߴµ¥ ´çÀå¿¡ ¾µ ¼ö°¡ ¾øÀ» ¶§.
    -ioctl()ÀÌ ´çÀå¿¡ ½ÇÇàµÉ ¼ö ¾øÀ» ¶§.

    ÀÌ ¿Ü¿¡µµ ¸¹Àº °æ¿ì°¡ ÀÖÁö¸¸ ÀÌ ÇÁ·Î±×·¥¿¡¼­´Â À§ÀÇ °æ¿ì¿¡ ºí·ÏÀÌ ÀϾ´Ù. ºí·ÏÀÌ ÀϾ¸é ÇÁ·Î¼¼¼­´Â ºí·ÏÀÌ ÇØÁ¦µÉ ¶§±îÁö ¸ØÃß¾î Áø´Ù.
    Åڳݿ¡¼­´Â ¿©·¯ ÀÛ¾÷À» µ¿½Ã¿¡ ¼öÇàÇϹǷΠºí·°ÀÌ ÀϾ´Â °ÍÀ» ¸·¾Æ¾ß ÇÑ´Ù.
    nonblock ¸ðµå¿¡¼­´Â À§ÀÇ ÀÛ¾÷ÀÌ Àý´ë·Î ºí·°µÇÁö ¾Ê´Â´Ù´Â °ÍÀ» º¸ÀåÇÑ´Ù.
    ¸¸¾à nonblock »óÅ·Π¼³Á¤Ç߱⠶§¹®¿¡ ÀÛ¾÷ÀÌ ¿Ï¼ºµÇÁö ¾Ê´Â´Ù¸é ÇØ´ç ½Ã½ºÅÛ È£ÃâÀº ¿¡·¯¸¦ ¸®ÅÏÇÏ°í, errno º¯¼ö°¡ EWOULDBLOCKÀ¸·Î ¼³Á¤µÉ °ÍÀÌ´Ù.
    nonblockÀÇ ¼³Á¤Àº ´ÙÀ½°ú °°ÀÌ ÇàÇØÁø´Ù.

     

    void nonblock(int onoff)
    {
      if (ioctl(sock, FIONBIO, &onoff)<0)
      {
        perror("ioctl");
        sys_error();
      }
    }

     

    ¼ÒÄÏÀÇ ¿¬°áÀÌ ²÷°åÀ» ¶§¿¡´Â read()°¡ 0À» ¸®ÅÏÇÏ°í ¶ÇÇÑ write()°¡ SIGPIPE ½Ã±×³ÎÀ» ¹ß»ýÇÑ´Ù. SIGPIPE ½Ã±×³ÎÀ» °¡·ÎèÀ¸·Î¼­ ¼ÒÄÏ ¿¬°áÀÌ ²÷°åÀ» ¶§¸¦ ¾Ë ¼ö ÀÖ´Ù.

     

    Signal(SIGPIPE,peer_died);

     

    SIGPIPE ½Ã±×³ÎÀº peer_died()ÇÔ¼ö¿¡ ¿¬°áµÇ¾ú´Ù. Peer_died()ÇÔ¼ö´Â »ó´ë¹æÀÇ ¿¬°áÀÌ ²÷°åÀ» ¶§ÀÇ °¢Á¾ 󸮸¦ ¼öÇàÇÑ´Ù. ±×·¯¹Ç·Î, ¼ÒÄÏÀÇ ¿¬°áÀÌ ²÷¾îÁ®¼­ write()°¡ SIGPIPE ½Ã±×³ÎÀ» ¹ß»ý½ÃÅ°¸é peer_died()ÇÔ¼ö°¡ ½ÇÇàµÈ´Ù.
    set_terminal()Àº ÇöÀçÀÇ ÅÚ³Ý »óÅ¿¡ µû¶ó Å͹̳ÎÀ» ¼¼ÆÃÇÏ´Â ÇÔ¼öÀÌ´Ù.
    Å͹̳ÎÀÇ »óÅ´ ÅÚ³Ý ÇÁ·ÎÅäÄÝ·Î Á¶Á¤ÀÌ µÈ´Ù. set_terminal()ÀÇ Àμö°¡ 0ÀÏ ¶§´Â Å͹̳ÎÀ»
    ¿¹ÀüÀÇ »óÅ·ΠµÇµ¹·Á ³õ´Â´Ù.  
    ÀÌ ´ÙÀ½À¸·Î main() ÇÔ¼ö´Â init_telnet((port ==23));À» ½ÇÇàÇÑ´Ù.
    init_telnet()ÇÔ¼ö´Â ÅÚ³Ý ÇÁ·ÎÅäÄÝÀ» ÆĽÌÇϱâ À§ÇÑ º¯¼öµéÀ» ÃʱâÈ­ ÇÏ°í, ÅÚ³Ý ¿¬°áÀÌ ÅÚ³Ý µ¥¸ó°úÀÇ ¿¬°áÀÏ ¶© ÅÚ³Ý ¿¬°áÀÇ Ãʱ⠼³Á¤À» À§ÇÑ ÇÁ·ÎÅäÄÝÀ» º¸³½´Ù. ÀϹÝÀûÀ¸·Î Åڳݵ¥¸óÀÇ Æ÷Æ®´Â 23¹øÀ̹ǷΠ¿©±â¼­´Â ÀÌ Æ÷Æ®¹øÈ£¿¡ ±Ù°ÅÇؼ­ ÅÚ³Ý µ¥¸ó°úÀÇ ¿¬°áÀÎÁö¸¦ ÆÇ´ÜÇÑ´Ù.

main_loop()

    main-loop() ÇÔ¼ö´Â ÅÚ³Ý Å¬¶óÀ̾ðÆ®ÀÇ ÀϹÝÀûÀÎ ÀÛ¾÷À» ¼öÇàÇÑ´Ù. ÇϳªÀÇ ¹«ÇÑ·çÇÁÀÎ ÀÌ ÇÔ¼ö´Â ¼ÒÄÏ°ú µ¥ÀÌÅÍÀÇ ÀÔÃâ·Â, ±×°ÍÀÇ ÇÁ·ÎÅäÄÝ Ã³¸® ±×¸®°í Å°º¸µå·ÎºÎÅÍÀÇ ÀÔ·ÂÀ» ó¸®ÇÏ´Â °úÁ¤À» ¹Ýº¹Çؼ­ ó¸®ÇÑ´Ù.
    ÀÌ·¯ÇÑ ÀÛ¾÷Àº select()½Ã½ºÅÛ È£ÃâÀ» ÀÌ¿ëÇÏ¿© ÀÌ·ç¾îÁø´Ù.
    Åڳݿ¡¼­´Â Àü¼ÛµÇ´Â µ¥ÀÌÅÍ¿¡ ´ëÇØ ÇÁ·ÎÅäÄÝÀ» ó¸®ÇØ¾ß Çϸç, È¿À²ÀûÀ¸·Î µ¥ÀÌÅ͸¦ Àü¼ÛÇØ¾ß Çϱ⠶§¹®¿¡ ¿ì¸®´Â ÀԷ°ú Ãâ·Â¿¡ ´ëÇØ ¹öÆÛ¸¦ ¼³Á¤ÇÏ¿´´Ù.
    ¹öÆÛ´Â write_buf¿Í read_buf°¡ ÀÖÀ¸¸ç ÀÌ°ÍÀÇ ÇüÀº buffer±¸Á¶Ã¼ÀÌ´Ù.

     

    Struct buffer
    {
      char buf;       /*µ¥ÀÌÅ͸¦ ÀúÀåÇÒ ÁÖ¼Ò°ø°£*/
      int size;         /*buf¿¡ ÇÒ´çµÈ ¸Þ¸ð¸®ÀÇ Å©±â*/
      int head, tail; /*buf¿¡ ÀúÀåµÈ µ¥ÀÌÅÍÀÇ Ã³À½°ú ³¡ÀÇ À妽º */
      int count;      /*buf¿¡ ÀúÀåµÈ µ¥ÀÌÅÍÀÇ byte¼ö*/
    };

    struct buffer write_buf, read_buf;

     

    ¿ì¸®°¡ ¼ÒÄÏ¿¡ ¾µ µ¥ÀÌÅÍ´Â ¸ÕÀú write_buf¿¡ ÀúÀåµÈ´Ù. ÀÌ µ¥ÀÌÅÍ´Â main_loop()¿¡¼­ select()½Ã½ºÅÛ È£Ãâ·Î ¼ÒÄÏ¿¡ µ¥ÀÌÅ͸¦ ¾µ ¼ö ÀÖ´Ù´Â °ÍÀÌ È®ÀÎµÈ µÚ¿¡¾ß write_socket()ÇÔ¼ö¸¦ ÅëÇؼ­ ½ÇÁ¦·Î Àü¼ÛÀÌ µÈ´Ù. ¼ÒÄÏÀ¸·Î ÀÐÀº µ¥ÀÌÅÍ´Â ÀÐÀ» µ¥ÀÌÅÍ°¡ ÀÖÀ» ¶§¿¡¸¸ read_socket()À» ÅëÇؼ­, ¸ðµÎ read_buf¿¡ ÀúÀåµÈ´Ù. read_buf¿¡ ÀúÀåµÈ µ¥ÀÌÅÍ´Â ÇÁ·ÎÅäÄÝ Ã³¸®¸¦ À§ÇÏ¿© process_protocol() ÇÔ¼ö¿¡¼­ ÀÐÇôÁø´Ù. Ç¥3Àº ÀÌ·¯ÇÑ µ¥ÀÌÅÍÀÇ Ã³¸® °úÁ¤À» µµ½ÄÀûÀ¸·Î ±×¸° °ÍÀÌ´Ù.

     

    KEY_BOARD  --------> write_buf --------> Socket output
              Read_terminal()        write_socket()
    TERMINAL  <--------  read_buf  <-------- Socket input
              Process_protocol()       read_socket()

     

    <Ç¥3 µ¥ÀÌÅÍ Ã³¸®°úÁ¤>
    main_loop()´Â ÀÌ·¯ÇÑ °úÁ¤À» ¹Ýº¹ÀûÀ¸·Î ó¸®ÇÑ´Ù.

¹öÆÛ Ã³¸® ÇÔ¼ö

    ÅÚ³Ý ÇÁ·ÎÅäÄÝÀ» ó¸®ÇÏ´Â °úÁ¤¿¡¼­ ¿ì¸®´Â ¼­¹öÂÊÀ¸·Î ÇÁ·ÎÅäÄÝÀ» º¸³¾ ¼öµµ ÀÖ¾î¾ß ÇÏ°í, ¼ÒÄÏ¿¡¼­ ÀÐÇôÁø µ¥ÀÌÅ͸¦ ÆĽÌÇÏ¿© ÇÁ·ÎÅäÄÝ Ã³¸®¸¦ ÇÒ ¶§¿¡´Â read_buf¿¡¼­ Çϳª¾¿ ¹®ÀÚ¸¦ Àо ÇÊ¿äÇÑ ÇÁ·ÎÅäÄÝ ºÎºÐÀ» ÃßÃâÇØ¾ß ÇÑ´Ù.
    ÀÌ°ÍÀ» À§Çؼ­´Â write_buf¿¡ ÀÓÀ¸·Î µ¥ÀÌÅ͸¦ ¾µ ¼ö ÀÖ´Â ÇÔ¼ö°¡ ÇÊ¿äÇÏ°í, read_buf¿¡¼­ µ¥ÀÌÅ͸¦ ÀÓÀÇ·Î ÀÐ¾î µéÀÌ´Â ÇÔ¼ö°¡ ÇÊ¿äÇÏ´Ù.

    putc_socket()°ú puts_socket()Àº write_buf¿¡ µ¥ÀÌÅ͸¦ Áý¾î³Ö´Â ÇÔ¼öÀÌ´Ù.
    putc_socket()Àº ÇϳªÀÇ ¹®ÀÚ¸¸À», puts_socket()Àº ÇϳªÀÇ ¹®ÀÚ¿­À» Àμö·Î ¹Þ´Â´Ù. ÀÌ ÇÔ¼öµéÀº ¼­¹ö·Î ÇÁ·ÎÅäÄÝÀ» Àü¼ÛÇϱâ À§ÇØ ¾²¿©Áú °ÍÀÌ´Ù.
    putc_socket()À̳ª puts_socket()¿¡ Àü´ÞµÈ µ¥ÀÌÅÍ´Â write_buf¿¡ ÀúÀåµÉ °ÍÀÌ°í, ÀÌ°ÍÀº Å°º¸µå·ÎºÎÅÍ ÀÐÀº µ¥ÀÌÅÍ¿Í ÇÔ²² ¼ÒÄÏÀ» ÅëÇØ ¼­¹ö¿¡ Àü¼ÛµÈ´Ù.
    getc_socket()Àº read_buf·ÎºÎÅÍ ÇϳªÀÇ ¹®ÀÚ¸¦ ²ôÁý¾î ³½´Ù.
    Putc_terminal()Àº ÇϳªÀÇ ¹®ÀÚ¸¦ Å͹̳Î, Áï È­¸é¿¡ Ãâ·ÂÇÏ´Â ÇÔ¼öÀÌ´Ù.

    ÀÌ·¯ÇÑ ÆíÀÇÇÔ¼öµéÀº ÀüºÎ ÇÁ·ÎÅäÄÝÀ» ó¸®ÇÏ´Â °úÁ¤¿¡¼­ ÇÊ¿äÇÑ ÇÔ¼öµéÀÌ´Ù.
    Ç¥3ÀÇ µ¥ÀÌÅÍ Ã³¸®°úÁ¤À¸·ÎºÎÅÍ º»´Ù¸é, ÀÌ ÇÔ¼öµéÀº ÀüºÎ process_protocol()ÇÔ¼ö¿¡¼­ ÇÊ
    ¿ä·Î ÇÑ´Ù.

ÅÚ³Ý ÇÁ·ÎÅäÄÝ ÆĽÌ

    process_protocol()Àº read_buf¿¡ ÀúÀåµÈ µ¥ÀÌÅ͸¦ ÆĽÌÇÏ¿© ÅÚ³Ý ÇÁ·ÎÅäÄÝÀ» ó¸®ÇÑ´Ù. ÀÌ
    ÇÔ¼ö´Â main_loop()¿¡¼­ read_buf¿¡ µ¥ÀÌÅÍ°¡ ÀÖÀ» ¶§¸¸ ºÒ·ÁÁø´Ù.
    ÅÚ³Ý ÇÁ·ÎÅäÄÝÀ» À§ÇÑ ¿©·¯ #define µîÀÌ arpa/telnet.h¿¡ Á¤ÀǵǾî ÀÖ´Ù.

     

    #define TELCMDS
    #define TELOPTS
    #include <arpa/telnet.h>

     

    ¿©±â¼­ TELCMDS, TELOPTS¸¦ #include ¾Õ¿¡¼­ Á¤ÀÇÇÑ ÀÌÀ¯´Â telnet.h¿¡ ÀÖ´Â ÅÚ³Ý ¸í·É¾î Å×À̺íÀÎ telcmds¿Í, ÅÚ³Ý ¿É¼Ç Å×À̺íÀÎ telopts¸¦ »ç¿ëÇϱâ À§Çؼ­ÀÌ´Ù.
    Process_protocol()¿¡¼­´Â read_buf¿¡¼­ ÇÁ·ÎÅäÄÝÀ» ÃßÃâÇÏ°í, ÇÁ·ÎÅäÄÝÀÌ ¾Æ´Ï¸é È­¸é¿¡ Ãâ·ÂÇÏ´Â ÀÛ¾÷À» ÇÑ´Ù. ÅÚ³Ý ¸í·É¾î´Â Ç×»ó IAC·Î ½ÃÀÛÇÑ´Ù.
    getc_socket()Àº read_buf¿¡¼­ ÇϳªÀÇ ¹®ÀÚ¸¦ ²ôÁý¾î ³½´Ù. ±× ¹®ÀÚ°¡ IACÀÌ¸é ´ÙÀ½ ¹®ÀÚµéÀ» ÅÚ³Ý ¸í·É¾î·Î ÀνÄÀ» ÇÏ°í ÆĽÌÇÏ°Ô µÈ´Ù. ¾Æ´Ï¶ó¸é putc_terminal()À» ÀÌ¿ëÇÏ¿© È­¸é¿¡ Ãâ·ÂÇÑ´Ù.
    ¿ì¸®°¡ ±¸ÇöÇÑ ÅÚ³Ý ¸í·É¾î´Â DO , DON'T, WILL, WONTÀ¸·Î ½ÃÀÛÇÏ´Â ÅÚ³Ý ¿É¼Ç°ú, SB·Î ½ÃÀÛÇÏ´Â ÅÚ³Ý ¼­ºê ¿É¼ÇÀÌ´Ù.

ÅÚ³Ý ¿É¼Ç ó¸®

    process_option()Àº IAC+[DO|DONT|WILL|WONT]À¸·Î ½ÃÀ۵Ǵ ¿É¼ÇÀ» ó¸®ÇÏ´Â ÇÔ¼öÀÌ´Ù. ¿É¼ÇÀ» ó¸®Çϴµ¥ À־ °¡Àå ¾î·Á¿î Á¡Àº ÅÚ³Ý ¿É¼Ç Çù»ó °úÁ¤ÀÌ ´ëĪÀûÀ̶õ Á¡ÀÌ´Ù. Áï ¶È °°Àº ¿É¼ÇÀ» ¹ÞÀ» ¼ö ÀÖ°í, º¸³¾ ¼öµµ ÀÖ¾î¾ß ÇÑ´Ù´Â Á¡ÀÌ´Ù. ÀÌ·² ¶§´Â ¼­¹ö·ÎºÎÅÍ ¹ÞÀº ¿É¼ÇÀÌ ¿ì¸®°¡ º¸³½ ¿É¼ÇÀÇ ÀÀ´äÀÎÁö ¾Æ´Ï¸é ¿ä±¸¸¦ ÇÏ´Â ¸í·ÉÀÎÁö¸¦ ±¸ºÐÇϱⰡ ¾î·Æ´Ù. ÀÌ Ã³¸®¸¦ Çϱâ À§Çؼ­ option[]¹è¿­À» ¸¸µé¾ú´Ù.

    options[]ÀÇ °¢°¢ÀÇ Çʵå´Â ÇØ´ç ¿É¼Ç¿¡ ´ëÇØ ¿ä±¸¸¦ Çß´ÂÁöÀÇ ¿©ºÎ¸¦ ÀúÀåÇÑ´Ù.
    ÀÌ ¹è¿­À» ´Ù·ç±â À§ÇØ ÆíÀÇÇÔ¼ö option_requeted()¿Í option_request()°¡ ÀÖ´Ù.
    option_request()´Â option[]¿¡¼­ ÇØ´ç ¿É¼Ç Çʵ带 ¿ä±¸½Ã¿¡´Â 1 Áõ°¡ ½ÃÅ°°í, ÀÀ´ä½Ã¿¡´Â 1 °¨¼Ò½ÃÅ´À¸·Î¼­ ÇöÀçÀÇ ¿ä±¸ »óŸ¦ °ü¸®ÇÑ´Ù.

    option_requested()´Â ÇØ´ç ¿É¼ÇÀÌ ¿ä±¸µÇ¾ú´ÂÁö ¿©ºÎ¸¦ ÆÇ´ÜÇÑ´Ù. ÀÌ°ÍÀÌ 'Âü'À» ¸®ÅÏÇϸé ÇØ´ç ¿É¼ÇÀÌ ¿ä±¸µÇ¾ú´Ù´Â °ÍÀ» ÀǹÌÇÑ´Ù. ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¿© ¿ì¸®°¡ ¿É¼ÇÀ» ¼­¹ö¿¡ º¸³¾ ¶§¿¡´Â option_requestd()¸¦ È£ÃâÇÏ¿© ¿É¼Ç ¿ä±¸ »óŸ¦ ¼³Á¤ÇÏ°í, ¿É¼ÇÀ» ¼­¹ö·ÎºÎÅÍ ¹ÞÀ» ¶§¿¡´Â ±×°ÍÀÌ ¿ä±¸ÀÎÁö ÀÀ´äÀÎÁöÀÇ ¿©ºÎ¸¦ option_requested()¸¦ È£ÃâÇÔÀ¸·Î½á ÆÇ´ÜÇÑ´Ù.

    ¿É¼Ç Çù»ó °úÁ¤À» ÅëÇØ Ã³¸®µÈ ¿É¼ÇÀÌ ÀúÀåµÇ¾î¾ß ÇÒ °æ¿ì¿¡´Â ÀÌ Á¤º¸¸¦ mode¿¡ ÀúÀåÇÑ´Ù. ECHOÀÇ ¿©ºÎ(MODE_ECHO)³ª ¹ÙÀ̳ʸ® ¸ðµåÀÎÁöÀÇ ¿©ºÎ (MODE_INBIN, MODE_OUTBIN) µîÀÌ ÀÌ·¯ÇÑ Á¤º¸´Ù. Mode¸¦ ´Ù·ç´Â ÇÔ¼ö´Â mode_set() ÀÌ´Ù. °¡°ø ¸ðµå¿¡ ´ëÇÑ Á¤ÀÇ´Â arpa/telnet.h¿¡ Æ÷ÇԵǾî ÀÖ´Ù. ¿ì¸®°¡ ´Ù·ç´Â ¸ðµå´Â ¸ðµÎ set_terminal()¿¡¼­ 󸮵ȴÙ.
    ¿É¼ÇÀÌ ON ¶Ç´Â OFF µÇ¾úÀ» °æ¿ì set_terminal()ÀÌ È£ÃâµÇ¾î ÇØ´ç ¸ðµå¿¡ ´ëÇÑ ½ÇÁ¦ÀûÀΠ󸮸¦ ÇÑ´Ù.

    ÅÚ³Ý ÇÁ·ÎÅäÄÝÀÇ Á¤ÀÇ¿¡ µû¸£¸é ÅÚ³Ý Å¬¶óÀ̾ðÆ®´Â ¸ðµç ÅÚ³Ý ¿É¼ÇÀ» ó¸®ÇÒ ¼ö ÀÖ¾î¾ß ÇÑ´Ù°í µÇ¾î ÀÖ´Ù. ¿ì¸®°¡ Áö¿øÇÏÁö ¾Ê´Â ¿É¼ÇÀÌ¶óµµ ¼­¹ö°¡ ¿ä±¸Çϸé ÀÀ´äÇÒ ¼ö ÀÖ¾î¾ß ÇÑ´Ù. Option_ok()´Â ¿É¼ÇÀÌ ÇöÀç Áö¿øµÇ´ÂÁö ¿©ºÎ¸¦ ÆÇ´ÜÇÑ´Ù.
    ¾î¶² ¿É¼ÇÀº ¿ä±¸ÇÒ ¶§ÀÇ ÀÇ¹Ì¿Í ¿ä±¸ ¹Þ¾ÒÀ» ¶§ÀÇ Àǹ̰¡ ´Ù¸£´Ù

    TELOPT_BINARY ¿É¼ÇÀº 8ºñÆ® µ¥ÀÌÅÍÀÇ Ã³¸® ¿©ºÎ¸¦ °áÁ¤ÇÏ´Â ¿É¼ÇÀÌ´Ù. ¼­¹ö°¡ WILL ¶Ç´Â WONT·Î ¿ä±¸ÇßÀ» °æ¿ì¿¡´Â ¼­¹ö°¡ 8 ºñÆ® µ¥ÀÌÅ͸¦ ó¸®ÇÒÁö ¿©ºÎ¸¦ ¸»ÇÏ´Â °ÍÀ̹ǷÎ, ¿ì¸®´Â MODE_INBIN Áï 8ºñÆ®¸¦ ¹Þ¾ÆµéÀÌ°Ú´Ù´Â ¸ðµå¸¦ ¼³Á¤ÇØ¾ß ÇÑ´Ù. TELOPT_BINARY°¡ DO ¶Ç´Â DONT¸¦ ¿ä±¸ÇÑ´Ù¸é À̴ Ŭ¶óÀ̾ðÆ®ÀÇ 8ºñÆ® ó¸® ¿©ºÎÀÌÅ©·Î, Ʋ¶óÀ̾ðÆ®°¡ 8ºñÆ®¸¦ Ãâ·ÂÇÏ°Ú´Ù´Â MODE_OUTBINÀ» ¼³Á¤ÇØ¾ß ÇÑ´Ù. TELOPT_ECHO´Â Å͹̳ÎÀÌ Å°º¸µå·ÎºÎÅÍÀÇ ÀÔ·ÂÀ» ECHOÇØ¾ß ÇÏ´ÂÁö¸¦ ¼³Á¤ÇÑ´Ù. ¼­¹ö°¡ ECHO¸¦ ÇÏ°Ú´Ù¸é ÄöóÀ̾ðÆ®´Â ECHO¸¦ ÇÏÁö ¸»¾Æ¾ßÇÏ°í, ¼­¹ö°¡ ECHO¸¦ ÇÏÁö ¾Ê°Ú´Ù¸é Ŭ¶óÀ̾ðÆ®´Â ECHO¸¦ ÇؾßÇÑ´Ù.

Network Virtual Terminal

    ÅÚ³Ý ÇÁ·ÎÅäÄÝÀº Network Virtual Terminal(NVT)¸¦ Æ÷ÇÔÇÑ´Ù. Ŭ¶óÀ̾ðÆ®´Â ¼­¹ö·ÎºÎÅÍ ¹ÞÀº NVTÄڵ带 È­¸é 󸮸¦ À§ÇÑ ÀûÀýÇÑ ÄÚµå·Î ¹Ù²Ù¾î¾ß ÇÏ°í, »ç¿ëÀÚ Å°º¸µå·ÎºÎÅÍ ¹ÞÀº ÀÔ·ÂÀ» NVTÄÚµå·Î ¹Ù²Ù¾î¾ß ÇÑ´Ù. ÀÌ°ÍÀº CR/NL ¸ÊÆÃ, ÅÇÀÇ Ã³¸® µîÀ» Æ÷ÇÔÇÑ´Ù. ¿ì¸®ÀÇ ÇÁ·Î±×·¥Àº ÀÌ·¯ÇÑ Ã³¸®¸¦ set_terminal()¿¡¼­ Å͹̳Π¼¼ÆÃÀ» ÅëÇؼ­ ÇàÇÑ´Ù. ±×·¯³ª ÀÌ°ÍÀº NVT¸¦ ¿Ïº®È÷ Áö¿øÇÏÁö ¾Ê´Â´Ù. ´Ù¸¸ °£´ÜÈ÷ Çϱâ À§ÇÑ ÇØÅ·ÀÌ´Ù.

ÇÁ·Î±×·¥ Á¾·á ÇÔ¼ö

    ÇÁ·Î±×·¥À» ³¡³»´Â ÇÔ¼ö·Î´Â peer_died(), do_bye(), sys_error()°¡ ÀÖ´Ù.
    peer_error()´Â ¼­¹ö°¡ ¿¬°áÀ» ²÷¾úÀ» ¶§ È£ÃâµÇ°í, sys_error()´Â ½Ã½ºÅÛ È£ÃâÀÇ ¿¡·¯·Î ÀÎÇÏ¿© ´õ ÀÌ»ó ÀÛ¾÷À» ÇÒ ¼ö ¾øÀ» ¶§ È£ÃâµÈ´Ù. Do_bye()´Â »ç¿ëÀÚ°¡ ¿¬°áÀ» ²÷À» ¶§ ºÒ¸®¾îÁø´Ù. ÀÌ Á¾·á ÇÔ¼öµéÀÌ ÇÏ´Â ÀÏÀº ¸ðµÎ °°´Ù.

    -close()·Î ¼ÒÄÏÀ» ´Ý´Â´Ù.
    -Å͹̳ÎÀ» ¿ø·¡ÀÇ »óÅ·Πȸº¹½ÃŲ´Ù.
    -mallocµÈ ¸Þ¸ð¸®¸¦ ¸ðµÎ ÇØÁ¦ÇÑ´Ù.
    -ÀûÀýÇÑ ¸Þ½ÃÁö¸¦ ³»º¸³½´Ù.
    -exit()¸¦ È£ÃâÇÏ¿© ÇÁ·Î±×·¥À» ³¡³½´Ù.

    Set_terminal()¿¡¼­ Å͹̳ÎÀ» Ç×»ó raw ¸ðµå·Î ¸¸µç´Ù(¿ÏÀüÇÑ raw ¸ðµå´Â ¾Æ´Ï´Ù). ±×·¡¼­ »ç¿ëÀÚÀÇ Å°º¸µå ÀÎÅÍ·´Æ® µîÀÌ µ¿ÀÛÇÏÁö ¾Ê´Â´Ù. ¿ì¸®°¡ escape character¸¦ Áö¿øÇÏÁö ¾Ê±â ¶§¹®¿¡ ÇöÀç do_bye()¸¦ ÅëÇØ »ç¿ëÀÚ°¡ ÇÁ·Î±×·¥À» °­Á¦ Á¾·á ½Ãų ¼ö´Â ¾ø´Ù.

 

5. °£´ÜÇÑ ÅÚ³Ý Å¬¶óÀ̾ðÆ®ÀÇ ¼Ò½º

    ÅÚ³ÝÀÇ ¿É¼ÇÀº ¸¹°íµµ ¾ÆÁÖ º¹ÀâÇÏ´Ù. ÀÌ·¯ÇÑ Ã³¸®¸¦ ¸ðµÎ Áö¿øÇϱâ À§Çؼ­´Â ÇÁ·Î±×·¥ÀÌ »ó´çÈ÷ º¹ÀâÇØÁø´Ù. ¿©±â¼­´Â °£´ÜÈ÷ ÇÊ¿äÇÑ ¸î °³ÀÇ ¿É¼Ç¸¸ Áö¿øÇϸç, ¾Ë°í¸®Áòµµ °£´ÜÇÏ°Ô ÇÏ¿© ¿ÏÀüÇÑ ÅÚ³Ý ½ºÆåÀ» Áö¿øÇÏÁö ¾Ê´Â´Ù.

     

    /*
     * telnet.h
     *
     *ÇÔ¼ö ¼±¾ð.
     *by Àü¿µÁØ
     */

    /* telnet.c ¿¡¼­ Á¤ÀÇµÈ ÇÔ¼ö*/
    void peer_died();
    void do_bye();
    void sys_error();

    void putc_terminal(int.c);
    int getc_socket(int*c);
    void putc_socket(int c);
    void puts_socket(char*);

    int set_terminal(int set);
    void nonblock(int onoff);

    void debug(const char*, ...);

    /* protocol.c ¿¡¼­ Á¤ÀÇµÈ ÇÔ¼ö*/
    void int_telnet(int istelnet);
    void process_protocol(void);

    /*the end of telnet*/

    /*
    *telnet.c
    *
    *by Àü¿µÁØ
    */

    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <stdarg.h>

    #include <sys/time.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <arpa/inet.h>

    #include <termios.h>
    #include <sys/ioctl.h>

    #include <arpa/telnet.h>

    #include "telnet.h"

    #define MAX_WRITE_BUF PIPE_BUF*2
    #define MAX_READ_BUF PIPE_BUF

    int do_debug = 0;

    char hostname[MAXHOSTNAMELEN]
    int port;
    int sock;

    struct buffer
    {
      char buf;      /*µ¥ÀÌÅ͸¦ ÀúÀåÇÒ ÁÖ¼Ò°ø°£*/
      int size;     /*buf¿¡ ÇÒ´çµÈ ¸Þ¸ð¸®ÀÇ Å©±â*/
      int head, tail; /*buf¿¡ ÀúÀåµÈ µ¥ÀÌÅÍÀÇ Ã³À½°ú ²öÀÇ À妽º*/
      int count;    /*buf¿¡ ÀúÀåµÈ µ¥ÀÌÅÍÀÇ byte¼ö*/
    };

    struct buffer write_buf, read_buf;

    void init_system(void);

    void main_loop();
    void read_socket();
    void read_terminal();
    void write_socket();

    void usage()
    {
      fprintf(stdeer,"usage; mtelnet[-g] [hostname [port]]¡¬n");
      exit(1);
    }

    void main(int argc, char *argv[])
    {
      struct hostent *host;
      struct sockaddr_ serv_addr;
      int c;
      extern int optind;

      while((c = getopt(argc, argv, "g"))!=EOF)
      {
        switch(c )
        {
        case 'g';
          do_debug = 1;
          break;
        default;
          usage();
        }  
    }

            argc-=optind;
            argv+=optind;

    if(argc <=0||argc>2)
      usage();
    if(argc==2)
      port=atoi(argv[1]);
    else
      port=23;

    bzero((char*)&serv_addr,sizeof(serv_addr));
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_port =htons(port);

    if((serv_addr.sin_addr.s_addr=inet_addr(argv[0]))!=INADDR_NONE)
    {
      strcpy(hostname,arv[0]);
    }
    else
    {
      if((host=gethostbyname(argv[0]))==NULL)
      {
        herror("gethostbyname");
        exit(1);
      }
      serv_addr.sin_family=host->h_addrtype;
    bcopy(host->h_addr,(char*) &serv_addr.sin_addr,host->h_length);
    strcpy(hostname, host->h_name);
    }

    if((sock=socket(AF_INET,SOCK_STREAM,0))<0)
    {
    perror("socket");
    exit(1);
    }
    printf("Connected to %s.¡¬n", hostname);

    init_system(void)
    {
    write_buf.buf = (char*) malloc(MAX_WRITE_BUF);
    write_buf.size = MAX_WRITE_BUF;
    write_buf.head = write_buf.tail = 0;
    write_buf.count = 0;

    read_buf.buf = (char*) malloc(MAX_READ_BUF);
    read_buf.size = MAX_READ_BUF;
    read_buf.head = read_buf.tail = 0;
    read_buf.count = 0;

      signal(SIGPIPE, peer_died);
      nonblock(1);
      set_terminal(1);
    }

    void peer_died(void)
    {
      close(sock);
      set_terminal(0);

      free(write_buf.buf);
      free(read_buf.buf);

      fprintf(stderr,"Connection closed by foreign host.¡¬n");
      exit(1);
    }

    void do_bye()
    {
      close(sock);
      set_terminal(0);

      free(write_buf.buf);
      free(read_buf.buf);

              printf("Connection closed.¡¬n");
      exit(0);
    }

    void sys_error()
    {
      close(sock);
      set_terminal(0);

      free(write_buf.buf);
      free(read_buf.buf);

      exit(1);
    }

    void main_loop()
    {
      int maxfd;
      fd_set in_set, out_set, exc_set;
      int ret;

      for(;;)
      {
        FD_ZERO(&in_set);
        FD_ZERO(&out_set);
        FD_ZERO(&exc_set);
        FD_SET(sock, &in_set);
        If(write_buf.count>0)
          FD_SET(sock, &out_set);
        FD_SET(0, &in_set);
        maxfd = sock;
        /*
         *µð½ºÅ©¸³ÅÍ¿¡ µ¥ÀÌÅÍ°¡ µé¾î¿Ã¶§±îÁö °è¼Ó ±â´Ù¸®°Ô Çϱâ À§ÇÏ¿©
         *timeoutÀ» NULL·Î ÁöÁ¤ ÇÏ¿´´Ù.
         */
         ret = select(maxfd + 1, &in_set, &out_set, &exc_set, NULL);
         if(ret<0)
         {
           perror("select");
           sys_error();
         }
         /*Å°º¸µå·ÎºÎÅÍÀÇ ÀÔ·ÂÀ» Àд´Ù.*/
         if(FD_ISSET(0, &in_set))
         {
           FD_CLR(sock, &in_set);
           read_terminal();
         }
         /*¼ÒÄÏ¿¡ µ¥ÀÌÅ͸¦ ¾´´Ù.*/
         if(FD_ISEET(sock, &out_set))
         {
           F

    D_DLR(sock, &out_set);
           Write_socket();
         }
         /*¼ÒÄÏÀ¸·ÎºÎÅÍ µ¥ÀÌÅ͸¦ Àд´Ù.*/
         if(FD_ISSET(sock, &in_set))
         {
            FD_CLR(sock, &in_set);
            read_socket();
         }  
         /*¼ÒÄÏ¿¡¼­ºÎÅÍ ÀÐÀº µ¥ÀÌÅÍ°¡ ÀÖÀ¸¸é ±×°ÍÀ» ó¸®ÇÑ´Ù.*/
         if(read_buf.count>0)
         {
           process_protocol();
         }
      
      }
    }
    /*¼ÒÄÏ¿¡¼­ µ¥ÀÌÅ͸¦ Àо read_bif¿¡ ÀúÀåÇÑ´Ù. */
    void read_socket()
    {
      int n;

    if(read_buf.size == read_buf.tail)
      return;/*read_buf¿¡ ¿©À¯°ø°£ÀÌ ¾ø´Ù. */

    n=read(sock, read_buf.buf+read_buf.tail, read_buf.size_read_buf.tail);
      if(n< 0 && errno ==EWOULDBLOCK)
         n = 0;
      if(n<0)
      {
        perror("read");
        sys_error();
      }
      if (n ==0)
        peer_died();

      read_buf.count +=n;
      read_buf.tail +=n;
    }

    /*Å°º¸µå·ÎºÎÅÍ ÀÔ·ÂÀ» ¹Þ¾Æ¼­ write_buf¿¡ ÀúÀåÇÑ´Ù.*/
    void read_terminal()
    {
      int n;

      if (write_buf.size ==write_buf.tail)
         return;

      n = read(0, write_buf.buf+write_buf.tail,
          write_buf.size-write_buf.tail);
      if(n<0 &&errno ==EWOULDBLOCK)
        n = 0;
      if(n<0)
      {
        perror("read");
        sys_error();
      }
      if(n ==0)
      {
        do_bye();
      }

      write_buf.count+= n;
      write_buf.tail+= n;

    }

    /*write_buf¿¡ ÀÖ´Â µ¥ÀÌÅ͸¦ ¼ÒÄÏ¿¡ ¾´´Ù.*/
    void write_socket()
    {
      int n;

      n = write(sock, write_buf.buf+write_buf.head, write_buf.count);
             if(n<0&&(errno==ENOBUFS || errno==EWOULDBLOCK))
        n = 0;
      if(n<0)
      {
        perror("write");
        sys_error();
      }

      write_buf.head+=n;
      write_buf.count-=n;

      if(write_buf.count==0)
        write_buf.hea = write_buf.tail = 0;

    }

    /*
     *putc_socket(int)
     *puts_socket(char*)
     *getc_socket(char*)
     *putc_terminal(int)
     *ÀÌ ÇÔ¼öµéÀº process_protocol() ¼öÇàÁß ÇÊ¿äÇÑ ÇÔ¼öµéÀÌ´Ù.
     *
     *putc_socket()¿Í puts_socket()´Â write_buf¿¡ µ¥ÀÌÅ͸¦ ¾²±âÀ§ÇÑ ÇÔ¼ö.
     *getc_socket()´Â read_buf¿¡¼­ µ¥ÀÌÅ͸¦ Àбâ À§ÇÑ ÇÔ¼ö.
     *putc_terminal()´Â µ¥ÀÌÅ͸¦ È­¸é¿¡ Âï±â À§ÇÑ ÇÔ¼öÀÌ´Ù.
     */

    void putc_socket(int c)
    {
    if(write_buf.tail == write_buf.size)
      /*write_buf¿¡ ¿©À¯°ø°£ÀÌ ¾ø´Ù.*/
      write_socket();
    if(write_buf.tail ==write_buf.size)
    {
      fprintf(stderr,"write buffer full!¡¬n");
      return;
    }
    write_buf.buf[write_buf.tail++] = c;
    write_buf.count++;
    }

    void puts_socket(char*s)
    {
    int len = strlen(s);
    if(write_buf.tail + len>write_buf.size)
      /*write_buf¿¡ ¿©À¯°ø°£ÀÌ ¾ø´Ù.*/
      write_socket();
    if(write_buf.tail + len > write_buf.size)
    {
      fprintf(stderr,"write buffer full!¡¬n");
      return;
    }
    strcpy(write_buf.buf+write_buf.tail, s);
    write_buf.tail +=len;
    write_buf.count+=len;
    }

    int getc_socket(int*c)
    {
    if(read_buf.count==0)
      /*´õ ÀÌ»ó ÀÐÀ» °ÍÀÌ ¾ø´Ù.*/
      return 0;

    *c = read_buf.buf[read_buf.head++];
    *c = *c & 0xff;

    read_buf.count-;

    if(read_buf.count ==0)
      read_buf.head = read_buf.tail =0;
    return read_buf.count+1;
    }

    void putc_terminal(int c)
    {
    int n;
    n = write(1, &c, 1);
    if(n<0)
    {
      perror("write");
      sys_error();
    }
    }

    /*¼ÒÄÏÀ» nonblock »óÅ·Π¸¸µç´Ù. */
    void nonblock(int onoff)
    {
    if(ioctl(sock, FIONBIO, &onoff)<0
    {
      perror("ioctl");
      sys_error();
    }

    }

    int set_terminal(int set)
    {
    static struct termios save_termios;
    struct termios buf;
    static int isset = 0;
    extern int mode;

    if(isset == 0 && set ==0)
      return 0;

    if(set ==0)
    {
      if(tcsetattr(0, TCSAFLUSH, &save_termios)<0)
        return -1;
      return 0;
    }

    if(isset == 0)
      if(tcgetattr(0, &save_termios)<0)
        return-1;

    if(tcgetattr(0, &buf)<0)
      return-1;

    buf.c_lflag &=~ISIG;
    buf.c_oflag |=ONLCR;
    buf.c_oflag |=OPOST;
    buf.c_iflag |=ICRNL;

      if(mode & MODE_ECHO)
    {
    buf.c_flag|=ECHO;
    buf.c_oflag|=ONLCR;

    buf.c_iflag|=ICRNL;
    buf.c_lflag|=ICANON;
    }
    else
    {
    buf.c_lflag & =~ECHO;
    /*buf.c_oflag&=~ONLCR;*/

    buf.c_lflag&=~ICANON;
    /*¾î¶² ½Ã½ºÅÛ¿¡¼­´Â NL(0x0A)À» º¸³»¾ß ÇÑ´Ù.*/
    /*buf.c_iflag & =~ICRNL;*/
    buf.c_cc[VMIN] = 1;
    buf.c_cc[VTIME] = 0;
      }

    if(mode & MODE_FLOW)
    buf.c_iflag|=IXANY|IXOFF|IXON;
    else
    buf.c_iflag &=~(IXANY|IXOFF|IXON);

          if (mode & MODE_INBIN)
                    buf.c_iflag & =~ISTRIP;
          else
    buf.c_iflag |=ISTRIP;
          if(mode& MODE_OUTBIN)
    {
                    buf.c_cflag &=~(CSIZE|PARENB);
                    buf.c_cflag|=CS8;
                    /*buf.c_oflag &= ~OPOST;*/
    }
    else
    {
    buf.c_cflag &=~(CSIZE|PARENB);
    buf.c_cflag|=save_termios.c_cflag & (CSIZE|PARENNB);
    buf.c_oflag|=OPOST;
    }
    if(tcsetattr(0, TCSAFLUSH, &buf<0)
      return-1;
    isset = set;
    return 0;
    }

    void debug(const char *msg, ...)
    {
    va_list ap;

    if(!do_debug)
      return;

    va_start( ap,msg);
    vfprintf( stderr, msg, ap);
    va_end(ap);
    fprintf(stderr, "¡¬n");

    }

    /*the end of telnet.c*/

    /*
     *protocol.c
     *
     *ÇÁ·ÎÅäÄÝ Ã³¸®¸¦ À§ÇÑ ·çƾµé
     *by Àü¿µÁØ
     */

    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/ioctl.h>

    #define TELCMDS
    #define TELOPTS
    #include <arpa/telnet.h>

    #include "telnet.h"

    char options[256];
    int mode;

    void process_option(int cmd, int opt);
    void send_option(in cmd, int opt, int);
    int option_ok(int opt);
    void clean_sb();
    void process_sb();
    void send_naws();
    void send_ttype();
    void mode_set(int m, int set);
    int option_requested(int opt);
    void option_request(int opt, int req);

    void init_telnet(int istelnet)
    {
    int i;

    for(i=0;i<256;I++)
    options[i] = 0;

    mode = 0;
    /*ÇöÀç µðÆúÆ®·Î ¼³Á¤µÇ¾î ÀÖ´Â ¸ðµå*/
    mode_set(MODE_ECHO,1);

    set_terminal(1);
    /*ÅÚ³ÝÁ¢¼ÓÀÏ °æ¿ì¿¡´Â ÅÚ³Ý Ãʱ⠼³Á¤À» ÇÑ´Ù.*/
    if(istelnet)
    {
       send_option(DO, TELOPT_SGA, 1);
       send_option(WILL, TELOPT_TTYPE, 1);
       send_option(WILL, TELOPT_NAWS, 1);
       send_option(WILL, TELOPT_LFLOW, 1);
       send_option(WILL, TELOPT_LINEMODE, 1);
       send_option(DO, TELOPT_STATUS, 1);

       /*enter binarymode*/
       send_option(DO, TELOPT_BINARY, 1);
       send_option(WILL, TELOPT_BINARY, 1);
    }
    }

    /*read_buf¿¡ ÀúÀåµÇ¾î ÀÖ´Â µ¥ÀÌÅÍ¿¡¼­ ÇÁ·ÎÅäÄÝÀ» ã¾Æ¼­ ó¸®ÇÑ´Ù.*/
    void process_protocol(void)
    {
    int c;

    while(getc_socket(&c))
    {
      if(c ==IAC)
      {
        if(!getc_socket(&c))
           return;
        switch(c)
        {
        case IAC:
          putc_terminal(c);
          break;
        case DON'T:
        case DO:
        case WONT:
        case WILL:
        {
            int opt;
            if(!getc_socket(&opt))
    return;
            process_option(c, opt);
            break;
    }
    case SB:
       if(!getc_socket(&c))
         return;
       if(c ==TELOPT_TTYPE)
       {
         if(!getc_socket(&c))
           return;
         clean_sb();
         if(c ==TELQUAL_SEND)
           send_ttype();
         break;
       }
       clean_sb();
       break;

    default:
       break;

    }
        }
        else
        {
    putc_terminal(c);
        }
    }
    }

    void clean_sb()
    {
    int c;
    for(;;)
    {
         if(!getc_socket(&c))
            return;
         if(c ==IAC)
         {
    if(!getc_socket(&c))
       return;
    if(c ==SE)
       return;
    }
       }
    }

    void process_option(int cmd, int opt)
    {
    debug("RCVD: IAC %s%s", TELCMD(cmd), TELOPT(opt));

    /* If this is an option we do not understand or have not implemented, refuse any 'DO'
    request. */
    if(!option_ok(opt))
    {
      if( cmd == DO)
         send_option(WONT, opt,0);
      if( cmd == WILL)
         send_option(DONT, opt,0);
    }
    else if(cmd == DO)
    {
      switch(opt)
      {
      case TELOPT_ECHO:
        /*never echo if once turned off*/
        mode_set(MODE_ECHO, 0);
        send_option(WONT, opt, 0);
        goto out_processing;
        return;
      case TELOPT_BINARY:
        mode_set(MODE_OUTBIN, 1);
        break;
      case TELOPT_LFLOW:
        mode_set(MODE_FLOW, 1);
        break;
      case TELOPT_NAWS:
        send_naws();
        break;
      }
      if(!option_requested(opt))

        send_option(WILL, opt, 0);
    }
    else if( cmd == DONT)
    {
      switch(opt)
      {
      case TELOPT_ECHO;
        mode_set(MODE_ECHO, 0);
        break;
      case TELOPT_BINARY:
        mode_set(MODE_OUTBIN, 0);
        break;
      case TELOPT_LFLOW:
        mode_set(MODE_FLOW, 0);
        break;

      }
      if(!option_requested(opt))
        send_option(WONT, opt, 0);
    }
    else if( cmd==WILL)
    {
      switch(opt)
      {
      case TELOPT_ECHO:
        mode_set(MODE_ECHO, 0);
        break;
      case TELOPT_BINARY:
        mode_set(MODE_INBIN, 1);
        break;
      case TELOPT_LFLOW:
        mode_set(MODE_FLOW, 1);
        break;

      }
      if(!option_requested(opt))
        send_option(DO, opt, 0);
    }
    else if(cmd == WONT)
    {
      switch(opt)
      {
      case TELOPT_ECHO:
        mode_set(MODE_ECHO, 1);
        break;
      case TELOPT_BINARY:
        mode_set(MODE_INBIN, 0);
        break;
      case TELOPT_LFLOW:
        mode_set(MODE_FLOW, 0);
        break;
      }
      if(!option_requested(opt))
        send_option(DON'T, opt, 0);
    }
    out_processing:
    set_terminal(1);
    }
    void send_option(int cmd, int opt, int request)
    {
    if(request && !option_ok(opt))
      return;

    option_request(opt, request);

    debug("SENT:IAC%s%s", TELCMD(cmd), TELOPT(opt));
    putc_socket(IAC);
    putc_socket(cmd);
    putc_socket(opt);
    }

    /*Å͹̳ΠŸÀÔ*/
    void send_ttype()
    {
    char s[50];
    strcpy(s, (getenv("TERM") ==NULL? "UNKNOWN" : getenv("TERM")));

    putc_socket(IAC);
    putc_socket(SB);
    putc_socket(TELOPT_TTYPE);
    putc_socket(TELQUAL_IS);
    putc_socket(s);
    putc_socket(IAC);
    putc_socket(SE);

    debug("SENT: IAC SB TELOPT_TTYPE IS¡¬"%s¡¬" IAC AE" ,s);

    }

    /*Å͹̳ΠÀ©µµ¿ì Å©±â*/
    void send_naws()
    {
    char s[50];
    struct winsize size;
    if(ioctl(0, TIOCGWINSZ, (char*)&size)<0)
    {
      perror("ioctl");
      sys_error();
    }
    s[0] = (size.ws_col>>8)&0xFF;
    s[1] = (size.ws_col&0xFF);
    s[2] = (size.ws_row>>8)&0xFF;
    s[3] = (size.ws_row&0xFF);
    s[4] = 0;
    putc_socket(IAC);
    putc_socket(SB);
    putc_socket(TELOPT_NAWS);
    putc_socket(s);
    putc_socket(IAC);
    putc_socket(SE);

    debug("SENT:IAC SB TELOPT_NAWS%d%d%d%dIAC SE", s[0],s[1],s[2],s[3]);
    }

    int option_ok(int opt)
    {
    if(opt == TELOPT_ECHO||opt==TELOPT_BINARY||opt==TELOPT_SGA||
      opt == TELOPT_LFLOW||opt==TELOPT_TTYPE||opt==TELOPT_NAWS)
      return 1;
    else
      return 0;
    }

    void mode_set(int m, int set)
    {
    if(set)
      mode |=m;
    else
      mode &=~m;
    }

    int option_requested(int opt)
    {
    return option[opt]>0;
    }

    void option_request(int opt, int req)
    {
    if(req>0)
      options[opt]++;
    else if(options[opt]>0)
      options[opt]-;

    }

    /*the end of protocol.c*/
    ´ÙÀ½Àº ÀÌ ÇÁ·Î±×·¥À» À§ÇÑ MakefileÀÌ´Ù.
    telnet.h, telnet.c, protocol.c¸¦ °¢°¢ ÀúÀåÇÑ µÚ °°Àº µð·ºÅ丮¿¡ ´ÙÀ½ÀÇ MakefileÀ» ÀúÀåÇÏ¿© makeÇÏ¸é µÈ´Ù.

    #Makefile for mtelnet
    CC     = cc
    DEBUG  =
    O_FLAGS=
    C_FLAGS=$(O_FLAGS)-Wall$(DEBUG)
    L_FLAGS=$(O_FLAGS)

    O_FILES = mtelnet
    $(TARGET):$(O_FILES)
             $(CC)$(L_FLAGS)-o$(TARGET)$(O_FILES)

    .c.o:
             $(CC)$-c$(C_FLAGS)$<

    clean:
             rm*.o$(TARGET)

     

7.¸¶Ä¡¸é¼­

    ÀÌ ÇÁ·Î±×·¥Àº ½ÇÁ¦ÀûÀÎ ¾îÇø®ÄÉÀ̼ǿ¡¼­ ¾²À̱⿡´Â ³Ê¹«³ª ¹ö±×°¡ ¸¹°í, ÇÁ·ÎÅäÄÝ Áö¿øÀÌ ºó¾àÇÏ´Ù. ±×·¯³ª ÅÚ³Ý Å¬¶óÀ̾ðÆ® ÇÁ·Î±×·¡¹ÖÀ» ÀÌÇØÇϱ⿡´Â ÃæºÐÇϸ®¶ó »ý°¢µÈ´Ù. ´ÙÀ½ Æí¿¡¼­´Â ¼ÒÄÏÀ» ¼­¹ö ÇÁ·Î±×·¥ÀÇ ÀÔÀå¿¡¼­ ´Ù·ç¾î º»´Ù.




¡ã top

homeÀ¸·Î...